Zulip Chat Archive

Stream: mathlib4

Topic: !4#4473 Proving that Gram–Schmidt terminates


Jeremy Tan (May 29 2023 at 16:17):

The following recursive definition of the Gram–Schmidt process doesn't work in Lean 4; how can I get it to work?

import Mathlib.Analysis.InnerProductSpace.PiL2
import Mathlib.LinearAlgebra.Matrix.Block

open scoped BigOperators

open Finset Submodule FiniteDimensional

variable (𝕜 : Type _) {E : Type _} [IsROrC 𝕜] [NormedAddCommGroup E] [InnerProductSpace 𝕜 E]

variable {ι : Type _} [LinearOrder ι] [LocallyFiniteOrderBot ι] [IsWellOrder ι (· < ·)]

attribute [local instance] IsWellOrder.toHasWellFounded

local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y

noncomputable def gramSchmidt (f : ι  E) : ι  E
  | n => f n -  i : Iio n, orthogonalProjection (𝕜  gramSchmidt f i) (f n)
  termination_by gramSchmidt f n => n
  decreasing_by exact mem_Iio.1 i.2

Mario Carneiro (May 29 2023 at 16:18):

try have : i < n := ... inside the sigma

Jeremy Tan (May 29 2023 at 16:21):

As it is I get a huge number of identical copies of the error

type mismatch
  Iff.mp mem_Iio i.property
has type
  i < n : Prop
but is expected to have type
  (invImage (fun a  a) instWellFoundedRelation).1 (i) a : Prop

With

noncomputable def gramSchmidt (f : ι  E) : ι  E
  | n => f n -  i : Iio n,
    have : i < n := by exact mem_Iio.1 i.2
    orthogonalProjection (𝕜  gramSchmidt f i) (f n)
  termination_by gramSchmidt f n => n

I'm instead getting this error on gramSchmidt f i:

failed to prove termination, possible solutions:
  - Use `have`-expressions to prove the remaining goals
  - Use `termination_by` to specify a different well-founded relation
  - Use `decreasing_by` to specify your own tactic for discharging this kind of goal
ι: Type u_3
inst✝¹: LinearOrder ι
inst: LocallyFiniteOrderBot ι
a: ι
n: ι := a
i: { x // x  Iio n }
this: i < n
 False

And I believe that my termination_by is correct since n is of the well-founded type ι

Mario Carneiro (May 29 2023 at 16:22):

oh, I just noticed that you are doing well founded recursion on a weird type

Mario Carneiro (May 29 2023 at 16:23):

It needs to be something with a WellFoundedRelation instance, not sure if IsWellOrder implies that

Jeremy Tan (May 29 2023 at 16:27):

Ultimately all of this is from !4#4473. I can see that the induction is on n : ι; given that I have [LinearOrder ι] [LocallyFiniteOrderBot ι] [IsWellOrder ι (· < ·)] how can I get a proper WellFoundedRelation from this, and state termination_by correctly?

Mario Carneiro (May 29 2023 at 16:51):

Note that in the (invImage (fun a ↦ a) instWellFoundedRelation).1 (↑i) a✝ : Prop error message, if you dig down into instWellFoundedRelation you will notice that it uses instSizeOf, i.e. the default well order on any type which comes from the default sizeof which makes everything 0, which is the empty relation

Mario Carneiro (May 29 2023 at 16:53):

oh, and using termination_by' IsWellOrder.toHasWellFounded fails because of

failed to synthesize instance
  IsWellOrder ι fun x x_1  x < x_1

...which is true, the well order instance is not in the context

Mario Carneiro (May 29 2023 at 16:58):

this is really interesting. The following works:

variable {ι : Type _} [LinearOrder ι] [LocallyFiniteOrderBot ι] [inst : IsWellOrder ι (· < ·)]

attribute [local instance] IsWellOrder.toHasWellFounded

noncomputable def gramSchmidt (f : ι  E) (n : ι) : E :=
  have := inst
  f n -  i : Iio n, have : i < n := sorry; orthogonalProjection (𝕜  gramSchmidt f i) (f n)
termination_by _ n => n

but

noncomputable def gramSchmidt (f : ι  E) (n : ι) : E :=
  f n -  i : Iio n, have : i < n := sorry; orthogonalProjection (𝕜  gramSchmidt f i) (f n)
termination_by _ n =>
  have := inst
  n

gives unknown identifier 'inst' at the have := inst line. Apparently, the full set of variables is available in the body of the definition, but once it is processed anything which was not referenced is not included in the context for the termination_by and other clauses

Jeremy Tan (May 29 2023 at 17:08):

Mario Carneiro said:

The following works:

variable {ι : Type _} [LinearOrder ι] [LocallyFiniteOrderBot ι] [inst : IsWellOrder ι (· < ·)]

attribute [local instance] IsWellOrder.toHasWellFounded

noncomputable def gramSchmidt (f : ι  E) (n : ι) : E :=
  have := inst
  f n -  i : Iio n, have : i < n := sorry; orthogonalProjection (𝕜  gramSchmidt f i) (f n)
termination_by _ n => n

no it still gives unknown identifier 'inst' at the have := inst line

Mario Carneiro (May 29 2023 at 17:10):

note the modification to the variable line

Jeremy Tan (May 29 2023 at 17:10):

oh

Mario Carneiro (May 29 2023 at 17:12):

(this is the sort of situation where one wishes for the include command)

Mario Carneiro (May 29 2023 at 17:12):

another alternative is to put the [IsWellOrder ι (· < ·)] argument on the definition itself instead of in a variable

Mario Carneiro (May 29 2023 at 17:14):

i.e.

noncomputable def gramSchmidt [IsWellOrder ι (· < ·)] (f : ι  E) (n : ι) : E :=
  f n -  i : Iio n, orthogonalProjection (𝕜  gramSchmidt f i) (f n)
termination_by _ n => n
decreasing_by exact mem_Iio.1 i.2

Jeremy Tan (May 29 2023 at 17:23):

OK, that works; I've just pushed it

Jeremy Tan (May 29 2023 at 18:53):

The next error I can't seem to fix is at gramSchmidtOrthonormalBasis:

noncomputable def gramSchmidtOrthonormalBasis : OrthonormalBasis ι 𝕜 E :=
  ((gramSchmidt_orthonormal' f).exists_orthonormalBasis_extension_of_card_eq h).some

the error being

application type mismatch
  Orthonormal.exists_orthonormalBasis_extension_of_card_eq h (gramSchmidt_orthonormal' f)
argument
  gramSchmidt_orthonormal' f
has type
  Orthonormal 𝕜 fun i  gramSchmidtNormed 𝕜 f i : Prop
but is expected to have type
  Orthonormal 𝕜 (restrict { i | gramSchmidtNormed 𝕜 f i  0 } ?m.424507) : Prop

In mathlib3 the restrict was applied automatically

Jeremy Tan (May 29 2023 at 18:53):

how to fix this?

Jeremy Tan (May 29 2023 at 20:00):

Anyone?


Last updated: Dec 20 2023 at 11:08 UTC