GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/theory_arith_private.cpp Lines: 1752 2958 59.2 %
Date: 2021-08-01 Branches: 3430 12530 27.4 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Alex Ozdemir, Andrew Reynolds
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 "theory/arith/theory_arith_private.h"
20
21
#include <map>
22
#include <queue>
23
#include <vector>
24
25
#include "base/output.h"
26
#include "context/cdhashset.h"
27
#include "context/cdinsert_hashmap.h"
28
#include "context/cdlist.h"
29
#include "context/cdqueue.h"
30
#include "context/context.h"
31
#include "expr/kind.h"
32
#include "expr/metakind.h"
33
#include "expr/node.h"
34
#include "expr/node_algorithm.h"
35
#include "expr/node_builder.h"
36
#include "expr/skolem_manager.h"
37
#include "options/arith_options.h"
38
#include "options/base_options.h"
39
#include "preprocessing/util/ite_utilities.h"
40
#include "proof/proof_generator.h"
41
#include "proof/proof_node_manager.h"
42
#include "proof/proof_rule.h"
43
#include "smt/logic_exception.h"
44
#include "smt/smt_statistics_registry.h"
45
#include "smt_util/boolean_simplification.h"
46
#include "theory/arith/approx_simplex.h"
47
#include "theory/arith/arith_ite_utils.h"
48
#include "theory/arith/arith_rewriter.h"
49
#include "theory/arith/arith_static_learner.h"
50
#include "theory/arith/arith_utilities.h"
51
#include "theory/arith/arithvar.h"
52
#include "theory/arith/congruence_manager.h"
53
#include "theory/arith/constraint.h"
54
#include "theory/arith/cut_log.h"
55
#include "theory/arith/delta_rational.h"
56
#include "theory/arith/dio_solver.h"
57
#include "theory/arith/linear_equality.h"
58
#include "theory/arith/matrix.h"
59
#include "theory/arith/nl/nonlinear_extension.h"
60
#include "theory/arith/normal_form.h"
61
#include "theory/arith/partial_model.h"
62
#include "theory/arith/simplex.h"
63
#include "theory/arith/theory_arith.h"
64
#include "theory/ext_theory.h"
65
#include "theory/quantifiers/fmf/bounded_integers.h"
66
#include "theory/rewriter.h"
67
#include "theory/theory_model.h"
68
#include "theory/trust_substitutions.h"
69
#include "theory/valuation.h"
70
#include "util/dense_map.h"
71
#include "util/integer.h"
72
#include "util/random.h"
73
#include "util/rational.h"
74
#include "util/result.h"
75
#include "util/statistics_stats.h"
76
77
using namespace std;
78
using namespace cvc5::kind;
79
80
namespace cvc5 {
81
namespace theory {
82
namespace arith {
83
84
static Node toSumNode(const ArithVariables& vars, const DenseMap<Rational>& sum);
85
static bool complexityBelow(const DenseMap<Rational>& row, uint32_t cap);
86
87
9838
TheoryArithPrivate::TheoryArithPrivate(TheoryArith& containing,
88
                                       context::Context* c,
89
                                       context::UserContext* u,
90
                                       BranchAndBound& bab,
91
9838
                                       ProofNodeManager* pnm)
92
    : d_containing(containing),
93
      d_foundNl(false),
94
      d_rowTracking(),
95
      d_bab(bab),
96
      d_pnm(pnm),
97
      d_checker(),
98
9838
      d_pfGen(new EagerProofGenerator(d_pnm, u)),
99
      d_constraintDatabase(c,
100
                           u,
101
                           d_partialModel,
102
                           d_congruenceManager,
103
                           RaiseConflict(*this),
104
                           d_pfGen.get(),
105
                           d_pnm),
106
      d_qflraStatus(Result::SAT_UNKNOWN),
107
      d_unknownsInARow(0),
108
      d_hasDoneWorkSinceCut(false),
109
      d_learner(u),
110
      d_assertionsThatDoNotMatchTheirLiterals(c),
111
      d_nextIntegerCheckVar(0),
112
      d_constantIntegerVariables(c),
113
      d_diseqQueue(c, false),
114
      d_currentPropagationList(),
115
      d_learnedBounds(c),
116
      d_preregisteredNodes(u),
117
19676
      d_partialModel(c, DeltaComputeCallback(*this)),
118
      d_errorSet(
119
9838
          d_partialModel, TableauSizes(&d_tableau), BoundCountingLookup(*this)),
120
      d_tableau(),
121
      d_linEq(d_partialModel,
122
              d_tableau,
123
              d_rowTracking,
124
19676
              BasicVarModelUpdateCallBack(*this)),
125
      d_diosolver(c),
126
      d_restartsCounter(0),
127
      d_tableauSizeHasBeenModified(false),
128
      d_tableauResetDensity(1.6),
129
      d_tableauResetPeriod(10),
130
      d_conflicts(c),
131
19676
      d_blackBoxConflict(c, Node::null()),
132
19676
      d_blackBoxConflictPf(c, std::shared_ptr<ProofNode>(nullptr)),
133
      d_congruenceManager(c,
134
                          u,
135
                          d_constraintDatabase,
136
19676
                          SetupLiteralCallBack(*this),
137
                          d_partialModel,
138
                          RaiseEqualityEngineConflict(*this),
139
                          d_pnm),
140
29514
      d_cmEnabled(c, options::arithCongMan()),
141
142
      d_dualSimplex(
143
19676
          d_linEq, d_errorSet, RaiseConflict(*this), TempVarMalloc(*this)),
144
      d_fcSimplex(
145
19676
          d_linEq, d_errorSet, RaiseConflict(*this), TempVarMalloc(*this)),
146
      d_soiSimplex(
147
19676
          d_linEq, d_errorSet, RaiseConflict(*this), TempVarMalloc(*this)),
148
      d_attemptSolSimplex(
149
19676
          d_linEq, d_errorSet, RaiseConflict(*this), TempVarMalloc(*this)),
150
      d_pass1SDP(NULL),
151
      d_otherSDP(NULL),
152
      d_lastContextIntegerAttempted(c, -1),
153
154
      d_DELTA_ZERO(0),
155
      d_approxCuts(c),
156
      d_fullCheckCounter(0),
157
      d_cutCount(c, 0),
158
      d_cutInContext(c),
159
      d_likelyIntegerInfeasible(c, false),
160
      d_guessedCoeffSet(c, false),
161
      d_guessedCoeffs(),
162
      d_treeLog(NULL),
163
      d_replayVariables(),
164
      d_replayConstraints(),
165
      d_lhsTmp(),
166
      d_approxStats(NULL),
167
      d_attemptSolveIntTurnedOff(u, 0),
168
      d_dioSolveResources(0),
169
      d_solveIntMaybeHelp(0u),
170
      d_solveIntAttempts(0u),
171
      d_newFacts(false),
172
      d_previousStatus(Result::SAT_UNKNOWN),
173
226274
      d_statistics("theory::arith::")
174
{
175
9838
}
176
177
19676
TheoryArithPrivate::~TheoryArithPrivate(){
178
9838
  if(d_treeLog != NULL){ delete d_treeLog; }
179
9838
  if(d_approxStats != NULL) { delete d_approxStats; }
180
9838
}
181
182
9799
bool TheoryArithPrivate::needsEqualityEngine(EeSetupInfo& esi)
183
{
184
9799
  if (!d_cmEnabled)
185
  {
186
    return false;
187
  }
188
9799
  return d_congruenceManager.needsEqualityEngine(esi);
189
}
190
9838
void TheoryArithPrivate::finishInit()
191
{
192
9838
  if (d_cmEnabled)
193
  {
194
9799
    eq::EqualityEngine* ee = d_containing.getEqualityEngine();
195
9799
    Assert(ee != nullptr);
196
9799
    d_congruenceManager.finishInit(ee);
197
  }
198
9838
}
199
200
static bool contains(const ConstraintCPVec& v, ConstraintP con){
201
  for(unsigned i = 0, N = v.size(); i < N; ++i){
202
    if(v[i] == con){
203
      return true;
204
    }
205
  }
206
  return false;
207
}
208
static void drop( ConstraintCPVec& v, ConstraintP con){
209
  size_t readPos, writePos, N;
210
  for(readPos = 0, writePos = 0, N = v.size(); readPos < N; ++readPos){
211
    ConstraintCP curr = v[readPos];
212
    if(curr != con){
213
      v[writePos] = curr;
214
      writePos++;
215
    }
216
  }
217
  v.resize(writePos);
218
}
219
220
221
static void resolve(ConstraintCPVec& buf, ConstraintP c, const ConstraintCPVec& pos, const ConstraintCPVec& neg){
222
  unsigned posPos CVC5_UNUSED = pos.size();
223
  for(unsigned i = 0, N = pos.size(); i < N; ++i){
224
    if(pos[i] == c){
225
      posPos = i;
226
    }else{
227
      buf.push_back(pos[i]);
228
    }
229
  }
230
  Assert(posPos < pos.size());
231
  ConstraintP negc = c->getNegation();
232
  unsigned negPos CVC5_UNUSED = neg.size();
233
  for(unsigned i = 0, N = neg.size(); i < N; ++i){
234
    if(neg[i] == negc){
235
      negPos = i;
236
    }else{
237
      buf.push_back(neg[i]);
238
    }
239
  }
240
  Assert(negPos < neg.size());
241
242
  // Assert(dnconf.getKind() == kind::AND);
243
  // Assert(upconf.getKind() == kind::AND);
244
  // Assert(dnpos < dnconf.getNumChildren());
245
  // Assert(uppos < upconf.getNumChildren());
246
  // Assert(equalUpToNegation(dnconf[dnpos], upconf[uppos]));
247
248
  // NodeBuilder nb(kind::AND);
249
  // dropPosition(nb, dnconf, dnpos);
250
  // dropPosition(nb, upconf, uppos);
251
  // return safeConstructNary(nb);
252
}
253
254
TheoryArithPrivate::ModelException::ModelException(TNode n, const char* msg)
255
{
256
  stringstream ss;
257
  ss << "Cannot construct a model for " << n << " as " << endl << msg;
258
  setMessage(ss.str());
259
}
260
TheoryArithPrivate::ModelException::~ModelException() {}
261
262
9838
TheoryArithPrivate::Statistics::Statistics(const std::string& name)
263
    : d_statAssertUpperConflicts(
264
19676
        smtStatisticsRegistry().registerInt(name + "AssertUpperConflicts")),
265
      d_statAssertLowerConflicts(
266
19676
          smtStatisticsRegistry().registerInt(name + "AssertLowerConflicts")),
267
      d_statUserVariables(
268
19676
          smtStatisticsRegistry().registerInt(name + "UserVariables")),
269
      d_statAuxiliaryVariables(
270
19676
          smtStatisticsRegistry().registerInt(name + "AuxiliaryVariables")),
271
      d_statDisequalitySplits(
272
19676
          smtStatisticsRegistry().registerInt(name + "DisequalitySplits")),
273
      d_statDisequalityConflicts(
274
19676
          smtStatisticsRegistry().registerInt(name + "DisequalityConflicts")),
275
      d_simplifyTimer(
276
19676
          smtStatisticsRegistry().registerTimer(name + "simplifyTimer")),
277
      d_staticLearningTimer(
278
19676
          smtStatisticsRegistry().registerTimer(name + "staticLearningTimer")),
279
      d_presolveTime(
280
19676
          smtStatisticsRegistry().registerTimer(name + "presolveTime")),
281
      d_newPropTime(
282
19676
          smtStatisticsRegistry().registerTimer(name + "newPropTimer")),
283
9838
      d_externalBranchAndBounds(smtStatisticsRegistry().registerInt(
284
19676
          name + "externalBranchAndBounds")),
285
      d_initialTableauSize(
286
19676
          smtStatisticsRegistry().registerInt(name + "initialTableauSize")),
287
      d_currSetToSmaller(
288
19676
          smtStatisticsRegistry().registerInt(name + "currSetToSmaller")),
289
      d_smallerSetToCurr(
290
19676
          smtStatisticsRegistry().registerInt(name + "smallerSetToCurr")),
291
      d_restartTimer(
292
19676
          smtStatisticsRegistry().registerTimer(name + "restartTimer")),
293
      d_boundComputationTime(
294
19676
          smtStatisticsRegistry().registerTimer(name + "bound::time")),
295
9838
      d_boundComputations(smtStatisticsRegistry().registerInt(
296
19676
          name + "bound::boundComputations")),
297
9838
      d_boundPropagations(smtStatisticsRegistry().registerInt(
298
19676
          name + "bound::boundPropagations")),
299
      d_unknownChecks(
300
19676
          smtStatisticsRegistry().registerInt(name + "status::unknowns")),
301
9838
      d_maxUnknownsInARow(smtStatisticsRegistry().registerInt(
302
19676
          name + "status::maxUnknownsInARow")),
303
9838
      d_avgUnknownsInARow(smtStatisticsRegistry().registerAverage(
304
19676
          name + "status::avgUnknownsInARow")),
305
9838
      d_revertsOnConflicts(smtStatisticsRegistry().registerInt(
306
19676
          name + "status::revertsOnConflicts")),
307
9838
      d_commitsOnConflicts(smtStatisticsRegistry().registerInt(
308
19676
          name + "status::commitsOnConflicts")),
309
9838
      d_nontrivialSatChecks(smtStatisticsRegistry().registerInt(
310
19676
          name + "status::nontrivialSatChecks")),
311
      d_replayLogRecCount(
312
19676
          smtStatisticsRegistry().registerInt(name + "z::approx::replay::rec")),
313
9838
      d_replayLogRecConflictEscalation(smtStatisticsRegistry().registerInt(
314
19676
          name + "z::approx::replay::rec::escalation")),
315
9838
      d_replayLogRecEarlyExit(smtStatisticsRegistry().registerInt(
316
19676
          name + "z::approx::replay::rec::earlyexit")),
317
9838
      d_replayBranchCloseFailures(smtStatisticsRegistry().registerInt(
318
19676
          name + "z::approx::replay::rec::branch::closefailures")),
319
9838
      d_replayLeafCloseFailures(smtStatisticsRegistry().registerInt(
320
19676
          name + "z::approx::replay::rec::leaf::closefailures")),
321
9838
      d_replayBranchSkips(smtStatisticsRegistry().registerInt(
322
19676
          name + "z::approx::replay::rec::branch::skips")),
323
9838
      d_mirCutsAttempted(smtStatisticsRegistry().registerInt(
324
19676
          name + "z::approx::cuts::mir::attempted")),
325
9838
      d_gmiCutsAttempted(smtStatisticsRegistry().registerInt(
326
19676
          name + "z::approx::cuts::gmi::attempted")),
327
9838
      d_branchCutsAttempted(smtStatisticsRegistry().registerInt(
328
19676
          name + "z::approx::cuts::branch::attempted")),
329
9838
      d_cutsReconstructed(smtStatisticsRegistry().registerInt(
330
19676
          name + "z::approx::cuts::reconstructed")),
331
9838
      d_cutsReconstructionFailed(smtStatisticsRegistry().registerInt(
332
19676
          name + "z::approx::cuts::reconstructed::failed")),
333
9838
      d_cutsProven(smtStatisticsRegistry().registerInt(
334
19676
          name + "z::approx::cuts::proofs")),
335
9838
      d_cutsProofFailed(smtStatisticsRegistry().registerInt(
336
19676
          name + "z::approx::cuts::proofs::failed")),
337
9838
      d_mipReplayLemmaCalls(smtStatisticsRegistry().registerInt(
338
19676
          name + "z::approx::external::calls")),
339
9838
      d_mipExternalCuts(smtStatisticsRegistry().registerInt(
340
19676
          name + "z::approx::external::cuts")),
341
9838
      d_mipExternalBranch(smtStatisticsRegistry().registerInt(
342
19676
          name + "z::approx::external::branches")),
343
9838
      d_inSolveInteger(smtStatisticsRegistry().registerInt(
344
19676
          name + "z::approx::inSolverInteger")),
345
9838
      d_branchesExhausted(smtStatisticsRegistry().registerInt(
346
19676
          name + "z::approx::exhausted::branches")),
347
9838
      d_execExhausted(smtStatisticsRegistry().registerInt(
348
19676
          name + "z::approx::exhausted::exec")),
349
9838
      d_pivotsExhausted(smtStatisticsRegistry().registerInt(
350
19676
          name + "z::approx::exhausted::pivots")),
351
      d_panicBranches(
352
19676
          smtStatisticsRegistry().registerInt(name + "z::arith::paniclemmas")),
353
      d_relaxCalls(
354
19676
          smtStatisticsRegistry().registerInt(name + "z::arith::relax::calls")),
355
9838
      d_relaxLinFeas(smtStatisticsRegistry().registerInt(
356
19676
          name + "z::arith::relax::feasible::res")),
357
9838
      d_relaxLinFeasFailures(smtStatisticsRegistry().registerInt(
358
19676
          name + "z::arith::relax::feasible::failures")),
359
9838
      d_relaxLinInfeas(smtStatisticsRegistry().registerInt(
360
19676
          name + "z::arith::relax::infeasible")),
361
9838
      d_relaxLinInfeasFailures(smtStatisticsRegistry().registerInt(
362
19676
          name + "z::arith::relax::infeasible::failures")),
363
9838
      d_relaxLinExhausted(smtStatisticsRegistry().registerInt(
364
19676
          name + "z::arith::relax::exhausted")),
365
      d_relaxOthers(
366
19676
          smtStatisticsRegistry().registerInt(name + "z::arith::relax::other")),
367
9838
      d_applyRowsDeleted(smtStatisticsRegistry().registerInt(
368
19676
          name + "z::arith::cuts::applyRowsDeleted")),
369
9838
      d_replaySimplexTimer(smtStatisticsRegistry().registerTimer(
370
19676
          name + "z::approx::replay::simplex::timer")),
371
9838
      d_replayLogTimer(smtStatisticsRegistry().registerTimer(
372
19676
          name + "z::approx::replay::log::timer")),
373
      d_solveIntTimer(
374
19676
          smtStatisticsRegistry().registerTimer(name + "z::solveInt::timer")),
375
9838
      d_solveRealRelaxTimer(smtStatisticsRegistry().registerTimer(
376
19676
          name + "z::solveRealRelax::timer")),
377
      d_solveIntCalls(
378
19676
          smtStatisticsRegistry().registerInt(name + "z::solveInt::calls")),
379
9838
      d_solveStandardEffort(smtStatisticsRegistry().registerInt(
380
19676
          name + "z::solveInt::calls::standardEffort")),
381
      d_approxDisabled(
382
19676
          smtStatisticsRegistry().registerInt(name + "z::approxDisabled")),
383
      d_replayAttemptFailed(
384
19676
          smtStatisticsRegistry().registerInt(name + "z::replayAttemptFailed")),
385
9838
      d_cutsRejectedDuringReplay(smtStatisticsRegistry().registerInt(
386
19676
          name + "z::approx::replay::cuts::rejected")),
387
9838
      d_cutsRejectedDuringLemmas(smtStatisticsRegistry().registerInt(
388
19676
          name + "z::approx::external::cuts::rejected")),
389
9838
      d_satPivots(smtStatisticsRegistry().registerHistogram<uint32_t>(
390
19676
          name + "pivots::sat")),
391
9838
      d_unsatPivots(smtStatisticsRegistry().registerHistogram<uint32_t>(
392
19676
          name + "pivots::unsat")),
393
9838
      d_unknownPivots(smtStatisticsRegistry().registerHistogram<uint32_t>(
394
19676
          name + "pivots::unknown")),
395
9838
      d_solveIntModelsAttempts(smtStatisticsRegistry().registerInt(
396
19676
          name + "z::solveInt::models::attempts")),
397
9838
      d_solveIntModelsSuccessful(smtStatisticsRegistry().registerInt(
398
19676
          name + "zzz::solveInt::models::successful")),
399
9838
      d_mipTimer(smtStatisticsRegistry().registerTimer(
400
19676
          name + "z::approx::mip::timer")),
401
      d_lpTimer(
402
19676
          smtStatisticsRegistry().registerTimer(name + "z::approx::lp::timer")),
403
9838
      d_mipProofsAttempted(smtStatisticsRegistry().registerInt(
404
19676
          name + "z::mip::proofs::attempted")),
405
9838
      d_mipProofsSuccessful(smtStatisticsRegistry().registerInt(
406
19676
          name + "z::mip::proofs::successful")),
407
9838
      d_numBranchesFailed(smtStatisticsRegistry().registerInt(
408
718174
          name + "z::mip::branch::proof::failed"))
409
{
410
9838
}
411
412
bool complexityBelow(const DenseMap<Rational>& row, uint32_t cap){
413
  DenseMap<Rational>::const_iterator riter, rend;
414
  for(riter=row.begin(), rend=row.end(); riter != rend; ++riter){
415
    ArithVar v = *riter;
416
    const Rational& q = row[v];
417
    if(q.complexity() > cap){
418
      return false;
419
    }
420
  }
421
  return true;
422
}
423
424
164520
bool TheoryArithPrivate::isProofEnabled() const
425
{
426
164520
  return d_pnm != nullptr;
427
}
428
429
68085
void TheoryArithPrivate::raiseConflict(ConstraintCP a, InferenceId id){
430
68085
  Assert(a->inConflict());
431
136170
  d_conflicts.push_back(std::make_pair(a, id));
432
68085
}
433
434
2144
void TheoryArithPrivate::raiseBlackBoxConflict(Node bb,
435
                                               std::shared_ptr<ProofNode> pf)
436
{
437
2144
  Debug("arith::bb") << "raiseBlackBoxConflict: " << bb << std::endl;
438
2144
  if (d_blackBoxConflict.get().isNull())
439
  {
440
2144
    if (isProofEnabled())
441
    {
442
416
      Debug("arith::bb") << "  with proof " << pf << std::endl;
443
416
      d_blackBoxConflictPf.set(pf);
444
    }
445
2144
    d_blackBoxConflict = bb;
446
  }
447
2144
}
448
449
14537068
bool TheoryArithPrivate::anyConflict() const
450
{
451
14537068
  return !conflictQueueEmpty() || !d_blackBoxConflict.get().isNull();
452
}
453
454
50029
void TheoryArithPrivate::revertOutOfConflict(){
455
50029
  d_partialModel.revertAssignmentChanges();
456
50029
  clearUpdates();
457
50029
  d_currentPropagationList.clear();
458
50029
}
459
460
1571572
void TheoryArithPrivate::clearUpdates(){
461
1571572
  d_updatedBounds.purge();
462
1571572
}
463
464
// void TheoryArithPrivate::raiseConflict(ConstraintCP a, ConstraintCP b){
465
//   ConstraintCPVec v;
466
//   v.push_back(a);
467
//   v.push_back(b);
468
//   d_conflicts.push_back(v);
469
// }
470
471
// void TheoryArithPrivate::raiseConflict(ConstraintCP a, ConstraintCP b, ConstraintCP c){
472
//   ConstraintCPVec v;
473
//   v.push_back(a);
474
//   v.push_back(b);
475
//   v.push_back(c);
476
//   d_conflicts.push_back(v);
477
// }
478
479
515796
void TheoryArithPrivate::zeroDifferenceDetected(ArithVar x){
480
515796
  if(d_cmEnabled){
481
515796
    Assert(d_congruenceManager.isWatchedVariable(x));
482
515796
    Assert(d_partialModel.upperBoundIsZero(x));
483
515796
    Assert(d_partialModel.lowerBoundIsZero(x));
484
485
515796
    ConstraintP lb = d_partialModel.getLowerBoundConstraint(x);
486
515796
    ConstraintP ub = d_partialModel.getUpperBoundConstraint(x);
487
488
515796
    if(lb->isEquality()){
489
207589
      d_congruenceManager.watchedVariableIsZero(lb);
490
308207
    }else if(ub->isEquality()){
491
      d_congruenceManager.watchedVariableIsZero(ub);
492
    }else{
493
308207
      d_congruenceManager.watchedVariableIsZero(lb, ub);
494
    }
495
  }
496
515796
}
497
498
bool TheoryArithPrivate::getSolveIntegerResource(){
499
  if(d_attemptSolveIntTurnedOff > 0){
500
    d_attemptSolveIntTurnedOff = d_attemptSolveIntTurnedOff - 1;
501
    return false;
502
  }else{
503
    return true;
504
  }
505
}
506
507
2537
bool TheoryArithPrivate::getDioCuttingResource(){
508
2537
  if(d_dioSolveResources > 0){
509
1883
    d_dioSolveResources--;
510
1883
    if(d_dioSolveResources == 0){
511
262
      d_dioSolveResources = -options::rrTurns();
512
    }
513
1883
    return true;
514
  }else{
515
654
    d_dioSolveResources++;
516
654
    if(d_dioSolveResources >= 0){
517
804
      d_dioSolveResources = options::dioSolverTurns();
518
    }
519
654
    return false;
520
  }
521
}
522
523
/* procedure AssertLower( x_i >= c_i ) */
524
1965249
bool TheoryArithPrivate::AssertLower(ConstraintP constraint){
525
1965249
  Assert(constraint != NullConstraint);
526
1965249
  Assert(constraint->isLowerBound());
527
1965249
  Assert(constraint->isTrue());
528
1965249
  Assert(!constraint->negationHasProof());
529
530
1965249
  ArithVar x_i = constraint->getVariable();
531
1965249
  const DeltaRational& c_i = constraint->getValue();
532
533
1965249
  Debug("arith") << "AssertLower(" << x_i << " " << c_i << ")"<< std::endl;
534
535
1965249
  Assert(!isInteger(x_i) || c_i.isIntegral());
536
537
  //TODO Relax to less than?
538
1965249
  if(d_partialModel.lessThanLowerBound(x_i, c_i)){
539
803474
    return false; //sat
540
  }
541
542
1161775
  int cmpToUB = d_partialModel.cmpToUpperBound(x_i, c_i);
543
1161775
  if(cmpToUB > 0){ //  c_i < \lowerbound(x_i)
544
734
    ConstraintP ubc = d_partialModel.getUpperBoundConstraint(x_i);
545
734
    ConstraintP negation = constraint->getNegation();
546
734
    negation->impliedByUnate(ubc, true);
547
548
734
    raiseConflict(constraint, InferenceId::ARITH_CONF_LOWER);
549
550
734
    ++(d_statistics.d_statAssertLowerConflicts);
551
734
    return true;
552
1161041
  }else if(cmpToUB == 0){
553
362484
    if(isInteger(x_i)){
554
164687
      d_constantIntegerVariables.push_back(x_i);
555
164687
      Debug("dio::push") << "dio::push " << x_i << endl;
556
    }
557
362484
    ConstraintP ub = d_partialModel.getUpperBoundConstraint(x_i);
558
559
362484
    if(d_cmEnabled){
560
362484
      if(!d_congruenceManager.isWatchedVariable(x_i) || c_i.sgn() != 0){
561
        // if it is not a watched variable report it
562
        // if it is is a watched variable and c_i == 0,
563
        // let zeroDifferenceDetected(x_i) catch this
564
115106
        d_congruenceManager.equalsConstant(constraint, ub);
565
      }
566
    }
567
568
362484
    const ValueCollection& vc = constraint->getValueCollection();
569
362484
    if(vc.hasEquality()){
570
256217
      Assert(vc.hasDisequality());
571
256217
      ConstraintP eq = vc.getEquality();
572
256217
      ConstraintP diseq = vc.getDisequality();
573
      // x <= b, x >= b |= x = b
574
      // (x > b or x < b or x = b)
575
256217
      Debug("arith::eq") << "lb == ub, propagate eq" << eq << endl;
576
256217
      bool triConflict = diseq->isTrue();
577
578
256217
      if(!eq->isTrue()){
579
251834
        eq->impliedByTrichotomy(constraint, ub, triConflict);
580
251834
        eq->tryToPropagate();
581
      }
582
256217
      if(triConflict){
583
        ++(d_statistics.d_statDisequalityConflicts);
584
        raiseConflict(eq, InferenceId::ARITH_CONF_TRICHOTOMY);
585
        return true;
586
      }
587
    }
588
  }else{
589
    // l <= x <= u and l < u
590
798557
    Assert(cmpToUB < 0);
591
798557
    const ValueCollection& vc = constraint->getValueCollection();
592
593
798557
    if(vc.hasDisequality()){
594
205967
      const ConstraintP diseq = vc.getDisequality();
595
205967
      if(diseq->isTrue()){
596
10679
        const ConstraintP ub = d_constraintDatabase.ensureConstraint(const_cast<ValueCollection&>(vc), UpperBound);
597
10679
        ConstraintP negUb = ub->getNegation();
598
599
        // l <= x, l != x |= l < x
600
        // |= not (l >= x)
601
10679
        bool ubInConflict = ub->hasProof();
602
10679
        bool learnNegUb = !(negUb->hasProof());
603
10679
        if(learnNegUb){
604
10679
          negUb->impliedByTrichotomy(constraint, diseq, ubInConflict);
605
10679
          negUb->tryToPropagate();
606
        }
607
10679
        if(ubInConflict){
608
          raiseConflict(ub, InferenceId::ARITH_CONF_TRICHOTOMY);
609
          return true;
610
10679
        }else if(learnNegUb){
611
10679
          d_learnedBounds.push_back(negUb);
612
        }
613
      }
614
    }
615
  }
616
617
1161041
  d_currentPropagationList.push_back(constraint);
618
1161041
  d_currentPropagationList.push_back(d_partialModel.getLowerBoundConstraint(x_i));
619
620
1161041
  d_partialModel.setLowerBoundConstraint(constraint);
621
622
1161041
  if(d_cmEnabled){
623
1160476
    if(d_congruenceManager.isWatchedVariable(x_i)){
624
771606
      int sgn = c_i.sgn();
625
771606
      if(sgn > 0){
626
172170
        d_congruenceManager.watchedVariableCannotBeZero(constraint);
627
599436
      }else if(sgn == 0 && d_partialModel.upperBoundIsZero(x_i)){
628
247378
        zeroDifferenceDetected(x_i);
629
      }
630
    }
631
  }
632
633
1161041
  d_updatedBounds.softAdd(x_i);
634
635
1161041
  if(Debug.isOn("model")) {
636
    Debug("model") << "before" << endl;
637
    d_partialModel.printModel(x_i);
638
    d_tableau.debugPrintIsBasic(x_i);
639
  }
640
641
1161041
  if(!d_tableau.isBasic(x_i)){
642
420370
    if(d_partialModel.getAssignment(x_i) < c_i){
643
57766
      d_linEq.update(x_i, c_i);
644
    }
645
  }else{
646
740671
    d_errorSet.signalVariable(x_i);
647
  }
648
649
1161041
  if(Debug.isOn("model")) {
650
    Debug("model") << "after" << endl;
651
    d_partialModel.printModel(x_i);
652
    d_tableau.debugPrintIsBasic(x_i);
653
 }
654
655
1161041
  return false; //sat
656
}
657
658
/* procedure AssertUpper( x_i <= c_i) */
659
1841257
bool TheoryArithPrivate::AssertUpper(ConstraintP constraint){
660
1841257
  Assert(constraint != NullConstraint);
661
1841257
  Assert(constraint->isUpperBound());
662
1841257
  Assert(constraint->isTrue());
663
1841257
  Assert(!constraint->negationHasProof());
664
665
1841257
  ArithVar x_i = constraint->getVariable();
666
1841257
  const DeltaRational& c_i = constraint->getValue();
667
668
1841257
  Debug("arith") << "AssertUpper(" << x_i << " " << c_i << ")"<< std::endl;
669
670
671
  //Too strong because of rounding with integers
672
  //Assert(!constraint->hasLiteral() || original == constraint->getLiteral());
673
1841257
  Assert(!isInteger(x_i) || c_i.isIntegral());
674
675
1841257
  Debug("arith") << "AssertUpper(" << x_i << " " << c_i << ")"<< std::endl;
676
677
1841257
  if(d_partialModel.greaterThanUpperBound(x_i, c_i) ){ // \upperbound(x_i) <= c_i
678
819346
    return false; //sat
679
  }
680
681
  // cmpToLb =  \lowerbound(x_i).cmp(c_i)
682
1021911
  int cmpToLB = d_partialModel.cmpToLowerBound(x_i, c_i);
683
1021911
  if( cmpToLB < 0 ){ //  \upperbound(x_i) < \lowerbound(x_i)
684
    // l_i <= x_i and c_i < l_i |= c_i < x_i
685
    // or ... |= not (x_i <= c_i)
686
2021
    ConstraintP lbc = d_partialModel.getLowerBoundConstraint(x_i);
687
2021
    ConstraintP negConstraint = constraint->getNegation();
688
2021
    negConstraint->impliedByUnate(lbc, true);
689
2021
    raiseConflict(constraint, InferenceId::ARITH_CONF_UPPER);
690
2021
    ++(d_statistics.d_statAssertUpperConflicts);
691
2021
    return true;
692
1019890
  }else if(cmpToLB == 0){ // \lowerBound(x_i) == \upperbound(x_i)
693
131567
    if(isInteger(x_i)){
694
81629
      d_constantIntegerVariables.push_back(x_i);
695
81629
      Debug("dio::push") << "dio::push " << x_i << endl;
696
    }
697
698
131567
    const ValueCollection& vc = constraint->getValueCollection();
699
131567
    ConstraintP lb = d_partialModel.getLowerBoundConstraint(x_i);
700
131567
    if(d_cmEnabled){
701
131567
      if(!d_congruenceManager.isWatchedVariable(x_i) || c_i.sgn() != 0){
702
        // if it is not a watched variable report it
703
        // if it is is a watched variable and c_i == 0,
704
        // let zeroDifferenceDetected(x_i) catch this
705
70738
        d_congruenceManager.equalsConstant(lb, constraint);
706
      }
707
    }
708
709
131567
    if(vc.hasDisequality()){
710
97042
      Assert(vc.hasDisequality());
711
97042
      ConstraintP eq = vc.getEquality();
712
97042
      ConstraintP diseq = vc.getDisequality();
713
      // x <= b, x >= b |= x = b
714
      // (x > b or x < b or x = b)
715
97042
      Debug("arith::eq") << "lb == ub, propagate eq" << eq << endl;
716
97042
      bool triConflict = diseq->isTrue();
717
97042
      if(!eq->isTrue()){
718
70394
        eq->impliedByTrichotomy(constraint, lb, triConflict);
719
70394
        eq->tryToPropagate();
720
      }
721
97042
      if(triConflict){
722
2
        ++(d_statistics.d_statDisequalityConflicts);
723
2
        raiseConflict(eq, InferenceId::ARITH_CONF_TRICHOTOMY);
724
2
        return true;
725
      }
726
    }
727
888323
  }else if(cmpToLB > 0){
728
    // l <= x <= u and l < u
729
888323
    Assert(cmpToLB > 0);
730
888323
    const ValueCollection& vc = constraint->getValueCollection();
731
732
888323
    if(vc.hasDisequality()){
733
357119
      const ConstraintP diseq = vc.getDisequality();
734
357119
      if(diseq->isTrue()){
735
34082
        const ConstraintP lb = d_constraintDatabase.ensureConstraint(const_cast<ValueCollection&>(vc), LowerBound);
736
34082
        ConstraintP negLb = lb->getNegation();
737
738
        // x <= u, u != x |= u < x
739
        // |= not (u >= x)
740
34082
        bool lbInConflict = lb->hasProof();
741
34082
        bool learnNegLb = !(negLb->hasProof());
742
34082
        if(learnNegLb){
743
34081
          negLb->impliedByTrichotomy(constraint, diseq, lbInConflict);
744
34081
          negLb->tryToPropagate();
745
        }
746
34082
        if(lbInConflict){
747
          raiseConflict(lb, InferenceId::ARITH_CONF_TRICHOTOMY);
748
          return true;
749
34082
        }else if(learnNegLb){
750
34081
          d_learnedBounds.push_back(negLb);
751
        }
752
      }
753
    }
754
  }
755
756
1019888
  d_currentPropagationList.push_back(constraint);
757
1019888
  d_currentPropagationList.push_back(d_partialModel.getUpperBoundConstraint(x_i));
758
  //It is fine if this is NullConstraint
759
760
1019888
  d_partialModel.setUpperBoundConstraint(constraint);
761
762
1019888
  if(d_cmEnabled){
763
1019057
    if(d_congruenceManager.isWatchedVariable(x_i)){
764
713104
      int sgn = c_i.sgn();
765
713104
      if(sgn < 0){
766
317478
        d_congruenceManager.watchedVariableCannotBeZero(constraint);
767
395626
      }else if(sgn == 0 && d_partialModel.lowerBoundIsZero(x_i)){
768
60829
        zeroDifferenceDetected(x_i);
769
      }
770
    }
771
  }
772
773
1019888
  d_updatedBounds.softAdd(x_i);
774
775
1019888
  if(Debug.isOn("model")) {
776
    Debug("model") << "before" << endl;
777
    d_partialModel.printModel(x_i);
778
    d_tableau.debugPrintIsBasic(x_i);
779
  }
780
781
1019888
  if(!d_tableau.isBasic(x_i)){
782
416577
    if(d_partialModel.getAssignment(x_i) > c_i){
783
47154
      d_linEq.update(x_i, c_i);
784
    }
785
  }else{
786
603311
    d_errorSet.signalVariable(x_i);
787
  }
788
789
1019888
  if(Debug.isOn("model")) {
790
    Debug("model") << "after" << endl;
791
    d_partialModel.printModel(x_i);
792
    d_tableau.debugPrintIsBasic(x_i);
793
  }
794
795
1019888
  return false; //sat
796
}
797
798
799
/* procedure AssertEquality( x_i == c_i ) */
800
937642
bool TheoryArithPrivate::AssertEquality(ConstraintP constraint){
801
937642
  Assert(constraint != NullConstraint);
802
937642
  Assert(constraint->isEquality());
803
937642
  Assert(constraint->isTrue());
804
937642
  Assert(!constraint->negationHasProof());
805
806
937642
  ArithVar x_i = constraint->getVariable();
807
937642
  const DeltaRational& c_i = constraint->getValue();
808
809
937642
  Debug("arith") << "AssertEquality(" << x_i << " " << c_i << ")"<< std::endl;
810
811
  //Should be fine in integers
812
937642
  Assert(!isInteger(x_i) || c_i.isIntegral());
813
814
937642
  int cmpToLB = d_partialModel.cmpToLowerBound(x_i, c_i);
815
937642
  int cmpToUB = d_partialModel.cmpToUpperBound(x_i, c_i);
816
817
  // u_i <= c_i <= l_i
818
  // This can happen if both c_i <= x_i and x_i <= c_i are in the system.
819
937642
  if(cmpToUB >= 0 && cmpToLB <= 0){
820
43324
    return false; //sat
821
  }
822
823
894318
  if(cmpToUB > 0 || cmpToLB < 0){
824
2854
    ConstraintP cb = (cmpToUB > 0) ?  d_partialModel.getUpperBoundConstraint(x_i) :
825
2854
      d_partialModel.getLowerBoundConstraint(x_i);
826
1870
    ConstraintP diseq = constraint->getNegation();
827
1870
    Assert(!diseq->isTrue());
828
1870
    diseq->impliedByUnate(cb, true);
829
1870
    raiseConflict(constraint, InferenceId::ARITH_CONF_EQ);
830
1870
    return true;
831
  }
832
833
892448
  Assert(cmpToUB <= 0);
834
892448
  Assert(cmpToLB >= 0);
835
892448
  Assert(cmpToUB < 0 || cmpToLB > 0);
836
837
892448
  if(isInteger(x_i)){
838
846900
    d_constantIntegerVariables.push_back(x_i);
839
846900
    Debug("dio::push") << "dio::push " << x_i << endl;
840
  }
841
842
  // Don't bother to check whether x_i != c_i is in d_diseq
843
  // The a and (not a) should never be on the fact queue
844
892448
  d_currentPropagationList.push_back(constraint);
845
892448
  d_currentPropagationList.push_back(d_partialModel.getLowerBoundConstraint(x_i));
846
892448
  d_currentPropagationList.push_back(d_partialModel.getUpperBoundConstraint(x_i));
847
848
892448
  d_partialModel.setUpperBoundConstraint(constraint);
849
892448
  d_partialModel.setLowerBoundConstraint(constraint);
850
851
892448
  if(d_cmEnabled){
852
890835
    if(d_congruenceManager.isWatchedVariable(x_i)){
853
240953
      int sgn = c_i.sgn();
854
240953
      if(sgn == 0){
855
207589
        zeroDifferenceDetected(x_i);
856
      }else{
857
33364
        d_congruenceManager.watchedVariableCannotBeZero(constraint);
858
33364
        d_congruenceManager.equalsConstant(constraint);
859
      }
860
    }else{
861
649882
      d_congruenceManager.equalsConstant(constraint);
862
    }
863
  }
864
865
892448
  d_updatedBounds.softAdd(x_i);
866
867
892448
  if(Debug.isOn("model")) {
868
    Debug("model") << "before" << endl;
869
    d_partialModel.printModel(x_i);
870
    d_tableau.debugPrintIsBasic(x_i);
871
  }
872
873
892448
  if(!d_tableau.isBasic(x_i)){
874
486108
    if(!(d_partialModel.getAssignment(x_i) == c_i)){
875
52609
      d_linEq.update(x_i, c_i);
876
    }
877
  }else{
878
406340
    d_errorSet.signalVariable(x_i);
879
  }
880
881
892448
  if(Debug.isOn("model")) {
882
    Debug("model") << "after" << endl;
883
    d_partialModel.printModel(x_i);
884
    d_tableau.debugPrintIsBasic(x_i);
885
  }
886
887
892448
  return false;
888
}
889
890
891
/* procedure AssertDisequality( x_i != c_i ) */
892
678577
bool TheoryArithPrivate::AssertDisequality(ConstraintP constraint){
893
678577
  Assert(constraint != NullConstraint);
894
678577
  Assert(constraint->isDisequality());
895
678577
  Assert(constraint->isTrue());
896
678577
  Assert(!constraint->negationHasProof());
897
898
678577
  ArithVar x_i = constraint->getVariable();
899
678577
  const DeltaRational& c_i = constraint->getValue();
900
678577
  Debug("arith") << "AssertDisequality(" << x_i << " " << c_i << ")"<< std::endl;
901
902
  //Should be fine in integers
903
678577
  Assert(!isInteger(x_i) || c_i.isIntegral());
904
905
678577
  if(d_cmEnabled){
906
677986
    if(d_congruenceManager.isWatchedVariable(x_i)){
907
155493
      int sgn = c_i.sgn();
908
155493
      if(sgn == 0){
909
139548
        d_congruenceManager.watchedVariableCannotBeZero(constraint);
910
      }
911
    }
912
  }
913
914
678577
  const ValueCollection& vc = constraint->getValueCollection();
915
678577
  if(vc.hasLowerBound() && vc.hasUpperBound()){
916
288125
    const ConstraintP lb = vc.getLowerBound();
917
288125
    const ConstraintP ub = vc.getUpperBound();
918
288125
    if(lb->isTrue() && ub->isTrue()){
919
82
      ConstraintP eq = constraint->getNegation();
920
82
      eq->impliedByTrichotomy(lb, ub, true);
921
82
      raiseConflict(constraint, InferenceId::ARITH_CONF_TRICHOTOMY);
922
      //in conflict
923
82
      ++(d_statistics.d_statDisequalityConflicts);
924
82
      return true;
925
    }
926
  }
927
678495
  if(vc.hasLowerBound() ){
928
329679
    const ConstraintP lb = vc.getLowerBound();
929
329679
    if(lb->isTrue()){
930
106105
      const ConstraintP ub = d_constraintDatabase.ensureConstraint(const_cast<ValueCollection&>(vc), UpperBound);
931
106105
      Assert(!ub->isTrue());
932
106105
      Debug("arith::eq") << "propagate UpperBound " << constraint << lb << ub << endl;
933
106105
      const ConstraintP negUb = ub->getNegation();
934
106105
      if(!negUb->isTrue()){
935
53484
        negUb->impliedByTrichotomy(constraint, lb, false);
936
53484
        negUb->tryToPropagate();
937
53484
        d_learnedBounds.push_back(negUb);
938
      }
939
    }
940
  }
941
678495
  if(vc.hasUpperBound()){
942
337040
    const ConstraintP ub = vc.getUpperBound();
943
337040
    if(ub->isTrue()){
944
67587
      const ConstraintP lb = d_constraintDatabase.ensureConstraint(const_cast<ValueCollection&>(vc), LowerBound);
945
67587
      Assert(!lb->isTrue());
946
947
67587
      Debug("arith::eq") << "propagate LowerBound " << constraint << lb << ub << endl;
948
67587
      const ConstraintP negLb = lb->getNegation();
949
67587
      if(!negLb->isTrue()){
950
11961
        negLb->impliedByTrichotomy(constraint, ub, false);
951
11961
        negLb->tryToPropagate();
952
11961
        d_learnedBounds.push_back(negLb);
953
      }
954
    }
955
  }
956
957
678495
  bool split = constraint->isSplit();
958
959
678495
  if(!split && c_i == d_partialModel.getAssignment(x_i)){
960
14291
    Debug("arith::eq") << "lemma now! " << constraint << endl;
961
14291
    outputTrustedLemma(constraint->split(), InferenceId::ARITH_SPLIT_DEQ);
962
14291
    return false;
963
664204
  }else if(d_partialModel.strictlyLessThanLowerBound(x_i, c_i)){
964
203597
    Debug("arith::eq") << "can drop as less than lb" << constraint << endl;
965
460607
  }else if(d_partialModel.strictlyGreaterThanUpperBound(x_i, c_i)){
966
163046
    Debug("arith::eq") << "can drop as less than ub" << constraint << endl;
967
297561
  }else if(!split){
968
179256
    Debug("arith::eq") << "push back" << constraint << endl;
969
179256
    d_diseqQueue.push(constraint);
970
179256
    d_partialModel.invalidateDelta();
971
  }else{
972
118305
    Debug("arith::eq") << "skipping already split " << constraint << endl;
973
  }
974
664204
  return false;
975
}
976
977
570356
void TheoryArithPrivate::notifySharedTerm(TNode n)
978
{
979
570356
  Debug("arith::notifySharedTerm") << "notifySharedTerm: " << n << endl;
980
570356
  if(n.isConst()){
981
74401
    d_partialModel.invalidateDelta();
982
  }
983
570356
  if(!n.isConst() && !isSetup(n)){
984
423680
    Polynomial poly = Polynomial::parsePolynomial(n);
985
423680
    Polynomial::iterator it = poly.begin();
986
423680
    Polynomial::iterator it_end = poly.end();
987
1173528
    for (; it != it_end; ++ it) {
988
961688
      Monomial m = *it;
989
480844
      if (!m.isConstant() && !isSetup(m.getVarList().getNode())) {
990
5569
        setupVariableList(m.getVarList());
991
      }
992
    }
993
  }
994
570356
}
995
996
2850
Node TheoryArithPrivate::getModelValue(TNode term) {
997
  try{
998
5700
    const DeltaRational drv = getDeltaValue(term);
999
2850
    const Rational& delta = d_partialModel.getDelta();
1000
5700
    const Rational qmodel = drv.substituteDelta( delta );
1001
2850
    return mkRationalNode( qmodel );
1002
  } catch (DeltaRationalException& dr) {
1003
    return Node::null();
1004
  } catch (ModelException& me) {
1005
    return Node::null();
1006
  }
1007
}
1008
1009
11635
Theory::PPAssertStatus TheoryArithPrivate::ppAssert(
1010
    TrustNode tin, TrustSubstitutionMap& outSubstitutions)
1011
{
1012
23270
  TimerStat::CodeTimer codeTimer(d_statistics.d_simplifyTimer);
1013
23270
  TNode in = tin.getNode();
1014
11635
  Debug("simplify") << "TheoryArithPrivate::solve(" << in << ")" << endl;
1015
1016
1017
  // Solve equalities
1018
23270
  Rational minConstant = 0;
1019
23270
  Node minMonomial;
1020
23270
  Node minVar;
1021
28578
  if (in.getKind() == kind::EQUAL &&
1022
16943
      Theory::theoryOf(in[0].getType()) == THEORY_ARITH) {
1023
4109
    Comparison cmp = Comparison::parseNormalForm(in);
1024
1025
4109
    Polynomial left = cmp.getLeft();
1026
1027
4109
    Monomial m = left.getHead();
1028
2654
    if (m.getVarList().singleton()){
1029
5192
      VarList vl = m.getVarList();
1030
5192
      Node var = vl.getNode();
1031
2596
      if (var.isVar())
1032
      {
1033
        // if vl.isIntegral then m.getConstant().isOne()
1034
1411
        if(!vl.isIntegral() || m.getConstant().isOne()){
1035
1399
          minVar = var;
1036
        }
1037
      }
1038
    }
1039
1040
    // Solve for variable
1041
2654
    if (!minVar.isNull()) {
1042
1599
      Polynomial right = cmp.getRight();
1043
1599
      Node elim = right.getNode();
1044
      // ax + p = c -> (ax + p) -ax - c = -ax
1045
      // x = (p - ax - c) * -1/a
1046
      // Add the substitution if not recursive
1047
1399
      Assert(elim == Rewriter::rewrite(elim));
1048
1049
2798
      if (right.size() > options::ppAssertMaxSubSize())
1050
      {
1051
218
        Debug("simplify")
1052
            << "TheoryArithPrivate::solve(): did not substitute due to the "
1053
109
               "right hand side containing too many terms: "
1054
109
            << minVar << ":" << elim << endl;
1055
109
        Debug("simplify") << right.size() << endl;
1056
      }
1057
1290
      else if (d_containing.isLegalElimination(minVar, elim))
1058
      {
1059
        // cannot eliminate integers here unless we know the resulting
1060
        // substitution is integral
1061
2398
        Debug("simplify") << "TheoryArithPrivate::solve(): substitution "
1062
1199
                          << minVar << " |-> " << elim << endl;
1063
1064
1199
        outSubstitutions.addSubstitutionSolved(minVar, elim, tin);
1065
1199
        return Theory::PP_ASSERT_STATUS_SOLVED;
1066
      }
1067
      else
1068
      {
1069
182
        Debug("simplify") << "TheoryArithPrivate::solve(): can't substitute "
1070
182
                          << minVar << ":" << minVar.getType() << " |-> "
1071
91
                          << elim << ":" << elim.getType() << endl;
1072
      }
1073
    }
1074
  }
1075
1076
  // If a relation, remember the bound
1077
10436
  switch(in.getKind()) {
1078
5791
  case kind::LEQ:
1079
  case kind::LT:
1080
  case kind::GEQ:
1081
  case kind::GT:
1082
5791
    if (in[0].isVar()) {
1083
2503
      d_learner.addBound(in);
1084
    }
1085
5791
    break;
1086
4645
  default:
1087
    // Do nothing
1088
4645
    break;
1089
  }
1090
1091
10436
  return Theory::PP_ASSERT_STATUS_UNSOLVED;
1092
}
1093
1094
105752
void TheoryArithPrivate::ppStaticLearn(TNode n, NodeBuilder& learned)
1095
{
1096
211504
  TimerStat::CodeTimer codeTimer(d_statistics.d_staticLearningTimer);
1097
1098
105752
  d_learner.staticLearning(n, learned);
1099
105752
}
1100
1101
ArithVar TheoryArithPrivate::findShortestBasicRow(ArithVar variable){
1102
  ArithVar bestBasic = ARITHVAR_SENTINEL;
1103
  uint64_t bestRowLength = std::numeric_limits<uint64_t>::max();
1104
1105
  Tableau::ColIterator basicIter = d_tableau.colIterator(variable);
1106
  for(; !basicIter.atEnd(); ++basicIter){
1107
    const Tableau::Entry& entry = *basicIter;
1108
    Assert(entry.getColVar() == variable);
1109
    RowIndex ridx = entry.getRowIndex();
1110
    ArithVar basic = d_tableau.rowIndexToBasic(ridx);
1111
    uint32_t rowLength = d_tableau.getRowLength(ridx);
1112
    if((rowLength < bestRowLength) ||
1113
       (rowLength == bestRowLength && basic < bestBasic)){
1114
      bestBasic = basic;
1115
      bestRowLength = rowLength;
1116
    }
1117
  }
1118
  Assert(bestBasic == ARITHVAR_SENTINEL
1119
         || bestRowLength < std::numeric_limits<uint32_t>::max());
1120
  return bestBasic;
1121
}
1122
1123
65872
void TheoryArithPrivate::setupVariable(const Variable& x){
1124
131744
  Node n = x.getNode();
1125
1126
65872
  Assert(!isSetup(n));
1127
1128
65872
  ++(d_statistics.d_statUserVariables);
1129
65872
  requestArithVar(n, false,  false);
1130
  //ArithVar varN = requestArithVar(n,false);
1131
  //setupInitialValue(varN);
1132
1133
65872
  markSetup(n);
1134
65872
}
1135
1136
67340
void TheoryArithPrivate::setupVariableList(const VarList& vl){
1137
67340
  Assert(!vl.empty());
1138
1139
134680
  TNode vlNode = vl.getNode();
1140
67340
  Assert(!isSetup(vlNode));
1141
67340
  Assert(!d_partialModel.hasArithVar(vlNode));
1142
1143
140877
  for(VarList::iterator i = vl.begin(), end = vl.end(); i != end; ++i){
1144
147074
    Variable var = *i;
1145
1146
73537
    if(!isSetup(var.getNode())){
1147
65872
      setupVariable(var);
1148
    }
1149
  }
1150
1151
67340
  if(!vl.singleton()){
1152
    // vl is the product of at least 2 variables
1153
    // vl : (* v1 v2 ...)
1154
2441
    if(getLogicInfo().isLinear()){
1155
1
      throw LogicException("A non-linear fact was asserted to arithmetic in a linear logic.");
1156
    }
1157
2440
    d_foundNl = true;
1158
1159
2440
    ++(d_statistics.d_statUserVariables);
1160
2440
    requestArithVar(vlNode, false, false);
1161
    //ArithVar av = requestArithVar(vlNode, false);
1162
    //setupInitialValue(av);
1163
1164
2440
    markSetup(vlNode);
1165
  }
1166
129798
  else if (vlNode.getKind() == kind::EXPONENTIAL
1167
64851
           || vlNode.getKind() == kind::SINE || vlNode.getKind() == kind::COSINE
1168
129301
           || vlNode.getKind() == kind::TANGENT)
1169
  {
1170
497
    d_foundNl = true;
1171
  }
1172
1173
  /* Note:
1174
   * Only call markSetup if the VarList is not a singleton.
1175
   * See the comment in setupPolynomail for more.
1176
   */
1177
67339
}
1178
1179
void TheoryArithPrivate::cautiousSetupPolynomial(const Polynomial& p){
1180
  if(p.containsConstant()){
1181
    if(!p.isConstant()){
1182
      Polynomial noConstant = p.getTail();
1183
      if(!isSetup(noConstant.getNode())){
1184
        setupPolynomial(noConstant);
1185
      }
1186
    }
1187
  }else if(!isSetup(p.getNode())){
1188
    setupPolynomial(p);
1189
  }
1190
}
1191
1192
1193
118085
void TheoryArithPrivate::setupPolynomial(const Polynomial& poly) {
1194
118085
  Assert(!poly.containsConstant());
1195
236170
  TNode polyNode = poly.getNode();
1196
118085
  Assert(!isSetup(polyNode));
1197
118085
  Assert(!d_partialModel.hasArithVar(polyNode));
1198
1199
354942
  for(Polynomial::iterator i = poly.begin(), end = poly.end(); i != end; ++i){
1200
473714
    Monomial mono = *i;
1201
236857
    const VarList& vl = mono.getVarList();
1202
236857
    if(!isSetup(vl.getNode())){
1203
61771
      setupVariableList(vl);
1204
    }
1205
  }
1206
1207
118084
  if(polyNode.getKind() == PLUS){
1208
90703
    d_tableauSizeHasBeenModified = true;
1209
1210
181406
    vector<ArithVar> variables;
1211
181406
    vector<Rational> coefficients;
1212
90703
    asVectors(poly, coefficients, variables);
1213
1214
90703
    ArithVar varSlack = requestArithVar(polyNode, true, false);
1215
90703
    d_tableau.addRow(varSlack, coefficients, variables);
1216
90703
    setupBasicValue(varSlack);
1217
90703
    d_linEq.trackRowIndex(d_tableau.basicToRowIndex(varSlack));
1218
1219
    //Add differences to the difference manager
1220
181406
    Polynomial::iterator i = poly.begin(), end = poly.end();
1221
90703
    if(i != end){
1222
181406
      Monomial first = *i;
1223
90703
      ++i;
1224
90703
      if(i != end){
1225
181406
        Monomial second = *i;
1226
90703
        ++i;
1227
90703
        if(i == end){
1228
72765
          if(first.getConstant().isOne() && second.getConstant().getValue() == -1){
1229
125238
            VarList vl0 = first.getVarList();
1230
125238
            VarList vl1 = second.getVarList();
1231
62619
            if(vl0.singleton() && vl1.singleton()){
1232
60431
              d_congruenceManager.addWatchedPair(varSlack, vl0.getNode(), vl1.getNode());
1233
            }
1234
          }
1235
        }
1236
      }
1237
    }
1238
1239
90703
    ++(d_statistics.d_statAuxiliaryVariables);
1240
90703
    markSetup(polyNode);
1241
  }
1242
1243
  /* Note:
1244
   * It is worth documenting that polyNode should only be marked as
1245
   * being setup by this function if it has kind PLUS.
1246
   * Other kinds will be marked as being setup by lower levels of setup
1247
   * specifically setupVariableList.
1248
   */
1249
118084
}
1250
1251
261546
void TheoryArithPrivate::setupAtom(TNode atom) {
1252
261546
  Assert(isRelationOperator(atom.getKind())) << atom;
1253
261546
  Assert(Comparison::isNormalAtom(atom));
1254
261546
  Assert(!isSetup(atom));
1255
261546
  Assert(!d_constraintDatabase.hasLiteral(atom));
1256
1257
523092
  Comparison cmp = Comparison::parseNormalForm(atom);
1258
523092
  Polynomial nvp = cmp.normalizedVariablePart();
1259
261546
  Assert(!nvp.isZero());
1260
1261
261546
  if(!isSetup(nvp.getNode())){
1262
118085
    setupPolynomial(nvp);
1263
  }
1264
1265
261545
  d_constraintDatabase.addLiteral(atom);
1266
1267
261545
  markSetup(atom);
1268
261545
}
1269
1270
781005
void TheoryArithPrivate::preRegisterTerm(TNode n) {
1271
781005
  Debug("arith::preregister") <<"begin arith::preRegisterTerm("<< n <<")"<< endl;
1272
1273
781005
  d_preregisteredNodes.insert(n);
1274
1275
  try {
1276
781005
    if(isRelationOperator(n.getKind())){
1277
402084
      if(!isSetup(n)){
1278
207889
        setupAtom(n);
1279
      }
1280
402083
      ConstraintP c = d_constraintDatabase.lookup(n);
1281
402083
      Assert(c != NullConstraint);
1282
1283
402083
      Debug("arith::preregister") << "setup constraint" << c << endl;
1284
402083
      Assert(!c->canBePropagated());
1285
402083
      c->setPreregistered();
1286
    }
1287
2
  } catch(LogicException& le) {
1288
2
    std::stringstream ss;
1289
1
    ss << le.getMessage() << endl << "The fact in question: " << n << endl;
1290
1
    throw LogicException(ss.str());
1291
  }
1292
1293
781004
  Debug("arith::preregister") << "end arith::preRegisterTerm("<< n <<")" << endl;
1294
781004
}
1295
1296
void TheoryArithPrivate::releaseArithVar(ArithVar v){
1297
  //Assert(d_partialModel.hasNode(v));
1298
1299
  d_constraintDatabase.removeVariable(v);
1300
  d_partialModel.releaseArithVar(v);
1301
}
1302
1303
159015
ArithVar TheoryArithPrivate::requestArithVar(TNode x, bool aux, bool internal){
1304
  //TODO : The VarList trick is good enough?
1305
159015
  Assert(isLeaf(x) || VarList::isMember(x) || x.getKind() == PLUS || internal);
1306
159015
  if(getLogicInfo().isLinear() && Variable::isDivMember(x)){
1307
    stringstream ss;
1308
    ss << "A non-linear fact (involving div/mod/divisibility) was asserted to "
1309
          "arithmetic in a linear logic: "
1310
       << x << std::endl;
1311
    throw LogicException(ss.str());
1312
  }
1313
159015
  Assert(!d_partialModel.hasArithVar(x));
1314
159015
  Assert(x.getType().isReal());  // real or integer
1315
1316
159015
  ArithVar max = d_partialModel.getNumberOfVariables();
1317
159015
  ArithVar varX = d_partialModel.allocate(x, aux);
1318
1319
159015
  bool reclaim =  max >= d_partialModel.getNumberOfVariables();;
1320
1321
159015
  if(!reclaim){
1322
159015
    d_dualSimplex.increaseMax();
1323
1324
159015
    d_tableau.increaseSize();
1325
159015
    d_tableauSizeHasBeenModified = true;
1326
  }
1327
159015
  d_constraintDatabase.addVariable(varX);
1328
1329
318030
  Debug("arith::arithvar") << "@" << getSatContext()->getLevel()
1330
159015
                           << " " << x << " |-> " << varX
1331
159015
                           << "(relaiming " << reclaim << ")" << endl;
1332
1333
159015
  Assert(!d_partialModel.hasUpperBound(varX));
1334
159015
  Assert(!d_partialModel.hasLowerBound(varX));
1335
1336
159015
  return varX;
1337
}
1338
1339
90703
void TheoryArithPrivate::asVectors(const Polynomial& p, std::vector<Rational>& coeffs, std::vector<ArithVar>& variables) {
1340
300178
  for(Polynomial::iterator i = p.begin(), end = p.end(); i != end; ++i){
1341
418950
    const Monomial& mono = *i;
1342
209475
    const Constant& constant = mono.getConstant();
1343
209475
    const VarList& variable = mono.getVarList();
1344
1345
418950
    Node n = variable.getNode();
1346
1347
209475
    Debug("arith::asVectors") << "should be var: " << n << endl;
1348
1349
    // TODO: This VarList::isMember(n) can be stronger
1350
209475
    Assert(isLeaf(n) || VarList::isMember(n));
1351
209475
    Assert(theoryOf(n) != THEORY_ARITH || d_partialModel.hasArithVar(n));
1352
1353
209475
    Assert(d_partialModel.hasArithVar(n));
1354
209475
    ArithVar av = d_partialModel.asArithVar(n);
1355
1356
209475
    coeffs.push_back(constant.getValue());
1357
209475
    variables.push_back(av);
1358
  }
1359
90703
}
1360
1361
/* Requirements:
1362
 * For basic variables the row must have been added to the tableau.
1363
 */
1364
90703
void TheoryArithPrivate::setupBasicValue(ArithVar x){
1365
90703
  Assert(d_tableau.isBasic(x));
1366
  //If the variable is basic, assertions may have already happened and updates
1367
  //may have occured before setting this variable up.
1368
1369
  //This can go away if the tableau creation is done at preregister
1370
  //time instead of register
1371
181406
  DeltaRational safeAssignment = d_linEq.computeRowValue(x, true);
1372
181406
  DeltaRational assignment = d_linEq.computeRowValue(x, false);
1373
90703
  d_partialModel.setAssignment(x,safeAssignment,assignment);
1374
1375
90703
  Debug("arith") << "setupVariable("<<x<<")"<<std::endl;
1376
90703
}
1377
1378
ArithVar TheoryArithPrivate::determineArithVar(const Polynomial& p) const{
1379
  Assert(!p.containsConstant());
1380
  Assert(p.getHead().constantIsPositive());
1381
  TNode n = p.getNode();
1382
  Debug("determineArithVar") << "determineArithVar(" << n << ")" << endl;
1383
  return d_partialModel.asArithVar(n);
1384
}
1385
1386
ArithVar TheoryArithPrivate::determineArithVar(TNode assertion) const{
1387
  Debug("determineArithVar") << "determineArithVar " << assertion << endl;
1388
  Comparison cmp = Comparison::parseNormalForm(assertion);
1389
  Polynomial variablePart = cmp.normalizedVariablePart();
1390
  return determineArithVar(variablePart);
1391
}
1392
1393
1394
bool TheoryArithPrivate::canSafelyAvoidEqualitySetup(TNode equality){
1395
  Assert(equality.getKind() == EQUAL);
1396
  return d_partialModel.hasArithVar(equality[0]);
1397
}
1398
1399
36967
Comparison TheoryArithPrivate::mkIntegerEqualityFromAssignment(ArithVar v){
1400
36967
  const DeltaRational& beta = d_partialModel.getAssignment(v);
1401
1402
36967
  Assert(beta.isIntegral());
1403
73934
  Polynomial betaAsPolynomial = Polynomial::mkPolynomial( Constant::mkConstant(beta.floor()) );
1404
1405
73934
  TNode var = d_partialModel.asNode(v);
1406
73934
  Polynomial varAsPolynomial = Polynomial::parsePolynomial(var);
1407
73934
  return Comparison::mkComparison(EQUAL, varAsPolynomial, betaAsPolynomial);
1408
}
1409
1410
1883
TrustNode TheoryArithPrivate::dioCutting()
1411
{
1412
3766
  context::Context::ScopedPush speculativePush(getSatContext());
1413
  //DO NOT TOUCH THE OUTPUTSTREAM
1414
1415
81985
  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
1416
80102
    ArithVar v = *vi;
1417
80102
    if(isInteger(v)){
1418
128962
      if(d_partialModel.cmpAssignmentUpperBound(v) == 0 ||
1419
50374
         d_partialModel.cmpAssignmentLowerBound(v) == 0){
1420
36113
        if(!d_partialModel.boundsAreEqual(v)){
1421
          // If the bounds are equal this is already in the dioSolver
1422
          //Add v = dr as a speculation.
1423
31936
          Comparison eq = mkIntegerEqualityFromAssignment(v);
1424
15968
          Debug("dio::push") << "dio::push " << v << " " <<  eq.getNode() << endl;
1425
15968
          Assert(!eq.isBoolean());
1426
15968
          d_diosolver.pushInputConstraint(eq, eq.getNode());
1427
          // It does not matter what the explanation of eq is.
1428
          // It cannot be used in a conflict
1429
        }
1430
      }
1431
    }
1432
  }
1433
1434
3766
  SumPair plane = d_diosolver.processEquationsForCut();
1435
1883
  if(plane.isZero()){
1436
445
    return TrustNode::null();
1437
  }else{
1438
2876
    Polynomial p = plane.getPolynomial();
1439
2876
    Polynomial c = Polynomial::mkPolynomial(plane.getConstant() * Constant::mkConstant(-1));
1440
2876
    Integer gcd = p.gcd();
1441
1438
    Assert(p.isIntegral());
1442
1438
    Assert(c.isIntegral());
1443
1438
    Assert(gcd > 1);
1444
1438
    Assert(!gcd.divides(c.asConstant().getNumerator()));
1445
2876
    Comparison leq = Comparison::mkComparison(LEQ, p, c);
1446
2876
    Comparison geq = Comparison::mkComparison(GEQ, p, c);
1447
2876
    Node lemma = NodeManager::currentNM()->mkNode(OR, leq.getNode(), geq.getNode());
1448
2876
    Node rewrittenLemma = Rewriter::rewrite(lemma);
1449
1438
    Debug("arith::dio::ex") << "dioCutting found the plane: " << plane.getNode() << endl;
1450
1438
    Debug("arith::dio::ex") << "resulting in the cut: " << lemma << endl;
1451
1438
    Debug("arith::dio::ex") << "rewritten " << rewrittenLemma << endl;
1452
1438
    Debug("arith::dio") << "dioCutting found the plane: " << plane.getNode() << endl;
1453
1438
    Debug("arith::dio") << "resulting in the cut: " << lemma << endl;
1454
1438
    Debug("arith::dio") << "rewritten " << rewrittenLemma << endl;
1455
1438
    if (proofsEnabled())
1456
    {
1457
205
      NodeManager* nm = NodeManager::currentNM();
1458
410
      Node gt = nm->mkNode(kind::GT, p.getNode(), c.getNode());
1459
410
      Node lt = nm->mkNode(kind::LT, p.getNode(), c.getNode());
1460
1461
410
      Pf pfNotLeq = d_pnm->mkAssume(leq.getNode().negate());
1462
      Pf pfGt =
1463
410
          d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM, {pfNotLeq}, {gt});
1464
410
      Pf pfNotGeq = d_pnm->mkAssume(geq.getNode().negate());
1465
      Pf pfLt =
1466
410
          d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM, {pfNotGeq}, {lt});
1467
      Pf pfSum =
1468
205
          d_pnm->mkNode(PfRule::MACRO_ARITH_SCALE_SUM_UB,
1469
                        {pfGt, pfLt},
1470
410
                        {nm->mkConst<Rational>(-1), nm->mkConst<Rational>(1)});
1471
205
      Pf pfBot = d_pnm->mkNode(
1472
410
          PfRule::MACRO_SR_PRED_TRANSFORM, {pfSum}, {nm->mkConst<bool>(false)});
1473
205
      std::vector<Node> assumptions = {leq.getNode().negate(),
1474
410
                                       geq.getNode().negate()};
1475
410
      Pf pfNotAndNot = d_pnm->mkScope(pfBot, assumptions);
1476
410
      Pf pfOr = d_pnm->mkNode(PfRule::NOT_AND, {pfNotAndNot}, {});
1477
205
      Pf pfRewritten = d_pnm->mkNode(
1478
410
          PfRule::MACRO_SR_PRED_TRANSFORM, {pfOr}, {rewrittenLemma});
1479
205
      return d_pfGen->mkTrustNode(rewrittenLemma, pfRewritten);
1480
    }
1481
    else
1482
    {
1483
1233
      return TrustNode::mkTrustLemma(rewrittenLemma, nullptr);
1484
    }
1485
  }
1486
}
1487
1488
23690
Node TheoryArithPrivate::callDioSolver(){
1489
44689
  while(!d_constantIntegerVariables.empty()){
1490
20999
    ArithVar v = d_constantIntegerVariables.front();
1491
20999
    d_constantIntegerVariables.pop();
1492
1493
20999
    Debug("arith::dio")  << "callDioSolver " << v << endl;
1494
1495
20999
    Assert(isInteger(v));
1496
20999
    Assert(d_partialModel.boundsAreEqual(v));
1497
1498
20999
    ConstraintP lb = d_partialModel.getLowerBoundConstraint(v);
1499
20999
    ConstraintP ub = d_partialModel.getUpperBoundConstraint(v);
1500
1501
41998
    Node orig = Node::null();
1502
20999
    if(lb->isEquality()){
1503
19515
      orig = Constraint::externalExplainByAssertions({lb});
1504
1484
    }else if(ub->isEquality()){
1505
      orig = Constraint::externalExplainByAssertions({ub});
1506
    }else {
1507
1484
      orig = Constraint::externalExplainByAssertions(ub, lb);
1508
    }
1509
1510
20999
    Assert(d_partialModel.assignmentIsConsistent(v));
1511
1512
41998
    Comparison eq = mkIntegerEqualityFromAssignment(v);
1513
1514
20999
    if(eq.isBoolean()){
1515
      //This can only be a conflict
1516
      Assert(!eq.getNode().getConst<bool>());
1517
1518
      //This should be handled by the normal form earlier in the case of equality
1519
      Assert(orig.getKind() != EQUAL);
1520
      return orig;
1521
    }else{
1522
20999
      Debug("dio::push") << "dio::push " << v << " " << eq.getNode() << " with reason " << orig << endl;
1523
20999
      d_diosolver.pushInputConstraint(eq, orig);
1524
    }
1525
  }
1526
1527
2691
  return d_diosolver.processEquationsForConflict();
1528
}
1529
1530
5576055
ConstraintP TheoryArithPrivate::constraintFromFactQueue(TNode assertion)
1531
{
1532
5576055
  Kind simpleKind = Comparison::comparisonKind(assertion);
1533
5576055
  ConstraintP constraint = d_constraintDatabase.lookup(assertion);
1534
5576055
  if(constraint == NullConstraint){
1535
691010
    Assert(simpleKind == EQUAL || simpleKind == DISTINCT);
1536
691010
    bool isDistinct = simpleKind == DISTINCT;
1537
1372361
    Node eq = (simpleKind == DISTINCT) ? assertion[0] : assertion;
1538
691010
    Assert(!isSetup(eq));
1539
1372361
    Node reEq = Rewriter::rewrite(eq);
1540
691010
    Debug("arith::distinct::const") << "Assertion: " << assertion << std::endl;
1541
691010
    Debug("arith::distinct::const") << "Eq       : " << eq << std::endl;
1542
691010
    Debug("arith::distinct::const") << "reEq     : " << reEq << std::endl;
1543
691010
    if(reEq.getKind() == CONST_BOOLEAN){
1544
9659
      if(reEq.getConst<bool>() == isDistinct){
1545
        // if is (not true), or false
1546
        Assert((reEq.getConst<bool>() && isDistinct)
1547
               || (!reEq.getConst<bool>() && !isDistinct));
1548
        if (proofsEnabled())
1549
        {
1550
          Pf assume = d_pnm->mkAssume(assertion);
1551
          std::vector<Node> assumptions = {assertion};
1552
          Pf pf = d_pnm->mkScope(d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM,
1553
                                               {d_pnm->mkAssume(assertion)},
1554
                                               {}),
1555
                                 assumptions);
1556
          raiseBlackBoxConflict(assertion, pf);
1557
        }
1558
        else
1559
        {
1560
          raiseBlackBoxConflict(assertion);
1561
        }
1562
      }
1563
9659
      return NullConstraint;
1564
    }
1565
681351
    Assert(reEq.getKind() != CONST_BOOLEAN);
1566
681351
    if(!isSetup(reEq)){
1567
34753
      setupAtom(reEq);
1568
    }
1569
1362702
    Node reAssertion = isDistinct ? reEq.notNode() : reEq;
1570
681351
    constraint = d_constraintDatabase.lookup(reAssertion);
1571
1572
681351
    if(assertion != reAssertion){
1573
663773
      Debug("arith::nf") << "getting non-nf assertion " << assertion << " |-> " <<  reAssertion << endl;
1574
663773
      Assert(constraint != NullConstraint);
1575
663773
      d_assertionsThatDoNotMatchTheirLiterals.insert(assertion, constraint);
1576
    }
1577
  }
