GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/constraint.h Lines: 114 120 95.0 %
Date: 2021-05-22 Branches: 42 238 17.6 %

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