1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Tim King, Morgan Deters, 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 |
|
* This is an implementation of the Simplex Module for the Simplex for |
14 |
|
* DPLL(T) decision procedure. |
15 |
|
* |
16 |
|
* This implements the Simplex module for the Simpelx for DPLL(T) decision |
17 |
|
* procedure. |
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. |
24 |
|
* |
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 |
27 |
|
* their bounds. |
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. |
31 |
|
* |
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. |
38 |
|
* |
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. |
44 |
|
* |
45 |
|
* Conflicts are greedily slackened to use the weakest bounds that still |
46 |
|
* produce the conflict. |
47 |
|
* |
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 |
52 |
|
*/ |
53 |
|
|
54 |
|
#include "cvc5_private.h" |
55 |
|
|
56 |
|
#pragma once |
57 |
|
|
58 |
|
#include "theory/arith/linear_equality.h" |
59 |
|
#include "theory/arith/simplex.h" |
60 |
|
#include "theory/arith/simplex_update.h" |
61 |
|
#include "util/dense_map.h" |
62 |
|
#include "util/statistics_stats.h" |
63 |
|
|
64 |
|
namespace cvc5 { |
65 |
|
namespace theory { |
66 |
|
namespace arith { |
67 |
|
|
68 |
9853 |
class SumOfInfeasibilitiesSPD : public SimplexDecisionProcedure { |
69 |
|
public: |
70 |
|
SumOfInfeasibilitiesSPD(LinearEqualityModule& linEq, ErrorSet& errors, RaiseConflict conflictChannel, TempVarMalloc tvmalloc); |
71 |
|
|
72 |
|
Result::Sat findModel(bool exactResult) override; |
73 |
|
|
74 |
|
// other error variables are dropping |
75 |
|
WitnessImprovement dualLikeImproveError(ArithVar evar); |
76 |
|
WitnessImprovement primalImproveError(ArithVar evar); |
77 |
|
|
78 |
|
private: |
79 |
|
/** The current sum of infeasibilities variable. */ |
80 |
|
ArithVar d_soiVar; |
81 |
|
|
82 |
|
// dual like |
83 |
|
// - found conflict |
84 |
|
// - satisfied error set |
85 |
|
Result::Sat sumOfInfeasibilities(); |
86 |
|
|
87 |
|
// static const uint32_t PENALTY = 4; |
88 |
|
// DenseMultiset d_scores; |
89 |
|
// void decreasePenalties(){ d_scores.removeOneOfEverything(); } |
90 |
|
// uint32_t penalty(ArithVar x) const { return d_scores.count(x); } |
91 |
|
// void setPenalty(ArithVar x, WitnessImprovement w){ |
92 |
|
// if(improvement(w)){ |
93 |
|
// if(d_scores.count(x) > 0){ |
94 |
|
// d_scores.removeAll(x); |
95 |
|
// } |
96 |
|
// }else{ |
97 |
|
// d_scores.setCount(x, PENALTY); |
98 |
|
// } |
99 |
|
// } |
100 |
|
|
101 |
|
int32_t d_pivotBudget; |
102 |
|
// enum PivotImprovement { |
103 |
|
// ErrorDropped, |
104 |
|
// NonDegenerate, |
105 |
|
// HeuristicDegenerate, |
106 |
|
// BlandsDegenerate |
107 |
|
// }; |
108 |
|
|
109 |
|
WitnessImprovement d_prevWitnessImprovement; |
110 |
|
uint32_t d_witnessImprovementInARow; |
111 |
|
|
112 |
|
uint32_t degeneratePivotsInARow() const; |
113 |
|
|
114 |
|
static const uint32_t s_focusThreshold = 6; |
115 |
|
static const uint32_t s_maxDegeneratePivotsBeforeBlandsOnLeaving = 100; |
116 |
|
static const uint32_t s_maxDegeneratePivotsBeforeBlandsOnEntering = 10; |
117 |
|
|
118 |
|
DenseMap<uint32_t> d_leavingCountSinceImprovement; |
119 |
|
void increaseLeavingCount(ArithVar x){ |
120 |
|
if(!d_leavingCountSinceImprovement.isKey(x)){ |
121 |
|
d_leavingCountSinceImprovement.set(x,1); |
122 |
|
}else{ |
123 |
|
(d_leavingCountSinceImprovement.get(x))++; |
124 |
|
} |
125 |
|
} |
126 |
|
LinearEqualityModule::UpdatePreferenceFunction selectLeavingFunction(ArithVar x){ |
127 |
|
bool useBlands = d_leavingCountSinceImprovement.isKey(x) && |
128 |
|
d_leavingCountSinceImprovement[x] >= s_maxDegeneratePivotsBeforeBlandsOnEntering; |
129 |
|
if(useBlands) { |
130 |
|
return &LinearEqualityModule::preferWitness<false>; |
131 |
|
} else { |
132 |
|
return &LinearEqualityModule::preferWitness<true>; |
133 |
|
} |
134 |
|
} |
135 |
|
|
136 |
|
bool debugSOI(WitnessImprovement w, std::ostream& out, int instance) const; |
137 |
|
|
138 |
|
void debugPrintSignal(ArithVar updated) const; |
139 |
|
|
140 |
|
ArithVarVec d_sgnDisagreements; |
141 |
|
|
142 |
|
void logPivot(WitnessImprovement w); |
143 |
|
|
144 |
|
void updateAndSignal(const UpdateInfo& selected, WitnessImprovement w); |
145 |
|
|
146 |
|
UpdateInfo selectUpdate(LinearEqualityModule::UpdatePreferenceFunction upf, |
147 |
|
LinearEqualityModule::VarPreferenceFunction bpf); |
148 |
|
|
149 |
|
|
150 |
|
// UpdateInfo selectUpdateForDualLike(ArithVar basic){ |
151 |
|
// TimerStat::CodeTimer codeTimer(d_statistics.d_selectUpdateForDualLike); |
152 |
|
|
153 |
|
// LinearEqualityModule::UpdatePreferenceFunction upf = |
154 |
|
// &LinearEqualityModule::preferWitness<true>; |
155 |
|
// LinearEqualityModule::VarPreferenceFunction bpf = |
156 |
|
// &LinearEqualityModule::minVarOrder; |
157 |
|
// return selectPrimalUpdate(basic, upf, bpf); |
158 |
|
// } |
159 |
|
|
160 |
|
// UpdateInfo selectUpdateForPrimal(ArithVar basic, bool useBlands){ |
161 |
|
// TimerStat::CodeTimer codeTimer(d_statistics.d_selectUpdateForPrimal); |
162 |
|
|
163 |
|
// LinearEqualityModule::UpdatePreferenceFunction upf = useBlands ? |
164 |
|
// &LinearEqualityModule::preferWitness<false>: |
165 |
|
// &LinearEqualityModule::preferWitness<true>; |
166 |
|
|
167 |
|
// LinearEqualityModule::VarPreferenceFunction bpf = useBlands ? |
168 |
|
// &LinearEqualityModule::minVarOrder : |
169 |
|
// &LinearEqualityModule::minRowLength; |
170 |
|
// bpf = &LinearEqualityModule::minVarOrder; |
171 |
|
|
172 |
|
// return selectPrimalUpdate(basic, upf, bpf); |
173 |
|
// } |
174 |
|
// WitnessImprovement selectFocusImproving() ; |
175 |
|
WitnessImprovement soiRound(); |
176 |
|
WitnessImprovement SOIConflict(); |
177 |
|
std::vector< ArithVarVec > greedyConflictSubsets(); |
178 |
|
bool generateSOIConflict(const ArithVarVec& subset); |
179 |
|
|
180 |
|
// WitnessImprovement focusUsingSignDisagreements(ArithVar basic); |
181 |
|
// WitnessImprovement focusDownToLastHalf(); |
182 |
|
// WitnessImprovement adjustFocusShrank(const ArithVarVec& drop); |
183 |
|
// WitnessImprovement focusDownToJust(ArithVar v); |
184 |
|
|
185 |
|
|
186 |
|
void adjustFocusAndError(const UpdateInfo& up, const AVIntPairVec& focusChanges); |
187 |
|
|
188 |
|
/** |
189 |
|
* This is the main simplex for DPLL(T) loop. |
190 |
|
* It runs for at most maxIterations. |
191 |
|
* |
192 |
|
* Returns true iff it has found a conflict. |
193 |
|
* d_conflictVariable will be set and the conflict for this row is reported. |
194 |
|
*/ |
195 |
|
bool searchForFeasibleSolution(uint32_t maxIterations); |
196 |
|
|
197 |
|
bool initialProcessSignals(){ |
198 |
|
TimerStat &timer = d_statistics.d_initialSignalsTime; |
199 |
|
IntStat& conflictStat = d_statistics.d_initialConflicts; |
200 |
|
return standardProcessSignals(timer, conflictStat); |
201 |
|
} |
202 |
|
|
203 |
|
void quickExplain(); |
204 |
|
DenseSet d_qeInSoi; |
205 |
|
DenseSet d_qeInUAndNotInSoi; |
206 |
|
ArithVarVec d_qeConflict; |
207 |
|
ArithVarVec d_qeGreedyOrder; |
208 |
|
sgn_table d_qeSgns; |
209 |
|
|
210 |
|
uint32_t quickExplainRec(uint32_t cEnd, uint32_t uEnd); |
211 |
|
void qeAddRange(uint32_t begin, uint32_t end); |
212 |
|
void qeRemoveRange(uint32_t begin, uint32_t end); |
213 |
|
void qeSwapRange(uint32_t N, uint32_t r, uint32_t s); |
214 |
|
|
215 |
|
unsigned trySet(const ArithVarVec& set); |
216 |
|
unsigned tryAllSubsets(const ArithVarVec& set, unsigned depth, ArithVarVec& tmp); |
217 |
|
|
218 |
|
/** These fields are designed to be accessible to TheoryArith methods. */ |
219 |
9853 |
class Statistics { |
220 |
|
public: |
221 |
|
TimerStat d_initialSignalsTime; |
222 |
|
IntStat d_initialConflicts; |
223 |
|
|
224 |
|
IntStat d_soiFoundUnsat; |
225 |
|
IntStat d_soiFoundSat; |
226 |
|
IntStat d_soiMissed; |
227 |
|
|
228 |
|
IntStat d_soiConflicts; |
229 |
|
IntStat d_hasToBeMinimal; |
230 |
|
IntStat d_maybeNotMinimal; |
231 |
|
|
232 |
|
TimerStat d_soiTimer; |
233 |
|
TimerStat d_soiFocusConstructionTimer; |
234 |
|
TimerStat d_soiConflictMinimization; |
235 |
|
TimerStat d_selectUpdateForSOI; |
236 |
|
|
237 |
|
ReferenceStat<uint32_t> d_finalCheckPivotCounter; |
238 |
|
|
239 |
|
Statistics(const std::string& name, uint32_t& pivots); |
240 |
|
} d_statistics; |
241 |
|
};/* class FCSimplexDecisionProcedure */ |
242 |
|
|
243 |
|
} // namespace arith |
244 |
|
} // namespace theory |
245 |
|
} // namespace cvc5 |