Zulip Chat Archive

Stream: maths

Topic: Piecewise linear maps


GENNARO PORPORA (Mar 24 2025 at 21:29):

Hi, im a math student at the university of Salerno (Italy). Im trying to implement piecewise linear maps between simplicial complexes in lean togheter with my logic professor. Neither I nor my supervisor are very experienced with lean. This is the code I have written so far

import Mathlib.Analysis.Convex.Hull
import Mathlib.Analysis.Convex.Combination
import Mathlib.LinearAlgebra.AffineSpace.Independent
import Mathlib.LinearAlgebra.AffineSpace.AffineSubspace.Basic
import Mathlib.Analysis.Convex.SimplicialComplex.Basic
import Mathlib.Data.Real.Basic

open Set Finset
open Geometry
open SimplicialComplex

variable {๐•œ : Type*} [LinearOrderedField ๐•œ]
variable {V: Type*} [AddCommGroup V] [Module ๐•œ V]
variable {W : Type*} [AddCommGroup W] [Module ๐•œ W]


/- piecewise linear map -/
structure PLMap (K: SimplicialComplex ๐•œ V) (L: SimplicialComplex ๐•œ W) where
  toFun : V โ†’ W
  face2face : โˆ€ sk โˆˆ K.faces, โˆƒ sl โˆˆ L.faces, MapsTo toFun sk sl
  isLin : โˆ€ s โˆˆ K.faces, โˆ€ (w: V โ†’ ๐•œ), toFun (โˆ‘ y โˆˆ s, w y โ€ข y) = โˆ‘ y โˆˆ s, w y โ€ข toFun y

namespace PLMap

variable {K : SimplicialComplex ๐•œ V}
variable {L : SimplicialComplex ๐•œ W}
variable {f: PLMap K L}

instance : CoeFun (PLMap K L) (fun g => V โ†’ W) where
  coe g := g.toFun


/- vertices are mapped to vertices -/
theorem v2v: MapsTo f K.vertices L.vertices := by
  intro x xink
  rw [mem_vertices] at xink
  have : โˆƒ sl โˆˆ L.faces, MapsTo f ({x}: Finset V) sl := f.face2face {x} xink
  rcases this with โŸจsl,โŸจslinl,x2slโŸฉโŸฉ
  have xinx : x โˆˆ ({x}: Finset V) := by exact mem_singleton.mpr rfl
  have fxinsl : f x โˆˆ sl := by apply x2sl xinx
  have : โˆƒz โˆˆ sl, f x = z := by
    exact exists_eq_right'.mpr (x2sl xinx)
  rcases this with โŸจz,โŸจzinsl,fxeqzโŸฉโŸฉ
  rw [fxeqz]
  apply mem_vertices.mpr
  apply L.down_closed slinl
  exact Finset.singleton_subset_iff.mpr zinsl
  exact Finset.singleton_ne_empty z


