diff --git a/src/counterexamples/MILPMinimalLabelSetGenerator.h b/src/counterexamples/MILPMinimalLabelSetGenerator.h index de9c6b057..b73ff1590 100644 --- a/src/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/counterexamples/MILPMinimalLabelSetGenerator.h @@ -92,8 +92,7 @@ namespace storm { StateInformation result; result.relevantStates = storm::utility::graph::performProbGreater0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates); result.relevantStates &= ~psiStates; - result.problematicStates = storm::utility::graph::performProbGreater0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates); - result.problematicStates.complement(); + result.problematicStates = storm::utility::graph::performProb0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates); result.problematicStates &= result.relevantStates; LOG4CPLUS_DEBUG(logger, "Found " << phiStates.getNumberOfSetBits() << " filter states."); LOG4CPLUS_DEBUG(logger, "Found " << psiStates.getNumberOfSetBits() << " target states."); diff --git a/src/solver/GurobiLpSolver.cpp b/src/solver/GurobiLpSolver.cpp index c06233942..75a0d5a7e 100644 --- a/src/solver/GurobiLpSolver.cpp +++ b/src/solver/GurobiLpSolver.cpp @@ -1,6 +1,7 @@ #include "src/solver/GurobiLpSolver.h" #ifdef STORM_HAVE_GUROBI +#include #include "src/exceptions/InvalidStateException.h" #include "src/settings/Settings.h" @@ -162,12 +163,29 @@ namespace storm { throw storm::exceptions::InvalidStateException() << "Sizes of variable indices vector and coefficients vector do not match."; } - // Convert the uint vector to ints for proper input to Gurobi. - std::vector variablesCopy(variables.begin(), variables.end()); + // As Gurobi requires the indices to be unique, we now explicitly make them unique. For this, we sort the + // variables and coefficients and eliminated duplicates by adding the coefficients. - // Copy the coefficients, because Gurobi does not take the coefficients as const values. The alternative to this would be casting - // away the constness, which gives undefined behaviour if Gurobi actually modifies something. - std::vector coefficientsCopy(coefficients); + // We start by sorting both vectors. + std::vector sortedVariables(variables); + std::vector sortedCoefficients(coefficients); + std::vector permutation(variables.size()); + std::iota(permutation.begin(), permutation.end(), 0); + std::sort(permutation.begin(), permutation.end(), [&] (uint_fast64_t i, uint_fast64_t j) { return variables[i] < variables[j]; } ); + std::transform(permutation.begin(), permutation.end(), sortedVariables.begin(), [&] (uint_fast64_t i) { return variables[i]; } ); + std::transform(permutation.begin(), permutation.end(), sortedCoefficients.begin(), [&] (uint_fast64_t i) { return coefficients[i]; } ); + + // Now we perform the duplicate elimination step. + std::vector uniqueVariables; + std::vector uniqueCoefficients; + for (uint_fast64_t i = 0; i < sortedVariables.size(); ++i) { + if (!uniqueVariables.empty() && uniqueVariables.back() == sortedVariables[i]) { + uniqueCoefficients.back() += sortedCoefficients[i]; + } else { + uniqueVariables.push_back(static_cast(sortedVariables[i])); + uniqueCoefficients.push_back(sortedCoefficients[i]); + } + } bool strictBound = boundType == LESS || boundType == GREATER; char sense = boundType == LESS || boundType == LESS_EQUAL ? GRB_LESS_EQUAL : boundType == EQUAL ? GRB_EQUAL : GRB_GREATER_EQUAL; @@ -181,7 +199,7 @@ namespace storm { rightHandSideValue += storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); } } - int error = GRBaddconstr(model, variablesCopy.size(), variablesCopy.data(), coefficientsCopy.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str()); + int error = GRBaddconstr(model, uniqueVariables.size(), uniqueVariables.data(), uniqueCoefficients.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str()); if (error) { LOG4CPLUS_ERROR(logger, "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ").");