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 !!

GENNARO PORPORA (May 10 2025 at 15:00):

Hi, I have this bit of code

  intro exKp
  rcases exKp with ⟨Kp,eqspace⟩
  have plts := {plt | βˆƒface ∈ Kp.faces, plt = convexHull π•œ (face: Set V)}
  use plts
  constructor
  intro plt hplt

From the hypoteses hplt: plt in plts I want to recover the condition exists face in Kp ... defining the set plts. How I do this ?

Matteo Cipollina (May 10 2025 at 15:30):

is this what you are looking for? Switched fromΒ haveΒ toΒ letΒ for the set definition, which allowedΒ simpΒ to correctly unpack the hypothesis.

import Mathlib.Analysis.Convex.Hull
import Mathlib.Analysis.Convex.SimplicialComplex.Basic
import Mathlib.Data.Set.Basic

variable {π•œ : Type*} [Field π•œ] [LinearOrder π•œ]
open Set Finset
open Geometry
open SimplicialComplex

variable {V: Type*} [AddCommGroup V] [Module π•œ V] [DecidableEq V]

variable (K Kp : SimplicialComplex π•œ V)

example : βˆƒ (plts : Set (Set V)), (βˆ€ plt ∈ plts, βˆƒ face ∈ Kp.faces, plt = convexHull π•œ (face : Set V)) ∧ True := by
  let plts_def : Set (Set V) := {plt_inner | βˆƒ face ∈ Kp.faces, plt_inner = convexHull π•œ (face : Set V)}
  use plts_def
  constructor
  Β· intro plt hplt
    have property_of_plt : (βˆƒ face ∈ Kp.faces, plt = convexHull π•œ (face : Set V)) := by
      revert hplt
      simp [plts_def]
    rcases property_of_plt with ⟨face, ⟨h_face_in_Kp_faces, h_plt_eq_hull⟩⟩
    exact ⟨face, h_face_in_Kp_faces, h_plt_eq_hull⟩
  Β· trivial

GENNARO PORPORA (May 10 2025 at 15:40):

Thank you so much ! I will try and let you know if it works !

GENNARO PORPORA (Jun 02 2025 at 11:00):

Ok that worked great, now i'm stuck on this

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

structure Polytope where
  vertices : Finset V
  carrier : Set V := (convexHull π•œ vertices)

structure isPolytope (s: Set V): Prop where
  exFinset : βˆƒ(t:Finset V), s = convexHull π•œ t

structure Polyhedron where
  polytopes : Finset (Set V)
  arePoly : Prop := βˆ€ s ∈ polytopes, (isPolytope (π•œ:=π•œ) s)
  carrier : Set V := ⋃ s ∈ polytopes, s

structure isPolyhedron (plh: Set V): Prop where
  exPoly : βˆƒ(plts: Finset (Set V)), (βˆ€ s ∈ plts, isPolytope (π•œ:=π•œ) s) ∧
           (plh = ⋃ s ∈ plts, s)

structure Triangulation (P: Polyhedron (π•œ:=π•œ) (V:=V)) where
  complex: SimplicialComplex π•œ V
  eqSpace: P.carrier = complex.space

lemma inter_politopes (plt1 plt2: Polytope (π•œ:=π•œ)):
      isPolytope (π•œ:=π•œ) (V:=V) (plt1.carrier ∩ plt2.carrier) := by
  sorry

def baryCenter (P: Polytope (π•œ:=π•œ) (V:=V)) :=
    (βˆ‘v ∈ P.vertices, (1:π•œ))⁻¹ β€’ (βˆ‘v ∈ P.vertices, v)

def indipSubsets (s: Finset V): Set (Finset V) :=
    {t βŠ† s | AffineIndependent π•œ ((↑) : t β†’ V)}

def stellar_div (P: Polytope (π•œ:=π•œ) (V:=V)) : SimplicialComplex π•œ V where
    faces := (indipSubsets (P.vertices βˆͺ {(baryCenter P)}))\{βˆ…}
    not_empty_mem h := h.2 (mem_singleton _)
    indep := by
      intro s hs
      simp at hs
      have := hs.left
      simp [indipSubsets] at this
      exact this.right
    down_closed := by
      intro s t
      intro hs tins tneo
      simp [indipSubsets] at hs
      simp [indipSubsets]
      rcases hs with ⟨⟨hs1,hs2⟩,hs3⟩
      constructor; constructor
      exact fun ⦃a⦄ a_1 ↦ hs1 (tins a_1)

I need to prove that t is an Affine indipendent set of point knowing that s is so and (tins: t subset s)

GENNARO PORPORA (Jun 02 2025 at 11:03):

I forgot to mention that Im trying to prove that the barycentric (or stellar) subdivision of a n-polytope is Simplicial Complex

Aaron Liu (Jun 02 2025 at 11:13):

Try docs#AffineIndependent.comp_embedding

GENNARO PORPORA (Jun 02 2025 at 18:07):

Aaron Liu ha scritto:

Try docs#AffineIndependent.comp_embedding

thank you ! :smile: In the end I solved with
AffineIndependent.mono hs2 tins


Last updated: Dec 20 2025 at 21:32 UTC