File: Mathlib/Combinatorics/Configuration.lean

full_name: Configuration.Dual
code: /-- A type synonym. -/
def Dual 
goal: Type u_1

full_name: Configuration.instInhabitedDual
code: instance [h : Inhabited P] : Inhabited (Dual P) 
goal: Inhabited (Configuration.Dual P)

full_name: Configuration.instFiniteDual
code: instance [Finite P] : Finite (Dual P) 
goal: Finite (Configuration.Dual P)

full_name: Configuration.instFintypeDual
code: instance [h : Fintype P] : Fintype (Dual P) 
goal: Fintype (Configuration.Dual P)

full_name: Configuration.instMembershipDual
code: instance : Membership (Dual L) (Dual P) 
goal: Membership (Configuration.Dual L) (Configuration.Dual P)

full_name: Configuration.Nondegenerate.exists_point
code: /-- A configuration is nondegenerate if:
  1) there does not exist a line that passes through all of the points,
  2) there does not exist a point that is on all of the lines,
  3) there is at most one line through any two points,
  4) any two lines have at most one intersection point.
  Conditions 3 and 4 are equivalent. -/
class Nondegenerate : Prop where
  exists_point : ∀ l : L, ∃ p, p ∉ l
  exists_line : ∀ p, ∃ l : L, p ∉ l
  eq_or_eq : ∀ {p₁ p₂ : P} {l₁ l₂ : L}, p₁ ∈ l₁ → p₂ ∈ l₁ → p₁ ∈ l₂ → p₂ ∈ l₂ → p₁ = p₂ ∨ l₁ = l₂
goal: ∃ p, p ∉ l

full_name: Configuration.Nondegenerate
code: /-- A configuration is nondegenerate if:
  1) there does not exist a line that passes through all of the points,
  2) there does not exist a point that is on all of the lines,
  3) there is at most one line through any two points,
  4) any two lines have at most one intersection point.
  Conditions 3 and 4 are equivalent. -/
class Nondegenerate : Prop where
  exists_point : ∀ l : L, ∃ p, p ∉ l
  exists_line : ∀ p, ∃ l : L, p ∉ l
  eq_or_eq : ∀ {p₁ p₂ : P} {l₁ l₂ : L}, p₁ ∈ l₁ → p₂ ∈ l₁ → p₁ ∈ l₂ → p₂ ∈ l₂ → p₁ = p₂ ∨ l₁ = l₂
goal: Prop

full_name: Configuration.Nondegenerate.eq_or_eq
code: /-- A configuration is nondegenerate if:
  1) there does not exist a line that passes through all of the points,
  2) there does not exist a point that is on all of the lines,
  3) there is at most one line through any two points,
  4) any two lines have at most one intersection point.
  Conditions 3 and 4 are equivalent. -/
class Nondegenerate : Prop where
  exists_point : ∀ l : L, ∃ p, p ∉ l
  exists_line : ∀ p, ∃ l : L, p ∉ l
  eq_or_eq : ∀ {p₁ p₂ : P} {l₁ l₂ : L}, p₁ ∈ l₁ → p₂ ∈ l₁ → p₁ ∈ l₂ → p₂ ∈ l₂ → p₁ = p₂ ∨ l₁ = l₂
goal: p₁ ∈ l₁ → p₂ ∈ l₁ → p₁ ∈ l₂ → p₂ ∈ l₂ → p₁ = p₂ ∨ l₁ = l₂

full_name: Configuration.Nondegenerate.exists_line
code: /-- A configuration is nondegenerate if:
  1) there does not exist a line that passes through all of the points,
  2) there does not exist a point that is on all of the lines,
  3) there is at most one line through any two points,
  4) any two lines have at most one intersection point.
  Conditions 3 and 4 are equivalent. -/
class Nondegenerate : Prop where
  exists_point : ∀ l : L, ∃ p, p ∉ l
  exists_line : ∀ p, ∃ l : L, p ∉ l
  eq_or_eq : ∀ {p₁ p₂ : P} {l₁ l₂ : L}, p₁ ∈ l₁ → p₂ ∈ l₁ → p₁ ∈ l₂ → p₂ ∈ l₂ → p₁ = p₂ ∨ l₁ = l₂
goal: ∃ l, p ∉ l

full_name: Configuration.HasPoints
code: /-- A nondegenerate configuration in which every pair of lines has an intersection point. -/
class HasPoints extends Nondegenerate P L where
  mkPoint : ∀ {l₁ l₂ : L}, l₁ ≠ l₂ → P
  mkPoint_ax : ∀ {l₁ l₂ : L} (h : l₁ ≠ l₂), mkPoint h ∈ l₁ ∧ mkPoint h ∈ l₂
goal: Type (max u_1 u_2)

