1 /********************* */
2 /*! \file theory_datatypes_utils.h
4 ** Top contributors (to current version):
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 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.\endverbatim
12 ** \brief Util functions for theory datatypes.
14 ** Util functions for theory datatypes.
17 #include "cvc4_private.h"
19 #ifndef CVC4__THEORY__STRINGS__THEORY_DATATYPES_UTILS_H
20 #define CVC4__THEORY__STRINGS__THEORY_DATATYPES_UTILS_H
24 #include "expr/dtype.h"
25 #include "expr/node.h"
26 #include "expr/node_manager_attributes.h"
31 // ----------------------- sygus datatype attributes
33 struct SygusVarNumAttributeId
36 typedef expr::Attribute
<SygusVarNumAttributeId
, uint64_t> SygusVarNumAttribute
;
39 * Attribute true for enumerators whose current model values were registered by
40 * the datatypes sygus solver, and were not excluded by sygus symmetry breaking.
41 * This is set by the datatypes sygus solver during LAST_CALL effort checks for
42 * each active sygus enumerator.
44 struct SygusSymBreakOkAttributeId
47 typedef expr::Attribute
<SygusSymBreakOkAttributeId
, bool>
48 SygusSymBreakOkAttribute
;
52 * This attribute is used to mark whether sygus operators have free occurrences
53 * of variables from the formal argument list of the function-to-synthesize.
55 * We store three possible cases for sygus operators op:
56 * (1) op.getAttribute(SygusVarFreeAttribute())==Node::null()
57 * In this case, op has no free variables from the formal argument list of the
58 * function-to-synthesize.
59 * (2) op.getAttribute(SygusVarFreeAttribute())==v, where v is a bound variable.
60 * In this case, op has exactly one free variable, v.
61 * (3) op.getAttribute(SygusVarFreeAttribute())==op
62 * In this case, op has an arbitrary set (cardinality >1) of free variables from
63 * the formal argument list of the function to synthesize.
65 * This attribute is used to compute applySygusArgs below.
67 struct SygusVarFreeAttributeId
70 typedef expr::Attribute
<SygusVarFreeAttributeId
, Node
> SygusVarFreeAttribute
;
71 // ----------------------- end sygus datatype attributes
76 /** get instantiate cons
78 * This returns the term C( sel^{C,1}( n ), ..., sel^{C,m}( n ) ),
79 * where C is the index^{th} constructor of datatype dt.
81 Node
getInstCons(Node n
, const DType
& dt
, int index
);
82 /** is instantiation cons
84 * If this method returns a value >=0, then that value, call it index,
85 * is such that n = C( sel^{C,1}( t ), ..., sel^{C,m}( t ) ),
86 * where C is the index^{th} constructor of dt.
88 int isInstCons(Node t
, Node n
, const DType
& dt
);
91 * This method returns a value >=0 if n is a tester predicate. The return
92 * value indicates the constructor index that the tester n is for. If this
93 * method returns a value >=0, then it updates a to the argument that the
94 * tester n applies to.
96 int isTester(Node n
, Node
& a
);
97 /** is tester, same as above but does not update an argument */
100 * Get the index of a constructor or tester in its datatype, or the
101 * index of a selector in its constructor. (Zero is always the
104 size_t indexOf(Node n
);
106 * Get the index of constructor corresponding to selector.
107 * (Zero is always the first index.)
109 size_t cindexOf(Node n
);
111 * Get the datatype of n.
113 const DType
& datatypeOf(Node n
);
114 /** make tester is-C( n ), where C is the i^{th} constructor of dt */
115 Node
mkTester(Node n
, int i
, const DType
& dt
);
116 /** make tester split
118 * Returns the formula (OR is-C1( n ) ... is-Ck( n ) ), where C1...Ck
119 * are the constructors of n's type (dt).
121 Node
mkSplit(Node n
, const DType
& dt
);
122 /** returns true iff n is a constructor term with no datatype children */
123 bool isNullaryApplyConstructor(Node n
);
124 /** returns true iff c is a constructor with no datatype children */
125 bool isNullaryConstructor(const DTypeConstructor
& c
);
128 * This method returns true if and only if n1 and n2 have a skeleton that has
129 * conflicting constructors at some term position.
130 * Examples of terms that clash are:
131 * C( x, y ) and D( z )
132 * C( D( x ), y ) and C( E( x ), y )
133 * Examples of terms that do not clash are:
134 * C( x, y ) and C( D( x ), y )
135 * C( D( x ), y ) and C( x, E( z ) )
138 bool checkClash(Node n1
, Node n2
, std::vector
<Node
>& rew
);
140 // ------------------------ sygus utils
142 /** get operator kind for sygus builtin
144 * This returns the Kind corresponding to applications of the operator op
145 * when building the builtin version of sygus terms. This is used by the
146 * function mkSygusTerm.
148 Kind
getOperatorKindForSygusBuiltin(Node op
);
150 * Returns the total version of Kind k if it is a partial operator, or
151 * otherwise k itself.
153 Kind
getEliminateKind(Kind k
);
155 * Returns a version of n where all partial functions such as bvudiv
156 * have been replaced by their total versions like bvudiv_total.
158 Node
eliminatePartialOperators(Node n
);
161 * This function returns a builtin term f( children[0], ..., children[n] )
162 * where f is the builtin op that the i^th constructor of sygus datatype dt
163 * encodes. If doBetaReduction is true, then lambdas are eagerly eliminated
164 * via beta reduction.
166 * If isExternal is true, then the returned term respects the original grammar
167 * that was provided. This includes the use of defined functions.
169 Node
mkSygusTerm(const DType
& dt
,
171 const std::vector
<Node
>& children
,
172 bool doBetaReduction
= true,
173 bool isExternal
= false);
175 * Same as above, but we already have the sygus operator op. The above method
176 * is syntax sugar for calling this method on dt[i].getSygusOp().
178 Node
mkSygusTerm(Node op
,
179 const std::vector
<Node
>& children
,
180 bool doBetaReduction
= true);
182 * n is a builtin term that is an application of operator op.
184 * This returns an n' such that (eval n args) is n', where n' is a instance of
185 * n for the appropriate substitution.
187 * For example, given a function-to-synthesize with formal argument list (x,y),
188 * say we have grammar:
189 * A -> A+A | A+x | A+(x+y) | y
190 * These lead to constructors with sygus ops:
191 * C1 / (lambda w1 w2. w1+w2)
192 * C2 / (lambda w1. w1+x)
193 * C3 / (lambda w1. w1+(x+y))
195 * Examples of calling this function:
196 * applySygusArgs( dt, C1, (APPLY_UF (lambda w1 w2. w1+w2) t1 t2), { 3, 5 } )
197 * ... returns (APPLY_UF (lambda w1 w2. w1+w2) t1 t2).
198 * applySygusArgs( dt, C2, (APPLY_UF (lambda w1. w1+x) t1), { 3, 5 } )
199 * ... returns (APPLY_UF (lambda w1. w1+3) t1).
200 * applySygusArgs( dt, C3, (APPLY_UF (lambda w1. w1+(x+y)) t1), { 3, 5 } )
201 * ... returns (APPLY_UF (lambda w1. w1+(3+5)) t1).
202 * applySygusArgs( dt, C4, y, { 3, 5 } )
204 * Notice the attribute SygusVarFreeAttribute is applied to C1, C2, C3, C4,
205 * to cache the results of whether the evaluation of this constructor needs
206 * a substitution over the formal argument list of the function-to-synthesize.
208 Node
applySygusArgs(const DType
& dt
,
211 const std::vector
<Node
>& args
);
214 * This method converts a constant term of SyGuS datatype type to its builtin
215 * equivalent. For example, given input C_*( C_x(), C_y() ), this method returns
216 * x*y, assuming C_+, C_x, and C_y have sygus operators *, x, and y
219 * If isExternal is true, then the returned term respects the original grammar
220 * that was provided. This includes the use of defined functions. This argument
221 * should typically be false, unless we are e.g. exporting the value of the
222 * term as a final solution.
224 Node
sygusToBuiltin(Node c
, bool isExternal
= false);
225 /** Sygus to builtin eval
227 * This method returns the rewritten form of (DT_SYGUS_EVAL n args). Notice that
228 * n does not necessarily need to be a constant.
230 * It does so by (1) converting constant subterms of n to builtin terms and
231 * evaluating them on the arguments args, (2) unfolding non-constant
232 * applications of sygus constructors in n with respect to args and (3)
233 * converting all other non-constant subterms of n to applications of
237 * n = C_+( C_*( C_x(), C_y() ), n' ), and args = { 3, 4 }
238 * where n' is a variable, then this method returns:
239 * 12 + (DT_SYGUS_EVAL n' 3 4)
240 * Notice that the subterm C_*( C_x(), C_y() ) is converted to its builtin
241 * equivalent x*y and evaluated under the substition { x -> 3, x -> 4 } giving
242 * 12. The subterm n' is non-constant and thus we return its evaluation under
243 * 3,4, giving the term (DT_SYGUS_EVAL n' 3 4). Since the top-level constructor
244 * is C_+, these terms are added together to give the result.
246 Node
sygusToBuiltinEval(Node n
, const std::vector
<Node
>& args
);
248 // ------------------------ end sygus utils
251 } // namespace datatypes
252 } // namespace theory