1578
1579
5566396
  Assert(constraint != NullConstraint);
1580
1581
5566396
  if(constraint->assertedToTheTheory()){
1582
    //Do nothing
1583
247506
    return NullConstraint;
1584
  }
1585
5318890
  Assert(!constraint->assertedToTheTheory());
1586
5318890
  bool inConflict = constraint->negationHasProof();
1587
5318890
  constraint->setAssertedToTheTheory(assertion, inConflict);
1588
1589
5318890
  if(!constraint->hasProof()){
1590
4473977
    Debug("arith::constraint") << "marking as constraint as self explaining " << endl;
1591
4473977
    constraint->setAssumption(inConflict);
1592
  } else {
1593
1689826
    Debug("arith::constraint")
1594
844913
        << "already has proof: "
1595
844913
        << Constraint::externalExplainByAssertions({constraint});
1596
  }
1597
1598
5318890
  if(Debug.isOn("arith::negatedassumption") && inConflict){
1599
    ConstraintP negation = constraint->getNegation();
1600
    if(Debug.isOn("arith::negatedassumption") && negation->isAssumption()){
1601
      debugPrintFacts();
1602
    }
1603
    Debug("arith::eq") << "negation has proof" << endl;
1604
    Debug("arith::eq") << constraint << endl;
1605
    Debug("arith::eq") << negation << endl;
1606
  }
