Zulip Chat Archive

Stream: new members

Topic: lemmas on int and subsingleton


Damiano Testa (Apr 06 2021 at 07:04):

Dear All,

while working on the lean-liquid branch, I found the lemmas below useful and I could not find them in mathlib. If you think that it would be helpful to have some of them in mathlib, let me know and I will be happy to make the relevant PRs!

Thanks!

import algebra.associated

lemma int.nat_abs_eq_iff {n : } {k : } : n.nat_abs = k  n = k  n = -k :=
by { rintro rfl, exact int.nat_abs_eq n }, by rintro (rfl | rfl); simp

lemma int.is_unit_plus_minus_one_of {n : } : is_unit n  n = 1  n = -1 :=
is_unit_int.trans (int.nat_abs_eq_iff.trans iff.rfl)

lemma function.injective.of_subsingleton {s t : Type*} [hs : subsingleton s] (f : s  t) :
  function.injective f :=
λ a b ab, subsingleton_iff.mp hs a b

lemma function.surjective.to_subsingleton {s t : Type*} [nonempty s] (f : s  t) [subsingleton t] :
  function.surjective f :=
function.surjective_iff_has_right_inverse.mpr function.inv_fun f, by finish

lemma subsingleton_eq_univ_of_mem {A : Type*} (hA : subsingleton A) (a : A) :
  ({a} : set A) = set.univ :=
le_antisymm (λ a1 ha, set.mem_univ a1)
  (λ x hx, set.mem_singleton_iff.mpr (subsingleton_iff.mp hA x a))

Johan Commelin (Apr 06 2021 at 07:07):

LGTM.
nonempty s should be a type class assumption (in lemma 4)

Johan Commelin (Apr 06 2021 at 07:08):

For the last lemma, I wonder whether you want to generalise the LHS to an arbitrary set s with assumption s.nonempty

Damiano Testa (Apr 06 2021 at 07:09):

Johan, thanks!

lemma4 : I edited the list above and, in the same lemma, went ahead to make subsingleton also a typeclass assumption!

Damiano Testa (Apr 06 2021 at 07:13):

I am working on a proof of the other suggestion that you made!

Damiano Testa (Apr 06 2021 at 07:28):

I could almost find the version that Johan suggested with a set:

lemma subsingleton_eq_univ_of_subset {A : Type*} [hA : subsingleton A] (a : set A) [nonempty a] :
  a = set.univ :=
subsingleton.eq_univ_of_nonempty set.nonempty_of_nonempty_subtype

and the same proof works for the earlier lemma:

lemma subsingleton_eq_univ_of_mem {A : Type*} (hA : subsingleton A) (a : A) :
  ({a} : set A) = set.univ :=
subsingleton.eq_univ_of_nonempty set.nonempty_of_nonempty_subtype

I guess that this means that this lemma "is" already in mathlib!

Eric Wieser (Apr 06 2021 at 07:40):

Is nonempty a (for a : set _) the preferred spelling of set emptiness? That inserts a coercion to sort, which is why it would surprise me if it is!

Eric Wieser (Apr 06 2021 at 07:41):

Ah, indeed the proof you give translates your spelling to the less surprising one

Eric Wieser (Apr 06 2021 at 07:42):

I'm pretty sure I've seen int.nat_abs_eq_iff or similar in review recently...

Johan Commelin (Apr 06 2021 at 07:44):

@Eric Wieser s is a Type. Maybe those letters should be changed to X and Y or \alpha and \beta.

Eric Wieser (Apr 06 2021 at 07:45):

Ah, I mistakenly assumed the last code snippet agreed with the earlier ones, and didn't scroll sideways to check on mobile!

Damiano Testa (Apr 06 2021 at 07:54):

Besides the fact that there is one case in which the assumption nonempty is applied to a set, the confusion is probably also caused by the fact that I used s for a Type, whereas often s denotes a subset. I tried to uniformize the notation, in the code below:

namespace int

-- proof provided by Ruben
lemma nat_abs_eq_iff {a : } {n : } : a.nat_abs = n  a = n  a = -n :=
by rw [int.nat_abs_eq_nat_abs_iff, int.nat_abs_of_nat]

lemma is_unit_plus_minus_one_of {a : } : is_unit a  a = 1  a = -1 :=
is_unit_int.trans (nat_abs_eq_iff.trans iff.rfl)

end int

lemma function.injective.of_subsingleton {α β : Type*} [h : subsingleton α] (f : α  β) :
  function.injective f :=
