Zulip Chat Archive
Stream: general
Topic: lean golf
Sean Leather (Feb 28 2018 at 13:27):
Shortest proof of this?
a ∧ b ∧ c ∧ d ∧ e ↔ a ∧ b ∧ c ∧ c ∧ d ∧ e
Sebastian Ullrich (Feb 28 2018 at 13:32):
Let's start with the basics
by split;intro;simp*
Sean Leather (Feb 28 2018 at 13:40):
That's like a sledgehammer using sledgehammers to hit small nails. For some reason, I never think to try simp *
.
Sebastian Ullrich (Feb 28 2018 at 13:43):
Well, I don't really need *
here, but naming the hypothesis obviously is a golf no-go :P
Sean Leather (Feb 28 2018 at 13:52):
Is it? If the proof is short, I don't see why. :simple_smile:
Scott Morrison (Feb 28 2018 at 13:53):
I was happy to see by tidy
works too. Maybe one day I'll get up the courage to PR it.
Kevin Buzzard (Feb 28 2018 at 21:57):
I wondered whether by cc
would work -- but it doesn't. I still don't really know what to expect with cc but I think I've seen it prove other goals of this nature.
Sean Leather (Mar 01 2018 at 09:11):
I'm slowly learning how to use simp *
:
namespace list variables {α : Type} {l : list α} {n : ℕ} theorem nth_of_map {f : α → α} {a : α} (p : f a = a) : option.get_or_else (nth (map f l) n) a = f (option.get_or_else (nth l n) a) := by induction l generalizing n; [skip, cases n]; simp [*, option.get_or_else] end list
Johannes Hölzl (Mar 02 2018 at 11:22):
I guess cc
doesn't work as it currently doesn't handle idempotent laws (i.e. c ∧ c
).
Kevin Buzzard (Mar 13 2018 at 15:09):
Curry:
Kevin Buzzard (Mar 13 2018 at 15:09):
example (P Q R : Prop) : (P ∧ Q → R) ↔ (P → (Q → R)) := sorry
Kevin Buzzard (Mar 13 2018 at 15:10):
Doing this one taught me something, although it was arguably not very useful
Kevin Buzzard (Mar 13 2018 at 15:10):
Actually it taught me 2 things, one being that bash shell is not very good at counting unicode characters
Sean Leather (May 24 2018 at 06:31):
I'm sure I've asked this before, but I don't remember the answer. Better/shorter way to do this?
intro h, simp at h, simp [h]
Note that simp
by itself doesn't work.
Johannes Hölzl (May 24 2018 at 06:55):
simp {contextual:=tt}
should do it.
Sean Leather (May 24 2018 at 06:58):
Yep, that did it. Thanks!
Sean Leather (May 24 2018 at 07:38):
simp
doesn't solve this. Is there a theorem I can use with simp
to solve it?
⟨a, b⟩ ∈ l ↔ a = a₁ ∧ b == b₁ ∨ ⟨a, b⟩ ∈ l
Johannes Hölzl (May 24 2018 at 07:49):
I guess you have ⟨a₁, b₁⟩ ∈ l
?
Johannes Hölzl (May 24 2018 at 07:50):
But I also don't see how to solve it with the simplifier.
Sean Leather (May 24 2018 at 07:52):
Oh wait, I'm stupid. Let me actually think. :simple_smile:
Kevin Buzzard (May 24 2018 at 07:53):
Do you CS people know how to parse that sort of statement?
Kevin Buzzard (May 24 2018 at 07:54):
I look at it (away from Lean) and have no idea about the relative priorities of and, or and iff. Is this just all some standard convention that you CS people know and we maths people just avoid by adding brackets?
Kevin Buzzard (May 24 2018 at 07:54):
I mean -- I know I can go and check them -- my question is whether there are uniform standards or whether Lean made some random choice and you find different choices in other systems.
Kevin Buzzard (May 24 2018 at 07:55):
obviously I can guess the answer in this situation from the context, but in the past I have written statements without brackets and then later on gone "oh crap, that doesn't mean what I wanted it to mean at all"
Gabriel Ebner (May 24 2018 at 07:56):
The precedence is pretty standard. In most (all?) programming languages as well as logic, and binds more tightly than or. C doesn't have iff, so its hard to compare.
Sean Leather (May 24 2018 at 07:57):
The “usual conventions:” https://groups.google.com/d/msg/lean-user/lbFwVL21Az4/1erXpLqBAwAJ
Gabriel Ebner (May 24 2018 at 07:58):
Excerpt from a proof theory textbook lying around here (Troelstra & Schwichtenberg):
Notation (Saving on parentheses) In writing formulas we save on parentheses by assuming that ∀, ∃, ¬ bind more strongly than ∧, ∨, and that in turn ∨, ∧ bind more strongly than →, ↔. [...]
Gabriel Ebner (May 24 2018 at 07:58):
I guess you will find similar boilerplate in most texts that deal with logical formulas.
Sean Leather (May 24 2018 at 07:58):
One that I struggled with was =
vs. ↔
, but now I'm used to it.
Kevin Buzzard (May 24 2018 at 08:07):
I guess you will find similar boilerplate in most texts that deal with logical formulas.
I follow a text which deals with logical formulas in my introduction to proof class and I can find no mention of binding preferences anywhere!
Kevin Buzzard (May 24 2018 at 08:07):
But I do see a lot of brackets :-)
Kevin Buzzard (May 24 2018 at 08:08):
I conclude that the guy who wrote it (who is in the office a few doors down from me) was also a mathematician who had no idea of standard CS conventions :-)
Gabriel Ebner (May 24 2018 at 08:14):
There is one confusing difference between proof theory and CS though: the precedence of ∀, ∃ is different.
∃x P(x) → Q means: (∃x P(x)) → Q for everyone in my research group ∃x (P(x) → Q) in Lean, Coq, etc.
Chris Hughes (May 24 2018 at 08:20):
(∃x P(x)) → Q
seems like really stupid precedence, since you would usually write ∀ x , P x → Q
instead of that.
Sean Leather (May 24 2018 at 08:21):
Interesting. Pierce (Types and Programming Languages) uses explicit bracketing : {∃x, P(x)}
Gabriel Ebner (May 24 2018 at 08:29):
@Chris Hughes The same precedence is also used for ∀: (∀x P(x)) → Q
vs. ∀x (P(x) → Q)
, which is just as confusing.
Kevin Buzzard (May 24 2018 at 08:43):
In fact it was exactly this forall point which I was referring to in my earlier "that doesn't mean what I wanted it to mean" comment
Sean Leather (Aug 20 2018 at 13:35):
Shortest proof of this?
a : ℕ b : ℕ p : a < b + 1, q : a ≠ b ⊢ a < b
Sean Leather (Aug 20 2018 at 13:44):
This is what I came up with:
nat.lt_of_le_and_ne (nat.le_of_lt_succ p) q
Kenny Lau (Aug 20 2018 at 13:59):
example (a b : ℕ) (p : a < b + 1) (q : a ≠ b) : a < b := by cases p; [cc, assumption]
Johan Commelin (Aug 20 2018 at 14:05):
I'm not on a Lean machine atm, but could cooper
or tidy
kill this one?
Kenny Lau (Aug 21 2018 at 17:17):
import data.fintype universe u variables (α : Type u) [decidable_eq α] (S T : finset α) example (H1 : S ⊆ T) (H2 : T.card ≤ S.card) : S = T := have H3 : disjoint S (T \ S), by simp [disjoint], have H4 : _, from finset.card_disjoint_union H3, have H5 : S ∪ T \ S = T, from finset.ext' $ λ x, ⟨λ H, or.cases_on (finset.mem_union.1 H) (finset.mem_of_subset H1) (and.left ∘ finset.mem_sdiff.1), λ H, classical.by_cases (finset.mem_union_left _) (λ H', finset.mem_union_right _ $ finset.mem_sdiff.2 ⟨H, H'⟩)⟩, have H6 : S.card = T.card, from le_antisymm (finset.card_le_of_subset H1) H2, have H7 : T \ S = ∅, from finset.card_eq_zero.1 $ nat.add_left_cancel $ eq.symm $ by rwa [H5, H6] at H4, have H8 : T ⊆ S, from finset.subset_iff.2 $ λ x H, classical.by_contradiction $ λ H', finset.ne_empty_of_mem (finset.mem_sdiff.2 ⟨H, H'⟩) H7, finset.subset.antisymm H1 H8
Kenny Lau (Aug 21 2018 at 17:17):
is there a shorter proof?
Mario Carneiro (Aug 21 2018 at 17:46):
example (H1 : S ⊆ T) (H2 : T.card ≤ S.card) : S = T := finset.eq_of_veq $ multiset.eq_of_le_of_card_le (finset.val_le_iff.2 H1) H2
Mario Carneiro (Aug 21 2018 at 17:47):
this should be in mathlib though
Kenny Lau (Aug 21 2018 at 17:53):
ah it's in multiset lol
Chris Hughes (Aug 21 2018 at 17:59):
Pretty sure it's there for finsets. I remember seeing it.
Chris Hughes (Aug 21 2018 at 18:00):
finset.eq_of_subset_of_card_le
Kenny Lau (Aug 21 2018 at 18:01):
genius
Kenny Lau (Aug 21 2018 at 18:27):
import data.fintype universe u variables (α : Type u) [decidable_eq α] example [fintype α] (f : α → α) (H : function.injective f) : function.surjective f := have H : _ := finset.eq_univ_iff_forall.1 $ finset.eq_of_subset_of_card_le (finset.subset_univ _) (le_of_eq $ eq.symm $ finset.card_image_of_injective _ H), λ y, let ⟨x, _, H2⟩ := finset.mem_image.1 (H y) in ⟨x, H2⟩
Kenny Lau (Aug 21 2018 at 18:27):
how about this?
Chris Hughes (Aug 21 2018 at 18:33):
Already in mathlib. fintype.injective_iff_surjective
Your proof is shorter though
Kenny Lau (Aug 21 2018 at 18:38):
import data.fintype universe u variables (α : Type u) [fintype α] [decidable_eq α] theorem something (f : α → α) (H : function.injective f) : function.surjective f := have H : _ := finset.eq_univ_iff_forall.1 $ finset.eq_of_subset_of_card_le (finset.subset_univ _) (le_of_eq $ eq.symm $ finset.card_image_of_injective _ H), λ y, let ⟨x, _, H2⟩ := finset.mem_image.1 (H y) in ⟨x, H2⟩ theorem something2 [integral_domain α] (x : α) (H : x ≠ 0) : ∃ r , r * x = 1 := something α (λ r, r * x) (λ r s (H' : r * x = s * x), eq_of_sub_eq_zero $ or.resolve_right (eq_zero_or_eq_zero_of_mul_eq_zero $ show (r - s) * x = 0, by rw [sub_mul, H', sub_self]) H) 1 noncomputable instance field_of_fintype_of_integral_domain [integral_domain α] : field α := { inv := λ x, if H : x = 0 then 0 else classical.some $ something2 α x H, mul_inv_cancel := λ x H, by unfold has_inv.inv; rw [dif_neg H, mul_comm, classical.some_spec (something2 α x H)], inv_mul_cancel := λ x H, by unfold has_inv.inv; rw [dif_neg H, classical.some_spec (something2 α x H)], .. (by apply_instance : integral_domain α) }
Kenny Lau (Aug 21 2018 at 18:38):
Already in mathlib.
fintype.injective_iff_surjective
Your proof is shorter though
well I didn't prove the other direction
Chris Hughes (Aug 21 2018 at 18:39):
Don't make that an instance or we have a cycle.
Kenny Lau (Aug 21 2018 at 18:39):
also I can't find injective_iff_surjective
Chris Hughes (Aug 21 2018 at 18:40):
It's quite new. Last month or so.
Kevin Buzzard (Aug 22 2018 at 20:46):
example (α : Type) (a b : α) : a = b = (b = a) := sorry
Too embarrassed to post my effort. @Chris Hughes this came up with that countp v count thing. The proof isn't refl even though the predicates are whatever they call it -- eta equivalent or something.
Patrick Massot (Aug 22 2018 at 20:48):
by cc
Mario Carneiro (Aug 22 2018 at 20:49):
propext eq_comm
Patrick Massot (Aug 22 2018 at 20:50):
Mine is shorter! :trophy:
Patrick Massot (Aug 22 2018 at 20:50):
I know, yours is probably faster
Mario Carneiro (Aug 22 2018 at 20:50):
Mine is smaller with pp.all
:)
Kevin Buzzard (Aug 22 2018 at 21:37):
Here's the context this came up in:
import data.multiset open multiset example (α : Type) [decidable_eq α] (s : multiset α) (a : α) : count a s = card (filter (λ b, b = a) s) := begin rw ←countp_eq_card_filter, unfold count, congr, funext, by cc, end
I was surprised this wasn't there, but perhaps the issue is that you can filter on λ b, b = a
or λ b, a = b
Kenny Lau (Aug 22 2018 at 21:47):
import data.multiset open multiset example (α : Type) [decidable_eq α] (s : multiset α) (a : α) : count a s = card (filter (λ b, b = a) s) := begin convert countp_eq_card_filter s, funext b, cc end
Mario Carneiro (Aug 22 2018 at 21:48):
by simp [count, countp_eq_card_filter, eq_comm]; congr
Kenny Lau (Aug 22 2018 at 21:51):
by convert countp_eq_card_filter s; simp [eq_comm]
Kevin Buzzard (Aug 22 2018 at 22:03):
If I hover over convert
in VS Code I get "convert <- expr <error while executing interactive.param_desc: don't know how to pretty print lean.parser.small_nat> Similar to refine
but generates equality proof obligations for every discrepancy between the goal and the type of the rule"
Mario Carneiro (Aug 22 2018 at 22:04):
that's because small_nat
doesn't have a description - compare with congr'
Sean Leather (Sep 12 2018 at 12:31):
example (m n : ℕ) : m < 1 + max m n := _
Reid Barton (Sep 12 2018 at 12:42):
not very creative, but by rw [add_comm, nat.lt_succ_iff]; apply le_max_left
Kenny Lau (Oct 18 2018 at 16:45):
import analysis.topology.topological_space example (α : Type*) [topological_space α] [t1_space α] [fintype α] (s : set α) : is_open s := by letI := classical.dec_pred (λ x, x ∈ -s); exact (is_closed_compl_iff.1 $ set.bUnion_of_singleton (-s) ▸ is_closed_Union ⟨set.fintype_of_finset (finset.univ.filter (λ x, x ∈ -s)) (λ x, by simp only [finset.mem_filter, finset.mem_univ, true_and])⟩ (λ _ _, is_closed_singleton))
Mario Carneiro (Oct 18 2018 at 17:45):
I think this theorem could also be stated as t = \top
Mario Carneiro (Oct 18 2018 at 17:53):
class t2_space' (α : Type u) [topological_space α] := (t2 : ∀x y, (∀ u v : set α, is_open u → is_open v → x ∈ u → y ∈ v → ∃ z, z ∈ u ∧ z ∈ v) → x = y) variables (α : Type u) [t : topological_space α] include t def Hausdorffification.setoid : setoid α := { r := λ x y, ∀ (s : setoid α) [t2_space' (quotient s)], @setoid.r α s x y, iseqv := ⟨λ _ s _, s.2.1 _, λ _ _ H s ht2, s.2.2.1 (@H s ht2), λ _ _ _ H1 H2 s ht2, s.2.2.2 (@H1 s ht2) (@H2 s ht2)⟩ } local attribute [instance] Hausdorffification.setoid @[reducible] def Hausdorffification : Type u := quotient (Hausdorffification.setoid α) instance Hausdorffification.t2_space' : t2_space' (Hausdorffification α) := { t2 := λ x y, quotient.induction_on₂ x y $ λ m n H, quot.sound $ λ r ht2, begin resetI, let f : Hausdorffification α → quotient r, { refine λ e, quotient.lift_on' e quotient.mk _, intros a b H, apply quotient.sound, apply H }, have hf : continuous f, { intros s hs, change is_open (quotient.mk ⁻¹' _), rw ← set.preimage_comp, exact hs }, refine quotient.exact (t2_space'.t2 _ _ $ λ u v h1 h2 h3 h4, _), rcases H _ _ (hf _ h1) (hf _ h2) h3 h4 with ⟨z, zu, zv⟩, exact ⟨fz, zu, zv⟩ end }
Johannes Hölzl (Oct 18 2018 at 18:04):
By the way: this T2 space definition is equal to not (disjoint (nhds x) (nhds y)) -> x = y
.
Mario Carneiro (Oct 18 2018 at 18:11):
not constructively
Mario Carneiro (Oct 18 2018 at 18:16):
(oops, wrong thread, this should be in Hausdorffification)
Last updated: Dec 20 2023 at 11:08 UTC