STORM_LOG_THROW(SingleObjectiveMode,storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported in single objective mode.");// It most likely also works with multiple objectives with the same shape. However, we haven't checked this yet.
STORM_LOG_THROW(SingleObjectiveMode,storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported in single objective mode.");// It most likely also works with multiple objectives with the same shape. However, we haven't checked this yet.
STORM_LOG_THROW(objectives.front().formula->isProbabilityOperatorFormula(),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported for probability operator formulas");
STORM_LOG_THROW(objectives.front().formula->isProbabilityOperatorFormula(),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported for probability operator formulas");
STORM_LOG_THROW(probabilityOperatorFormula.getSubformula().isBoundedUntilFormula()&&probabilityOperatorFormula.hasOptimalityType()&&storm::solver::maximize(probabilityOperatorFormula.getOptimalityType()),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported for maximizing bounded until probabilities.");
STORM_LOG_THROW(probabilityOperatorFormula.getSubformula().isBoundedUntilFormula(),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported for bounded until probabilities.");
STORM_LOG_THROW(!model.isNondeterministicModel()||(probabilityOperatorFormula.hasOptimalityType()&&storm::solver::maximize(probabilityOperatorFormula.getOptimalityType())),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported for maximizing bounded until probabilities.");
STORM_LOG_THROW(upperBoundedDimensions.empty()||!probabilityOperatorFormula.getSubformula().asBoundedUntilFormula().hasMultiDimensionalSubformulas(),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported if the formula has either only lower bounds or if it has a single goal state.");// This would fail because the upper bounded dimension(s) might be satisfied already. One should erase epoch steps in the epoch model (after applying the goal-unfolding).
STORM_LOG_THROW(upperBoundedDimensions.empty()||!probabilityOperatorFormula.getSubformula().asBoundedUntilFormula().hasMultiDimensionalSubformulas(),storm::exceptions::NotSupportedException,"Letting lower bounds approach infinity is only supported if the formula has either only lower bounds or if it has a single goal state.");// This would fail because the upper bounded dimension(s) might be satisfied already. One should erase epoch steps in the epoch model (after applying the goal-unfolding).
STORM_LOG_DEBUG("Setting model for epoch "<<epochManager.toString(epoch));
STORM_LOG_DEBUG("Setting model for epoch "<<epochManager.toString(epoch));
STORM_LOG_THROW(getProb1Objectives().empty(),storm::exceptions::InvalidOperationException,"The objective "<<objectives[*getProb1Objectives().begin()].formula<<" is satisfied already in the initial state(s). This special case can not be handled by the reward unfolding.");// This case should have been handled 'from the outside'
// Check if we need to update the current epoch class
// Check if we need to update the current epoch class
STORM_LOG_ASSERT(productState<epochSolution.productStateToSolutionVectorMap->size(),"Requested solution at an unexisting product state.");
STORM_LOG_ASSERT(productState<epochSolution.productStateToSolutionVectorMap->size(),"Requested solution at an unexisting product state.");
STORM_LOG_ASSERT((*epochSolution.productStateToSolutionVectorMap)[productState]<epochSolution.solutions.size(),"Requested solution for epoch at a state for which no solution was stored.");
STORM_LOG_ASSERT(getProb1Objectives().empty(),"One of the objectives is already satisfied in the initial state. This special case is not handled.");// This case should have been handled 'from the outside'
STORM_LOG_ASSERT((*epochSolution.productStateToSolutionVectorMap)[productState]<epochSolution.solutions.size(),"Requested solution for epoch at product state "<<productState<<" for which no solution was stored.");
STORM_LOG_THROW(model.getInitialStates()==initialTransitionStates,storm::exceptions::NotSupportedException,"The objective "<<*objectives[objIndex].formula<<" is already satisfied in an initial state. This special case is not supported.");
prob1Objectives.set(objIndex,true);
// Such a situation can not be reduced (easily) to an expected reward computation and thus requires special treatment
STORM_LOG_THROW(quantileVariables.count(quantileVariable.second)==0,storm::exceptions::NotSupportedException,"Quantile formula considers the same bound variable twice.");
STORM_LOG_THROW(quantileFormula.getSubformula().isProbabilityOperatorFormula(),storm::exceptions::NotSupportedException,"Quantile formula needs probability operator inside. The formula "<<quantileFormula<<" is not supported.");
STORM_LOG_THROW(quantileFormula.getSubformula().isProbabilityOperatorFormula(),storm::exceptions::NotSupportedException,"Quantile formula needs probability operator inside. The formula "<<quantileFormula<<" is not supported.");
STORM_LOG_THROW(probOpFormula.getBound().comparisonType==storm::logic::ComparisonType::Greater||probOpFormula.getBound().comparisonType==storm::logic::ComparisonType::LessEqual,storm::exceptions::NotSupportedException,"Probability operator inside quantile formula needs to have bound > or <=.");
STORM_LOG_THROW(probOpFormula.hasBound(),storm::exceptions::InvalidOperationException,"Probability operator inside quantile formula needs to have a bound.");
STORM_LOG_THROW(!model.isNondeterministicModel()||probOpFormula.hasOptimalityType(),storm::exceptions::InvalidOperationException,"Probability operator inside quantile formula needs to have an optimality type.");
STORM_LOG_WARN_COND(probOpFormula.getBound().comparisonType==storm::logic::ComparisonType::Greater||probOpFormula.getBound().comparisonType==storm::logic::ComparisonType::LessEqual,"Probability operator inside quantile formula needs to have bound > or <=. The specified comparison type might lead to non-termination.");// This has to do with letting bound variables approach infinity, e.g., Pr>0.7 [F "goal"] holds iff Pr>0.7 [F<=B "goal"] holds for some B.
STORM_LOG_THROW(probOpFormula.getSubformula().isBoundedUntilFormula(),storm::exceptions::NotSupportedException,"Quantile formula needs bounded until probability operator formula as subformula. The formula "<<quantileFormula<<" is not supported.");
STORM_LOG_THROW(probOpFormula.getSubformula().isBoundedUntilFormula(),storm::exceptions::NotSupportedException,"Quantile formula needs bounded until probability operator formula as subformula. The formula "<<quantileFormula<<" is not supported.");
STORM_LOG_THROW(!boundedUntilFormula.hasLowerBound(dim),storm::exceptions::NotSupportedException,"Interval bounds are not supported within quantile formulas.");
STORM_LOG_THROW(!boundedUntilFormula.isUpperBoundStrict(dim),storm::exceptions::NotSupportedException,"Only non-strict upper reward bounds are supported for quantiles.");
STORM_LOG_THROW(!boundedUntilFormula.isLowerBoundStrict(dim),storm::exceptions::NotSupportedException,"Only non-strict lower reward bounds are supported for quantiles.");
STORM_LOG_THROW(boundExpression.isVariable(),storm::exceptions::NotSupportedException,"Non-trivial bound expressions such as '"<<boundExpression<<"' are not supported. Either specify a constant or a quantile variable.");
STORM_LOG_THROW(boundVariables.count(boundVariable)==0,storm::exceptions::NotSupportedException,"Variable "<<boundExpression<<" occurs at multiple reward bounds.");
boundVariables.insert(boundVariable);
STORM_LOG_THROW(quantileVariables.count(boundVariable)==1,storm::exceptions::NotSupportedException,"The formula contains undefined constant '"<<boundExpression<<"'.");
}
}
// Only > and <= are supported for upper bounds. This is to make sure that Pr>0.7 [F "goal"] holds iff Pr>0.7 [F<=B "goal"] holds for some B.
// Only >= and < are supported for lower bounds. (EC construction..)
// TODO
// TODO
// Fix precision increasing
// Fix precision increasing
// Multiple quantile formulas in the same file yield constants def clash
// Multiple quantile formulas in the same file yield constants def clash
// Bounds are either constants or variables that are declared in the quantile formula.
// Prop op has optimality type
// No Prmin with lower cost bounds: Ec construction fails. In single obj we would do 1-Prmax[F "nonRewOrNonGoalEC"] but this invalidates other lower/upper cost bounds.
STORM_LOG_ASSERT(transformations.size()==origBoundedUntil.getDimension(),"Tried to replace the bound of a dimension that is higher than the number of dimensions of the formula.");
STORM_LOG_ASSERT(transformations.size()==origBoundedUntil.getDimension(),"Tried to replace the bound of a dimension that is higher than the number of dimensions of the formula.");
STORM_LOG_THROW(false,storm::exceptions::NotSupportedException,"The quantile formula considers "<<getOpenDimensions().getNumberOfSetBits()<<" open dimensions. Only one- or two-dimensional quantiles are supported.");
STORM_LOG_ASSERT(consideredDimensions.isSubsetOf(getOpenDimensions()),"Considered dimensions for a quantile query should be a subset of the set of dimensions without a fixed bound.");
STORM_LOG_THROW(dimensionsAsBitVector.back().getNumberOfSetBits()==1,storm::exceptions::NotSupportedException,"There is not exactly one reward bound referring to quantile variable '"<<dirVar.second.getName()<<"'.");
// When maximizing bounds, the computed single dimensional quantile value is sat for all values of the other bound.
// Increase the computed value so that there is at least one unsat assignment of bounds with B[i] = singleQuantileValues[i]
++singleQuantileValues.back().first;
}
}
// Decrease the value for lower cost bounds to convert >= to >
if(lowerCostBounds[i]){
--singleQuantileValues[i].first;
}
}
std::vector<int64_t>currentEpochValues={(int64_t)singleQuantileValues[0].first,(int64_t)singleQuantileValues[1].first};// signed int is needed to allow lower bounds >-1 (aka >=0).
STORM_LOG_THROW(dimensionsAsBitVector.back().getNumberOfSetBits()==1,storm::exceptions::NotSupportedException,"There is not exactly one reward bound referring to quantile variable '"<<dirVar.second.getName()<<"'.");
// When maximizing, we actually searched for each x-value the smallest y-value that leads to a property violation. Hence, decreasing y by one means property satisfaction