1 /********************* */ 2 /*! \file datatypes_sygus.h 3 ** \verbatim 4 ** Top contributors (to current version): 5 ** Andrew Reynolds, 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 Sygus utilities for theory of datatypes 13 ** 14 ** Theory of datatypes. 15 **/ 16 17 #include "cvc4_private.h" 18 19 #ifndef __CVC4__THEORY__DATATYPES__DATATYPES_SYGUS_NEW_H 20 #define __CVC4__THEORY__DATATYPES__DATATYPES_SYGUS_NEW_H 21 22 #include <iostream> 23 #include <map> 24 25 #include "context/cdhashmap.h" 26 #include "context/cdhashset.h" 27 #include "context/cdlist.h" 28 #include "context/cdo.h" 29 #include "context/context.h" 30 #include "expr/datatype.h" 31 #include "expr/node.h" 32 #include "theory/datatypes/sygus_simple_sym.h" 33 #include "theory/quantifiers/sygus/sygus_explain.h" 34 #include "theory/quantifiers/sygus/synth_conjecture.h" 35 #include "theory/quantifiers/sygus_sampler.h" 36 #include "theory/quantifiers/term_database.h" 37 38 namespace CVC4 { 39 namespace theory { 40 namespace datatypes { 41 42 class TheoryDatatypes; 43 44 /** 45 * This is the sygus extension of the decision procedure for quantifier-free 46 * inductive datatypes. At a high level, this class takes as input a 47 * set of asserted testers is-C1( x ), is-C2( x.1 ), is-C3( x.2 ), and 48 * generates lemmas that restrict the models of x, if x is a "sygus enumerator" 49 * (see TermDbSygus::registerEnumerator). 50 * 51 * Some of these techniques are described in these papers: 52 * "Refutation-Based Synthesis in SMT", Reynolds et al 2017. 53 * "Sygus Techniques in the Core of an SMT Solver", Reynolds et al 2017. 54 * 55 * This class enforces two decisions stragies via calls to registerStrategy 56 * of the owning theory's DecisionManager: 57 * (1) Positive decisions on the active guards G of enumerators e registered 58 * to this class. These assert "there are more values to enumerate for e". 59 * (2) Positive bounds (DT_SYGUS_BOUND m n) for "measure terms" m (see below), 60 * where n is a non-negative integer. This asserts "the measure of terms 61 * we are enumerating for enumerators whose measure term m is at most n", 62 * where measure is commonly term size, but can also be height. 63 * 64 * We prioritize decisions of form (1) before (2). Both kinds of decision are 65 * critical for solution completeness, which is enforced by DecisionManager. 66 */ 67 class SygusSymBreakNew 68 { 69 typedef context::CDHashMap< Node, int, NodeHashFunction > IntMap; 70 typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap; 71 typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap; 72 typedef context::CDHashSet<Node, NodeHashFunction> NodeSet; 73 74 public: 75 SygusSymBreakNew(TheoryDatatypes* td, 76 QuantifiersEngine* qe, 77 context::Context* c); 78 ~SygusSymBreakNew(); 79 /** 80 * Notify this class that tester for constructor tindex has been asserted for 81 * n. Exp is the literal corresponding to this tester. This method may add 82 * lemmas to the vector lemmas, for details see assertTesterInternal below. 83 * These lemmas are sent out on the output channel of datatypes by the caller. 84 */ 85 void assertTester(int tindex, TNode n, Node exp, std::vector<Node>& lemmas); 86 /** 87 * Notify this class that literal n has been asserted with the given 88 * polarity. This method may add lemmas to the vector lemmas, for instance 89 * based on inferring consequences of (not) n. One example is if n is 90 * (DT_SIZE_BOUND x n), we add the lemma: 91 * (DT_SIZE_BOUND x n) <=> ((DT_SIZE x) <= n ) 92 */ 93 void assertFact(Node n, bool polarity, std::vector<Node>& lemmas); 94 /** pre-register term n 95 * 96 * This is called when n is pre-registered with the theory of datatypes. 97 * If n is a sygus enumerator, then we may add lemmas to the vector lemmas 98 * that are used to enforce fairness regarding the size of n. 99 */ 100 void preRegisterTerm(TNode n, std::vector<Node>& lemmas); 101 /** check 102 * 103 * This is called at last call effort, when the current model assignment is 104 * satisfiable according to the quantifier-free decision procedures and a 105 * model is built. This method may add lemmas to the vector lemmas based 106 * on dynamic symmetry breaking techniques, based on the model values of 107 * all preregistered enumerators. 108 */ 109 void check(std::vector<Node>& lemmas); 110 private: 111 /** Pointer to the datatype theory that owns this class. */ 112 TheoryDatatypes* d_td; 113 /** Pointer to the sygus term database */ 114 quantifiers::TermDbSygus* d_tds; 115 /** the simple symmetry breaking utility */ 116 SygusSimpleSymBreak d_ssb; 117 /** 118 * Map from terms to the index of the tester that is asserted for them in 119 * the current SAT context. In other words, if d_testers[n] = 2, then the 120 * tester is-C_2(n) is asserted in this SAT context. 121 */ 122 IntMap d_testers; 123 /** 124 * Map from terms to the tester asserted for them. In the example above, 125 * d_testers[n] = is-C_2(n). 126 */ 127 NodeMap d_testers_exp; 128 /** 129 * The set of (selector chain) terms that are active in the current SAT 130 * context. A selector chain term S_n( ... S_1( x )... ) is active if either: 131 * (1) n=0 and x is a sygus enumerator, 132 * or: 133 * (2.1) S_{n-1}( ... S_1( x )) is active, 134 * (2.2) is-C( S_{n-1}( ... S_1( x )) ) is asserted in this SAT context, and 135 * (2.3) S_n is a selector for constructor C. 136 */ 137 NodeSet d_active_terms; 138 /** 139 * Map from enumerators to a lower bound on their size in the current SAT 140 * context. 141 */ 142 IntMap d_currTermSize; 143 /** zero */ 144 Node d_zero; 145 /** true */ 146 Node d_true; 147 /** 148 * Map from terms (selector chains) to their anchors. The anchor of a 149 * selector chain S1( ... Sn( x ) ... ) is x. 150 */ 151 std::unordered_map<Node, Node, NodeHashFunction> d_term_to_anchor; 152 /** 153 * Map from anchors to the conjecture they are associated with. 154 */ 155 std::map<Node, quantifiers::SynthConjecture*> d_anchor_to_conj; 156 /** 157 * Map from terms (selector chains) to their depth. The depth of a selector 158 * chain S1( ... Sn( x ) ... ) is: 159 * weight( S1 ) + ... + weight( Sn ), 160 * where weight is the selector weight of Si 161 * (see SygusTermDatabase::getSelectorWeight). 162 */ 163 std::unordered_map<Node, unsigned, NodeHashFunction> d_term_to_depth; 164 /** 165 * Map from terms (selector chains) to whether they are the topmost term 166 * of their type. For example, if: 167 * S1 : T1 -> T2 168 * S2 : T2 -> T2 169 * S3 : T2 -> T1 170 * S4 : T1 -> T3 171 * Then, x, S1( x ), and S4( S3( S2( S1( x ) ) ) ) are top-level terms, 172 * whereas S2( S1( x ) ) and S3( S2( S1( x ) ) ) are not. 173 */ 174 std::unordered_map<Node, bool, NodeHashFunction> d_is_top_level; 175 /** 176 * Returns true if the selector chain n is top-level based on the above 177 * definition, when tn is the type of n. 178 */ 179 bool computeTopLevel( TypeNode tn, Node n ); 180 private: 181 /** This caches all information regarding symmetry breaking for an anchor. */ 182 class SearchCache 183 { 184 public: SearchCache()185 SearchCache(){} 186 /** 187 * A cache of all search terms for (types, sizes). See registerSearchTerm 188 * for definition of search terms. 189 */ 190 std::map< TypeNode, std::map< unsigned, std::vector< Node > > > d_search_terms; 191 /** A cache of all symmetry breaking lemma templates for (types, sizes). */ 192 std::map< TypeNode, std::map< unsigned, std::vector< Node > > > d_sb_lemmas; 193 /** search value 194 * 195 * For each sygus type, a map from a builtin term to a sygus term for that 196 * type that we encountered during the search whose analog rewrites to that 197 * term. The range of this map can be updated if we later encounter a sygus 198 * term that also rewrites to the builtin value but has a smaller term size. 199 */ 200 std::map<TypeNode, std::unordered_map<Node, Node, NodeHashFunction>> 201 d_search_val; 202 /** the size of terms in the range of d_search val. */ 203 std::map<TypeNode, std::unordered_map<Node, unsigned, NodeHashFunction>> 204 d_search_val_sz; 205 /** For each term, whether this cache has processed that term */ 206 std::unordered_set<Node, NodeHashFunction> d_search_val_proc; 207 }; 208 /** An instance of the above cache, for each anchor */ 209 std::map< Node, SearchCache > d_cache; 210 //-----------------------------------traversal predicates 211 /** pre/post traversal predicates for each type, variable 212 * 213 * This stores predicates (pre, post) whose semantics correspond to whether 214 * a variable has occurred by a (pre, post) traversal of a symbolic term, 215 * where index = 0 corresponds to pre, index = 1 corresponds to post. For 216 * details, see getTraversalPredicate below. 217 */ 218 std::map<TypeNode, std::map<Node, Node>> d_traversal_pred[2]; 219 /** traversal applications to Boolean variables 220 * 221 * This maps each application of a traversal predicate pre_x( t ) or 222 * post_x( t ) to a fresh Boolean variable. 223 */ 224 std::map<Node, Node> d_traversal_bool; 225 /** get traversal predicate 226 * 227 * Get the predicates (pre, post) whose semantics correspond to whether 228 * a variable has occurred by this point in a (pre, post) traversal of a term. 229 * The type of getTraversalPredicate(tn, n, _) is tn -> Bool. 230 * 231 * For example, consider the term: 232 * f( x_1, g( x_2, x_3 ) ) 233 * and a left-to-right, depth-first traversal of this term. Let e be 234 * a variable of the same type as this term. We say that for the above term: 235 * pre_{x_1} is false for e, e.1 and true for e.2, e.2.1, e.2.2 236 * pre_{x_2} is false for e, e.1, e.2, e.2.1, and true for e.2.2 237 * pre_{x_3} is false for e, e.1, e.2, e.2.1, e.2.2 238 * post_{x_1} is true for e.1, e.2.1, e.2.2, e.2, e 239 * post_{x_2} is false for e.1 and true for e.2.1, e.2.2, e.2, e 240 * post_{x_3} is false for e.1, e.2.1 and true for e.2.2, e.2, e 241 * 242 * We enforce a symmetry breaking scheme for each enumerator e that is 243 * "variable-agnostic" (see argument isVarAgnostic in registerEnumerator) 244 * that ensures the variables are ordered. This scheme makes use of these 245 * predicates, described in the following: 246 * 247 * Let x_1, ..., x_m be variables that occur in the same subclass in the type 248 * of e (see TermDbSygus::getSubclassForVar). 249 * For i = 1, ..., m: 250 * // each variable does not occur initially in a traversal of e 251 * ~pre_{x_i}( e ) AND 252 * // for each subterm of e 253 * template z. 254 * // if this is variable x_i, then x_{i-1} must have already occurred 255 * is-x_i( z ) => pre_{x_{i-1}}( z ) AND 256 * for args a = 1...n 257 * // pre-definition for each argument of this term 258 * pre_{x_i}( z.a ) = a=0 ? pre_{x_i}( z ) : post_{x_i}( z.{a-1} ) AND 259 * // post-definition for this term 260 * post_{x_i}( z ) = post_{x_i}( z.n ) OR is-x_i( z ) 261 * 262 * For clarity, above we have written pre and post as first-order predicates. 263 * However, applications of pre/post should be seen as indexed Boolean 264 * variables. The reason for this is pre and post cannot be given a consistent 265 * semantics. For example, consider term f( x_1, x_1 ) and enumerator variable 266 * e of the same type over which we are encoding a traversal. We have that 267 * pre_{x_1}( e.1 ) is false and pre_{x_1}( e.2 ) is true, although the model 268 * values for e.1 and e.2 are equal. Instead, pre_{x_1}( e.1 ) should be seen 269 * as a Boolean variable V_pre_{x_1,e.1} indexed by x_1 and e.1. and likewise 270 * for e.2. We convert all applications of pre/post to Boolean variables in 271 * the method eliminateTraversalPredicates below. Nevertheless, it is 272 * important that applications pre and post are encoded as APPLY_UF 273 * applications so that they behave as expected under substitutions. For 274 * example, pre_{x_1}( z.1 ) { z -> e.2 } results in pre_{x_1}( e.2.1 ), which 275 * after eliminateTraversalPredicates is V_pre_{x_1, e.2.1}. 276 */ 277 Node getTraversalPredicate(TypeNode tn, Node n, bool isPre); 278 /** eliminate traversal predicates 279 * 280 * This replaces all applications of traversal predicates P( x ) in n with 281 * unique Boolean variables, given by d_traversal_bool[ P( x ) ], and 282 * returns the result. 283 */ 284 Node eliminateTraversalPredicates(Node n); 285 //-----------------------------------end traversal predicates 286 /** a sygus sampler object for each (anchor, sygus type) pair 287 * 288 * This is used for the sygusRewVerify() option to verify the correctness of 289 * the rewriter. 290 */ 291 std::map<Node, std::map<TypeNode, quantifiers::SygusSampler>> d_sampler; 292 /** Assert tester internal 293 * 294 * This function is called when the tester with index tindex is asserted for 295 * n, exp is the tester predicate. For example, for grammar: 296 * A -> A+A | x | 1 | 0 297 * when is_+( d ) is asserted, 298 * assertTesterInternal(0, s( d ), is_+( s( d ) ),...) is called. This 299 * function may add lemmas to lemmas, which are sent out on the output 300 * channel of datatypes by the caller. 301 * 302 * These lemmas are of various forms, including: 303 * (1) dynamic symmetry breaking clauses for subterms of n (those added to 304 * lemmas on calls to addSymBreakLemmasFor, see function below), 305 * (2) static symmetry breaking clauses for subterms of n (those added to 306 * lemmas on getSimpleSymBreakPred, see function below), 307 * (3) conjecture-specific symmetry breaking lemmas, see 308 * SynthConjecture::getSymmetryBreakingPredicate, 309 * (4) fairness conflicts if sygusFair() is SYGUS_FAIR_DIRECT, e.g.: 310 * size( d ) <= 1 V ~is-C1( d ) V ~is-C2( d.1 ) 311 * where C1 and C2 are non-nullary constructors. 312 */ 313 void assertTesterInternal( int tindex, TNode n, Node exp, std::vector< Node >& lemmas ); 314 /** 315 * This function is called when term n is registered to the theory of 316 * datatypes. It makes the appropriate call to registerSearchTerm below, 317 * if applicable. 318 */ 319 void registerTerm(Node n, std::vector<Node>& lemmas); 320 321 //------------------------dynamic symmetry breaking 322 /** Register search term 323 * 324 * This function is called when selector chain n of the form 325 * S_1( ... S_m( x ) ... ) is registered to the theory of datatypes, where 326 * tn is the type of n, d indicates the depth of n (the sum of weights of the 327 * selectors S_1...S_m), and topLevel is whether n is a top-level term 328 * (see d_is_top_level). We refer to n as a "search term". 329 * 330 * The purpose of this function is to notify this class that symmetry breaking 331 * lemmas should be instantiated for n. Any symmetry breaking lemmas that 332 * are active for n (see description of addSymBreakLemmasFor) are added to 333 * lemmas in this call. 334 */ 335 void registerSearchTerm( TypeNode tn, unsigned d, Node n, bool topLevel, std::vector< Node >& lemmas ); 336 /** Register search value 337 * 338 * This function is called when a selector chain n has been assigned a model 339 * value nv. This function calls itself recursively so that extensions of the 340 * selector chain n are registered with all the subterms of nv. For example, 341 * if we call this function with: 342 * n = x, nv = +( 1(), x() ) 343 * we make recursive calls with: 344 * n = x.1, nv = 1() and n = x.2, nv = x() 345 * 346 * a : the anchor of n, 347 * d : the depth of n. 348 * 349 * This function determines if the value nv is equivalent via rewriting to 350 * any previously registered search values for anchor a. If so, we construct 351 * a symmetry breaking lemma template and register it in d_cache[a]. For 352 * example, for grammar: 353 * A -> A+A | x | 1 | 0 354 * Registering search value d -> x followed by d -> +( x, 0 ) results in the 355 * construction of the symmetry breaking lemma template: 356 * ~is_+( z ) V ~is_x( z.1 ) V ~is_0( z.2 ) 357 * which is stored in d_cache[a].d_sb_lemmas. This lemma is instantiated with 358 * z -> t for all terms t of appropriate depth, including d. 359 * This function strengthens blocking clauses using generalization techniques 360 * described in Reynolds et al SYNT 2017. 361 * 362 * The return value of this function is an abstraction of model assignment 363 * of nv to n, or null if we wish to exclude the model assignment nv to n. 364 * The return value of this method is different from nv itself, e.g. if it 365 * contains occurrences of the "any constant" constructor. For example, if 366 * nv is C_+( C_x(), C_{any_constant}( 5 ) ), then the return value of this 367 * function will either be null, or C_+( C_x(), C_{any_constant}( n.1.0 ) ), 368 * where n.1.0 is the appropriate selector chain applied to n. We build this 369 * abstraction since the semantics of C_{any_constant} is "any constant" and 370 * not "some constant". Thus, we should consider the subterm 371 * C_{any_constant}( 5 ) above to be an unconstrained variable (as represented 372 * by a selector chain), instead of the concrete value 5. 373 * 374 * The flag isVarAgnostic is whether "a" is a variable agnostic enumerator. If 375 * this is the case, we restrict symmetry breaking to subterms of n on its 376 * leftmost subchain. For example, consider the grammar: 377 * A -> B=B 378 * B -> B+B | x | y | 0 379 * Say we are registering the search value x = y+x. Notice that this value is 380 * ordered. If a were a variable-agnostic enumerator of type A in this 381 * case, we would only register x = y+x and x, and not y+x or y, since the 382 * latter two terms are not leftmost subterms in this value. If we did on the 383 * other hand register y+x, we would be prevented from solutions like x+y = 0 384 * later, since x+y is equivalent to (the already registered value) y+x. 385 * 386 * If doSym is false, we are not performing symmetry breaking on n. This flag 387 * is set to false on branches of n that are not leftmost. 388 */ 389 Node registerSearchValue(Node a, 390 Node n, 391 Node nv, 392 unsigned d, 393 std::vector<Node>& lemmas, 394 bool isVarAgnostic, 395 bool doSym); 396 /** Register symmetry breaking lemma 397 * 398 * This function adds the symmetry breaking lemma template lem for terms of 399 * type tn with anchor a. This is added to d_cache[a].d_sb_lemmas. Notice that 400 * we use lem as a template with free variable x, e.g. our template is: 401 * (lambda ((x tn)) lem) 402 * where x = getFreeVar( tn ). For all search terms t of the appropriate 403 * depth, 404 * we add the lemma lem{ x -> t } to lemmas. 405 * 406 * The argument sz indicates the size of terms that the lemma applies to, e.g. 407 * ~is_+( z ) has size 1 408 * ~is_+( z ) V ~is_x( z.1 ) V ~is_0( z.2 ) has size 1 409 * ~is_+( z ) V ~is_+( z.1 ) has size 2 410 * This is equivalent to sum of weights of constructors corresponding to each 411 * tester, e.g. above + has weight 1, and x and 0 have weight 0. 412 */ 413 void registerSymBreakLemma( 414 TypeNode tn, Node lem, unsigned sz, Node a, std::vector<Node>& lemmas); 415 /** Register symmetry breaking lemma for value 416 * 417 * This function adds a symmetry breaking lemma template for selector chains 418 * with anchor a, that effectively states that val should never be a subterm 419 * of any value for a. 420 * 421 * et : an "invariance test" (see sygus/sygus_invariance.h) which states a 422 * criterion that val meets, which is the reason for its exclusion. This is 423 * used for generalizing the symmetry breaking lemma template. 424 * valr : if non-null, this states a value that should *not* be excluded by 425 * the symmetry breaking lemma template, which is a restriction to the above 426 * generalization. 427 * 428 * This function may add instances of the symmetry breaking template for 429 * existing search terms, which are added to lemmas. 430 */ 431 void registerSymBreakLemmaForValue(Node a, 432 Node val, 433 quantifiers::SygusInvarianceTest& et, 434 Node valr, 435 std::map<TypeNode, int>& var_count, 436 std::vector<Node>& lemmas); 437 /** Add symmetry breaking lemmas for term 438 * 439 * Adds all active symmetry breaking lemmas for selector chain t to lemmas. A 440 * symmetry breaking lemma L is active for t based on three factors: 441 * (1) the current search size sz(a) for its anchor a, 442 * (2) the depth d of term t (see d_term_to_depth), 443 * (3) the size sz(L) of the symmetry breaking lemma L. 444 * In particular, L is active if sz(L) <= sz(a) - d. In other words, a 445 * symmetry breaking lemma is active if it is intended to block terms of 446 * size sz(L), and the maximum size that t can take in the current search, 447 * sz(a)-d, is greater than or equal to this value. 448 * 449 * tn : the type of term t, 450 * a : the anchor of term t, 451 * d : the depth of term t. 452 */ 453 void addSymBreakLemmasFor( 454 TypeNode tn, Node t, unsigned d, Node a, std::vector<Node>& lemmas); 455 /** calls the above function where a is the anchor t */ 456 void addSymBreakLemmasFor( TypeNode tn, Node t, unsigned d, std::vector< Node >& lemmas ); 457 //------------------------end dynamic symmetry breaking 458 459 /** Get relevancy condition 460 * 461 * This returns (the negation of) a predicate that holds in the contexts in 462 * which the selector chain n is specified. For example, the negation of the 463 * relevancy condition for sel_{C2,1}( sel_{C1,1}( d ) ) is 464 * ~( is-C1( d ) ^ is-C2( sel_{C1,1}( d ) ) ) 465 * If shared selectors are enabled, this is a conjunction of disjunctions, 466 * since shared selectors may apply to multiple constructors. 467 */ 468 Node getRelevancyCondition( Node n ); 469 /** Cache of the above function */ 470 std::map<Node, Node> d_rlv_cond; 471 472 //------------------------static symmetry breaking 473 /** Get simple symmetry breakind predicate 474 * 475 * This function returns the "static" symmetry breaking lemma template for 476 * terms with type tn and constructor index tindex, for the given depth. This 477 * includes inferences about size with depth=0. Given grammar: 478 * A -> ite( B, A, A ) | A+A | x | 1 | 0 479 * B -> A = A 480 * Examples of static symmetry breaking lemma templates are: 481 * for +, depth 0: size(z)=size(z.1)+size(z.2)+1 482 * for +, depth 1: ~is-0( z.1 ) ^ ~is-0( z.2 ) ^ F 483 * where F ensures the constructor of z.1 is less than that of z.2 based 484 * on some ordering. 485 * for ite, depth 1: z.2 != z.3 486 * These templates can be thought of as "hard-coded" cases of dynamic symmetry 487 * breaking lemma templates. Notice that the above lemma templates are in 488 * terms of getFreeVar( tn ), hence only one is created per 489 * (constructor, depth). A static symmetry break lemma template F[z] for 490 * constructor C are included in lemmas of the form: 491 * is-C( t ) => F[t] 492 * where t is a search term, see registerSearchTerm for definition of search 493 * term. 494 * 495 * usingSymCons: whether we are using symbolic constructors for subterms in 496 * the type tn, 497 * isVarAgnostic: whether the terms we are enumerating are agnostic to 498 * variables. 499 * 500 * The latter two options may affect the form of the predicate we construct. 501 */ 502 Node getSimpleSymBreakPred(Node e, 503 TypeNode tn, 504 int tindex, 505 unsigned depth, 506 bool usingSymCons, 507 bool isVarAgnostic); 508 /** Cache of the above function */ 509 std::map<Node, 510 std::map<TypeNode, 511 std::map<int, std::map<bool, std::map<unsigned, Node>>>>> 512 d_simple_sb_pred; 513 /** 514 * For each search term, this stores the maximum depth for which we have added 515 * a static symmetry breaking lemma. 516 * 517 * This should be user context-dependent if sygus is updated to work in 518 * incremental mode. 519 */ 520 std::unordered_map<Node, unsigned, NodeHashFunction> d_simple_proc; 521 //------------------------end static symmetry breaking 522 523 /** Get the canonical free variable for type tn */ 524 TNode getFreeVar( TypeNode tn ); 525 /** get term order predicate 526 * 527 * Assuming that n1 and n2 are children of a commutative operator, this 528 * returns a symmetry breaking predicate that can be instantiated for n1 and 529 * n2 while preserving satisfiability. By default, this is the predicate 530 * ( DT_SIZE n1 ) >= ( DT_SIZE n2 ) 531 */ 532 Node getTermOrderPredicate( Node n1, Node n2 ); 533 534 private: 535 /** 536 * Map from registered variables to whether they are a sygus enumerator. 537 * 538 * This should be user context-dependent if sygus is updated to work in 539 * incremental mode. 540 */ 541 std::map<Node, bool> d_register_st; 542 //----------------------search size information 543 /** 544 * Checks whether e is a sygus enumerator, that is, a term for which this 545 * class will track size for. 546 * 547 * We associate each sygus enumerator e with a "measure term", which is used 548 * for bounding the size of terms for the models of e. The measure term for a 549 * sygus enumerator may be e itself (if e has an active guard), or an 550 * arbitrary sygus variable otherwise. A measure term m is one for which our 551 * decision strategy decides on literals of the form (DT_SYGUS_BOUND m n). 552 * 553 * After determining the measure term m for e, if applicable, we initialize 554 * SygusSizeDecisionStrategy for m below. This may result in lemmas 555 */ 556 void registerSizeTerm(Node e, std::vector<Node>& lemmas); 557 /** A decision strategy for each measure term allocated by this class */ 558 class SygusSizeDecisionStrategy : public DecisionStrategyFmf 559 { 560 public: SygusSizeDecisionStrategy(Node t,context::Context * c,Valuation valuation)561 SygusSizeDecisionStrategy(Node t, context::Context* c, Valuation valuation) 562 : DecisionStrategyFmf(c, valuation), d_this(t), d_curr_search_size(0) 563 { 564 } 565 /** the measure term */ 566 Node d_this; 567 /** 568 * For each size n, an explanation for why this measure term has size at 569 * most n. This is typically the literal (DT_SYGUS_BOUND m n), which 570 * we call the (n^th) "fairness literal" for m. 571 */ 572 std::map< unsigned, Node > d_search_size_exp; 573 /** 574 * For each size, whether we have called SygusSymBreakNew::notifySearchSize. 575 */ 576 std::map< unsigned, bool > d_search_size; 577 /** 578 * The current search size. This corresponds to the number of times 579 * incrementCurrentSearchSize has been called for this measure term. 580 */ 581 unsigned d_curr_search_size; 582 /** the list of all enumerators whose measure term is this */ 583 std::vector< Node > d_anchors; 584 /** get or make the measure value 585 * 586 * The measure value is an integer variable v that is a (symbolic) integer 587 * value that is constrained to be less than or equal to the current search 588 * size. For example, if we are using the fairness strategy 589 * SYGUS_FAIR_DT_SIZE (see options/datatype_options.h), then we constrain: 590 * (DT_SYGUS_BOUND m n) <=> (v <= n) 591 * for all asserted fairness literals. Then, if we are enforcing fairness 592 * based on the maximum size, we assert: 593 * (DT_SIZE e) <= v 594 * for all enumerators e. 595 */ 596 Node getOrMkMeasureValue(std::vector<Node>& lemmas); 597 /** get or make the active measure value 598 * 599 * The active measure value av is an integer variable that corresponds to 600 * the (symbolic) value of the sum of enumerators that are yet to be 601 * registered. This is to enforce the "sum of measures" strategy. For 602 * example, if we are using the fairness strategy SYGUS_FAIR_DT_SIZE, 603 * then initially av is equal to the measure value v, and the constraints 604 * (DT_SYGUS_BOUND m n) <=> (v <= n) 605 * are added as before. When an enumerator e is registered, we add the 606 * lemma: 607 * av = (DT_SIZE e) + av' 608 * and update the active measure value to av'. This ensures that the sum 609 * of sizes of active enumerators is at most n. 610 * 611 * If the flag mkNew is set to true, then we return a fresh variable and 612 * update the active measure value. 613 */ 614 Node getOrMkActiveMeasureValue(std::vector<Node>& lemmas, 615 bool mkNew = false); 616 /** Returns the s^th fairness literal for this measure term. */ 617 Node mkLiteral(unsigned s) override; 618 /** identify */ identify()619 std::string identify() const override 620 { 621 return std::string("sygus_enum_size"); 622 } 623 624 private: 625 /** the measure value */ 626 Node d_measure_value; 627 /** the sygus measure value */ 628 Node d_measure_value_active; 629 }; 630 /** the above information for each registered measure term */ 631 std::map<Node, std::unique_ptr<SygusSizeDecisionStrategy>> d_szinfo; 632 /** map from enumerators (anchors) to their associated measure term */ 633 std::map< Node, Node > d_anchor_to_measure_term; 634 /** map from enumerators (anchors) to their active guard*/ 635 std::map< Node, Node > d_anchor_to_active_guard; 636 /** map from enumerators (anchors) to a decision stratregy for that guard */ 637 std::map<Node, std::unique_ptr<DecisionStrategy>> d_anchor_to_ag_strategy; 638 /** generic measure term 639 * 640 * This is a global term that is used as the measure term for all sygus 641 * enumerators that do not have active guards. This class enforces that 642 * all enumerators have size at most n, where n is the minimal integer 643 * such that (DT_SYGUS_BOUND d_generic_measure_term n) is asserted. 644 */ 645 Node d_generic_measure_term; 646 /** 647 * This increments the current search size for measure term m. This may 648 * cause lemmas to be added to lemmas based on the fact that symmetry 649 * breaking lemmas are now relevant for new search terms, see discussion 650 * of how search size affects which lemmas are relevant above 651 * addSymBreakLemmasFor. 652 */ 653 void incrementCurrentSearchSize( Node m, std::vector< Node >& lemmas ); 654 /** 655 * Notify this class that we are currently searching for terms of size at 656 * most s as model values for measure term m. Literal exp corresponds to the 657 * explanation of why the measure term has size at most n. This calls 658 * incrementSearchSize above, until the total number of times we have called 659 * incrementSearchSize so far is at least s. 660 */ 661 void notifySearchSize( Node m, unsigned s, Node exp, std::vector< Node >& lemmas ); 662 /** Allocates a SygusSizeDecisionStrategy object in d_szinfo. */ 663 void registerMeasureTerm( Node m ); 664 /** 665 * Return the current search size for arbitrary term n. This is the current 666 * search size of the anchor of n. 667 */ 668 unsigned getSearchSizeFor( Node n ); 669 /** return the current search size for enumerator (anchor) e */ 670 unsigned getSearchSizeForAnchor(Node e); 671 /** Get the current search size for measure term m in this SAT context. */ 672 unsigned getSearchSizeForMeasureTerm(Node m); 673 /** get current template 674 * 675 * For debugging. This returns a term that corresponds to the current 676 * inferred shape of n. For example, if the testers 677 * is-C1( n ) and is-C2( n.1 ) 678 * have been asserted where C1 and C2 are binary constructors, then this 679 * method may return a term of the form: 680 * C1( C2( x1, x2 ), x3 ) 681 * for fresh variables x1, x2, x3. The map var_count maintains the variable 682 * count for generating these fresh variables. 683 */ 684 Node getCurrentTemplate( Node n, std::map< TypeNode, int >& var_count ); 685 //----------------------end search size information 686 /** check value 687 * 688 * This is called when we have a model assignment vn for n, where n is 689 * a selector chain applied to an enumerator (a search term). This function 690 * ensures that testers have been asserted for each subterm of vn. This is 691 * critical for ensuring that the proper steps have been taken by this class 692 * regarding whether or not vn is a legal value for n (not greater than the 693 * current search size and not a value that can be blocked by symmetry 694 * breaking). 695 * 696 * For example, if vn = +( x(), x() ), then we ensure that the testers 697 * is-+( n ), is-x( n.1 ), is-x( n.2 ) 698 * have been asserted to this class. If a tester is not asserted for some 699 * relevant selector chain S( n ) of n, then we add a lemma L for that 700 * selector chain to lemmas, where L is the "splitting lemma" for S( n ), that 701 * states that the top symbol of S( n ) must be one of the constructors of 702 * its type. 703 * 704 * Notice that this function is a sanity check. Typically, it should be the 705 * case that testers are asserted for all subterms of vn, and hence this 706 * method should not ever add anything to lemmas. However, due to its 707 * importance, we check this regardless. 708 */ 709 bool checkValue(Node n, Node vn, int ind, std::vector<Node>& lemmas); 710 /** 711 * Get the current SAT status of the guard g. 712 * In particular, this returns 1 if g is asserted true, -1 if it is asserted 713 * false, and 0 if it is not asserted. 714 */ 715 int getGuardStatus( Node g ); 716 }; 717 718 } 719 } 720 } 721 722 #endif 723 724