Zulip Chat Archive

Stream: new members

Topic: lean4 calc developments with simp


Augustin d'Oultremont (Apr 09 2022 at 15:17):

Hi ! I started 2 months ago in lean4 (without any prior experience in theorem proving languages, but a good experience in programming), and I encountered a timeout at 'whnf', maximum number of heartbeats (50000) has been reached error using simp.

I am trying to automate solving equalities like (3 * k + 2)^2 = 3 * (3 * k^2 + 4 * k + 1) + 1 using simp. For now, I've added a handful of very basic theorems (listed below), that are sufficient to solve it (works with set_option maxHeartbeats 350000).

My current method solves (3 * k + 1)^2 = 3 * (3 * k^2 + 2 * k) + 1 without problems (with the default maxHeartbeats 50000). For context : I'm trying to prove a % b ≠ 0 → (q^2 % 3 = 1) by development on the different cases, hence the two examples given.

Reading @Leonardo de Moura's response at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/New.20simp.20feature, and other topics (following the trace and trying to understand the process), I get the impression that

  • the theorems I've added are too basic and thus require a big development
  • developments like that would need better theorems / methods to work well
  • mathlib4 might solve the problem but it seems like the theorems that I would need are not implemented yet

Could a more experienced leaner give me a clue on whether this would need (the fully ported) mathlib4 or how to make it work without it (with only the current mathlib4 or only basic lean) ?

Thanks a lot !
Augustin

:down:️ the theorems added to simp

attribute [simp]
    -- addition
      -- swapping
      Nat.add_assoc
      Nat.add_comm
      Nat.add_left_comm
      -- zero & one
      Nat.add_zero
      Nat.zero_add
    -- multiplication
      -- succ
      Nat.mul_succ
      Nat.succ_mul
      -- swapping
      Nat.mul_assoc
      Nat.mul_comm
      Nat.mul_left_comm
      -- zero & one
      Nat.mul_zero
      Nat.zero_mul
      Nat.mul_one
      Nat.one_mul
    -- powers
      -- zero & one
      Nat.pow_zero
      -- succ
      Nat.pow_succ
    -- multiplication to addition
    Nat.left_distrib
    Nat.right_distrib

Mario Carneiro (Apr 09 2022 at 15:20):

have you met tactic#ring?

Mario Carneiro (Apr 09 2022 at 15:21):

also you should show a #mwe

Augustin d'Oultremont (Apr 09 2022 at 15:34):

Mario Carneiro said:

also you should show a #mwe

Sorry about that, here it is :

attribute [simp] Nat.add_assoc Nat.add_comm Nat.add_left_comm Nat.add_zero Nat.zero_add Nat.mul_succ Nat.succ_mul Nat.mul_assoc Nat.mul_comm Nat.mul_left_comm Nat.mul_zero Nat.zero_mul Nat.mul_one Nat.one_mul Nat.pow_zero Nat.pow_succ Nat.left_distrib Nat.right_distrib

-- simple example
example (k : Nat) : (3 * k + 1)^2 = 3 * (3 * k^2 + 2 * k) + 1 := by simp

-- more complex, only works with set_option maxHeartbeats 350000
set_option maxHeartbeats 350000
example (k : Nat) : (3 * k + 2)^2 = 3 * (3 * k^2 + 4 * k + 1) + 1 := by simp

Mario Carneiro (Apr 09 2022 at 15:40):

to get a sense for why this proof method is so terrible, note that the normal form worked out in the first example is

        (k +
          (k +
            (k +
              (k +
                (k +
                  (k +
                    (k * k + (k * k + (k * k + (k * k + (k * k + (k * k + (k * k + (k * k + (k * k + 1))))))))))))))))

Mario Carneiro (Apr 09 2022 at 15:41):

ring knows about scalar multiples and performs much better on these goals (and is ultimately what we want to use here)

Mario Carneiro (Apr 09 2022 at 15:42):

mathlib4 already has the ring tactic well enough for these examples

import Mathlib.Tactic.Ring

example (k : Nat) : (3 * k + 1)^2 = 3 * (3 * k^2 + 2 * k) + 1 := by ring
example (k : Nat) : (3 * k + 2)^2 = 3 * (3 * k^2 + 4 * k + 1) + 1 := by ring

Last updated: Dec 20 2023 at 11:08 UTC