Zulip Chat Archive

Stream: new members

Topic: Reasoning modulo 4 by cases


Aniruddh Agarwal (Jul 03 2020 at 21:04):

If I want to prove something about x % 4, how can I split the current goal into 4 goals with the first one having the additional hypothesis x % 4 = 0 % 4, the second x % 4 = 1 % 4, and so on?

Patrick Massot (Jul 03 2020 at 21:05):

I tried something at https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/even.20or.20odd/near/195632609 but my threat wasn't taken seriously (and indeed I didn't follow up).

Patrick Massot (Jul 03 2020 at 21:06):

But there is no obstruction beyond available time and energy.

Mario Carneiro (Jul 03 2020 at 21:27):

doesn't fin_cases work here?

Patrick Massot (Jul 03 2020 at 21:28):

The thing I linked to is a wrapper around fin_cases

Mario Carneiro (Jul 03 2020 at 21:29):

okay, but the proof script using fin_cases directly shouldn't be nearly that bad

Aniruddh Agarwal (Jul 03 2020 at 22:00):

I'm unable to use ring for some reason:

import data.int.basic
import data.nat.parity
import tactic.interval_cases

namespace tactic.interactive
open tactic
open interactive (parse)
open lean.parser (tk)
open interactive.types (texpr)

meta def modulo_cases (n : parse texpr) (q : parse (tk ":" *> texpr)) : tactic unit :=
do qe  tactic.i_to_expr q,
   ne  tactic.i_to_expr n,
   «have» `h1 ``(%%ne = %%ne % %%qe + %%qe * (%%n / %%qe)) ``((int.mod_add_div %%ne %%qe).symm),
   `[rw add_comm at h1],
   «have» `h2 ``(%%ne % %%qe < abs %%qe) ``(int.mod_lt %%ne (by norm_num : (%%qe : )  0)),
   «have» `h4 ``(0  (%%qe: )) ``(dec_trivial),
   `[rw abs_of_nonneg h4 at h2],
   h4e  get_local `h4,
   tactic.clear h4e,
   «have» `h3 ``(0  %%ne % %%qe) ``(int.mod_nonneg %%ne dec_trivial),
   h1e  get_local `h1,
   h2e  get_local `h2,
   h3e  get_local `h3,
   tactic.revert h1e,
   tactic.revert h2e,
   tactic.revert h3e,
   e  (to_expr ``(%%ne % %%qe)),
   tactic.generalize e,
   e  (to_expr ``(%%ne / %%qe)),
   `[ intros r h1 h2 h3,
      interval_cases r ; clear h1 h2 ; try {rw add_zero at h3}],
   tactic.all_goals $ do
      h3e  get_local `h3,
      tactic.revert h3e,
      tactic.generalize e,
      `[rintros k rfl]

end tactic.interactive

theorem th (y : ) (h :  x : , y = x*x) : ( k, y = 4 * k)  ( k, y = 4 * k + 1) :=
begin
  cases h with x hx,
  modulo_cases x : (4 : ); rw hx,
  { left,
    use k * (4 * k),
    sorry },
  { right,
    use 4 * k * k + 2 * k,
    sorry, },
  { left,
    use 4 * k * k + 4 * k + 1,
    sorry },
  { right,
    use 4 * k * k + 6 * k + 2,
    ring }
end

The error I'm getting is

type mismatch at application
  tactic.istep 56 4 56 4 ring
term
  ring
has type
  Type ?  Type ? : Type (?+1)
but is expected to have type
  tactic ?m_1 : Type ?
don't know how to synthesize placeholder
context:
y : ,
h :  (x : ), y = x * x
 Type ?

Jalex Stark (Jul 03 2020 at 22:02):

you still have all the open statements from the tactic-writing part

Mario Carneiro (Jul 03 2020 at 22:05):

you haven't imported ring

Jalex Stark (Jul 03 2020 at 22:06):

ah. Type ? → Type ? : Type (?+1) is the type signature of ring typeclass

Aniruddh Agarwal (Jul 03 2020 at 23:39):

Can someone help me finish the proof?

import data.int.basic
import data.int.parity
import data.nat.parity
import tactic.interval_cases
import tactic

namespace tactic.interactive
open tactic
open interactive (parse)
open lean.parser (tk)
open interactive.types (texpr)

meta def modulo_cases (n : parse texpr) (q : parse (tk ":" *> texpr)) : tactic unit :=
do qe  tactic.i_to_expr q,
   ne  tactic.i_to_expr n,
   «have» `h1 ``(%%ne = %%ne % %%qe + %%qe * (%%n / %%qe)) ``((int.mod_add_div %%ne %%qe).symm),
   `[rw add_comm at h1],
   «have» `h2 ``(%%ne % %%qe < abs %%qe) ``(int.mod_lt %%ne (by norm_num : (%%qe : )  0)),
   «have» `h4 ``(0  (%%qe: )) ``(dec_trivial),
   `[rw abs_of_nonneg h4 at h2],
   h4e  get_local `h4,
   tactic.clear h4e,
   «have» `h3 ``(0  %%ne % %%qe) ``(int.mod_nonneg %%ne dec_trivial),
   h1e  get_local `h1,
   h2e  get_local `h2,
   h3e  get_local `h3,
   tactic.revert h1e,
   tactic.revert h2e,
   tactic.revert h3e,
   e  (to_expr ``(%%ne % %%qe)),
   tactic.generalize e,
   e  (to_expr ``(%%ne / %%qe)),
   `[ intros r h1 h2 h3,
      interval_cases r ; clear h1 h2 ; try {rw add_zero at h3}],
   tactic.all_goals $ do
      h3e  get_local `h3,
      tactic.revert h3e,
      tactic.generalize e,
      `[rintros k rfl]

end tactic.interactive

theorem square_eq_zero_or_one_mod_four (y : ) (h :  x : , y = x*x) :  k, y = 4 * k  y = 4 * k + 1 :=
begin
  cases h with x hx,
  modulo_cases x : (4 : ); rw hx,
  { use k * (4 * k),
    left,
    ring },
  { use 4 * k * k + 2 * k,
    right,
    ring },
  { use 4 * k * k + 4 * k + 1,
    left,
    ring },
  { use 4 * k * k + 6 * k + 2,
    right,
    ring }
end

theorem pyth_triples (x : ) (y : ) (z : ) (h : x*x + y*y = z*z) (h' : x.gcd y = 1  x.gcd z = 1  y.gcd z = 1)
  : ¬ (int.even z)
:=
begin
intro hz,
cases square_eq_zero_or_one_mod_four (z*z) (exists.intro z rfl),
cases square_eq_zero_or_one_mod_four (y*y) (exists.intro y rfl),
cases square_eq_zero_or_one_mod_four (x*x) (exists.intro x rfl),
cases h_3 with; cases h_2 with; cases h_1 with,
{ sorry }, -- contradiction gcd =/= 1
{ sorry }, -- contradiction gcd =/= 1
{ sorry }, -- contradiction gcd =/= 1
{ cases hz with,
  rw hz_h at h_1,
  sorry }, -- contradiction, 1 % 4 implies not even
{ sorry }, -- contradiction gcd =/= 1
{ cases hz with,
  rw hz_h at h_1,
  sorry }, -- contradiction, 1 % 4 implies not even
{ rw h_1 at h,
  rw h_2 at h,
  rw h_3 at h,
  sorry }, -- contradiction 1 % 4 + 1 % 4 != 0 % 4
{ rw h_1 at h,
  rw h_2 at h,
  rw h_3 at h,
  sorry }  -- contradiction 1 % 4 + 1 % 4 != 1 % 4
end

Johan Commelin (Jul 04 2020 at 04:54):

@Aniruddh Agarwal Often you can prove a helper lemma directly by dec_trivial... see for example here: https://github.com/leanprover-community/mathlib/blob/pythagorean_triples_jmc/src/number_theory/pythagorean_triples.lean#L123L126

Johan Commelin (Jul 04 2020 at 04:55):

I hope you are aware that there is an ongoing PR on pythagorean triples. So please don't duplicate effort, unless this is all for fun.

Aniruddh Agarwal (Jul 05 2020 at 20:52):

@Johan Commelin Thanks, I'll check that out. I'm just doing this for fun, and don't intend to PR this into mathlib.


Last updated: Dec 20 2023 at 11:08 UTC