import Lean.Elab.Term set_option warn.classDefReducibility false /-! # Turán's theorem -/ set_option warn.sorry false section Mathlib.Tactic.TypeStar open Lean elab "Sort*" : term => do let u ← Lean.Meta.mkFreshLevelMVar Elab.Term.levelMVarToParam (.sort u) elab "Type*" : term => do let u ← Lean.Meta.mkFreshLevelMVar Elab.Term.levelMVarToParam (.sort (.succ u)) end Mathlib.Tactic.TypeStar section Mathlib.Data.Set.Defs universe u variable {α : Type u} /-- A set is a collection of elements of some type `α`. Although `Set` is defined as `α → Prop`, this is an implementation detail which should not be relied on. Instead, `setOf` and membership of a set (`∈`) should be used to convert between sets and predicates. -/ def Set (α : Type u) := α → Prop /-- Turn a predicate `p : α → Prop` into a set, also written as `{x | p x}` -/ def setOf {α : Type u} (p : α → Prop) : Set α := p namespace Set /-- Membership in a set -/ protected def Mem (s : Set α) (a : α) : Prop := s a instance : Membership α (Set α) := ⟨Set.Mem⟩ end Set end Mathlib.Data.Set.Defs section Mathlib.Order.Defs.Unbundled variable {α : Sort*} (r : α → α → Prop) /-- `IsSymm` as a definition, suitable for use in proofs. -/ def Symmetric := ∀ ⦃x y⦄, r x y → r y x end Mathlib.Order.Defs.Unbundled section Mathlib.Data.List.Defs namespace List variable {α : Type*} section Choose variable (p : α → Prop) [DecidablePred p] (l : List α) /-- Given a decidable predicate `p` and a proof of existence of `a ∈ l` such that `p a`, choose the first element with this property. This version returns both `a` and proofs of `a ∈ l` and `p a`. -/ def chooseX : ∀ l : List α, ∀ _ : ∃ a, a ∈ l ∧ p a, { a // a ∈ l ∧ p a } | [], hp => False.elim (Exists.elim hp fun _ h => not_mem_nil h.left) | l :: ls, hp => if pl : p l then ⟨l, ⟨mem_cons.mpr <| Or.inl rfl, pl⟩⟩ else -- pattern matching on `hx` too makes this not reducible! let ⟨a, ha⟩ := chooseX ls (hp.imp fun _ ⟨o, h₂⟩ => ⟨(mem_cons.mp o).resolve_left fun e => pl <| e ▸ h₂, h₂⟩) ⟨a, mem_cons.mpr <| Or.inr ha.1, ha.2⟩ end Choose end List end Mathlib.Data.List.Defs section Mathlib.Data.Set.CoeSort namespace Set universe u v w variable {α : Type u} {β : Type v} {γ : Type w} /-- Given the set `s`, `Elem s` is the `Type` of element of `s`. It is currently an abbreviation so that instance coming from `Subtype` are available. If you're interested in making it a `def`, as it probably should be, you'll then need to create additional instances (and possibly prove lemmas about them). See e.g. `Mathlib/Data/Set/Order.lean`. -/ @[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s} /-- Coercion from a set to the corresponding subtype. -/ instance : CoeSort (Set α) (Type u) := ⟨Elem⟩ end Set end Mathlib.Data.Set.CoeSort section Mathlib.Data.Multiset.Defs universe v open List Subtype Nat Function variable {α : Type*} {β : Type v} {γ : Type*} /-- `Multiset α` is the quotient of `List α` by list permutation. The result is a type of finite sets with duplicates allowed. -/ def Multiset.{u} (α : Type u) : Type u := Quotient (List.isSetoid α) namespace Multiset /-- The quotient map from `List α` to `Multiset α`. -/ def ofList : List α → Multiset α := Quot.mk _ section Mem /-- `a ∈ s` means that `a` has nonzero multiplicity in `s`. -/ def Mem (s : Multiset α) (a : α) : Prop := Quot.liftOn s (fun l => a ∈ l) fun l₁ l₂ (e : l₁ ~ l₂) => propext <| e.mem_iff instance : Membership α (Multiset α) := ⟨Mem⟩ instance decidableMem [DecidableEq α] (a : α) (s : Multiset α) : Decidable (a ∈ s) := Quot.recOnSubsingleton s fun l ↦ inferInstanceAs (Decidable (a ∈ l)) end Mem /-- The cardinality of a multiset is the sum of the multiplicities of all its elements, or simply the length of the underlying list. -/ def card : Multiset α → Nat := Quot.lift length sorry /-- Lift of the list `pmap` operation. Map a partial function `f` over a multiset `s` whose elements are all in the domain of `f`. -/ nonrec def pmap {p : α → Prop} (f : ∀ a, p a → β) (s : Multiset α) : (∀ a ∈ s, p a) → Multiset β := Quot.recOn s (fun l H => ofList (pmap f l H)) sorry end Multiset end Mathlib.Data.Multiset.Defs section Mathlib.Data.Multiset.ZeroCons universe v open List Subtype Nat Function variable {α : Type*} {β : Type v} {γ : Type*} namespace Multiset /-- `0 : Multiset α` is the empty set -/ protected def zero : Multiset α := ofList (@nil α) instance : Zero (Multiset α) := ⟨Multiset.zero⟩ end Multiset end Mathlib.Data.Multiset.ZeroCons section Mathlib.Data.Multiset.Basic universe v open List Subtype Nat Function variable {α : Type*} {β : Type v} {γ : Type*} namespace Multiset section Choose variable (p : α → Prop) [DecidablePred p] (l : Multiset α) /-- Given a proof `hp` that there exists a unique `a ∈ l` such that `p a`, `chooseX p l hp` returns that `a` together with proofs of `a ∈ l` and `p a`. -/ def chooseX : ∀ _hp : ∃ a, a ∈ l ∧ p a, { a // a ∈ l ∧ p a } := Quotient.recOn l (fun l' h => List.chooseX p l' h) sorry end Choose end Multiset end Mathlib.Data.Multiset.Basic section Mathlib.Data.Multiset.MapFold variable {α β : Type*} namespace Multiset /-- `map f s` is the lift of the list `map` operation. The multiplicity of `b` in `map f s` is the number of `a ∈ s` (counting multiplicity) such that `f a = b`. -/ def map (f : α → β) (s : Multiset α) : Multiset β := Quot.liftOn s (fun l : List α => ofList <| l.map f) sorry end Multiset end Mathlib.Data.Multiset.MapFold section Mathlib.Data.Multiset.Filter variable {α : Type*} namespace Multiset variable (p : α → Prop) [DecidablePred p] /-- `Filter p s` returns the elements in `s` (with the same multiplicities) which satisfy `p`, and removes the rest. -/ def filter (s : Multiset α) : Multiset α := Quot.liftOn s (fun l => ofList <| List.filter p l) sorry end Multiset end Mathlib.Data.Multiset.Filter section Mathlib.Data.Finset.Defs universe u variable {α : Type*} {β : Type*} {γ : Type*} /-- `Finset α` is the type of finite sets of elements of `α`. It is implemented as a multiset (a list up to permutation) which has no duplicate elements. -/ structure Finset (α : Type*) where /-- The underlying multiset -/ val : Multiset α namespace Finset theorem val_inj {s t : Finset α} : s.1 = t.1 ↔ s = t := sorry instance : Membership α (Finset α) := ⟨fun s a => a ∈ s.1⟩ instance decidableMem [_h : DecidableEq α] (a : α) (s : Finset α) : Decidable (a ∈ s) := Multiset.decidableMem _ _ end Finset end Mathlib.Data.Finset.Defs section Mathlib.Data.Finset.Dedup universe u variable {α : Type*} {β : Type*} {γ : Type*} namespace Finset end Finset /-! ### dedup on list and multiset -/ namespace Multiset variable [DecidableEq α] {s t : Multiset α} /-- `toFinset s` removes duplicates from the multiset `s` to produce a finset. -/ def toFinset (s : Multiset α) : Finset α := ⟨s⟩ end Multiset end Mathlib.Data.Finset.Dedup section Mathlib.Data.Finset.Empty universe u variable {α : Type*} {β : Type*} {γ : Type*} namespace Finset section Empty variable {s : Finset α} /-- The empty finset -/ protected def empty : Finset α := ⟨0⟩ end Empty end Finset end Mathlib.Data.Finset.Empty section Mathlib.Data.Finset.Filter variable {α : Type*} namespace Finset section Filter variable (p : α → Prop) [DecidablePred p] /-- `Finset.filter p s` is the set of elements of `s` that satisfy `p`. For example, one can use `s.filter (· ∈ t)` to get the intersection of `s` with `t : Set α` as a `Finset α` (when a `DecidablePred (· ∈ t)` instance is available). -/ def filter (s : Finset α) : Finset α := ⟨s.1.filter p⟩ end Finset.Filter end Mathlib.Data.Finset.Filter section Mathlib.Data.Finset.Basic variable {α : Type*} namespace Finset section Choose variable (p : α → Prop) [DecidablePred p] (l : Finset α) /-- Given a finset `l` and a predicate `p`, associate to a proof that there is a unique element of `l` satisfying `p` this unique element, as an element of the corresponding subtype. -/ def chooseX (hp : ∃ a, a ∈ l ∧ p a) : { a // a ∈ l ∧ p a } := Multiset.chooseX p l.val hp /-- Given a finset `l` and a predicate `p`, associate to a proof that there is a unique element of `l` satisfying `p` this unique element, as an element of the ambient type. -/ def choose (hp : ∃ a, a ∈ l ∧ p a) : α := chooseX p l hp end Choose end Finset end Mathlib.Data.Finset.Basic section Mathlib.Data.Finset.Image variable {α β γ : Type*} namespace Finset section Map /-- When `f` is an embedding of `α` in `β` and `s` is a finset in `α`, then `s.map f` is the image finset in `β`. The embedding condition guarantees that there are no duplicates in the image. -/ def map (f : α → β) (s : Finset α) : Finset β := ⟨s.1.map f⟩ end Map section Image variable [DecidableEq β] /-- `image f s` is the forward image of `s` under `f`. -/ def image (f : α → β) (s : Finset α) : Finset β := (s.1.map f).toFinset end Image end Finset end Mathlib.Data.Finset.Image section Mathlib.Data.Finset.Card variable {α β R : Type*} namespace Finset variable {s t : Finset α} {a b : α} /-- `s.card` is the number of elements of `s`, aka its cardinality. The notation `#s` can be accessed in the `Finset` locale. -/ def card (s : Finset α) : Nat := Multiset.card s.1 end Finset end Mathlib.Data.Finset.Card section Mathlib.Data.Fintype.Defs variable {α β γ : Type*} /-- `Fintype α` means that `α` is finite, i.e. there are only finitely many distinct elements of type `α`. The evidence of this is a finset `elems` (a list up to permutation without duplicates), together with a proof that everything of type `α` is in the list. -/ class Fintype (α : Type*) where /-- The `Finset` containing all elements of a `Fintype` -/ elems : Finset α namespace Finset variable [Fintype α] {s t : Finset α} /-- `univ` is the universal finite set of type `Finset α` implied from the assumption `Fintype α`. -/ def univ : Finset α := @Fintype.elems α _ end Finset namespace Fintype /-- Given a predicate that can be represented by a finset, the subtype associated to the predicate is a fintype. -/ protected def subtype {p : α → Prop} (s : Finset α) (H : ∀ x : α, x ∈ s ↔ p x) : Fintype { x // p x } := ⟨⟨s.1.pmap Subtype.mk fun x => (H x).1⟩⟩ end Fintype end Mathlib.Data.Fintype.Defs section Mathlib.Data.Fintype.Sets variable {α β γ : Type*} open Finset namespace Set variable {s t : Set α} /-- Construct a finset enumerating a set `s`, given a `Fintype` instance. -/ def toFinset (s : Set α) [Fintype s] : Finset α := (@Finset.univ s _).map <| Subtype.val end Set instance Subtype.fintype (p : α → Prop) [DecidablePred p] [Fintype α] : Fintype { x // p x } := Fintype.subtype (univ.filter p) sorry end Mathlib.Data.Fintype.Sets section Mathlib.Data.Sym.Sym2 open Function universe u variable {α β γ : Type*} namespace Sym2 /-- This is the relation capturing the notion of pairs equivalent up to permutations. -/ inductive Rel (α : Type u) : α × α → α × α → Prop | refl (x y : α) : Rel _ (x, y) (x, y) | swap (x y : α) : Rel _ (x, y) (y, x) end Sym2 /-- `Sym2 α` is the symmetric square of `α`, which, in other words, is the type of unordered pairs. -/ abbrev Sym2 (α : Type u) := Quot (Sym2.Rel α) /-- Constructor for `Sym2`. This is the quotient map `α × α → Sym2 α`. -/ protected abbrev Sym2.mk {α : Type*} (p : α × α) : Sym2 α := Quot.mk (Sym2.Rel α) p namespace Sym2 /-- The universal property of `Sym2`; symmetric functions of two arguments are equivalent to functions from `Sym2`. Note that when `β` is `Prop`, it can sometimes be more convenient to use `Sym2.fromRel` instead. -/ def lift : { f : α → α → β // ∀ a₁ a₂, f a₁ a₂ = f a₂ a₁ } → (Sym2 α → β) := fun f => Quot.lift (uncurry f) <| by sorry section Relations variable {r : α → α → Prop} /-- Symmetric relations define a set on `Sym2 α` by taking all those pairs of elements that are related. -/ def fromRel (sym : Symmetric r) : Set (Sym2 α) := setOf (lift ⟨r, fun _ _ => propext ⟨(sym ·), (sym ·)⟩⟩) instance fromRel.decidablePred (sym : Symmetric r) [h : DecidableRel r] : DecidablePred (· ∈ Sym2.fromRel sym) := fun z => z.recOnSubsingleton fun _ => h _ _ end Relations end Sym2 end Mathlib.Data.Sym.Sym2 section Mathlib.Data.List.Sym namespace List variable {α β : Type*} section Sym2 /-- `xs.sym2` is a list of all unordered pairs of elements from `xs`. If `xs` has no duplicates then neither does `xs.sym2`. -/ protected def sym2 : List α → List (Sym2 α) | [] => [] | x :: xs => (x :: xs).map (fun y => .mk (x, y)) ++ xs.sym2 end Sym2 end List end Mathlib.Data.List.Sym section Mathlib.Data.Multiset.Sym namespace Multiset variable {α β : Type*} section Sym2 /-- `m.sym2` is the multiset of all unordered pairs of elements from `m`, with multiplicity. If `m` has no duplicates then neither does `m.sym2`. -/ protected def sym2 (m : Multiset α) : Multiset (Sym2 α) := m.liftOn (fun xs => ofList xs.sym2) fun _ _ h => sorry end Sym2 end Multiset end Mathlib.Data.Multiset.Sym section Mathlib.Data.Finset.Sym namespace Finset variable {α β : Type*} protected def sym2 (s : Finset α) : Finset (Sym2 α) := ⟨s.1.sym2⟩ section variable {s t : Finset α} {a b : α} instance _root_.Sym2.instFintype [Fintype α] : Fintype (Sym2 α) where elems := Finset.univ.sym2 end end Finset end Mathlib.Data.Finset.Sym section Mathlib.Combinatorics.SimpleGraph.Basic open Function universe u v w /-- A simple graph is an irreflexive symmetric relation `Adj` on a vertex type `V`. The relation describes which pairs of vertices are adjacent. There is exactly one edge for every pair of adjacent vertices; see `SimpleGraph.edgeSet` for the corresponding edge set. -/ structure SimpleGraph (V : Type u) where /-- The adjacency relation of a simple graph. -/ Adj : V → V → Prop namespace SimpleGraph variable {ι : Sort*} {V : Type u} (G : SimpleGraph V) {a b c u v w : V} {e : Sym2 V} section EdgeSet variable {G₁ G₂ : SimpleGraph V} /-- The edges of G consist of the unordered pairs of vertices related by `G.Adj`. This is the order embedding; for the edge set of a particular graph, see `SimpleGraph.edgeSet`. The way `edgeSet` is defined is such that `mem_edgeSet` is proved by `Iff.rfl`. (That is, `s(v, w) ∈ G.edgeSet` is definitionally equal to `G.Adj v w`.) -/ -- Porting note: We need a separate definition so that dot notation works. def edgeSetEmbedding (V : Type*) : SimpleGraph V → Set (Sym2 V) := fun G => Sym2.fromRel (r := G.1) sorry /-- `G.edgeSet` is the edge set for `G`. This is an abbreviation for `edgeSetEmbedding G` that permits dot notation. -/ abbrev edgeSet (G : SimpleGraph V) : Set (Sym2 V) := edgeSetEmbedding V G variable (G₁ G₂) instance decidableMemEdgeSet [DecidableRel G.Adj] : DecidablePred (· ∈ G.edgeSet) := Sym2.fromRel.decidablePred sorry end EdgeSet end SimpleGraph end Mathlib.Combinatorics.SimpleGraph.Basic section Mathlib.Combinatorics.SimpleGraph.Finite namespace SimpleGraph variable {V : Type*} (G : SimpleGraph V) {e : Sym2 V} variable {G₁ G₂ : SimpleGraph V} [Fintype G.edgeSet] [Fintype G₁.edgeSet] [Fintype G₂.edgeSet] /-- The `edgeSet` of the graph as a `Finset`. -/ abbrev edgeFinset : Finset (Sym2 V) := Set.toFinset G.edgeSet end SimpleGraph end Mathlib.Combinatorics.SimpleGraph.Finite section Mathlib.Combinatorics.SimpleGraph.Clique namespace SimpleGraph variable {α β : Type*} (G H : SimpleGraph α) /-! ### `n`-cliques -/ section NClique variable {n : Nat} {s : Finset α} /-- An `n`-clique in a graph is a set of `n` vertices which are pairwise connected. -/ structure IsNClique (G : SimpleGraph α) (n : Nat) (s : Finset α) : Prop where end NClique /-! ### Graphs without cliques -/ section CliqueFree variable {m n : Nat} /-- `G.CliqueFree n` means that `G` has no `n`-cliques. -/ def CliqueFree (n : Nat) : Prop := ∀ t, ¬G.IsNClique n t end CliqueFree end SimpleGraph end Mathlib.Combinatorics.SimpleGraph.Clique section Mathlib.Order.Partition.Finpartition open Finset variable {α : Type*} /-- A finite partition of `a : α` is a pairwise disjoint finite set of elements whose supremum is `a`. We forbid `⊥` as a part. -/ structure Finpartition (a : α) where /-- The elements of the finite partition of `a` -/ parts : Finset α /-! ### Finite partitions of finsets -/ namespace Finpartition variable [DecidableEq α] {s t u : Finset α} (P : Finpartition s) {a : α} theorem existsUnique_mem (ha : a ∈ s) : ∃ t, t ∈ P.parts ∧ a ∈ t := by sorry /-- The part of the finpartition that `a` lies in. -/ def part (a : α) : Finset α := if ha : a ∈ s then choose (hp := P.existsUnique_mem ha) else .empty section SetSetoid /-- A setoid over a finite type induces a finpartition of the type's elements, where the parts are the setoid's equivalence classes. -/ def ofSetSetoid (s : Setoid α) (x : Finset α) [DecidableRel s.r] : Finpartition x where parts := x.image fun a ↦ x.filter (s.r a ·) end SetSetoid section Setoid variable [Fintype α] /-- A setoid over a finite type induces a finpartition of the type's elements, where the parts are the setoid's equivalence classes. -/ def ofSetoid (s : Setoid α) [DecidableRel s.r] : Finpartition (univ : Finset α) := ofSetSetoid s univ end Setoid end Finpartition end Mathlib.Order.Partition.Finpartition open Finset namespace SimpleGraph variable {V : Type*} [Fintype V] {G : SimpleGraph V} [DecidableRel G.Adj] {n r : Nat} variable (G) in /-- An `r + 1`-cliquefree graph is `r`-Turán-maximal if any other `r + 1`-cliquefree graph on the same vertex set has the same or fewer number of edges. -/ def IsTuranMaximal (r : Nat) : Prop := G.CliqueFree (r + 1) ∧ ∀ (H : SimpleGraph V) [DecidableRel H.Adj], H.CliqueFree (r + 1) → H.edgeFinset.card ≤ G.edgeFinset.card namespace IsTuranMaximal variable {s t u : V} variable (h : G.IsTuranMaximal r) include h /-- In a Turán-maximal graph, non-adjacency is an equivalence relation. -/ theorem equivalence_not_adj : Equivalence (¬G.Adj · ·) where refl := sorry symm := sorry trans := sorry /-- The non-adjacency setoid over the vertices of a Turán-maximal graph induced by `equivalence_not_adj`. -/ def setoid : Setoid V := ⟨_, h.equivalence_not_adj⟩ instance : DecidableRel h.setoid.r := inferInstanceAs <| DecidableRel (¬G.Adj · ·) /-- The finpartition derived from `h.setoid`. -/ def finpartition [DecidableEq V] : Finpartition (univ : Finset V) := Finpartition.ofSetoid h.setoid theorem not_adj_iff_part_eq [DecidableEq V] : ¬G.Adj s t ↔ h.finpartition.part s = h.finpartition.part t := by sorry theorem card_parts_extracted_1_11 [DecidableEq V] : let fp := h.finpartition; fp.parts.card < (Finset.univ (α := V)).card ∧ fp.parts.card < r → ∀ (x y : V), x ≠ y → fp.part x = fp.part y → ∀ ⦃z : Finset V⦄, z.card = r → ∃ x ∈ ↑z, ∃ y ∈ ↑z, x ≠ y ∧ ¬G.Adj x y := by intro fp l x y hn he z zc simp [h.not_adj_iff_part_eq] ---- should work sorry end IsTuranMaximal end SimpleGraph