full_name: Configuration.HasPoints.mkPoint_ax
code: /-- A nondegenerate configuration in which every pair of lines has an intersection point. -/
class HasPoints extends Nondegenerate P L where
  mkPoint : ∀ {l₁ l₂ : L}, l₁ ≠ l₂ → P
  mkPoint_ax : ∀ {l₁ l₂ : L} (h : l₁ ≠ l₂), mkPoint h ∈ l₁ ∧ mkPoint h ∈ l₂
goal: Configuration.HasPoints.mkPoint h ∈ l₁ ∧ Configuration.HasPoints.mkPoint h ∈ l₂

full_name: Configuration.HasPoints.mkPoint
code: /-- A nondegenerate configuration in which every pair of lines has an intersection point. -/
class HasPoints extends Nondegenerate P L where
  mkPoint : ∀ {l₁ l₂ : L}, l₁ ≠ l₂ → P
  mkPoint_ax : ∀ {l₁ l₂ : L} (h : l₁ ≠ l₂), mkPoint h ∈ l₁ ∧ mkPoint h ∈ l₂
goal: l₁ ≠ l₂ → P

full_name: Configuration.HasLines.mkLine_ax
code: /-- A nondegenerate configuration in which every pair of points has a line through them. -/
class HasLines extends Nondegenerate P L where
  mkLine : ∀ {p₁ p₂ : P}, p₁ ≠ p₂ → L
  mkLine_ax : ∀ {p₁ p₂ : P} (h : p₁ ≠ p₂), p₁ ∈ mkLine h ∧ p₂ ∈ mkLine h
goal: p₁ ∈ Configuration.HasLines.mkLine h ∧ p₂ ∈ Configuration.HasLines.mkLine h

full_name: Configuration.HasLines
code: /-- A nondegenerate configuration in which every pair of points has a line through them. -/
class HasLines extends Nondegenerate P L where
  mkLine : ∀ {p₁ p₂ : P}, p₁ ≠ p₂ → L
  mkLine_ax : ∀ {p₁ p₂ : P} (h : p₁ ≠ p₂), p₁ ∈ mkLine h ∧ p₂ ∈ mkLine h
goal: Type (max u_1 u_2)

full_name: Configuration.HasLines.mkLine
code: /-- A nondegenerate configuration in which every pair of points has a line through them. -/
class HasLines extends Nondegenerate P L where
  mkLine : ∀ {p₁ p₂ : P}, p₁ ≠ p₂ → L
  mkLine_ax : ∀ {p₁ p₂ : P} (h : p₁ ≠ p₂), p₁ ∈ mkLine h ∧ p₂ ∈ mkLine h
goal: p₁ ≠ p₂ → L

full_name: Configuration.Dual.Nondegenerate
code: instance Dual.Nondegenerate [Nondegenerate P L] : Nondegenerate (Dual L) (Dual P) 
goal: Configuration.Nondegenerate (Configuration.Dual L) (Configuration.Dual P)

full_name: Configuration.Dual.hasLines
code: instance Dual.hasLines [HasPoints P L] : HasLines (Dual L) (Dual P) 
goal: Configuration.HasLines (Configuration.Dual L) (Configuration.Dual P)

full_name: Configuration.Dual.hasPoints
code: instance Dual.hasPoints [HasLines P L] : HasPoints (Dual L) (Dual P) 
goal: Configuration.HasPoints (Configuration.Dual L) (Configuration.Dual P)

full_name: Configuration.HasPoints.existsUnique_point
code: theorem HasPoints.existsUnique_point [HasPoints P L] (l₁ l₂ : L) (hl : l₁ ≠ l₂) :
    ∃! p, p ∈ l₁ ∧ p ∈ l₂ 
goal: ∃! p, p ∈ l₁ ∧ p ∈ l₂

full_name: Configuration.HasLines.existsUnique_line
code: theorem HasLines.existsUnique_line [HasLines P L] (p₁ p₂ : P) (hp : p₁ ≠ p₂) :
    ∃! l : L, p₁ ∈ l ∧ p₂ ∈ l 
goal: ∃! l, p₁ ∈ l ∧ p₂ ∈ l

full_name: Configuration.Nondegenerate.exists_injective_of_card_le
code: /-- If a nondegenerate configuration has at least as many points as lines, then there exists
  an injective function `f` from lines to points, such that `f l` does not lie on `l`. -/
theorem Nondegenerate.exists_injective_of_card_le [Nondegenerate P L] [Fintype P] [Fintype L]
    (h : Fintype.card L ≤ Fintype.card P) : ∃ f : L → P, Function.Injective f ∧ ∀ l, f l ∉ l 
goal: ∃ f, Function.Injective f ∧ ∀ (l : L), f l ∉ l

full_name: Configuration.lineCount
code: /-- Number of points on a given line. -/
noncomputable def lineCount (p : P) : ℕ 
goal: ℕ