1607
1608
5318890
  if(inConflict){
1609
2940
    ConstraintP negation = constraint->getNegation();
1610
2940
    if(Debug.isOn("arith::negatedassumption") && negation->isAssumption()){
1611
      debugPrintFacts();
1612
    }
1613
2940
    Debug("arith::eq") << "negation has proof" << endl;
1614
2940
    Debug("arith::eq") << constraint << endl;
1615
2940
    Debug("arith::eq") << negation << endl;
1616
2940
    raiseConflict(negation, InferenceId::UNKNOWN);
1617
2940
    return NullConstraint;
1618
  }else{
1619
5315950
    return constraint;
1620
  }
1621
}
1622
1623
5425120
bool TheoryArithPrivate::assertionCases(ConstraintP constraint){
1624
5425120
  Assert(constraint->hasProof());
1625
5425120
  Assert(!constraint->negationHasProof());
1626
1627
5425120
  ArithVar x_i = constraint->getVariable();
1628
1629
5425120
  switch(constraint->getType()){
1630
1843618
  case UpperBound:
1631
1843618
    if(isInteger(x_i) && constraint->isStrictUpperBound()){
1632
1120643
      ConstraintP floorConstraint = constraint->getFloor();
1633
1120643
      if(!floorConstraint->isTrue()){
1634
968382
        bool inConflict = floorConstraint->negationHasProof();
1635
968382
        if (Debug.isOn("arith::intbound")) {
1636
          Debug("arith::intbound") << "literal, before: " << constraint->getLiteral() << std::endl;
1637
          Debug("arith::intbound") << "constraint, after: " << floorConstraint << std::endl;
1638
        }
1639
968382
        floorConstraint->impliedByIntTighten(constraint, inConflict);
1640
968382
        floorConstraint->tryToPropagate();
1641
968382
        if(inConflict){
1642
2361
          raiseConflict(floorConstraint, InferenceId::ARITH_TIGHTEN_FLOOR);
1643
2361
          return true;
1644
        }
1645
      }
1646
1118282
      return AssertUpper(floorConstraint);
1647
    }else{
1648
722975
      return AssertUpper(constraint);
1649
    }
1650
1965283
  case LowerBound:
1651
1965283
    if(isInteger(x_i) && constraint->isStrictLowerBound()){
1652
60651
      ConstraintP ceilingConstraint = constraint->getCeiling();
1653
60651
      if(!ceilingConstraint->isTrue()){
1654
35311
        bool inConflict = ceilingConstraint->negationHasProof();
1655
35311
        if (Debug.isOn("arith::intbound")) {
1656
          Debug("arith::intbound") << "literal, before: " << constraint->getLiteral() << std::endl;
1657
          Debug("arith::intbound") << "constraint, after: " << ceilingConstraint << std::endl;
1658
        }
1659
35311
        ceilingConstraint->impliedByIntTighten(constraint, inConflict);
1660
35311
        ceilingConstraint->tryToPropagate();
1661
35311
        if(inConflict){
1662
34
          raiseConflict(ceilingConstraint, InferenceId::ARITH_TIGHTEN_CEIL);
1663
34
          return true;
1664
        }
1665
      }
1666
60617
      return AssertLower(ceilingConstraint);
1667
    }else{
1668
1904632
      return AssertLower(constraint);
1669
    }
1670
937642
  case Equality:
1671
937642
    return AssertEquality(constraint);
1672
678577
  case Disequality:
1673
678577
    return AssertDisequality(constraint);
1674
  default:
1675
    Unreachable();
1676
    return false;
1677
  }
1678
}
1679
/**
1680
 * Looks for through the variables starting at d_nextIntegerCheckVar
1681
 * for the first integer variable that is between its upper and lower bounds
1682
 * that has a non-integer assignment.
1683
 *
1684
 * If assumeBounds is true, skip the check that the variable is in bounds.
1685
 *
1686
 * If there is no such variable, returns ARITHVAR_SENTINEL;
1687
 */
1688
3142972
ArithVar TheoryArithPrivate::nextIntegerViolation(bool assumeBounds) const
1689
{
1690
3142972
  ArithVar numVars = d_partialModel.getNumberOfVariables();
1691
3142972
  ArithVar v = d_nextIntegerCheckVar;
1692
3142972
  if (numVars > 0)
1693
  {
1694
3102109
    const ArithVar rrEnd = d_nextIntegerCheckVar;
1695
576258591
    do
1696
    {
1697
579360700
      if (isIntegerInput(v))
1698
      {
1699
157015103
        if (!d_partialModel.integralAssignment(v))
1700
        {
1701
107868
          if (assumeBounds || d_partialModel.assignmentIsConsistent(v))
1702
          {
1703
107868
            return v;
1704
          }
1705
        }
1706
      }
1707
579252832
      v = (1 + v == numVars) ? 0 : (1 + v);
1708
579252832
    } while (v != rrEnd);
1709
  }
1710
3035104
  return ARITHVAR_SENTINEL;
1711
}
1712
1713
/**
1714
 * Checks the set of integer variables I to see if each variable
1715
 * in I has an integer assignment.
1716
 */
1717
3142972
bool TheoryArithPrivate::hasIntegerModel()
1718
{
1719
3142972
  ArithVar next = nextIntegerViolation(true);
1720
3142972
  if (next != ARITHVAR_SENTINEL)
1721
  {
1722
107868
    d_nextIntegerCheckVar = next;
1723
107868
    if (Debug.isOn("arith::hasIntegerModel"))
1724
    {
1725
      Debug("arith::hasIntegerModel") << "has int model? " << next << endl;
1726
      d_partialModel.printModel(next, Debug("arith::hasIntegerModel"));
1727
    }
1728
107868
    return false;
1729
  }
1730
  else
1731
  {
1732
3035104
    return true;
1733
  }
1734
}
1735
1736
Node flattenAndSort(Node n){
1737
  Kind k = n.getKind();
1738
  switch(k){
1739
  case kind::OR:
1740
  case kind::AND:
1741
  case kind::PLUS:
1742
  case kind::MULT:
1743
    break;
1744
  default:
1745
    return n;
1746
  }
1747
1748
  std::vector<Node> out;
1749
  std::vector<Node> process;
1750
  process.push_back(n);
1751
  while(!process.empty()){
1752
    Node b = process.back();
1753
    process.pop_back();
1754
    if(b.getKind() == k){
1755
      for(Node::iterator i=b.begin(), end=b.end(); i!=end; ++i){
1756
        process.push_back(*i);
1757
      }
1758
    } else {
1759
      out.push_back(b);
1760
    }
1761
  }
1762
  Assert(out.size() >= 2);
1763
  std::sort(out.begin(), out.end());
1764
  return NodeManager::currentNM()->mkNode(k, out);
1765
}
1766
1767
1768
1769
/** Outputs conflicts to the output channel. */
1770
50029
void TheoryArithPrivate::outputConflicts(){
1771
50029
  Debug("arith::conflict") << "outputting conflicts" << std::endl;
1772
50029
  Assert(anyConflict());
1773
  static unsigned int conflicts = 0;
1774
1775
50029
  if(!conflictQueueEmpty()){
1776
47890
    Assert(!d_conflicts.empty());
1777
115975
    for(size_t i = 0, i_end = d_conflicts.size(); i < i_end; ++i){
1778
68085
      const std::pair<ConstraintCP, InferenceId>& conf = d_conflicts[i];
1779
68085
      const ConstraintCP& confConstraint = conf.first;
1780
68085
      bool hasProof = confConstraint->hasProof();
1781
68085
      Assert(confConstraint->inConflict());
1782
68085
      const ConstraintRule& pf = confConstraint->getConstraintRule();
1783
68085
      if (Debug.isOn("arith::conflict"))
1784
      {
1785
        pf.print(std::cout);
1786
        std::cout << std::endl;
1787
      }
1788
68085
      if (Debug.isOn("arith::pf::tree"))
1789
      {
1790
        Debug("arith::pf::tree") << "\n\nTree:\n";
1791
        confConstraint->printProofTree(Debug("arith::pf::tree"));
1792
        confConstraint->getNegation()->printProofTree(Debug("arith::pf::tree"));
1793
      }
1794
1795
136170
      TrustNode trustedConflict = confConstraint->externalExplainConflict();
1796
136170
      Node conflict = trustedConflict.getNode();
1797
1798
68085
      ++conflicts;
1799
136170
      Debug("arith::conflict") << "d_conflicts[" << i << "] " << conflict
1800
68085
                               << " has proof: " << hasProof << endl;
1801
68085
      if(Debug.isOn("arith::normalize::external")){
1802
        conflict = flattenAndSort(conflict);
1803
        Debug("arith::conflict") << "(normalized to) " << conflict << endl;
1804
      }
1805
1806
68085
      if (isProofEnabled())
1807
      {
1808
11556
        outputTrustedConflict(trustedConflict, conf.second);
1809
      }
1810
      else
1811
      {
1812
56529
        outputConflict(conflict, conf.second);
1813
      }
1814
    }
1815
  }
1816
50029
  if(!d_blackBoxConflict.get().isNull()){
1817
4288
    Node bb = d_blackBoxConflict.get();
1818
2144
    ++conflicts;
1819
4288
    Debug("arith::conflict") << "black box conflict" << bb
1820
      //<< "("<<conflicts<<")"
1821
2144
                             << endl;
1822
2144
    if(Debug.isOn("arith::normalize::external")){
1823
      bb = flattenAndSort(bb);
1824
      Debug("arith::conflict") << "(normalized to) " << bb << endl;
1825
    }
1826
2144
    if (isProofEnabled() && d_blackBoxConflictPf.get())
1827
    {
1828
760
      auto confPf = d_blackBoxConflictPf.get();
1829
380
      outputTrustedConflict(d_pfGen->mkTrustNode(bb, confPf, true), InferenceId::ARITH_BLACK_BOX);
1830
    }
1831
    else
1832
    {
1833
1764
      outputConflict(bb, InferenceId::ARITH_BLACK_BOX);
1834
    }
1835
  }
1836
50029
}
1837
1838
71424
bool TheoryArithPrivate::outputTrustedLemma(TrustNode lemma, InferenceId id)
1839
{
1840
71424
  Debug("arith::channel") << "Arith trusted lemma: " << lemma << std::endl;
1841
71424
  return d_containing.d_im.trustedLemma(lemma, id);
1842
}
1843
1844
77861
bool TheoryArithPrivate::outputLemma(TNode lem, InferenceId id) {
1845
77861
  Debug("arith::channel") << "Arith lemma: " << lem << std::endl;
1846
77861
  return d_containing.d_im.lemma(lem, id);
1847
}
1848
1849
11936
void TheoryArithPrivate::outputTrustedConflict(TrustNode conf, InferenceId id)
1850
{
1851
11936
  Debug("arith::channel") << "Arith trusted conflict: " << conf << std::endl;
1852
11936
  d_containing.d_im.trustedConflict(conf, id);
1853
11936
}
1854
1855
58293
void TheoryArithPrivate::outputConflict(TNode lit, InferenceId id) {
1856
58293
  Debug("arith::channel") << "Arith conflict: " << lit << std::endl;
1857
58293
  d_containing.d_im.conflict(lit, id);
1858
58293
}
1859
1860
1277274
void TheoryArithPrivate::outputPropagate(TNode lit) {
1861
1277274
  Debug("arith::channel") << "Arith propagation: " << lit << std::endl;
1862
  // call the propagate lit method of the
1863
1277274
  d_containing.d_im.propagateLit(lit);
1864
1277274
}
1865
1866
void TheoryArithPrivate::outputRestart() {
1867
  Debug("arith::channel") << "Arith restart!" << std::endl;
1868
  (d_containing.d_out)->demandRestart();
1869
}
1870
1871
1540489
bool TheoryArithPrivate::attemptSolveInteger(Theory::Effort effortLevel, bool emmmittedLemmaOrSplit){
1872
1540489
  int level = getSatContext()->getLevel();
1873
3080978
  Debug("approx")
1874
1540489
    << "attemptSolveInteger " << d_qflraStatus
1875
1540489
    << " " << emmmittedLemmaOrSplit
1876
1540489
    << " " << effortLevel
1877
1540489
    << " " << d_lastContextIntegerAttempted
1878
1540489
    << " " << level
1879
3080978
    << " " << hasIntegerModel()
1880
1540489
    << endl;
1881
1882
1540489
  if(d_qflraStatus == Result::UNSAT){ return false; }
1883
1502643
  if(emmmittedLemmaOrSplit){ return false; }
1884
5975024
  if(!options::useApprox()){ return false; }
1885
  if(!ApproximateSimplex::enabled()){ return false; }
1886
1887
  if(Theory::fullEffort(effortLevel)){
1888
    if(hasIntegerModel()){
1889
      return false;
1890
    }else{
1891
      return getSolveIntegerResource();
1892
    }
1893
  }
1894
1895
  if(d_lastContextIntegerAttempted <= 0){
1896
    if(hasIntegerModel()){
1897
      d_lastContextIntegerAttempted = getSatContext()->getLevel();
1898
      return false;
1899
    }else{
1900
      return getSolveIntegerResource();
1901
    }
1902
  }
1903
1904
1905
  if(!options::trySolveIntStandardEffort()){ return false; }
1906
1907
  if (d_lastContextIntegerAttempted <= (level >> 2))
1908
  {
1909
    double d = (double)(d_solveIntMaybeHelp + 1)
1910
               / (d_solveIntAttempts + 1 + level * level);
1911
    if (Random::getRandom().pickWithProb(d))
1912
    {
1913
      return getSolveIntegerResource();
1914
    }
1915
  }
1916
  return false;
1917
}
1918
1919
bool TheoryArithPrivate::replayLog(ApproximateSimplex* approx){
1920
  TimerStat::CodeTimer codeTimer(d_statistics.d_replayLogTimer);
1921
1922
  ++d_statistics.d_mipProofsAttempted;
1923
1924
  Assert(d_replayVariables.empty());
1925
  Assert(d_replayConstraints.empty());
1926
1927
  size_t enteringPropN = d_currentPropagationList.size();
1928
  Assert(conflictQueueEmpty());
1929
  TreeLog& tl = getTreeLog();
1930
  //tl.applySelected(); /* set row ids */
1931
1932
  d_replayedLemmas = false;
1933
1934
  /* use the try block for the purpose of pushing the sat context */
1935
  context::Context::ScopedPush speculativePush(getSatContext());
1936
  d_cmEnabled = false;
1937
  std::vector<ConstraintCPVec> res =
1938
      replayLogRec(approx, tl.getRootId(), NullConstraint, 1);
1939
1940
  if(res.empty()){
1941
    ++d_statistics.d_replayAttemptFailed;
1942
  }else{
1943
    unsigned successes = 0;
1944
    for(size_t i =0, N = res.size(); i < N; ++i){
1945
      ConstraintCPVec& vec = res[i];
1946
      Assert(vec.size() >= 2);
1947
      for(size_t j=0, M = vec.size(); j < M; ++j){
1948
        ConstraintCP at_j = vec[j];
1949
        Assert(at_j->isTrue());
1950
        if(!at_j->negationHasProof()){
1951
          successes++;
1952
          vec[j] = vec.back();
1953
          vec.pop_back();
1954
          ConstraintP neg_at_j = at_j->getNegation();
1955
1956
          Debug("approx::replayLog") << "Setting the proof for the replayLog conflict on:" << endl
1957
                                     << "  (" << neg_at_j->isTrue() <<") " << neg_at_j << endl
1958
                                     << "  (" << at_j->isTrue() <<") " << at_j << endl;
1959
          neg_at_j->impliedByIntHole(vec, true);
1960
          raiseConflict(at_j, InferenceId::UNKNOWN);
1961
          break;
1962
        }
1963
      }
1964
    }
1965
    if(successes > 0){
1966
      ++d_statistics.d_mipProofsSuccessful;
1967
    }
1968
  }
1969
1970
  if(d_currentPropagationList.size() > enteringPropN){
1971
    d_currentPropagationList.resize(enteringPropN);
1972
  }
1973
1974
  /* It is not clear what the d_qflraStatus is at this point */
1975
  d_qflraStatus = Result::SAT_UNKNOWN;
1976
1977
  Assert(d_replayVariables.empty());
1978
  Assert(d_replayConstraints.empty());
1979
1980
  return !conflictQueueEmpty();
1981
}
1982
1983
std::pair<ConstraintP, ArithVar> TheoryArithPrivate::replayGetConstraint(const DenseMap<Rational>& lhs, Kind k, const Rational& rhs, bool branch)
1984
{
1985
  ArithVar added = ARITHVAR_SENTINEL;
1986
  Node sum = toSumNode(d_partialModel, lhs);
1987
  if(sum.isNull()){ return make_pair(NullConstraint, added); }
1988
1989
  Debug("approx::constraint") << "replayGetConstraint " << sum
1990
                              << " " << k
1991
                              << " " << rhs
1992
                              << endl;
1993
1994
  Assert(k == kind::LEQ || k == kind::GEQ);
1995
1996
  Node comparison = NodeManager::currentNM()->mkNode(k, sum, mkRationalNode(rhs));
1997
  Node rewritten = Rewriter::rewrite(comparison);
1998
  if(!(Comparison::isNormalAtom(rewritten))){
1999
    return make_pair(NullConstraint, added);
2000
  }
2001
2002
  Comparison cmp = Comparison::parseNormalForm(rewritten);
2003
  if(cmp.isBoolean()){ return make_pair(NullConstraint, added); }
2004
2005
  Polynomial nvp =  cmp.normalizedVariablePart();
2006
  if(nvp.isZero()){ return make_pair(NullConstraint, added); }
2007
2008
  Node norm = nvp.getNode();
2009
2010
  ConstraintType t = Constraint::constraintTypeOfComparison(cmp);
2011
  DeltaRational dr = cmp.normalizedDeltaRational();
2012
2013
  Debug("approx::constraint") << "rewriting " << rewritten << endl
2014
                              << " |-> " << norm << " " << t << " " << dr << endl;
2015
2016
  Assert(!branch || d_partialModel.hasArithVar(norm));
2017
  ArithVar v = ARITHVAR_SENTINEL;
2018
  if(d_partialModel.hasArithVar(norm)){
2019
2020
    v = d_partialModel.asArithVar(norm);
2021
    Debug("approx::constraint") << "replayGetConstraint found "
2022
                                << norm << " |-> " << v << " @ " << getSatContext()->getLevel() << endl;
2023
    Assert(!branch || d_partialModel.isIntegerInput(v));
2024
  }else{
2025
    v = requestArithVar(norm, true, true);
2026
    d_replayVariables.push_back(v);
2027
2028
    added = v;
2029
2030
    Debug("approx::constraint") << "replayGetConstraint adding "
2031
                                << norm << " |-> " << v << " @ " << getSatContext()->getLevel() << endl;
2032
2033
    Polynomial poly = Polynomial::parsePolynomial(norm);
2034
    vector<ArithVar> variables;
2035
    vector<Rational> coefficients;
2036
    asVectors(poly, coefficients, variables);
2037
    d_tableau.addRow(v, coefficients, variables);
2038
    setupBasicValue(v);
2039
    d_linEq.trackRowIndex(d_tableau.basicToRowIndex(v));
2040
  }
2041
  Assert(d_partialModel.hasArithVar(norm));
2042
  Assert(d_partialModel.asArithVar(norm) == v);
2043
  Assert(d_constraintDatabase.variableDatabaseIsSetup(v));
2044
2045
  ConstraintP imp = d_constraintDatabase.getBestImpliedBound(v, t, dr);
2046
  if(imp != NullConstraint){
2047
    if(imp->getValue() == dr){
2048
      Assert(added == ARITHVAR_SENTINEL);
2049
      return make_pair(imp, added);
2050
    }
2051
  }
2052
2053
  ConstraintP newc = d_constraintDatabase.getConstraint(v, t, dr);
2054
  d_replayConstraints.push_back(newc);
2055
  return make_pair(newc, added);
2056
}
2057
2058
std::pair<ConstraintP, ArithVar> TheoryArithPrivate::replayGetConstraint(
2059
    ApproximateSimplex* approx, const NodeLog& nl)
2060
{
2061
  Assert(nl.isBranch());
2062
  Assert(d_lhsTmp.empty());
2063
2064
  ArithVar v = approx->getBranchVar(nl);
2065
  if(v != ARITHVAR_SENTINEL && d_partialModel.isIntegerInput(v)){
2066
    if(d_partialModel.hasNode(v)){
2067
      d_lhsTmp.set(v, Rational(1));
2068
      double dval = nl.branchValue();
2069
      Maybe<Rational> maybe_value = ApproximateSimplex::estimateWithCFE(dval);
2070
      if (!maybe_value)
2071
      {
2072
        return make_pair(NullConstraint, ARITHVAR_SENTINEL);
2073
      }
2074
      Rational fl(maybe_value.value().floor());
2075
      pair<ConstraintP, ArithVar> p;
2076
      p = replayGetConstraint(d_lhsTmp, kind::LEQ, fl, true);
2077
      d_lhsTmp.purge();
2078
      return p;
2079
    }
2080
  }
2081
  return make_pair(NullConstraint, ARITHVAR_SENTINEL);
2082
}
2083
2084
std::pair<ConstraintP, ArithVar> TheoryArithPrivate::replayGetConstraint(const CutInfo& ci) {
2085
  Assert(ci.reconstructed());
2086
  const DenseMap<Rational>& lhs = ci.getReconstruction().lhs;
2087
  const Rational& rhs = ci.getReconstruction().rhs;
2088
  Kind k = ci.getKind();
2089
2090
  return replayGetConstraint(lhs, k, rhs, ci.getKlass() == BranchCutKlass);
2091
}
2092
2093
// Node denseVectorToLiteral(const ArithVariables& vars, const DenseVector& dv, Kind k){
2094
//   NodeManager* nm = NodeManager::currentNM();
2095
//   Node sumLhs = toSumNode(vars, dv.lhs);
2096
//   Node ineq = nm->mkNode(k, sumLhs, mkRationalNode(dv.rhs) );
2097
//   Node lit = Rewriter::rewrite(ineq);
2098
//   return lit;
2099
// }
2100
2101
Node toSumNode(const ArithVariables& vars, const DenseMap<Rational>& sum){
2102
  Debug("arith::toSumNode") << "toSumNode() begin" << endl;
2103
  NodeBuilder nb(kind::PLUS);
2104
  NodeManager* nm = NodeManager::currentNM();
2105
  DenseMap<Rational>::const_iterator iter, end;
2106
  iter = sum.begin(), end = sum.end();
2107
  for(; iter != end; ++iter){
2108
    ArithVar x = *iter;
2109
    if(!vars.hasNode(x)){ return Node::null(); }
2110
    Node xNode = vars.asNode(x);
2111
    const Rational& q = sum[x];
2112
    Node mult = nm->mkNode(kind::MULT, mkRationalNode(q), xNode);
2113
    Debug("arith::toSumNode") << "toSumNode() " << x << " " << mult << endl;
2114
    nb << mult;
2115
  }
2116
  Debug("arith::toSumNode") << "toSumNode() end" << endl;
2117
  return safeConstructNary(nb);
2118
}
2119
2120
ConstraintCP TheoryArithPrivate::vectorToIntHoleConflict(const ConstraintCPVec& conflict){
2121
  Assert(conflict.size() >= 2);
2122
  ConstraintCPVec exp(conflict.begin(), conflict.end()-1);
2123
  ConstraintCP back = conflict.back();
2124
  Assert(back->hasProof());
2125
  ConstraintP negBack = back->getNegation();
2126
  // This can select negBack multiple times so we need to test if negBack has a proof.
2127
  if(negBack->hasProof()){
2128
    // back is in conflict already
2129
  } else {
2130
    negBack->impliedByIntHole(exp, true);
2131
  }
2132
2133
  return back;
2134
}
2135
2136
void TheoryArithPrivate::intHoleConflictToVector(ConstraintCP conflicting, ConstraintCPVec& conflict){
2137
  ConstraintCP negConflicting = conflicting->getNegation();
2138
  Assert(conflicting->hasProof());
2139
  Assert(negConflicting->hasProof());
2140
2141
  conflict.push_back(conflicting);
2142
  conflict.push_back(negConflicting);
2143
2144
  Constraint::assertionFringe(conflict);
2145
}
2146
2147
void TheoryArithPrivate::tryBranchCut(ApproximateSimplex* approx, int nid, BranchCutInfo& bci){
2148
  Assert(conflictQueueEmpty());
2149
  std::vector< ConstraintCPVec > conflicts;
2150
2151
  approx->tryCut(nid, bci);
2152
  Debug("approx::branch") << "tryBranchCut" << bci << endl;
2153
  Assert(bci.reconstructed());
2154
  Assert(!bci.proven());
2155
  pair<ConstraintP, ArithVar> p = replayGetConstraint(bci);
2156
  Assert(p.second == ARITHVAR_SENTINEL);
2157
  ConstraintP bc = p.first;
2158
  Assert(bc != NullConstraint);
2159
  if(bc->hasProof()){
2160
    return;
2161
  }
2162
2163
  ConstraintP bcneg = bc->getNegation();
2164
  {
2165
    context::Context::ScopedPush speculativePush(getSatContext());
2166
    replayAssert(bcneg);
2167
    if(conflictQueueEmpty()){
2168
      TimerStat::CodeTimer codeTimer(d_statistics.d_replaySimplexTimer);
2169
2170
      //test for linear feasibility
2171
      d_partialModel.stopQueueingBoundCounts();
2172
      UpdateTrackingCallback utcb(&d_linEq);
2173
      d_partialModel.processBoundsQueue(utcb);
2174
      d_linEq.startTrackingBoundCounts();
2175
2176
      SimplexDecisionProcedure& simplex = selectSimplex(true);
2177
      simplex.findModel(false);
2178
      // Can change d_qflraStatus
2179
2180
      d_linEq.stopTrackingBoundCounts();
2181
      d_partialModel.startQueueingBoundCounts();
2182
    }
2183
    for(size_t i = 0, N = d_conflicts.size(); i < N; ++i){
2184
2185
      conflicts.push_back(ConstraintCPVec());
2186
      intHoleConflictToVector(d_conflicts[i].first, conflicts.back());
2187
      Constraint::assertionFringe(conflicts.back());
2188
2189
      // ConstraintCP conflicting = d_conflicts[i];
2190
      // ConstraintCP negConflicting = conflicting->getNegation();
2191
      // Assert(conflicting->hasProof());
2192
      // Assert(negConflicting->hasProof());
2193
2194
      // conflicts.push_back(ConstraintCPVec());
2195
      // ConstraintCPVec& back = conflicts.back();
2196
      // back.push_back(conflicting);
2197
      // back.push_back(negConflicting);
2198
2199
      // // remove the floor/ceiling contraint implied by bcneg
2200
      // Constraint::assertionFringe(back);
2201
    }
2202
2203
    if(Debug.isOn("approx::branch")){
2204
      if(d_conflicts.empty()){
2205
        entireStateIsConsistent("branchfailure");
2206
      }
2207
    }
2208
  }
2209
2210
  Debug("approx::branch") << "branch constraint " << bc << endl;
2211
  for(size_t i = 0, N = conflicts.size(); i < N; ++i){
2212
    ConstraintCPVec& conf = conflicts[i];
2213
2214
    // make sure to be working on the assertion fringe!
2215
    if(!contains(conf, bcneg)){
2216
      Debug("approx::branch") << "reraise " << conf  << endl;
2217
      ConstraintCP conflicting = vectorToIntHoleConflict(conf);
2218
      raiseConflict(conflicting, InferenceId::UNKNOWN);
2219
    }else if(!bci.proven()){
2220
      drop(conf, bcneg);
2221
      bci.setExplanation(conf);
2222
      Debug("approx::branch") << "dropped " << bci  << endl;
2223
    }
2224
  }
2225
}
2226
2227
void TheoryArithPrivate::replayAssert(ConstraintP c) {
2228
  if(!c->assertedToTheTheory()){
2229
    bool inConflict = c->negationHasProof();
2230
    if(!c->hasProof()){
2231
      c->setInternalAssumption(inConflict);
2232
      Debug("approx::replayAssert") << "replayAssert " << c << " set internal" << endl;
2233
    }else{
2234
      Debug("approx::replayAssert") << "replayAssert " << c << " has explanation" << endl;
2235
    }
2236
    Debug("approx::replayAssert") << "replayAssertion " << c << endl;
2237
    if(inConflict){
2238
      raiseConflict(c, InferenceId::UNKNOWN);
2239
    }else{
2240
      assertionCases(c);
2241
    }
2242
  }else{
2243
    Debug("approx::replayAssert")
2244
        << "replayAssert " << c << " already asserted" << endl;
2245
  }
2246
}
2247
2248
2249
void TheoryArithPrivate::resolveOutPropagated(std::vector<ConstraintCPVec>& confs, const std::set<ConstraintCP>& propagated) const {
2250
  Debug("arith::resolveOutPropagated")
2251
    << "starting resolveOutPropagated() " << confs.size() << endl;
2252
  for(size_t i =0, N = confs.size(); i < N; ++i){
2253
    ConstraintCPVec& conf = confs[i];
2254
    size_t orig = conf.size();
2255
    Constraint::assertionFringe(conf);
2256
    Debug("arith::resolveOutPropagated")
2257
      << "  conf["<<i<<"] " << orig << " to " << conf.size() << endl;
2258
  }
2259
  Debug("arith::resolveOutPropagated")
2260
    << "ending resolveOutPropagated() " << confs.size() << endl;
2261
}
2262
2263
struct SizeOrd {
2264
  bool operator()(const ConstraintCPVec& a, const ConstraintCPVec& b) const{
2265
    return a.size() < b.size();
2266
  }
2267
};
2268
2269
void TheoryArithPrivate::subsumption(
2270
    std::vector<ConstraintCPVec> &confs) const {
2271
  int checks CVC5_UNUSED = 0;
2272
  int subsumed CVC5_UNUSED = 0;
2273
2274
  for (size_t i = 0, N = confs.size(); i < N; ++i) {
2275
    ConstraintCPVec &conf = confs[i];
2276
    std::sort(conf.begin(), conf.end());
2277
  }
2278
2279
  std::sort(confs.begin(), confs.end(), SizeOrd());
2280
  for (size_t i = 0; i < confs.size(); i++) {
2281
    // i is not subsumed
2282
    for (size_t j = i + 1; j < confs.size();) {
2283
      ConstraintCPVec& a = confs[i];
2284
      ConstraintCPVec& b = confs[j];
2285
      checks++;
2286
      bool subsumes = std::includes(a.begin(), a.end(), b.begin(), b.end());
2287
      if (subsumes) {
2288
        ConstraintCPVec& back = confs.back();
2289
        b.swap(back);
2290
        confs.pop_back();
2291
        subsumed++;
2292
      } else {
2293
        j++;
2294
      }
2295
    }
2296
  }
2297
  Debug("arith::subsumption") << "subsumed " << subsumed << "/" << checks
2298
                              << endl;
2299
}
2300
2301
std::vector<ConstraintCPVec> TheoryArithPrivate::replayLogRec(ApproximateSimplex* approx, int nid, ConstraintP bc, int depth){
2302
  ++(d_statistics.d_replayLogRecCount);
2303
  Debug("approx::replayLogRec") << "replayLogRec()" << std::endl;
2304
2305
  size_t rpvars_size = d_replayVariables.size();
2306
  size_t rpcons_size = d_replayConstraints.size();
2307
  std::vector<ConstraintCPVec> res;
2308
2309
  { /* create a block for the purpose of pushing the sat context */
2310
    context::Context::ScopedPush speculativePush(getSatContext());
2311
    Assert(!anyConflict());
2312
    Assert(conflictQueueEmpty());
2313
    set<ConstraintCP> propagated;
2314
2315
    TreeLog& tl = getTreeLog();
2316
2317
    if(bc != NullConstraint){
2318
      replayAssert(bc);
2319
    }
2320
2321
    const NodeLog& nl = tl.getNode(nid);
2322
    NodeLog::const_iterator iter = nl.begin(), end = nl.end();
2323
    for(; conflictQueueEmpty() && iter != end; ++iter){
2324
      CutInfo* ci = *iter;
2325
      bool reject = false;
2326
      //cout << "  trying " << *ci << endl;
2327
      if(ci->getKlass() == RowsDeletedKlass){
2328
        RowsDeleted* rd = dynamic_cast<RowsDeleted*>(ci);
2329
2330
        tl.applyRowsDeleted(nid, *rd);
2331
        // The previous line modifies nl
2332
2333
        ++d_statistics.d_applyRowsDeleted;
2334
      }else if(ci->getKlass() == BranchCutKlass){
2335
        BranchCutInfo* bci = dynamic_cast<BranchCutInfo*>(ci);
2336
        Assert(bci != NULL);
2337
        tryBranchCut(approx, nid, *bci);
2338
2339
        ++d_statistics.d_branchCutsAttempted;
2340
        if(!(conflictQueueEmpty() || ci->reconstructed())){
2341
          ++d_statistics.d_numBranchesFailed;
2342
        }
2343
      }else{
2344
        approx->tryCut(nid, *ci);
2345
        if(ci->getKlass() == GmiCutKlass){
2346
          ++d_statistics.d_gmiCutsAttempted;
2347
        }else if(ci->getKlass() == MirCutKlass){
2348
          ++d_statistics.d_mirCutsAttempted;
2349
        }
2350
2351
        if(ci->reconstructed() && ci->proven()){
2352
          const DenseMap<Rational>& row = ci->getReconstruction().lhs;
2353
          reject = !complexityBelow(row, options::replayRejectCutSize());
2354
        }
2355
      }
2356
      if(conflictQueueEmpty()){
2357
        if(reject){
2358
          ++d_statistics.d_cutsRejectedDuringReplay;
2359
        }else if(ci->reconstructed()){
2360
          // success
2361
          ++d_statistics.d_cutsReconstructed;
2362
2363
          pair<ConstraintP, ArithVar> p = replayGetConstraint(*ci);
2364
          if(p.second != ARITHVAR_SENTINEL){
2365
            Assert(ci->getRowId() >= 1);
2366
            tl.mapRowId(nl.getNodeId(), ci->getRowId(), p.second);
2367
          }
2368
          ConstraintP con = p.first;
2369
          if(Debug.isOn("approx::replayLogRec")){
2370
            Debug("approx::replayLogRec") << "cut was remade " << con << " " << *ci << endl;
2371
          }
2372
2373
          if(ci->proven()){
2374
            ++d_statistics.d_cutsProven;
2375
2376
            const ConstraintCPVec& exp = ci->getExplanation();
2377
            // success
2378
            if(con->isTrue()){
2379
              Debug("approx::replayLogRec") << "not asserted?" << endl;
2380
            }else if(!con->negationHasProof()){
2381
              con->impliedByIntHole(exp, false);
2382
              replayAssert(con);
2383
              Debug("approx::replayLogRec") << "cut prop" << endl;
2384
            }else {
2385
              con->impliedByIntHole(exp, true);
2386
              Debug("approx::replayLogRec") << "cut into conflict " << con << endl;
2387
              raiseConflict(con, InferenceId::UNKNOWN);
2388
            }
2389
          }else{
2390
            ++d_statistics.d_cutsProofFailed;
2391
            Debug("approx::replayLogRec") << "failed to get proof " << *ci << endl;
2392
          }
2393
        }else if(ci->getKlass() != RowsDeletedKlass){
2394
          ++d_statistics.d_cutsReconstructionFailed;
2395
        }
2396
      }
2397
    }
2398
2399
    /* check if the system is feasible under with the cuts */
2400
    if(conflictQueueEmpty()){
2401
      Assert(options::replayEarlyCloseDepths() >= 1);
2402
      if(!nl.isBranch() || depth % options::replayEarlyCloseDepths() == 0 ){
2403
        TimerStat::CodeTimer codeTimer(d_statistics.d_replaySimplexTimer);
2404
        //test for linear feasibility
2405
        d_partialModel.stopQueueingBoundCounts();
2406
        UpdateTrackingCallback utcb(&d_linEq);
2407
        d_partialModel.processBoundsQueue(utcb);
2408
        d_linEq.startTrackingBoundCounts();
2409
2410
        SimplexDecisionProcedure& simplex = selectSimplex(true);
2411
        simplex.findModel(false);
2412
        // can change d_qflraStatus
2413
2414
        d_linEq.stopTrackingBoundCounts();
2415
        d_partialModel.startQueueingBoundCounts();
2416
      }
2417
    }else{
2418
      ++d_statistics.d_replayLogRecConflictEscalation;
2419
    }
2420
2421
    if(!conflictQueueEmpty()){
2422
      /* if a conflict has been found stop */
2423
      for(size_t i = 0, N = d_conflicts.size(); i < N; ++i){
2424
        res.push_back(ConstraintCPVec());
2425
        intHoleConflictToVector(d_conflicts[i].first, res.back());
2426
      }
2427
      ++d_statistics.d_replayLogRecEarlyExit;
2428
    }else if(nl.isBranch()){
2429
      /* if it is a branch try the branch */
2430
      pair<ConstraintP, ArithVar> p = replayGetConstraint(approx, nl);
2431
      Assert(p.second == ARITHVAR_SENTINEL);
2432
      ConstraintP dnc = p.first;
2433
      if(dnc != NullConstraint){
2434
        ConstraintP upc = dnc->getNegation();
2435
2436
        int dnid = nl.getDownId();
2437
        int upid = nl.getUpId();
2438
2439
        NodeLog& dnlog = tl.getNode(dnid);
2440
        NodeLog& uplog = tl.getNode(upid);
2441
        dnlog.copyParentRowIds();
2442
        uplog.copyParentRowIds();
2443
2444
        std::vector<ConstraintCPVec> dnres;
2445
        std::vector<ConstraintCPVec> upres;
2446
        std::vector<size_t> containsdn;
2447
        std::vector<size_t> containsup;
2448
        if(res.empty()){
2449
          dnres = replayLogRec(approx, dnid, dnc, depth+1);
2450
          for(size_t i = 0, N = dnres.size(); i < N; ++i){
2451
            ConstraintCPVec& conf = dnres[i];
2452
            if(contains(conf, dnc)){
2453
              containsdn.push_back(i);
2454
            }else{
2455
              res.push_back(conf);
2456
            }
2457
          }
2458
        }else{
2459
          Debug("approx::replayLogRec") << "replayLogRec() skipping" << dnlog << std::endl;
2460
          ++d_statistics.d_replayBranchSkips;
2461
        }
2462
2463
        if(res.empty()){
2464
          upres = replayLogRec(approx, upid, upc, depth+1);
2465
2466
          for(size_t i = 0, N = upres.size(); i < N; ++i){
2467
            ConstraintCPVec& conf = upres[i];
2468
            if(contains(conf, upc)){
2469
              containsup.push_back(i);
2470
            }else{
2471
              res.push_back(conf);
2472
            }
2473
          }
2474
        }else{
2475
          Debug("approx::replayLogRec") << "replayLogRec() skipping" << uplog << std::endl;
2476
          ++d_statistics.d_replayBranchSkips;
2477
        }
2478
2479
        if(res.empty()){
2480
          for(size_t i = 0, N = containsdn.size(); i < N; ++i){
2481
            ConstraintCPVec& dnconf = dnres[containsdn[i]];
2482
            for(size_t j = 0, M = containsup.size(); j < M; ++j){
2483
              ConstraintCPVec& upconf = upres[containsup[j]];
2484
2485
              res.push_back(ConstraintCPVec());
2486
              ConstraintCPVec& back = res.back();
2487
              resolve(back, dnc, dnconf, upconf);
2488
            }
2489
          }
2490
          if(res.size() >= 2u){
2491
            subsumption(res);
2492
2493
            if(res.size() > 100u){
2494
              res.resize(100u);
2495
            }
2496
          }
2497
        }else{
2498
          Debug("approx::replayLogRec") << "replayLogRec() skipping resolving" << nl << std::endl;
2499
        }
2500
        Debug("approx::replayLogRec") << "found #"<<res.size()<<" conflicts on branch " << nid << endl;
2501
        if(res.empty()){
2502
          ++d_statistics.d_replayBranchCloseFailures;
2503
        }
2504
2505
      }else{
2506
        Debug("approx::replayLogRec") << "failed to make a branch " << nid << endl;
2507
      }
2508
    }else{
2509
      ++d_statistics.d_replayLeafCloseFailures;
2510
      Debug("approx::replayLogRec") << "failed on node " << nid << endl;
2511
      Assert(res.empty());
2512
    }
2513
    resolveOutPropagated(res, propagated);
2514
    Debug("approx::replayLogRec") << "replayLogRec() ending" << std::endl;
2515
2516
2517
    if(options::replayFailureLemma()){
2518
      // must be done inside the sat context to get things
2519
      // propagated at this level
2520
      if(res.empty() && nid == getTreeLog().getRootId()){
2521
        Assert(!d_replayedLemmas);
2522
        d_replayedLemmas = replayLemmas(approx);
2523
        Assert(d_acTmp.empty());
2524
        while(!d_approxCuts.empty()){
2525
          TrustNode lem = d_approxCuts.front();
2526
          d_approxCuts.pop();
2527
          d_acTmp.push_back(lem);
2528
        }
2529
      }
2530
    }
2531
  } /* pop the sat context */
2532
2533
  /* move into the current context. */
2534
  while(!d_acTmp.empty()){
2535
    TrustNode lem = d_acTmp.back();
2536
    d_acTmp.pop_back();
2537
    d_approxCuts.push_back(lem);
2538
  }
2539
  Assert(d_acTmp.empty());
2540
2541
  /* Garbage collect the constraints from this call */
2542
  while(d_replayConstraints.size() > rpcons_size){
2543
    ConstraintP c = d_replayConstraints.back();
2544
    d_replayConstraints.pop_back();
2545
    d_constraintDatabase.deleteConstraintAndNegation(c);
2546
  }
2547
2548
  /* Garbage collect the ArithVars made by this call */
2549
  if(d_replayVariables.size() > rpvars_size){
2550
    d_partialModel.stopQueueingBoundCounts();
2551
    UpdateTrackingCallback utcb(&d_linEq);
2552
    d_partialModel.processBoundsQueue(utcb);
2553
    d_linEq.startTrackingBoundCounts();
2554
    while(d_replayVariables.size() > rpvars_size){
2555
      ArithVar v = d_replayVariables.back();
2556
      d_replayVariables.pop_back();
2557
      Assert(d_partialModel.canBeReleased(v));
2558
      if(!d_tableau.isBasic(v)){
2559
        /* if it is not basic make it basic. */
2560
        ArithVar b = ARITHVAR_SENTINEL;
2561
        for(Tableau::ColIterator ci = d_tableau.colIterator(v); !ci.atEnd(); ++ci){
2562
          const Tableau::Entry& e = *ci;
2563
          b = d_tableau.rowIndexToBasic(e.getRowIndex());
2564
          break;
2565
        }
2566
        Assert(b != ARITHVAR_SENTINEL);
2567
        DeltaRational cp = d_partialModel.getAssignment(b);
2568
        if(d_partialModel.cmpAssignmentLowerBound(b) < 0){
2569
          cp = d_partialModel.getLowerBound(b);
2570
        }else if(d_partialModel.cmpAssignmentUpperBound(b) > 0){
2571
          cp = d_partialModel.getUpperBound(b);
2572
        }
2573
        d_linEq.pivotAndUpdate(b, v, cp);
2574
      }
2575
      Assert(d_tableau.isBasic(v));
2576
      d_linEq.stopTrackingRowIndex(d_tableau.basicToRowIndex(v));
2577
      d_tableau.removeBasicRow(v);
2578
2579
      releaseArithVar(v);
2580
      Debug("approx::vars") << "releasing " << v << endl;
2581
    }
2582
    d_linEq.stopTrackingBoundCounts();
2583
    d_partialModel.startQueueingBoundCounts();
2584
    d_partialModel.attemptToReclaimReleased();
2585
  }
2586
  return res;
2587
}
2588
2589
TreeLog& TheoryArithPrivate::getTreeLog(){
2590
  if(d_treeLog == NULL){
2591
    d_treeLog = new TreeLog();
2592
  }
2593
  return *d_treeLog;
2594
}
2595
2596
ApproximateStatistics& TheoryArithPrivate::getApproxStats(){
2597
  if(d_approxStats == NULL){
2598
    d_approxStats = new ApproximateStatistics();
2599
  }
2600
  return *d_approxStats;
2601
}
2602
2603
Node TheoryArithPrivate::branchToNode(ApproximateSimplex* approx,
2604
                                      const NodeLog& bn) const
