Zulip Chat Archive

Stream: new members

Topic: Lean not acknowledging value of term in recursor


Vivek Rajesh Joshi (Dec 01 2024 at 07:49):

import Mathlib.Data.Matrix.Notation
import Mathlib.Data.Fin.Tuple.Reflection

variable (F : Type) [Field F] [DecidableEq F]

inductive ElemOp (m : ) : Type where
| scalarMul (c : F) (hc : c0) (i : Fin m) : ElemOp m
| rowSwap (i : Fin m) (j : Fin m) : ElemOp m
| rowMulAdd (c : F) (i : Fin m) (j : Fin m) (hij : ij) : ElemOp m

namespace ElemOp

variable {F} in
@[simp] def onMatrix (E : ElemOp F m) (A : Matrix (Fin m) (Fin k) F) : Matrix (Fin m) (Fin k) F :=
match E with
| scalarMul c _ i => A.updateRow i (c  (A i))
| rowSwap i j => let newr := (A i)
    Matrix.updateRow (Matrix.updateRow A i (A j)) j newr
| rowMulAdd c i j _ => A.updateRow i (A i + (c  (A j)))

end ElemOp

inductive RowEchelonForm : (m n : Nat)  Type where
| nil : RowEchelonForm m 0
| pad : RowEchelonForm m n  RowEchelonForm m (n+1)
| extend : RowEchelonForm m n  (Fin n  F)  RowEchelonForm (m+1) (n+1)
deriving Repr

variable {F} in
def RowEchelonForm.toMatrix (R : RowEchelonForm F m n) : Matrix (Fin m) (Fin n) F :=
  match R with
  | nil => fun _ => ![]
  | pad R0 => FinVec.map (fun r => (Matrix.vecCons 0 r)) R0.toMatrix
  | extend R0 v => Matrix.vecCons (Matrix.vecCons 1 v) (FinVec.map (fun r => (Matrix.vecCons 0 r)) R0.toMatrix)

variable {F} in
def RowEchelonForm.pivots (R : RowEchelonForm F m n) : List {(i,j) : (Fin m)×(Fin n) | R.toMatrix i j = 1} :=
  match R with
  | nil => []
  | pad M => M.pivots.map (fun (i,j),hij => (i,j.succ),by simp at hij; simp [toMatrix,hij])
  | extend M _ => (0,0),by simp [toMatrix] :: (M.pivots.map (fun (i,j),hij => (i.succ,j.succ),by simp at hij; simp [toMatrix,hij]))

variable {F} in
def RowEchelonForm.zerosAtPivots (R0 : RowEchelonForm F m n) (w : Fin n  F) : Prop := (R0.pivots.all (fun (_,j),_⟩ => w j = 0))

@[instance]
def RowEchelonForm.decidable_zerosAtPivots (R : RowEchelonForm F m n) (w : Fin n  F) : Decidable (R.zerosAtPivots w) :=
  inferInstanceAs (Decidable (R.pivots.all (fun (_,j),_⟩ => w j = 0)))

def RowEchelonForm.isReduced : RowEchelonForm F m n  Prop
  | nil => True
  | pad R0 => R0.isReduced
  | extend R0 w => (R0.zerosAtPivots w)  (R0.isReduced)

def RowReducedEchelonForm (m n : Nat) := {R : RowEchelonForm F m n // R.isReduced}

@[instance]
def RowEchelonForm.decidable_isReduced (R : RowEchelonForm F m n) : Decidable (R.isReduced) :=
  match R with
  | .nil => .isTrue (trivial)
  | .pad R0 => R0.decidable_isReduced
  | .extend R0 v => instDecidableAnd (dq := R0.decidable_isReduced)

variable {F} in
def RowReducedEchelonForm.extend_eltPivotColEntries (R0 : RowReducedEchelonForm F m n) (v : Fin n  F) : {w : Fin n  F // R0.1.zerosAtPivots w} :=
  R0.1.pivots.rec
  (v,by dsimp [RowEchelonForm.zerosAtPivots]; simp; intro a b R h; simp at h)      --error here
  (fun (i,j),_⟩ l iw =>
  let w := (iw + (-(v j))(R0.1.toMatrix i))
  have hw : R0.1.zerosAtPivots w := by sorry
  w,hw)

In this code, in the last function, how do I make Lean acknowledge that R0.1.pivots is taking the value List.nil in the first argument of the recursor?

Giacomo Stevanato (Dec 01 2024 at 12:20):

Vivek Rajesh Joshi said:

how do I make Lean acknowledge that R0.1.pivots is taking the value List.nil in the first argument of the recursor?

If you want this then you can't do induction. Intuitively with induction you're trying to prove something for all lists, so you can't assume that the given list (List.nil in this case) is equal to your list of interest (R0.1.pivots). Or, in other words, you're proving something for your list by proving that it holds for its tail, and that tail's tail, and so on until such tail becomes an empty list; these tails will obviously be different than your original list.

If you want such equality proof then you want to match on R0.1.pivots to distinguish its possible cases. With match you can get a proof of equality using match eq_proof : thing_to_match with ..., which you can then use in your simp. It would look something like this:

  match eh : R0.1.pivots with
  | .nil => v, by dsimp [RowEchelonForm.zerosAtPivots]; simp; intro a b R h; simp[eh] at h
  | .cons (i,j),_⟩ l =>
    let w := (iw + (-(v j))(R0.1.toMatrix i))
    have hw : R0.1.zerosAtPivots w := by sorry
    w,hw

This will of course complain about iw being not defined because since you're not doing induction. That iw didn't really make sense in the first place since it was a proof for goal though.


Last updated: May 02 2025 at 03:31 UTC