Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * This file is part of the cvc5 project. 3 : : * 4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS 5 : : * in the top-level source directory and their institutional affiliations. 6 : : * All rights reserved. See the file COPYING in the top-level source 7 : : * directory for licensing information. 8 : : * **************************************************************************** 9 : : * 10 : : * This is an implementation of the Simplex Module for the Simplex for 11 : : * DPLL(T) decision procedure. 12 : : * 13 : : * This implements the Simplex module for the Simpelx for DPLL(T) decision 14 : : * procedure. 15 : : * See the Simplex for DPLL(T) technical report for more background.(citation?) 16 : : * This shares with the theory a Tableau, and a PartialModel that: 17 : : * - satisfies the equalities in the Tableau, and 18 : : * - the assignment for the non-basic variables satisfies their bounds. 19 : : * This is required to either produce a conflict or satisifying PartialModel. 20 : : * Further, we require being told when a basic variable updates its value. 21 : : * 22 : : * During the Simplex search we maintain a queue of variables. 23 : : * The queue is required to contain all of the basic variables that voilate 24 : : * their bounds. 25 : : * As elimination from the queue is more efficient to be done lazily, 26 : : * we do not maintain that the queue of variables needs to be only basic 27 : : * variables or only variables that satisfy their bounds. 28 : : * 29 : : * The simplex procedure roughly follows Alberto's thesis. (citation?) 30 : : * There is one round of selecting using a heuristic pivoting rule. 31 : : * (See PreferenceFunction Documentation for the available options.) 32 : : * The non-basic variable is the one that appears in the fewest pivots. 33 : : * (Bruno says that Leonardo invented this first.) 34 : : * After this, Bland's pivot rule is invoked. 35 : : * 36 : : * During this process, we periodically inspect the queue of variables to 37 : : * 1) remove now extraneous extries, 38 : : * 2) detect conflicts that are "waiting" on the queue but may not be detected 39 : : * by the current queue heuristics, and 40 : : * 3) detect multiple conflicts. 41 : : * 42 : : * Conflicts are greedily slackened to use the weakest bounds that still 43 : : * produce the conflict. 44 : : * 45 : : * Extra things tracked atm: (Subject to change at Tim's whims) 46 : : * - A superset of all of the newly pivoted variables. 47 : : * - A queue of additional conflicts that were discovered by Simplex. 48 : : * These are theory valid and are currently turned into lemmas 49 : : */ 50 : : 51 : : #include "cvc5_private.h" 52 : : 53 : : #pragma once 54 : : 55 : : #include "theory/arith/linear/linear_equality.h" 56 : : #include "theory/arith/linear/simplex.h" 57 : : #include "theory/arith/linear/simplex_update.h" 58 : : #include "util/dense_map.h" 59 : : #include "util/statistics_stats.h" 60 : : 61 : : namespace cvc5::internal { 62 : : namespace theory { 63 : : namespace arith::linear { 64 : : 65 : : class SumOfInfeasibilitiesSPD : public SimplexDecisionProcedure 66 : : { 67 : : public: 68 : : SumOfInfeasibilitiesSPD(Env& env, 69 : : LinearEqualityModule& linEq, 70 : : ErrorSet& errors, 71 : : RaiseConflict conflictChannel, 72 : : TempVarMalloc tvmalloc); 73 : : 74 : : Result::Status findModel(bool exactResult) override; 75 : : 76 : : // other error variables are dropping 77 : : WitnessImprovement dualLikeImproveError(ArithVar evar); 78 : : WitnessImprovement primalImproveError(ArithVar evar); 79 : : 80 : : private: 81 : : /** The current sum of infeasibilities variable. */ 82 : : ArithVar d_soiVar; 83 : : 84 : : // dual like 85 : : // - found conflict 86 : : // - satisfied error set 87 : : Result::Status sumOfInfeasibilities(); 88 : : 89 : : int32_t d_pivotBudget; 90 : : 91 : : WitnessImprovement d_prevWitnessImprovement; 92 : : uint32_t d_witnessImprovementInARow; 93 : : 94 : : uint32_t degeneratePivotsInARow() const; 95 : : 96 : : static constexpr uint32_t s_focusThreshold = 6; 97 : : static constexpr uint32_t s_maxDegeneratePivotsBeforeBlandsOnLeaving = 100; 98 : : static constexpr uint32_t s_maxDegeneratePivotsBeforeBlandsOnEntering = 10; 99 : : 100 : : DenseMap<uint32_t> d_leavingCountSinceImprovement; 101 : 7918 : void increaseLeavingCount(ArithVar x) 102 : : { 103 [ + - ]: 7918 : if (!d_leavingCountSinceImprovement.isKey(x)) 104 : : { 105 : 7918 : d_leavingCountSinceImprovement.set(x, 1); 106 : : } 107 : : else 108 : : { 109 : 0 : (d_leavingCountSinceImprovement.get(x))++; 110 : : } 111 : 7918 : } 112 : 28349 : LinearEqualityModule::UpdatePreferenceFunction selectLeavingFunction( 113 : : ArithVar x) 114 : : { 115 : 28349 : bool useBlands = d_leavingCountSinceImprovement.isKey(x) 116 [ - + ]: 28349 : && d_leavingCountSinceImprovement[x] 117 [ - - ]: 0 : >= s_maxDegeneratePivotsBeforeBlandsOnEntering; 118 [ - + ]: 28349 : if (useBlands) 119 : : { 120 : 0 : return &LinearEqualityModule::preferWitness<false>; 121 : : } 122 : : else 123 : : { 124 : 28349 : return &LinearEqualityModule::preferWitness<true>; 125 : : } 126 : : } 127 : : 128 : : void debugPrintSignal(ArithVar updated) const; 129 : : 130 : : ArithVarVec d_sgnDisagreements; 131 : : 132 : : void logPivot(WitnessImprovement w); 133 : : 134 : : void updateAndSignal(const UpdateInfo& selected); 135 : : 136 : : UpdateInfo selectUpdate(LinearEqualityModule::UpdatePreferenceFunction upf); 137 : : 138 : : // UpdateInfo selectUpdateForDualLike(ArithVar basic){ 139 : : // TimerStat::CodeTimer codeTimer(d_statistics.d_selectUpdateForDualLike); 140 : : 141 : : // LinearEqualityModule::UpdatePreferenceFunction upf = 142 : : // &LinearEqualityModule::preferWitness<true>; 143 : : // LinearEqualityModule::VarPreferenceFunction bpf = 144 : : // &LinearEqualityModule::minVarOrder; 145 : : // return selectPrimalUpdate(basic, upf, bpf); 146 : : // } 147 : : 148 : : // UpdateInfo selectUpdateForPrimal(ArithVar basic, bool useBlands){ 149 : : // TimerStat::CodeTimer codeTimer(d_statistics.d_selectUpdateForPrimal); 150 : : 151 : : // LinearEqualityModule::UpdatePreferenceFunction upf = useBlands ? 152 : : // &LinearEqualityModule::preferWitness<false>: 153 : : // &LinearEqualityModule::preferWitness<true>; 154 : : 155 : : // LinearEqualityModule::VarPreferenceFunction bpf = useBlands ? 156 : : // &LinearEqualityModule::minVarOrder : 157 : : // &LinearEqualityModule::minRowLength; 158 : : // bpf = &LinearEqualityModule::minVarOrder; 159 : : 160 : : // return selectPrimalUpdate(basic, upf, bpf); 161 : : // } 162 : : // WitnessImprovement selectFocusImproving() ; 163 : : WitnessImprovement soiRound(); 164 : : WitnessImprovement SOIConflict(); 165 : : std::vector<ArithVarVec> greedyConflictSubsets(); 166 : : bool generateSOIConflict(const ArithVarVec& subset); 167 : : 168 : : // WitnessImprovement focusUsingSignDisagreements(ArithVar basic); 169 : : // WitnessImprovement focusDownToLastHalf(); 170 : : // WitnessImprovement adjustFocusShrank(const ArithVarVec& drop); 171 : : // WitnessImprovement focusDownToJust(ArithVar v); 172 : : 173 : : void adjustFocusAndError(const AVIntPairVec& focusChanges); 174 : : 175 : : /** 176 : : * This is the main simplex for DPLL(T) loop. 177 : : * It runs for at most maxIterations. 178 : : * 179 : : * Returns true iff it has found a conflict. 180 : : * d_conflictVariable will be set and the conflict for this row is reported. 181 : : */ 182 : : bool searchForFeasibleSolution(uint32_t maxIterations); 183 : : 184 : 14189 : bool initialProcessSignals() 185 : : { 186 : 14189 : TimerStat& timer = d_statistics.d_initialSignalsTime; 187 : 14189 : IntStat& conflictStat = d_statistics.d_initialConflicts; 188 : 14189 : return standardProcessSignals(timer, conflictStat); 189 : : } 190 : : 191 : : void quickExplain(); 192 : : DenseSet d_qeInSoi; 193 : : DenseSet d_qeInUAndNotInSoi; 194 : : ArithVarVec d_qeConflict; 195 : : ArithVarVec d_qeGreedyOrder; 196 : : sgn_table d_qeSgns; 197 : : 198 : : uint32_t quickExplainRec(uint32_t cEnd, uint32_t uEnd); 199 : : void qeAddRange(uint32_t begin, uint32_t end); 200 : : void qeRemoveRange(uint32_t begin, uint32_t end); 201 : : void qeSwapRange(uint32_t N, uint32_t r, uint32_t s); 202 : : 203 : : unsigned trySet(const ArithVarVec& set); 204 : : unsigned tryAllSubsets(const ArithVarVec& set, 205 : : unsigned depth, 206 : : ArithVarVec& tmp); 207 : : 208 : : /** These fields are designed to be accessible to TheoryArith methods. */ 209 : : class Statistics 210 : : { 211 : : public: 212 : : TimerStat d_initialSignalsTime; 213 : : IntStat d_initialConflicts; 214 : : 215 : : IntStat d_soiFoundUnsat; 216 : : IntStat d_soiFoundSat; 217 : : IntStat d_soiMissed; 218 : : 219 : : IntStat d_soiConflicts; 220 : : IntStat d_hasToBeMinimal; 221 : : IntStat d_maybeNotMinimal; 222 : : 223 : : TimerStat d_soiTimer; 224 : : TimerStat d_soiFocusConstructionTimer; 225 : : TimerStat d_soiConflictMinimization; 226 : : TimerStat d_selectUpdateForSOI; 227 : : 228 : : ReferenceStat<uint32_t> d_finalCheckPivotCounter; 229 : : 230 : : Statistics(StatisticsRegistry& sr, 231 : : const std::string& name, 232 : : uint32_t& pivots); 233 : : } d_statistics; 234 : : }; /* class FCSimplexDecisionProcedure */ 235 : : 236 : : } // namespace arith::linear 237 : : } // namespace theory 238 : : } // namespace cvc5::internal