2605
{
2606
  Assert(bn.isBranch());
2607
  ArithVar v = approx->getBranchVar(bn);
2608
  if(v != ARITHVAR_SENTINEL && d_partialModel.isIntegerInput(v)){
2609
    if(d_partialModel.hasNode(v)){
2610
      Node n = d_partialModel.asNode(v);
2611
      double dval = bn.branchValue();
2612
      Maybe<Rational> maybe_value = ApproximateSimplex::estimateWithCFE(dval);
2613
      if (!maybe_value)
2614
      {
2615
        return Node::null();
2616
      }
2617
      Rational fl(maybe_value.value().floor());
2618
      NodeManager* nm = NodeManager::currentNM();
2619
      Node leq = nm->mkNode(kind::LEQ, n, mkRationalNode(fl));
2620
      Node norm = Rewriter::rewrite(leq);
2621
      return norm;
2622
    }
2623
  }
2624
  return Node::null();
2625
}
2626
2627
Node TheoryArithPrivate::cutToLiteral(ApproximateSimplex* approx, const CutInfo& ci) const{
2628
  Assert(ci.reconstructed());
2629
2630
  const DenseMap<Rational>& lhs = ci.getReconstruction().lhs;
2631
  Node sum = toSumNode(d_partialModel, lhs);
2632
  if(!sum.isNull()){
2633
    Kind k = ci.getKind();
2634
    Assert(k == kind::LEQ || k == kind::GEQ);
2635
    Node rhs = mkRationalNode(ci.getReconstruction().rhs);
2636
2637
    NodeManager* nm = NodeManager::currentNM();
2638
    Node ineq = nm->mkNode(k, sum, rhs);
2639
    return Rewriter::rewrite(ineq);
2640
  }
2641
  return Node::null();
2642
}
2643
2644
bool TheoryArithPrivate::replayLemmas(ApproximateSimplex* approx){
2645
    ++(d_statistics.d_mipReplayLemmaCalls);
2646
    bool anythingnew = false;
2647
2648
    TreeLog& tl = getTreeLog();
2649
    NodeLog& root = tl.getRootNode();
2650
    root.applySelected(); /* set row ids */
2651
2652
    vector<const CutInfo*> cuts = approx->getValidCuts(root);
2653
    for(size_t i =0, N =cuts.size(); i < N; ++i){
2654
      const CutInfo* cut = cuts[i];
2655
      Assert(cut->reconstructed());
2656
      Assert(cut->proven());
2657
2658
      const DenseMap<Rational>& row =  cut->getReconstruction().lhs;
2659
      if(!complexityBelow(row, options::lemmaRejectCutSize())){
2660
        ++(d_statistics.d_cutsRejectedDuringLemmas);
2661
        continue;
2662
      }
2663
2664
      Node cutConstraint = cutToLiteral(approx, *cut);
2665
      if(!cutConstraint.isNull()){
2666
        const ConstraintCPVec& exp = cut->getExplanation();
2667
        Node asLemma = Constraint::externalExplainByAssertions(exp);
2668
2669
        Node implied = Rewriter::rewrite(cutConstraint);
2670
        anythingnew = anythingnew || !isSatLiteral(implied);
2671
2672
        Node implication = asLemma.impNode(implied);
2673
        // DO NOT CALL OUTPUT LEMMA!
2674
        // TODO (project #37): justify
2675
        d_approxCuts.push_back(TrustNode::mkTrustLemma(implication, nullptr));
2676
        Debug("approx::lemmas") << "cut["<<i<<"] " << implication << endl;
2677
        ++(d_statistics.d_mipExternalCuts);
2678
      }
2679
    }
2680
    if(root.isBranch()){
2681
      Node lit = branchToNode(approx, root);
2682
      if(!lit.isNull()){
2683
        anythingnew = anythingnew || !isSatLiteral(lit);
2684
        Node branch = lit.orNode(lit.notNode());
2685
        if (proofsEnabled())
2686
        {
2687
          d_pfGen->mkTrustNode(branch, PfRule::SPLIT, {}, {lit});
2688
        }
2689
        else
2690
        {
2691
          d_approxCuts.push_back(TrustNode::mkTrustLemma(branch, nullptr));
2692
        }
2693
        ++(d_statistics.d_mipExternalBranch);
2694
        Debug("approx::lemmas") << "branching "<< root <<" as " << branch << endl;
2695
      }
2696
    }
2697
    return anythingnew;
2698
}
2699
2700
void TheoryArithPrivate::turnOffApproxFor(int32_t rounds){
2701
  d_attemptSolveIntTurnedOff = d_attemptSolveIntTurnedOff + rounds;
2702
  ++(d_statistics.d_approxDisabled);
2703
}
2704
2705
1484869
bool TheoryArithPrivate::safeToCallApprox() const{
2706
1484869
  unsigned numRows = 0;
2707
1484869
  unsigned numCols = 0;
2708
1484869
  var_iterator vi = var_begin(), vi_end = var_end();
2709
  // Assign each variable to a row and column variable as it appears in the input
2710
23563305
  for(; vi != vi_end && !(numRows > 0 && numCols > 0); ++vi){
2711
11039218
    ArithVar v = *vi;
2712
2713
11039218
    if(d_partialModel.isAuxiliary(v)){
2714
1467888
      ++numRows;
2715
    }else{
2716
9571330
      ++numCols;
2717
    }
2718
  }
2719
1484869
  return (numRows > 0 && numCols > 0);
2720
}
2721
2722
// solve()
2723
//   res = solveRealRelaxation(effortLevel);
2724
//   switch(res){
2725
//   case LinFeas:
2726
//   case LinInfeas:
2727
//     return replay()
2728
//   case Unknown:
2729
//   case Error
2730
//     if()
2731
void TheoryArithPrivate::solveInteger(Theory::Effort effortLevel){
2732
  if(!safeToCallApprox()) { return; }
2733
2734
  Assert(safeToCallApprox());
2735
  TimerStat::CodeTimer codeTimer0(d_statistics.d_solveIntTimer);
2736
2737
  ++(d_statistics.d_solveIntCalls);
2738
  d_statistics.d_inSolveInteger = 1;
2739
2740
  if(!Theory::fullEffort(effortLevel)){
2741
    d_solveIntAttempts++;
2742
    ++(d_statistics.d_solveStandardEffort);
2743
  }
2744
2745
  // if integers are attempted,
2746
  Assert(options::useApprox());
2747
  Assert(ApproximateSimplex::enabled());
2748
2749
  int level = getSatContext()->getLevel();
2750
  d_lastContextIntegerAttempted = level;
2751
2752
2753
  static const int32_t mipLimit = 200000;
2754
2755
  TreeLog& tl = getTreeLog();
2756
  ApproximateStatistics& stats = getApproxStats();
2757
  ApproximateSimplex* approx =
2758
    ApproximateSimplex::mkApproximateSimplexSolver(d_partialModel, tl, stats);
2759
2760
    approx->setPivotLimit(mipLimit);
2761
    if(!d_guessedCoeffSet){
2762
      d_guessedCoeffs = approx->heuristicOptCoeffs();
2763
      d_guessedCoeffSet = true;
2764
    }
2765
    if(!d_guessedCoeffs.empty()){
2766
      approx->setOptCoeffs(d_guessedCoeffs);
2767
    }
2768
    static const int32_t depthForLikelyInfeasible = 10;
2769
    int maxDepthPass1 = d_likelyIntegerInfeasible ?
2770
      depthForLikelyInfeasible : options::maxApproxDepth();
2771
    approx->setBranchingDepth(maxDepthPass1);
2772
    approx->setBranchOnVariableLimit(100);
2773
    LinResult relaxRes = approx->solveRelaxation();
2774
    if( relaxRes == LinFeasible ){
2775
      MipResult mipRes = MipUnknown;
2776
      {
2777
        TimerStat::CodeTimer codeTimer1(d_statistics.d_mipTimer);
2778
        mipRes = approx->solveMIP(false);
2779
      }
2780
2781
      Debug("arith::solveInteger") << "mipRes " << mipRes << endl;
2782
      switch(mipRes) {
2783
      case MipBingo:
2784
        // attempt the solution
2785
        {
2786
          ++(d_statistics.d_solveIntModelsAttempts);
2787
2788
          d_partialModel.stopQueueingBoundCounts();
2789
          UpdateTrackingCallback utcb(&d_linEq);
2790
          d_partialModel.processBoundsQueue(utcb);
2791
          d_linEq.startTrackingBoundCounts();
2792
2793
          ApproximateSimplex::Solution mipSolution;
2794
          mipSolution = approx->extractMIP();
2795
          importSolution(mipSolution);
2796
          solveRelaxationOrPanic(effortLevel);
2797
2798
          if (d_qflraStatus == Result::SAT)
2799
          {
2800
            if (!anyConflict())
2801
            {
2802
              if (ARITHVAR_SENTINEL == nextIntegerViolation(false))
2803
              {
2804
                ++(d_statistics.d_solveIntModelsSuccessful);
2805
              }
2806
            }
2807
          }
2808
2809
          // shutdown simplex
2810
          d_linEq.stopTrackingBoundCounts();
2811
          d_partialModel.startQueueingBoundCounts();
2812
        }
2813
        break;
2814
      case MipClosed:
2815
        /* All integer branches closed */
2816
        approx->setPivotLimit(2*mipLimit);
2817
        {
2818
          TimerStat::CodeTimer codeTimer2(d_statistics.d_mipTimer);
2819
          mipRes = approx->solveMIP(true);
2820
        }
2821
2822
        if(mipRes == MipClosed){
2823
          d_likelyIntegerInfeasible = true;
2824
          replayLog(approx);
2825
          AlwaysAssert(anyConflict() || d_qflraStatus != Result::SAT);
2826
2827
          if (!anyConflict())
2828
          {
2829
            solveRealRelaxation(effortLevel);
2830
          }
2831
        }
2832
        if(!(anyConflict() || !d_approxCuts.empty())){
2833
          turnOffApproxFor(options::replayNumericFailurePenalty());
2834
        }
2835
        break;
2836
      case BranchesExhausted:
2837
      case ExecExhausted:
2838
      case PivotsExhauasted:
2839
        if(mipRes == BranchesExhausted){
2840
          ++d_statistics.d_branchesExhausted;
2841
        }else if(mipRes == ExecExhausted){
2842
          ++d_statistics.d_execExhausted;
2843
        }else if(mipRes == PivotsExhauasted){
2844
          ++d_statistics.d_pivotsExhausted;
2845
        }
2846
2847
        approx->setPivotLimit(2*mipLimit);
2848
        approx->setBranchingDepth(2);
2849
        {
2850
          TimerStat::CodeTimer codeTimer3(d_statistics.d_mipTimer);
2851
          mipRes = approx->solveMIP(true);
2852
        }
2853
        replayLemmas(approx);
2854
        break;
2855
      case MipUnknown:
2856
        break;
2857
      }
2858
    }
2859
  delete approx;
2860
2861
  if(!Theory::fullEffort(effortLevel)){
2862
    if(anyConflict() || !d_approxCuts.empty()){
2863
      d_solveIntMaybeHelp++;
2864
    }
2865
  }
2866
2867
  d_statistics.d_inSolveInteger = 0;
2868
}
2869
2870
1484869
SimplexDecisionProcedure& TheoryArithPrivate::selectSimplex(bool pass1){
2871
1484869
  if(pass1){
2872
1484869
    if(d_pass1SDP == NULL){
2873
1553161
      if(options::useFC()){
2874
        d_pass1SDP = (SimplexDecisionProcedure*)(&d_fcSimplex);
2875
12672
      }else if(options::useSOI()){
2876
        d_pass1SDP = (SimplexDecisionProcedure*)(&d_soiSimplex);
2877
      }else{
2878
6336
        d_pass1SDP = (SimplexDecisionProcedure*)(&d_dualSimplex);
2879
      }
2880
    }
2881
1484869
    Assert(d_pass1SDP != NULL);
2882
1484869
    return *d_pass1SDP;
2883
  }else{
2884
     if(d_otherSDP == NULL){
2885
      if(options::useFC()){
2886
        d_otherSDP  = (SimplexDecisionProcedure*)(&d_fcSimplex);
2887
      }else if(options::useSOI()){
2888
        d_otherSDP = (SimplexDecisionProcedure*)(&d_soiSimplex);
2889
      }else{
2890
        d_otherSDP = (SimplexDecisionProcedure*)(&d_soiSimplex);
2891
      }
2892
    }
2893
    Assert(d_otherSDP != NULL);
2894
    return *d_otherSDP;
2895
  }
2896
}
2897
2898
void TheoryArithPrivate::importSolution(const ApproximateSimplex::Solution& solution){
2899
  if(Debug.isOn("arith::importSolution")){
2900
    Debug("arith::importSolution") << "importSolution before " << d_qflraStatus << endl;
2901
    d_partialModel.printEntireModel(Debug("arith::importSolution"));
2902
  }
2903
2904
  d_qflraStatus = d_attemptSolSimplex.attempt(solution);
2905
2906
  if(Debug.isOn("arith::importSolution")){
2907
    Debug("arith::importSolution") << "importSolution intermediate " << d_qflraStatus << endl;
2908
    d_partialModel.printEntireModel(Debug("arith::importSolution"));
2909
  }
2910
2911
  if(d_qflraStatus != Result::UNSAT){
2912
    static const int32_t pass2Limit = 20;
2913
    int16_t oldCap = options::arithStandardCheckVarOrderPivots();
2914
    Options::current().arith.arithStandardCheckVarOrderPivots = pass2Limit;
2915
    SimplexDecisionProcedure& simplex = selectSimplex(false);
2916
    d_qflraStatus = simplex.findModel(false);
2917
    Options::current().arith.arithStandardCheckVarOrderPivots = oldCap;
2918
  }
2919
2920
  if(Debug.isOn("arith::importSolution")){
2921
    Debug("arith::importSolution") << "importSolution after " << d_qflraStatus << endl;
2922
    d_partialModel.printEntireModel(Debug("arith::importSolution"));
2923
  }
2924
}
2925
2926
1484869
bool TheoryArithPrivate::solveRelaxationOrPanic(Theory::Effort effortLevel)
2927
{
2928
  // if at this point the linear relaxation is still unknown,
2929
  //  attempt to branch an integer variable as a last ditch effort on full check
2930
1484869
  if (d_qflraStatus == Result::SAT_UNKNOWN)
2931
  {
2932
    d_qflraStatus = selectSimplex(true).findModel(false);
2933
  }
2934
2935
1484869
  if (Theory::fullEffort(effortLevel) && d_qflraStatus == Result::SAT_UNKNOWN)
2936
  {
2937
    ArithVar canBranch = nextIntegerViolation(false);
2938
    if (canBranch != ARITHVAR_SENTINEL)
2939
    {
2940
      ++d_statistics.d_panicBranches;
2941
      TrustNode branch = branchIntegerVariable(canBranch);
2942
      Assert(branch.getNode().getKind() == kind::OR);
2943
      Node rwbranch = Rewriter::rewrite(branch.getNode()[0]);
2944
      if (!isSatLiteral(rwbranch))
2945
      {
2946
        d_approxCuts.push_back(branch);
2947
        return true;
2948
      }
2949
    }
2950
    d_qflraStatus = selectSimplex(false).findModel(true);
2951
  }
2952
1484869
  return false;
2953
}
2954
2955
1484869
bool TheoryArithPrivate::solveRealRelaxation(Theory::Effort effortLevel){
2956
2969738
  TimerStat::CodeTimer codeTimer0(d_statistics.d_solveRealRelaxTimer);
2957
1484869
  Assert(d_qflraStatus != Result::SAT);
2958
2959
1484869
  d_partialModel.stopQueueingBoundCounts();
2960
2969738
  UpdateTrackingCallback utcb(&d_linEq);
2961
1484869
  d_partialModel.processBoundsQueue(utcb);
2962
1484869
  d_linEq.startTrackingBoundCounts();
2963
2964
2959267
  bool noPivotLimit = Theory::fullEffort(effortLevel) ||
2965
4433665
    !options::restrictedPivots();
2966
2967
1484869
  SimplexDecisionProcedure& simplex = selectSimplex(true);
2968
2969
1484869
  bool useApprox = options::useApprox() && ApproximateSimplex::enabled() && getSolveIntegerResource();
2970
2971
2969738
  Debug("TheoryArithPrivate::solveRealRelaxation")
2972
1484869
    << "solveRealRelaxation() approx"
2973
2969738
    << " " <<  options::useApprox()
2974
2969738
    << " " << ApproximateSimplex::enabled()
2975
1484869
    << " " << useApprox
2976
2969738
    << " " << safeToCallApprox()
2977
1484869
    << endl;
2978
2979
1484869
  bool noPivotLimitPass1 = noPivotLimit && !useApprox;
2980
1484869
  d_qflraStatus = simplex.findModel(noPivotLimitPass1);
2981
2982
2969738
  Debug("TheoryArithPrivate::solveRealRelaxation")
2983
1484869
    << "solveRealRelaxation()" << " pass1 " << d_qflraStatus << endl;
2984
2985
1484869
  if(d_qflraStatus == Result::SAT_UNKNOWN && useApprox && safeToCallApprox()){
2986
    // pass2: fancy-final
2987
    static const int32_t relaxationLimit = 10000;
2988
    Assert(ApproximateSimplex::enabled());
2989
2990
    TreeLog& tl = getTreeLog();
2991
    ApproximateStatistics& stats = getApproxStats();
2992
    ApproximateSimplex* approxSolver =
2993
      ApproximateSimplex::mkApproximateSimplexSolver(d_partialModel, tl, stats);
2994
2995
    approxSolver->setPivotLimit(relaxationLimit);
2996
2997
    if(!d_guessedCoeffSet){
2998
      d_guessedCoeffs = approxSolver->heuristicOptCoeffs();
2999
      d_guessedCoeffSet = true;
3000
    }
3001
    if(!d_guessedCoeffs.empty()){
3002
      approxSolver->setOptCoeffs(d_guessedCoeffs);
3003
    }
3004
3005
    ++d_statistics.d_relaxCalls;
3006
3007
    ApproximateSimplex::Solution relaxSolution;
3008
    LinResult relaxRes = LinUnknown;
3009
    {
3010
      TimerStat::CodeTimer codeTimer1(d_statistics.d_lpTimer);
3011
      relaxRes = approxSolver->solveRelaxation();
3012
    }
3013
      Debug("solveRealRelaxation") << "solve relaxation? " << endl;
3014
      switch(relaxRes){
3015
      case LinFeasible:
3016
        Debug("solveRealRelaxation") << "lin feasible? " << endl;
3017
        ++d_statistics.d_relaxLinFeas;
3018
        relaxSolution = approxSolver->extractRelaxation();
3019
        importSolution(relaxSolution);
3020
        if(d_qflraStatus != Result::SAT){
3021
          ++d_statistics.d_relaxLinFeasFailures;
3022
        }
3023
        break;
3024
      case LinInfeasible:
3025
        // todo attempt to recreate approximate conflict
3026
        ++d_statistics.d_relaxLinInfeas;
3027
        Debug("solveRealRelaxation") << "lin infeasible " << endl;
3028
        relaxSolution = approxSolver->extractRelaxation();
3029
        importSolution(relaxSolution);
3030
        if(d_qflraStatus != Result::UNSAT){
3031
          ++d_statistics.d_relaxLinInfeasFailures;
3032
        }
3033
        break;
3034
      case LinExhausted:
3035
        ++d_statistics.d_relaxLinExhausted;
3036
        Debug("solveRealRelaxation") << "exhuasted " << endl;
3037
        break;
3038
      case LinUnknown:
3039
      default:
3040
        ++d_statistics.d_relaxOthers;
3041
        break;
3042
      }
3043
    delete approxSolver;
3044
3045
  }
3046
3047
1484869
  bool emmittedConflictOrSplit = solveRelaxationOrPanic(effortLevel);
3048
3049
  // TODO Save zeroes with no conflicts
3050
1484869
  d_linEq.stopTrackingBoundCounts();
3051
1484869
  d_partialModel.startQueueingBoundCounts();
3052
3053
2969738
  return emmittedConflictOrSplit;
3054
}
3055
3056
bool TheoryArithPrivate::hasFreshArithLiteral(Node n) const{
3057
  switch(n.getKind()){
3058
  case kind::LEQ:
3059
  case kind::GEQ:
3060
  case kind::GT:
3061
  case kind::LT:
3062
    return !isSatLiteral(n);
3063
  case kind::EQUAL:
3064
    if(n[0].getType().isReal()){
3065
      return !isSatLiteral(n);
3066
    }else if(n[0].getType().isBoolean()){
3067
      return hasFreshArithLiteral(n[0]) ||
3068
        hasFreshArithLiteral(n[1]);
3069
    }else{
3070
      return false;
3071
    }
3072
  case kind::IMPLIES:
3073
    // try the rhs first
3074
    return hasFreshArithLiteral(n[1]) ||
3075
      hasFreshArithLiteral(n[0]);
3076
  default:
3077
    if(n.getType().isBoolean()){
3078
      for(Node::iterator ni=n.begin(), nend=n.end(); ni!=nend; ++ni){
3079
        Node child = *ni;
3080
        if(hasFreshArithLiteral(child)){
3081
          return true;
3082
        }
3083
      }
3084
    }
3085
    return false;
3086
  }
3087
}
3088
3089
1555531
bool TheoryArithPrivate::preCheck(Theory::Effort level)
3090
{
3091
1555531
  Assert(d_currentPropagationList.empty());
3092
1555531
  if(Debug.isOn("arith::consistency")){
3093
    Assert(unenqueuedVariablesAreConsistent());
3094
  }
3095
3096
1555531
  d_newFacts = !done();
3097
  // If d_previousStatus == SAT, then reverts on conflicts are safe
3098
  // Otherwise, they are not and must be committed.
3099
1555531
  d_previousStatus = d_qflraStatus;
3100
1555531
  if (d_newFacts)
3101
  {
3102
1493929
    d_qflraStatus = Result::SAT_UNKNOWN;
3103
1493929
    d_hasDoneWorkSinceCut = true;
3104
  }
3105
1555531
  return false;
3106
}
3107
3108
5576055
void TheoryArithPrivate::preNotifyFact(TNode atom, bool pol, TNode fact)
3109
{
3110
5576055
  ConstraintP curr = constraintFromFactQueue(fact);
3111
5576055
  if (curr != NullConstraint)
3112
  {
3113
5315950
    bool res CVC5_UNUSED = assertionCases(curr);
3114
5315950
    Assert(!res || anyConflict());
3115
  }
3116
5576055
}
3117
3118
1552518
bool TheoryArithPrivate::postCheck(Theory::Effort effortLevel)
3119
{
3120
1552518
  if(!anyConflict()){
3121
1758775
    while(!d_learnedBounds.empty()){
3122
      // we may attempt some constraints twice.  this is okay!
3123
109170
      ConstraintP curr = d_learnedBounds.front();
3124
109170
      d_learnedBounds.pop();
3125
109170
      Debug("arith::learned") << curr << endl;
3126
3127
109170
      bool res CVC5_UNUSED = assertionCases(curr);
3128
109170
      Assert(!res || anyConflict());
3129
3130
109170
      if(anyConflict()){ break; }
3131
    }
3132
  }
3133
3134
1552518
  if(anyConflict()){
3135
12029
    d_qflraStatus = Result::UNSAT;
3136
24058
    if (options::revertArithModels() && d_previousStatus == Result::SAT)
3137
    {
3138
      ++d_statistics.d_revertsOnConflicts;
3139
      Debug("arith::bt") << "clearing here "
3140
                         << " " << d_newFacts << " " << d_previousStatus << " "
3141
                         << d_qflraStatus << endl;
3142
      revertOutOfConflict();
3143
      d_errorSet.clear();
3144
    }else{
3145
12029
      ++d_statistics.d_commitsOnConflicts;
3146
24058
      Debug("arith::bt") << "committing here "
3147
12029
                         << " " << d_newFacts << " " << d_previousStatus << " "
3148
12029
                         << d_qflraStatus << endl;
3149
12029
      d_partialModel.commitAssignmentChanges();
3150
12029
      revertOutOfConflict();
3151
    }
3152
12029
    outputConflicts();
3153
    //cout << "unate conflict 1 " << effortLevel << std::endl;
3154
12029
    return true;
3155
  }
3156
3157
3158
1540489
  if(Debug.isOn("arith::print_assertions")) {
3159
    debugPrintAssertions(Debug("arith::print_assertions"));
3160
  }
3161
3162
1540489
  bool emmittedConflictOrSplit = false;
3163
1540489
  Assert(d_conflicts.empty());
3164
3165
1540489
  bool useSimplex = d_qflraStatus != Result::SAT;
3166
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3167
1540489
                      << "pre realRelax" << endl;
3168
3169
1540489
  if(useSimplex){
3170
1484869
    emmittedConflictOrSplit = solveRealRelaxation(effortLevel);
3171
  }
3172
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3173
1540489
                      << "post realRelax" << endl;
3174
3175
3176
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3177
1540489
                      << "pre solveInteger" << endl;
3178
3179
1540489
  if(attemptSolveInteger(effortLevel, emmittedConflictOrSplit)){
3180
    solveInteger(effortLevel);
3181
    if(anyConflict()){
3182
      ++d_statistics.d_commitsOnConflicts;
3183
      Debug("arith::bt") << "committing here "
3184
                         << " " << d_newFacts << " " << d_previousStatus << " "
3185
                         << d_qflraStatus << endl;
3186
      revertOutOfConflict();
3187
      d_errorSet.clear();
3188
      outputConflicts();
3189
      return true;
3190
    }
3191
  }
3192
3193
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3194
1540489
                      << "post solveInteger" << endl;
3195
3196
1540489
  switch(d_qflraStatus){
3197
1502643
  case Result::SAT:
3198
1502643
    if (d_newFacts)
3199
    {
3200
1444054
      ++d_statistics.d_nontrivialSatChecks;
3201
    }
3202
3203
3005286
    Debug("arith::bt") << "committing sap inConflit"
3204
1502643
                       << " " << d_newFacts << " " << d_previousStatus << " "
3205
1502643
                       << d_qflraStatus << endl;
3206
1502643
    d_partialModel.commitAssignmentChanges();
3207
1502643
    d_unknownsInARow = 0;
3208
1502643
    if(Debug.isOn("arith::consistency")){
3209
      Assert(entireStateIsConsistent("sat comit"));
3210
    }
3211
2987512
    if(useSimplex && options::collectPivots()){
3212
      if(options::useFC()){
3213
        d_statistics.d_satPivots << d_fcSimplex.getPivots();
3214
      }else{
3215
        d_statistics.d_satPivots << d_dualSimplex.getPivots();
3216
      }
3217
    }
3218
1502643
    break;
3219
  case Result::SAT_UNKNOWN:
3220
    ++d_unknownsInARow;
3221
    ++(d_statistics.d_unknownChecks);
3222
    Assert(!Theory::fullEffort(effortLevel));
3223
    Debug("arith::bt") << "committing unknown"
3224
                       << " " << d_newFacts << " " << d_previousStatus << " "
3225
                       << d_qflraStatus << endl;
3226
    d_partialModel.commitAssignmentChanges();
3227
    d_statistics.d_maxUnknownsInARow.maxAssign(d_unknownsInARow);
3228
3229
    if(useSimplex && options::collectPivots()){
3230
      if(options::useFC()){
3231
        d_statistics.d_unknownPivots << d_fcSimplex.getPivots();
3232
      }else{
3233
        d_statistics.d_unknownPivots << d_dualSimplex.getPivots();
3234
      }
3235
    }
3236
    break;
3237
37846
  case Result::UNSAT:
3238
37846
    d_unknownsInARow = 0;
3239
3240
37846
    ++d_statistics.d_commitsOnConflicts;
3241
3242
75692
    Debug("arith::bt") << "committing on conflict"
3243
37846
                       << " " << d_newFacts << " " << d_previousStatus << " "
3244
37846
                       << d_qflraStatus << endl;
3245
37846
    d_partialModel.commitAssignmentChanges();
3246
37846
    revertOutOfConflict();
3247
3248
37846
    if(Debug.isOn("arith::consistency::comitonconflict")){
3249
      entireStateIsConsistent("commit on conflict");
3250
    }
3251
37846
    outputConflicts();
3252
37846
    emmittedConflictOrSplit = true;
3253
37846
    Debug("arith::conflict") << "simplex conflict" << endl;
3254
3255
37846
    if(useSimplex && options::collectPivots()){
3256
      if(options::useFC()){
3257
        d_statistics.d_unsatPivots << d_fcSimplex.getPivots();
3258
      }else{
3259
        d_statistics.d_unsatPivots << d_dualSimplex.getPivots();
3260
      }
3261
    }
3262
37846
    break;
3263
  default:
3264
    Unimplemented();
3265
  }
3266
1540489
  d_statistics.d_avgUnknownsInARow << d_unknownsInARow;
3267
3268
  size_t nPivots =
3269
1540489
      options::useFC() ? d_fcSimplex.getPivots() : d_dualSimplex.getPivots();
3270
1739306
  for (std::size_t i = 0; i < nPivots; ++i)
3271
  {
3272
397634
    d_containing.d_out->spendResource(
3273
198817
        Resource::ArithPivotStep);
3274
  }
3275
3276
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3277
1540489
                      << "pre approx cuts" << endl;
3278
1540489
  if(!d_approxCuts.empty()){
3279
    bool anyFresh = false;
3280
    while(!d_approxCuts.empty()){
3281
      TrustNode lem = d_approxCuts.front();
3282
      d_approxCuts.pop();
3283
      Debug("arith::approx::cuts") << "approximate cut:" << lem << endl;
3284
      anyFresh = anyFresh || hasFreshArithLiteral(lem.getNode());
3285
      Debug("arith::lemma") << "approximate cut:" << lem << endl;
3286
      outputTrustedLemma(lem, InferenceId::ARITH_APPROX_CUT);
3287
    }
3288
    if(anyFresh){
3289
      emmittedConflictOrSplit = true;
3290
    }
3291
  }
3292
3293
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3294
1540489
                      << "post approx cuts" << endl;
3295
3296
  // This should be fine if sat or unknown
3297
3080978
  if (!emmittedConflictOrSplit
3298
10963818
      && (options::arithPropagationMode()
3299
              == options::ArithPropagationMode::UNATE_PROP
3300
1502643
          || options::arithPropagationMode()
3301
                 == options::ArithPropagationMode::BOTH_PROP))
3302
  {
3303
3005286
    TimerStat::CodeTimer codeTimer0(d_statistics.d_newPropTime);
3304
1502643
    Assert(d_qflraStatus != Result::UNSAT);
3305
3306
7303997
    while(!d_currentPropagationList.empty()  && !anyConflict()){
3307
2900677
      ConstraintP curr = d_currentPropagationList.front();
3308
2900677
      d_currentPropagationList.pop_front();
3309
3310
2900677
      ConstraintType t = curr->getType();
3311
2900677
      Assert(t != Disequality)
3312
          << "Disequalities are not allowed in d_currentPropagation";
3313
3314
2900677
      switch(t){
3315
1091329
      case LowerBound:
3316
        {
3317
1091329
          ConstraintP prev = d_currentPropagationList.front();
3318
1091329
          d_currentPropagationList.pop_front();
3319
1091329
          d_constraintDatabase.unatePropLowerBound(curr, prev);
3320
1091329
          break;
3321
        }
3322
964684
      case UpperBound:
3323
        {
3324
964684
          ConstraintP prev = d_currentPropagationList.front();
3325
964684
          d_currentPropagationList.pop_front();
3326
964684
          d_constraintDatabase.unatePropUpperBound(curr, prev);
3327
964684
          break;
3328
        }
3329
844664
      case Equality:
3330
        {
3331
844664
          ConstraintP prevLB = d_currentPropagationList.front();
3332
844664
          d_currentPropagationList.pop_front();
3333
844664
          ConstraintP prevUB = d_currentPropagationList.front();
3334
844664
          d_currentPropagationList.pop_front();
3335
844664
          d_constraintDatabase.unatePropEquality(curr, prevLB, prevUB);
3336
844664
          break;
3337
        }
3338
        default: Unhandled() << curr->getType();
3339
      }
3340
    }
3341
3342
1502643
    if(anyConflict()){
3343
      Debug("arith::unate") << "unate conflict" << endl;
3344
      revertOutOfConflict();
3345
      d_qflraStatus = Result::UNSAT;
3346
      outputConflicts();
3347
      emmittedConflictOrSplit = true;
3348
      //cout << "unate conflict " << endl;
3349
      Debug("arith::bt") << "committing on unate conflict"
3350
                         << " " << d_newFacts << " " << d_previousStatus << " "
3351
                         << d_qflraStatus << endl;
3352
3353
      Debug("arith::conflict") << "unate arith conflict" << endl;
3354
    }
3355
  }
3356
  else
3357
  {
3358
75692
    TimerStat::CodeTimer codeTimer1(d_statistics.d_newPropTime);
3359
37846
    d_currentPropagationList.clear();
3360
  }
3361
1540489
  Assert(d_currentPropagationList.empty());
3362
3363
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3364
1540489
                      << "post unate" << endl;
3365
3366
1540489
  if(!emmittedConflictOrSplit && Theory::fullEffort(effortLevel)){
3367
61052
    ++d_fullCheckCounter;
3368
  }
3369
1540489
  if(!emmittedConflictOrSplit && Theory::fullEffort(effortLevel)){
3370
61052
    emmittedConflictOrSplit = splitDisequalities();
3371
  }
3372
3080978
  Debug("arith::ems") << "ems: " << emmittedConflictOrSplit
3373
1540489
                      << "pos splitting" << endl;
3374
3375
3376
3080978
  Debug("arith") << "integer? "
3377
1540489
       << " conf/split " << emmittedConflictOrSplit
3378
3080978
       << " fulleffort " << Theory::fullEffort(effortLevel)
3379
1540489
       << " hasintmodel " << hasIntegerModel() << endl;
3380
3381
1540489
  if(!emmittedConflictOrSplit && Theory::fullEffort(effortLevel) && !hasIntegerModel()){
3382
5382
    Node possibleConflict = Node::null();
3383
7919
    if(!emmittedConflictOrSplit && options::arithDioSolver()){
3384
2691
      possibleConflict = callDioSolver();
3385
2691
      if(possibleConflict != Node::null()){
3386
154
        revertOutOfConflict();
3387
154
        Debug("arith::conflict") << "dio conflict   " << possibleConflict << endl;
3388
        // TODO (project #37): justify (proofs in the DIO solver)
3389
154
        raiseBlackBoxConflict(possibleConflict);
3390
154
        outputConflicts();
3391
154
        emmittedConflictOrSplit = true;
3392
      }
3393
    }
3394
3395
2691
    if(!emmittedConflictOrSplit && d_hasDoneWorkSinceCut && options::arithDioSolver()){
3396
2537
      if(getDioCuttingResource()){
3397
3766
        TrustNode possibleLemma = dioCutting();
3398
1883
        if(!possibleLemma.isNull()){
3399
1438
          d_hasDoneWorkSinceCut = false;
3400
1438
          d_cutCount = d_cutCount + 1;
3401
1438
          Debug("arith::lemma") << "dio cut   " << possibleLemma << endl;
3402
1438
          if (outputTrustedLemma(possibleLemma, InferenceId::ARITH_DIO_CUT))
3403
          {
3404
1438
            emmittedConflictOrSplit = true;
3405
          }
3406
        }
3407
      }
3408
    }
3409
3410
2691
    if(!emmittedConflictOrSplit) {
3411
2198
      TrustNode possibleLemma = roundRobinBranch();
3412
1099
      if (!possibleLemma.getNode().isNull())
3413
      {
3414
1099
        ++(d_statistics.d_externalBranchAndBounds);
3415
1099
        d_cutCount = d_cutCount + 1;
3416
2198
        Debug("arith::lemma") << "rrbranch lemma"
3417
1099
                              << possibleLemma << endl;
3418
1099
        if (outputTrustedLemma(possibleLemma, InferenceId::ARITH_BB_LEMMA))
3419
        {
3420
1097
          emmittedConflictOrSplit = true;
3421
        }
3422
      }
3423
    }
3424
3425
5382
    if(options::maxCutsInContext() <= d_cutCount){
3426
      if(d_diosolver.hasMoreDecompositionLemmas()){
3427
        while(d_diosolver.hasMoreDecompositionLemmas()){
3428
          Node decompositionLemma = d_diosolver.nextDecompositionLemma();
3429
          Debug("arith::lemma") << "dio decomposition lemma "
3430
                                << decompositionLemma << endl;
3431
          outputLemma(decompositionLemma, InferenceId::ARITH_DIO_DECOMPOSITION);
3432
        }
3433
      }else{
3434
        Debug("arith::restart") << "arith restart!" << endl;
3435
        outputRestart();
3436
      }
3437
    }
3438
  }//if !emmittedConflictOrSplit && fullEffort(effortLevel) && !hasIntegerModel()
3439
3440
1540489
  if(Theory::fullEffort(effortLevel)){
3441
66091
    if(Debug.isOn("arith::consistency::final")){
3442
      entireStateIsConsistent("arith::consistency::final");
3443
    }
3444
  }
3445
3446
1540489
  if(Debug.isOn("paranoid:check_tableau")){ d_linEq.debugCheckTableau(); }
3447
1540489
  if(Debug.isOn("arith::print_model")) {
3448
    debugPrintModel(Debug("arith::print_model"));
3449
  }
3450
1540489
  Debug("arith") << "TheoryArithPrivate::check end" << std::endl;
3451
1540489
  return emmittedConflictOrSplit;
3452
}
3453
3454
26328
bool TheoryArithPrivate::foundNonlinear() const { return d_foundNl; }
3455
3456
1099
TrustNode TheoryArithPrivate::branchIntegerVariable(ArithVar x) const
3457
{
3458
1099
  const DeltaRational& d = d_partialModel.getAssignment(x);
3459
1099
  Assert(!d.isIntegral());
3460
1099
  const Rational& r = d.getNoninfinitesimalPart();
3461
1099
  const Rational& i = d.getInfinitesimalPart();
3462
1099
  Trace("integers") << "integers: assignment to [[" << d_partialModel.asNode(x) << "]] is " << r << "[" << i << "]" << endl;
3463
1099
  Assert(!(r.getDenominator() == 1 && i.getNumerator() == 0));
3464
2198
  TNode var = d_partialModel.asNode(x);
3465
1099
  TrustNode lem = d_bab.branchIntegerVariable(var, r);
3466
1099
  if (Debug.isOn("integers"))
3467
  {
3468
    Node l = lem.getNode();
3469
    if (isSatLiteral(l[0]))
3470
    {
3471
      Debug("integers") << "    " << l[0] << " == " << getSatValue(l[0])
3472
                        << endl;
3473
    }
3474
    else
3475
    {
3476
      Debug("integers") << "    " << l[0] << " is not assigned a SAT literal"
3477
                        << endl;
3478
    }
3479
    if (isSatLiteral(l[1]))
3480
    {
3481
      Debug("integers") << "    " << l[1] << " == " << getSatValue(l[1])
3482
                        << endl;
3483
    }
3484
    else
3485
    {
3486
      Debug("integers") << "    " << l[1] << " is not assigned a SAT literal"
3487
                        << endl;
3488
    }
3489
  }
3490
2198
  return lem;
3491
}
3492
3493
std::vector<ArithVar> TheoryArithPrivate::cutAllBounded() const{
3494
  vector<ArithVar> lemmas;
3495
  ArithVar max = d_partialModel.getNumberOfVariables();
3496
3497
  if(options::doCutAllBounded() && max > 0){
3498
    for(ArithVar iter = 0; iter != max; ++iter){
3499
    //Do not include slack variables
3500
      const DeltaRational& d = d_partialModel.getAssignment(iter);
3501
      if(isIntegerInput(iter) &&
3502
         !d_cutInContext.contains(iter) &&
3503
         d_partialModel.hasUpperBound(iter) &&
3504
         d_partialModel.hasLowerBound(iter) &&
3505
         !d.isIntegral()){
3506
        lemmas.push_back(iter);
3507
      }
3508
    }
3509
  }
3510
  return lemmas;
3511
}
3512
3513
/** Returns true if the roundRobinBranching() issues a lemma. */
3514
1099
TrustNode TheoryArithPrivate::roundRobinBranch()
3515
{
3516
1099
  if(hasIntegerModel()){
3517
    return TrustNode::null();
3518
  }else{
3519
1099
    ArithVar v = d_nextIntegerCheckVar;
3520
3521
1099
    Assert(isInteger(v));
3522
1099
    Assert(!isAuxiliaryVariable(v));
3523
1099
    return branchIntegerVariable(v);
3524
  }
3525
}
3526
3527
61052
bool TheoryArithPrivate::splitDisequalities(){
3528
61052
  bool splitSomething = false;
3529
3530
122104
  vector<ConstraintP> save;
3531
3532
511912
  while(!d_diseqQueue.empty()){
3533
225430
    ConstraintP front = d_diseqQueue.front();
3534
225430
    d_diseqQueue.pop();
3535
3536
225430
    if(front->isSplit()){
3537
205
      Debug("arith::eq") << "split already" << endl;
3538
    }else{
3539
225225
      Debug("arith::eq") << "not split already" << endl;
3540
3541
225225
      ArithVar lhsVar = front->getVariable();
3542
3543
225225
      const DeltaRational& lhsValue = d_partialModel.getAssignment(lhsVar);
3544
225225
      const DeltaRational& rhsValue = front->getValue();
3545
225225
      if(lhsValue == rhsValue){
3546
215
        Debug("arith::lemma") << "Splitting on " << front << endl;
3547
215
        Debug("arith::lemma") << "LHS value = " << lhsValue << endl;
3548
215
        Debug("arith::lemma") << "RHS value = " << rhsValue << endl;
3549
430
        TrustNode lemma = front->split();
3550
215
        ++(d_statistics.d_statDisequalitySplits);
3551
3552
430
        Debug("arith::lemma")
3553
215
            << "Now " << Rewriter::rewrite(lemma.getNode()) << endl;
3554
215
        outputTrustedLemma(lemma, InferenceId::ARITH_SPLIT_DEQ);
3555
        //cout << "Now " << Rewriter::rewrite(lemma) << endl;
3556
215
        splitSomething = true;
3557
225010
      }else if(d_partialModel.strictlyLessThanLowerBound(lhsVar, rhsValue)){
3558
40911
        Debug("arith::eq") << "can drop as less than lb" << front << endl;
3559
184099
      }else if(d_partialModel.strictlyGreaterThanUpperBound(lhsVar, rhsValue)){
3560
19920
        Debug("arith::eq") << "can drop as greater than ub" << front << endl;
3561
      }else{
3562
164179
        Debug("arith::eq") << "save" << front << ": " <<lhsValue << " != " << rhsValue << endl;
3563
164179
        save.push_back(front);
3564
      }
3565
    }
3566
  }
3567
61052
  vector<ConstraintP>::const_iterator i=save.begin(), i_end = save.end();
3568
389410
  for(; i != i_end; ++i){
3569
164179
    d_diseqQueue.push(*i);
3570
  }
3571
122104
  return splitSomething;
3572
}
3573
3574
/**
3575
 * Should be guarded by at least Debug.isOn("arith::print_assertions").
3576
 * Prints to Debug("arith::print_assertions")
3577
 */
