STORM_LOG_TRACE("initializing multi-dimensional reward unfolding for formula "<<*objectiveFormula<<" and "<<infinityBoundVariables.size()<<" bound variables should approach infinity.");
// for simplicity we do not allow interval formulas.
STORM_LOG_THROW(!subformula.hasLowerBound(dim)||!subformula.hasUpperBound(dim),storm::exceptions::NotSupportedException,"Bounded until formulas are only supported by this method if they consider either an upper bound or a lower bound. Got "<<subformula<<" instead.");
// lower bounded until formulas with non-trivial left hand side are excluded as this would require some additional effort (in particular the ProductModel::transformMemoryState method).
STORM_LOG_THROW(dimension.isUpperBounded||subformula.getLeftSubformula(dim).isTrueFormula(),storm::exceptions::NotSupportedException,"Lower bounded until formulas are only supported by this method if the left subformula is 'true'. Got "<<subformula<<" instead.");
STORM_LOG_THROW(subformula.hasUpperBound(dim)||subformula.getLeftSubformula(dim).isTrueFormula(),storm::exceptions::NotSupportedException,"Lower bounded until formulas are only supported by this method if the left subformula is 'true'. Got "<<subformula<<" instead.");
// Treat formulas that aren't acutally bounded differently
STORM_LOG_THROW(this->model.hasRewardModel(rewardName),storm::exceptions::IllegalArgumentException,"No reward model with name '"<<rewardName<<"' found.");
STORM_LOG_THROW(!rewardModel.hasTransitionRewards(),storm::exceptions::NotSupportedException,"Transition rewards are currently not supported as reward bounds.");
STORM_LOG_THROW(this->model.hasRewardModel(rewardName),storm::exceptions::IllegalArgumentException,"No reward model with name '"<<rewardName<<"' found.");
STORM_LOG_THROW(!rewardModel.hasTransitionRewards(),storm::exceptions::NotSupportedException,"Transition rewards are currently not supported as reward bounds.");
STORM_LOG_THROW(!(dimension.formula->asCumulativeRewardFormula().getBound().isVariable()&&infinityBoundVariables.count(dimension.formula->asCumulativeRewardFormula().getBound().getBaseExpression().asVariableExpression().getVariable())>0),storm::exceptions::NotSupportedException,"Letting cumulative reward bounds approach infinite is not supported.");
// We can currently only handle this case for single maximizing bounded until probability objectives.
// The approach is to erase all epochSteps that are not part of an end component and then change the reward bound to '> 0'.
// Then, reaching a reward means reaching an end component where arbitrarily many reward can be collected.
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(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(upperBoundedDimensions.empty()||!probabilityOperatorFormula.getSubformula().asBoundedUntilFormula().isMultiDimensional(),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(setUnknownDimsToBottom||!dimensions[dim].isBounded,storm::exceptions::UnexpectedException,"Tried to obtain the start epoch although not all dimensions are known.");
STORM_LOG_THROW(setUnknownDimsToBottom||dimensions[dim].boundType==DimensionBoundType::Unbounded,storm::exceptions::UnexpectedException,"Tried to obtain the start epoch although no bound on dimension "<<dim<<" is known.");
STORM_LOG_ASSERT(epochSolutionIt!=epochSolutions.end(),"Requested unexisting solution for epoch "<<epochManager.toString(epoch)<<".");
autoconst&epochSolution=epochSolutionIt->second;
STORM_LOG_ASSERT(productState<epochSolution.productStateToSolutionVectorMap->size(),"Requested solution for epoch "<<epochManager.toString(epoch)<<" at an unexisting product state.");
STORM_LOG_ASSERT((*epochSolution.productStateToSolutionVectorMap)[productState]<epochSolution.solutions.size(),"Requested solution for epoch "<<epochManager.toString(epoch)<<" at a state for which no solution was stored.");
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.");
if(!productModel->getProb1Objectives().empty()){
STORM_LOG_THROW(SingleObjectiveMode,storm::exceptions::NotSupportedException,"One of the objectives is already satisfied in the initial state. This is not implemented in multi-objective mode.");
// At this point we can check whether there is an initial state that already satisfies all subObjectives.
// Such a situation is not supported as we can not reduce this (easily) to an expected reward computation.
STORM_LOG_THROW(!memStatePrimeBV.empty()||initialTransitionStates.empty()||objectiveContainsLowerBound||initialTransitionStates.isDisjointFrom(constraintStates),storm::exceptions::NotSupportedException,"The objective "<<*objectives[objIndex].formula<<" is already satisfied in an initial state. This special case is not supported.");
// Such a situation can not be reduced (easily) to an expected reward computation.
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.");
STORM_LOG_ASSERT(productStateExists(modelState,memoryState),"Tried to obtain a state in the model-memory-product that does not exist");
STORM_LOG_ASSERT(productStateExists(modelState,memoryState),"Tried to obtain state ("<<modelState<<", "<<memoryStateManager.toString(memoryState)<<") in the model-memory-product which does not exist");
// 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
// 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_THROW(false,storm::exceptions::InvalidOperationException,"The bound variable '"<<dimVar.getName()<<"' is not specified within the quantile formula '"<<quantileFormula<<"'.");
STORM_LOG_ASSERT(!upperCostBound,"It is not possible to let other open dimensions approach infinity if this is an upper cost bound and others are lower cost bounds.");
STORM_LOG_ASSERT(std::find(bts.begin(),bts.end(),BoundTransformation::GreaterZero)==bts.end(),"Unable to compute extremal value for minimizing lower and upper bounded dimensions.");
}else{
bts[d]=BoundTransformation::GreaterZero;
minimizingLowerBoundedDimensions.set(d,true);
STORM_LOG_ASSERT(std::find(bts.begin(),bts.end(),BoundTransformation::LessEqualZero)==bts.end(),"Unable to compute extremal value for minimizing lower and upper bounded dimensions.");