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