Skip to content

New Sparse Bisimulation - #1049

Open
tquatmann wants to merge 27 commits into
stormchecker:masterfrom
tquatmann:feature/revised-bisim
Open

tquatmann wants to merge 27 commits into
stormchecker:masterfrom
tquatmann:feature/revised-bisim

Conversation

@tquatmann

Copy link
Copy Markdown
Contributor

Completely revised sparse bisimulation implementation.

What's new

  • Usually faster compared to the current implementation. In particular for MDPs.
  • Now supports Markov automata, multiple reward models, preservation of choice labels.
  • Returns mappings between quotient and original model states/choices. Useful, e.g. to translate a scheduler for the quotient model to a scheduler for the original model.
  • More explicit and robust handling of the approximate case (tolerance > 0), in particular for MDPs where choices might be "equivalent up to a tolerance".
  • (hopefully) no more undefined behaviour with positive tolerances: previously std::sort was called on a non-total order induced by the ConstantsComparator. There is still an issue with RationalFunction which imo should be handled within carl.
  • Moved to transformer (see also Restructure storage directory #1033).
  • fix Differences in CTMC bisimulation quotient #833.

Where to start

performBisimulationMinimization in Bisimulation.cpp serves as an entry point and goes through the three min steps of bisimulation minimization:

  1. Compute an initial partition based on the properties to preserve and on provided options.
  2. Apply partition refinement (Splitter-based for DTMC/CTMC or Signature-based for DTMC/CTMC/MDP/MA)
  3. Build the quotient from the partition.

Caveats

I deliberately did not port the "measure driven initial partitions", which lump together states with equal value (e.g. prob0/prob1 states for a P=? [ F "target" ] query). While that could be useful in certain cases, I found that it made the entire procedure significantly more complicated—conceptually (qualitative model checking would be a subtask of bisimulation, which is a preprocessing for model checking...) and code-wise.
The functionality has been moved into mergeEquivalentStatesForFormula which can be combined with bisimulation. Hence the combination--merge-equivalent-states --bisimulation should be equivalent to the old --bisimulation, except that the new one has to create an intermediate model. #91 is relevant.

@tquatmann

Copy link
Copy Markdown
Contributor Author

Here's a quick performance comparison between old (current master) and new (this PR) implementation generated using this script benchmark.py

+==============================+==========+==============+==============+============+============+
| Metric                       |    Model | New (strong) | Old (strong) | New (weak) | Old (weak) |
+==============================+==========+==============+==============+============+============+
| csma3-4 (MDP)                |          |              |              |            |            |
| States                       |  1460287 |        30422 |        30422 |          - |          - |
| Choices                      |  1471059 |        30870 |        30870 |          - |          - |
| Transitions                  |  2396727 |        64996 |        64996 |          - |          - |
| Time (s)                     |    3.768 |        1.021 |       14.421 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| csma4-2 (MDP)                |          |              |              |            |            |
| States                       |   761962 |         9901 |         9901 |          - |          - |
| Choices                      |   825504 |        10574 |        10574 |          - |          - |
| Transitions                  |  1327068 |        17526 |        17526 |          - |          - |
| Time (s)                     |    2.310 |        0.315 |        7.788 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| wlan3-COL0 (MDP)             |          |              |              |            |            |
| States                       |    96302 |        35707 |        35707 |          - |          - |
| Choices                      |   123730 |        39732 |        39732 |          - |          - |
| Transitions                  |   204576 |        79083 |        79083 |          - |          - |
| Time (s)                     |    0.215 |        0.089 |        5.820 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| firewire-false-delay36 (MDP) |          |              |              |            |            |
| States                       |   212268 |        12413 |        12413 |          - |          - |
| Choices                      |   478756 |        17897 |        17897 |          - |          - |
| Transitions                  |   481792 |        18083 |        18083 |          - |          - |
| Time (s)                     |    0.754 |        0.144 |       12.977 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| pnueli-zuck5 (MDP)           |          |              |              |            |            |
| States                       |   307523 |        12116 |        12116 |          - |          - |
| Choices                      |  1753715 |        57321 |        63676 |          - |          - |
| Transitions                  |  1886851 |        61804 |        68325 |          - |          - |
| Time (s)                     |    1.340 |        1.138 |        6.091 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| ij10 (MDP)                   |          |              |              |            |            |
| States                       |     1023 |           77 |           77 |          - |          - |
| Choices                      |     5120 |          272 |          336 |          - |          - |
| Transitions                  |     8950 |          456 |          564 |          - |          - |
| Time (s)                     |    0.007 |        0.002 |        0.016 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| consensus6-2 (MDP)           |          |              |              |            |            |
| States                       |  1258240 |         9328 |         9328 |          - |          - |
| Choices                      |  5008128 |        21745 |        21962 |          - |          - |
| Transitions                  |  6236736 |        27196 |        27460 |          - |          - |
| Time (s)                     |    3.369 |        1.463 |       21.063 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| resources25-25-5 (MDP)       |          |              |              |            |            |
| States                       |    63544 |        60526 |        60526 |          - |          - |
| Choices                      |   204152 |       194576 |       194576 |          - |          - |
| Transitions                  |   220376 |       210226 |       210226 |          - |          - |
| Time (s)                     |    0.231 |        0.114 |        4.839 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| nand35-5 (DTMC)              |          |              |              |            |            |
| States                       |  3020652 |      2448222 |      2448222 |          - |          - |
| Choices                      |  3020652 |      2448222 |      2448222 |          - |          - |
| Transitions                  |  4737492 |      3795063 |      3795063 |          - |          - |
| Time (s)                     |    2.776 |        0.722 |        3.869 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+
| crowds10-10 (DTMC)           |          |              |              |            |            |
| States                       | 10647781 |          181 |          181 |         93 |         93 |
| Choices                      | 10647781 |          181 |          181 |         93 |         93 |
| Transitions                  | 25622741 |          271 |          271 |        183 |        183 |
| Time (s)                     |   16.693 |        0.896 |        2.046 |      2.884 |      8.497 |
+------------------------------+----------+--------------+--------------+------------+------------+
| herman15 (DTMC)              |          |              |              |            |            |
| States                       |    32768 |          612 |          612 |          2 |          2 |
| Choices                      |    32768 |          612 |          612 |          2 |          2 |
| Transitions                  | 14348908 |       104721 |       104721 |          2 |          2 |
| Time (s)                     |    5.694 |        0.265 |        0.428 |      0.294 |      2.226 |
+------------------------------+----------+--------------+--------------+------------+------------+
| cluster100 (CTMC)            |          |              |              |            |            |
| States                       |   365620 |       183113 |       183113 |     183113 |     183113 |
| Choices                      |   365620 |       183113 |       183113 |     183113 |     183113 |
| Transitions                  |  1779232 |       889919 |       889919 |     889919 |     889919 |
| Time (s)                     |    0.986 |        0.154 |       13.914 |      0.193 |      8.503 |
+------------------------------+----------+--------------+--------------+------------+------------+
| philosophers16 (CTMC)        |          |              |              |            |            |
| States                       |  1331714 |        83311 |        83311 |      83311 |      83311 |
| Choices                      |  1331714 |        83311 |        83311 |      83311 |      83311 |
| Transitions                  | 13774113 |       860723 |       860723 |     860723 |     860722 |
| Time (s)                     |    8.015 |        0.895 |       11.656 |      1.390 |     11.669 |
+------------------------------+----------+--------------+--------------+------------+------------+
| haddadmonmege (DTMC)         |          |              |              |            |            |
| States                       | 10000001 |     10000001 |     10000001 |          - |          - |
| Choices                      | 10000001 |     10000001 |     10000001 |          - |          - |
| Transitions                  | 20000000 |     20000000 |     20000000 |          - |          - |
| Time (s)                     |    6.556 |        2.049 |        4.005 |          - |          - |
+------------------------------+----------+--------------+--------------+------------+------------+

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Replaces the legacy sparse bisimulation engine with a transformer-based implementation supporting MAs, rewards, tolerances, choice metadata, weak bisimulation, and quotient mappings.

Changes:

  • Adds new partition-refinement, signature, quotient, and mapping infrastructure.
  • Migrates APIs, CLI settings, formula traversal, and callers.
  • Replaces legacy tests with comprehensive transformer-based coverage.
File summaries
File Description
src/test/storm/transformer/bisimulation/PartitionTest.cpp Updated as part of this pull request.
src/test/storm/transformer/bisimulation/BisimulationTestHelper.h Updated as part of this pull request.
src/test/storm/storage/SymbolicBisimulationDecompositionTest.cpp Updated as part of this pull request.
src/test/storm/storage/NondeterministicModelBisimulationDecompositionTest.cpp Updated as part of this pull request.
src/test/storm/storage/DeterministicModelBisimulationDecompositionTest.cpp Updated as part of this pull request.
src/test/storm/logic/TraverseFormulaVisitorTest.cpp Updated as part of this pull request.
src/test/storm-pars/transformer/BinaryDtmcTransformerTest.cpp Updated as part of this pull request.
src/test/storm-pars/transformer/BigStepTest.cpp Updated as part of this pull request.
src/test/storm-pars/modelchecker/SparseDtmcParameterLiftingMonotonicityTest.cpp Updated as part of this pull request.
src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp Updated as part of this pull request.
src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityHelperTest.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/WeakBisimulationData.h Updated as part of this pull request.
src/storm/transformer/bisimulation/WeakBisimulationData.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/SplitterBasedRefinement.h Updated as part of this pull request.
src/storm/transformer/bisimulation/SparseAccumulator.h Updated as part of this pull request.
src/storm/transformer/bisimulation/SparseAccumulator.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/Signatures.h Updated as part of this pull request.
src/storm/transformer/bisimulation/SignatureBasedRefinement.h Updated as part of this pull request.
src/storm/transformer/bisimulation/SignatureBasedRefinement.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/QuotientData.h Updated as part of this pull request.
src/storm/transformer/bisimulation/QuotientData.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/Quotient.h Updated as part of this pull request.
src/storm/transformer/bisimulation/Quotient.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/PreservationInformation.h Updated as part of this pull request.
src/storm/transformer/bisimulation/Partition.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/Options.h Updated as part of this pull request.
src/storm/transformer/bisimulation/Options.cpp Updated as part of this pull request.
src/storm/transformer/bisimulation/Initialization.h Updated as part of this pull request.
src/storm/transformer/bisimulation/BisimulationType.h Updated as part of this pull request.
src/storm/transformer/bisimulation/Bisimulation.h Updated as part of this pull request.
src/storm/transformer/bisimulation/Bisimulation.cpp Updated as part of this pull request.
src/storm/storage/sparse/ChoiceOrigins.h Updated as part of this pull request.
src/storm/storage/sparse/ChoiceOrigins.cpp Updated as part of this pull request.
src/storm/storage/dd/bisimulation/PreservationInformation.h Updated as part of this pull request.
src/storm/storage/dd/bisimulation/Partition.h Updated as part of this pull request.
src/storm/storage/dd/bisimulation/Partition.cpp Updated as part of this pull request.
src/storm/storage/dd/bisimulation/BisimulationDecomposition.h Updated as part of this pull request.
src/storm/storage/dd/bisimulation/BisimulationDecomposition.cpp Updated as part of this pull request.
src/storm/storage/bisimulation/Partition.h Updated as part of this pull request.
src/storm/storage/bisimulation/Partition.cpp Updated as part of this pull request.
src/storm/storage/bisimulation/NondeterministicModelBisimulationDecomposition.h Updated as part of this pull request.
src/storm/storage/bisimulation/NondeterministicModelBisimulationDecomposition.cpp Updated as part of this pull request.
src/storm/storage/bisimulation/DeterministicModelBisimulationDecomposition.h Updated as part of this pull request.
src/storm/storage/bisimulation/DeterministicBlockData.h Updated as part of this pull request.
src/storm/storage/bisimulation/DeterministicBlockData.cpp Updated as part of this pull request.
src/storm/storage/bisimulation/Block.h Updated as part of this pull request.
src/storm/storage/bisimulation/Block.cpp Updated as part of this pull request.
src/storm/storage/bisimulation/BisimulationType.h Updated as part of this pull request.
src/storm/storage/bisimulation/BisimulationDecomposition.h Updated as part of this pull request.
src/storm/storage/bisimulation/BisimulationDecomposition.cpp Updated as part of this pull request.
src/storm/settings/modules/BisimulationSettings.h Updated as part of this pull request.
src/storm/settings/modules/BisimulationSettings.cpp Updated as part of this pull request.
src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp Updated as part of this pull request.
src/storm/modelchecker/AbstractModelChecker.cpp Updated as part of this pull request.
src/storm/logic/TraverseFormulaVisitor.h Updated as part of this pull request.
src/storm/logic/TraverseFormulaVisitor.cpp Updated as part of this pull request.
src/storm/logic/Formula.h Updated as part of this pull request.
src/storm/logic/Formula.cpp Updated as part of this pull request.
src/storm/api/bisimulation.h Updated as part of this pull request.
src/storm-pomdp-cli/storm-pomdp.cpp Updated as part of this pull request.
src/storm-gamebased-ar/modelchecker/abstraction/BisimulationAbstractionRefinementModelChecker.cpp Updated as part of this pull request.
src/storm-dft/modelchecker/DFTModelChecker.cpp Updated as part of this pull request.
src/storm-cli-utilities/model-handling.h Updated as part of this pull request.
Review details

Suppressed comments (4)

src/storm-cli-utilities/model-handling.h:724

  • The graphPreserving argument is now ignored, so the --assume-graph-preserving false path no longer switches to the old all-label preservation mode. In that mode, formula-based FormulaPropositional preservation can merge states that differ in labels outside the maximal propositional subformulas, changing the region-analysis model and potentially invalidating the intended non-graph-preserving behavior; use graphPreserving to select StateLabelPreservation::All (and retain the existing reward-selection semantics).
    return storm::api::performBisimulationMinimization<ValueType>(model, createFormulasToRespect(input.properties), options);

src/storm/transformer/bisimulation/Bisimulation.cpp:117

  • The new public state/choice mapping result is not exercised by the bisimulation tests: the current tests only inspect quotient sizes and formula values. A regression in representative selection or mapping non-representative MDP choices would therefore go unnoticed even though scheduler translation is a stated feature; add assertions for both state mappings and choice mappings (including deduplicated choices).
    src/storm/transformer/bisimulation/Quotient.cpp:141
  • The quotient currently drops stateValuations even when the input model has them. This loses state-variable metadata used by exporters and downstream transformations; preserve the representative state entries here, consistent with SubsystemBuilder and GoalStateMerger.
    src/storm/transformer/bisimulation/Signatures.cpp:127
  • devided is misspelled in this newly added comment; it should be divided.
  • Files reviewed: 70/70 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/storm/transformer/bisimulation/Partition.cpp
Comment thread src/storm/api/bisimulation.h
Comment thread src/test/storm/transformer/bisimulation/PartitionTest.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@tquatmann
tquatmann requested a lite review from Copilot September 12, 2026 13:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (6)

Previously missed (3) — in code that hasn't changed since the last review.

src/storm-cli-utilities/model-handling.h:724

  • The parametric CLI passes graphPreserving into this helper, but this call never uses it when constructing the sparse bisimulation options. Consequently --assume-graph-preserving false has no effect on this preprocessing path, even though both callers still pass that setting. Please either propagate the setting into the new implementation or remove/update the parameter and callers if the option is intentionally unsupported.
    src/storm/transformer/bisimulation/Quotient.cpp:139
  • This quotient rebuilds labels and rewards but silently drops stateValuations whenever the input model has them. That loses state metadata used by model exporters, schedulers, and counterexamples; other sparse transformations select representative valuations (for example GoalStateMerger). Copy the valuations for toRepresentativeState here, or explicitly reject/warn if this transformation is not meant to preserve them.
    src/storm/transformer/bisimulation/Signatures.cpp:127
  • The comment contains the typo devided; please correct it to divided.

src/storm/transformer/bisimulation/Partition.h:174

  • The documentation should use the plural “sub-blocks” because a proper superblock contains more than one sub-block.
    src/storm/transformer/bisimulation/Signatures.cpp:390
  • The PR exposes toQuotientChoiceMapping, but the tests never request or validate it, including the approximate matching path for choices of non-representative states. Since the implementation has separate representative and non-representative mapping logic below, add focused deterministic and MDP tests covering deduplication and tolerance-based matching.
    src/test/storm/transformer/bisimulation/PartitionTest.cpp:74
  • This comment uses “their” for the singular block and contains an extra space; please correct the grammar.
  • Files reviewed: 70/70 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src/storm/transformer/bisimulation/Quotient.cpp Outdated
Comment thread src/test/storm/transformer/bisimulation/PartitionTest.cpp Outdated
Comment thread src/storm/logic/TraverseFormulaVisitor.h
Comment thread src/storm/logic/Formula.h Outdated
.build())
.build());