3578
void TheoryArithPrivate::debugPrintAssertions(std::ostream& out) const {
3579
  out << "Assertions:" << endl;
3580
  for (var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
3581
    ArithVar i = *vi;
3582
    if (d_partialModel.hasLowerBound(i)) {
3583
      ConstraintP lConstr = d_partialModel.getLowerBoundConstraint(i);
3584
      out << lConstr << endl;
3585
    }
3586
3587
    if (d_partialModel.hasUpperBound(i)) {
3588
      ConstraintP uConstr = d_partialModel.getUpperBoundConstraint(i);
3589
      out << uConstr << endl;
3590
    }
3591
  }
3592
  context::CDQueue<ConstraintP>::const_iterator it = d_diseqQueue.begin();
3593
  context::CDQueue<ConstraintP>::const_iterator it_end = d_diseqQueue.end();
3594
  for(; it != it_end; ++ it) {
3595
    out << *it << endl;
3596
  }
3597
}
3598
3599
void TheoryArithPrivate::debugPrintModel(std::ostream& out) const{
3600
  out << "Model:" << endl;
3601
  for (var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
3602
    ArithVar i = *vi;
3603
    if(d_partialModel.hasNode(i)){
3604
      out << d_partialModel.asNode(i) << " : " <<
3605
        d_partialModel.getAssignment(i);
3606
      if(d_tableau.isBasic(i)){
3607
        out << " (basic)";
3608
      }
3609
      out << endl;
3610
    }
3611
  }
3612
}
3613
3614
23387
TrustNode TheoryArithPrivate::explain(TNode n)
3615
{
3616
23387
  Debug("arith::explain") << "explain @" << getSatContext()->getLevel() << ": " << n << endl;
3617
3618
23387
  ConstraintP c = d_constraintDatabase.lookup(n);
3619
23387
  TrustNode exp;
3620
23387
  if(c != NullConstraint){
3621
9652
    Assert(!c->isAssumption());
3622
9652
    exp = c->externalExplainForPropagation(n);
3623
9652
    Debug("arith::explain") << "constraint explanation" << n << ":" << exp << endl;
3624
13735
  }else if(d_assertionsThatDoNotMatchTheirLiterals.find(n) != d_assertionsThatDoNotMatchTheirLiterals.end()){
3625
10563
    c = d_assertionsThatDoNotMatchTheirLiterals[n];
3626
10563
    if(!c->isAssumption()){
3627
3951
      exp = c->externalExplainForPropagation(n);
3628
3951
      Debug("arith::explain") << "assertions explanation" << n << ":" << exp << endl;
3629
    }else{
3630
6612
      Debug("arith::explain") << "this is a strange mismatch" << n << endl;
3631
6612
      Assert(d_congruenceManager.canExplain(n));
3632
6612
      exp = d_congruenceManager.explain(n);
3633
    }
3634
  }else{
3635
3172
    Assert(d_congruenceManager.canExplain(n));
3636
3172
    Debug("arith::explain") << "dm explanation" << n << endl;
3637
3172
    exp = d_congruenceManager.explain(n);
3638
  }
3639
23387
  return exp;
3640
}
3641
3642
2484343
void TheoryArithPrivate::propagate(Theory::Effort e) {
3643
  // This uses model values for safety. Disable for now.
3644
4968686
  if (d_qflraStatus == Result::SAT
3645
2457700
      && (options::arithPropagationMode()
3646
              == options::ArithPropagationMode::BOUND_INFERENCE_PROP
3647
2457700
          || options::arithPropagationMode()
3648
                 == options::ArithPropagationMode::BOTH_PROP)
3649
4942043
      && hasAnyUpdates())
3650
  {
3651
1925600
    if(options::newProp()){
3652
960248
      propagateCandidatesNew();
3653
    }else{
3654
2552
      propagateCandidates();
3655
    }
3656
  }
3657
  else
3658
  {
3659
1521543
    clearUpdates();
3660
  }
3661
3662
3813935
  while(d_constraintDatabase.hasMorePropagations()){
3663
664796
    ConstraintCP c = d_constraintDatabase.nextPropagation();
3664
664796
    Debug("arith::prop") << "next prop" << getSatContext()->getLevel() << ": " << c << endl;
3665
3666
664796
    if(c->negationHasProof()){
3667
      Debug("arith::prop") << "negation has proof " << c->getNegation() << endl;
3668
      Debug("arith::prop") << c->getNegation()->externalExplainByAssertions()
3669
                           << endl;
3670
    }
3671
664796
    Assert(!c->negationHasProof())
3672
        << "A constraint has been propagated on the constraint propagation "
3673
           "queue, but the negation has been set to true.  Contact Tim now!";
3674
3675
664796
    if(!c->assertedToTheTheory()){
3676
1291734
      Node literal = c->getLiteral();
3677
645867
      Debug("arith::prop") << "propagating @" << getSatContext()->getLevel() << " " << literal << endl;
3678
3679
645867
      outputPropagate(literal);
3680
    }else{
3681
18929
      Debug("arith::prop") << "already asserted to the theory " <<  c->getLiteral() << endl;
3682
    }
3683
  }
3684
3685
3747157
  while(d_congruenceManager.hasMorePropagations()){
3686
1262814
    TNode toProp = d_congruenceManager.getNextPropagation();
3687
3688
    //Currently if the flag is set this came from an equality detected by the
3689
    //equality engine in the the difference manager.
3690
1262814
    Node normalized = Rewriter::rewrite(toProp);
3691
3692
631407
    ConstraintP constraint = d_constraintDatabase.lookup(normalized);
3693
631407
    if(constraint == NullConstraint){
3694
147
      Debug("arith::prop") << "propagating on non-constraint? "  << toProp << endl;
3695
3696
147
      outputPropagate(toProp);
3697
631260
    }else if(constraint->negationHasProof()){
3698
      // The congruence manager can prove: antecedents => toProp,
3699
      // ergo. antecedents ^ ~toProp is a conflict.
3700
      TrustNode exp = d_congruenceManager.explain(toProp);
3701
      Node notNormalized = normalized.negate();
3702
      std::vector<Node> ants(exp.getNode().begin(), exp.getNode().end());
3703
      ants.push_back(notNormalized);
3704
      Node lp = safeConstructNary(kind::AND, ants);
3705
      Debug("arith::prop") << "propagate conflict" <<  lp << endl;
3706
      if (proofsEnabled())
3707
      {
3708
        // Assume all of antecedents and ~toProp (rewritten)
3709
        std::vector<Pf> pfAntList;
3710
        for (size_t i = 0; i < ants.size(); ++i)
3711
        {
3712
          pfAntList.push_back(d_pnm->mkAssume(ants[i]));
3713
        }
3714
        Pf pfAnt = pfAntList.size() > 1
3715
                       ? d_pnm->mkNode(PfRule::AND_INTRO, pfAntList, {})
3716
                       : pfAntList[0];
3717
        // Use modus ponens to get toProp (un rewritten)
3718
        Pf pfConc = d_pnm->mkNode(
3719
            PfRule::MODUS_PONENS,
3720
            {pfAnt, exp.getGenerator()->getProofFor(exp.getProven())},
3721
            {});
3722
        // prove toProp (rewritten)
3723
        Pf pfConcRewritten = d_pnm->mkNode(
3724
            PfRule::MACRO_SR_PRED_TRANSFORM, {pfConc}, {normalized});
3725
        Pf pfNotNormalized = d_pnm->mkAssume(notNormalized);
3726
        // prove bottom from toProp and ~toProp
3727
        Pf pfBot;
3728
        if (normalized.getKind() == kind::NOT)
3729
        {
3730
          pfBot = d_pnm->mkNode(
3731
              PfRule::CONTRA, {pfNotNormalized, pfConcRewritten}, {});
3732
        }
3733
        else
3734
        {
3735
          pfBot = d_pnm->mkNode(
3736
              PfRule::CONTRA, {pfConcRewritten, pfNotNormalized}, {});
3737
        }
3738
        // close scope
3739
        Pf pfNotAnd = d_pnm->mkScope(pfBot, ants);
3740
        raiseBlackBoxConflict(lp, pfNotAnd);
3741
      }
3742
      else
3743
      {
3744
        raiseBlackBoxConflict(lp);
3745
      }
3746
      outputConflicts();
3747
      return;
3748
    }else{
3749
631260
      Debug("arith::prop") << "propagating still?" <<  toProp << endl;
3750
631260
      outputPropagate(toProp);
3751
    }
3752
  }
3753
}
3754
3755
5316446
DeltaRational TheoryArithPrivate::getDeltaValue(TNode term) const
3756
{
3757
5316446
  AlwaysAssert(d_qflraStatus != Result::SAT_UNKNOWN);
3758
5316446
  Debug("arith::value") << term << std::endl;
3759
3760
5316446
  if (d_partialModel.hasArithVar(term)) {
3761
1673523
    ArithVar var = d_partialModel.asArithVar(term);
3762
1673523
    return d_partialModel.getAssignment(var);
3763
  }
3764
3765
3642923
  switch (Kind kind = term.getKind()) {
3766
2028549
    case kind::CONST_RATIONAL:
3767
2028549
      return term.getConst<Rational>();
3768
3769
1164452
    case kind::PLUS: {  // 2+ args
3770
2328904
      DeltaRational value(0);
3771
3759964
      for (TNode::iterator i = term.begin(), iend = term.end(); i != iend;
3772
           ++i) {
3773
2595512
        value = value + getDeltaValue(*i);
3774
      }
3775
1164452
      return value;
3776
    }
3777
3778
449922
    case kind::NONLINEAR_MULT:
3779
    case kind::MULT: {  // 2+ args
3780
449922
      Assert(!isSetup(term));
3781
899844
      DeltaRational value(1);
3782
1349766
      for (TNode::iterator i = term.begin(), iend = term.end(); i != iend;
3783
           ++i) {
3784
899844
        value = value * getDeltaValue(*i);
3785
      }
3786
449922
      return value;
3787
    }
3788
    case kind::MINUS: {  // 2 args
3789
      return getDeltaValue(term[0]) - getDeltaValue(term[1]);
3790
    }
3791
    case kind::UMINUS: {  // 1 arg
3792
      return (-getDeltaValue(term[0]));
3793
    }
3794
3795
    case kind::DIVISION: {  // 2 args
3796
      Assert(!isSetup(term));
3797
      return getDeltaValue(term[0]) / getDeltaValue(term[1]);
3798
    }
3799
    case kind::DIVISION_TOTAL:
3800
    case kind::INTS_DIVISION_TOTAL:
3801
    case kind::INTS_MODULUS_TOTAL: {  // 2 args
3802
      Assert(!isSetup(term));
3803
      DeltaRational denominator = getDeltaValue(term[1]);
3804
      if (denominator.isZero()) {
3805
        return DeltaRational(0, 0);
3806
      }
3807
      DeltaRational numerator = getDeltaValue(term[0]);
3808
      if (kind == kind::DIVISION_TOTAL) {
3809
        return numerator / denominator;
3810
      } else if (kind == kind::INTS_DIVISION_TOTAL) {
3811
        return Rational(numerator.euclidianDivideQuotient(denominator));
3812
      } else {
3813
        Assert(kind == kind::INTS_MODULUS_TOTAL);
3814
        return Rational(numerator.euclidianDivideRemainder(denominator));
3815
      }
3816
    }
3817
3818
    default:
3819
      throw ModelException(term, "No model assignment.");
3820
  }
3821
}
3822
3823
12708
Rational TheoryArithPrivate::deltaValueForTotalOrder() const{
3824
25416
  Rational min(2);
3825
25416
  std::set<DeltaRational> relevantDeltaValues;
3826
12708
  context::CDQueue<ConstraintP>::const_iterator qiter = d_diseqQueue.begin();
3827
12708
  context::CDQueue<ConstraintP>::const_iterator qiter_end = d_diseqQueue.end();
3828
3829
64154
  for(; qiter != qiter_end; ++qiter){
3830
25723
    ConstraintP curr = *qiter;
3831
3832
25723
    const DeltaRational& rhsValue = curr->getValue();
3833
25723
    relevantDeltaValues.insert(rhsValue);
3834
  }
3835
3836
12708
  Theory::shared_terms_iterator shared_iter = d_containing.shared_terms_begin();
3837
12708
  Theory::shared_terms_iterator shared_end = d_containing.shared_terms_end();
3838
529312
  for(; shared_iter != shared_end; ++shared_iter){
3839
516604
    Node sharedCurr = *shared_iter;
3840
3841
    // ModelException is fatal as this point. Don't catch!
3842
    // DeltaRationalException is fatal as this point. Don't catch!
3843
516604
    DeltaRational val = getDeltaValue(sharedCurr);
3844
258302
    relevantDeltaValues.insert(val);
3845
  }
3846
3847
596090
  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
3848
583382
    ArithVar v = *vi;
3849
583382
    const DeltaRational& value = d_partialModel.getAssignment(v);
3850
583382
    relevantDeltaValues.insert(value);
3851
583382
    if( d_partialModel.hasLowerBound(v)){
3852
349954
      const DeltaRational& lb = d_partialModel.getLowerBound(v);
3853
349954
      relevantDeltaValues.insert(lb);
3854
    }
3855
583382
    if( d_partialModel.hasUpperBound(v)){
3856
282730
      const DeltaRational& ub = d_partialModel.getUpperBound(v);
3857
282730
      relevantDeltaValues.insert(ub);
3858
    }
3859
  }
