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