this->addOption(storm::settings::OptionBuilder(moduleName, toleranceOptionName, true,

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.

is this now also used for dd-based bisim?

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.

The tolerance is currently sparse only. The help message already mentions this. Should I make this more clear somehow?

dd-bisim does not use any tolerance-based comparison right now.
This example yields some evidence: sparse-bisim correctly yields a quotient with 4 states while dd-bisim yields a quotient with 5 states.

dtmc
module M
  s : [0..5] init 0;
  [] s=0 -> 0.5: (s'=1) + 0.5: (s'=2);
  [] s=1 -> 0.1: (s'=3) + 0.2: (s'=4) + 0.7: (s'=5);
  [] s=2 -> 0.3: (s'=3) + 0.7: (s'=5);
  [] s>2 -> true;
endmodule
label "target" = s=3 | s=4;

Note that (s=3 and s=4) and (s=1 and s=2) are bisimular, but s=1 and s=2 are split because 0.1+0.2==0.3 doesn't hold in double arithmethic. sparse-bisim with --bisimulation:tolerance 0 has the same problem.

return indexToIdentifier[choiceIndex];
}

std::vector<uint_fast64_t> const& ChoiceOrigins::getIdentifiers() const {

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.

dont use fast64_t

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 how it is consistent :-)

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.

Yes, this was intentional because we take that vector by reference.
I'd rather keep it this way and globally replace all remaining fast64_t at a convenient time.

@tquatmann
tquatmann requested a lite review from Copilot September 12, 2026 19:47
Comment thread src/storm/logic/TraverseFormulaVisitor.h

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Critical issues remain in preprocessing, quotient valuation preservation, and tolerance handling.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (3)

src/storm/transformer/bisimulation/Bisimulation.cpp:117

  • The advertised state/choice mappings are not exercised by the new bisimulation tests: none enables createQuotientChoiceMapping or checks mappings after choice deduplication/approximate matching. Please add regression tests for deterministic and MDP quotients (including the representative-choice and non-representative-choice paths) so this public result cannot silently regress.
    src/storm/transformer/bisimulation/Signatures.cpp:127
  • The new comment misspells “divided”; please correct it to keep the explanatory documentation clear.
    src/test/storm/transformer/bisimulation/PartitionTest.cpp:74
  • This new test comment contains a duplicated space in “their remainder”; please remove the extra space.
  • Files reviewed: 70/70 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread src/storm-cli-utilities/model-handling.h
Comment thread src/storm/transformer/bisimulation/Quotient.cpp
Comment thread src/storm/transformer/bisimulation/Signatures.cpp

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Approximate choice mappings can be non-injective, preventing reliable quotient-scheduler translation for some equivalent states.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 71/71 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/storm/transformer/bisimulation/Signatures.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

It replaces the core sparse bisimulation engine across multiple model types and removes the legacy implementation, requiring final human validation.

Review effort: Lite
Findings: None

Resolved since last review (1)

@volkm
volkm self-requested a review September 22, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Differences in CTMC bisimulation quotient

3 participants