GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/abstraction.h Lines: 8 35 22.9 %
Date: 2021-09-18 Branches: 2 50 4.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Tim King, Mathias Preiner
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
 * Bitvector theory.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__BV__ABSTRACTION_H
19
#define CVC5__THEORY__BV__ABSTRACTION_H
20
21
#include <unordered_map>
22
#include <unordered_set>
23
24
#include "expr/node.h"
25
#include "theory/substitutions.h"
26
#include "util/statistics_stats.h"
27
28
namespace cvc5 {
29
namespace theory {
30
namespace bv {
31
32
typedef std::vector<TNode> ArgsVec;
33
34
4
class AbstractionModule {
35
  using NodeVecMap = std::unordered_map<Node, std::vector<Node>>;
36
  using NodeTNodeMap = std::unordered_map<Node, TNode>;
37
  using TNodeTNodeMap = std::unordered_map<TNode, TNode>;
38
  using NodeNodeMap = std::unordered_map<Node, Node>;
39
  using TNodeNodeMap = std::unordered_map<Node, TNode>;
40
  using TNodeSet = std::unordered_set<TNode>;
41
  using IntNodeMap = std::unordered_map<unsigned, Node>;
42
  using IndexMap = std::unordered_map<unsigned, unsigned>;
43
  using SkolemMap = std::unordered_map<unsigned, std::vector<Node> >;
44
  using SignatureMap = std::unordered_map<TNode, unsigned>;
45
46
4
  struct Statistics {
47
    SizeStat<NodeNodeMap> d_numFunctionsAbstracted;
48
    IntStat d_numArgsSkolemized;
49
    TimerStat d_abstractionTime;
50
    Statistics(const std::string& name, const NodeNodeMap& functionsAbstracted);
51
  };
52
53
54
  class ArgsTableEntry {
55
    std::vector<ArgsVec> d_data;
56
    unsigned d_arity;
57
  public:
58
    ArgsTableEntry(unsigned n)
59
      : d_arity(n)
60
    {}
61
    ArgsTableEntry()
62
      : d_arity(0)
63
    {}
64
    void addArguments(const ArgsVec& args);
65
    typedef std::vector<ArgsVec>::iterator iterator;
66
67
    iterator begin() { return d_data.begin(); }
68
    iterator end() { return d_data.end(); }
69
    unsigned getArity() { return d_arity; }
70
    unsigned getNumEntries() { return d_data.size(); }
71
    ArgsVec& getEntry(unsigned i)
72
    {
73
      Assert(i < d_data.size());
74
      return d_data[i];
75
    }
76
  };
77
78
4
  class ArgsTable {
79
    std::unordered_map<TNode, ArgsTableEntry> d_data;
80
    bool hasEntry(TNode signature) const;
81
  public:
82
   typedef std::unordered_map<TNode, ArgsTableEntry>::iterator iterator;
83
4
   ArgsTable() {}
84
   void addEntry(TNode signature, const ArgsVec& args);
85
   ArgsTableEntry& getEntry(TNode signature);
86
   iterator begin() { return d_data.begin(); }
87
   iterator end() { return d_data.end(); }
88
  };
89
90
  /**
91
   * Checks if one pattern is a generalization of the other
92
   *
93
   * @param s
94
   * @param t
95
   *
96
   * @return 1 if s :> t, 2 if s <: t, 0 if they equivalent and -1 if they are incomparable
97
   */
98
  static int comparePatterns(TNode s, TNode t);
99
100
  class LemmaInstantiatior {
101
    std::vector<TNode> d_functions;
102
    std::vector<int> d_maxMatch;
103
    ArgsTable& d_argsTable;
104
    context::Context* d_ctx;
105
    theory::SubstitutionMap d_subst;
106
    TNode d_conflict;
107
    std::vector<Node> d_lemmas;
108
109
    void backtrack(std::vector<int>& stack);
110
    int next(int val, int index);
111
    bool isConsistent(const std::vector<int>& stack);
112
    bool accept(const std::vector<int>& stack);
113
    void mkLemma();
114
  public:
115
    LemmaInstantiatior(const std::vector<TNode>& functions, ArgsTable& table, TNode conflict)
116
      : d_functions(functions)
117
      , d_argsTable(table)
118
      , d_ctx(new context::Context())
119
      , d_subst(d_ctx)
120
      , d_conflict(conflict)
121
      , d_lemmas()
122
    {
123
      Debug("bv-abstraction-gen") << "LemmaInstantiator conflict:" << conflict << "\n";
124
      // initializing the search space
125
      for (unsigned i = 0; i < functions.size(); ++i) {
126
        TNode func_op = functions[i].getOperator();
127
        // number of matches for this function
128
        unsigned maxCount = table.getEntry(func_op).getNumEntries();
129
        d_maxMatch.push_back(maxCount);
130
      }
131
    }
132
133
    void generateInstantiations(std::vector<Node>& lemmas);
134
135
  };
136
137
  ArgsTable d_argsTable;
138
139
  // mapping between signature and uninterpreted function symbol used to
140
  // abstract the signature
141
  NodeNodeMap d_signatureToFunc;
142
  NodeNodeMap d_funcToSignature;
143
144
  NodeNodeMap d_assertionToSignature;
145
  SignatureMap d_signatures;
146
  NodeNodeMap d_sigToGeneralization;
147
  TNodeSet d_skolems;
148
149
  // skolems maps
150
  IndexMap d_signatureIndices;
151
  SkolemMap d_signatureSkolems;
152
153
  void collectArgumentTypes(TNode sig, std::vector<TypeNode>& types, TNodeSet& seen);
154
  void collectArguments(TNode node, TNode sig, std::vector<Node>& args, TNodeSet& seen);
155
  void finalizeSignatures();
156
  Node abstractSignatures(TNode assertion);
157
  Node computeSignature(TNode node);
158
159
  bool isConjunctionOfAtoms(TNode node, TNodeSet& seen);
160
161
  TNode getGeneralization(TNode term);
162
  void storeGeneralization(TNode s, TNode t);
163
164
  // signature skolem stuff
165
  Node getGeneralizedSignature(Node node);
166
  Node getSignatureSkolem(TNode node);
167
168
  unsigned getBitwidthIndex(unsigned bitwidth);
169
  void resetSignatureIndex();
170
  Node computeSignatureRec(TNode, NodeNodeMap&);
171
  void storeSignature(Node signature, TNode assertion);
172
  bool hasSignature(Node node);
173
174
  Node substituteArguments(TNode signature, TNode apply, unsigned& i, TNodeTNodeMap& seen);
175
176
  // crazy instantiation methods
177
  void generateInstantiations(unsigned current,
178
                              std::vector<ArgsTableEntry>& matches,
179
                              std::vector<std::vector<ArgsVec> >& instantiations,
180
                              std::vector<std::vector<ArgsVec> >& new_instantiations);
181
182
  Node tryMatching(const std::vector<Node>& ss, const std::vector<TNode>& tt, TNode conflict);
183
  void makeFreshArgs(TNode func, std::vector<Node>& fresh_args);
184
  void makeFreshSkolems(TNode node, SubstitutionMap& map, SubstitutionMap& reverse_map);
185
186
  void skolemizeArguments(std::vector<Node>& assertions);
187
  Node reverseAbstraction(Node assertion, NodeNodeMap& seen);
188
189
  TNodeSet d_addedLemmas;
190
  TNodeSet d_lemmaAtoms;
191
  TNodeSet d_inputAtoms;
192
  void storeLemma(TNode lemma);
193
194
  Statistics d_statistics;
195
196
public:
197
4
 AbstractionModule(const std::string& name)
198
4
     : d_argsTable(),
199
       d_signatureToFunc(),
200
       d_funcToSignature(),
201
       d_assertionToSignature(),
202
       d_signatures(),
203
       d_sigToGeneralization(),
204
       d_skolems(),
205
       d_signatureIndices(),
206
       d_signatureSkolems(),
207
       d_addedLemmas(),
208
       d_lemmaAtoms(),
209
       d_inputAtoms(),
210
4
       d_statistics(name + "abstraction::", d_signatureToFunc)
211
 {
212
4
 }
213
  /**
214
   * returns true if there are new uninterepreted functions symbols in the output
215
   *
216
   * @param assertions
217
   * @param new_assertions
218
   *
219
   * @return
220
   */
221
  bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
222
  /**
223
   * Returns true if the node represents an abstraction predicate.
224
   *
225
   * @param node
226
   *
227
   * @return
228
   */
229
  bool isAbstraction(TNode node);
230
  /**
231
   * Returns the interpretation of the abstraction predicate.
232
   *
233
   * @param node
234
   *
235
   * @return
236
   */
237
  Node getInterpretation(TNode node);
238
  Node simplifyConflict(TNode conflict);
239
  void generalizeConflict(TNode conflict, std::vector<Node>& lemmas);
240
  void addInputAtom(TNode atom);
241
  bool isLemmaAtom(TNode node) const;
242
};
243
244
}
245
}
246
}  // namespace cvc5
247
248
#endif