Zulip Chat Archive

Stream: new members

Topic: How to extract propositions from instance's (non-)existence?


Chung Thai Nguyen (Mar 10 2025 at 07:06):

There is a structure called Irreducible (https://github.com/leanprover-community/mathlib4/blob/0d1fc2182203e994dddc69190f494eb361b18963/Mathlib/Algebra/Prime/Defs.lean#L99)

structure Irreducible [Monoid M] (p : M) : Prop where
  /-- `p` is not a unit -/
  not_unit : ¬IsUnit p
  /-- if `p` factors then one factor is a unit -/
  isUnit_or_isUnit' :  a b, p = a * b  IsUnit a  IsUnit b

Currently my code assumes a specific polynomial to be NOT Irreducible, the assumption is like this:

h_neg_irreducible : ¬Irreducible (poly)

But now I want to convert this assumption of non-existence of an instance of Irreducible into propositions about its properties:

IsUnit (poly)   a b, poly = a * b  ¬IsUnit a  ¬IsUnit b

Could you give me some ideas on which tactics can I use to achieve this goal? I really appreciate any help from you. Thank you.

Vlad Tsyrklevich (Mar 10 2025 at 07:27):

You can use by_contra h and then apply docs#irreducible_iff. You will get better answers if you post an #mwe to fill-in.

Vlad Tsyrklevich (Mar 10 2025 at 07:38):

ah I see now that you specified it's a hypothesis, simp [irreducible_iff] at h should do it.

Chung Thai Nguyen (Mar 10 2025 at 07:57):

Vlad Tsyrklevich said:

ah I see now that you specified it's a hypothesis, simp [irreducible_iff] at h should do it.

Thank you so much @Vlad Tsyrklevich. This is the final working #mwe using apply docs#irreducible_iff.

import Mathlib.Algebra.Polynomial.Basic
import Mathlib.Algebra.Group.Units.Defs
import Mathlib.Algebra.Field.Defs
import Mathlib.RingTheory.Ideal.Span

variable {F3: Type*} [Field F3]
variable {poly: Polynomial F3}

instance polyIrreducible : Irreducible (poly: Polynomial F3) := by
  by_contra h_neg_irreducible
  unfold Irreducible at h_neg_irreducible
  simp [irreducible_iff] at h_neg_irreducible
  -- split h_neg_irreducible into two cases and derive contradiction in both cases
  simp only [imp_iff_not_or] at h_neg_irreducible
  -- consider cases and prove both cases lead to contradiction
  cases h_neg_irreducible
  case inl left_case => -- left_case : ¬¬IsUnit poly
    sorry
  case inr right_case => -- right_case : ∃ x x_1, poly = x * x_1 ∧ ¬IsUnit x ∧ ¬IsUnit x_1
    sorry

Ruben Van de Velde (Mar 10 2025 at 08:19):

(That's not a #mwe, if only because it doesn't have imports)

Vlad Tsyrklevich (Mar 10 2025 at 08:24):

(hover over the code and press the button in the top-right to see)

Chung Thai Nguyen (Mar 11 2025 at 08:21):

Ruben Van de Velde said:

(That's not a #mwe, if only because it doesn't have imports)

Thank you for your feedback. I will post a full #mwe soon.

Chung Thai Nguyen (Mar 11 2025 at 09:30):

I've updated the #mwe. Thank you you all.

Kevin Buzzard (Mar 11 2025 at 09:50):

But now what exactly is the question? I don't see IsUnit (poly) ∨ ∃ a b, poly = a * b ∧ ¬IsUnit a ∧ ¬IsUnit b in the #mwe. Can you write down the Lean code for the exact theorem you want to prove?

Kevin Buzzard (Mar 11 2025 at 09:52):

Is this the question?

import Mathlib.Algebra.Polynomial.Basic
import Mathlib.Algebra.Group.Units.Defs
import Mathlib.Algebra.Field.Defs
import Mathlib.RingTheory.Ideal.Span

variable {F3: Type*} [Field F3]
variable {poly: Polynomial F3}

example (h_neg_irreducible : ¬Irreducible (poly)) :
    IsUnit (poly)   a b, poly = a * b  ¬IsUnit a  ¬IsUnit b :=
  sorry

Your mwe seems unrelated to your question.

Chung Thai Nguyen (Mar 11 2025 at 09:53):

I've just added comments the #mwe, with cases we can prove each case separately. That's what I needed.

Kevin Buzzard (Mar 11 2025 at 09:54):

import Mathlib.Algebra.Polynomial.Basic
import Mathlib.Algebra.Group.Units.Defs
import Mathlib.Algebra.Field.Defs
import Mathlib.RingTheory.Ideal.Span

variable {F3: Type*} [Field F3]
variable {poly: Polynomial F3}

example (h_neg_irreducible : ¬Irreducible (poly)) :
    IsUnit (poly)   a b, poly = a * b  ¬IsUnit a  ¬IsUnit b := by
  rw [irreducible_iff] at h_neg_irreducible
  push_neg at h_neg_irreducible
  tauto

Chung Thai Nguyen (Mar 11 2025 at 09:58):

Great. Thank you for this very clean approach. push_neg looks really useful.

Chung Thai Nguyen (Mar 11 2025 at 10:19):

btw do you think that the way we have to use a supporting theorem like irreducible_iff to decompose a structure is a bit repetitive? Because we will have to create such a theorem for every structure? Especially for structures that extend other structures and more (nested extension), it would be complex and long.

So I'm looking for a way to get the proposition that represents the existence/non-existence of an instance of a structure in the most clean way. Do you have any ideas?

Riccardo Brasca (Mar 11 2025 at 10:34):

Using irreducible_iff instead of unfolding a definition makes a proof more robust. Imagine that tomorrow for some reason someone changes the definition of Irreducible, to something mathematically equivalent but expressed in a different way, maybe more convenient for formalization. Of course the proof of irreducible_iff would need to be fixed, but all the other proofs will work automatically. On the other hand proofs unfolding the definition will break.

Riccardo Brasca (Mar 11 2025 at 10:36):

In an ideal world all definitions should have a good API, and after the API is developed nobody should never unfold the definition. For example you really don't want to know how is defined in mathlib (at least if you are a mathematician), but the point is that you don't need to know it.

Chung Thai Nguyen (Mar 11 2025 at 10:38):

Riccardo Brasca said:

Using irreducible_iff instead of unfolding a definition makes a proof more robust. Imagine that tomorrow for some reason someone changes the definition of Irreducible, to something mathematically equivalent but expressed in a different way, maybe more convenient for formalization. Of course the proof of irreducible_iff would need to be fixed, but all the other proofs will work automatically. On the other hand proofs unfolding the definition will break.

Yep I got your point.
My concern is how can we unfold definitions that are abstract like this? Or do we have to trace back to all of the dependencies to gather the full definitions and put them into a theorem? Because I don't have the concrete propositions, I have to find a longer way around it.

/-- A domain is a nontrivial semiring such that multiplication by a non zero element
is cancellative on both sides. In other words, a nontrivial semiring `R` satisfying
`∀ {a b c : R}, a ≠ 0 → a * b = a * c → b = c` and
`∀ {a b c : R}, b ≠ 0 → a * b = c * b → a = c`.

This is implemented as a mixin for `Semiring α`.
To obtain an integral domain use `[CommRing α] [IsDomain α]`. -/
@[stacks 09FE]
class IsDomain (α : Type u) [Semiring α] extends IsCancelMulZero α, Nontrivial α : Prop

Riccardo Brasca (Mar 11 2025 at 10:54):

The short answer is: don't unfold the definition. If you find a missing lemma in the API add it, but in proofs of "serious" theorems you should never unfold.

Chung Thai Nguyen (Mar 11 2025 at 10:55):

Riccardo Brasca said:

The short answer is: don't unfold the definition. If you find a missing lemma in the API add it, but in proofs of "serious" theorems you should never unfold.

Yep. Thank you for your answer.

Riccardo Brasca (Mar 11 2025 at 10:57):

the fact that isDoman_iff does not exist is probably because nobody wants it. We surely have that all the trivial stuff hold for a domain. And if you want to provide an instance of IsDomain is much better to use the where syntax.

Riccardo Brasca (Mar 11 2025 at 10:59):

The rationale is something like: "Prop valued structures deserve an iff lemma, other structures don't"


Last updated: May 02 2025 at 03:31 UTC