Zulip Chat Archive
Stream: lean4
Topic: indexed inductive types overwhelming server
Siddhartha Gadgil (May 09 2022 at 07:46):
I have been working with indexed inductive types (to define group rings). One piece of code (surprisingly to me) times out even with high limits. A self-contained piece of the code is the following:
variable (X: Type)[DecidableEq X]
abbrev FormalSum : Type := List (Nat × X)
inductive BasicRel : FormalSum X → FormalSum X → Prop where
| zeroCoeff (tail: FormalSum X)(x: X)(a : Nat)(h: a = 0):
BasicRel ((a, x):: tail) tail
| addCoeffs (a b: Nat)(x: X)(tail: FormalSum X):
BasicRel ((a, x) :: (b, x) :: tail) ((a + b, x) :: tail)
| cons (a: Nat)(x: X)(s₁ s₂ : FormalSum X):
BasicRel s₁ s₂ → BasicRel ((a, x) :: s₁) ((a, x) :: s₂)
| swap (a₁ a₂: Nat)(x₁ x₂: X)(tail : FormalSum X):
BasicRel ((a₁, x₁) :: (a₂, x₂) :: tail)
((a₂, x₂) :: (a₁, x₁) :: tail)
def linear_extension{X: Type}[DecidableEq X](f₀ : X → Nat) : FormalSum X → Nat
| [] => 0
| h :: t =>
let (a, x) := h
a * f₀ x + (linear_extension f₀ t)
termination_by _ _ s => s.length
set_option maxHeartbeats 2000000
open BasicRel in
theorem invariance_of_linear_extension{X: Type}[DecidableEq X](f₀ : X → Nat) :
(∀ s₁ s₂ : FormalSum X, ∀ rel : BasicRel X s₁ s₂, linear_extension f₀ s₁ = linear_extension f₀ s₂) :=
fun s₁ s₂ rel =>
match s₁, s₂, rel with
| (a, x) :: tail, .(tail), zeroCoeff .(tail) .(x) .(a) hyp => by
rw [hyp]
simp [linear_extension]
| (a, x) :: (b, .(x)) :: tail, .((a + b, x) :: tail),
addCoeffs .(a) .(b) .(x) .(tail) => by
simp [linear_extension, ← Nat.add_assoc]
have step : a * f₀ x + b * f₀ x = (a + b) * f₀ x :=
by simp [Nat.right_distrib]
rw [← step]
| (a, x) :: t₁, (.(a), .(x)) :: t₂, cons .(a) .(x) .(t₁) .(t₂) r =>
by
simp [linear_extension, ← Nat.add_assoc]
let ih := invariance_of_linear_extension f₀ t₁ t₂ r
rw [ih]
| (a₁, x₁) :: (a₂, x₂) :: tail,
(.(a₂), .(x₂)) :: (.(a₁), .(x₁)) :: .(tail) ,
swap .(a₁) .(a₂) .(x₁) .(x₂) .(tail) => by
simp [linear_extension, ← Nat.add_assoc]
have step : a₁ * f₀ x₁ + a₂ * f₀ x₂ = a₂ * f₀ x₂ + a₁ * f₀ x₁ :=
by simp [Nat.add_comm]
rw [step]
termination_by _ _ s₁ s₂ => s₁.length
Is there something I should be doing differently? Or is this an issue with the server. For context, I tried using the induction tactic, which worked very well in related code, but could not prove termination in this case as the relation between s
and its tail t
was lost.
Thanks.
Siddhartha Gadgil (May 09 2022 at 07:56):
Actually, there is an obvious thing I should (and will try) - prove separate theorems for the cases. But I anyway wanted to report this as a possible performance issue.
Siddhartha Gadgil (May 09 2022 at 08:39):
With more experiments, this is clearly a case of checking exhaustiveness of pattern matching taking too long. I could minimize further to the following code hanging:
variable (X: Type)[DecidableEq X]
abbrev FormalSum : Type := List (Nat × X)
inductive BasicRel : FormalSum X → FormalSum X → Prop where
| zeroCoeff (tail: FormalSum X)(x: X)(a : Nat)(h: a = 0):
BasicRel ((a, x):: tail) tail
| addCoeffs (a b: Nat)(x: X)(tail: FormalSum X):
BasicRel ((a, x) :: (b, x) :: tail) ((a + b, x) :: tail)
| cons (a: Nat)(x: X)(s₁ s₂ : FormalSum X):
BasicRel s₁ s₂ → BasicRel ((a, x) :: s₁) ((a, x) :: s₂)
| swap (a₁ a₂: Nat)(x₁ x₂: X)(tail : FormalSum X):
BasicRel ((a₁, x₁) :: (a₂, x₂) :: tail)
((a₂, x₂) :: (a₁, x₁) :: tail)
def linear_extension{X: Type}[DecidableEq X](f₀ : X → Nat) : FormalSum X → Nat
| _ => 0
set_option maxHeartbeats 2000000
open BasicRel in
theorem invariance_of_linear_extension{X: Type}[DecidableEq X]
(s₁ s₂: FormalSum X)(h: BasicRel X s₁ s₂)(f₀ : X → Nat) :
linear_extension f₀ s₁ = linear_extension f₀ s₂ :=
match s₁, s₂, h with
| (a₁, x₁) :: (a₂, x₂) :: tail,
(.(a₂), .(x₂)) :: (.(a₁), .(x₁)) :: .(tail) ,
swap .(a₁) .(a₂) .(x₁) .(x₂) .(tail) => sorry
| (a, x) :: tail, .(tail), zeroCoeff .(tail) .(x) .(a) hyp =>
sorry
| _, _, _ => sorry
For comparison, if I remove the second case match then everything is instantaneous. By this I mean replacing the theorem with:
theorem invariance_of_linear_extension{X: Type}[DecidableEq X]
(s₁ s₂: FormalSum X)(h: BasicRel X s₁ s₂)(f₀ : X → Nat) :
linear_extension f₀ s₁ = linear_extension f₀ s₂ :=
match s₁, s₂, h with
| (a₁, x₁) :: (a₂, x₂) :: tail,
(.(a₂), .(x₂)) :: (.(a₁), .(x₁)) :: .(tail) ,
swap .(a₁) .(a₂) .(x₁) .(x₂) .(tail) => sorry
| _, _, _ => sorry
I am using the nightly: leanprover/lean4:nightly-2022-05-08
Last updated: Dec 20 2023 at 11:08 UTC