Skip to content

Add upper and lowerbounds to check results. - #1031

Draft
lukovdm wants to merge 3 commits into
stormchecker:masterfrom
lukovdm:soundresults
Draft

Add upper and lowerbounds to check results.#1031
lukovdm wants to merge 3 commits into
stormchecker:masterfrom
lukovdm:soundresults

Conversation

@lukovdm

@lukovdm lukovdm commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Added optional upper and lower bound vectors to ExplicitQuantitativeCheckResult.
Added a solution bounds field to the AbstractEquationSolver which is populated by the solvers.
Currently II and OVI return their bounds through the native and iterative-min-max solver for DTMCs and MDPs.
This was done for until and globally formula.

Comment thread src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp Outdated

// The values of the quantitative check result. These are estimates of the actual values, which lie within
// the bounds below but carry no further guarantee.
boost::variant<vector_type, map_type> values;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have thought that the values itself would now incorporate the type SolutionBounds to already include the lower and upper bounds.
Why are separate lower/upper bounds the better approach?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several of the methods producing bounds currently do so in the form of a vector of lower bounds and a vector of upper bounds. This is also the format they are usually consumed in. I first tried incorporating the bounds in the value, but that led to a lot of rebuilding of vectors from the boundvalues. I thought this was ineligent and it looked slow.

I would like a better way to bundle soundess results of modelchecking that is more universal, but every CheckResult has a slightly different (justified) way of handling its values and thus I did not see a good way to do this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the bare-bone methods return vectors. I would have thought that at the CheckResult stage, the result is somewhat stable and will not change anymore. So this could be good point to go to the SolutionBounds?

I think the general discussion is at what level we want to introduce the SolutionBounds. For me, I would for example already find them useful in some of the helper methods such as Fox-Glynn.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting to have vectors of pairs instead of a pair of vectors? I am not sure I would agree with that, from an algorithm perspective.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep the pair of vectors. I agree that this is more performant.
In the current version using SolutionBounds = std::optional<std::pair<std::vector<ValueType>, std::vector<ValueType>>>; so it would should already fit. I would just use these new type to make sure we have a consistent handling of the bounds.

Comment thread src/storm/solver/SolutionBounds.h Outdated
@lukovdm

lukovdm commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

I will do a pass over the code and clean up any weird AI smells, this draft is mostly so I can have early feedback on the architecture.

std::optional<boost::variant<vector_type, map_type>> lowerBounds;

// Sound upper bounds on the actual values, if an algorithm provided them.
std::optional<boost::variant<vector_type, map_type>> upperBounds;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont know whehter this should be part of this PR, but this could be a good moment to replace boost::variant here with std::variant?

@sjunges

sjunges commented Aug 24, 2026 via email

Copy link
Copy Markdown
Contributor

@volkm

volkm commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Is there a difference between infinity and undefined or can they be considered the same?
For example, a conditional probability should throw an exception if the condition is not reachable but one could also set the result to undefined. There could also be a difference between not calculating the upper bound (undefined) and calculating it but getting infinity (for example in reward queries)? But I am not sure whether there is actually a distinction to be made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants