Zulip Chat Archive
Stream: lean4
Topic: beginner's problem [nightly]
Aron (Jun 10 2022 at 23:51):
import Mathlib.Logic.Basic
-- def exunique (p : α → Prop) := ∃ (x : α), (p x ∧ ∀ y, p y → x = y)
-- syntax "∃!" term "," term: term
-- macro_rules
-- | `(∃! $t:term, $p:term) => `(exunique (fun $t => $p))
class incidence (point line: Type) (inc:point → line → Prop) :=
(one: ∀ P Q, P ≠ Q → ∃! l, inc P l ∧ inc Q l)
(two: ∀ l, ∃ P Q, P ≠ Q ∧ inc P l ∧ inc Q l)
(three: ∃ P Q R, P ≠ Q ∧ Q ≠ R ∧ P ≠ R ∧ ∀ l, ¬(inc P l ∧ inc Q l ∧ inc R l))
variable (point line:Type)
variable (inc:point → line → Prop)
variable [i: incidence point line inc]
theorem t1:
∀ l m,
l ≠ m
→ (∃ p, inc p l ∧ inc p m)
→ (∃! p, inc p l ∧ inc p m)
:= by
intro l m hlnm hex
have ⟨a,ha⟩:= hex
refine ⟨a, ha, λ b hb => ?_⟩
-- apply Classical.byContradiction; intro hanb
refine Classical.byContradiction fun hanb => ?_
rewrite [eq_comm,← ne_eq] at hanb
have ⟨hal,ham⟩:=ha
have ⟨hbl,hbm⟩:=hb
have h:=i.one a b hanb
have ⟨x,hx1,hx2⟩:=h
have hl':= hx2 l ⟨hal,hbl⟩
have hm':= hx2 m ⟨ham,hbm⟩
have hlm:= Eq.trans hl' (Eq.symm hm')
-- hlm hlnm
contradiction
theorem t2: ∀ l, ∃ p, ¬ inc p l := by
intro l
have ⟨p,q,r,hpnq,hqnr,hpnr,hncol⟩ := i.three
have hnl:= hncol l
apply Classical.byContradiction
intro hallinc
rw [not_exists,not_not] at hallinc
-- have hpqrinc:= And.intro (And.intro (hallinc p) (hallinc q)) (hallinc r)
././Trying.lean:46:15: error: tactic 'rewrite' failed, did not find instance of the pattern in the target expression
¬¬?m.1516
case h
point line : Type
inc : point → line → Prop
i : incidence point line inc
l : line
p q r : point
hpnq : p ≠ q
hqnr : q ≠ r
hpnr : p ≠ r
hncol : ∀ (l : line), ¬(inc p l ∧ inc q l ∧ inc r l)
hnl : ¬(inc p l ∧ inc q l ∧ inc r l)
hallinc : ∀ (x : point), ¬¬inc x l
⊢ False
Aron (Jun 10 2022 at 23:52):
See the last line, not_not is not matching its pattern.
Aron (Jun 10 2022 at 23:52):
It isn't matching ¬¬something
in hallinc : ∀ (x : point), ¬¬inc x l
.
Siddhartha Gadgil (Jun 11 2022 at 02:39):
I believe rewrite
will not work inside a ∀
. Here is one way to achieve what you want (replacing the last line).
rw [not_exists] at hallinc
have halinc' : ∀ (x : point), inc x l := by
intro x
let hx := hallinc x
rw [not_not] at hx
assumption
Somebody more skilled than me at tactics will probably suggest a shorter way.
Aron (Jun 11 2022 at 03:13):
Siddhartha Gadgil said:
I believe
rewrite
will not work inside a∀
. Here is one way to achieve what you want (replacing the last line).rw [not_exists] at hallinc have halinc' : ∀ (x : point), inc x l := by intro x let hx := hallinc x rw [not_not] at hx assumption
Somebody more skilled than me at tactics will probably suggest a shorter way.
Why doesn't the nightly build automatically collapse not_not?
Siddhartha Gadgil (Jun 11 2022 at 03:14):
What do you mean by "collapse not_not"?
Aron (Jun 11 2022 at 03:17):
It seemed like the stable build of lean4 would automatically simplify not not p into p.
Siddhartha Gadgil (Jun 11 2022 at 03:17):
I don't expect ¬¬something
is _definitionally equal_ to something
.
Siddhartha Gadgil (Jun 11 2022 at 03:20):
If p
is a literal boolean that will happen. Did it happen with boolean expressions?
Siddhartha Gadgil (Jun 11 2022 at 03:23):
I don't see how one could have reflexive equality of not not p
and p
for arbitrary boolean expressions. The definition of not
is
@[inline] def not : Bool → Bool
| true => false
| false => true
which, due to _inline_, will expand for literals and so simplify. But for expressions it should just inline to a nested match.
Aron (Jun 11 2022 at 03:26):
I guess my lean3 examples had not_not as a simplification tactic because they were working classically.
Siddhartha Gadgil (Jun 11 2022 at 03:26):
That makes sense. Simplification will do all this expansion.
Siddhartha Gadgil (Jun 11 2022 at 03:27):
i thought "automatically" meant definitional equality.
Siddhartha Gadgil (Jun 11 2022 at 03:29):
I just checked: simp
does work within functions, so you could simply replace your last lines with
rw [not_exists] at hallinc
simp [not_not] at hallinc
Siddhartha Gadgil (Jun 11 2022 at 03:29):
Better still, simp [not_exists, not_not] at hallinc
does the job.
Aron (Jun 11 2022 at 03:37):
Alright, now I'm having trouble getting And.assoc to work the way it advertises.
Aron (Jun 11 2022 at 03:38):
Apparently it works fine in rw
, but not as a direct application.
Aron (Jun 11 2022 at 03:47):
Ignore that, the problem got solved so I don't mind.
Aron (Jun 11 2022 at 20:13):
Alright, I've got another.
import Mathlib.Logic.Basic
-- def exunique (p : α → Prop) := ∃ (x : α), (p x ∧ ∀ y, p y → x = y)
-- syntax "∃!" term "," term: term
-- macro_rules
-- | `(∃! $t:term, $p:term) => `(exunique (fun $t => $p))
class incidence (point line: Type) (inc:point → line → Prop) :=
(one: ∀ P Q, P ≠ Q → ∃! l, inc P l ∧ inc Q l)
(two: ∀ l, ∃ P Q, P ≠ Q ∧ inc P l ∧ inc Q l)
(three: ∃ P Q R, P ≠ Q ∧ P ≠ R ∧ Q ≠ R ∧ ∀ l, ¬(inc P l ∧ inc Q l ∧ inc R l))
variable (point line:Type)
variable (inc:point → line → Prop)
variable [i: incidence point line inc]
theorem t1:
∀ l m,
l ≠ m
→ (∃ p, inc p l ∧ inc p m)
→ (∃! p, inc p l ∧ inc p m)
:= by
intro l m hlnm hex
have ⟨a,ha⟩:= hex
refine ⟨a, ha, λ b hb => ?_⟩
-- apply Classical.byContradiction; intro hanb
refine Classical.byContradiction fun hanb => ?_
rewrite [eq_comm,← ne_eq] at hanb
have ⟨hal,ham⟩:=ha
have ⟨hbl,hbm⟩:=hb
have h:=i.one a b hanb
have ⟨x,hx1,hx2⟩:=h
have hl':= hx2 l ⟨hal,hbl⟩
have hm':= hx2 m ⟨ham,hbm⟩
have hlm:= Eq.trans hl' (Eq.symm hm')
-- hlm hlnm
contradiction
theorem t2: ∀ l, ∃ p, ¬ inc p l := by
intro l
have ⟨p,q,r,hpnq,hpnr,hqnr,hncol⟩ := i.three
have hnl:= hncol l
apply Classical.byContradiction
intro hallinc
simp [not_not,not_exists] at hallinc
have hl:= And.intro (And.intro (hallinc p) (hallinc q)) (hallinc r)
-- exact hnl (And.assoc hl)
rw [And.assoc] at hl
contradiction
theorem another_point: ∀ (p:point), ∃ q, p ≠ q:=by
intro p
have ⟨a,b,c,hanb,hanc,hbnc,habc⟩:= i.three
apply Classical.byContradiction
simp [not_exists,ne_eq]
intro h
-- exact hab (Eq.trans (eq_comm.mp (h a)) (h b))
have ha:= h a
have hb:= h b
rw [eq_comm] at ha
have hab:= Eq.trans ha hb
exact hanb hab
theorem t3: ∀ p, ∃ l m, l ≠ m ∧ inc p l ∧ inc p m := by
intro p
have h:= another_point p
././Trying.lean:66:23: error: application type mismatch
another_point p
argument
p
has type
point : Type
but is expected to have type
Type : Type 1
././Trying.lean:64:53: error: unsolved goals
point line : Type
inc : point → line → Prop
i : incidence point line inc
p : point
h :
∀ (line : Type) (inc : sorryAx Type → line → Prop) [i : incidence (sorryAx Type) line inc] (p : sorryAx Type),
∃ q, p ≠ q
⊢ ∃ l m, l ≠ m ∧ inc p l ∧ inc p m
I'm trying to apply another_point
at the bottom line, but it's not typechecking.
It's also saying the type involves sorryAx - not sure what that is.
Marc Huisinga (Jun 11 2022 at 20:53):
If you hover over another_point
, it'll show you the type of the theorem.
Aron (Jun 11 2022 at 21:03):
Yes, it's ∀ (line : Type) (inc : sorryAx Type → line → Prop) [i : incidence (sorryAx Type) line inc] (p : sorryAx Type),
∃ q, p ≠ q
.
Kevin Buzzard (Jun 11 2022 at 21:04):
So it's expecting a term of type Type and you gave it a term of type point
Kevin Buzzard (Jun 11 2022 at 21:04):
Which is exactly what the error says
Aron (Jun 11 2022 at 21:06):
Why would it be expecting a term of type Type
when I defined the theorem with a term of type point
?
Aron (Jun 11 2022 at 21:07):
theorem another_point: ∀ (p:point), ∃ q, p ≠ q:=by
intro p
have ⟨a,b,c,hanb,hanc,hbnc,habc⟩:= i.three
apply Classical.byContradiction
simp [not_exists,ne_eq]
intro h
-- exact hab (Eq.trans (eq_comm.mp (h a)) (h b))
have ha:= h a
have hb:= h b
rw [eq_comm] at ha
have hab:= Eq.trans ha hb
exact hanb hab
Sébastien Michelland (Jun 11 2022 at 21:10):
These are your variable
definitions - the theorem implicitly uses them, so they have been included as parameters. The theorem uses them in the proof; see how you mention i.three
.
If you change your variable
declarations to use braces, the parameters will be made implicit and automatically inferred, resulting in the behavior that you expect - if inference succeeds.
Aron (Jun 11 2022 at 21:11):
Oh, so if I were to keep the variables as is, I would have had to define point
, line
, and inc
in the call to another_point
. Makes sense.
Aron (Jun 11 2022 at 21:12):
Tried changing to braces, everything's exploding.
Aron (Jun 11 2022 at 21:16):
Figured out something that works without braces, but I'm not sure how I'd go about condensing it to get the definitions out of the way.
theorem another_point: ∀ (p:point), ∃ q, p ≠ q:=by
intro p
have ⟨a,b,c,hanb,hanc,hbnc,habc⟩:= i.three
apply Classical.byContradiction
simp [not_exists,ne_eq]
intro h
-- exact hab (Eq.trans (eq_comm.mp (h a)) (h b))
have ha:= h a
have hb:= h b
have hab:= Eq.trans (eq_comm.mp ha) hb
exact hanb hab
theorem t3: ∀ p, ∃ l m, l ≠ m ∧ inc p l ∧ inc p m := by
intro p
have h:= another_point point line inc p
Sébastien Michelland (Jun 11 2022 at 21:16):
Yes precisely. I'm not too surprised it's exploding, in my experience changing binder types is always tricky. It helps to get them right on the first try when you already know what you will be able to infer. It's also a limitation of variable
that every theorem gets the same binder type.
Marc Huisinga (Jun 11 2022 at 22:06):
The rule of thumb is that something can be inferred if it appears in the type of a later argument.
Applying this rule to your example, we can declare variable {point line : Type}
implicit, but leave inc
explicit. Then you can use another_point inc p
and your file typechecks without issues.
Kevin Buzzard (Jun 11 2022 at 22:06):
In Lean 3 you can change the binder type of a variable after it's been declared with a line such as variable {line}
Mario Carneiro (Jun 12 2022 at 08:30):
that also works in lean 4
Last updated: Dec 20 2023 at 11:08 UTC