GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/constraint.h Lines: 101 107 94.4 %
Date: 2021-09-29 Branches: 36 216 16.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Alex Ozdemir, Haniel Barbosa
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
 * Defines Constraint and ConstraintDatabase which is the internal
14
 * representation of variables in arithmetic
15
 *
16
 * This file defines Constraint and ConstraintDatabase.
17
 * A Constraint is the internal representation of literals in TheoryArithmetic.
18
 * Constraints are fundamentally a triple:
19
 *  - ArithVar associated with the constraint,
20
 *  - a DeltaRational value,
21
 *  - and a ConstraintType.
22
 *
23
 * Literals:
24
 *   The constraint may also keep track of a node corresponding to the
25
 *   Constraint.
26
 *   This can be accessed by getLiteral() in O(1) if it has been set.
27
 *   This node must be in normal form and may be used for communication with
28
 *   the TheoryEngine.
29
 *
30
 * In addition, Constraints keep track of the following:
31
 *  - A Constraint that is the negation of the Constraint.
32
 *  - An iterator into a set of Constraints for the ArithVar sorted by
33
 *    DeltaRational value.
34
 *  - A context dependent internal proof of the node that can be used for
35
 *    explanations.
36
 *  - Whether an equality/disequality has been split in the user context via a
37
 *    lemma.
38
 *  - Whether a constraint, be be used in explanations sent to the context
39
 *
40
 * Looking up constraints:
41
 *  - All of the Constraints with associated nodes in the ConstraintDatabase
42
 *    can be accessed via a single hashtable lookup until the Constraint is
43
 *    removed.
44
 *  - Nodes that have not been associated to a constraints can be
45
 *    inserted/associated to existing nodes in O(log n) time.
46
 *
47
 * Implications:
48
 *  - A Constraint can be used to find unate implications.
49
 *  - A unate implication is an implication based purely on the ArithVar
50
 *    matching  and the DeltaRational value.
51
 *    (implies (<= x c) (<= x d)) given c <= d
52
 *  - This is done using the iterator into the sorted set of constraints.
53
 *  - Given a tight constraint and previous tightest constraint, this will
54
 *    efficiently propagate internally.
55
 *
56
 * Additing and Removing Constraints
57
 *  - Adding Constraints takes O(log n) time where n is the number of
58
 *    constraints associated with the ArithVar.
59
 *  - Removing Constraints takes O(1) time.
60
 *
61
 * Internals:
62
 *  - Constraints are pointers to ConstraintValues.
63
 *  - Undefined Constraints are NullConstraint.
64
 *
65
 * Assumption vs. Assertion:
66
 * - An assertion is anything on the theory d_fact queue.
67
 *   This includes any thing propagated and returned to the fact queue.
68
 *   These can be used in external conflicts and propagations of earlier
69
 *   proofs.
70
 * - An assumption is anything on the theory d_fact queue that has no further
71
 *   explanation i.e. this theory did not propagate it.
72
 * - To set something an assumption, first set it as being as assertion.
73
 * - Internal assumptions have no explanations and must be regressed out of the
74
 *   proof.
75
 */
