1 /*********************                                                        */
2 /*! \file inst_match_trie.h
3  ** \verbatim
4  ** Top contributors (to current version):
5  **   Andrew Reynolds, Morgan Deters, Tim King
6  ** This file is part of the CVC4 project.
7  ** Copyright (c) 2009-2019 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.\endverbatim
11  **
12  ** \brief inst match class
13  **/
14 
15 #include "cvc4_private.h"
16 
17 #ifndef __CVC4__THEORY__QUANTIFIERS__INST_MATCH_TRIE_H
18 #define __CVC4__THEORY__QUANTIFIERS__INST_MATCH_TRIE_H
19 
20 #include <map>
21 
22 #include "context/cdlist.h"
23 #include "context/cdo.h"
24 #include "expr/node.h"
25 #include "theory/quantifiers/inst_match.h"
26 
27 namespace CVC4 {
28 namespace theory {
29 
30 class QuantifiersEngine;
31 class EqualityQuery;
32 
33 namespace inst {
34 
35 /** trie for InstMatch objects
36  *
37  * This class is used for storing instantiations of a quantified formula q.
38  * It is a trie data structure for which entries can be added and removed.
39  * This class has interfaces for adding instantiations that are either
40  * represented by std::vectors or InstMatch objects (see inst_match.h).
41  */
42 class InstMatchTrie
43 {
44  public:
45   /** index ordering */
46   class ImtIndexOrder
47   {
48    public:
49     std::vector<unsigned> d_order;
50   };
51 
52  public:
InstMatchTrie()53   InstMatchTrie() {}
~InstMatchTrie()54   ~InstMatchTrie() {}
55   /** exists inst match
56    *
57    * This method considers the entry given by m, starting at the given index.
58    * The domain of m is the bound variables of quantified formula q.
59    * It returns true if (the suffix) of m exists in this trie.
60    * If modEq is true, we check for duplication modulo equality the current
61    * equalities in the active equality engine of qe.
62    */
63   bool existsInstMatch(QuantifiersEngine* qe,
64                        Node q,
65                        InstMatch& m,
66                        bool modEq = false,
67                        ImtIndexOrder* imtio = NULL,
68                        unsigned index = 0)
69   {
70     return !addInstMatch(qe, q, m, modEq, imtio, true, index);
71   }
72   /** exists inst match, vector version */
73   bool existsInstMatch(QuantifiersEngine* qe,
74                        Node q,
75                        std::vector<Node>& m,
76                        bool modEq = false,
77                        ImtIndexOrder* imtio = NULL,
78                        unsigned index = 0)
79   {
80     return !addInstMatch(qe, q, m, modEq, imtio, true, index);
81   }
82   /** add inst match
83    *
84    * This method adds (the suffix of) m starting at the given index to this
85    * trie, and returns true if and only if m did not already occur in this trie.
86    * The domain of m is the bound variables of quantified formula q.
87    * If modEq is true, we check for duplication modulo equality the current
88    * equalities in the active equality engine of qe.
89    */
90   bool addInstMatch(QuantifiersEngine* qe,
91                     Node q,
92                     InstMatch& m,
93                     bool modEq = false,
94                     ImtIndexOrder* imtio = NULL,
95                     bool onlyExist = false,
96                     unsigned index = 0)
97   {
98     return addInstMatch(qe, q, m.d_vals, modEq, imtio, onlyExist, index);
99   }
100   /** add inst match, vector version */
101   bool addInstMatch(QuantifiersEngine* qe,
102                     Node f,
103                     std::vector<Node>& m,
104                     bool modEq = false,
105                     ImtIndexOrder* imtio = NULL,
106                     bool onlyExist = false,
107                     unsigned index = 0);
108   /** remove inst match
109    *
110    * This removes (the suffix of) m starting at the given index from this trie.
111    * It returns true if and only if this entry existed in this trie.
112    * The domain of m is the bound variables of quantified formula q.
113    */
114   bool removeInstMatch(Node f,
115                        std::vector<Node>& m,
116                        ImtIndexOrder* imtio = NULL,
117                        unsigned index = 0);
118   /** record instantiation lemma
119    *
120    * This records that the instantiation lemma lem corresponds to the entry
121    * given by (the suffix of) m starting at the given index.
122    */
123   bool recordInstLemma(Node q,
124                        std::vector<Node>& m,
125                        Node lem,
126                        ImtIndexOrder* imtio = NULL,
127                        unsigned index = 0);
128 
129   /** get instantiations
130    *
131    * This gets the set of instantiation lemmas that were recorded in this trie
132    * via calls to recordInstLemma. If useActive is true, we only add
133    * instantiations that occur in active.
134    */
getInstantiations(std::vector<Node> & insts,Node q,QuantifiersEngine * qe,bool useActive,std::vector<Node> & active)135   void getInstantiations(std::vector<Node>& insts,
136                          Node q,
137                          QuantifiersEngine* qe,
138                          bool useActive,
139                          std::vector<Node>& active)
140   {
141     std::vector<Node> terms;
142     getInstantiations(insts, q, terms, qe, useActive, active);
143   }
144   /** get explanation for inst lemmas
145    *
146    * This gets the explanation for the instantiation lemmas in lems for
147    * quantified formula q, for which this trie stores instantiation matches for.
148    * For each instantiation lemma lem recording in this trie via calls to
149    * recordInstLemma, we map lem to q in map quant, and lem to its corresponding
150    * vector of terms in tvec.
151    */
getExplanationForInstLemmas(Node q,const std::vector<Node> & lems,std::map<Node,Node> & quant,std::map<Node,std::vector<Node>> & tvec)152   void getExplanationForInstLemmas(
153       Node q,
154       const std::vector<Node>& lems,
155       std::map<Node, Node>& quant,
156       std::map<Node, std::vector<Node> >& tvec) const
157   {
158     std::vector<Node> terms;
159     getExplanationForInstLemmas(q, terms, lems, quant, tvec);
160   }
161 
162   /** clear the data of this class */
clear()163   void clear() { d_data.clear(); }
164   /** print this class */
print(std::ostream & out,Node q,bool & firstTime,bool useActive,std::vector<Node> & active)165   void print(std::ostream& out,
166              Node q,
167              bool& firstTime,
168              bool useActive,
169              std::vector<Node>& active) const
170   {
171     std::vector<TNode> terms;
172     print(out, q, terms, firstTime, useActive, active);
173   }
174   /** the data */
175   std::map<Node, InstMatchTrie> d_data;
176 
177  private:
178   /** helper for print
179    * terms accumulates the path we are on in the trie.
180    */
181   void print(std::ostream& out,
182              Node q,
183              std::vector<TNode>& terms,
184              bool& firstTime,
185              bool useActive,
186              std::vector<Node>& active) const;
187   /** helper for get instantiations
188    * terms accumulates the path we are on in the trie.
189    */
190   void getInstantiations(std::vector<Node>& insts,
191                          Node q,
192                          std::vector<Node>& terms,
193                          QuantifiersEngine* qe,
194                          bool useActive,
195                          std::vector<Node>& active) const;
196   /** helper for get explantaion for inst lemmas
197    * terms accumulates the path we are on in the trie.
198    */
199   void getExplanationForInstLemmas(
200       Node q,
201       std::vector<Node>& terms,
202       const std::vector<Node>& lems,
203       std::map<Node, Node>& quant,
204       std::map<Node, std::vector<Node> >& tvec) const;
205   /** set instantiation lemma at this node in the trie */
setInstLemma(Node n)206   void setInstLemma(Node n)
207   {
208     d_data.clear();
209     d_data[n].clear();
210   }
211   /** does this node of the trie store an instantiation lemma? */
hasInstLemma()212   bool hasInstLemma() const { return !d_data.empty(); }
213   /** get the instantiation lemma stored in this node of the trie */
getInstLemma()214   Node getInstLemma() const { return d_data.begin()->first; }
215 };
216 
217 /** trie for InstMatch objects
218  *
219  * This is a context-dependent version of the above class.
220  */
221 class CDInstMatchTrie
222 {
223  public:
CDInstMatchTrie(context::Context * c)224   CDInstMatchTrie(context::Context* c) : d_valid(c, false) {}
225   ~CDInstMatchTrie();
226 
227   /** exists inst match
228    *
229    * This method considers the entry given by m, starting at the given index.
230    * The domain of m is the bound variables of quantified formula q.
231    * It returns true if (the suffix) of m exists in this trie.
232    * If modEq is true, we check for duplication modulo equality the current
233    * equalities in the active equality engine of qe.
234    * It additionally takes a context c, for which the entry is valid in.
235    */
236   bool existsInstMatch(QuantifiersEngine* qe,
237                        Node q,
238                        InstMatch& m,
239                        context::Context* c,
240                        bool modEq = false,
241                        unsigned index = 0)
242   {
243     return !addInstMatch(qe, q, m, c, modEq, index, true);
244   }
245   /** exists inst match, vector version */
246   bool existsInstMatch(QuantifiersEngine* qe,
247                        Node q,
248                        std::vector<Node>& m,
249                        context::Context* c,
250                        bool modEq = false,
251                        unsigned index = 0)
252   {
253     return !addInstMatch(qe, q, m, c, modEq, index, true);
254   }
255   /** add inst match
256    *
257    * This method adds (the suffix of) m starting at the given index to this
258    * trie, and returns true if and only if m did not already occur in this trie.
259    * The domain of m is the bound variables of quantified formula q.
260    * If modEq is true, we check for duplication modulo equality the current
261    * equalities in the active equality engine of qe.
262    * It additionally takes a context c, for which the entry is valid in.
263    */
264   bool addInstMatch(QuantifiersEngine* qe,
265                     Node q,
266                     InstMatch& m,
267                     context::Context* c,
268                     bool modEq = false,
269                     unsigned index = 0,
270                     bool onlyExist = false)
271   {
272     return addInstMatch(qe, q, m.d_vals, c, modEq, index, onlyExist);
273   }
274   /** add inst match, vector version */
275   bool addInstMatch(QuantifiersEngine* qe,
276                     Node q,
277                     std::vector<Node>& m,
278                     context::Context* c,
279                     bool modEq = false,
280                     unsigned index = 0,
281                     bool onlyExist = false);
282   /** remove inst match
283    *
284    * This removes (the suffix of) m starting at the given index from this trie.
285    * It returns true if and only if this entry existed in this trie.
286    * The domain of m is the bound variables of quantified formula q.
287    */
288   bool removeInstMatch(Node q, std::vector<Node>& m, unsigned index = 0);
289   /** record instantiation lemma
290    *
291    * This records that the instantiation lemma lem corresponds to the entry
292    * given by (the suffix of) m starting at the given index.
293    */
294   bool recordInstLemma(Node q,
295                        std::vector<Node>& m,
296                        Node lem,
297                        unsigned index = 0);
298 
299   /** get instantiations
300    *
301    * This gets the set of instantiation lemmas that were recorded in this class
302    * via calls to recordInstLemma. If useActive is true, we only add
303    * instantiations that occur in active.
304    */
getInstantiations(std::vector<Node> & insts,Node q,QuantifiersEngine * qe,bool useActive,std::vector<Node> & active)305   void getInstantiations(std::vector<Node>& insts,
306                          Node q,
307                          QuantifiersEngine* qe,
308                          bool useActive,
309                          std::vector<Node>& active)
310   {
311     std::vector<Node> terms;
312     getInstantiations(insts, q, terms, qe, useActive, active);
313   }
314   /** get explanation for inst lemmas
315    *
316    * This gets the explanation for the instantiation lemmas in lems for
317    * quantified formula q, for which this trie stores instantiation matches for.
318    * For each instantiation lemma lem recording in this trie via calls to
319    * recordInstLemma, we map lem to q in map quant, and lem to its corresponding
320    * vector of terms in tvec.
321    */
getExplanationForInstLemmas(Node q,const std::vector<Node> & lems,std::map<Node,Node> & quant,std::map<Node,std::vector<Node>> & tvec)322   void getExplanationForInstLemmas(
323       Node q,
324       const std::vector<Node>& lems,
325       std::map<Node, Node>& quant,
326       std::map<Node, std::vector<Node> >& tvec) const
327   {
328     std::vector<Node> terms;
329     getExplanationForInstLemmas(q, terms, lems, quant, tvec);
330   }
331 
332   /** print this class */
print(std::ostream & out,Node q,bool & firstTime,bool useActive,std::vector<Node> & active)333   void print(std::ostream& out,
334              Node q,
335              bool& firstTime,
336              bool useActive,
337              std::vector<Node>& active) const
338   {
339     std::vector<TNode> terms;
340     print(out, q, terms, firstTime, useActive, active);
341   }
342 
343  private:
344   /** the data */
345   std::map<Node, CDInstMatchTrie*> d_data;
346   /** is valid */
347   context::CDO<bool> d_valid;
348   /** helper for print
349    * terms accumulates the path we are on in the trie.
350    */
351   void print(std::ostream& out,
352              Node q,
353              std::vector<TNode>& terms,
354              bool& firstTime,
355              bool useActive,
356              std::vector<Node>& active) const;
357   /** helper for get instantiations
358    * terms accumulates the path we are on in the trie.
359    */
360   void getInstantiations(std::vector<Node>& insts,
361                          Node q,
362                          std::vector<Node>& terms,
363                          QuantifiersEngine* qe,
364                          bool useActive,
365                          std::vector<Node>& active) const;
366   /** helper for get explanation for inst lemma
367    * terms accumulates the path we are on in the trie.
368    */
369   void getExplanationForInstLemmas(
370       Node q,
371       std::vector<Node>& terms,
372       const std::vector<Node>& lems,
373       std::map<Node, Node>& quant,
374       std::map<Node, std::vector<Node> >& tvec) const;
375   /** set instantiation lemma at this node in the trie */
setInstLemma(Node n)376   void setInstLemma(Node n)
377   {
378     d_data.clear();
379     d_data[n] = NULL;
380   }
381   /** does this node of the trie store an instantiation lemma? */
hasInstLemma()382   bool hasInstLemma() const { return !d_data.empty(); }
383   /** get the instantiation lemma stored in this node of the trie */
getInstLemma()384   Node getInstLemma() const { return d_data.begin()->first; }
385 };
386 
387 /** inst match trie ordered
388  *
389  * This is an ordered version of the context-independent instantiation match
390  * trie. It stores a variable order and a base InstMatchTrie.
391  */
392 class InstMatchTrieOrdered
393 {
394  public:
InstMatchTrieOrdered(InstMatchTrie::ImtIndexOrder * imtio)395   InstMatchTrieOrdered(InstMatchTrie::ImtIndexOrder* imtio) : d_imtio(imtio) {}
~InstMatchTrieOrdered()396   ~InstMatchTrieOrdered() {}
397   /** get the ordering */
getOrdering()398   InstMatchTrie::ImtIndexOrder* getOrdering() { return d_imtio; }
399   /** get the trie data */
getTrie()400   InstMatchTrie* getTrie() { return &d_imt; }
401   /** add match m for quantified formula q
402    *
403    * This method returns true if the match m was not previously added to this
404    * class. If modEq is true, we consider duplicates modulo the current
405    * equalities stored in the active equality engine of quantifiers engine.
406    */
407   bool addInstMatch(QuantifiersEngine* qe,
408                     Node q,
409                     InstMatch& m,
410                     bool modEq = false)
411   {
412     return d_imt.addInstMatch(qe, q, m, modEq, d_imtio);
413   }
414   /** returns true if this trie contains m
415    *
416    * This method returns true if the match m exists in this
417    * class. If modEq is true, we consider duplicates modulo the current
418    * equalities stored in the active equality engine of quantifiers engine.
419    */
420   bool existsInstMatch(QuantifiersEngine* qe,
421                        Node q,
422                        InstMatch& m,
423                        bool modEq = false)
424   {
425     return d_imt.existsInstMatch(qe, q, m, modEq, d_imtio);
426   }
427 
428  private:
429   /** the ordering */
430   InstMatchTrie::ImtIndexOrder* d_imtio;
431   /** the data of this class */
432   InstMatchTrie d_imt;
433 };
434 
435 } /* CVC4::theory::inst namespace */
436 } /* CVC4::theory namespace */
437 } /* CVC4 namespace */
438 
439 #endif /* __CVC4__THEORY__QUANTIFIERS__INST_MATCH_H */
440