This document describes certain well-trodden paths for finding proofs. These are just suggestions that might work.
- Start a soundness or completeness proof with
circuit_proof_start. - The simpset
circuit_normis supposed to bring the goal state to well-trodden forms:simp only [circuit_norm]. - Often, custom definitions like
MySubgadget.circuitneed to be unfolded. You can do so by passing them along in the simp set:circuit_proof_start [MySubgadget.circuit]orsimp only [circuit_norm, MySubgadget.circuit]. - In many cases, it's needed to keep unfolding things so that only the math content remains.
- The most usual moves are just
simp only [...]. - Most
Cleandefinitions are meant to be unfolded away.- Clean's subcircuit mechanism prevents you from seeing the internal operations of subcircuits, so it's usually fine to unfold everything that you don't know about.
- Exceptionally, it's usually better not to unfold loop constructions like
Circuit.foldl. Usesimp only [circuit_norm]to transform them into plain statements like∀ i < m, .... To deal with the result, it can be beneficial to state a separate lemma for lifting properties to the loop, using induction.
- When a context has an assumption
h : something → something, probably it's helpful tospecialize h (by ...). - If math is involved, you use lemmas from Mathlib or
Utils. The goal state in Clean is usually too large forrw?(and also usually forapply?), so Loogle is your friend.
Once there is nothing about Clean and the goal is just about math, the proof branch is about to be closed.
- When
simp_all,aesoporgrindquickly solves a goal, that proof is very maintainable. - When it's about natural numbers, addition, equality and less-than,
omegaorlinarithmight be useful. - When it's about
1 + 1and2(as field elements), or distributing multiplication over addition, tryring_nforfield_simp.