Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * This file is part of the cvc5 project. 3 : : * 4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS 5 : : * in the top-level source directory and their institutional affiliations. 6 : : * All rights reserved. See the file COPYING in the top-level source 7 : : * directory for licensing information. 8 : : * **************************************************************************** 9 : : * 10 : : * Implementation of algorithm suggested by Deharbe, Fontaine, Merz, 11 : : * and Paleo, "Exploiting symmetry in SMT problems," CADE 2011. 12 : : * 13 : : * From the paper: 14 : : * 15 : : * <pre> 16 : : * \f$ P := guess\_permutations(\phi) \f$ 17 : : * foreach \f$ {c_0, ..., c_n} \in P \f$ do 18 : : * if \f$ invariant\_by\_permutations(\phi, {c_0, ..., c_n}) \f$ then 19 : : * T := \f$ select\_terms(\phi, {c_0, ..., c_n}) \f$ 20 : : * cts := \f$ \emptyset \f$ 21 : : * while T != \f$ \empty \wedge |cts| <= n \f$ do 22 : : * \f$ t := select\_most\_promising\_term(T, \phi) \f$ 23 : : * \f$ T := T \setminus {t} \f$ 24 : : * cts := cts \f$ \cup used\_in(t, {c_0, ..., c_n}) \f$ 25 : : * let \f$ c \in {c_0, ..., c_n} \setminus cts \f$ 26 : : * cts := cts \f$ \cup {c} \f$ 27 : : * if cts != \f$ {c_0, ..., c_n} \f$ then 28 : : * \f$ \phi := \phi \wedge ( \vee_{c_i \in cts} t = c_i ) \f$ 29 : : * end 30 : : * end 31 : : * end 32 : : * end 33 : : * return \f$ \phi \f$ 34 : : * </pre> 35 : : */ 36 : : 37 : : #include "cvc5_private.h" 38 : : 39 : : #ifndef CVC5__THEORY__UF__SYMMETRY_BREAKER_H 40 : : #define CVC5__THEORY__UF__SYMMETRY_BREAKER_H 41 : : 42 : : #include <iostream> 43 : : #include <list> 44 : : #include <unordered_map> 45 : : #include <vector> 46 : : 47 : : #include "context/cdlist.h" 48 : : #include "context/context.h" 49 : : #include "expr/node.h" 50 : : #include "expr/node_builder.h" 51 : : #include "smt/env_obj.h" 52 : : #include "util/statistics_stats.h" 53 : : 54 : : namespace cvc5::internal { 55 : : namespace theory { 56 : : namespace uf { 57 : : 58 : : class SymmetryBreaker : protected EnvObj, public context::ContextNotifyObj 59 : : { 60 : : class Template 61 : : { 62 : : Node d_template; 63 : : NodeBuilder d_assertions; 64 : : std::unordered_map<TNode, std::set<TNode>> d_sets; 65 : : std::unordered_map<TNode, TNode> d_reps; 66 : : 67 : : TNode find(TNode n); 68 : : bool matchRecursive(TNode t, TNode n); 69 : : 70 : : public: 71 : : Template(NodeManager* nm); 72 : : bool match(TNode n); 73 : 91265 : std::unordered_map<TNode, std::set<TNode>>& partitions() { return d_sets; } 74 : : Node assertions() 75 : : { 76 : : switch (d_assertions.getNumChildren()) 77 : : { 78 : : case 0: return Node::null(); 79 : : case 1: return d_assertions[0]; 80 : : default: return Node(d_assertions); 81 : : } 82 : : } 83 : : void reset(); 84 : : }; /* class SymmetryBreaker::Template */ 85 : : 86 : : public: 87 : : typedef std::set<TNode> Permutation; 88 : : typedef std::set<Permutation> Permutations; 89 : : typedef TNode Term; 90 : : typedef std::list<Term> Terms; 91 : : typedef std::set<Term> TermEq; 92 : : typedef std::unordered_map<Term, TermEq> TermEqs; 93 : : 94 : : private: 95 : : /** 96 : : * This class wasn't initially built to be incremental. It should 97 : : * be attached to a UserContext so that it clears everything when 98 : : * a pop occurs. This "assertionsToRerun" is a set of assertions to 99 : : * feed back through assertFormula() when we started getting things 100 : : * again. It's not just a matter of effectiveness, but also soundness; 101 : : * if some assertions (still in scope) are not seen by a symmetry-breaking 102 : : * round, then some symmetries that don't actually exist might be broken, 103 : : * leading to unsound results! 104 : : */ 105 : : context::CDList<Node> d_assertionsToRerun; 106 : : bool d_rerunningAssertions; 107 : : 108 : : std::vector<Node> d_phi; 109 : : std::set<TNode> d_phiSet; 110 : : Permutations d_permutations; 111 : : Terms d_terms; 112 : : Template d_template; 113 : : std::unordered_map<Node, Node> d_normalizationCache; 114 : : TermEqs d_termEqs; 115 : : TermEqs d_termEqsOnly; 116 : : 117 : : void clear(); 118 : : void rerunAssertionsIfNecessary(); 119 : : 120 : : void guessPermutations(); 121 : : bool invariantByPermutations(const Permutation& p); 122 : : void selectTerms(const Permutation& p); 123 : : Terms::iterator selectMostPromisingTerm(Terms& terms); 124 : : void insertUsedIn(Term term, const Permutation& p, std::set<Node>& cts); 125 : : Node normInternal(TNode phi, size_t level); 126 : : Node norm(TNode n); 127 : : 128 : : std::string d_name; 129 : : 130 : : // === STATISTICS === 131 : : /** number of new clauses that come from the SymmetryBreaker */ 132 : : struct Statistics 133 : : { 134 : : /** number of new clauses that come from the SymmetryBreaker */ 135 : : IntStat d_clauses; 136 : : IntStat d_units; 137 : : /** number of potential permutation sets we found */ 138 : : IntStat d_permutationSetsConsidered; 139 : : /** number of invariant permutation sets we found */ 140 : : IntStat d_permutationSetsInvariant; 141 : : /** time spent in invariantByPermutations() */ 142 : : TimerStat d_invariantByPermutationsTimer; 143 : : /** time spent in selectTerms() */ 144 : : TimerStat d_selectTermsTimer; 145 : : /** time spent in initial round of normalization */ 146 : : TimerStat d_initNormalizationTimer; 147 : : 148 : : Statistics(StatisticsRegistry& sr, const std::string& name); 149 : : }; 150 : : 151 : : Statistics d_stats; 152 : : 153 : : protected: 154 : 33056 : void contextNotifyPop() override 155 : : { 156 [ + - ]: 33056 : Trace("ufsymm") << "UFSYMM: clearing state due to pop" << std::endl; 157 : 33056 : clear(); 158 : 33056 : } 159 : : 160 : : public: 161 : : SymmetryBreaker(Env& env, std::string name = ""); 162 : : 163 : : void assertFormula(TNode phi); 164 : : void apply(std::vector<Node>& newClauses); 165 : : 166 : : }; /* class SymmetryBreaker */ 167 : : 168 : : } // namespace uf 169 : : } // namespace theory 170 : : 171 : : std::ostream& operator<<( 172 : : std::ostream& out, 173 : : const cvc5::internal::theory::uf::SymmetryBreaker::Permutation& p); 174 : : 175 : : } // namespace cvc5::internal 176 : : 177 : : #endif /* CVC5__THEORY__UF__SYMMETRY_BREAKER_H */