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