GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/uf/equality_engine.h Lines: 37 39 94.9 %
Date: 2021-08-16 Branches: 5 34 14.7 %

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