/- Copyright (c) 2024 Joseph Tooby-Smith. All rights reserved. Released under Apache 2.0 license. Authors: Joseph Tooby-Smith -/ import Mathlib.Logic.Equiv.Fin import Mathlib.Tactic.FinCases import Mathlib.Data.Finset.Card import Mathlib.CategoryTheory.IsomorphismClasses import Mathlib.CategoryTheory.Functor.Category import Mathlib.CategoryTheory.Comma.Over import Mathlib.Data.Fintype.Pi import Mathlib.CategoryTheory.Limits.Shapes.Terminal import Mathlib.Data.Fintype.Prod import Mathlib.Data.Fintype.Perm import Mathlib.Combinatorics.SimpleGraph.Basic import Mathlib.Combinatorics.SimpleGraph.Connectivity import Mathlib.SetTheory.Cardinal.Basic /-! # Feynman diagrams Feynman diagrams are a graphical representation of the terms in the perturbation expansion of a quantum field theory. -/ open CategoryTheory /-! ## The definition of Pre Feynman rules We define the notion of a pre-Feynman rule, which specifies the possible half-edges, edges and vertices in a diagram. It does not specify how to turn a diagram into an algebraic expression. ## TODO Prove that the `halfEdgeLimit` functor lands on limits of functors. -/ /-- A `PreFeynmanRule` is a set of rules specifying the allowed half-edges, edges and vertices in a diagram. (It does not specify how to turn the diagram into an algebraic expression.) -/ structure PreFeynmanRule where /-- The type labelling the different half-edges. -/ HalfEdgeLabel : Type /-- A type labelling the different types of edges. -/ EdgeLabel : Type /-- A type labelling the different types of vertices. -/ VertexLabel : Type /-- A function taking `EdgeLabels` to the half edges it contains. -/ edgeLabelMap : EdgeLabel β†’ CategoryTheory.Over HalfEdgeLabel /-- A function taking `VertexLabels` to the half edges it contains. -/ vertexLabelMap : VertexLabel β†’ CategoryTheory.Over HalfEdgeLabel namespace PreFeynmanRule variable (P : PreFeynmanRule) /-- The functor from `Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` to `Over (P.VertexLabel)` induced by projections on products. -/ @[simps!] def toVertex {𝓔 π“₯ : Type} : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) β₯€ Over π“₯ := Over.map <| Prod.snd ∘ Prod.snd /-- The functor from `Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` to `Over (P.EdgeLabel)` induced by projections on products. -/ @[simps!] def toEdge {𝓔 π“₯ : Type} : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) β₯€ Over 𝓔 := Over.map <| Prod.fst ∘ Prod.snd /-- The functor from `Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` to `Over (P.HalfEdgeLabel)` induced by projections on products. -/ @[simps!] def toHalfEdge {𝓔 π“₯ : Type} : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) β₯€ Over P.HalfEdgeLabel := Over.map Prod.fst /-- The functor from `Over P.VertexLabel` to `Type` induced by pull-back along insertion of `v : P.VertexLabel`. -/ @[simps!] def preimageType' {π“₯ : Type} (v : π“₯) : Over π“₯ β₯€ Type where obj := fun f => f.hom ⁻¹' {v} map {f g} F := fun x => ⟨F.left x.1, by have h := congrFun F.w x simp only [Functor.const_obj_obj, Functor.id_obj, Functor.id_map, types_comp_apply, CostructuredArrow.right_eq_id, Functor.const_obj_map, types_id_apply] at h simpa [h] using x.2⟩ /-- The functor from `Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` to `Over P.HalfEdgeLabel` induced by pull-back along insertion of `v : P.VertexLabel`. -/ def preimageVertex {𝓔 π“₯ : Type} (v : π“₯) : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) β₯€ Over P.HalfEdgeLabel where obj f := Over.mk (fun x => Prod.fst (f.hom x.1) : (P.toVertex β‹™ preimageType' v).obj f ⟢ P.HalfEdgeLabel) map {f g} F := Over.homMk ((P.toVertex β‹™ preimageType' v).map F) (funext <| fun x => congrArg Prod.fst <| congrFun F.w x.1) /-- The functor from `Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` to `Over P.HalfEdgeLabel` induced by pull-back along insertion of `v : P.EdgeLabel`. -/ def preimageEdge {𝓔 π“₯ : Type} (v : 𝓔) : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) β₯€ Over P.HalfEdgeLabel where obj f := Over.mk (fun x => Prod.fst (f.hom x.1) : (P.toEdge β‹™ preimageType' v).obj f ⟢ P.HalfEdgeLabel) map {f g} F := Over.homMk ((P.toEdge β‹™ preimageType' v).map F) (funext <| fun x => congrArg Prod.fst <| congrFun F.w x.1) /-! ## Finitness of pre-Feynman rules We define a class of `PreFeynmanRule` which have nice properties with regard to decidablity and finitness. In practice, every pre-Feynman rule considered in the physics literature satisfies these properties. -/ /-- A set of conditions on `PreFeynmanRule` for it to be considered finite. -/ class IsFinitePreFeynmanRule (P : PreFeynmanRule) where /-- The type of edge labels is decidable. -/ edgeLabelDecidable : DecidableEq P.EdgeLabel /-- The type of vertex labels is decidable. -/ vertexLabelDecidable : DecidableEq P.VertexLabel /-- The type of half-edge labels is decidable. -/ halfEdgeLabelDecidable : DecidableEq P.HalfEdgeLabel /-- The type of half-edges associated with a vertex is finite. -/ vertexMapFintype : βˆ€ v : P.VertexLabel, Fintype (P.vertexLabelMap v).left /-- The type of half-edges associated with a vertex is decidable. -/ vertexMapDecidable : βˆ€ v : P.VertexLabel, DecidableEq (P.vertexLabelMap v).left /-- The type of half-edges associated with an edge is finite. -/ edgeMapFintype : βˆ€ v : P.EdgeLabel, Fintype (P.edgeLabelMap v).left /-- The type of half-edges associated with an edge is decidable. -/ edgeMapDecidable : βˆ€ v : P.EdgeLabel, DecidableEq (P.edgeLabelMap v).left instance preFeynmanRuleDecEq𝓔 (P : PreFeynmanRule) [IsFinitePreFeynmanRule P] : DecidableEq P.EdgeLabel := IsFinitePreFeynmanRule.edgeLabelDecidable instance preFeynmanRuleDecEqπ“₯ (P : PreFeynmanRule) [IsFinitePreFeynmanRule P] : DecidableEq P.VertexLabel := IsFinitePreFeynmanRule.vertexLabelDecidable instance preFeynmanRuleDecEq𝓱𝓔 (P : PreFeynmanRule) [IsFinitePreFeynmanRule P] : DecidableEq P.HalfEdgeLabel := IsFinitePreFeynmanRule.halfEdgeLabelDecidable instance [IsFinitePreFeynmanRule P] (v : P.VertexLabel) : Fintype (P.vertexLabelMap v).left := IsFinitePreFeynmanRule.vertexMapFintype v instance [IsFinitePreFeynmanRule P] (v : P.VertexLabel) : DecidableEq (P.vertexLabelMap v).left := IsFinitePreFeynmanRule.vertexMapDecidable v instance [IsFinitePreFeynmanRule P] (v : P.EdgeLabel) : Fintype (P.edgeLabelMap v).left := IsFinitePreFeynmanRule.edgeMapFintype v instance [IsFinitePreFeynmanRule P] (v : P.EdgeLabel) : DecidableEq (P.edgeLabelMap v).left := IsFinitePreFeynmanRule.edgeMapDecidable v instance preimageVertexDecidablePred {𝓔 π“₯ : Type} [DecidableEq π“₯] (v : π“₯) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) : DecidablePred fun x => x ∈ (P.toVertex.obj F).hom ⁻¹' {v} := fun y => match decEq ((P.toVertex.obj F).hom y) v with | isTrue h => isTrue h | isFalse h => isFalse h instance preimageEdgeDecidablePred {𝓔 π“₯ : Type} [DecidableEq 𝓔] (v : 𝓔) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) : DecidablePred fun x => x ∈ (P.toEdge.obj F).hom ⁻¹' {v} := fun y => match decEq ((P.toEdge.obj F).hom y) v with | isTrue h => isTrue h | isFalse h => isFalse h instance preimageVertexDecidable {𝓔 π“₯ : Type} (v : π“₯) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [DecidableEq F.left] : DecidableEq ((P.preimageVertex v).obj F).left := Subtype.instDecidableEq instance preimageEdgeDecidable {𝓔 π“₯ : Type} (v : 𝓔) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [DecidableEq F.left] : DecidableEq ((P.preimageEdge v).obj F).left := Subtype.instDecidableEq instance preimageVertexFintype {𝓔 π“₯ : Type} [DecidableEq π“₯] (v : π“₯) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [h : Fintype F.left] : Fintype ((P.preimageVertex v).obj F).left := @Subtype.fintype _ _ _ h instance preimageEdgeFintype {𝓔 π“₯ : Type} [DecidableEq 𝓔] (v : 𝓔) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [h : Fintype F.left] : Fintype ((P.preimageEdge v).obj F).left := @Subtype.fintype _ _ _ h instance preimageVertexMapFintype [IsFinitePreFeynmanRule P] {𝓔 π“₯ : Type} [DecidableEq π“₯] (v : π“₯) (f : π“₯ ⟢ P.VertexLabel) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [Fintype F.left] : Fintype ((P.vertexLabelMap (f v)).left β†’ ((P.preimageVertex v).obj F).left) := Pi.fintype instance preimageEdgeMapFintype [IsFinitePreFeynmanRule P] {𝓔 π“₯ : Type} [DecidableEq 𝓔] (v : 𝓔) (f : 𝓔 ⟢ P.EdgeLabel) (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [Fintype F.left] : Fintype ((P.edgeLabelMap (f v)).left β†’ ((P.preimageEdge v).obj F).left) := Pi.fintype /-! ## Conditions to form a diagram. -/ /-- The proposition on vertices which must be satisfied by an object `F : Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` for it to be a Feynman diagram. This condition corresponds to the vertices of `F` having the correct half-edges associated with them. -/ def diagramVertexProp {𝓔 π“₯ : Type} (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) (f : π“₯ ⟢ P.VertexLabel) := βˆ€ v, IsIsomorphic (P.vertexLabelMap (f v)) ((P.preimageVertex v).obj F) /-- The proposition on edges which must be satisfied by an object `F : Over (P.HalfEdgeLabel Γ— P.EdgeLabel Γ— P.VertexLabel)` for it to be a Feynman diagram. This condition corresponds to the edges of `F` having the correct half-edges associated with them. -/ def diagramEdgeProp {𝓔 π“₯ : Type} (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) (f : 𝓔 ⟢ P.EdgeLabel) := βˆ€ v, IsIsomorphic (P.edgeLabelMap (f v)) ((P.preimageEdge v).obj F) lemma diagramVertexProp_iff {𝓔 π“₯ : Type} (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) (f : π“₯ ⟢ P.VertexLabel) : P.diagramVertexProp F f ↔ βˆ€ v, βˆƒ (ΞΊ : (P.vertexLabelMap (f v)).left β†’ ((P.preimageVertex v).obj F).left), Function.Bijective ΞΊ ∧ ((P.preimageVertex v).obj F).hom ∘ ΞΊ = (P.vertexLabelMap (f v)).hom := by refine Iff.intro (fun h v => ?_) (fun h v => ?_) obtain ⟨κ, ΞΊm1, h1, h2⟩ := h v let f := (Over.forget P.HalfEdgeLabel).mapIso ⟨κ, ΞΊm1, h1, h2⟩ refine ⟨f.hom, (isIso_iff_bijective f.hom).mp $ Iso.isIso_hom f, ΞΊ.w⟩ obtain ⟨κ, h1, h2⟩ := h v let f : (P.vertexLabelMap (f v)) ⟢ ((P.preimageVertex v).obj F) := Over.homMk ΞΊ h2 have ft : IsIso ((Over.forget P.HalfEdgeLabel).map f) := (isIso_iff_bijective ΞΊ).mpr h1 obtain ⟨fm, hf1, hf2⟩ := (isIso_of_reflects_iso _ (Over.forget P.HalfEdgeLabel) : IsIso f) exact ⟨f, fm, hf1, hf2⟩ lemma diagramEdgeProp_iff {𝓔 π“₯ : Type} (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) (f : 𝓔 ⟢ P.EdgeLabel) : P.diagramEdgeProp F f ↔ βˆ€ v, βˆƒ (ΞΊ : (P.edgeLabelMap (f v)).left β†’ ((P.preimageEdge v).obj F).left), Function.Bijective ΞΊ ∧ ((P.preimageEdge v).obj F).hom ∘ ΞΊ = (P.edgeLabelMap (f v)).hom := by refine Iff.intro (fun h v => ?_) (fun h v => ?_) obtain ⟨κ, ΞΊm1, h1, h2⟩ := h v let f := (Over.forget P.HalfEdgeLabel).mapIso ⟨κ, ΞΊm1, h1, h2⟩ refine ⟨f.hom, (isIso_iff_bijective f.hom).mp $ Iso.isIso_hom f, ΞΊ.w⟩ obtain ⟨κ, h1, h2⟩ := h v let f : (P.edgeLabelMap (f v)) ⟢ ((P.preimageEdge v).obj F) := Over.homMk ΞΊ h2 have ft : IsIso ((Over.forget P.HalfEdgeLabel).map f) := (isIso_iff_bijective ΞΊ).mpr h1 obtain ⟨fm, hf1, hf2⟩ := (isIso_of_reflects_iso _ (Over.forget P.HalfEdgeLabel) : IsIso f) exact ⟨f, fm, hf1, hf2⟩ instance diagramVertexPropDecidable [IsFinitePreFeynmanRule P] {𝓔 π“₯ : Type} [Fintype π“₯] [DecidableEq π“₯] (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [DecidableEq F.left] [Fintype F.left] (f : π“₯ ⟢ P.VertexLabel) : Decidable (P.diagramVertexProp F f) := @decidable_of_decidable_of_iff _ _ (@Fintype.decidableForallFintype _ _ (fun _ => @Fintype.decidableExistsFintype _ _ (fun _ => @And.decidable _ _ _ (@Fintype.decidablePiFintype _ _ (fun _ => P.preFeynmanRuleDecEq𝓱𝓔) _ _ _)) _ ) _) (P.diagramVertexProp_iff F f).symm instance diagramEdgePropDecidable [IsFinitePreFeynmanRule P] {𝓔 π“₯ : Type} [Fintype 𝓔] [DecidableEq 𝓔] (F : Over (P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯)) [DecidableEq F.left] [Fintype F.left] (f : 𝓔 ⟢ P.EdgeLabel) : Decidable (P.diagramEdgeProp F f) := @decidable_of_decidable_of_iff _ _ (@Fintype.decidableForallFintype _ _ (fun _ => @Fintype.decidableExistsFintype _ _ (fun _ => @And.decidable _ _ _ (@Fintype.decidablePiFintype _ _ (fun _ => P.preFeynmanRuleDecEq𝓱𝓔) _ _ _)) _ ) _) (P.diagramEdgeProp_iff F f).symm end PreFeynmanRule /-! ## The definition of Feynman diagrams We now define the type of Feynman diagrams for a given pre-Feynman rule. -/ open PreFeynmanRule /-- The type of Feynman diagrams given a `PreFeynmanRule`. -/ structure FeynmanDiagram (P : PreFeynmanRule) where /-- The type of edges in the Feynman diagram, labelled by their type. -/ π“”π“ž : Over P.EdgeLabel /-- The type of vertices in the Feynman diagram, labelled by their type. -/ π“₯π“ž : Over P.VertexLabel /-- The type of half-edges in the Feynman diagram, labelled by their type, the edge it belongs to, and the vertex they belong to. -/ 𝓱𝓔To𝓔π“₯ : Over (P.HalfEdgeLabel Γ— π“”π“ž.left Γ— π“₯π“ž.left) /-- Each edge has the correct type of half edges. -/ 𝓔Cond : P.diagramEdgeProp 𝓱𝓔To𝓔π“₯ π“”π“ž.hom /-- Each vertex has the correct sort of half edges. -/ π“₯Cond : P.diagramVertexProp 𝓱𝓔To𝓔π“₯ π“₯π“ž.hom namespace FeynmanDiagram variable {P : PreFeynmanRule} (F : FeynmanDiagram P) /-- The type of edges. -/ def 𝓔 : Type := F.π“”π“ž.left /-- The type of vertices. -/ def π“₯ : Type := F.π“₯π“ž.left /-- The type of half-edges. -/ def 𝓱𝓔 : Type := F.𝓱𝓔To𝓔π“₯.left /-- The object in Over P.HalfEdgeLabel generated by a Feynman diagram. -/ def π“±π“”π“ž : Over P.HalfEdgeLabel := P.toHalfEdge.obj F.𝓱𝓔To𝓔π“₯ /-! ## Making a Feynman diagram -/ /-- The condition which must be satisfied by maps to form a Feynman diagram. -/ def Cond {𝓔 π“₯ 𝓱𝓔 : Type} (π“”π“ž : 𝓔 β†’ P.EdgeLabel) (π“₯π“ž : π“₯ β†’ P.VertexLabel) (𝓱𝓔To𝓔π“₯ : 𝓱𝓔 β†’ P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) : Prop := P.diagramEdgeProp (Over.mk 𝓱𝓔To𝓔π“₯) π“”π“ž ∧ P.diagramVertexProp (Over.mk 𝓱𝓔To𝓔π“₯) π“₯π“ž lemma cond_self : Cond F.π“”π“ž.hom F.π“₯π“ž.hom F.𝓱𝓔To𝓔π“₯.hom := ⟨F.𝓔Cond, F.π“₯Cond⟩ /-- `Cond` is decidable. -/ instance CondDecidable [IsFinitePreFeynmanRule P] {𝓔 π“₯ 𝓱𝓔 : Type} (π“”π“ž : 𝓔 β†’ P.EdgeLabel) (π“₯π“ž : π“₯ β†’ P.VertexLabel) (𝓱𝓔To𝓔π“₯ : 𝓱𝓔 β†’ P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) [Fintype π“₯] [DecidableEq π“₯] [Fintype 𝓔] [DecidableEq 𝓔] [h : Fintype 𝓱𝓔] [DecidableEq 𝓱𝓔] : Decidable (Cond π“”π“ž π“₯π“ž 𝓱𝓔To𝓔π“₯) := @And.decidable _ _ (@diagramEdgePropDecidable P _ _ _ _ _ (Over.mk 𝓱𝓔To𝓔π“₯) _ h π“”π“ž) (@diagramVertexPropDecidable P _ _ _ _ _ (Over.mk 𝓱𝓔To𝓔π“₯) _ h π“₯π“ž) /-- Making a Feynman diagram from maps of edges, vertices and half-edges. -/ def mk' {𝓔 π“₯ 𝓱𝓔 : Type} (π“”π“ž : 𝓔 β†’ P.EdgeLabel) (π“₯π“ž : π“₯ β†’ P.VertexLabel) (𝓱𝓔To𝓔π“₯ : 𝓱𝓔 β†’ P.HalfEdgeLabel Γ— 𝓔 Γ— π“₯) (C : Cond π“”π“ž π“₯π“ž 𝓱𝓔To𝓔π“₯): FeynmanDiagram P where π“”π“ž := Over.mk π“”π“ž π“₯π“ž := Over.mk π“₯π“ž 𝓱𝓔To𝓔π“₯ := Over.mk 𝓱𝓔To𝓔π“₯ 𝓔Cond := C.1 π“₯Cond := C.2 lemma mk'_self : mk' F.π“”π“ž.hom F.π“₯π“ž.hom F.𝓱𝓔To𝓔π“₯.hom F.cond_self = F := rfl /-! ## Finitness of Feynman diagrams As defined above our Feynman diagrams can have non-finite Types of half-edges etc. We define the class of those Feynman diagrams which are `finite` in the appropriate sense. In practice, every Feynman diagram considered in the physics literature is `finite`. This finiteness condition will be used to prove certain `Types` are `Fintype`, and prove that certain propositions are decidable. -/ /-- A set of conditions on a Feynman diagram for it to be considered finite. -/ class IsFiniteDiagram (F : FeynmanDiagram P) where /-- The type of edges is finite. -/ 𝓔Fintype : Fintype F.𝓔 /-- The type of edges is decidable. -/ 𝓔DecidableEq : DecidableEq F.𝓔 /-- The type of vertices is finite. -/ π“₯Fintype : Fintype F.π“₯ /-- The type of vertices is decidable. -/ π“₯DecidableEq : DecidableEq F.π“₯ /-- The type of half-edges is finite. -/ 𝓱𝓔Fintype : Fintype F.𝓱𝓔 /-- The type of half-edges is decidable. -/ 𝓱𝓔DecidableEq : DecidableEq F.𝓱𝓔 instance {F : FeynmanDiagram P} [IsFiniteDiagram F] : Fintype F.𝓔 := IsFiniteDiagram.𝓔Fintype instance {F : FeynmanDiagram P} [IsFiniteDiagram F] : DecidableEq F.𝓔 := IsFiniteDiagram.𝓔DecidableEq instance {F : FeynmanDiagram P} [IsFiniteDiagram F] : Fintype F.π“₯ := IsFiniteDiagram.π“₯Fintype instance {F : FeynmanDiagram P} [IsFiniteDiagram F] : DecidableEq F.π“₯ := IsFiniteDiagram.π“₯DecidableEq instance {F : FeynmanDiagram P} [IsFiniteDiagram F] : Fintype F.𝓱𝓔 := IsFiniteDiagram.𝓱𝓔Fintype instance {F : FeynmanDiagram P} [IsFiniteDiagram F] : DecidableEq F.𝓱𝓔 := IsFiniteDiagram.𝓱𝓔DecidableEq instance fintypeProdHalfEdgeLabel𝓔π“₯ {F : FeynmanDiagram P} [IsFinitePreFeynmanRule P] [IsFiniteDiagram F] : DecidableEq (P.HalfEdgeLabel Γ— F.𝓔 Γ— F.π“₯) := instDecidableEqProd /-! ## Morphisms of Feynman diagrams We define a morphism between Feynman diagrams, and properties thereof. This will be used to define the category of Feynman diagrams. -/ /-- Given two maps `F.𝓔 ⟢ G.𝓔` and `F.π“₯ ⟢ G.π“₯` the corresponding map `P.HalfEdgeLabel Γ— F.𝓔 Γ— F.π“₯ β†’ P.HalfEdgeLabel Γ— G.𝓔 Γ— G.π“₯`. -/ @[simps!] def edgeVertexMap {F G : FeynmanDiagram P} (𝓔 : F.𝓔 ⟢ G.𝓔) (π“₯ : F.π“₯ ⟢ G.π“₯) : P.HalfEdgeLabel Γ— F.𝓔 Γ— F.π“₯ β†’ P.HalfEdgeLabel Γ— G.𝓔 Γ— G.π“₯ := fun x => ⟨x.1, 𝓔 x.2.1, π“₯ x.2.2⟩ /-- Given equivalences `F.𝓔 ≃ G.𝓔` and `F.π“₯ ≃ G.π“₯`, the induced equivalence between `P.HalfEdgeLabel Γ— F.𝓔 Γ— F.π“₯` and `P.HalfEdgeLabel Γ— G.𝓔 Γ— G.π“₯ ` -/ def edgeVertexEquiv {F G : FeynmanDiagram P} (𝓔 : F.𝓔 ≃ G.𝓔) (π“₯ : F.π“₯ ≃ G.π“₯) : P.HalfEdgeLabel Γ— F.𝓔 Γ— F.π“₯ ≃ P.HalfEdgeLabel Γ— G.𝓔 Γ— G.π“₯ where toFun := edgeVertexMap 𝓔.toFun π“₯.toFun invFun := edgeVertexMap 𝓔.invFun π“₯.invFun left_inv := by aesop_cat right_inv := by aesop_cat /-- The functor of over-categories generated by `edgeVertexMap`. -/ @[simps!] def edgeVertexFunc {F G : FeynmanDiagram P} (𝓔 : F.𝓔 ⟢ G.𝓔) (π“₯ : F.π“₯ ⟢ G.π“₯) : Over (P.HalfEdgeLabel Γ— F.𝓔 Γ— F.π“₯) β₯€ Over (P.HalfEdgeLabel Γ— G.𝓔 Γ— G.π“₯) := Over.map <| edgeVertexMap 𝓔 π“₯ /-- A morphism of Feynman diagrams. -/ structure Hom (F G : FeynmanDiagram P) where /-- The morphism of edge objects. -/ π“”π“ž : F.π“”π“ž ⟢ G.π“”π“ž /-- The morphism of vertex objects. -/ π“₯π“ž : F.π“₯π“ž ⟢ G.π“₯π“ž /-- The morphism of half-edge objects. -/ 𝓱𝓔To𝓔π“₯ : (edgeVertexFunc π“”π“ž.left π“₯π“ž.left).obj F.𝓱𝓔To𝓔π“₯ ⟢ G.𝓱𝓔To𝓔π“₯ namespace Hom variable {F G : FeynmanDiagram P} variable (f : Hom F G) /-- The map `F.𝓔 β†’ G.𝓔` induced by a homomorphism of Feynman diagrams. -/ @[simp] def 𝓔 : F.𝓔 β†’ G.𝓔 := f.π“”π“ž.left /-- The map `F.π“₯ β†’ G.π“₯` induced by a homomorphism of Feynman diagrams. -/ @[simp] def π“₯ : F.π“₯ β†’ G.π“₯ := f.π“₯π“ž.left /-- The map `F.𝓱𝓔 β†’ G.𝓱𝓔` induced by a homomorphism of Feynman diagrams. -/ @[simp] def 𝓱𝓔 : F.𝓱𝓔 β†’ G.𝓱𝓔 := f.𝓱𝓔To𝓔π“₯.left /-- The morphism `F.π“±π“”π“ž ⟢ G.π“±π“”π“ž` induced by a homomorphism of Feynman diagrams. -/ @[simp] def π“±π“”π“ž : F.π“±π“”π“ž ⟢ G.π“±π“”π“ž := P.toHalfEdge.map f.𝓱𝓔To𝓔π“₯ /-- The identity morphism for a Feynman diagram. -/ def id (F : FeynmanDiagram P) : Hom F F where π“”π“ž := πŸ™ F.π“”π“ž π“₯π“ž := πŸ™ F.π“₯π“ž 𝓱𝓔To𝓔π“₯ := πŸ™ F.𝓱𝓔To𝓔π“₯ /-- The composition of two morphisms of Feynman diagrams. -/ @[simps! π“”π“ž_left π“₯π“ž_left 𝓱𝓔To𝓔π“₯_left] def comp {F G H : FeynmanDiagram P} (f : Hom F G) (g : Hom G H) : Hom F H where π“”π“ž := f.π“”π“ž ≫ g.π“”π“ž π“₯π“ž := f.π“₯π“ž ≫ g.π“₯π“ž 𝓱𝓔To𝓔π“₯ := (edgeVertexFunc g.𝓔 g.π“₯).map f.𝓱𝓔To𝓔π“₯ ≫ g.𝓱𝓔To𝓔π“₯ lemma ext' {F G : FeynmanDiagram P} {f g : Hom F G} (h𝓔 : f.π“”π“ž = g.π“”π“ž) (hπ“₯ : f.π“₯π“ž = g.π“₯π“ž) (h𝓱𝓔 : f.𝓱𝓔 = g.𝓱𝓔) : f = g := by cases f cases g subst h𝓔 hπ“₯ simp_all only [mk.injEq, heq_eq_eq, true_and] ext a : 2 simp only [𝓱𝓔] at h𝓱𝓔 exact congrFun h𝓱𝓔 a lemma ext {F G : FeynmanDiagram P} {f g : Hom F G} (h𝓔 : f.𝓔 = g.𝓔) (hπ“₯ : f.π“₯ = g.π“₯) (h𝓱𝓔 : f.𝓱𝓔 = g.𝓱𝓔) : f = g := ext' (Over.OverMorphism.ext h𝓔) (Over.OverMorphism.ext hπ“₯) h𝓱𝓔 /-- The condition on maps of edges, vertices and half-edges for it to be lifted to a morphism of Feynman diagrams. -/ def Cond {F G : FeynmanDiagram P} (𝓔 : F.𝓔 β†’ G.𝓔) (π“₯ : F.π“₯ β†’ G.π“₯) (𝓱𝓔 : F.𝓱𝓔 β†’ G.𝓱𝓔) : Prop := (βˆ€ x, G.π“”π“ž.hom (𝓔 x) = F.π“”π“ž.hom x) ∧ (βˆ€ x, G.π“₯π“ž.hom (π“₯ x) = F.π“₯π“ž.hom x) ∧ (βˆ€ x, G.𝓱𝓔To𝓔π“₯.hom (𝓱𝓔 x) = edgeVertexMap 𝓔 π“₯ (F.𝓱𝓔To𝓔π“₯.hom x)) lemma cond_satisfied {F G : FeynmanDiagram P} (f : Hom F G) : Cond f.𝓔 f.π“₯ f.𝓱𝓔 := ⟨fun x => congrFun f.π“”π“ž.w x, fun x => congrFun f.π“₯π“ž.w x, fun x => congrFun f.𝓱𝓔To𝓔π“₯.w x ⟩ lemma cond_symm {F G : FeynmanDiagram P} (𝓔 : F.𝓔 ≃ G.𝓔) (π“₯ : F.π“₯ ≃ G.π“₯) (𝓱𝓔 : F.𝓱𝓔 ≃ G.𝓱𝓔) (h : Cond 𝓔 π“₯ 𝓱𝓔) : Cond 𝓔.symm π“₯.symm 𝓱𝓔.symm := by refine ⟨?_, ?_, ?_⟩ simpa using fun x => (h.1 (𝓔.symm x)).symm simpa using fun x => (h.2.1 (π“₯.symm x)).symm intro x have h1 := h.2.2 (𝓱𝓔.symm x) simp at h1 exact (edgeVertexEquiv 𝓔 π“₯).apply_eq_iff_eq_symm_apply.mp (h1).symm instance {F G : FeynmanDiagram P} [IsFiniteDiagram F] [IsFinitePreFeynmanRule P] (𝓔 : F.𝓔 β†’ G.𝓔) : Decidable (βˆ€ x, G.π“”π“ž.hom (𝓔 x) = F.π“”π“ž.hom x) := @Fintype.decidableForallFintype _ _ (fun _ => preFeynmanRuleDecEq𝓔 P _ _) _ instance {F G : FeynmanDiagram P} [IsFiniteDiagram F] [IsFinitePreFeynmanRule P] (π“₯ : F.π“₯ β†’ G.π“₯) : Decidable (βˆ€ x, G.π“₯π“ž.hom (π“₯ x) = F.π“₯π“ž.hom x) := @Fintype.decidableForallFintype _ _ (fun _ => preFeynmanRuleDecEqπ“₯ P _ _) _ instance {F G : FeynmanDiagram P} [IsFiniteDiagram F] [IsFiniteDiagram G] [IsFinitePreFeynmanRule P] (𝓔 : F.𝓔 β†’ G.𝓔) (π“₯ : F.π“₯ β†’ G.π“₯) (𝓱𝓔 : F.𝓱𝓔 β†’ G.𝓱𝓔) : Decidable (βˆ€ x, G.𝓱𝓔To𝓔π“₯.hom (𝓱𝓔 x) = edgeVertexMap 𝓔 π“₯ (F.𝓱𝓔To𝓔π“₯.hom x)) := @Fintype.decidableForallFintype _ _ (fun _ => fintypeProdHalfEdgeLabel𝓔π“₯ _ _) _ instance {F G : FeynmanDiagram P} [IsFiniteDiagram F] [IsFiniteDiagram G] [IsFinitePreFeynmanRule P] (𝓔 : F.𝓔 β†’ G.𝓔) (π“₯ : F.π“₯ β†’ G.π“₯) (𝓱𝓔 : F.𝓱𝓔 β†’ G.𝓱𝓔) : Decidable (Cond 𝓔 π“₯ 𝓱𝓔) := And.decidable /-- Making a Feynman diagram from maps of edges, vertices and half-edges. -/ @[simps! π“”π“ž_left π“₯π“ž_left 𝓱𝓔To𝓔π“₯_left] def mk' {F G : FeynmanDiagram P} (𝓔 : F.𝓔 β†’ G.𝓔) (π“₯ : F.π“₯ β†’ G.π“₯) (𝓱𝓔 : F.𝓱𝓔 β†’ G.𝓱𝓔) (C : Cond 𝓔 π“₯ 𝓱𝓔) : Hom F G where π“”π“ž := Over.homMk 𝓔 $ funext C.1 π“₯π“ž := Over.homMk π“₯ $ funext C.2.1 𝓱𝓔To𝓔π“₯ := Over.homMk 𝓱𝓔 $ funext C.2.2 lemma mk'_self {F G : FeynmanDiagram P} (f : Hom F G) : mk' f.𝓔 f.π“₯ f.𝓱𝓔 f.cond_satisfied = f := rfl end Hom /-! ## The Category of Feynman diagrams Feynman diagrams, as defined above, form a category. We will be able to use this category to define the symmetry factor of a Feynman diagram, and the condition on whether a diagram is connected. -/ /-- Feynman diagrams form a category. -/ @[simps! id_π“”π“ž_left id_π“₯π“ž_left id_𝓱𝓔To𝓔π“₯_left comp_π“”π“ž_left comp_π“₯π“ž_left comp_𝓱𝓔To𝓔π“₯_left] instance : Category (FeynmanDiagram P) where Hom := Hom id := Hom.id comp := Hom.comp /-- An isomorphism of Feynman diagrams from isomorphisms of edges, vertices and half-edges. -/ def mkIso {F G : FeynmanDiagram P} (𝓔 : F.𝓔 ≃ G.𝓔) (π“₯ : F.π“₯ ≃ G.π“₯) (𝓱𝓔 : F.𝓱𝓔 ≃ G.𝓱𝓔) (C : Hom.Cond 𝓔 π“₯ 𝓱𝓔) : F β‰… G where hom := Hom.mk' 𝓔 π“₯ 𝓱𝓔 C inv := Hom.mk' 𝓔.symm π“₯.symm 𝓱𝓔.symm (Hom.cond_symm 𝓔 π“₯ 𝓱𝓔 C) hom_inv_id := by apply Hom.ext all_goals aesop_cat inv_hom_id := by apply Hom.ext all_goals aesop_cat /-- The functor from Feynman diagrams to category over edge labels. -/ def funcπ“”π“ž : FeynmanDiagram P β₯€ Over P.EdgeLabel where obj F := F.π“”π“ž map f := f.π“”π“ž /-- The functor from Feynman diagrams to category over vertex labels. -/ def funcπ“₯π“ž : FeynmanDiagram P β₯€ Over P.VertexLabel where obj F := F.π“₯π“ž map f := f.π“₯π“ž /-- The functor from Feynman diagrams to category over half-edge labels. -/ def funcπ“±π“”π“ž : FeynmanDiagram P β₯€ Over P.HalfEdgeLabel where obj F := F.π“±π“”π“ž map f := f.π“±π“”π“ž /-- The functor from Feynman diagrams to `Type` landing on edges. -/ def func𝓔 : FeynmanDiagram P β₯€ Type where obj F := F.𝓔 map f := f.𝓔 /-- The functor from Feynman diagrams to `Type` landing on vertices. -/ def funcπ“₯ : FeynmanDiagram P β₯€ Type where obj F := F.π“₯ map f := f.π“₯ /-- The functor from Feynman diagrams to `Type` landing on half-edges. -/ def func𝓱𝓔 : FeynmanDiagram P β₯€ Type where obj F := F.𝓱𝓔 map f := f.𝓱𝓔 section symmetryFactor /-! ## Symmetry factors The symmetry factor of a Feynman diagram is the cardinality of the group of automorphisms of that diagram. We show that the symmetry factor for a finite Feynman diagram is finite. -/ /-- The type of isomorphisms of a Feynman diagram. -/ def SymmetryType : Type := F β‰… F /-- An equivalence between `SymmetryType` and permutation of edges, vertices and half-edges satisfying `Hom.Cond`. -/ def symmetryTypeEquiv : F.SymmetryType ≃ {S : Equiv.Perm F.𝓔 Γ— Equiv.Perm F.π“₯ Γ— Equiv.Perm F.𝓱𝓔 // Hom.Cond S.1 S.2.1 S.2.2} where toFun f := ⟨⟨(func𝓔.mapIso f).toEquiv, (funcπ“₯.mapIso f).toEquiv, (func𝓱𝓔.mapIso f).toEquiv⟩, f.1.cond_satisfied⟩ invFun S := mkIso S.1.1 S.1.2.1 S.1.2.2 S.2 left_inv _ := rfl right_inv _ := rfl instance [IsFinitePreFeynmanRule P] [IsFiniteDiagram F] : Fintype F.SymmetryType := Fintype.ofEquiv _ F.symmetryTypeEquiv.symm /-- The symmetry factor can be defined as the cardinal of the symmetry type. In general this is not a finite number. -/ @[simp] def cardSymmetryFactor : Cardinal := Cardinal.mk (F.SymmetryType) /-- The symmetry factor of a Finite Feynman diagram, as a natural number. -/ @[simp] def symmetryFactor [IsFinitePreFeynmanRule P] [IsFiniteDiagram F] : β„• := (Fintype.card F.SymmetryType) @[simp] lemma symmetryFactor_eq_cardSymmetryFactor [IsFinitePreFeynmanRule P] [IsFiniteDiagram F] : F.symmetryFactor = F.cardSymmetryFactor := by simp only [symmetryFactor, cardSymmetryFactor, Cardinal.mk_fintype] end symmetryFactor section connectedness /-! ## Connectedness Given a Feynman diagram we can create a simple graph based on the obvious adjacency relation. A feynman diagram is connected if its simple graph is connected. ## TODO - Complete this section. -/ /-- A relation on the vertices of Feynman diagrams. The proposition is true if the two vertices are not equal and are connected by a single edge. -/ @[simp] def adjRelation : F.π“₯ β†’ F.π“₯ β†’ Prop := fun x y => x β‰  y ∧ βˆƒ (a b : F.𝓱𝓔), ((F.𝓱𝓔To𝓔π“₯.hom a).2.1 = (F.𝓱𝓔To𝓔π“₯.hom b).2.1 ∧ (F.𝓱𝓔To𝓔π“₯.hom a).2.2 = x ∧ (F.𝓱𝓔To𝓔π“₯.hom b).2.2 = y) instance [IsFiniteDiagram F] : DecidableRel F.adjRelation := fun _ _ => @And.decidable _ _ _ $ @Fintype.decidableExistsFintype _ _ (fun _ => @Fintype.decidableExistsFintype _ _ ( fun _ => @And.decidable _ _ (instDecidableEq𝓔OfIsFiniteDiagram _ _) $ @And.decidable _ _ (instDecidableEqπ“₯OfIsFiniteDiagram _ _) (instDecidableEqπ“₯OfIsFiniteDiagram _ _)) _ ) _ /-- From a Feynman diagram the simple graph showing those vertices which are connected. -/ def toSimpleGraph : SimpleGraph F.π“₯ where Adj := adjRelation F symm := by intro x y h apply And.intro (Ne.symm h.1) obtain ⟨a, b, hab⟩ := h.2 use b, a simp_all only [adjRelation, ne_eq, and_self] loopless := by intro x h simp at h instance [IsFiniteDiagram F] : DecidableRel F.toSimpleGraph.Adj := instDecidableRelπ“₯AdjRelationOfIsFiniteDiagram F instance [IsFiniteDiagram F] : Decidable (F.toSimpleGraph.Preconnected ∧ Nonempty F.π“₯) := @And.decidable _ _ _ $ decidable_of_iff _ Finset.univ_nonempty_iff instance [IsFiniteDiagram F] : Decidable F.toSimpleGraph.Connected := decidable_of_iff _ (SimpleGraph.connected_iff F.toSimpleGraph).symm /-- We say a Feynman diagram is connected if its simple graph is connected. -/ def Connected : Prop := F.toSimpleGraph.Connected instance [IsFiniteDiagram F] : Decidable (Connected F) := instDecidableConnectedπ“₯ToSimpleGraphOfIsFiniteDiagram F end connectedness end FeynmanDiagram