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;
 
   56    auto const& feasibilitySettings = storm::settings::getModule<storm::settings::modules::FeasibilitySettings>();
 
   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,
 
   84    auto const& feasibilitySettings = storm::settings::getModule<storm::settings::modules::FeasibilitySettings>();
 
   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,
 
  109    auto derSettings = storm::settings::getModule<storm::settings::modules::DerivativeSettings>();
 
  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.");
 
  195    auto regionVerificationSettings = storm::settings::getModule<storm::settings::modules::RegionVerificationSettings>();
 
  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);