19template<
typename ModelType,
typename GeometryValueType>
22 : model(model), objectiveHelper(objectiveHelper), numLpQueries(0) {
26template<
typename ModelType,
typename GeometryValueType>
27void DeterministicSchedsLpChecker<ModelType, GeometryValueType>::initialize(
Environment const& env) {
30 initializeLpModel(env);
35template<
typename ModelType,
typename GeometryValueType>
37 std::stringstream out;
38 out << prefix << swAll <<
" seconds for LP Checker including... \n";
39 out << prefix <<
" " << swInit <<
" seconds for LP initialization\n";
40 out << prefix <<
" " << swCheckWeightVectors <<
" seconds for checking weight vectors\n";
41 out << prefix <<
" " << swCheckAreas <<
" seconds for checking areas\n";
42 out << prefix <<
" " << swValidate <<
" seconds for validating LP solutions\n";
43 out << prefix <<
" " << numLpQueries <<
" calls to LP optimization\n";
47template<
typename ModelType,
typename GeometryValueType>
49 std::vector<GeometryValueType>
const& weightVector) {
52 STORM_LOG_ASSERT(weightVector.size() == objectiveHelper.size(),
"Setting a weight vector with invalid number of entries.");
53 if (!currentWeightVector.empty()) {
57 currentObjectiveVariables.clear();
60 currentWeightVector = weightVector;
64 for (uint64_t objIndex = 0; objIndex < initialStateResults.size(); ++objIndex) {
65 currentObjectiveVariables.push_back(
67 lpModel->addConstraint(
"", currentObjectiveVariables.back().getExpression() == initialStateResults[objIndex]);
73template<
typename ModelType,
typename GeometryValueType>
78 STORM_LOG_ASSERT(!currentWeightVector.empty(),
"Checking invoked before specifying a weight vector.");
81 auto areaConstraints = overapproximation->getConstraints(lpModel->getManager(), currentObjectiveVariables);
82 for (
auto const& c : areaConstraints) {
83 lpModel->addConstraint(
"", c);
87 STORM_LOG_ASSERT(currentWeightVector.size() == eps.size(),
"Eps vector has unexpected size.");
93 swCheckWeightVectors.start();
95 swCheckWeightVectors.stop();
99 std::optional<std::pair<Point, GeometryValueType>> result;
100 if (!lpModel->isInfeasible()) {
103 auto resultPoint = validateCurrentModel(env);
109 result = std::make_pair(resultPoint, resultValue);
117template<
typename ModelType,
typename GeometryValueType>
118std::pair<std::vector<std::vector<GeometryValueType>>, std::vector<std::shared_ptr<storm::storage::geometry::Polytope<GeometryValueType>>>>
124 STORM_LOG_ASSERT(!currentWeightVector.empty(),
"Checking invoked before specifying a weight vector.");
136 std::vector<Point> foundPoints;
137 std::vector<Polytope> infeasableAreas;
138 checkRecursive(env, polytopeTree, eps, foundPoints, infeasableAreas, 0);
140 return {foundPoints, infeasableAreas};
143template<
typename ValueType>
145 std::vector<storm::expressions::Expression> choiceVariables;
149 if (choices.size() == 1) {
152 std::vector<storm::expressions::Expression> localChoices;
153 for (
auto const choice : choices) {
155 choiceVariables.push_back(localChoices.back());
161 return choiceVariables;
164template<
typename ValueType,
typename HelperType>
167 HelperType
const& objectiveHelper,
168 std::vector<storm::expressions::Expression>
const& choiceVariables) {
170 std::vector<storm::expressions::Expression> objectiveValueVariables(matrix.
getRowGroupCount());
171 for (
auto const& state : objectiveHelper.getMaybeStates()) {
172 if (indicatorConstraints) {
173 objectiveValueVariables[state] = lpModel.
addContinuousVariable(
"x_" + std::to_string(objIndex) +
"_" + std::to_string(state));
175 objectiveValueVariables[state] =
177 objectiveHelper.getLowerValueBoundAtState(state), objectiveHelper.getUpperValueBoundAtState(state));
180 std::vector<storm::expressions::Expression> reachVars;
181 if (objectiveHelper.getInfinityCase() == HelperType::InfinityCase::HasNegativeInfinite) {
183 for (
auto const& state : objectiveHelper.getRewMinusInfEStates()) {
184 reachVars[state] = lpModel.
addBinaryVariable(
"c_" + std::to_string(objIndex) +
"_" + std::to_string(state));
186 STORM_LOG_ASSERT(objectiveHelper.getRewMinusInfEStates().get(initialState),
"Initial state must be in RewMinusInfEStates.");
191 for (
auto const& state : objectiveHelper.getMaybeStates()) {
192 bool const requireReachConstraints =
193 objectiveHelper.getInfinityCase() == HelperType::InfinityCase::HasNegativeInfinite && objectiveHelper.getRewMinusInfEStates().get(state);
195 auto const& choiceVarAsExpression = choiceVariables.at(choice);
197 (!choiceVarAsExpression.containsVariables() &&
storm::utility::isOne(choiceVarAsExpression.evaluateAsRational())),
198 "Unexpected kind of choice variable: " << choiceVarAsExpression);
199 std::vector<storm::expressions::Expression> summands;
200 if (!indicatorConstraints && choiceVarAsExpression.isVariable()) {
202 lpModel.
getConstant(objectiveHelper.getUpperValueBoundAtState(state) - objectiveHelper.getLowerValueBoundAtState(state)));
204 if (
auto findRes = objectiveHelper.getChoiceRewards().find(choice); findRes != objectiveHelper.getChoiceRewards().end()) {
205 auto rewExpr = lpModel.
getConstant(findRes->second);
206 if (requireReachConstraints) {
207 summands.push_back(reachVars[state] * rewExpr);
209 summands.push_back(rewExpr);
212 for (
auto const& succ : matrix.
getRow(choice)) {
213 if (objectiveHelper.getMaybeStates().get(succ.getColumn())) {
214 summands.push_back(lpModel.
getConstant(succ.getValue()) * objectiveValueVariables.at(succ.getColumn()));
216 if (requireReachConstraints && objectiveHelper.getRewMinusInfEStates().get(succ.getColumn())) {
221 if (summands.empty()) {
224 if (indicatorConstraints && choiceVarAsExpression.isVariable()) {
225 auto choiceVar = choiceVarAsExpression.getBaseExpression().asVariableExpression().getVariable();
232 return objectiveValueVariables;
237template<
typename ValueType,
typename ObjHelperType>
239 std::vector<ObjHelperType>
const& objectiveHelper) {
240 std::vector<std::pair<storm::storage::MaximalEndComponent, std::vector<uint64_t>>> problMecs;
241 for (uint64_t objIndex = 0; objIndex < objectiveHelper.size(); ++objIndex) {
242 auto const& obj = objectiveHelper[objIndex];
244 obj.getRelevantZeroRewardChoices());
245 for (
auto& newMec : objMecs) {
247 for (
auto& problMec : problMecs) {
248 if (problMec.first == newMec) {
249 problMec.second.push_back(objIndex);
255 problMecs.emplace_back(std::move(newMec), std::vector<uint64_t>({objIndex}));
263template<
typename ValueType,
typename UpperBoundsGetterType>
267 std::vector<uint64_t>
const& relevantObjectiveIndices,
268 std::vector<std::vector<storm::expressions::Expression>>
const& objectiveValueVariables,
269 std::vector<storm::expressions::Expression>
const& choiceVariables,
270 UpperBoundsGetterType
const& objectiveStateUpperBoundGetter) {
272 if (!indicatorConstraints) {
278 std::map<uint64_t, storm::expressions::Expression> expVisitsVars;
279 std::map<uint64_t, storm::expressions::Expression> botVars;
280 std::map<uint64_t, storm::expressions::Expression> bsccIndicatorVariables;
281 for (
auto const& stateChoices : problematicMec) {
282 auto const state = stateChoices.first;
283 auto bsccIndicatorVar = lpModel.
addBinaryVariable(
"b_" + std::to_string(mecIndex) +
"_" + std::to_string(state));
284 bsccIndicatorVariables.emplace(state, bsccIndicatorVar.getExpression());
285 std::string visitsVarPref =
"z_" + std::to_string(mecIndex) +
"_";
286 auto stateBotVisitsVar =
288 botVars.emplace(state, stateBotVisitsVar);
290 if (indicatorConstraints) {
293 lpModel.
addConstraint(
"", stateBotVisitsVar <= bsccIndicatorVar.getExpression() * visitsUpperBound);
296 auto stateActionVisitsVar =
299 if (indicatorConstraints) {
300 if (
auto const& a = choiceVariables[choice]; a.isVariable()) {
301 auto aVar = a.getBaseExpression().asVariableExpression().getVariable();
305 lpModel.
addConstraint(
"", stateActionVisitsVar <= choiceVariables[choice] * visitsUpperBound);
307 expVisitsVars.emplace(choice, stateActionVisitsVar);
309 for (
auto const& ecChoice : stateChoices.second) {
310 mecChoices.
set(ecChoice,
true);
312 for (
auto const& objIndex : relevantObjectiveIndices) {
313 if (indicatorConstraints) {
317 auto const upperBnd = lpModel.
getConstant(objectiveStateUpperBoundGetter(objIndex, state));
318 lpModel.
addConstraint(
"", objectiveValueVariables[objIndex][state] <= upperBnd - upperBnd * bsccIndicatorVar.getExpression());
325 std::vector<storm::expressions::Expression> outVisitsSummands;
326 for (
auto const& stateChoices : problematicMec) {
327 auto const state = stateChoices.first;
328 auto const& choices = stateChoices.second;
329 auto const& stateBotVar = botVars.at(state);
330 outVisitsSummands.push_back(stateBotVar);
331 std::vector<storm::expressions::Expression> stateVisitsSummands;
332 stateVisitsSummands.push_back(stateBotVar);
334 auto const& choiceVisitsVar = expVisitsVars.at(choice);
335 stateVisitsSummands.push_back(choiceVisitsVar);
336 if (choices.count(choice) != 0) {
337 if (redundantConstraints) {
338 for (
auto const& postElem : matrix.
getRow(choice)) {
342 auto succ = postElem.getColumn();
343 lpModel.
addConstraint(
"", bsccIndicatorVariables.at(state) + choiceVariables.at(choice) <=
348 outVisitsSummands.push_back(choiceVisitsVar);
351 for (
auto const& preEntry : backwardChoices.
getRow(state)) {
352 uint64_t
const preChoice = preEntry.getColumn();
353 if (mecChoices.
get(preChoice)) {
356 stateVisitsSummands.push_back(lpModel.
getConstant(-preProb) * expVisitsVars.at(preChoice));
364template<
typename ValueType,
typename UpperBoundsGetterType>
368 std::vector<storm::expressions::Expression>
const& choiceVariables,
369 std::vector<std::vector<storm::expressions::Expression>>
const& objectiveValueVariables,
370 UpperBoundsGetterType
const& objectiveStateUpperBoundGetter) {
373 std::map<uint64_t, storm::expressions::Expression> bsccIndicatorVariables;
374 std::map<uint64_t, storm::expressions::Expression> orderVariables;
375 for (
auto const& stateChoices : problematicMec) {
376 auto const state = stateChoices.first;
377 auto bsccIndicatorVar = lpModel.
addBinaryVariable(
"b_" + std::to_string(mecIndex) +
"_" + std::to_string(state));
378 bsccIndicatorVariables.emplace(state, bsccIndicatorVar.getExpression());
379 auto orderVar = lpModel
384 orderVariables.emplace(state, orderVar);
385 for (
auto const& ecChoice : stateChoices.second) {
386 mecChoices.
set(ecChoice,
true);
388 for (
auto const& objIndex : relevantObjectiveIndices) {
389 if (indicatorConstraints) {
393 auto const upperBnd = lpModel.
getConstant(objectiveStateUpperBoundGetter(objIndex, state));
394 lpModel.
addConstraint(
"", objectiveValueVariables[objIndex][state] <= upperBnd - upperBnd * bsccIndicatorVar.getExpression());
401 for (
auto const& stateChoices : problematicMec) {
402 auto const state = stateChoices.first;
403 auto const& choices = stateChoices.second;
404 auto const& bsccIndicatorVar = bsccIndicatorVariables.at(state);
405 auto const& orderVar = orderVariables.at(state);
406 for (
auto choice : choices) {
407 auto const& choiceVariable = choiceVariables.at(choice);
408 std::vector<storm::expressions::Expression> choiceConstraint;
409 choiceConstraint.push_back(bsccIndicatorVar);
410 std::string
const transSelectPrefix =
"d_" + std::to_string(mecIndex) +
"_" + std::to_string(choice) +
"_";
411 for (
auto const& postElem : matrix.
getRow(choice)) {
415 auto succ = postElem.getColumn();
416 if (redundantConstraints) {
420 auto transVar = lpModel.
addBinaryVariable(transSelectPrefix + std::to_string(succ)).getExpression();
422 choiceConstraint.push_back(transVar);
431template<
typename ValueType,
typename HelperType>
436 std::vector<HelperType>
const& objectiveHelper,
437 std::vector<storm::expressions::Expression>
const& choiceVariables) {
438 auto objHelpIt = objectiveHelper.begin();
440 for (++objHelpIt; objHelpIt != objectiveHelper.end(); ++objHelpIt) {
441 anyMaybeStates |= objHelpIt->getMaybeStates();
444 for (
auto const& oh : objectiveHelper) {
445 for (
auto const& rew : oh.getChoiceRewards()) {
447 allZeroRewardChoices.
set(rew.first,
false);
452 for (
auto const& mec : mecs) {
453 for (
auto const& sc : mec) {
454 mecStates.
set(sc.first,
true);
457 std::vector<ValueType> maxVisits;
458 if (!indicatorConstraints) {
465 for (uint64_t state : anyMaybeStates) {
468 choiceVisitsVars[choice] =
471 if (indicatorConstraints) {
472 if (
auto const& a = choiceVariables[choice]; a.isVariable()) {
473 auto aVar = a.getBaseExpression().asVariableExpression().getVariable();
477 lpModel.
addConstraint(
"", choiceVisitsVars[choice] <= choiceVariables.at(choice) * lpModel.
getConstant(maxVisits[state]));
480 if (mecStates.
get(state)) {
481 bsccVars[state] = lpModel.
addBinaryVariable(
"b_" + std::to_string(state)).getExpression();
482 botVisitsVars[state] =
485 if (indicatorConstraints) {
486 lpModel.
addIndicatorConstraint(
"", bsccVars[state].getBaseExpression().asVariableExpression().getVariable(),
false,
495 auto notMaybe = ~anyMaybeStates;
496 std::vector<storm::expressions::Expression> outSummands;
497 for (uint64_t state : anyMaybeStates) {
498 std::vector<storm::expressions::Expression> visitsSummands;
499 if (mecStates.
get(state)) {
500 visitsSummands.push_back(-botVisitsVars[state]);
501 outSummands.push_back(botVisitsVars[state]);
504 visitsSummands.push_back(-choiceVisitsVars[choice]);
506 outSummands.push_back(lpModel.
getConstant(outProb) * choiceVisitsVars[choice]);
509 if (state == initialState) {
512 for (
auto const& preEntry : backwardChoices.
getRow(state)) {
513 STORM_LOG_ASSERT(choiceVisitsVars[preEntry.getColumn()].isInitialized(),
"Choice visit variable not initialized.");
514 visitsSummands.push_back(lpModel.
getConstant(preEntry.getValue()) * choiceVisitsVars[preEntry.getColumn()]);
521 for (
auto const& mec : mecs) {
522 for (
auto const& stateChoices : mec) {
523 auto const& state = stateChoices.first;
525 if (stateChoices.second.count(choice) != 0) {
526 for (
auto const& succ : matrix.
getRow(choice)) {
532 choiceVariables[choice]);
542 std::vector<storm::expressions::Expression> objectiveValueVariables;
543 for (uint64_t objIndex = 0; objIndex < objectiveHelper.size(); ++objIndex) {
544 if (objectiveHelper[objIndex].getMaybeStates().get(initialState)) {
547 std::vector<storm::expressions::Expression> summands;
548 for (
auto const& objRew : objectiveHelper[objIndex].getChoiceRewards()) {
549 STORM_LOG_ASSERT(choiceVisitsVars[objRew.first].isInitialized(),
"Choice visit variable not initialized.");
550 summands.push_back(choiceVisitsVars[objRew.first] * lpModel.
getConstant(objRew.second));
554 objectiveValueVariables.push_back(lpModel.
getConstant(objectiveHelper[objIndex].getConstantInitialStateValue()));
557 return objectiveValueVariables;
560template<
typename HelperType>
562 bool supportsFlowEncoding = std::all_of(objectiveHelper.begin(), objectiveHelper.end(), [](
auto const& h) { return h.isTotalRewardObjective(); });
565 return supportsFlowEncoding;
567 STORM_LOG_THROW(supportsFlowEncoding, storm::exceptions::InvalidOperationException,
568 "Flow encoding only applicable if all objectives are (transformable to) total reward objectives.");
575template<
typename ModelType,
typename GeometryValueType>
576void DeterministicSchedsLpChecker<ModelType, GeometryValueType>::initializeLpModel(
Environment const& env) {
577 STORM_LOG_INFO(
"Initializing LP model with " << model.getNumberOfStates() <<
" states.");
579 STORM_LOG_INFO(
"Using " << (flowEncoding ?
"flow" :
"classical") <<
" encoding.\n");
580 uint64_t initialState = *model.getInitialStates().begin();
581 auto backwardTransitions = model.getBackwardTransitions();
582 auto backwardChoices = model.getTransitionMatrix().transpose();
584 "The selected MILP solver might not perform well. Consider installing / using Gurobi.");
587 lpModel->setOptimizationDirection(storm::solver::OptimizationDirection::Maximize);
588 initialStateResults.clear();
594 backwardTransitions, backwardChoices, initialState, objectiveHelper, choiceVariables);
596 std::vector<std::vector<storm::expressions::Expression>> objectiveValueVariables;
597 initialStateResults.clear();
598 for (uint64_t objIndex = 0; objIndex < objectiveHelper.size(); ++objIndex) {
599 if (objectiveHelper[objIndex].getMaybeStates().get(initialState)) {
601 model.getTransitionMatrix(), initialState, objIndex, objectiveHelper[objIndex],
603 initialStateResults.push_back(objectiveValueVariables.back()[initialState]);
605 initialStateResults.push_back(lpModel->getConstant(objectiveHelper[objIndex].getConstantInitialStateValue()));
608 auto problematicMecs =
computeProblematicMecs(model.getTransitionMatrix(), backwardTransitions, objectiveHelper);
609 uint64_t mecIndex = 0;
610 auto upperBoundsGetter = [&](uint64_t objIndex, uint64_t state) -> ValueType {
return objectiveHelper[objIndex].getUpperValueBoundAtState(state); };
611 for (
auto const& mecObj : problematicMecs) {
615 mecObj.second, choiceVariables, objectiveValueVariables, upperBoundsGetter);
619 mecIndex, mecObj.first, mecObj.second, objectiveValueVariables, choiceVariables, upperBoundsGetter);
628template<
typename ModelType,
typename GeometryValueType>
629void DeterministicSchedsLpChecker<ModelType, GeometryValueType>::checkRecursive(Environment
const& env,
630 storm::storage::geometry::PolytopeTree<GeometryValueType>& polytopeTree,
631 Point
const& eps, std::vector<Point>& foundPoints,
632 std::vector<Polytope>& infeasableAreas, uint64_t
const& depth) {
639 auto nodeConstraints = polytopeTree.
getPolytope()->getConstraints(lpModel->getManager(), currentObjectiveVariables);
640 for (
auto const& constr : nodeConstraints) {
641 lpModel->addConstraint(
"", constr);
653 uint64_t num_sharpen = 0;
654 auto halfspaces = polytopeTree.
getPolytope()->getHalfspaces();
657 swCheckAreas.start();
663 if (lpModel->isInfeasible()) {
664 infeasableAreas.push_back(polytopeTree.
getPolytope());
665 polytopeTree.
clear();
670 Point newPoint = validateCurrentModel(env);
675 Point newPointPlusEps = newPoint;
677 if (polytopeTree.
getPolytope()->contains(newPoint) ||
686 auto halfspace = storm::storage::geometry::Halfspace<GeometryValueType>(currentWeightVector, offset).invert();
687 infeasableAreas.push_back(polytopeTree.
getPolytope()->intersection(halfspace));
688 if (infeasableAreas.back()->isEmpty()) {
689 infeasableAreas.pop_back();
692 foundPoints.push_back(newPoint);
695 checkRecursive(env, polytopeTree, eps, foundPoints, infeasableAreas, depth);
700 for (
auto& h : halfspaces) {
701 GeometryValueType distance = h.distance(newPoint);
706 bool normalVectorContainsNegative =
false;
707 for (
auto const& hi : h.normalVector()) {
709 normalVectorContainsNegative =
true;
713 if (normalVectorContainsNegative) {
715 if (num_sharpen == 0) {
718 lpModel->addConstraint(
"", h.toExpression(lpModel->getManager(), currentObjectiveVariables));
728 if (num_sharpen > 0) {
730 "Numerical instabilities detected: LP Solver found an achievable point outside of the search area. The search area had to be sharpened "
731 << num_sharpen <<
" times.");
738 for (uint64_t childId = 0; childId < polytopeTree.
getChildren().size(); ++childId) {
739 if (polytopeTree.
getChildren()[childId].isEmpty()) {
742 uint64_t newPointIndex = foundPoints.size();
743 checkRecursive(env, polytopeTree.
getChildren()[childId], eps, foundPoints, infeasableAreas, depth + 1);
746 for (; newPointIndex < foundPoints.size(); ++newPointIndex) {
747 for (uint64_t siblingId = childId + 1; siblingId < polytopeTree.
getChildren().size(); ++siblingId) {
748 polytopeTree.
getChildren()[siblingId].substractDownwardClosure(foundPoints[newPointIndex], eps);
753 polytopeTree.
clear();
761template<
typename ModelType,
typename GeometryValueType>
763 Environment
const& env)
const {
764 storm::storage::BitVector selectedChoices(model.getNumberOfChoices(),
false);
765 for (uint64_t state = 0; state < model.getNumberOfStates(); ++state) {
766 auto choices = model.getTransitionMatrix().getRowGroupIndices(state);
767 if (choices.size() == 1) {
768 selectedChoices.set(*choices.begin());
770 bool choiceFound =
false;
771 for (
auto choice : choices) {
772 STORM_LOG_ASSERT(choiceVariables[choice].isVariable(),
"Choice variable is not a variable.");
773 if (lpModel->getBinaryValue(choiceVariables[choice].getBaseExpression().asVariableExpression().getVariable())) {
774 STORM_LOG_THROW(!choiceFound, storm::exceptions::UnexpectedException,
"Multiple choices selected at state " << state <<
".");
775 selectedChoices.set(choice,
true);
783 for (uint64_t objIndex = 0; objIndex < objectiveHelper.size(); ++objIndex) {
784 ValueType inducedValue = objectiveHelper[objIndex].evaluateScheduler(env, selectedChoices);
788 ValueType lpValue = lpModel->getContinuousValue(currentObjectiveVariables[objIndex]);
791 "Imprecise value for objective " << objIndex <<
": LP says " << lpValue <<
" but scheduler induces " << inducedValue
792 <<
" (difference is " << diff <<
")");
SolverEnvironment & solver()
ModelCheckerEnvironment & modelchecker()
MultiObjectiveModelCheckerEnvironment & multi()
bool getUseIndicatorConstraints() const
EncodingType const & getEncodingType() const
@ Flow
The classic backwards encoding.
bool getUseBsccOrderEncoding() const
bool getUseRedundantBsccConstraints() const
bool isLpSolverTypeSetFromDefaultValue() const
storm::solver::LpSolverType const & getLpSolverType() const
Represents the LP Encoding for achievability under simple strategies.
void setCurrentWeightVector(Environment const &env, std::vector< GeometryValueType > const &weightVector)
Specifies the current direction.
std::string getStatistics(std::string const &prefix="") const
Returns usage statistics in a human readable format.
DeterministicSchedsLpChecker(ModelType const &model, std::vector< DeterministicSchedsObjectiveHelper< ModelType > > const &objectiveHelper)
std::optional< std::pair< Point, GeometryValueType > > check(storm::Environment const &env, Polytope overapproximation, Point const &eps={})
Optimizes in the currently given direction.
std::vector< GeometryValueType > Point
std::shared_ptr< storm::storage::geometry::Polytope< GeometryValueType > > Polytope
static ValueType computeMecVisitsUpperBound(storm::storage::MaximalEndComponent const &mec, storm::storage::SparseMatrix< ValueType > const &transitions, bool assumeOptimalTransitionProbabilities=false)
Computes an upper bound for the largest finite expected number of times a state s in the given MEC is...
static std::vector< ValueType > computeUpperBoundsOnExpectedVisitingTimes(storm::storage::BitVector const &subsystem, storm::storage::SparseMatrix< ValueType > const &transitions, storm::storage::SparseMatrix< ValueType > const &backwardTransitions)
Computes for each state in the given subsystem an upper bound for the maximal finite expected number ...
An interface that captures the functionality of an LP solver.
Variable addContinuousVariable(std::string const &name, std::optional< ValueType > const &lowerBound=std::nullopt, std::optional< ValueType > const &upperBound=std::nullopt, ValueType objectiveFunctionCoefficient=0)
Registers a continuous variable, i.e.
virtual void update() const =0
Updates the model to make the variables that have been declared since the last call to update usable.
virtual void addConstraint(std::string const &name, Constraint const &constraint)=0
Adds a the given constraint to the LP problem.
Variable addLowerBoundedContinuousVariable(std::string const &name, ValueType lowerBound, ValueType objectiveFunctionCoefficient=0)
Registers a lower-bounded continuous variable, i.e.
Constant getConstant(ValueType value) const
Retrieves an expression that characterizes the given constant value.
virtual void addIndicatorConstraint(std::string const &name, Variable indicatorVariable, bool indicatorValue, Constraint const &constraint)=0
Adds the given indicator constraint to the LP problem: "If indicatorVariable == indicatorValue,...
Variable addBoundedContinuousVariable(std::string const &name, ValueType lowerBound, ValueType upperBound, ValueType objectiveFunctionCoefficient=0)
Registers an upper- and lower-bounded continuous variable, i.e.
Variable addUnboundedContinuousVariable(std::string const &name, ValueType objectiveFunctionCoefficient=0)
Registers a unbounded continuous variable, i.e.
Variable addBinaryVariable(std::string const &name, ValueType objectiveFunctionCoefficient=0)
Registers a boolean variable, i.e.
A bit vector that is internally represented as a vector of 64-bit values.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
This class represents the decomposition of a nondeterministic model into its maximal end components.
This class represents a maximal end-component of a nondeterministic model.
index_type getNumberOfEntries() const
Retrieves the number of entries in the rows.
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
value_type getConstrainedRowSum(index_type row, storm::storage::BitVector const &columns) const
Sums the entries in the given row and columns.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
static std::shared_ptr< Polytope< ValueType > > createDownwardClosure(std::vector< Point > const &points)
Creates the downward closure of the given points (i.e., the set { x | ex.
static std::shared_ptr< Polytope< ValueType > > create(std::vector< Halfspace< ValueType > > const &halfspaces)
Creates a polytope from the given halfspaces.
Represents a set of points in Euclidean space.
std::shared_ptr< Polytope< ValueType > > & getPolytope()
Gets the polytope at this node.
void substractDownwardClosure(std::vector< ValueType > const &point)
Substracts the downward closure of the given point from this set.
void setMinus(std::shared_ptr< Polytope< ValueType > > const &rhs)
Substracts the given rhs from this polytope.
bool isEmpty() const
Returns true if this is the empty set.
std::vector< PolytopeTree > & getChildren()
Gets the children at this node.
std::string toString()
Returns a string representation of this node (for debugging purposes).
void clear()
Clears all contents of this set, making it the empty set.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
Expression sum(std::vector< storm::expressions::Expression > const &expressions)
std::vector< storm::expressions::Expression > expVisitsConstraints(storm::solver::LpSolver< ValueType > &lpModel, bool const &indicatorConstraints, storm::storage::SparseMatrix< ValueType > const &matrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::SparseMatrix< ValueType > const &backwardChoices, uint64_t initialState, std::vector< HelperType > const &objectiveHelper, std::vector< storm::expressions::Expression > const &choiceVariables)
auto createChoiceVariables(storm::solver::LpSolver< ValueType > &lpModel, storm::storage::SparseMatrix< ValueType > const &matrix)
auto computeProblematicMecs(storm::storage::SparseMatrix< ValueType > const &matrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, std::vector< ObjHelperType > const &objectiveHelper)
Computes the set of problematic MECS with the objective indices that induced them An EC is problemati...
auto problematicMecConstraintsExpVisits(storm::solver::LpSolver< ValueType > &lpModel, bool const &indicatorConstraints, bool const &redundantConstraints, storm::storage::SparseMatrix< ValueType > const &matrix, storm::storage::SparseMatrix< ValueType > const &backwardChoices, uint64_t mecIndex, storm::storage::MaximalEndComponent const &problematicMec, std::vector< uint64_t > const &relevantObjectiveIndices, std::vector< std::vector< storm::expressions::Expression > > const &objectiveValueVariables, std::vector< storm::expressions::Expression > const &choiceVariables, UpperBoundsGetterType const &objectiveStateUpperBoundGetter)
std::vector< storm::expressions::Expression > classicConstraints(storm::solver::LpSolver< ValueType > &lpModel, bool const &indicatorConstraints, storm::storage::SparseMatrix< ValueType > const &matrix, uint64_t initialState, uint64_t objIndex, HelperType const &objectiveHelper, std::vector< storm::expressions::Expression > const &choiceVariables)
bool useFlowEncoding(storm::Environment const &env, std::vector< HelperType > const &objectiveHelper)
auto problematicMecConstraintsOrder(storm::solver::LpSolver< ValueType > &lpModel, bool const &indicatorConstraints, bool const &redundantConstraints, storm::storage::SparseMatrix< ValueType > const &matrix, uint64_t mecIndex, storm::storage::MaximalEndComponent const &problematicMec, std::vector< uint64_t > const &relevantObjectiveIndices, std::vector< storm::expressions::Expression > const &choiceVariables, std::vector< std::vector< storm::expressions::Expression > > const &objectiveValueVariables, UpperBoundsGetterType const &objectiveStateUpperBoundGetter)
std::unique_ptr< storm::solver::LpSolver< ValueType > > getLpSolver(storm::Environment const &env, std::string const &name, storm::solver::LpSolverTypeSelection solvType)
T dotProduct(std::vector< T > const &firstOperand, std::vector< T > const &secondOperand)
Computes the dot product (aka scalar product) and returns the result.
void addScaledVector(std::vector< InValueType1 > &firstOperand, std::vector< InValueType2 > const &secondOperand, InValueType3 const &factor)
Computes x:= x + a*y, i.e., adds each element of the first vector and (the corresponding element of t...
bool isOne(ValueType const &a)
bool isZero(ValueType const &a)
ValueType abs(ValueType const &number)
TargetType convertNumber(SourceType const &number)