Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Polyhedral.lean
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.AffineSubspace.Basic
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.AffineSubspace.Defs
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Defs
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Dimension
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.FiniteDimensional
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Homogenization.Basic
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Homogenization.Set
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Independent
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Lattice
public import Polyhedral.Mathlib.LinearAlgebra.BilinearMap
public import Polyhedral.Mathlib.LinearAlgebra.Dual.Basis
Expand Down
5 changes: 4 additions & 1 deletion Polyhedral/Mathlib/Data/SetLike/IsConcrete.lean
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ variable {A B : Type*} [setLike : SetLike A B] [EmptyCollection A] [IsConcreteEm

@[simp] lemma coe_empty : (∅ : A) = (∅ : Set B) := IsConcreteEmpty.coe_empty'

@[simp, norm_cast]
lemma coe_eq_empty {a : A} : (a : Set B) = ∅ ↔ a = ∅ := by rw [← coe_empty (A := A), coe_set_eq]

@[simp, grind =, push]
theorem mem_empty_iff_false {x : B} : x ∈ (∅ : A) ↔ False := by simp [← mem_coe]

Expand All @@ -124,7 +127,7 @@ include setLike in

include setLike in
@[simp, grind =]
theorem le_empty_iff {a : A} : a ≤ ∅ ↔ a = ∅ := by simp [← coe_set_eq, ← coe_subset_coe]
theorem le_empty_iff {a : A} : a ≤ ∅ ↔ a = ∅ := by simp [← coe_subset_coe]

include setLike in
theorem eq_empty_of_le_empty {a : A} : a ≤ ∅ → a = ∅ := le_empty_iff.1
Expand Down
16 changes: 12 additions & 4 deletions Polyhedral/Mathlib/Geometry/Convex/Cone/Pointed/Rank.lean
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,17 @@ section Semiring
variable [Semiring R] [PartialOrder R] [IsOrderedRing R]
variable [AddCommMonoid M] [Module R M]

noncomputable abbrev rank (C : PointedCone R M) := Module.rank R (span R (C : Set M))
noncomputable def rank (C : PointedCone R M) := Module.rank R (span R (C : Set M))
Comment thread
martinwintermath marked this conversation as resolved.

noncomputable abbrev finrank (C : PointedCone R M) := Module.finrank R (span R (C : Set M))
noncomputable def finrank (C : PointedCone R M) := Module.finrank R (span R (C : Set M))

@[simp] protected lemma rank_bot [Nontrivial R] : (⊥ : PointedCone R M).rank = 0 :=
have : Subsingleton (span R ((⊥ : PointedCone R M) : Set M)) :=
Submodule.subsingleton_iff_eq_bot.mpr (by simp)
rank_subsingleton' _ _

@[simp] protected lemma finrank_bot [Nontrivial R] : (⊥ : PointedCone R M).finrank = 0 :=
Module.finrank_eq_zero_of_rank_eq_zero PointedCone.rank_bot

-- NOTE: this is not the same as Module.Finite or FG!
abbrev FinRank (C : PointedCone R M) := (span R (C : Set M)).FG
Expand Down Expand Up @@ -81,11 +89,11 @@ theorem affineSpan_ne_bot (C : PointedCone R M) : affineSpan R (C : Set M) ≠

theorem dim_affineSpan_eq_rank (C : PointedCone R M) :
(affineSpan R (C : Set M)).dim = C.rank := by
simp [affineSpan_eq_span]
simp [rank, affineSpan_eq_span]

theorem finDim_affineSpan_eq_finrank (C : PointedCone R M) :
(affineSpan R (C : Set M)).finDim = C.finrank := by
simp [affineSpan_eq_span]
simp [finrank, affineSpan_eq_span]

variable [IsDomain R] [Module.IsTorsionFree R M] {C : PointedCone R M}

Expand Down
2 changes: 1 addition & 1 deletion Polyhedral/Mathlib/Geometry/Convex/Cone/Pointed/Ray.lean
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ lemma rank_one_of_ray {x : M} (hx : x ≠ 0) : (hull R {x}).rank = 1 := by
simpa using hr

lemma finrank_one_of_ray {x : M} (hx : x ≠ 0) : (hull R {x}).finrank = 1 := by
simpa [Module.finrank, Cardinal.toNat_eq_one] using rank_one_of_ray hx
simpa [finrank, rank, Module.finrank, Cardinal.toNat_eq_one] using rank_one_of_ray hx

end Ring

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ module

public import Polyhedral.Mathlib.Geometry.Convex.Cone.Pointed.Convexity
public import Polyhedral.Mathlib.Geometry.Convex.Cone.Pointed.Lineal
public import Polyhedral.Mathlib.Geometry.Convex.Cone.Pointed.Rank
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.FiniteDimensional
public import Polyhedral.Mathlib.LinearAlgebra.AffineSpace.Homogenization.Basic

import Polyhedral.Mathlib.Geometry.Convex.ConvexSpace.Set.Lattice
Expand Down Expand Up @@ -120,7 +122,7 @@ lemma dehomogenize_bot : dehomogenize A (⊥ : PointedCone R W) = ⊥ := by
@[simp]
lemma dehomogenize_top : dehomogenize A (⊤ : PointedCone R W) = ⊤ := by
ext
simp [dehomogenize, SetLike.mem_coe.mp]
simp [dehomogenize, ← SetLike.mem_coe]

@[simp]
lemma dehomogenize_weight_positive : dehomogenize A hom.weight.positive = ⊤ :=
Expand Down Expand Up @@ -173,6 +175,35 @@ lemma homogenize_top : homogenize W (⊤ : ConvexSet R A) = hom.weight.positive
congr! with x
simp

variable (W) in
theorem finrank_homogenize
(K : ConvexSet R A) [Module.Finite R (vectorSpan R (K : Set A))] :
(homogenize W K).finrank = Order.succ (affineSpan R (K : Set A)).finDim := by
by_cases hK : K = ∅
· simp [hK, ← SetLike.bot_eq_empty]
obtain ⟨t, -, ht₂, ht₃, ht₄⟩ := exists_affineIndepOn_of_finiteDimensional R V (K : Set A)
rw [← WithBot.succ_eq_succ, ← ht₄, ← finDim_affineSpan_eq_finrank, homogenize,
AffineSubspace.finDim_eq_finrank (PointedCone.affineSpan_ne_bot _),
affineSpan_hull, ← affineSpan_insert_zero',
affineSpan_insert_congr R 0 (t := hom.ofPoint '' t) (by simp [← AffineSubspace.map_span, ht₂])]
have ht : t.Finite := by
have : affineSpan R (K : Set A) ≠ ⊥ := by simpa
exact Set.finite_of_ncard_pos <| by
simp [AffineSubspace.finDim_eq_finrank this, ht₄, WithBot.succ_natCast]
have hai : AffineIndepOn R id (insert 0 (hom.ofPoint '' t)) := by
refine (ht₃.map' _ hom.ofPoint_injective).id_image.insert ?_
simp [← AffineSubspace.map_span, hom.ofPoint_ne_zero]
rw [direction_affineSpan, hai.finrank_vectorSpan (by simp [ht.image _]) (by simp),
Set.ncard_insert_of_notMem (by simp [hom.ofPoint_ne_zero]) (ht.image _),
Set.ncard_image_of_injective t hom.ofPoint_injective]
norm_cast

variable (W) in
theorem finDim_affineSpan_eq_pred_finrank_homogenize
(K : ConvexSet R A) [Module.Finite R (vectorSpan R (K : Set A))] :
(affineSpan R (K : Set A)).finDim = Order.pred ((homogenize W K).finrank : WithBot ℕ) := by
simp [finrank_homogenize]

variable [ConvexSpace R W] [IsAffineConvexSpace R V A] [IsModuleConvexSpace R W]

lemma smul_pos_of_mem_homogenize {P : ConvexSet R A} {x} (h : x ∈ homogenize W P) (hx : x ≠ 0) :
Expand Down
10 changes: 10 additions & 0 deletions Polyhedral/Mathlib/LinearAlgebra/AffineSpace/Defs.lean
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ variable {A : Type*} [AddTorsor V A]

lemma spanPoints_empty : spanPoints R (∅ : Set A) = ∅ := by simp [spanPoints]

theorem _root_.affineSpan_insert_congr {s t : Set A} (x : A)
(h : affineSpan R s = affineSpan R t) :
affineSpan R (insert x s) = affineSpan R (insert x t) := by
rw [← affineSpan_insert_affineSpan, h, affineSpan_insert_affineSpan]

theorem _root_.vectorSpan_insert_congr {s t : Set A} (x : A)
(h : affineSpan R s = affineSpan R t) :
vectorSpan R (insert x s) = vectorSpan R (insert x t) := by
rw [← direction_affineSpan, affineSpan_insert_congr R x h, direction_affineSpan]

@[gcongr]
lemma spanPoints_mono {F G : Set A} (hFG : G ⊆ F) : spanPoints R G ⊆ spanPoints R F :=
fun _p ⟨p₁, hp₁, v, hv, hp⟩ =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/-

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file and the one below are leanprover-community/mathlib4#43910

Copyright (c) 2026 Vlad Tsyrklevich. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Vlad Tsyrklevich
-/
module

public import Mathlib.LinearAlgebra.AffineSpace.Dimension
public import Mathlib.LinearAlgebra.AffineSpace.FiniteDimensional

/-! Finite-dimensional affine space lemmas -/

@[expose] public section

open Affine

section AffineSpace'

variable (k : Type*) {V : Type*} {P : Type*}

open AffineSubspace Module

variable [DivisionRing k] [AddCommGroup V] [Module k V] [AffineSpace V P]

variable {k}

theorem AffineIndepOn.ncard_eq_succ_finDim_affineSpan {s : Set P} (hai : AffineIndepOn k id s)
[hf : FiniteDimensional k (vectorSpan k s)] : s.ncard = (affineSpan k s).finDim.succ := by

@martinwintermath martinwintermath Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should first define FiniteDimensional on affine spaces directly. Going via the vector span is a hack.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bigger mathlib refactor than just this change, as it stands this is the canonical way to spell it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it just defining an affine version of FiniteDimensional in the same way as you just defined range for AffineMap by copying LinearMap.range?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it depends, do you expect this to be a def or an abbrev? Either way, the difference is that this file upstream already uses this pattern, as do others, so it would make more sense to do a targetted refactor rather then try to fix it here.

@martinwintermath martinwintermath Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I am not happy that it got to mathlib in this form. To some degree I am okay with leaving it with the hack here if we are really sure we get rid of it sometime soon (we should add plenty comments to highlight that this is temporary). On the other hand, looking into your other PR, this seems to have further implications for how we write lemmas, and we should not let this get out of hand.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this force us to require that the ambient space is finite dimensional rather than just the subspace we are looking at?

@martinwintermath martinwintermath Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use it, yes. You don't have to use it :P You should use a "the set is finite dim" variant. This is the distinction between Module.Finite and PointedCone.FinRank.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the (draft) PR contains Affine.FinDim for sets. What are your thoughts. Will this work? Codex actually implemented some of your lemmas to demonstrate that it works :D

@vlad902 vlad902 Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The definition seems fine, it's an abbrev which I think is good. There's a lot of unnecessary copy-and-paste slop that is hard to wade through. I'm not sure why the use of this typeclass was changed from a typeclass parameter to an explicit hypothesis and another thing I find odd is that AffineSubspace.FinDim is defined using AffineSubspace.direction but Affine.FinDim is defined using vectorSpan, maybe it should be defined using FinDim (affineSpan R s).direction instead to match?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are good points. Let's continue discussing over there.

rcases Set.eq_empty_or_nonempty s with rfl | hs
· simp
rw [← Subtype.range_coe (s := s)] at hf
have := finiteDimensional_iff_setFinite k hai |>.mp hf
have := hai.finrank_vectorSpan this hs
rw [finDim_eq_finrank (by simp [Set.nonempty_iff_ne_empty.mp hs]), direction_affineSpan,
WithBot.succ_natCast, this]
grind only [Set.ncard_eq_zero, Set.not_nonempty_empty]

theorem AffineIndependent.ncard_eq_succ_finDim_affineSpan {s : Set P}
(hai : AffineIndependent k ((↑) : s → P)) [hf : FiniteDimensional k (vectorSpan k s)] :
s.ncard = (affineSpan k s).finDim.succ :=
AffineIndepOn.ncard_eq_succ_finDim_affineSpan ((affineIndependent_subtype_iff _).mp hai)

variable (k)

variable (V) in
theorem exists_affineIndependent_of_finiteDimensional (s : Set P)
[F : FiniteDimensional k (vectorSpan k s)] :
∃ t ⊆ s, affineSpan k t = affineSpan k s ∧ AffineIndependent k ((↑) : t → P) ∧
t.ncard = (affineSpan k s).finDim.succ := by
obtain ⟨t, ht₁, ht₂, ht₃⟩ := exists_affineIndependent k V s
refine ⟨t, ht₁, ht₂, ht₃, ?_⟩
rw [← direction_affineSpan, ← ht₂, direction_affineSpan] at F
exact ht₂ ▸ ht₃.ncard_eq_succ_finDim_affineSpan

variable (V) in
theorem exists_affineIndepOn_of_finiteDimensional (s : Set P)
[F : FiniteDimensional k (vectorSpan k s)] :
∃ t ⊆ s, affineSpan k t = affineSpan k s ∧ AffineIndepOn k id t ∧
t.ncard = (affineSpan k s).finDim.succ :=
exists_affineIndependent_of_finiteDimensional k V s

end AffineSpace'
25 changes: 25 additions & 0 deletions Polyhedral/Mathlib/LinearAlgebra/AffineSpace/Independent.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/-
Copyright (c) 2026 Vlad Tsyrklevich. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Vlad Tsyrklevich
-/
module

public import Mathlib.LinearAlgebra.AffineSpace.Independent

/-! Affine independence lemmas -/

@[expose] public section

open Affine

section DivisionRing

variable (k : Type*) (V : Type*) {P : Type*} [DivisionRing k] [AddCommGroup V] [Module k V]
variable [AffineSpace V P]

theorem exists_affineIndepOn (s : Set P) :
∃ t ⊆ s, affineSpan k t = affineSpan k s ∧ AffineIndepOn k id t :=
exists_affineIndependent k V s

end DivisionRing
Loading