GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/uf/symmetry_breaker.h Lines: 7 7 100.0 %
Date: 2021-08-06 Branches: 4 8 50.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Morgan Deters, Liana Hadarean, Tim King
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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/smt_statistics_registry.h"
55
#include "util/statistics_stats.h"
56
57
namespace cvc5 {
58
namespace theory {
59
namespace uf {
60
61
9853
class SymmetryBreaker : public context::ContextNotifyObj {
62
63
16581
  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();
74
    bool match(TNode n);
75
28522
    std::unordered_map<TNode, std::set<TNode>>& partitions() { return d_sets; }
76
    Node assertions() {
77
      switch(d_assertions.getNumChildren()) {
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
88
  typedef std::set<TNode> Permutation;
89
  typedef std::set<Permutation> Permutations;
90
  typedef TNode Term;
91
  typedef std::list<Term> Terms;
92
  typedef std::set<Term> TermEq;
93
  typedef std::unordered_map<Term, TermEq> TermEqs;
94
95
 private:
96
  /**
97
   * This class wasn't initially built to be incremental.  It should
98
   * be attached to a UserContext so that it clears everything when
99
   * a pop occurs.  This "assertionsToRerun" is a set of assertions to
100
   * feed back through assertFormula() when we started getting things
101
   * again.  It's not just a matter of effectiveness, but also soundness;
102
   * if some assertions (still in scope) are not seen by a symmetry-breaking
103
   * round, then some symmetries that don't actually exist might be broken,
104
   * leading to unsound results!
105
   */
106
  context::CDList<Node> d_assertionsToRerun;
107
  bool d_rerunningAssertions;
108
109
  std::vector<Node> d_phi;
110
  std::set<TNode> d_phiSet;
111
  Permutations d_permutations;
112
  Terms d_terms;
113
  Template d_template;
114
  std::unordered_map<Node, Node> d_normalizationCache;
115
  TermEqs d_termEqs;
116
  TermEqs d_termEqsOnly;
117
118
  void clear();
119
  void rerunAssertionsIfNecessary();
120
121
  void guessPermutations();
122
  bool invariantByPermutations(const Permutation& p);
123
  void selectTerms(const Permutation& p);
124
  Terms::iterator selectMostPromisingTerm(Terms& terms);
125
  void insertUsedIn(Term term, const Permutation& p, std::set<Node>& cts);
126
  Node normInternal(TNode phi, size_t level);
127
  Node norm(TNode n);
128
129
  std::string d_name;
130
131
  // === STATISTICS ===
132
  /** number of new clauses that come from the SymmetryBreaker */
133
  struct Statistics {
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(const std::string& name);
149
  };
150
151
  Statistics d_stats;
152
153
 protected:
154
14783
  void contextNotifyPop() override
155
  {
156
14783
    Debug("ufsymm") << "UFSYMM: clearing state due to pop" << std::endl;
157
14783
    clear();
158
14783
  }
159
160
 public:
161
  SymmetryBreaker(context::Context* context, 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::theory::uf::SymmetryBreaker::Permutation& p);
174
175
}  // namespace cvc5
176
177
#endif /* CVC5__THEORY__UF__SYMMETRY_BREAKER_H */