summaryrefslogtreecommitdiff
path: root/src/theory/rewriterules/rr_inst_match.h
blob: 3ec9438fd9e2e0715efa7522678177e8903c7d92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*********************                                                        */
/*! \file rr_inst_match.h
 ** \verbatim
 ** Original author: Morgan Deters
 ** Major contributors: Francois Bobot
 ** Minor contributors (to current version): Andrew Reynolds
 ** This file is part of the CVC4 project.
 ** Copyright (c) 2009-2013  New York University and The University of Iowa
 ** See the file COPYING in the top-level source directory for licensing
 ** information.\endverbatim
 **
 ** \brief inst match class
 **/

#include "cvc4_private.h"

#ifndef __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_H
#define __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_H

#include "theory/theory.h"
#include "util/hash.h"
#include "util/ntuple.h"

#include <ext/hash_set>
#include <iostream>
#include <map>

#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf.h"
#include "context/cdlist.h"

#include "theory/quantifiers/inst_match.h"
#include "theory/quantifiers/term_database.h"
#include "expr/node_manager.h"
#include "expr/node_builder.h"

#include "theory/quantifiers/options.h"
#include "theory/rewriterules/options.h"

//#define USE_EFFICIENT_E_MATCHING

namespace CVC4 {
namespace theory {

namespace rrinst{

class CandidateGenerator
{
public:
  CandidateGenerator(){}
  virtual ~CandidateGenerator(){};

  /** Get candidates functions.  These set up a context to get all match candidates.
      cg->reset( eqc );
      do{
        Node cand = cg->getNextCandidate();
        //.......
      }while( !cand.isNull() );

      eqc is the equivalence class you are searching in
  */
  virtual void reset( TNode eqc ) = 0;
  virtual TNode getNextCandidate() = 0;
  /** call this at the beginning of each instantiation round */
  virtual void resetInstantiationRound() = 0;
public:
  /** legal candidate */
  static inline bool isLegalCandidate( TNode n ){
    return !n.getAttribute(NoMatchAttribute()) &&
      ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute())) &&
      ( !options::efficientEMatching() || n.hasAttribute(AvailableInTermDb()) );
}

};


inline std::ostream& operator<<(std::ostream& out, const InstMatch& m) {
  m.toStream(out);
  return out;
}

template<bool modEq = false> class InstMatchTrie2;
template<bool modEq = false> class InstMatchTrie2Pairs;

template<bool modEq = false>
class InstMatchTrie2Gen
{
  friend class InstMatchTrie2<modEq>;
  friend class InstMatchTrie2Pairs<modEq>;

private:

  class Tree {
  public:
    typedef std::hash_map< Node, Tree *, NodeHashFunction > MLevel;
    MLevel e;
    const size_t level; //context level of creation
    Tree() CVC4_UNDEFINED;
    const Tree & operator =(const Tree & t){
      Assert(t.e.empty()); Assert(e.empty());
      Assert(t.level == level);
      return t;
    }
    Tree(size_t l): level(l) {};
    ~Tree(){
      for(typename MLevel::iterator i = e.begin(); i!=e.end(); ++i)
        delete(i->second);
    };
  };


  typedef std::pair<Tree *, TNode> Mod;

  class CleanUp{
  public:
    inline void operator()(Mod * m){
      typename Tree::MLevel::iterator i = m->first->e.find(m->second);
      Assert (i != m->first->e.end()); //should not have been already removed
      m->first->e.erase(i);
    };
  };

  EqualityQuery* d_eQ;
  CandidateGenerator * d_cG;

  context::Context* d_context;
  context::CDList<Mod, CleanUp, std::allocator<Mod> > d_mods;


  typedef std::map<Node, Node>::const_iterator mapIter;

  /** add the substitution given by the iterator*/
  void addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel);
  /** test if it exists match, modulo uf-equations if modEq is true if
   *  return false the deepest point of divergence is put in [e] and
   *  [diverge].
   */
  bool existsInstMatch( Tree * root,
                        mapIter & current, mapIter & end,
                        Tree * & e, mapIter & diverge) const;