3860
3861
12708
  if(relevantDeltaValues.size() >= 2){
3862
10823
    std::set<DeltaRational>::const_iterator iter = relevantDeltaValues.begin();
3863
10823
    std::set<DeltaRational>::const_iterator iter_end = relevantDeltaValues.end();
3864
21646
    DeltaRational prev = *iter;
3865
10823
    ++iter;
3866
277523
    for(; iter != iter_end; ++iter){
3867
133350
      const DeltaRational& curr = *iter;
3868
3869
133350
      Assert(prev < curr);
3870
3871
133350
      DeltaRational::seperatingDelta(min, prev, curr);
3872
133350
      prev = curr;
3873
    }
3874
  }
3875
3876
12708
  Assert(min.sgn() > 0);
3877
12708
  Rational belowMin = min/Rational(2);
3878
25416
  return belowMin;
3879
}
3880
3881
14565
void TheoryArithPrivate::collectModelValues(const std::set<Node>& termSet,
3882
                                            std::map<Node, Node>& arithModel)
3883
{
3884
14565
  AlwaysAssert(d_qflraStatus == Result::SAT);
3885
3886
14565
  if(Debug.isOn("arith::collectModelInfo")){
3887
    debugPrintFacts();
3888
  }
3889
3890
14565
  Debug("arith::collectModelInfo") << "collectModelInfo() begin " << endl;
3891
3892
  // Delta lasts at least the duration of the function call
3893
14565
  const Rational& delta = d_partialModel.getDelta();
3894
29130
  std::unordered_set<TNode> shared = d_containing.currentlySharedTerms();
3895
3896
  // TODO:
3897
  // This is not very good for user push/pop....
3898
  // Revisit when implementing push/pop
3899
593256
  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
3900
578691
    ArithVar v = *vi;
3901
3902
578691
    if(!isAuxiliaryVariable(v)){
3903
505054
      Node term = d_partialModel.asNode(v);
3904
3905
929434
      if((theoryOf(term) == THEORY_ARITH || shared.find(term) != shared.end())
3906
1004968
         && termSet.find(term) != termSet.end()){
3907
3908
241443
        const DeltaRational& mod = d_partialModel.getAssignment(v);
3909
482886
        Rational qmodel = mod.substituteDelta(delta);
3910
3911
482886
        Node qNode = mkRationalNode(qmodel);
3912
241443
        Debug("arith::collectModelInfo") << "m->assertEquality(" << term << ", " << qmodel << ", true)" << endl;
3913
        // Add to the map
3914
241443
        arithModel[term] = qNode;
3915
      }else{
3916
11084
        Debug("arith::collectModelInfo") << "Skipping m->assertEquality(" << term << ", true)" << endl;
3917
3918
      }
3919
    }
3920
  }
3921
3922
  // Iterate over equivalence classes in LinearEqualityModule
3923
  // const eq::EqualityEngine& ee = d_congruenceManager.getEqualityEngine();
3924
  // m->assertEqualityEngine(&ee);
3925
3926
14565
  Debug("arith::collectModelInfo") << "collectModelInfo() end " << endl;
3927
14565
}
3928
3929
bool TheoryArithPrivate::safeToReset() const {
3930
  Assert(!d_tableauSizeHasBeenModified);
3931
  Assert(d_errorSet.noSignals());
3932
3933
  ErrorSet::error_iterator error_iter = d_errorSet.errorBegin();
3934
  ErrorSet::error_iterator error_end = d_errorSet.errorEnd();
3935
  for(; error_iter != error_end; ++error_iter){
3936
    ArithVar basic = *error_iter;
3937
    if(!d_smallTableauCopy.isBasic(basic)){
3938
      return false;
3939
    }
3940
  }
3941
3942
  return true;
3943
}
3944
3945
1748
void TheoryArithPrivate::notifyRestart(){
3946
3496
  TimerStat::CodeTimer codeTimer(d_statistics.d_restartTimer);
3947
3948
1748
  if(Debug.isOn("paranoid:check_tableau")){ d_linEq.debugCheckTableau(); }
3949
3950
1748
  ++d_restartsCounter;
3951
1748
  d_solveIntMaybeHelp = 0;
3952
1748
  d_solveIntAttempts = 0;
3953
1748
}
3954
3955
bool TheoryArithPrivate::entireStateIsConsistent(const string& s){
3956
  bool result = true;
3957
  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
3958
    ArithVar var = *vi;
3959
    //ArithVar var = d_partialModel.asArithVar(*i);
3960
    if(!d_partialModel.assignmentIsConsistent(var)){
3961
      d_partialModel.printModel(var);
3962
      Warning() << s << ":" << "Assignment is not consistent for " << var << d_partialModel.asNode(var);
3963
      if(d_tableau.isBasic(var)){
3964
        Warning() << " (basic)";
3965
      }
3966
      Warning() << endl;
3967
      result = false;
3968
    }else if(d_partialModel.isInteger(var) && !d_partialModel.integralAssignment(var)){
3969
      d_partialModel.printModel(var);
3970
      Warning() << s << ":" << "Assignment is not integer for integer variable " << var << d_partialModel.asNode(var);
3971
      if(d_tableau.isBasic(var)){
3972
        Warning() << " (basic)";
3973
      }
3974
      Warning() << endl;
3975
      result = false;
3976
    }
3977
  }
3978
  return result;
3979
}
3980
3981
bool TheoryArithPrivate::unenqueuedVariablesAreConsistent(){
3982
  bool result = true;
3983
  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
3984
    ArithVar var = *vi;
3985
    if(!d_partialModel.assignmentIsConsistent(var)){
3986
      if(!d_errorSet.inError(var)){
3987
3988
        d_partialModel.printModel(var);
3989
        Warning() << "Unenqueued var is not consistent for " << var <<  d_partialModel.asNode(var);
3990
        if(d_tableau.isBasic(var)){
3991
          Warning() << " (basic)";
3992
        }
3993
        Warning() << endl;
3994
        result = false;
3995
      } else if(Debug.isOn("arith::consistency::initial")){
3996
        d_partialModel.printModel(var);
3997
        Warning() << "Initial var is not consistent for " << var <<  d_partialModel.asNode(var);
3998
        if(d_tableau.isBasic(var)){
3999
          Warning() << " (basic)";
4000
        }
4001
        Warning() << endl;
4002
      }
4003
     }
4004
  }
4005
  return result;
4006
}
4007
4008
15189
void TheoryArithPrivate::presolve(){
4009
30378
  TimerStat::CodeTimer codeTimer(d_statistics.d_presolveTime);
4010
4011
15189
  d_statistics.d_initialTableauSize = d_tableau.size();
4012
4013
15189
  if(Debug.isOn("paranoid:check_tableau")){ d_linEq.debugCheckTableau(); }
4014
4015
  static thread_local unsigned callCount = 0;
4016
15189
  if(Debug.isOn("arith::presolve")) {
4017
    Debug("arith::presolve") << "TheoryArithPrivate::presolve #" << callCount << endl;
4018
    callCount = callCount + 1;
4019
  }
4020
4021
30378
  vector<TrustNode> lemmas;
4022
15189
  if(!options::incrementalSolving()) {
4023
15238
    switch(options::arithUnateLemmaMode()){
4024
      case options::ArithUnateLemmaMode::NO: break;
4025
      case options::ArithUnateLemmaMode::INEQUALITY:
4026
        d_constraintDatabase.outputUnateInequalityLemmas(lemmas);
4027
        break;
4028
      case options::ArithUnateLemmaMode::EQUALITY:
4029
        d_constraintDatabase.outputUnateEqualityLemmas(lemmas);
4030
        break;
4031
7619
      case options::ArithUnateLemmaMode::ALL:
4032
7619
        d_constraintDatabase.outputUnateInequalityLemmas(lemmas);
4033
7619
        d_constraintDatabase.outputUnateEqualityLemmas(lemmas);
4034
7619
        break;
4035
      default: Unhandled() << options::arithUnateLemmaMode();
4036
    }
4037
  }
4038
4039
15189
  vector<TrustNode>::const_iterator i = lemmas.begin(), i_end = lemmas.end();
4040
95379
  for(; i != i_end; ++i){
4041
80190
    TrustNode lem = *i;
4042
40095
    Debug("arith::oldprop") << " lemma lemma duck " <<lem << endl;
4043
40095
    outputTrustedLemma(lem, InferenceId::ARITH_UNATE);
4044
  }
4045
15189
}
4046
4047
779969
EqualityStatus TheoryArithPrivate::getEqualityStatus(TNode a, TNode b) {
4048
779969
  if(d_qflraStatus == Result::SAT_UNKNOWN){
4049
    return EQUALITY_UNKNOWN;
4050
  }else{
4051
    try {
4052
779969
      if (getDeltaValue(a) == getDeltaValue(b)) {
4053
73577
        return EQUALITY_TRUE_IN_MODEL;
4054
      } else {
4055
706392
        return EQUALITY_FALSE_IN_MODEL;
4056
      }
4057
    } catch (DeltaRationalException& dr) {
4058
      return EQUALITY_UNKNOWN;
4059
    } catch (ModelException& me) {
4060
      return EQUALITY_UNKNOWN;
4061
    }
4062
  }
4063
}
4064
4065
1746
bool TheoryArithPrivate::propagateCandidateBound(ArithVar basic, bool upperBound){
4066
1746
  ++d_statistics.d_boundComputations;
4067
4068
1746
  RowIndex ridx = d_tableau.basicToRowIndex(basic);
4069
3492
  DeltaRational bound = d_linEq.computeRowBound(ridx, upperBound, basic);
4070
4071
4504
  if((upperBound && d_partialModel.strictlyLessThanUpperBound(basic, bound)) ||
4072
2048
     (!upperBound && d_partialModel.strictlyGreaterThanLowerBound(basic, bound))){
4073
4074
    // TODO: "Policy point"
4075
    //We are only going to recreate the functionality for now.
4076
    //In the future this can be improved to generate a temporary constraint
4077
    //if none exists.
4078
    //Experiment with doing this every time or only when the new constraint
4079
    //implies an unknown fact.
4080
4081
1730
    ConstraintType t = upperBound ? UpperBound : LowerBound;
4082
1730
    ConstraintP bestImplied = d_constraintDatabase.getBestImpliedBound(basic, t, bound);
4083
4084
    // Node bestImplied = upperBound ?
4085
    //   d_apm.getBestImpliedUpperBound(basic, bound):
4086
    //   d_apm.getBestImpliedLowerBound(basic, bound);
4087
4088
1730
    if(bestImplied != NullConstraint){
4089
      //This should be stronger
4090
1272
      Assert(!upperBound || bound <= bestImplied->getValue());
4091
1272
      Assert(
4092
          !upperBound
4093
          || d_partialModel.lessThanUpperBound(basic, bestImplied->getValue()));
4094
4095
1272
      Assert(upperBound || bound >= bestImplied->getValue());
4096
1272
      Assert(upperBound
4097
             || d_partialModel.greaterThanLowerBound(basic,
4098
                                                     bestImplied->getValue()));
4099
      //slightly changed
4100
4101
      // ConstraintP c = d_constraintDatabase.lookup(bestImplied);
4102
      // Assert(c != NullConstraint);
4103
4104
1272
      bool assertedToTheTheory = bestImplied->assertedToTheTheory();
4105
1272
      bool canBePropagated = bestImplied->canBePropagated();
4106
1272
      bool hasProof = bestImplied->hasProof();
4107
4108
2544
      Debug("arith::prop") << "arith::prop" << basic
4109
1272
                           << " " << assertedToTheTheory
4110
1272
                           << " " << canBePropagated
4111
1272
                           << " " << hasProof
4112
1272
                           << endl;
4113
4114
1272
      if(bestImplied->negationHasProof()){
4115
        Warning() << "the negation of " <<  bestImplied << " : " << endl
4116
                  << "has proof " << bestImplied->getNegation() << endl
4117
                  << bestImplied->getNegation()->externalExplainByAssertions()
4118
                  << endl;
4119
      }
4120
4121
1272
      if(!assertedToTheTheory && canBePropagated && !hasProof ){
4122
232
        d_linEq.propagateBasicFromRow(bestImplied);
4123
        // I think this can be skipped if canBePropagated is true
4124
        //d_learnedBounds.push(bestImplied);
4125
232
        if(Debug.isOn("arith::prop")){
4126
          Debug("arith::prop") << "success " << bestImplied << endl;
4127
          d_partialModel.printModel(basic, Debug("arith::prop"));
4128
        }
4129
232
        return true;
4130
      }
4131
1040
      if(Debug.isOn("arith::prop")){
4132
        Debug("arith::prop") << "failed " << basic
4133
                             << " " << bound
4134
                             << " " << assertedToTheTheory
4135
                             << " " << canBePropagated
4136
                             << " " << hasProof << endl;
4137
        d_partialModel.printModel(basic, Debug("arith::prop"));
4138
      }
4139
    }
4140
16
  }else if(Debug.isOn("arith::prop")){
4141
    Debug("arith::prop") << "false " << bound << " ";
4142
    d_partialModel.printModel(basic, Debug("arith::prop"));
4143
  }
4144
1514
  return false;
4145
}
4146
4147
4434
void TheoryArithPrivate::propagateCandidate(ArithVar basic){
4148
4434
  bool success = false;
4149
4434
  RowIndex ridx = d_tableau.basicToRowIndex(basic);
4150
4151
  bool tryLowerBound =
4152
8480
    d_partialModel.strictlyAboveLowerBound(basic) &&
4153
8480
    d_linEq.rowLacksBound(ridx, false, basic) == NULL;
4154
4155
  bool tryUpperBound =
4156
8446
    d_partialModel.strictlyBelowUpperBound(basic) &&
4157
8446
    d_linEq.rowLacksBound(ridx, true, basic) == NULL;
4158
4159
4434
  if(tryLowerBound){
4160
1020
    success |= propagateCandidateLowerBound(basic);
4161
  }
4162
4434
  if(tryUpperBound){
4163
726
    success |= propagateCandidateUpperBound(basic);
4164
  }
4165
4434
  if(success){
4166
226
    ++d_statistics.d_boundPropagations;
4167
  }
4168
4434
}
4169
4170
2552
void TheoryArithPrivate::propagateCandidates(){
4171
5104
  TimerStat::CodeTimer codeTimer(d_statistics.d_boundComputationTime);
4172
4173
2552
  Debug("arith::prop") << "propagateCandidates begin" << endl;
4174
4175
2552
  Assert(d_candidateBasics.empty());
4176
4177
2552
  if(d_updatedBounds.empty()){ return; }
4178
4179
2552
  DenseSet::const_iterator i = d_updatedBounds.begin();
4180
2552
  DenseSet::const_iterator end = d_updatedBounds.end();
4181
9200
  for(; i != end; ++i){
4182
3324
    ArithVar var = *i;
4183
4098
    if(d_tableau.isBasic(var) &&
4184
10286392
       d_tableau.basicRowLength(var) <= options::arithPropagateMaxLength()){
4185
702
      d_candidateBasics.softAdd(var);
4186
    }else{
4187
2622
      Tableau::ColIterator basicIter = d_tableau.colIterator(var);
4188
15002
      for(; !basicIter.atEnd(); ++basicIter){
4189
6190
        const Tableau::Entry& entry = *basicIter;
4190
6190
        RowIndex ridx = entry.getRowIndex();
4191
6190
        ArithVar rowVar = d_tableau.rowIndexToBasic(ridx);
4192
6190
        Assert(entry.getColVar() == var);
4193
6190
        Assert(d_tableau.isBasic(rowVar));
4194
6190
        if(d_tableau.getRowLength(ridx) <= options::arithPropagateMaxLength()){
4195
4576
          d_candidateBasics.softAdd(rowVar);
4196
        }
4197
      }
4198
    }
4199
  }
4200
2552
  d_updatedBounds.purge();
4201
4202
11420
  while(!d_candidateBasics.empty()){
4203
4434
    ArithVar candidate = d_candidateBasics.back();
4204
4434
    d_candidateBasics.pop_back();
4205
4434
    Assert(d_tableau.isBasic(candidate));
4206
4434
    propagateCandidate(candidate);
4207
  }
4208
2552
  Debug("arith::prop") << "propagateCandidates end" << endl << endl << endl;
4209
}
4210
4211
960248
void TheoryArithPrivate::propagateCandidatesNew(){
4212
  /* Four criteria must be met for progagation on a variable to happen using a row:
4213
   * 0: A new bound has to have been added to the row.
4214
   * 1: The hasBoundsCount for the row must be "full" or be full minus one variable
4215
   *    (This is O(1) to check, but requires book keeping.)
4216
   * 2: The current assignment must be strictly smaller/greater than the current bound.
4217
   *    assign(x) < upper(x)
4218
   *    (This is O(1) to compute.)
4219
   * 3: There is a bound that is strictly smaller/greater than the current assignment.
4220
   *    assign(x) < c for some x <= c literal
4221
   *    (This is O(log n) to compute.)
4222
   * 4: The implied bound on x is strictly smaller/greater than the current bound.
4223
   *    (This is O(n) to compute.)
4224
   */
4225
4226
1920496
  TimerStat::CodeTimer codeTimer(d_statistics.d_boundComputationTime);
4227
960248
  Debug("arith::prop") << "propagateCandidatesNew begin" << endl;
4228
4229
960248
  Assert(d_qflraStatus == Result::SAT);
4230
960248
  if(d_updatedBounds.empty()){ return; }
4231
960248
  dumpUpdatedBoundsToRows();
4232
960248
  Assert(d_updatedBounds.empty());
4233
4234
960248
  if(!d_candidateRows.empty()){
4235
1820302
    UpdateTrackingCallback utcb(&d_linEq);
4236
910151
    d_partialModel.processBoundsQueue(utcb);
4237
  }
4238
4239
18433794
  while(!d_candidateRows.empty()){
4240
8736773
    RowIndex candidate = d_candidateRows.back();
4241
8736773
    d_candidateRows.pop_back();
4242
8736773
    propagateCandidateRow(candidate);
4243
  }
4244
960248
  Debug("arith::prop") << "propagateCandidatesNew end" << endl << endl << endl;
4245
}
4246
4247
14872833
bool TheoryArithPrivate::propagateMightSucceed(ArithVar v, bool ub) const{
4248
22500201
  int cmp = ub ? d_partialModel.cmpAssignmentUpperBound(v)
4249
22500201
    : d_partialModel.cmpAssignmentLowerBound(v);
4250
14872833
  bool hasSlack = ub ? cmp < 0 : cmp > 0;
4251
14872833
  if(hasSlack){
4252
7182010
    ConstraintType t = ub ? UpperBound : LowerBound;
4253
7182010
    const DeltaRational& a = d_partialModel.getAssignment(v);
4254
4255
7182010
    if(isInteger(v) && !a.isIntegral()){
4256
60913
      return true;
4257
    }
4258
4259
7121097
    ConstraintP strongestPossible = d_constraintDatabase.getBestImpliedBound(v, t, a);
4260
7121097
    if(strongestPossible == NullConstraint){
4261
4391039
      return false;
4262
    }else{
4263
2730058
      bool assertedToTheTheory = strongestPossible->assertedToTheTheory();
4264
2730058
      bool canBePropagated = strongestPossible->canBePropagated();
4265
2730058
      bool hasProof = strongestPossible->hasProof();
4266
4267
2730058
      return !assertedToTheTheory && canBePropagated && !hasProof;
4268
    }
4269
  }else{
4270
7690823
    return false;
4271
  }
4272
}
4273
4274
3728359
bool TheoryArithPrivate::attemptSingleton(RowIndex ridx, bool rowUp){
4275
3728359
  Debug("arith::prop") << "  attemptSingleton" << ridx;
4276
4277
  const Tableau::Entry* ep;
4278
3728359
  ep = d_linEq.rowLacksBound(ridx, rowUp, ARITHVAR_SENTINEL);
4279
3728359
  Assert(ep != NULL);
4280
4281
3728359
  ArithVar v = ep->getColVar();
4282
3728359
  const Rational& coeff = ep->getCoefficient();
4283
4284
  // 0 = c * v + \sum rest
4285
  // Suppose rowUp
4286
  // - c * v = \sum rest \leq D
4287
  // if c > 0, v \geq -D/c so !vUp
4288
  // if c < 0, v \leq -D/c so  vUp
4289
  // Suppose not rowUp
4290
  // - c * v = \sum rest \geq D
4291
  // if c > 0, v \leq -D/c so  vUp
4292
  // if c < 0, v \geq -D/c so !vUp
4293
3728359
  bool vUp = (rowUp == ( coeff.sgn() < 0));
4294
4295
3728359
  Debug("arith::prop") << "  " << rowUp << " " << v << " " << coeff << " " << vUp << endl;
4296
3728359
  Debug("arith::prop") << "  " << propagateMightSucceed(v, vUp) << endl;
4297
4298
3728359
  if(propagateMightSucceed(v, vUp)){
4299
589600
    DeltaRational dr = d_linEq.computeRowBound(ridx, rowUp, v);
4300
589600
    DeltaRational bound = dr / (- coeff);
4301
294800
    return tryToPropagate(ridx, rowUp, v, vUp, bound);
4302
  }
4303
3433559
  return false;
4304
}
4305
4306
1441225
bool TheoryArithPrivate::attemptFull(RowIndex ridx, bool rowUp){
4307
1441225
  Debug("arith::prop") << "  attemptFull" << ridx << endl;
4308
4309
2882450
  vector<const Tableau::Entry*> candidates;
4310
4311
8857340
  for(Tableau::RowIterator i = d_tableau.ridRowIterator(ridx); !i.atEnd(); ++i){
4312
7416115
    const Tableau::Entry& e =*i;
4313
7416115
    const Rational& c = e.getCoefficient();
4314
7416115
    ArithVar v = e.getColVar();
4315
7416115
    bool vUp = (rowUp == (c.sgn() < 0));
4316
7416115
    if(propagateMightSucceed(v, vUp)){
4317
158894
      candidates.push_back(&e);
4318
    }
4319
  }
4320
1441225
  if(candidates.empty()){ return false; }
4321
4322
  const DeltaRational slack =
4323
284320
    d_linEq.computeRowBound(ridx, rowUp, ARITHVAR_SENTINEL);
4324
142160
  bool any = false;
4325
142160
  vector<const Tableau::Entry*>::const_iterator i, iend;
4326
301054
  for(i = candidates.begin(), iend = candidates.end(); i != iend; ++i){
4327
158894
    const Tableau::Entry* ep = *i;
4328
158894
    const Rational& c = ep->getCoefficient();
4329
158894
    ArithVar v = ep->getColVar();
4330
4331
    // See the comment for attemptSingleton()
4332
158894
    bool activeUp = (rowUp == (c.sgn() > 0));
4333
158894
    bool vUb = (rowUp == (c.sgn() < 0));
4334
4335
317788
    const DeltaRational& activeBound = activeUp ?
4336
125178
      d_partialModel.getUpperBound(v):
4337
192610
      d_partialModel.getLowerBound(v);
4338
4339
317788
    DeltaRational contribution = activeBound * c;
4340
317788
    DeltaRational impliedBound = (slack - contribution)/(-c);
4341
4342
158894
    bool success = tryToPropagate(ridx, rowUp, v, vUb, impliedBound);
4343
158894
    any |= success;
4344
  }
4345
142160
  return any;
4346
}
4347
4348
453694
bool TheoryArithPrivate::tryToPropagate(RowIndex ridx, bool rowUp, ArithVar v, bool vUb, const DeltaRational& bound){
4349
4350
783030
  bool weaker = vUb ? d_partialModel.strictlyLessThanUpperBound(v, bound):
4351
783030
    d_partialModel.strictlyGreaterThanLowerBound(v, bound);
4352
453694
  if(weaker){
4353
294530
    ConstraintType t = vUb ? UpperBound : LowerBound;
4354
4355
294530
    ConstraintP implied = d_constraintDatabase.getBestImpliedBound(v, t, bound);
4356
294530
    if(implied != NullConstraint){
4357
147962
      return rowImplicationCanBeApplied(ridx, rowUp, implied);
4358
    }
4359
  }
4360
305732
  return false;
4361
}
4362
4363
92147
Node flattenImplication(Node imp){
4364
184294
  NodeBuilder nb(kind::OR);
4365
184294
  std::unordered_set<Node> included;
4366
184294
  Node left = imp[0];
4367
184294
  Node right = imp[1];
4368
4369
92147
  if(left.getKind() == kind::AND){
4370
417610
    for(Node::iterator i = left.begin(), iend = left.end(); i != iend; ++i) {
4371
325463
      if (!included.count((*i).negate()))
4372
      {
4373
325463
        nb << (*i).negate();
4374
325463
        included.insert((*i).negate());
4375
      }
4376
    }
4377
  }else{
4378
    if (!included.count(left.negate()))
4379
    {
4380
      nb << left.negate();
4381
      included.insert(left.negate());
4382
    }
4383
  }
4384
4385
92147
  if(right.getKind() == kind::OR){
4386
    for(Node::iterator i = right.begin(), iend = right.end(); i != iend; ++i) {
4387
      if (!included.count(*i))
4388
      {
4389
        nb << *i;
4390
        included.insert(*i);
4391
      }
4392
    }
4393
  }else{
4394
92147
    if (!included.count(right))
4395
    {
4396
92147
      nb << right;
4397
92147
      included.insert(right);
4398
    }
4399
  }
4400
4401
184294
  return nb;
4402
}
4403
4404
147962
bool TheoryArithPrivate::rowImplicationCanBeApplied(RowIndex ridx, bool rowUp, ConstraintP implied){
4405
147962
  Assert(implied != NullConstraint);
4406
147962
  ArithVar v = implied->getVariable();
4407
4408
147962
  bool assertedToTheTheory = implied->assertedToTheTheory();
4409
147962
  bool canBePropagated = implied->canBePropagated();
4410
147962
  bool hasProof = implied->hasProof();
4411
4412
295924
  Debug("arith::prop") << "arith::prop" << v
4413
147962
                       << " " << assertedToTheTheory
4414
147962
                       << " " << canBePropagated
4415
147962
                       << " " << hasProof
4416
147962
                       << endl;
4417
4418
4419
147962
  if( !assertedToTheTheory && canBePropagated && !hasProof ){
4420
248666
    ConstraintCPVec explain;
4421
124333
    ARITH_PROOF(d_farkasBuffer.clear());
4422
124333
    RationalVectorP coeffs = ARITH_NULLPROOF(&d_farkasBuffer);
4423
4424
    // After invoking `propegateRow`:
4425
    //   * coeffs[0] is for implied
4426
    //   * coeffs[i+1] is for explain[i]
4427
124333
    d_linEq.propagateRow(explain, ridx, rowUp, implied, coeffs);
4428
248666
    if(d_tableau.getRowLength(ridx) <= options::arithPropAsLemmaLength()){
4429
92147
      if (Debug.isOn("arith::prop::pf")) {
4430
        for (const auto & constraint : explain) {
4431
          Assert(constraint->hasProof());
4432
          constraint->printProofTree(Debug("arith::prop::pf"));
4433
        }
4434
      }
4435
184294
      Node implication = implied->externalImplication(explain);
4436
184294
      Node clause = flattenImplication(implication);
4437
184294
      std::shared_ptr<ProofNode> clausePf{nullptr};
4438
4439
92147
      if (isProofEnabled())
4440
      {
4441
        // We can prove this lemma from Farkas...
4442
28572
        std::vector<std::shared_ptr<ProofNode>> conflictPfs;
4443
        // Assume the negated getLiteral version of the implied constaint
4444
        // then rewrite it into proof normal form.
4445
14286
        conflictPfs.push_back(
4446
85716
            d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM,
4447
28572
                          {d_pnm->mkAssume(implied->getLiteral().negate())},
4448
28572
                          {implied->getNegation()->getProofLiteral()}));
4449
        // Add the explaination proofs.
4450
62633
        for (const auto constraint : explain)
4451
        {
4452
96694
          NodeBuilder nb;
4453
48347
          conflictPfs.push_back(constraint->externalExplainByAssertions(nb));
4454
        }
4455
        // Collect the farkas coefficients, as nodes.
4456
28572
        std::vector<Node> farkasCoefficients;
4457
14286
        farkasCoefficients.reserve(coeffs->size());
4458
14286
        auto nm = NodeManager::currentNM();
4459
14286
        std::transform(
4460
            coeffs->begin(),
4461
            coeffs->end(),
4462
            std::back_inserter(farkasCoefficients),
4463
76919
            [nm](const Rational& r) { return nm->mkConst<Rational>(r); });
4464
4465
        // Prove bottom.
4466
14286
        auto sumPf = d_pnm->mkNode(
4467
28572
            PfRule::MACRO_ARITH_SCALE_SUM_UB, conflictPfs, farkasCoefficients);
4468
14286
        auto botPf = d_pnm->mkNode(
4469
28572
            PfRule::MACRO_SR_PRED_TRANSFORM, {sumPf}, {nm->mkConst(false)});
4470
4471
        // Prove the conflict
4472
28572
        std::vector<Node> assumptions;
4473
14286
        assumptions.reserve(clause.getNumChildren());
4474
14286
        std::transform(clause.begin(),
4475
                       clause.end(),
4476
                       std::back_inserter(assumptions),
4477
77553
                       [](TNode r) { return r.negate(); });
4478
28572
        auto notAndNotPf = d_pnm->mkScope(botPf, assumptions);
4479
4480
        // Convert it to a clause
4481
28572
        auto orNotNotPf = d_pnm->mkNode(PfRule::NOT_AND, {notAndNotPf}, {});
4482
42858
        clausePf = d_pnm->mkNode(
4483
28572
            PfRule::MACRO_SR_PRED_TRANSFORM, {orNotNotPf}, {clause});
4484
4485
        // Output it
4486
28572
        TrustNode trustedClause = d_pfGen->mkTrustNode(clause, clausePf);
4487
14286
        outputTrustedLemma(trustedClause, InferenceId::ARITH_ROW_IMPL);
4488
      }
4489
      else
4490
      {
4491
77861
        outputLemma(clause, InferenceId::ARITH_ROW_IMPL);
4492
      }
4493
    }else{
4494
32186
      Assert(!implied->negationHasProof());
4495
32186
      implied->impliedByFarkas(explain, coeffs, false);
4496
32186
      implied->tryToPropagate();
4497
    }
4498
124333
    return true;
4499
  }
