Documentation

CslibFrontier.Algorithms.Lean.Karger.Contraction

Karger's contraction algorithm as a randomized client #

Karger's contraction algorithm [Kar93] [KS96] keeps a weighted multigraph on its current supervertices. It repeatedly picks an edge with probability proportional to its weight and contracts it. Here the multigraph is an abstract data type, the contraction structure spec, whose state is the weight matrix of the current supervertices (Graph) and whose operations are deterministic:

The algorithm is a client with private coins, a ProbOracleComp Op.Result program, run against spec.toRandomized.withCoins. Each step draws a uniform offset below S, asks for the pair there and contracts it (contractStep), so it contracts each edge {u, v} with probability 2 W u v / S. contractTimes s makes s steps, and karger contracts down to two supervertices and answers half their total weight, the weight of the cut between them.

All probability is proved here, on the specification. Run laws are derived over trackedSpec n, the same structure that also keeps the block of original vertices merged into each supervertex (TrackedGraph, Karger and Stein, Section 2). The blocks are bookkeeping: forgetting them maps every run over trackedSpec n to the run of the same client over spec (map_run_trackedSpec), so each statement about spec is the corresponding statement over the blocks with the blocks forgotten. Contracting from t + s down to t supervertices preserves a fixed minimum cut with probability at least t (t - 1) / ((t + s) (t + s - 1)) (trackedSurvives_contractTimes, hence survives_contractTimes). One run of karger over trackedSpec n also outputs a cut, the block of the second of the two supervertices it leaves (TrackedGraph.side, with law cutLaw W₀), and answers its weight (answer_eq_cutWeight_side, answerLaw_eq_map_cutLaw). A minimum cut that survives down to two supervertices is the output cut, up to complement, so karger outputs a fixed minimum cut with probability at least 2 / (n (n - 1)) (two_div_le_cutLaw). Hence it answers the minimum cut weight with at least that probability (two_div_le_toOuterMeasure_karger), and every answer is the weight of a non-trivial cut (exists_cut_of_mem_support_answerLaw), never less than the minimum (minCut_le_of_mem_support_karger). Every call it makes is admissible (demonicValid_karger). The combinatorics and the one-step bound are Karger.Graph's (isContractionOf_contract, pullbackCut_contractCut, step_survival_prob_ge, telescope_survival_step), used unchanged, and the composition of the stages is Probability.PMF.toOuterMeasure_bind_ge_mul_ennreal. The bound on the number of minimum cuts is in CslibFrontier.Algorithms.Lean.Karger.MinCutCount.

Source map for the output cut ([KS96], author copy dated 6 August 1996):

Amplification is a client of a trial oracle whose one call answers one run of karger: minRuns R makes R calls and keeps the least answer, one minStep per call after the first. Answered by independent runs, OracleComp.evalWith (fun _ => answerLaw G), it misses the minimum cut weight with probability at most (1 - 2 / (n (n - 1))) ^ R (minRuns_ne_minCut_le), since the least answer misses it only when every run does (minRuns_ne_le, for any trial).

No register, address or instruction count appears here. The word-RAM loop Cslib.Algorithms.WordRAM.Karger.contractDownTo simulates contractTimes: the graph it holds has the law of the client's final state (Cslib.Algorithms.WordRAM.Karger.contractDownTo_law), so its survival bound is survives_contractTimes. The programs of Cslib.Algorithms.WordRAM.KargerMinCut simulate karger and minRuns in the same way. An implementation of spec over the memory oracle is a separate, deterministic hop, and Refinement.toRandomized with RandomizedRefinement.withCoins carries the law of the client through it.

Main definitions #

Main results #

References #

The contraction structure #

A weighted multigraph on size supervertices, given by its weight matrix.

  • size : ℕ

    The number of supervertices.

  • weight : Fin self.size → Fin self.size → ℕ

    The weight matrix.

