1 /******************************************************************************
2 * Top contributors (to current version):
3 * Tim King, Aina Niemetz, Mathias Preiner
5 * This file is part of the cvc5 project.
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 * ****************************************************************************
13 * [[ Add one-line brief description here ]]
15 * [[ Add lengthier description here ]]
16 * \todo document this file
18 #include "theory/arith/attempt_solution_simplex.h"
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"
34 AttemptSolutionSDP::AttemptSolutionSDP(Env
& env
,
35 LinearEqualityModule
& linEq
,
37 RaiseConflict conflictChannel
,
38 TempVarMalloc tvmalloc
)
39 : SimplexDecisionProcedure(env
, linEq
, errors
, conflictChannel
, tvmalloc
),
43 AttemptSolutionSDP::Statistics::Statistics()
44 : d_searchTime(smtStatisticsRegistry().registerTimer(
45 "theory::arith::attempt::searchTime")),
46 d_queueTime(smtStatisticsRegistry().registerTimer(
47 "theory::arith::attempt::queueTime")),
48 d_conflicts(smtStatisticsRegistry().registerInt(
49 "theory::arith::attempt::conflicts"))
53 bool AttemptSolutionSDP::matchesNewValue(const DenseMap
<DeltaRational
>& nv
, ArithVar v
) const{
54 return nv
[v
] == d_variables
.getAssignment(v
);
57 Result::Sat
AttemptSolutionSDP::attempt(const ApproximateSimplex::Solution
& sol
){
58 const DenseSet
& newBasis
= sol
.newBasis
;
59 const DenseMap
<DeltaRational
>& newValues
= sol
.newValues
;
61 DenseSet needsToBeAdded
;
62 for(DenseSet::const_iterator i
= newBasis
.begin(), i_end
= newBasis
.end(); i
!= i_end
; ++i
){
64 if(!d_tableau
.isBasic(b
)){
65 needsToBeAdded
.add(b
);
68 DenseMap
<DeltaRational
>::const_iterator nvi
= newValues
.begin(), nvi_end
= newValues
.end();
69 for(; nvi
!= nvi_end
; ++nvi
){
70 ArithVar currentlyNb
= *nvi
;
71 if(!d_tableau
.isBasic(currentlyNb
)){
72 if(!matchesNewValue(newValues
, currentlyNb
)){
73 const DeltaRational
& newValue
= newValues
[currentlyNb
];
74 Trace("arith::updateMany")
75 << "updateMany:" << currentlyNb
<< " "
76 << d_variables
.getAssignment(currentlyNb
) << " to "<< newValue
<< endl
;
77 d_linEq
.update(currentlyNb
, newValue
);
78 Assert(d_variables
.assignmentIsConsistent(currentlyNb
));
82 d_errorSet
.reduceToSignals();
83 d_errorSet
.setSelectionRule(options::ErrorSelectionRule::VAR_ORDER
);
85 static int instance
= 0;
89 Debug("arith::findModel") << "attemptSolution("<< instance
<<") early conflict" << endl
;
90 d_conflictVariables
.purge();
92 }else if(d_errorSet
.errorEmpty()){
93 Debug("arith::findModel") << "attemptSolution("<< instance
<<") fixed itself" << endl
;
97 while(!needsToBeAdded
.empty() && !d_errorSet
.errorEmpty()){
98 ArithVar toRemove
= ARITHVAR_SENTINEL
;
99 ArithVar toAdd
= ARITHVAR_SENTINEL
;
100 DenseSet::const_iterator i
= needsToBeAdded
.begin(), i_end
= needsToBeAdded
.end();
101 for(; toAdd
== ARITHVAR_SENTINEL
&& i
!= i_end
; ++i
){
104 Tableau::ColIterator colIter
= d_tableau
.colIterator(v
);
105 for(; !colIter
.atEnd(); ++colIter
){
106 const Tableau::Entry
& entry
= *colIter
;
107 Assert(entry
.getColVar() == v
);
108 ArithVar b
= d_tableau
.rowIndexToBasic(entry
.getRowIndex());
109 if(!newBasis
.isMember(b
)){
112 bool favorBOverToRemove
=
113 (toRemove
== ARITHVAR_SENTINEL
) ||
114 (matchesNewValue(newValues
, toRemove
) && !matchesNewValue(newValues
, b
)) ||
115 (d_tableau
.basicRowLength(toRemove
) > d_tableau
.basicRowLength(b
));
117 if(favorBOverToRemove
){
123 Assert(toRemove
!= ARITHVAR_SENTINEL
);
124 Assert(toAdd
!= ARITHVAR_SENTINEL
);
126 Trace("arith::forceNewBasis") << toRemove
<< " " << toAdd
<< endl
;
128 d_linEq
.pivotAndUpdate(toRemove
, toAdd
, newValues
[toRemove
]);
130 Trace("arith::forceNewBasis") << needsToBeAdded
.size() << "to go" << endl
;
131 needsToBeAdded
.remove(toAdd
);
133 bool conflict
= processSignals();
135 d_errorSet
.reduceToSignals();
136 d_conflictVariables
.purge();
138 return Result::UNSAT
;
141 Assert(d_conflictVariables
.empty());
143 if(d_errorSet
.errorEmpty()){
146 d_errorSet
.reduceToSignals();
147 return Result::SAT_UNKNOWN
;
152 } // namespace theory