λ a b ab, subsingleton_iff.mp h a b

lemma function.surjective.to_subsingleton {α β : Type*} (f : α  β) [nonempty α] [subsingleton β] :
  function.surjective f :=
function.surjective_iff_has_right_inverse.mpr function.inv_fun f, by finish

-- this lemma and the next may be "too close" to results in mathlib: I will probably not PR them,
-- unless there is some explicit interest in them!
lemma subsingleton_eq_univ_of_mem {α : Type*} [subsingleton α] (a : α) :
  ({a} : set α) = set.univ :=
subsingleton.eq_univ_of_nonempty set.nonempty_of_nonempty_subtype

-- here [nonempty s] introduces a coercion mentioned by Eric
lemma subsingleton_eq_univ_of_subset {α : Type*} [h : subsingleton α] (s : set α) [nonempty s] :
  s = set.univ :=
subsingleton.eq_univ_of_nonempty set.nonempty_of_nonempty_subtype

Ruben Van de Velde (Apr 06 2021 at 07:55):

Alternative proof for the first one:

import algebra.associated
lemma int.nat_abs_eq_iff {n : } {k : } : n.nat_abs = k  n = k  n = -k :=
by rw [int.nat_abs_eq_nat_abs_iff, int.nat_abs_of_nat]

Damiano Testa (Apr 06 2021 at 07:56):

Ruben, thanks! I will update with your proof, since it seems more direct!

Eric Wieser (Apr 06 2021 at 08:07):

I think is_unit_plus_minus_one_of is docs#int.units_eq_one_or

Eric Wieser (Apr 06 2021 at 08:07):

Or at least, it's a more direct proof via that lemma

Damiano Testa (Apr 06 2021 at 08:08):

Ok, I was actually right now playing with this, since I had also found int.units_eq_one_or, trying to place is_unit_plus_minus_one_of

Damiano Testa (Apr 06 2021 at 08:17):

I am failing to be able to use int.units_eq_one_or. I would like to apply the conclusion of that lemma to get Lean to ask me to produce a unit. Is there a way to do this?

What is a good way to proceed?

Below is a proof that I would like to see if it can be made to work:

lemma is_unit_plus_neg_one_of {a : } (h : is_unit a) : a = 1  a = -1 :=
begin
  apply units_eq_one_or _,
-- of course this does not work, since Lean does not know that `a` is a piece of a unit.
-- How can I get Lean to proceed there?
end

Eric Wieser (Apr 06 2021 at 08:24):

Also, the word minus should be neg!

Damiano Testa (Apr 06 2021 at 08:25):

Eric, this last one was easy to fix! :wink:

Johan Commelin (Apr 06 2021 at 08:27):

is_unit.eq_one_or_neg_one?

Johan Commelin (Apr 06 2021 at 08:28):

Of course it's a bit weird to put a lemma specific to int in the is_unit namespace

Johan Commelin (Apr 06 2021 at 08:28):

Do we already have is_unit.eq_one for nat?

Eric Wieser (Apr 06 2021 at 08:30):

library_search doesn't find either of these:

lemma nat.units_eq_one (a : units ) : a = 1 :=
by library_search

lemma is_unit.eq_one {a : } (h : is_unit a) : a = 1 :=
by library_search

edit: ah, we have docs#nat.units_eq_one

Eric Wieser (Apr 06 2021 at 08:31):

And docs#nat.is_unit_iff

Damiano Testa (Apr 06 2021 at 08:32):

So, should the name be int.is_unit_iff?

Damiano Testa (Apr 06 2021 at 08:33):

Still, I have not been able to prove the is_unit lemma from the units one.

Eric Wieser (Apr 06 2021 at 08:36):

lemma is_unit.eq_one_or {a : } (h : is_unit a) : a = 1  a = -1 :=
begin
  obtain x, rfl := h,
  rw [units.coe_one, units.coe_neg],
  exact (int.units_eq_one_or _).imp (congr_arg coe) (congr_arg coe),
end

Damiano Testa (Apr 06 2021 at 08:37):

To confuse me further,

theorem is_unit_int {n : } : is_unit n  n.nat_abs = 1 :=

is in algebra/associated and not in data/int/basic, where the stuff about units in int appears.

Damiano Testa (Apr 06 2021 at 08:39):

It might be that the reason for this is to not import algebra/associated into data/int/basic.

Eric Wieser (Apr 06 2021 at 08:39):

Or a shorter proof,

