Zulip Chat Archive

Stream: new members

Topic: Fail to show termination


Richard Copley (Feb 11 2024 at 18:33):

Can you tell me what I'm doing wrong here? I expected fprod (k + 1) to be able to use fprod k without any fuss.

import Mathlib.Data.Finsupp.Basic

-- For all vectors `f : Fin k → (κ →₀ R)` of finitely-supported functions on $$κ$$, there
-- is a single finitely-supported function on $$κᵏ$$, `fprod k f : (Fin k → κ) →₀ R`,
-- such that `fprod k f v = List.prod <| .ofFn fun i => x i (v i)` for all `v` in $$κᵏ$$.
def fprod {κ R} [DecidableEq κ] [MonoidWithZero R] [Nontrivial R] [NoZeroDivisors R]
    (k : ) (f : Fin k -> κ →₀ R) : (Fin k  κ) →₀ R :=
  match k with
  | 0 => {
      toFun := fun _ => 1
      support := {fun.}
      mem_support_toFun := fun _ => fun _ => one_ne_zero,
        fun _ => Finset.mem_singleton.mpr (Subsingleton.allEq _ _)⟩
    }
  | (m + 1) => {
      toFun := fun p => f 0 (p 0) * fprod m (Fin.tail f) (Fin.tail p)
      support := (f 0).support.biUnion fun i =>
        (fprod m (Fin.tail f)).support.map Fin.cons i, Fin.cons_right_injective _
      mem_support_toFun := fun i =>
        fun h => by
          obtain h, hj, htail := Finset.mem_biUnion.mp h
          obtain a, ha, rfl := Finset.mem_map.mp htail
          dsimp only [Function.Embedding.coeFn_mk]
          rw [Fin.cons_zero, Fin.tail_cons, ne_eq, mul_eq_zero, not_or]
          exact Finsupp.mem_support_iff.mp hj, Finsupp.mem_support_iff.mp ha⟩,
        fun h =>
          have hhead, htail := mul_ne_zero_iff.mp h
          Finset.mem_biUnion.mpr i 0, Finsupp.mem_support_iff.mpr hhead,
            Finset.mem_map.mpr Fin.tail i, Finsupp.mem_support_iff.mpr htail,
              Fin.cons_self_tail i⟩⟩⟩
    }

The error is

fail to show termination for
  fprod
with errors
argument #7 was not used for structural recursion
  unexpected occurrence of recursive application
    @fprod

structural recursion cannot be used

and the remaining goal is just

 k < Nat.succ m

Matt Diamond (Feb 11 2024 at 19:37):

here's one solution:

import Mathlib.Data.Finsupp.Basic

-- For all vectors `f : Fin k → (κ →₀ R)` of finitely-supported functions on $$κ$$, there
-- is a single finitely-supported function on $$κᵏ$$, `fprod k f : (Fin k → κ) →₀ R`,
-- such that `fprod k f v = List.prod <| .ofFn fun i => x i (v i)` for all `v` in $$κᵏ$$.
def fprod {κ R} [DecidableEq κ] [MonoidWithZero R] [Nontrivial R] [NoZeroDivisors R]
    (k : ) (f : Fin k -> κ →₀ R) : (Fin k  κ) →₀ R :=
  match k with
  | 0 => {
      toFun := fun _ => 1
      support := {fun.}
      mem_support_toFun := fun _ => fun _ => one_ne_zero,
        fun _ => Finset.mem_singleton.mpr (Subsingleton.allEq _ _)⟩
    }
  | (m + 1) =>
    let f' := fprod m (Fin.tail f)
    {
      toFun := fun p => f 0 (p 0) * f' (Fin.tail p)
      support := (f 0).support.biUnion fun i =>
        (fprod m (Fin.tail f)).support.map Fin.cons i, Fin.cons_right_injective _
      mem_support_toFun := fun i =>
        fun h => by
          obtain h, hj, htail := Finset.mem_biUnion.mp h
          obtain a, ha, rfl := Finset.mem_map.mp htail
          dsimp only [Function.Embedding.coeFn_mk]
          rw [Fin.cons_zero, Fin.tail_cons, ne_eq, mul_eq_zero, not_or]
          exact Finsupp.mem_support_iff.mp hj, Finsupp.mem_support_iff.mp ha⟩,
        fun h =>
          have hhead, htail := mul_ne_zero_iff.mp h
          Finset.mem_biUnion.mpr i 0, Finsupp.mem_support_iff.mpr hhead,
            Finset.mem_map.mpr Fin.tail i, Finsupp.mem_support_iff.mpr htail,
              Fin.cons_self_tail i⟩⟩⟩
    }

Matt Diamond (Feb 11 2024 at 19:39):

strangely it doesn't require replacing the 2nd instance of fprod m (Fin.tail f), though you can certainly do that for the sake of consistency

Richard Copley (Feb 11 2024 at 19:43):

How mysterious! Thank you very much.

(Here is a diff:)

--- mwe.lean    2024-02-11 19:41:39 +0000
+++ fixed.lean  2024-02-11 19:41:39 +0000
@@ -12,8 +12,10 @@
       mem_support_toFun := fun _ => ⟨fun _ => one_ne_zero,
         fun _ => Finset.mem_singleton.mpr (Subsingleton.allEq _ _)⟩
     }
-  | (m + 1) => {
-      toFun := fun p => f 0 (p 0) * fprod m (Fin.tail f) (Fin.tail p)
+  | (m + 1) =>
+    let f' := fprod m (Fin.tail f)
+    {
+      toFun := fun p => f 0 (p 0) * f' (Fin.tail p)
       support := (f 0).support.biUnion fun i =>
         (fprod m (Fin.tail f)).support.map ⟨Fin.cons i, Fin.cons_right_injective _⟩
       mem_support_toFun := fun i =>

Last updated: May 02 2025 at 03:31 UTC