void IterationWorker::doAction() { // do iterations while shut down flag is true while (!getShutDown()) { // do one iteration of computation cycle iterate(); // serve signals processSignals(); } }
//corresponds to Check() in dM06 //template <SimplexDecisionProcedure::PreferenceFunction pf> bool DualSimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingIterations){ TimerStat::CodeTimer codeTimer(d_statistics.d_searchTime); Debug("arith") << "searchForFeasibleSolution" << endl; Assert(remainingIterations > 0); while(remainingIterations > 0 && !d_errorSet.focusEmpty()){ if(Debug.isOn("paranoid:check_tableau")){ d_linEq.debugCheckTableau(); } Assert(d_conflictVariables.empty()); ArithVar x_i = d_errorSet.topFocusVariable(); Debug("arith::update::select") << "selectSmallestInconsistentVar()=" << x_i << endl; if(x_i == ARITHVAR_SENTINEL){ Debug("arith::update") << "No inconsistent variables" << endl; return false; //sat } --remainingIterations; bool useVarOrderPivot = d_pivotsInRound.count(x_i) >= options::arithPivotThreshold(); if(!useVarOrderPivot){ d_pivotsInRound.add(x_i); } Debug("arith::update") << "pivots in rounds: " << d_pivotsInRound.count(x_i) << " use " << useVarOrderPivot << " threshold " << options::arithPivotThreshold() << endl; LinearEqualityModule::VarPreferenceFunction pf = useVarOrderPivot ? &LinearEqualityModule::minVarOrder : &LinearEqualityModule::minBoundAndColLength; //DeltaRational beta_i = d_variables.getAssignment(x_i); ArithVar x_j = ARITHVAR_SENTINEL; int32_t prevErrorSize CVC4_UNUSED = d_errorSet.errorSize(); if(d_variables.cmpAssignmentLowerBound(x_i) < 0 ){ x_j = d_linEq.selectSlackUpperBound(x_i, pf); if(x_j == ARITHVAR_SENTINEL ){ Unreachable(); // ++(d_statistics.d_statUpdateConflicts); // reportConflict(x_i); // ++(d_statistics.d_simplexConflicts); // Node conflict = d_linEq.generateConflictBelowLowerBound(x_i); //unsat // d_conflictVariable = x_i; // reportConflict(conflict); // return true; }else{ const DeltaRational& l_i = d_variables.getLowerBound(x_i); d_linEq.pivotAndUpdate(x_i, x_j, l_i); } }else if(d_variables.cmpAssignmentUpperBound(x_i) > 0){ x_j = d_linEq.selectSlackLowerBound(x_i, pf); if(x_j == ARITHVAR_SENTINEL ){ Unreachable(); // ++(d_statistics.d_statUpdateConflicts); // reportConflict(x_i); // ++(d_statistics.d_simplexConflicts); // Node conflict = d_linEq.generateConflictAboveUpperBound(x_i); //unsat // d_conflictVariable = x_i; // reportConflict(conflict); // return true; }else{ const DeltaRational& u_i = d_variables.getUpperBound(x_i); d_linEq.pivotAndUpdate(x_i, x_j, u_i); } } Assert(x_j != ARITHVAR_SENTINEL); bool conflict = processSignals(); int32_t currErrorSize CVC4_UNUSED = d_errorSet.errorSize(); d_pivots++; if(Debug.isOn("arith::dual")){ Debug("arith::dual") << "#" << d_pivots << " c" << conflict << " d" << (prevErrorSize - currErrorSize) << " f" << d_errorSet.inError(x_j) << " h" << d_conflictVariables.isMember(x_j) << " " << x_i << "->" << x_j << endl; } if(conflict){ return true; } } Assert(!d_errorSet.focusEmpty() || d_errorSet.errorEmpty()); Assert(remainingIterations == 0 || d_errorSet.focusEmpty()); Assert(d_errorSet.noSignals()); return false; }
Result::Sat DualSimplexDecisionProcedure::dualFindModel(bool exactResult){ Assert(d_conflictVariables.empty()); static thread_local unsigned int instance = 0; instance = instance + 1; d_pivots = 0; if(d_errorSet.errorEmpty() && !d_errorSet.moreSignals()){ Debug("arith::findModel") << "dualFindModel("<< instance <<") trivial" << endl; return Result::SAT; } // We need to reduce this because of d_errorSet.reduceToSignals(); d_errorSet.setSelectionRule(VAR_ORDER); if(processSignals()){ d_conflictVariables.purge(); Debug("arith::findModel") << "dualFindModel("<< instance <<") early conflict" << endl; return Result::UNSAT; }else if(d_errorSet.errorEmpty()){ Debug("arith::findModel") << "dualFindModel("<< instance <<") fixed itself" << endl; Assert(!d_errorSet.moreSignals()); return Result::SAT; } Debug("arith::findModel") << "dualFindModel(" << instance <<") start non-trivial" << endl; Result::Sat result = Result::SAT_UNKNOWN; static const bool verbose = false; exactResult |= options::arithStandardCheckVarOrderPivots() < 0; uint32_t checkPeriod = options::arithSimplexCheckPeriod(); if(result == Result::SAT_UNKNOWN){ uint32_t numDifferencePivots = options::arithHeuristicPivots() < 0 ? d_numVariables + 1 : options::arithHeuristicPivots(); // The signed to unsigned conversion is safe. if(numDifferencePivots > 0){ d_errorSet.setSelectionRule(d_heuristicRule); if(searchForFeasibleSolution(numDifferencePivots)){ result = Result::UNSAT; } } if(verbose && numDifferencePivots > 0){ if(result == Result::UNSAT){ Message() << "diff order found unsat" << endl; }else if(d_errorSet.errorEmpty()){ Message() << "diff order found model" << endl; }else{ Message() << "diff order missed" << endl; } } } Assert(!d_errorSet.moreSignals()); if(!d_errorSet.errorEmpty() && result != Result::UNSAT){ if(exactResult){ d_errorSet.setSelectionRule(VAR_ORDER); while(!d_errorSet.errorEmpty() && result != Result::UNSAT){ Assert(checkPeriod > 0); if(searchForFeasibleSolution(checkPeriod)){ result = Result::UNSAT; } } }else if( options::arithStandardCheckVarOrderPivots() > 0){ d_errorSet.setSelectionRule(VAR_ORDER); if(searchForFeasibleSolution(options::arithStandardCheckVarOrderPivots())){ result = Result::UNSAT; } if(verbose){ if(result == Result::UNSAT){ Message() << "restricted var order found unsat" << endl; }else if(d_errorSet.errorEmpty()){ Message() << "restricted var order found model" << endl; }else{ Message() << "restricted var order missed" << endl; } } } } Assert(!d_errorSet.moreSignals()); if(result == Result::SAT_UNKNOWN && d_errorSet.errorEmpty()){ result = Result::SAT; } d_pivotsInRound.purge(); // ensure that the conflict variable is still in the queue. d_conflictVariables.purge(); Debug("arith::findModel") << "end findModel() " << instance << " " << result << endl; return result; }
Result::Sat AttemptSolutionSDP::attempt(const ApproximateSimplex::Solution& sol){ const DenseSet& newBasis = sol.newBasis; const DenseMap<DeltaRational>& newValues = sol.newValues; DenseSet needsToBeAdded; for(DenseSet::const_iterator i = newBasis.begin(), i_end = newBasis.end(); i != i_end; ++i){ ArithVar b = *i; if(!d_tableau.isBasic(b)){ needsToBeAdded.add(b); } } DenseMap<DeltaRational>::const_iterator nvi = newValues.begin(), nvi_end = newValues.end(); for(; nvi != nvi_end; ++nvi){ ArithVar currentlyNb = *nvi; if(!d_tableau.isBasic(currentlyNb)){ if(!matchesNewValue(newValues, currentlyNb)){ const DeltaRational& newValue = newValues[currentlyNb]; Trace("arith::updateMany") << "updateMany:" << currentlyNb << " " << d_variables.getAssignment(currentlyNb) << " to "<< newValue << endl; d_linEq.update(currentlyNb, newValue); Assert(d_variables.assignmentIsConsistent(currentlyNb)); } } } d_errorSet.reduceToSignals(); d_errorSet.setSelectionRule(VAR_ORDER); static int instance = 0; ++instance; if(processSignals()){ Debug("arith::findModel") << "attemptSolution("<< instance <<") early conflict" << endl; d_conflictVariables.purge(); return Result::UNSAT; }else if(d_errorSet.errorEmpty()){ Debug("arith::findModel") << "attemptSolution("<< instance <<") fixed itself" << endl; return Result::SAT; } while(!needsToBeAdded.empty() && !d_errorSet.errorEmpty()){ ArithVar toRemove = ARITHVAR_SENTINEL; ArithVar toAdd = ARITHVAR_SENTINEL; DenseSet::const_iterator i = needsToBeAdded.begin(), i_end = needsToBeAdded.end(); for(; toAdd == ARITHVAR_SENTINEL && i != i_end; ++i){ ArithVar v = *i; Tableau::ColIterator colIter = d_tableau.colIterator(v); for(; !colIter.atEnd(); ++colIter){ const Tableau::Entry& entry = *colIter; Assert(entry.getColVar() == v); ArithVar b = d_tableau.rowIndexToBasic(entry.getRowIndex()); if(!newBasis.isMember(b)){ toAdd = v; bool favorBOverToRemove = (toRemove == ARITHVAR_SENTINEL) || (matchesNewValue(newValues, toRemove) && !matchesNewValue(newValues, b)) || (d_tableau.basicRowLength(toRemove) > d_tableau.basicRowLength(b)); if(favorBOverToRemove){ toRemove = b; } } } } Assert(toRemove != ARITHVAR_SENTINEL); Assert(toAdd != ARITHVAR_SENTINEL); Trace("arith::forceNewBasis") << toRemove << " " << toAdd << endl; //Message() << toRemove << " " << toAdd << endl; d_linEq.pivotAndUpdate(toRemove, toAdd, newValues[toRemove]); Trace("arith::forceNewBasis") << needsToBeAdded.size() << "to go" << endl; //Message() << needsToBeAdded.size() << "to go" << endl; needsToBeAdded.remove(toAdd); bool conflict = processSignals(); if(conflict){ d_errorSet.reduceToSignals(); d_conflictVariables.purge(); return Result::UNSAT; } } Assert( d_conflictVariables.empty() ); if(d_errorSet.errorEmpty()){ return Result::SAT; }else{ d_errorSet.reduceToSignals(); return Result::SAT_UNKNOWN; } }