76
77
#include "cvc5_private.h"
78
79
#ifndef CVC5__THEORY__ARITH__CONSTRAINT_H
80
#define CVC5__THEORY__ARITH__CONSTRAINT_H
81
82
#include <unordered_map>
83
#include <vector>
84
85
#include "base/configuration_private.h"
86
#include "context/cdlist.h"
87
#include "context/cdqueue.h"
88
#include "expr/node.h"
89
#include "proof/trust_node.h"
90
#include "smt/env_obj.h"
91
#include "theory/arith/arithvar.h"
92
#include "theory/arith/callbacks.h"
93
#include "theory/arith/constraint_forward.h"
94
#include "theory/arith/delta_rational.h"
95
#include "util/statistics_stats.h"
96
97
namespace cvc5 {
98
99
class ProofNodeManager;
100
class EagerProofGenerator;
101
102
namespace context {
103
class Context;
104
}
105
namespace theory {
106
107
namespace arith {
108
109
class Comparison;
110
class ArithCongruenceManager;
111
class ArithVariables;
112
113
/**
114
 * Logs the types of different proofs.
115
 * Current, proof types:
116
 * - NoAP             : This constraint is not known to be true.
117
 * - AssumeAP         : This is an input assertion. There is no proof.
118
 *                    : Something can be both asserted and have a proof.
119
 * - InternalAssumeAP : An internal assumption. This has no guarantee of having an external proof.
120
 *                    : This must be removed by regression.
121
 * - FarkasAP         : A proof with Farka's coefficients, i.e.
122
 *                    :  \sum lambda_i ( asNode(x_i) <= c_i  ) |= 0 < 0
123
 *                    : If proofs are on, coefficients will be logged.
124
 *                    : If proofs are off, coefficients will not be logged.
125
 *                    : A unate implication is a FarkasAP.
126
 * - TrichotomyAP     : This is any entailment using (x<= a and x >=a) => x = a
127
 *                    : Equivalently, (x > a or x < a or x = a)
128
 *                    : There are 3 candidate ways this can propagate:
129
 *                    :   !(x > a) and !(x = a) => x < a
130
 *                    :   !(x < a) and !(x = a) => x > a
131
 *                    :   !(x > a) and !(x < a) => x = a
132
 * - EqualityEngineAP : This is propagated by the equality engine.
133
 *                    : Consult this for the proof.
134
 * - IntTightenAP     : This is indicates that a bound involving integers was tightened.
135
 *                    : e.g. i < 5.5 became i <= 5, when i is an integer.
136
 * - IntHoleAP        : This is currently a catch-all for all integer specific reason.
137
 */
138
enum ArithProofType
139
  { NoAP,
140
    AssumeAP,
141
    InternalAssumeAP,
142
    FarkasAP,
143
    TrichotomyAP,
144
    EqualityEngineAP,
145
    IntTightenAP,
146
    IntHoleAP};
147
148
/**
149
 * The types of constraints.
150
 * The convex constraints are the constraints are LowerBound, Equality,
151
 * and UpperBound.
152
 */
153
enum ConstraintType {LowerBound, Equality, UpperBound, Disequality};
154
155
156
typedef context::CDList<ConstraintCP> CDConstraintList;
157
158
typedef std::unordered_map<Node, ConstraintP> NodetoConstraintMap;
159
160
typedef size_t ConstraintRuleID;
161
static const ConstraintRuleID ConstraintRuleIdSentinel = std::numeric_limits<ConstraintRuleID>::max();
162
163
typedef size_t AntecedentId;
164
static const AntecedentId AntecedentIdSentinel = std::numeric_limits<AntecedentId>::max();
165
166
167
typedef size_t AssertionOrder;
168
static const AssertionOrder AssertionOrderSentinel = std::numeric_limits<AssertionOrder>::max();
169
170
171
/**
172
 * A ValueCollection binds together convex constraints that have the same
173
 * DeltaRational value.
174
 */
175
class ValueCollection {
176
private:
177
178
  ConstraintP d_lowerBound;
179
  ConstraintP d_upperBound;
180
  ConstraintP d_equality;
181
  ConstraintP d_disequality;
182
183
public:
184
  ValueCollection();
185
186
  static ValueCollection mkFromConstraint(ConstraintP c);
187
188
  bool hasLowerBound() const;
189
  bool hasUpperBound() const;
190
  bool hasEquality() const;
191
  bool hasDisequality() const;
192
193
  bool hasConstraintOfType(ConstraintType t) const;
194
195
  ConstraintP getLowerBound() const;
196
  ConstraintP getUpperBound() const;
197
  ConstraintP getEquality() const;
198
  ConstraintP getDisequality() const;
199
200
  ConstraintP getConstraintOfType(ConstraintType t) const;
201
202
  /** Returns true if any of the constraints are non-null. */
203
  bool empty() const;
204
205
  /**
206
   * Remove the constraint of the type t from the collection.
207
   * Returns true if the ValueCollection is now empty.
208
   * If true is returned, d_value is now NULL.
209
   */
210
  void remove(ConstraintType t);
211
212
  /**
213
   * Adds a constraint to the set.
214
   * The collection must not have a constraint of that type already.
215
   */
216
  void add(ConstraintP c);
217
218
  void push_into(std::vector<ConstraintP>& vec) const;
219
220
  ConstraintP nonNull() const;
221
222
  ArithVar getVariable() const;
223
  const DeltaRational& getValue() const;
224
};
225
226
/**
227
 * A Map of ValueCollections sorted by the associated DeltaRational values.
228
 *
229
 * Discussion:
230
 * While it is more natural to consider this a set, this cannot be a set as in
231
 * sets the type of both iterator and const_iterator in sets are
232
 * "constant iterators".  We require iterators that dereference to
233
 * ValueCollection&.
234
 *
235
 * See:
236
 * http://gcc.gnu.org/onlinedocs/libstdc++/ext/lwg-defects.html#103
237
 */
238
typedef std::map<DeltaRational, ValueCollection> SortedConstraintMap;
239
typedef SortedConstraintMap::iterator SortedConstraintMapIterator;
240
typedef SortedConstraintMap::const_iterator SortedConstraintMapConstIterator;
241
242
/** A Pair associating a variables and a Sorted ConstraintSet. */
243
92282
struct PerVariableDatabase{
244
  ArithVar d_var;
245
  SortedConstraintMap d_constraints;
246
247
  // x ? c_1, x ? c_2, x ? c_3, ...
248
  // where ? is a non-empty subset of {lb, ub, eq}
249
  // c_1 < c_2 < c_3 < ...
250
251
92282
  PerVariableDatabase(ArithVar v) : d_var(v), d_constraints() {}
252
253
  bool empty() const {
254
    return d_constraints.empty();
255
  }
256
257
  static bool IsEmpty(const PerVariableDatabase& p){
258
    return p.empty();
259
  }
260
};
261
262
/**
263
 * If proofs are on, there is a vector of rationals for farkas coefficients.
264
 * This is the owner of the memory for the vector, and calls delete upon
265
 * cleanup.
266
 *
267
 */
268
struct ConstraintRule {
269
  ConstraintP d_constraint;
270
  ArithProofType d_proofType;
271
  AntecedentId d_antecedentEnd;
272
273
  /**
274
   * In this comment, we abbreviate ConstraintDatabase::d_antecedents
275
   * and d_farkasCoefficients as ans and fc.
276
   *
277
   * This list is always empty if proofs are not enabled.
278
   *
279
   * If proofs are enabled, the proof of constraint c at p in ans[p] of length n
280
   * is (NullConstraint, ans[p-(n-1)], ... , ans[p-1], ans[p])
281
   *
282
   * Farkas' proofs show a contradiction with the negation of c, c_not =
283
   * c->getNegation().
284
   *
285
   * We treat the position for NullConstraint (p-n) as the position for the
286
   * farkas coefficient for so we pretend c_not is ans[p-n]. So this correlation
287
   * for the constraints we are going to use: (c_not, ans[p-n+(1)], ... ,
288
   * ans[p-n+(n-1)], ans[p-n+(n)]) With the coefficients at positions: (fc[0],
289
   * fc[1)], ... fc[n])
290
   *
291
   * The index of the constraints in the proof are {i | i <= 0 <= n] } (with
292
   * c_not being p-n). Partition the indices into L, U, and E, the lower bounds,
293
   * the upper bounds and equalities.
294
   *
295
   * We standardize the proofs to be upper bound oriented following the
296
   * convention: A x <= b with the proof witness of the form (lambda) Ax <=
297
   * (lambda) b and lambda >= 0.
298
   *
299
   * To accomplish this cleanly, the fc coefficients must be negative for lower
300
   * bounds. The signs of equalities can be either positive or negative.
301
   *
302
   * Thus the proof corresponds to (with multiplication over inequalities):
303
   *    \sum_{u in U} fc[u] ans[p-n+u] + \sum_{e in E} fc[e] ans[p-n+e]
304
   *  + \sum_{l in L} fc[l] ans[p-n+l]
305
   * |= 0 < 0
306
   * where fc[u] > 0, fc[l] < 0, and fc[e] != 0 (i.e. it can be either +/-).
307
   *
308
   * There is no requirement that the proof is minimal.
309
   * We do however use all of the constraints by requiring non-zero
310
   * coefficients.
311
   */
312
  RationalVectorCP d_farkasCoefficients;
313
314
  ConstraintRule();
315
  ConstraintRule(ConstraintP con, ArithProofType pt);
316
  ConstraintRule(ConstraintP con,
317
                 ArithProofType pt,
318
                 AntecedentId antecedentEnd);
319
  ConstraintRule(ConstraintP con,
320
                 ArithProofType pt,
321
                 AntecedentId antecedentEnd,
322
                 RationalVectorCP coeffs);
323
324
  void print(std::ostream& out, bool produceProofs) const;
325
  void debugPrint() const;
326
}; /* class ConstraintRule */
327
328
class Constraint {
329
330
  friend class ConstraintDatabase;
331
332
 public:
333
  /**
334
   * This begins construction of a minimal constraint.
335
   *
336
   * This should only be called by ConstraintDatabase.
337
   *
338
   * Because of circular dependencies a Constraint is not fully valid until
339
   * initialize has been called on it.
340
   */
341
  Constraint(ArithVar x,
342
             ConstraintType t,
343
             const DeltaRational& v,
344
             bool produceProofs);
345
346
  /**
347
   * Destructor for a constraint.
348
   * This should only be called if safeToGarbageCollect() is true.
349
   */
350
  ~Constraint();
351
352
  static ConstraintType constraintTypeOfComparison(const Comparison& cmp);
353
354
8687938
  inline ConstraintType getType() const {
355
8687938
    return d_type;
356
  }
357
358
13488620
  inline ArithVar getVariable() const {
359
13488620
    return d_variable;
360
  }
361
362
24952892
  const DeltaRational& getValue() const {
363
24952892
    return d_value;
364
  }
365
366
485064
  inline ConstraintP getNegation() const {
367
485064
    return d_negation;
368
  }
369
370
4393811
  bool isEquality() const{
371
4393811
    return d_type == Equality;
372
  }
373
568939
  bool isDisequality() const{
374
568939
    return d_type == Disequality;
375
  }
376
2726433
  bool isLowerBound() const{
377
2726433
    return d_type == LowerBound;
378
  }
379
2663242
  bool isUpperBound() const{
380
2663242
    return d_type == UpperBound;
381
  }
382
790148
  bool isStrictUpperBound() const{
383
790148
    Assert(isUpperBound());
384
790148
    return getValue().infinitesimalSgn() < 0;
385
  }
386
387
718963
  bool isStrictLowerBound() const{
388
718963
    Assert(isLowerBound());
389
718963
    return getValue().infinitesimalSgn() > 0;
390
  }
391
392
1118475
  bool isSplit() const {
393
1118475
    return d_split;
394
  }
395
396
  /**
397
   * Splits the node in the user context.
398
   * Returns a lemma that is assumed to be true for the rest of the user context.
399
   * Constraint must be an equality or disequality.
400
   */
401
  TrustNode split();
402
403
6424981
  bool canBePropagated() const {
404
6424981
    return d_canBePropagated;
405
  }
406
  void setCanBePropagated();
407
408
  /**
409
   * Light wrapper for calling setCanBePropagated(),
410
   * on this and this->d_negation.
411
   */
412
223082
  void setPreregistered(){
413
223082
    setCanBePropagated();
414
223082
    d_negation->setCanBePropagated();
415
223082
  }
416
417
33514776
  bool assertedToTheTheory() const {
418
33514776
    Assert((d_assertionOrder < AssertionOrderSentinel) != d_witness.isNull());
419
33514776
    return d_assertionOrder < AssertionOrderSentinel;
420
  }
421
3310659
  TNode getWitness() const {
422
3310659
    Assert(assertedToTheTheory());
423
3310659
    return d_witness;
424
  }
425
426
3454929
  bool assertedBefore(AssertionOrder time) const {
427
3454929
    return d_assertionOrder < time;
428
  }
429
430
  /**
431
   * Sets the witness literal for a node being on the assertion stack.
432
   *
433
   * If the negation of the node is true, inConflict must be true.
434
   * If the negation of the node is false, inConflict must be false.
435
   * Hence, negationHasProof() == inConflict.
436
   *
437
   * This replaces:
438
   *   void setAssertedToTheTheory(TNode witness);
439
   *   void setAssertedToTheTheoryWithNegationTrue(TNode witness);
440
   */
441
  void setAssertedToTheTheory(TNode witness, bool inConflict);
442
443
8116194
  bool hasLiteral() const {
444
8116194
    return !d_literal.isNull();
445
  }
446
447
  void setLiteral(Node n);
448
449
966528
  Node getLiteral() const {
450
966528
    Assert(hasLiteral());
451
966528
    return d_literal;
452
  }
453
454
  /** Gets a literal in the normal form suitable for proofs.
455
   * That is, (sum of non-const monomials) >< const.
456
   *
457
   * This is a sister method to `getLiteral`, which returns a normal form
458
   * literal, suitable for external solving use.
459
   */
460
  Node getProofLiteral() const;
461
462
  /**
463
   * Set the node as having a proof and being an assumption.
464
   * The node must be assertedToTheTheory().
465
   *
466
   * Precondition: negationHasProof() == inConflict.
467
   *
468
   * Replaces:
469
   *  selfExplaining().
470
   *  selfExplainingWithNegationTrue().
471
   */
472
  void setAssumption(bool inConflict);
473
474
  /** Returns true if the node is an assumption.*/
475
  bool isAssumption() const;
476
477
  /** Whether we produce proofs */
478
6506284
  bool isProofProducing() const { return d_produceProofs; }
479
480
  /** Set the constraint to have an EqualityEngine proof. */
481
  void setEqualityEngineProof();
482
  bool hasEqualityEngineProof() const;
483
484
  /** Returns true if the node has a Farkas' proof. */
485
  bool hasFarkasProof() const;
486
487
  /**
488
   * @brief Returns whether this constraint is provable using a Farkas
489
   * proof applied to (possibly tightened) input assertions.
490
   *
491
   * An example of a constraint that has a simple Farkas proof:
492
   *    x <= 0 proven from x + y <= 0 and x - y <= 0.
493
   *
494
   * An example of another constraint that has a simple Farkas proof:
495
   *    x <= 0 proven from x + y <= 0 and x - y <= 0.5 for integers x, y
496
   *       (integer bound-tightening is applied first!).
497
   *
498
   * An example of a constraint that might be proven **without** a simple
499
   * Farkas proof:
500
   *    x < 0 proven from not(x == 0) and not(x > 0).
501
   *
502
   * This could be proven internally by the arithmetic theory using
503
   * `TrichotomyAP` as the proof type.
504
   *
505
   */
506
  bool hasSimpleFarkasProof() const;
507
  /**
508
   * Returns whether this constraint is an assumption or a tightened
509
   * assumption.
510
   */
511
  bool isPossiblyTightenedAssumption() const;
512
513
  /** Returns true if the node has a int bound tightening proof. */
514
  bool hasIntTightenProof() const;
515
516
  /** Returns true if the node has a int hole proof. */
517
  bool hasIntHoleProof() const;
518
519
  /** Returns true if the node has a trichotomy proof. */
520
  bool hasTrichotomyProof() const;
521
522
  void printProofTree(std::ostream & out, size_t depth = 0) const;
523
524
  /**
525
   * A sets the constraint to be an internal assumption.
526
   *
527
   * This does not need to have a witness or an associated literal.
528
   * This is always itself in the explanation fringe for both conflicts
529
   * and propagation.
530
   * This cannot be converted back into a Node conflict or explanation.
531
   *
532
   * This cannot have a proof or be asserted to the theory!
533
   *
534
   */
535
  void setInternalAssumption(bool inConflict);
536
  bool isInternalAssumption() const;
537
538
  /**
539
   * Returns a explanation of the constraint that is appropriate for conflicts.
540
   *
541
   * This is not appropriate for propagation!
542
   *
543
   * This is the minimum fringe of the implication tree s.t.
544
   * every constraint is assertedToTheTheory() or hasEqualityEngineProof().
545
   */
546
  TrustNode externalExplainByAssertions() const;
547
548
  /**
549
   * Writes an explanation of a constraint into the node builder.
550
   * Pushes back an explanation that is acceptable to send to the sat solver.
551
   * nb is assumed to be an AND.
552
   *
553
   * This is the minimum fringe of the implication tree s.t.
554
   * every constraint is assertedToTheTheory() or hasEqualityEngineProof().
555
   *
556
   * This is not appropriate for propagation!
557
   * Use explainForPropagation() instead.
558
   */
559
1534381
  std::shared_ptr<ProofNode> externalExplainByAssertions(NodeBuilder& nb) const
560
  {
561
1534381
    return externalExplain(nb, AssertionOrderSentinel);
562
  }
563
564
  /* Equivalent to calling externalExplainByAssertions on all constraints in b */
565
  static Node externalExplainByAssertions(const ConstraintCPVec& b);
566
  static Node externalExplainByAssertions(ConstraintCP a, ConstraintCP b);
567
  static Node externalExplainByAssertions(ConstraintCP a, ConstraintCP b, ConstraintCP c);
568
569
  /**
570
   * This is the minimum fringe of the implication tree s.t. every constraint is
571
   * - assertedToTheTheory(),
572
   * - isInternalDecision() or
573
   * - hasEqualityEngineProof().
574
   */
575
  static void assertionFringe(ConstraintCPVec& v);
576
  static void assertionFringe(ConstraintCPVec& out, const ConstraintCPVec& in);
577
578
  /** The fringe of a farkas' proof. */
579
  bool onFringe() const {
580
    return assertedToTheTheory() || isInternalAssumption() || hasEqualityEngineProof();
581
  }
582
583
  /**
584
   * Returns an explanation of a propagation by the ConstraintDatabase.
585
   * The constraint must have a proof.
586
   * The constraint cannot be an assumption.
587
   *
588
   * This is the minimum fringe of the implication tree (excluding the
589
   * constraint itself) s.t. every constraint is assertedToTheTheory() or
590
   * hasEqualityEngineProof().
591
   *
592
   * All return conjuncts were asserted before this constraint.
593
   *
594
   * Requires the given node to rewrite to the canonical literal for this
595
   * constraint.
596
   *
597
   * @params n the literal to prove
598
   *           n must rewrite to the constraint's canonical literal
599
   *
600
   * @returns a trust node of the form:
601
   *         (=> explanation n)
602
   */
603
  TrustNode externalExplainForPropagation(TNode n) const;
604
605
  /**
606
   * Explain the constraint and its negation in terms of assertions.
607
   * The constraint must be in conflict.
608
   */
609
  TrustNode externalExplainConflict() const;
610
611
  /** The constraint is known to be true. */
612
94998735
  inline bool hasProof() const {
613
94998735
    return d_crid != ConstraintRuleIdSentinel;
614
  }
615
616
  /** The negation of the constraint is known to hold. */
617
30266330
  inline bool negationHasProof() const {
618
30266330
    return d_negation->hasProof();
619
  }
620
621
  /** Neither the contraint has a proof nor the negation has a proof.*/
622
131191
  bool truthIsUnknown() const {
623
131191
    return !hasProof() && !negationHasProof();
624
  }
625
626
  /** This is a synonym for hasProof(). */
627
9233055
  inline bool isTrue() const {
628
9233055
    return hasProof();
629
  }
630
631
  /** Both the constraint and its negation are true. */
632
5919548
  inline bool inConflict() const {
633
5919548
    return hasProof() && negationHasProof();
634
  }
635
636
  /**
637
   * Returns the constraint that corresponds to taking
638
   *    x r ceiling(getValue()) where r is the node's getType().
639
   * Esstentially this is an up branch.
640
   */
641
  ConstraintP getCeiling();
642
643
  /**
644
   * Returns the constraint that corresponds to taking
645
   *    x r floor(getValue()) where r is the node's getType().
646
   * Esstentially this is a down branch.
647
   */
648
  ConstraintP getFloor();
649
650
  static ConstraintP makeNegation(ArithVar v,
651
                                  ConstraintType t,
652
                                  const DeltaRational& r,
653
                                  bool produceProofs);
654
655
  const ValueCollection& getValueCollection() const;
656
657
658
  ConstraintP getStrictlyWeakerUpperBound(bool hasLiteral, bool mustBeAsserted) const;
659
  ConstraintP getStrictlyWeakerLowerBound(bool hasLiteral, bool mustBeAsserted) const;
660
661
  /**
662
   * Marks a the constraint c as being entailed by a.
663
   * The Farkas proof 1*(a) + -1 (c) |= 0<0
664
   *
665
   * After calling impliedByUnate(), the caller should either raise a conflict
666
   * or try call tryToPropagate().
667
   */
668
  void impliedByUnate(ConstraintCP a, bool inConflict);
669
670
  /**
671
   * Marks a the constraint c as being entailed by a.
672
   * The reason has to do with integer bound tightening.
673
   *
674
   * After calling impliedByIntTighten(), the caller should either raise a conflict
675
   * or try call tryToPropagate().
676
   */
677
  void impliedByIntTighten(ConstraintCP a, bool inConflict);
678
679
  /**
680
   * Marks a the constraint c as being entailed by a.
681
   * The reason has to do with integer reasoning.
682
   *
683
   * After calling impliedByIntHole(), the caller should either raise a conflict
684
   * or try call tryToPropagate().
685
   */
686
  void impliedByIntHole(ConstraintCP a, bool inConflict);
687
688
  /**
689
   * Marks a the constraint c as being entailed by a.
690
   * The reason has to do with integer reasoning.
691
   *
692
   * After calling impliedByIntHole(), the caller should either raise a conflict
693
   * or try call tryToPropagate().
694
   */
695
  void impliedByIntHole(const ConstraintCPVec& b, bool inConflict);
696
697
  /**
698
   * This is a lemma of the form:
699
   *   x < d or x = d or x > d
700
   * The current constraint c is one of the above constraints and {a,b}
701
   * are the negation of the other two constraints.
702
   *
703
   * Preconditions:
704
   * - negationHasProof() == inConflict.
705
   *
706
   * After calling impliedByTrichotomy(), the caller should either raise a conflict
707
   * or try call tryToPropagate().
708
   */
709
  void impliedByTrichotomy(ConstraintCP a, ConstraintCP b, bool inConflict);
710
711
  /**
712
   * Marks the node as having a Farkas proof.
713
   *
714
   * Preconditions:
715
   * - coeffs == NULL if proofs are off.
716
   * - See the comments for ConstraintRule for the form of coeffs when
717
   *   proofs are on.
718
   * - negationHasProof() == inConflict.
719
   *
720
   * After calling impliedByFarkas(), the caller should either raise a conflict
721
   * or try call tryToPropagate().
722
   */
723
  void impliedByFarkas(const ConstraintCPVec& b, RationalVectorCP coeffs, bool inConflict);
724
725
  /**
726
   * Generates an implication node, B => getLiteral(),
727
   * where B is the result of externalExplainByAssertions(b).
728
   * Does not guarantee b is the explanation of the constraint.
729
   */
730
  Node externalImplication(const ConstraintCPVec& b) const;
731
732
  /**
733
   * Returns true if the variable is assigned the value dr,
734
   * the constraint would be satisfied.
735
   */
736
  bool satisfiedBy(const DeltaRational& dr) const;
737
738
  /**
739
   * The node must have a proof already and be eligible for propagation!
740
   * You probably want to call tryToPropagate() instead.
741
   *
742
   * Preconditions:
743
   * - hasProof()
744
   * - canBePropagated()
745
   * - !assertedToTheTheory()
746
   */
747
  void propagate();
748
749
  /**
750
   * If the constraint
751
   *   canBePropagated() and
752
   *   !assertedToTheTheory(),
753
   * the constraint is added to the database's propagation queue.
754
   *
755
   * Precondition:
756
   * - hasProof()
757
   */
758
  void tryToPropagate();
759
760
  /**
761
   * Returns a reference to the containing database.
762
   * Precondition: the constraint must be initialized.
763
   */
764
  const ConstraintDatabase& getDatabase() const;
765
766
  /** Returns the constraint rule at the position. */
767
  const ConstraintRule& getConstraintRule() const;
768
769
 private:
770
  /**  Returns true if the constraint has been initialized. */
771
  bool initialized() const;
772
773
  /**
774
   * This initializes the fields that cannot be set in the constructor due to
775
   * circular dependencies.
776
   */
777
  void initialize(ConstraintDatabase* db,
778
                  SortedConstraintMapIterator v,
779
                  ConstraintP negation);
780
781
  class ConstraintRuleCleanup
782
  {
783
   public:
784
5110077
    inline void operator()(ConstraintRule* crp)
785
    {
786
5110077
      Assert(crp != NULL);
787
5110077
      ConstraintP constraint = crp->d_constraint;
788
5110077
      Assert(constraint->d_crid != ConstraintRuleIdSentinel);
789
5110077
      constraint->d_crid = ConstraintRuleIdSentinel;
790
5110077
      if (constraint->isProofProducing())
791
      {
792
131368
        if (crp->d_farkasCoefficients != RationalVectorCPSentinel)
793
        {
794
34766
          delete crp->d_farkasCoefficients;
795
        }
796
      }
797
5110077
    }
798
  };
799
800
  class CanBePropagatedCleanup
801
  {
802
   public:
803
446164
    inline void operator()(ConstraintP* p)
804
    {
805
446164
      ConstraintP constraint = *p;
806
446164
      Assert(constraint->d_canBePropagated);
807
446164
      constraint->d_canBePropagated = false;
808
446164
    }
809
  };
810
811
  class AssertionOrderCleanup
812
  {
813
   public:
814
3285040
    inline void operator()(ConstraintP* p)
815
    {
816
3285040
      ConstraintP constraint = *p;
817
3285040
      Assert(constraint->assertedToTheTheory());
818
3285040
      constraint->d_assertionOrder = AssertionOrderSentinel;
819
3285040
      constraint->d_witness = TNode::null();
820
3285040
      Assert(!constraint->assertedToTheTheory());
821
3285040
    }
822
  };
823
824
  class SplitCleanup
825
  {
826
   public:
827
17838
    inline void operator()(ConstraintP* p)
828
    {
829
17838
      ConstraintP constraint = *p;
830
17838
      Assert(constraint->d_split);
831
17838
      constraint->d_split = false;
832
17838
    }
833
  };
834
835
  /**
836
   * Returns true if the node is safe to garbage collect.
837
   * Both it and its negation must have no context dependent data set.
838
   */
839
  bool safeToGarbageCollect() const;
840
841
  /**
842
   * Returns true if the constraint has no context dependent data set.
843
   */
844
  bool contextDependentDataIsSet() const;
845
846
  /**
847
   * Returns true if the node correctly corresponds to the constraint that is
848
   * being set.
849
   */
850
  bool sanityChecking(Node n) const;
851
852
  /** Returns a reference to the map for d_variable. */
853
  SortedConstraintMap& constraintSet() const;
854
855
  /** Returns coefficients for the proofs for farkas cancellation. */
856
  static std::pair<int, int> unateFarkasSigns(ConstraintCP a, ConstraintCP b);
857
858
  Node externalExplain(AssertionOrder order) const;
859
  /**
860
   * Returns an explanation of that was assertedBefore(order).
861
   * The constraint must have a proof.
862
   * The constraint cannot be selfExplaining().
863
   *
864
   * This is the minimum fringe of the implication tree
865
   * s.t. every constraint is assertedBefore(order) or hasEqualityEngineProof().
866
   */
867
  std::shared_ptr<ProofNode> externalExplain(NodeBuilder& nb,
868
                                             AssertionOrder order) const;
869
870
  static Node externalExplain(const ConstraintCPVec& b, AssertionOrder order);
871
872
14209911
  inline ArithProofType getProofType() const {
873
14209911
    return getConstraintRule().d_proofType;
874
  }
875
876
310183
  inline AntecedentId getEndAntecedent() const {
877
310183
    return getConstraintRule().d_antecedentEnd;
878
  }
879
880
312
  inline RationalVectorCP getFarkasCoefficients() const
881
  {
882
312
    return d_produceProofs ? getConstraintRule().d_farkasCoefficients : nullptr;
883
  }
884
885
  void debugPrint() const;
886
887
  /**
888
   * The proof of the node is empty.
889
   * The proof must be a special proof. Either
890
   *   isSelfExplaining() or
891
   *    hasEqualityEngineProof()
892
   */
893
  bool antecentListIsEmpty() const;
894
895
  bool antecedentListLengthIsOne() const;
896
897
  /** Return true if every element in b has a proof. */
898
  static bool allHaveProof(const ConstraintCPVec& b);
899
900
  /** Precondition: hasFarkasProof()
901
   * Computes the combination implied by the farkas coefficients. Sees if it is
902
   * a contradiction.
903
   */
904
905
  bool wellFormedFarkasProof() const;
906
907
  /** The ArithVar associated with the constraint. */
908
  const ArithVar d_variable;
909
910
  /** The type of the Constraint. */
911
  const ConstraintType d_type;
912
913
  /** The DeltaRational value with the constraint. */
914
  const DeltaRational d_value;
915
916
  /** A pointer to the associated database for the Constraint. */
917
  ConstraintDatabase* d_database;
918
919
  /**
920
   * The node to be communicated with the TheoryEngine.
921
   *
922
   * This is not context dependent, but may be set once.
923
   *
924
   * This must be set if the constraint canBePropagated().
925
   * This must be set if the constraint assertedToTheTheory().
926
   * Otherwise, this may be null().
927
   */
928
  Node d_literal;
929
930
  /** Pointer to the negation of the Constraint. */
931
  ConstraintP d_negation;
932
933
  /**
934
   * This is true if the associated node can be propagated.
935
   *
936
   * This should be enabled if the node has been preregistered.
937
   *
938
   * Sat Context Dependent.
939
   * This is initially false.
940
   */
941
  bool d_canBePropagated;
942
943
  /**
944
   * This is the order the constraint was asserted to the theory.
945
   * If this has been set, the node can be used in conflicts.
946
   * If this is c.d_assertedOrder < d.d_assertedOrder, then c can be used in the
947
   * explanation of d.
948
   *
949
   * This should be set after the literal is dequeued by Theory::get().
950
   *
951
   * Sat Context Dependent.
952
   * This is initially AssertionOrderSentinel.
953
   */
954
  AssertionOrder d_assertionOrder;
955
956
  /**
957
   * This is guaranteed to be on the fact queue.
958
   * For example if x + y = x + 1 is on the fact queue, then use this
959
   */
960
  TNode d_witness;
961
962
  /**
963
   * The position of the constraint in the constraint rule id.
964
   *
965
   * Sat Context Dependent.
966
   * This is initially
967
   */
968
  ConstraintRuleID d_crid;
969
970
  /**
971
   * True if the equality has been split.
972
   * Only meaningful if ConstraintType == Equality.
973
   *
974
   * User Context Dependent.
975
   * This is initially false.
976
   */
977
  bool d_split;
978
979
  /**
980
   * Position in sorted constraint set for the variable.
981
   * Unset if d_type is Disequality.
982
   */
983
  SortedConstraintMapIterator d_variablePosition;
984
985
  /** Whether to produce proofs, */
986
  bool d_produceProofs;
987
988
}; /* class ConstraintValue */
989
990
std::ostream& operator<<(std::ostream& o, const Constraint& c);
991
std::ostream& operator<<(std::ostream& o, const ConstraintP c);
992
std::ostream& operator<<(std::ostream& o, const ConstraintCP c);
993
std::ostream& operator<<(std::ostream& o, const ConstraintType t);
994
std::ostream& operator<<(std::ostream& o, const ValueCollection& c);
995
std::ostream& operator<<(std::ostream& o, const ConstraintCPVec& v);
996
std::ostream& operator<<(std::ostream& o, const ArithProofType);
997
998
class ConstraintDatabase : protected EnvObj
999
{
1000
 private:
1001
  /**
1002
   * The map from ArithVars to their unique databases.
1003
   * When the vector changes size, we cannot allow the maps to move so this
1004
   * is a vector of pointers.
1005
   */
1006
  std::vector<PerVariableDatabase*> d_varDatabases;
1007
1008
  SortedConstraintMap& getVariableSCM(ArithVar v) const;
1009
1010
  /** Maps literals to constraints.*/
1011
  NodetoConstraintMap d_nodetoConstraintMap;
1012
1013
  /**
1014
   * A queue of propagated constraints.
1015
   * ConstraintCP are pointers.
1016
   * The elements of the queue do not require destruction.
1017
   */
1018
  context::CDQueue<ConstraintCP> d_toPropagate;
1019
1020
  /**
1021
   * Proofs are lists of valid constraints terminated by the first null
1022
   * sentinel value in the proof list.
1023
   * We abbreviate d_antecedents as ans in the comment.
1024
   *
1025
   * The proof at p in ans[p] of length n is
1026
   *  (NullConstraint, ans[p-(n-1)], ... , ans[p-1], ans[p])
1027
   *
1028
   * The proof at p corresponds to the conjunction:
1029
   *  (and x_i)
1030
   *
1031
   * So the proof of a Constraint c corresponds to the horn clause:
1032
   *  (implies (and x_i) c)
1033
   * where (and x_i) is the proof at c.d_crid d_antecedentEnd.
1034
   *
1035
   * Constraints are pointers so this list is designed not to require any destruction.
1036
   */
1037
  CDConstraintList d_antecedents;
1038
1039
  typedef context::CDList<ConstraintRule, Constraint::ConstraintRuleCleanup> ConstraintRuleList;
1040
  typedef context::CDList<ConstraintP, Constraint::CanBePropagatedCleanup> CBPList;
1041
  typedef context::CDList<ConstraintP, Constraint::AssertionOrderCleanup> AOList;
1042
  typedef context::CDList<ConstraintP, Constraint::SplitCleanup> SplitList;
1043
1044
1045
1046
  /**
1047
   * The watch lists are collected together as they need to be garbage collected
1048
   * carefully.
1049
   */
1050
6268
  struct Watches{
1051
1052
    /**
1053
     * Contains the exact list of constraints that have a proof.
1054
     * Upon pop, this unsets d_crid to NoAP.
1055
     *
1056
     * The index in this list is the proper ordering of the proofs.
1057
     */
1058
    ConstraintRuleList d_constraintProofs;
1059
1060
    /**
1061
     * Contains the exact list of constraints that can be used for propagation.
1062
     */
1063
    CBPList d_canBePropagatedWatches;
1064
1065
    /**
1066
     * Contains the exact list of constraints that have been asserted to the theory.
1067
     */
1068
    AOList d_assertionOrderWatches;
1069
1070
1071
    /**
1072
     * Contains the exact list of atoms that have been preregistered.
1073
     * This is a pointer as it must be destroyed before the elements of
1074
     * d_varDatabases.
1075
     */
1076
    SplitList d_splitWatches;
1077
    Watches(context::Context* satContext, context::Context* userContext);
1078
  };
1079
  Watches* d_watches;
1080
1081
  void pushSplitWatch(ConstraintP c);
1082
  void pushCanBePropagatedWatch(ConstraintP c);
1083
  void pushAssertionOrderWatch(ConstraintP c, TNode witness);
1084
1085
  /** Assumes that antecedents have already been pushed. */
1086
  void pushConstraintRule(const ConstraintRule& crp);
1087
1088
  /** Returns true if all of the entries of the vector are empty. */
1089
  static bool emptyDatabase(const std::vector<PerVariableDatabase>& vec);
1090
1091
  /** Map from nodes to arithvars. */
1092
  const ArithVariables& d_avariables;
1093
1094
342064
  const ArithVariables& getArithVariables() const{
1095
342064
    return d_avariables;
1096
  }
1097
1098
  ArithCongruenceManager& d_congruenceManager;
1099
1100
  /** Owned by the TheoryArithPrivate, used here. */
1101
  EagerProofGenerator* d_pfGen;
1102
  /** Owned by the TheoryArithPrivate, used here. */
1103
  ProofNodeManager* d_pnm;
1104
1105
  RaiseConflict d_raiseConflict;
1106
1107
1108
  const Rational d_one;
1109
  const Rational d_negOne;
1110
1111
  friend class Constraint;
1112
1113
 public:
1114
  ConstraintDatabase(Env& env,
1115
                     const ArithVariables& variables,
1116
                     ArithCongruenceManager& dm,
1117
                     RaiseConflict conflictCallBack,
1118
                     EagerProofGenerator* pfGen);
1119
1120
  ~ConstraintDatabase();
1121
1122
  /** Adds a literal to the database. */
1123
  ConstraintP addLiteral(TNode lit);
1124
1125
  /**
1126
   * If hasLiteral() is true, returns the constraint.
1127
   * Otherwise, returns NullConstraint.
1128
   */
1129
  ConstraintP lookup(TNode literal) const;
1130
1131
  /**
1132
   * Returns true if the literal has been added to the database.
1133
   * This is a hash table lookup.
1134
   * It does not look in the database for an equivalent corresponding constraint.
1135
   */
1136
  bool hasLiteral(TNode literal) const;
1137
1138
2878666
  bool hasMorePropagations() const{
1139
2878666
    return !d_toPropagate.empty();
1140
  }
1141
1142
507262
  ConstraintCP nextPropagation(){
1143
507262
    Assert(hasMorePropagations());
1144
1145
507262
    ConstraintCP p = d_toPropagate.front();
1146
507262
    d_toPropagate.pop();
1147
1148
507262
    return p;
1149
  }
1150
1151
  void addVariable(ArithVar v);
1152
  bool variableDatabaseIsSetup(ArithVar v) const;
1153
  void removeVariable(ArithVar v);
1154
1155
  /** Get an explanation and proof for this constraint from the equality engine
1156
   */
1157
  TrustNode eeExplain(ConstraintCP c) const;
1158
  /** Get an explanation for this constraint from the equality engine */
1159
  void eeExplain(ConstraintCP c, NodeBuilder& nb) const;
1160
1161
  /**
1162
   * Returns a constraint with the variable v, the constraint type t, and a value
1163
   * dominated by r (explained below) if such a constraint exists in the database.
1164
   * If no such constraint exists, NullConstraint is returned.
1165
   *
1166
   * t must be either UpperBound or LowerBound.
1167
   * The returned value v is dominated:
1168
   *  If t is UpperBound, r <= v
1169
   *  If t is LowerBound, r >= v
1170
   *
1171
   * variableDatabaseIsSetup(v) must be true.
1172
   */
1173
  ConstraintP getBestImpliedBound(ArithVar v, ConstraintType t, const DeltaRational& r) const;
1174
1175
  /** Returns the constraint, if it exists */
1176
  ConstraintP lookupConstraint(ArithVar v, ConstraintType t, const DeltaRational& r) const;
1177
1178
  /**
1179
   * Returns a constraint with the variable v, the constraint type t and the value r.
1180
   * If there is such a constraint in the database already, it is returned.
1181
   * If there is no such constraint, this constraint is added to the database.
1182
   *
1183
   */
1184
  ConstraintP getConstraint(ArithVar v, ConstraintType t, const DeltaRational& r);
1185
1186
  /**
1187
   * Returns a constraint of the given type for the value and variable
1188
   * for the given ValueCollection, vc.
1189
   * This is made if there is no such constraint.
1190
   */
1191
  ConstraintP ensureConstraint(ValueCollection& vc, ConstraintType t);
1192
1193
1194
  void deleteConstraintAndNegation(ConstraintP c);
1195
1196
  /** Given constraints `a` and `b` such that `a OR b` by unate reasoning,
1197
   *  adds a TrustNode to `out` which proves `a OR b` as a lemma.
1198
   *
1199
   *  Example: `x <= 5` OR `5 <= x`.
1200
   */
1201
  void proveOr(std::vector<TrustNode>& out,
1202
               ConstraintP a,
1203
               ConstraintP b,
1204
               bool negateSecond) const;
1205
  /** Given constraints `a` and `b` such that `a` implies `b` by unate
1206
   * reasoning, adds a TrustNode to `out` which proves `-a OR b` as a lemma.
1207
   *
1208
   *  Example: `x >= 5` -> `x >= 4`.
1209
   */
1210
  void implies(std::vector<TrustNode>& out, ConstraintP a, ConstraintP b) const;
1211
  /** Given constraints `a` and `b` such that `not(a AND b)` by unate reasoning,
1212
   *  adds a TrustNode to `out` which proves `-a OR -b` as a lemma.
1213
   *
1214
   *  Example: `x >= 4` -> `x <= 3`.
1215
   */
1216
  void mutuallyExclusive(std::vector<TrustNode>& out,
1217
                         ConstraintP a,
1218
                         ConstraintP b) const;
1219
1220
  /**
1221
   * Outputs a minimal set of unate implications onto the vector for the variable.
1222
   * This outputs lemmas of the general forms
1223
   *     (= p c) implies (<= p d) for c < d, or
1224
   *     (= p c) implies (not (= p d)) for c != d.
1225
   */
1226
  void outputUnateEqualityLemmas(std::vector<TrustNode>& lemmas) const;
1227
  void outputUnateEqualityLemmas(std::vector<TrustNode>& lemmas,
1228
                                 ArithVar v) const;
1229
1230
  /**
1231
   * Outputs a minimal set of unate implications onto the vector for the variable.
1232
   *
1233
   * If ineqs is true, this outputs lemmas of the general form
1234
   *     (<= p c) implies (<= p d) for c < d.
1235
   */
1236
  void outputUnateInequalityLemmas(std::vector<TrustNode>& lemmas) const;
1237
  void outputUnateInequalityLemmas(std::vector<TrustNode>& lemmas,
1238
                                   ArithVar v) const;
1239
1240
  void unatePropLowerBound(ConstraintP curr, ConstraintP prev);
1241
  void unatePropUpperBound(ConstraintP curr, ConstraintP prev);
1242
  void unatePropEquality(ConstraintP curr, ConstraintP prevLB, ConstraintP prevUB);
1243
1244
  /** AntecendentID must be in range. */
1245
  ConstraintCP getAntecedent(AntecedentId p) const;
1246
1247
4564598
  bool isProofEnabled() const { return d_pnm != nullptr; }
1248
1249
 private:
1250
  /** returns true if cons is now in conflict. */
1251
  bool handleUnateProp(ConstraintP ant, ConstraintP cons);
1252
1253
  DenseSet d_reclaimable;
1254
1255
  class Statistics {
1256
  public:
1257
    IntStat d_unatePropagateCalls;
1258
    IntStat d_unatePropagateImplications;
1259
1260
    Statistics();
1261
  } d_statistics;
1262
1263
}; /* ConstraintDatabase */
1264
1265
}  // namespace arith
1266
}  // namespace theory
1267
}  // namespace cvc5
1268
1269
#endif /* CVC5__THEORY__ARITH__CONSTRAINT_H */