Back to Program Verification Index | Previous: (y-16) Abstractions and ARG | Next: (y-18) Trace Abstraction and Floyd-Hoare Automata
Mental Model for CEGAR
- Automated Refinement: We don’t know the best predicates for a program. CEGAR (CounterExample-Guided Abstraction Refinement) starts with nothing and learns the predicates it needs automatically.
- Trace Analysis: If our simplified (abstract) model finds an “error,” we check whether it is a real bug or a False Counterexample.
- Infeasibility Proofs: If the error is a false alarm, we find an Infeasibility Proof (a sequence of formulas that prove the trace is impossible).
- Learning: We add the formulas from that proof to our set , making our model more precise so it won’t make that same mistake again.
Traces and Feasibility
A Trace () is a sequence of statements .
- Feasible: There is at least one execution that follows the trace.
- Infeasible: No execution can ever follow this trace.
Infeasibility Proof
A sequence of formulas is a Proof of Infeasibility for if:
- Each step follows the logic:
- The final result is
The CEGAR Approach (Step-by-Step)

- Step 1: Start Simple. Set the predicates (or some initial set).
- Step 2: Build ARG. Construct the Abstract Reachability Graph based on .
- Step 3: Check for Errors.
- If no error location is reachable in the ARG, the Program is Safe.
- If an error location is reachable, find the Abstract Error Trace that led to it.
- Step 4: Check Trace Feasibility.
- If is Feasible (satisfiable in concrete semantics), the Program is Incorrect. Return “Bug” + the concrete counterexample.
- If is Infeasible (unsatisfiable in concrete semantics), our abstraction is too coarse.
- Step 5: Refine.
- Find an Infeasibility Proof sequence for such that , and .
- Add these new formulas to our set of predicates .
- Go back to Step 2.
💡 Intuition: Progressive Learning
Imagine trying to find a path in a dark room.
- Iteration 1: You assume the room is empty. You walk forward and hit a chair (the chair is your error trace).
- Refinement: You now know “There is a chair at coordinate X.” You add this to your mental map (your set ).
- Iteration 2: You build a new plan that avoids that chair. If you hit a table, you repeat the process.
- End: Eventually, you either reach the exit (Safety Proof) or prove there is no way out (Real Bug).
Summary
- CEGAR automates the discovery of program properties (Predicates).
- Traces are paths through the program.
- Infeasibility Proofs are the source of new knowledge for the verifier.
- Progress Property: Once an error trace is proven infeasible, the verifier will never encounter it again in future iterations.
- Abstraction: CEGAR verifies complex programs without anyone guessing invariants by hand.
Self-Check
- When is a trace called feasible, and when is it infeasible?
Answer
is feasible iff there is at least one concrete execution that follows in order; equivalently, the SSA-encoded path formula is satisfiable. It is infeasible iff no such execution exists, i.e., the path formula is unsatisfiable. CEGAR’s whole job is to distinguish these two for abstract counterexamples.
- State the three conditions that make an infeasibility proof for .
Answer
First, . Second, for every from to , , i.e., the next formula over-approximates the strongest postcondition. Third, . Together they certify the trace cannot reach its end with any state.
- Outline the five steps of the CEGAR loop.
Answer
(1) Start with an initial predicate set , often empty. (2) Build the ARG using . (3) Check whether any error location is reachable in the ARG; if not, the program is safe. (4) If an abstract error trace is found, check its concrete feasibility; if feasible, report a real bug. (5) If infeasible, extract an infeasibility proof, add its formulas to , and restart at step 2.
- Why does CEGAR refine its abstraction using the formulas from the infeasibility proof, rather than arbitrary predicates?
Answer
The infeasibility proof identifies exactly the conjunction of facts that ruled out the spurious trace. Adding those formulas to guarantees the next ARG can distinguish the abstract states that would have re-introduced the same trace, so the verifier cannot make the same spurious counterexample twice. This is the progress property that keeps the loop from looping forever on the same error.
- Why is the abstraction necessarily coarsened back when CEGAR starts, and what does each refinement step do to it?
Answer
The initial is empty (or minimal), so the abstraction is the coarsest possible and many concrete states collapse into a few abstract ones. Each refinement step grows with formulas drawn from a real infeasibility proof, which strictly refines the abstraction: more predicates means more abstract states and a tighter over-approximation of reachability. The loop progressively narrows the gap until it either proves safety or finds a true bug.
Back to Program Verification Index | Previous: (y-16) Abstractions and ARG | Next: (y-18) Trace Abstraction and Floyd-Hoare Automata | (y) Return to Notes | (y) Return to Home