Skip to content

Better isolation of non-determinism in Core#617

Draft
MikaelMayer wants to merge 22 commits intomainfrom
issue-612-better-isolation-of-non-determinism-in-c
Draft

Better isolation of non-determinism in Core#617
MikaelMayer wants to merge 22 commits intomainfrom
issue-612-better-isolation-of-non-determinism-in-c

Conversation

@MikaelMayer
Copy link
Copy Markdown
Contributor

@MikaelMayer MikaelMayer commented Mar 19, 2026

Summary

Completes the isolation of non-determinism in the Strata Core dialect by extending ExprOrNondet from commands (init/set) to statement-level constructs (ite/loop).

Problem

The previous commits on this branch replaced Option/havoc with ExprOrNondet in Cmd, but Stmt.ite and Stmt.loop still used P.Expr for their conditions/guards. This meant non-deterministic branching and looping could only be expressed indirectly.

Solution

Changed Stmt.ite and Stmt.loop to use ExprOrNondet P for their condition/guard fields. When the condition is .nondet, the branch or loop iteration is chosen arbitrarily.

Key changes:

  • Stmt.ite condition and Stmt.loop guard now accept ExprOrNondet P
  • Big-step semantics: added ite_nondet_true_sem/ite_nondet_false_sem constructors
  • Small-step semantics: added nondet variants for ite and loop steps
  • DetToNondet transform handles nondet conditions (no assume needed)
  • LoopElim transform handles nondet guards (no guard negation needed)
  • All frontends wrap deterministic conditions with .det
  • All backends handle ExprOrNondet in condition positions
  • Correctness proofs updated for new semantic cases

Testing

All existing tests pass (except a pre-existing failure in StrataTest/DDM/Integration/Java/TestGen.lean due to a sorry in StatementWF.lean on main).

Fixes #612

@MikaelMayer MikaelMayer changed the title [Strata] Better isolation of non-determinism in Core Better isolation of non-determinism in Core Mar 24, 2026
Replace Option/havoc with ExprOrNondet in Cmd, and extend ExprOrNondet
to Stmt.ite and Stmt.loop conditions. This unifies non-determinism
handling across commands and control flow.

Changes:
- Add ExprOrNondet type for deterministic-or-nondet expressions
- Merge set/havoc into single set command with ExprOrNondet RHS
- Use ExprOrNondet for ite/loop conditions in Stmt
- Add DDM syntax: if (*) and while (*) for nondet conditions
- Introduce fresh nondet booleans in PE and StructuredToUnstructured
- Update all downstream code, semantics, transforms, backends, tests
- Add boolTy to HasNot for declaring fresh boolean variables
@MikaelMayer MikaelMayer force-pushed the issue-612-better-isolation-of-non-determinism-in-c branch from c79a486 to 3ce8e92 Compare March 26, 2026 15:14
Update test file to use ExprOrNondet (.det/.nondet) instead of
Option (some/none) for Cmd and ExprOrNondet for Stmt conditions.
Add boolTy to HasNot instance.
Copy link
Copy Markdown
Contributor Author

@MikaelMayer MikaelMayer left a comment

Choose a reason for hiding this comment

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

Thorough and well-structured PR that extends ExprOrNondet from commands to statement-level constructs (ite/loop). The design is clean: the ExprOrNondet type, its .map helper, and the HasNot.boolTy field are good abstractions. Semantics (big-step and small-step), correctness proofs, and all frontends/backends are updated consistently. New tests cover type-checking and evaluation of nondet conditions.

A few observations below, mostly about minor code duplication and one design question about the nondet loop elimination ignoring the measure parameter.

- Extract isBstarArg helper in Translate.lean to reduce duplication
- Use ExprOrNondet.map in StatementType.lean and C_Simp/Verify.lean
- Add comment explaining why measure is ignored for nondet loops
…m-in-c

Resolve conflicts between ExprOrNondet changes (PR #612) and
Hoare triple / DetToNondet correctness with loops (PR #660).

Key merge decisions:
- Keep ExprOrNondet (.det/.nondet) from our branch
- Adopt main's Env record (ρ) style and Bool failure flag in EvalCmd
- Add nondet ite/loop cases to all new proofs from main
- Add loop_sim_nondet for nondet loop correctness proof
Add a .nondet guard branch mirroring LoopElim.lean: havoc assigned
vars, assert/assume entry invariants, run body with invariant
maintenance, and use .ite .nondet. The catch-all now only matches
.det guards without a measure, with a more specific error message.
Introduce a CondBool category with condDet (parenthesized bool) and
condNondet (*) variants, so nondet conditions parse as 'if * { ... }'
and 'while * { ... }' without parentheses. Deterministic conditions
retain their parenthesized form 'if (expr) { ... }'.

Remove the bstar bool function, now superseded by condNondet.
.assume s!"invariant_{i}" (translate_expr inv) {}

.ite (.det (translate_expr guard_expr)) ([first_iter_facts, arbitrary_iter_facts, havocd, not_guard] ++ invariant_assumes) [] {}
| .det guard_expr, .none, _ =>
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.

This is super nice but that case was not supported in main, was it? If so I would like to see a test that demonstrates this rewriting of core to core, and that the test be human readable.

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.

For all cases

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.

Added StrataTest/Languages/C_Simp/Examples/LoopElimTests.lean with human-readable #guard_msgs tests for the two new loop elimination cases:

  1. Deterministic guard without measure (.det guard_expr, .none, _): Uses a C_Simp program parsed via #strata with a while loop that has an invariant but no decreases clause. The to_core output shows the loop elimination without any measure-related obligations.

  2. Nondet guard (.nondet, _, _): Constructs a C_Simp.Program programmatically (since C_Simp's parser always produces deterministic guards) and passes it through to_core. The output shows the nondet loop elimination with if * { ... } and the entry invariant assert/assume pattern.

The existing LoopTrivial.lean and LoopSimple.lean already cover the .det guard_expr, .some measure, _ case.

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.

Better isolation of non-determinism in Core

1 participant