Skip to content

DieHardest: compare jug configurations via parallel and interleaved self-composition#199

Open
lemmy wants to merge 1 commit intomasterfrom
mku-DieHardest
Open

DieHardest: compare jug configurations via parallel and interleaved self-composition#199
lemmy wants to merge 1 commit intomasterfrom
mku-DieHardest

Conversation

@lemmy
Copy link
Member

@lemmy lemmy commented Feb 13, 2026

Add DieHardest.tla, which composes two instances of DieHarder to compare which configuration has the shorter path to the Goal (state).

Four composition approaches are contrasted in clearly labeled sections that progressively motivate interleaved composition:

  1. Parallel — shows that BFS finds the shortest path for the slower configuration but not the faster one.
  2. Parallel + "per-behavior freeze" — shows that freezing after reaching the Goal does not help.
  3. Parallel + "global BFS-level freeze" — correct, but relies on TLC-specific operators.
  4. Interleaved — each instance steps independently, so BFS minimizes both step counts.

@lemmy lemmy self-assigned this Feb 13, 2026
@lemmy lemmy force-pushed the mku-DieHardest branch 2 times, most recently from d872bd6 to f9d4e0c Compare February 25, 2026 18:49
@lemmy lemmy changed the title DieHardest: compare jug configurations via self-composition DieHardest: compare jug configurations via parallel and interleaved self-composition Feb 25, 2026
@lemmy lemmy requested a review from Copilot February 25, 2026 19:45

This comment was marked as resolved.

Add DieHardest.tla, which composes two instances of DieHarder to
check a 2-hyperproperty as an ordinary invariant: given two jug
configurations that can each solve the Die Hard problem, which one
reaches the Goal in fewer steps?  The invariant NotSolved holds as
long as both configurations have not yet reached the Goal; a
counterexample is a behavior in which both solve the problem,
revealing which configuration is faster.

The module also defines HasSolution, a GCD-based predicate (via
Bézout's identity) used in ASSUME to reject unsolvable
configurations before model checking begins.

Four composition approaches are contrasted in clearly labeled
sections that progressively motivate interleaved composition:

  1. Parallel — shows that BFS finds the shortest path for the slower
     configuration but not the faster one.
  2. Parallel + per-behavior freeze — shows that freezing after
     reaching the Goal does not help.
  3. Parallel + g BFS-level freeze — correct, but relies on
     TLC-specific operators outsi the logic of TLA+.
  4. Interleaved — the clean solution: each instanceteps
     independently, so BFS minimizes both step counts.

Annotated counterexample traces in Sections 1 and 3 illustrate the
difference concretely.

MCDieHardest instantiates the spec with Goal = 4, comparing a 2-jug
<<5, 3>> setup against a 3-jug <<5, 3, 3>> setup — the duplicate jug
reduces the shortest solution from 6 to steps.

Co-authored-by: Dmitry Kulagin <craft095@users.noreply.github.com>
Signed-off-by: Markus Alexander Kuppe <github.com@lemmster.de>
@lemmy lemmy marked this pull request as ready for review February 25, 2026 22:13
@lemmy
Copy link
Member Author

lemmy commented Feb 25, 2026

@hwayne Could you please review this example? It references your “Hypermodeling Hyperproperties” article.

(* *)
(* Both paths are individually shortest. However, TLCSet and TLCGet *)
(* are TLC-specific operators outside the logic of TLA+, making this *)
(* approach incompatible with other TLA+ tools (e.g. Apalache). *)
Copy link

Choose a reason for hiding this comment

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

Also, unless things changed recently, TLC global registers are local to each worker

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed, this would also only work with a single worker.

@hwayne
Copy link

hwayne commented Feb 26, 2026

These solutions depend on two assumptions: that the states are searched with BFS, and that the BFS is strict. The first is violated with the -depth and -simulate parameters. I've seen the second be violated when using multiple workers:

  1. worker 1 picks the last state of length N on the queue
  2. worker 2 picks the first state of length N+1
  3. Both workers are evaluating a state that violates an invariant, but
  4. worker 2 reaches the violation before worker 1 does.

It's pretty rare, but I've seen it happen!

A robust and universal TLA+ spec would probably have to store the diehard traces as data values and implement Dijkstra's algorithm to find the shortest path, with the property that <>[](shortest_c1 <= shortest_c2).

@lemmy
Copy link
Member Author

lemmy commented Feb 26, 2026

These solutions depend on two assumptions: that the states are searched with BFS, and that the BFS is strict. The first is violated with the -depth and -simulate parameters. I've seen the second be violated when using multiple workers:

  1. worker 1 picks the last state of length N on the queue
  2. worker 2 picks the first state of length N+1
  3. Both workers are evaluating a state that violates an invariant, but
  4. worker 2 reaches the violation before worker 1 does.

It's pretty rare, but I've seen it happen!

A robust and universal TLA+ spec would probably have to store the diehard traces as data values and implement Dijkstra's algorithm to find the shortest path, with the property that <>[](shortest_c1 <= shortest_c2).

Strict BFS has in fact been an implicit assumption in the current formulation. This directly contradicts the spec's own statement: "This approach stays entirely within the logic of TLA+ and is compatible with all TLA+ tools."

Given that contradiction, what do you think about removing that statement and instead making the assumption explicit, for example:

ASSUME TLCGet("config").mode = "bfs" /\ TLCGet("config").worker = 1

In my view, the example would still offer an interesting and valuable perspective on self-composition, even with this assumption made explicit.

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

Development

Successfully merging this pull request may close these issues.

3 participants