1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Tim King, Aina Niemetz, Mathias Preiner |
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 |
|
#include "theory/arith/attempt_solution_simplex.h" |
19 |
|
|
20 |
|
#include "base/output.h" |
21 |
|
#include "options/arith_options.h" |
22 |
|
#include "smt/smt_statistics_registry.h" |
23 |
|
#include "theory/arith/constraint.h" |
24 |
|
#include "theory/arith/error_set.h" |
25 |
|
#include "theory/arith/linear_equality.h" |
26 |
|
#include "theory/arith/tableau.h" |
27 |
|
|
28 |
|
using namespace std; |
29 |
|
|
30 |
|
namespace cvc5 { |
31 |
|
namespace theory { |
32 |
|
namespace arith { |
33 |
|
|
34 |
9917 |
AttemptSolutionSDP::AttemptSolutionSDP(LinearEqualityModule& linEq, ErrorSet& errors, RaiseConflict conflictChannel, TempVarMalloc tvmalloc) |
35 |
|
: SimplexDecisionProcedure(linEq, errors, conflictChannel, tvmalloc) |
36 |
9917 |
, d_statistics() |
37 |
9917 |
{ } |
38 |
|
|
39 |
9917 |
AttemptSolutionSDP::Statistics::Statistics() |
40 |
9917 |
: d_searchTime(smtStatisticsRegistry().registerTimer( |
41 |
19834 |
"theory::arith::attempt::searchTime")), |
42 |
9917 |
d_queueTime(smtStatisticsRegistry().registerTimer( |
43 |
19834 |
"theory::arith::attempt::queueTime")), |
44 |
9917 |
d_conflicts(smtStatisticsRegistry().registerInt( |
45 |
29751 |
"theory::arith::attempt::conflicts")) |
46 |
|
{ |
47 |
9917 |
} |
48 |
|
|
49 |
|
bool AttemptSolutionSDP::matchesNewValue(const DenseMap<DeltaRational>& nv, ArithVar v) const{ |
50 |
|
return nv[v] == d_variables.getAssignment(v); |
51 |
|
} |
52 |
|
|
53 |
|
Result::Sat AttemptSolutionSDP::attempt(const ApproximateSimplex::Solution& sol){ |
54 |
|
const DenseSet& newBasis = sol.newBasis; |
55 |
|
const DenseMap<DeltaRational>& newValues = sol.newValues; |
56 |
|
|
57 |
|
DenseSet needsToBeAdded; |
58 |
|
for(DenseSet::const_iterator i = newBasis.begin(), i_end = newBasis.end(); i != i_end; ++i){ |
59 |
|
ArithVar b = *i; |
60 |
|
if(!d_tableau.isBasic(b)){ |
61 |
|
needsToBeAdded.add(b); |
62 |
|
} |
63 |
|
} |
64 |
|
DenseMap<DeltaRational>::const_iterator nvi = newValues.begin(), nvi_end = newValues.end(); |
65 |
|
for(; nvi != nvi_end; ++nvi){ |
66 |
|
ArithVar currentlyNb = *nvi; |
67 |
|
if(!d_tableau.isBasic(currentlyNb)){ |
68 |
|
if(!matchesNewValue(newValues, currentlyNb)){ |
69 |
|
const DeltaRational& newValue = newValues[currentlyNb]; |
70 |
|
Trace("arith::updateMany") |
71 |
|
<< "updateMany:" << currentlyNb << " " |
72 |
|
<< d_variables.getAssignment(currentlyNb) << " to "<< newValue << endl; |
73 |
|
d_linEq.update(currentlyNb, newValue); |
74 |
|
Assert(d_variables.assignmentIsConsistent(currentlyNb)); |
75 |
|
} |
76 |
|
} |
77 |
|
} |
78 |
|
d_errorSet.reduceToSignals(); |
79 |
|
d_errorSet.setSelectionRule(options::ErrorSelectionRule::VAR_ORDER); |
80 |
|
|
81 |
|
static int instance = 0; |
82 |
|
++instance; |
83 |
|
|
84 |
|
if(processSignals()){ |
85 |
|
Debug("arith::findModel") << "attemptSolution("<< instance <<") early conflict" << endl; |
86 |
|
d_conflictVariables.purge(); |
87 |
|
return Result::UNSAT; |
88 |
|
}else if(d_errorSet.errorEmpty()){ |
89 |
|
Debug("arith::findModel") << "attemptSolution("<< instance <<") fixed itself" << endl; |
90 |
|
return Result::SAT; |
91 |
|
} |
92 |
|
|
93 |
|
while(!needsToBeAdded.empty() && !d_errorSet.errorEmpty()){ |
94 |
|
ArithVar toRemove = ARITHVAR_SENTINEL; |
95 |
|
ArithVar toAdd = ARITHVAR_SENTINEL; |
96 |
|
DenseSet::const_iterator i = needsToBeAdded.begin(), i_end = needsToBeAdded.end(); |
97 |
|
for(; toAdd == ARITHVAR_SENTINEL && i != i_end; ++i){ |
98 |
|
ArithVar v = *i; |
99 |
|
|
100 |
|
Tableau::ColIterator colIter = d_tableau.colIterator(v); |
101 |
|
for(; !colIter.atEnd(); ++colIter){ |
102 |
|
const Tableau::Entry& entry = *colIter; |
103 |
|
Assert(entry.getColVar() == v); |
104 |
|
ArithVar b = d_tableau.rowIndexToBasic(entry.getRowIndex()); |
105 |
|
if(!newBasis.isMember(b)){ |
106 |
|
toAdd = v; |
107 |
|
|
108 |
|
bool favorBOverToRemove = |
109 |
|
(toRemove == ARITHVAR_SENTINEL) || |
110 |
|
(matchesNewValue(newValues, toRemove) && !matchesNewValue(newValues, b)) || |
111 |
|
(d_tableau.basicRowLength(toRemove) > d_tableau.basicRowLength(b)); |
112 |
|
|
113 |
|
if(favorBOverToRemove){ |
114 |
|
toRemove = b; |
115 |
|
} |
116 |
|
} |
117 |
|
} |
118 |
|
} |
119 |
|
Assert(toRemove != ARITHVAR_SENTINEL); |
120 |
|
Assert(toAdd != ARITHVAR_SENTINEL); |
121 |
|
|
122 |
|
Trace("arith::forceNewBasis") << toRemove << " " << toAdd << endl; |
123 |
|
// CVC5Message() << toRemove << " " << toAdd << endl; |
124 |
|
|
125 |
|
d_linEq.pivotAndUpdate(toRemove, toAdd, newValues[toRemove]); |
126 |
|
|
127 |
|
Trace("arith::forceNewBasis") << needsToBeAdded.size() << "to go" << endl; |
128 |
|
// CVC5Message() << needsToBeAdded.size() << "to go" << endl; |
129 |
|
needsToBeAdded.remove(toAdd); |
130 |
|
|
131 |
|
bool conflict = processSignals(); |
132 |
|
if(conflict){ |
133 |
|
d_errorSet.reduceToSignals(); |
134 |
|
d_conflictVariables.purge(); |
135 |
|
|
136 |
|
return Result::UNSAT; |
137 |
|
} |
138 |
|
} |
139 |
|
Assert(d_conflictVariables.empty()); |
140 |
|
|
141 |
|
if(d_errorSet.errorEmpty()){ |
142 |
|
return Result::SAT; |
143 |
|
}else{ |
144 |
|
d_errorSet.reduceToSignals(); |
145 |
|
return Result::SAT_UNKNOWN; |
146 |
|
} |
147 |
|
} |
148 |
|
|
149 |
|
} // namespace arith |
150 |
|
} // namespace theory |
151 |
29514 |
} // namespace cvc5 |