Skip to content

Commit 8d0743e

Browse files
committed
updated P02S02 up to B02
1 parent e45a9b3 commit 8d0743e

1 file changed

Lines changed: 176 additions & 0 deletions

File tree

LeanBlockCourse26/P02_Logic/S02_Reasoning.lean

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,182 @@ Find a path from `A` to `I` using different reasoning styles. Have at least
136136
one purely forward arguing path and one purely backward arguing path.
137137
-/
138138

139+
example (A B C D E F G H I : Prop)
140+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
141+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
142+
(q : H → G) (r : H → I) (a : A) : I := by
143+
have b : B := f a
144+
have e : E := i b
145+
have f : F := l e
146+
have i : I := p f
147+
exact i
148+
149+
example (A B C D E F G H I : Prop)
150+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
151+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
152+
(q : H → G) (r : H → I) (a : A) : I := by
153+
have b := f a -- output type is inferred / determined by the term mode proof
154+
have e := i b -- output type is inferred / determined by the term mode proof
155+
have f := l e -- output type is inferred / determined by the term mode proof
156+
have i := p f -- output type is inferred / determined by the term mode proof
157+
exact i
158+
159+
example (A B C D E F G H I : Prop)
160+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
161+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
162+
(q : H → G) (r : H → I) (a : A) : I :=
163+
p <| l <| i <| f a -- Can just collapse everything into term mode
164+
165+
example (A B C D E F G H I : Prop)
166+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
167+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
168+
(q : H → G) (r : H → I) (a : A) : I := by
169+
apply p
170+
apply l
171+
apply i
172+
apply f
173+
exact a
174+
175+
-- mixed reasoning: argue backwards from `I` to `E` and then forwards from `A`
176+
example (A B C D E F G H I : Prop)
177+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
178+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
179+
(q : H → G) (r : H → I) (a : A) : I := by
180+
apply p
181+
apply l
182+
exact i (f a)
183+
184+
/-
185+
## Forgetting about assumptions with `clear`
186+
187+
The `clear` tactic lets you forget assumptions. You should generally not need
188+
this and instead structure your code to only have necessary assumptions in scope.
189+
-/
190+
191+
example (A B C D E F G H I : Prop)
192+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
193+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
194+
(q : H → G) (r : H → I) (a : A) : I := by
195+
clear g h j k m n q r -- The linter still complains though
196+
exact p <| l <| i <| f a
197+
198+
/-
199+
## The `suffices` Tactic
200+
201+
Enables explicit backward reasoning by declaring intermediate goals:
202+
203+
1. Declares a subgoal that would suffice to prove the original goal
204+
2. Once proven, provides access to the subgoal proof via `this`
205+
3. Maintains goal context for clearer proof structuring
206+
207+
This tactic is used around 2,600 times in mathlib. But it is very nice
208+
in that mimicks the human language "it suffices to show that ... because ...".
209+
-/
210+
211+
-- Basic suffices example showing goal transformation
212+
example (P Q R : Prop) (h₁ : P → Q) (h₂ : Q → R) (p : P) : R := by
213+
suffices Q by -- unlike `apply h₂` the result is already visible in code
214+
-- At this point we have entered a sub-proof where we show that it does
215+
-- in fact suffice to show Q, similar to how `have` has its own sub-proof.
216+
-- In this sub-proof the actual assumption you are claiming suffices is
217+
-- introduced as `this`. Note that the term `this` (if not used as an
218+
-- actual variable name as it us here) also refers the last unnamed variable.
219+
exact h₂ this
220+
exact h₁ p
221+
222+
/-
223+
Unlike for example `have`, the tactic `suffices` only supports term mode
224+
proofs, i.e., it always needs the `by` and does not use the `:=` proof indicator.
225+
-/
226+
227+
-- Compare with equivalent `apply`
228+
example (P Q R : Prop) (h₁ : P → Q) (h₂ : Q → R) (p : P) : R := by
229+
apply h₂
230+
exact h₁ p
231+
232+
-- You can actually name the hypothesis in `suffices`
233+
example (P Q R : Prop) (h₁ : P → Q) (h₂ : Q → R) (p : P) : R := by
234+
suffices q : Q by
235+
exact h₂ q
236+
exact h₁ p
237+
238+
/-
239+
## The `refine` Tactic
240+
241+
The `refine` tactic behaves like `exact` but permits placeholders (i.e. `?_`)
242+
in the provided term. Any unsolved hole that is not fixed by unification with
243+
the main goal's target is converted into a new goal. This tactic is used
244+
around 19,000 times in mathlib.
245+
-/
246+
247+
example (P Q : Prop) (f : P → Q) (p : P) : Q := by
248+
refine f ?_ -- in this case it behaves like `apply`
249+
exact p -- this answers a sub-goal raised `_?`
250+
251+
example (P Q : Prop) (f : P → Q) (p : P) : Q := by
252+
refine f p -- in this case it behaves like `exact`
253+
254+
-- You can also stack proofs inside proofs for `refine`
255+
example (P Q : Prop) (f : P → Q) (p : P) : Q := by
256+
refine f (by exact p)
257+
258+
-- In fact this also works for `exact`
259+
example (P Q : Prop) (f : P → Q) (p : P) : Q := by
260+
exact f (by exact p)
261+
262+
/-
263+
## Tactics are just "syntactic sugar" to make mathematician's live easier
264+
265+
At its core everything is term mode forward arguing compositing of methods,
266+
but tactics allow you to argue closer to natural language. This inherently
267+
will mean there are many equivalent ways of achieving the same goal
268+
and there will always some weirdness and inconsistencies because of that
269+
flexibility.
270+
271+
## Notational inconsistencies
272+
273+
Unfortunately the syntax of mathlib tactics is not entirely
274+
consistent, so in particular `:=` is not always used to signal
275+
the start of a sub-proof (`let` and `have` use it, `refine` and
276+
`suffices` do not) and just because one tactic admits a certain
277+
syntax, another does not necessarily allow the same, so the
278+
following are all *invalid* for `suffices`:
279+
280+
* suffices Q -- just leave argument open
281+
* suffices Q by ?_ -- leave an intentional gap
282+
* suffices Q := exact h₂ this -- use term mode
283+
284+
## Whitespace (indentation and newlines)
285+
286+
Indentation does not matter (since lean / mathlib 4), but you
287+
can use it freely to structure your proofs and indicate when
288+
you are in a sub-proof. Newlines matter, but as in many languages,
289+
you can replace them with `;`, e.g.:
290+
-/
291+
292+
example (P Q R : Prop) (h₁ : P → Q) (h₂ : Q → R) (p : P) : R :=
293+
by apply h₂; exact h₁ p
294+
295+
296+
/-
297+
## Exercise Block B02: Graph of Implications (Continued)
298+
-/
299+
300+
-- Use only `suffices` to work backwards from the goal:
301+
example (A B C D E F G H I : Prop)
302+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
303+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
304+
(q : H → G) (r : H → I) (a : A) : I := by
305+
sorry
306+
307+
-- Use only `refine` to work backwards from the goal:
308+
example (A B C D E F G H I : Prop)
309+
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
310+
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)
311+
(q : H → G) (r : H → I) (a : A) : I := by
312+
sorry
313+
314+
-- Combine all of `clear`, `exact`, `have`, `suffices`, `refine`, and `apply`
139315
example (A B C D E F G H I : Prop)
140316
(f : A → B) (g : C → B) (h : A → D) (i : B → E) (j : C → F)
141317
(k : E → D) (l : E → F) (m : G → D) (n : H → E) (p : F → I)

0 commit comments

Comments
 (0)