full_name: Configuration.pointCount
code: /-- Number of lines through a given point. -/
noncomputable def pointCount (l : L) : ℕ 
goal: ℕ

full_name: Configuration.sum_lineCount_eq_sum_pointCount
code: theorem sum_lineCount_eq_sum_pointCount [Fintype P] [Fintype L] :
    ∑ p : P, lineCount L p = ∑ l : L, pointCount P l 
goal: ∑ p : P, Configuration.lineCount L p = ∑ l : L, Configuration.pointCount P l

full_name: Configuration.HasLines.pointCount_le_lineCount
code: theorem HasLines.pointCount_le_lineCount [HasLines P L] {p : P} {l : L} (h : p ∉ l)
    [Finite { l : L // p ∈ l }] : pointCount P l ≤ lineCount L p 
goal: Configuration.pointCount P l ≤ Configuration.lineCount L p

full_name: Configuration.HasPoints.lineCount_le_pointCount
code: theorem HasPoints.lineCount_le_pointCount [HasPoints P L] {p : P} {l : L} (h : p ∉ l)
    [hf : Finite { p : P // p ∈ l }] : lineCount L p ≤ pointCount P l 
goal: Configuration.lineCount L p ≤ Configuration.pointCount P l

full_name: Configuration.HasLines.card_le
code: /-- If a nondegenerate configuration has a unique line through any two points, then `|P| ≤ |L|`. -/
theorem HasLines.card_le [HasLines P L] [Fintype P] [Fintype L] :
    Fintype.card P ≤ Fintype.card L 
goal: Fintype.card P ≤ Fintype.card L

full_name: Configuration.HasPoints.card_le
code: /-- If a nondegenerate configuration has a unique point on any two lines, then `|L| ≤ |P|`. -/
theorem HasPoints.card_le [HasPoints P L] [Fintype P] [Fintype L] :
    Fintype.card L ≤ Fintype.card P 
goal: Fintype.card L ≤ Fintype.card P

full_name: Configuration.HasLines.exists_bijective_of_card_eq
code: theorem HasLines.exists_bijective_of_card_eq [HasLines P L] [Fintype P] [Fintype L]
    (h : Fintype.card P = Fintype.card L) :
    ∃ f : L → P, Function.Bijective f ∧ ∀ l, pointCount P l = lineCount L (f l) 
goal: ∃ f, Function.Bijective f ∧ ∀ (l : L), Configuration.pointCount P l = Configuration.lineCount L (f l)

full_name: Configuration.HasLines.lineCount_eq_pointCount
code: theorem HasLines.lineCount_eq_pointCount [HasLines P L] [Fintype P] [Fintype L]
    (hPL : Fintype.card P = Fintype.card L) {p : P} {l : L} (hpl : p ∉ l) :
    lineCount L p = pointCount P l 
goal: Configuration.lineCount L p = Configuration.pointCount P l

full_name: Configuration.HasPoints.lineCount_eq_pointCount
code: theorem HasPoints.lineCount_eq_pointCount [HasPoints P L] [Fintype P] [Fintype L]
    (hPL : Fintype.card P = Fintype.card L) {p : P} {l : L} (hpl : p ∉ l) :
    lineCount L p = pointCount P l 
goal: Configuration.lineCount L p = Configuration.pointCount P l

full_name: Configuration.HasLines.hasPoints
code: /-- If a nondegenerate configuration has a unique line through any two points, and if `|P| = |L|`,
  then there is a unique point on any two lines. -/
noncomputable def HasLines.hasPoints [HasLines P L] [Fintype P] [Fintype L]
    (h : Fintype.card P = Fintype.card L) : HasPoints P L 
goal: Configuration.HasPoints P L

full_name: Configuration.HasPoints.hasLines
code: /-- If a nondegenerate configuration has a unique point on any two lines, and if `|P| = |L|`,
  then there is a unique line through any two points. -/
noncomputable def HasPoints.hasLines [HasPoints P L] [Fintype P] [Fintype L]
    (h : Fintype.card P = Fintype.card L) : HasLines P L 
goal: Configuration.HasLines P L

full_name: Configuration.ProjectivePlane.exists_config
code: /-- A projective plane is a nondegenerate configuration in which every pair of lines has
  an intersection point, every pair of points has a line through them,
  and which has three points in general position. -/
class ProjectivePlane extends HasPoints P L, HasLines P L where
  exists_config :
    ∃ (p₁ p₂ p₃ : P) (l₁ l₂ l₃ : L),
      p₁ ∉ l₂ ∧ p₁ ∉ l₃ ∧ p₂ ∉ l₁ ∧ p₂ ∈ l₂ ∧ p₂ ∈ l₃ ∧ p₃ ∉ l₁ ∧ p₃ ∈ l₂ ∧ p₃ ∉ l₃
goal: ∃ p₁ p₂ p₃ l₁ l₂ l₃, p₁ ∉ l₂ ∧ p₁ ∉ l₃ ∧ p₂ ∉ l₁ ∧ p₂ ∈ l₂ ∧ p₂ ∈ l₃ ∧ p₃ ∉ l₁ ∧ p₃ ∈ l₂ ∧ p₃ ∉ l₃

full_name: Configuration.ProjectivePlane
code: /-- A projective plane is a nondegenerate configuration in which every pair of lines has
  an intersection point, every pair of points has a line through them,
  and which has three points in general position. -/
class ProjectivePlane extends HasPoints P L, HasLines P L where
  exists_config :
    ∃ (p₁ p₂ p₃ : P) (l₁ l₂ l₃ : L),
      p₁ ∉ l₂ ∧ p₁ ∉ l₃ ∧ p₂ ∉ l₁ ∧ p₂ ∈ l₂ ∧ p₂ ∈ l₃ ∧ p₃ ∉ l₁ ∧ p₃ ∈ l₂ ∧ p₃ ∉ l₃
goal: Type (max u_1 u_2)

full_name: Configuration.ProjectivePlane.instDual
code: instance : ProjectivePlane (Dual L) (Dual P) 
goal: Configuration.ProjectivePlane (Configuration.Dual L) (Configuration.Dual P)

full_name: Configuration.ProjectivePlane.order
code: /-- The order of a projective plane is one less than the number of lines through an arbitrary point.
Equivalently, it is one less than the number of points on an arbitrary line. -/
noncomputable def order : ℕ 
goal: ℕ

full_name: Configuration.ProjectivePlane.card_points_eq_card_lines
code: theorem card_points_eq_card_lines [Fintype P] [Fintype L] : Fintype.card P = Fintype.card L 
goal: Fintype.card P = Fintype.card L

full_name: Configuration.ProjectivePlane.lineCount_eq_lineCount
code: theorem lineCount_eq_lineCount [Finite P] [Finite L] (p q : P) : lineCount L p = lineCount L q 
goal: Configuration.lineCount L p = Configuration.lineCount L q

full_name: Configuration.ProjectivePlane.pointCount_eq_pointCount
code: theorem pointCount_eq_pointCount [Finite P] [Finite L] (l m : L) :
    pointCount P l = pointCount P m 
goal: Configuration.pointCount P l = Configuration.pointCount P m

full_name: Configuration.ProjectivePlane.lineCount_eq_pointCount
code: theorem lineCount_eq_pointCount [Finite P] [Finite L] (p : P) (l : L) :
    lineCount L p = pointCount P l 
goal: Configuration.lineCount L p = Configuration.pointCount P l

full_name: Configuration.ProjectivePlane.Dual.order
code: theorem Dual.order [Finite P] [Finite L] : order (Dual L) (Dual P) = order P L 
goal: Configuration.ProjectivePlane.order (Configuration.Dual L) (Configuration.Dual P) =
  Configuration.ProjectivePlane.order P L

full_name: Configuration.ProjectivePlane.lineCount_eq
code: theorem lineCount_eq [Finite P] [Finite L] (p : P) : lineCount L p = order P L + 1 
goal: Configuration.lineCount L p = Configuration.ProjectivePlane.order P L + 1

full_name: Configuration.ProjectivePlane.pointCount_eq
code: theorem pointCount_eq [Finite P] [Finite L] (l : L) : pointCount P l = order P L + 1 
goal: Configuration.pointCount P l = Configuration.ProjectivePlane.order P L + 1

full_name: Configuration.ProjectivePlane.one_lt_order
code: theorem one_lt_order [Finite P] [Finite L] : 1 < order P L 
goal: 1 < Configuration.ProjectivePlane.order P L

full_name: Configuration.ProjectivePlane.two_lt_lineCount
code: theorem two_lt_lineCount [Finite P] [Finite L] (p : P) : 2 < lineCount L p 
goal: 2 < Configuration.lineCount L p

full_name: Configuration.ProjectivePlane.two_lt_pointCount
code: theorem two_lt_pointCount [Finite P] [Finite L] (l : L) : 2 < pointCount P l 
goal: 2 < Configuration.pointCount P l

full_name: Configuration.ProjectivePlane.card_points
code: theorem card_points [Fintype P] [Finite L] : Fintype.card P = order P L ^ 2 + order P L + 1 
goal: Fintype.card P = Configuration.ProjectivePlane.order P L ^ 2 + Configuration.ProjectivePlane.order P L + 1

full_name: Configuration.ProjectivePlane.card_lines
code: theorem card_lines [Finite P] [Fintype L] : Fintype.card L = order P L ^ 2 + order P L + 1 
goal: Fintype.card L = Configuration.ProjectivePlane.order P L ^ 2 + Configuration.ProjectivePlane.order P L + 1