GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/preprocessing/passes/ho_elim.h Lines: 1 1 100.0 %
Date: 2021-09-15 Branches: 0 0 0.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Andres Noetzli
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * The HoElim preprocessing pass.
14
 *
15
 * Eliminates higher-order constraints.
16
 */
17
18
#include "cvc5_private.h"
19
20
#ifndef __CVC5__PREPROCESSING__PASSES__HO_ELIM_PASS_H
21
#define __CVC5__PREPROCESSING__PASSES__HO_ELIM_PASS_H
22
23
#include <map>
24
#include <unordered_map>
25
#include <unordered_set>
26
27
#include "expr/node.h"
28
#include "preprocessing/preprocessing_pass.h"
29
30
namespace cvc5 {
31
namespace preprocessing {
32
namespace passes {
33
34
/** Higher-order elimination.
35
 *
36
 * This preprocessing pass eliminates all occurrences of higher-order
37
 * constraints in the input, and replaces the entire input problem with
38
 * an equisatisfiable one. This is based on the following steps.
39
 *
40
 * [1] Eliminate all occurrences of lambdas via lambda lifting. This includes
41
 * lambdas with free variables that occur in quantifier bodies (see
42
 * documentation for eliminateLambdaComplete).
43
 *
44
 * [2] Eliminate all occurrences of partial applications and constraints
45
 * involving functions as first-class members. This is done by first
46
 * turning all function applications into an applicative encoding involving the
47
 * parametric binary operator @ (of kind HO_APPLY). Then we introduce:
48
 * - An uninterpreted sort U(T) for each function type T,
49
 * - A function H(f) of sort U(T1) x .. x U(Tn) -> U(T) for each function f
50
 * of sort T1 x ... x Tn -> T.
51
 * - A function App_{T1 x T2 ... x Tn -> T} of type
52
 *   U(T1 x T2 ... x Tn -> T) x U(T1) -> U(T2 ... x Tn -> T)
53
 * for each occurrence of @ applied to arguments of types T1 x T2 ... x Tn -> T
54
 * and T1.
55
 *
56
 * [3] Add additional axioms to ensure the correct interpretation of
57
 * the sorts U(...), and functions App_{...}. This includes:
58
 *
59
 * - The "extensionality" axiom for App_{...} terms, stating that functions
60
 * that behave the same according to App for all inputs must be equal:
61
 *   forall x : U(T1->T2), y : U(T1->T2).
62
 *      ( forall z : T1. App_{T1->T2}( x, z ) = App_{T1->T2}( y, z ) ) =>
63
 *        x = y
64
 *
65
 * - The "store" axiom, which effectively states that for all (encoded)
66
 * functions f, there exists a function g that behaves identically to f, except
67
 * that g for argument i is e:
68
 *   forall x : U(T1->T2), i : U(T1), e : U(T2).
69
 *     exists g : U(T1->T2).
70
 *       forall z: T1.
71
 *         App_{T1->T2}( g, z ) = ite( z = i, e, App_{T1->T2}( f, z ) ).
72
 *
73
 *
74
 * Based on options, this preprocessing pass may apply a subset o the above
75
 * steps. In particular:
76
 * * If hoElim is true, then step [2] is taken and extensionality
77
 * axioms are added in step [3].
78
 * * If hoElimStoreAx is true, then store axioms are added in step 3.
79
 * The form of these axioms depends on whether hoElim is true. If it
80
 * is true, the axiom is given in terms of the uninterpreted functions that
81
 * encode function sorts. If it is false, then the store axiom is given in terms
82
 * of the original function sorts.
83
 */
84
19878
class HoElim : public PreprocessingPass
85
{
86
 public:
87
  HoElim(PreprocessingPassContext* preprocContext);
88
89
 protected:
90
  PreprocessingPassResult applyInternal(
91
      AssertionPipeline* assertionsToPreprocess) override;
92
  /**
93
   * Eliminate all occurrences of lambdas in term n, return the result. This
94
   * is step [1] mentioned at the header of this class.
95
   *
96
   * The map newLambda maps newly introduced function skolems with their
97
   * (lambda) definition, which is a closed term.
98
   *
99
   * Notice that to ensure that all lambda definitions are closed, we
100
   * introduce extra bound arguments to the lambda, for example:
101
   *    forall x. (lambda y. x+y) != f
102
   * becomes
103
   *    forall x. g(x) != f
104
   * where g is mapped to the (closed) term ( lambda xy. x+y ).
105
   *
106
   * Notice that the definitions in newLambda may themselves contain lambdas,
107
   * hence, this method is run until a fix point is reached.
108
   */
109
  Node eliminateLambdaComplete(Node n, std::map<Node, Node>& newLambda);
110
111
  /**
112
   * Eliminate all higher-order constraints in n, return the result. This is
113
   * step [2] mentioned at the header of this class.
114
   */
115
  Node eliminateHo(Node n);
116
  /**
117
   * Stores the set of nodes we have current visited and their results
118
   * in steps [1] and [2] of this pass.
119
   */
120
  std::unordered_map<Node, Node> d_visited;
121
  /**
122
   * Stores the mapping from functions f to their corresponding function H(f)
123
   * in the encoding for step [2] of this pass.
124
   */
125
  std::unordered_map<TNode, Node> d_visited_op;
126
  /** The set of all function types encountered in assertions. */
127
  std::unordered_set<TypeNode> d_funTypes;
128
129
  /**
130
   * Get ho apply uf, this returns App_{@_{T1 x T2 ... x Tn -> T}}
131
   */
132
  Node getHoApplyUf(TypeNode tn);
133
  /**
134
   * Get ho apply uf, where:
135
   *   tn is T1 x T2 ... x Tn -> T,
136
   *   tna is T1,
137
   *   tnr is T2 ... x Tn -> T
138
   * This returns App_{@_{T1 x T2 ... x Tn -> T}}.
139
   */
140
  Node getHoApplyUf(TypeNode tn, TypeNode tna, TypeNode tnr);
141
  /** cache of getHoApplyUf */
142
  std::map<TypeNode, Node> d_hoApplyUf;
143
  /**
144
   * Get uninterpreted sort for function sort. This returns U(T) for function
145
   * type T for step [2] of this pass.
146
   */
147
  TypeNode getUSort(TypeNode tn);
148
  /** cache of the above function */
149
  std::map<TypeNode, TypeNode> d_ftypeMap;
150
};
151
152
}  // namespace passes
153
}  // namespace preprocessing
154
}  // namespace cvc5
155
156
#endif /* __CVC5__PREPROCESSING__PASSES__HO_ELIM_PASS_H */