lemma is_unit.eq_one_or' {a : } : is_unit a  a = 1  a = -1
| x, hx := hx  (int.units_eq_one_or _).imp (congr_arg coe) (congr_arg coe)

Eric Wieser (Apr 06 2021 at 08:40):

If that proof can be moved to data/int/basic, it probably should be

Damiano Testa (Apr 06 2021 at 08:41):

At the moment, it cannot, since the proof uses lemmas in algebra/associated, but I am sure that I can prove this lemma from what is in data/int/basic, since we already know that units in int are 1 and -1! :upside_down:

Ruben Van de Velde (Apr 06 2021 at 08:48):

Should it be an iff, though?

Damiano Testa (Apr 06 2021 at 08:50):

Ruben, I took Erics suggestion to mean the following:

lemma is_unit.eq_one_or' {a : } : is_unit a  a = 1  a = -1
| x, hx := hx  (int.units_eq_one_or _).imp (congr_arg coe) (congr_arg coe)

lemma is_unit_iff {a : } : is_unit a  a = 1  a = -1 :=
begin
  refine λ h, is_unit.eq_one_or' h, λ h, _⟩,
  rcases h with rfl | rfl,
  { exact is_unit_one },
  { exact is_unit_of_mul_eq_one _ (- 1 : ) (neg_one_mul _) }
end

Eric Wieser (Apr 06 2021 at 08:54):

Note the ' was just to distinguish it from my previous lemma, there's no need for ' if you PR that

Damiano Testa (Apr 06 2021 at 08:55):

How do people feel about making is_unit_iff a simp lemma?

Damiano Testa (Apr 06 2021 at 08:56):

Should the iff version of units be there as well?
Hmm, I had not given enough TT thought about this: the units lemma is tricky to convert into an iff, right?

Damiano Testa (Apr 06 2021 at 08:56):

Also as a simp lemma?

Eric Wieser (Apr 06 2021 at 09:00):

Looks like you could do with an is_unit.neg lemma there too:

lemma is_unit.neg {α : Type*} [ring α] {a : α} (h : is_unit a) : is_unit (-a) :=
begin
  obtain x, rfl := h,
  exact (-x).is_unit,
end

lemma is_unit_iff {a : } : is_unit a  a = 1  a = -1 :=
begin
  refine is_unit.eq_one_or, λ h, _⟩,
  rcases h with rfl | rfl,
  { exact is_unit_one },
  { exact is_unit_one.neg }
end

Eric Wieser (Apr 06 2021 at 09:02):

I think that might be a bad idea as a simp lemma

Damiano Testa (Apr 06 2021 at 09:02):

With the changes above, the lemma below now fits in data/int/basic and is no longer needed in algebra/associated:

theorem is_unit_int {n : } : is_unit n  n.nat_abs = 1 :=
by simp [nat_abs_eq_iff, is_unit_iff]

Damiano Testa (Apr 06 2021 at 09:02):

Ok, I will remove the simp attribute!

Damiano Testa (Apr 06 2021 at 09:04):

I was thinking about the is_unit.neg, but it probably does not belong to any file that is already imported into data/int/basic, right?

Damiano Testa (Apr 06 2021 at 09:04):

I am happy to prove that the opposite of a unit is again a unit, though it would probably be a different PR!

Ruben Van de Velde (Apr 06 2021 at 09:10):

I had

variables {α : Type*} [ring α]

lemma is_unit.neg (u : α) : is_unit (-u)  is_unit u :=
begin
  split;
  { rintro u', hu⟩,
    use -u',
    simp only [hu, neg_neg, units.coe_neg] }
end

Damiano Testa (Apr 06 2021 at 09:15):

PR #7058

Yakov Pechersky (Apr 06 2021 at 14:27):

Any is_unit lemma is also a lemma about units. And units are a group/subgroup depending on how you approach it. The neg one is just a special case of a mul_hom

Eric Wieser (Apr 06 2021 at 14:28):

Sure, but we have is_unit.mul and is_unit.inv, so we may as well add versions for the other operators for convenience

Eric Wieser (Apr 06 2021 at 14:28):

Do we have the fact that units are a subgroup?

Damiano Testa (Apr 06 2021 at 14:32):

In case it helps, this is the part of the code where opposites interact with is_unit in the PR:

https://github.com/leanprover-community/mathlib/blob/042166150bc51f7976161ff8642f3b408a823f07/src/algebra/ring/basic.lean#L627


Last updated: Dec 20 2023 at 11:08 UTC