Instances For

    The operations of the contraction structure.

    • size : Op

      The number of supervertices.

    • total : Op

      The total doubled weight, the sum of the weighted degrees.

    • pairAt (r : ℕ) : Op

      The pair sampled at offset r of the prefix sums of the weights.

    • contract (u v : ℕ) : Op

      Merge supervertex v into u.

    Instances For
      @[reducible, inline]

      The answer type of each operation.

      Instances For
        noncomputable def Cslib.Algorithms.Lean.Karger.sampledPair {k : ℕ} (W : Fin k → Fin k → ℕ) (r : ℕ) :

        The pair sampled at offset r: the pair (u, v) whose interval of the prefix sums of the weights contains r (IsSampledPair), or (0, 0) if there is none.

        Instances For

          Contraction: merge v into u and move the last supervertex into slot v (contractMatrix). Arguments out of range leave the graph unchanged.

          Instances For
            noncomputable def Cslib.Algorithms.Lean.Karger.step (G : Graph) (o : Op) :

            The transition function of the contraction structure.

            Instances For

              Admissibility: an offset below the total weight, and two distinct supervertices.

              Instances For
                @[reducible, inline]

                The contraction structure.

                Instances For
                  theorem Cslib.Algorithms.Lean.Karger.sampledPair_eq {k : ℕ} {W : Fin k → Fin k → ℕ} {r : ℕ} {u v : Fin k} (h : Karger.IsSampledPair W r u v) :
                  sampledPair W r = (↑u, ↑v)

                  The pair sampled at an offset is the unique pair whose interval contains it.

                  theorem Cslib.Algorithms.Lean.Karger.contractGraph_fin {m : ℕ} (W : Fin (m + 1) → Fin (m + 1) → ℕ) (u v : Fin (m + 1)) :
                  contractGraph { size := m + 1, weight := W } ↑u ↑v = { size := m, weight := WeightedCut.contractMatrix W u v }

                  Contracting two supervertices in range is contractMatrix.

                  The contraction structure with blocks #

                  A contraction of a multigraph on Fin n: the weight matrix on size supervertices, and the block of original vertices merged into each supervertex.

                  • size : ℕ

                    The number of supervertices.

                  • weight : Fin self.size → Fin self.size → ℕ

                    The weight matrix.

                  • blocks : Fin self.size → Finset (Fin n)

                    The original vertices merged into each supervertex.

                  Instances For

                    The graph of a tracked contraction, forgetting the blocks.

                    Instances For

                      The singleton blocks of the uncontracted graph W.

                      Instances For

                        Contraction with blocks: contractGraph on the weights, and contractBlocks on the blocks. Arguments out of range leave the graph unchanged.

                        Instances For
                          theorem Cslib.Algorithms.Lean.Karger.contractTracked_fin {n m : ℕ} (W : Fin (m + 1) → Fin (m + 1) → ℕ) (b : Fin (m + 1) → Finset (Fin n)) (u v : Fin (m + 1)) :
                          contractTracked { size := m + 1, weight := W, blocks := b } ↑u ↑v = { size := m, weight := WeightedCut.contractMatrix W u v, blocks := WeightedCut.contractBlocks b u v }

                          Contraction with blocks at a pair of supervertices in range.

                          Forgetting the blocks commutes with contraction.

                          The transition function of the contraction structure with blocks: step on the weights.

                          Instances For
                            @[reducible, inline]

                            The contraction structure with blocks: the operations of spec, with the same answers.

                            Instances For

                              The steps of the two structures agree on the graph.

                              The algorithm #

                              @[reducible, inline]

                              A call of the contraction structure, in a program with coins.

                              Instances For

                                One contraction: draw a uniform offset below the total weight, and contract the pair sampled there. A weightless graph contracts its first and last supervertices.

                                Instances For

                                  Contract s times.

                                  Instances For

                                    Karger's algorithm: contract down to two supervertices, and answer the weight between them, half their total weight.

                                    Instances For

                                      Runs #

                                      The blocks are bookkeeping. Every client with coins draws the same answers and the same graphs over the structure with blocks as over spec: TrackedGraph.toGraph represents the state (Cslib.ProbOracleComp.run_interpret_map_state).

                                      theorem Cslib.Algorithms.Lean.Karger.run_tracked_contractStep_bind {n : ℕ} {α : Type} (p : ProbOracleComp Op.Result α) {m : ℕ} (W : Fin (m + 1) → Fin (m + 1) → ℕ) (b : Fin (m + 1) → Finset (Fin n)) (hS : WeightedCut.totalDoubledWeight W ≠ 0) :
                                      (trackedSpec n).toRandomized.withCoins.run (do contractStep p) { size := m + 1, weight := W, blocks := b } = (ProbComp.unifOracle (WeightedCut.totalDoubledWeight W - 1)).bind fun (r : Fin (WeightedCut.totalDoubledWeight W - 1 + 1)) => (trackedSpec n).toRandomized.withCoins.run p (contractTracked { size := m + 1, weight := W, blocks := b } (sampledPair W ↑r).1 (sampledPair W ↑r).2)

                                      One contraction of a graph with positive total weight, over the structure with blocks: a uniform offset below the total doubled weight, then contraction of the pair sampled there.

                                      theorem Cslib.Algorithms.Lean.Karger.run_tracked_contractStep_bind_of_eq_zero {n : ℕ} {α : Type} (p : ProbOracleComp Op.Result α) {m : ℕ} (W : Fin (m + 1) → Fin (m + 1) → ℕ) (b : Fin (m + 1) → Finset (Fin n)) (hS : WeightedCut.totalDoubledWeight W = 0) :
                                      (trackedSpec n).toRandomized.withCoins.run (do contractStep p) { size := m + 1, weight := W, blocks := b } = (trackedSpec n).toRandomized.withCoins.run p { size := m, weight := WeightedCut.contractMatrix W 0 (Fin.last m), blocks := WeightedCut.contractBlocks b 0 (Fin.last m) }

                                      One contraction of a weightless graph contracts its first and last supervertices.

                                      theorem Cslib.Algorithms.Lean.Karger.run_contractStep_bind {α : Type} (p : ProbOracleComp Op.Result α) {m : ℕ} (W : Fin (m + 1) → Fin (m + 1) → ℕ) (hS : WeightedCut.totalDoubledWeight W ≠ 0) :
                                      spec.toRandomized.withCoins.run (do contractStep p) { size := m + 1, weight := W } = (ProbComp.unifOracle (WeightedCut.totalDoubledWeight W - 1)).bind fun (r : Fin (WeightedCut.totalDoubledWeight W - 1 + 1)) => spec.toRandomized.withCoins.run p (contractGraph { size := m + 1, weight := W } (sampledPair W ↑r).1 (sampledPair W ↑r).2)

                                      One contraction of a graph of positive weight draws a uniform offset below the weight and contracts the pair sampled there.

                                      One contraction of a weightless graph contracts its first and last supervertices.

                                      Survival of a minimum cut #

                                      def Cslib.Algorithms.Lean.Karger.TrackedSurvives {n : ℕ} (W₀ : Fin n → Fin n → ℕ) (C : Finset (Fin n)) (t : ℕ) (G : TrackedGraph n) :

                                      The cut C of W₀ survives in G: G is a contraction of W₀ to t supervertices along a map whose fibres are the blocks of G, under which C is the preimage of a cut.

                                      Instances For
                                        theorem Cslib.Algorithms.Lean.Karger.trackedSurvives_contractTimes {n t : ℕ} (ht : 2 ≤ t) {W₀ : Fin n → Fin n → ℕ} (hmin : 0 < WeightedCut.minCut W₀) (s : ℕ) {W : Fin (t + s) → Fin (t + s) → ℕ} {part : Fin n → Fin (t + s)} (hC : WeightedCut.IsContractionOf W₀ part W) {B : Finset (Fin (t + s))} (hB : WeightedCut.IsNonTrivialCut B) (hBmin : WeightedCut.cutWeight W₀ (WeightedCut.pullbackCut part B) = WeightedCut.minCut W₀) :
                                        ↑(t * (t - 1)) / ↑((t + s) * (t + s - 1)) ≤ ((trackedSpec n).toRandomized.withCoins.run (contractTimes s) { size := t + s, weight := W, blocks := fun (i : Fin (t + s)) => WeightedCut.pullbackCut part {i} }).toOuterMeasure {x : Unit × (trackedSpec n).toRandomized.withCoins.State | TrackedSurvives W₀ (WeightedCut.pullbackCut part B) t x.2}

                                        Survival of a minimum cut, over the blocks [KS96]. Contracting a contraction of a connected multigraph W₀ from t + s down to t ≥ 2 supervertices, with the fibres of its map as blocks, preserves a fixed minimum cut with probability at least t (t - 1) / ((t + s) (t + s - 1)).

                                        def Cslib.Algorithms.Lean.Karger.Survives {n : ℕ} (W₀ : Fin n → Fin n → ℕ) (C : Finset (Fin n)) (t : ℕ) (G : Graph) :

                                        The cut C of W₀ survives in G: G is a contraction of W₀ to t supervertices along some map, under which C is the preimage of a cut.

                                        Instances For
                                          theorem Cslib.Algorithms.Lean.Karger.TrackedSurvives.survives {n : ℕ} {W₀ : Fin n → Fin n → ℕ} {C : Finset (Fin n)} {t : ℕ} {G : TrackedGraph n} (h : TrackedSurvives W₀ C t G) :
                                          Survives W₀ C t G.toGraph

                                          A cut that survives over the blocks survives in the graph.

                                          theorem Cslib.Algorithms.Lean.Karger.survives_contractTimes {n t : ℕ} (ht : 2 ≤ t) {W₀ : Fin n → Fin n → ℕ} (hmin : 0 < WeightedCut.minCut W₀) (s : ℕ) {W : Fin (t + s) → Fin (t + s) → ℕ} {part : Fin n → Fin (t + s)} (hC : WeightedCut.IsContractionOf W₀ part W) {B : Finset (Fin (t + s))} (hB : WeightedCut.IsNonTrivialCut B) (hBmin : WeightedCut.cutWeight W₀ (WeightedCut.pullbackCut part B) = WeightedCut.minCut W₀) :
                                          ↑(t * (t - 1)) / ↑((t + s) * (t + s - 1)) ≤ (spec.toRandomized.withCoins.run (contractTimes s) { size := t + s, weight := W }).toOuterMeasure {x : Unit × spec.toRandomized.withCoins.State | Survives W₀ (WeightedCut.pullbackCut part B) t x.2}

                                          Survival of a minimum cut [KS96]. Contracting a contraction of a connected multigraph W₀ from t + s down to t ≥ 2 supervertices preserves a fixed minimum cut with probability at least t (t - 1) / ((t + s) (t + s - 1)). This is trackedSurvives_contractTimes with the blocks forgotten.

                                          Every outcome is a contraction #

                                          theorem Cslib.Algorithms.Lean.Karger.exists_of_mem_support_tracked_contractTimes {n t : ℕ} (ht : 1 ≤ t) {W₀ : Fin n → Fin n → ℕ} (s : ℕ) {W : Fin (t + s) → Fin (t + s) → ℕ} {part : Fin n → Fin (t + s)} (hC : WeightedCut.IsContractionOf W₀ part W) {x : Unit × TrackedGraph n} (hx : x ∈ ((trackedSpec n).toRandomized.withCoins.run (contractTimes s) { size := t + s, weight := W, blocks := fun (i : Fin (t + s)) => WeightedCut.pullbackCut part {i} }).support) :
                                          ∃ (W' : Fin t → Fin t → ℕ) (part' : Fin n → Fin t), x.2 = { size := t, weight := W', blocks := fun (i : Fin t) => WeightedCut.pullbackCut part' {i} } ∧ WeightedCut.IsContractionOf W₀ part' W'

                                          Every outcome of s contractions of a contraction of W₀ from t + s ≥ 2 supervertices, with the fibres of its map as blocks, is a contraction of W₀ to t supervertices with the fibres of its map as blocks.

                                          theorem Cslib.Algorithms.Lean.Karger.isContractionOf_of_mem_support_contractTimes {n t : ℕ} (ht : 1 ≤ t) {W₀ : Fin n → Fin n → ℕ} (s : ℕ) {W : Fin (t + s) → Fin (t + s) → ℕ} {part : Fin n → Fin (t + s)} (hC : WeightedCut.IsContractionOf W₀ part W) {x : Unit × Graph} (hx : x ∈ (spec.toRandomized.withCoins.run (contractTimes s) { size := t + s, weight := W }).support) :
                                          ∃ (W' : Fin t → Fin t → ℕ) (part' : Fin n → Fin t), x.2 = { size := t, weight := W' } ∧ WeightedCut.IsContractionOf W₀ part' W'

                                          Every outcome of s contractions of a contraction of W₀ from t + s ≥ 2 supervertices is a contraction of W₀ to t supervertices. This is exists_of_mem_support_tracked_contractTimes with the blocks forgotten.

                                          theorem Cslib.Algorithms.Lean.Karger.minCut_eq_zero_of_mem_support_contractTimes {t : ℕ} (ht : 2 ≤ t) (s : ℕ) {W : Fin (t + s) → Fin (t + s) → ℕ} (hW : WeightedCut.IsMultigraph W) (hmin : WeightedCut.minCut W = 0) {x : Unit × Graph} (hx : x ∈ (spec.toRandomized.withCoins.run (contractTimes s) { size := t + s, weight := W }).support) :
                                          ∃ (W' : Fin t → Fin t → ℕ), x.2 = { size := t, weight := W' } ∧ WeightedCut.IsMultigraph W' ∧ WeightedCut.minCut W' = 0

                                          Every outcome of s contractions of a disconnected (minCut W = 0) multigraph down to t ≥ 2 supervertices is a multigraph with minCut = 0.

                                          The output cut #

                                          The cut that a tracked contraction to two supervertices outputs: the block of supervertex 1.

                                          Instances For

                                            The law of the answer of one run of karger on G.

                                            Instances For
                                              theorem Cslib.Algorithms.Lean.Karger.answerLaw_eq {n : ℕ} (W : Fin n → Fin n → ℕ) :
                                              answerLaw { size := n, weight := W } = PMF.map (fun (G : spec.toRandomized.withCoins.State) => WeightedCut.totalDoubledWeight G.weight / 2) (PMF.map Prod.snd (spec.toRandomized.withCoins.run (contractTimes (n - 2)) { size := n, weight := W }))

                                              The answer of karger is half the total weight of the graph that n - 2 contractions leave.

                                              noncomputable def Cslib.Algorithms.Lean.Karger.cutLaw {n : ℕ} (W : Fin n → Fin n → ℕ) :
                                              PMF (Finset (Fin n))

                                              The law of the cut that one run of karger outputs on W: the block of the second of the two supervertices it leaves.

                                              Instances For

                                                The output cut is the block of supervertex 1 after n - 2 contractions.

                                                The answer is the weight of the output cut. Every outcome of karger on a multigraph with n ≥ 2 vertices, over the structure with blocks, outputs a non-trivial cut side and answers its weight.

                                                theorem Cslib.Algorithms.Lean.Karger.answerLaw_eq_map_cutLaw {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) :
                                                answerLaw { size := n, weight := W₀ } = PMF.map (WeightedCut.cutWeight W₀) (cutLaw W₀)

                                                The answer of karger on a multigraph with n ≥ 2 vertices is the weight of the cut it outputs: its law is the image of cutLaw under cutWeight.

                                                Every cut that karger outputs on a multigraph with n ≥ 2 vertices is non-trivial.

                                                theorem Cslib.Algorithms.Lean.Karger.two_div_le_cutLaw {n : ℕ} {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) (hmin : 0 < WeightedCut.minCut W₀) {C : Finset (Fin n)} (hC : WeightedCut.IsNonTrivialCut C) (hCmin : WeightedCut.cutWeight W₀ C = WeightedCut.minCut W₀) :
                                                2 / ↑(n * (n - 1)) ≤ (cutLaw W₀).toOuterMeasure {C, Finset.univ \ C}

                                                Karger's theorem for a fixed cut [KS96]. On a connected multigraph on Fin n, karger outputs a fixed minimum cut {C, Cᶜ} with probability at least 2 / (n (n - 1)) = 1 / C(n, 2). (C non-trivial forces n ≥ 2.)

                                                Karger's theorem #

                                                theorem Cslib.Algorithms.Lean.Karger.two_div_le_toOuterMeasure_karger {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) (hmin : 0 < WeightedCut.minCut W₀) :

                                                Karger's theorem [Kar93]. On a connected multigraph with n ≥ 2 vertices, karger answers the minimum cut weight with probability at least 2 / (n (n - 1)).

                                                theorem Cslib.Algorithms.Lean.Karger.exists_cut_of_mem_support_answerLaw {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) {v : ℕ} (hv : v ∈ (answerLaw { size := n, weight := W₀ }).support) :

                                                Every answer of karger on a multigraph with n ≥ 2 vertices is the weight of a non-trivial cut.

                                                theorem Cslib.Algorithms.Lean.Karger.eq_zero_of_mem_support_answerLaw {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) (hmin : WeightedCut.minCut W₀ = 0) {v : ℕ} (hv : v ∈ (answerLaw { size := n, weight := W₀ }).support) :
                                                v = 0

                                                On a disconnected (minCut W₀ = 0) multigraph with n ≥ 2 vertices, every answer of karger is 0.

                                                theorem Cslib.Algorithms.Lean.Karger.minCut_le_of_mem_support_karger {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) {x : ℕ × Graph} (hx : x ∈ (spec.toRandomized.withCoins.run karger { size := n, weight := W₀ }).support) :

                                                One-sided error. Every answer of karger on a multigraph with n ≥ 2 vertices is the weight of a non-trivial cut, so it is never below the minimum cut weight.

                                                Amplification #

                                                One more run of a trial, keeping the least answer b so far. The trial is an oracle whose one call () answers one run of karger.

                                                Instances For

                                                  Amplification [Kar93]: make R runs of a trial and answer the least answer, or 0 when R = 0. Answering each call by an independent run of karger on G, with OracleComp.evalWith (fun _ => answerLaw G), gives the law of R independent runs.

                                                  Instances For

                                                    After the least answer b of earlier runs, R more runs answer at most b: either b or the answer of one of them.

                                                    theorem Cslib.Algorithms.Lean.Karger.mem_support_minRuns {μ : PMF ℕ} {R v : ℕ} (hR : R ≠ 0) (hv : v ∈ (OracleComp.evalWith (fun (x : Unit) => μ) (minRuns R)).support) :

                                                    With R ≥ 1 runs, every answer of minRuns R is the answer of one of the runs.

                                                    theorem Cslib.Algorithms.Lean.Karger.minRuns_ne_le {μ : PMF ℕ} {m : ℕ} {q : ENNReal} (hge : ∀ v ∈ μ.support, m ≤ v) (hmiss : μ.toOuterMeasure {v : ℕ | v ≠ m} ≤ q) (R : ℕ) :
                                                    (OracleComp.evalWith (fun (x : Unit) => μ) (minRuns R)).toOuterMeasure {v : ℕ | v ≠ m} ≤ q ^ R

                                                    Amplification. If every answer of a run is at least m and a run misses m with probability at most q, then R independent runs all miss it, so minRuns R misses it, with probability at most q ^ R.

                                                    theorem Cslib.Algorithms.Lean.Karger.minRuns_ne_minCut_le {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) (hmin : 0 < WeightedCut.minCut W₀) (R : ℕ) :
                                                    (OracleComp.evalWith (fun (x : Unit) => answerLaw { size := n, weight := W₀ }) (minRuns R)).toOuterMeasure {v : ℕ | v ≠ WeightedCut.minCut W₀} ≤ (1 - 2 / ↑(n * (n - 1))) ^ R

                                                    Amplification of Karger's algorithm [Kar93]. On a connected multigraph with n ≥ 2 vertices, R independent runs of karger all miss the minimum cut weight, so minRuns R misses it, with probability at most (1 - 2 / (n (n - 1))) ^ R.

                                                    Calls #

                                                    theorem Cslib.Algorithms.Lean.Karger.isCostBounded_contractStep {cost : ℕ ⊕ Op → ℕ} {a b : ℕ} (hcoin : ∀ (n : ℕ), cost (Sum.inl n) ≤ a) (hop : ∀ (o : Op), cost (Sum.inr o) ≤ b) :

                                                    One contraction makes at most one coin call and four calls of the structure.

                                                    theorem Cslib.Algorithms.Lean.Karger.isCostBounded_contractTimes {cost : ℕ ⊕ Op → ℕ} {a b : ℕ} (hcoin : ∀ (n : ℕ), cost (Sum.inl n) ≤ a) (hop : ∀ (o : Op), cost (Sum.inr o) ≤ b) (s : ℕ) :

                                                    s contractions make at most s coin calls and 4 s calls of the structure.

                                                    Admissibility #

                                                    theorem Cslib.Algorithms.Lean.Karger.demonicValid_contractTimes {t : ℕ} (ht : 1 ≤ t) (s : ℕ) {W : Fin (t + s) → Fin (t + s) → ℕ} (hW : WeightedCut.IsMultigraph W) :

                                                    Every call of s contractions of a multigraph on t + s ≥ 2 supervertices is admissible.

                                                    theorem Cslib.Algorithms.Lean.Karger.demonicValid_karger {n : ℕ} (hn : 2 ≤ n) {W₀ : Fin n → Fin n → ℕ} (hW₀ : WeightedCut.IsMultigraph W₀) :

                                                    Every call of karger on a multigraph with n ≥ 2 vertices is admissible.