42 STORM_LOG_THROW(formula->isRewardOperatorFormula() || formula->isProbabilityOperatorFormula(), storm::exceptions::NotSupportedException,
43 "We only support reward- and probability operator formulas.");
44 STORM_LOG_THROW(regions.size() <= 1, storm::exceptions::NotSupportedException,
"Storm only supports one or zero regions.");
46 std::shared_ptr<storm::logic::Formula const> formulaNoBound;
47 if (formula->asOperatorFormula().hasBound()) {
48 std::shared_ptr<storm::logic::Formula> formulaWithoutBounds = formula->clone();
49 formulaWithoutBounds->asOperatorFormula().removeBound();
50 formulaNoBound = formulaWithoutBounds->asSharedPointer();
52 formulaNoBound = formula;
58 if (formula->asOperatorFormula().hasBound()) {
59 t.
setBound(formula->asOperatorFormula().getBound());
61 STORM_LOG_THROW(!feasibilitySettings.isParameterDirectionSet(), storm::exceptions::NotSupportedException,
62 "With a bound, the direction for the parameters is inferred from the bound.");
63 STORM_LOG_THROW(!feasibilitySettings.hasOptimalValueGuaranteeBeenSet(), storm::exceptions::NotSupportedException,
64 "When a bound is given, the guarantee is that this bound will be satisfied by a solution.");
66 if (feasibilitySettings.hasOptimalValueGuaranteeBeenSet()) {
67 t.
setMaximalAllowedGap(storm::utility::convertNumber<storm::RationalNumber>(feasibilitySettings.getOptimalValueGuarantee()));
70 STORM_LOG_THROW(feasibilitySettings.isParameterDirectionSet(), storm::exceptions::NotSupportedException,
71 "Without a bound, the direction for the parameters must be explicitly given.");
74 if (regions.size() == 1) {
77 return std::make_shared<FeasibilitySynthesisTask const>(std::move(t));
82 std::shared_ptr<storm::pars::FeasibilitySynthesisTask const>
const& task,
87 if (task->isRegionSet()) {
101 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"SCP is not yet implemented.");
107 std::shared_ptr<storm::pars::FeasibilitySynthesisTask const>
const& task,
112 "Gradient descent is currently only supported for DTMCs.");
113 STORM_LOG_THROW(!task->isRegionSet(), storm::exceptions::NotSupportedException,
"Gradient descent only works with *the* graph-preserving region.");
114 std::shared_ptr<storm::models::sparse::Dtmc<ValueType>> dtmc = model->template as<storm::models::sparse::Dtmc<ValueType>>();
116 STORM_LOG_THROW(task->getFormula().isProbabilityOperatorFormula() || task->getFormula().isRewardOperatorFormula(), storm::exceptions::NotSupportedException,
117 "Input formula needs to be either a probability operator formula or a reward operator formula.");
118 STORM_LOG_THROW(task->isBoundSet(), storm::exceptions::NotImplementedException,
"GD (right now) requires an explicitly given bound.");
119 STORM_LOG_THROW(task->getMaximalAllowedGap() == std::nullopt, storm::exceptions::NotSupportedException,
120 "GD cannot provide guarantees on the optimality of the solution..");
122 if (omittedParameters && !omittedParameters->empty()) {
124 std::cout <<
"Parameters ";
125 for (
auto const& entry : *omittedParameters) {
126 std::cout << entry <<
" ";
128 std::cout <<
"are inconsequential.";
129 if (derSettings.areInconsequentialParametersOmitted()) {
130 std::cout <<
" They will be omitted in the found instantiation.\n";
132 std::cout <<
" They will be set to 0.5 in the found instantiation. To omit them, set the flag --omit-inconsequential-params.\n";
136 boost::optional<derivative::GradientDescentConstraintMethod> constraintMethod = derSettings.getConstraintMethod();
137 if (!constraintMethod) {
138 STORM_LOG_ERROR(
"Unknown Gradient Descent Constraint method: " << derSettings.getConstraintMethodAsString());
142 boost::optional<derivative::GradientDescentMethod> method = derSettings.getGradientDescentMethod();
144 STORM_LOG_ERROR(
"Unknown Gradient Descent method: " << derSettings.getGradientDescentMethodAsString());
151 STORM_PRINT(
"Finding an extremum using Gradient Descent\n");
154 *dtmc, *method, derSettings.getLearningRate(), derSettings.getAverageDecay(), derSettings.getSquaredAverageDecay(), derSettings.getMiniBatchSize(),
155 derSettings.getTerminationEpsilon(), startPoint, *constraintMethod, derSettings.isPrintJsonSet());
160 if (!derSettings.areInconsequentialParametersOmitted() && omittedParameters) {
163 instantiationAndValue.first[param] = startPoint->at(param);
165 instantiationAndValue.first[param] = utility::convertNumber<RationalFunction::CoeffType>(0.5);
169 derivativeWatch.
stop();
172 std::pair<double, typename storm::storage::ParameterRegion<ValueType>::Valuation> valueValuationPair;
173 valueValuationPair.first = instantiationAndValue.second;
174 valueValuationPair.second = instantiationAndValue.first;
176 if (derSettings.isPrintJsonSet()) {
180 if (task->isBoundSet()) {
181 printFeasibilityResult(task->getBound().isSatisfied(valueValuationPair.first), valueValuationPair, derivativeWatch);
189 std::shared_ptr<storm::pars::FeasibilitySynthesisTask const>
const& task,
191 STORM_LOG_THROW(task->isRegionSet(), storm::exceptions::NotSupportedException,
"PLA requires an explicitly given region.");
196 auto engine = regionVerificationSettings.getRegionCheckEngine();
197 bool generateSplitEstimates = regionVerificationSettings.isSplittingThresholdSet();
199 if (task->isBoundSet()) {
201 auto valueValuation = storm::api::computeExtremalValue<ValueType>(
202 model, storm::api::createTask<ValueType>(task->getFormula().asSharedPointer(),
true), task->getRegion(), engine, direction,
203 storm::utility::zero<ValueType>(), !task->isMaxGapRelative(), monotonicitySettings, task->getBound().getInvertedBound(), generateSplitEstimates);
208 STORM_LOG_THROW(task->getMaximalAllowedGap() != std::nullopt, storm::exceptions::NotSupportedException,
209 "Without a bound, PLA requires an explicit target in form of a guarantee.");
211 ValueType precision = storm::utility::convertNumber<ValueType>(task->getMaximalAllowedGap().value());
213 auto valueValuation = storm::api::computeExtremalValue<ValueType>(model, storm::api::createTask<ValueType>(task->getFormula().asSharedPointer(),
true),
214 task->getRegion(), engine, direction, precision, !task->isMaxGapRelative(),
215 monotonicitySettings, std::nullopt, generateSplitEstimates);