23 bool mCalledOptimizer =
false;
25 std::unordered_map<storm::storage::StateActionPair, storm::expressions::Variable> multistrategyVariables;
26 std::unordered_map<uint_fast64_t, storm::expressions::Variable> mProbVariables;
27 std::unordered_map<uint_fast64_t, storm::expressions::Variable> mAlphaVariables;
28 std::unordered_map<storm::storage::StateActionTarget, storm::expressions::Variable> mBetaVariables;
29 std::unordered_map<uint_fast64_t, storm::expressions::Variable> mGammaVariables;
37 createMILP(lowerBound, boundary, this->
mPenalties);
41 mCalledOptimizer =
true;
46 return !solver.isInfeasible();
54 for (
auto const& entry : multistrategyVariables) {
55 if (!solver.getBinaryValue(entry.second)) {
56 result.
disable(this->
mdp.getChoiceIndex(entry.first));
63 std::ofstream filestream;
65 for (
auto const& pVar : mProbVariables) {
66 filestream << pVar.second.getName() <<
"->" << solver.getContinuousValue(pVar.second) <<
'\n';
68 for (
auto const& yVar : multistrategyVariables) {
69 filestream << yVar.second.getName() <<
"->" << solver.getBinaryValue(yVar.second) <<
'\n';
71 for (
auto const& aVar : mAlphaVariables) {
72 filestream << aVar.second.getName() <<
"->" << solver.getBinaryValue(aVar.second) <<
'\n';
74 for (
auto const& betaVar : mBetaVariables) {
75 filestream << betaVar.second.getName() <<
"->" << solver.getBinaryValue(betaVar.second) <<
'\n';
77 for (
auto const& gammaVar : mGammaVariables) {
78 filestream << gammaVar.second.getName() <<
"->" << solver.getContinuousValue(gammaVar.second) <<
'\n';
84 solver.writeModelToFile(filename);
97 for (uint_fast64_t s : relevantStates) {
100 if (s == initialStateIndex) {
101 var =
solver.addLowerBoundedContinuousVariable(
"x_" + std::to_string(s), 0.0, -1.0);
103 var =
solver.addLowerBoundedContinuousVariable(
"x_" + std::to_string(s), 0.0);
105 mProbVariables[s] = var;
108 mAlphaVariables[s] = var;
111 mGammaVariables[s] = var;
113 auto stateAndAction = storage::StateActionPair(s, a);
116 double penalty = penalties.
get(stateAndAction);
117 var = solver.
addBinaryVariable(
"y_" + std::to_string(s) +
"_" + std::to_string(a), -penalty);
118 multistrategyVariables[stateAndAction] = var;
122 for (
auto const& entry : this->
mdp.
getTransitionMatrix().getRow(this->mdp.getNondeterministicChoiceIndices()[s] + a)) {
123 if (entry.getValue() != 0) {
124 storage::StateActionTarget sat = {s, a, entry.getColumn()};
125 var = solver.addBinaryVariable(
"beta_" +
to_string(sat));
126 mBetaVariables[sat] = var;
137 void createConstraints(
bool lowerBound,
double boundary, storm::storage::BitVector
const& relevantStates) {
141 STORM_LOG_ASSERT(this->
mdp.getInitialStates().getNumberOfSetBits() == 1,
"No unique initial state.");
142 uint_fast64_t initialStateIndex = this->
mdp.getInitialStates().getNextSetIndex(0);
143 STORM_LOG_ASSERT(relevantStates[initialStateIndex],
"Initial state not relevant.");
145 solver.addConstraint(
"c1", mProbVariables[initialStateIndex] >= solver.getConstant(boundary));
147 solver.addConstraint(
"c1", mProbVariables[initialStateIndex] <= solver.getConstant(boundary));
149 for (uint_fast64_t s : relevantStates) {
150 std::string stateString = std::to_string(s);
151 storm::expressions::Expression expr = solver.getConstant(0.0);
153 for (uint_fast64_t a = 0; a < this->
mdp.getNumberOfChoices(s); ++a) {
154 expr = expr + multistrategyVariables[storage::StateActionPair(s, a)];
156 solver.addConstraint(
"c2-" + stateString, solver.getConstant(1) <= expr);
158 solver.addConstraint(
"c5-" + std::to_string(s), mProbVariables[s] <= mAlphaVariables[s]);
161 for (uint_fast64_t a = 0; a < this->
mdp.getNumberOfChoices(s); ++a) {
162 std::string sastring(stateString +
"_" + std::to_string(a));
163 expr = solver.getConstant(0.0);
164 for (
auto const& entry : this->
mdp.getTransitionMatrix().getRow(this->mdp.getNondeterministicChoiceIndices()[s] + a)) {
165 if (entry.getValue() != 0 && relevantStates.get(entry.getColumn())) {
166 expr = expr + solver.getConstant(entry.getValue()) * mProbVariables[entry.getColumn()];
167 }
else if (entry.getValue() != 0 && this->mGoals.get(entry.getColumn())) {
168 expr = expr + solver.getConstant(entry.getValue());
172 solver.addConstraint(
"c3-" + sastring,
173 mProbVariables[s] <= (solver.getConstant(1) - multistrategyVariables[storage::StateActionPair(s, a)]) + expr);
175 solver.addConstraint(
"c3-" + sastring,
176 mProbVariables[s] >= (solver.getConstant(1) - multistrategyVariables[storage::StateActionPair(s, a)]) + expr);
180 for (uint_fast64_t a = 0; a < this->
mdp.getNumberOfChoices(s); ++a) {
182 std::string sastring(stateString +
"_" + std::to_string(a));
183 expr = solver.getConstant(0.0);
184 for (
auto const& entry : this->
mdp.getTransitionMatrix().getRow(this->mdp.getNondeterministicChoiceIndices()[s] + a)) {
185 if (entry.getValue() != 0) {
186 storage::StateActionTarget sat = {s, a, entry.getColumn()};
187 expr = expr + mBetaVariables[sat];
190 solver.addConstraint(
"c6-" + sastring,
191 multistrategyVariables[storage::StateActionPair(s, a)] == (solver.getConstant(1) - mAlphaVariables[s]) + expr);
193 for (
auto const& entry : this->
mdp.getTransitionMatrix().getRow(this->mdp.getNondeterministicChoiceIndices()[s] + a)) {
194 if (entry.getValue() != 0) {
195 storage::StateActionTarget sat = {s, a, entry.getColumn()};
198 if (relevantStates[entry.getColumn()]) {
199 STORM_LOG_ASSERT(mGammaVariables.count(entry.getColumn()) > 0,
"Entry not found.");
202 solver.addConstraint(
"c8-" + satstring,
203 mGammaVariables[entry.getColumn()] < mGammaVariables[s] + (solver.getConstant(1) - mBetaVariables[sat]));
214 void createMILP(
bool lowerBound,
double boundary, PermissiveSchedulerPenalties
const& penalties) {
215 storm::storage::BitVector irrelevant = this->
mGoals | this->
mSinks;
216 storm::storage::BitVector relevantStates = ~irrelevant;
220 createVariables(penalties, relevantStates);
221 createConstraints(lowerBound, boundary, relevantStates);
223 solver.setOptimizationDirection(storm::OptimizationDirection::Minimize);