1 /******************************************************************************
2 * Top contributors (to current version):
3 * Tim King, Morgan Deters, 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 * This is an implementation of the Simplex Module for the Simplex for
14 * DPLL(T)decision procedure.
16 * This implements the Simplex module for the Simpelx for DPLL(T) decision
18 * See the Simplex for DPLL(T) technical report for more background.(citation?)
19 * This shares with the theory a Tableau, and a PartialModel that:
20 * - satisfies the equalities in the Tableau, and
21 * - the assignment for the non-basic variables satisfies their bounds.
22 * This is required to either produce a conflict or satisifying PartialModel.
23 * Further, we require being told when a basic variable updates its value.
25 * During the Simplex search we maintain a queue of variables.
26 * The queue is required to contain all of the basic variables that voilate
28 * As elimination from the queue is more efficient to be done lazily,
29 * we do not maintain that the queue of variables needs to be only basic
30 * variables or only variables that satisfy their bounds.
32 * The simplex procedure roughly follows Alberto's thesis. (citation?)
33 * There is one round of selecting using a heuristic pivoting rule.
34 * (See PreferenceFunction Documentation for the available options.)
35 * The non-basic variable is the one that appears in the fewest pivots.
36 * (Bruno says that Leonardo invented this first.)
37 * After this, Bland's pivot rule is invoked.
39 * During this proccess, we periodically inspect the queue of variables to
40 * 1) remove now extraneous extries,
41 * 2) detect conflicts that are "waiting" on the queue but may not be detected
42 * by the current queue heuristics, and
43 * 3) detect multiple conflicts.
45 * Conflicts are greedily slackened to use the weakest bounds that still
46 * produce the conflict.
48 * Extra things tracked atm: (Subject to change at Tim's whims)
49 * - A superset of all of the newly pivoted variables.
50 * - A queue of additional conflicts that were discovered by Simplex.
51 * These are theory valid and are currently turned into lemmas
54 #include "cvc5_private.h"
58 #include "theory/arith/error_set.h"
59 #include "theory/arith/linear_equality.h"
60 #include "theory/arith/simplex.h"
61 #include "theory/arith/simplex_update.h"
62 #include "util/dense_map.h"
63 #include "util/statistics_stats.h"
69 class FCSimplexDecisionProcedure
: public SimplexDecisionProcedure
{
71 FCSimplexDecisionProcedure(Env
& env
,
72 LinearEqualityModule
& linEq
,
74 RaiseConflict conflictChannel
,
75 TempVarMalloc tvmalloc
);
77 Result::Sat
findModel(bool exactResult
) override
;
79 // other error variables are dropping
80 WitnessImprovement
dualLikeImproveError(ArithVar evar
);
81 WitnessImprovement
primalImproveError(ArithVar evar
);
85 // - satisfied error set
86 Result::Sat
dualLike();
89 static const uint32_t PENALTY
= 4;
90 DenseMultiset d_scores
;
91 void decreasePenalties(){ d_scores
.removeOneOfEverything(); }
92 uint32_t penalty(ArithVar x
) const { return d_scores
.count(x
); }
93 void setPenalty(ArithVar x
, WitnessImprovement w
){
95 if(d_scores
.count(x
) > 0){
96 d_scores
.removeAll(x
);
99 d_scores
.setCount(x
, PENALTY
);
103 /** The size of the focus set. */
104 uint32_t d_focusSize
;
106 /** The current error focus variable. */
107 ArithVar d_focusErrorVar
;
110 * The signs of the coefficients in the focus set.
111 * This is empty until this has been loaded.
113 DenseMap
<const Rational
*> d_focusCoefficients
;
116 * Loads the signs of the coefficients of the variables on the row d_focusErrorVar
119 void loadFocusSigns();
121 /** Unloads the information from d_focusSgns. */
122 void unloadFocusSigns();
125 * The signs of a variable in the row of d_focusErrorVar.
126 * d_focusSgns must be loaded.
128 const Rational
& focusCoefficient(ArithVar nb
) const;
130 int32_t d_pivotBudget
;
131 // enum PivotImprovement {
134 // HeuristicDegenerate,
138 WitnessImprovement d_prevWitnessImprovement
;
139 uint32_t d_witnessImprovementInARow
;
141 uint32_t degeneratePivotsInARow() const;
143 static const uint32_t s_focusThreshold
= 6;
144 static const uint32_t s_maxDegeneratePivotsBeforeBlandsOnLeaving
= 100;
145 static const uint32_t s_maxDegeneratePivotsBeforeBlandsOnEntering
= 10;
147 DenseMap
<uint32_t> d_leavingCountSinceImprovement
;
148 void increaseLeavingCount(ArithVar x
){
149 if(!d_leavingCountSinceImprovement
.isKey(x
)){
150 d_leavingCountSinceImprovement
.set(x
,1);
152 (d_leavingCountSinceImprovement
.get(x
))++;
155 LinearEqualityModule::UpdatePreferenceFunction
selectLeavingFunction(ArithVar x
){
156 bool useBlands
= d_leavingCountSinceImprovement
.isKey(x
) &&
157 d_leavingCountSinceImprovement
[x
] >= s_maxDegeneratePivotsBeforeBlandsOnEntering
;
159 return &LinearEqualityModule::preferWitness
<false>;
161 return &LinearEqualityModule::preferWitness
<true>;
165 bool debugDualLike(WitnessImprovement w
, std::ostream
& out
,
167 uint32_t prevFocusSize
, uint32_t prevErrorSize
) const;
169 void debugPrintSignal(ArithVar updated
) const;
171 ArithVarVec d_sgnDisagreements
;
173 //static PivotImprovement pivotImprovement(const UpdateInfo& selected, bool useBlands = false);
175 void logPivot(WitnessImprovement w
);
177 void updateAndSignal(const UpdateInfo
& selected
, WitnessImprovement w
);
179 UpdateInfo
selectPrimalUpdate(ArithVar error
,
180 LinearEqualityModule::UpdatePreferenceFunction upf
,
181 LinearEqualityModule::VarPreferenceFunction bpf
);
184 UpdateInfo
selectUpdateForDualLike(ArithVar basic
){
185 TimerStat::CodeTimer
codeTimer(d_statistics
.d_selectUpdateForDualLike
);
187 LinearEqualityModule::UpdatePreferenceFunction upf
=
188 &LinearEqualityModule::preferWitness
<true>;
189 LinearEqualityModule::VarPreferenceFunction bpf
=
190 &LinearEqualityModule::minVarOrder
;
191 return selectPrimalUpdate(basic
, upf
, bpf
);
194 UpdateInfo
selectUpdateForPrimal(ArithVar basic
, bool useBlands
){
195 TimerStat::CodeTimer
codeTimer(d_statistics
.d_selectUpdateForPrimal
);
197 LinearEqualityModule::UpdatePreferenceFunction upf
;
199 upf
= &LinearEqualityModule::preferWitness
<false>;
201 upf
= &LinearEqualityModule::preferWitness
<true>;
204 LinearEqualityModule::VarPreferenceFunction bpf
= useBlands
?
205 &LinearEqualityModule::minVarOrder
:
206 &LinearEqualityModule::minRowLength
;
208 return selectPrimalUpdate(basic
, upf
, bpf
);
210 WitnessImprovement
selectFocusImproving() ;
212 WitnessImprovement
focusUsingSignDisagreements(ArithVar basic
);
213 WitnessImprovement
focusDownToLastHalf();
214 WitnessImprovement
adjustFocusShrank(const ArithVarVec
& drop
);
215 WitnessImprovement
focusDownToJust(ArithVar v
);
218 void adjustFocusAndError(const UpdateInfo
& up
, const AVIntPairVec
& focusChanges
);
221 * This is the main simplex for DPLL(T) loop.
222 * It runs for at most maxIterations.
224 * Returns true iff it has found a conflict.
225 * d_conflictVariable will be set and the conflict for this row is reported.
227 bool searchForFeasibleSolution(uint32_t maxIterations
);
229 bool initialProcessSignals(){
230 TimerStat
&timer
= d_statistics
.d_initialSignalsTime
;
231 IntStat
& conflictStat
= d_statistics
.d_initialConflicts
;
232 bool res
= standardProcessSignals(timer
, conflictStat
);
233 d_focusSize
= d_errorSet
.focusSize();
237 static bool debugCheckWitness(const UpdateInfo
& inf
, WitnessImprovement w
, bool useBlands
);
239 /** These fields are designed to be accessible to TheoryArith methods. */
242 TimerStat d_initialSignalsTime
;
243 IntStat d_initialConflicts
;
245 IntStat d_fcFoundUnsat
;
246 IntStat d_fcFoundSat
;
250 TimerStat d_fcFocusConstructionTimer
;
252 TimerStat d_selectUpdateForDualLike
;
253 TimerStat d_selectUpdateForPrimal
;
255 ReferenceStat
<uint32_t> d_finalCheckPivotCounter
;
257 Statistics(const std::string
& name
, uint32_t& pivots
);
259 };/* class FCSimplexDecisionProcedure */
262 } // namespace theory