  /** add match m in the trie root
      return true if it was never seen */
  bool addInstMatch( InstMatch& m, Tree * root);

public:
  InstMatchTrie2Gen(context::Context* c,  QuantifiersEngine* q);
  InstMatchTrie2Gen(const InstMatchTrie2Gen &) CVC4_UNDEFINED;
  const InstMatchTrie2Gen & operator =(const InstMatchTrie2Gen & e) CVC4_UNDEFINED;
};

template<bool modEq>
class InstMatchTrie2
{
  typename InstMatchTrie2Gen<modEq>::Tree d_data;
  InstMatchTrie2Gen<modEq> d_backtrack;
public:
  InstMatchTrie2(context::Context* c,  QuantifiersEngine* q): d_data(0),
                                                              d_backtrack(c,q) {};
  InstMatchTrie2(const InstMatchTrie2 &) CVC4_UNDEFINED;
  const InstMatchTrie2 & operator =(const InstMatchTrie2 & e) CVC4_UNDEFINED;
  /** add match m in the trie,
      return true if it was never seen */
  inline bool addInstMatch( InstMatch& m){
    return d_backtrack.addInstMatch(m,&d_data);
  };

};/* class InstMatchTrie2 */

class Matcher
{
public:
  /** reset instantiation round (call this whenever equivalence classes have changed) */
  virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
  /** reset the term to match, return false if there is no such term */
  virtual bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ) = 0;
  /** get the next match. If it return false once you shouldn't call
      getNextMatch again before doing a reset */
  virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
  /** If reset, or getNextMatch return false they remove from the
      InstMatch the binding that they have previously created */

  /** virtual Matcher in order to have defined behavior */
  virtual ~Matcher(){};
};


class ApplyMatcher: public Matcher{
private:
  /** What to check first: constant and variable */
  std::vector< triple< TNode,size_t,EqualityQuery* > > d_constants;
  std::vector< triple< TNode,size_t,EqualityQuery* > > d_variables;
  /** children generators, only the sub-pattern which are
      neither a variable neither a constant appears */
  std::vector< triple< Matcher*, size_t, EqualityQuery* > > d_childrens;
  /** the variable that have been set by this matcher (during its own reset) */
  std::vector< TNode > d_binded; /* TNode because the variable are already in d_pattern */
  /** the representative of the argument of the term given by the last reset */
  std::vector< Node > d_reps;
public:
  /** The pattern we are producing matches for */
  Node d_pattern;
public:
  /** constructors */
  ApplyMatcher( Node pat, QuantifiersEngine* qe);
  /** destructor */
  ~ApplyMatcher(){/*TODO delete dandling pointers? */}
  /** reset instantiation round (call this whenever equivalence classes have changed) */
  void resetInstantiationRound( QuantifiersEngine* qe );
  /** reset the term to match */
  bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
  /** get the next match. */
  bool getNextMatch(InstMatch& m, QuantifiersEngine* qe);
private:
  bool getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset);
};


/* Match literal so you don't choose the equivalence class( */
class PatMatcher
{
public:
  /** reset instantiation round (call this whenever equivalence classes have changed) */
  virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
  /** reset the matcher, return false if there is no such term */
  virtual bool reset( InstMatch& m, QuantifiersEngine* qe ) = 0;
  /** get the next match. If it return false once you shouldn't call
      getNextMatch again before doing a reset */
  virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
  /** If reset, or getNextMatch return false they remove from the
      InstMatch the binding that they have previously created */
};

Matcher* mkMatcher( Node pat, QuantifiersEngine* qe );
PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe );

/* Match literal so you don't choose the equivalence class( */
class PatsMatcher
{
public:
  /** reset instantiation round (call this whenever equivalence classes have changed) */
  virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
  /** reset the matcher, return false if there is no such term */
  virtual bool getNextMatch( QuantifiersEngine* qe ) = 0;
  virtual const InstMatch& getInstMatch() = 0;
  /** Add directly the instantiation to quantifiers engine */
  virtual int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe) = 0;
};

PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe );
PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe );

/** return true if whatever Node is substituted for the variables the
    given Node can't match the pattern */
bool nonunifiable( TNode t, TNode pat, const std::vector<Node> & vars);

class InstMatchGenerator;

}/* CVC4::theory rrinst */

}/* CVC4::theory namespace */

}/* CVC4 namespace */

#endif /* __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_H */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback