Back to Program Verification Index | Previous: (y-10) Array Theory and Arrays in Boostan | Next: (y-12) Control-Flow Graphs
Mental Model for Nondeterminism

- Beyond Predictability: Real programs interact with the world (users, networks, hardware). We can’t predict what a user will type, so we model it as Nondeterminism.
- Havoc: The
havoc xstatement is like a “chaos” command. It tells the verifier: “From this point on, could be absolutely anything.” - Assume: The
assume Pstatement is a filter. It tells the verifier: “Throw away any execution where is false. Only focus on the worlds where holds.” - Nondeterministic Choice: By combining
havocandassume, we can model complex inputs (e.g., “user enters a positive number”).
Modeling Input with havoc
In standard programming, we use scanf or read(). In verification, we use havoc.
The havoc x Statement

- Meaning: Assign an arbitrary value to from its domain.
- Relational Semantics:
- for all .
- can be any value in .
- Use Case: Modeling uninitialized variables or external inputs inside a loop.
The assume Statement
An assume P statement is NOT a check; it is a constraint on the verifier.
Relational Semantics of assume P

- Partial Identity Relation: .
- The relation is a subset of the Identity Relation.
- if and only if satisfies .
- If does not satisfy , there is no successor state. The execution simply “disappears” (blocks).
💡 Intuition: Asserts vs. Assumes
assert P: A Requirement. If is false, the program crashes (it’s a bug).assume P: A Promise. If is false, the execution path simply ceases to exist. It’s like the program “blocks” forever, so we don’t have to worry about those cases.
Modeling “User Input” (Havoc + Assume)

To model a C statement like x = read_positive_int(), where the user provides an input we don’t control, we use the following pattern in Boogie/Boostan:
havoc x; // x could be absolutely anything (negative, zero, or positive)
assume x > 0; // discard any world where the user didn't give a positive number- Result: Every execution that survives the
assumestatement will have a value of that is strictly greater than zero.
Why use assume?
- Environmental Facts:
assume temperature < 100;(The sensor won’t go higher). - Modular Verification: When calling a function, we
assumeits postcondition holds. - Path Filtering:
if (x > 0) { ... }is internally modeled as anassume x > 0on the “true” branch.
Summary
- Nondeterminism is essential for modeling the real world.
- Havoc resets a variable to a completely unknown state.
- Assume acts as a filter, removing “impossible” executions.
- Asserts are things we must prove; Assumes are things we get for free.
- Relational Semantics:
assumeis a partial identity;havocis a broad relation allowing any value for one variable.
Self-Check
- Give the relational semantics of
havoc xin words.
Answer
The relation contains every pair where agrees with on every variable other than , and can be any value in the domain of . After
havoc x, the verifier reasons about all possible values of .
- Give the relational semantics of
assume Pand describe what happens when is false in the current state.
Answer
, a partial identity relation. If the current state does not satisfy , there is no pair starting at , so the execution path is dropped from consideration. The verifier simply ignores those paths.
- How is
x = read_positive_int()modeled withhavocandassume?
Answer
Write
havoc x; assume x > 0;.havocintroduces an arbitrary value forx, andassumefilters out the executions where that value is not positive. Every surviving execution hasx > 0, which captures the external-input situation without referring to actual I/O.
- What is the operational difference between
assert Pandassume P?
Answer
assert Pis a proof obligation: the verifier must show holds along every path that reaches it; otherwise it reports a bug.assume Pis a constraint: the verifier treats as given, and paths where fails simply disappear. Asserts catch errors; assumes encode environmental facts and the conditions taken on branches.
- Why is an
if (B) {...}branch internally modeled with anassume?
Answer
Entering the then branch only makes sense in states where the guard holds, so the verifier prepends
assume Bto that branch andassume !Bto the else branch. This reuses theassumemachinery to filter states by the guard, and matches the conditional Hoare rule’s split between and .
Back to Program Verification Index | Previous: (y-10) Array Theory and Arrays in Boostan | Next: (y-12) Control-Flow Graphs | (y) Return to Notes | (y) Return to Home