1 /********************* */ 2 /*! \file datatypes_rewriter.h 3 ** \verbatim 4 ** Top contributors (to current version): 5 ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic 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 11 ** 12 ** \brief Rewriter for the theory of (co)inductive datatypes 13 ** 14 ** Rewriter for the theory of (co)inductive datatypes. 15 **/ 16 17 #include "cvc4_private.h" 18 19 #ifndef __CVC4__THEORY__DATATYPES__DATATYPES_REWRITER_H 20 #define __CVC4__THEORY__DATATYPES__DATATYPES_REWRITER_H 21 22 #include "expr/node_manager_attributes.h" 23 #include "options/datatypes_options.h" 24 #include "theory/rewriter.h" 25 #include "theory/type_enumerator.h" 26 27 namespace CVC4 { 28 namespace theory { 29 30 /** sygus var num */ 31 struct SygusVarNumAttributeId 32 { 33 }; 34 typedef expr::Attribute<SygusVarNumAttributeId, uint64_t> SygusVarNumAttribute; 35 36 /** Attribute true for variables that represent any constant */ 37 struct SygusAnyConstAttributeId 38 { 39 }; 40 typedef expr::Attribute<SygusAnyConstAttributeId, bool> SygusAnyConstAttribute; 41 42 /** 43 * Attribute true for enumerators whose current model values were registered by 44 * the datatypes sygus solver, and were not excluded by sygus symmetry breaking. 45 * This is set by the datatypes sygus solver during LAST_CALL effort checks for 46 * each active sygus enumerator. 47 */ 48 struct SygusSymBreakOkAttributeId 49 { 50 }; 51 typedef expr::Attribute<SygusSymBreakOkAttributeId, bool> 52 SygusSymBreakOkAttribute; 53 54 namespace datatypes { 55 56 class DatatypesRewriter { 57 public: 58 static RewriteResponse postRewrite(TNode in); 59 60 static RewriteResponse preRewrite(TNode in); 61 init()62 static inline void init() {} shutdown()63 static inline void shutdown() {} 64 /** get instantiate cons 65 * 66 * This returns the term C( sel^{C,1}( n ), ..., sel^{C,m}( n ) ), 67 * where C is the index^{th} constructor of datatype dt. 68 */ 69 static Node getInstCons(Node n, const Datatype& dt, int index); 70 /** is instantiation cons 71 * 72 * If this method returns a value >=0, then that value, call it index, 73 * is such that n = C( sel^{C,1}( t ), ..., sel^{C,m}( t ) ), 74 * where C is the index^{th} constructor of dt. 75 */ 76 static int isInstCons(Node t, Node n, const Datatype& dt); 77 /** is tester 78 * 79 * This method returns a value >=0 if n is a tester predicate. The return 80 * value indicates the constructor index that the tester n is for. If this 81 * method returns a value >=0, then it updates a to the argument that the 82 * tester n applies to. 83 */ 84 static int isTester(Node n, Node& a); 85 /** is tester, same as above but does not update an argument */ 86 static int isTester(Node n); 87 /** 88 * Get the index of a constructor or tester in its datatype, or the 89 * index of a selector in its constructor. (Zero is always the 90 * first index.) 91 */ 92 static unsigned indexOf(Node n); 93 /** make tester is-C( n ), where C is the i^{th} constructor of dt */ 94 static Node mkTester(Node n, int i, const Datatype& dt); 95 /** make tester split 96 * 97 * Returns the formula (OR is-C1( n ) ... is-Ck( n ) ), where C1...Ck 98 * are the constructors of n's type (dt). 99 */ 100 static Node mkSplit(Node n, const Datatype& dt); 101 /** returns true iff n is a constructor term with no datatype children */ 102 static bool isNullaryApplyConstructor(Node n); 103 /** returns true iff c is a constructor with no datatype children */ 104 static bool isNullaryConstructor(const DatatypeConstructor& c); 105 /** normalize codatatype constant 106 * 107 * This returns the normal form of the codatatype constant n. This runs a 108 * DFA minimization algorithm based on the private functions below. 109 * 110 * In particular, we first call collectRefs to setup initial information 111 * about what terms occur in n. Then, we run a DFA minimization algorithm to 112 * partition these subterms in equivalence classes. Finally, we call 113 * normalizeCodatatypeConstantEqc to construct the normalized codatatype 114 * constant that is equivalent to n. 115 */ 116 static Node normalizeCodatatypeConstant(Node n); 117 /** normalize constant 118 * 119 * This method returns the normal form of n, which calls the above function 120 * on all top-level codatatype subterms of n. 121 */ 122 static Node normalizeConstant(Node n); 123 /** check clash 124 * 125 * This method returns true if and only if n1 and n2 have a skeleton that has 126 * conflicting constructors at some term position. 127 * Examples of terms that clash are: 128 * C( x, y ) and D( z ) 129 * C( D( x ), y ) and C( E( x ), y ) 130 * Examples of terms that do not clash are: 131 * C( x, y ) and C( D( x ), y ) 132 * C( D( x ), y ) and C( x, E( z ) ) 133 * C( x, y ) and z 134 */ 135 static bool checkClash(Node n1, Node n2, std::vector<Node>& rew); 136 /** get operator kind for sygus builtin 137 * 138 * This returns the Kind corresponding to applications of the operator op 139 * when building the builtin version of sygus terms. This is used by the 140 * function mkSygusTerm. 141 */ 142 static Kind getOperatorKindForSygusBuiltin(Node op); 143 /** make sygus term 144 * 145 * This function returns a builtin term f( children[0], ..., children[n] ) 146 * where f is the builtin op that the i^th constructor of sygus datatype dt 147 * encodes. 148 */ 149 static Node mkSygusTerm(const Datatype& dt, 150 unsigned i, 151 const std::vector<Node>& children); 152 /** 153 * Get the builtin sygus operator for constructor term n of sygus datatype 154 * type. For example, if n is the term C_+( d1, d2 ) where C_+ is a sygus 155 * constructor whose sygus op is the builtin operator +, this method returns +. 156 */ 157 static Node getSygusOpForCTerm(Node n); 158 159 private: 160 /** rewrite constructor term in */ 161 static RewriteResponse rewriteConstructor(TNode in); 162 /** rewrite selector term in */ 163 static RewriteResponse rewriteSelector(TNode in); 164 /** rewrite tester term in */ 165 static RewriteResponse rewriteTester(TNode in); 166 167 /** collect references 168 * 169 * This function, given as input a codatatype term n, collects the necessary 170 * information for constructing a (canonical) codatatype constant that is 171 * equivalent to n if one exists, or null otherwise. 172 * 173 * In particular it returns a term ret such that all non-codatatype datatype 174 * subterms of n are replaced by a constant that is equal to them via a 175 * (mutually) recursive call to normalizeConstant above. Additionally, this 176 * function replaces references to mu-binders with fresh variables. 177 * In detail, mu-terms are represented by uninterpreted constants of datatype 178 * type that carry their Debruijn index. 179 * 180 * Consider the example of a codatatype representing a stream of integers: 181 * Stream := cons( head : Int, tail : Stream ) 182 * The stream 1,0,1,0,1,0... when written in mu-notation is the term: 183 * mu x. cons( 1, mu y. cons( 0, x ) ) 184 * This is represented in CVC4 by the Node: 185 * cons( 1, cons( 0, c[1] ) ) 186 * where c[1] is a uninterpreted constant datatype with Debruijn index 1, 187 * indicating that c[1] is nested underneath 1 level on the path to the 188 * term which it binds. On the other hand, the stream 1,0,0,0,0,... is 189 * represented by the codatatype term: 190 * cons( 1, cons( 0, c[0] ) ) 191 * 192 * Subterms that are references to mu-binders in n are replaced by a new 193 * variable. If n contains any subterm that is a reference to a mu-binder not 194 * bound in n, then we return null. For example we return null when n is: 195 * cons( 1, cons( 0, c[2] ) ) 196 * since c[2] is not bound by this codatatype term. 197 * 198 * All valid references to mu-binders are replaced by a variable that is unique 199 * for the term it references. For example, for the infinite tree codatatype: 200 * Tree : node( data : Int, left : Tree, right : Tree ) 201 * If n is the term: 202 * node( 0, c[0], node( 1, c[0], c[1] ) ) 203 * then the return value ret of this function is: 204 * node( 0, x, node( 1, y, x ) ) 205 * where x refers to the root of the term and y refers to the right tree of the 206 * root. 207 * 208 * The argument sk stores the current set of node that we are traversing 209 * beneath. The argument rf_pending stores, for each node that we are 210 * traversing beneath either null or the free variable that we are using to 211 * refer to its mu-binder. The remaining arguments store information that is 212 * relevant when performing normalization of n using the value of ret: 213 * 214 * rf : maps subterms of n to the corresponding term in ret for all subterms 215 * where the corresponding term in ret is different. 216 * terms : stores all subterms of ret. 217 * cdts : for each term t in terms, stores whether t is a codatatype. 218 */ 219 static Node collectRef(Node n, 220 std::vector<Node>& sk, 221 std::map<Node, Node>& rf, 222 std::vector<Node>& rf_pending, 223 std::vector<Node>& terms, 224 std::map<Node, bool>& cdts); 225 /** normalize codatatype constant eqc 226 * 227 * This recursive function returns a codatatype constant that is equivalent to 228 * n based on a pre-computed partition of the subterms of n into equivalence 229 * classes, as stored in the mapping eqc, which maps the subterms of n to 230 * equivalence class ids. The arguments eqc_stack and depth store information 231 * about the traversal in a term we have recursed, where 232 * 233 * eqc_stack : maps the depth of each term we have traversed to its equivalence 234 * class id. 235 * depth : the number of levels which we have traversed. 236 */ 237 static Node normalizeCodatatypeConstantEqc(Node n, 238 std::map<int, int>& eqc_stack, 239 std::map<Node, int>& eqc, 240 int depth); 241 /** replace debruijn 242 * 243 * This function, given codatatype term n, returns a node 244 * where all subterms of n that have Debruijn indices that refer to a 245 * term of input depth are replaced by orig. For example, for the infinite Tree 246 * datatype, 247 * replaceDebruijn( node( 0, c[0], node( 1, c[0], c[1] ) ), t, Tree, 0 ) 248 * returns 249 * node( 0, t, node( 1, c[0], t ) ). 250 */ 251 static Node replaceDebruijn(Node n, 252 Node orig, 253 TypeNode orig_tn, 254 unsigned depth); 255 };/* class DatatypesRewriter */ 256 257 }/* CVC4::theory::datatypes namespace */ 258 }/* CVC4::theory namespace */ 259 }/* CVC4 namespace */ 260 261 #endif /* __CVC4__THEORY__DATATYPES__DATATYPES_REWRITER_H */ 262