/- the convex hull of a face is mapped to the convex hull of another face -/
lemma hull2hull (sk: Finset V) (hs: sk โˆˆ K.faces): โˆƒsl โˆˆ L.faces,
  MapsTo f (convexHull ๐•œ โ†‘sk) (convexHull ๐•œ โ†‘sl) := by
  rcases f.face2face sk hs with โŸจsl, โŸจslinl,sk2slโŸฉโŸฉ
  use sl; constructor
  exact slinl
  intro x hx
  rw [mem_convexHull'] at hx
  rcases hx with โŸจw,โŸจwnng,sum1,xeqโŸฉโŸฉ
  have fxeq : โˆ‘ y โˆˆ sk, w y โ€ข f y = f x := by
    rw [Eq.comm,<-xeq]
    apply f.isLin sk hs w
  have hullconv : Convex ๐•œ ((convexHull ๐•œ) โ†‘sl : Set W) := by
    apply convex_convexHull
  have fyinsl : โˆ€ y โˆˆ sk, f y โˆˆ (convexHull ๐•œ sl) := by
    intro y yinsk
    have := by apply sk2sl yinsk
    apply subset_convexHull ๐•œ sl
    exact this
    apply Set.mem_range.mpr
    simp
    constructor
    apply subset_convexHull ๐•œ (sl: Set W)
    apply convex_convexHull
  rw [<-fxeq]
  apply Convex.sum_mem hullconv wnng sum1 fyinsl


/- the underlying space of K is mapped to the underlying space of L -/
theorem space2space: MapsTo f K.space L.space := by
  intro x xink
  rcases (mem_space_iff.mp xink) with โŸจsk,โŸจskink,xinskโŸฉโŸฉ
  rcases (f.hull2hull sk skink) with โŸจsl,โŸจslinl,sk2slโŸฉโŸฉ
  have fxinsl := sk2sl xinsk
  have hullinsp := convexHull_subset_space slinl
  exact hullinsp fxinsl


theorem linear_pieces: โˆ€ sk โˆˆ K.faces, โˆƒ (fsk: V โ†’ W), IsLinearMap ๐•œ fsk โˆง
  EqOn f fsk sk := by
  intro sk skink
  sorry

Sorry if my code is not very readable, im not a good at coding :smiling_face_with_tear:
But now im stuck with the last theorem. I want to build a linear map from V to W that coincide with the map f on the convex hull of the face sk of the simplicial complex K. In other words i want to restrict f to (convex hull sk) and then extend the restriction to a linear map V -> W. How can i do this , any idea ? Thak you !!

Ben Eltschig (Mar 26 2025 at 02:45):

This is not an answer to your quesiton, but - are you sure your definition of PLMap actually does what you want it to do? As far as I can see it currently is a map between the ambient spaces, not just the simplicial complexes, and your isLin condition forces it to be linear on every linear linear subspace spanned by one of the faces

Ben Eltschig (Mar 26 2025 at 02:45):

I assume what you actually want is a map that is affine-linear on each of the faces

GENNARO PORPORA (Mar 26 2025 at 05:22):

Thank you for your answer. Initially I defined plmap to be a map from K.space to L.space but I faced a lot of type mismatch problems so I tought well lets define it from V to W and then prove that it maps k.space to L.space. You are right it should be affine linear but the mathlib version of simplicial complex I found actually lives in a Module not in an Affine Space and unless I want to define my own version of simplicial complex (and I dont want xD) I have to adapt the definition somehow.

GENNARO PORPORA (Apr 12 2025 at 19:34):

I changed my strategy, now isLin says that f coincides with a linear map on each face. And everything works but I have a new problem. I want to define a barycentric subdivision of a simplicial complex. I defined Bcenter but when I use it in isSubdive it tells me typeclass problem Module ??? V

import Mathlib.Analysis.Convex.Hull
import Mathlib.Analysis.Convex.Combination
import Mathlib.LinearAlgebra.AffineSpace.Independent
import Mathlib.LinearAlgebra.AffineSpace.AffineSubspace.Basic
import Mathlib.Analysis.Convex.SimplicialComplex.Basic
import Mathlib.Data.Real.Basic

open Set Finset
open Geometry
open SimplicialComplex

variable {๐•œ : Type*} [LinearOrderedField ๐•œ]
variable {V: Type*} [AddCommGroup V] [Module ๐•œ V] [DecidableEq V]
variable {W : Type*} [AddCommGroup W] [Module ๐•œ W]

/- piecewise linear map -/
structure PLMap (K: SimplicialComplex ๐•œ V) (L: SimplicialComplex ๐•œ W) where
  toFun : V โ†’ W
  face2face : โˆ€ sk โˆˆ K.faces, โˆƒ sl โˆˆ L.faces, MapsTo toFun sk sl
  isLin : โˆ€ sk โˆˆ K.faces, โˆƒ (fsk: V โ†’โ‚—[๐•œ] W), IsLinearMap ๐•œ fsk โˆง
          EqOn toFun fsk (convexHull ๐•œ sk)
  -- isLin : โˆ€ s โˆˆ K.faces, โˆ€ (w: V โ†’ ๐•œ), toFun (โˆ‘ y โˆˆ s, w y โ€ข y) = โˆ‘ y โˆˆ s, w y โ€ข toFun y

namespace PLMap

variable {K : SimplicialComplex ๐•œ V}
variable {L : SimplicialComplex ๐•œ W}
variable {f: PLMap K L}

variable (s : Finset V)
variable (v : V โ†’ V)
variable (c : V โ†’ ๐•œ)

variable (f1 f2 : V โ†’ W)
def idV : V โ†’โ‚—[๐•œ] V := LinearMap.id

instance : CoeFun (PLMap K L) (fun g => V โ†’ W) where
  coe g := g.toFun

theorem _linear_map_sum (g:V โ†’โ‚—[๐•œ] W): g (โˆ‘ i โˆˆ s, c i โ€ข v i) = โˆ‘ i โˆˆ s, c i โ€ข g (v i) := by
  induction s using Finset.induction with
  | empty =>
    simp [Finset.sum_empty]
  | insert i ih =>
    simp

theorem _sum_rewrite (h: EqOn f1 f2 s ):
  โˆ‘ a โˆˆ s, c a โ€ข f1 a = โˆ‘ a โˆˆ s, c a โ€ข f2 ((idV : V โ†’โ‚—[๐•œ] V) a) := by
  -- Usa l'induzione su s
  induction s using Finset.induction with
  | empty =>
    -- Caso base: s รจ vuoto
    simp [sum_empty]
  | insert a s' =>
    exact sum_congr rfl fun x a โ†ฆ congrArg (HSMul.hSMul (c x)) (h a)



/- vertices are mapped to vertices -/
theorem v2v: MapsTo f K.vertices L.vertices := by
  intro x xink
  rw [mem_vertices] at xink
  have : โˆƒ sl โˆˆ L.faces, MapsTo f ({x}: Finset V) sl := f.face2face {x} xink
  rcases this with โŸจsl,โŸจslinl,x2slโŸฉโŸฉ
  have xinx : x โˆˆ ({x}: Finset V) := by exact mem_singleton.mpr rfl
  have fxinsl : f x โˆˆ sl := by apply x2sl xinx
  have : โˆƒz โˆˆ sl, f x = z := by
    exact exists_eq_right'.mpr (x2sl xinx)
  rcases this with โŸจz,โŸจzinsl,fxeqzโŸฉโŸฉ
  rw [fxeqz]
  apply mem_vertices.mpr
  apply L.down_closed slinl
  exact Finset.singleton_subset_iff.mpr zinsl
  exact Finset.singleton_ne_empty z


/- the convex hull of a face is mapped to the convex hull of another face -/
lemma hull2hull (sk: Finset V) (hs: sk โˆˆ K.faces): โˆƒsl โˆˆ L.faces,
  MapsTo f (convexHull ๐•œ โ†‘sk) (convexHull ๐•œ โ†‘sl) := by
  rcases f.face2face sk hs with โŸจsl, โŸจslinl,sk2slโŸฉโŸฉ
  use sl; constructor
  exact slinl
  intro x hx
  rw [mem_convexHull'] at hx
  rcases hx with โŸจw,โŸจwnng,sum1,xeqโŸฉโŸฉ
  have := f.isLin sk hs
  rcases this with โŸจfsk,โŸจfsklin,eqonhullโŸฉโŸฉ

  have hullconvsk : Convex ๐•œ ((convexHull ๐•œ) โ†‘sk : Set V) := by
    apply convex_convexHull

  have fxeq : โˆ‘ y โˆˆ sk, w y โ€ข f y = f x := by
    rw [Eq.comm,<-xeq]
    --rcases fsklin with โŸจfskadd,fskmulโŸฉ

    have := _linear_map_sum sk (idV : V โ†’โ‚—[๐•œ] V) w fsk
    have eqonsk : EqOn f fsk sk := by
      intro z zinsk
      apply eqonhull
      exact mem_convexHull_iff.mpr fun t a a_1 โ†ฆ a zinsk
    rw [_sum_rewrite sk w f fsk eqonsk, eqonhull]
    exact this
    apply Convex.sum_mem hullconvsk wnng sum1
    apply subset_convexHull ๐•œ (sk: Set V)

  have hullconv : Convex ๐•œ ((convexHull ๐•œ) โ†‘sl : Set W) := by
    apply convex_convexHull
  have fyinsl : โˆ€ y โˆˆ sk, f y โˆˆ (convexHull ๐•œ sl) := by
    intro y yinsk
    have := by apply sk2sl yinsk
    apply subset_convexHull ๐•œ sl
    exact this
    apply Set.mem_range.mpr
    simp
    constructor
    apply subset_convexHull ๐•œ (sl: Set W)
    apply convex_convexHull
  rw [<-fxeq]
  apply Convex.sum_mem hullconv wnng sum1 fyinsl


/- the underlying space of K is mapped to the underlying space of L -/
theorem space2space: MapsTo f K.space L.space := by
  intro x xink
  rcases (mem_space_iff.mp xink) with โŸจsk,โŸจskink,xinskโŸฉโŸฉ
  rcases (f.hull2hull sk skink) with โŸจsl,โŸจslinl,sk2slโŸฉโŸฉ
  have fxinsl := sk2sl xinsk
  have hullinsp := convexHull_subset_space slinl
  exact hullinsp fxinsl

def Bcenter (s : Finset V) : V :=
  Finset.centerMass s (fun _ => 1 : V โ†’ ๐•œ) id

def isSubdiv (K K' : SimplicialComplex ๐•œ V) : Prop :=
  โˆ€ s โˆˆ K.faces, Bcenter s โˆˆ K'.vertices
```

```

GENNARO PORPORA (Apr 17 2025 at 15:53):

I cant solve a typeclass instance problem in this bit of code (the problem appears in (isPLMap p) in the plmap_iff theorem ). I tried everything
:sob:

-- K' รจ una suddivisione di K
def isSubdiv (K K' : SimplicialComplex ๐•œ V) : Prop :=
  โˆ€ s โˆˆ K.faces, โˆƒ(t: Set (Finset V)),
  (t โІ K'.faces) โˆง (s: Set V) = (โ‹ƒ s' โˆˆ t, s')
-- TODO : se K' e' una suddivisione di K allora K'.space = K.space
-- p รจ una PLMap tra il supporto di K' e il supporto di L' ?
def isPLMap (p:V โ†’ W) : Prop :=
  โˆƒ(K' : SimplicialComplex ๐•œ V), โˆƒ(L' : SimplicialComplex ๐•œ W),
  โˆƒ(f: PLMap K' L'), EqOn p f K'.space
-- p รจ lineare sulle facce di K'
def lin_on_faces (p:V โ†’ W) (K' : SimplicialComplex ๐•œ V) : Prop :=
  โˆ€ s โˆˆ K'.faces, โˆƒ (fs: V โ†’โ‚—[๐•œ] W), EqOn p fs (convexHull ๐•œ s)


theorem plmap_iff (p:V โ†’ W) (sp2sp: MapsTo p K.space L.space):

  (isPLMap p) โ†” โˆƒ(K' : SimplicialComplex ๐•œ V),
  (isSubdiv K K') โˆง (lin_on_faces p K') := by

  sorry

end PLMap
```

```

Ben Eltschig (Apr 17 2025 at 15:54):

Sorry for the late reply - I assume you figured this out by now, but in case you didn't, the error thrown on Bcenter s is lean telling you that Bcenter requives V to be a vector field over some field ๐•œ and can't figure out from the context what that field is. You can fix that by either making ๐•œ an explicit argument of Bcenter and then using it as Bcenter ๐•œ s, or by passing the implicit argument explicitly like in Bcenter (๐•œ := ๐•œ) s. Since this issue likely occurs every time you try to use Bcenter s, I would recommend the former.

Ben Eltschig (Apr 17 2025 at 16:00):

In case you're wondering, the reason that lean can't infer ๐•œ from the Module ๐•œ V instance you have around is that V could very well be a vector space over two different fields; for example, every complex vector space is also a real vector space and so on. It is for this reason that when lean needs an instance like Module ? V and doesn't know yet what ? is, it complains right away instead of looking at the instances you have around and picking the first one it finds.

Ben Eltschig (Apr 17 2025 at 16:01):

(that was meant in reply to your message from 5 days ago, I didn't see the other one until after I replied)

GENNARO PORPORA (Apr 17 2025 at 16:01):

OMG you are my SAVIOR !! In truth I completely eliminated Bcenter from my code, but the same problem occured now with isPLMap. With ( k := k) now works !!


Last updated: May 02 2025 at 03:31 UTC