Definitions bundle OAIQ051M003 of the split of OpenAI, A Fully Polynomial Randomized Approximation Scheme for Perfect Matchings in General Graphs (result family 113)
DefinitionOAIQ051M003A definitions bundle of the split of OpenAI's proof of OAI.MatchingFPRAS.thm_main, carved from OpenAI's openai/math development (OpenAI, A Fully Polynomial Randomized Approximation Scheme for Perfect Matchings in General Graphs (result family 113), OpenAI Math Release, September 23, 2026, result family 113, github.com/openai/math at commit adc7f12, Apache License 2.0) and ported to Lean 4.33.1 and Mathlib 0df444a. The declarations and their proofs are OpenAI's.
Contents. It holds 732 declarations of OpenAI's Lean: 374 definitions, 11 inductive types or structures, 15 instances and 332 theorems. The definitions and types are OAI.MatchingFPRAS.ExecutableSource.logicalRepr, OAI.MatchingFPRAS.ExecutableUnit.resultRep, OAI.MatchingFPRAS.FiniteTrial.estimateMatrix, OAI.MatchingFPRAS.FiniteTrial.probeMatrix, OAI.MatchingFPRAS.FixedAlphabetCompiler.word, OAI.MatchingFPRAS.GraphBridge.perfectEquiv, OAI.MatchingFPRAS.Initializer.fillFixed, OAI.MatchingFPRAS.Initializer.holesPairingEquiv, OAI.MatchingFPRAS.Initializer.restrictHoles, OAI.MatchingFPRAS.LiteralAlgorithm.empty, OAI.MatchingFPRAS.LiteralAlgorithm.invalid, OAI.MatchingFPRAS.LiteralAlgorithm.materialize, OAI.MatchingFPRAS.LiteralCodec.ratWord, OAI.MatchingFPRAS.LiteralInput.Parsed, OAI.MatchingFPRAS.LiteralInput.fromNumbers, OAI.MatchingFPRAS.LiteralInput.parseInput, OAI.MatchingFPRAS.LiteralInput.ratTail, OAI.MatchingFPRAS.LiteralPacked.Row, OAI.MatchingFPRAS.LiteralPacked.baseRow, OAI.MatchingFPRAS.LiteralPacked.bitRow, OAI.MatchingFPRAS.LiteralPacked.block, OAI.MatchingFPRAS.LiteralPacked.bottom, OAI.MatchingFPRAS.LiteralPacked.header, OAI.MatchingFPRAS.LiteralPacked.letter, OAI.MatchingFPRAS.LiteralPacked.width, OAI.MatchingFPRAS.LiteralPhysical.erase, OAI.MatchingFPRAS.LiteralPhysical.eraseTime, OAI.MatchingFPRAS.LiteralTape.Exec, OAI.MatchingFPRAS.LiteralTape.states, OAI.MatchingFPRAS.LiteralTape.table, OAI.MatchingFPRAS.Marking.completionEquiv, OAI.MatchingFPRAS.Marking.conditional, OAI.MatchingFPRAS.NumericLadder.instDecidableEqBagPM, OAI.MatchingFPRAS.NumericMarking.Summaries, OAI.MatchingFPRAS.NumericMarking.UpdateConfig, OAI.MatchingFPRAS.NumericMarking.logicalProbes, OAI.MatchingFPRAS.OnlineControl.At, OAI.MatchingFPRAS.OnlineControl.Instr, OAI.MatchingFPRAS.OnlineControl.Label, OAI.MatchingFPRAS.OnlineControl.cfg and 345 more.
Sources. They come from these modules of lean/OAI/Combinatorics/MatchingCount, in whole or in part: MatchingCount_Algorithm_AffineWeights, MatchingCount_Algorithm_Algorithm, MatchingCount_Algorithm_FiniteStage, MatchingCount_Algorithm_OnlineCoolingSchedule, MatchingCount_Algorithm_OnlineGuard, MatchingCount_Algorithm_OnlineGuardLaw, MatchingCount_Algorithm_OnlineInitial, MatchingCount_Algorithm_OnlineLaw, MatchingCount_Algorithm_OnlineMedian, MatchingCount_Algorithm_OnlinePowerSearch, MatchingCount_Algorithm_OnlineSampleCount, MatchingCount_Algorithm_OnlineTransitionLaw, MatchingCount_Algorithm_OutputLengthBound, MatchingCount_Algorithm_RationalEstimator, MatchingCount_Algorithm_RationalObservables, MatchingCount_Algorithm_RationalStart, MatchingCount_Algorithm_RelabelWeights, MatchingCount_Algorithm_TreeNumericSummaries, MatchingCount_Arithmetic_ArithmeticSize, MatchingCount_Arithmetic_OnlineFractionParam, MatchingCount_Arithmetic_TreeFraction, MatchingCount_Complexity_TreeFractionCosts, MatchingCount_Graphs_Admissible, MatchingCount_Graphs_ColoredEdge, MatchingCount_Graphs_Cycle, MatchingCount_Graphs_Edge, MatchingCount_Graphs_Edge2, MatchingCount_Graphs_EdgeLow, MatchingCount_Graphs_EnlargementRun, MatchingCount_Graphs_Evolve, MatchingCount_Graphs_FillHoles, MatchingCount_Graphs_Height, MatchingCount_Graphs_HoleBlocks, MatchingCount_Graphs_Incident, MatchingCount_Graphs_IndexedCycle, MatchingCount_Graphs_LabelCycle, MatchingCount_Graphs_LabelOrder, MatchingCount_Graphs_Marked, MatchingCount_Graphs_MatchingMap, MatchingCount_Graphs_OnlineGraphInvariant, MatchingCount_Graphs_PM, MatchingCount_Graphs_Profile, MatchingCount_Graphs_RatWeight, MatchingCount_Graphs_RelabelMore, MatchingCount_Graphs_Related, MatchingCount_Graphs_Related2, MatchingCount_Graphs_RemainingBags, MatchingCount_Graphs_SafeSwitch, MatchingCount_Graphs_SafeTrace, MatchingCount_Graphs_Sets, MatchingCount_Graphs_SumLiftMate, MatchingCount_Graphs_TreeCycleTable, MatchingCount_Graphs_TreeGeometry, MatchingCount_Graphs_TreeMatchingCheck, MatchingCount_Machines_OnlineBounds, MatchingCount_Machines_OnlineCase, MatchingCount_Machines_OnlineControl, MatchingCount_Machines_OnlineFold, MatchingCount_Machines_OnlineFrame, MatchingCount_Machines_OnlineTree, MatchingCount_Machines_PhysicalPost, MatchingCount_Machines_PhysicalProcess, MatchingCount_Machines_PhysicalProgram, MatchingCount_Machines_PhysicalRestriction, MatchingCount_Machines_PhysicalSequential, MatchingCount_Machines_TreeCertify, MatchingCount_Machines_TreePairProposal, MatchingCount_Machines_TreePostRealization, MatchingCount_Machines_Wrapper, MatchingCount_Probability_LocalVariance, MatchingCount_Probability_Tv, MatchingCount_Probability_Variance, MatchingCount_Sampling_AssignmentEquiv, MatchingCount_Sampling_Certify, MatchingCount_Sampling_ChosenChord, MatchingCount_Sampling_Component, MatchingCount_Sampling_ComponentOrder, MatchingCount_Sampling_Components, MatchingCount_Sampling_Corner, MatchingCount_Sampling_DiscreteLadderSteps, MatchingCount_Sampling_EndpointPair, MatchingCount_Sampling_Endpoints, MatchingCount_Sampling_IntervalPattern, MatchingCount_Sampling_LadderL, MatchingCount_Sampling_MarkBridge, MatchingCount_Sampling_PM, MatchingCount_Sampling_Plan, MatchingCount_Sampling_RankOrder, MatchingCount_Sampling_Relabel, MatchingCount_Sampling_RelabelMarking, MatchingCount_Sampling_RelationDestinations, MatchingCount_Sampling_Sewn, MatchingCount_Sampling_Span, MatchingCount_Sampling_Sym2Order, MatchingCount_Sampling_TableMarking, MatchingCount_Sampling_Through, MatchingCount_Sampling_TierClamp, MatchingCount_Sampling_TreeLadder, MatchingCount_Sampling_TreeUnitAssemble, MatchingCount_Sampling_Underlying, MatchingCount_Tapes_Codec, MatchingCount_Tapes_FixedAlphabetCompiler, MatchingCount_Tapes_Input, MatchingCount_Tapes_Online, MatchingCount_Tapes_OnlineComposition, MatchingCount_Tapes_OnlineStackCompiler, MatchingCount_Tapes_Packed, MatchingCount_Tapes_Physical, MatchingCount_Tapes_PhysicalAlphabet, MatchingCount_Tapes_StackWords, MatchingCount_Tapes_TapeTools.
Imports. It imports the published bundle Def_MatchingFPRAS; the bundles OAIQ051M000 and OAIQ051M001 of this split.
Imported by (directly, in this split): the bundle OAIQ051M004.
import Mathlib
import Definitions.Def_MatchingFPRAS
import Definitions.Def_OAIQ051M000
import Definitions.Def_OAIQ051M001
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Edge
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Switching
open Finset
open scoped Classical symmDiff
variable {V : Type*}
theorem withEdge_holes [DecidableEq V] (m : Mate V) (S : Finset V)
(hm : HasHoles m S) (a b : V) (ha : a ∈ S) (hb : b ∈ S) (hab : a ≠ b) :
HasHoles (withEdge m a b) (S \ {a, b}) := by
classical
intro v
rw [withEdge_apply m a b v ((hm a).mpr ha) ((hm b).mpr hb)]
by_cases hva : v = a
· subst v
simp [hab, Ne.symm hab]
by_cases hvb : v = b
· subst v
simp [hab, Ne.symm hab]
simp [hva, hvb, hm v]
theorem rowMax_attained [Fintype V] [LinearOrder V]
(hcard : 2 ≤ Fintype.card V) (w : V → V → ℝ) (a : V) :
∃ b, b ≠ a ∧ holeRatio w {a,b} = rowMax hcard w a := by
unfold rowMax
obtain ⟨b,hb,he⟩ := Finset.exists_mem_eq_sup'
(show (Finset.univ.erase a).Nonempty by
apply Finset.card_pos.mp
rw [Finset.card_erase_of_mem (Finset.mem_univ a), Finset.card_univ]
omega) (fun b => holeRatio w {a,b})
exact ⟨b,(Finset.mem_erase.mp hb).1,he.symm⟩
end MatchingFPRAS.Switching
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_AffineWeights
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Switching
open Finset
open scoped Classical symmDiff
variable {V : Type*}
noncomputable def holeAugmentation [Fintype V] [LinearOrder V]
(w : V → V → ℝ) (a b : V) : ℝ := bottleneck w a b / holeScale V
end MatchingFPRAS.Switching
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_FixedAlphabetCompiler
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.FixedAlphabetCompiler
open Turing MachineCost
open scoped Classical
variable {Γ Λ σ : Type*} [Inhabited Γ] [Fintype Γ] [Inhabited Λ]
[Inhabited σ] [Fintype σ]
variable {w : ℕ} (enc : Γ → List.Vector Bool w) (dec : List.Vector Bool w → Γ)
(enc0 : enc default = List.Vector.replicate w false)
(encdec : ∀ a,dec (enc a)=a) (M : Λ → TM1.Stmt Γ Λ σ)
(S : Finset Λ) (hS : TM1.Supports M S)
def word (input : List Γ) : List Symbol := (bitsWord enc input).map BoolPostCompiler.up
end MatchingFPRAS.FixedAlphabetCompiler
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_StackWords
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.StackWords
open Turing MachineCost
variable {K : Type*} {Γ : K → Type*}
variable {Λ σ : Type*} [Inhabited Λ] [Inhabited σ]
variable [DecidableEq K] [Fintype K] [∀ k,Fintype (Γ k)] [Fintype σ]
variable {w : ℕ} (enc : TM2to1.Γ' K Γ → List.Vector Bool w)
(dec : List.Vector Bool w → TM2to1.Γ' K Γ)
(enc0 : enc default=List.Vector.replicate w false)
(encdec : ∀ a,dec (enc a)=a)
(M : Λ → TM2.Stmt Γ Λ σ) (S : Finset Λ) (hs : TM2.Supports M S)
def encoded (S₀ : ∀ k,List (Γ k)) (H : ℕ) : List Symbol :=
FixedAlphabetCompiler.word enc (word S₀ H)
end MatchingFPRAS.StackWords
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_ColoredEdge
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V L : Type*}
namespace ColoredEdge
variable (e : ColoredEdge V L)
lemma exists_incident : ∃ v, e.Incident v := by
change ∃ v, v ∈ e.val.1
exact Sym2.inductionOn e.val.1 fun a b => ⟨a, by simp⟩
end ColoredEdge
namespace BagEdge
variable {bags : V → Finset L}
lemma exists_incident (e : BagEdge bags) : ∃ v, e.Incident v := e.val.exists_incident
end BagEdge
variable {E : Type*} [DecidableEq V] [DecidableEq E] (inc : E → V → Prop)
namespace MatchingOn
variable {inc} {M P Q : Finset E} {U W : Finset V}
omit [DecidableEq V] [DecidableEq E] in
lemma unique (hM : MatchingOn inc M U) {v : V} (hv : v ∈ U)
{e f : E} (he : e ∈ M) (hev : inc e v) (hf : f ∈ M) (hfv : inc f v) : e = f := by
obtain ⟨g, _, hg⟩ := hM.2 v hv
exact (hg e ⟨he, hev⟩).trans (hg f ⟨hf, hfv⟩).symm
omit [DecidableEq V] [DecidableEq E] in
lemma edge_mem_of_incident (hM : MatchingOn inc M U) (hP : MatchingOn inc P W)
(hsub : P ⊆ M) {e : E} (he : e ∈ M) {v : V} (hv : v ∈ W) (hev : inc e v) : e ∈ P := by
obtain ⟨f, ⟨hf, hfv⟩, _⟩ := hP.2 v hv
have eq : e = f := hM.unique (hM.1 e he v hev) he hev (hsub hf) hfv
exact eq ▸ hf
omit [DecidableEq V] [DecidableEq E] in
lemma disjoint_edges (hM : MatchingOn inc M U) (hP : MatchingOn inc P W)
(hinc : ∀ e, ∃ v, inc e v) (hdis : Disjoint U W) : Disjoint M P := by
apply Finset.disjoint_left.mpr
intro e he hf
obtain ⟨v, hv⟩ := hinc e
exact Finset.disjoint_left.mp hdis (hM.1 e he v hv) (hP.1 e hf v hv)
lemma union (hM : MatchingOn inc M U) (hP : MatchingOn inc P W)
(hdis : Disjoint U W) : MatchingOn inc (M ∪ P) (U ∪ W) := by
refine ⟨?_, ?_⟩
· intro e he v hev
rcases Finset.mem_union.mp he with he | he
· exact Finset.mem_union_left _ (hM.1 e he v hev)
· exact Finset.mem_union_right _ (hP.1 e he v hev)
· intro v hv
rcases Finset.mem_union.mp hv with hv | hv
· obtain ⟨e, ⟨he, hev⟩, hu⟩ := hM.2 v hv
refine ⟨e, ⟨Finset.mem_union_left _ he, hev⟩, ?_⟩
intro f hf
rcases Finset.mem_union.mp hf.1 with hfM | hfP
· exact hu f ⟨hfM, hf.2⟩
· exact False.elim (Finset.disjoint_left.mp hdis hv (hP.1 f hfP v hf.2))
· obtain ⟨e, ⟨he, hev⟩, hu⟩ := hP.2 v hv
refine ⟨e, ⟨Finset.mem_union_right _ he, hev⟩, ?_⟩
intro f hf
rcases Finset.mem_union.mp hf.1 with hfM | hfP
· exact False.elim (Finset.disjoint_left.mp hdis (hM.1 f hfM v hf.2) hv)
· exact hu f ⟨hfP, hf.2⟩
lemma sdiff (hM : MatchingOn inc M U) (hP : MatchingOn inc P W) (hsub : P ⊆ M) :
MatchingOn inc (M \ P) (U \ W) := by
refine ⟨?_, ?_⟩
· intro e he v hev
obtain ⟨heM, heP⟩ := Finset.mem_sdiff.mp he
refine Finset.mem_sdiff.mpr ⟨hM.1 e heM v hev, ?_⟩
intro hv
exact heP (hM.edge_mem_of_incident hP hsub heM hv hev)
· intro v hv
obtain ⟨hvU, hvW⟩ := Finset.mem_sdiff.mp hv
obtain ⟨e, ⟨he, hev⟩, hu⟩ := hM.2 v hvU
have heP : e ∉ P := fun hp => hvW (hP.1 e hp v hev)
refine ⟨e, ⟨Finset.mem_sdiff.mpr ⟨he, heP⟩, hev⟩, ?_⟩
intro f hf
exact hu f ⟨(Finset.mem_sdiff.mp hf.1).1, hf.2⟩
lemma replace (hM : MatchingOn inc M U) (hP : MatchingOn inc P W)
(hQ : MatchingOn inc Q W) (hsub : P ⊆ M) (hWU : W ⊆ U) :
MatchingOn inc ((M \ P) ∪ Q) U := by
have h := (hM.sdiff hP hsub).union hQ Finset.sdiff_disjoint
simpa only [Finset.sdiff_union_of_subset hWU] using h
lemma context_disjoint (hM : MatchingOn inc M U) (hP : MatchingOn inc P W)
(hQ : MatchingOn inc Q W) (hsub : P ⊆ M)
(hinc : ∀ e, ∃ v, inc e v) : Disjoint (M \ P) Q :=
(hM.sdiff hP hsub).disjoint_edges hQ hinc Finset.sdiff_disjoint
end MatchingOn
lemma pattern_interchange {M N P Q : Finset E} {U W : Finset V}
(hM : MatchingOn inc M U) (hN : MatchingOn inc N U)
(hP : MatchingOn inc P W) (hQ : MatchingOn inc Q W)
(hPM : P ⊆ M) (hQN : Q ⊆ N) (hWU : W ⊆ U)
(hinc : ∀ e, ∃ v, inc e v) :
MatchingOn inc ((M \ P) ∪ Q) U ∧
MatchingOn inc ((N \ Q) ∪ P) U ∧
((M \ P) ∪ Q).val + ((N \ Q) ∪ P).val = M.val + N.val := by
refine ⟨hM.replace hP hQ hPM hWU, hN.replace hQ hP hQN hWU, ?_⟩
rw [union_val_add (hM.context_disjoint hP hQ hPM hinc),
union_val_add (hN.context_disjoint hQ hP hQN hinc)]
calc
_ = ((M \ P).val + P.val) + ((N \ Q).val + Q.val) := by ac_rfl
_ = _ := by rw [sdiff_val_add hPM, sdiff_val_add hQN]
lemma pathPattern_matching (vertices : ℕ → V) (edges : ℕ → E) (lo hi : ℕ)
(hlohi : lo < hi) (hodd : (hi - lo) % 2 = 1)
(hinj : Set.InjOn vertices (Set.Icc lo hi))
(hedges : ∀ i, lo ≤ i → i < hi →
∀ v, inc (edges i) v ↔ v = vertices i ∨ v = vertices (i + 1)) :
MatchingOn inc (pathPattern edges lo hi) ((Finset.Icc lo hi).image vertices) := by
classical
refine ⟨?_, ?_⟩
· intro e he v hv
obtain ⟨i, hi', rfl⟩ := Finset.mem_image.mp he
obtain ⟨hirange, hiParity⟩ := Finset.mem_filter.mp hi'
obtain ⟨hil, hih⟩ := Finset.mem_Ico.mp hirange
rcases (hedges i hil hih v).mp hv with rfl | rfl
· exact Finset.mem_image.mpr ⟨i, Finset.mem_Icc.mpr ⟨hil, by omega⟩, rfl⟩
· exact Finset.mem_image.mpr ⟨i + 1, Finset.mem_Icc.mpr ⟨by omega, by omega⟩, rfl⟩
· intro v hv
obtain ⟨k, hkrange, rfl⟩ := Finset.mem_image.mp hv
obtain ⟨hkl, hkh⟩ := Finset.mem_Icc.mp hkrange
have hex : ∃ i, lo ≤ i ∧ i < hi ∧ i % 2 = lo % 2 ∧ (k = i ∨ k = i + 1) := by
by_cases hk : k % 2 = lo % 2
· exact ⟨k, hkl, by omega, hk, Or.inl rfl⟩
· exact ⟨k - 1, by omega, by omega, by omega, Or.inr (by omega)⟩
obtain ⟨i, hil, hih, hip, hki⟩ := hex
have hem : edges i ∈ pathPattern edges lo hi :=
Finset.mem_image.mpr ⟨i, Finset.mem_filter.mpr ⟨Finset.mem_Ico.mpr ⟨hil, hih⟩, hip⟩, rfl⟩
have hev : inc (edges i) (vertices k) := by
apply (hedges i hil hih _).mpr
exact hki.imp (congrArg vertices) (congrArg vertices)
refine ⟨edges i, ⟨hem, hev⟩, ?_⟩
intro f hf
obtain ⟨j, hj', rfl⟩ := Finset.mem_image.mp hf.1
obtain ⟨hjrange, hjp⟩ := Finset.mem_filter.mp hj'
obtain ⟨hjl, hjh⟩ := Finset.mem_Ico.mp hjrange
have hkj : k = j ∨ k = j + 1 := by
rcases (hedges j hjl hjh _).mp hf.2 with h | h
· exact Or.inl (hinj ⟨hkl, hkh⟩ ⟨hjl, by omega⟩ h)
· exact Or.inr (hinj ⟨hkl, hkh⟩ ⟨by omega, by omega⟩ h)
have hji : j = i := by omega
exact congrArg edges hji
omit [DecidableEq E] in
lemma singleton_matching (e : E) (a b : V)
(he : ∀ v, inc e v ↔ v = a ∨ v = b) : MatchingOn inc {e} {a, b} := by
classical
refine ⟨?_, ?_⟩
· intro f hf v hv
have hf' : f = e := Finset.mem_singleton.mp hf
subst f
simpa only [Finset.mem_insert, Finset.mem_singleton] using (he v).mp hv
· intro v hv
refine ⟨e, ⟨Finset.mem_singleton_self _, ?_⟩, ?_⟩
· apply (he v).mpr
simpa only [Finset.mem_insert, Finset.mem_singleton] using hv
· intro f hf
exact Finset.mem_singleton.mp hf.1
omit [DecidableEq V] [DecidableEq E] in
lemma empty_matching : MatchingOn inc ∅ ∅ := by simp [MatchingOn]
lemma repairedThrough_matching (vertices : ℕ → V) (edges : ℕ → E) (lo hi : ℕ)
(hlong : lo + 3 ≤ hi) (hodd : (hi - lo) % 2 = 1)
(hinj : Set.InjOn vertices (Set.Icc lo hi))
(hedges : ∀ i, lo ≤ i → i < hi →
∀ v, inc (edges i) v ↔ v = vertices i ∨ v = vertices (i + 1))
(repair : E)
(hrepair : ∀ v, inc repair v ↔ v = vertices (lo + 1) ∨ v = vertices (hi - 1)) :
MatchingOn inc (pathPattern edges (lo + 2) (hi - 2) ∪ {repair})
((Finset.Icc (lo + 1) (hi - 1)).image vertices) := by
have hT : MatchingOn inc (pathPattern edges (lo + 2) (hi - 2))
((Finset.Icc (lo + 2) (hi - 2)).image vertices) := by
by_cases h : lo + 2 < hi - 2
· apply pathPattern_matching inc vertices edges (lo + 2) (hi - 2) h
· omega
· intro i hi' j hj' heq
simp only [Set.mem_Icc] at hi' hj'
exact hinj ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ heq
· intro i hi' hi'' v
exact hedges i (by omega) (by omega) v
· have hl : hi - 2 < lo + 2 := by omega
have he : Finset.Ico (lo + 2) (hi - 2) = ∅ := Finset.Ico_eq_empty_of_le (by omega)
have he' : Finset.Icc (lo + 2) (hi - 2) = ∅ := Finset.Icc_eq_empty_of_lt hl
simpa [pathPattern, he, he'] using (empty_matching (V := V) (E := E) inc)
have hc := singleton_matching inc repair (vertices (lo + 1)) (vertices (hi - 1)) hrepair
have hd : Disjoint ((Finset.Icc (lo + 2) (hi - 2)).image vertices)
{vertices (lo + 1), vertices (hi - 1)} := by
apply Finset.disjoint_left.mpr
intro v hv hw
obtain ⟨i, hi', rfl⟩ := Finset.mem_image.mp hv
have hir := Finset.mem_Icc.mp hi'
rcases Finset.mem_insert.mp hw with h | h
· have heq := hinj ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ h
omega
· have heq := hinj ⟨by omega, by omega⟩ ⟨by omega, by omega⟩
(Finset.mem_singleton.mp h)
omega
have hs : ((Finset.Icc (lo + 2) (hi - 2)).image vertices) ∪
{vertices (lo + 1), vertices (hi - 1)} =
(Finset.Icc (lo + 1) (hi - 1)).image vertices := by
ext v
simp only [Finset.mem_union, Finset.mem_image, Finset.mem_Icc,
Finset.mem_insert, Finset.mem_singleton]
constructor
· rintro (⟨i, hi', rfl⟩ | h | h)
· exact ⟨i, ⟨by omega, by omega⟩, rfl⟩
· exact ⟨lo + 1, ⟨le_rfl, by omega⟩, h.symm⟩
· exact ⟨hi - 1, ⟨by omega, le_rfl⟩, h.symm⟩
· rintro ⟨i, hi', rfl⟩
by_cases hl : i = lo + 1
· exact Or.inr (Or.inl (congrArg vertices hl))
by_cases hh : i = hi - 1
· exact Or.inr (Or.inr (congrArg vertices hh))
exact Or.inl ⟨i, ⟨by omega, by omega⟩, rfl⟩
simpa only [hs] using hT.union hc hd
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Span
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V L : Type*} [DecidableEq V]
variable {E : Type*} [DecidableEq E] (inc : E → V → Prop)
namespace OddPath
variable {inc}
variable (p : OddPath inc)
lemma through_matching : MatchingOn inc p.through p.span := by
apply pathPattern_matching inc p.vertex p.edge 0 p.length p.positive
· simpa using p.odd
· exact p.simple
· intro i _ hi v
exact p.incidence i hi v
lemma interior_matching : MatchingOn inc p.interior p.inside := by
by_cases h : p.length = 1
· simpa [interior, inside, h, pathPattern] using
(empty_matching (V := V) (E := E) inc)
· have hpos := p.positive
have hodd := p.odd
apply pathPattern_matching inc p.vertex p.edge 1 (p.length - 1)
· omega
· omega
· intro i hi j hj heq
simp only [Set.mem_Icc] at hi hj
exact p.simple ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ heq
· intro i hi hj v
exact p.incidence i (by omega) v
lemma closed_matching (chord : E)
(hc : ∀ v, inc chord v ↔ v = p.vertex 0 ∨ v = p.vertex p.length) :
MatchingOn inc (p.closed chord) p.span := by
have hm := p.interior_matching.union (singleton_matching inc chord _ _ hc)
p.inside_disjoint_ends
change MatchingOn inc (p.closed chord) (p.inside ∪ p.ends) at hm
rwa [p.inside_union_ends] at hm
lemma repaired_matching (repair : E)
(hr : p.length ≠ 1 → ∀ v,
inc repair v ↔ v = p.vertex 1 ∨ v = p.vertex (p.length - 1)) :
MatchingOn inc (p.repaired repair) p.inside := by
by_cases h : p.length = 1
· simpa [repaired, inside, h] using (empty_matching (V := V) (E := E) inc)
· have hpos := p.positive
have hodd := p.odd
simp only [repaired, ite_eq_right h]
simpa only [Nat.zero_add, inside] using repairedThrough_matching inc p.vertex p.edge 0
p.length (by omega) (by simpa using p.odd) p.simple
(fun i _ hi v => p.incidence i hi v) repair (hr h)
lemma closed_val (chord : E)
(hc : ∀ v, inc chord v ↔ v = p.vertex 0 ∨ v = p.vertex p.length)
(hinc : ∀ e, ∃ v, inc e v) :
(p.closed chord).val = p.interior.val + {chord} := by
apply union_val_add
exact p.interior_matching.disjoint_edges (singleton_matching inc chord _ _ hc)
hinc p.inside_disjoint_ends
omit [DecidableEq V] in
lemma repair_conservation (repair : E)
(hr : p.length ≠ 1 → ∀ v,
inc repair v ↔ v = p.vertex 1 ∨ v = p.vertex (p.length - 1))
(_hinc : ∀ e, ∃ v, inc e v) :
(p.repaired repair).val + p.boundary.val = p.through.val + p.repairAdded repair := by
by_cases h : p.length = 1
· have ht : p.through = {p.edge 0} := by simp [through, pathPattern, h, Finset.filter_singleton]
simp only [repaired, boundary, repairAdded, ite_eq_left h, ht, Finset.empty_val,
zero_add, add_zero]
· have hpos := p.positive
have hodd := p.odd
have hlen : 3 ≤ p.length := by omega
let trim := pathPattern p.edge 2 (p.length - 2)
have ht : p.through = trim ∪ p.boundary := by
simpa only [through, trim, Nat.zero_add, boundary, ite_eq_right h] using
pathPattern_boundary p.edge 0 p.length hlen (by simpa using hodd)
have hbdis : Disjoint trim p.boundary := by
apply Finset.disjoint_left.mpr
intro e he hb
obtain ⟨i, hi, rfl⟩ := Finset.mem_image.mp he
obtain ⟨hi, _⟩ := Finset.mem_filter.mp hi
obtain ⟨hil, hih⟩ := Finset.mem_Ico.mp hi
simp only [boundary, ite_eq_right h, Finset.mem_insert, Finset.mem_singleton] at hb
rcases hb with hh | hh
· have hh' := p.edge_injective ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ hh
omega
· have hh' := p.edge_injective ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ hh
omega
have hrdis : Disjoint trim {repair} := by
apply Finset.disjoint_left.mpr
intro e he hr'
obtain ⟨i, hi, rfl⟩ := Finset.mem_image.mp he
obtain ⟨hi, _⟩ := Finset.mem_filter.mp hi
obtain ⟨hil, hih⟩ := Finset.mem_Ico.mp hi
have heq := Finset.mem_singleton.mp hr'
have hiinc : inc repair (p.vertex i) := by
rw [← heq]
exact (p.incidence i (by omega) _).mpr (Or.inl rfl)
rcases (hr h _).mp hiinc with hh | hh
· have hh' := p.simple ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ hh
omega
· have hh' := p.simple ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ hh
omega
rw [ht, union_val_add hbdis]
simp only [repaired, ite_eq_right h, repairAdded]
rw [union_val_add hrdis]
simp only [Finset.singleton_val]
ac_rfl
end OddPath
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Corner
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V L : Type*} [DecidableEq V]
variable {E : Type*} [DecidableEq E] (inc : E → V → Prop)
namespace CellPaths
variable {inc} (c : CellPaths inc)
lemma matching_even_full (M : Fin 4 → Finset E)
(h0 : MatchingOn inc (M 0) (c.side 0).span)
(h2 : MatchingOn inc (M 2) (c.side 2).span)
(h1 : MatchingOn inc (M 1) (c.side 1).inside)
(h3 : MatchingOn inc (M 3) (c.side 3).inside) :
MatchingOn inc (assemble M) c.vertices := by
have h02 := h0.union h2 c.opposite_span_even
have h13 := h1.union h3 (c.interiors_disjoint (by decide : (1 : Fin 4) ≠ 3))
have hd : Disjoint ((c.side 0).span ∪ (c.side 2).span)
((c.side 1).inside ∪ (c.side 3).inside) := by
simp only [Finset.disjoint_union_left, Finset.disjoint_union_right]
exact ⟨⟨(c.inside_disjoint_span 1 0 (by decide)).symm,
(c.inside_disjoint_span 1 2 (by decide)).symm⟩,
⟨(c.inside_disjoint_span 3 0 (by decide)).symm,
(c.inside_disjoint_span 3 2 (by decide)).symm⟩⟩
simpa only [c.even_blocks_union, assemble] using h02.union h13 hd
lemma matching_odd_full (M : Fin 4 → Finset E)
(h0 : MatchingOn inc (M 0) (c.side 0).inside)
(h2 : MatchingOn inc (M 2) (c.side 2).inside)
(h1 : MatchingOn inc (M 1) (c.side 1).span)
(h3 : MatchingOn inc (M 3) (c.side 3).span) :
MatchingOn inc (assemble M) c.vertices := by
have h02 := h0.union h2 (c.interiors_disjoint (by decide : (0 : Fin 4) ≠ 2))
have h13 := h1.union h3 c.opposite_span_odd
have hd : Disjoint ((c.side 0).inside ∪ (c.side 2).inside)
((c.side 1).span ∪ (c.side 3).span) := by
simp only [Finset.disjoint_union_left, Finset.disjoint_union_right]
exact ⟨⟨c.inside_disjoint_span 0 1 (by decide), c.inside_disjoint_span 2 1 (by decide)⟩,
⟨c.inside_disjoint_span 0 3 (by decide), c.inside_disjoint_span 2 3 (by decide)⟩⟩
have hs : ((c.side 0).inside ∪ (c.side 2).inside) ∪
((c.side 1).span ∪ (c.side 3).span) = c.vertices :=
(Finset.union_comm _ _).trans c.odd_blocks_union
simpa only [hs, assemble] using h02.union h13 hd
omit [DecidableEq E] in
lemma blocks_disjoint (b : Bool) : Pairwise fun i j => Disjoint (c.blocks b i) (c.blocks b j) := by
intro i j hij
by_cases hi : sideBit i = b <;> by_cases hj : sideBit j = b
· simp only [blocks, ite_eq_left hi, ite_eq_left hj]
exact c.same_bit_spans i j hij (hi.trans hj.symm)
· simp only [blocks, ite_eq_left hi, ite_eq_right hj]
exact (c.inside_disjoint_span j i hij.symm).symm
· simp only [blocks, ite_eq_right hi, ite_eq_left hj]
exact c.inside_disjoint_span i j hij
· simp only [blocks, ite_eq_right hi, ite_eq_right hj]
exact c.interiors_disjoint hij
lemma assembled_matching (b : Bool) (M : Fin 4 → Finset E)
(hM : ∀ i, MatchingOn inc (M i) (c.blocks b i)) :
MatchingOn inc (assemble M) c.vertices := by
cases b
· apply c.matching_odd_full M <;> first
| simpa [blocks, sideBit] using hM 0
| simpa [blocks, sideBit] using hM 1
| simpa [blocks, sideBit] using hM 2
| simpa [blocks, sideBit] using hM 3
· apply c.matching_even_full M <;> first
| simpa [blocks, sideBit] using hM 0
| simpa [blocks, sideBit] using hM 1
| simpa [blocks, sideBit] using hM 2
| simpa [blocks, sideBit] using hM 3
lemma assemble_val (b : Bool) (M : Fin 4 → Finset E)
(hM : ∀ i, MatchingOn inc (M i) (c.blocks b i)) (hinc : ∀ e, ∃ v, inc e v) :
(assemble M).val = ∑ i, (M i).val := by
have hd (i j : Fin 4) (hij : i ≠ j) : Disjoint (M i) (M j) :=
(hM i).disjoint_edges (hM j) hinc (c.blocks_disjoint b hij)
have hu : Disjoint (M 0 ∪ M 2) (M 1 ∪ M 3) := by
simp only [Finset.disjoint_union_left, Finset.disjoint_union_right]
exact ⟨⟨hd 0 1 (by decide), hd 2 1 (by decide)⟩,
⟨hd 0 3 (by decide), hd 2 3 (by decide)⟩⟩
rw [assemble, union_val_add hu, union_val_add (hd 0 2 (by decide)),
union_val_add (hd 1 3 (by decide))]
rw [Fin.sum_univ_four]
ac_rfl
omit [DecidableEq E] in
lemma pieces_matching (b : Bool) (full inner : Fin 4 → Finset E)
(hf : ∀ i, sideBit i = b → MatchingOn inc (full i) (c.side i).span)
(hi : ∀ i, sideBit i ≠ b → MatchingOn inc (inner i) (c.side i).inside) :
∀ i, MatchingOn inc (pieces b full inner i) (c.blocks b i) := by
intro i
by_cases h : sideBit i = b
· simpa only [pieces, blocks, ite_eq_left h] using hf i h
· simpa only [pieces, blocks, ite_eq_right h] using hi i h
lemma orientation_pieces_matching (b : Bool) :
∀ i, MatchingOn inc (c.orientationPieces b i) (c.blocks b i) :=
c.pieces_matching b _ _ (fun i _ => (c.side i).through_matching)
(fun i _ => (c.side i).interior_matching)
lemma switch_pieces_matching (b : Bool) :
∀ i, MatchingOn inc (c.switchPieces b i) (c.blocks b i) :=
c.pieces_matching b _ _ (fun i _ => (c.side i).closed_matching _ (c.chord_incidence i))
(fun i _ => (c.side i).interior_matching)
lemma repair_pieces_matching (b : Bool) (repair : Fin 4 → E) (hr : c.Repairs b repair) :
∀ i, MatchingOn inc (c.repairPieces b repair i) (c.blocks b i) :=
c.pieces_matching b _ _ (fun i _ => (c.side i).through_matching)
(fun i hi => (c.side i).repaired_matching _ (hr i hi))
lemma guide_pieces_matching (b : Bool) (repair : Fin 4 → E) (hr : c.Repairs b repair) :
∀ i, MatchingOn inc (c.guidePieces b repair i) (c.blocks b i) :=
c.pieces_matching b _ _ (fun i _ => (c.side i).closed_matching _ (c.chord_incidence i))
(fun i hi => (c.side i).repaired_matching _ (hr i hi))
lemma orientation_matching (b : Bool) : MatchingOn inc (c.orientation b) c.vertices :=
c.assembled_matching b _ (c.orientation_pieces_matching b)
lemma switched_matching (b : Bool) : MatchingOn inc (c.switched b) c.vertices :=
c.assembled_matching b _ (c.switch_pieces_matching b)
lemma repaired_matching (b : Bool) (repair : Fin 4 → E) (hr : c.Repairs b repair) :
MatchingOn inc (c.repaired b repair) c.vertices :=
c.assembled_matching b _ (c.repair_pieces_matching b repair hr)
lemma guide_matching (b : Bool) (repair : Fin 4 → E) (hr : c.Repairs b repair) :
MatchingOn inc (c.guide b repair) c.vertices :=
c.assembled_matching b _ (c.guide_pieces_matching b repair hr)
lemma closed_subset_guide (b : Bool) (repair : Fin 4 → E) (i : Fin 4) (hi : sideBit i = b) :
(c.side i).closed (c.chord i) ⊆ c.guide b repair := by
have h := component_subset_assemble (c.guidePieces b repair) i
simpa only [guidePieces, pieces, ite_eq_left hi, guide] using h
lemma orientation_val (b : Bool) (hinc : ∀ e, ∃ v, inc e v) :
(c.orientation b).val = ∑ i, (c.orientationPieces b i).val :=
c.assemble_val b _ (c.orientation_pieces_matching b) hinc
lemma switched_val (b : Bool) (hinc : ∀ e, ∃ v, inc e v) :
(c.switched b).val = ∑ i, (c.switchPieces b i).val :=
c.assemble_val b _ (c.switch_pieces_matching b) hinc
lemma repaired_val (r : Bool) (repair : Fin 4 → E) (hr : c.Repairs r repair)
(hinc : ∀ e, ∃ v, inc e v) :
(c.repaired r repair).val = ∑ i, (c.repairPieces r repair i).val :=
c.assemble_val r _ (c.repair_pieces_matching r repair hr) hinc
lemma guide_val (b : Bool) (repair : Fin 4 → E) (hr : c.Repairs b repair)
(hinc : ∀ e, ∃ v, inc e v) :
(c.guide b repair).val = ∑ i, (c.guidePieces b repair i).val :=
c.assemble_val b _ (c.guide_pieces_matching b repair hr) hinc
lemma switch_piece_val (b : Bool) (i : Fin 4) (hinc : ∀ e, ∃ v, inc e v) :
(c.switchPieces b i).val = (c.side i).interior.val +
(if sideBit i = b then {c.chord i} else 0) := by
by_cases h : sideBit i = b
· simp only [switchPieces, pieces, ite_eq_left h]
exact (c.side i).closed_val _ (c.chord_incidence i) hinc
· simp [switchPieces, pieces, h]
lemma repair_piece_conservation (r : Bool) (repair : Fin 4 → E)
(hr : c.Repairs r repair) (i : Fin 4) (hinc : ∀ e, ∃ v, inc e v) :
(c.repairPieces r repair i).val +
(if sideBit i = r then 0 else (c.side i).boundary.val) =
(c.side i).through.val +
(if sideBit i = r then 0 else (c.side i).repairAdded (repair i)) := by
by_cases h : sideBit i = r
· simp [repairPieces, pieces, h]
· simp only [repairPieces, pieces, ite_eq_right h]
exact (c.side i).repair_conservation _ (hr i h) hinc
lemma switch_conservation (b r : Bool) (repair : Fin 4 → E)
(hr : c.Repairs r repair) (hinc : ∀ e, ∃ v, inc e v) :
(c.orientation true).val + (c.orientation false).val + c.additions b r repair =
(c.switched b).val + (c.repaired r repair).val + c.drops r := by
rw [c.orientation_val true hinc, c.orientation_val false hinc,
c.switched_val b hinc, c.repaired_val r repair hr hinc]
simp only [additions, drops, ← Finset.sum_add_distrib]
apply Finset.sum_congr rfl
intro i _
rw [c.two_orientation_pieces i, c.switch_piece_val b i hinc]
have h := c.repair_piece_conservation r repair hr i hinc
calc
_ = (c.side i).interior.val + (if sideBit i = b then {c.chord i} else 0) +
((c.side i).through.val +
(if sideBit i = r then 0 else (c.side i).repairAdded (repair i))) := by ac_rfl
_ = _ := by rw [← h]; ac_rfl
lemma guide_piece_conservation (b : Bool) (repair : Fin 4 → E)
(hr : c.Repairs b repair) (i : Fin 4) (hinc : ∀ e, ∃ v, inc e v) :
(c.orientationPieces b i).val + (c.guidePieces b repair i).val +
(if sideBit i = b then 0 else (c.side i).boundary.val) =
(c.side i).through.val + (c.side i).interior.val +
(if sideBit i = b then {c.chord i} else 0) +
(if sideBit i = b then 0 else (c.side i).repairAdded (repair i)) := by
by_cases h : sideBit i = b
· simp only [orientationPieces, guidePieces, pieces, ite_eq_left h, add_zero]
rw [(c.side i).closed_val _ (c.chord_incidence i) hinc]
ac_rfl
· simp only [orientationPieces, guidePieces, pieces, ite_eq_right h, add_zero]
have hh := (c.side i).repair_conservation _ (hr i h) hinc
calc
_ = (c.side i).interior.val +
((c.side i).repaired (repair i)).val + (c.side i).boundary.val := rfl
_ = _ := by rw [add_assoc, hh]; ac_rfl
lemma guide_conservation (b : Bool) (repair : Fin 4 → E)
(hr : c.Repairs b repair) (hinc : ∀ e, ∃ v, inc e v) :
(c.orientation true).val + (c.orientation false).val + c.additions b b repair =
(c.orientation b).val + (c.guide b repair).val + c.drops b := by
rw [c.orientation_val true hinc, c.orientation_val false hinc,
c.orientation_val b hinc, c.guide_val b repair hr hinc]
simp only [additions, drops, ← Finset.sum_add_distrib]
apply Finset.sum_congr rfl
intro i _
rw [c.two_orientation_pieces i]
have h := c.guide_piece_conservation b repair hr i hinc
simpa only [add_assoc] using h.symm
lemma through_subset_orientation (b : Bool) (i : Fin 4) (hi : sideBit i = b) :
(c.side i).through ⊆ c.orientation b := by
have h := component_subset_assemble (c.orientationPieces b) i
simpa only [orientationPieces, pieces, ite_eq_left hi, orientation] using h
lemma context_one_properties (b : Bool) (repair : Fin 4 → E) (hr : c.Repairs b repair)
(Y : Fin 4) (hY : sideBit Y = b) (hinc : ∀ e, ∃ v, inc e v) :
MatchingOn inc (c.contextOne b Y) c.vertices ∧
MatchingOn inc (c.guideOne b repair Y) c.vertices ∧
(c.contextOne b Y).val + (c.guideOne b repair Y).val =
(c.orientation b).val + (c.guide b repair).val := by
exact pattern_interchange inc (c.orientation_matching b) (c.guide_matching b repair hr)
(c.side Y).through_matching ((c.side Y).closed_matching _ (c.chord_incidence Y))
(c.through_subset_orientation b Y hY) (c.closed_subset_guide b repair Y hY)
(c.span_subset_vertices Y) hinc
lemma closed_subset_guide_one (b : Bool) (repair : Fin 4 → E) (X Y : Fin 4)
(hX : sideBit X = b) (hY : sideBit Y = b) (hXY : X ≠ Y)
(hinc : ∀ e, ∃ v, inc e v) :
(c.side X).closed (c.chord X) ⊆ c.guideOne b repair Y := by
have hdis := ((c.side X).closed_matching _ (c.chord_incidence X)).disjoint_edges
((c.side Y).closed_matching _ (c.chord_incidence Y)) hinc
(c.same_bit_spans X Y hXY (hX.trans hY.symm))
intro e he
exact Finset.mem_union_left _ <| Finset.mem_sdiff.mpr
⟨c.closed_subset_guide b repair X hX he, fun hh => Finset.disjoint_left.mp hdis he hh⟩
end CellPaths
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_IndexedCycle
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V E : Type*}
variable {inc : E → V → Prop}
namespace IndexedCycle
variable (c : IndexedCycle inc)
section
variable [Fintype V] [DecidableEq E]
lemma adjacent_mem_complement {M N : Finset E}
(hM : MatchingOn inc M Finset.univ) (hN : MatchingOn inc N Finset.univ)
(hU : ∀ i, c.edgeAt i ∈ M ∪ N) (i : ℕ) (hi : i < c.size) :
c.edgeAt (i+1) ∈ M ↔ c.edgeAt i ∉ M := by
have hein := (c.edgeAt_incidence i (c.vertexAt (i+1))).mpr (Or.inr rfl)
have hfin := (c.edgeAt_incidence (i+1) (c.vertexAt (i+1))).mpr (Or.inl rfl)
constructor
· intro hf he
exact c.consecutive_ne i hi (hM.unique (Finset.mem_univ _) he hein hf hfin)
· intro he
have heN := (Finset.mem_union.mp (hU i)).resolve_left he
rcases Finset.mem_union.mp (hU (i+1)) with hf | hf
· exact hf
· exact False.elim (c.consecutive_ne i hi (hN.unique (Finset.mem_univ _) heN hein hf hfin))
lemma cycle_edge_mem_complement {M N : Finset E}
(hM : MatchingOn inc M Finset.univ) (hN : MatchingOn inc N Finset.univ)
(hU : ∀ i, c.edgeAt i ∈ M ∪ N) (i : ℕ) :
c.edgeAt i ∈ N ↔ c.edgeAt i ∉ M := by
have hm : i % c.size < c.size := Nat.mod_lt i (by have := c.four_le; omega)
have heq := c.edgeAt_mod i
have h := c.adjacent_mem_complement hM hN hU (i % c.size) hm
have hn := c.adjacent_mem_complement hN hM
(fun j => by rw [Finset.union_comm]; exact hU j) (i % c.size) hm
constructor
· intro hiN hiM
have hjM : c.edgeAt (i % c.size + 1) ∉ M := fun hj => (h.mp hj) (heq.symm ▸ hiM)
have hjN : c.edgeAt (i % c.size + 1) ∉ N := fun hj => (hn.mp hj) (heq.symm ▸ hiN)
exact (Finset.mem_union.mp (hU _)).elim hjM hjN
· intro hiM
exact (Finset.mem_union.mp (hU i)).resolve_left hiM
lemma cycle_edge_mem_parity {M N : Finset E}
(hM : MatchingOn inc M Finset.univ) (hN : MatchingOn inc N Finset.univ)
(hU : ∀ i, c.edgeAt i ∈ M ∪ N) (i : ℕ) :
c.edgeAt i ∈ M ↔ if i % 2 = 0 then c.edgeAt 0 ∈ M else c.edgeAt 0 ∉ M := by
have hb : ∀ j, j < c.size →
(c.edgeAt j ∈ M ↔ if j % 2 = 0 then c.edgeAt 0 ∈ M else c.edgeAt 0 ∉ M) := by
intro j hj
induction j with
| zero => simp
| succ j ih =>
rw [c.adjacent_mem_complement hM hN hU j (by omega), ih (by omega)]
split_ifs <;> first | omega | tauto
have hh := hb (i % c.size) (Nat.mod_lt i (by have := c.four_le; omega))
have hdiv : 2 ∣ c.size := Nat.dvd_of_mod_eq_zero c.even
have hmod : (i % c.size) % 2 = i % 2 := Nat.mod_mod_of_dvd i hdiv
simpa only [c.edgeAt_mod, hmod] using hh
end
end IndexedCycle
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Sets
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V E L : Type*}
namespace BagEdge
variable {bags : V → Finset L}
def color (e : BagEdge bags) : L := e.val.color
lemma color_mem (e : BagEdge bags) {v : V} (hv : e.Incident v) : e.color ∈ bags v :=
e.property v hv
def ofEndpoints (v w : V) (hvw : v ≠ w) (l : L)
(hlv : l ∈ bags v) (hlw : l ∈ bags w) : BagEdge bags :=
⟨⟨(s(v,w),l), by simpa using hvw⟩, by
intro u hu
change u ∈ s(v,w) at hu
change l ∈ bags u
rcases Sym2.mem_iff.mp hu with rfl | rfl
· exact hlv
· exact hlw⟩
lemma ofEndpoints_incidence (v w : V) (hvw : v ≠ w) (l : L)
(hlv : l ∈ bags v) (hlw : l ∈ bags w) (u : V) :
(ofEndpoints v w hvw l hlv hlw).Incident u ↔ u = v ∨ u = w :=
Sym2.mem_iff
lemma ofEndpoints_color (v w : V) (hvw : v ≠ w) (l : L)
(hlv : l ∈ bags v) (hlw : l ∈ bags w) :
(ofEndpoints v w hvw l hlv hlw).color = l := rfl
end BagEdge
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_LabelCycle
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V E L : Type*}
namespace IndexedCycle
variable {bags : V → Finset L}
variable (c : IndexedCycle (BagEdge.Incident (bags := bags)))
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
lemma current_color_mem (i : ℤ) : (c.edgeAtZ i).color ∈ bags (c.vertexAtZ i) :=
BagEdge.color_mem _ ((c.edgeAtZ_incidence i _).mpr (Or.inl rfl))
lemma previous_color_mem (i : ℤ) : (c.edgeAtZ (i-1)).color ∈ bags (c.vertexAtZ i) := by
apply BagEdge.color_mem
apply (c.edgeAtZ_incidence (i-1) _).mpr
right
congr 1
omega
def labelCycle : MatchingFPRAS.Cells.CycleData G c.size where
labels i := (c.edgeAtZ i).color
periodic i := by rw [c.edgeAtZ_periodic]
adjacent i := hbags (c.vertexAtZ i) _ (c.previous_color_mem i) _ (c.current_color_mem i)
variable [DecidableEq L]
lemma labelCycle_sets_subset (i : ℤ) : (c.labelCycle hbags).sets i ⊆ bags (c.vertexAtZ i) := by
intro l hl
simp only [MatchingFPRAS.Cells.CycleData.sets, labelCycle,
Finset.mem_insert, Finset.mem_singleton] at hl
rcases hl with rfl | rfl
· exact c.previous_color_mem i
· exact c.current_color_mem i
lemma labelSets_periodic (i : ℤ) :
(c.labelCycle hbags).sets (i+c.size) = (c.labelCycle hbags).sets i := by
have h : i + (c.size : ℤ) - 1 = (i-1) + c.size := by ring
simp only [MatchingFPRAS.Cells.CycleData.sets, labelCycle, h, c.edgeAtZ_periodic]
lemma edge_color_fixed (i : ℕ) :
(c.edgeAt i).color ∈ (c.labelCycle hbags).sets i ∧
(c.edgeAt i).color ∈ (c.labelCycle hbags).sets (i+1) := by
have h : (c.edgeAtZ (i : ℤ)).color ∈ (c.labelCycle hbags).sets (i : ℤ) ∧
(c.edgeAtZ (i : ℤ)).color ∈ (c.labelCycle hbags).sets ((i : ℤ)+1) := by
simp [MatchingFPRAS.Cells.CycleData.sets, labelCycle]
simpa only [c.edgeAtZ_nat] using h
noncomputable def chord (x y : ℕ) (hxy : x < y) (hy : y < c.size)
(ha : (c.labelCycle hbags).Admissible x y) : BagEdge bags := by
classical
exact if hshort : y = x+1 then c.edgeAt x
else if hwrap : x = 0 ∧ y+1 = c.size then c.edgeAt y
else
let l := ha.choose
BagEdge.ofEndpoints (c.vertexAt x) (c.vertexAt y)
(fun h => by
have := (c.vertexAt_eq_iff (a := 0) (by have := c.four_le; omega)
⟨by omega, by omega⟩ ⟨by omega, by omega⟩).mp h
omega) l
(by simpa [c.vertexAtZ_nat] using c.labelCycle_sets_subset hbags x ha.choose_spec.1)
(by simpa [c.vertexAtZ_nat] using c.labelCycle_sets_subset hbags y ha.choose_spec.2)
lemma chord_incidence (x y : ℕ) (hxy : x < y) (hy : y < c.size)
(ha : (c.labelCycle hbags).Admissible x y) (v : V) :
(c.chord hbags x y hxy hy ha).Incident v ↔ v = c.vertexAt x ∨ v = c.vertexAt y := by
classical
dsimp only [chord]
split_ifs with hshort hwrap
· simpa [hshort] using c.edgeAt_incidence x v
· rw [c.edgeAt_incidence]
have he : c.vertexAt (y+1) = c.vertexAt x := by
rw [hwrap.2, hwrap.1]
simpa using c.vertexAt_periodic 0
rw [he]
tauto
· exact BagEdge.ofEndpoints_incidence _ _ _ _ _ _ _
lemma chord_color_fixed (x y : ℕ) (hxy : x < y) (hy : y < c.size)
(ha : (c.labelCycle hbags).Admissible x y) :
(c.chord hbags x y hxy hy ha).color ∈ (c.labelCycle hbags).sets x ∧
(c.chord hbags x y hxy hy ha).color ∈ (c.labelCycle hbags).sets y := by
classical
dsimp only [chord]
split_ifs with hs hw
· simpa only [hs, Nat.cast_add, Nat.cast_one] using c.edge_color_fixed hbags x
· have hb := c.edge_color_fixed hbags y
refine ⟨?_, hb.1⟩
have he : (y : ℤ)+1 = (0 : ℤ)+c.size := by omega
rw [he, c.labelSets_periodic hbags] at hb
simpa only [hw.1, Nat.cast_zero] using hb.2
· exact ha.choose_spec
def cellCorners {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) : c.Corners where
a₀ := x
a₁ := p
a₂ := q
a₃ := y
lt₀ := hc.first_pos
lt₁ := hc.middle_pos
lt₂ := hc.third_pos
lt₃ := hy
odd₀ := hc.odd_first
odd₁ := hc.odd_middle
odd₂ := hc.odd_third
odd₃ := by
have he : c.size + x - y = c.size - (y-x) := by have := hc.first_pos; have := hc.middle_pos; have := hc.third_pos; omega
rw [he]
exact hc.odd_exterior
noncomputable def cellChords {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) : Fin 4 → BagEdge bags :=
![c.chord hbags x p hc.first_pos (by have := hc.middle_pos; have := hc.third_pos; omega) hc.first,
c.chord hbags p q hc.middle_pos (by have := hc.third_pos; omega) hc.middle,
c.chord hbags q y hc.third_pos hy hc.third,
c.chord hbags x y (by have := hc.first_pos; have := hc.middle_pos; have := hc.third_pos; omega)
hy (by obtain ⟨l, hly, hlx⟩ := hc.exterior; exact ⟨l,hlx,hly⟩)]
lemma cellChords_incidence {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (i : Fin 4) (v : V) :
(c.cellChords hbags hc hy i).Incident v ↔
v = ((c.cellCorners hbags hc hy).side i).vertex 0 ∨
v = ((c.cellCorners hbags hc hy).side i).vertex
((c.cellCorners hbags hc hy).side i).length := by
simp only [Corners.side_first, Corners.side_last]
have hper : c.vertexAt (c.size+x) = c.vertexAt x := by
simpa only [Nat.add_comm] using c.vertexAt_periodic x
fin_cases i <;> simp [cellChords, chord_incidence, cellCorners, Corners.start,
Corners.stop, hper, or_comm]
noncomputable def pathsOfCell [DecidableEq V] {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) : CellPaths (BagEdge.Incident (bags := bags)) :=
(c.cellCorners hbags hc hy).cellPaths (c.cellChords hbags hc hy)
(c.cellChords_incidence hbags hc hy)
def sideGood (k : c.Corners) (i : Fin 4) : Prop :=
k.length i = 1 ∨ ∃ l, l ∈ (c.labelCycle hbags).sets (k.start i+1) ∧
l ∈ (c.labelCycle hbags).sets ((k.stop i : ℤ)-1)
lemma cell_sideGood {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (i : Fin 4) :
c.sideGood hbags (c.cellCorners hbags hc hy) i ↔
![(c.labelCycle hbags).Good x p, (c.labelCycle hbags).Good p q,
(c.labelCycle hbags).Good q y, (c.labelCycle hbags).ExteriorGood x y] i := by
have hxp := hc.first_pos
have hpq := hc.middle_pos
have hqy := hc.third_pos
have cast_sub (a : ℕ) (ha : 1 ≤ a) : ((a-1 : ℕ) : ℤ) = (a : ℤ)-1 := by omega
have he : ((c.size : ℤ)+(x : ℤ))-1 = ((x : ℤ)-1) + c.size := by ring
fin_cases i <;> simp only [sideGood, cellCorners, Corners.length, Corners.start,
Corners.stop]
· simp [MatchingFPRAS.Cells.CycleData.Good, MatchingFPRAS.Cells.CycleData.Admissible,
cast_sub p (by omega), Nat.cast_add, Nat.cast_one, show p-x=1 ↔ p=x+1 by omega]
· simp [MatchingFPRAS.Cells.CycleData.Good, MatchingFPRAS.Cells.CycleData.Admissible,
cast_sub q (by omega), Nat.cast_add, Nat.cast_one, show q-p=1 ↔ q=p+1 by omega]
· simp [MatchingFPRAS.Cells.CycleData.Good, MatchingFPRAS.Cells.CycleData.Admissible,
cast_sub y (by omega), Nat.cast_add, Nat.cast_one, show y-q=1 ↔ y=q+1 by omega]
· simp [MatchingFPRAS.Cells.CycleData.ExteriorGood, Nat.cast_add, he,
c.labelSets_periodic hbags, show c.size+x-y=1 ↔ y+1=x+c.size by omega]
noncomputable def leafRepair (k : c.Corners) (i : Fin 4) : BagEdge bags := by
classical
exact if hg : c.sideGood hbags k i ∧ k.length i ≠ 1 then
let hl := hg.1.resolve_left hg.2
BagEdge.ofEndpoints ((k.side i).vertex 1) ((k.side i).vertex ((k.side i).length-1))
(by
have hp := (k.side i).positive
have ho := (k.side i).odd
have hn : (k.side i).length ≠ 1 := hg.2
intro he
have hh := (k.side i).simple ⟨by omega, by omega⟩ ⟨by omega, by omega⟩ he
omega)
hl.choose
(by
have hm := c.labelCycle_sets_subset hbags (k.start i+1) hl.choose_spec.1
have hv : c.vertexAtZ ((k.start i : ℤ)+1) = (k.side i).vertex 1 := by
simpa only [Corners.side_vertex, Nat.cast_add, Nat.cast_one] using c.vertexAtZ_nat (k.start i+1)
exact (congrArg (fun v => hl.choose ∈ bags v) hv).mp hm)
(by
have hm := c.labelCycle_sets_subset hbags ((k.stop i : ℤ)-1) hl.choose_spec.2
have hb := k.bounds i
have he : ((k.stop i : ℤ)-1) = ((k.start i + ((k.side i).length-1) : ℕ) : ℤ) := by
rw [Corners.side_length]
dsimp [Corners.length]
omega
have hv : c.vertexAtZ ((k.stop i : ℤ)-1) = (k.side i).vertex ((k.side i).length-1) := by
rw [he, c.vertexAtZ_nat]
rfl
exact (congrArg (fun v => hl.choose ∈ bags v) hv).mp hm)
else c.edgeAt (k.start i)
lemma leafRepair_incidence (k : c.Corners) (i : Fin 4)
(hg : c.sideGood hbags k i) (hl : k.length i ≠ 1) (v : V) :
(c.leafRepair hbags k i).Incident v ↔
v = (k.side i).vertex 1 ∨ v = (k.side i).vertex ((k.side i).length-1) := by
simp only [leafRepair, dite_eq_left (And.intro hg hl), BagEdge.ofEndpoints_incidence]
lemma leafRepair_color_fixed (k : c.Corners) (i : Fin 4)
(hg : c.sideGood hbags k i) (hl : k.length i ≠ 1) :
(c.leafRepair hbags k i).color ∈ (c.labelCycle hbags).sets (k.start i+1) ∧
(c.leafRepair hbags k i).color ∈ (c.labelCycle hbags).sets ((k.stop i : ℤ)-1) := by
simp only [leafRepair, dite_eq_left (And.intro hg hl), BagEdge.ofEndpoints_color]
exact (hg.resolve_left hl).choose_spec
lemma cell_has_good_pair {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) :
∃ b : Bool, ∀ i : Fin 4, CellPaths.sideBit i ≠ b →
c.sideGood hbags (c.cellCorners hbags hc hy) i := by
rcases hc.some_good with ⟨hf,ht⟩ | ⟨hm,he⟩
· refine ⟨false, ?_⟩
intro i hi
rw [c.cell_sideGood hbags hc hy]
fin_cases i <;> simp_all [CellPaths.sideBit]
· refine ⟨true, ?_⟩
intro i hi
rw [c.cell_sideGood hbags hc hy]
fin_cases i <;> simp_all [CellPaths.sideBit]
lemma cell_actual_repairs [DecidableEq V] {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (b : Bool)
(hg : ∀ i : Fin 4, CellPaths.sideBit i ≠ b →
c.sideGood hbags (c.cellCorners hbags hc hy) i) :
(c.pathsOfCell hbags hc hy).Repairs b
(c.leafRepair hbags (c.cellCorners hbags hc hy)) := by
intro i hi hl v
exact c.leafRepair_incidence hbags _ i (hg i hi) hl v
lemma cell_long_opposite_good {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (b : Bool)
(hl : ∀ i : Fin 4, CellPaths.sideBit i = b →
(c.cellCorners hbags hc hy).length i ≠ 1) :
∀ i : Fin 4, CellPaths.sideBit i ≠ b →
c.sideGood hbags (c.cellCorners hbags hc hy) i := by
have hxp := hc.first_pos
have hpq := hc.middle_pos
have hqy := hc.third_pos
cases b
· have h₁ := hl 1 (by decide)
have h₃ := hl 3 (by decide)
simp only [Corners.length, Corners.start, Corners.stop, cellCorners] at h₁ h₃
have hg := hc.middle_exterior_long (by dsimp at h₁; omega) (by dsimp at h₃; omega)
intro i hi
rw [c.cell_sideGood hbags hc hy]
fin_cases i <;> simp_all [CellPaths.sideBit]
· have h₀ := hl 0 (by decide)
have h₂ := hl 2 (by decide)
simp only [Corners.length, Corners.start, Corners.stop, cellCorners] at h₀ h₂
have hg := hc.outer_long (by dsimp at h₀; omega) (by dsimp at h₂; omega)
intro i hi
rw [c.cell_sideGood hbags hc hy]
fin_cases i <;> simp_all [CellPaths.sideBit]
lemma cellChords_fixed {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (i : Fin 4) :
(c.cellChords hbags hc hy i).color ∈
(c.labelCycle hbags).sets ((c.cellCorners hbags hc hy).start i) ∧
(c.cellChords hbags hc hy i).color ∈
(c.labelCycle hbags).sets ((c.cellCorners hbags hc hy).stop i) := by
fin_cases i
· exact c.chord_color_fixed hbags x p hc.first_pos
(by have := hc.middle_pos; have := hc.third_pos; omega) hc.first
· exact c.chord_color_fixed hbags p q hc.middle_pos
(by have := hc.third_pos; omega) hc.middle
· exact c.chord_color_fixed hbags q y hc.third_pos hy hc.third
· have hb := c.chord_color_fixed hbags x y
(by have := hc.first_pos; have := hc.middle_pos; have := hc.third_pos; omega) hy
(by obtain ⟨l,hly,hlx⟩ := hc.exterior; exact ⟨l,hlx,hly⟩)
change _ ∈ (c.labelCycle hbags).sets y ∧ _ ∈ (c.labelCycle hbags).sets (c.size+x)
rw [add_comm, c.labelSets_periodic hbags]
exact ⟨hb.2,hb.1⟩
lemma cellChords_previous_fixed {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (i : Fin 4) :
(c.cellChords hbags hc hy (i+1)).color ∈
(c.labelCycle hbags).sets ((c.cellCorners hbags hc hy).stop i) := by
have h := (c.cellChords_fixed hbags hc hy (i+1)).1
fin_cases i
· exact h
· exact h
· exact h
· change _ ∈ (c.labelCycle hbags).sets (c.size+x)
rw [add_comm, c.labelSets_periodic hbags]
exact h
variable (height : L → ℝ) (hheight : ∀ l, 0 < height l)
variable (hstep : ∀ a b, G.Adj a b → height a ≤ 2 * height b)
include hheight hstep in
lemma fixed_height_ratio (i : ℤ) {a b : L}
(ha : a ∈ (c.labelCycle hbags).sets i) (hb : b ∈ (c.labelCycle hbags).sets i) :
height a ≤ 2 * height b := by
rcases (c.labelCycle hbags).sets_clique i a ha b hb with rfl | hab
· linarith [hheight a]
· exact hstep a b hab
include hheight hstep in
lemma cellChords_height_ratio {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (i j : Fin 4) :
height (c.cellChords hbags hc hy i).color ≤ 4 * height (c.cellChords hbags hc hy j).color := by
have hn (i : Fin 4) :
height (c.cellChords hbags hc hy i).color ≤ 2 * height (c.cellChords hbags hc hy (i+1)).color ∧
height (c.cellChords hbags hc hy (i+1)).color ≤ 2 * height (c.cellChords hbags hc hy i).color := by
exact ⟨c.fixed_height_ratio hbags height hheight hstep _
(c.cellChords_fixed hbags hc hy i).2 (c.cellChords_previous_fixed hbags hc hy i),
c.fixed_height_ratio hbags height hheight hstep _
(c.cellChords_previous_fixed hbags hc hy i) (c.cellChords_fixed hbags hc hy i).2⟩
have h₀ := hn 0
have h₁ := hn 1
have h₂ := hn 2
have h₃ := hn 3
change height (c.cellChords hbags hc hy 0).color ≤ 2 * height (c.cellChords hbags hc hy 1).color ∧
height (c.cellChords hbags hc hy 1).color ≤ 2 * height (c.cellChords hbags hc hy 0).color at h₀
change height (c.cellChords hbags hc hy 1).color ≤ 2 * height (c.cellChords hbags hc hy 2).color ∧
height (c.cellChords hbags hc hy 2).color ≤ 2 * height (c.cellChords hbags hc hy 1).color at h₁
change height (c.cellChords hbags hc hy 2).color ≤ 2 * height (c.cellChords hbags hc hy 3).color ∧
height (c.cellChords hbags hc hy 3).color ≤ 2 * height (c.cellChords hbags hc hy 2).color at h₂
change height (c.cellChords hbags hc hy 3).color ≤ 2 * height (c.cellChords hbags hc hy 0).color ∧
height (c.cellChords hbags hc hy 0).color ≤ 2 * height (c.cellChords hbags hc hy 3).color at h₃
have hp₀ := hheight (c.cellChords hbags hc hy 0).color
have hp₁ := hheight (c.cellChords hbags hc hy 1).color
have hp₂ := hheight (c.cellChords hbags hc hy 2).color
have hp₃ := hheight (c.cellChords hbags hc hy 3).color
rcases h₀ with ⟨h₀,h₀'⟩
rcases h₁ with ⟨h₁,h₁'⟩
rcases h₂ with ⟨h₂,h₂'⟩
rcases h₃ with ⟨h₃,h₃'⟩
have hi : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 := by omega
have hj : j = 0 ∨ j = 1 ∨ j = 2 ∨ j = 3 := by omega
rcases hi with rfl | rfl | rfl | rfl <;>
rcases hj with rfl | rfl | rfl | rfl <;> linarith
def LocalEdge {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (e : BagEdge bags) : Prop :=
∃ i : Fin 4, e = c.cellChords hbags hc hy i ∨
e = ((c.cellCorners hbags hc hy).side i).edge 0 ∨
e = ((c.cellCorners hbags hc hy).side i).edge
(((c.cellCorners hbags hc hy).side i).length-1) ∨
(c.sideGood hbags (c.cellCorners hbags hc hy) i ∧
(c.cellCorners hbags hc hy).length i ≠ 1 ∧
e = c.leafRepair hbags (c.cellCorners hbags hc hy) i)
lemma side_boundaries_fixed (k : c.Corners) (i : Fin 4) :
((k.side i).edge 0).color ∈ (c.labelCycle hbags).sets (k.start i) ∧
((k.side i).edge 0).color ∈ (c.labelCycle hbags).sets (k.start i+1) ∧
((k.side i).edge ((k.side i).length-1)).color ∈ (c.labelCycle hbags).sets ((k.stop i : ℤ)-1) ∧
((k.side i).edge ((k.side i).length-1)).color ∈ (c.labelCycle hbags).sets (k.stop i) := by
have hb := k.bounds i
have he : k.start i + (k.length i-1) = k.stop i-1 := by dsimp [Corners.length]; omega
change (c.edgeAt (k.start i+0)).color ∈ _ ∧ (c.edgeAt (k.start i+0)).color ∈ _ ∧
(c.edgeAt (k.start i + (k.length i-1))).color ∈ _ ∧
(c.edgeAt (k.start i + (k.length i-1))).color ∈ _
rw [Nat.add_zero, he]
have hs := c.edge_color_fixed hbags (k.start i)
have ht := c.edge_color_fixed hbags (k.stop i-1)
have hcast : ((k.stop i-1 : ℕ) : ℤ) = (k.stop i : ℤ)-1 := by omega
have hcast' : ((k.stop i-1 : ℕ) : ℤ)+1 = (k.stop i : ℤ) := by omega
exact ⟨hs.1, hs.2, by simpa only [hcast] using ht.1, by simpa only [hcast'] using ht.2⟩
include hheight hstep in
lemma localEdge_height_ratio {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) {e : BagEdge bags} (he : c.LocalEdge hbags hc hy e) :
∃ i : Fin 4,
height e.color ≤ 4 * height (c.cellChords hbags hc hy i).color ∧
height (c.cellChords hbags hc hy i).color ≤ 4 * height e.color := by
obtain ⟨i,he⟩ := he
refine ⟨i,?_⟩
have hh := hheight e.color
have hch := hheight (c.cellChords hbags hc hy i).color
have hbc := c.side_boundaries_fixed hbags (c.cellCorners hbags hc hy) i
have hc' := c.cellChords_fixed hbags hc hy i
rcases he with rfl | rfl | rfl | ⟨hg,hl,rfl⟩
· constructor <;> linarith
· have h₁ := c.fixed_height_ratio hbags height hheight hstep _ hbc.1 hc'.1
have h₂ := c.fixed_height_ratio hbags height hheight hstep _ hc'.1 hbc.1
constructor <;> linarith
· have h₁ := c.fixed_height_ratio hbags height hheight hstep _ hbc.2.2.2 hc'.2
have h₂ := c.fixed_height_ratio hbags height hheight hstep _ hc'.2 hbc.2.2.2
constructor <;> linarith
· have hrc := c.leafRepair_color_fixed hbags _ i hg hl
have h₁ := c.fixed_height_ratio hbags height hheight hstep _ hrc.1 hbc.2.1
have h₂ := c.fixed_height_ratio hbags height hheight hstep _ hbc.2.1 hrc.1
have h₃ := c.fixed_height_ratio hbags height hheight hstep _ hbc.1 hc'.1
have h₄ := c.fixed_height_ratio hbags height hheight hstep _ hc'.1 hbc.1
constructor <;> linarith
include hheight hstep in
theorem cell_comparability {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (D : ℝ) (hD : 1 ≤ D) (w : BagEdge bags → ℝ)
(hw : ∀ e, height e.color / D ≤ w e ∧ w e ≤ 3 * height e.color)
{e f : BagEdge bags} (he : c.LocalEdge hbags hc hy e) (hf : c.LocalEdge hbags hc hy f) :
w e ≤ (1000 * D) * w f := by
obtain ⟨i,hei,hie⟩ := c.localEdge_height_ratio hbags height hheight hstep hc hy he
obtain ⟨j,hfj,hjf⟩ := c.localEdge_height_ratio hbags height hheight hstep hc hy hf
have hij := c.cellChords_height_ratio hbags height hheight hstep hc hy i j
have hh : height e.color ≤ 64 * height f.color := by linarith
have hDpos : 0 < D := by linarith
have hfpos : 0 < w f := lt_of_lt_of_le (div_pos (hheight f.color) hDpos) (hw f).1
have hlo : height f.color ≤ w f * D := (div_le_iff₀ hDpos).mp (hw f).1
have h192 : w e ≤ 192 * D * w f := by nlinarith [(hw e).2]
nlinarith [mul_pos hDpos hfpos]
include hheight hstep in
lemma cell_clamp_comparability {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (D : ℝ) (hD : 1 ≤ D) (w : BagEdge bags → ℝ)
(hw : ∀ e, height e.color / D ≤ w e ∧ w e ≤ 3 * height e.color)
(lo hi : ℝ) (hlo : 0 ≤ lo)
{e f : BagEdge bags} (he : c.LocalEdge hbags hc hy e) (hf : c.LocalEdge hbags hc hy f) :
max lo (min hi (w e)) ≤ (1000 * D) * max lo (min hi (w f)) :=
common_clamp_ratio hlo (by linarith) (c.cell_comparability hbags height hheight hstep hc hy D hD w hw he hf)
lemma drops_local [DecidableEq V] {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (r : Bool) {e : BagEdge bags}
(he : e ∈ (c.pathsOfCell hbags hc hy).drops r) : c.LocalEdge hbags hc hy e := by
obtain ⟨i, _, hi⟩ := Multiset.mem_sum.mp he
by_cases h : CellPaths.sideBit i = r
· simp only [ite_eq_left h, Multiset.notMem_zero] at hi
· simp only [ite_eq_right h, Finset.mem_val] at hi
refine ⟨i, Or.inr ?_⟩
change e ∈ ((c.cellCorners hbags hc hy).side i).boundary at hi
by_cases hl : ((c.cellCorners hbags hc hy).side i).length = 1
· simp only [OddPath.boundary, ite_eq_left hl, Finset.mem_singleton] at hi
exact Or.inl hi
· simp only [OddPath.boundary, ite_eq_right hl, Finset.mem_insert, Finset.mem_singleton] at hi
exact hi.imp_right Or.inl
lemma additions_local [DecidableEq V] {x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y)
(hy : y < c.size) (b r : Bool)
(hg : ∀ i, CellPaths.sideBit i ≠ r → c.sideGood hbags (c.cellCorners hbags hc hy) i)
{e : BagEdge bags} (he : e ∈ (c.pathsOfCell hbags hc hy).additions b r
(c.leafRepair hbags (c.cellCorners hbags hc hy))) : c.LocalEdge hbags hc hy e := by
rcases Multiset.mem_add.mp he with he | he
· obtain ⟨i, _, hi⟩ := Multiset.mem_sum.mp he
by_cases h : CellPaths.sideBit i = b
· simp only [ite_eq_left h, Multiset.mem_singleton] at hi
exact ⟨i, Or.inl hi⟩
· simp only [ite_eq_right h, Multiset.notMem_zero] at hi
· obtain ⟨i, _, hi⟩ := Multiset.mem_sum.mp he
by_cases h : CellPaths.sideBit i = r
· simp only [ite_eq_left h, Multiset.notMem_zero] at hi
· simp only [ite_eq_right h] at hi
change e ∈ ((c.cellCorners hbags hc hy).side i).repairAdded (c.leafRepair hbags (c.cellCorners hbags hc hy) i) at hi
by_cases hl : ((c.cellCorners hbags hc hy).side i).length = 1
· simp only [OddPath.repairAdded, ite_eq_left hl, Multiset.notMem_zero] at hi
· simp only [OddPath.repairAdded, ite_eq_right hl, Multiset.mem_singleton] at hi
exact ⟨i, Or.inr (Or.inr (Or.inr ⟨hg i h, hl, hi⟩))⟩
end IndexedCycle
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_PM
attribute [-instance] _root_.OAI.MatchingFPRAS.Transport.Sparse.decideOverlay
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
variable {V E : Type*} [Fintype V] [DecidableEq E]
variable (inc : E → V → Prop)
abbrev PM := {M : Finset E // MatchingOn inc M Finset.univ}
@[ext] structure RawDemand where
first : PM inc
second : PM inc
anchor : E
corners : Fin 4 → V
flags : Fin 64
structure DemandEncoding (d : RawDemand inc) where
first : PM inc
second : PM inc
added : Multiset E
dropped : Multiset E
added_card : added.card ≤ 4
dropped_card : dropped.card ≤ 4
conservation : d.first.val.val + d.second.val.val + added =
first.val.val + second.val.val + dropped
outside : ∀ e ∈ d.first.val ∪ d.second.val,
¬ (overlayLineGraph inc (d.first.val ∪ d.second.val)).Reachable d.anchor e →
(e ∈ d.first.val ↔ e ∈ first.val)
namespace DemandEncoding
variable {inc}
def code {d : RawDemand inc} (a : DemandEncoding inc d) :=
(a.first, a.second, d.anchor, d.corners, d.flags,
decide (d.anchor ∈ d.first.val), a.added, a.dropped)
noncomputable def tag {d : RawDemand inc} (a : DemandEncoding inc d) : DemandTag (V := V) (E := E) :=
(d.anchor, d.corners, d.flags, decide (d.anchor ∈ d.first.val),
padOccurrences a.added, padOccurrences a.dropped)
noncomputable def finiteCode {d : RawDemand inc} (a : DemandEncoding inc d) :=
(a.first, a.second, a.tag)
end DemandEncoding
end
section
variable {V E : Type*} [Fintype V] [DecidableEq V] [DecidableEq E]
variable (inc : E → V → Prop)
structure EmbeddedCell (d : RawDemand inc) where
cell : CellPaths inc
orientation : Bool
first_pattern : cell.orientation orientation ⊆ d.first.val
second_pattern : cell.orientation (!orientation) ⊆ d.second.val
reach : ∀ e ∈ cell.orientation true ∪ cell.orientation false,
(overlayLineGraph inc (d.first.val ∪ d.second.val)).Reachable d.anchor e
namespace EmbeddedCell
variable {inc} {d : RawDemand inc} (c : EmbeddedCell inc d)
variable (hinc : ∀ e, ∃ v, inc e v)
def outsideFirst : Finset E := d.first.val \ c.cell.orientation c.orientation
def outsideSecond : Finset E := d.second.val \ c.cell.orientation (!c.orientation)
lemma outsideFirst_matching : MatchingOn inc c.outsideFirst (Finset.univ \ c.cell.vertices) :=
d.first.property.sdiff (c.cell.orientation_matching c.orientation) c.first_pattern
lemma outsideSecond_matching : MatchingOn inc c.outsideSecond (Finset.univ \ c.cell.vertices) :=
d.second.property.sdiff (c.cell.orientation_matching (!c.orientation)) c.second_pattern
lemma context_vertices_disjoint : Disjoint (Finset.univ \ c.cell.vertices) c.cell.vertices :=
Finset.sdiff_disjoint
def attachFirst (p : Finset E) (hp : MatchingOn inc p c.cell.vertices) : PM inc :=
⟨c.outsideFirst ∪ p, by
have h := c.outsideFirst_matching.union hp c.context_vertices_disjoint
simpa only [Finset.sdiff_union_of_subset (Finset.subset_univ _)] using h⟩
def attachSecond (p : Finset E) (hp : MatchingOn inc p c.cell.vertices) : PM inc :=
⟨c.outsideSecond ∪ p, by
have h := c.outsideSecond_matching.union hp c.context_vertices_disjoint
simpa only [Finset.sdiff_union_of_subset (Finset.subset_univ _)] using h⟩
include hinc in
lemma attachFirst_val (p : Finset E) (hp : MatchingOn inc p c.cell.vertices) :
(c.attachFirst p hp).val.val = c.outsideFirst.val + p.val :=
union_val_add (c.outsideFirst_matching.disjoint_edges hp hinc c.context_vertices_disjoint)
include hinc in
lemma attachSecond_val (p : Finset E) (hp : MatchingOn inc p c.cell.vertices) :
(c.attachSecond p hp).val.val = c.outsideSecond.val + p.val :=
union_val_add (c.outsideSecond_matching.disjoint_edges hp hinc c.context_vertices_disjoint)
include hinc in
lemma source_first_val : d.first.val.val =
c.outsideFirst.val + (c.cell.orientation c.orientation).val := by
have h := c.attachFirst_val hinc _ (c.cell.orientation_matching c.orientation)
have he : (c.attachFirst _ (c.cell.orientation_matching c.orientation)).val = d.first.val := by
exact Finset.sdiff_union_of_subset c.first_pattern
rwa [he] at h
include hinc in
lemma source_second_val : d.second.val.val =
c.outsideSecond.val + (c.cell.orientation (!c.orientation)).val := by
have h := c.attachSecond_val hinc _ (c.cell.orientation_matching (!c.orientation))
have he : (c.attachSecond _ (c.cell.orientation_matching (!c.orientation))).val = d.second.val := by
exact Finset.sdiff_union_of_subset c.second_pattern
rwa [he] at h
include hinc in
lemma attach_outside (p : Finset E) (hp : MatchingOn inc p c.cell.vertices)
(e : E) (he : e ∈ d.first.val ∪ d.second.val)
(hn : ¬ (overlayLineGraph inc (d.first.val ∪ d.second.val)).Reachable d.anchor e) :
e ∈ d.first.val ↔ e ∈ (c.attachFirst p hp).val := by
have hnot (b : Bool) : e ∉ c.cell.orientation b := by
intro hm
apply hn
apply c.reach e
cases b
· exact Finset.mem_union_right _ hm
· exact Finset.mem_union_left _ hm
have hnp : e ∉ p := by
intro hm
obtain ⟨v,hv⟩ := hinc e
have hvc := hp.1 e hm v hv
rcases Finset.mem_union.mp he with he | he
· exact hnot _ (d.first.property.edge_mem_of_incident
(c.cell.orientation_matching c.orientation) c.first_pattern he hvc hv)
· exact hnot _ (d.second.property.edge_mem_of_incident
(c.cell.orientation_matching (!c.orientation)) c.second_pattern he hvc hv)
change e ∈ d.first.val ↔ e ∈ c.outsideFirst ∪ p
simp only [outsideFirst, Finset.mem_union, Finset.mem_sdiff, hnot, hnp, not_false_eq_true,
and_true, or_false]
def encode (p q : Finset E) (hp : MatchingOn inc p c.cell.vertices)
(hq : MatchingOn inc q c.cell.vertices) (add drop : Multiset E)
(ha : add.card ≤ 4) (hd : drop.card ≤ 4)
(hcons : (c.cell.orientation true).val + (c.cell.orientation false).val + add =
p.val + q.val + drop) : DemandEncoding inc d where
first := c.attachFirst p hp
second := c.attachSecond q hq
added := add
dropped := drop
added_card := ha
dropped_card := hd
conservation := by
rw [c.source_first_val hinc, c.source_second_val hinc,
c.attachFirst_val hinc p hp, c.attachSecond_val hinc q hq]
have ho : (c.cell.orientation c.orientation).val +
(c.cell.orientation (!c.orientation)).val =
(c.cell.orientation true).val + (c.cell.orientation false).val := by
cases c.orientation <;> simp only [Bool.not_false, Bool.not_true]
ac_rfl
calc
_ = c.outsideFirst.val + c.outsideSecond.val +
((c.cell.orientation c.orientation).val + (c.cell.orientation (!c.orientation)).val + add) := by ac_rfl
_ = c.outsideFirst.val + c.outsideSecond.val + (p.val + q.val + drop) := by rw [ho,hcons]
_ = _ := by ac_rfl
outside := c.attach_outside hinc p hp
def switchEncoding (b r : Bool) (repair : Fin 4 → E) (hr : c.cell.Repairs r repair) :
DemandEncoding inc d :=
c.encode hinc (c.cell.switched b) (c.cell.repaired r repair)
(c.cell.switched_matching b) (c.cell.repaired_matching r repair hr)
(c.cell.additions b r repair) (c.cell.drops r)
(by rw [← (c.cell.modification_cards b r repair).1]; exact (c.cell.modification_cards b r repair).2)
(c.cell.modification_cards b r repair).2
(c.cell.switch_conservation b r repair hr hinc)
def errorZeroEncoding (b : Bool) (repair : Fin 4 → E) (hr : c.cell.Repairs b repair) :
DemandEncoding inc d :=
c.encode hinc (c.cell.orientation b) (c.cell.guide b repair)
(c.cell.orientation_matching b) (c.cell.guide_matching b repair hr)
(c.cell.additions b b repair) (c.cell.drops b)
(by rw [← (c.cell.modification_cards b b repair).1]; exact (c.cell.modification_cards b b repair).2)
(c.cell.modification_cards b b repair).2
(c.cell.guide_conservation b repair hr hinc)
def errorOneEncoding (b : Bool) (repair : Fin 4 → E) (hr : c.cell.Repairs b repair)
(Y : Fin 4) (hY : CellPaths.sideBit Y = b) : DemandEncoding inc d :=
c.encode hinc (c.cell.contextOne b Y) (c.cell.guideOne b repair Y)
(c.cell.context_one_properties b repair hr Y hY hinc).1
(c.cell.context_one_properties b repair hr Y hY hinc).2.1
(c.cell.additions b b repair) (c.cell.drops b)
(by rw [← (c.cell.modification_cards b b repair).1]; exact (c.cell.modification_cards b b repair).2)
(c.cell.modification_cards b b repair).2 (by
rw [(c.cell.context_one_properties b repair hr Y hY hinc).2.2]
exact c.cell.guide_conservation b repair hr hinc)
lemma zero_guide_contains (b : Bool) (repair : Fin 4 → E) (hr : c.cell.Repairs b repair)
(X : Fin 4) (hX : CellPaths.sideBit X = b) :
(c.cell.side X).closed (c.cell.chord X) ⊆
(c.errorZeroEncoding hinc b repair hr).second.val := by
intro e he
exact Finset.mem_union_right _ (c.cell.closed_subset_guide b repair X hX he)
lemma one_guide_contains (b : Bool) (repair : Fin 4 → E) (hr : c.cell.Repairs b repair)
(X Y : Fin 4) (hX : CellPaths.sideBit X = b) (hY : CellPaths.sideBit Y = b)
(hne : X ≠ Y) :
(c.cell.side X).closed (c.cell.chord X) ⊆
(c.errorOneEncoding hinc b repair hr Y hY).second.val := by
intro e he
exact Finset.mem_union_right _ (c.cell.closed_subset_guide_one b repair X Y hX hY hne hinc he)
end EmbeddedCell
end
section
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
namespace IndexedCycle.Corners
variable {c : IndexedCycle inc} (k : c.Corners)
def rawDemand (M N : PM inc) (flags : Fin 64) : RawDemand inc :=
⟨M, N, c.edgeAt 0, (fun i => c.vertexAt (k.start i)), flags⟩
noncomputable def embeddedPair (M N : PM inc)
(hU : ∀ i, c.edgeAt i ∈ M.val ∪ N.val)
(chord : Fin 4 → E)
(hc : ∀ i v, inc (chord i) v ↔
v = (k.side i).vertex 0 ∨ v = (k.side i).vertex (k.side i).length)
(flags : Fin 64) : EmbeddedCell inc (k.rawDemand M N flags) := by
classical
let a : ℕ := if c.edgeAt 0 ∈ M.val then 0 else 1
have ha : a < 2 := by dsimp [a]; split <;> omega
have hM : ∀ t, t % 2 = a → c.edgeAt t ∈ M.val := by
intro t ht
apply (c.cycle_edge_mem_parity M.property N.property hU t).mpr
dsimp [a] at ht
split_ifs at ht ⊢ <;> omega
have hN : ∀ t, t % 2 = 1-a → c.edgeAt t ∈ N.val := by
intro t ht
apply (c.cycle_edge_mem_complement M.property N.property hU t).mpr
rw [c.cycle_edge_mem_parity M.property N.property hU t]
dsimp [a] at ht
split_ifs at ht ⊢ <;> first | omega | tauto
have hb : decide (k.a₀ % 2 = 1-a) = !decide (k.a₀ % 2 = a) := by
by_cases h : k.a₀ % 2 = a
· have hn : k.a₀ % 2 ≠ 1-a := by omega
simp [h]
omega
· have hn : k.a₀ % 2 = 1-a := by omega
simp [hn]
omega
refine ⟨k.cellPaths chord hc, decide (k.a₀ % 2 = a),
k.cell_orientation_subset chord hc M.val a ha hM, ?_, ?_⟩
· rw [← hb]
exact k.cell_orientation_subset chord hc N.val (1-a) (by omega) hN
· intro e he
rcases Finset.mem_union.mp he with he | he
· exact k.cell_orientation_reachable chord hc _ hU true e he
· exact k.cell_orientation_reachable chord hc _ hU false e he
end IndexedCycle.Corners
end
variable {V E : Type*} [Fintype V]
variable {inc : E → V → Prop}
noncomputable def matchingWeight (w : E → ℝ) (M : PM inc) : ℝ := ∏ e ∈ M.val, w e
lemma matchingWeight_pos (w : E → ℝ) (hw : ∀ e, 0 < w e) (M : PM inc) :
0 < matchingWeight w M := Finset.prod_pos (fun e _ => hw e)
variable [Fintype E]
noncomputable def partition (w : E → ℝ) : ℝ := by
classical
exact ∑ M : PM inc, matchingWeight w M
lemma partition_pos (w : E → ℝ) (hw : ∀ e, 0 < w e) (M : PM inc) :
0 < partition (inc := inc) w := by
classical
exact Finset.sum_pos' (fun A _ => le_of_lt (matchingWeight_pos w hw A))
⟨M, Finset.mem_univ _, matchingWeight_pos w hw M⟩
noncomputable def gibbs (w : E → ℝ) (M : PM inc) : ℝ :=
matchingWeight w M / partition (inc := inc) w
lemma gibbs_pos (w : E → ℝ) (hw : ∀ e, 0 < w e) (M : PM inc) :
0 < gibbs w M := div_pos (matchingWeight_pos w hw M) (partition_pos w hw M)
lemma gibbs_sum (w : E → ℝ) (hw : ∀ e, 0 < w e) (M : PM inc) :
letI : Fintype (PM inc) := Fintype.ofFinite _
∑ A : PM inc, gibbs w A = 1 := by
classical
simp only [gibbs, ← Finset.sum_div]
have hp := ne_of_gt (partition_pos w hw M)
convert div_self hp using 1
all_goals try with_reducible_and_instances rfl
all_goals (try congr 1)
all_goals (try unfold partition)
all_goals (try congr 1)
all_goals (try ext A)
all_goals (try simp)
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_IntervalPattern
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
namespace DemandEncoding
variable {d : RawDemand inc} (enc : DemandEncoding inc d)
lemma gibbs_bound (w : E → ℝ) (hw : ∀ e, 0 < w e) (A : ℝ) (hA : 1 ≤ A)
(hcard : enc.dropped.card = enc.added.card)
(hcompare : ∀ e ∈ enc.dropped, ∀ f ∈ enc.added, w e ≤ A * w f) :
gibbs w d.first * gibbs w d.second ≤ A^4 * gibbs w enc.first * gibbs w enc.second := by
have h := four_edge_weight_bound w hw A hA
(d.first.val.val + d.second.val.val) (enc.first.val.val + enc.second.val.val)
enc.dropped enc.added enc.conservation hcard enc.dropped_card hcompare
simp only [Multiset.map_add, Multiset.prod_add, ← Finset.prod_eq_multiset_prod] at h
have h' : matchingWeight w d.first * matchingWeight w d.second ≤
A^4 * (matchingWeight w enc.first * matchingWeight w enc.second) := h
have hp : 0 ≤ partition (inc := inc) w * partition (inc := inc) w := mul_self_nonneg _
have hh := div_le_div_of_nonneg_right h' hp
dsimp only [gibbs]
calc
_ = (matchingWeight w d.first * matchingWeight w d.second) /
(partition (inc := inc) w * partition (inc := inc) w) := div_mul_div_comm _ _ _ _
_ ≤ A^4 * (matchingWeight w enc.first * matchingWeight w enc.second) /
(partition (inc := inc) w * partition (inc := inc) w) := hh
_ = _ := by
field_simp [ne_of_gt (partition_pos w hw d.first)]
end DemandEncoding
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport.IndexedCycle
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L}
noncomputable local instance instFintypeBagEdge : Fintype (BagEdge bags) := Fintype.ofFinite _
variable (c : IndexedCycle (BagEdge.Incident (bags := bags)))
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
variable (height : L → ℝ) (hheight : ∀ l, 0 < height l)
variable (hstep : ∀ a b, G.Adj a b → height a ≤ 2 * height b)
include hheight hstep
theorem actual_switch_encoding
(M N : PM (BagEdge.Incident (bags := bags)))
(hU : ∀ i, c.edgeAt i ∈ M.val ∪ N.val)
{x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y) (hy : y < c.size)
(flags : Fin 64) (b : Bool) (D : ℝ) (hD : 1 ≤ D)
(w : BagEdge bags → ℝ)
(hw : ∀ e, height e.color / D ≤ w e ∧ w e ≤ 3 * height e.color)
(lo hi : ℝ) (hlo : 0 < lo) (_hlohi : lo ≤ hi) :
let k := c.cellCorners hbags hc hy
let emb := k.embeddedPair M N hU (c.cellChords hbags hc hy)
(c.cellChords_incidence hbags hc hy) flags
let wt := fun e => max lo (min hi (w e))
∃ enc : DemandEncoding BagEdge.Incident (k.rawDemand M N flags),
enc.first.val = emb.outsideFirst ∪ (c.pathsOfCell hbags hc hy).switched b ∧
gibbs wt M * gibbs wt N ≤
(1000*D)^4 * gibbs wt enc.first * gibbs wt enc.second := by
classical
dsimp only
let k := c.cellCorners hbags hc hy
let emb := k.embeddedPair M N hU (c.cellChords hbags hc hy)
(c.cellChords_incidence hbags hc hy) flags
obtain ⟨r, hg⟩ := c.cell_has_good_pair hbags hc hy
have hr := c.cell_actual_repairs hbags hc hy r hg
let enc := emb.switchEncoding BagEdge.exists_incident b r (c.leafRepair hbags k) hr
refine ⟨enc, rfl, ?_⟩
apply enc.gibbs_bound (fun e => max lo (min hi (w e)))
(fun e => lt_of_lt_of_le hlo (le_max_left _ _)) (1000*D) (by linarith)
· exact ((c.pathsOfCell hbags hc hy).modification_cards b r (c.leafRepair hbags k)).1
· intro e he f hf
exact c.cell_clamp_comparability hbags height hheight hstep hc hy D hD w hw lo hi
(le_of_lt hlo) (c.drops_local hbags hc hy r he)
(c.additions_local hbags hc hy b r hg hf)
theorem actual_error_encodings
(M N : PM (BagEdge.Incident (bags := bags)))
(hU : ∀ i, c.edgeAt i ∈ M.val ∪ N.val)
{x p q y : ℕ} (hc : (c.labelCycle hbags).Cell x p q y) (hy : y < c.size)
(flags : Fin 64) (b : Bool) (X Y : Fin 4)
(hX : CellPaths.sideBit X = b) (hY : CellPaths.sideBit Y = b) (hne : X ≠ Y)
(hl : ∀ i : Fin 4, CellPaths.sideBit i = b → (c.cellCorners hbags hc hy).length i ≠ 1)
(D : ℝ) (hD : 1 ≤ D) (w : BagEdge bags → ℝ)
(hw : ∀ e, height e.color / D ≤ w e ∧ w e ≤ 3 * height e.color)
(lo hi : ℝ) (hlo : 0 < lo) (_hlohi : lo ≤ hi) :
let k := c.cellCorners hbags hc hy
let emb := k.embeddedPair M N hU (c.cellChords hbags hc hy)
(c.cellChords_incidence hbags hc hy) flags
let cp := c.pathsOfCell hbags hc hy
let wt := fun e => max lo (min hi (w e))
∃ enc₀ enc₁ : DemandEncoding BagEdge.Incident (k.rawDemand M N flags),
enc₀.first.val = emb.outsideFirst ∪ cp.orientation b ∧
enc₁.first.val = emb.outsideFirst ∪ cp.contextOne b Y ∧
(cp.side X).closed (cp.chord X) ⊆ enc₀.second.val ∧
(cp.side X).closed (cp.chord X) ⊆ enc₁.second.val ∧
gibbs wt M * gibbs wt N ≤ (1000*D)^4 * gibbs wt enc₀.first * gibbs wt enc₀.second ∧
gibbs wt M * gibbs wt N ≤ (1000*D)^4 * gibbs wt enc₁.first * gibbs wt enc₁.second := by
classical
dsimp only
let k := c.cellCorners hbags hc hy
let emb := k.embeddedPair M N hU (c.cellChords hbags hc hy)
(c.cellChords_incidence hbags hc hy) flags
have hg := c.cell_long_opposite_good hbags hc hy b hl
have hr := c.cell_actual_repairs hbags hc hy b hg
let enc₀ := emb.errorZeroEncoding BagEdge.exists_incident b (c.leafRepair hbags k) hr
let enc₁ := emb.errorOneEncoding BagEdge.exists_incident b (c.leafRepair hbags k) hr Y hY
refine ⟨enc₀, enc₁, rfl, rfl,
emb.zero_guide_contains BagEdge.exists_incident b _ hr X hX,
emb.one_guide_contains BagEdge.exists_incident b _ hr X Y hX hY hne, ?_, ?_⟩
all_goals
first
| apply enc₀.gibbs_bound (fun e => max lo (min hi (w e)))
(fun e => lt_of_lt_of_le hlo (le_max_left _ _)) (1000*D) (by linarith)
| apply enc₁.gibbs_bound (fun e => max lo (min hi (w e)))
(fun e => lt_of_lt_of_le hlo (le_max_left _ _)) (1000*D) (by linarith)
· exact ((c.pathsOfCell hbags hc hy).modification_cards b b (c.leafRepair hbags k)).1
· intro e he f hf
exact c.cell_clamp_comparability hbags height hheight hstep hc hy D hD w hw lo hi
(le_of_lt hlo) (c.drops_local hbags hc hy b he)
(c.additions_local hbags hc hy b b hg hf)
end MatchingFPRAS.Transport.IndexedCycle
namespace MatchingFPRAS.Transport
section
variable {V E : Type*}
variable {inc : E → V → Prop}
namespace IndexedCycle
variable (c : IndexedCycle inc)
variable [DecidableEq E]
variable [DecidableEq V]
namespace Corners
variable {c} (k : c.Corners)
lemma cell_piece_interval (chord : Fin 4 → E)
(hc : ∀ i v, inc (chord i) v ↔
v = (k.side i).vertex 0 ∨ v = (k.side i).vertex (k.side i).length)
(b : Bool) (i : Fin 4) :
(k.cellPaths chord hc).orientationPieces b i =
c.intervalPattern (k.start i) (k.stop i) (if b then k.a₀%2 else 1-k.a₀%2) := by
have hs := k.parity_start i
have hb := k.bounds i
have he : k.start i + k.length i = k.stop i := by dsimp [length]; omega
change (if CellPaths.sideBit i = b then (k.side i).through else (k.side i).interior) = _
by_cases h : CellPaths.sideBit i = b
· rw [ite_eq_left h]
rw [show (k.side i).through = _ from c.arc_through _ _ _ _ _ _, he]
cases b <;> simp_all
· rw [ite_eq_right h]
rw [show (k.side i).interior = _ from c.arc_interior _ _ _ _ _ _, he]
cases b <;> cases hi : CellPaths.sideBit i <;> simp_all
congr 1
omega
lemma cell_orientation_parity (chord : Fin 4 → E)
(hc : ∀ i v, inc (chord i) v ↔
v = (k.side i).vertex 0 ∨ v = (k.side i).vertex (k.side i).length)
(b : Bool) :
(k.cellPaths chord hc).orientation b =
c.parityPattern (if b then k.a₀%2 else 1-k.a₀%2) := by
have h₀ := k.lt₀
have h₁ := k.lt₁
have h₂ := k.lt₂
have h₃ := k.lt₃
unfold CellPaths.orientation CellPaths.assemble
simp only [k.cell_piece_interval, start, stop, Fin.isValue, Matrix.cons_val_zero,
Matrix.cons_val_one, Matrix.cons_val]
rw [show c.size + k.a₀ = k.a₀ + c.size by omega]
have h := c.rotatedPattern (x := k.a₀) (by omega) (if b then k.a₀%2 else 1-k.a₀%2)
rw [← h]
ext e
simp only [Finset.mem_union, c.mem_intervalPattern]
constructor
· rintro ((⟨i,hi,hj,hp,he⟩ | ⟨i,hi,hj,hp,he⟩) | (⟨i,hi,hj,hp,he⟩ | ⟨i,hi,hj,hp,he⟩)) <;>
exact ⟨i,by omega,by omega,hp,he⟩
· rintro ⟨i,hi,hj,hp,he⟩
by_cases ha : i < k.a₁
· exact Or.inl (Or.inl ⟨i,hi,ha,hp,he⟩)
· by_cases hb : i < k.a₂
· exact Or.inr (Or.inl ⟨i,by omega,hb,hp,he⟩)
· by_cases hd : i < k.a₃
· exact Or.inl (Or.inr ⟨i,by omega,hd,hp,he⟩)
· exact Or.inr (Or.inr ⟨i,by omega,hj,hp,he⟩)
end Corners
end IndexedCycle
end
open scoped symmDiff
variable {V E : Type*} [DecidableEq E]
variable {inc : E → V → Prop}
lemma exchange_matching [Fintype V] {M N S : Finset E}
(hM : MatchingOn inc M Finset.univ) (hN : MatchingOn inc N Finset.univ)
(h : ExchangeCompatible (inc := inc) M N S) :
MatchingOn inc (exchange M N S) Finset.univ := by
refine ⟨fun _ _ v _ => Finset.mem_univ v, ?_⟩
intro v _
obtain ⟨e,⟨he,hev⟩,hu⟩ := hM.2 v (Finset.mem_univ v)
obtain ⟨f,⟨hf,hfv⟩,hv⟩ := hN.2 v (Finset.mem_univ v)
have hs := h e he f hf v hev hfv
by_cases hse : e ∈ S
· have hsf := hs.mp hse
refine ⟨f, ⟨(mem_exchange M N S f).mpr (Or.inr ⟨hf,hsf⟩),hfv⟩, ?_⟩
rintro g ⟨hg,hgv⟩
rcases (mem_exchange M N S g).mp hg with ⟨hgm,hgs⟩ | ⟨hgn,_⟩
· have heq := hu g ⟨hgm,hgv⟩
exact (hgs (heq ▸ hse)).elim
· exact hv g ⟨hgn,hgv⟩
· refine ⟨e, ⟨(mem_exchange M N S e).mpr (Or.inl ⟨he,hse⟩),hev⟩, ?_⟩
rintro g ⟨hg,hgv⟩
rcases (mem_exchange M N S g).mp hg with ⟨hgm,_⟩ | ⟨hgn,hgs⟩
· exact hu g ⟨hgm,hgv⟩
· have heq := hv g ⟨hgn,hgv⟩
exact (hse (hs.mpr (heq ▸ hgs))).elim
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Components
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
variable {V E : Type*} [DecidableEq E]
variable {inc : E → V → Prop}
namespace IndexedCycle
variable (c : IndexedCycle inc)
variable [Fintype V]
lemma inter_edgeSet_parity {M N : Finset E}
(hM : MatchingOn inc M Finset.univ) (hN : MatchingOn inc N Finset.univ)
(hU : ∀ i, c.edgeAt i ∈ M ∪ N) :
M ∩ c.edgeSet = c.parityPattern (if c.edgeAt 0 ∈ M then 0 else 1) := by
classical
ext e
simp only [Finset.mem_inter, c.mem_edgeSet, parityPattern, mem_intervalPattern]
constructor
· rintro ⟨heM,i,hi,rfl⟩
refine ⟨i, Nat.zero_le _,hi,?_,rfl⟩
have hp := (c.cycle_edge_mem_parity hM hN hU i).mp heM
split_ifs at hp ⊢ <;> first | omega | tauto
· rintro ⟨i,_,hi,hpar,rfl⟩
refine ⟨?_, i,hi,rfl⟩
apply (c.cycle_edge_mem_parity hM hN hU i).mpr
split_ifs at hpar ⊢ <;> omega
end IndexedCycle
end
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Sewn
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
variable {V E : Type*} [DecidableEq V] [DecidableEq E]
variable {inc : E → V → Prop}
namespace IndexedCycle.Corners
variable {c : IndexedCycle inc} (k : c.Corners)
lemma embeddedPair_outside [Fintype V] (M N : PM inc) (hU : ∀ i, c.edgeAt i ∈ M.val ∪ N.val)
(chord : Fin 4 → E)
(hc : ∀ i v, inc (chord i) v ↔
v = (k.side i).vertex 0 ∨ v = (k.side i).vertex (k.side i).length)
(flags : Fin 64) :
(k.embeddedPair M N hU chord hc flags).outsideFirst = M.val \ c.edgeSet := by
classical
change M.val \ (k.cellPaths chord hc).orientation
(decide (k.a₀ % 2 = if c.edgeAt 0 ∈ M.val then 0 else 1)) = _
rw [k.cell_orientation_parity]
have hp := c.inter_edgeSet_parity M.property N.property hU
have he : (if decide (k.a₀ % 2 = if c.edgeAt 0 ∈ M.val then 0 else 1)
then k.a₀ % 2 else 1-k.a₀ % 2) = (if c.edgeAt 0 ∈ M.val then 0 else 1) := by
by_cases hz : c.edgeAt 0 ∈ M.val <;> simp only [hz,ite_true,ite_false]
all_goals split_ifs <;> simp_all
rw [he,← hp]
ext e
simp
end IndexedCycle.Corners
end
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_ChosenChord
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.IndexedCycle
variable {V L : Type*} [Fintype V] [DecidableEq V] [DecidableEq L] [Fintype L]
variable {bags : V → Finset L} (c : IndexedCycle (BagEdge.Incident (bags := bags)))
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
noncomputable def chosenChord (x y : ℕ) : BagEdge bags := by
classical
exact if h : x < y ∧ y < c.size ∧ (c.labelCycle hbags).Admissible x y then
c.chord hbags x y h.1 h.2.1 h.2.2 else c.edgeAt 0
noncomputable def diagramGain (R : Finset (BagEdge bags)) (f : Finset (BagEdge bags) → ℝ)
(x y : ℕ) : ℝ := c.signedGain R f x y (c.chosenChord hbags x y)
noncomputable def diagramTerm (R : Finset (BagEdge bags)) (f : Finset (BagEdge bags) → ℝ)
(x p q y : ℕ) : ℝ := by
classical
exact if h : (c.labelCycle hbags).Cell x p q y ∧ y < c.size then
(c.cellCorners hbags h.1 h.2).signedLocalTerm (c.cellChords hbags h.1 h.2)
(c.cellChords_incidence hbags h.1 h.2) R f else 0
end MatchingFPRAS.Transport.IndexedCycle
namespace MatchingFPRAS.Transport.IndexedCycle
section
variable {V L : Type*} [Fintype V] [DecidableEq V] [DecidableEq L] [Fintype L]
variable {bags : V → Finset L} (c : IndexedCycle (BagEdge.Incident (bags := bags)))
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
noncomputable def diagramEnergy (R : Finset (BagEdge bags)) (f : Finset (BagEdge bags) → ℝ)
(x p q y : ℕ) : ℝ := by
classical
exact if h : (c.labelCycle hbags).Cell x p q y ∧ y < c.size then
let P := c.pathsOfCell hbags h.1 h.2
(f (R ∪ P.switched true) - f (R ∪ P.switched false))^2 +
(P.contextError R f true 2 0)^2 + (P.contextError R f false 3 1)^2
else 0
end
variable {V L : Type*} [Fintype V] [DecidableEq V] [DecidableEq L] [Fintype L]
variable {bags : V → Finset L} (c : IndexedCycle (BagEdge.Incident (bags := bags)))
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
noncomputable def subdivision (hG : G.IsAcyclic) :
MatchingFPRAS.Cells.CycleData.Subdivision (c.labelCycle hbags) 0 (c.size-1) :=
Classical.choice ((c.labelCycle hbags).quadrangulate hG c.four_le c.even)
end MatchingFPRAS.Transport.IndexedCycle
namespace MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
abbrev LongComponent (p : PM inc × PM inc) :=
{S : Finset E // ∃ c : IndexedCycle inc, c.edgeSet = S ∧ ∀ i, c.edgeAt i ∈ p.1.val ∪ p.2.val}
namespace LongComponent
variable {p : PM inc × PM inc} (S : LongComponent p)
noncomputable instance instFintype : Fintype (LongComponent p) := Fintype.ofFinite _
noncomputable def cycle : IndexedCycle inc := S.property.choose
omit [DecidableEq V] [Fintype E] in
lemma cycle_union : ∀ i, S.cycle.edgeAt i ∈ p.1.val ∪ p.2.val := S.property.choose_spec.2
end LongComponent
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L}
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
variable (hG : G.IsAcyclic)
abbrev Demand := Σ p : PM (BagEdge.Incident (bags := bags)) × PM BagEdge.Incident,
Σ S : LongComponent p, ↥(S.cycle.subdivision hbags hG).cellSet
end MatchingFPRAS.Transport.CellDemands
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Cycle
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L}
variable {G : SimpleGraph L}
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
variable (hG : G.IsAcyclic)
namespace Demand
variable {hbags hG} (d : Demand hbags hG)
noncomputable def cycle := d.2.1.cycle
omit [Fintype L] in
lemma cell : (d.cycle.labelCycle hbags).Cell d.2.2.val.x d.2.2.val.p d.2.2.val.q d.2.2.val.y :=
((d.2.1.cycle.subdivision hbags hG).mem_cellList (List.mem_toFinset.mp d.2.2.property)).2.2
omit [Fintype L] in
lemma last_lt : d.2.2.val.y < d.cycle.size := by
have hy := ((d.2.1.cycle.subdivision hbags hG).mem_cellList (List.mem_toFinset.mp d.2.2.property)).2.1
have hsize := d.cycle.four_le
change d.2.2.val.y ≤ d.cycle.size-1 at hy
omega
noncomputable def corners : d.cycle.Corners := d.cycle.cellCorners hbags d.cell d.last_lt
noncomputable def raw (flags : Fin 64) : RawDemand (BagEdge.Incident (bags := bags)) :=
d.corners.rawDemand d.1.1 d.1.2 flags
end Demand
end MatchingFPRAS.Transport.CellDemands
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_1 : Fintype (BagEdge bags) := Fintype.ofFinite _
variable {hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b}
variable {hG : G.IsAcyclic}
noncomputable instance instFintypeDemand : Fintype (Demand hbags hG) := Fintype.ofFinite _
namespace Demand
noncomputable def paths (d : Demand hbags hG) := d.cycle.pathsOfCell hbags d.cell d.last_lt
noncomputable def outside (d : Demand hbags hG) := d.1.1.val \ d.cycle.edgeSet
end Demand
abbrev ErrorDemand (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
(hG : G.IsAcyclic) :=
{e : Bool × Demand hbags hG // ∀ i : Fin 4, CellPaths.sideBit i = e.1 →
(e.2.paths.side i).length ≠ 1}
noncomputable instance instFintypeErrorDemand : Fintype (ErrorDemand hbags hG) := Fintype.ofFinite _
namespace ErrorDemand
variable (e : ErrorDemand hbags hG)
def bit : Bool := e.val.1
def demand : Demand hbags hG := e.val.2
def X : Fin 4 := if e.bit then 2 else 3
def Y : Fin 4 := if e.bit then 0 else 1
omit [Fintype L] in
lemma X_bit : CellPaths.sideBit e.X = e.bit := by cases hb : e.bit <;> simp [X,hb,CellPaths.sideBit]
omit [Fintype L] in
lemma Y_bit : CellPaths.sideBit e.Y = e.bit := by cases hb : e.bit <;> simp [Y,hb,CellPaths.sideBit]
omit [Fintype L] in
lemma X_ne_Y : e.X ≠ e.Y := by cases hb : e.bit <;> simp [X,Y,hb]
def flags : Fin 64 := if e.bit then 2 else 1
noncomputable def raw := e.demand.raw e.flags
end ErrorDemand
variable (height : L → ℝ) (hheight : ∀ l, 0 < height l)
variable (hstep : ∀ a b, G.Adj a b → height a ≤ 2 * height b)
variable (D : ℝ) (hD : 1 ≤ D) (w : BagEdge bags → ℝ)
variable (hw : ∀ e, height e.color / D ≤ w e ∧ w e ≤ 3 * height e.color)
variable (lo hi : ℝ) (hlo : 0 < lo) (hlohi : lo ≤ hi)
namespace Demand
variable (d : Demand hbags hG)
include hheight hstep hD hw hlo hlohi in
lemma exists_switch : ∃ enc : DemandEncoding BagEdge.Incident (d.raw 0),
enc.first.val = d.outside ∪ d.paths.switched true ∧
gibbs (fun e => max lo (min hi (w e))) d.1.1 * gibbs (fun e => max lo (min hi (w e))) d.1.2 ≤
(1000*D)^4 * gibbs (fun e => max lo (min hi (w e))) enc.first *
gibbs (fun e => max lo (min hi (w e))) enc.second := by
obtain ⟨enc,he,hw⟩ := d.cycle.actual_switch_encoding hbags height hheight hstep
d.1.1 d.1.2 d.2.1.cycle_union d.cell d.last_lt 0 true D hD w hw lo hi hlo hlohi
refine ⟨enc,?_,hw⟩
exact he.trans (congrArg (fun R => R ∪ d.paths.switched true)
(d.corners.embeddedPair_outside d.1.1 d.1.2 d.2.1.cycle_union d.paths.chord d.paths.chord_incidence 0))
noncomputable def switchChoice : DemandEncoding BagEdge.Incident (d.raw 0) :=
(d.exists_switch height hheight hstep D hD w hw lo hi hlo hlohi).choose
end Demand
namespace ErrorDemand
variable (e : ErrorDemand hbags hG)
include hheight hstep hD hw hlo hlohi in
lemma exists_errors : ∃ enc₀ enc₁ : DemandEncoding BagEdge.Incident e.raw,
enc₀.first.val = e.demand.outside ∪ e.demand.paths.orientation e.bit ∧
enc₁.first.val = e.demand.outside ∪ e.demand.paths.contextOne e.bit e.Y ∧
(e.demand.paths.side e.X).closed (e.demand.paths.chord e.X) ⊆ enc₀.second.val ∧
(e.demand.paths.side e.X).closed (e.demand.paths.chord e.X) ⊆ enc₁.second.val ∧
gibbs (fun e => max lo (min hi (w e))) e.demand.1.1 *
gibbs (fun e => max lo (min hi (w e))) e.demand.1.2 ≤
(1000*D)^4 * gibbs (fun e => max lo (min hi (w e))) enc₀.first *
gibbs (fun e => max lo (min hi (w e))) enc₀.second ∧
gibbs (fun e => max lo (min hi (w e))) e.demand.1.1 *
gibbs (fun e => max lo (min hi (w e))) e.demand.1.2 ≤
(1000*D)^4 * gibbs (fun e => max lo (min hi (w e))) enc₁.first *
gibbs (fun e => max lo (min hi (w e))) enc₁.second := by
obtain ⟨enc₀,enc₁,h₀,h₁,hr⟩ := e.demand.cycle.actual_error_encodings hbags height hheight hstep
e.demand.1.1 e.demand.1.2 e.demand.2.1.cycle_union e.demand.cell e.demand.last_lt
e.flags e.bit e.X e.Y e.X_bit e.Y_bit e.X_ne_Y e.property D hD w hw lo hi hlo hlohi
refine ⟨enc₀,enc₁,?_,?_,hr⟩
· exact h₀.trans (congrArg (fun R => R ∪ e.demand.paths.orientation e.bit)
(e.demand.corners.embeddedPair_outside e.demand.1.1 e.demand.1.2 e.demand.2.1.cycle_union
e.demand.paths.chord e.demand.paths.chord_incidence e.flags))
· exact h₁.trans (congrArg (fun R => R ∪ e.demand.paths.contextOne e.bit e.Y)
(e.demand.corners.embeddedPair_outside e.demand.1.1 e.demand.1.2 e.demand.2.1.cycle_union
e.demand.paths.chord e.demand.paths.chord_incidence e.flags))
noncomputable def errorZero : DemandEncoding BagEdge.Incident e.raw :=
(e.exists_errors height hheight hstep D hD w hw lo hi hlo hlohi).choose
noncomputable def errorOne : DemandEncoding BagEdge.Incident e.raw :=
(e.exists_errors height hheight hstep D hD w hw lo hi hlo hlohi).choose_spec.choose
end ErrorDemand
end MatchingFPRAS.Transport.CellDemands
namespace MatchingFPRAS.Transport.OddPath
variable {V E : Type*} [Fintype V] [DecidableEq V] [DecidableEq E]
variable {inc : E → V → Prop} (p : OddPath inc) (chord : E)
variable (hlong : 3 ≤ p.length)
variable (hc : ∀ v, inc chord v ↔ v = p.vertex 0 ∨ v = p.vertex p.length)
def closedCycle : IndexedCycle inc where
size := p.length + 1
four_le := by omega
even := by have := p.odd; omega
vertex i := p.vertex i
simple := by
intro i j h
exact Fin.ext (p.simple ⟨by omega,by omega⟩ ⟨by omega,by omega⟩ h)
edge i := if i.val < p.length then p.edge i else chord
incidence := by
intro i v
by_cases hi : i.val < p.length
· rw [ite_eq_left hi,p.incidence i hi]
have hm : (i.val + 1) % (p.length + 1) = i.val + 1 := Nat.mod_eq_of_lt (by omega)
simp only [hm]
· have hil : i.val = p.length := by omega
rw [ite_eq_right hi,hc]
simp only [hil,Nat.mod_self]
exact or_comm
omit [Fintype V] [DecidableEq V] [DecidableEq E] in
lemma closedCycle_edgeAt (i : ℕ) (hi : i < p.length) :
(p.closedCycle chord hlong hc).edgeAt i = p.edge i := by
simp only [IndexedCycle.edgeAt,IndexedCycle.index,closedCycle]
rw [Nat.mod_eq_of_lt (by omega),ite_eq_left hi]
omit [Fintype V] [DecidableEq V] [DecidableEq E] in
lemma closedCycle_chord :
(p.closedCycle chord hlong hc).edgeAt p.length = chord := by
simp [IndexedCycle.edgeAt,IndexedCycle.index,closedCycle,Nat.mod_eq_of_lt (by omega : p.length < p.length+1)]
omit [Fintype V] [DecidableEq V] in
lemma closedCycle_parity_zero :
(p.closedCycle chord hlong hc).parityPattern 0 = p.through := by
ext e
simp only [IndexedCycle.parityPattern,IndexedCycle.mem_intervalPattern,through,
pathPattern,Finset.mem_image,Finset.mem_filter,Finset.mem_Ico]
constructor
· rintro ⟨i,hi,hj,hp,he⟩
have hil : i < p.length := by
change i < p.length + 1 at hj
have := p.odd
omega
exact ⟨i,⟨⟨by omega,hil⟩,by simpa using hp⟩,
(p.closedCycle_edgeAt chord hlong hc i hil).symm.trans he⟩
· rintro ⟨i,⟨hi,hp⟩,he⟩
refine ⟨i,by omega,by change i < p.length+1; omega,?_,?_⟩
· simpa using hp
· exact (p.closedCycle_edgeAt chord hlong hc i hi.2).trans he
omit [Fintype V] [DecidableEq V] in
lemma closedCycle_parity_one :
(p.closedCycle chord hlong hc).parityPattern 1 = p.closed chord := by
ext e
simp only [IndexedCycle.parityPattern,IndexedCycle.mem_intervalPattern,closed,
interior,pathPattern,Finset.mem_union,Finset.mem_image,Finset.mem_filter,
Finset.mem_Ico,Finset.mem_singleton]
constructor
· rintro ⟨i,hi,hj,hp,he⟩
change i < p.length+1 at hj
by_cases hil : i < p.length
· left
refine ⟨i,⟨⟨by omega,?_⟩,?_⟩, (p.closedCycle_edgeAt chord hlong hc i hil).symm.trans he⟩
· have := p.odd; omega
· omega
· right
have hie : i = p.length := by omega
subst i
exact he.symm.trans (p.closedCycle_chord chord hlong hc)
· rintro (⟨i,⟨hi,hp⟩,he⟩ | he)
· refine ⟨i,by omega,by change i < p.length+1; omega,by omega,?_⟩
exact (p.closedCycle_edgeAt chord hlong hc i (by omega)).trans he
· exact ⟨p.length,by omega,by change p.length < p.length+1; omega,
p.odd,(p.closedCycle_chord chord hlong hc).trans he.symm⟩
end MatchingFPRAS.Transport.OddPath
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Through
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [DecidableEq V] [DecidableEq E]
variable {inc : E → V → Prop}
namespace PatternCode
variable (x : PatternCode inc)
noncomputable def ofPath (p : OddPath inc) (chord : E) (hlong : 3 ≤ p.length)
(hc : ∀ v, inc chord v ↔ v = p.vertex 0 ∨ v = p.vertex p.length) : PatternCode inc :=
⟨(p.through,p.closed chord),p.closedCycle chord hlong hc,
p.closedCycle_parity_zero chord hlong hc,p.closedCycle_parity_one chord hlong hc⟩
end PatternCode
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
noncomputable instance instFintypePM : Fintype (PM inc) := Fintype.ofFinite _
noncomputable def gibbsLaw (w : E → ℝ) (hw : ∀ e, 0 < w e) (M : PM inc) :
MatchingFPRAS.PairEnergy.Law (PM inc) where
weight := gibbs w
nonneg := fun A => le_of_lt (gibbs_pos w hw A)
total := gibbs_sum w hw M
namespace PatternCode
noncomputable def throughStates (x : PatternCode inc) : Finset (PM inc) := by
classical
exact Finset.univ.filter (fun A => x.through ⊆ A.val)
noncomputable def closedStates (x : PatternCode inc) : Finset (PM inc) := by
classical
exact Finset.univ.filter (fun A => x.closed ⊆ A.val)
def firstDerivative (f : Finset E → ℝ) (x : PatternCode inc) (A : PM inc) : ℝ :=
f A.val - f ((A.val \ x.through) ∪ x.closed)
def secondDerivative (g : Finset E → ℝ) (x : PatternCode inc) (B : PM inc) : ℝ :=
g ((B.val \ x.closed) ∪ x.through) - g B.val
end PatternCode
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_2 : Fintype (BagEdge bags) := Fintype.ofFinite _
variable {hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b}
variable {hG : G.IsAcyclic}
namespace ErrorDemand
variable (e : ErrorDemand hbags hG)
omit [Fintype L] in
lemma X_long : 3 ≤ (e.demand.paths.side e.X).length := by
have hp := (e.demand.paths.side e.X).positive
have ho := (e.demand.paths.side e.X).odd
have hn := e.property e.X e.X_bit
change (e.demand.paths.side e.X).length ≠ 1 at hn
omega
noncomputable def pattern : PatternCode (BagEdge.Incident (bags := bags)) :=
PatternCode.ofPath (e.demand.paths.side e.X) (e.demand.paths.chord e.X) e.X_long
(e.demand.paths.chord_incidence e.X)
variable (height : L → ℝ) (hheight : ∀ l, 0 < height l)
variable (hstep : ∀ a b, G.Adj a b → height a ≤ 2 * height b)
variable (D : ℝ) (hD : 1 ≤ D) (w : BagEdge bags → ℝ)
variable (hw : ∀ e, height e.color / D ≤ w e ∧ w e ≤ 3 * height e.color)
variable (lo hi : ℝ) (hlo : 0 < lo) (hlohi : lo ≤ hi)
noncomputable def choice (j : Bool) : DemandEncoding BagEdge.Incident e.raw :=
if j then e.errorOne height hheight hstep D hD w hw lo hi hlo hlohi
else e.errorZero height hheight hstep D hD w hw lo hi hlo hlohi
end ErrorDemand
end MatchingFPRAS.Transport.CellDemands
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_SafeSwitch
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_3 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport.CellDemands
namespace MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
def SafeSwitch (w : E → ℝ) (K : ℝ) (A B : PM inc) : Prop :=
∃ (v : Fin 4 → V) (e : Fin 4 → E) (R : Finset E),
Function.Injective v ∧
(∀ i x, inc (e i) x ↔ x = v i ∨ x = v (i+1)) ∧
A.val = R ∪ {e 0,e 2} ∧ B.val = R ∪ {e 1,e 3} ∧
(∀ i j, w (e i) ≤ K * w (e j))
noncomputable def safeDestinations (w : E → ℝ) (K : ℝ) (A : PM inc) : Finset (PM inc) := by
classical
exact Finset.univ.filter (SafeSwitch w K A)
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport.CellDemands
section
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_4 : Fintype (BagEdge bags) := Fintype.ofFinite _
variable {hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b}
variable {hG : G.IsAcyclic}
namespace Demand
variable (d : Demand hbags hG)
noncomputable def switchState (b : Bool) : PM (BagEdge.Incident (bags := bags)) :=
let emb := d.corners.embeddedPair d.1.1 d.1.2 d.2.1.cycle_union
d.paths.chord d.paths.chord_incidence 0
emb.attachFirst (d.paths.switched b) (d.paths.switched_matching b)
end Demand
end
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_5 : Fintype (BagEdge bags) := Fintype.ofFinite _
variable {hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b}
variable {hG : G.IsAcyclic}
namespace Demand
noncomputable def cellError (d : Demand hbags hG) (f : Finset (BagEdge bags) → ℝ) (b : Bool) : ℝ :=
d.paths.contextError d.outside f b (if b then 2 else 3) (if b then 0 else 1)
noncomputable def cellSwitch (d : Demand hbags hG) (f : Finset (BagEdge bags) → ℝ) : ℝ :=
f (d.outside ∪ d.paths.switched true)-f (d.outside ∪ d.paths.switched false)
noncomputable def cellCost (d : Demand hbags hG) (f : Finset (BagEdge bags) → ℝ) : ℝ :=
(d.cellSwitch f)^2+(d.cellError f true)^2+(d.cellError f false)^2
end Demand
end MatchingFPRAS.Transport.CellDemands
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Underlying
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [DecidableEq V] [DecidableEq E]
namespace Overlay
variable (ends : E → Sym2 V) (hloop : ∀ e, ¬ (ends e).IsDiag)
omit [DecidableEq V] [DecidableEq E] in
lemma underlying_perfect [DecidableEq V] [DecidableEq E] (M : Finset E)
(hM : MatchingOn (fun e v => v ∈ ends e) M Finset.univ) :
(SimpleGraph.toSubgraph (G := ⊤) (underlying ends hloop M) le_top).IsPerfectMatching := by
rw [SimpleGraph.Subgraph.isPerfectMatching_iff]
intro v
obtain ⟨e, ⟨he, hev⟩, heuniq⟩ := hM.2 v (Finset.mem_univ v)
obtain ⟨w, hw⟩ := exists_partner ends hev
refine ⟨w, ⟨e, he, hw⟩, ?_⟩
rintro u ⟨f, hf, hfu⟩
have hfv : v ∈ ends f := by rw [hfu]; simp
have hfe := heuniq f ⟨hf, hfv⟩
have hsym : s(v,u) = s(v,w) := hfu.symm.trans ((congrArg ends hfe).trans hw)
have h : u = w ∨ v = w ∧ u = v := by simpa using hsym
exact h.elim id (fun h => h.2.trans h.1)
open scoped symmDiff
lemma discrepancy_alternating (M N : Finset E)
(hM : MatchingOn (fun e v => v ∈ ends e) M Finset.univ)
(hN : MatchingOn (fun e v => v ∈ ends e) N Finset.univ) :
(discrepancy ends hloop M N).IsAlternating (underlying ends hloop M) := by
have h := (underlying_perfect ends hloop M hM).isAlternating_symmDiff_left
(underlying_perfect ends hloop N hN)
exact h
lemma unique_colored_lift (M N : Finset E)
(hM : MatchingOn (fun e v => v ∈ ends e) M Finset.univ)
(hN : MatchingOn (fun e v => v ∈ ends e) N Finset.univ)
{v w : V} (hadj : (discrepancy ends hloop M N).Adj v w) :
∃! e, e ∈ M ∪ N ∧ ends e = s(v,w) := by
rcases (discrepancy_adj_iff ends hloop M N v w).mp hadj with h | h
· obtain ⟨e, he, hend⟩ := h.1
refine ⟨e, ⟨Finset.mem_union_left N he, hend⟩, ?_⟩
rintro f ⟨hf, hfend⟩
rcases Finset.mem_union.mp hf with hf | hf
· obtain ⟨g, hg, hu⟩ := hM.2 v (Finset.mem_univ v)
exact (hu f ⟨hf, by change v ∈ ends f; rw [hfend]; simp⟩).trans
(hu e ⟨he, by change v ∈ ends e; rw [hend]; simp⟩).symm
· exact (h.2 ⟨f, hf, hfend⟩).elim
· obtain ⟨e, he, hend⟩ := h.1
refine ⟨e, ⟨Finset.mem_union_right M he, hend⟩, ?_⟩
rintro f ⟨hf, hfend⟩
rcases Finset.mem_union.mp hf with hf | hf
· exact (h.2 ⟨f, hf, hfend⟩).elim
· obtain ⟨g, hg, hu⟩ := hN.2 v (Finset.mem_univ v)
exact (hu f ⟨hf, by change v ∈ ends f; rw [hfend]; simp⟩).trans
(hu e ⟨he, by change v ∈ ends e; rw [hend]; simp⟩).symm
noncomputable def cyclicEdge (M N : Finset E)
(hM : MatchingOn (fun e v => v ∈ ends e) M Finset.univ)
(hN : MatchingOn (fun e v => v ∈ ends e) N Finset.univ)
{v : V} (p : (discrepancy ends hloop M N).Walk v v) (hp : p.IsCycle) (i : ℕ) : E :=
(unique_colored_lift ends hloop M N hM hN (cyclicVertex_adj p hp i)).choose
lemma cyclicEdge_spec (M N : Finset E)
(hM : MatchingOn (fun e v => v ∈ ends e) M Finset.univ)
(hN : MatchingOn (fun e v => v ∈ ends e) N Finset.univ)
{v : V} (p : (discrepancy ends hloop M N).Walk v v) (hp : p.IsCycle) (i : ℕ) :
cyclicEdge ends hloop M N hM hN p hp i ∈ M ∪ N ∧
ends (cyclicEdge ends hloop M N hM hN p hp i) =
s(cyclicVertex p i, cyclicVertex p (i + 1)) :=
(unique_colored_lift ends hloop M N hM hN (cyclicVertex_adj p hp i)).choose_spec.1
end Overlay
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport.Overlay
section
variable {V E : Type*} [Fintype V] [DecidableEq V] [DecidableEq E]
variable (ends : E → Sym2 V) (hloop : ∀ e, ¬ (ends e).IsDiag)
variable (M N : Finset E)
variable (hM : MatchingOn (fun e v => v ∈ ends e) M Finset.univ)
variable (hN : MatchingOn (fun e v => v ∈ ends e) N Finset.univ)
noncomputable def indexedCycle {v : V}
(p : (discrepancy ends hloop M N).Walk v v) (hp : p.IsCycle) :
IndexedCycle (fun e v => v ∈ ends e) where
size := p.length
four_le := by
have hh := hp.three_le_length
have he := alternating_cycle_parity p hp (discrepancy_alternating ends hloop M N hM hN)
omega
even := alternating_cycle_parity p hp (discrepancy_alternating ends hloop M N hM hN)
vertex i := cyclicVertex p i.val
simple := by
intro i j h
apply Fin.ext
exact cyclicVertex_injOn p hp ⟨Nat.zero_le _, i.isLt⟩ ⟨Nat.zero_le _, j.isLt⟩ h
edge i := cyclicEdge ends hloop M N hM hN p hp i.val
incidence := by
intro i w
rw [(cyclicEdge_spec ends hloop M N hM hN p hp i.val).2]
simp only [Sym2.mem_iff, cyclicVertex, Nat.mod_mod]
end
end MatchingFPRAS.Transport.Overlay
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_ComponentOrder
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
noncomputable def prefixPair (p : PM inc × PM inc) (i : ℕ) : PM inc × PM inc :=
(⟨exchange p.1.val p.2.val (componentPrefix (inc := inc) (p.1.val ∪ p.2.val) i),
exchange_matching p.1.property p.2.property (componentPrefix_compatible _ _ _)⟩,
⟨exchange p.2.val p.1.val (componentPrefix (inc := inc) (p.1.val ∪ p.2.val) i),
exchange_matching p.2.property p.1.property (componentPrefix_compatible _ _ _).symm⟩)
noncomputable def componentPair (p : PM inc × PM inc) (i : ℕ) : PM inc × PM inc :=
(⟨exchange p.1.val p.2.val (componentAt (inc := inc) (p.1.val ∪ p.2.val) i),
exchange_matching p.1.property p.2.property (componentAt_compatible _ _ _)⟩,
⟨exchange p.2.val p.1.val (componentAt (inc := inc) (p.1.val ∪ p.2.val) i),
exchange_matching p.2.property p.1.property (componentAt_compatible _ _ _).symm⟩)
noncomputable def componentDifference (f : PM inc → ℝ) (p : PM inc × PM inc) (i : ℕ) : ℝ :=
f p.1 - f (componentPair p i).1
end
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
def ColorChange (A B : PM (fun e v => v ∈ ends e)) : Prop :=
∃ e f : E, ∃ R : Finset E, ends e = ends f ∧ A.val = R ∪ {e} ∧ B.val = R ∪ {f}
noncomputable def colorDestinations (A : PM (fun e v => v ∈ ends e)) :
Finset (PM (fun e v => v ∈ ends e)) := by
classical
exact Finset.univ.filter (ColorChange ends A)
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_6 : Fintype (BagEdge bags) := Fintype.ofFinite _
variable {hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b}
variable {hG : G.IsAcyclic}
noncomputable def longCellCost (p : PM (BagEdge.Incident (bags := bags)) × PM (BagEdge.Incident (bags := bags)))
(f : Finset (BagEdge bags) → ℝ) : ℝ :=
∑ S : LongComponent p, ∑ a : ↥(S.cycle.subdivision hbags hG).cellSet,
(show Demand hbags hG from ⟨p,S,a⟩).cellCost f
noncomputable def colorCost (A : PM (BagEdge.Incident (bags := bags)))
(f : Finset (BagEdge bags) → ℝ) : ℝ :=
∑ B ∈ colorDestinations (fun e : BagEdge bags => e.val.val.1) A, (f A.val-f B.val)^2
end MatchingFPRAS.Transport.CellDemands
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_EndpointPair
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_7 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport.CellDemands
namespace MatchingFPRAS.Transport
section
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance endpointPairBagEdgeFintype : Fintype (BagEdge bags) :=
Fintype.ofFinite _
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
variable (hG : G.IsAcyclic)
namespace BagEdge
noncomputable def endpointPair (e : BagEdge bags) : V × V :=
Classical.choose (show ∃ p : V × V, e.val.val.1 = s(p.1,p.2) from
Sym2.inductionOn e.val.val.1 (fun a b => ⟨(a,b),rfl⟩))
omit [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L] in
lemma endpointPair_eq (e : BagEdge bags) : e.val.val.1 = s(e.endpointPair.1,e.endpointPair.2) :=
Classical.choose_spec (show ∃ p : V × V, e.val.val.1 = s(p.1,p.2) from
Sym2.inductionOn e.val.val.1 (fun a b => ⟨(a,b),rfl⟩))
noncomputable def verticesColor (e : BagEdge bags) : Σ v : V, V × ↥(bags v) :=
⟨e.endpointPair.1,e.endpointPair.2,⟨e.color,e.property _ (by
change e.endpointPair.1 ∈ e.val.val.1
rw [e.endpointPair_eq]
simp)⟩⟩
end BagEdge
end
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
def TwoEdgeSwitch (A B : PM inc) : Prop :=
∃ (v : Fin 4 → V) (e : Fin 4 → E) (R : Finset E),
Function.Injective v ∧
(∀ i x, inc (e i) x ↔ x = v i ∨ x = v (i+1)) ∧
A.val = R ∪ {e 0,e 2} ∧ B.val = R ∪ {e 1,e 3}
noncomputable def switchDestinations (A : PM inc) : Finset (PM inc) := by
classical
exact Finset.univ.filter (TwoEdgeSwitch A)
noncomputable def discrepancyComponents (A B : PM inc) : Finset (Finset E) := by
classical
exact (components (inc := inc) (A.val ∪ B.val)).filter (fun S => ¬ S ⊆ A.val ∩ B.val)
noncomputable def switchDirichlet (w : E → ℝ) (f : Finset E → ℝ) : ℝ :=
∑ A : PM inc, ∑ B ∈ switchDestinations A,
min (gibbs w A) (gibbs w B) * (f A.val-f B.val)^2 / (48 * (A.val.card.choose 2 : ℝ))
noncomputable def cycleDirichlet (w : E → ℝ) (f g : Finset E → ℝ) : ℝ :=
∑ A : PM inc, ∑ B : PM inc, gibbs w A * gibbs w B *
(∑ S ∈ discrepancyComponents A B, cycleSquare f g A.val B.val S /
(6 * ((discrepancyComponents A B).card : ℝ)))
variable (ends : E → Sym2 V)
noncomputable def colorDirichlet (w : E → ℝ) (f : Finset E → ℝ) : ℝ :=
∑ A : PM (fun e v => v ∈ ends e), ∑ B ∈ colorDestinations ends A,
min (gibbs w A) (gibbs w B) * (f A.val-f B.val)^2 / (12 * (A.val.card : ℝ))
noncomputable def pairDirichlet (w : E → ℝ) (f g : Finset E → ℝ) : ℝ :=
switchDirichlet (inc := fun e v => v ∈ ends e) w f + colorDirichlet ends w f +
cycleDirichlet (inc := fun e v => v ∈ ends e) w f g
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Probability_Variance
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.CellDemands
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_8 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport.CellDemands
namespace MatchingFPRAS.Transport
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V) (hloop : ∀ e, ¬(ends e).IsDiag)
include hloop
omit [Fintype E] [DecidableEq E] in
lemma PM.twice_card (A : PM (fun e v => v ∈ ends e)) : 2*A.val.card = Fintype.card V := by
classical
have hv (v : V) : (∑ e ∈ A.val, if v ∈ ends e then (1:ℕ) else 0) = 1 := by
obtain ⟨e,⟨he,hev⟩,hu⟩ := A.property.2 v (Finset.mem_univ v)
rw [Finset.sum_eq_single e]
· simp [hev]
· intro f hf hfe
have : v ∉ ends f := fun hfv => hfe (hu f ⟨hf,hfv⟩)
simp [this]
· exact fun h => (h he).elim
have he (e : E) : (∑ v : V, if v ∈ ends e then (1:ℕ) else 0) = 2 := by
have hs : Finset.univ.filter (fun v => v ∈ ends e) = (ends e).toFinset := by
ext v; simp
rw [← Finset.sum_filter,Finset.sum_const,smul_eq_mul,mul_one,hs]
exact Sym2.card_toFinset_of_not_isDiag _ (hloop e)
calc
_ = ∑ e ∈ A.val, ∑ v : V, if v ∈ ends e then (1:ℕ) else 0 := by
simp [he,Nat.mul_comm]
_ = ∑ v : V, ∑ e ∈ A.val, if v ∈ ends e then (1:ℕ) else 0 := by rw [Finset.sum_comm]
_ = _ := by simp [hv]
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Arithmetic_ArithmeticSize
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.StackComposition
open Turing MachineCost
variable {K Λ P σ : Type*} {Γ : K → Type*} [DecidableEq K]
omit [DecidableEq K] in
lemma mapCfg_none (f : Λ → P) (h : Option P) (v : σ) (S : ∀ k,List (Γ k)) :
mapCfg f h ⟨none,v,S⟩=⟨h,v,S⟩ := rfl
open Turing MachineCost
end MatchingFPRAS.StackComposition
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_FillHoles
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Switching
open Finset
open scoped Classical symmDiff
variable {V : Type*}
theorem mate_edge_count [Fintype V] [LinearOrder V] (q : Mate V) (S : Finset V)
(hq : HasHoles q Sᶜ) :
2 * (Finset.univ.filter (fun v => v < q.1 v)).card = S.card := by
let L := Finset.univ.filter (fun v => v < q.1 v)
let R := Finset.univ.filter (fun v => q.1 v < v)
have himg : L.image q.1 = R := by
ext v
simp only [Finset.mem_image, L,R,Finset.mem_filter,Finset.mem_univ,true_and]
constructor
· rintro ⟨a,ha,rfl⟩
simpa using ha
· intro hv
exact ⟨q.1 v,by simpa using hv,mate_mate q v⟩
have hcard : L.card = R.card := by
rw [← himg]
exact (Finset.card_image_of_injective L q.2.injective).symm
have hdis : Disjoint L R := by
apply Finset.disjoint_left.mpr
intro v hl hr
have hl' : v < q.1 v := (Finset.mem_filter.mp hl).2
have hr' : q.1 v < v := (Finset.mem_filter.mp hr).2
exact (lt_asymm hl' hr')
have hunion : L ∪ R = S := by
ext v
simp only [L,R,Finset.mem_union,Finset.mem_filter,Finset.mem_univ,true_and]
rw [← ne_iff_lt_or_gt]
have h := hq v
simp only [Finset.mem_compl] at h
simpa only [ne_eq, eq_comm, not_not] using (not_congr h)
have hc := Finset.card_union_of_disjoint hdis
rw [hunion,← hcard] at hc
change 2 * L.card = S.card
omega
theorem pairing_exists [Fintype V] [DecidableEq V] (S : Finset V) (hS : Even S.card) :
∃ q : Mate V, HasHoles q Sᶜ := by
classical
induction S using Finset.strongInductionOn with
| _ S ih =>
by_cases hEmpty : S = ∅
· subst S
refine ⟨⟨id,fun _ => rfl⟩,?_⟩
intro v
simp
· obtain ⟨a,ha⟩ := Finset.nonempty_iff_ne_empty.mpr hEmpty
have hcardpos := Finset.card_pos.mpr (show S.Nonempty from ⟨a,ha⟩)
have hcard2 : 2 ≤ S.card := by obtain ⟨k,hk⟩ := hS; omega
have herase : (S.erase a).Nonempty := by
apply Finset.card_pos.mp
rw [Finset.card_erase_of_mem ha]
omega
obtain ⟨b,hb⟩ := herase
have hba := (Finset.mem_erase.mp hb).1
have hbS := (Finset.mem_erase.mp hb).2
let T := S \ {a,b}
have hTcard : T.card + 2 = S.card := by
have h := sdiff_pair_card S a b ha hbS hba.symm
change T.card = S.card - 2 at h
omega
have hTeven : Even T.card := by
obtain ⟨k,hk⟩ := hS
refine ⟨k-1,?_⟩
omega
have hTsub : T ⊂ S := Finset.ssubset_iff_subset_ne.mpr
⟨Finset.sdiff_subset,by intro he; have := congrArg Finset.card he; omega⟩
obtain ⟨q,hq⟩ := ih T hTsub hTeven
have haT : a ∈ Tᶜ := by simp [T]
have hbT : b ∈ Tᶜ := by simp [T]
refine ⟨withEdge q a b,?_⟩
have hh := withEdge_holes q Tᶜ hq a b haT hbT hba.symm
have he : Tᶜ \ {a,b} = Sᶜ := by
ext v
simp only [T,Finset.mem_sdiff,Finset.mem_compl,Finset.mem_insert,Finset.mem_singleton]
have hsub : ({a,b} : Finset V) ⊆ S := by
intro x hx
simp only [Finset.mem_insert,Finset.mem_singleton] at hx
rcases hx with rfl | rfl <;> assumption
constructor
· intro h
tauto
· intro hv
constructor
· tauto
· intro hvp
exact hv (hsub (by simpa using hvp))
rwa [he] at hh
noncomputable def pairingCapacity [Fintype V] [LinearOrder V]
(B : V → V → ℝ) (S : Finset V) (hS : Even S.card) : ℝ :=
(matchings Sᶜ).sup' (by
obtain ⟨q,hq⟩ := pairing_exists S hS
exact ⟨q,(mem_matchings q Sᶜ).mpr hq⟩) (weight B)
end MatchingFPRAS.Switching
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_SumLiftMate
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Switching
section
open Finset
variable {V W : Type*}
def sumRetractMate (q : Mate (V ⊕ W)) (hfix : ∀ w, q.val (Sum.inr w)=Sum.inr w) : Mate V := by
let f : V → V := fun a => Sum.elim id (fun _ => a) (q.val (Sum.inl a))
have hf : ∀ a, Sum.inl (f a)=q.val (Sum.inl a) := by
intro a
cases he : q.val (Sum.inl a) with
| inl b => simp [f,he]
| inr w =>
have hh := q.property (Sum.inl a)
rw [he,hfix] at hh
contradiction
refine ⟨f,?_⟩
intro a
apply Sum.inl_injective (β := W)
rw [hf,hf,q.property]
end
end MatchingFPRAS.Switching
namespace MatchingFPRAS.Subdivision
open Finset
noncomputable def selectedWeight {m : ℕ} (w : Fin (m+1) → ℝ) (b : Selection m) : ℝ :=
∏ i, if b i then w i else 1
end MatchingFPRAS.Subdivision
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Profile
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Subdivision
open Finset
lemma valid_step_eq_iff {m : ℕ} {U : Finset (Fin m)} {b c : Selection m}
(hb : Valid U b) (hc : Valid U c) (i : Fin m) :
b i.castSucc = c i.castSucc ↔ b i.succ = c i.succ := by
by_cases hi : i ∈ U
· have hb' := hb i
have hc' := hc i
simp only [hi, ↓reduceIte] at hb' hc'
simp [hb'.1,hb'.2,hc'.1,hc'.2]
· have hb' : b i.succ = !(b i.castSucc) := by
apply (bool_ne_iff_eq_not _ _).mp
simpa only [hi, ↓reduceIte] using hb i
have hc' : c i.succ = !(c i.castSucc) := by
apply (bool_ne_iff_eq_not _ _).mp
simpa only [hi, ↓reduceIte] using hc i
rw [hb',hc']
simp
lemma valid_eq_iff_zero {m : ℕ} {U : Finset (Fin m)} {b c : Selection m}
(hb : Valid U b) (hc : Valid U c) (i : Fin (m+1)) :
b i = c i ↔ b 0 = c 0 := by
have aux (k : ℕ) (hk : k < m+1) : b ⟨k,hk⟩ = c ⟨k,hk⟩ ↔ b 0 = c 0 := by
induction k with
| zero => rfl
| succ k ih =>
have hk' : k < m := by omega
exact ((valid_step_eq_iff hb hc ⟨k,hk'⟩).symm).trans (ih (by omega))
exact aux i.val i.isLt
theorem broken_unique {m : ℕ} {U : Finset (Fin m)} (hU : U.Nonempty)
{b c : Selection m} (hb : Valid U b) (hc : Valid U c) : b = c := by
obtain ⟨j,hj⟩ := hU
have hb' := hb j
have hc' := hc j
simp only [hj, ↓reduceIte] at hb' hc'
have hzero := (valid_eq_iff_zero hb hc j.castSucc).mp (hb'.1.trans hc'.1.symm)
funext i
exact (valid_eq_iff_zero hb hc i).mpr hzero
section Deletion
variable {V E : Type*} [Fintype V] [Fintype E]
theorem residualHoles_independent {m : ℕ} (u v : E → V) (R₀ : Finset V)
(U : E → Finset (Fin m)) {b c : E → Selection m}
(hb : FamilyHoles u v m R₀ U b) (hc : FamilyHoles u v m R₀ U c) :
residualHoles u v R₀ U b = residualHoles u v R₀ U c := by
classical
have he (e) (h : e ∈ broken U) : b e = c e :=
broken_unique ((mem_broken U e).mp h) (hb.1 e) (hc.1 e)
ext x
simp only [mem_residualHoles]
apply or_congr Iff.rfl
apply exists_congr
intro e
constructor <;> rintro ⟨h,hx⟩ <;> refine ⟨h,?_⟩
· simpa only [Uses,he e h] using hx
· simpa only [Uses,he e h] using hx
noncomputable def extract {m : ℕ} (U : E → Finset (Fin m))
(b : E → Selection m) (e : E) : Bool :=
if (U e).Nonempty then false else b e 0
theorem extract_legal {m : ℕ} (hm : Even m) (u v : E → V) (R₀ : Finset V)
(U : E → Finset (Fin m)) (b : E → Selection m)
(hb : FamilyHoles u v m R₀ U b) :
LogicalHoles u v (residualHoles u v R₀ U b) (broken U) (extract U b) := by
classical
have he (e x) : extract U b e = true ∧ (u e = x ∨ v e = x) ↔
e ∉ broken U ∧ Uses u v b e x := by
by_cases h : (U e).Nonempty
· simp [extract,h]
· have hu : U e = ∅ := Finset.not_nonempty_iff_eq_empty.mp h
simp only [extract,h,↓reduceIte,mem_broken,not_false_eq_true,true_and]
exact (intact_uses hm u v b e x (by simpa [hu] using hb.1 e)).symm
refine ⟨?_,?_,?_⟩
· intro e he'
simp [extract,(mem_broken U e).mp he']
· intro x hx e hxe
rw [he] at hxe
rcases (mem_residualHoles u v R₀ U b x).mp hx with hx | ⟨f,hf,hfx⟩
· exact hb.2.1 x hx e hxe.2
· have hx0 : x ∉ R₀ := by intro hx0; exact hb.2.1 x hx0 f hfx
obtain ⟨a,ha,hu⟩ := hb.2.2 x hx0
have hef : e = f := (hu e hxe.2).trans (hu f hfx).symm
exact hxe.1 (hef.symm ▸ hf)
· intro x hx
have hx0 : x ∉ R₀ := by intro h; exact hx ((mem_residualHoles _ _ _ _ _ _).mpr (Or.inl h))
obtain ⟨e,he',hu⟩ := hb.2.2 x hx0
have hn : e ∉ broken U := by
intro h
exact hx ((mem_residualHoles _ _ _ _ _ _).mpr (Or.inr ⟨e,h,he'⟩))
refine ⟨e,(he e x).mpr ⟨hn,he'⟩,?_⟩
intro f hf
exact hu f ((he f x).mp hf).2
noncomputable def rebuild {m : ℕ} (U : E → Finset (Fin m))
(base : E → Selection m) (s : E → Bool) (e : E) : Selection m :=
if (U e).Nonempty then base e else fun i => alternating (s e) i.val
omit [Fintype V] in
lemma rebuild_uses {m : ℕ} (hm : Even m) (u v : E → V)
(U : E → Finset (Fin m)) (base : E → Selection m) (s : E → Bool) (e : E) (x : V) :
Uses u v (rebuild U base s) e x ↔
(e ∈ broken U ∧ Uses u v base e x) ∨
(e ∉ broken U ∧ s e = true ∧ (u e = x ∨ v e = x)) := by
classical
by_cases h : (U e).Nonempty
· simp [rebuild,h,Uses]
· simp [rebuild,h,Uses,alternating,Nat.even_iff.mp hm,and_or_left]
theorem rebuild_legal {m : ℕ} (hm : Even m) (u v : E → V) (R₀ : Finset V)
(U : E → Finset (Fin m)) (base : E → Selection m)
(hb : FamilyHoles u v m R₀ U base) (s : E → Bool)
(hs : LogicalHoles u v (residualHoles u v R₀ U base) (broken U) s) :
FamilyHoles u v m R₀ U (rebuild U base s) := by
classical
let R := residualHoles u v R₀ U base
have hu (e x) := rebuild_uses hm u v U base s e x
refine ⟨?_,?_,?_⟩
· intro e
by_cases he : (U e).Nonempty
· simpa [rebuild,he] using hb.1 e
· have he' : U e = ∅ := Finset.not_nonempty_iff_eq_empty.mp he
simpa [rebuild,he,he'] using alternating_valid m (s e)
· intro x hx e he
have hxR : x ∈ R := (mem_residualHoles _ _ _ _ _ _).mpr (Or.inl hx)
rcases (hu e x).mp he with ⟨_,he⟩ | ⟨_,he⟩
· exact hb.2.1 x hx e he
· exact hs.2.1 x hxR e he
· intro x hx
by_cases hxR : x ∈ R
· obtain hx0 | ⟨e,he,hxe⟩ := (mem_residualHoles _ _ _ _ _ _).mp hxR
· exact (hx hx0).elim
obtain ⟨a,ha,hauniq⟩ := hb.2.2 x hx
refine ⟨e,(hu e x).mpr (Or.inl ⟨he,hxe⟩),?_⟩
intro f hf
rcases (hu f x).mp hf with ⟨_,hf⟩ | ⟨_,hf⟩
· exact (hauniq f hf).trans (hauniq e hxe).symm
· exact (hs.2.1 x hxR f hf).elim
· obtain ⟨e,he,heuniq⟩ := hs.2.2 x hxR
have hen : e ∉ broken U := by
intro he'
have := hs.1 e he'
simp [this] at he
refine ⟨e,(hu e x).mpr (Or.inr ⟨hen,he⟩),?_⟩
intro f hf
rcases (hu f x).mp hf with ⟨hfb,hf⟩ | ⟨_,hf⟩
· exact (hxR ((mem_residualHoles _ _ _ _ _ _).mpr (Or.inr ⟨f,hfb,hf⟩))).elim
· exact heuniq f hf
omit [Fintype V] [Fintype E] in
theorem rebuild_extract [Fintype V] [Fintype E] {m : ℕ} (u v : E → V) (R₀ : Finset V)
(U : E → Finset (Fin m)) (base b : E → Selection m)
(hb0 : FamilyHoles u v m R₀ U base) (hb : FamilyHoles u v m R₀ U b) :
rebuild U base (extract U b) = b := by
classical
funext e i
by_cases he : (U e).Nonempty
· have hbe := broken_unique he (hb0.1 e) (hb.1 e)
simp [rebuild,he,hbe]
· have he' : U e = ∅ := Finset.not_nonempty_iff_eq_empty.mp he
have hl := (intact_iff (b e)).mp (by simpa [he'] using hb.1 e) i
simpa [rebuild,extract,he] using hl.symm
omit [Fintype V] [Fintype E] in
theorem extract_rebuild [Fintype V] [Fintype E] {m : ℕ} (u v : E → V) (R : Finset V)
(U : E → Finset (Fin m)) (base : E → Selection m) (s : E → Bool)
(hs : LogicalHoles u v R (broken U) s) :
extract U (rebuild U base s) = s := by
classical
funext e
by_cases he : (U e).Nonempty
· have hs' := hs.1 e ((mem_broken U e).mpr he)
simp [extract,he,hs']
· simp [extract,rebuild,he]
noncomputable def deletionEquiv {m : ℕ} (hm : Even m) (u v : E → V) (R₀ : Finset V)
(U : E → Finset (Fin m)) (base : E → Selection m)
(hb : FamilyHoles u v m R₀ U base) :
{b : E → Selection m // FamilyHoles u v m R₀ U b} ≃
{s : E → Bool // LogicalHoles u v (residualHoles u v R₀ U base) (broken U) s} where
toFun b := ⟨extract U b.val, by
have h := extract_legal hm u v R₀ U b.val b.property
rwa [residualHoles_independent u v R₀ U b.property hb] at h⟩
invFun s := ⟨rebuild U base s.val,rebuild_legal hm u v R₀ U base hb s.val s.property⟩
left_inv b := Subtype.ext (rebuild_extract u v R₀ U base b.val hb b.property)
right_inv s := Subtype.ext (extract_rebuild u v _ U base s.val s.property)
noncomputable def realHolePartition (u v : E → V) (m : ℕ) (R₀ : Finset V)
(U : E → Finset (Fin m)) (w : E → Fin (m+1) → ℝ) : ℝ := by
classical
letI := Fintype.ofFinite {b : E → Selection m // FamilyHoles u v m R₀ U b}
exact ∑ b : {b : E → Selection m // FamilyHoles u v m R₀ U b},
∏ e, selectedWeight (w e) (b.val e)
noncomputable def logicalHolePartition (u v : E → V) (R : Finset V)
(forbidden : Finset E) (lam : E → ℝ) : ℝ := by
classical
letI := Fintype.ofFinite {s : E → Bool // LogicalHoles u v R forbidden s}
exact ∑ s : {s : E → Bool // LogicalHoles u v R forbidden s},
∏ e, if s.val e then lam e else 1
noncomputable def deletionConstant {m : ℕ} (U : E → Finset (Fin m))
(base : E → Selection m) (w : E → Fin (m+1) → ℝ) (C : E → ℝ) : ℝ :=
∏ e, if (U e).Nonempty then selectedWeight (w e) (base e) else C e
end Deletion
end MatchingFPRAS.Subdivision
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_HoleBlocks
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Subdivision
open Finset
def HoleBlocks.flatten {m : ℕ} (d : HoleBlocks m) : List (Fin m) :=
d.left.toList ++ d.neutral.flatMap (fun q => [q.1,q.2]) ++ d.right.toList
def HoleBlocks.Parity {m : ℕ} (d : HoleBlocks m) : Prop :=
(∀ j ∈ d.left, j.val%2=1) ∧
(∀ q ∈ d.neutral, q.1.val%2=0 ∧ q.2.val%2=1) ∧
(∀ j ∈ d.right, j.val%2=0)
end MatchingFPRAS.Subdivision
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Related
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Hierarchy
variable {V : Type*} [Fintype V]
variable (B : V → V → ℝ)
variable (hsym : ∀ a b, B a b = B b a)
variable (htri : ∀ a b c, a ≠ b → a ≠ c → b ≠ c → min (B a c) (B c b) ≤ B a b)
omit [Fintype V] in
lemma related_mono {s t : ℝ} (hst : s ≤ t) {a b : V} (h : Related B t a b) :
Related B s a b := h.imp id (fun hb => hst.trans hb)
variable (hfloor : ∀ a b, 1 ≤ B a b)
noncomputable instance labelFintype (H : ℕ) : Fintype (Label B hsym htri H) := Fintype.ofFinite _
lemma dyadic_lower (H : ℕ) (x : ℝ) (hx : 1 ≤ x) :
(2:ℝ)^(dyadicLevel H x).val ≤ x := by
classical
exact Nat.findGreatest_spec (P := fun k => (2:ℝ)^k ≤ x) (Nat.zero_le H) (by simpa using hx)
lemma dyadic_upper_of_lt (H : ℕ) (x : ℝ) (hx : x < (2:ℝ)^(H+1)) :
x < (2:ℝ)^((dyadicLevel H x).val+1) := by
classical
by_cases he : (dyadicLevel H x).val=H
· simpa [he] using hx
· by_contra hn
have hle : (dyadicLevel H x).val+1 ≤ H := by have := (dyadicLevel H x).isLt; omega
have hg := Nat.le_findGreatest (P := fun k => (2:ℝ)^k ≤ x) hle (le_of_not_gt hn)
change (dyadicLevel H x).val+1 ≤ (dyadicLevel H x).val at hg
omega
lemma dyadic_near_of_lt (H : ℕ) (x y : ℝ) (hxlo : 1≤x) (hyhi : y < (2:ℝ)^(H+1))
(hxy : x≤2*y) : (dyadicLevel H x).val ≤ (dyadicLevel H y).val+1 := by
by_contra hn
have hpow : (2:ℝ)^((dyadicLevel H y).val+2) ≤ 2^(dyadicLevel H x).val :=
pow_le_pow_right₀ (by norm_num) (by omega)
have hx := dyadic_lower H x hxlo
have hy := dyadic_upper_of_lt H y hyhi
rw [show (dyadicLevel H y).val+2=((dyadicLevel H y).val+1)+1 by omega,pow_succ] at hpow
linarith
variable {E : Type*} [Fintype E] (left right : E → V) (H : ℕ)
variable (hupper : ∀ e, B (left e) (right e) < (2:ℝ)^(H+1))
variable (hnear : ∀ x e f, Incident left right e x → Incident left right f x →
B (left e) (right e) ≤ 2*B (left f) (right f))
omit [Fintype V] in
include hfloor hupper hnear in
lemma memberships_level_near {x : V} {a b : Label B hsym htri H}
(ha : a ∈ memberships B hsym htri left right H x)
(hb : b ∈ memberships B hsym htri left right H x) : a.1.val ≤ b.1.val+1 := by
obtain ⟨e,he,rfl⟩ := (mem_memberships B hsym htri left right H x a).mp ha
obtain ⟨f,hf,rfl⟩ := (mem_memberships B hsym htri left right H x b).mp hb
exact dyadic_near_of_lt H _ _ (hfloor _ _) (hupper f) (hnear x e f he hf)
end MatchingFPRAS.Hierarchy
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Height
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
open Finset
variable {V E : Type*} [Fintype V] [Fintype E] [DecidableEq V] [DecidableEq E]
variable (inc : E → V → Prop)
noncomputable instance partialFintype : Fintype (Partial inc) := Fintype.ofFinite _
omit [Fintype E] [DecidableEq V] [DecidableEq E] in
lemma submatching {M Q : Finset E} {U : Finset V} (hM : MatchingOn inc M U) (hQ : Q⊆M) :
MatchingOn inc Q (support inc Q) := by
refine ⟨?_,?_⟩
· intro e he v hv; exact (mem_support inc Q v).mpr ⟨e,he,hv⟩
· intro v hv
obtain ⟨e,he,hev⟩ := (mem_support inc Q v).mp hv
refine ⟨e,⟨he,hev⟩,?_⟩
intro f hf
exact hM.unique (hM.1 e (hQ he) v hev) (hQ hf.1) hf.2 (hQ he) hev
omit [Fintype E] [DecidableEq E] in
lemma support_sdiff_disjoint (Q : Finset E) : Disjoint (support inc Q) (univ \ support inc Q) := by
exact Finset.disjoint_left.mpr (fun x hx hy => (Finset.mem_sdiff.mp hy).2 hx)
noncomputable def expansionEquiv (hinc : ∀ e, ∃ v, inc e v) :
(Σ M : Matchings inc univ, {Q : Finset E // Q⊆M.val}) ≃
Σ Q : Partial inc, Matchings inc (univ \ support inc Q.val) where
toFun a := ⟨⟨a.2.val,submatching inc a.1.property a.2.property⟩,
⟨a.1.val \ a.2.val,a.1.property.sdiff
(submatching inc a.1.property a.2.property) a.2.property⟩⟩
invFun a := ⟨⟨a.1.val ∪ a.2.val,by
have h := a.1.property.union a.2.property (support_sdiff_disjoint inc a.1.val)
rw [Finset.union_sdiff_of_subset (Finset.subset_univ _)] at h
exact h⟩,⟨a.1.val,Finset.subset_union_left⟩⟩
left_inv a := by
rcases a with ⟨M,Q,hQ⟩
have h : Q ∪ (M.val \ Q)=M.val := Finset.union_sdiff_of_subset hQ
apply Sigma.ext (Subtype.ext h)
change HEq (⟨Q,Finset.subset_union_left⟩ : {R : Finset E // R ⊆ Q ∪ (M.val \ Q)})
(⟨Q,hQ⟩ : {R : Finset E // R ⊆ M.val})
exact (Subtype.heq_iff_coe_eq (fun R => by rw [h])).mpr rfl
right_inv a := by
rcases a with ⟨Q,M⟩
have hd : Disjoint Q.val M.val := Q.property.disjoint_edges M.property hinc
(support_sdiff_disjoint inc Q.val)
change (⟨Q,⟨(Q.val ∪ M.val) \ Q.val,_⟩⟩ :
Σ Q : Partial inc, Matchings inc (univ \ support inc Q.val)) = ⟨Q,M⟩
apply congrArg (fun R : Matchings inc (univ \ support inc Q.val) =>
(⟨Q,R⟩ : Σ Q : Partial inc, Matchings inc (univ \ support inc Q.val)))
exact Subtype.ext (Finset.union_sdiff_cancel_left hd)
end
open Finset
variable {V E : Type*} [Fintype V] [Fintype E] [DecidableEq V] [DecidableEq E]
variable (inc : E → V → Prop)
noncomputable def emptyPartial : Partial inc := ⟨∅,by simp [MatchingOn]⟩
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Incident
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Representation
open MatchingFPRAS.Switching MatchingFPRAS.Subdivision MatchingFPRAS.Enlargement
open Finset
variable {V : Type*} [Fintype V] [LinearOrder V]
variable (R : Finset V) (s : LogicalEdge V → Bool)
(hs : LogicalHoles source target R ∅ s)
lemma asMate_holes : HasHoles (asMate R s hs) R := by
intro x
change mateFun R s hs x=x ↔ x ∈ R
by_cases hx : x ∈ R
· simp [hx,mateFun_hole R s hs x hx]
· simp only [hx,iff_false]
change mateFun R s hs x ≠ x
rw [mateFun_selected R s hs _ (chosen_spec R s hs x hx).1 x (chosen_spec R s hs x hx).2]
exact other_ne _ x (chosen_spec R s hs x hx).2
variable {R s hs}
lemma asMate_select (m : Mate V) (hm : HasHoles m R) :
asMate R (select m) (select_holes m hm)=m := by
apply Subtype.ext
funext x
by_cases hx : x ∈ R
· exact (mateFun_hole R _ _ x hx).trans ((hm x).mpr hx).symm
· let h := select_holes m hm
let e := chosen R (select m) h x hx
have he := chosen_spec R (select m) h x hx
exact (mateFun_selected R _ h e he.1 x he.2).trans
(select_mate_other m e he.1 x he.2).symm
noncomputable def matchingEquiv (R : Finset V) :
{s : LogicalEdge V → Bool // LogicalHoles source target R ∅ s} ≃
{m : Mate V // HasHoles m R} where
toFun s := ⟨asMate R s.val s.property,asMate_holes R s.val s.property⟩
invFun m := ⟨select m.val,select_holes m.val m.property⟩
left_inv _selection := Subtype.ext select_asMate
right_inv m := Subtype.ext (asMate_select m.val m.property)
end MatchingFPRAS.Representation
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_EdgeLow
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
open Finset MatchingFPRAS.Switching
variable {V E : Type*} [Fintype V] [LinearOrder V]
variable (edge : E → Sym2 V) (hnd : ∀ e, ¬(edge e).IsDiag)
local notation "inc" => (fun (e : E) (x : V) => x ∈ edge e)
variable (Q : Partial (fun (e : E) (x : V) => x ∈ edge e))
noncomputable def pickedEdge (x : V) (hx : x ∈ support inc Q.val) : E :=
Classical.choose (Q.property.2 x hx)
omit [LinearOrder V] in
lemma pickedEdge_spec (x : V) (hx : x ∈ support inc Q.val) :
pickedEdge edge Q x hx ∈ Q.val ∧ x ∈ edge (pickedEdge edge Q x hx) :=
(Classical.choose_spec (Q.property.2 x hx)).1
omit [LinearOrder V] in
lemma pickedEdge_unique (x : V) (hx : x ∈ support inc Q.val) (e : E)
(he : e∈Q.val) (hxe : x ∈ edge e) : e=pickedEdge edge Q x hx :=
(Classical.choose_spec (Q.property.2 x hx)).2 e ⟨he,hxe⟩
noncomputable def partialMateFun (x : V) : V :=
if hx : x∈support inc Q.val then Sym2.Mem.other (pickedEdge_spec edge Q x hx).2 else x
lemma partialMateFun_out (x : V) (hx : x∉support inc Q.val) : partialMateFun edge Q x=x := by
simp [partialMateFun,hx]
include hnd in
lemma partialMateFun_ne (x : V) (hx : x∈support inc Q.val) : partialMateFun edge Q x≠x := by
simp only [partialMateFun,dite_eq_left hx]
exact Sym2.other_ne (hnd _) _
lemma partialMateFun_pair (x : V) (hx : x∈support inc Q.val) :
s(x,partialMateFun edge Q x)=edge (pickedEdge edge Q x hx) := by
simp only [partialMateFun,dite_eq_left hx]
exact Sym2.other_spec _
lemma partialMateFun_incident (e : E) (he : e∈Q.val) (x : V) (hx : x∈edge e) :
s(x,partialMateFun edge Q x)=edge e := by
have hxQ := (mem_support inc Q.val x).mpr ⟨e,he,hx⟩
rw [partialMateFun_pair edge Q x hxQ,←pickedEdge_unique edge Q x hxQ e he hx]
include hnd in
lemma partialMateFun_involutive : Function.Involutive (partialMateFun edge Q) := by
intro x
by_cases hx : x∈support inc Q.val
· have h₁ := partialMateFun_pair edge Q x hx
have hi : partialMateFun edge Q x ∈ edge (pickedEdge edge Q x hx) := by rw [←h₁]; simp
have h₂ := partialMateFun_incident edge Q (pickedEdge edge Q x hx)
(pickedEdge_spec edge Q x hx).1 _ hi
rcases Sym2.eq_iff.mp (h₂.trans h₁.symm) with h | h
· exact False.elim (partialMateFun_ne edge hnd Q x hx h.1)
· exact h.2
· rw [partialMateFun_out edge Q x hx,partialMateFun_out edge Q x hx]
noncomputable def partialMate : Mate V := ⟨partialMateFun edge Q,partialMateFun_involutive edge hnd Q⟩
lemma partialMate_holes : HasHoles (partialMate edge hnd Q) (support inc Q.val)ᶜ := by
intro x
change partialMateFun edge Q x=x ↔ _
rw [Finset.mem_compl]
constructor
· intro h hx; exact partialMateFun_ne edge hnd Q x hx h
· exact partialMateFun_out edge Q x
lemma partialMate_low (e : E) (he : e∈Q.val) :
partialMateFun edge Q (edgeLow (edge e))=edgeHigh (edge e) := by
have h := partialMateFun_incident edge Q e he _ (edgeLow_mem _)
exact Sym2.congr_right.mp (h.trans (edge_low_high (edge e)).symm)
lemma partial_low_mem (e : E) (he : e∈Q.val) :
edgeLow (edge e) ∈ univ.filter (fun x => x < (partialMate edge hnd Q).val x) := by
simp only [Finset.mem_filter,Finset.mem_univ,true_and]
change edgeLow (edge e) < partialMateFun edge Q (edgeLow (edge e))
rw [partialMate_low edge Q e he]
exact edgeLow_lt_high _ (hnd e)
lemma partial_low_injective (e : E) (he : e∈Q.val) (f : E) (hf : f∈Q.val)
(h : edgeLow (edge e)=edgeLow (edge f)) : e=f := by
have hx := edgeLow_mem (edge e)
exact Q.property.unique (Q.property.1 e he _ hx) he hx hf (h.symm ▸ edgeLow_mem (edge f))
lemma partial_low_surjective (x : V)
(hx : x ∈ univ.filter (fun x => x < (partialMate edge hnd Q).val x)) :
∃ e, ∃ _ : e∈Q.val, edgeLow (edge e)=x := by
have hx' : x < partialMateFun edge Q x := (Finset.mem_filter.mp hx).2
have hcov : x∈support inc Q.val := by
by_contra hn
rw [partialMateFun_out edge Q x hn] at hx'
exact lt_irrefl _ hx'
refine ⟨pickedEdge edge Q x hcov,(pickedEdge_spec edge Q x hcov).1,?_⟩
rw [←partialMateFun_pair edge Q x hcov,edgeLow_mk,min_eq_left hx'.le]
include hnd in
lemma partial_card : (support inc Q.val).card=2*Q.val.card := by
have hcard := Finset.card_bij (fun e _ => edgeLow (edge e))
(partial_low_mem edge hnd Q) (partial_low_injective edge Q)
(partial_low_surjective edge hnd Q)
have hmate := mate_edge_count (partialMate edge hnd Q) (support inc Q.val)
(partialMate_holes edge hnd Q)
omega
include hnd in
lemma partial_even : Even (support inc Q.val).card := by
rw [partial_card edge hnd Q]
exact even_two_mul _
end
section
open Finset
variable {V L : Type*} [Fintype V] [Fintype L] [LinearOrder V] [DecidableEq L]
variable (bags : V → Finset L)
noncomputable local instance edgeLowCardinalityBagEdgeFintype : Fintype (BagEdge bags) :=
Fintype.ofFinite _
noncomputable def bagEdgeSigmaEquiv : BagEdge bags ≃
Σ s : {s : Sym2 V // ¬s.IsDiag}, {l : L // ∀ x, x∈s.val → l∈bags x} where
toFun e := ⟨⟨e.val.val.1,e.val.property⟩,⟨e.val.val.2,e.property⟩⟩
invFun a := ⟨⟨(a.1.val,a.2.val),a.1.property⟩,a.2.property⟩
left_inv _ := rfl
right_inv _ := rfl
end
open Finset MatchingFPRAS.Switching
variable {V L : Type*} [Fintype V] [Fintype L] [LinearOrder V] [DecidableEq L]
variable (bags : V → Finset L)
noncomputable local instance edgeLowInflationBagEdgeFintype : Fintype (BagEdge bags) :=
Fintype.ofFinite _
end MatchingFPRAS.Transport
namespace MatchingFPRAS.RealGeometry
open Finset MatchingFPRAS.Subdivision MatchingFPRAS.Transport
variable {V E : Type*} [Fintype V] [Fintype E] [DecidableEq V] [DecidableEq E]
variable (u v : E → V) (m : ℕ)
omit [Fintype V] [Fintype E] [DecidableEq V] [DecidableEq E] in
lemma edge_incident_internal (q : E × Fin (m+1)) (e : E) (i : Fin m) :
Sum.inr (e,i) ∈ edge u v m q.1 q.2 ↔ q=(e,i.castSucc) ∨ q=(e,i.succ) := by
simp only [edge,Sym2.mem_iff,eq_comm (a := Sum.inr _) ]
rw [atVertex_eq_inr_iff,atVertex_eq_inr_iff]
simp only [Fin.val_castSucc,Fin.val_succ,Prod.ext_iff]
constructor
· rintro (⟨h,h'⟩|⟨h,h'⟩)
· exact Or.inr ⟨h,Fin.ext h'⟩
· exact Or.inl ⟨h,Fin.ext (show q.2.val=i.val by omega)⟩
· rintro (⟨h,h'⟩|⟨h,h'⟩)
· exact Or.inr ⟨h,by have := congrArg Fin.val h'; simpa using this⟩
· exact Or.inl ⟨h,by have := congrArg Fin.val h'; simpa using this⟩
omit [Fintype V] [Fintype E] [DecidableEq V] [DecidableEq E] in
lemma edge_incident_terminal (q : E × Fin (m+1)) (x : V) :
Sum.inl x ∈ edge u v m q.1 q.2 ↔
(q.2=0 ∧ u q.1=x) ∨ (q.2=Fin.last m ∧ v q.1=x) := by
simp only [edge,Sym2.mem_iff,eq_comm (a := Sum.inl _)]
rw [first_vertex_terminal,second_vertex_terminal]
simp only [Fin.ext_iff,Fin.val_zero,Fin.val_last]
noncomputable def selectedSet (b : E → Selection m) : Finset (E × Fin (m+1)) := by
classical
exact univ.filter fun q => b q.1 q.2=true
omit [DecidableEq E] in
@[simp] lemma mem_selectedSet (b : E → Selection m) (q : E × Fin (m+1)) :
q∈selectedSet m b ↔ b q.1 q.2=true := by
simp [selectedSet]
omit [Fintype V] [DecidableEq V] [DecidableEq E] in
lemma internal_unique_iff (b : E → Selection m) (e : E) (i : Fin m) :
(∃! q, q∈selectedSet m b ∧ Sum.inr (e,i)∈edge u v m q.1 q.2) ↔
b e i.castSucc ≠ b e i.succ := by
simp only [mem_selectedSet,edge_incident_internal]
have hne : i.castSucc≠i.succ := by intro h; have := congrArg Fin.val h; simp at this
cases h₁ : b e i.castSucc <;> cases h₂ : b e i.succ <;> simp only [ne_eq,Bool.false_eq_true,
not_false_eq_true,Bool.true_eq_false,not_true_eq_false,iff_false,iff_true]
· rintro ⟨q,hq,_⟩; rcases hq.2 with rfl|rfl <;> simp_all
· refine ⟨(e,i.succ),⟨h₂,Or.inr rfl⟩,?_⟩
rintro ⟨f,j⟩ ⟨hs,hq⟩
rcases hq with hq|hq
· cases hq; simp_all
· exact hq
· refine ⟨(e,i.castSucc),⟨h₁,Or.inl rfl⟩,?_⟩
rintro ⟨f,j⟩ ⟨hs,hq⟩
rcases hq with hq|hq
· exact hq
· cases hq; simp_all
· rintro ⟨q,hq,hu⟩
have h := (hu (e,i.castSucc) ⟨h₁,Or.inl rfl⟩).trans (hu (e,i.succ) ⟨h₂,Or.inr rfl⟩).symm
exact hne (congrArg Prod.snd h)
omit [Fintype V] [DecidableEq V] [DecidableEq E] in
lemma terminal_selected_iff (b : E → Selection m) (q : E × Fin (m+1)) (x : V) :
q∈selectedSet m b ∧ Sum.inl x∈edge u v m q.1 q.2 ↔
(q.2=0 ∧ b q.1 0=true ∧ u q.1=x) ∨
(q.2=Fin.last m ∧ b q.1 (Fin.last m)=true ∧ v q.1=x) := by
rw [mem_selectedSet,edge_incident_terminal]
constructor
· rintro ⟨hs, (⟨h₀,hu⟩|⟨hm,hv⟩)⟩
· exact Or.inl ⟨h₀,h₀ ▸ hs,hu⟩
· exact Or.inr ⟨hm,hm ▸ hs,hv⟩
· rintro (⟨h₀,hs,hu⟩|⟨hm,hs,hv⟩)
· exact ⟨h₀ ▸ hs,Or.inl ⟨h₀,hu⟩⟩
· exact ⟨hm ▸ hs,Or.inr ⟨hm,hv⟩⟩
omit [Fintype V] [DecidableEq V] [DecidableEq E] in
lemma terminal_unique_iff (huv : ∀ e,u e≠v e) (b : E → Selection m) (x : V) :
(∃! q, q∈selectedSet m b ∧ Sum.inl x∈edge u v m q.1 q.2) ↔
(∃! e, Uses u v b e x) := by
constructor
· rintro ⟨q,hq,hunique⟩
rw [terminal_selected_iff] at hq
have huse : Uses u v b q.1 x := by rcases hq with h|h; exact Or.inl h.2; exact Or.inr h.2
refine ⟨q.1,huse,?_⟩
intro f hf
rcases hf with hf|hf
· exact congrArg Prod.fst (hunique (f,0) ((terminal_selected_iff _ _ _ _ _ _).mpr (Or.inl ⟨rfl,hf⟩)))
· exact congrArg Prod.fst (hunique (f,Fin.last m) ((terminal_selected_iff _ _ _ _ _ _).mpr (Or.inr ⟨rfl,hf⟩)))
· rintro ⟨e,he,hu⟩
have uniq (i : Fin (m+1)) (hi : (e,i)∈selectedSet m b ∧ Sum.inl x∈edge u v m e i)
(q : E × Fin (m+1)) (hq : q∈selectedSet m b ∧ Sum.inl x∈edge u v m q.1 q.2) : q=(e,i) := by
rw [terminal_selected_iff] at hi hq
have hf : q.1=e := hu q.1 (by rcases hq with h|h; exact Or.inl h.2; exact Or.inr h.2)
apply Prod.ext hf
rcases hi with hi|hi <;> rcases hq with hq|hq
· exact hq.1.trans hi.1.symm
· exact False.elim (huv e (hi.2.2.trans (hf ▸ hq.2.2).symm))
· exact False.elim (huv e ((hf ▸ hq.2.2).trans hi.2.2.symm))
· exact hq.1.trans hi.1.symm
rcases he with he|he
· have hi := (terminal_selected_iff u v m b (e,0) x).mpr (Or.inl ⟨rfl,he⟩)
exact ⟨(e,0),hi,uniq 0 hi⟩
· have hi := (terminal_selected_iff u v m b (e,Fin.last m) x).mpr (Or.inr ⟨rfl,he⟩)
exact ⟨(e,Fin.last m),hi,uniq _ hi⟩
omit [DecidableEq V] [DecidableEq E] in
theorem family_iff_matching (huv : ∀ e,u e≠v e) (R : Finset V)
(U : E → Finset (Fin m)) (b : E → Selection m) :
FamilyHoles u v m R U b ↔
MatchingOn (fun (q : E × Fin (m+1)) x => x∈edge u v m q.1 q.2) (selectedSet m b) (survivors m R U) := by
constructor
· intro hb
constructor
· intro q hq x hx
cases x with
| inl x =>
rw [mem_survivors_terminal]
intro hr
have huse : Uses u v b q.1 x := by
rcases (terminal_selected_iff u v m b q x).mp ⟨hq,hx⟩ with h|h
· exact Or.inl h.2
· exact Or.inr h.2
exact hb.2.1 x hr q.1 huse
| inr ei =>
rcases ei with ⟨e,i⟩
rw [mem_survivors_internal]
intro hi
have hd := hb.1 e i
simp only [hi,ite_eq_left] at hd
rcases (edge_incident_internal u v m q e i).mp hx with rfl|rfl
· have h := (mem_selectedSet m b _).mp hq; simp_all
· have h := (mem_selectedSet m b _).mp hq; simp_all
· intro x hx
cases x with
| inl x => exact (terminal_unique_iff u v m huv b x).mpr (hb.2.2 x ((mem_survivors_terminal m R U x).mp hx))
| inr ei =>
rcases ei with ⟨e,i⟩
apply (internal_unique_iff u v m b e i).mpr
simpa only [Valid,ite_eq_right ((mem_survivors_internal m R U e i).mp hx)] using hb.1 e i
· intro hM
refine ⟨?_,?_,?_⟩
· intro e i
split_ifs with hi
· constructor
· cases h : b e i.castSucc
· rfl
· have hx := hM.1 (e,i.castSucc) ((mem_selectedSet m b _).mpr h) (Sum.inr (e,i))
((edge_incident_internal u v m _ e i).mpr (Or.inl rfl))
exact False.elim (((mem_survivors_internal m R U e i).mp hx) hi)
· cases h : b e i.succ
· rfl
· have hx := hM.1 (e,i.succ) ((mem_selectedSet m b _).mpr h) (Sum.inr (e,i))
((edge_incident_internal u v m _ e i).mpr (Or.inr rfl))
exact False.elim (((mem_survivors_internal m R U e i).mp hx) hi)
· exact (internal_unique_iff u v m b e i).mp (hM.2 (Sum.inr (e,i)) ((mem_survivors_internal m R U e i).mpr hi))
· intro x hx e he
have hq : ∃ q, q∈selectedSet m b ∧ Sum.inl x∈edge u v m q.1 q.2 := by
rcases he with he|he
· exact ⟨(e,0),(terminal_selected_iff u v m b _ x).mpr (Or.inl ⟨rfl,he⟩)⟩
· exact ⟨(e,Fin.last m),(terminal_selected_iff u v m b _ x).mpr (Or.inr ⟨rfl,he⟩)⟩
obtain ⟨q,hq,hqx⟩ := hq
exact ((mem_survivors_terminal m R U x).mp (hM.1 q hq _ hqx)) hx
· intro x hx
exact (terminal_unique_iff u v m huv b x).mp (hM.2 (Sum.inl x) ((mem_survivors_terminal m R U x).mpr hx))
noncomputable def selectionEquiv : (E → Selection m) ≃ Finset (E × Fin (m+1)) where
toFun := selectedSet m
invFun S e i := decide ((e,i)∈S)
left_inv b := by
funext e i
simp [mem_selectedSet]
right_inv S := by
ext ⟨e,i⟩
simp
noncomputable def realMatchingEquiv (huv : ∀ e,u e≠v e) (R : Finset V) (U : E → Finset (Fin m)) :
{b : E → Selection m // FamilyHoles u v m R U b} ≃
Matchings (fun (q : E × Fin (m+1)) x => x∈edge u v m q.1 q.2) (survivors m R U) :=
(selectionEquiv (E := E) m).subtypeEquiv (family_iff_matching u v m huv R U)
end MatchingFPRAS.RealGeometry
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_MatchingMap
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset
variable {V E F : Type*} [Fintype V] [Fintype E] [Fintype F]
variable [DecidableEq V] [DecidableEq E] [DecidableEq F]
variable (inc : E → V → Prop) (inc' : F → V → Prop) (f : E ↪ F)
variable (hinc : ∀ e x,inc' (f e) x ↔ inc e x)
include hinc in
omit [Fintype V] [Fintype E] [Fintype F] [DecidableEq V] [DecidableEq E] [DecidableEq F] in
lemma matching_map_iff [Fintype V] [Fintype E] [Fintype F]
[DecidableEq V] [DecidableEq E] [DecidableEq F] (S : Finset E) (U : Finset V) :
MatchingOn inc' (S.map f) U ↔ MatchingOn inc S U := by
constructor
· intro hM
refine ⟨fun e he x hx => hM.1 (f e) (Finset.mem_map.mpr ⟨e,he,rfl⟩) x ((hinc e x).mpr hx),?_⟩
intro x hx
obtain ⟨q,⟨hq,hqx⟩,hu⟩ := hM.2 x hx
obtain ⟨e,he,rfl⟩ := Finset.mem_map.mp hq
refine ⟨e,⟨he,(hinc e x).mp hqx⟩,?_⟩
intro e' he'
apply f.injective
exact hu (f e') ⟨Finset.mem_map.mpr ⟨e',he'.1,rfl⟩,(hinc e' x).mpr he'.2⟩
· intro hM
constructor
· intro q hq x hx
obtain ⟨e,he,rfl⟩ := Finset.mem_map.mp hq
exact hM.1 e he x ((hinc e x).mp hx)
· intro x hx
obtain ⟨e,⟨he,hex⟩,hu⟩ := hM.2 x hx
refine ⟨f e,⟨Finset.mem_map.mpr ⟨e,he,rfl⟩,(hinc e x).mpr hex⟩,?_⟩
intro q hq
obtain ⟨e',he',rfl⟩ := Finset.mem_map.mp hq.1
exact congrArg f (hu e' ⟨he',(hinc e' x).mp hq.2⟩)
noncomputable def matchingMap (U : Finset V) (M : Matchings inc U) : Matchings inc' U :=
⟨M.val.map f,(matching_map_iff inc inc' f hinc M.val U).mpr M.property⟩
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_TierClamp
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
noncomputable def cycleMove (p : PM inc × PM inc) (S : Finset E) : PM inc × PM inc := by
classical
exact if h : S ∈ components (inc := inc) (p.1.val ∪ p.2.val) then
(⟨exchange p.1.val p.2.val S, exchange_matching p.1.property p.2.property
(component_exchange_compatible h)⟩,
⟨exchange p.2.val p.1.val S, exchange_matching p.2.property p.1.property
(component_exchange_compatible h).symm⟩) else p
omit [DecidableEq V] [Fintype E] in
lemma cycleMove_val (p : PM inc × PM inc) (S : Finset E)
(h : S ∈ components (inc := inc) (p.1.val ∪ p.2.val)) :
(cycleMove p S).1.val = exchange p.1.val p.2.val S ∧
(cycleMove p S).2.val = exchange p.2.val p.1.val S := by
classical
simp only [cycleMove,dite_eq_left h,Subtype.coe_mk,and_self]
omit [DecidableEq V] [Fintype E] in
lemma cycleMove_union (p : PM inc × PM inc) (S : Finset E) :
(cycleMove p S).1.val ∪ (cycleMove p S).2.val = p.1.val ∪ p.2.val := by
classical
unfold cycleMove
split_ifs with h
· exact exchange_union _ _ _
· rfl
omit [DecidableEq V] [Fintype E] in
lemma cycleMove_inter (p : PM inc × PM inc) (S : Finset E) :
(cycleMove p S).1.val ∩ (cycleMove p S).2.val = p.1.val ∩ p.2.val := by
classical
unfold cycleMove
split_ifs with h
· exact exchange_inter _ _ _
· rfl
omit [DecidableEq V] [Fintype E] in
lemma cycleMove_discrepancy (p : PM inc × PM inc) (S : Finset E) :
discrepancyComponents (cycleMove p S).1 (cycleMove p S).2 = discrepancyComponents p.1 p.2 := by
classical
unfold discrepancyComponents
rw [cycleMove_union,cycleMove_inter]
omit [DecidableEq V] [Fintype E] in
lemma cycleMove_involution (p : PM inc × PM inc) (S : Finset E) :
cycleMove (cycleMove p S) S = p := by
classical
by_cases h : S ∈ components (inc := inc) (p.1.val ∪ p.2.val)
· have h' : S ∈ components (inc := inc) ((cycleMove p S).1.val ∪ (cycleMove p S).2.val) := by
rwa [cycleMove_union]
apply Prod.ext <;> apply Subtype.ext
· rw [(cycleMove_val _ _ h').1,(cycleMove_val _ _ h).1,(cycleMove_val _ _ h).2]
exact exchange_involution _ _ _
· rw [(cycleMove_val _ _ h').2,(cycleMove_val _ _ h).1,(cycleMove_val _ _ h).2]
exact exchange_involution _ _ _
· simp only [cycleMove,dite_eq_right h]
noncomputable def cycleTerm (p q : PM inc × PM inc) (S : Finset E) : ℝ := by
classical
exact if S ∈ discrepancyComponents p.1 p.2 ∧ cycleMove p S = q then
((discrepancyComponents p.1 p.2).card : ℝ)⁻¹ else 0
noncomputable def cycleProposal (p q : PM inc × PM inc) : ℝ := by
classical
exact if (discrepancyComponents p.1 p.2).Nonempty then ∑ S, cycleTerm p q S
else if p = q then 1 else 0
omit [DecidableEq V] [Fintype E] in
lemma cycleTerm_symmetric (p q : PM inc × PM inc) (S : Finset E) :
cycleTerm p q S = cycleTerm q p S := by
classical
have he : (S ∈ discrepancyComponents p.1 p.2 ∧ cycleMove p S = q) ↔
(S ∈ discrepancyComponents q.1 q.2 ∧ cycleMove q S = p) := by
constructor
· rintro ⟨h,rfl⟩
exact ⟨by rwa [cycleMove_discrepancy],cycleMove_involution _ _⟩
· rintro ⟨h,rfl⟩
exact ⟨by rwa [cycleMove_discrepancy],cycleMove_involution _ _⟩
unfold cycleTerm
by_cases h : S ∈ discrepancyComponents p.1 p.2 ∧ cycleMove p S = q
· rw [ite_eq_left h,ite_eq_left (he.mp h),← h.2,cycleMove_discrepancy]
· rw [ite_eq_right h,ite_eq_right (mt he.mpr h)]
omit [DecidableEq V] [Fintype E] in
lemma cycleTerm_nonneg (p q : PM inc × PM inc) (S : Finset E) : 0 ≤ cycleTerm p q S := by
classical
unfold cycleTerm
split_ifs <;> positivity
omit [DecidableEq V] in
lemma cycleTerm_sum (p : PM inc × PM inc) (S : Finset E) :
(∑ q, cycleTerm p q S) = if S ∈ discrepancyComponents p.1 p.2 then
((discrepancyComponents p.1 p.2).card : ℝ)⁻¹ else 0 := by
classical
by_cases h : S ∈ discrepancyComponents p.1 p.2
· simp only [cycleTerm,h,true_and]
simp
· simp [cycleTerm,h]
omit [DecidableEq V] [Fintype E] in
lemma cycleTerm_zero (p q : PM inc × PM inc) (h : ¬(discrepancyComponents p.1 p.2).Nonempty)
(S : Finset E) : cycleTerm p q S = 0 := by
classical
have he := Finset.not_nonempty_iff_eq_empty.mp h
simp [cycleTerm,he]
omit [DecidableEq V] in
lemma cycleProposal_nonneg (p q : PM inc × PM inc) : 0 ≤ cycleProposal p q := by
classical
unfold cycleProposal
split_ifs
· exact Finset.sum_nonneg (fun S _ => cycleTerm_nonneg p q S)
· norm_num
· norm_num
omit [DecidableEq V] in
lemma cycleProposal_row (p : PM inc × PM inc) : (∑ q, cycleProposal p q) = 1 := by
classical
by_cases h : (discrepancyComponents p.1 p.2).Nonempty
· simp only [cycleProposal,ite_eq_left h]
rw [Finset.sum_comm]
simp_rw [cycleTerm_sum]
rw [← Finset.sum_filter]
simp only [Finset.filter_mem_eq_inter,Finset.univ_inter,Finset.sum_const,nsmul_eq_mul]
exact mul_inv_cancel₀ (by exact_mod_cast ne_of_gt (Finset.card_pos.mpr h))
· simp [cycleProposal,h]
omit [DecidableEq V] in
lemma cycleProposal_symmetric (p q : PM inc × PM inc) : cycleProposal p q = cycleProposal q p := by
classical
by_cases hp : (discrepancyComponents p.1 p.2).Nonempty <;>
by_cases hq : (discrepancyComponents q.1 q.2).Nonempty
· simp only [cycleProposal,ite_eq_left hp,ite_eq_left hq,cycleTerm_symmetric p q]
· have hpq : p ≠ q := by rintro rfl; exact hq hp
simp only [cycleProposal,ite_eq_left hp,ite_eq_right hq,ite_eq_right (Ne.symm hpq)]
apply Finset.sum_eq_zero; intro S _
rw [cycleTerm_symmetric,cycleTerm_zero _ _ hq]
· exact (by
have hpq : q ≠ p := by rintro rfl; exact hp hq
simp only [cycleProposal,ite_eq_right hp,ite_eq_left hq,ite_eq_right (Ne.symm hpq)]
symm; apply Finset.sum_eq_zero; intro S _
rw [cycleTerm_symmetric,cycleTerm_zero _ _ hp])
· simp only [cycleProposal,ite_eq_right hp,ite_eq_right hq,eq_comm]
end
section
open Finset
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L}
noncomputable local instance tierClampBagEdgeFintype : Fintype (BagEdge bags) :=
Fintype.ofFinite _
namespace BagEdge
noncomputable def parallels (e : BagEdge bags) : Finset (BagEdge bags) := by
classical
exact Finset.univ.filter (fun f => f.val.val.1 = e.val.val.1)
omit [DecidableEq L] in
lemma parallels_card_le (hb : ∀ v, (bags v).card ≤ 2) (e : BagEdge bags) :
(parallels e).card ≤ 2 := by
classical
obtain ⟨v,hv⟩ := e.exists_incident
let colorMap : ↥(parallels e) → ↥(bags v) := fun f => ⟨f.val.color, by
apply f.val.color_mem
change v ∈ f.val.val.val.1
rw [(Finset.mem_filter.mp f.property).2]
exact hv⟩
have hinj : Function.Injective colorMap := by
intro f g h
apply Subtype.ext; apply Subtype.ext; apply Subtype.ext
apply Prod.ext
· exact (Finset.mem_filter.mp f.property).2.trans (Finset.mem_filter.mp g.property).2.symm
· exact congrArg Subtype.val h
have hc : (parallels e).card ≤ (bags v).card := by
simpa only [Fintype.card_coe] using Fintype.card_le_of_injective colorMap hinj
exact hc.trans (hb v)
end BagEdge
end
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
omit [DecidableEq V] [Fintype E] in
lemma ColorChange.symm {A B : PM (fun e v => v ∈ ends e)} (h : ColorChange ends A B) :
ColorChange ends B A := by
obtain ⟨e,f,R,hef,hA,hB⟩ := h
exact ⟨f,e,R,hef.symm,hB,hA⟩
omit [DecidableEq V] [Fintype E] in
lemma ColorChange.edit {A B : PM (fun e v => v ∈ ends e)} (h : ColorChange ends A B) :
∃ e ∈ A.val, ∃ f, ends f = ends e ∧ B.val = insert f (A.val.erase e) := by
classical
obtain ⟨e,f,R,hef,hA,hB⟩ := h
have he : e ∈ A.val := by rw [hA]; simp
refine ⟨e,he,f,hef.symm,?_⟩
by_cases h : e = f
· subst f
rw [Finset.insert_erase he]
exact hB.trans hA.symm
· obtain ⟨v,hv⟩ : ∃ v, v ∈ ends e := Sym2.inductionOn (ends e) (fun u v => ⟨u,by simp⟩)
have hr : e ∉ R := by
intro hr
exact h (B.property.unique (Finset.mem_univ v) (by rw [hB]; simp [hr]) hv
(by rw [hB]; simp) (hef ▸ hv))
rw [hA,hB]
ext a
simp only [Finset.mem_union,Finset.mem_singleton,Finset.mem_insert,Finset.mem_erase]
by_cases ha : a = e
· subst a; simp [hr,h]
· tauto
lemma colorDestinations_card_bound
(hpar : ∀ e, (Finset.univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) : (colorDestinations ends A).card ≤ 2*A.val.card := by
classical
let options (e : E) : Finset (Finset E) :=
(Finset.univ.filter (fun f => ends f = ends e)).image (fun f => insert f (A.val.erase e))
have hsub : (colorDestinations ends A).image Subtype.val ⊆ A.val.biUnion options := by
intro B hB
obtain ⟨C,hC,hCB⟩ := Finset.mem_image.mp hB
rw [← hCB]
obtain ⟨e,he,f,hf,hval⟩ := ColorChange.edit ends ((Finset.mem_filter.mp hC).2)
apply Finset.mem_biUnion.mpr
exact ⟨e,he,Finset.mem_image.mpr ⟨f,Finset.mem_filter.mpr ⟨Finset.mem_univ _,hf⟩,hval.symm⟩⟩
have hi : (colorDestinations ends A).card = ((colorDestinations ends A).image Subtype.val).card := by
symm; exact Finset.card_image_of_injective _ Subtype.val_injective
calc
_ = _ := hi
_ ≤ (A.val.biUnion options).card := Finset.card_le_card hsub
_ ≤ ∑ e ∈ A.val, (options e).card := Finset.card_biUnion_le
_ ≤ ∑ e ∈ A.val, 2 := Finset.sum_le_sum (fun e _ => (Finset.card_image_le).trans (hpar e))
_ = _ := by simp [Nat.mul_comm]
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_RelationDestinations
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
open Finset
variable {Ω : Type*} [Fintype Ω] [DecidableEq Ω]
lemma relationProposal_row (R : Ω → Ω → Prop) (d : ℕ) (a : Ω) :
(∑ b, relationProposal R d a b) = 1 := by
classical
rw [← Finset.sum_erase_add _ _ (Finset.mem_univ a)]
have hh : (∑ b ∈ Finset.univ.erase a, relationProposal R d a b) =
∑ b, relationOff R d a b := by
rw [← Finset.sum_erase_add _ _ (Finset.mem_univ a),relationOff_self,add_zero]
apply Finset.sum_congr rfl; intro b hb
simp only [relationProposal,ite_eq_right (Finset.ne_of_mem_erase hb).symm]
rw [hh]
simp only [relationProposal,ite_true]
ring
end
section
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
attribute [local instance] Classical.propDecidable
noncomputable def colorProposal (A B : PM (fun e v => v ∈ ends e)) : ℝ :=
relationProposal (ColorChange ends) (Fintype.card V) A B
omit [DecidableEq V] in
lemma colorProposal_row (A : PM (fun e v => v ∈ ends e)) : (∑ B, colorProposal ends A B) = 1 :=
relationProposal_row _ _ _
omit [DecidableEq V] in
lemma colorProposal_symmetric (A B : PM (fun e v => v ∈ ends e)) :
colorProposal ends A B = colorProposal ends B A :=
relationProposal_symmetric _ _ (fun _ _ => ⟨ColorChange.symm ends,ColorChange.symm ends⟩) A B
lemma colorProposal_nonneg (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (Finset.univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A B : PM (fun e v => v ∈ ends e)) : 0 ≤ colorProposal ends A B := by
classical
apply relationProposal_nonneg
intro C
calc
_ ≤ (colorDestinations ends C).card := Finset.card_le_card (by
intro D hD; exact Finset.mem_filter.mpr ⟨Finset.mem_univ _,((Finset.mem_filter.mp hD).2).2⟩)
_ ≤ 2*C.val.card := colorDestinations_card_bound ends hpar C
_ = _ := C.twice_card ends hloop
end
section
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
omit [DecidableEq V] [Fintype E] in
lemma TwoEdgeSwitch.symm {A B : PM inc} (h : TwoEdgeSwitch A B) : TwoEdgeSwitch B A := by
obtain ⟨v,e,R,hv,he,hA,hB⟩ := h
refine ⟨(fun i => v (i+1)),(fun i => e (i+1)),R,?_,?_,?_,?_⟩
· exact hv.comp (fun _ _ h => add_right_cancel h)
· intro i x
simpa only [add_assoc] using he (i+1) x
· simpa using hB
· simpa [Finset.pair_comm] using hA
omit [DecidableEq V] [Fintype E] in
lemma TwoEdgeSwitch.normal_form {A B : PM inc} (h : TwoEdgeSwitch A B) :
∃ (v : Fin 4 → V) (e : Fin 4 → E), Function.Injective v ∧
(∀ i x, inc (e i) x ↔ x = v i ∨ x = v (i+1)) ∧
e 0 ≠ e 2 ∧ {e 0,e 2} ⊆ A.val ∧
B.val = (A.val \ {e 0,e 2}) ∪ {e 1,e 3} := by
classical
obtain ⟨v,e,R,hv,he,hA,hB⟩ := h
have hne (i j : Fin 4) (hij : i ≠ j) (hij' : i ≠ j+1) : e i ≠ e j := by
intro h
have hi := (he i (v i)).mpr (Or.inl rfl)
rw [h] at hi
rcases (he j (v i)).mp hi with h | h
· exact hij (hv h)
· exact hij' (hv h)
have h01 : e 0 ≠ e 1 := hne 0 1 (by decide) (by decide)
have h23 : e 2 ≠ e 3 := hne 2 3 (by decide) (by decide)
have h02 : e 0 ≠ e 2 := hne 0 2 (by decide) (by decide)
have hRB : R ⊆ B.val := by rw [hB]; exact Finset.subset_union_left
have hb1 : e 1 ∈ B.val := by rw [hB]; simp
have hb3 : e 3 ∈ B.val := by rw [hB]; simp
have hr0 : e 0 ∉ R := by
intro hr
exact h01 (B.property.unique (Finset.mem_univ (v 1)) (hRB hr)
((he 0 (v 1)).mpr (Or.inr rfl)) hb1 ((he 1 (v 1)).mpr (Or.inl rfl)))
have hr2 : e 2 ∉ R := by
intro hr
exact h23 (B.property.unique (Finset.mem_univ (v 3)) (hRB hr)
((he 2 (v 3)).mpr (Or.inr rfl)) hb3 ((he 3 (v 3)).mpr (Or.inl rfl)))
have hR : A.val \ {e 0,e 2} = R := by
rw [hA]
ext a
simp only [Finset.mem_sdiff,Finset.mem_union,Finset.mem_insert,Finset.mem_singleton]
constructor
· tauto
· intro ha
exact ⟨Or.inl ha,by rintro (rfl|rfl) <;> contradiction⟩
exact ⟨v,e,hv,he,h02,by rw [hA]; exact Finset.subset_union_right,by rw [hR]; exact hB⟩
end
section
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
lemma switch_mem_options {A B : PM (fun e v => v ∈ ends e)} (h : TwoEdgeSwitch A B) :
∃ I ∈ A.val.powersetCard 2, B.val ∈ switchOptions ends A.val I := by
classical
obtain ⟨v,e,hv,he,h02,hsub,hB⟩ := h.normal_form
let I : Finset E := {e 0,e 2}
have hI : I.card = 2 := by simp [I,h02]
refine ⟨I,Finset.mem_powersetCard.mpr ⟨hsub,hI⟩,?_⟩
have hend (i : Fin 4) : ends (e i) = s(v i,v (i+1)) :=
inc_eq_ends ends (e i) (v i) (v (i+1))
(fun h => (by omega : i ≠ i+1) (hv h)) (he i)
unfold switchOptions
rw [dite_eq_left hI]
dsimp only
obtain ⟨hne,hr⟩ := pairRep_spec I hI
have h1 : (pairRep I hI).1 = e 0 ∨ (pairRep I hI).1 = e 2 := by
have : (pairRep I hI).1 ∈ I := by
exact (congrArg (fun S : Finset E => (pairRep I hI).1 ∈ S) hr).mpr (by simp)
simpa [I] using this
have h2 : (pairRep I hI).2 = e 0 ∨ (pairRep I hI).2 = e 2 := by
have : (pairRep I hI).2 ∈ I := by
exact (congrArg (fun S : Finset E => (pairRep I hI).2 ∈ S) hr).mpr (by simp)
simpa [I] using this
rw [hB]
rcases h1 with h1 | h1 <;> rcases h2 with h2 | h2
· exact False.elim (hne (h1.trans h2.symm))
· rw [h1,h2]
exact mem_pairOptions_of_endpoints ends (A.val\I) (e 0) (e 2) (e 1) (e 3)
(v 0) (v 1) (v 2) (v 3) (hend 0) (hend 2) (hend 1) (hend 3)
· rw [h1,h2,Finset.pair_comm (e 1) (e 3)]
exact mem_pairOptions_of_endpoints ends (A.val\I) (e 2) (e 0) (e 3) (e 1)
(v 2) (v 3) (v 0) (v 1) (hend 2) (hend 0) (hend 3) (hend 1)
· exact False.elim (hne (h1.trans h2.symm))
lemma switchDestinations_card_bound
(hpar : ∀ e, (Finset.univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) :
(switchDestinations A).card ≤ 8 * A.val.card.choose 2 := by
classical
have hsub : (switchDestinations A).image Subtype.val ⊆
(A.val.powersetCard 2).biUnion (switchOptions ends A.val) := by
intro B hB
obtain ⟨C,hC,hCB⟩ := Finset.mem_image.mp hB
rw [← hCB]
obtain ⟨I,hI,hB⟩ := switch_mem_options ends ((Finset.mem_filter.mp hC).2)
exact Finset.mem_biUnion.mpr ⟨I,hI,hB⟩
calc
_ = ((switchDestinations A).image Subtype.val).card :=
(Finset.card_image_of_injective _ Subtype.val_injective).symm
_ ≤ ((A.val.powersetCard 2).biUnion (switchOptions ends A.val)).card := Finset.card_le_card hsub
_ ≤ ∑ I ∈ A.val.powersetCard 2, (switchOptions ends A.val I).card := Finset.card_biUnion_le
_ ≤ ∑ I ∈ A.val.powersetCard 2, 8 :=
Finset.sum_le_sum fun I _ => switchOptions_card_le ends hpar A.val I
_ = _ := by simp [Nat.mul_comm]
end
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
attribute [local instance] Classical.propDecidable
noncomputable def switchProposal (A B : PM (fun e v => v ∈ ends e)) : ℝ :=
relationProposal TwoEdgeSwitch (8*(Fintype.card V/2).choose 2) A B
omit [DecidableEq V] in
lemma switchProposal_row (A : PM (fun e v => v ∈ ends e)) : (∑ B, switchProposal ends A B) = 1 :=
relationProposal_row _ _ _
omit [DecidableEq V] in
lemma switchProposal_symmetric (A B : PM (fun e v => v ∈ ends e)) :
switchProposal ends A B = switchProposal ends B A :=
relationProposal_symmetric _ _ (fun _ _ => ⟨TwoEdgeSwitch.symm,TwoEdgeSwitch.symm⟩) A B
lemma switchProposal_nonneg (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (Finset.univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A B : PM (fun e v => v ∈ ends e)) : 0 ≤ switchProposal ends A B := by
classical
apply relationProposal_nonneg
intro C
have hn : Fintype.card V/2 = C.val.card := by have := C.twice_card ends hloop; omega
calc
_ ≤ (switchDestinations C).card := Finset.card_le_card (by
intro D hD; exact Finset.mem_filter.mpr ⟨Finset.mem_univ _,((Finset.mem_filter.mp hD).2).2⟩)
_ ≤ 8*C.val.card.choose 2 := switchDestinations_card_bound ends hpar C
_ = _ := by rw [hn]
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Probability_LocalVariance
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Replica
open Finset
variable {Ω : Type*} [Fintype Ω] [DecidableEq Ω]
lemma metropolisCapacity_symmetric (P : SymmetricProposal Ω) (π : Ω → ℝ)
(a b : Ω) : metropolisCapacity P π a b = metropolisCapacity P π b a := by
by_cases h : a = b
· subst b; rfl
· simp only [metropolisCapacity,ite_eq_right h,ite_eq_right (Ne.symm h)]
exact offCapacity_symmetric P π a b
lemma metropolisCapacity_row (P : SymmetricProposal Ω) (π : Ω → ℝ)
(a : Ω) : (∑ b, metropolisCapacity P π a b) = π a := by
rw [← Finset.sum_erase_add _ _ (Finset.mem_univ a)]
have he : (∑ b ∈ Finset.univ.erase a, metropolisCapacity P π a b) =
∑ b ∈ Finset.univ.erase a, offCapacity P π a b := by
apply Finset.sum_congr rfl; intro b hb
rw [metropolisCapacity,ite_eq_right (Finset.ne_of_mem_erase hb).symm]
rw [he]
simp only [metropolisCapacity,ite_true]
ring
lemma metropolisCapacity_col (P : SymmetricProposal Ω) (π : Ω → ℝ)
(b : Ω) : (∑ a, metropolisCapacity P π a b) = π b := by
simp_rw [metropolisCapacity_symmetric P π]
exact metropolisCapacity_row P π b
end MatchingFPRAS.Replica
namespace MatchingFPRAS.Transport
section
open Finset MatchingFPRAS.Replica
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
attribute [local instance] Classical.propDecidable
noncomputable def pairProposalRaw (a b : PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) : ℝ :=
(firstLift (switchProposal ends) a b + firstLift (colorProposal ends) a b + cycleProposal a b)/3
noncomputable def pairProposal (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (Finset.univ.filter (fun f => ends f = ends e)).card ≤ 2) :
SymmetricProposal (PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) where
q := pairProposalRaw ends
nonneg a b := by
unfold pairProposalRaw firstLift
have hs := switchProposal_nonneg ends hloop hpar a.1 b.1
have hc := colorProposal_nonneg ends hloop hpar a.1 b.1
have hy := cycleProposal_nonneg a b
split_ifs <;> positivity
row a := by
unfold pairProposalRaw
rw [← Finset.sum_div,Finset.sum_add_distrib,Finset.sum_add_distrib,
firstLift_row _ (switchProposal_row ends),firstLift_row _ (colorProposal_row ends),cycleProposal_row]
norm_num
symmetric a b := by
unfold pairProposalRaw
rw [firstLift_symmetric _ (switchProposal_symmetric ends),
firstLift_symmetric _ (colorProposal_symmetric ends),cycleProposal_symmetric a b]
noncomputable def pairLaw (w z : E → ℝ) (a : PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) : ℝ :=
gibbs w a.1*gibbs z a.2
end
open Finset MatchingFPRAS.Replica
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_TreePairProposal
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
open Finset MatchingFPRAS.Replica
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge : Fintype (BagEdge bags) := Fintype.ofFinite _
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
variable (hG : G.IsAcyclic)
noncomputable def treePairProposal : SymmetricProposal (PM (BagEdge.Incident (bags := bags)) × PM (BagEdge.Incident (bags := bags))) :=
pairProposal (fun e : BagEdge bags => e.val.val.1) (fun e => e.val.property)
(fun e => BagEdge.parallels_card_le (label_memberships_le_two hbags hG) e)
noncomputable def treePairLaw (w z : BagEdge bags → ℝ)
(a : PM (BagEdge.Incident (bags := bags)) × PM (BagEdge.Incident (bags := bags))) : ℝ := gibbs w a.1*gibbs z a.2
noncomputable def treePairEnergy (w z : BagEdge bags → ℝ)
(f : (PM (BagEdge.Incident (bags := bags)) × PM (BagEdge.Incident (bags := bags))) → ℝ) : ℝ := by
classical
exact localEnergy (metropolisCapacity (treePairProposal hbags hG) (treePairLaw w z)) f
end
section
open Finset MatchingFPRAS.Replica
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_1 : Fintype (BagEdge bags) := Fintype.ofFinite _
end
open Finset MatchingFPRAS.Replica
variable {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
variable {bags : V → Finset L} {G : SimpleGraph L}
noncomputable local instance instFintypeBagEdge_2 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport
section
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J} {G : SimpleGraph J}
noncomputable local instance instFintypeBagEdge_3 : Fintype (BagEdge bags) := Fintype.ofFinite _
noncomputable def slotWeight {T q : ℕ} (w : BagEdge bags → ℝ) (x : Slot T q) (e : BagEdge bags) : ℝ :=
tierClamp (tierBase V) (tier x) (w e)
omit [DecidableEq V] [Fintype J] [DecidableEq J] in
lemma slotWeight_pos {T q : ℕ} (w : BagEdge bags → ℝ) (x : Slot T q) (e : BagEdge bags) :
0 < slotWeight w x e := tierClamp_pos (tierBase_pos V) _ _
noncomputable def slotLaw {T q : ℕ} (w : BagEdge bags → ℝ) (x : Slot T q)
(A : PM (BagEdge.Incident (bags := bags))) : ℝ := gibbs (slotWeight w x) A
omit [DecidableEq V] [DecidableEq J] in
lemma slotLaw_pos {T q : ℕ} (w : BagEdge bags → ℝ) (x : Slot T q)
(A : PM (BagEdge.Incident (bags := bags))) : 0 < slotLaw w x A := gibbs_pos _ (slotWeight_pos w x) A
variable (hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
variable (hG : G.IsAcyclic)
noncomputable def treeLadderCapacity {T q : ℕ} (w : BagEdge bags → ℝ) (x y : Slot T q) :
PairCapacity (slotLaw w) x y := by
classical
let π : (PM (BagEdge.Incident (bags := bags)) × PM (BagEdge.Incident (bags := bags))) → ℝ :=
fun a => slotLaw w x a.1*slotLaw w y a.2
exact {
q := metropolisCapacity (treePairProposal hbags hG) π
nonneg := metropolisCapacity_nonneg _ _ (fun a => mul_nonneg (slotLaw_pos w x a.1).le (slotLaw_pos w y a.2).le)
row := metropolisCapacity_row _ _
col := metropolisCapacity_col _ _ }
end
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J} {G : SimpleGraph J}
noncomputable local instance instFintypeBagEdge_4 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Evolve
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
section
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J} {G : SimpleGraph J}
noncomputable local instance instFintypeBagEdge_5 : Fintype (BagEdge bags) := Fintype.ofFinite _
noncomputable local instance instDecidableEqPMBagEdgeIncident : DecidableEq (PM (BagEdge.Incident (bags := bags))) := Classical.decEq _
noncomputable def ladderLaw (w : BagEdge bags → ℝ) (T q : ℕ) :
(Slot T q → PM (BagEdge.Incident (bags := bags))) → ℝ := density (slotLaw w)
noncomputable def ladderFlow
(hbags : ∀ v, ∀ a ∈ bags v, ∀ b ∈ bags v, a = b ∨ G.Adj a b)
(hG : G.IsAcyclic) (w : BagEdge bags → ℝ) (T q : ℕ) :
(Slot T q → PM (BagEdge.Incident (bags := bags))) →
(Slot T q → PM (BagEdge.Incident (bags := bags))) → ℝ :=
scanFlow (slotLaw w) guides (base T q) (treeLadderCapacity hbags hG w)
noncomputable local instance instFintypeBagEdge_6 : Fintype (BagEdge bags) := Fintype.ofFinite _
noncomputable local instance instDecidableEqPMBagEdgeIncident_1 : DecidableEq (PM (BagEdge.Incident (bags := bags))) := Classical.decEq _
end
section
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable {inc : E → V → Prop}
noncomputable def chosenEdge (A : PM inc) (v : V) : E :=
Classical.choose (A.property.2 v (mem_univ v))
end
section
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J} {G : SimpleGraph J}
noncomputable local instance instFintypeBagEdge_7 : Fintype (BagEdge bags) := Fintype.ofFinite _
end
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J} {G : SimpleGraph J}
noncomputable local instance instFintypeBagEdge_8 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_LadderL
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J} {G : SimpleGraph J}
noncomputable local instance instFintypeBagEdge_10 : Fintype (BagEdge bags) := Fintype.ofFinite _
noncomputable local instance instDecidableEqPMBagEdgeIncident_2 : DecidableEq (PM (BagEdge.Incident (bags := bags))) := Classical.decEq _
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_PM
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Subdivision
open Finset
def probeWord (p : ℕ) : Selection (4*p) :=
fun i => if i.val=2*p then false else alternating true i.val
@[simp] lemma probeWord_first (p : ℕ) (hp : 1≤p) : probeWord p 0=true := by
simp [probeWord,show 0≠2*p by omega]
@[simp] lemma probeWord_last (p : ℕ) (hp : 1≤p) : probeWord p (Fin.last (4*p))=true := by
simp [probeWord,show 4*p≠2*p by omega,alternating,Nat.mul_mod]
variable {V E : Type*} [Fintype V] [Fintype E] [DecidableEq V] [DecidableEq E]
variable (u v : E → V) (p : ℕ) (hp : 1≤p) (e₀ : E)
def insertProbe (s : E → Bool) (e : E) : Selection (4*p) :=
if e=e₀ then probeWord p else fun i => alternating (s e) i.val
end MatchingFPRAS.Subdivision
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Marked
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Marking
open Finset MatchingFPRAS.Transport
variable {V E I : Type*} [Fintype V] [Fintype E] [Fintype I]
variable [DecidableEq V] [DecidableEq E] [DecidableEq I]
variable (inc : E → V → Prop)
noncomputable def completionEquiv (hinc : ∀ e,∃ x,inc e x) (Q : Partial inc) :
{M : Matchings inc univ // Q.val⊆M.val} ≃ Matchings inc (univ \ support inc Q.val) where
toFun M := ⟨M.val.val \ Q.val,M.val.property.sdiff Q.property M.property⟩
invFun M := ⟨⟨Q.val∪M.val,by
have h := Q.property.union M.property (support_sdiff_disjoint inc Q.val)
rw [Finset.union_sdiff_of_subset (Finset.subset_univ _)] at h
exact h⟩,Finset.subset_union_left⟩
left_inv M := by
apply Subtype.ext
exact Subtype.ext (Finset.union_sdiff_of_subset M.property)
right_inv M := by
have hd := Q.property.disjoint_edges M.property hinc (support_sdiff_disjoint inc Q.val)
exact Subtype.ext (Finset.union_sdiff_cancel_left hd)
noncomputable def conditional (part : E → I → ℝ) (M : Matchings inc univ)
(m : ↥M.val → I) : ℝ := ∏ e : M.val,part e.val (m e)/collapse part e.val
end MatchingFPRAS.Marking
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Probability_Tv
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder
variable {V J : Type*} [Fintype V] [DecidableEq V] [Fintype J] [DecidableEq J]
variable {bags : V → Finset J}
noncomputable local instance instFintypeBagEdge_11 : Fintype (BagEdge bags) := Fintype.ofFinite _
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_EnlargementRun
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.UnitRefresh
variable {α β : Type*}
variable [DecidableEq α]
def Pairing.insert (a b : α) (hab : b≠a)
(p : Pairing {x : α // x≠a ∧ x≠b}) : Pairing α where
mate x := if hx : x=a then b else if hy : x=b then a else (p.mate ⟨x,hx,hy⟩).val
involutive x := by
by_cases hx : x=a
· subst x; simp [hab]
by_cases hy : x=b
· subst x; simp [hab]
simp only [dite_eq_right hx,dite_eq_right hy]
rw [dite_eq_right (p.mate ⟨x,hx,hy⟩).property.1,dite_eq_right (p.mate ⟨x,hx,hy⟩).property.2]
exact congrArg Subtype.val (p.involutive ⟨x,hx,hy⟩)
no_fixed x := by
by_cases hx : x=a
· subst x; simpa using hab
by_cases hy : x=b
· subst x; simpa [hx] using hab.symm
simp only [dite_eq_right hx,dite_eq_right hy]
intro h
exact p.no_fixed ⟨x,hx,hy⟩ (Subtype.ext h)
@[simp] lemma Pairing.insert_at (a b : α) (hab : b≠a)
(p : Pairing {x : α // x≠a ∧ x≠b}) : (p.insert a b hab).mate a=b := by
simp [Pairing.insert]
@[simp] lemma Pairing.insert_other (a b : α) (hab : b≠a)
(p : Pairing {x : α // x≠a ∧ x≠b}) (x : {x : α // x≠a ∧ x≠b}) :
(p.insert a b hab).mate x=(p.mate x).val := by
simp [Pairing.insert,x.property.1,x.property.2]
noncomputable def Pairing.split (a : α) :
Pairing α ≃ Σ b : {x : α // x≠a}, Pairing {x : α // x≠a ∧ x≠b.val} where
toFun p := ⟨⟨p.mate a,p.no_fixed a⟩,p.remove a⟩
invFun q := q.2.insert a q.1.val q.1.property
left_inv p := by
ext x
by_cases hx : x=a
· subst x; simp
by_cases hy : x=p.mate a
· subst x
simp [Pairing.insert,p.no_fixed a,p.involutive a]
· simp [Pairing.insert,hx,hy,Pairing.remove]
right_inv q := by
rcases q with ⟨⟨b,hb⟩,p⟩
apply Sigma.ext (Subtype.ext (by simp))
apply Pairing.subtype_hext
· intro x; simp only [Pairing.insert_at]
· intro x y hxy
change (p.insert a b hb).mate x = (p.mate y).val
rw [hxy]
exact Pairing.insert_other a b hb p y
universe u
theorem pairing_card_aux (n : ℕ) : ∀ (α : Type u) [Fintype α],
Fintype.card α=n → Fintype.card (Pairing α)=pairingCount n := by
induction n using Nat.strong_induction_on with
| h n ih =>
intro α inst hcard
classical
by_cases hn : n=0
· have hzero : Fintype.card α=0 := hcard.trans hn
let : IsEmpty α := Fintype.card_eq_zero_iff.mp hzero
let p : Pairing α := ⟨id,fun x => rfl,fun x => isEmptyElim x⟩
let : Unique (Pairing α) := ⟨⟨p⟩,fun q => by ext x; exact isEmptyElim x⟩
simp [hn]
· have hnpos : 0<n := Nat.pos_of_ne_zero hn
have hα : Nonempty α := Fintype.card_pos_iff.mp (by omega)
let a : α := Classical.choice hα
have hm : n-2<n := Nat.sub_lt hnpos (by omega)
have he (b : {x : α // x≠a}) :
Fintype.card (Pairing {x : α // x≠a ∧ x≠b.val})=pairingCount (n-2) := by
apply ih (n-2) hm
rw [card_except_two a b.val b.property,hcard]
calc
_ = Fintype.card (Σ b : {x : α // x≠a}, Pairing {x : α // x≠a ∧ x≠b.val}) :=
Fintype.card_congr (Pairing.split a)
_ = ∑ b : {x : α // x≠a}, Fintype.card (Pairing {x : α // x≠a ∧ x≠b.val}) :=
Fintype.card_sigma
_ = ∑ _b : {x : α // x≠a}, pairingCount (n-2) := Finset.sum_congr rfl (fun b _ => he b)
_ = (n-1)*pairingCount (n-2) := by
simp [Fintype.card_subtype_compl,hcard]
_ = pairingCount n := (pairingCount_pos_recurrence hnpos).symm
omit [DecidableEq α] in
theorem pairing_card [Fintype α] : Fintype.card (Pairing α)=pairingCount (Fintype.card α) :=
pairing_card_aux (Fintype.card α) α rfl
end MatchingFPRAS.UnitRefresh
namespace MatchingFPRAS.Initializer
open Finset MatchingFPRAS.Switching MatchingFPRAS.UnitRefresh
variable {V : Type*} [Fintype V] [LinearOrder V]
noncomputable def restrictHoles (R : Finset V) (m : {m : Mate V // HasHoles m R}) :
Pairing {x : V // x∉R} where
mate x := ⟨m.val.val x.val,fun h => x.property ((mate_mem_holes_iff m.val R m.property x.val).mp h)⟩
involutive x := Subtype.ext (m.val.property x.val)
no_fixed x h := x.property ((m.property x.val).mp (congrArg Subtype.val h))
noncomputable def fillFixed (R : Finset V) (p : Pairing {x : V // x∉R}) : Mate V := by
classical
refine ⟨fun x => if hx : x∉R then (p.mate ⟨x,hx⟩).val else x,?_⟩
intro x
by_cases hx : x∉R
· simp only [dite_eq_left hx]
rw [dite_eq_left (p.mate ⟨x,hx⟩).property]
exact congrArg Subtype.val (p.involutive ⟨x,hx⟩)
· simp only [dite_eq_right hx]
omit [Fintype V] in
lemma fillFixed_holes (R : Finset V) (p : Pairing {x : V // x∉R}) : HasHoles (fillFixed R p) R := by
classical
intro x
by_cases hx : x∉R
· simp only [fillFixed,iff_false,hx]
intro h
exact p.no_fixed ⟨x,hx⟩ (Subtype.ext h)
· simp only [fillFixed,dite_eq_right hx]
exact iff_of_true trivial (not_not.mp hx)
noncomputable def holesPairingEquiv (R : Finset V) :
{m : Mate V // HasHoles m R} ≃ Pairing {x : V // x∉R} where
toFun := restrictHoles R
invFun p := ⟨fillFixed R p,fillFixed_holes R p⟩
left_inv m := by
apply Subtype.ext
apply Subtype.ext
funext x
by_cases hx : x∉R
· change (if hy : x∉R then (restrictHoles R m).mate ⟨x,hy⟩ |>.val else x)=m.val.val x
rw [dite_eq_left hx]
rfl
· change (if hy : x∉R then (restrictHoles R m).mate ⟨x,hy⟩ |>.val else x)=m.val.val x
rw [dite_eq_right hx]
exact ((m.property x).mpr (not_not.mp hx)).symm
right_inv p := by
apply Pairing.ext
intro x
apply Subtype.ext
change (fillFixed R p).val x.val=(p.mate x).val
simp only [fillFixed,dite_eq_left x.property]
lemma matchings_card (R : Finset V) :
(matchings R).card=pairingCount (Fintype.card V-R.card) := by
classical
calc
_ = Fintype.card {m : Mate V // HasHoles m R} := by
rw [Fintype.card_subtype]
apply congrArg Finset.card
ext m
simp [matchings]
_ = Fintype.card (Pairing {x : V // x∉R}) := Fintype.card_congr (holesPairingEquiv R)
_ = _ := by rw [pairing_card,Fintype.card_subtype_compl,Fintype.card_coe]
lemma uniform_weight (c : ℝ) (R : Finset V) (m : Mate V) (hm : HasHoles m R) :
weight (fun _ _ => c) m=c^((Fintype.card V-R.card)/2) := by
classical
have hmc : HasHoles m Rᶜᶜ := by simpa using hm
have hc := mate_edge_count m Rᶜ hmc
rw [Finset.card_compl] at hc
have he : (univ.filter fun v => v < m.val v).card=(Fintype.card V-R.card)/2 := by omega
unfold weight
rw [←Finset.prod_filter (s:=univ) (fun v : V => v < m.val v) (fun _ : V => c)]
simp only [Finset.prod_const,he]
theorem uniform_partition (c : ℝ) (R : Finset V) :
partition (fun _ _ : V => c) R=
(pairingCount (Fintype.card V-R.card):ℝ)*c^((Fintype.card V-R.card)/2) := by
unfold partition
simp_rw [Finset.sum_congr rfl (fun m hm => uniform_weight c R m ((mem_matchings m R).mp hm))]
simp only [Finset.sum_const,nsmul_eq_mul,matchings_card]
lemma uniform_hole_ratio (hn : 2 ≤ Fintype.card V) (he : Even (Fintype.card V))
(c : ℝ) (hc : 0 < c) (a b : V) (hab : a≠b) :
holeRatio (fun _ _ : V => c) {a,b}=1/((Fintype.card V-1)*c) := by
have h2 : ({a,b} : Finset V).card=2 := by simp [hab]
have hc2 : Fintype.card V-2+2=Fintype.card V := by omega
have he2 : Even (Fintype.card V-2) := by obtain ⟨k,hk⟩ := he; exact ⟨k-1,by omega⟩
have hp : (pairingCount (Fintype.card V-2):ℝ)≠0 := by
exact_mod_cast (pairingCount_pos_of_even _ he2).ne'
have hpow : c^((Fintype.card V-2)/2)≠0 := pow_ne_zero _ hc.ne'
unfold holeRatio
rw [uniform_partition,uniform_partition,h2,Finset.card_empty,Nat.sub_zero]
have hnrec : pairingCount (Fintype.card V)=
(Fintype.card V-1)*pairingCount (Fintype.card V-2) :=
pairingCount_pos_recurrence (by omega)
have hexp : Fintype.card V/2=(Fintype.card V-2)/2+1 := by omega
rw [hnrec,hexp,pow_succ,Nat.cast_mul,Nat.cast_sub (by omega : 1≤Fintype.card V),Nat.cast_one]
field_simp
theorem initial_balanced (hn : 2 ≤ Fintype.card V) (he : Even (Fintype.card V)) :
let w := fun _ _ : V => ((initialScale (Fintype.card V):ℚ):ℝ)^2
(0 < partition w ∅) ∧
(∀ a,(1:ℝ)/4 ≤ rowMax hn w a) ∧ (∀ a,rowMax hn w a ≤ 1) := by
dsimp only
let n := Fintype.card V
have hs : 0 < ((initialScale n:ℚ):ℝ) := by exact_mod_cast initialScale_pos n hn
have hsq : 0 < ((initialScale n:ℚ):ℝ)^2 := sq_pos_of_pos hs
have hr (a b : V) (hab : a≠b) :
holeRatio (fun _ _ : V => ((initialScale n:ℚ):ℝ)^2) {a,b}=
(Nat.sqrt (n-1):ℝ)^2/(n-1) := by
rw [uniform_hole_ratio hn he _ hsq a b hab]
unfold initialScale
push_cast
change 1/((n-1)*((1:ℝ)/Nat.sqrt (n-1))^2)=_
have hp : (Nat.sqrt (n-1):ℝ)≠0 := by
have h := initialScale_pos n hn
simp only [initialScale,one_div,inv_pos] at h
exact_mod_cast h.ne'
field_simp
have hnreal : (2:ℝ) ≤ n := by exact_mod_cast hn
have hden : (0:ℝ) < n-1 := by linarith
refine ⟨?_,?_,?_⟩
· rw [uniform_partition,Finset.card_empty,Nat.sub_zero]
exact mul_pos (by exact_mod_cast pairingCount_pos_of_even n he) (pow_pos hsq _)
· intro a
obtain ⟨b,hba,hb⟩ := rowMax_attained hn (fun _ _ : V => ((initialScale n:ℚ):ℝ)^2) a
rw [←hb,hr a b hba.symm]
have hbnd := (sqrt_square_bounds n hn).1
apply (le_div_iff₀ hden).mpr
linarith
· intro a
obtain ⟨b,hba,hb⟩ := rowMax_attained hn (fun _ _ : V => ((initialScale n:ℚ):ℝ)^2) a
rw [←hb,hr a b hba.symm]
exact (div_le_one hden).mpr
(sqrt_square_bounds n hn).2
end MatchingFPRAS.Initializer
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Certify
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.Sparse
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
instance decideMatching (M : Finset E) :
Decidable (MatchingOn (fun e v => v ∈ ends e) M univ) := by
unfold MatchingOn ExistsUnique
infer_instance
def certify (s : Finset (Finset E)) : Finset (PM (fun e v => v ∈ ends e)) :=
Finset.subtype (fun A => MatchingOn (fun e v => v ∈ ends e) A univ) s
@[simp] lemma mem_certify (s : Finset (Finset E)) (A : PM (fun e v => v ∈ ends e)) :
A ∈ certify ends s ↔ A.val ∈ s := Finset.mem_subtype
def colors (A : PM (fun e v => v ∈ ends e)) : Finset (PM (fun e v => v ∈ ends e)) :=
certify ends (colorRaw ends A.val)
@[simp] lemma mem_colors (A B : PM (fun e v => v ∈ ends e)) :
B ∈ colors ends A ↔ ColorChange ends A B := by
rw [colors,mem_certify,mem_colorRaw]
constructor
· rintro ⟨e,he,f,hf,hB⟩
refine ⟨e,f,A.val.erase e,hf.symm,?_,?_⟩
· simpa only [union_singleton] using (insert_erase he).symm
· simpa only [union_singleton] using hB
· exact ColorChange.edit ends
lemma colors_eq (A : PM (fun e v => v ∈ ends e)) :
colors ends A = colorDestinations ends A := by
ext B
simp [colorDestinations]
def switches (A : PM (fun e v => v ∈ ends e)) : Finset (PM (fun e v => v ∈ ends e)) :=
certify ends (switchRaw ends A.val)
@[simp] lemma mem_switches (A B : PM (fun e v => v ∈ ends e)) :
B ∈ switches ends A ↔ TwoEdgeSwitch A B := by
rw [switches,mem_certify]
constructor
· intro h
obtain ⟨⟨v,e⟩,hp,hB⟩ := mem_image.mp h
obtain ⟨hv,he,hne,hsub⟩ := (mem_filter.mp hp).2
refine ⟨v,e,A.val \ {e 0,e 2},hv,he,?_,hB.symm⟩
exact (sdiff_union_of_subset hsub).symm
· intro h
obtain ⟨v,e,hv,he,hne,hsub,hB⟩ := h.normal_form
exact mem_image.mpr ⟨(v,e),mem_filter.mpr ⟨mem_univ _,hv,he,hne,hsub⟩,hB.symm⟩
lemma switches_eq (A : PM (fun e v => v ∈ ends e)) :
switches ends A = switchDestinations A := by
ext B
simp [switchDestinations]
theorem colors_card (hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) : (colors ends A).card ≤ 2*A.val.card := by
rw [colors_eq]
exact colorDestinations_card_bound ends hpar A
theorem switches_card (hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) : (switches ends A).card ≤ 8*A.val.card.choose 2 := by
rw [switches_eq]
exact switchDestinations_card_bound ends hpar A
end MatchingFPRAS.Transport.Sparse
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Component
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.Sparse
open Finset
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E]
variable (ends : E → Sym2 V)
def component (U : Finset E) (a : E) : Finset E :=
U ∩ ComputableReach.closure (overlayLineGraph (fun e v => v ∈ ends e) U) a
lemma component_eq (U : Finset E) (a : E) :
component ends U a = componentEdges (inc:=fun e v => v ∈ ends e) U a := by
ext e
simp only [component,mem_inter,ComputableReach.mem_closure,mem_componentEdges]
def allComponents (U : Finset E) : Finset (Finset E) := U.image (component ends U)
lemma allComponents_eq (U : Finset E) :
allComponents ends U = components (inc:=fun e v => v ∈ ends e) U := by
simp only [allComponents,components]
exact Finset.image_congr (fun a _ => component_eq ends U a)
def discrepancies (A B : PM (fun e v => v ∈ ends e)) : Finset (Finset E) :=
(allComponents ends (A.val ∪ B.val)).filter (fun S => ¬S ⊆ A.val ∩ B.val)
def cycle (p : PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e))
(S : Finset E) : PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e) :=
if h : S ∈ allComponents ends (p.1.val ∪ p.2.val) then
(⟨exchange p.1.val p.2.val S,exchange_matching p.1.property p.2.property
(component_exchange_compatible (by rwa [allComponents_eq] at h))⟩,
⟨exchange p.2.val p.1.val S,exchange_matching p.2.property p.1.property
(component_exchange_compatible (by rwa [allComponents_eq] at h)).symm⟩)
else p
end MatchingFPRAS.Transport.Sparse
namespace MatchingFPRAS.Transport.Sparse
open Finset WeightedOptions
variable {Ω : Type*} [Fintype Ω] [LinearOrder Ω] [DecidableEq Ω]
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [LinearOrder E]
variable (ends : E → Sym2 V)
attribute [local instance] OAI.MatchingFPRAS.Transport.Sparse.finsetOrder
local instance pmOrder : LinearOrder (PM (fun e v => v ∈ ends e)) :=
LinearOrder.lift' Subtype.val Subtype.val_injective
lemma color_degree (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) : ((colors ends A).erase A).card ≤ Fintype.card V :=
(card_erase_le).trans ((colors_card ends hpar A).trans_eq (A.twice_card ends hloop))
lemma switch_degree (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) :
((switches ends A).erase A).card ≤ 8*(Fintype.card V/2).choose 2 := by
have h : Fintype.card V/2=A.val.card := by have := A.twice_card ends hloop; omega
rw [h]
exact card_erase_le.trans (switches_card ends hpar A)
def colorTable (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) : WeightedOptions (PM (fun e v => v ∈ ends e)) :=
WeightedOptions.neighbors A ((colors ends A).erase A) (Fintype.card V)
(color_degree ends hloop hpar A)
def switchTable (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(A : PM (fun e v => v ∈ ends e)) : WeightedOptions (PM (fun e v => v ∈ ends e)) :=
WeightedOptions.neighbors A ((switches ends A).erase A) (8*(Fintype.card V/2).choose 2)
(switch_degree ends hloop hpar A)
def cycleTable (p : PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) :
WeightedOptions (PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) :=
if h : (discrepancies ends p.1 p.2).Nonempty then
(WeightedOptions.uniform _ h).map (cycle ends p)
else WeightedOptions.pure p
def pairTable (hloop : ∀ e, ¬(ends e).IsDiag)
(hpar : ∀ e, (univ.filter (fun f => ends f = ends e)).card ≤ 2)
(p : PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) :
WeightedOptions (PM (fun e v => v ∈ ends e) × PM (fun e v => v ∈ ends e)) :=
WeightedOptions.mix (1/3) (by norm_num) (by norm_num)
((switchTable ends hloop hpar p.1).map (fun x => (x,p.2)))
(WeightedOptions.mix (1/2) (by norm_num) (by norm_num)
((colorTable ends hloop hpar p.1).map (fun x => (x,p.2)))
(cycleTable ends p))
end MatchingFPRAS.Transport.Sparse
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Admissible
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport.Sparse
open Finset Replica Variation
variable {V E : Type*} [Fintype V] [DecidableEq V] [Fintype E] [LinearOrder E]
variable (ends : E → Sym2 V)
attribute [local instance] finsetOrder pmOrder
def rationalWeight (w : E → ℚ) (A : PM (fun e v=>v∈ends e)) : ℚ := ∏ e∈A.val,w e
omit [DecidableEq V] [Fintype E] [LinearOrder E] in
lemma rationalWeight_pos [DecidableEq V] [Fintype E] [LinearOrder E]
(w : E → ℚ) (hw : ∀ e,0<w e) (A : PM (fun e v=>v∈ends e)) :
0 < rationalWeight ends w A := prod_pos (fun e _=>hw e)
def rationalPairWeight (w z : E → ℚ) (a : PM (fun e v=>v∈ends e) × PM (fun e v=>v∈ends e)) : ℚ :=
rationalWeight ends w a.1*rationalWeight ends z a.2
lemma rationalPairWeight_pos (w z : E → ℚ) (hw : ∀ e,0<w e) (hz : ∀ e,0<z e)
(a : PM (fun e v=>v∈ends e) × PM (fun e v=>v∈ends e)) : 0 < rationalPairWeight ends w z a :=
mul_pos (rationalWeight_pos ends w hw a.1) (rationalWeight_pos ends z hz a.2)
def pairStepTable (hloop : ∀ e,¬(ends e).IsDiag)
(hpar : ∀ e,(univ.filter (fun f=>ends f=ends e)).card≤2)
(w z : E → ℚ) (hw : ∀ e,0<w e) (hz : ∀ e,0<z e)
(a : PM (fun e v=>v∈ends e) × PM (fun e v=>v∈ends e)) :=
(pairTable ends hloop hpar a).metropolisChoice (rationalPairWeight ends w z)
(rationalPairWeight_pos ends w z hw hz) a
end MatchingFPRAS.Transport.Sparse
namespace MatchingFPRAS.UnitRefresh
instance instFinitePairing_1 {α : Type*} [Finite α] : Finite (Pairing α) := by
apply Finite.of_injective Pairing.mate
intro p q h
cases p; cases q
simp only [Pairing.mk.injEq] at *
exact h
noncomputable instance instFintypePairing_1 {α : Type*} [Fintype α] : Fintype (Pairing α) := Fintype.ofFinite _
variable {α β : Type*}
variable [DecidableEq α]
universe u
open Finset Polynomial
variable {I : Type*} [Fintype I] [DecidableEq I]
open Finset Polynomial
variable {I : Type*} [Fintype I] [DecidableEq I]
def Pairing.sigma {L : Type*} {A : L → Type*} (p : ∀ l, Pairing (A l)) : Pairing (Sigma A) where
mate x := ⟨x.1,(p x.1).mate x.2⟩
involutive x := by
cases x with
| mk l x => exact congrArg (Sigma.mk l) ((p l).involutive x)
no_fixed x h := by
have he : (p x.1).mate x.2=x.2 := eq_of_heq (Sigma.mk.inj_iff.mp h).2
exact (p x.1).no_fixed x.2 he
variable {V L : Type*} [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L]
structure ColoredPairing (bags : V → Finset L) where
pair : Pairing V
color : V → L
allowed : ∀ x, color x ∈ bags x
same_color : ∀ x, color (pair.mate x)=color x
omit [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L] in
@[ext] lemma ColoredPairing.ext {bags : V → Finset L} {p q : ColoredPairing bags}
(hp : p.pair=q.pair) (hc : p.color=q.color) : p=q := by
cases p; cases q; simp_all
instance instFiniteColoredPairing (bags : V → Finset L) : Finite (ColoredPairing bags) :=
Finite.of_injective (fun p : ColoredPairing bags => (p.pair,p.color)) (by
intro p q h
exact ColoredPairing.ext (congrArg Prod.fst h) (congrArg Prod.snd h))
noncomputable instance instFintypeColoredPairing (bags : V → Finset L) : Fintype (ColoredPairing bags) := Fintype.ofFinite _
def ColoredPairing.fiber {bags : V → Finset L} (p : ColoredPairing bags) (l : L) :
Pairing {x : V // p.color x=l} where
mate x := ⟨p.pair.mate x,(p.same_color x).trans x.property⟩
involutive x := Subtype.ext (p.pair.involutive x)
no_fixed x h := p.pair.no_fixed x (congrArg Subtype.val h)
def ColoredPairing.glue (bags : V → Finset L) (f : Assignment bags)
(p : ∀ l,Pairing {x : V // f.val x=l}) : ColoredPairing bags where
pair := (Pairing.sigma p).map (Equiv.sigmaFiberEquiv f.val)
color := f.val
allowed := f.property
same_color x := (p (f.val x)).mate ⟨x,rfl⟩ |>.property
def assignmentPairingEquiv (bags : V → Finset L) :
ColoredPairing bags ≃ Σ f : Assignment bags, ∀ l, Pairing {x : V // f.val x=l} where
toFun p := ⟨⟨p.color,p.allowed⟩,p.fiber⟩
invFun q := ColoredPairing.glue bags q.1 q.2
left_inv p := by
apply ColoredPairing.ext
· ext x; rfl
· rfl
right_inv q := by
rcases q with ⟨f,p⟩
change (⟨f,(ColoredPairing.glue bags f p).fiber⟩ :
Σ f : Assignment bags, ∀ l, Pairing {x : V // f.val x=l}) = ⟨f,p⟩
apply congrArg (fun q : ∀ l, Pairing {x : V // f.val x=l} =>
(⟨f,q⟩ : Σ f : Assignment bags, ∀ l, Pairing {x : V // f.val x=l}))
funext l
ext x
change ((p (f.val x)).mate ⟨x,rfl⟩).val = ((p l).mate x).val
obtain ⟨x,hx⟩ := x
dsimp at hx ⊢
subst l
rfl
theorem coloredPairing_card (bags : V → Finset L) :
Fintype.card (ColoredPairing bags) =
∑ f : Assignment bags, ∏ l : L, pairingCount (Fintype.card {x : V // f.val x=l}) := by
classical
rw [Fintype.card_congr (assignmentPairingEquiv bags),Fintype.card_sigma]
apply Finset.sum_congr rfl
intro f hf
rw [Fintype.card_pi]
apply Finset.prod_congr rfl
intro l hl
exact pairing_card
end MatchingFPRAS.UnitRefresh
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Edge2
attribute [-instance] _root_.OAI.MatchingFPRAS.UnitRefresh.Computable.allowedDec
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.UnitRefresh
open Finset MatchingFPRAS.Transport
variable {V L : Type*} [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L]
variable {bags : V → Finset L}
def ColoredPairing.edgeAt (p : ColoredPairing bags) (x : V) : BagEdge bags :=
⟨⟨(s(x,p.pair.mate x),p.color x),by
simp only [Sym2.mk_isDiag_iff]
exact (p.pair.no_fixed x).symm⟩,by
intro y hy
change p.color x ∈ bags y
rcases Sym2.mem_iff.mp hy with h | h <;> subst y
· exact p.allowed x
· rw [←p.same_color x]
exact p.allowed (p.pair.mate x)⟩
omit [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L] in
lemma ColoredPairing.edgeAt_incident (p : ColoredPairing bags) (x y : V) :
(p.edgeAt x).Incident y ↔ y=x ∨ y=p.pair.mate x := Sym2.mem_iff
omit [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L] in
lemma ColoredPairing.edgeAt_mate (p : ColoredPairing bags) (x : V) :
p.edgeAt (p.pair.mate x)=p.edgeAt x := by
apply Subtype.ext
apply Subtype.ext
change (s(p.pair.mate x,p.pair.mate (p.pair.mate x)),p.color (p.pair.mate x)) = _
rw [p.pair.involutive,p.same_color,Sym2.eq_swap]
rfl
omit [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L] in
lemma ColoredPairing.edgeAt_of_incident (p : ColoredPairing bags) (x y : V)
(h : (p.edgeAt x).Incident y) : p.edgeAt y=p.edgeAt x := by
rcases (p.edgeAt_incident x y).mp h with rfl | rfl
· rfl
· exact p.edgeAt_mate x
noncomputable def ColoredPairing.toPM (p : ColoredPairing bags) : PM (BagEdge.Incident (bags := bags)) :=
⟨Finset.univ.image p.edgeAt,by
constructor
· intros; exact Finset.mem_univ _
· intro x hx
refine ⟨p.edgeAt x,⟨Finset.mem_image.mpr ⟨x,Finset.mem_univ _,rfl⟩,?_⟩,?_⟩
· exact (p.edgeAt_incident x x).mpr (Or.inl rfl)
· intro e he
obtain ⟨y,hy,rfl⟩ := Finset.mem_image.mp he.1
exact (p.edgeAt_of_incident y x he.2).symm⟩
noncomputable def chosenEdge (M : PM (BagEdge.Incident (bags := bags))) (x : V) : BagEdge bags :=
Classical.choose (M.property.2 x (Finset.mem_univ x))
omit [Fintype L] [DecidableEq V] [DecidableEq L] in
lemma chosenEdge_spec [Fintype L] [DecidableEq V] [DecidableEq L]
(M : PM (BagEdge.Incident (bags := bags))) (x : V) :
chosenEdge M x ∈ M.val ∧ (chosenEdge M x).Incident x :=
(Classical.choose_spec (M.property.2 x (Finset.mem_univ x))).1
omit [Fintype L] [DecidableEq V] [DecidableEq L] in
lemma chosenEdge_unique [Fintype L] [DecidableEq V] [DecidableEq L]
(M : PM (BagEdge.Incident (bags := bags))) (x : V) (e : BagEdge bags)
(he : e ∈ M.val) (hx : e.Incident x) : e=chosenEdge M x :=
(Classical.choose_spec (M.property.2 x (Finset.mem_univ x))).2 e ⟨he,hx⟩
noncomputable def chosenMate (M : PM (BagEdge.Incident (bags := bags))) (x : V) : V :=
Sym2.Mem.other (chosenEdge_spec M x).2
lemma chosenMate_pair (M : PM (BagEdge.Incident (bags := bags))) (x : V) :
s(x,chosenMate M x)=(chosenEdge M x).val.val.1 := Sym2.other_spec _
lemma chosenMate_ne (M : PM (BagEdge.Incident (bags := bags))) (x : V) : chosenMate M x ≠ x :=
Sym2.other_ne (chosenEdge M x).val.property _
lemma chosenEdge_chosenMate (M : PM (BagEdge.Incident (bags := bags))) (x : V) :
chosenEdge M (chosenMate M x)=chosenEdge M x := by
symm
apply chosenEdge_unique M _ _ (chosenEdge_spec M x).1
exact Sym2.other_mem (chosenEdge_spec M x).2
lemma chosenMate_involutive (M : PM (BagEdge.Incident (bags := bags))) :
Function.Involutive (chosenMate M) := by
intro x
have h := chosenMate_pair M (chosenMate M x)
rw [chosenEdge_chosenMate,←chosenMate_pair M x] at h
rcases Sym2.eq_iff.mp h with h | h
· exact False.elim (chosenMate_ne M x h.1)
· exact h.2
noncomputable def fromPM (M : PM (BagEdge.Incident (bags := bags))) : ColoredPairing bags where
pair := ⟨chosenMate M,chosenMate_involutive M,chosenMate_ne M⟩
color x := (chosenEdge M x).val.color
allowed x := (chosenEdge M x).property x (chosenEdge_spec M x).2
same_color x := congrArg (fun e : BagEdge bags => e.val.color) (chosenEdge_chosenMate M x)
lemma fromPM_edgeAt (M : PM (BagEdge.Incident (bags := bags))) (x : V) :
(fromPM M).edgeAt x=chosenEdge M x := by
apply Subtype.ext
apply Subtype.ext
exact Prod.ext (chosenMate_pair M x) rfl
lemma chosenEdge_toPM (p : ColoredPairing bags) (x : V) : chosenEdge p.toPM x=p.edgeAt x := by
symm
apply chosenEdge_unique
· exact Finset.mem_image.mpr ⟨x,Finset.mem_univ _,rfl⟩
· exact (p.edgeAt_incident x x).mpr (Or.inl rfl)
noncomputable def coloredPMEquiv : PM (BagEdge.Incident (bags := bags)) ≃ ColoredPairing bags where
toFun := fromPM
invFun := ColoredPairing.toPM
left_inv M := by
apply Subtype.ext
ext e
constructor
· intro he
obtain ⟨x,hx,rfl⟩ := Finset.mem_image.mp he
rw [fromPM_edgeAt]
exact (chosenEdge_spec M x).1
· intro he
obtain ⟨x,hx⟩ := e.exists_incident
apply Finset.mem_image.mpr
exact ⟨x,Finset.mem_univ _,(fromPM_edgeAt M x).trans (chosenEdge_unique M x e he hx).symm⟩
right_inv p := by
apply ColoredPairing.ext
· ext x
change chosenMate p.toPM x=p.pair.mate x
have h := chosenMate_pair p.toPM x
rw [chosenEdge_toPM] at h
change s(x,chosenMate p.toPM x)=s(x,p.pair.mate x) at h
exact Sym2.congr_right.mp h
· funext x
change (chosenEdge p.toPM x).val.color=p.color x
rw [chosenEdge_toPM]
rfl
open Finset
variable {U S W L : Type*} [Fintype U] [Fintype S] [Fintype W] [Fintype L]
[DecidableEq U] [DecidableEq S] [DecidableEq W] [DecidableEq L]
omit [DecidableEq W] in
lemma fiberCount_leaf [DecidableEq W] (l p : L) (hlp : l≠p) (b : W → Finset L)
(hb : ∀ x,l∉b x) (T : Finset S) (f : Assignment b) :
fiberCount (leafAssignment (U := U) l p b T f).val l = Fintype.card U+T.card := by
rw [fiberCount_sum,fiberCount_sum]
have hz : fiberCount f.val l=0 := fiberCount_zero _ _ (fun x h => hb x (h ▸ f.property x))
change fiberCount (fun _ : U => l) l +
(fiberCount (fun x : S => if x∈T then l else p) l + fiberCount f.val l)=_
rw [fiberCount_const,ite_eq_left rfl,hz,Nat.add_zero]
congr 1
unfold fiberCount
rw [Fintype.card_congr (Equiv.subtypeEquivRight (q := fun x => x∈T) (fun x => by simp [hlp.symm]))]
exact Fintype.card_coe T
omit [DecidableEq W] in
lemma fiberCount_parent [DecidableEq W] (l p : L) (hlp : l≠p) (b : W → Finset L)
(T : Finset S) (f : Assignment b) :
fiberCount (leafAssignment (U := U) l p b T f).val p =
Fintype.card S-T.card+fiberCount f.val p := by
rw [fiberCount_sum,fiberCount_sum]
change fiberCount (fun _ : U => l) p +
(fiberCount (fun x : S => if x∈T then l else p) p + fiberCount f.val p)=_
rw [fiberCount_const,ite_eq_right hlp,Nat.zero_add]
congr 1
unfold fiberCount
rw [Fintype.card_congr (Equiv.subtypeEquivRight (q := fun x => x∉T) (fun x => by simp [hlp]))]
rw [Fintype.card_subtype_compl,Fintype.card_coe]
omit [DecidableEq W] in
lemma fiberCount_other [DecidableEq W] (l p a : L) (hal : a≠l) (hap : a≠p) (b : W → Finset L)
(T : Finset S) (f : Assignment b) :
fiberCount (leafAssignment (U := U) l p b T f).val a = fiberCount f.val a := by
rw [fiberCount_sum,fiberCount_sum]
change fiberCount (fun _ : U => l) a +
(fiberCount (fun x : S => if x∈T then l else p) a + fiberCount f.val a)=_
rw [fiberCount_const,ite_eq_right hal.symm]
have hz : fiberCount (fun x : S => if x∈T then l else p) a=0 := by
apply fiberCount_zero
intro x
split_ifs
· exact hal.symm
· exact hap.symm
simp [hz]
lemma leaf_assignment_weight (l p : L) (hlp : l≠p) (b : W → Finset L)
(hb : ∀ x,l∉b x) (w : L → ℕ → ℕ) (T : Finset S) (f : Assignment b) :
(∏ a,w a (fiberCount (leafAssignment (U := U) l p b T f).val a)) =
w l (Fintype.card U+T.card) * w p (Fintype.card S-T.card+fiberCount f.val p) *
(∏ a∈(univ.erase l).erase p,w a (fiberCount f.val a)) := by
rw [prod_split_two l p hlp,fiberCount_leaf l p hlp b hb,fiberCount_parent l p hlp]
congr 1
apply prod_congr rfl
intro a ha
rw [fiberCount_other _ _ _ (mem_erase.mp (mem_erase.mp ha).2).1 (mem_erase.mp ha).1]
theorem leaf_elimination (l p : L) (hlp : l≠p) (b : W → Finset L)
(hb : ∀ x,l∉b x) (w : L → ℕ → ℕ) :
assignmentPartition (leafBags (U := U) (S := S) l p b) w =
assignmentPartition b (leafUpdate (Fintype.card U) (Fintype.card S) l p w) := by
classical
unfold assignmentPartition
calc
_ = ∑ q : Finset S × Assignment b,
∏ a,w a (fiberCount (leafAssignment (U := U) l p b q.1 q.2).val a) := by
apply Fintype.sum_equiv (leafAssignmentEquiv l p hlp b)
intro f
exact congrArg (fun q : Assignment (leafBags (U := U) (S := S) l p b) =>
∏ a,w a (fiberCount q.val a)) ((leafAssignmentEquiv l p hlp b).left_inv f).symm
_ = _ := by
rw [Fintype.sum_prod_type,sum_comm]
apply sum_congr rfl
intro f hf
simp_rw [leaf_assignment_weight l p hlp b hb w]
rw [sum_finset_card (S:=S) (fun k =>
w l (Fintype.card U+k)*w p (Fintype.card S-k+fiberCount f.val p)*
(∏ a∈(univ.erase l).erase p,w a (fiberCount f.val a)))]
rw [prod_split_two l p hlp]
have he : (∏ a∈(univ.erase l).erase p,
leafUpdate (Fintype.card U) (Fintype.card S) l p w a (fiberCount f.val a)) =
∏ a∈(univ.erase l).erase p,w a (fiberCount f.val a) := by
apply prod_congr rfl
intro a ha
simp only [leafUpdate,ite_eq_right (mem_erase.mp (mem_erase.mp ha).2).1,
ite_eq_right (mem_erase.mp ha).1]
rw [he]
simp only [leafUpdate,ite_true,ite_eq_right hlp.symm,one_mul]
rw [sum_mul]
apply sum_congr rfl
intro k hk
ac_rfl
end MatchingFPRAS.UnitRefresh
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_AssignmentEquiv
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.UnitRefresh
open Finset
variable {V W L : Type*} [Fintype V] [Fintype W] [Fintype L]
[DecidableEq V] [DecidableEq W] [DecidableEq L]
theorem tree_leaf_elimination (b : V → Finset L) (l p : L) (hlp : l≠p)
(h : LeafAt b l p) (w : L → ℕ → ℕ) :
assignmentPartition b w =
assignmentPartition (fun x : Outside b l => b x.val)
(leafUpdate (Fintype.card (Private b l)) (Fintype.card (Shared b l)) l p w) := by
classical
rw [assignmentPartition_equiv b _ (splitLeaf b l) (splitLeaf_bags b l p h)]
exact leaf_elimination l p hlp _ (fun x => x.property) w
lemma root_elimination {U : Type*} [Fintype U] [DecidableEq U]
(l : L) (b : W → Finset L) (hb : ∀ x,l∉b x) (w : L → ℕ → ℕ) :
assignmentPartition (rootBags (U:=U) l b) w =
assignmentPartition b (rootUpdate (Fintype.card U) l w) := by
classical
unfold assignmentPartition
apply Fintype.sum_equiv (rootAssignmentEquiv l b)
intro f
have hl : fiberCount f.val l = Fintype.card U := by
rw [fiberCount_sum]
have he : (fun x : U => f.val (.inl x))=(fun _ => l) := by
funext x; simpa [rootBags] using f.property (.inl x)
rw [he,fiberCount_const,ite_eq_left rfl]
have hz : fiberCount (fun x : W => f.val (.inr x)) l=0 := by
apply fiberCount_zero
intro x hx
exact hb x (hx ▸ f.property (.inr x))
omega
apply prod_congr rfl
intro a ha
by_cases h : a=l
· subst a; simp [rootUpdate,hl]
· simp only [rootUpdate,ite_eq_right h]
congr 1
rw [fiberCount_sum]
have he : (fun x : U => f.val (.inl x))=(fun _ => l) := by
funext x; simpa [rootBags] using f.property (.inl x)
rw [he,fiberCount_const,ite_eq_right (Ne.symm h),zero_add]
rfl
theorem tree_root_elimination (b : V → Finset L) (l : L)
(h : ∀ x,l∈b x → b x={l}) (w : L → ℕ → ℕ) :
assignmentPartition b w =
assignmentPartition (fun x : Outside b l => b x.val)
(rootUpdate (Fintype.card {x : V // l∈b x}) l w) := by
classical
have he (x : V) : rootBags l (fun y : Outside b l => b y.val) (splitRoot b l x)=b x := by
unfold splitRoot
simp only [Equiv.coe_fn_mk]
split_ifs with hx
· exact (h x hx).symm
· rfl
rw [assignmentPartition_equiv b _ (splitRoot b l) he]
exact root_elimination l _ (fun x => x.property) w
open Finset
variable {V L : Type*} [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L]
theorem active_leaf_elimination (b : V → Finset L) (R : Finset V) (l p : L) (hlp : l≠p)
(h : LeafAt (fun x : R => b x.val) l p) (w : L → ℕ → ℕ) :
activePartition b R w = activePartition b (trim b R l)
(leafUpdate (privateCount b R l) (sharedCount b R l) l p w) := by
unfold activePartition
rw [tree_leaf_elimination _ l p hlp h,active_outside]
rw [show Fintype.card (Private (fun x : R => b x.val) l)=privateCount b R l from
active_card_filter R (fun x => b x={l}),
show Fintype.card (Shared (fun x : R => b x.val) l)=sharedCount b R l from
active_card_filter R (fun x => l∈b x ∧ b x≠{l})]
rfl
lemma active_root_elimination (b : V → Finset L) (R : Finset V) (l : L)
(h : ∀ x : R,l∈b x.val → b x.val={l}) (w : L → ℕ → ℕ) :
activePartition b R w = activePartition b (trim b R l)
(rootUpdate ((R.filter fun x => l∈b x).card) l w) := by
unfold activePartition
rw [tree_root_elimination _ l h,active_outside,active_card_filter R (fun x => l∈b x)]
rfl
theorem tableDP_correct (b : V → Finset L) (parent : L → Option L)
(ls : List L) (R : Finset V) (hp : LegalPlan b parent ls R) (w : L → ℕ → ℕ) :
activePartition b R w=∏ l,tableDP b parent ls R w l 0 := by
induction ls generalizing R w with
| nil =>
have hR : R=∅ := hp
subst R
exact active_empty b w
| cons l ls ih =>
have ht : activePartition b R w =
activePartition b (trim b R l) (advanceTable b R parent l w) := by
cases hpar : parent l with
| none =>
unfold advanceTable; rw [hpar]
exact active_root_elimination b R l (by simpa only [LegalPlan,hpar] using hp.1) w
| some p =>
have h := hp.1
simp only [hpar] at h
unfold advanceTable; rw [hpar]
exact active_leaf_elimination b R l p h.1 h.2 w
rw [ht]
exact ih _ hp.2 _
end MatchingFPRAS.UnitRefresh
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_RankOrder
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.UnitRefresh
open Finset
variable {V L : Type*} [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L]
lemma finiteDP_correct (b : V → Finset L) (parent : L → Option L) (ls : List L)
(R : Finset V) (w z : L → ℕ → ℕ)
(h : ∀ a r,r≤Fintype.card V*ls.length → w a r=z a r) (a : L) :
finiteDP b parent ls R w a 0=tableDP b parent ls R z a 0 := by
induction ls generalizing R w z with
| nil => exact h a 0 (by simp)
| cons l ls ih =>
apply ih
intro a r hr
rw [capTable,ite_eq_left hr]
apply advanceTable_congr b R parent l w z (Fintype.card V*ls.length)
· intro a r hr
apply h
simpa only [List.length_cons,Nat.mul_add,Nat.mul_one] using hr
· exact hr
omit [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L] in
lemma ColoredPairing.subtype_hext [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L]
{bags : V → Finset L} {P Q : V → Prop}
[DecidablePred P] [DecidablePred Q]
(p : ColoredPairing (fun x : {x // P x} => bags x.val))
(q : ColoredPairing (fun x : {x // Q x} => bags x.val))
(hPQ : ∀ x,P x ↔ Q x)
(hm : ∀ (x : {x // P x}) (y : {x // Q x}),x.val=y.val →
(p.pair.mate x).val=(q.pair.mate y).val)
(hc : ∀ (x : {x // P x}) (y : {x // Q x}),x.val=y.val → p.color x=q.color y) :
HEq p q := by
have he : P=Q := funext fun x => propext (hPQ x)
subst Q
apply heq_of_eq
apply ColoredPairing.ext
· ext x; exact hm x x rfl
· funext x; exact hc x x rfl
def ColoredPairing.remove {bags : V → Finset L} (p : ColoredPairing bags) (a : V) :
ColoredPairing (residualBags bags a (p.pair.mate a)) where
pair := p.pair.remove a
color x := p.color x.val
allowed x := p.allowed x.val
same_color x := p.same_color x.val
def ColoredPairing.insert {bags : V → Finset L} (a : V) (c : Partner bags a)
(p : ColoredPairing (residualBags bags a c.val.1)) : ColoredPairing bags where
pair := p.pair.insert a c.val.1 c.property.1
color x := if hx : x=a ∨ x=c.val.1 then c.val.2 else p.color ⟨x,by tauto⟩
allowed x := by
dsimp
split_ifs with hx
· rcases hx with rfl|rfl
· exact c.property.2.1
· exact c.property.2.2
· exact p.allowed _
same_color x := by
by_cases ha : x=a
· subst x
simp [Pairing.insert,c.property.1]
by_cases hb : x=c.val.1
· subst x
simp [Pairing.insert,c.property.1]
simp only [Pairing.insert,dite_eq_right ha,dite_eq_right hb]
rw [dite_eq_right (by exact not_or.mpr (p.pair.mate ⟨x,ha,hb⟩).property),
dite_eq_right (not_or.mpr ⟨ha,hb⟩)]
exact p.same_color ⟨x,ha,hb⟩
omit [Fintype V] [Fintype L] [DecidableEq L] in
@[simp] lemma ColoredPairing.insert_color [Fintype V] [Fintype L] [DecidableEq L]
{bags : V → Finset L} (a : V) (c : Partner bags a)
(p : ColoredPairing (residualBags bags a c.val.1)) :
(p.insert a c).color a=c.val.2 := by simp [ColoredPairing.insert]
omit [Fintype V] [Fintype L] [DecidableEq L] in
@[simp] lemma ColoredPairing.insert_color_residual [Fintype V] [Fintype L] [DecidableEq L]
{bags : V → Finset L} (a : V)
(c : Partner bags a) (p : ColoredPairing (residualBags bags a c.val.1))
(x : withoutPair a c.val.1) :
(p.insert a c).color x.val=p.color x := by
simp [ColoredPairing.insert,x.property.1,x.property.2]
noncomputable def ColoredPairing.split {bags : V → Finset L} (a : V) :
ColoredPairing bags ≃ Σ c : Partner bags a,ColoredPairing (residualBags bags a c.val.1) where
toFun p := ⟨⟨(p.pair.mate a,p.color a),p.pair.no_fixed a,p.allowed a,
by rw [← p.same_color a]; exact p.allowed _⟩,p.remove a⟩
invFun q := q.2.insert a q.1
left_inv p := by
apply ColoredPairing.ext
· ext x
by_cases ha : x=a
· subst x; simp [ColoredPairing.insert,Pairing.insert]
by_cases hb : x=p.pair.mate a
· subst x; simp [ColoredPairing.insert,Pairing.insert,p.pair.no_fixed,p.pair.involutive a]
simp [ColoredPairing.insert,Pairing.insert,ColoredPairing.remove,Pairing.remove,ha,hb]
· funext x
by_cases ha : x=a
· subst x; simp [ColoredPairing.insert]
by_cases hb : x=p.pair.mate a
· subst x; simp [ColoredPairing.insert,p.same_color]
simp [ColoredPairing.insert,ColoredPairing.remove,ha,hb]
right_inv q := by
rcases q with ⟨c,p⟩
apply Sigma.ext
· apply Subtype.ext
exact Prod.ext (Pairing.insert_at a c.val.1 c.property.1 p.pair) (ColoredPairing.insert_color a c p)
· apply ColoredPairing.subtype_hext
· intro x; simp only [ColoredPairing.insert,Pairing.insert_at]
· intro x y hxy
change (p.pair.insert a c.val.1 c.property.1).mate x.val=(p.pair.mate y).val
rw [hxy]
exact Pairing.insert_other _ _ _ _ y
· intro x y hxy
change (p.insert a c).color x.val=p.color y
rw [hxy]
exact ColoredPairing.insert_color_residual _ _ _ y
end MatchingFPRAS.UnitRefresh
namespace MatchingFPRAS.UnitRefresh.Materialized
open Finset
variable {V : Type*} [Fintype V] [DecidableEq V]
lemma read_tabulate {m B : ℕ} (f : Fin m → ℕ → ℕ) (a : Fin m) (r : ℕ) :
read (tabulate m B f) a.val r = if r≤B then f a r else 0 := by
unfold read tabulate List.getD
simp only [List.getElem?_ofFn, a.isLt, dite_eq_left, Option.getD_some]
by_cases hr : r≤B
· have h : r<B+1 := by omega
simp [hr,h]
· have h : ¬r<B+1 := by omega
simp [hr,h]
lemma read_update {m : ℕ} (bags : V → Finset (Fin m)) (R : Finset V)
(parent : Fin m → Option (Fin m)) (l a : Fin m) (B r : ℕ) (t : Table) :
read (update bags R parent l B t) a.val r =
capTable B (advanceTable bags R parent l (fun a r=>read t a.val r)) a r := by
rw [update,read_tabulate]
unfold capTable
split_ifs <;> simp [entry_eq]
lemma read_run {m : ℕ} (bags : V → Finset (Fin m)) (parent : Fin m → Option (Fin m))
(ls : List (Fin m)) (R : Finset V) (t : Table) (a : Fin m) (r : ℕ) :
read (run bags parent ls R t) a.val r =
finiteDP bags parent ls R (fun a r=>read t a.val r) a r := by
induction ls generalizing R t with
| nil => rfl
| cons l ls ih =>
rw [run,finiteDP,ih]
congr 2
funext a r
exact read_update bags R parent l a _ r t
end MatchingFPRAS.UnitRefresh.Materialized
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Arithmetic_TreeFraction
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreeFraction
open TreeTyped
def val (x : Fraction) : ℚ := (x.1:ℚ)/x.2
end MatchingFPRAS.TreeFraction
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Plan
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.UnitRefresh.Materialized
open Finset
variable {V : Type*} [Fintype V] [DecidableEq V]
theorem computable_count_eq {m : ℕ} (bags : V → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l) :
count bags parent (plan rank)=Fintype.card (ColoredPairing bags) := by
rw [coloredPairing_card]
change count bags parent (plan rank)=assignmentPartition bags (fun _=>pairingCount)
rw [←active_univ]
rw [tableDP_correct bags parent _ _ (plan_legal bags rank parent hb hne hp)]
unfold count
apply prod_congr rfl
intro a _
rw [read_run]
apply finiteDP_correct
intro b r hr
rw [plan_length] at hr
simp [initial,read_tabulate,hr]
def branchCount {m : ℕ} (bags : V → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (a b : V) : ℕ :=
count (residualBags bags a b) parent (plan rank)
lemma branchCount_eq {m : ℕ} (bags : V → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a b : V) : branchCount bags rank parent a b=
Fintype.card (ColoredPairing (residualBags bags a b)) := by
apply computable_count_eq
· intro x c hc d hd; exact hb x.val c hc d hd
· intro x; exact hne x.val
· exact hp
lemma branchCount_sum {m : ℕ} (bags : V → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : V) : (∑ c : Partner bags a,branchCount bags rank parent a c.val.1)=
count bags parent (plan rank) := by
rw [computable_count_eq bags rank parent hb hne hp,
Fintype.card_congr (ColoredPairing.split a),Fintype.card_sigma]
apply sum_congr rfl
intro c _
exact branchCount_eq bags rank parent hb hne hp a c.val.1
open Finset MatchingFPRAS.FiniteChoice
variable {n m : ℕ}
def edgeCount (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (a : Fin n) (bc : Fin n × Fin m) : ℕ :=
if validBranch bags a bc then branchCount bags rank parent a bc.1 else 0
lemma edgeCount_sum (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin n) : (∑ bc,edgeCount bags rank parent a bc)=count bags parent (plan rank) := by
rw [←branchCount_sum bags rank parent hb hne hp a]
change (∑ bc,if validBranch bags a bc then branchCount bags rank parent a bc.1 else 0)=_
rw [←Finset.sum_filter]
exact Finset.sum_subtype _ (by intro bc; simp only [Finset.mem_filter,Finset.mem_univ,true_and]; rfl) _
def edgeProbability (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (a : Fin n) (i : Fin (n*m)) : ℚ :=
edgeCount bags rank parent a (finProdFinEquiv.symm i)/count bags parent (plan rank)
lemma edgeProbability_sum (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin n) (hz : 0 < count bags parent (plan rank)) :
∑ i,edgeProbability bags rank parent a i=1 := by
unfold edgeProbability
rw [←Finset.sum_div,←Nat.cast_sum]
rw [←finProdFinEquiv.sum_comp (fun i=>edgeCount bags rank parent a (finProdFinEquiv.symm i))]
simp only [Equiv.symm_apply_apply]
rw [edgeCount_sum bags rank parent hb hne hp a]
exact div_self (by exact_mod_cast hz.ne')
def drawEdge (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin n) (hz : 0 < count bags parent (plan rank)) (k : ℕ) (bits : Fin k → Bool) :
{c : Partner bags a // 0<branchCount bags rank parent a c.val.1} := by
let p := edgeProbability bags rank parent a
have hs := edgeProbability_sum bags rank parent hb hne hp a hz
let i := chooseBits p hs k bits
let bc := finProdFinEquiv.symm i
have hh : 0<edgeCount bags rank parent a bc := by
have h := chooseBits_pos p hs k bits
change 0<(edgeCount bags rank parent a bc:ℚ)/(count bags parent (plan rank):ℚ) at h
have := (div_pos_iff_of_pos_right (by exact_mod_cast hz : (0:ℚ) < count bags parent (plan rank))).mp h
exact_mod_cast this
have hv : validBranch bags a bc := by
by_contra hv
simp [edgeCount,hv] at hh
exact ⟨⟨bc,hv⟩,by simpa [edgeCount,hv] using hh⟩
end MatchingFPRAS.UnitRefresh.Materialized
namespace MatchingFPRAS.UnitRefresh
open Finset
variable {U V L : Type*} [Fintype U] [Fintype V] [Fintype L] [DecidableEq U] [DecidableEq V] [DecidableEq L]
def ColoredPairing.map (bags : V → Finset L) (e : U ≃ V)
(p : ColoredPairing (fun x=>bags (e x))) : ColoredPairing bags where
pair := p.pair.map e
color x := p.color (e.symm x)
allowed x := by simpa using p.allowed (e.symm x)
same_color x := by simpa [Pairing.map] using p.same_color (e.symm x)
def ColoredPairing.comap (bags : V → Finset L) (e : U ≃ V)
(p : ColoredPairing bags) : ColoredPairing (fun x=>bags (e x)) where
pair := p.pair.map e.symm
color x := p.color (e x)
allowed x := p.allowed (e x)
same_color x := by simpa [Pairing.map] using p.same_color (e x)
def ColoredPairing.equiv (bags : V → Finset L) (e : U ≃ V) :
ColoredPairing (fun x=>bags (e x)) ≃ ColoredPairing bags where
toFun := ColoredPairing.map bags e
invFun := ColoredPairing.comap bags e
left_inv p := by
apply ColoredPairing.ext
· ext x; simp [ColoredPairing.map,ColoredPairing.comap,Pairing.map]
· funext x; simp [ColoredPairing.map,ColoredPairing.comap]
right_inv p := by
apply ColoredPairing.ext
· ext x; simp [ColoredPairing.map,ColoredPairing.comap,Pairing.map]
· funext x; simp [ColoredPairing.map,ColoredPairing.comap]
def removePairEquiv {n : ℕ} (a b : Fin (n+2)) (hb : b≠a) :
Fin n ≃ withoutPair a b := by
let e := gapEquiv a
let b' := e.symm ⟨b,hb⟩
let f := gapEquiv b'
refine {
toFun := fun i=>⟨(e (f i).val).val,(e (f i).val).property,?_⟩
invFun := fun x=>f.symm ⟨e.symm ⟨x.val,x.property.1⟩,?_⟩
left_inv := ?_
right_inv := ?_ }
· intro h
apply (f i).property
apply e.injective
apply Subtype.ext
simpa [b'] using h
· intro h
have hh := congrArg (fun i=>(e i).val) h
apply x.property.2
simpa [b'] using hh
· intro i
apply f.injective
simp
· intro x
apply Subtype.ext
simp
end MatchingFPRAS.UnitRefresh
namespace MatchingFPRAS.UnitRefresh.Materialized
open Finset MatchingFPRAS.FiniteChoice
variable {m : ℕ}
lemma singleton_count_zero (bags : Fin 1 → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l) :
count bags parent (plan rank)=0 := by
rw [computable_count_eq bags rank parent hb hne hp]
have : IsEmpty (ColoredPairing bags) := ⟨fun p=>p.pair.no_fixed 0 (Subsingleton.elim _ _)⟩
exact Fintype.card_eq_zero
def sampleUnit (k : ℕ) : (n : ℕ) → (bags : Fin n → Finset (Fin m)) →
(rank : Fin m → ℕ) → (parent : Fin m → Option (Fin m)) →
(hb : RankedBags bags rank parent) → (hne : ∀ x,(bags x).Nonempty) →
(hp : ∀ l p,parent l=some p → rank p < rank l) →
0 < count bags parent (plan rank) → (Fin n → Fin k → Bool) → ColoredPairing bags
| 0,bags,_,_,_,_,_,_,_ =>
⟨⟨fun x=>Fin.elim0 x,fun x=>Fin.elim0 x,fun x=>Fin.elim0 x⟩,
(fun x=>Fin.elim0 x),(fun x=>Fin.elim0 x),(fun x=>Fin.elim0 x)⟩
| 1,bags,rank,parent,hb,hne,hp,hz,_ =>
False.elim (by rw [singleton_count_zero bags rank parent hb hne hp] at hz; omega)
| n+2,bags,rank,parent,hb,hne,hp,hz,bits => by
let a : Fin (n+2) := Fin.last (n+1)
let c := drawEdge bags rank parent hb hne hp a hz k (bits a)
let e := removePairEquiv a c.val.val.1 c.val.property.1
let b' : Fin n → Finset (Fin m) := fun x=>bags (e x).val
have hb' : RankedBags b' rank parent := by
intro x l hl r hr; exact hb (e x).val l hl r hr
have hne' : ∀ x,(b' x).Nonempty := fun x=>hne (e x).val
have hz' : 0 < count b' parent (plan rank) := by
rw [computable_count_eq b' rank parent hb' hne' hp]
rw [Fintype.card_congr (ColoredPairing.equiv (residualBags bags a c.val.val.1) e)]
rw [←branchCount_eq bags rank parent hb hne hp]
exact c.property
let p := sampleUnit k n b' rank parent hb' hne' hp hz'
(fun i=>bits i.castSucc.castSucc)
exact (ColoredPairing.map (residualBags bags a c.val.val.1) e p).insert a c.val
open Finset MatchingFPRAS.FiniteChoice MatchingFPRAS.Variation
open scoped Classical
variable {n m : ℕ}
abbrev PositivePartner (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (a : Fin n) :=
{c : Partner bags a // 0<branchCount bags rank parent a c.val.1}
def partnerIndex (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (a : Fin n)
(c : PositivePartner bags rank parent a) : Fin (n*m) := finProdFinEquiv c.val.val
noncomputable def positiveSplitEquiv (bags : Fin n → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin n) :
(Σ c : PositivePartner bags rank parent a,ColoredPairing (residualBags bags a c.val.val.1)) ≃ ColoredPairing bags := by
let e : (Σ c : PositivePartner bags rank parent a,ColoredPairing (residualBags bags a c.val.val.1)) ≃
(Σ c : Partner bags a,ColoredPairing (residualBags bags a c.val.1)) := {
toFun := fun s=>⟨s.1.val,s.2⟩
invFun := fun s=>⟨⟨s.1,by
rw [branchCount_eq bags rank parent hb hne hp]
exact Fintype.card_pos_iff.mpr ⟨s.2⟩⟩,s.2⟩
left_inv := fun s=>by rcases s with ⟨⟨c,hc⟩,x⟩; rfl
right_inv := fun s=>by cases s; rfl }
exact e.trans (ColoredPairing.split a).symm
end MatchingFPRAS.UnitRefresh.Materialized
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_RemainingBags
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.UnitRefresh.Materialized
open Finset MatchingFPRAS.FiniteChoice MatchingFPRAS.Variation
open scoped Classical
variable {n m : ℕ}
def remainingBags (bags : Fin (n+2) → Finset (Fin m)) (a : Fin (n+2))
(c : Partner bags a) : Fin n → Finset (Fin m) :=
fun x=>bags (removePairEquiv a c.val.1 c.property.1 x).val
lemma remainingRanked (bags : Fin (n+2) → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(a : Fin (n+2)) (c : Partner bags a) : RankedBags (remainingBags bags a c) rank parent := by
intro x l hl r hr
exact hb _ l hl r hr
lemma remainingNonempty (bags : Fin (n+2) → Finset (Fin m))
(hne : ∀ x,(bags x).Nonempty) (a : Fin (n+2)) (c : Partner bags a) :
∀ x,(remainingBags bags a c x).Nonempty := fun _=>hne _
lemma remainingCard (bags : Fin (n+2) → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin (n+2)) (c : Partner bags a) :
Fintype.card (ColoredPairing (remainingBags bags a c))=branchCount bags rank parent a c.val.1 := by
have h := Fintype.card_congr (ColoredPairing.equiv (residualBags bags a c.val.1)
(removePairEquiv a c.val.1 c.property.1))
exact h.trans (branchCount_eq bags rank parent hb hne hp _ _).symm
lemma remainingPositive (bags : Fin (n+2) → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin (n+2)) (c : PositivePartner bags rank parent a) :
0 < count (remainingBags bags a c.val) parent (plan rank) := by
rw [computable_count_eq _ rank parent (remainingRanked bags rank parent hb a c.val)
(remainingNonempty bags hne a c.val) hp, remainingCard bags rank parent hb hne hp]
exact c.property
def assembleEdge (bags : Fin (n+2) → Finset (Fin m)) (a : Fin (n+2)) (c : Partner bags a)
(p : ColoredPairing (remainingBags bags a c)) : ColoredPairing bags :=
(ColoredPairing.map (residualBags bags a c.val.1) (removePairEquiv a c.val.1 c.property.1) p).insert a c
def residualSampler (k : ℕ) (bags : Fin (n+2) → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin (n+2)) (c : PositivePartner bags rank parent a) (bits : Fin n → Fin k → Bool) : ColoredPairing bags :=
assembleEdge bags a c.val (sampleUnit k n (remainingBags bags a c.val) rank parent
(remainingRanked bags rank parent hb a c.val) (remainingNonempty bags hne a c.val) hp
(remainingPositive bags rank parent hb hne hp a c) bits)
noncomputable def renumberedSplitEquiv (bags : Fin (n+2) → Finset (Fin m)) (rank : Fin m → ℕ)
(parent : Fin m → Option (Fin m)) (hb : RankedBags bags rank parent)
(hne : ∀ x,(bags x).Nonempty) (hp : ∀ l p,parent l=some p → rank p < rank l)
(a : Fin (n+2)) :
(Σ c : PositivePartner bags rank parent a,ColoredPairing (remainingBags bags a c.val)) ≃ ColoredPairing bags :=
(Equiv.sigmaCongrRight (fun c : PositivePartner bags rank parent a=>
ColoredPairing.equiv (residualBags bags a c.val.val.1)
(removePairEquiv a c.val.val.1 c.val.property.1))).trans
(positiveSplitEquiv bags rank parent hb hne hp a)
open Finset MatchingFPRAS.Variation
open scoped Classical
end MatchingFPRAS.UnitRefresh.Materialized
namespace MatchingFPRAS.UnitRefresh.Computable
open Finset MatchingFPRAS.Transport
variable {V L : Type*} [Fintype V] [Fintype L] [DecidableEq V] [DecidableEq L]
variable {bags : V → Finset L}
instance edgeDec (e : BagEdge bags) (x : V) : Decidable (e.Incident x) :=
inferInstanceAs (Decidable (x∈e.val.val.1))
def edge (M : PM (BagEdge.Incident (bags := bags))) (x : V) : BagEdge bags :=
M.val.choose (fun e=>e.Incident x) (M.property.2 x (mem_univ x))
omit [Fintype L] [DecidableEq L] in
lemma edge_spec [DecidableEq L] (M : PM (BagEdge.Incident (bags := bags))) (x : V) :
edge M x∈M.val ∧ (edge M x).Incident x :=
M.val.choose_spec _ (M.property.2 x (mem_univ x))
lemma edge_eq (M : PM (BagEdge.Incident (bags := bags))) (x : V) : edge M x=chosenEdge M x :=
chosenEdge_unique M x _ (edge_spec M x).1 (edge_spec M x).2
def mate (M : PM (BagEdge.Incident (bags := bags))) (x : V) : V :=
Sym2.Mem.other' (edge_spec M x).2
lemma mate_eq (M : PM (BagEdge.Incident (bags := bags))) (x : V) : mate M x=chosenMate M x := by
have hp : s(x,mate M x)=(edge M x).val.val.1 := Sym2.other_spec' (edge_spec M x).2
apply (Sym2.congr_right (a:=x)).mp
exact hp.trans (by rw [edge_eq,←chosenMate_pair])
def fromMatching (M : PM (BagEdge.Incident (bags := bags))) : ColoredPairing bags where
pair := ⟨mate M,(fun x=>by simpa only [mate_eq] using chosenMate_involutive M x),
fun x=>by simpa only [mate_eq] using chosenMate_ne M x⟩
color x := (edge M x).val.color
allowed x := (edge M x).property x (edge_spec M x).2
same_color x := by
simp only [mate_eq,edge_eq]
exact congrArg (fun e : BagEdge bags=>e.val.color) (chosenEdge_chosenMate M x)
lemma from_eq (M : PM (BagEdge.Incident (bags := bags))) : fromMatching M=fromPM M := by
apply ColoredPairing.ext
· apply Pairing.ext; intro x; exact mate_eq M x
· funext x; exact congrArg (fun e : BagEdge bags=>e.val.color) (edge_eq M x)
def toMatching (p : ColoredPairing bags) : PM (BagEdge.Incident (bags := bags)) :=
⟨Finset.univ.image p.edgeAt,by exact p.toPM.property⟩
omit [Fintype L] in
lemma to_eq [Fintype L] (p : ColoredPairing bags) : toMatching p=p.toPM := rfl
def pairingEquiv : PM (BagEdge.Incident (bags := bags)) ≃ ColoredPairing bags where
toFun := fromMatching
invFun := toMatching
left_inv M := by
rw [from_eq,to_eq]
exact (coloredPMEquiv (bags:=bags)).left_inv M
right_inv p := by
rw [to_eq,from_eq]
exact (coloredPMEquiv (bags:=bags)).right_inv p
end MatchingFPRAS.UnitRefresh.Computable
namespace MatchingFPRAS.UnitRefresh
open Finset MatchingFPRAS.Variation
variable {V L J : Type*} [Fintype V] [DecidableEq V] [Fintype L] [Fintype J] [DecidableEq L] [DecidableEq J]
def ColoredPairing.colorEquiv (bags : V → Finset L) (e : L ≃ J) :
ColoredPairing bags ≃ ColoredPairing (fun x=>(bags x).map e.toEmbedding) where
toFun p := {
pair:=p.pair
color:=fun x=>e (p.color x)
allowed:=fun x=>by simpa using p.allowed x
same_color:=fun x=>congrArg e (p.same_color x) }
invFun p := {
pair:=p.pair
color:=fun x=>e.symm (p.color x)
allowed:=fun x=>by
obtain ⟨l,hl,he⟩:=mem_map.mp (p.allowed x)
simpa only [←he,Equiv.toEmbedding_apply,Equiv.symm_apply_apply] using hl
same_color:=fun x=>congrArg e.symm (p.same_color x) }
left_inv p := by
apply ColoredPairing.ext
· rfl
· funext x; exact e.symm_apply_apply _
right_inv p := by
apply ColoredPairing.ext
· rfl
· funext x; exact e.apply_symm_apply _
open Finset MatchingFPRAS.Variation
variable {V L : Type*} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
def numberingEquiv (bags : V → Finset L) :
ColoredPairing (numberedBags bags) ≃ ColoredPairing bags :=
(ColoredPairing.colorEquiv (fun x=>bags (orderedEnum V x)) (orderedEnum L).symm).symm.trans
(ColoredPairing.equiv bags (orderedEnum V))
lemma numbered_count_pos (bags : V → Finset L) (rank : L → ℕ) (parent : L → Option L)
(hb : RankedBags bags rank parent) (hne : ∀ x,(bags x).Nonempty)
(hp : ∀ l p,parent l=some p → rank p < rank l) (M : ColoredPairing bags) :
0<Materialized.count (numberedBags bags) (numberedParent parent)
(Materialized.plan (numberedRank rank)) := by
rw [Materialized.computable_count_eq _ _ _ (numberedRanked bags rank parent hb)
(numberedNonempty bags hne) (numberedDecreasing rank parent hp)]
exact Fintype.card_pos_iff.mpr ⟨(numberingEquiv bags).symm M⟩
def sampleNumbered (k : ℕ) (bags : V → Finset L) (rank : L → ℕ) (parent : L → Option L)
(hb : RankedBags bags rank parent) (hne : ∀ x,(bags x).Nonempty)
(hp : ∀ l p,parent l=some p → rank p < rank l) (M : ColoredPairing bags)
(bits : Fin (Fintype.card V) → Fin k → Bool) : ColoredPairing bags :=
numberingEquiv bags (Materialized.sampleUnit k (Fintype.card V) (numberedBags bags)
(numberedRank rank) (numberedParent parent) (numberedRanked bags rank parent hb)
(numberedNonempty bags hne) (numberedDecreasing rank parent hp)
(numbered_count_pos bags rank parent hb hne hp M) bits)
open MatchingFPRAS.Transport
def sampleMatching (k : ℕ) (bags : V → Finset L) (rank : L → ℕ) (parent : L → Option L)
(hb : RankedBags bags rank parent) (hne : ∀ x,(bags x).Nonempty)
(hp : ∀ l p,parent l=some p → rank p < rank l)
(M : PM (BagEdge.Incident (bags:=bags)))
(bits : Fin (Fintype.card V) → Fin k → Bool) : PM (BagEdge.Incident (bags:=bags)) :=
(Computable.pairingEquiv (bags:=bags)).symm
(sampleNumbered k bags rank parent hb hne hp (Computable.pairingEquiv M) bits)
end MatchingFPRAS.UnitRefresh
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Sym2Order
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset Replica Replica.Ladder Variation
variable {V L : Type*} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
attribute [local instance] sym2Order
attribute [local instance] bagEdgeOrder
def rationalSlotWeight {bags : V → Finset L} {T q : ℕ} (w : BagEdge bags → ℚ)
(x : Slot T q) (e : BagEdge bags) : ℚ :=
max ((rationalTierBase V)^tier x)⁻¹ (min ((rationalTierBase V)^tier x) (w e))
omit [LinearOrder V] [Fintype L] [LinearOrder L] in
lemma rationalSlotWeight_cast [LinearOrder V] [Fintype L] [LinearOrder L]
{bags : V → Finset L} {T q : ℕ} (w : BagEdge bags → ℚ)
(x : Slot T q) (e : BagEdge bags) :
(rationalSlotWeight w x e:ℝ)=slotWeight (fun e=>(w e:ℝ)) x e := by
simp [rationalSlotWeight,slotWeight,tierClamp,rationalTierBase_cast]
lemma rationalSlotWeight_pos {bags : V → Finset L} {T q : ℕ} (w : BagEdge bags → ℚ)
(x : Slot T q) (e : BagEdge bags) : 0 < rationalSlotWeight w x e := by
have h:=slotWeight_pos (fun e=>(w e:ℝ)) x e
rw [←rationalSlotWeight_cast] at h
exact_mod_cast h
variable {bags : V → Finset L} {G : SimpleGraph L}
variable (hbags : ∀ v,∀ a∈bags v,∀ b∈bags v,a=b ∨ G.Adj a b) (hG : G.IsAcyclic)
attribute [local instance] UnitRefresh.Computable.allowedDec
attribute [local instance] bagEdgeFintype
abbrev BagPM (bags : V → Finset L) := PM (BagEdge.Incident (bags:=bags))
noncomputable local instance instDecidableEqBagPM_r8038f5_1 : DecidableEq (BagPM bags) := Classical.decEq _
include hbags hG in
lemma parallels_bound (e : BagEdge bags) :
(univ.filter (fun f : BagEdge bags=>f.val.val.1=e.val.val.1)).card≤2 := by
have h:=BagEdge.parallels_card_le (label_memberships_le_two hbags hG) e
unfold BagEdge.parallels at h
have instances_eq : tierClampBagEdgeFintype (bags:=bags) =
(inferInstance : Fintype (BagEdge bags)) := Subsingleton.elim _ _
rw [instances_eq] at h
exact h
def sampleLadderPair {T q : ℕ} (w : BagEdge bags → ℚ) (x y : Slot T q)
(a : BagPM bags × BagPM bags) (k : ℕ) : (Fin k → Bool) → BagPM bags × BagPM bags :=
(Sparse.pairStepTable (fun e : BagEdge bags=>e.val.val.1) (fun e=>e.val.property)
(parallels_bound hbags hG)
(rationalSlotWeight w x) (rationalSlotWeight w y)
(rationalSlotWeight_pos w x) (rationalSlotWeight_pos w y) a).draw k
end MatchingFPRAS.Transport
namespace MatchingFPRAS.Transport
open Finset Replica Replica.Ladder Variation
variable {V L : Type*} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
variable {bags : V → Finset L}
attribute [local instance] sym2Order bagEdgeOrder bagEdgeFintype UnitRefresh.Computable.allowedDec
open Finset Replica Replica.Ladder Variation
variable {V L : Type*} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
variable {bags : V → Finset L} {G : SimpleGraph L}
attribute [local instance] sym2Order bagEdgeOrder bagEdgeFintype UnitRefresh.Computable.allowedDec
noncomputable local instance instDecidableEqBagPM_2 : DecidableEq (BagPM bags) := Classical.decEq _
attribute [local instance] prodOrder sumOrder
noncomputable local instance instDecidableEqBagPM_1_r8038f5_1 : DecidableEq (BagPM bags) := Classical.decEq _
variable (hbags : ∀ v,∀ a∈bags v,∀ b∈bags v,a=b ∨ G.Adj a b) (hG : G.IsAcyclic)
variable (rank : L → ℕ) (parent : L → Option L)
variable (hb : UnitRefresh.RankedBags bags rank parent) (hne : ∀ v,(bags v).Nonempty)
variable (hp : ∀ l p,parent l=some p → rank p < rank l)
def pairDraw {T q : ℕ} (w : BagEdge bags → ℚ) (k : ℕ) (x y : Slot T q)
(a : BagPM bags × BagPM bags) (bits : LocalBits V k) : BagPM bags × BagPM bags :=
sampleLadderPair hbags hG w x y a k bits.1
def baseDraw (M : BagPM bags) (k : ℕ) (bits : LocalBits V k) : BagPM bags :=
UnitRefresh.sampleMatching k bags rank parent hb hne hp M bits.2
def ladderScan {T q : ℕ} (hq : 0<q) (w : BagEdge bags → ℚ) (M : BagPM bags) (k : ℕ)
(s : Slot T q → BagPM bags) (bits : ScanBits V k) : Slot T q → BagPM bags :=
sampleScan guides (base T q) (base_nonempty T q hq) (pairDraw hbags hG w k)
(fun _=>baseDraw rank parent hb hne hp M k) k s bits
def scanErrorNumerator (V L : Type*) [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L] (bags : V → Finset L)
(T q : ℕ) : ℕ :=
2*(1+(T*q^2+q))+
4*(8*(Fintype.card (BagEdge bags))^2+4*Fintype.card (BagEdge bags)+3)+
2*(Fintype.card V)^2*Fintype.card L
def ladderRun {T q : ℕ} (hq : 0<q) (w : BagEdge bags → ℚ) (M : BagPM bags) (k n : ℕ)
(s : Slot T q → BagPM bags) (bits : Fin n → ScanBits V k) : Slot T q → BagPM bags :=
runSample (ladderScan hbags hG rank parent hb hne hp hq w M k) s n bits
open Finset Replica Replica.Ladder Variation
variable {V L : Type*} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
variable {bags : V → Finset L} {G : SimpleGraph L}
attribute [local instance] sym2Order bagEdgeOrder bagEdgeFintype UnitRefresh.Computable.allowedDec
noncomputable local instance instDecidableEqBagPM_3 : DecidableEq (BagPM bags) := Classical.decEq _
attribute [local instance] prodOrder sumOrder
variable (hbags : ∀ v,∀ a∈bags v,∀ b∈bags v,a=b ∨ G.Adj a b) (hG : G.IsAcyclic)
variable (rank : L → ℕ) (parent : L → Option L)
variable (hb : UnitRefresh.RankedBags bags rank parent) (hne : ∀ v,(bags v).Nonempty)
variable (hp : ∀ l p,parent l=some p → rank p < rank l)
def ladderBitRun {T q : ℕ} (hq : 0<q) (w : BagEdge bags → ℚ) (M : BagPM bags) (k n : ℕ)
(s : Slot T q → BagPM bags) (bits : Fin (n*scanBitCount (Fintype.card V) k) → Bool) :
Slot T q → BagPM bags :=
ladderRun hbags hG rank parent hb hne hp hq w M k n s (runBitsEquiv V k n bits)
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_DiscreteLadderSteps
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset Replica Replica.Ladder Variation
variable {V L : Type*} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
variable {bags : V → Finset L} {G : SimpleGraph L}
attribute [local instance] sym2Order bagEdgeOrder bagEdgeFintype UnitRefresh.Computable.allowedDec
attribute [local instance] prodOrder sumOrder
noncomputable local instance instDecidableEqBagPM_4_r8038f5_1 : DecidableEq (BagPM bags) := Classical.decEq _
variable (hbags : ∀ v,∀ a∈bags v,∀ b∈bags v,a=b ∨ G.Adj a b) (hG : G.IsAcyclic)
variable (rank : L → ℕ) (parent : L → Option L)
variable (hb : UnitRefresh.RankedBags bags rank parent) (hne : ∀ v,(bags v).Nonempty)
variable (hp : ∀ l p,parent l=some p → rank p < rank l)
def finiteLadder (D K T m : ℕ) (hq : 0<ladderQ (Fintype.card V) D)
(w : BagEdge bags → ℚ) (M : BagPM bags) (η : ℚ)
(s : Slot T (ladderQ (Fintype.card V) D) → BagPM bags) :
(Fin (discreteLadderSteps (Fintype.card V) D K T m * scanBitCount (Fintype.card V)
(bitPrecision (discreteLadderSteps (Fintype.card V) D K T m *
scanErrorNumerator V L bags T (ladderQ (Fintype.card V) D)) η)) → Bool) →
Slot T (ladderQ (Fintype.card V) D) → BagPM bags :=
ladderBitRun hbags hG rank parent hb hne hp hq w M
(bitPrecision (discreteLadderSteps (Fintype.card V) D K T m *
scanErrorNumerator V L bags T (ladderQ (Fintype.card V) D)) η)
(discreteLadderSteps (Fintype.card V) D K T m) s
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_PhysicalPost
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.PhysicalPost
open Turing PhysicalStream
variable {Γ Q R : Type} [Inhabited Γ]
def tick (M : Table Γ Q) (c : Cfg Γ Q) (b : Bool) : Cfg Γ Q :=
match c.state with
| none => c
| some q => match M q c.tape.head b with
| none => ⟨none,c.tape⟩
| some (q',a) => ⟨some q',match a with
| .move d => c.tape.move d
| .write s => c.tape.write s⟩
def execute (M : Table Γ Q) : ℕ → Cfg Γ Q → Stream → Cfg Γ Q
| 0,c,_ => c
| n+1,c,b => execute M n (tick M c (b 0)) (shift 1 b)
variable [Fintype Q] [Inhabited Q]
noncomputable def machine (M : Table Symbol Q) : RandomMachine where
states := Fintype.card Q-1
transition q a b := (M ((enumeration (Q:=Q)).symm q) a b).map
(fun qa=>(enumeration qa.1,qa.2))
noncomputable def sealCfg (M : Table Symbol Q) (c : Cfg Symbol Q) : Configuration (machine M) :=
⟨c.state.map enumeration,c.tape⟩
end MatchingFPRAS.PhysicalPost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_PhysicalRestriction
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.PhysicalPost
open Turing PhysicalStream
variable {Γ Q : Type} [Inhabited Γ]
noncomputable def restrict (M : Table Γ Q) (S : Finset Q) (_h : Supported M S) :
Table Γ {q // q∈S} := by
classical
exact fun q a b=>(M q.val a b).map (fun qa=>
((if hm:qa.1∈S then ⟨qa.1,hm⟩ else q),qa.2))
def liftCfg (S : Finset Q) (c : Cfg Γ {q // q∈S}) : Cfg Γ Q :=
⟨c.state.map Subtype.val,c.tape⟩
noncomputable def restrictedMachine (M : Table Symbol Q) (S : Finset Q)
(h : Supported M S) (q₀ : Q) (hq₀ : q₀∈S) : RandomMachine :=
letI : Inhabited {q //q∈S}:=⟨⟨q₀,hq₀⟩⟩
machine (restrict M S h)
end MatchingFPRAS.PhysicalPost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_SafeTrace
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.SafeTrace
open Turing MachineCost PhysicalStream
variable {Γ Λ σ : Type} [Inhabited Γ]
inductive Path (M : Λ → TM1.Stmt Γ Λ σ) (safe : Λ → Prop) :
ℕ → TM1.Cfg Γ Λ σ → TM1.Cfg Γ Λ σ → Prop
| refl (c) : Path M safe 0 c c
| cons {n c d} (hc : ∀ l,c.l=some l→safe l)
(rest : Path M safe n (advance (TM1.step M) c) d) : Path M safe (n+1) c d
end MatchingFPRAS.SafeTrace
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_PhysicalProcess
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.PhysicalPost
open Turing PhysicalStream
variable {Γ Q α β : Type} [Inhabited Γ]
inductive Implements (M : Table Γ Q) (out : α → Cfg Γ Q) :
Cfg Γ Q → Experiment α → Prop
| done (a) : Implements M out (out a) (.done a)
| read (c) (f : Bool → Experiment α)
(h : ∀ b,Implements M out (tick M c b) (f b)) : Implements M out c (.read f)
| delay (c d) (n : ℕ) (p : Experiment α)
(step : ∀ b : Stream,execute M n c b=d)
(rest : Implements M out d p) : Implements M out c (.delay n p)
end MatchingFPRAS.PhysicalPost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_PhysicalAlphabet
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.PhysicalPost
open Turing PhysicalStream BoolPostCompiler
variable {Q : Type}
def liftBool (M : Table Bool Q) : Table Symbol Q := fun q a b=>
(M q (down a) b).map (fun qa=>(qa.1,qa.2.map up))
def upCfg (c : Cfg Bool Q) : Cfg Symbol Q := ⟨c.state,c.tape.map up⟩
lemma liftBool_supported (M : Table Bool Q) (S : Finset Q) (hS : Supported M S) :
Supported (liftBool M) S := by
intro q hq a b q' act he
simp only [liftBool,Option.map_eq_some_iff] at he
obtain ⟨⟨q'',act'⟩,h,e⟩:=he
have hqq : q''=q':=congrArg Prod.fst e
subst q''
exact hS q hq (down a) b q' act' h
end MatchingFPRAS.PhysicalPost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_OnlineStackCompiler
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineStack
open Turing MachineCost PhysicalStream SafeTrace
open scoped Classical
variable {K Λ σ : Type} {Γ : K → Type} [DecidableEq K] [Fintype K]
[∀ k,Fintype (Γ k)] [Inhabited Λ] [Fintype Λ] [Inhabited σ] [Fintype σ]
abbrev Q (K : Type) (Γ : K → Type) (Λ σ : Type) := CoinTM1.State Bool (L2 K Γ Λ σ) σ
variable (M : Λ → TM2.Stmt Γ Λ σ) (coin : CoinTM1.Coins Λ)
noncomputable def coin2 := CoinAlphabet.coins (Γ:=Alpha K Γ) (σ:=σ) (CoinStack.coins (Γ:=Γ) (σ:=σ) coin)
noncomputable def table := CoinTM1.table (program2 M) (coin2 coin)
noncomputable def states := CoinTM1.states (program2 M) (support2 M)
omit [Inhabited Λ] [Inhabited σ] [Fintype σ] in
lemma coin2_supported [Inhabited Λ] [Inhabited σ] [Fintype σ] :
∀ l∈support2 M,∀ f,coin2 coin l=some f→∀ b,f b∈support2 M :=
CoinAlphabet.coins_supported (program1 M) (support1 M) _
(CoinStack.coins_supported M Finset.univ coin (fun _ _ _ _ _=>Finset.mem_univ _))
lemma table_supported : PhysicalPost.Supported (table M coin) (states M) :=
CoinTM1.table_supported (program2 M) (support2 M) (supports2 M) (coin2 coin) (coin2_supported M coin)
noncomputable def cfg (c : TM2.Cfg Γ Λ σ) : PhysicalPost.Cfg Bool (Q K Γ Λ σ) :=
CoinTM1.trCfg (TM1to1.trCfg enc enc0 (stackCfg c))
noncomputable def overhead : ℕ :=
(AlphabetCost.supportedWrites (program1 M) (support1 M)+1)*
SupportedCompiler.cost (program2 M) (support2 M)
noncomputable def initialState : Q K Γ Λ σ :=
(.inl (.normal (.normal default)),default)
lemma initialState_mem : initialState (K:=K) (Γ:=Γ) (Λ:=Λ) (σ:=σ)∈states M := by
apply CoinTM1.state_mem
apply CoinTM1.node_entry
apply (CoinAlphabet.normal_mem _ _ _).mpr
exact (CoinStack.normal_mem M Finset.univ default).mpr (Finset.mem_univ default)
end MatchingFPRAS.OnlineStack
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_Online
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineStack
open Turing MachineCost PhysicalStream
variable {K Λ σ α : Type} {Γ : K → Type} [DecidableEq K]
inductive Executes (M : Λ → TM2.Stmt Γ Λ σ) (coin : CoinTM1.Coins Λ)
(out : α → TM2.Cfg Γ Λ σ) : TM2.Cfg Γ Λ σ → Experiment α → Prop
| done (a) : Executes M coin out (out a) (.done a)
| read (l v S) (f : Bool → Λ) (p : Bool → Experiment α)
(hf : coin l=some f)
(rest : ∀ b,Executes M coin out ⟨some (f b),v,S⟩ (p b)) :
Executes M coin out ⟨some l,v,S⟩ (.read p)
| step (l v S) (p : Experiment α) (safe : coin l=none)
(rest : Executes M coin out (TM2.stepAux (M l) v S) p) :
Executes M coin out ⟨some l,v,S⟩ (.delay 1 p)
namespace Executes
variable {M : Λ → TM2.Stmt Γ Λ σ} {coin : CoinTM1.Coins Λ}
{out : α → TM2.Cfg Γ Λ σ} {c : TM2.Cfg Γ Λ σ} {p : Experiment α}
lemma bind {β : Type} (h : Executes M coin out c p) (q : α → Experiment β)
(out' : β → TM2.Cfg Γ Λ σ) (hq : ∀ a,Executes M coin out' (out a) (q a)) :
Executes M coin out' c (p.bind q) := by
induction h with
| done a => exact hq a
| read l v S f p hf rest ih => exact .read l v S f _ hf ih
| step l v S p safe rest ih => exact .step l v S _ safe ih
variable [Fintype K] [∀ k,Fintype (Γ k)] [Inhabited Λ] [Fintype Λ]
[Inhabited σ] [Fintype σ]
noncomputable def factor (M : Λ → TM2.Stmt Γ Λ σ) (H n : ℕ) : ℕ :=
overhead M*(1+2*accesses M*(H+n*accesses M+1))+1
end Executes
end MatchingFPRAS.OnlineStack
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_OnlineComposition
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineStack
open Turing MachineCost PhysicalStream StackComposition
variable {K Λ Λ' σ α : Type} {Γ : K → Type} [DecidableEq K]
namespace Executes
lemma relabel {M : Λ → TM2.Stmt Γ Λ σ} {coin : CoinTM1.Coins Λ}
{out : α → TM2.Cfg Γ Λ σ} {c : TM2.Cfg Γ Λ σ} {p : Experiment α}
(h : Executes M coin out c p) (N : Λ' → TM2.Stmt Γ Λ' σ)
(co : CoinTM1.Coins Λ') (f : Λ → Λ') (halt : Option Λ')
(hN : ∀ l,N (f l)=StackComposition.relabel f halt (M l))
(hco : ∀ l,co (f l)=(coin l).map (fun g=>f ∘ g)) :
Executes N co (fun a=>mapCfg f halt (out a)) (mapCfg f halt c) p := by
induction h with
| done a => exact .done a
| read l v S g p hg rest ih =>
apply Executes.read (f l) v S (f ∘ g) p
· rw [hco,hg]; rfl
· exact ih
| step l v S p hs rest ih =>
apply Executes.step (f l) v S p
· rw [hco,hs]; rfl
· rw [hN,StackComposition.relabel_eval]
exact ih
lemma of_run (M : Λ → TM2.Stmt Γ Λ σ) (n : ℕ) (c : TM2.Cfg Γ Λ σ)
(v : σ) (S : ∀ k,List (Γ k)) (he : MachineCost.run (TM2.step M) n c=⟨none,v,S⟩) :
∃ p : Experiment Unit,Executes M (fun _=>none) (fun _ : Unit=>⟨none,v,S⟩) c p ∧
(∀ f : Unit → ℚ,p.mean f=f ()) ∧ p.cost≤n := by
induction n generalizing c with
| zero => cases he; exact ⟨.done (),.done (),fun _=>rfl,le_rfl⟩
| succ n ih =>
rcases c with ⟨l,v',S'⟩
cases l with
| none =>
rw [StackComposition.run_halted] at he
cases he
exact ⟨.done (),.done (),fun _=>rfl,Nat.zero_le _⟩
| some l =>
obtain ⟨p,hp,hm,hc⟩:=ih (TM2.stepAux (M l) v' S') he
exact ⟨.delay 1 p,.step l v' S' p rfl hp,hm,by simpa [Experiment.cost,Nat.add_comm] using Nat.succ_le_succ hc⟩
end Executes
end MatchingFPRAS.OnlineStack
namespace MatchingFPRAS.OnlineProc
open Turing MachineCost PhysicalStream OnlineStack RegisterProc
variable {K : Type} [DecidableEq K]
structure Proc (K : Type) extends RegisterProc.Proc K where
coin : CoinTM1.Coins Label
def deterministic (P : RegisterProc.Proc K) : Proc K := ⟨P,fun _=>none⟩
def seq (P Q : Proc K) : Proc K where
toProc := RegisterProc.seq P.toProc Q.toProc
coin := fun l=>match l with
| .inl l => (P.coin l).map (fun f b=>Sum.inl (f b))
| .inr l => (Q.coin l).map (fun f b=>Sum.inr (f b))
end MatchingFPRAS.OnlineProc
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_OnlineControl
attribute [-instance] _root_.OAI.MatchingFPRAS.TreeTyped.instCodecData
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineControl
open TreeData TreeMachine RegisterProc Turing MachineCost PhysicalStream OnlineStack
variable {R Λ α : Type} [DecidableEq R]
inductive Instr (R Λ : Type) where
| halt
| go (next : Λ)
| branch (i : R) (nil cons : Λ)
| call (P : OnlineProc.Proc (K R)) (next : Λ)
def procedure : Instr R Λ → OnlineProc.Proc (K R)
| .call P _ => P
| _ => OnlineProc.deterministic (atom .halt)
def successor : Instr R Λ → Option Λ
| .call _ l => some l
| _ => none
abbrev Label (M : Λ → Instr R Λ) := Λ ⊕ ((l : Λ) × (procedure (M l)).Label)
instance instFintypeLabel (M : Λ → Instr R Λ) [Fintype Λ] : Fintype (Label M) := by unfold Label; infer_instance
def code (M : Λ → Instr R Λ) : Label M → TM2.Stmt (fun _ : K R=>Bool) (Label M) Store
| .inl l => match M l with
| .halt => .halt
| .go k => .goto (fun _=>.inl k)
| .branch i a b => .peek (.inl i) (fun _ x=>x) (.branch (fun x=>x.getD false)
(.load (fun _=>none) (.goto (fun _=>.inl b)))
(.load (fun _=>none) (.goto (fun _=>.inl a))))
| .call _ _ => .goto (fun _=>.inr ⟨l,default⟩)
| .inr ⟨l,u⟩ => StackComposition.relabel (fun u=>.inr ⟨l,u⟩)
((successor (M l)).map Sum.inl) ((procedure (M l)).code u)
def coins (M : Λ → Instr R Λ) : CoinTM1.Coins (Label M)
| .inl _ => none
| .inr ⟨l,u⟩ => ((procedure (M l)).coin u).map (fun g b=>.inr ⟨l,g b⟩)
def compile [Fintype Λ] [Inhabited Λ] (M : Λ → Instr R Λ) : OnlineProc.Proc (K R) :=
{ toProc := { Label := Label M, entry := ⟨.inl default⟩, code := code M }, coin := coins M }
def cfg (M : Λ → Instr R Λ) (l : Option Λ) (E : Env R) : TM2.Cfg (fun _ : K R=>Bool) (Label M) Store :=
⟨l.map Sum.inl,none,encodeEnv E⟩
def At (M : Λ → Instr R Λ) (out : α → Env R) (l : Option Λ) (E : Env R) (p : Experiment α) : Prop :=
Executes (code M) (coins M) (fun a=>cfg M none (out a)) (cfg M l E) p
lemma done (M : Λ → Instr R Λ) (out : α → Env R) (a : α) :
At M out none (out a) (.done a) := .done a
lemma halt (M : Λ → Instr R Λ) (out : α → Env R) (l : Λ) (h : M l=.halt) (a : α) :
At M out (some l) (out a) (.delay 1 (.done a)) := by
apply Executes.step _ _ _ _ rfl
simpa only [At,code,h,TM2.stepAux,cfg,Option.map_none] using done M out a
lemma nilBranch (M : Λ → Instr R Λ) (out : α → Env R) (l a b : Λ) (i : R)
(h : M l=.branch i a b) (E : Env R) (hi : E i=.nil)
(p : Experiment α) (hp : At M out (some a) E p) :
At M out (some l) E (.delay 1 p) := by
apply Executes.step _ _ _ _ rfl
simpa only [At,code,h,TM2.stepAux,encodeEnv,hi,encode,List.head?_cons,Option.getD_some,Bool.cond_false,
cfg,Option.map_some] using hp
lemma consBranch (M : Λ → Instr R Λ) (out : α → Env R) (l a b : Λ) (i : R)
(h : M l=.branch i a b) (E : Env R) (x y : Data) (hi : E i=.cons x y)
(p : Experiment α) (hp : At M out (some b) E p) :
At M out (some l) E (.delay 1 p) := by
apply Executes.step _ _ _ _ rfl
simpa only [At,code,h,TM2.stepAux,encodeEnv,hi,encode,List.head?_cons,Option.getD_some,Bool.cond_true,
cfg,Option.map_some] using hp
lemma call {β : Type} (M : Λ → Instr R Λ) (out : α → Env R) (l next : Λ)
(P : OnlineProc.Proc (K R)) (h : M l=.call P next)
(E : Env R) (F : β → Env R) (q : Experiment β)
(hq : Executes P.code P.coin (fun b=>⟨none,none,encodeEnv (F b)⟩)
⟨some default,none,encodeEnv E⟩ q)
(p : β → Experiment α) (hp : ∀ b,At M out (some next) (F b) (p b)) :
At M out (some l) E (.delay 1 (q.bind p)) := by
have hq' : Executes (procedure (M l)).code (procedure (M l)).coin
(fun b=>⟨none,none,encodeEnv (F b)⟩) ⟨some default,none,encodeEnv E⟩ q := by
rw [show procedure (M l)=P by rw [h]; rfl]
exact hq
have hh := hq'.relabel (code M) (coins M) (fun u=>Sum.inr ⟨l,u⟩)
((successor (M l)).map Sum.inl) (fun _=>rfl) (fun _=>rfl)
apply Executes.step _ _ _ _ rfl
have hb := hh.bind p (fun a=>cfg M none (out a)) (fun b=>by
simpa only [At,cfg,Option.map_none,StackComposition.mapCfg_none,h,successor,Option.map_some] using hp b)
simpa only [code,h,TM2.stepAux,StackComposition.mapCfg_some] using hb
lemma deterministicCall (M : Λ → Instr R Λ) (out : α → Env R) (l next : Λ)
(P : RegisterProc.Proc (K R)) (h : M l=.call (OnlineProc.deterministic P) next)
(E F : Env R) (n : ℕ) (he : RegisterProc.Exec P (encodeEnv E) (encodeEnv F) n)
(p : Experiment α) (hp : At M out (some next) F p) :
∃ q,At M out (some l) E q ∧ (∀ f : α → ℚ,q.mean f=p.mean f) ∧ q.cost ≤ n+1+p.cost := by
obtain ⟨k,hk,he⟩:=he
obtain ⟨r,hr,hm,hc⟩:=Executes.of_run P.code k _ _ _ he
refine ⟨.delay 1 (r.bind (fun _=>p)),call M out l next (OnlineProc.deterministic P) h E (fun _ : Unit=>F)
r hr (fun _=>p) (fun _=>hp),?_,?_⟩
· intro f
simpa only [Experiment.mean,Experiment.mean_bind] using hm (fun _=>p.mean f)
· have hh:=Experiment.cost_bind_le r (fun _=>p) p.cost (fun _=>le_rfl)
simp only [Experiment.cost]
omega
end MatchingFPRAS.OnlineControl
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_OnlineTree
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineTree
open Turing MachineCost PhysicalStream OnlineStack TreeData TreeMachine TreeFunction TreeTyped
abbrev StoreCfg (P : OnlineProc.Proc (K Reg)) := TM2.Cfg (fun _ : K Reg=>Bool) P.Label RegisterProc.Store
variable {A B C : Type} [Codec A] [Codec B] [Codec C]
def chooseProgram (P Q : OnlineProc.Proc (K Reg)) : OnlineProc.Proc (K Reg) where
toProc := {
Label := Unit ⊕ (P.Label ⊕ Q.Label)
entry := ⟨.inl ()⟩
code := fun l=>match l with
| .inl _ => .halt
| .inr (.inl l) => StackComposition.relabel (fun u=>Sum.inr (Sum.inl u)) none (P.code l)
| .inr (.inr l) => StackComposition.relabel (fun u=>Sum.inr (Sum.inr u)) none (Q.code l) }
coin := fun l=>match l with
| .inl _ => some (fun b=>if b then .inr (.inr default) else .inr (.inl default))
| .inr (.inl l) => (P.coin l).map (fun f b=>.inr (.inl (f b)))
| .inr (.inr l) => (Q.coin l).map (fun f b=>.inr (.inr (f b)))
end MatchingFPRAS.OnlineTree
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_OnlineFold
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineTree
open TreeData TreeMachine RegisterProc TreeFunction TreeTyped
open Turing MachineCost PhysicalStream OnlineStack
variable {A B : Type} [Codec A] [Codec B]
namespace Fold
open OnlineControl
open TreeTyped.Fold (Point)
def code (P : OnlineProc.Proc (K Reg)) : Point → OnlineControl.Instr Reg Point
| .loop => .call (OnlineProc.deterministic (TreeFunction.split 1 0 (by decide))) .check
| .check => .branch 1 .halt .splitHead
| .splitHead => .call (OnlineProc.deterministic (TreeFunction.split 3 1 (by decide))) .pushTail
| .pushTail => .call (OnlineProc.deterministic (TreeFunction.cons 1 2 (by decide))) .pushArgs
| .pushArgs => .call (OnlineProc.deterministic (TreeFunction.cons 3 0 (by decide))) .body
| .body => .call P .popTail
| .popTail => .call (OnlineProc.deterministic (TreeFunction.split 1 2 (by decide))) .rebuild
| .rebuild => .call (OnlineProc.deterministic (TreeFunction.cons 1 0 (by decide))) .loop
| .halt => .halt
end Fold
end MatchingFPRAS.OnlineTree
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_OnlineFrame
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineTree
open TreeData TreeMachine RegisterProc TreeFunction TreeTyped
open Turing MachineCost PhysicalStream OnlineStack
variable {A B C D : Type} [Codec A] [Codec B] [Codec C] [Codec D]
namespace Second
open OnlineControl
def code (P : OnlineProc.Proc (K Reg)) : Point → OnlineControl.Instr Reg Point
| .split => .call (OnlineProc.deterministic (TreeFunction.split 1 0 (by decide))) .save
| .save => .call (OnlineProc.deterministic (TreeFunction.cons 1 2 (by decide))) .body
| .body => .call P .pop
| .pop => .call (OnlineProc.deterministic (TreeFunction.split 1 2 (by decide))) .cons
| .cons => .call (OnlineProc.deterministic (TreeFunction.cons 1 0 (by decide))) .halt
| .halt => .halt
end Second
end MatchingFPRAS.OnlineTree
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_Related2
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.NumberedHierarchy
open Finset
variable {V : Type*} [Fintype V] [LinearOrder V]
variable (B : V → V → ℚ)
variable (hsym : ∀ x y,B x y=B y x)
variable (htri : ∀ x y z,x≠y → x≠z → y≠z → min (B x z) (B z y)≤B x y)
lemma level_cast (H : ℕ) (x : ℚ) : level H x=Hierarchy.dyadicLevel H (x:ℝ) := by
apply Fin.ext
change Nat.findGreatest (fun k => (2:ℚ)^k≤x) H = Nat.findGreatest (fun k => (2:ℝ)^k≤(x:ℝ)) H
have h : (fun k => (2:ℚ)^k≤x) = (fun k => (2:ℝ)^k≤(x:ℝ)) := by
funext k
apply propext
norm_cast
simp only [h]
end MatchingFPRAS.NumberedHierarchy
namespace MatchingFPRAS.RationalSource
open MatchingFPRAS Switching Subdivision RealGeometry Enlargement Finset
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
def logicalB (w : V → V → ℚ) : V → V → ℚ :=
BottleneckAlgorithm.close w (Fintype.card V)
omit [Nontrivial V] in
lemma logicalB_cast [Nontrivial V] (w : V → V → ℚ) (x y : V) :
(logicalB w x y:ℝ)=bottleneck (fun x y=>(w x y:ℝ)) x y :=
BottleneckAlgorithm.rational_close_eq w x y
def height (w : V → V → ℚ) (x : V) : ℚ :=
(univ.erase x).sup' (row_nonempty x) (logicalB w x)
lemma height_cast (w : V → V → ℚ) (x : V) :
(height w x:ℝ)=sourceHeight (fun x y=>(w x y:ℝ)) x := by
unfold height sourceHeight
rw [Finset.apply_sup'_eq_sup'_comp _ (fun x:ℚ=>(x:ℝ)) (by intro x y; exact Rat.cast_max x y)]
apply Finset.sup'_congr _ rfl
intro y _
exact logicalB_cast w x y
def maxHeight (w : V → V → ℚ) : ℚ := univ.sup' univ_nonempty (height w)
lemma maxHeight_cast (w : V → V → ℚ) :
(maxHeight w:ℝ)=maxSourceHeight (fun x y=>(w x y:ℝ)) := by
unfold maxHeight maxSourceHeight
rw [Finset.apply_sup'_eq_sup'_comp _ (fun x:ℚ=>(x:ℝ)) (by intro x y; exact Rat.cast_max x y)]
apply Finset.sup'_congr _ rfl
intro x _
exact height_cast w x
def levels (w : V → V → ℚ) (K : ℕ) : ℕ :=
(NumberedHierarchy.level (2*K) (maxHeight w)).val
lemma levels_eq (w : V → V → ℚ) (K : ℕ) :
levels w K=sourceLevels (fun x y=>(w x y:ℝ)) K := by
simp only [levels,NumberedHierarchy.level_cast,maxHeight_cast,sourceLevels]
lemma profile_cast (p : ℕ) (B Hu Hv lam : ℚ) (i : Fin (4*p+1)) :
(profile p B Hu Hv lam i:ℝ)=profileActivity p B Hu Hv lam i := by
rcases lt_trichotomy i.val (2*p) with h|h|h
· rw [profile,ite_eq_left h,profile_left _ _ _ _ _ _ h]
norm_cast
· have he : i=⟨2*p,by omega⟩:=Fin.ext h
rw [he]
simp [profile]
· rw [profile,ite_eq_right (by omega),ite_eq_right (by omega),profile_right _ _ _ _ _ _ h]
norm_cast
def pathActivity (w : V → V → ℚ) (K : ℕ) (e : LogicalEdge V) : Fin (4*(2*K+2)+1) → ℚ :=
profile (2*K+2) (logicalB w (source e) (target e)) (height w (source e))
(height w (target e)) (BottleneckAlgorithm.edge w (source e) (target e))
lemma pathActivity_cast (w : V → V → ℚ) (K : ℕ) (e : LogicalEdge V) (i : Fin (4*(2*K+2)+1)) :
(pathActivity w K e i:ℝ) = Enlargement.pathActivity (2*K+2)
(fun e=>bottleneck (fun x y=>(w x y:ℝ)) (source e) (target e))
(fun e=>sourceHeight (fun x y=>(w x y:ℝ)) (source e))
(fun e=>sourceHeight (fun x y=>(w x y:ℝ)) (target e))
(logicalActivity (fun x y=>(w x y:ℝ))) e i := by
rw [pathActivity,profile_cast,logicalB_cast,height_cast,height_cast]
congr 1
have he : source e<target e:=e.property
simp [BottleneckAlgorithm.edge,logicalActivity,edgeActivity,he]
def activity (w : V → V → ℚ) (K : ℕ) (x y : SourceVertex V K) : ℚ :=
∑ q : SourceRealEdge V K,
if RealGeometry.edge source target (4*(2*K+2)) q.1 q.2=s(x,y)
then pathActivity w K q.1 q.2 else 0
lemma activity_cast (w : V → V → ℚ) (K : ℕ) (x y : SourceVertex V K) :
(activity w K x y:ℝ)=RealGeometry.activity source target (4*(2*K+2))
(Enlargement.pathActivity (2*K+2)
(fun e=>bottleneck (fun x y=>(w x y:ℝ)) (source e) (target e))
(fun e=>sourceHeight (fun x y=>(w x y:ℝ)) (source e))
(fun e=>sourceHeight (fun x y=>(w x y:ℝ)) (target e))
(logicalActivity (fun x y=>(w x y:ℝ)))) x y := by
unfold activity RealGeometry.activity
push_cast
apply sum_congr rfl
intro q _
split_ifs
· exact pathActivity_cast w K q.1 q.2
· norm_cast
def realB (w : V → V → ℚ) (K : ℕ) : SourceVertex V K → SourceVertex V K → ℚ :=
BottleneckAlgorithm.close (activity w K) (Fintype.card (SourceVertex V K))
lemma realB_cast (w : V → V → ℚ) (K : ℕ) (x y : SourceVertex V K) :
(realB w K x y:ℝ)=sourceRealB (fun x y=>(w x y:ℝ)) K x y := by
rw [realB,BottleneckAlgorithm.rational_close_eq]
unfold sourceRealB realBottleneck
congr 2
funext a b
exact activity_cast w K a b
lemma realB_symm (w : V → V → ℚ) (K : ℕ) (x y : SourceVertex V K) :
realB w K x y=realB w K y x := by
apply Rat.cast_injective (α:=ℝ)
simp only [realB_cast,sourceRealB_comm]
lemma realB_tri (w : V → V → ℚ) (K : ℕ) (x y z : SourceVertex V K)
(hxy : x≠y) (hxz : x≠z) (hyz : y≠z) :
min (realB w K x z) (realB w K z y) ≤ realB w K x y := by
apply (Rat.cast_le (K:=ℝ)).mp
simp only [Rat.cast_min,realB_cast]
exact sourceRealB_tri _ _ _ _ _ hxy hxz hyz
abbrev Label (w : V → V → ℚ) (K : ℕ) := NumberedHierarchy.Label (realB w K) (levels w K)
theorem label_card (w : V → V → ℚ) (K : ℕ) :
Fintype.card (Label w K)≤(2*K+1)*Fintype.card (SourceVertex V K) := by
calc
_ ≤ (levels w K+1)*Fintype.card (SourceVertex V K) := by
rw [Fintype.card_sigma]
calc
_ ≤ ∑ k : Fin (levels w K+1),Fintype.card (SourceVertex V K) :=
sum_le_sum (fun k _=>Fintype.card_subtype_le _)
_ = _ := by simp
_ ≤ _ := by
apply Nat.mul_le_mul_right
rw [levels_eq]
exact Nat.add_le_add_right (sourceLevels_le _ _) 1
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_LabelOrder
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open Finset MatchingFPRAS.Switching MatchingFPRAS.Subdivision MatchingFPRAS.RealGeometry
open MatchingFPRAS.Hierarchy MatchingFPRAS.Transport MatchingFPRAS.Enlargement
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec
omit [Fintype V] [Nontrivial V] in
lemma raw_cast [Fintype V] [Nontrivial V] (w : V → V → ℚ) (K : ℕ)
(h : ∀ x y,x≠y → BottleneckAlgorithm.edge w x y≤(4:ℚ)^K) :
∀ x y,x≠y → edgeActivity (fun x y=>(w x y:ℝ)) x y≤(4:ℝ)^K := by
intro x y hxy
have he : ((BottleneckAlgorithm.edge w x y:ℚ):ℝ)=edgeActivity (fun x y=>(w x y:ℝ)) x y := by
unfold BottleneckAlgorithm.edge edgeActivity
split_ifs <;> rfl
simpa only [he,Rat.cast_pow,Rat.cast_ofNat] using (Rat.cast_le (K:=ℝ)).mpr (h x y hxy)
lemma realB_floor (w : V → V → ℚ) (K : ℕ) (x y : SourceVertex V K) : 1 ≤ realB w K x y := by
apply (Rat.cast_le (K:=ℝ)).mp
simpa only [Rat.cast_one,realB_cast] using sourceRealB_floor (fun x y=>(w x y:ℝ)) K x y
lemma realB_upper (w : V → V → ℚ) (K : ℕ)
(h : ∀ x y,x≠y → BottleneckAlgorithm.edge w x y≤(4:ℚ)^K) (e : SourceRealEdge V K) :
realB w K (realLeft K e) (realRight K e)<(2:ℚ)^(levels w K+1) := by
apply (Rat.cast_lt (K:=ℝ)).mp
simpa only [realB_cast,levels_eq,Rat.cast_pow,Rat.cast_ofNat] using
(source_strength_le_max (fun x y=>(w x y:ℝ)) K (raw_cast w K h) e).trans_lt
(maxSourceHeight_lt (fun x y=>(w x y:ℝ)) K (raw_cast w K h))
lemma realB_near (w : V → V → ℚ) (K : ℕ)
(h : ∀ x y,x≠y → BottleneckAlgorithm.edge w x y≤(4:ℚ)^K)
(x : SourceVertex V K) (e f : SourceRealEdge V K)
(he : Hierarchy.Incident (realLeft K) (realRight K) e x)
(hf : Hierarchy.Incident (realLeft K) (realRight K) f x) :
realB w K (realLeft K e) (realRight K e)≤2*realB w K (realLeft K f) (realRight K f) := by
apply (Rat.cast_le (K:=ℝ)).mp
simpa only [realB_cast,Rat.cast_mul,Rat.cast_ofNat] using
source_strength_incident_near (fun x y=>(w x y:ℝ)) K (raw_cast w K h) x e f he hf
omit [Fintype V] in
lemma incident_exists [Fintype V] (K : ℕ) (x : SourceVertex V K) :
∃ e,Hierarchy.Incident (realLeft K) (realRight K) e x := by
cases x with
| inl x =>
obtain ⟨y,hy⟩ := exists_ne x
rcases lt_or_gt_of_ne hy with h | h
· let e : LogicalEdge V := ⟨(y,x),h⟩
refine ⟨(e,Fin.last (4*(2*K+2))),Or.inr ?_⟩
simp [realRight,atVertex_last,target,e]
· let e : LogicalEdge V := ⟨(x,y),h⟩
refine ⟨(e,0),Or.inl ?_⟩
simp [realLeft,atVertex_zero,source,e]
| inr q =>
obtain ⟨e,i⟩ := q
refine ⟨(e,i.castSucc),Or.inr ?_⟩
change Sum.inr (e,i)=atVertex source target _ e i.castSucc.succ
have he : i.castSucc.succ=i.succ.castSucc := Fin.ext rfl
rw [he,atVertex_internal]
omit [Nontrivial V] in
lemma real_not_diag [Nontrivial V] (K : ℕ) (e : SourceRealEdge V K) :
¬(edge source target (4*(2*K+2)) e.1 e.2).IsDiag := by
rw [edge,Sym2.mk_isDiag_iff]
intro he
have hi := atVertex_injective source target (4*(2*K+2)) e.1 (source_ne_target e.1) he
have := congrArg Fin.val hi
simp at this
lemma pathActivity_pos (w : V → V → ℚ) (hw : ∀ x y,0<w x y) (K : ℕ)
(e : LogicalEdge V) (i : Fin (4*(2*K+2)+1)) : 0<pathActivity w K e i := by
have hb : 0<logicalB w (source e) (target e) := by
have h : (1:ℝ)≤(logicalB w (source e) (target e):ℝ) := by
rw [logicalB_cast]; exact one_le_bottleneck _ _ _
have : (1:ℚ)≤logicalB w (source e) (target e) := by exact_mod_cast h
linarith
unfold pathActivity profile
split_ifs
· exact hb.trans_le (le_max_left _ _)
· unfold BottleneckAlgorithm.edge
split_ifs <;> exact hw _ _
· exact hb.trans_le (le_max_left _ _)
def bagHeight (w : V → V → ℚ) (K : ℕ) (l : Label w K) : ℚ := 2^l.1.val
lemma bagHeight_one (w : V → V → ℚ) (K : ℕ) (l : Label w K) : 1≤bagHeight w K l := by
exact one_le_pow₀ (by norm_num)
open MatchingFPRAS.Replica MatchingFPRAS.Replica.Ladder MatchingFPRAS.Variation
attribute [local instance] prodOrder sumOrder
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Relabel
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset
variable {V L J : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
[Fintype J] [DecidableEq J]
variable {b : V → Finset L} {c : V → Finset J}
def relabelEdge (e : L ≃ J) (h : ∀ v,(b v).image e=c v) (a : BagEdge b) : BagEdge c :=
⟨⟨(a.val.val.1,e a.val.val.2),a.val.property⟩,by
intro v hv
change e a.val.val.2∈c v
rw [←h v]
exact mem_image.mpr ⟨a.val.val.2,a.property v hv,rfl⟩⟩
def relabelEdgeEquiv (e : L ≃ J) (h : ∀ v,(b v).image e=c v) : BagEdge b ≃ BagEdge c where
toFun:=relabelEdge e h
invFun:=relabelEdge e.symm (image_symm_bags e h)
left_inv a := by apply Subtype.ext; apply Subtype.ext; simp [relabelEdge]
right_inv a := by apply Subtype.ext; apply Subtype.ext; simp [relabelEdge]
variable {E F : Type*} [Fintype E] [DecidableEq E] [Fintype F] [DecidableEq F]
variable {inc : E → V → Prop} {j : F → V → Prop}
omit [Fintype V] [DecidableEq V] [Fintype E] [DecidableEq E] [Fintype F] in
lemma MatchingOn.image (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v)
{M : Finset E} {U : Finset V} (hM : MatchingOn inc M U) :
MatchingOn j (M.image e) U := by
constructor
· intro f hf v hv
obtain ⟨a,ha,rfl⟩:=mem_image.mp hf
exact hM.1 a ha v ((he a v).mp hv)
· intro v hv
obtain ⟨a,⟨ha,hav⟩,hu⟩:=hM.2 v hv
refine ⟨e a,⟨mem_image.mpr ⟨a,ha,rfl⟩,(he a v).mpr hav⟩,?_⟩
rintro f ⟨hf,hfv⟩
obtain ⟨d,hd,rfl⟩:=mem_image.mp hf
exact congrArg e (hu d ⟨hd,(he d v).mp hfv⟩)
def pmEquiv (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v) : PM inc ≃ PM j where
toFun M:=⟨M.val.image e,M.property.image e he⟩
invFun M:=⟨M.val.image e.symm,M.property.image e.symm (by intro a v; simpa using (he (e.symm a) v).symm)⟩
left_inv M:=by apply Subtype.ext; simp [image_image]
right_inv M:=by apply Subtype.ext; simp [image_image]
omit [DecidableEq V] [Fintype E] [Fintype F] in
lemma matchingWeight_pmEquiv [DecidableEq V] [Fintype E] [Fintype F]
(e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v)
(w : F → ℝ) (M : PM inc) : matchingWeight w (pmEquiv e he M)=matchingWeight (w ∘ e) M := by
unfold matchingWeight pmEquiv
exact Finset.prod_image (fun _ _ _ _ h=>e.injective h)
end MatchingFPRAS.Transport
namespace MatchingFPRAS.RationalSource
open MatchingFPRAS Switching Subdivision RealGeometry Hierarchy Enlargement Transport Finset
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance instDecidableEqLabelOfFintype {X : Type*} [Fintype X] (B : X → X → ℝ)
(s : ∀ x y,B x y=B y x)
(t : ∀ x y z,x≠y → x≠z → y≠z → min (B x z) (B z y)≤B x y) (H : ℕ) :
DecidableEq (Hierarchy.Label B s t H) := Classical.decEq _
noncomputable def labelCast {X : Type*} [Fintype X] {B B' : X → X → ℝ}
(s : ∀ x y,B x y=B y x)
(t : ∀ x y z,x≠y → x≠z → y≠z → min (B x z) (B z y)≤B x y)
(s' : ∀ x y,B' x y=B' y x)
(t' : ∀ x y z,x≠y → x≠z → y≠z → min (B' x z) (B' z y)≤B' x y)
{H H' : ℕ} (hB : B=B') (hH : H=H') :
Hierarchy.Label B s t H ≃ Hierarchy.Label B' s' t' H' :=
Equiv.cast (by cases hB;cases hH;rfl)
lemma labelCast_bags {X E : Type*} [Fintype X] [DecidableEq X] [Fintype E]
{B B' : X → X → ℝ}
(s : ∀ x y,B x y=B y x)
(t : ∀ x y z,x≠y → x≠z → y≠z → min (B x z) (B z y)≤B x y)
(s' : ∀ x y,B' x y=B' y x)
(t' : ∀ x y z,x≠y → x≠z → y≠z → min (B' x z) (B' z y)≤B' x y)
(u v : E → X) {H H' : ℕ} (hB : B=B') (hH : H=H') (x : X) :
(memberships B s t u v H x).image (labelCast s t s' t' hB hH)=
memberships B' s' t' u v H' x := by
classical
cases hB;cases hH
simp [labelCast]
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_RelabelMore
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open MatchingFPRAS Switching Subdivision RealGeometry Hierarchy Enlargement Transport Finset
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
lemma labelCast_edgeLabel {X E : Type*} [Fintype X] [DecidableEq X] [Fintype E]
{B B' : X → X → ℝ}
(s : ∀ x y,B x y=B y x)
(t : ∀ x y z,x≠y → x≠z → y≠z → min (B x z) (B z y)≤B x y)
(s' : ∀ x y,B' x y=B' y x)
(t' : ∀ x y z,x≠y → x≠z → y≠z → min (B' x z) (B' z y)≤B' x y)
(u v : E → X) {H H' : ℕ} (hB : B=B') (hH : H=H') (e : E) :
labelCast s t s' t' hB hH (Hierarchy.edgeLabel B s t u v H e)=
Hierarchy.edgeLabel B' s' t' u v H' e := by
cases hB;cases hH;rfl
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_RelabelWeights
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open MatchingFPRAS Transport Enlargement Finset
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance instDecidableEqSourceLabelCastReal (w : V → V → ℚ) (K : ℕ) :
DecidableEq (SourceLabel (fun x y=>(w x y:ℝ)) K) := Classical.decEq _
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_RatWeight
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.StageAnalysis
open Finset MatchingFPRAS.Switching MatchingFPRAS.Initializer
variable {V : Type*} [Fintype V] [LinearOrder V]
lemma partition_pos_of_even (w : V → V → ℝ) (hw : ∀ x y,0 < w x y)
(R : Finset V) (he : Even (Fintype.card V-R.card)) : 0 < partition w R := by
have hm : 0 < (matchings R).card := by rw [matchings_card]; exact pairingCount_pos_of_even _ he
apply Finset.sum_pos
· intro m _
unfold weight
apply Finset.prod_pos
intro x _
split_ifs <;> first | exact hw _ _ | norm_num
· exact Finset.card_pos.mp hm
open Finset MatchingFPRAS.Switching
end MatchingFPRAS.StageAnalysis
noncomputable section
namespace MatchingFPRAS.RealStage
open Finset
open Finset
variable {n : ℕ}
structure ScaleInvariant (G : Fin n → Fin n → ℝ) (v : Fin n → ℝ) : Prop where
lower : ∀ i, alpha/2 ≤ v i
upper : ∀ i, v i ≤ 2
feasible : ∀ i j, i≠j → G i j ≤ v i*v j
end MatchingFPRAS.RealStage
end
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_Endpoints
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.GraphBridge
open Finset MatchingFPRAS.Enlargement MatchingFPRAS.Subdivision MatchingFPRAS.Representation MatchingFPRAS.Switching
variable {n : ℕ}
lemma selected_increasing (s : LogicalEdge (Fin n) → Bool) :
selectedEdges s ⊆ (completeGraph n).edges := by
intro e he
obtain ⟨f,hf,rfl⟩ := mem_map.mp he
exact mem_filter.mpr ⟨mem_univ _,f.property⟩
lemma selected_edgeSelection (M : Finset (Fin n × Fin n)) (hM : M⊆(completeGraph n).edges) :
selectedEdges (edgeSelection M)=M := by
ext e
constructor
· intro he
obtain ⟨f,hf,rfl⟩ := mem_map.mp he
simpa [edgeSelection,endpoints] using (mem_filter.mp hf).2
· intro he
have hi : e.1 < e.2 := (mem_filter.mp (hM he)).2
apply mem_map.mpr
exact ⟨⟨e,hi⟩,mem_filter.mpr ⟨mem_univ _,by simp [edgeSelection,he]⟩,rfl⟩
lemma logical_iff_perfect (s : LogicalEdge (Fin n) → Bool) :
LogicalHoles source target ∅ ∅ s ↔ Perfect (completeGraph n) (selectedEdges s) := by
constructor
· intro hs
refine ⟨selected_increasing s,?_⟩
intro v
obtain ⟨e,he,hu⟩ := hs.2.2 v (by simp)
refine ⟨e.val,⟨(mem_selected s e).mpr he.1,he.2⟩,?_⟩
intro f hf
have hi := (completeGraph n).increasing f (selected_increasing s hf.1)
have hf' : s ⟨f,hi⟩=true := (mem_selected s ⟨f,hi⟩).mp hf.1
exact congrArg Subtype.val (hu ⟨f,hi⟩ ⟨hf',hf.2⟩)
· intro hs
refine ⟨by simp,by simp,?_⟩
intro v _
obtain ⟨e,he,hu⟩ := hs.2 v
have hi := (completeGraph n).increasing e (hs.1 he.1)
refine ⟨⟨e,hi⟩,⟨(mem_selected s ⟨e,hi⟩).mp he.1,he.2⟩,?_⟩
intro f hf
exact Subtype.ext (hu f.val ⟨(mem_selected s f).mpr hf.1,hf.2⟩)
noncomputable def perfectEquiv :
{s : LogicalEdge (Fin n) → Bool // LogicalHoles source target ∅ ∅ s} ≃
{M : Finset (Fin n × Fin n) // Perfect (completeGraph n) M} where
toFun s := ⟨selectedEdges s.val,(logical_iff_perfect s.val).mp s.property⟩
invFun M := ⟨edgeSelection M.val,(logical_iff_perfect _).mpr (by
rw [selected_edgeSelection M.val M.property.1]; exact M.property)⟩
left_inv s := Subtype.ext (edgeSelection_selected s.val)
right_inv M := Subtype.ext (selected_edgeSelection M.val M.property.1)
end MatchingFPRAS.GraphBridge
namespace MatchingFPRAS.Trial
open Finset Switching Subdivision RealGeometry Hierarchy Transport Enlargement StageAnalysis
open scoped Classical
variable {G : GraphInput} {j K S : ℕ}
lemma ScaleState.cap (s : ScaleState G j) (h : j ≤ K) (a b : Fin G.n) (_hab : a≠b) :
edgeActivity s.activity a b ≤ (4:ℝ)^K := by
unfold edgeActivity
split_ifs
all_goals exact (s.activity_bound _ _).trans (pow_le_pow_right₀ (by norm_num) h)
lemma ScaleState.partition_pos (s : ScaleState G j) (he : Even G.n) : 0<partition s.activity ∅ := by
apply partition_pos_of_even _ s.activity_pos
simpa using he
def ScaleState.Balanced (hn : 2 ≤ G.n) (s : ScaleState G j) : Prop :=
(∀ i,(1:ℝ)/4 ≤ rowMax (by simpa using hn) s.activity i) ∧
(∀ i,rowMax (by simpa using hn) s.activity i ≤ 1)
lemma initial_balanced (G : GraphInput) (hn : 2 ≤ G.n) (he : Even G.n) :
(initialScaleState G hn).Balanced hn := by
have h := Initializer.initial_balanced (V:=Fin G.n) (by simpa using hn) (by simpa using he)
have ha : (initialScaleState G hn).activity=(fun _ _ : Fin G.n => (Initializer.initialScale G.n:ℝ)^2) := by
funext a b
simp [ScaleState.activity,raw_zero,initialScaleState,pow_two]
simpa only [ScaleState.Balanced,ha,Fintype.card_fin] using h.2
variable [Nontrivial (Fin G.n)]
noncomputable local instance instDecidableEqSourceLabelFinN_r8038f5_1 (w : Fin G.n → Fin G.n → ℝ) (K : ℕ) : DecidableEq (SourceLabel w K) := Classical.decEq _
noncomputable def ScaleState.matrix (s : ScaleState G j) (x : Fin S → SourceMarked s.activity K) :
Fin G.n → Fin G.n → ℝ :=
estimateMatrix (sourceD (V:=Fin G.n) K) (sampleAverage (observableD s.activity s.nextActivity K) x)
(fun e => sampleAverage (observableProbe s.activity s.nextActivity K e) x)
noncomputable def ScaleState.ratioEstimate (s : ScaleState G j) (x : Fin S → SourceMarked s.activity K) : ℝ :=
RealStage.ratioEstimate (sampleAverage (observableA s.activity K) x)
(sampleAverage (observableD s.activity s.nextActivity K) x)
noncomputable def stageData (G : GraphInput) (hn : 2 ≤ G.n) (he : Even G.n) (K : ℕ) (hK : 0<K)
(ε : ℝ) (hε : 0<ε) (hε1 : ε<1) (j : ℕ) (hj : j ≤ K) (s : ScaleState G j)
(hs : s.Balanced hn) : StageData G.n K K where
hn := hn
w := s.activity
next := s.nextActivity
positive := s.activity_pos
next_positive := s.nextActivity_pos
partition_positive := s.partition_pos he
lower := hs.1
upper := hs.2
cool_lower a b _ := (s.cooling a b).1
cool_upper a b _ := (s.cooling a b).2
cap := s.cap hj
stages := hK
epsilon := ε
epsilon_positive := hε
epsilon_lt_one := hε1
end MatchingFPRAS.Trial
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_TableMarking
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TableMarking
open Finset Transport Variation
variable {V E I : Type*} [Fintype V] [Fintype E] [DecidableEq E] [Fintype I] [DecidableEq I]
variable (inc : E → V → Prop)
abbrev Marked := Σ M : PM inc, (↥M.val → I)
def reveal (M : PM inc) (marks : E → I) : Marked (I:=I) inc := ⟨M,fun e=>marks e.val⟩
variable {A : Type*} [Fintype A] [Nonempty A]
def draw (f : A → PM inc) (c : E → WeightedOptions I) (k : ℕ)
(bits : A×(E → Fin k → Bool)) : Marked (I:=I) inc :=
reveal inc (f bits.1) (fun e=>(c e).draw k (bits.2 e))
noncomputable def law (w : E → ℝ) (c : E → WeightedOptions I) : Marked (I:=I) inc → ℝ :=
sigmaLift (gibbs w) (fun M=>product (fun e : M.val=>portion c e.val))
end MatchingFPRAS.TableMarking
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_RelabelMarking
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset
variable {V E F I : Type*} [Fintype V] [DecidableEq V]
variable [Fintype E] [DecidableEq E] [Fintype F] [DecidableEq F] [Fintype I]
variable {inc : E → V → Prop} {j : F → V → Prop}
def selectedEquiv (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v) (M : PM inc) :
↥M.val ≃ ↥(pmEquiv e he M).val where
toFun a:=⟨e a.val,mem_image.mpr ⟨a.val,a.property,rfl⟩⟩
invFun a:=⟨e.symm a.val,by
obtain ⟨b,hb,heq⟩:=mem_image.mp a.property
simpa [←heq] using hb⟩
left_inv a:=by apply Subtype.ext; exact e.symm_apply_apply _
right_inv a:=by apply Subtype.ext; exact e.apply_symm_apply _
def markedEquiv (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v) :
Marking.Marked (I:=I) inc ≃ Marking.Marked (I:=I) j :=
Equiv.sigmaCongr (pmEquiv e he) (fun M=>Equiv.arrowCongr (selectedEquiv e he M) (Equiv.refl I))
omit [DecidableEq V] [Fintype E] [Fintype F] [Fintype I] in
lemma markedEquiv_mark (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v)
(a : Marking.Marked (I:=I) inc) (x : a.1.val) :
(markedEquiv e he a).2 (selectedEquiv e he a.1 x)=a.2 x := by
change a.2 ((selectedEquiv e he a.1).symm (selectedEquiv e he a.1 x))=a.2 x
rw [Equiv.symm_apply_apply]
end MatchingFPRAS.Transport
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_MarkBridge
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open Finset Transport Variation Enlargement
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance instDecidableEqSourceLabelCastReal_1 (w : V → V → ℚ) (K : ℕ) :
DecidableEq (SourceLabel (fun x y=>(w x y:ℝ)) K) := Classical.decEq _
noncomputable local instance instFintypeBagEdgeSourceVertexSourceLabelCastRealSourceBags_1 (w : V → V → ℚ) (K : ℕ) :
Fintype (BagEdge (sourceBags (fun x y=>(w x y:ℝ)) K)) := Fintype.ofFinite _
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_RationalObservables
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open Finset Transport Variation Enlargement
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance instDecidableEqSourceLabelCastReal_2 (w : V → V → ℚ) (K : ℕ) :
DecidableEq (SourceLabel (fun x y=>(w x y:ℝ)) K) := Classical.decEq _
def rawReweight (w w₁ : V → V → ℚ) (K : ℕ) (e : SourceRealEdge V K) : ℚ :=
if e.2.val=2*(2*K+2) then BottleneckAlgorithm.edge w₁ (source e.1) (target e.1)/
BottleneckAlgorithm.edge w (source e.1) (target e.1) else 1
omit [Fintype V] [Nontrivial V] in
lemma rawReweight_cast (w w₁ : V → V → ℚ) (K : ℕ) (q : SourceRealEdge V K) :
(rawReweight w w₁ K q:ℝ)=Enlargement.rawReweight (fun x y=>(w x y:ℝ))
(fun x y=>(w₁ x y:ℝ)) K q := by
simp only [rawReweight,Enlargement.rawReweight]
split_ifs
· simp only [Rat.cast_div,BottleneckAlgorithm.edge,logicalActivity,Switching.edgeActivity]
split_ifs <;> rfl
· norm_cast
end MatchingFPRAS.RationalSource
namespace MatchingFPRAS.Transport
open Finset
variable {V E F I : Type*} [Fintype V] [DecidableEq V]
variable [Fintype E] [DecidableEq E] [Fintype F] [DecidableEq F] [Fintype I]
variable {inc : E → V → Prop} {j : F → V → Prop}
omit [DecidableEq V] [Fintype E] [Fintype F] [Fintype I] in
lemma markedEquiv_marks_eq (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v)
(a : Marking.Marked (I:=I) inc) (r : F → I) :
(markedEquiv e he a).2=(fun x=>r x.val) ↔ a.2=(fun x=>r (e x.val)) := by
constructor
· intro h
funext x
have hh:=congrFun h (selectedEquiv e he a.1 x)
rw [markedEquiv_mark] at hh
exact hh
· intro h
funext x
obtain ⟨y,rfl⟩:=(selectedEquiv e he a.1).surjective x
rw [markedEquiv_mark,congrFun h]
rfl
omit [DecidableEq V] [Fintype E] [Fintype F] in
lemma markedEquiv_zero (e : E ≃ F) (he : ∀ a v,j (e a) v ↔ inc a v)
(a : Marking.Marked (I:=Fin 3) inc) :
(markedEquiv e he a).2=(fun _=>0) ↔ a.2=(fun _=>0) :=
markedEquiv_marks_eq e he a (fun _=>0)
end MatchingFPRAS.Transport
namespace MatchingFPRAS.RationalSource
open Finset Transport Variation Enlargement
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance instDecidableEqSourceLabelCastReal_3 (w : V → V → ℚ) (K : ℕ) :
DecidableEq (SourceLabel (fun x y=>(w x y:ℝ)) K) := Classical.decEq _
noncomputable local instance instFintypeBagEdgeSourceVertexSourceLabelCastRealSourceBags_3 (w : V → V → ℚ) (K : ℕ) :
Fintype (BagEdge (sourceBags (fun x y=>(w x y:ℝ)) K)) := Fintype.ofFinite _
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Complexity_TreeFractionCosts
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreeFraction
open TreeTyped Polynomial
def height (x : Fraction) : ℕ := max x.1.size x.2.size
end MatchingFPRAS.TreeFraction
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_TreeGeometry
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.ExecutableSource
open TreeTyped Polynomial Enlargement RealGeometry
variable {n m : ℕ}
def logicalRepr (e : LogicalEdge (Fin n)) : RawLogical := (e.val.1.val,e.val.2.val)
end MatchingFPRAS.ExecutableSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_TreePostRealization
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreePost
open TreeTyped TreeData TreeFunction TreeMachine RegisterProc Turing Polynomial
abbrev Alphabet := TM2to1.Γ' (K Reg) (fun _=>Bool)
end MatchingFPRAS.TreePost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_TreeUnitAssemble
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.ExecutableUnit
open TreeTyped ExecutableDP
noncomputable def resultRep {n m : ℕ} {bags : Fin n → Finset (Fin m)}
(p : UnitRefresh.ColoredPairing bags) : Result := List.ofFn (fun i=>(p.pair.mate i |>.val,p.color i |>.val))
end MatchingFPRAS.ExecutableUnit
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_TreeCycleTable
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreeTyped.SparseProgram
open TreeTyped
variable {E C : Type} [Codec E] [Codec C] [LinearOrder E]
attribute [local instance] Transport.Sparse.finsetOrder
variable [Fintype E] {V : Type} [Fintype V] [DecidableEq V]
variable (ends : E→Sym2 V) (p : C×(E×E)→Bool) (c : C)
variable (hp : ∀ a b,p (c,(a,b))=decide (∃ v,v∈ends a ∧ v∈ends b))
def pairRepr (a : Transport.PM (fun e v=>v∈ends e)×Transport.PM (fun e v=>v∈ends e)) : PairState E :=
(a.1.val,a.2.val)
end MatchingFPRAS.TreeTyped.SparseProgram
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_TreeMatchingCheck
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreeTyped.SparseProgram
open TreeTyped
variable {E V C : Type} [Codec E] [Codec V] [Codec C] [LinearOrder E] [LinearOrder V]
instance decideMatchingOn [Fintype E] [Fintype V] (inc : E→V→Prop) [DecidableRel inc] (M : Finset E) :
Decidable (Transport.MatchingOn inc M Finset.univ) := by
unfold Transport.MatchingOn ExistsUnique
infer_instance
end MatchingFPRAS.TreeTyped.SparseProgram
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_TreeCertify
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreeTyped.SparseProgram
open TreeTyped
variable {E V C : Type} [Codec E] [Codec V] [Codec C] [LinearOrder E] [LinearOrder V]
attribute [local instance] Transport.Sparse.finsetOrder
variable [Fintype E] [Fintype V] (ends : E→Sym2 V)
attribute [local instance] Transport.Sparse.pmOrder
def pmEmbedding : @OrderEmbedding (Transport.PM (fun e v=>v∈ends e)) (Finset E)
(Transport.Sparse.pmOrder ends).toLE (Transport.Sparse.finsetOrder (E:=E)).toLE :=
{ toFun := Subtype.val
inj' := Subtype.val_injective
map_rel_iff' := Iff.rfl }
end MatchingFPRAS.TreeTyped.SparseProgram
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Sampling_TreeLadder
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.NumericLadder
open TreeTyped TreeTyped.Numbered ExecutableLadder UnitRefresh Transport Replica.Ladder
attribute [local instance] Transport.sym2Order Transport.bagEdgeOrder Transport.bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec Transport.prodOrder Transport.sumOrder
variable {V L : Type} [Fintype V] [LinearOrder V] [Fintype L] [LinearOrder L]
variable {bags : V→Finset L} {G : SimpleGraph L}
variable (hbags : ∀ v,∀ a∈bags v,∀ b∈bags v,a=b ∨ G.Adj a b) (hG : G.IsAcyclic)
variable (rank : L→ℕ) (parent : L→Option L)
variable (hb : RankedBags bags rank parent) (hne : ∀ v,(bags v).Nonempty)
variable (hp : ∀ l p,parent l=some p → rank p < rank l)
variable {T q : ℕ} [Inhabited (Slot T q)]
noncomputable local instance instDecidableEqBagPM : DecidableEq (BagPM bags) := Classical.decEq _
end MatchingFPRAS.NumericLadder
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_RationalStart
attribute [-instance] _root_.OAI.MatchingFPRAS.TreeTyped.SparseProgram.decideMatchingOn
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open Finset Transport Enlargement Subdivision RealGeometry Switching
variable {n : ℕ}
lemma pairIndex_involutive (he : Even n) : Function.Involutive (pairIndex he) := by
intro i
apply Fin.ext
by_cases hi : i.val % 2 = 0
· have hp : (i.val+1) % 2 ≠ 0 := by omega
simp only [pairIndex, dite_eq_left hi, dite_eq_right hp]
omega
· have hp : (i.val-1) % 2 = 0 := by omega
simp only [pairIndex, dite_eq_right hi, dite_eq_left hp]
omega
def orderedMate (he : Even n) : Mate (Fin n) := ⟨pairIndex he,pairIndex_involutive he⟩
lemma orderedMate_holes (he : Even n) : HasHoles (orderedMate he) ∅ := by
intro i
simp only [Finset.notMem_empty,iff_false]
exact pairIndex_ne he i
def selectMate (m : Mate (Fin n)) (e : LogicalEdge (Fin n)) : Bool :=
decide (m.val (source e)=target e)
lemma selectMate_eq (m : Mate (Fin n)) : selectMate m=Representation.select m := by
funext e
exact rfl
def startSet (K : ℕ) (he : Even n) : Finset (SourceRealEdge (Fin n) K) :=
univ.filter fun q=>alternating (selectMate (orderedMate he) q.1) q.2.val=true
variable [Nontrivial (Fin n)]
lemma startSet_matching (K : ℕ) (he : Even n) :
MatchingOn (fun (q : SourceRealEdge (Fin n) K) x=>x∈edge source target (4*(2*K+2)) q.1 q.2)
(startSet K he) univ := by
have h:= (family_iff_matching source target (4*(2*K+2)) source_ne_target ∅ (fun _=>∅)
(fun e i=>alternating (Representation.select (orderedMate he) e) i.val)).mp
(intact_family (2*K+2) (orderedMate he) (orderedMate_holes he))
rw [survivors_empty] at h
convert h using 1
all_goals try with_reducible_and_instances rfl
unfold startSet selectedSet
rw [selectMate_eq]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_RationalEstimator
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.FiniteTrial
open Finset Enlargement Transport
variable {V : Type*} [LinearOrder V]
def probeMatrix (z : LogicalEdge V → ℚ) (i j : V) : ℚ :=
if hij : i=j then 0 else z (pairEdge i j hij)
lemma probeMatrix_cast (z : LogicalEdge V → ℚ) (i j : V) :
(probeMatrix z i j:ℝ)=Enlargement.probeMatrix (fun e=>(z e:ℝ)) i j := by
simp only [probeMatrix,Enlargement.probeMatrix]
split_ifs <;> norm_cast
lemma probeMatrix_symm (z : LogicalEdge V → ℚ) (i j : V) : probeMatrix z i j=probeMatrix z j i := by
apply Rat.cast_injective (α:=ℝ)
rw [probeMatrix_cast,probeMatrix_cast,Enlargement.probeMatrix_symm]
def estimateMatrix (D : ℕ) (dbar : ℚ) (zbar : LogicalEdge V → ℚ) (i j : V) : ℚ :=
Counting.upperEstimate D dbar (probeMatrix zbar i j)
lemma estimateMatrix_symm (D : ℕ) (dbar : ℚ) (zbar : LogicalEdge V → ℚ) (i j : V) :
estimateMatrix D dbar zbar i j=estimateMatrix D dbar zbar j i := by
rw [estimateMatrix,estimateMatrix,probeMatrix_symm]
lemma estimateMatrix_bounds (D : ℕ) (dbar : ℚ) (zbar : LogicalEdge V → ℚ) (i j : V) :
Counting.alpha≤estimateMatrix D dbar zbar i j ∧ estimateMatrix D dbar zbar i j≤3 := by
unfold estimateMatrix Counting.upperEstimate
split_ifs
· exact ⟨le_max_left _ _,max_le (by norm_num [Counting.alpha]) (min_le_left _ _)⟩
· norm_num [Counting.alpha]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
end MatchingFPRAS.FiniteTrial
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_TreeNumericSummaries
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.NumericMarking
open TreeTyped TreeFraction TreeTyped.Numbered ExecutableStatistics ExecutableLadder
abbrev Summaries := (Fraction×Fraction)×List (ℕ×Fraction)
def logicalProbes (x : Bindings×List (ℕ×Fraction)) : ExecutableAdaptive.ProbeTable :=
x.1.map (fun z=>(z.1,lookup (0,1) (x.2,z.2)))
abbrev UpdateConfig := (ℕ×List ℕ)×(Bindings×ExecutableScaling.Vector)
end MatchingFPRAS.NumericMarking
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_FiniteStage
attribute [-instance] _root_.OAI.MatchingFPRAS.TreeTyped.SparseProgram.decideMatchingOn
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.RationalSource
open Finset Transport Variation Enlargement
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance finiteStageSourceLabelDecidableEq_r8038f5_1 (w : V → V → ℚ) (K : ℕ) :
DecidableEq (SourceLabel (fun x y=>(w x y:ℝ)) K) := Classical.decEq _
noncomputable local instance finiteStageSourceBagEdgeFintype (w : V → V → ℚ) (K : ℕ) :
Fintype (BagEdge (sourceBags (fun x y=>(w x y:ℝ)) K)) := Fintype.ofFinite _
noncomputable local instance instFintypeSourceMarkedCastReal_1 (w : V → V → ℚ) (K : ℕ) :
Fintype (SourceMarked (fun x y=>(w x y:ℝ)) K) := Fintype.ofFinite _
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OutputLengthBound
attribute [-instance] _root_.OAI.MatchingFPRAS.TreeTyped.SparseProgram.decideMatchingOn
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.Transport
open Finset
lemma bagEdge_card_le {V L : Type*} [Fintype V] [DecidableEq V] [Fintype L] [DecidableEq L]
(bags : V → Finset L) [Fintype (BagEdge bags)] :
Fintype.card (BagEdge bags) ≤ (Fintype.card V)^2*Fintype.card L := by
classical
have hi : Function.Injective (fun e : BagEdge bags=>e.val.val) :=
Subtype.val_injective.comp Subtype.val_injective
exact (Fintype.card_le_of_injective _ hi).trans (by
rw [Fintype.card_prod]
exact Nat.mul_le_mul_right _ (sym2_card_le_square V))
end MatchingFPRAS.Transport
namespace MatchingFPRAS.RationalSource
open Transport Enlargement Variation
variable {V : Type*} [Fintype V] [LinearOrder V] [Nontrivial V]
attribute [local instance] NumberedHierarchy.labelOrder sym2Order bagEdgeOrder bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec prodOrder sumOrder
noncomputable local instance instDecidableEqSourceLabelCastReal_4_r8038f5_1 (w : V → V → ℚ) (K : ℕ) :
DecidableEq (SourceLabel (fun x y=>(w x y:ℝ)) K) := Classical.decEq _
noncomputable local instance instFintypeBagEdgeSourceVertexSourceLabelCastRealSourceBags_4 (w : V → V → ℚ) (K : ℕ) :
Fintype (BagEdge (sourceBags (fun x y=>(w x y:ℝ)) K)) := Fintype.ofFinite _
noncomputable local instance instFintypeSourceMarkedCastReal_2 (w : V → V → ℚ) (K : ℕ) :
Fintype (SourceMarked (fun x y=>(w x y:ℝ)) K) := Fintype.ofFinite _
end MatchingFPRAS.RationalSource
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineGuard
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineGuard
open PhysicalStream TreeTyped TreeFraction ExecutableSource NumericMarking OnlineSchedule
def finish (x : Fraction×Bool) : Fraction := if x.2 then x.1 else (0,1)
end MatchingFPRAS.OnlineGuard
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineLaw
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineStage
open PhysicalStream TreeTyped ExecutableSource NumericLadder TreeFraction ExecutableScaling
open UnitRefresh Transport Enlargement TreeTyped.Numbered ExecutableAdaptive Variation
attribute [local instance] NumberedHierarchy.labelOrder
attribute [local instance] Transport.sym2Order Transport.bagEdgeOrder Transport.bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec Transport.prodOrder Transport.sumOrder
variable {n : ℕ} [Nontrivial (Fin n)]
variable (w : Fin n→Fin n→ℚ) (K D m : ℕ)
abbrev vertexCount := Fintype.card (SourceVertex (Fin n) K)
abbrev labelCount := Fintype.card (RationalSource.Label w K)
abbrev tierCount := Transport.endpoint (vertexCount (n:=n) K) D K Fintype.card_pos
abbrev copies := ladderQ (vertexCount (n:=n) K) D
abbrev scansCount := discreteLadderSteps (vertexCount (n:=n) K) D K (tierCount (n:=n) K D) m
end MatchingFPRAS.OnlineStage
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineTransitionLaw
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineStage
open PhysicalStream TreeTyped ExecutableSource NumericLadder TreeFraction ExecutableScaling
open UnitRefresh Transport Enlargement TreeTyped.Numbered ExecutableAdaptive Variation
attribute [local instance] NumberedHierarchy.labelOrder
attribute [local instance] Transport.sym2Order Transport.bagEdgeOrder Transport.bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec Transport.prodOrder Transport.sumOrder
variable {n : ℕ} [Nontrivial (Fin n)]
variable (w : Fin n→Fin n→ℚ) (K D m : ℕ)
noncomputable local instance instFintypeSourceMarkedFinCastReal : Fintype (SourceMarked (fun a b=>(w a b:ℝ)) K) := Fintype.ofFinite _
end MatchingFPRAS.OnlineStage
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineGuardLaw
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineGuard
open PhysicalStream TreeTyped TreeFraction ExecutableSource ExecutableScaling OnlineSchedule OnlineStage
open Transport UnitRefresh Enlargement Variation TreeTyped.Numbered
open scoped Classical
noncomputable local instance instFintypeSourceMarkedFin {n : ℕ} [Nontrivial (Fin n)] (w : Fin n→Fin n→ℝ) (K : ℕ) :
Fintype (SourceMarked w K) := Fintype.ofFinite _
attribute [local instance] NumberedHierarchy.labelOrder
attribute [local instance] Transport.sym2Order Transport.bagEdgeOrder Transport.bagEdgeFintype
attribute [local instance] UnitRefresh.Computable.allowedDec Transport.prodOrder Transport.sumOrder
end MatchingFPRAS.OnlineGuard
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineMedian
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineMedian
open TreeTyped TreeFraction
def relation (a b : Fraction) : Prop := a.1*b.2≤b.1*a.2
instance instDecidableRelFractionRelation : DecidableRel relation := fun _ _=>inferInstanceAs (Decidable (_≤_))
def sorted (xs : List Fraction) : List Fraction := xs.insertionSort relation
def median (xs : List Fraction) : Fraction := (sorted xs).getD (xs.length/2) (0,1)
end MatchingFPRAS.OnlineMedian
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlinePowerSearch
attribute [-instance] _root_.OAI.MatchingFPRAS.OnlineMedian.instDecidableRelFractionRelation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineSchedule
open TreeTyped TreeFraction Polynomial
abbrev PowerSearchInput := (Fraction×Fraction)×List Bool
end MatchingFPRAS.OnlineSchedule
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Arithmetic_OnlineFractionParam
attribute [-instance] _root_.OAI.MatchingFPRAS.OnlineMedian.instDecidableRelFractionRelation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.TreeFraction
open TreeTyped Polynomial
def natCeil (x : Fraction) : ℕ := (x.1+x.2-1)/x.2
def inverse (x : Fraction) : Fraction := normalize (x.2,x.1)
end MatchingFPRAS.TreeFraction
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineCoolingSchedule
attribute [-instance] _root_.OAI.MatchingFPRAS.OnlineMedian.instDecidableRelFractionRelation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineSchedule
open TreeTyped TreeFraction Polynomial
abbrev CoolingInput := ℕ×Fraction
def scheduleBound (x : CoolingInput) : ℕ := x.1*(x.1*x.1+32*natCeil (inverse x.2))
abbrev CoolingPowerInput := CoolingInput×List Bool
def coolingPowerPlan (x : CoolingPowerInput) : Fraction×Fraction :=
(TreeFraction.add ((1,1),TreeFraction.div ((1,1),(x.1.1,1))),
TreeFraction.div (TreeFraction.mul ((32,1),fuelPower ((x.1.1,1),x.2)),x.1.2))
def coolingSearchInput (x : CoolingInput) : PowerSearchInput :=
(coolingPowerPlan (x,List.replicate (x.1/2) false),List.replicate (scheduleBound x) false)
end MatchingFPRAS.OnlineSchedule
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineSampleCount
attribute [-instance] _root_.OAI.MatchingFPRAS.OnlineMedian.instDecidableRelFractionRelation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineSchedule
open TreeTyped TreeFraction Polynomial
abbrev SigmaInput := (ℕ×ℕ)×Fraction
abbrev SampleCountInput := ℕ×SigmaInput
def sampleSumFn (x : SampleCountInput) : Fraction := (x.1+x.2.1.2+1,1)
variable {G : GraphInput} [Nontrivial (Fin G.n)]
def repetitions (x : Fraction) : ℕ := 10*(Nat.clog 2 (natCeil (inverse x))+1)+1
end MatchingFPRAS.OnlineSchedule
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_OnlineInitial
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineInitial
open TreeTyped TreeFraction ExecutableAdaptive ExecutableScaling ExecutableSource OnlineSchedule
abbrev Seed := GraphData×(Fraction×Fraction)
abbrev Config := (Seed×ℕ)×(ℕ×ℕ)
def seedD (x : (Seed×ℕ)×ℕ) : Config :=
(x.1,(x.2,distortion (x.1.1.1.1.length,x.2)))
def initialScale (n : ℕ) : Fraction := TreeFraction.div ((1,1),(root n,1))
def scaleVector (vs : List ℕ) : Vector := vs.map (fun i=>(i,initialScale vs.length))
end MatchingFPRAS.OnlineInitial
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Graphs_OnlineGraphInvariant
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineGraph
open TreeTyped TreeFraction ExecutableAdaptive ExecutableScaling ExecutableSource
open PhysicalStream OnlineSchedule
variable (f : Edges→Edges) (hf : ∀ es e,e∈f es↔e∈es)
def graph (g : GraphData) : GraphData := (g.1,f g.2)
def seed (x : OnlineInitial.Seed) : OnlineInitial.Seed := (graph f x.1,x.2)
end MatchingFPRAS.OnlineGraph
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_OnlineCase
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineTree
open TreeData TreeMachine RegisterProc TreeFunction TreeTyped
open Turing MachineCost PhysicalStream OnlineStack
variable {A B : Type} [Codec A] [Codec B]
namespace Case
open OnlineControl
def code (P Q : OnlineProc.Proc (K Reg)) : Point→OnlineControl.Instr Reg Point
| .split => .call (OnlineProc.deterministic (TreeFunction.split 1 0 (by decide))) .test
| .test => .branch 1 .noClear .yesClear
| .yesClear => .call (OnlineProc.deterministic (TreeFunction.clear 1)) .yes
| .noClear => .call (OnlineProc.deterministic (TreeFunction.clear 1)) .no
| .yes => .call P .halt
| .no => .call Q .halt
| .halt => .halt
end Case
end MatchingFPRAS.OnlineTree
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_Codec
attribute [-instance] _root_.OAI.MatchingFPRAS.OnlineMedian.instDecidableRelFractionRelation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralCodec
open TreeTyped TreeData TreeFunction
def ratWord (x : TreeFraction.Fraction) : List Symbol := 4::natWord x.1++natWord x.2
end MatchingFPRAS.LiteralCodec
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_Input
attribute [-instance] _root_.OAI.MatchingFPRAS.OnlineMedian.instDecidableRelFractionRelation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralInput
open TreeTyped TreeFunction Polynomial LiteralParse
abbrev Parsed := ℕ×(List (ℕ×ℕ)×(TreeFraction.Fraction×TreeFraction.Fraction))
def ratTail (ns : List ℕ) : TreeFraction.Fraction×TreeFraction.Fraction :=
((ns.tail.tail.tail.headD 0,ns.tail.tail.headD 0),(ns.tail.headD 0,ns.headD 0))
def fromNumbers (ns : List ℕ) : Parsed :=
(ns.headD 0,(pairs ns.tail.tail.reverse.tail.tail.tail.tail,ratTail ns.tail.tail.reverse))
def parseInput (as : List Symbol) : Parsed := fromNumbers (LiteralParse.parse as)
end MatchingFPRAS.LiteralInput
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Algorithm_Algorithm
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralAlgorithm
open TreeTyped TreeFraction PhysicalStream LiteralInput Polynomial
def empty (x : Parsed) : Bool := decide (x.1=0)
def invalid (x : Parsed) : Bool := !(decide (x.1%2=0)) || ExecutableInput.tooSparse (x.1,x.2.1)
def materialize (x : Parsed) : OnlineInitial.Seed := ((List.range x.1,x.2.1),x.2.2)
end MatchingFPRAS.LiteralAlgorithm
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_OnlineBounds
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.OnlineSourceBounds
open BitComplexity Transport Polynomial TreeTyped
def normBound (x : ℕ) : ℕ :=
2*x+boundK x+boundN x+boundD x+boundS x+
tierPolynomial (boundN x) (boundD x) (boundK x)+
ladderQ (boundN x) (boundD x)+(2*x)^2+3
end MatchingFPRAS.OnlineSourceBounds
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_PhysicalSequential
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.PhysicalPost
open Turing PhysicalStream
variable {Γ Q R α β : Type} [Inhabited Γ]
def seq (M : Table Γ Q) (N : Table Γ R) (r₀ : R) : Table Γ (Q⊕R)
| .inl q,a,b => match M q a b with
| none => some (.inr r₀,.write a)
| some (q',act) => some (.inl q',act)
| .inr r,a,b => (N r a b).map (fun ra=>(Sum.inr ra.1,ra.2))
def leftCfg (r₀ : R) (c : Cfg Γ Q) : Cfg Γ (Q⊕R) :=
⟨some (c.state.elim (Sum.inr r₀) Sum.inl),c.tape⟩
def rightCfg (c : Cfg Γ R) : Cfg Γ (Q⊕R) := ⟨c.state.map Sum.inr,c.tape⟩
def early (M : Table Γ Q) : ℕ→Cfg Γ Q→Experiment (Cfg Γ Q)
| 0,c => .done c
| n+1,c => match c.state with
| none => .done c
| some _ => .read (fun b=>early M n (tick M c b))
omit [Inhabited Γ] in
lemma seq_supported [Inhabited Γ] (M : Table Γ Q) (N : Table Γ R) (r₀ : R)
(S : Finset Q) (T : Finset R) (hM : Supported M S) (hN : Supported N T) (hr : r₀∈T) :
Supported (seq M N r₀) (S.disjSum T) := by
intro q hq a b q' act he
cases q with
| inl q =>
have hq':q∈S := Finset.inl_mem_disjSum.mp hq
cases h:M q a b with
| none => simp only [seq,h,Option.some.injEq,Prod.mk.injEq] at he;rcases he with ⟨rfl,rfl⟩;exact Finset.inr_mem_disjSum.mpr hr
| some x =>
rcases x with ⟨v,ac⟩
simp only [seq,h,Option.some.injEq,Prod.mk.injEq] at he
rcases he with ⟨rfl,rfl⟩
exact Finset.inl_mem_disjSum.mpr (hM q hq' a b v ac h)
| inr r =>
simp only [seq,Option.map_eq_some_iff] at he
obtain ⟨⟨r',ac⟩,hh,e⟩:=he
cases e
exact Finset.inr_mem_disjSum.mpr (hN r (Finset.inr_mem_disjSum.mp hq) a b r' ac hh)
end MatchingFPRAS.PhysicalPost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_TapeTools
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralTape
open Turing MachineCost
variable {Γ Λ σ : Type} [Inhabited Γ]
def Exec (M : Λ→TM1.Stmt Γ Λ σ) (c d : TM1.Cfg Γ Λ σ) (t : ℕ) : Prop :=
∃ k,k≤t ∧ MachineCost.run (TM1.step M) k c=d
end MatchingFPRAS.LiteralTape
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_Physical
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralTape
open Turing MachineCost PhysicalStream
variable {Γ Λ σ : Type} [Inhabited Γ] [Inhabited Λ] [Fintype Λ] [Fintype σ] [Inhabited σ]
noncomputable def table (M : Λ→TM1.Stmt Γ Λ σ) := CoinTM1.table M (fun _=>none)
noncomputable def states (M : Λ→TM1.Stmt Γ Λ σ) := CoinTM1.states M Finset.univ
omit [Inhabited Γ] [Inhabited σ] in
lemma supported (M : Λ→TM1.Stmt Γ Λ σ) : PhysicalPost.Supported (table M) (states M) :=
CoinTM1.table_supported M Finset.univ (supports_univ M) (fun _=>none) (by simp)
omit [Inhabited Γ] [Inhabited Λ] [Inhabited σ] in
lemma entry_mem (M : Λ→TM1.Stmt Γ Λ σ) (l : Λ) (v : σ) : (Sum.inl l,v)∈states M :=
CoinTM1.state_mem (CoinTM1.node_entry (Finset.mem_univ _))
end MatchingFPRAS.LiteralTape
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_PhysicalProgram
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.PhysicalPost
open Turing PhysicalStream
variable {Γ Q A B : Type} [Inhabited Γ]
structure Program where
State : Type
table : Table Symbol State
states : Finset State
supported : Supported table states
entry : State
entry_mem : entry∈states
namespace Program
noncomputable def seq (P R : Program) : Program where
State := P.State⊕R.State
table := PhysicalPost.seq P.table R.table R.entry
states := P.states.disjSum R.states
supported := seq_supported _ _ _ _ _ P.supported R.supported R.entry_mem
entry := .inl P.entry
entry_mem := Finset.inl_mem_disjSum.mpr P.entry_mem
noncomputable def machine (P : Program) : RandomMachine :=
restrictedMachine P.table P.states P.supported P.entry P.entry_mem
def initial (P : Program) (T : Tape Symbol) : Cfg Symbol P.State := ⟨some P.entry,T⟩
def final (P : Program) (T : Tape Symbol) : Cfg Symbol P.State := ⟨none,T⟩
def Realizes (P : Program) (input : Tape Symbol) (f : Experiment (Tape Symbol)) (N : ℕ) : Prop :=
∃ p : Experiment (Tape Symbol),Implements P.table P.final (P.initial input) p ∧
(∀ h,p.mean h=f.mean h) ∧ p.cost≤N
def earlyTapes (P : Program) (n : ℕ) (T : Tape Symbol) : Experiment (Tape Symbol) :=
(early P.table n (P.initial T)).map Cfg.tape
noncomputable def ofTM1 {Λ σ : Type} [Inhabited Λ] [Fintype Λ] [Inhabited σ] [Fintype σ]
(M : Λ→TM1.Stmt Symbol Λ σ) (l : Λ) (v : σ) : Program where
State := CoinTM1.State Symbol Λ σ
table := LiteralTape.table M
states := LiteralTape.states M
supported := LiteralTape.supported M
entry := (.inl l,v)
entry_mem := LiteralTape.entry_mem M l v
end Program
end MatchingFPRAS.PhysicalPost
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Tapes_Packed
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralPacked
open TreeTyped TreeData TreeFunction TreeMachine TreePost
abbrev Row := K Reg→Option Bool
def baseRow : Row
| .inl _ => some false
| .inr _ => none
def bitRow (b : Bool) : Row := fun k=>if k=Sum.inl 0 then some b else none
def bottom : Alphabet := (true,baseRow)
def letter (b : Bool) : Alphabet := (false,bitRow b)
noncomputable def block (a : Alphabet) : List Symbol :=
(FixedEncoding.enc Alphabet a).toList.map BoolPostCompiler.up
noncomputable def header : List Symbol := block bottom
noncomputable def width : ℕ := Fintype.card Alphabet
lemma map_enc_length {α : Type} [Fintype α] [Inhabited α] (a : α) :
((FixedEncoding.enc α a).toList.map BoolPostCompiler.up).length=Fintype.card α := by
rw [List.length_map]
exact (FixedEncoding.enc α a).2
lemma block_length (a : Alphabet) : (block a).length=width := by
unfold width block
exact map_enc_length a
end MatchingFPRAS.LiteralPacked
end OAI
end
section
-- module Solutions.OAIQ051_MC.MatchingCount_Machines_Wrapper
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace MatchingFPRAS.LiteralPhysical
open Turing PhysicalPost PhysicalStream LiteralPacked TreeTyped
noncomputable def erase : Program := Program.ofTM1 (LiteralTape.eraseCode header.length) () ()
noncomputable def eraseTime : ℕ := MachineCost.programCost (LiteralTape.eraseCode header.length)
end MatchingFPRAS.LiteralPhysical
end OAI
end