4500
4501
23629
  if(Debug.isOn("arith::prop")){
4502
    Debug("arith::prop")
4503
      << "failed " << v << " " << assertedToTheTheory << " "
4504
      << canBePropagated << " " << hasProof << " " << implied << endl;
4505
    d_partialModel.printModel(v, Debug("arith::prop"));
4506
  }
4507
23629
  return false;
4508
}
4509
4510
8736773
bool TheoryArithPrivate::propagateCandidateRow(RowIndex ridx){
4511
8736773
  BoundCounts hasCount = d_linEq.hasBoundCount(ridx);
4512
8736773
  uint32_t rowLength = d_tableau.getRowLength(ridx);
4513
4514
8736773
  bool success = false;
4515
  static int instance = 0;
4516
8736773
  ++instance;
4517
4518
17473546
  Debug("arith::prop")
4519
8736773
    << "propagateCandidateRow " << instance << " attempt " << rowLength << " " <<  hasCount << endl;
4520
4521
17473546
  if (rowLength >= options::arithPropagateMaxLength()
4522
10278654
      && Random::getRandom().pickWithProb(
4523
1541881
             1.0 - double(options::arithPropagateMaxLength()) / rowLength))
4524
  {
4525
331181
    return false;
4526
  }
4527
4528
8405592
  if(hasCount.lowerBoundCount() == rowLength){
4529
613717
    success |= attemptFull(ridx, false);
4530
7791875
  }else if(hasCount.lowerBoundCount() + 1 == rowLength){
4531
1945847
    success |= attemptSingleton(ridx, false);
4532
  }
4533
4534
8405592
  if(hasCount.upperBoundCount() == rowLength){
4535
827508
    success |= attemptFull(ridx, true);
4536
7578084
  }else if(hasCount.upperBoundCount() + 1 == rowLength){
4537
1782512
    success |= attemptSingleton(ridx, true);
4538
  }
4539
8405592
  return success;
4540
}
4541
4542
960248
void TheoryArithPrivate::dumpUpdatedBoundsToRows(){
4543
960248
  Assert(d_candidateRows.empty());
4544
960248
  DenseSet::const_iterator i = d_updatedBounds.begin();
4545
960248
  DenseSet::const_iterator end = d_updatedBounds.end();
4546
5795178
  for(; i != end; ++i){
4547
2417465
    ArithVar var = *i;
4548
2417465
    if(d_tableau.isBasic(var)){
4549
1345710
      RowIndex ridx = d_tableau.basicToRowIndex(var);
4550
1345710
      d_candidateRows.softAdd(ridx);
4551
    }else{
4552
1071755
      Tableau::ColIterator basicIter = d_tableau.colIterator(var);
4553
23893853
      for(; !basicIter.atEnd(); ++basicIter){
4554
11411049
        const Tableau::Entry& entry = *basicIter;
4555
11411049
        RowIndex ridx = entry.getRowIndex();
4556
11411049
        d_candidateRows.softAdd(ridx);
4557
      }
4558
    }
4559
  }
4560
960248
  d_updatedBounds.purge();
4561
960248
}
4562
4563
const BoundsInfo& TheoryArithPrivate::boundsInfo(ArithVar basic) const{
4564
  RowIndex ridx = d_tableau.basicToRowIndex(basic);
4565
  return d_rowTracking[ridx];
4566
}
4567
4568
6013
std::pair<bool, Node> TheoryArithPrivate::entailmentCheck(TNode lit, const ArithEntailmentCheckParameters& params, ArithEntailmentCheckSideEffects& out){
4569
  using namespace inferbounds;
4570
4571
  // l k r
4572
  // diff : (l - r) k 0
4573
6013
  Debug("arith::entailCheck") << "TheoryArithPrivate::entailmentCheck(" << lit << ")"<< endl;
4574
  Kind k;
4575
  int primDir;
4576
12026
  Rational lm, rm, dm;
4577
12026
  Node lp, rp, dp;
4578
12026
  DeltaRational sep;
4579
6013
  bool successful = decomposeLiteral(lit, k, primDir, lm, lp, rm, rp, dm, dp, sep);
4580
6013
  if(!successful) { return make_pair(false, Node::null()); }
4581
4582
6013
  if(dp.getKind() == CONST_RATIONAL){
4583
    Node eval = Rewriter::rewrite(lit);
4584
    Assert(eval.getKind() == kind::CONST_BOOLEAN);
4585
    // if true, true is an acceptable explaination
4586
    // if false, the node is uninterpreted and eval can be forgotten
4587
    return make_pair(eval.getConst<bool>(), eval);
4588
  }
4589
6013
  Assert(dm != Rational(0));
4590
6013
  Assert(primDir == 1 || primDir == -1);
4591
4592
6013
  int negPrim = -primDir;
4593
4594
6013
  int secDir = (k == EQUAL || k == DISTINCT) ? negPrim: 0;
4595
6013
  int negSecDir = (k == EQUAL || k == DISTINCT) ? primDir: 0;
4596
4597
  // primDir*[lm*( lp )] k primDir*[ [rm*( rp )] + sep ]
4598
  // primDir*[lm*( lp ) - rm*( rp ) ] k primDir*sep
4599
  // primDir*[dm * dp] k primDir*sep
4600
4601
12026
  std::pair<Node, DeltaRational> bestPrimLeft, bestNegPrimRight, bestPrimDiff, tmp;
4602
12026
  std::pair<Node, DeltaRational> bestSecLeft, bestNegSecRight, bestSecDiff;
4603
6013
  bestPrimLeft.first = Node::null(); bestNegPrimRight.first = Node::null(); bestPrimDiff.first = Node::null();
4604
6013
  bestSecLeft.first = Node::null(); bestNegSecRight.first = Node::null(); bestSecDiff.first = Node::null();
4605
4606
4607
4608
6013
  ArithEntailmentCheckParameters::const_iterator alg, alg_end;
4609
16670
  for( alg = params.begin(), alg_end = params.end(); alg != alg_end; ++alg ){
4610
11831
    const inferbounds::InferBoundAlgorithm& ibalg = *alg;
4611
4612
11831
    Debug("arith::entailCheck") << "entailmentCheck trying " << (inferbounds::Algorithms) ibalg.getAlgorithm() << endl;
4613
11831
    switch(ibalg.getAlgorithm()){
4614
    case inferbounds::None:
4615
      break;
4616
11831
    case inferbounds::Lookup:
4617
    case inferbounds::RowSum:
4618
      {
4619
        typedef void (TheoryArithPrivate::*EntailmentCheckFunc)(std::pair<Node, DeltaRational>&, int, TNode) const;
4620
4621
        EntailmentCheckFunc ecfunc =
4622
11831
          (ibalg.getAlgorithm() == inferbounds::Lookup)
4623
          ? (&TheoryArithPrivate::entailmentCheckBoundLookup)
4624
11831
          : (&TheoryArithPrivate::entailmentCheckRowSum);
4625
4626
11831
        (*this.*ecfunc)(tmp, primDir * lm.sgn(), lp);
4627
11831
        setToMin(primDir * lm.sgn(), bestPrimLeft, tmp);
4628
4629
11831
        (*this.*ecfunc)(tmp, negPrim * rm.sgn(), rp);
4630
11831
        setToMin(negPrim * rm.sgn(), bestNegPrimRight, tmp);
4631
4632
11831
        (*this.*ecfunc)(tmp, secDir * lm.sgn(), lp);
4633
11831
        setToMin(secDir * lm.sgn(), bestSecLeft, tmp);
4634
4635
11831
        (*this.*ecfunc)(tmp, negSecDir * rm.sgn(), rp);
4636
11831
        setToMin(negSecDir * rm.sgn(), bestNegSecRight, tmp);
4637
4638
11831
        (*this.*ecfunc)(tmp, primDir * dm.sgn(), dp);
4639
11831
        setToMin(primDir * dm.sgn(), bestPrimDiff, tmp);
4640
4641
11831
        (*this.*ecfunc)(tmp, secDir * dm.sgn(), dp);
4642
11831
        setToMin(secDir * dm.sgn(), bestSecDiff, tmp);
4643
      }
4644
11831
      break;
4645
    default:
4646
      Unhandled();
4647
    }
4648
4649
    // turn bounds on prim * left and -prim * right into bounds on prim * diff
4650
11831
    if(!bestPrimLeft.first.isNull() && !bestNegPrimRight.first.isNull()){
4651
      //  primDir*lm* lp <= primDir*lm*L
4652
      // -primDir*rm* rp <= -primDir*rm*R
4653
      // primDir*lm* lp -primDir*rm* rp <=  primDir*lm*L - primDir*rm*R
4654
      // primDir [lm* lp -rm* rp] <= primDir[lm*L - *rm*R]
4655
      // primDir [dm * dp] <= primDir[lm*L - *rm*R]
4656
      // primDir [dm * dp] <= primDir * dm * ([lm*L - *rm*R]/dm)
4657
1988
      tmp.second = ((bestPrimLeft.second * lm) - (bestNegPrimRight.second * rm)) / dm;
4658
1988
      tmp.first = (bestPrimLeft.first).andNode(bestNegPrimRight.first);
4659
1988
      setToMin(primDir, bestPrimDiff, tmp);
4660
    }
4661
4662
    // turn bounds on sec * left and sec * right into bounds on sec * diff
4663
11831
    if(secDir != 0 && !bestSecLeft.first.isNull() && !bestNegSecRight.first.isNull()){
4664
      //  secDir*lm* lp <= secDir*lm*L
4665
      // -secDir*rm* rp <= -secDir*rm*R
4666
      // secDir*lm* lp -secDir*rm* rp <=  secDir*lm*L - secDir*rm*R
4667
      // secDir [lm* lp -rm* rp] <= secDir[lm*L - *rm*R]
4668
      // secDir [dm * dp] <= secDir[lm*L - *rm*R]
4669
      // secDir [dm * dp] <= secDir * dm * ([lm*L - *rm*R]/dm)
4670
      tmp.second = ((bestSecLeft.second * lm) - (bestNegSecRight.second * rm)) / dm;
4671
      tmp.first = (bestSecLeft.first).andNode(bestNegSecRight.first);
4672
      setToMin(secDir, bestSecDiff, tmp);
4673
    }
4674
4675
11831
    switch(k){
4676
11787
    case LEQ:
4677
11787
      if(!bestPrimDiff.first.isNull()){
4678
2802
        DeltaRational d = (bestPrimDiff.second * dm);
4679
1988
        if((primDir > 0 && d <= sep) || (primDir < 0 && d >= sep) ){
4680
2348
          Debug("arith::entailCheck") << "entailmentCheck found "
4681
1174
                                      << primDir << "*" << dm << "*(" << dp<<")"
4682
1174
                                      << " <= " << primDir << "*" << dm << "*" << bestPrimDiff.second
4683
1174
                                      << " <= " << primDir << "*" << sep << endl
4684
1174
                                      << " by " << bestPrimDiff.first << endl;
4685
1174
          Assert(bestPrimDiff.second * (Rational(primDir) * dm)
4686
                 <= (sep * Rational(primDir)));
4687
1174
          return make_pair(true, bestPrimDiff.first);
4688
        }
4689
      }
4690
10613
      break;
4691
22
    case EQUAL:
4692
22
      if(!bestPrimDiff.first.isNull() && !bestSecDiff.first.isNull()){
4693
        // Is primDir [dm * dp] == primDir * sep entailed?
4694
        // Iff [dm * dp] == sep entailed?
4695
        // Iff dp == sep / dm entailed?
4696
        // Iff dp <= sep / dm and dp >= sep / dm entailed?
4697
4698
        // primDir [dm * dp] <= primDir * dm * U
4699
        // secDir [dm * dp] <= secDir * dm * L
4700
4701
        // Suppose primDir * dm > 0
4702
        // then secDir * dm < 0
4703
        //   dp >= (secDir * L) / secDir * dm
4704
        //   dp >= (primDir * L) / primDir * dm
4705
        //
4706
        //   dp <= U / dm
4707
        //   dp >= L / dm
4708
        //   dp == sep / dm entailed iff U == L == sep
4709
        // Suppose primDir * dm < 0
4710
        // then secDir * dm > 0
4711
        //   dp >= U / dm
4712
        //   dp <= L / dm
4713
        //   dp == sep / dm entailed iff U == L == sep
4714
        if(bestPrimDiff.second == bestSecDiff.second){
4715
          if(bestPrimDiff.second == sep){
4716
            return make_pair(true, (bestPrimDiff.first).andNode(bestSecDiff.first));
4717
          }
4718
        }
4719
      }
4720
      // intentionally fall through to DISTINCT case!
4721
      // entailments of negations are eager exit cases for EQUAL
4722
      CVC5_FALLTHROUGH;
4723
    case DISTINCT:
4724
44
      if(!bestPrimDiff.first.isNull()){
4725
        // primDir [dm * dp] <= primDir * dm * U < primDir * sep
4726
        if((primDir > 0 && (bestPrimDiff.second * dm  < sep)) ||
4727
           (primDir < 0 && (bestPrimDiff.second * dm  > sep))){
4728
          // entailment of negation
4729
          if(k == DISTINCT){
4730
            return make_pair(true, bestPrimDiff.first);
4731
          }else{
4732
            Assert(k == EQUAL);
4733
            return make_pair(false, Node::null());
4734
          }
4735
        }
4736
      }
4737
44
      if(!bestSecDiff.first.isNull()){
4738
        // If primDir [dm * dp] > primDir * sep, then this is not entailed.
4739
        // If primDir [dm * dp] >= primDir * dm * L > primDir * sep
4740
        // -primDir * dm * L < -primDir * sep
4741
        // secDir * dm * L < secDir * sep
4742
        if((secDir > 0 && (bestSecDiff.second * dm < sep)) ||
4743
           (secDir < 0 && (bestSecDiff.second * dm > sep))){
4744
          if(k == DISTINCT){
4745
            return make_pair(true, bestSecDiff.first);
4746
          }else{
4747
            Assert(k == EQUAL);
4748
            return make_pair(false, Node::null());
4749
          }
4750
        }
4751
      }
4752
4753
44
      break;
4754
    default:
4755
      Unreachable();
4756
      break;
4757
    }
4758
  }
4759
4839
  return make_pair(false, Node::null());
4760
}
4761
4762
18039
bool TheoryArithPrivate::decomposeTerm(Node term, Rational& m, Node& p, Rational& c){
4763
36078
  Node t = Rewriter::rewrite(term);
4764
18039
  if(!Polynomial::isMember(t)){
4765
    return false;
4766
  }
4767
4768
  // TODO Speed up
4769
36078
  preprocessing::util::ContainsTermITEVisitor ctv;
4770
18039
  if(ctv.containsTermITE(t)){
4771
    return false;
4772
  }
4773
4774
36078
  Polynomial poly = Polynomial::parsePolynomial(t);
4775
18039
  if(poly.isConstant()){
4776
5991
    c = poly.getHead().getConstant().getValue();
4777
5991
    p = mkRationalNode(Rational(0));
4778
5991
    m = Rational(1);
4779
5991
    return true;
4780
12048
  }else if(poly.containsConstant()){
4781
2895
    c = poly.getHead().getConstant().getValue();
4782
2895
    poly = poly.getTail();
4783
  }else{
4784
9153
    c = Rational(0);
4785
  }
4786
12048
  Assert(!poly.isConstant());
4787
12048
  Assert(!poly.containsConstant());
4788
4789
12048
  const bool intVars = poly.allIntegralVariables();
4790
4791
12048
  if(intVars){
4792
12048
    m = Rational(1);
4793
12048
    if(!poly.isIntegral()){
4794
      Integer denom = poly.denominatorLCM();
4795
      m /= denom;
4796
      poly = poly * denom;
4797
    }
4798
24096
    Integer g = poly.gcd();
4799
12048
    m *= g;
4800
12048
    poly = poly * Rational(1,g);
4801
12048
    Assert(poly.isIntegral());
4802
12048
    Assert(poly.leadingCoefficientIsPositive());
4803
  }else{
4804
    Assert(!intVars);
4805
    m = poly.getHead().getConstant().getValue();
4806
    poly = poly * m.inverse();
4807
    Assert(poly.leadingCoefficientIsAbsOne());
4808
  }
4809
12048
  p = poly.getNode();
4810
12048
  return true;
4811
}
4812
4813
72974
void TheoryArithPrivate::setToMin(int sgn, std::pair<Node, DeltaRational>& min, const std::pair<Node, DeltaRational>& e){
4814
72974
  if(sgn != 0){
4815
37613
    if(min.first.isNull() && !e.first.isNull()){
4816
9959
      min = e;
4817
27654
    }else if(!min.first.isNull() && !e.first.isNull()){
4818
1988
      if(sgn > 0 && min.second > e.second){
4819
        min = e;
4820
1988
      }else if(sgn < 0 &&  min.second < e.second){
4821
        min = e;
4822
      }
4823
    }
4824
  }
4825
72974
}
4826
4827
// std::pair<bool, Node> TheoryArithPrivate::entailmentUpperCheck(const Rational& lm, Node lp, const Rational& rm, Node rp, const DeltaRational& sep, const ArithEntailmentCheckParameters& params, ArithEntailmentCheckSideEffects& out){
4828
4829
//   Rational negRM = -rm;
4830
//   Node diff = NodeManager::currentNM()->mkNode(MULT, mkRationalConstan(lm), lp) + (negRM * rp);
4831
4832
//   Rational diffm;
4833
//   Node diffp;
4834
//   decompose(diff, diffm, diffNode);
4835
4836
4837
//   std::pair<Node, DeltaRational> bestUbLeft, bestLbRight, bestUbDiff, tmp;
4838
//   bestUbLeft = bestLbRight = bestUbDiff = make_pair(Node::Null(), DeltaRational());
4839
4840
//   return make_pair(false, Node::null());
4841
// }
4842
4843
/**
4844
 * Decomposes a literal into the form:
4845
 *   dir*[lm*( lp )] k dir*[ [rm*( rp )] + sep ]
4846
 *   dir*[dm* dp]  k dir *sep
4847
 *   dir is either 1 or -1
4848
 */
4849
6013
bool TheoryArithPrivate::decomposeLiteral(Node lit, Kind& k, int& dir, Rational& lm,  Node& lp, Rational& rm, Node& rp, Rational& dm, Node& dp, DeltaRational& sep){
4850
6013
  bool negated = (lit.getKind() == kind::NOT);
4851
12026
  TNode atom = negated ? lit[0] : lit;
4852
4853
12026
  TNode left = atom[0];
4854
12026
  TNode right = atom[1];
4855
4856
  // left : lm*( lp ) + lc
4857
  // right: rm*( rp ) + rc
4858
12026
  Rational lc, rc;
4859
6013
  bool success = decomposeTerm(left, lm, lp, lc);
4860
6013
  if(!success){ return false; }
4861
6013
  success = decomposeTerm(right, rm, rp, rc);
4862
6013
  if(!success){ return false; }
4863
4864
12026
  Node diff = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::MINUS, left, right));
4865
12026
  Rational dc;
4866
6013
  success = decomposeTerm(diff, dm, dp, dc);
4867
6013
  Assert(success);
4868
4869
  // reduce the kind of the to not include literals
4870
  // GT, NOT LEQ
4871
  // GEQ, NOT LT
4872
  // LT, NOT GEQ
4873
  // LEQ, NOT LT
4874
6013
  Kind atomKind = atom.getKind();
4875
6013
  Kind normKind = negated ? negateKind(atomKind) : atomKind;
4876
4877
6013
  if(normKind == GEQ || normKind == GT){
4878
2895
    dir = -1;
4879
2895
    normKind = (normKind == GEQ) ? LEQ : LT;
4880
  }else{
4881
3118
    dir = 1;
4882
  }
4883
4884
12026
  Debug("arith::decomp") << "arith::decomp "
4885
6013
                         << lit << "(" << normKind << "*" << dir << ")"<< endl
4886
6013
                         << "  left:" << lc << " + " << lm << "*(" <<  lp << ") : " <<left << endl
4887
6013
                         << "  right:" << rc << " + " << rm << "*(" <<  rp << ") : " << right << endl
4888
6013
                         << "  diff: " << dc << " + " << dm << "*("<< dp <<"): " << diff << endl
4889
6013
                         << "  sep: " << sep << endl;
4890
4891
4892
  // k in LT, LEQ, EQUAL, DISEQUAL
4893
  // [dir*lm*( lp ) + dir*lc] k [dir*rm*( rp ) + dir*rc]
4894
12026
  Rational change = rc - lc;
4895
6013
  Assert(change == (-dc));
4896
  // [dir*lm*( lp )] k [dir*rm*( rp ) + dir*(rc - lc)]
4897
6013
  if(normKind == LT){
4898
3096
    sep = DeltaRational(change, Rational(-1));
4899
3096
    k = LEQ;
4900
  }else{
4901
2917
    sep = DeltaRational(change);
4902
2917
    k = normKind;
4903
  }
4904
  // k in LEQ, EQUAL, DISEQUAL
4905
  // dir*lm*( lp ) k [dir*rm*( rp )] + dir*(sep + d * delta)
4906
6013
  return true;
4907
}
4908
4909
/**
4910
 *  Precondition:
4911
 *   tp is a polynomial not containing an ite.
4912
 *   either tp is constant or contains no constants.
4913
 *  Post:
4914
 *    if tmp.first is not null, then
4915
 *      sgn * tp <= sgn * tmp.second
4916
 */
4917
36078
void TheoryArithPrivate::entailmentCheckBoundLookup(std::pair<Node, DeltaRational>& tmp, int sgn, TNode tp) const {
4918
36078
  tmp.first = Node::null();
4919
36078
  if(sgn == 0){ return; }
4920
4921
18105
  Assert(Polynomial::isMember(tp));
4922
18105
  if(tp.getKind() == CONST_RATIONAL){
4923
5991
    tmp.first = mkBoolNode(true);
4924
5991
    tmp.second = DeltaRational(tp.getConst<Rational>());
4925
12114
  }else if(d_partialModel.hasArithVar(tp)){
4926
9548
    Assert(tp.getKind() != CONST_RATIONAL);
4927
9548
    ArithVar v = d_partialModel.asArithVar(tp);
4928
9548
    Assert(v != ARITHVAR_SENTINEL);
4929
    ConstraintP c = (sgn > 0)
4930
14198
      ? d_partialModel.getUpperBoundConstraint(v)
4931
14198
      : d_partialModel.getLowerBoundConstraint(v);
4932
9548
    if(c != NullConstraint){
4933
398
      tmp.first = Constraint::externalExplainByAssertions({c});
4934
398
      tmp.second = c->getValue();
4935
    }
4936
  }
4937
}
4938
4939
34908
void TheoryArithPrivate::entailmentCheckRowSum(std::pair<Node, DeltaRational>& tmp, int sgn, TNode tp) const {
4940
34908
  tmp.first = Node::null();
4941
66246
  if(sgn == 0){ return; }
4942
17520
  if(tp.getKind() != PLUS){ return; }
4943
11604
  Assert(Polynomial::isMember(tp));
4944
4945
11604
  tmp.second = DeltaRational(0);
4946
15174
  NodeBuilder nb(kind::AND);
4947
4948
15174
  Polynomial p = Polynomial::parsePolynomial(tp);
4949
22978
  for(Polynomial::iterator i = p.begin(), iend = p.end(); i != iend; ++i) {
4950
30782
    Monomial m = *i;
4951
30782
    Node x = m.getVarList().getNode();
4952
19408
    if(d_partialModel.hasArithVar(x)){
4953
19364
      ArithVar v = d_partialModel.asArithVar(x);
4954
19364
      const Rational& coeff = m.getConstant().getValue();
4955
19364
      int dir = sgn * coeff.sgn();
4956
      ConstraintP c = (dir > 0)
4957
27168
        ? d_partialModel.getUpperBoundConstraint(v)
4958
27168
        : d_partialModel.getLowerBoundConstraint(v);
4959
19364
      if(c != NullConstraint){
4960
11374
        tmp.second += c->getValue() * coeff;
4961
11374
        c->externalExplainByAssertions(nb);
4962
      }else{
4963
        //failed
4964
7990
        return;
4965
      }
4966
    }else{
4967
      // failed
4968
44
      return;
4969
    }
4970
  }
4971
  // success
4972
3570
  tmp.first = nb;
4973
}
4974
4975
3756
ArithProofRuleChecker* TheoryArithPrivate::getProofChecker()
4976
{
4977
3756
  return &d_checker;
4978
}
4979
4980
}  // namespace arith
4981
}  // namespace theory
4982
29280
}  // namespace cvc5