1 /*********************                                                        */
2 /*! \file equality_engine.h
3  ** \verbatim
4  ** Top contributors (to current version):
5  **   Dejan Jovanovic, Morgan Deters, Guy Katz
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 [[ Add one-line brief description here ]]
13  **
14  ** [[ Add lengthier description here ]]
15  ** \todo document this file
16  **/
17 
18 #include "cvc4_private.h"
19 
20 #pragma once
21 
22 #include <deque>
23 #include <queue>
24 #include <memory>
25 #include <unordered_map>
26 #include <vector>
27 
28 #include "base/output.h"
29 #include "context/cdhashmap.h"
30 #include "context/cdo.h"
31 #include "expr/kind_map.h"
32 #include "expr/node.h"
33 #include "theory/rewriter.h"
34 #include "theory/theory.h"
35 #include "theory/uf/equality_engine_types.h"
36 #include "util/statistics_registry.h"
37 
38 namespace CVC4 {
39 namespace theory {
40 namespace eq {
41 
42 
43 class EqProof;
44 class EqClassesIterator;
45 class EqClassIterator;
46 
47 /**
48  * Interface for equality engine notifications. All the notifications
49  * are safe as TNodes, but not necessarily for negations.
50  */
51 class EqualityEngineNotify {
52 
53   friend class EqualityEngine;
54 
55 public:
56 
~EqualityEngineNotify()57   virtual ~EqualityEngineNotify() {};
58 
59   /**
60    * Notifies about a trigger equality that became true or false.
61    *
62    * @param equality the equality that became true or false
63    * @param value the value of the equality
64    */
65   virtual bool eqNotifyTriggerEquality(TNode equality, bool value) = 0;
66 
67   /**
68    * Notifies about a trigger predicate that became true or false.
69    *
70    * @param predicate the trigger predicate that became true or false
71    * @param value the value of the predicate
72    */
73   virtual bool eqNotifyTriggerPredicate(TNode predicate, bool value) = 0;
74 
75   /**
76    * Notifies about the merge of two trigger terms.
77    *
78    * @param tag the theory that both triggers were tagged with
79    * @param t1 a term marked as trigger
80    * @param t2 a term marked as trigger
81    * @param value true if equal, false if dis-equal
82    */
83   virtual bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) = 0;
84 
85   /**
86    * Notifies about the merge of two constant terms. After this, all work is suspended and all you
87    * can do is ask for explanations.
88    *
89    * @param t1 a constant term
90    * @param t2 a constant term
91    */
92   virtual void eqNotifyConstantTermMerge(TNode t1, TNode t2) = 0;
93 
94   /**
95    * Notifies about the creation of a new equality class.
96    *
97    * @param t the term forming the new class
98    */
99   virtual void eqNotifyNewClass(TNode t) = 0;
100 
101   /**
102    * Notifies about the merge of two classes (just before the merge).
103    *
104    * @param t1 a term
105    * @param t2 a term
106    */
107   virtual void eqNotifyPreMerge(TNode t1, TNode t2) = 0;
108 
109   /**
110    * Notifies about the merge of two classes (just after the merge).
111    *
112    * @param t1 a term
113    * @param t2 a term
114    */
115   virtual void eqNotifyPostMerge(TNode t1, TNode t2) = 0;
116 
117   /**
118    * Notifies about the disequality of two terms.
119    *
120    * @param t1 a term
121    * @param t2 a term
122    * @param reason the reason
123    */
124   virtual void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) = 0;
125 
126 };/* class EqualityEngineNotify */
127 
128 /**
129  * Implementation of the notification interface that ignores all the
130  * notifications.
131  */
132 class EqualityEngineNotifyNone : public EqualityEngineNotify {
133 public:
eqNotifyTriggerEquality(TNode equality,bool value)134  bool eqNotifyTriggerEquality(TNode equality, bool value) override
135  {
136    return true;
137  }
eqNotifyTriggerPredicate(TNode predicate,bool value)138  bool eqNotifyTriggerPredicate(TNode predicate, bool value) override
139  {
140    return true;
141  }
eqNotifyTriggerTermEquality(TheoryId tag,TNode t1,TNode t2,bool value)142  bool eqNotifyTriggerTermEquality(TheoryId tag,
143                                   TNode t1,
144                                   TNode t2,
145                                   bool value) override
146  {
147    return true;
148  }
eqNotifyConstantTermMerge(TNode t1,TNode t2)149  void eqNotifyConstantTermMerge(TNode t1, TNode t2) override {}
eqNotifyNewClass(TNode t)150  void eqNotifyNewClass(TNode t) override {}
eqNotifyPreMerge(TNode t1,TNode t2)151  void eqNotifyPreMerge(TNode t1, TNode t2) override {}
eqNotifyPostMerge(TNode t1,TNode t2)152  void eqNotifyPostMerge(TNode t1, TNode t2) override {}
eqNotifyDisequal(TNode t1,TNode t2,TNode reason)153  void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) override {}
154 };/* class EqualityEngineNotifyNone */
155 
156 /**
157  * An interface for equality engine notifications during equality path reconstruction.
158  * Can be used to add theory-specific logic for, e.g., proof construction.
159  */
160 class PathReconstructionNotify {
161 public:
162 
~PathReconstructionNotify()163   virtual ~PathReconstructionNotify() {}
164 
165   virtual void notify(unsigned reasonType, Node reason, Node a, Node b,
166                       std::vector<TNode>& equalities,
167                       EqProof* proof) const = 0;
168 };
169 
170 /**
171  * Class for keeping an incremental congruence closure over a set of terms. It provides
172  * notifications via an EqualityEngineNotify object.
173  */
174 class EqualityEngine : public context::ContextNotifyObj {
175 
176   friend class EqClassesIterator;
177   friend class EqClassIterator;
178 
179   /** Default implementation of the notification object */
180   static EqualityEngineNotifyNone s_notifyNone;
181 
182   /**
183    * Master equality engine that gets all the equality information from
184    * this one, or null if none.
185    */
186   EqualityEngine* d_masterEqualityEngine;
187 
188 public:
189 
190   /**
191    * Initialize the equality engine, given the notification class.
192    */
193   EqualityEngine(EqualityEngineNotify& notify, context::Context* context, std::string name, bool constantsAreTriggers);
194 
195   /**
196    * Initialize the equality engine with no notification class.
197    */
198   EqualityEngine(context::Context* context, std::string name, bool constantsAreTriggers);
199 
200   /**
201    * Just a destructor.
202    */
203   virtual ~EqualityEngine();
204 
205   /**
206    * Set the master equality engine for this one. Master engine will get copies of all
207    * the terms and equalities from this engine.
208    */
209   void setMasterEqualityEngine(EqualityEngine* master);
210 
211   /** Statistics about the equality engine instance */
212   struct Statistics {
213     /** Total number of merges */
214     IntStat mergesCount;
215     /** Number of terms managed by the system */
216     IntStat termsCount;
217     /** Number of function terms managed by the system */
218     IntStat functionTermsCount;
219     /** Number of constant terms managed by the system */
220     IntStat constantTermsCount;
221 
222     Statistics(std::string name);
223 
224     ~Statistics();
225   };/* struct EqualityEngine::statistics */
226 
227 private:
228 
229   /** The context we are using */
230   context::Context* d_context;
231 
232   /** If we are done, we don't except any new assertions */
233   context::CDO<bool> d_done;
234 
235   /** Whether to notify or not (temporarily disabled on equality checks) */
236   bool d_performNotify;
237 
238   /** The class to notify when a representative changes for a term */
239   EqualityEngineNotify& d_notify;
240 
241   /** The map of kinds to be treated as function applications */
242   KindMap d_congruenceKinds;
243 
244   /** The map of kinds to be treated as interpreted function applications (for evaluation of constants) */
245   KindMap d_congruenceKindsInterpreted;
246 
247   /** The map of kinds with operators to be considered external (for higher-order) */
248   KindMap d_congruenceKindsExtOperators;
249 
250   /** Objects that need to be notified during equality path reconstruction */
251   std::map<unsigned, const PathReconstructionNotify*> d_pathReconstructionTriggers;
252 
253   /** Map from nodes to their ids */
254   std::unordered_map<TNode, EqualityNodeId, TNodeHashFunction> d_nodeIds;
255 
256   /** Map from function applications to their ids */
257   typedef std::unordered_map<FunctionApplication, EqualityNodeId, FunctionApplicationHashFunction> ApplicationIdsMap;
258 
259   /**
260    * A map from a pair (a', b') to a function application f(a, b), where a' and b' are the current representatives
261    * of a and b.
262    */
263   ApplicationIdsMap d_applicationLookup;
264 
265   /** Application lookups in order, so that we can backtrack. */
266   std::vector<FunctionApplication> d_applicationLookups;
267 
268   /** Number of application lookups, for backtracking.  */
269   context::CDO<DefaultSizeType> d_applicationLookupsCount;
270 
271   /**
272    * Store the application lookup, with enough information to backtrack
273    */
274   void storeApplicationLookup(FunctionApplication& funNormalized, EqualityNodeId funId);
275 
276   /** Map from ids to the nodes (these need to be nodes as we pick up the operators) */
277   std::vector<Node> d_nodes;
278 
279   /** A context-dependents count of nodes */
280   context::CDO<DefaultSizeType> d_nodesCount;
281 
282   /** Map from ids to the applications */
283   std::vector<FunctionApplicationPair> d_applications;
284 
285   /** Map from ids to the equality nodes */
286   std::vector<EqualityNode> d_equalityNodes;
287 
288   /** Number of asserted equalities we have so far */
289   context::CDO<DefaultSizeType> d_assertedEqualitiesCount;
290 
291   /** Memory for the use-list nodes */
292   std::vector<UseListNode> d_useListNodes;
293 
294   /** A fresh merge reason type to return upon request */
295   unsigned d_freshMergeReasonType;
296 
297   /**
298    * We keep a list of asserted equalities. Not among original terms, but
299    * among the class representatives.
300    */
301   struct Equality {
302     /** Left hand side of the equality */
303     EqualityNodeId lhs;
304     /** Right hand side of the equality */
305     EqualityNodeId rhs;
306     /** Equality constructor */
307     Equality(EqualityNodeId lhs = null_id, EqualityNodeId rhs = null_id)
lhsEquality308     : lhs(lhs), rhs(rhs) {}
309   };/* struct EqualityEngine::Equality */
310 
311   /** The ids of the classes we have merged */
312   std::vector<Equality> d_assertedEqualities;
313 
314   /** The reasons for the equalities */
315 
316   /**
317    * An edge in the equality graph. This graph is an undirected graph (both edges added)
318    * containing the actual asserted equalities.
319    */
320   class EqualityEdge {
321 
322     // The id of the RHS of this equality
323     EqualityNodeId d_nodeId;
324     // The next edge
325     EqualityEdgeId d_nextId;
326     // Type of reason for this equality
327     unsigned d_mergeType;
328     // Reason of this equality
329     TNode d_reason;
330 
331   public:
332 
EqualityEdge()333     EqualityEdge():
334       d_nodeId(null_edge), d_nextId(null_edge), d_mergeType(MERGED_THROUGH_CONGRUENCE) {}
335 
EqualityEdge(EqualityNodeId nodeId,EqualityNodeId nextId,unsigned type,TNode reason)336     EqualityEdge(EqualityNodeId nodeId, EqualityNodeId nextId, unsigned type, TNode reason):
337       d_nodeId(nodeId), d_nextId(nextId), d_mergeType(type), d_reason(reason) {}
338 
339     /** Returns the id of the next edge */
getNext()340     EqualityEdgeId getNext() const { return d_nextId; }
341 
342     /** Returns the id of the target edge node */
getNodeId()343     EqualityNodeId getNodeId() const { return d_nodeId; }
344 
345     /** The reason of this edge */
getReasonType()346     unsigned getReasonType() const { return d_mergeType; }
347 
348     /** The reason of this edge */
getReason()349     TNode getReason() const { return d_reason; }
350   };/* class EqualityEngine::EqualityEdge */
351 
352   /**
353    * All the equality edges (twice as many as the number of asserted equalities. If an equality
354    * t1 = t2 is asserted, the edges added are -> t2, -> t1 (in this order). Hence, having the index
355    * of one of the edges you can reconstruct the original equality.
356    */
357   std::vector<EqualityEdge> d_equalityEdges;
358 
359   /**
360    * Returns the string representation of the edges.
361    */
362   std::string edgesToString(EqualityEdgeId edgeId) const;
363 
364   /**
365    * Map from a node to its first edge in the equality graph. Edges are added to the front of the
366    * list which makes the insertion/backtracking easy.
367    */
368   std::vector<EqualityEdgeId> d_equalityGraph;
369 
370   /** Add an edge to the equality graph */
371   void addGraphEdge(EqualityNodeId t1, EqualityNodeId t2, unsigned type, TNode reason);
372 
373   /** Returns the equality node of the given node */
374   EqualityNode& getEqualityNode(TNode node);
375 
376   /** Returns the equality node of the given node */
377   const EqualityNode& getEqualityNode(TNode node) const;
378 
379   /** Returns the equality node of the given node */
380   EqualityNode& getEqualityNode(EqualityNodeId nodeId);
381 
382   /** Returns the equality node of the given node */
383   const EqualityNode& getEqualityNode(EqualityNodeId nodeId) const;
384 
385   /** Returns the id of the node */
386   EqualityNodeId getNodeId(TNode node) const;
387 
388   /**
389    * Merge the class2 into class1
390    * @return true if ok, false if to break out
391    */
392   bool merge(EqualityNode& class1, EqualityNode& class2, std::vector<TriggerId>& triggers);
393 
394   /** Undo the merge of class2 into class1 */
395   void undoMerge(EqualityNode& class1, EqualityNode& class2, EqualityNodeId class2Id);
396 
397   /** Backtrack the information if necessary */
398   void backtrack();
399 
400   /**
401    * Trigger that will be updated
402    */
403   struct Trigger {
404     /** The current class id of the LHS of the trigger */
405     EqualityNodeId classId;
406     /** Next trigger for class */
407     TriggerId nextTrigger;
408 
409     Trigger(EqualityNodeId classId = null_id, TriggerId nextTrigger = null_trigger)
classIdTrigger410     : classId(classId), nextTrigger(nextTrigger) {}
411   };/* struct EqualityEngine::Trigger */
412 
413   /**
414    * Vector of triggers. Triggers come in pairs for an
415    * equality trigger (t1, t2): one at position 2k for t1, and one at position 2k + 1 for t2. When
416    * updating triggers we always know where the other one is (^1).
417    */
418   std::vector<Trigger> d_equalityTriggers;
419 
420   /**
421    * Vector of original equalities of the triggers.
422    */
423   std::vector<TriggerInfo> d_equalityTriggersOriginal;
424 
425   /**
426    * Context dependent count of triggers
427    */
428   context::CDO<DefaultSizeType> d_equalityTriggersCount;
429 
430   /**
431    * Trigger lists per node. The begin id changes as we merge, but the end always points to
432    * the actual end of the triggers for this node.
433    */
434   std::vector<TriggerId> d_nodeTriggers;
435 
436   /**
437    * Map from ids to whether they are constants (constants are always
438    * representatives of their class.
439    */
440   std::vector<bool> d_isConstant;
441 
442   /**
443    * Map from ids of proper terms, to the number of non-constant direct subterms. If we update an interpreted
444    * application to a constant, we can decrease this value. If we hit 0, we can evaluate the term.
445    *
446    */
447   std::vector<unsigned> d_subtermsToEvaluate;
448 
449   /**
450    * For nodes that we need to postpone evaluation.
451    */
452   std::queue<EqualityNodeId> d_evaluationQueue;
453 
454   /**
455    * Evaluate all terms in the evaluation queue.
456    */
457   void processEvaluationQueue();
458 
459   /** Vector of nodes that evaluate. */
460   std::vector<EqualityNodeId> d_subtermEvaluates;
461 
462   /** Size of the nodes that evaluate vector. */
463   context::CDO<unsigned> d_subtermEvaluatesSize;
464 
465   /** Set the node evaluate flag */
466   void subtermEvaluates(EqualityNodeId id);
467 
468   /**
469    * Returns the evaluation of the term when all (direct) children are replaced with
470    * the constant representatives.
471    */
472   Node evaluateTerm(TNode node);
473 
474   /**
475    * Returns true if it's a constant
476    */
isConstant(EqualityNodeId id)477   bool isConstant(EqualityNodeId id) const {
478     return d_isConstant[getEqualityNode(id).getFind()];
479   }
480 
481   /**
482    * Map from ids to whether they are Boolean.
483    */
484   std::vector<bool> d_isEquality;
485 
486   /**
487    * Map from ids to whether the nods is internal. An internal node is a node
488    * that corresponds to a partially currified node, for example.
489    */
490   std::vector<bool> d_isInternal;
491 
492   /**
493    * Adds the trigger with triggerId to the beginning of the trigger list of the node with id nodeId.
494    */
495   void addTriggerToList(EqualityNodeId nodeId, TriggerId triggerId);
496 
497   /** Statistics */
498   Statistics d_stats;
499 
500   /** Add a new function application node to the database, i.e APP t1 t2 */
501   EqualityNodeId newApplicationNode(TNode original, EqualityNodeId t1, EqualityNodeId t2, FunctionApplicationType type);
502 
503   /** Add a new node to the database */
504   EqualityNodeId newNode(TNode t);
505 
506   /** Propagation queue */
507   std::deque<MergeCandidate> d_propagationQueue;
508 
509   /** Enqueue to the propagation queue */
510   void enqueue(const MergeCandidate& candidate, bool back = true);
511 
512   /** Do the propagation */
513   void propagate();
514 
515   /** Are we in propagate */
516   bool d_inPropagate;
517 
518   /**
519    * Get an explanation of the equality t1 = t2. Returns the asserted equalities that
520    * imply t1 = t2. Returns TNodes as the assertion equalities should be hashed somewhere
521    * else.
522    */
523   void getExplanation(EqualityEdgeId t1Id, EqualityNodeId t2Id, std::vector<TNode>& equalities, EqProof* eqp) const;
524 
525   /**
526    * Print the equality graph.
527    */
528   void debugPrintGraph() const;
529 
530   /** The true node */
531   Node d_true;
532   /** True node id */
533   EqualityNodeId d_trueId;
534 
535   /** The false node */
536   Node d_false;
537   /** False node id */
538   EqualityNodeId d_falseId;
539 
540   /**
541    * Adds an equality of terms t1 and t2 to the database.
542    */
543   void assertEqualityInternal(TNode t1, TNode t2, TNode reason, unsigned pid = MERGED_THROUGH_EQUALITY);
544 
545   /**
546    * Adds a trigger equality to the database with the trigger node and polarity for notification.
547    */
548   void addTriggerEqualityInternal(TNode t1, TNode t2, TNode trigger, bool polarity);
549 
550   /**
551    * This method gets called on backtracks from the context manager.
552    */
contextNotifyPop()553   void contextNotifyPop() override { backtrack(); }
554 
555   /**
556    * Constructor initialization stuff.
557    */
558   void init();
559 
560   /** Set of trigger terms */
561   struct TriggerTermSet {
562     /** Set of theories in this set */
563     Theory::Set tags;
564     /** The trigger terms */
565     EqualityNodeId triggers[0];
566     /** Returns the theory tags */
hasTriggerTriggerTermSet567     Theory::Set hasTrigger(TheoryId tag) const { return Theory::setContains(tag, tags); }
568     /** Returns a trigger by tag */
getTriggerTriggerTermSet569     EqualityNodeId getTrigger(TheoryId tag) const {
570       return triggers[Theory::setIndex(tag, tags)];
571     }
572   };/* struct EqualityEngine::TriggerTermSet */
573 
574   /** Are the constants triggers */
575   bool d_constantsAreTriggers;
576 
577   /** The information about trigger terms is stored in this easily maintained memory. */
578   char* d_triggerDatabase;
579 
580   /** Allocated size of the trigger term database */
581   DefaultSizeType d_triggerDatabaseAllocatedSize;
582 
583   /** Reference for the trigger terms set */
584   typedef DefaultSizeType TriggerTermSetRef;
585 
586   /** Null reference */
587   static const TriggerTermSetRef null_set_id = (TriggerTermSetRef)(-1);
588 
589   /** Create new trigger term set based on the internally set information */
590   TriggerTermSetRef newTriggerTermSet(Theory::Set newSetTags, EqualityNodeId* newSetTriggers, unsigned newSetTriggersSize);
591 
592   /** Get the trigger set give a reference */
getTriggerTermSet(TriggerTermSetRef ref)593   TriggerTermSet& getTriggerTermSet(TriggerTermSetRef ref) {
594     Assert(ref < d_triggerDatabaseSize);
595     return *(reinterpret_cast<TriggerTermSet*>(d_triggerDatabase + ref));
596   }
597 
598   /** Get the trigger set give a reference */
getTriggerTermSet(TriggerTermSetRef ref)599   const TriggerTermSet& getTriggerTermSet(TriggerTermSetRef ref) const {
600     Assert(ref < d_triggerDatabaseSize);
601     return *(reinterpret_cast<const TriggerTermSet*>(d_triggerDatabase + ref));
602   }
603 
604   /** Used part of the trigger term database */
605   context::CDO<DefaultSizeType> d_triggerDatabaseSize;
606 
607   struct TriggerSetUpdate {
608     EqualityNodeId classId;
609     TriggerTermSetRef oldValue;
610     TriggerSetUpdate(EqualityNodeId classId = null_id, TriggerTermSetRef oldValue = null_set_id)
classIdTriggerSetUpdate611     : classId(classId), oldValue(oldValue) {}
612   };/* struct EqualityEngine::TriggerSetUpdate */
613 
614   /**
615    * List of trigger updates for backtracking.
616    */
617   std::vector<TriggerSetUpdate> d_triggerTermSetUpdates;
618 
619   /**
620    * Size of the individual triggers list.
621    */
622   context::CDO<unsigned> d_triggerTermSetUpdatesSize;
623 
624   /**
625    * Map from ids to the individual trigger set representatives.
626    */
627   std::vector<TriggerTermSetRef> d_nodeIndividualTrigger;
628 
629   typedef std::unordered_map<EqualityPair, DisequalityReasonRef, EqualityPairHashFunction> DisequalityReasonsMap;
630 
631   /**
632    * A map from pairs of disequal terms, to the reason why we deduced they are disequal.
633    */
634   DisequalityReasonsMap d_disequalityReasonsMap;
635 
636   /**
637    * A list of all the disequalities we deduced.
638    */
639   std::vector<EqualityPair> d_deducedDisequalities;
640 
641   /**
642    * Context dependent size of the deduced disequalities
643    */
644   context::CDO<size_t> d_deducedDisequalitiesSize;
645 
646   /**
647    * For each disequality deduced, we add the pairs of equivalences needed to explain it.
648    */
649   std::vector<EqualityPair> d_deducedDisequalityReasons;
650 
651   /**
652    * Size of the memory for disequality reasons.
653    */
654   context::CDO<size_t> d_deducedDisequalityReasonsSize;
655 
656   /**
657    * Map from equalities to the tags that have received the notification.
658    */
659   typedef context::CDHashMap<EqualityPair, Theory::Set, EqualityPairHashFunction> PropagatedDisequalitiesMap;
660   PropagatedDisequalitiesMap d_propagatedDisequalities;
661 
662   /**
663    * Has this equality been propagated to anyone.
664    */
665   bool hasPropagatedDisequality(EqualityNodeId lhsId, EqualityNodeId rhsId) const;
666 
667   /**
668    * Has this equality been propagated to the tag owner.
669    */
670   bool hasPropagatedDisequality(TheoryId tag, EqualityNodeId lhsId, EqualityNodeId rhsId) const;
671 
672   /**
673    * Stores a propagated disequality for explanation purposes and remembers the reasons. The
674    * reasons should be pushed on the reasons vector.
675    */
676   void storePropagatedDisequality(TheoryId tag, EqualityNodeId lhsId, EqualityNodeId rhsId);
677 
678   /**
679    * An equality tagged with a set of tags.
680    */
681   struct TaggedEquality {
682     /** Id of the equality */
683     EqualityNodeId equalityId;
684     /** TriggerSet reference for the class of one of the sides */
685     TriggerTermSetRef triggerSetRef;
686     /** Is trigger equivalent to the lhs (rhs otherwise) */
687     bool lhs;
688 
689     TaggedEquality(EqualityNodeId equalityId = null_id, TriggerTermSetRef triggerSetRef = null_set_id, bool lhs = true)
equalityIdTaggedEquality690     : equalityId(equalityId), triggerSetRef(triggerSetRef), lhs(lhs) {}
691   };
692 
693   /** A map from equivalence class id's to tagged equalities */
694   typedef std::vector<TaggedEquality> TaggedEqualitiesSet;
695 
696   /**
697    * Returns a set of equalities that have been asserted false where one side of the equality
698    * belongs to the given equivalence class. The equalities are restricted to the ones where
699    * one side of the equality is in the tags set, but the other one isn't. Each returned
700    * dis-equality is associated with the tags that are the subset of the input tags, such that
701    * exactly one side of the equality is not in the set yet.
702    *
703    * @param classId the equivalence class to search
704    * @param inputTags the tags to filter the equalities
705    * @param out the output equalities, as described above
706    */
707   void getDisequalities(bool allowConstants, EqualityNodeId classId, Theory::Set inputTags, TaggedEqualitiesSet& out);
708 
709   /**
710    * Propagates the remembered disequalities with given tags the original triggers for those tags,
711    * and the set of disequalities produced by above.
712    */
713   bool propagateTriggerTermDisequalities(Theory::Set tags,
714     TriggerTermSetRef triggerSetRef, const TaggedEqualitiesSet& disequalitiesToNotify);
715 
716   /** Name of the equality engine */
717   std::string d_name;
718 
719   /** The internal addTerm */
720   void addTermInternal(TNode t, bool isOperator = false);
721 
722 public:
723 
724   /**
725    * Adds a term to the term database.
726    */
addTerm(TNode t)727   void addTerm(TNode t) {
728     addTermInternal(t, false);
729   }
730 
731   /**
732    * Add a kind to treat as function applications.
733    * When extOperator is true, this equality engine will treat the operators of this kind
734    * as "external" e.g. not internal nodes (see d_isInternal). This means that we will
735    * consider equivalence classes containing the operators of such terms, and "hasTerm" will
736    * return true.
737    */
738   void addFunctionKind(Kind fun, bool interpreted = false, bool extOperator = false);
739 
740   /**
741    * Returns true if this kind is used for congruence closure.
742    */
isFunctionKind(Kind fun)743   bool isFunctionKind(Kind fun) const {
744     return d_congruenceKinds.tst(fun);
745   }
746 
747   /**
748    * Returns true if this kind is used for congruence closure + evaluation of constants.
749    */
isInterpretedFunctionKind(Kind fun)750   bool isInterpretedFunctionKind(Kind fun) const {
751     return d_congruenceKindsInterpreted.tst(fun);
752   }
753 
754   /**
755    * Returns true if this kind has an operator that is considered external (e.g. not internal).
756    */
isExternalOperatorKind(Kind fun)757   bool isExternalOperatorKind(Kind fun) const {
758     return d_congruenceKindsExtOperators.tst(fun);
759   }
760 
761   /**
762    * Check whether the node is already in the database.
763    */
764   bool hasTerm(TNode t) const;
765 
766   /**
767    * Adds a predicate p with given polarity. The predicate asserted
768    * should be in the congruence closure kinds (otherwise it's
769    * useless).
770    *
771    * @param p the (non-negated) predicate
772    * @param polarity true if asserting the predicate, false if
773    *                 asserting the negated predicate
774    * @param reason the reason to keep for building explanations
775    */
776   void assertPredicate(TNode p, bool polarity, TNode reason, unsigned pid = MERGED_THROUGH_EQUALITY);
777 
778   /**
779    * Adds predicate p and q and makes them equal.
780    */
781   void mergePredicates(TNode p, TNode q, TNode reason);
782 
783   /**
784    * Adds an equality eq with the given polarity to the database.
785    *
786    * @param eq the (non-negated) equality
787    * @param polarity true if asserting the equality, false if
788    *                 asserting the negated equality
789    * @param reason the reason to keep for building explanations
790    */
791   void assertEquality(TNode eq, bool polarity, TNode reason, unsigned pid = MERGED_THROUGH_EQUALITY);
792 
793   /**
794    * Returns the current representative of the term t.
795    */
796   TNode getRepresentative(TNode t) const;
797 
798   /**
799    * Add all the terms where the given term appears as a first child
800    * (directly or implicitly).
801    */
802   void getUseListTerms(TNode t, std::set<TNode>& output);
803 
804   /**
805    * Get an explanation of the equality t1 = t2 being true or false.
806    * Returns the reasons (added when asserting) that imply it
807    * in the assertions vector.
808    */
809   void explainEquality(TNode t1, TNode t2, bool polarity,
810                        std::vector<TNode>& assertions,
811                        EqProof* eqp = nullptr) const;
812 
813   /**
814    * Get an explanation of the predicate being true or false.
815    * Returns the reasons (added when asserting) that imply imply it
816    * in the assertions vector.
817    */
818   void explainPredicate(TNode p, bool polarity, std::vector<TNode>& assertions,
819                         EqProof* eqp = nullptr) const;
820 
821   /**
822    * Add term to the set of trigger terms with a corresponding tag. The notify class will get
823    * notified when two trigger terms with the same tag become equal or dis-equal. The notification
824    * will not happen on all the terms, but only on the ones that are represent the class. Note that
825    * a term can be added more than once with different tags, and each tag appearance will merit
826    * it's own notification.
827    *
828    * @param t the trigger term
829    * @param theoryTag tag for this trigger (do NOT use THEORY_LAST)
830    */
831   void addTriggerTerm(TNode t, TheoryId theoryTag);
832 
833   /**
834    * Returns true if t is a trigger term or in the same equivalence
835    * class as some other trigger term.
836    */
837   bool isTriggerTerm(TNode t, TheoryId theoryTag) const;
838 
839   /**
840    * Returns the representative trigger term of the given term.
841    *
842    * @param t the term to check where isTriggerTerm(t) should be true
843    */
844   TNode getTriggerTermRepresentative(TNode t, TheoryId theoryTag) const;
845 
846   /**
847    * Adds a notify trigger for equality. When equality becomes true eqNotifyTriggerEquality
848    * will be called with value = true, and when equality becomes false eqNotifyTriggerEquality
849    * will be called with value = false.
850    */
851   void addTriggerEquality(TNode equality);
852 
853   /**
854    * Adds a notify trigger for the predicate p. When the predicate becomes true
855    * eqNotifyTriggerPredicate will be called with value = true, and when equality becomes false
856    * eqNotifyTriggerPredicate will be called with value = false.
857    */
858   void addTriggerPredicate(TNode predicate);
859 
860   /**
861    * Returns true if the two terms are equal. Requires both terms to
862    * be in the database.
863    */
864   bool areEqual(TNode t1, TNode t2) const;
865 
866   /**
867    * Check whether the two term are dis-equal. Requires both terms to
868    * be in the database.
869    */
870   bool areDisequal(TNode t1, TNode t2, bool ensureProof) const;
871 
872   /**
873    * Return the number of nodes in the equivalence class containing t
874    * Adds t if not already there.
875    */
876   size_t getSize(TNode t);
877 
878   /**
879    * Returns true if the engine is in a consistent state.
880    */
consistent()881   bool consistent() const { return !d_done; }
882 
883   /**
884    * Marks an object for merge type based notification during equality path reconstruction.
885    */
886   void addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify);
887 
888   /**
889    * Returns a fresh merge reason type tag for the client to use.
890    */
891   unsigned getFreshMergeReasonType();
892 };
893 
894 /**
895  * Iterator to iterate over the equivalence classes.
896  */
897 class EqClassesIterator {
898   const eq::EqualityEngine* d_ee;
899   size_t d_it;
900 public:
901   EqClassesIterator();
902   EqClassesIterator(const eq::EqualityEngine* ee);
903   Node operator*() const;
904   bool operator==(const EqClassesIterator& i) const;
905   bool operator!=(const EqClassesIterator& i) const;
906   EqClassesIterator& operator++();
907   EqClassesIterator operator++(int);
908   bool isFinished() const;
909 };/* class EqClassesIterator */
910 
911 /**
912  * Iterator to iterate over the equivalence class members.
913  */
914 class EqClassIterator {
915   const eq::EqualityEngine* d_ee;
916   /** Starting node */
917   EqualityNodeId d_start;
918   /** Current node */
919   EqualityNodeId d_current;
920 public:
921   EqClassIterator();
922   EqClassIterator(Node eqc, const eq::EqualityEngine* ee);
923   Node operator*() const;
924   bool operator==(const EqClassIterator& i) const;
925   bool operator!=(const EqClassIterator& i) const;
926   EqClassIterator& operator++();
927   EqClassIterator operator++(int);
928   bool isFinished() const;
929 };/* class EqClassIterator */
930 
931 class EqProof
932 {
933 public:
934   class PrettyPrinter {
935   public:
~PrettyPrinter()936     virtual ~PrettyPrinter() {}
937     virtual std::string printTag(unsigned tag) = 0;
938   };
939 
EqProof()940   EqProof() : d_id(MERGED_THROUGH_REFLEXIVITY){}
941   unsigned d_id;
942   Node d_node;
943   std::vector<std::shared_ptr<EqProof>> d_children;
944   void debug_print(const char* c, unsigned tb = 0,
945                    PrettyPrinter* prettyPrinter = nullptr) const;
946 };/* class EqProof */
947 
948 } // Namespace eq
949 } // Namespace theory
950 } // Namespace CVC4
951