1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Andres Noetzli, Mathias Preiner |
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 Evaluator class. |
14 |
|
* |
15 |
|
* The Evaluator class can be used to evaluate terms with constant leaves |
16 |
|
* quickly, without going through the rewriter. |
17 |
|
*/ |
18 |
|
|
19 |
|
#include "cvc5_private.h" |
20 |
|
|
21 |
|
#ifndef CVC5__THEORY__EVALUATOR_H |
22 |
|
#define CVC5__THEORY__EVALUATOR_H |
23 |
|
|
24 |
|
#include <utility> |
25 |
|
#include <vector> |
26 |
|
|
27 |
|
#include "base/output.h" |
28 |
|
#include "expr/node.h" |
29 |
|
#include "expr/uninterpreted_constant.h" |
30 |
|
#include "util/bitvector.h" |
31 |
|
#include "util/rational.h" |
32 |
|
#include "util/string.h" |
33 |
|
|
34 |
|
namespace cvc5 { |
35 |
|
namespace theory { |
36 |
|
|
37 |
|
/** |
38 |
|
* Struct that holds the result of an evaluation. The actual value is stored in |
39 |
|
* a union to avoid the overhead of a class hierarchy with virtual methods. |
40 |
|
*/ |
41 |
|
struct EvalResult |
42 |
|
{ |
43 |
|
/* Describes which type of result is being stored */ |
44 |
|
enum |
45 |
|
{ |
46 |
|
BOOL, |
47 |
|
BITVECTOR, |
48 |
|
RATIONAL, |
49 |
|
STRING, |
50 |
|
UCONST, |
51 |
|
INVALID |
52 |
|
} d_tag; |
53 |
|
|
54 |
|
/* Stores the actual result */ |
55 |
|
union |
56 |
|
{ |
57 |
|
bool d_bool; |
58 |
|
BitVector d_bv; |
59 |
|
Rational d_rat; |
60 |
|
String d_str; |
61 |
|
UninterpretedConstant d_uc; |
62 |
|
}; |
63 |
|
|
64 |
|
EvalResult(const EvalResult& other); |
65 |
3125460 |
EvalResult() : d_tag(INVALID) {} |
66 |
199084 |
EvalResult(bool b) : d_tag(BOOL), d_bool(b) {} |
67 |
1717908 |
EvalResult(const BitVector& bv) : d_tag(BITVECTOR), d_bv(bv) {} |
68 |
212111 |
EvalResult(const Rational& i) : d_tag(RATIONAL), d_rat(i) {} |
69 |
318397 |
EvalResult(const String& str) : d_tag(STRING), d_str(str) {} |
70 |
|
EvalResult(const UninterpretedConstant& u) : d_tag(UCONST), d_uc(u) {} |
71 |
|
|
72 |
|
EvalResult& operator=(const EvalResult& other); |
73 |
|
|
74 |
|
~EvalResult(); |
75 |
|
|
76 |
|
/** |
77 |
|
* Converts the result to a Node. If the result is not valid, this function |
78 |
|
* returns the null node. |
79 |
|
*/ |
80 |
|
Node toNode() const; |
81 |
|
}; |
82 |
|
|
83 |
|
/** |
84 |
|
* The class that performs the actual evaluation of a term under a |
85 |
|
* substitution. Right now, the class does not cache anything between different |
86 |
|
* calls to `eval` but this might change in the future. |
87 |
|
*/ |
88 |
|
class Evaluator |
89 |
|
{ |
90 |
|
public: |
91 |
|
/** |
92 |
|
* Evaluates node `n` under the substitution described by the variable names |
93 |
|
* `args` and the corresponding values `vals`. This method uses evaluation |
94 |
|
* for subterms that evaluate to constants supported in the EvalResult |
95 |
|
* class and substitution with rewriting for the others. |
96 |
|
* |
97 |
|
* The nodes in vals are typically intended to be constant, although this |
98 |
|
* is not required. |
99 |
|
* |
100 |
|
* If the parameter useRewriter is true, then we may invoke calls to the |
101 |
|
* rewriter for computing the result of this method. |
102 |
|
* |
103 |
|
* The result of this call is either equivalent to: |
104 |
|
* (1) Rewriter::rewrite(n.substitute(args,vars)) |
105 |
|
* (2) Node::null(). |
106 |
|
* If useRewriter is true, then we are always in the first case. If |
107 |
|
* useRewriter is false, then we may be in case (2) if computing the |
108 |
|
* rewritten, substituted form of n could not be determined by evaluation. |
109 |
|
*/ |
110 |
|
Node eval(TNode n, |
111 |
|
const std::vector<Node>& args, |
112 |
|
const std::vector<Node>& vals, |
113 |
|
bool useRewriter = true) const; |
114 |
|
/** |
115 |
|
* Same as above, but with a precomputed visited map. |
116 |
|
*/ |
117 |
|
Node eval(TNode n, |
118 |
|
const std::vector<Node>& args, |
119 |
|
const std::vector<Node>& vals, |
120 |
|
const std::unordered_map<Node, Node>& visited, |
121 |
|
bool useRewriter = true) const; |
122 |
|
|
123 |
|
private: |
124 |
|
/** |
125 |
|
* Evaluates node `n` under the substitution described by the variable names |
126 |
|
* `args` and the corresponding values `vals`. The internal version returns |
127 |
|
* an EvalResult which has slightly less overhead for recursive calls. |
128 |
|
* |
129 |
|
* The method returns an invalid EvalResult if the result of the substitution |
130 |
|
* on n does not result in a constant value that is one of those supported in |
131 |
|
* the EvalResult class. Notice that e.g. datatype constants are not supported |
132 |
|
* in this class. |
133 |
|
* |
134 |
|
* This method additionally adds subterms of n that could not be evaluated |
135 |
|
* (in the above sense) to the map evalAsNode. For each such subterm n', we |
136 |
|
* store the node corresponding to the result of applying the substitution |
137 |
|
* `args` to `vals` and rewriting. Notice that this map contains an entry |
138 |
|
* for n in the case that it cannot be evaluated. |
139 |
|
*/ |
140 |
|
EvalResult evalInternal(TNode n, |
141 |
|
const std::vector<Node>& args, |
142 |
|
const std::vector<Node>& vals, |
143 |
|
std::unordered_map<TNode, Node>& evalAsNode, |
144 |
|
std::unordered_map<TNode, EvalResult>& results, |
145 |
|
bool useRewriter) const; |
146 |
|
/** reconstruct |
147 |
|
* |
148 |
|
* This function reconstructs the result of evaluating n using a combination |
149 |
|
* of evaluation results (eresults) and substitution+rewriting (evalAsNode). |
150 |
|
* |
151 |
|
* Arguments eresults and evalAsNode are built within the context of the |
152 |
|
* above method for some args and vals. This method ensures that the return |
153 |
|
* value is equivalent to the rewritten form of n * { args -> vals }. |
154 |
|
*/ |
155 |
|
Node reconstruct(TNode n, |
156 |
|
std::unordered_map<TNode, EvalResult>& eresults, |
157 |
|
std::unordered_map<TNode, Node>& evalAsNode) const; |
158 |
|
}; |
159 |
|
|
160 |
|
} // namespace theory |
161 |
|
} // namespace cvc5 |
162 |
|
|
163 |
|
#endif /* CVC5__THEORY__EVALUATOR_H */ |