From 6af6e8194164beed7b40e3fe152394cf3f2ca5d0 Mon Sep 17 00:00:00 2001 From: amilchew Date: Thu, 16 Mar 2023 14:46:52 +0000 Subject: [PATCH 01/28] feat(library)max_flow_min_cut_first_draft --- .../quiver/max_flow_min_cut.lean | 996 ++++++++++++++++++ 1 file changed, 996 insertions(+) create mode 100644 src/combinatorics/quiver/max_flow_min_cut.lean diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean new file mode 100644 index 0000000000000..769440e3a02b9 --- /dev/null +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -0,0 +1,996 @@ +/- +Copyright (c) 2023 Aleksandar Milchev. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Author: Aleksandar Milchev +-/ + +import data.real.basic +import data.set +import tactic +import data.finset +import tactic.induction + +/-! +# Max flow min cut theorem + +In this file we will prove the max-flow min-cut theorem, stating that if a maximum flow exists in a flow network, +then its value is equal to the capacity of a minimum cut in the same network. + +## Main results + +- `weak_duality` : the value of every flow is less than or equal to the capacity of every cut. + direct consequences : + - the value of a max flow is always less than or equal to the capacity of a min cut. + - `max_flow_criterion` : if a flow value is equal to a cut capacity in the same flow network, then the flow is maximum. + - `min_cut_criterion` : if a capacity of a cut is equal to a flow value in the same network, then the cut is minimum. + +- `no_augm_path` : if the active flow gives a maximum flow, then there is no augmenting path in the residual network. +- `existence_of_a_cut` : there exists a cut with a capacity equal to the value of the maximum flow. +- `max_flow_min_cut` : if f is a max flow and c is a min cut in the same network, then their valies are equal (max flow min cut theorem). + +## Notation + +- Type V is used for the set of all vertices in our graph. + +## References + +- Some of the structure ideas and lemmas can be seen in https://github.com/Zetagon/maxflow-mincut. + +-/ + +open finset + + +open_locale big_operators +open_locale classical + +notation ` V' ` := univ + +/-! + We now define our flow network. Our goal will be to prove weak_duality. + As direct consequences, `max_flow_criterion` and `min_cut_criterion` will be proven. +-/ + +structure strange_digraph (V : Type*) [inst : fintype V] := + (is_edge : V → V → Prop) + (hnonsymmetric : ∀ u v : V, ¬ ((is_edge u v) ∧ (is_edge v u))) + +structure capacity (V : Type*) [inst : fintype V] + extends strange_digraph V := + (c : V -> V -> ℝ) + (non_neg_capacity : ∀ u v : V, c u v ≥ 0) + (vanishes : ∀ u v : V, ¬ (is_edge u v) → c u v = 0) + +structure flow_network (V : Type*) [inst : fintype V] + extends capacity V := + (source : V) + (sink : V) + +noncomputable +def mk_in {V : Type* } [inst : fintype V] + (f : V -> V -> ℝ) (s : finset V) : ℝ := ∑ x in finset.univ \ s, ∑ y in s, f x y + +noncomputable +def mk_out {V : Type* } [inst : fintype V] + (f : V -> V -> ℝ) (s : finset V) : ℝ := ∑ x in s, ∑ y in finset.univ \ s, f x y + +structure active_flow_network (V : Type*) [fintype V] := + (network : flow_network V) + (f : V -> V -> ℝ) + (sourceNotSink: network.source ≠ network.sink) + (non_neg_flow : ∀ u v : V, f u v ≥ 0) + (no_overflow : ∀ u v : V, f u v ≤ network.c u v) + (noEdgesInSource : ∀ u : V, ¬ (network.is_edge u network.source)) + (noEdgesOutSink : ∀ u: V, ¬ (network.is_edge network.sink u)) + (conservation : ∀ v : V, + v ∈ (V' : finset V) \ {network.source, network.sink} → + mk_out f {v} = mk_in f {v}) + +noncomputable +def F_value {V : Type*} [fintype V] : + active_flow_network V -> ℝ := +λ N, mk_out N.f {N.network.source} - mk_in N.f {N.network.source} + +structure cut (V : Type*) [fintype V] := + (network : flow_network V) + (S : finset V) + (T : finset V ) + (sins : network.source ∈ S) + (tint : network.sink ∈ T) + (Tcomp : T = univ \ S) + +noncomputable +def cut_cap {V : Type*} [inst' : fintype V] -- stays for capacity of the cut + (c : cut V) : ℝ := mk_out c.network.c c.S + +lemma f_vanishes_outside_edge {V : Type*} [fintype V] + (afn : active_flow_network V) (u : V) (v : V) (not_edge: ¬afn.network.is_edge u v): afn.f u v = 0 := + begin + have cap_is_zero: afn.network.c u v = 0 := + begin + exact afn.network.vanishes u v not_edge, + end, + have bar := afn.no_overflow u v, + have foo := afn.non_neg_flow u v, + linarith, + end + +lemma x_not_in_s {V : Type*} [fintype V] + (c : cut V) : ∀ x : V, x ∈ c.T -> x ∉ ({c.network.source} : finset V) := +begin + intros x hxinS, + cases c, + simp only [mem_singleton] at *, + rw c_Tcomp at hxinS, + have foo : univ \ c_S ∩ c_S = ∅ := sdiff_inter_self c_S univ, + have foo : disjoint (univ \ c_S) c_S := sdiff_disjoint, + have bar : c_network.source ∈ c_S := c_sins, + exact disjoint_iff_ne.mp foo x hxinS c_network.source c_sins +end + +lemma foobar { a b : ℝ } : a + - b = a - b := rfl + +lemma f_zero_zero {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (x : V) : afn.f x x = 0 := +begin + have hnonsymm : _ := afn.network.hnonsymmetric x x, + have hvanish: _ := afn.network.vanishes x x, + simp only [not_and, imp_not_self] at hnonsymm, + have hnon_edge := hnonsymm, clear hnonsymm, + have hcapacity_zero := hvanish hnon_edge, + have hno_overflow := afn.no_overflow x x, + rw hcapacity_zero at hno_overflow, + have hnon_neg_flow := afn.non_neg_flow x x, + linarith, +end + + +lemma mk_in_single_node { V : Type* } [fintype V] + (p : V) (afn : active_flow_network V) : + mk_in (afn.f) {p} = ∑ v in finset.univ, (afn.f) v p := +begin + rw @sum_eq_sum_diff_singleton_add _ _ _ _ univ p (by simp only [mem_univ]) (λ x, afn.f x p), + have foo : (λ (x : V), afn.f x p) p = afn.f p p := rfl, + simp only [congr_fun], + rw f_zero_zero afn p, + have bar : ∑ (x : V) in univ \ {p}, afn.f x p + 0 = (λp', ∑ (x : V) in univ \ {p'}, afn.f x p' ) p := by simp only [add_zero], + rw bar, clear bar, + rw ← @finset.sum_singleton _ _ p (λp', ∑ (x : V) in univ \ {p'}, afn.f x p' ) _, + simp only [mk_in, sum_singleton], +end + +@[simp] lemma mk_in_single_node' { V : Type* } [fintype V] + (p : V) (afn : active_flow_network V) : + ∑ v in finset.univ, (afn.f) v p = mk_in (afn.f) {p} := by rw mk_in_single_node + +lemma mk_out_single_node { V : Type* } [fintype V] + (p : V) (afn : active_flow_network V) : + mk_out afn.f {p} = ∑ v in finset.univ, (afn.f) p v := +begin + rw @sum_eq_sum_diff_singleton_add _ _ _ _ univ p (by simp only [mem_univ]) (λ x, afn.f p x), + have foo : (λ (x : V), afn.f p x) p = afn.f p p := rfl, + simp only [congr_fun], + rw f_zero_zero afn p, + have bar : ∑ (x : V) in univ \ {p}, afn.f p x + 0 = (λp', ∑ (x : V) in univ \ {p'}, afn.f p' x) p := by simp only [add_zero], + rw bar, clear bar, + rw ← @finset.sum_singleton _ _ p (λp', ∑ (x : V) in univ \ {p'}, afn.f p' x) _, + simp only [mk_out, sum_singleton], +end + +@[simp] lemma mk_out_single_node' { V : Type* } [fintype V] + (p : V) (afn : active_flow_network V) : + ∑ v in finset.univ, (afn.f) p v = mk_out afn.f {p} := by rw mk_out_single_node + +lemma break_out_neg (a b : ℝ) : (-a) + -(b) = -(a + b) := by ring + +noncomputable +def edge_flow {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (x : V) : ℝ := (mk_out afn.f {x} - mk_in afn.f {x}) + +lemma edge_flow_conservation {V: Type*} [inst' : fintype V] + (afn : active_flow_network V) (x : V) : + x ∈ (V' : finset V) \ {afn.network.source, afn.network.sink} -> edge_flow afn x = 0 := +begin + intro hx, + unfold edge_flow, + rw afn.conservation x, + {ring}, + {exact hx,} +end + +lemma sub_comm_zero (a b : ℝ) : a - b = 0 → b - a = 0 := +begin + intro eq, + rw ← add_left_inj (a), + rw sub_add_cancel, rw zero_add, + rw ← add_left_inj (-b), + rw add_neg_self, + rw ← sub_eq_add_neg, + rw eq_comm, + exact eq +end + +lemma set_flow_conservation {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (S : finset V) : +S ⊆ finset.univ \ {afn.network.source, afn.network.sink} -> mk_in afn.f S = mk_out afn.f S := +begin + intro hin, + rw ← add_left_inj (- mk_out afn.f S), + simp only [add_right_neg], + rw ← add_zero (mk_in afn.f S), + nth_rewrite 0 ← add_neg_self (∑ u in S, (∑ v in S, afn.f u v)), + rw ← add_assoc, + have tmp : mk_in afn.f S + ∑ u in S, ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := + begin + unfold mk_in, + have h: S ⊆ V' := by {exact finset.subset_univ S}, + have hyp: ∑ (x : V) in V' \ S, ∑ (y : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v = ∑ u in V', ∑ v in S, afn.f u v := + by {exact finset.sum_sdiff h}, + have fin: ∑ u in V', ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := by {exact finset.sum_comm}, + rw hyp, + exact fin, + end, + have tmp2: mk_out afn.f S + (∑ u in S, ∑ v in S, afn.f u v) = ∑ u in S, ∑ v in V', afn.f u v := + begin + unfold mk_out, + rw finset.sum_comm, + have h: S ⊆ V' := by {exact finset.subset_univ S}, + have hyp: ∑ (y : V) in V' \ S, ∑ (x : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ u in V', ∑ v in S, afn.f v u := + by {exact finset.sum_sdiff h}, + have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := by {exact finset.sum_comm}, + have fin: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := by {exact finset.sum_comm}, + rw obvs at hyp, + rw hyp, + exact fin, + end, + rw tmp, + rw add_assoc, + rw break_out_neg, + nth_rewrite 1 add_comm, + rw tmp2, + clear tmp tmp2, + rw foobar, + rw ← @sum_sub_distrib _ _ S _ _ _, + simp only [mk_in_single_node', mk_out_single_node'], + have hseq : S = S := rfl, + have h : ∀ (x : V), x ∈ S -> - edge_flow afn x = 0 := + begin + intros x hx, + unfold edge_flow, + rw afn.conservation x, + { ring, }, + { exact finset.mem_of_subset hin hx,} + end, + have foo := finset.sum_congr hseq h, + unfold edge_flow at foo, + simp at foo, + rw ← foo, + simp, +end + +lemma move_right (a b : ℝ) : b = a → a - b = 0 := +begin + intro eq, + rw eq_comm, + rw ← add_left_inj (b), + simp, exact eq +end + +lemma set_flow_conservation_eq {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (S : finset V) : +S ⊆ finset.univ \ {afn.network.source, afn.network.sink} -> mk_out afn.f S - mk_in afn.f S = 0 := +begin + intro hip, + have h: mk_in afn.f S = mk_out afn.f S := by {exact set_flow_conservation afn S hip}, + rw eq_comm at h, + rw ← add_left_inj (-mk_in afn.f S) at h, + rw add_neg_self(mk_in afn.f S) at h, exact h +end + +lemma add_zero_middle (a b c: ℝ): c = 0 → a + c - b = a - b := by {intro eq, linarith} + +lemma group_minus (a b c d : ℝ): a + b - c - d = a + b - (c + d) := by ring + +lemma same_source_and_sink {V: Type*} [inst' : fintype V] + (afn: active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network): + afn.network.source = ct.network.source ∧ afn.network.sink = ct.network.sink := +begin + rw same_net, + split, + {simp}, + simp +end + +/- + This lemma has issues, I am confused how finsets are handled. The complains mention "meta variables". +-/ +lemma flow_value_global_ver {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (ct : cut V) + (same_net : afn.network = ct.network) : + mk_out afn.f {afn.network.source} - mk_in afn.f {afn.network.source} = mk_out afn.f ct.S - mk_in afn.f ct.S := +begin + set S := ct.S, + set T := ct.T, + set s := afn.network.source, + set t := afn.network.sink, + set f := afn.f, + have hs : s = afn.network.source := rfl, + have hT : T = ct.T := rfl, + have singleton: s ∈ {s} := by {exact set.mem_singleton s}, + have sInS: s ∈ S := + begin + have same_source: s = ct.network.source := by {exact (same_source_and_sink afn ct same_net).1}, + rw same_source, + exact ct.sins, + end, + -- "meta" errors occur, how is finset handled? + have hS: {s} ⊆ S := by sorry, -- {exact (set.singleton_subset_iff).2 sInS}, + have tNotInS: t ∉ S := + begin + have same_sink: t = ct.network.sink := by {exact (same_source_and_sink afn ct same_net).2}, + have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, + have Tcomp : T = univ \ S := by {exact ct.Tcomp}, + have foo: S = univ \ (univ \ S) := by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, + have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, + rw Scomp at *, + -- exact set.not_mem_diff_of_mem tInT, + sorry, + end, + have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} = mk_out afn.f {s} - mk_in afn.f {s} := + begin + have h3: s ∉ (S \ {s}) := by sorry, -- {set.not_mem_diff_of_mem singleton}, + have eq: mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s}) = 0 := + begin + have h: (S \ {s}) ⊆ finset.univ \ {s,t} := + begin + intros x xInSet, + have memU: x ∈ finset.univ := by {exact finset.mem_univ x}, + have xInS: x ∈ S:= by sorry, -- {exact ((set.mem_diff x).1 xInSet).1}, + have xNotInS: x ∉ {t} := + begin + by_contradiction h, + have eq: x = t := by {exact set.mem_singleton_iff.1 h}, + rw eq at xInS, + contradiction, + end, + have union: {s} ∪ {t} = {s,t} := by {exact set.singleton_union}, + have xNotInS: x ∉ {s} := by sorry, -- {exact ((set.mem_diff x).1 xInSet).2}, + have xOut: x ∉ {s,t} := + begin + rw ← union, + by_contradiction h, + cases h with h0 h1, + {exact absurd h0 xNotInS}, + exact absurd h1 xNotInT, + end, + exact set.mem_diff.2 memU + end, + exact set_flow_conservation_eq afn (S \ {s}) h, + end, + exact add_zero_middle (mk_out afn.f {s}) (mk_in afn.f {s}) (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) eq, + end, + /- The next two equalities use sum over two elements, so I am not sure how to resolve them. -/ + have sum1: mk_out afn.f {s} + mk_out afn.f (S \ {s}) = mk_out afn.f S := by sorry, -- {unfold mk_out, rw finset.sum_sdiff hS}, + have sum2: mk_in afn.f (S \ {s}) + mk_in afn.f {s} = mk_in afn.f S := by sorry, -- {unfold mk_in, rw finset.sum_sdiff hS}, + rw ← expand, + rw add_sub, + rw group_minus (mk_out afn.f {s}) (mk_out afn.f (S \ {s})) (mk_in afn.f (S \ {s})) (mk_in afn.f {s}), + rw sum1, rw sum2, +end + +/-! + Here is our first big lemma, weak duality. + It states that the value of every flow is less than or equal to the capacity of every cut in the same network. +-/ + +lemma weak_duality {V: Type*} [inst' : fintype V] + (afn: active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network): + F_value afn ≤ cut_cap ct := +begin + set S := ct.S, + set T:= ct.T, + set s := afn.network.source, + set t := afn.network.sink, + unfold cut_cap, + have sInS: s ∈ S := + begin + have same_source: s = ct.network.source := by {exact (same_source_and_sink afn ct same_net).1}, + rw same_source, + exact ct.sins, + end, + have hS: {s} ⊆ S := by sorry, -- {exact (set.singleton_subset_iff).2 sInS}, + have singleton: s ∈ {s} := by {exact set.mem_singleton s}, + have tNotInS: t ∉ S := + begin + have same_sink: t = ct.network.sink := by {exact (same_source_and_sink afn ct same_net).2}, + have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, + have Tcomp : T = univ \ S := by {exact ct.Tcomp}, + have foo: S = univ \ (univ \ S) := by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, + have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, + rw Scomp at *, + -- exact set.not_mem_diff_of_mem tInT, + sorry, + end, + have lemma1: F_value afn = mk_out afn.f S - mk_in afn.f S := + begin + unfold F_value, + exact flow_value_global_ver afn ct same_net, + end, + have lemma2: mk_out afn.f S ≤ mk_out ct.network.to_capacity.c S := + begin + have no_overflow: mk_out afn.f S ≤ mk_out afn.network.to_capacity.c S := + begin + unfold mk_out, + have flowLEcut: ∀ (x y : V), (afn.f x y ≤ afn.network.to_capacity.c x y) := by {exact afn.no_overflow}, + -- exact finset.sum_le_sum flowLEcut, + sorry, + end, + unfold mk_out, + unfold mk_out at no_overflow, + rw same_net at no_overflow, + exact no_overflow, + end, + have lemma3: F_value afn ≤ mk_out afn.f S := + begin + rw lemma1, + have obs: mk_out afn.f S = mk_out afn.f S + 0 := by rw [add_zero], + rw obs, + simp, + unfold mk_in, + have nonneg_flow: ∀ v ∈ V', ∀ u ∈ S, afn.f u v ≥ 0 := by {intros v vInV' u uInS, exact afn.non_neg_flow u v}, -- meta errors again? + exact finset.sum_nonneg nonneg_flow, + end, + apply le_trans lemma3 lemma2, +end + +lemma zero_left_move {a b c d : ℝ} : (0 = a + b - c - d) -> (d - b = a - c) := by {intro h, linarith} + +def is_max_flow_network {V : Type*} [inst' : fintype V] + (fn: active_flow_network V) : Prop := ∀ fn' : active_flow_network V, fn.network = fn'.network → F_value fn' ≤ F_value fn + +def is_min_cut {V : Type*} [inst' : fintype V] + (fn: cut V) : Prop := ∀ fn' : cut V, fn.network = fn'.network → cut_cap fn ≤ cut_cap fn' + +lemma max_flow_criterion {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (ct : cut V) (hsame_network: afn.network = ct.network): + cut_cap ct = F_value afn -> is_max_flow_network afn := +begin + intro eq, + intro fn, + intro same_net, + rw ← eq, + have same_network: fn.network = ct.network := by {rw ← same_net, exact hsame_network,}, + exact weak_duality (fn) (ct) (same_network), +end + +lemma min_cut_criterion {V : Type*} [inst' : fintype V] + (afn : active_flow_network V) (ct : cut V) (same_net: afn.network = ct.network) : cut_cap ct = F_value afn -> is_min_cut ct := +begin + intro eq, + intros cut eq_net, + rw eq, + have h: afn.network = cut.network := by {rw same_net, exact eq_net,}, + exact weak_duality (afn) (cut) (h), +end + +/-! + We now define our residual network. Our goal is to prove no_augm_path. +-/ + +noncomputable +def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow + (afn : active_flow_network V) + (u v : V) : ℝ := + if afn.network.is_edge u v + then afn.network.c u v - afn.f u v + else if afn.network.is_edge v u + then afn.f v u + else 0 + +structure residual_network (V : Type*) [inst' : fintype V] := + (afn : active_flow_network V) + (f' : V -> V -> ℝ) + (f_def : f' = mk_rsf afn) + (is_edge : V -> V -> Prop) + (is_edge_def : is_edge = λ u v, f' u v > 0 ) + +noncomputable +def mk_rsn {V : Type*} [fintype V] -- stays for residual network + (afn : active_flow_network V) : residual_network V := ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl ⟩ + +universe u + +/- + We define a path structure indicating if there is a path between two vertices given the edges in the graph. +-/ + +inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) +| nil : path a +| cons : Π {b c : V}, path b → (is_edge b c) → path c + +def no_augumenting_path {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : Prop := ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) + +def path.in {V : Type u } + {is_edge : V -> V -> Prop} + (u v : V) + {s : V} : ∀ {t : V}, path is_edge s t -> Prop + | t (@path.nil _ is_edge' a) := u = v + | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) + +lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := +begin + intros u v, + cases rsn, + simp only, + rw rsn_f_def, + unfold mk_rsf, + have tmp := classical.em (rsn_afn.network.to_capacity.to_strange_digraph.is_edge u v), + cases tmp, + { + simp only [tmp, if_true, sub_nonneg, rsn_afn.no_overflow], + }, + { + simp only [tmp, if_false], clear tmp, + have tmp := classical.em (rsn_afn.network.to_capacity.to_strange_digraph.is_edge v u), + cases tmp, + { + have h := rsn_afn.non_neg_flow v u, + simp only [tmp, h, if_true], + linarith, + }, + { + simp only [tmp, if_false], + }, + }, +end + +/-! + Here is our second big lemma, if the active flow is maximum, then no augmenting path exists in the residual network. +-/ + +lemma no_augm_path {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : (is_max_flow_network rsn.afn) -> no_augumenting_path rsn := +begin + intros max_flow v exists_path, + by_contradiction is_sink, + set s := rsn.afn.network.source, + set t := rsn.afn.network.sink, + set vertices := {s} ∪ { x | (∃ y: V, exists_path.in x y) }, -- the set of all vertices in the augmenting path + set d := 0, + -- set flows := { rsn.f' x y | exists_path.in x y }, -- set of reals, why it doesn't work? + -- set d := flows.min, -- the minimum flow in the augmenting path + have pos: 0 < d := by sorry, -- by definition of is_edge in the residual network + set better_flow: active_flow_network V := + ⟨rsn.afn.network, + (λ u v : V, if exists_path.in u v then rsn.afn.f u v + d + else if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v), + begin -- source ≠ sink + exact rsn.afn.sourceNotSink, + end, + begin -- non_neg_flow + intros u v, + by_cases h: exists_path.in u v, + { + have h1: rsn.afn.f u v ≥ 0 := by {exact rsn.afn.non_neg_flow u v}, + have h2: d ≥ 0 := by {linarith}, -- needs to be changed, we can use the definition of rsn and split into cases + linarith, + }, + { + by_cases h': exists_path.in v u, + { + have h1: rsn.afn.f u v ≥ d := by sorry, -- d is the minimum flow in the residual network, so use the definition of rsn and split into cases + linarith, + }, + { + -- exact rsn.afn.non_neg_flow u v, -- should be correct, why is not working? + linarith, + }, + }, + end, + begin -- no_overflow + intros u v, + by_cases h: exists_path.in u v, + { + have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := by sorry, -- again, use def of rsn and split into cases + -- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := by def of rsn + -- have h3: d ≤ rsn.f' u v := by minimality of d + -- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, + -- exact le_trans h4 h2 + linarith, + }, + { + by_cases h': exists_path.in v u, + { + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := by {exact rsn.afn.no_overflow u v}, + linarith, + }, + { + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := by {exact rsn.afn.no_overflow u v}, + linarith, + }, + }, + end, + begin --noEdgesInSource + exact rsn.afn.noEdgesInSource, + end, + begin --noEdgesOutSink + exact rsn.afn.noEdgesOutSink, + end, + begin -- conservation + intros v vNotSinkSource, + by_cases h: v ∈ vertices, + { + sorry, + }, + { + sorry, + -- have h1: ∀ u : V, ¬exists_path.in u v := + -- begin + -- by_contradiction h', + -- have contr: ∃u: + -- end, + }, + end + ⟩, + have flow_value: F_value better_flow = F_value rsn.afn + d := + begin + unfold F_value, + have h1: mk_out better_flow.f {better_flow.network.source} = mk_out rsn.afn.f {rsn.afn.network.source} + d := by sorry, + -- take the edge with the added flow + have h2: mk_in better_flow.f {better_flow.network.source} = mk_in rsn.afn.f {rsn.afn.network.source} := by {linarith}, + rw [h1,h2], + linarith + end, + have le: F_value rsn.afn ≥ F_value better_flow := + begin + have same_net: better_flow.network = rsn.afn.network := by {simp}, + unfold is_max_flow_network at max_flow, + exact max_flow better_flow same_net, + end, + have lt: F_value rsn.afn < F_value better_flow := + begin + rw flow_value, + have h1: F_value rsn.afn - F_value rsn.afn < d := + begin + have eq: F_value rsn.afn - F_value rsn.afn = 0 := by ring, + rw eq, + linarith + end, + have h2: F_value rsn.afn < F_value rsn.afn + d := by exact lt_add_of_sub_left_lt h1, + exact gt_iff_lt.2 h2, + end, + have nlt: ¬F_value rsn.afn < F_value better_flow := by exact not_lt_of_ge le, + exact absurd lt nlt, +end + +/-! + Now, we will prove that there exists a cut with value equal to the max flow in the same network. + We will use a constructive proof, so we will construct our minimum cut. +-/ + +noncomputable +def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut + (rsn : residual_network V) : finset V := + {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset + +noncomputable +def mk_cut_from_S {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (hno_augumenting_path : no_augumenting_path rsn) + (S : finset V) (hS : S = mk_cut_set rsn) : cut V := +⟨rsn.afn.network, S, V' \ S, + begin + rw hS, + unfold mk_cut_set, + simp only [set.mem_to_finset, set.mem_set_of_eq], + exact exists.intro path.nil trivial, + end, + begin + rw hS, + unfold mk_cut_set, + simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], + intro p, + unfold no_augumenting_path at hno_augumenting_path, + specialize hno_augumenting_path rsn.afn.network.sink , + simp only [eq_self_iff_true, not_true] at hno_augumenting_path, + apply exists.elim p, + intros p h, + specialize hno_augumenting_path p, + exact hno_augumenting_path, + end, +rfl⟩ + +lemma s_t_not_connected {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (S : finset V) (hS : S = mk_cut_set rsn) : + ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := +begin + intros u h_u_in_S v h_v_in_T is_edge_u_v, + rw hS at *, + unfold mk_cut_set at *, + simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, + apply exists.elim h_u_in_S, + intros p _, + have tmp := path.cons p is_edge_u_v, + apply h_v_in_T, + exact exists.intro tmp trivial, +end + +lemma residual_capacity_zero {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (ct : cut V) + (h_eq_network : rsn.afn.network = ct.network) + (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : + ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := +begin + intros u h_u_in_S v h_v_in_T, + specialize h u h_u_in_S v h_v_in_T, + rw rsn.is_edge_def at h, + simp only [not_lt] at h, + have hge := residual_capacity_non_neg rsn u v, + exact ge_antisymm hge h, +end + +lemma min_max_cap_flow {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (ct : cut V) + (h_eq_network : rsn.afn.network = ct.network) + (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : + (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ + (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := +begin + split, + { + intros u h_u_in_S v h_v_in_T, + specialize h u h_u_in_S v h_v_in_T, + rw rsn.f_def at h, + unfold mk_rsf at h, + have tmp := classical.em (rsn.afn.network.to_capacity.to_strange_digraph.is_edge u v), + cases tmp, + { + simp only [tmp, if_true] at h, + linarith, + }, + { + simp only [tmp, if_false, ite_eq_right_iff] at h, + have foo := rsn.afn.network.vanishes u v tmp, + rw foo, + clear tmp h, + have foo := rsn.afn.non_neg_flow u v, + have bar := rsn.afn.no_overflow u v, + linarith, + } + }, + { + intros v h_v_in_T u h_u_in_S, + specialize h u h_u_in_S v h_v_in_T, + rw rsn.f_def at h, + unfold mk_rsf at h, + have tmp := classical.em (rsn.afn.network.to_capacity.to_strange_digraph.is_edge u v), + cases tmp, + { + have foo := rsn.afn.network.hnonsymmetric u v, + simp only [not_and] at foo, + specialize foo tmp, + have bar := rsn.afn.non_neg_flow v u, + have baz := rsn.afn.no_overflow v u, + have blurg := rsn.afn.network.vanishes v u foo, + linarith, + }, + { + simp only [tmp, if_false, ite_eq_right_iff] at h, + clear tmp, + have tmp := classical.em (rsn.afn.network.to_capacity.to_strange_digraph.is_edge v u), + cases tmp, + { + exact h tmp, + }, + { + have foo := rsn.afn.non_neg_flow v u, + have bar := rsn.afn.no_overflow v u, + have baz := rsn.afn.network.vanishes v u tmp, + linarith, + }, + }, + } +end + +lemma f_value_eq_out {V : Type*} [inst' : fintype V] + (ct : cut V) + (afn : active_flow_network V) + (h_eq_network : afn.network = ct.network) + (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : + F_value afn = mk_out afn.f ct.S := +begin + dsimp [F_value], + rw flow_value_global_ver afn ct h_eq_network, + dsimp [mk_in], + simp_rw [← ct.Tcomp], + simp only [sub_eq_self], + have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = ∑ x in ct.T, ∑ y in ct.S, 0 := + begin + apply finset.sum_congr rfl, + intros x x_in_T, + apply finset.sum_congr rfl, + intros y y_in_S, + exact h x x_in_T y y_in_S, + end, + rw sum_eq_sum_zero, + simp only [sum_const_zero], +end + +lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] + (ct : cut V) + (afn : active_flow_network V) + (h_eq_network : afn.network = ct.network) + (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ + (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : + mk_out afn.f ct.S = cut_cap ct := +begin + cases h with h_flow_eq_cap h_flow_zero, + dsimp [cut_cap, mk_out], + apply finset.sum_congr rfl, + intros x x_in_S, + rw ← ct.Tcomp at *, + apply finset.sum_congr rfl, + intros y y_in_T, + simp [h_eq_network, h_flow_eq_cap x x_in_S y y_in_T], +end + +lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] + (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) + (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : + ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := +begin + apply finset.sum_congr rfl, + intros a a_in_A, + apply finset.sum_congr rfl, + intros b b_in_B, + exact eq_on_res a a_in_A b b_in_B, +end + +/-! + Here is our last big lemma, if there is no augmenting path in the resiual network, + then there exists a cut with a capacity equal to the value of the active flow in the same network. +-/ + +lemma existence_of_a_cut {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (hno_augumenting_path : no_augumenting_path rsn) : + (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := +begin + let S : finset V := mk_cut_set rsn, + let T := V' \ S, + have h1: S = mk_cut_set rsn := by refl, + let min_cut := mk_cut_from_S (rsn) (hno_augumenting_path) (S) (h1), + have eq_net : rsn.afn.network = min_cut.network := by refl, + have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := by {intros x y, split, intro heq, linarith, intro heq, linarith}, + have cf_vanishes_on_pipes: ∀u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := + begin + intros u uInS v vInNS, + by_contradiction h, + have edge: rsn.is_edge u v := + begin + by_contradiction h', + have contr: rsn.f' u v = 0 := + begin + rw rsn.is_edge_def at h', + simp only [not_lt] at h', + have hge := residual_capacity_non_neg rsn u v, + exact ge_antisymm hge h', + end, + contradiction + end, + have notEdge: ¬ rsn.is_edge u v := by {exact s_t_not_connected rsn S h1 u uInS v vInNS}, + contradiction + end, + have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, (rsn.afn.network.is_edge u v) → + (rsn.afn.network.c u v - rsn.afn.f u v = 0) := + begin + intros u u_in_S v v_in_T is_edge, + have t: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := by {unfold mk_rsf, simp only [is_edge, if_true]}, + rw ← t, + have r: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, + rw r, + exact cf_vanishes_on_pipes u u_in_S v v_in_T, + end, + have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = rsn.afn.network.c u v := + begin + intros u u_in_S v v_in_T, + cases classical.em (rsn.afn.network.is_edge u v), + { + rw subtract (rsn.afn.f u v) (rsn.afn.network.to_capacity.c u v), + have mk_cf_spec: (rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v) := + begin + rw rsn.f_def, + unfold mk_rsf, + simp only [h, if_true], + end, + rw ← mk_cf_spec, + exact cf_vanishes_on_pipes u u_in_S v v_in_T, + }, + { + rw rsn.afn.network.vanishes u v h, + exact f_vanishes_outside_edge (rsn.afn) (u) (v) (h), + }, + end, + have no_backflow: ∀ u ∈ V' \ min_cut.S, ∀ v ∈ min_cut.S, rsn.afn.f u v = 0 := + begin + intros u uInNS v vInS, + exact (min_max_cap_flow rsn min_cut eq_net cf_vanishes_on_pipes).2 u uInNS v vInS, + end, + have func0 : ∀ u ∈ V' \ min_cut.S, ∀ v ∈ min_cut.S, (λ u v, 0) u v = 0 := by {simp}, + have no_backflow_func: ∀ u ∈ V' \ min_cut.S, ∀ v ∈ min_cut.S, rsn.afn.f u v = (λ u v, 0) u v := + begin + intros u uInNS v vInS, + rw no_backflow u uInNS v vInS, + rw func0 u uInNS v vInS, + simp + end, + have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := + begin + rw F_value, + simp only, + rw flow_value_global_ver rsn.afn min_cut eq_net, + have no_input : mk_in rsn.afn.f min_cut.S = 0 := + begin + rw mk_in, + rw eq_on_res_then_on_sum (V' \ min_cut.S) (min_cut.S) (rsn.afn.f) (λ u v, 0) (no_backflow_func), -- type mismatch because of ↑, why is this arrow arriving? + simp only [sum_const_zero], + end, + rw no_input, + simp only [sub_zero], + have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := + begin + unfold mk_out, + rw eq_on_res_then_on_sum (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), + end, + rw flow_eq_cap_on_cut, + refl, + end, + use min_cut, + split, + {exact eq_net}, + exact cut_eq_flow +end + +/-! + Finally, our biggest result, the max flow min cut theorem! + If a maximum flow exists, its value is equal to the capacity of the min cut in the same network. +-/ + +theorem max_flow_min_cut {V : Type*} [inst' : fintype V] + (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : + (is_max_flow_network rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := +begin + rintros ⟨max_flow, min_cut⟩ , + have noAugPath: no_augumenting_path rsn := by {exact no_augm_path rsn max_flow}, + have existsCut: ∃cut:cut V, rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn := by {exact existence_of_a_cut rsn noAugPath}, + have max_flow_min_cut: ∀ cut:cut V, (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := + begin + rintros cut ⟨same_net, eq⟩ , + have h1: is_min_cut cut := by {exact min_cut_criterion rsn.afn cut same_net eq}, + have h2: is_min_cut c := by {exact min_cut}, + have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, + have same_net2: c.network = cut.network := by rw ← same_net1, + have same_val: cut_cap cut = cut_cap c := + begin + have le1: cut_cap cut ≤ cut_cap c := + begin + unfold is_min_cut at h1, + exact h1 c same_net1, + end, + have le2: cut_cap c ≤ cut_cap cut := + begin + unfold is_min_cut at h2, + exact h2 cut same_net2, + end, + exact le_antisymm le1 le2, + end, + rw ← eq, + exact same_val, + end, + exact exists.elim existsCut max_flow_min_cut, +end From 85b042f9e68c417b9db6fbb1d9c433fc79b4cac7 Mon Sep 17 00:00:00 2001 From: amilchew Date: Thu, 16 Mar 2023 14:53:54 +0000 Subject: [PATCH 02/28] feat(max_flow_min_cut)first_draft --- src/combinatorics/quiver/max_flow_min_cut.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 769440e3a02b9..59858f73077ce 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -11,7 +11,7 @@ import data.finset import tactic.induction /-! -# Max flow min cut theorem +# Max flow Min cut theorem In this file we will prove the max-flow min-cut theorem, stating that if a maximum flow exists in a flow network, then its value is equal to the capacity of a minimum cut in the same network. From 8f0d198ddbb584a60ef08d18a4aa82a1cf09a543 Mon Sep 17 00:00:00 2001 From: amilchew Date: Thu, 16 Mar 2023 15:07:15 +0000 Subject: [PATCH 03/28] feat(max_flow_min_cut)_first_draft --- .../quiver/max_flow_min_cut.lean | 71 ++++++++++++------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 59858f73077ce..558ba37be7249 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -1,9 +1,10 @@ /- -Copyright (c) 2023 Aleksandar Milchev. All rights reserved. +Copyright (c) 2023 'Aleksandar Milchev'. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Author: Aleksandar Milchev +Author: 'Aleksandar Milchev' -/ + import data.real.basic import data.set import tactic @@ -13,7 +14,8 @@ import tactic.induction /-! # Max flow Min cut theorem -In this file we will prove the max-flow min-cut theorem, stating that if a maximum flow exists in a flow network, +In this file we will prove the max-flow min-cut theorem, +stating that if a maximum flow exists in a flow network, then its value is equal to the capacity of a minimum cut in the same network. ## Main results @@ -237,8 +239,10 @@ begin have h: S ⊆ V' := by {exact finset.subset_univ S}, have hyp: ∑ (y : V) in V' \ S, ∑ (x : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ u in V', ∑ v in S, afn.f v u := by {exact finset.sum_sdiff h}, - have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := by {exact finset.sum_comm}, - have fin: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := by {exact finset.sum_comm}, + have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := + by {exact finset.sum_comm}, + have fin: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := + by {exact finset.sum_comm}, rw obvs at hyp, rw hyp, exact fin, @@ -307,7 +311,8 @@ end lemma flow_value_global_ver {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network) : - mk_out afn.f {afn.network.source} - mk_in afn.f {afn.network.source} = mk_out afn.f ct.S - mk_in afn.f ct.S := + mk_out afn.f {afn.network.source} - mk_in afn.f {afn.network.source} = + mk_out afn.f ct.S - mk_in afn.f ct.S := begin set S := ct.S, set T := ct.T, @@ -330,13 +335,15 @@ begin have same_sink: t = ct.network.sink := by {exact (same_source_and_sink afn ct same_net).2}, have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, have Tcomp : T = univ \ S := by {exact ct.Tcomp}, - have foo: S = univ \ (univ \ S) := by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, + have foo: S = univ \ (univ \ S) := + by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, rw Scomp at *, -- exact set.not_mem_diff_of_mem tInT, sorry, end, - have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} = mk_out afn.f {s} - mk_in afn.f {s} := + have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} = + mk_out afn.f {s} - mk_in afn.f {s} := begin have h3: s ∉ (S \ {s}) := by sorry, -- {set.not_mem_diff_of_mem singleton}, have eq: mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s}) = 0 := @@ -405,7 +412,8 @@ begin have same_sink: t = ct.network.sink := by {exact (same_source_and_sink afn ct same_net).2}, have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, have Tcomp : T = univ \ S := by {exact ct.Tcomp}, - have foo: S = univ \ (univ \ S) := by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, + have foo: S = univ \ (univ \ S) := + by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, rw Scomp at *, -- exact set.not_mem_diff_of_mem tInT, @@ -421,7 +429,8 @@ begin have no_overflow: mk_out afn.f S ≤ mk_out afn.network.to_capacity.c S := begin unfold mk_out, - have flowLEcut: ∀ (x y : V), (afn.f x y ≤ afn.network.to_capacity.c x y) := by {exact afn.no_overflow}, + have flowLEcut: ∀ (x y : V), (afn.f x y ≤ afn.network.to_capacity.c x y) := + by {exact afn.no_overflow}, -- exact finset.sum_le_sum flowLEcut, sorry, end, @@ -437,7 +446,8 @@ begin rw obs, simp, unfold mk_in, - have nonneg_flow: ∀ v ∈ V', ∀ u ∈ S, afn.f u v ≥ 0 := by {intros v vInV' u uInS, exact afn.non_neg_flow u v}, -- meta errors again? + have nonneg_flow: ∀ v ∈ V', ∀ u ∈ S, afn.f u v ≥ 0 := + by {intros v vInV' u uInS, exact afn.non_neg_flow u v}, -- meta errors again? exact finset.sum_nonneg nonneg_flow, end, apply le_trans lemma3 lemma2, @@ -446,7 +456,8 @@ end lemma zero_left_move {a b c d : ℝ} : (0 = a + b - c - d) -> (d - b = a - c) := by {intro h, linarith} def is_max_flow_network {V : Type*} [inst' : fintype V] - (fn: active_flow_network V) : Prop := ∀ fn' : active_flow_network V, fn.network = fn'.network → F_value fn' ≤ F_value fn + (fn: active_flow_network V) : Prop := + ∀ fn' : active_flow_network V, fn.network = fn'.network → F_value fn' ≤ F_value fn def is_min_cut {V : Type*} [inst' : fintype V] (fn: cut V) : Prop := ∀ fn' : cut V, fn.network = fn'.network → cut_cap fn ≤ cut_cap fn' @@ -464,7 +475,8 @@ begin end lemma min_cut_criterion {V : Type*} [inst' : fintype V] - (afn : active_flow_network V) (ct : cut V) (same_net: afn.network = ct.network) : cut_cap ct = F_value afn -> is_min_cut ct := + (afn : active_flow_network V) (ct : cut V) (same_net: afn.network = ct.network) : + cut_cap ct = F_value afn -> is_min_cut ct := begin intro eq, intros cut eq_net, @@ -496,7 +508,8 @@ structure residual_network (V : Type*) [inst' : fintype V] := noncomputable def mk_rsn {V : Type*} [fintype V] -- stays for residual network - (afn : active_flow_network V) : residual_network V := ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl ⟩ + (afn : active_flow_network V) : residual_network V := + ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl ⟩ universe u @@ -509,7 +522,8 @@ inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u | cons : Π {b c : V}, path b → (is_edge b c) → path c def no_augumenting_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : Prop := ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) + (rsn : residual_network V) : Prop := + ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) def path.in {V : Type u } {is_edge : V -> V -> Prop} @@ -565,7 +579,7 @@ begin set better_flow: active_flow_network V := ⟨rsn.afn.network, (λ u v : V, if exists_path.in u v then rsn.afn.f u v + d - else if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v), + else if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v), begin -- source ≠ sink exact rsn.afn.sourceNotSink, end, @@ -603,11 +617,13 @@ begin { by_cases h': exists_path.in v u, { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := by {exact rsn.afn.no_overflow u v}, + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := + by {exact rsn.afn.no_overflow u v}, linarith, }, { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := by {exact rsn.afn.no_overflow u v}, + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := + by {exact rsn.afn.no_overflow u v}, linarith, }, }, @@ -637,7 +653,8 @@ begin have flow_value: F_value better_flow = F_value rsn.afn + d := begin unfold F_value, - have h1: mk_out better_flow.f {better_flow.network.source} = mk_out rsn.afn.f {rsn.afn.network.source} + d := by sorry, + have h1: mk_out better_flow.f {better_flow.network.source} = mk_out rsn.afn.f {rsn.afn.network.source} + d := + by sorry, -- take the edge with the added flow have h2: mk_in better_flow.f {better_flow.network.source} = mk_in rsn.afn.f {rsn.afn.network.source} := by {linarith}, rw [h1,h2], @@ -866,7 +883,8 @@ begin have h1: S = mk_cut_set rsn := by refl, let min_cut := mk_cut_from_S (rsn) (hno_augumenting_path) (S) (h1), have eq_net : rsn.afn.network = min_cut.network := by refl, - have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := by {intros x y, split, intro heq, linarith, intro heq, linarith}, + have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := + by {intros x y, split, intro heq, linarith, intro heq, linarith}, have cf_vanishes_on_pipes: ∀u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := begin intros u uInS v vInNS, @@ -886,11 +904,12 @@ begin have notEdge: ¬ rsn.is_edge u v := by {exact s_t_not_connected rsn S h1 u uInS v vInNS}, contradiction end, - have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, (rsn.afn.network.is_edge u v) → - (rsn.afn.network.c u v - rsn.afn.f u v = 0) := + have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, + (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := begin intros u u_in_S v v_in_T is_edge, - have t: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := by {unfold mk_rsf, simp only [is_edge, if_true]}, + have t: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := + by {unfold mk_rsf, simp only [is_edge, if_true]}, rw ← t, have r: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, rw r, @@ -967,8 +986,10 @@ theorem max_flow_min_cut {V : Type*} [inst' : fintype V] begin rintros ⟨max_flow, min_cut⟩ , have noAugPath: no_augumenting_path rsn := by {exact no_augm_path rsn max_flow}, - have existsCut: ∃cut:cut V, rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn := by {exact existence_of_a_cut rsn noAugPath}, - have max_flow_min_cut: ∀ cut:cut V, (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := + have existsCut: ∃cut:cut V, rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn := + by {exact existence_of_a_cut rsn noAugPath}, + have max_flow_min_cut: ∀ cut:cut V, + (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := begin rintros cut ⟨same_net, eq⟩ , have h1: is_min_cut cut := by {exact min_cut_criterion rsn.afn cut same_net eq}, From be0bef3562b6306b4c57ffe8910cc083d5a5f8bc Mon Sep 17 00:00:00 2001 From: Aleksandar Milchev <98773527+amilchew@users.noreply.github.com> Date: Thu, 16 Mar 2023 17:27:41 +0000 Subject: [PATCH 04/28] Proof of the Max-Flow Min-Cut theorem LaTeX is used. --- Max-Flow-Min-Cut-Proof.pdf | Bin 0 -> 144217 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Max-Flow-Min-Cut-Proof.pdf diff --git a/Max-Flow-Min-Cut-Proof.pdf b/Max-Flow-Min-Cut-Proof.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9ba8d3272ce4512d934a8d30184cb7bdbacf5c30 GIT binary patch literal 144217 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 z zwXs0pIah2X{V@J~BGxP>ePd>Ku1qIqe8sHoZ(RAlrT)u}0lX6jc)gRl#GH`blGJ2t zQsXqmU_Z^@4p6W1bJEiV#EHRpzUFcoyPgfQdj`Sp+#8rJR$s-EYy^H?-SqjMY2#>< z^Kw%o|NQ5g$oY1xq06uVjC##tz$!(~m5LytCj|Gkxzb~MGo?NKavcEObu-<%of>p8 zIg3q+t{sv>QvkMAOss#>T<<9asl>E~CmB#jwH93E%2-@>8bo0#c&%Uyc0ShdfSY2J z1QRZG1&+!(fxruN0+g~pF&BvggS3nFB{qzw zy(vN*r8IK;N$>%Rcfzmk)frH7v@AU!Bf7N6gh^;5n=GY8PIe<%hL?gPkCY=#%%IA? z;?EJ207$V7bRNeExYI(@YK{N{0VAVu;uG?dKpr+cdy4vqW-g<`DLJZ1e6fYqU! zv4KH8W6w*g+dRXs1WcFd+oXa9aEShknV1}k`arQoTtm~IW(FrVSz0XviiXb(5QO#8 zX5yX38tr9UU$mW0)UWv}WO@9;`S~O=w~i*VF-J2tRocV_*=6zUcWbnPMsE)jl*QM=x%tr@Dbk_3J`aVo*vLFNW`N+2zQo(h4t1-+H~&3+o zVp8N<0&Kc-BB>c8M?79Uu5=2ChXgv5xtE%PI<#&HQ7>yoCvX*CtADo=Mc-i;yjf9X z1pQJ6c44L{$u`D8mWTP|CCKiLPt$7I(;H^k|=mk>|_^K1DN1W@a zYvHv8u}V{IbiFD<#o!bTF;W0@Iw38Eef=RxbeP_I$EK9qE%diBcuylAvDSQ_P(uT8 z6=t+&a&NVQ@uz3VwCz~u?3Y7m%VglQL-e(fu*fOVw;rW*ynzLL1npOS%^+d@oEls1 zC;UqA57+vPSnEM*~Ibp+uFd{MA*d0&iMC6?tcx5V!&r$Vq^F} zSB&^99E`00=jwm={~&-Au_<^a6Dk%_iKi0g0nH1v)n_?f`)y+#bj33yT(%u+dR2Fwd?M=7 z>ioTc60d@lM2YOvK?~_O1|XpUMsffELkjNKC&bs)6=I%-d_n`e+ZJkTE38LP{}GXQ z6zX$um&S-0cxbFc=N}k=L_h@%A~6mkG0~^z2LVg`M*DL?3QRu0Gbhdu4P~y+K<A0&8OyJ7D)vTMNJ^2!N21k`na!dyLLfur&w41~%_=cqTXdjDcuH()Sn1Q(({i zwfReJ8rjn}4hrh*?98(_b0c4#x=sNA`MsUH1oTPb8lOT62JwZ3F(1fQ@FV>j=ng34 z)%fvi&0`h$5ZI9qz`YwJnn!>A3Ih*=cm%e~1`e}$1Heg3K8bgq%?AQ;`(h1XPh4$S%zaB|3<+r9zLI2D;ZR8n@1kd=eOH#E>&C| zy}vM#y+78ddp~x?KeBH-#d3dL@;imTyLKwyDS$00~dPGk#2y;J>{Zhd^t;k1ar94KR7BQeRsU_y{mgo z-a6_qP)Hwt3%69}w#kcVF+=Nq3e)&rxAbJ41dZg|)!iOz#h`hi!9Hryw{;=JJ`V

G{^77Ky}<)Kr<L2G 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 literal 0 HcmV?d00001 From accc92c478b21d9797aae63c48c97573459c2d9e Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 17 Mar 2023 00:25:01 +0000 Subject: [PATCH 05/28] feat(combinatorics/quiver/max_flow_min_cut)first_draft --- .../quiver/max_flow_min_cut.lean | 124 +++++++++++++----- 1 file changed, 91 insertions(+), 33 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 558ba37be7249..91c979f32f27c 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -1,14 +1,14 @@ /- -Copyright (c) 2023 'Aleksandar Milchev'. All rights reserved. +Copyright (c) 2023 Aleksandar Milchev. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Author: 'Aleksandar Milchev' +Author: Aleksandar Milchev -/ import data.real.basic import data.set import tactic -import data.finset +import data.finset.basic import tactic.induction /-! @@ -21,6 +21,7 @@ then its value is equal to the capacity of a minimum cut in the same network. ## Main results - `weak_duality` : the value of every flow is less than or equal to the capacity of every cut. + direct consequences : - the value of a max flow is always less than or equal to the capacity of a min cut. - `max_flow_criterion` : if a flow value is equal to a cut capacity in the same flow network, then the flow is maximum. @@ -106,7 +107,8 @@ def cut_cap {V : Type*} [inst' : fintype V] -- stays for capacity of the cut (c : cut V) : ℝ := mk_out c.network.c c.S lemma f_vanishes_outside_edge {V : Type*} [fintype V] - (afn : active_flow_network V) (u : V) (v : V) (not_edge: ¬afn.network.is_edge u v): afn.f u v = 0 := + (afn : active_flow_network V) (u : V) (v : V) (not_edge: ¬afn.network.is_edge u v) : + afn.f u v = 0 := begin have cap_is_zero: afn.network.c u v = 0 := begin @@ -155,7 +157,8 @@ begin have foo : (λ (x : V), afn.f x p) p = afn.f p p := rfl, simp only [congr_fun], rw f_zero_zero afn p, - have bar : ∑ (x : V) in univ \ {p}, afn.f x p + 0 = (λp', ∑ (x : V) in univ \ {p'}, afn.f x p' ) p := by simp only [add_zero], + have bar : ∑ (x : V) in univ \ {p}, afn.f x p + 0 = + (λ p', ∑ (x : V) in univ \ {p'}, afn.f x p') p := by simp only [add_zero], rw bar, clear bar, rw ← @finset.sum_singleton _ _ p (λp', ∑ (x : V) in univ \ {p'}, afn.f x p' ) _, simp only [mk_in, sum_singleton], @@ -173,7 +176,8 @@ begin have foo : (λ (x : V), afn.f p x) p = afn.f p p := rfl, simp only [congr_fun], rw f_zero_zero afn p, - have bar : ∑ (x : V) in univ \ {p}, afn.f p x + 0 = (λp', ∑ (x : V) in univ \ {p'}, afn.f p' x) p := by simp only [add_zero], + have bar : ∑ (x : V) in univ \ {p}, afn.f p x + 0 = + (λ p', ∑ (x : V) in univ \ {p'}, afn.f p' x) p := by simp only [add_zero], rw bar, clear bar, rw ← @finset.sum_singleton _ _ p (λp', ∑ (x : V) in univ \ {p'}, afn.f p' x) _, simp only [mk_out, sum_singleton], @@ -226,9 +230,12 @@ begin begin unfold mk_in, have h: S ⊆ V' := by {exact finset.subset_univ S}, - have hyp: ∑ (x : V) in V' \ S, ∑ (y : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v = ∑ u in V', ∑ v in S, afn.f u v := + have hyp: + ∑ (x : V) in V' \ S, ∑ (y : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v + = ∑ u in V', ∑ v in S, afn.f u v := by {exact finset.sum_sdiff h}, - have fin: ∑ u in V', ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := by {exact finset.sum_comm}, + have fin: ∑ u in V', ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := + by {exact finset.sum_comm}, rw hyp, exact fin, end, @@ -237,9 +244,12 @@ begin unfold mk_out, rw finset.sum_comm, have h: S ⊆ V' := by {exact finset.subset_univ S}, - have hyp: ∑ (y : V) in V' \ S, ∑ (x : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ u in V', ∑ v in S, afn.f v u := + have hyp: + ∑ (y : V) in V' \ S, ∑ (x : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = + ∑ u in V', ∑ v in S, afn.f v u := by {exact finset.sum_sdiff h}, - have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := + have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = + ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := by {exact finset.sum_comm}, have fin: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := by {exact finset.sum_comm}, @@ -306,7 +316,8 @@ begin end /- - This lemma has issues, I am confused how finsets are handled. The complains mention "meta variables". + This lemma has issues, I am confused how finsets are handled. + The complains mention "meta variables". -/ lemma flow_value_global_ver {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (ct : cut V) @@ -342,8 +353,8 @@ begin -- exact set.not_mem_diff_of_mem tInT, sorry, end, - have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} = - mk_out afn.f {s} - mk_in afn.f {s} := + have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} + = mk_out afn.f {s} - mk_in afn.f {s} := begin have h3: s ∉ (S \ {s}) := by sorry, -- {set.not_mem_diff_of_mem singleton}, have eq: mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s}) = 0 := @@ -377,17 +388,19 @@ begin exact add_zero_middle (mk_out afn.f {s}) (mk_in afn.f {s}) (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) eq, end, /- The next two equalities use sum over two elements, so I am not sure how to resolve them. -/ - have sum1: mk_out afn.f {s} + mk_out afn.f (S \ {s}) = mk_out afn.f S := by sorry, -- {unfold mk_out, rw finset.sum_sdiff hS}, - have sum2: mk_in afn.f (S \ {s}) + mk_in afn.f {s} = mk_in afn.f S := by sorry, -- {unfold mk_in, rw finset.sum_sdiff hS}, + have sum1: mk_out afn.f {s} + mk_out afn.f (S \ {s}) = mk_out afn.f S := + by sorry, -- {unfold mk_out, rw finset.sum_sdiff hS}, + have sum2: mk_in afn.f (S \ {s}) + mk_in afn.f {s} = mk_in afn.f S := + by sorry, -- {unfold mk_in, rw finset.sum_sdiff hS}, rw ← expand, rw add_sub, - rw group_minus (mk_out afn.f {s}) (mk_out afn.f (S \ {s})) (mk_in afn.f (S \ {s})) (mk_in afn.f {s}), + rw group_minus (mk_out afn.f {s}) (mk_out afn.f (S \ {s})) (mk_in afn.f (S \ {s})) (mk_in afn.f {s}), rw sum1, rw sum2, end /-! Here is our first big lemma, weak duality. - It states that the value of every flow is less than or equal to the capacity of every cut in the same network. + Every flow is less than or equal to the capacity of every cut in the same network. -/ lemma weak_duality {V: Type*} [inst' : fintype V] @@ -453,7 +466,8 @@ begin apply le_trans lemma3 lemma2, end -lemma zero_left_move {a b c d : ℝ} : (0 = a + b - c - d) -> (d - b = a - c) := by {intro h, linarith} +lemma zero_left_move {a b c d : ℝ} : (0 = a + b - c - d) -> (d - b = a - c) := +by {intro h, linarith} def is_max_flow_network {V : Type*} [inst' : fintype V] (fn: active_flow_network V) : Prop := @@ -514,7 +528,8 @@ def mk_rsn {V : Type*} [fintype V] -- stays for residual network universe u /- - We define a path structure indicating if there is a path between two vertices given the edges in the graph. + We define a path structure indicating if there is a path between two vertices, + given the edges in the graph. -/ inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) @@ -561,7 +576,8 @@ begin end /-! - Here is our second big lemma, if the active flow is maximum, then no augmenting path exists in the residual network. + Here is our second big lemma, if the active flow is maximum, + then no augmenting path exists in the residual network. -/ lemma no_augm_path {V : Type*} [inst' : fintype V] @@ -571,7 +587,7 @@ begin by_contradiction is_sink, set s := rsn.afn.network.source, set t := rsn.afn.network.sink, - set vertices := {s} ∪ { x | (∃ y: V, exists_path.in x y) }, -- the set of all vertices in the augmenting path + set vertices := {s} ∪ { x | (∃ y: V, exists_path.in x y) }, --all vertices in the augmenting path set d := 0, -- set flows := { rsn.f' x y | exists_path.in x y }, -- set of reals, why it doesn't work? -- set d := flows.min, -- the minimum flow in the augmenting path @@ -588,13 +604,27 @@ begin by_cases h: exists_path.in u v, { have h1: rsn.afn.f u v ≥ 0 := by {exact rsn.afn.non_neg_flow u v}, - have h2: d ≥ 0 := by {linarith}, -- needs to be changed, we can use the definition of rsn and split into cases + have h2: d ≥ 0 := -- needs to be changed, we can use the definition of rsn and split into cases + begin + by_contradiction h', + have h3: d < 0 := by {exact lt_of_not_ge h'}, + have h4: ¬ d < 0 := by {exact not_lt_of_gt pos}, + exact absurd h3 h4, + end, linarith, }, { by_cases h': exists_path.in v u, { - have h1: rsn.afn.f u v ≥ d := by sorry, -- d is the minimum flow in the residual network, so use the definition of rsn and split into cases + have h1: rsn.f' v u = rsn.afn.f u v := + begin + rw rsn.f_def, + have edge: rsn.afn.network.is_edge v u := by sorry,-- use h' and definition of path.in + unfold mk_rsf, + sorry, -- just use edge to get the wanted result + end, + have h2: rsn.f' v u ≥ d := by sorry, -- minimality of d + have h3: rsn.afn.f u v ≥ d := by {rw ←h1, exact h2}, linarith, }, { @@ -607,11 +637,13 @@ begin intros u v, by_cases h: exists_path.in u v, { - have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := by sorry, -- again, use def of rsn and split into cases - -- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := by def of rsn - -- have h3: d ≤ rsn.f' u v := by minimality of d - -- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, - -- exact le_trans h4 h2 + have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := by sorry, + -- begin + -- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := by def of rsn + -- have h3: d ≤ rsn.f' u v := by minimality of d + -- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, + -- exact le_trans h4 h2 + -- end, linarith, }, { @@ -619,7 +651,7 @@ begin { have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := by {exact rsn.afn.no_overflow u v}, - linarith, + linarith, -- maybe pos will have to be used when d is properly defined }, { have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := @@ -638,6 +670,16 @@ begin intros v vNotSinkSource, by_cases h: v ∈ vertices, { + -- Issues: How are we proving the cardinality of predecessor and ancestor is 1? + -- How exactly do we use that within the code to prove h2 and h3? + set predecessor := {u | exists_path.in u v}, + set ancestor := {w | exists_path.in v w}, + have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := + by {exact rsn.afn.conservation v vNotSinkSource}, + -- have h2: mk_in f {v} = rsn.afn.mk_in {v} + d := by sorry, -- use the predecessor + -- have h3: mk_out f {v} = rsn.afn.mk_out {v} + d := by sorry, -- use the ancestor + -- rw [h2,h3,h1], + -- rfl, sorry, }, { @@ -645,18 +687,33 @@ begin -- have h1: ∀ u : V, ¬exists_path.in u v := -- begin -- by_contradiction h', - -- have contr: ∃u: + -- have ancestor: ∃w: exists_path.in v w := by v ≠ t, + -- have contr: v ∈ vertives := by def of vertices and ancestor, + -- contradiction -- with ¬v ∈ vertices, + -- end, + -- have h2: ∀ w : V, ¬exists_path.in u w := + -- begin + -- by_contradiction h', + -- have contr: v ∈ vertives := by def of vertices, + -- contradiction -- with ¬v ∈ vertices -- end, + -- have h3: ∀ u : V, better_flow.f u v = rsn.afn.f u v := by h1 and h2 + -- have h4: ∀ w : V, better_flow.f v w = rsn.afn.f v w := by h1 and h2 + -- rw [h3,h4], + -- exact rsn.afn.conservation v vNotSinkSource, }, end ⟩, have flow_value: F_value better_flow = F_value rsn.afn + d := begin unfold F_value, - have h1: mk_out better_flow.f {better_flow.network.source} = mk_out rsn.afn.f {rsn.afn.network.source} + d := + have h1: mk_out better_flow.f {better_flow.network.source} = + mk_out rsn.afn.f {rsn.afn.network.source} + d := by sorry, -- take the edge with the added flow - have h2: mk_in better_flow.f {better_flow.network.source} = mk_in rsn.afn.f {rsn.afn.network.source} := by {linarith}, + -- Issue: How do we prove that there is exactly one edge? How do we use it to prove h1? + have h2: mk_in better_flow.f {better_flow.network.source} = + mk_in rsn.afn.f {rsn.afn.network.source} := by {linarith}, rw [h1,h2], linarith end, @@ -826,7 +883,8 @@ begin dsimp [mk_in], simp_rw [← ct.Tcomp], simp only [sub_eq_self], - have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = ∑ x in ct.T, ∑ y in ct.S, 0 := + have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = + ∑ x in ct.T, ∑ y in ct.S, 0 := begin apply finset.sum_congr rfl, intros x x_in_T, From 6661c3e2eac27c8572e51279e641f1a32643aa2a Mon Sep 17 00:00:00 2001 From: amilchew Date: Mon, 20 Mar 2023 16:59:24 +0000 Subject: [PATCH 06/28] feat(combinatorics\quiver\max_flow_mion_cut) --- leanpkg.toml | 1 + src/combinatorics/quiver/max_flow_min_cut.lean | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/leanpkg.toml b/leanpkg.toml index 98c2e9e127eb3..f443084a23bb5 100644 --- a/leanpkg.toml +++ b/leanpkg.toml @@ -5,3 +5,4 @@ lean_version = "leanprover-community/lean:3.50.3" path = "src" [dependencies] +mathlib = {git = "https://github.com/leanprover-community/mathlib", rev = "290a7ba01fbcab1b64757bdaa270d28f4dcede35"} diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 91c979f32f27c..a0c95ad2d8a79 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -460,7 +460,12 @@ begin simp, unfold mk_in, have nonneg_flow: ∀ v ∈ V', ∀ u ∈ S, afn.f u v ≥ 0 := - by {intros v vInV' u uInS, exact afn.non_neg_flow u v}, -- meta errors again? + begin + intros v vInV' u uInS, + have h1: v ∈ V' := by {exact vInV'}, + have h2: u ∈ S := by {exact uInS}, + exact afn.non_neg_flow u v, + end, exact finset.sum_nonneg nonneg_flow, end, apply le_trans lemma3 lemma2, From 949836cb277a428c61d47b6ffb11ca76b1400e03 Mon Sep 17 00:00:00 2001 From: amilchew Date: Mon, 20 Mar 2023 18:37:02 +0000 Subject: [PATCH 07/28] feat(max_flow_min_cut) --- src/combinatorics/quiver/max_flow_min_cut.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index a0c95ad2d8a79..ea57ac0a80c77 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Aleksandar Milchev. All rights reserved. +Copyright (c) 2023 Aleksandar Milchev, Leo Okawa Ericson, Viggo Laakshoharju. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Author: Aleksandar Milchev +Authors: Aleksandar Milchev, Leo Okawa Ericson, Viggo Laakshoharju -/ From 2606ce5f9cd45a62a06de22a893a00726ab97a7c Mon Sep 17 00:00:00 2001 From: amilchew Date: Mon, 20 Mar 2023 18:48:43 +0000 Subject: [PATCH 08/28] feat(max_flow_min_cut) --- src/combinatorics/quiver/max_flow_min_cut.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index ea57ac0a80c77..fcc712bf66a91 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -6,7 +6,7 @@ Authors: Aleksandar Milchev, Leo Okawa Ericson, Viggo Laakshoharju import data.real.basic -import data.set +import data.set.basic import tactic import data.finset.basic import tactic.induction From 1b01848de994120c0a014d85352c118219fa5ea7 Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 22 Mar 2023 12:44:28 +0000 Subject: [PATCH 09/28] feat(combinatorics/quiver/max_flow_min_cut) --- src/combinatorics/quiver/max_flow_min_cut.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index fcc712bf66a91..30534fc1a1254 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -350,8 +350,8 @@ begin by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, rw Scomp at *, - -- exact set.not_mem_diff_of_mem tInT, sorry, + -- exact set.not_mem_diff_of_mem tInT, end, have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} = mk_out afn.f {s} - mk_in afn.f {s} := @@ -429,8 +429,8 @@ begin by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, rw Scomp at *, - -- exact set.not_mem_diff_of_mem tInT, sorry, + -- exact set.not_mem_diff_of_mem tInT, end, have lemma1: F_value afn = mk_out afn.f S - mk_in afn.f S := begin @@ -444,8 +444,8 @@ begin unfold mk_out, have flowLEcut: ∀ (x y : V), (afn.f x y ≤ afn.network.to_capacity.c x y) := by {exact afn.no_overflow}, - -- exact finset.sum_le_sum flowLEcut, sorry, + -- exact finset.sum_le_sum flowLEcut, end, unfold mk_out, unfold mk_out at no_overflow, From ebe01892122065e260810fb713f29d4c316c5ffc Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 29 Mar 2023 11:31:20 +0100 Subject: [PATCH 10/28] feat(combinatorics/quiver/max_flow_min_cut) --- .../quiver/max_flow_min_cut.lean | 547 ++++++++++++------ 1 file changed, 366 insertions(+), 181 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 30534fc1a1254..7077eabd91d05 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -10,6 +10,7 @@ import data.set.basic import tactic import data.finset.basic import tactic.induction +import algebra.big_operators.order /-! # Max flow Min cut theorem @@ -54,12 +55,12 @@ notation ` V' ` := univ As direct consequences, `max_flow_criterion` and `min_cut_criterion` will be proven. -/ -structure strange_digraph (V : Type*) [inst : fintype V] := +structure digraph (V : Type*) [inst : fintype V] := (is_edge : V → V → Prop) (hnonsymmetric : ∀ u v : V, ¬ ((is_edge u v) ∧ (is_edge v u))) structure capacity (V : Type*) [inst : fintype V] - extends strange_digraph V := + extends digraph V := (c : V -> V -> ℝ) (non_neg_capacity : ∀ u v : V, c u v ≥ 0) (vanishes : ∀ u v : V, ¬ (is_edge u v) → c u v = 0) @@ -71,11 +72,11 @@ structure flow_network (V : Type*) [inst : fintype V] noncomputable def mk_in {V : Type* } [inst : fintype V] - (f : V -> V -> ℝ) (s : finset V) : ℝ := ∑ x in finset.univ \ s, ∑ y in s, f x y + (f : V -> V -> ℝ) (S : finset V) : ℝ := ∑ x in finset.univ \ S, ∑ y in S, f x y noncomputable def mk_out {V : Type* } [inst : fintype V] - (f : V -> V -> ℝ) (s : finset V) : ℝ := ∑ x in s, ∑ y in finset.univ \ s, f x y + (f : V -> V -> ℝ) (S : finset V) : ℝ := ∑ x in S, ∑ y in finset.univ \ S, f x y structure active_flow_network (V : Type*) [fintype V] := (network : flow_network V) @@ -122,19 +123,19 @@ lemma f_vanishes_outside_edge {V : Type*} [fintype V] lemma x_not_in_s {V : Type*} [fintype V] (c : cut V) : ∀ x : V, x ∈ c.T -> x ∉ ({c.network.source} : finset V) := begin - intros x hxinS, + intros x xInS, cases c, simp only [mem_singleton] at *, - rw c_Tcomp at hxinS, - have foo : univ \ c_S ∩ c_S = ∅ := sdiff_inter_self c_S univ, + rw c_Tcomp at xInS, + have h : univ \ c_S ∩ c_S = ∅ := sdiff_inter_self c_S univ, have foo : disjoint (univ \ c_S) c_S := sdiff_disjoint, have bar : c_network.source ∈ c_S := c_sins, - exact disjoint_iff_ne.mp foo x hxinS c_network.source c_sins + exact disjoint_iff_ne.mp foo x xInS c_network.source c_sins end lemma foobar { a b : ℝ } : a + - b = a - b := rfl -lemma f_zero_zero {V : Type*} [inst' : fintype V] +lemma f_zero {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (x : V) : afn.f x x = 0 := begin have hnonsymm : _ := afn.network.hnonsymmetric x x, @@ -156,7 +157,7 @@ begin rw @sum_eq_sum_diff_singleton_add _ _ _ _ univ p (by simp only [mem_univ]) (λ x, afn.f x p), have foo : (λ (x : V), afn.f x p) p = afn.f p p := rfl, simp only [congr_fun], - rw f_zero_zero afn p, + rw f_zero afn p, have bar : ∑ (x : V) in univ \ {p}, afn.f x p + 0 = (λ p', ∑ (x : V) in univ \ {p'}, afn.f x p') p := by simp only [add_zero], rw bar, clear bar, @@ -175,7 +176,7 @@ begin rw @sum_eq_sum_diff_singleton_add _ _ _ _ univ p (by simp only [mem_univ]) (λ x, afn.f p x), have foo : (λ (x : V), afn.f p x) p = afn.f p p := rfl, simp only [congr_fun], - rw f_zero_zero afn p, + rw f_zero afn p, have bar : ∑ (x : V) in univ \ {p}, afn.f p x + 0 = (λ p', ∑ (x : V) in univ \ {p'}, afn.f p' x) p := by simp only [add_zero], rw bar, clear bar, @@ -204,58 +205,43 @@ begin {exact hx,} end -lemma sub_comm_zero (a b : ℝ) : a - b = 0 → b - a = 0 := -begin - intro eq, - rw ← add_left_inj (a), - rw sub_add_cancel, rw zero_add, - rw ← add_left_inj (-b), - rw add_neg_self, - rw ← sub_eq_add_neg, - rw eq_comm, - exact eq -end +lemma sub_comm_zero (a b : ℝ) : a - b = 0 → b - a = 0 := by {intro eq, linarith} lemma set_flow_conservation {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (S : finset V) : S ⊆ finset.univ \ {afn.network.source, afn.network.sink} -> mk_in afn.f S = mk_out afn.f S := begin - intro hin, + intro stNotInS, rw ← add_left_inj (- mk_out afn.f S), simp only [add_right_neg], rw ← add_zero (mk_in afn.f S), nth_rewrite 0 ← add_neg_self (∑ u in S, (∑ v in S, afn.f u v)), rw ← add_assoc, - have tmp : mk_in afn.f S + ∑ u in S, ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := + have tmp: mk_in afn.f S + ∑ u in S, ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := begin unfold mk_in, - have h: S ⊆ V' := by {exact finset.subset_univ S}, + have h: S ⊆ V' := finset.subset_univ S, have hyp: ∑ (x : V) in V' \ S, ∑ (y : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v - = ∑ u in V', ∑ v in S, afn.f u v := - by {exact finset.sum_sdiff h}, - have fin: ∑ u in V', ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := - by {exact finset.sum_comm}, + = ∑ u in V', ∑ v in S, afn.f u v := finset.sum_sdiff h, + have swap: ∑ u in V', ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := finset.sum_comm, rw hyp, - exact fin, + exact swap, end, have tmp2: mk_out afn.f S + (∑ u in S, ∑ v in S, afn.f u v) = ∑ u in S, ∑ v in V', afn.f u v := begin unfold mk_out, rw finset.sum_comm, - have h: S ⊆ V' := by {exact finset.subset_univ S}, + have h: S ⊆ V' := finset.subset_univ S, have hyp: ∑ (y : V) in V' \ S, ∑ (x : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = - ∑ u in V', ∑ v in S, afn.f v u := - by {exact finset.sum_sdiff h}, + ∑ u in V', ∑ v in S, afn.f v u := finset.sum_sdiff h, have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = - ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := - by {exact finset.sum_comm}, - have fin: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := - by {exact finset.sum_comm}, + ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := finset.sum_comm, + have swap: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := finset.sum_comm, rw obvs at hyp, rw hyp, - exact fin, + exact swap, end, rw tmp, rw add_assoc, @@ -273,7 +259,7 @@ begin unfold edge_flow, rw afn.conservation x, { ring, }, - { exact finset.mem_of_subset hin hx,} + { exact finset.mem_of_subset stNotInS hx,} end, have foo := finset.sum_congr hseq h, unfold edge_flow at foo, @@ -282,23 +268,15 @@ begin simp, end -lemma move_right (a b : ℝ) : b = a → a - b = 0 := -begin - intro eq, - rw eq_comm, - rw ← add_left_inj (b), - simp, exact eq -end +lemma move_right (a b : ℝ) : b = a → a - b = 0 := by {intro eq, linarith} lemma set_flow_conservation_eq {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (S : finset V) : S ⊆ finset.univ \ {afn.network.source, afn.network.sink} -> mk_out afn.f S - mk_in afn.f S = 0 := begin intro hip, - have h: mk_in afn.f S = mk_out afn.f S := by {exact set_flow_conservation afn S hip}, - rw eq_comm at h, - rw ← add_left_inj (-mk_in afn.f S) at h, - rw add_neg_self(mk_in afn.f S) at h, exact h + have h: mk_in afn.f S = mk_out afn.f S := set_flow_conservation afn S hip, + linarith end lemma add_zero_middle (a b c: ℝ): c = 0 → a + c - b = a - b := by {intro eq, linarith} @@ -315,11 +293,7 @@ begin simp end -/- - This lemma has issues, I am confused how finsets are handled. - The complains mention "meta variables". --/ -lemma flow_value_global_ver {V : Type*} [inst' : fintype V] +lemma flow_value_source_in_S {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network) : mk_out afn.f {afn.network.source} - mk_in afn.f {afn.network.source} = @@ -330,72 +304,297 @@ begin set s := afn.network.source, set t := afn.network.sink, set f := afn.f, + have same: s = s := rfl, have hs : s = afn.network.source := rfl, have hT : T = ct.T := rfl, - have singleton: s ∈ {s} := by {exact set.mem_singleton s}, + have singleton: s ∈ {s} := finset.mem_singleton.2 same, have sInS: s ∈ S := begin - have same_source: s = ct.network.source := by {exact (same_source_and_sink afn ct same_net).1}, + have same_source: s = ct.network.source := (same_source_and_sink afn ct same_net).1, rw same_source, exact ct.sins, end, - -- "meta" errors occur, how is finset handled? - have hS: {s} ⊆ S := by sorry, -- {exact (set.singleton_subset_iff).2 sInS}, + have sSubsetS: {s} ⊆ S := (finset.singleton_subset_iff).2 sInS, + have disjS: disjoint {s} (S \ {s}) := + begin + have sOut: s ∉ (S \ {s}) := finset.not_mem_sdiff_of_mem_right singleton, + exact finset.disjoint_singleton_left.2 sOut, + end, + have sInCompl: {s} ⊆ V' \ (S \ {s}) := + begin + have sIn: {s} ⊆ V' := finset.subset_univ {s}, + have conj: {s} ⊆ V' ∧ disjoint {s} (S \ {s}) := and.intro sIn disjS, + exact finset.subset_sdiff.2 conj, + end, + have tNots: t ≠ s := + begin + by_contradiction h, + have contr: s = t := by rw ← h, + exact absurd contr afn.sourceNotSink, + end, have tNotInS: t ∉ S := begin - have same_sink: t = ct.network.sink := by {exact (same_source_and_sink afn ct same_net).2}, + have same_sink: t = ct.network.sink := (same_source_and_sink afn ct same_net).2, have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, - have Tcomp : T = univ \ S := by {exact ct.Tcomp}, + have Tcomp : T = univ \ S := ct.Tcomp, have foo: S = univ \ (univ \ S) := by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, rw Scomp at *, - sorry, - -- exact set.not_mem_diff_of_mem tInT, + exact finset.not_mem_sdiff_of_mem_right tInT, + end, + have seteq: V' \ (S \ {s}) \ {s} = V' \ S := + begin + ext x, + have eq1: V' \ (S \ {s}) \ {s} = V' \ (S \ {s}) ∩ (V' \ {s}) := + finset.sdiff_sdiff_left' V' (S \ {s}) {s}, + rw eq1, + have xIn: x ∈ V' := finset.mem_univ x, + split, + { + intro hyp, + have xIn1: x ∈ V' \ (S \ {s}) := (finset.mem_inter.1 hyp).1, + have xIn2: x ∈ V' \ {s} := (finset.mem_inter.1 hyp).2, + have xOut: x ∉ S := + begin + have xOut1: x ∉ (S \ {s}) := (finset.mem_sdiff.1 xIn1).2, + have xOut2: x ∉ {s} := (finset.mem_sdiff.1 xIn2).2, + have xOutAnd: x ∉ (S \ {s}) ∧ x ∉ {s} := and.intro xOut1 xOut2, + have eq2: S = (S \ {s}) ∪ {s} := + begin + have inter: S ∩ {s} = {s} := finset.inter_singleton_of_mem sInS, + have eq3: (S \ {s}) ∪ S ∩ {s} = S := by rw finset.sdiff_union_inter S {s}, + calc + S + = (S \ {s}) ∪ S ∩ {s} : eq_comm.1 eq3 + ... = (S \ {s}) ∪ {s} : by rw inter, + end, + rw eq2, + exact finset.not_mem_union.2 xOutAnd, + end, + have concl: x ∈ V' ∧ x ∉ S := and.intro xIn xOut, + exact finset.mem_sdiff.2 concl, + }, + intro hyp, + have xOutS: x ∉ S := (finset.mem_sdiff.1 hyp).2, + have xOut: x ∉ S \ {s} := + begin + by_contradiction h, + have contr: x ∈ S := (finset.mem_sdiff.1 h).1, + exact absurd contr xOutS, + end, + have sdiff: x ∈ V' ∧ x ∉ S \ {s} := and.intro xIn xOut, + have xIn1: x ∈ V' \ (S \ {s}) := finset.mem_sdiff.2 sdiff, + have xNotIns: x ∉ {s} := + begin + by_contradiction h, + have contr: x ∈ S := finset.mem_of_subset sSubsetS h, + exact absurd contr xOutS, + end, + have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, + have xIn2: x ∈ V' \ {s} := finset.mem_sdiff.2 concl, + have member: x ∈ V' \ (S \ {s}) ∧ x ∈ V' \ {s} := and.intro xIn1 xIn2, + exact finset.mem_inter.2 member, + end, + have union: V' \ S ∪ S \ {s} = V' \ {s} := + begin + ext x, + have xIn: x ∈ V' := finset.mem_univ x, + split, + { + intro hyp, + have h1: x ∈ V' \ S ∨ x ∈ S \ {s} := finset.mem_union.1 hyp, + have h2: x ∈ V' \ S → x ∈ V' \ {s} := + begin + intro hypo, + have xOutS: x ∉ S := (finset.mem_sdiff.1 hypo).2, + have xNotIns: x ∉ {s} := + begin + by_contradiction h, + have contr: x ∈ S := finset.mem_of_subset sSubsetS h, + exact absurd contr xOutS, + end, + have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, + exact finset.mem_sdiff.2 concl, + end, + have h3: x ∈ S \ {s} → x ∈ V' \ {s} := + begin + intro hypo, + have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hypo).2, + have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, + exact finset.mem_sdiff.2 concl, + end, + exact or.elim h1 h2 h3, + }, + intro hyp, + have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hyp).2, + by_cases h' : x ∈ S, + { + have and: x ∈ S ∧ x ∉ {s} := and.intro h' xNotIns, + have xInSs: x ∈ S \ {s} := finset.mem_sdiff.2 and, + have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_right (x ∈ V' \ S) xInSs, + exact finset.mem_union.2 conj, + }, + { + have and: x ∈ V' ∧ x ∉ S := and.intro xIn h', + have xInVS: x ∈ V' \ S := finset.mem_sdiff.2 and, + have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_left (x ∈ S \ {s}) xInVS, + exact finset.mem_union.2 conj, + }, + end, + have disj: disjoint (V' \ S) (S \ {s}) := + begin + have h1: (V' \ S) ∩ (S \ {s}) = ∅ := + begin + have noMembers: ∀ (v : V), v ∉ (V' \ S) ∩ (S \ {s}) := + begin + intro v, + by_contradiction h, + have vInVmS: v ∈ (V' \ S) := (finset.mem_inter.1 h).1, + have vNotInS: v ∉ S := (finset.mem_sdiff.1 vInVmS).2, + have vInSms: v ∈ (S \ {s}) := (finset.mem_inter.1 h).2, + have vInS: v ∈ S := (finset.mem_sdiff.1 vInSms).1, + exact absurd vInS vNotInS, + end, + exact finset.eq_empty_of_forall_not_mem noMembers, + end, + have h2: ¬ ((V' \ S) ∩ (S \ {s})).nonempty := + begin + by_contradiction h, + have contr: (V' \ S) ∩ (S \ {s}) ≠ ∅ := finset.nonempty.ne_empty h, + exact absurd h1 contr, + end, + by_contradiction notDisjoint, + have contr: ((V' \ S) ∩ (S \ {s})).nonempty := finset.not_disjoint_iff_nonempty_inter.1 notDisjoint, + exact absurd contr h2, end, - have expand: mk_out afn.f {s} + (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) - mk_in afn.f {s} - = mk_out afn.f {s} - mk_in afn.f {s} := + have disjTS: disjoint {t} {s} := finset.disjoint_singleton.2 (tNots), + have expand: mk_out f {s} + (mk_out f (S \ {s}) - mk_in f (S \ {s})) - mk_in f {s} + = mk_out f {s} - mk_in f {s} := begin - have h3: s ∉ (S \ {s}) := by sorry, -- {set.not_mem_diff_of_mem singleton}, - have eq: mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s}) = 0 := + have h3: s ∉ S \ {s} := finset.not_mem_sdiff_of_mem_right singleton, + have eq: mk_out f (S \ {s}) - mk_in f (S \ {s}) = 0 := begin have h: (S \ {s}) ⊆ finset.univ \ {s,t} := begin - intros x xInSet, - have memU: x ∈ finset.univ := by {exact finset.mem_univ x}, - have xInS: x ∈ S:= by sorry, -- {exact ((set.mem_diff x).1 xInSet).1}, - have xNotInS: x ∉ {t} := + intros x xInSms, + have xIn: x ∈ V' := finset.mem_univ x, + have xInS: x ∈ S:= ((finset.mem_sdiff).1 xInSms).1, + have xNotInT: x ∉ {t} := begin by_contradiction h, - have eq: x = t := by {exact set.mem_singleton_iff.1 h}, + have eq: x = t := finset.mem_singleton.1 h, rw eq at xInS, contradiction, end, - have union: {s} ∪ {t} = {s,t} := by {exact set.singleton_union}, - have xNotInS: x ∉ {s} := by sorry, -- {exact ((set.mem_diff x).1 xInSet).2}, + have union: ({s}: finset V) ∪ {t} = {s,t} := by refl, + have xNotInS: x ∉ {s} := ((finset.mem_sdiff).1 xInSms).2, have xOut: x ∉ {s,t} := begin - rw ← union, by_contradiction h, - cases h with h0 h1, - {exact absurd h0 xNotInS}, - exact absurd h1 xNotInT, + rw ← union at h, + have inUnion: x ∈ {s} ∨ x ∈ {t} := finset.mem_union.1 h, + have contr1: x ∈ {s} → false := + begin + intro assumption, + exact absurd assumption xNotInS, + end, + have contr2: x ∈ {t} → false := + begin + intro assumption, + exact absurd assumption xNotInT, + end, + exact or.elim inUnion contr1 contr2, end, - exact set.mem_diff.2 memU + have and: x ∈ V' ∧ x ∉ {s,t} := and.intro xIn xOut, + exact finset.mem_sdiff.2 and, end, exact set_flow_conservation_eq afn (S \ {s}) h, end, - exact add_zero_middle (mk_out afn.f {s}) (mk_in afn.f {s}) (mk_out afn.f (S \ {s}) - mk_in afn.f (S \ {s})) eq, + exact add_zero_middle (mk_out f {s}) (mk_in f {s}) (mk_out f (S \ {s}) - mk_in f (S \ {s})) eq, + end, + have sum1: mk_out f {s} + mk_out f (S \ {s}) = + mk_out f S + ∑ u in (S \ {s}), f s u + ∑ u in (S \ {s}), f u s := + begin + unfold mk_out, + have eq1: ∑ (x : V) in S, ∑ (y : V) in V' \ S, f x y = + ∑ (x : V) in (S \ {s}) , ∑ (y : V) in V' \ S, f x y + ∑ (x : V) in {s}, ∑ (y : V) in V' \ S, f x y := + by {rw finset.sum_sdiff sSubsetS}, + have eq2: ∑ (x : V) in {s}, ∑ (y : V) in V' \ S, f x y = ∑ (y : V) in V' \ S, f s y := by simp, + have eq3: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = + ∑ (x : V) in (S \ {s}), f x s + ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ S, f x y := + begin + have obvs: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = + ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y := finset.sum_comm, + have sdiff: ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y = + ∑ (y : V) in V' \ S, ∑ (x : V) in (S \ {s}), f x y + ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y := + by {rw ← finset.sum_sdiff sInCompl, rw seteq}, + have obs: ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y = ∑ (x : V) in (S \ {s}), f x s := by {simp}, + have swap: ∑ (y : V) in V' \ S, ∑ (x : V) in S \ {s}, f x y = + ∑ (x : V) in S \ {s}, ∑ (y : V) in V' \ S, f x y := finset.sum_comm, + rw obs at sdiff, + rw [obvs, sdiff, add_comm, swap], + end, + have eq4: ∑ (x : V) in {s}, ∑ (y : V) in V' \ {s}, f x y = + ∑ (y : V) in V' \ S, f s y + ∑ (u : V) in S \ {s}, f s u := + begin + have obvs: ∑ (x : V) in {s}, ∑ (y : V) in V' \ {s}, f x y = + ∑ (y : V) in V' \ {s}, f s y := by {simp}, + rw obvs, + rw ← union, + exact finset.sum_union disj, + end, + linarith + end, + have sum2: mk_in f (S \ {s}) + mk_in f {s} = + mk_in f S + ∑ u in (S \ {s}), f s u + ∑ u in (S \ {s}), f u s := + begin + unfold mk_in, + have eq1: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := + begin + have obvs: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y := finset.sum_comm, + have sdiff: ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y = + ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y := + by {rw finset.sum_sdiff sSubsetS}, + have swap: ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := + begin + have eq11: ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y := finset.sum_comm, + have eq12: ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := finset.sum_comm, + linarith, + end, + linarith, + end, + have eq2: ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y = ∑ (u : V) in V' \ S, f u s := by {simp}, + have eq3: ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (u : V) in S \ {s}, f s u := + begin + have eq31: ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y := + by {rw ← finset.sum_sdiff sInCompl, rw seteq}, + have eq32: ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y = ∑ (u : V) in S \ {s}, f s u := by {simp}, + linarith, + end, + have eq4: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, f x y = + ∑ (u : V) in V' \ S, f u s + ∑ (u : V) in S \ {s}, f u s := + begin + have obvs: ∑ (u : V) in V' \ S, f u s = + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := by {simp}, + have obs: ∑ (u : V) in S \ {s}, f u s = + ∑ (x : V) in S \ {s}, ∑ (y : V) in {s}, f x y := by {simp}, + rw ← union, + rw [obvs,obs], + exact finset.sum_union disj, + end, + linarith, end, - /- The next two equalities use sum over two elements, so I am not sure how to resolve them. -/ - have sum1: mk_out afn.f {s} + mk_out afn.f (S \ {s}) = mk_out afn.f S := - by sorry, -- {unfold mk_out, rw finset.sum_sdiff hS}, - have sum2: mk_in afn.f (S \ {s}) + mk_in afn.f {s} = mk_in afn.f S := - by sorry, -- {unfold mk_in, rw finset.sum_sdiff hS}, rw ← expand, rw add_sub, - rw group_minus (mk_out afn.f {s}) (mk_out afn.f (S \ {s})) (mk_in afn.f (S \ {s})) (mk_in afn.f {s}), - rw sum1, rw sum2, + rw group_minus (mk_out f {s}) (mk_out f (S \ {s})) (mk_in f (S \ {s})) (mk_in f {s}), + linarith end /-! @@ -412,42 +611,50 @@ begin set s := afn.network.source, set t := afn.network.sink, unfold cut_cap, + have same: s = s := by {simp}, + have hs : s = afn.network.source := rfl, + have hT : T = ct.T := rfl, + have singleton: s ∈ {s} := finset.mem_singleton.2 same, have sInS: s ∈ S := begin - have same_source: s = ct.network.source := by {exact (same_source_and_sink afn ct same_net).1}, + have same_source: s = ct.network.source := (same_source_and_sink afn ct same_net).1, rw same_source, exact ct.sins, end, - have hS: {s} ⊆ S := by sorry, -- {exact (set.singleton_subset_iff).2 sInS}, - have singleton: s ∈ {s} := by {exact set.mem_singleton s}, + have sInCompl: {s} ⊆ V' \ (S \ {s}) := + begin + have sIn: {s} ⊆ V' := finset.subset_univ {s}, + have disjS: disjoint {s} (S \ {s}) := + begin + have sOut: s ∉ (S \ {s}) := finset.not_mem_sdiff_of_mem_right singleton, + exact finset.disjoint_singleton_left.2 sOut, + end, + have conj: {s} ⊆ V' ∧ disjoint {s} (S \ {s}) := and.intro sIn disjS, + exact finset.subset_sdiff.2 conj, + end, have tNotInS: t ∉ S := begin - have same_sink: t = ct.network.sink := by {exact (same_source_and_sink afn ct same_net).2}, + have same_sink: t = ct.network.sink := (same_source_and_sink afn ct same_net).2, have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, - have Tcomp : T = univ \ S := by {exact ct.Tcomp}, + have Tcomp : T = univ \ S := ct.Tcomp, have foo: S = univ \ (univ \ S) := by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, rw Scomp at *, - sorry, - -- exact set.not_mem_diff_of_mem tInT, + exact finset.not_mem_sdiff_of_mem_right tInT, end, have lemma1: F_value afn = mk_out afn.f S - mk_in afn.f S := - begin - unfold F_value, - exact flow_value_global_ver afn ct same_net, - end, + by {unfold F_value, exact flow_value_source_in_S afn ct same_net}, have lemma2: mk_out afn.f S ≤ mk_out ct.network.to_capacity.c S := begin have no_overflow: mk_out afn.f S ≤ mk_out afn.network.to_capacity.c S := begin unfold mk_out, - have flowLEcut: ∀ (x y : V), (afn.f x y ≤ afn.network.to_capacity.c x y) := - by {exact afn.no_overflow}, - sorry, - -- exact finset.sum_le_sum flowLEcut, + have flowLEcut: ∀ (x y : V), (x ∈ S ∧ y ∈ V' \ S) → + (afn.f x y ≤ afn.network.to_capacity.c x y) := + by {intros x y hyp, exact afn.no_overflow x y}, + exact finset.sum_le_sum (λ i hi, finset.sum_le_sum $ λ j hj, flowLEcut i j ⟨hi, hj⟩) end, - unfold mk_out, unfold mk_out at no_overflow, rw same_net at no_overflow, exact no_overflow, @@ -455,18 +662,16 @@ begin have lemma3: F_value afn ≤ mk_out afn.f S := begin rw lemma1, - have obs: mk_out afn.f S = mk_out afn.f S + 0 := by rw [add_zero], - rw obs, + have obvs: mk_out afn.f S = mk_out afn.f S + 0 := by rw [add_zero], + rw obvs, simp, unfold mk_in, - have nonneg_flow: ∀ v ∈ V', ∀ u ∈ S, afn.f u v ≥ 0 := + have nonneg_flow: ∀ (u v : V), (u ∈ V' \ S ∧ v ∈ S) → afn.f u v ≥ 0 := begin - intros v vInV' u uInS, - have h1: v ∈ V' := by {exact vInV'}, - have h2: u ∈ S := by {exact uInS}, + intros u v hyp, exact afn.non_neg_flow u v, end, - exact finset.sum_nonneg nonneg_flow, + exact finset.sum_nonneg (λ i hi, finset.sum_nonneg $ λ j hj, nonneg_flow i j ⟨hi, hj⟩), end, apply le_trans lemma3 lemma2, end @@ -474,7 +679,7 @@ end lemma zero_left_move {a b c d : ℝ} : (0 = a + b - c - d) -> (d - b = a - c) := by {intro h, linarith} -def is_max_flow_network {V : Type*} [inst' : fintype V] +def is_max_flow {V : Type*} [inst' : fintype V] (fn: active_flow_network V) : Prop := ∀ fn' : active_flow_network V, fn.network = fn'.network → F_value fn' ≤ F_value fn @@ -483,13 +688,11 @@ def is_min_cut {V : Type*} [inst' : fintype V] lemma max_flow_criterion {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (ct : cut V) (hsame_network: afn.network = ct.network): - cut_cap ct = F_value afn -> is_max_flow_network afn := + cut_cap ct = F_value afn -> is_max_flow afn := begin - intro eq, - intro fn, - intro same_net, + intros eq fn same_net, rw ← eq, - have same_network: fn.network = ct.network := by {rw ← same_net, exact hsame_network,}, + have same_network: fn.network = ct.network := by {rw ← same_net, exact hsame_network}, exact weak_duality (fn) (ct) (same_network), end @@ -560,14 +763,14 @@ begin simp only, rw rsn_f_def, unfold mk_rsf, - have tmp := classical.em (rsn_afn.network.to_capacity.to_strange_digraph.is_edge u v), + have tmp := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), cases tmp, { simp only [tmp, if_true, sub_nonneg, rsn_afn.no_overflow], }, { simp only [tmp, if_false], clear tmp, - have tmp := classical.em (rsn_afn.network.to_capacity.to_strange_digraph.is_edge v u), + have tmp := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), cases tmp, { have h := rsn_afn.non_neg_flow v u, @@ -586,7 +789,7 @@ end -/ lemma no_augm_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : (is_max_flow_network rsn.afn) -> no_augumenting_path rsn := + (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augumenting_path rsn := begin intros max_flow v exists_path, by_contradiction is_sink, @@ -608,12 +811,12 @@ begin intros u v, by_cases h: exists_path.in u v, { - have h1: rsn.afn.f u v ≥ 0 := by {exact rsn.afn.non_neg_flow u v}, + have h1: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, have h2: d ≥ 0 := -- needs to be changed, we can use the definition of rsn and split into cases begin by_contradiction h', - have h3: d < 0 := by {exact lt_of_not_ge h'}, - have h4: ¬ d < 0 := by {exact not_lt_of_gt pos}, + have h3: d < 0 := lt_of_not_ge h', + have h4: ¬ d < 0 := not_lt_of_gt pos, exact absurd h3 h4, end, linarith, @@ -654,13 +857,11 @@ begin { by_cases h': exists_path.in v u, { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := - by {exact rsn.afn.no_overflow u v}, + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := rsn.afn.no_overflow u v, linarith, -- maybe pos will have to be used when d is properly defined }, { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := - by {exact rsn.afn.no_overflow u v}, + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := rsn.afn.no_overflow u v, linarith, }, }, @@ -679,8 +880,7 @@ begin -- How exactly do we use that within the code to prove h2 and h3? set predecessor := {u | exists_path.in u v}, set ancestor := {w | exists_path.in v w}, - have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := - by {exact rsn.afn.conservation v vNotSinkSource}, + have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := rsn.afn.conservation v vNotSinkSource, -- have h2: mk_in f {v} = rsn.afn.mk_in {v} + d := by sorry, -- use the predecessor -- have h3: mk_out f {v} = rsn.afn.mk_out {v} + d := by sorry, -- use the ancestor -- rw [h2,h3,h1], @@ -725,7 +925,7 @@ begin have le: F_value rsn.afn ≥ F_value better_flow := begin have same_net: better_flow.network = rsn.afn.network := by {simp}, - unfold is_max_flow_network at max_flow, + unfold is_max_flow at max_flow, exact max_flow better_flow same_net, end, have lt: F_value rsn.afn < F_value better_flow := @@ -737,10 +937,10 @@ begin rw eq, linarith end, - have h2: F_value rsn.afn < F_value rsn.afn + d := by exact lt_add_of_sub_left_lt h1, + have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, exact gt_iff_lt.2 h2, end, - have nlt: ¬F_value rsn.afn < F_value better_flow := by exact not_lt_of_ge le, + have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, exact absurd lt nlt, end @@ -822,11 +1022,11 @@ lemma min_max_cap_flow {V : Type*} [inst' : fintype V] begin split, { - intros u h_u_in_S v h_v_in_T, - specialize h u h_u_in_S v h_v_in_T, + intros u uInS v vInT, + specialize h u uInS v vInT, rw rsn.f_def at h, unfold mk_rsf at h, - have tmp := classical.em (rsn.afn.network.to_capacity.to_strange_digraph.is_edge u v), + have tmp := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), cases tmp, { simp only [tmp, if_true] at h, @@ -847,7 +1047,7 @@ begin specialize h u h_u_in_S v h_v_in_T, rw rsn.f_def at h, unfold mk_rsf at h, - have tmp := classical.em (rsn.afn.network.to_capacity.to_strange_digraph.is_edge u v), + have tmp := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), cases tmp, { have foo := rsn.afn.network.hnonsymmetric u v, @@ -861,7 +1061,7 @@ begin { simp only [tmp, if_false, ite_eq_right_iff] at h, clear tmp, - have tmp := classical.em (rsn.afn.network.to_capacity.to_strange_digraph.is_edge v u), + have tmp := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), cases tmp, { exact h tmp, @@ -884,7 +1084,7 @@ lemma f_value_eq_out {V : Type*} [inst' : fintype V] F_value afn = mk_out afn.f ct.S := begin dsimp [F_value], - rw flow_value_global_ver afn ct h_eq_network, + rw flow_value_source_in_S afn ct h_eq_network, dsimp [mk_in], simp_rw [← ct.Tcomp], simp only [sub_eq_self], @@ -892,10 +1092,10 @@ begin ∑ x in ct.T, ∑ y in ct.S, 0 := begin apply finset.sum_congr rfl, - intros x x_in_T, + intros x xInT, apply finset.sum_congr rfl, - intros y y_in_S, - exact h x x_in_T y y_in_S, + intros y yInS, + exact h x xInT y yInS, end, rw sum_eq_sum_zero, simp only [sum_const_zero], @@ -943,12 +1143,12 @@ lemma existence_of_a_cut {V : Type*} [inst' : fintype V] begin let S : finset V := mk_cut_set rsn, let T := V' \ S, - have h1: S = mk_cut_set rsn := by refl, - let min_cut := mk_cut_from_S (rsn) (hno_augumenting_path) (S) (h1), + have SCutSet: S = mk_cut_set rsn := by refl, + let min_cut := mk_cut_from_S (rsn) (hno_augumenting_path) (S) (SCutSet), have eq_net : rsn.afn.network = min_cut.network := by refl, have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := by {intros x y, split, intro heq, linarith, intro heq, linarith}, - have cf_vanishes_on_pipes: ∀u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := + have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := begin intros u uInS v vInNS, by_contradiction h, @@ -964,23 +1164,23 @@ begin end, contradiction end, - have notEdge: ¬ rsn.is_edge u v := by {exact s_t_not_connected rsn S h1 u uInS v vInNS}, + have notEdge: ¬ rsn.is_edge u v := by {exact s_t_not_connected rsn S SCutSet u uInS v vInNS}, contradiction end, have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := begin - intros u u_in_S v v_in_T is_edge, - have t: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := + intros u uInS v vInT is_edge, + have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := by {unfold mk_rsf, simp only [is_edge, if_true]}, - rw ← t, - have r: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, - rw r, - exact cf_vanishes_on_pipes u u_in_S v v_in_T, + rw ← h1, + have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, + rw h2, + exact cf_vanishes_on_pipes u uInS v vInT, end, have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = rsn.afn.network.c u v := begin - intros u u_in_S v v_in_T, + intros u uInS v vInT, cases classical.em (rsn.afn.network.is_edge u v), { rw subtract (rsn.afn.f u v) (rsn.afn.network.to_capacity.c u v), @@ -991,36 +1191,27 @@ begin simp only [h, if_true], end, rw ← mk_cf_spec, - exact cf_vanishes_on_pipes u u_in_S v v_in_T, + exact cf_vanishes_on_pipes u uInS v vInT, }, { rw rsn.afn.network.vanishes u v h, exact f_vanishes_outside_edge (rsn.afn) (u) (v) (h), }, end, - have no_backflow: ∀ u ∈ V' \ min_cut.S, ∀ v ∈ min_cut.S, rsn.afn.f u v = 0 := + have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := begin - intros u uInNS v vInS, - exact (min_max_cap_flow rsn min_cut eq_net cf_vanishes_on_pipes).2 u uInNS v vInS, - end, - have func0 : ∀ u ∈ V' \ min_cut.S, ∀ v ∈ min_cut.S, (λ u v, 0) u v = 0 := by {simp}, - have no_backflow_func: ∀ u ∈ V' \ min_cut.S, ∀ v ∈ min_cut.S, rsn.afn.f u v = (λ u v, 0) u v := - begin - intros u uInNS v vInS, - rw no_backflow u uInNS v vInS, - rw func0 u uInNS v vInS, - simp + intros u v hyp, + exact (min_max_cap_flow rsn min_cut eq_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, end, have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := begin rw F_value, simp only, - rw flow_value_global_ver rsn.afn min_cut eq_net, + rw flow_value_source_in_S rsn.afn min_cut eq_net, have no_input : mk_in rsn.afn.f min_cut.S = 0 := begin rw mk_in, - rw eq_on_res_then_on_sum (V' \ min_cut.S) (min_cut.S) (rsn.afn.f) (λ u v, 0) (no_backflow_func), -- type mismatch because of ↑, why is this arrow arriving? - simp only [sum_const_zero], + exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), end, rw no_input, simp only [sub_zero], @@ -1039,38 +1230,32 @@ begin end /-! - Finally, our biggest result, the max flow min cut theorem! + Finally, our biggest result, the max-flow min-cut theorem! If a maximum flow exists, its value is equal to the capacity of the min cut in the same network. -/ theorem max_flow_min_cut {V : Type*} [inst' : fintype V] (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : - (is_max_flow_network rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := + (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := begin rintros ⟨max_flow, min_cut⟩ , have noAugPath: no_augumenting_path rsn := by {exact no_augm_path rsn max_flow}, - have existsCut: ∃cut:cut V, rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn := - by {exact existence_of_a_cut rsn noAugPath}, - have max_flow_min_cut: ∀ cut:cut V, + have existsCut: ∃cut:cut V, rsn.afn.network = cut.network ∧ + cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, + have max_flow_min_cut: ∀ cut : cut V, (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := begin rintros cut ⟨same_net, eq⟩ , - have h1: is_min_cut cut := by {exact min_cut_criterion rsn.afn cut same_net eq}, - have h2: is_min_cut c := by {exact min_cut}, + have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, + have h2: is_min_cut c := min_cut, have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, have same_net2: c.network = cut.network := by rw ← same_net1, have same_val: cut_cap cut = cut_cap c := begin have le1: cut_cap cut ≤ cut_cap c := - begin - unfold is_min_cut at h1, - exact h1 c same_net1, - end, + by {unfold is_min_cut at h1, exact h1 c same_net1}, have le2: cut_cap c ≤ cut_cap cut := - begin - unfold is_min_cut at h2, - exact h2 cut same_net2, - end, + by {unfold is_min_cut at h2, exact h2 cut same_net2}, exact le_antisymm le1 le2, end, rw ← eq, From 8ca57aa3762a5b401ef6530ecd9942b89d62d302 Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 29 Mar 2023 11:41:08 +0100 Subject: [PATCH 11/28] feat(combinatorics/quiver/max_flow_min_cut) --- src/combinatorics/quiver/max_flow_min_cut.lean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 7077eabd91d05..061a9f62dc688 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -39,6 +39,8 @@ then its value is equal to the capacity of a minimum cut in the same network. ## References - Some of the structure ideas and lemmas can be seen in https://github.com/Zetagon/maxflow-mincut. +- A Lean 4 version of the proof can be found at + https://gitlab.com/Shreyas941/maxflowmincutlean4/-/blob/master/MaxFlowMinCut.lean. -/ From a82c829277cf360cf33e864b859ae2a5004a92b3 Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 29 Mar 2023 11:43:28 +0100 Subject: [PATCH 12/28] feat(combinatorics/quiver/max_flow_min_cut) --- src/combinatorics/quiver/max_flow_min_cut.lean | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 061a9f62dc688..7077eabd91d05 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -39,8 +39,6 @@ then its value is equal to the capacity of a minimum cut in the same network. ## References - Some of the structure ideas and lemmas can be seen in https://github.com/Zetagon/maxflow-mincut. -- A Lean 4 version of the proof can be found at - https://gitlab.com/Shreyas941/maxflowmincutlean4/-/blob/master/MaxFlowMinCut.lean. -/ From 80c25a010d7874f924e06018445420a5ee927021 Mon Sep 17 00:00:00 2001 From: Aleksandar Milchev <98773527+amilchew@users.noreply.github.com> Date: Sat, 8 Apr 2023 03:13:35 +0100 Subject: [PATCH 13/28] Formal Proof of the Theorem Implemented in LaTeX --- Max-Flow_Min-Cut_Proof.pdf | Bin 0 -> 143461 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Max-Flow_Min-Cut_Proof.pdf diff --git a/Max-Flow_Min-Cut_Proof.pdf b/Max-Flow_Min-Cut_Proof.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a2249fb32fa244f5b1b8855fd8e22c7570421b0f GIT binary patch literal 143461 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

G{^77Ky}<)Kr<L2G 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 From f57e08552f94c1b701c7a3267e43b53225e10cdb Mon Sep 17 00:00:00 2001 From: amilchew Date: Tue, 9 May 2023 11:23:29 +0100 Subject: [PATCH 15/28] only no_augm_path proof left --- .../quiver/max_flow_min_cut.lean | 1153 +++++++++++------ 1 file changed, 727 insertions(+), 426 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 7077eabd91d05..d84eeef469bc9 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -30,11 +30,11 @@ then its value is equal to the capacity of a minimum cut in the same network. - `no_augm_path` : if the active flow gives a maximum flow, then there is no augmenting path in the residual network. - `existence_of_a_cut` : there exists a cut with a capacity equal to the value of the maximum flow. -- `max_flow_min_cut` : if f is a max flow and c is a min cut in the same network, then their valies are equal (max flow min cut theorem). +- `max_flow_min_cut` : if f is a max flow and c is a min cut in the same network, then their values are equal (max flow min cut theorem). ## Notation -- Type V is used for the set of all vertices in our graph. +- Type V is used for the set of all vertices in our graph. It is a finite type. ## References @@ -44,11 +44,10 @@ then its value is equal to the capacity of a minimum cut in the same network. open finset - open_locale big_operators open_locale classical -notation ` V' ` := univ +notation ` V' ` := univ -- The universe, containing all vertices. /-! We now define our flow network. Our goal will be to prove weak_duality. @@ -57,7 +56,7 @@ notation ` V' ` := univ structure digraph (V : Type*) [inst : fintype V] := (is_edge : V → V → Prop) - (hnonsymmetric : ∀ u v : V, ¬ ((is_edge u v) ∧ (is_edge v u))) + (nonsymmetric : ∀ u v : V, ¬ ((is_edge u v) ∧ (is_edge v u))) structure capacity (V : Type*) [inst : fintype V] extends digraph V := @@ -81,11 +80,11 @@ def mk_out {V : Type* } [inst : fintype V] structure active_flow_network (V : Type*) [fintype V] := (network : flow_network V) (f : V -> V -> ℝ) - (sourceNotSink: network.source ≠ network.sink) + (source_not_sink: network.source ≠ network.sink) (non_neg_flow : ∀ u v : V, f u v ≥ 0) (no_overflow : ∀ u v : V, f u v ≤ network.c u v) - (noEdgesInSource : ∀ u : V, ¬ (network.is_edge u network.source)) - (noEdgesOutSink : ∀ u: V, ¬ (network.is_edge network.sink u)) + (no_edges_in_source : ∀ u : V, ¬ (network.is_edge u network.source)) + (no_edges_out_sink : ∀ u: V, ¬ (network.is_edge network.sink u)) (conservation : ∀ v : V, v ∈ (V' : finset V) \ {network.source, network.sink} → mk_out f {v} = mk_in f {v}) @@ -98,7 +97,7 @@ def F_value {V : Type*} [fintype V] : structure cut (V : Type*) [fintype V] := (network : flow_network V) (S : finset V) - (T : finset V ) + (T : finset V) (sins : network.source ∈ S) (tint : network.sink ∈ T) (Tcomp : T = univ \ S) @@ -111,10 +110,7 @@ lemma f_vanishes_outside_edge {V : Type*} [fintype V] (afn : active_flow_network V) (u : V) (v : V) (not_edge: ¬afn.network.is_edge u v) : afn.f u v = 0 := begin - have cap_is_zero: afn.network.c u v = 0 := - begin - exact afn.network.vanishes u v not_edge, - end, + have zeroCap: afn.network.c u v = 0 := afn.network.vanishes u v not_edge, have bar := afn.no_overflow u v, have foo := afn.non_neg_flow u v, linarith, @@ -127,18 +123,16 @@ begin cases c, simp only [mem_singleton] at *, rw c_Tcomp at xInS, - have h : univ \ c_S ∩ c_S = ∅ := sdiff_inter_self c_S univ, - have foo : disjoint (univ \ c_S) c_S := sdiff_disjoint, - have bar : c_network.source ∈ c_S := c_sins, + have h: univ \ c_S ∩ c_S = ∅ := sdiff_inter_self c_S univ, + have foo: disjoint (univ \ c_S) c_S := sdiff_disjoint, + have bar: c_network.source ∈ c_S := c_sins, exact disjoint_iff_ne.mp foo x xInS c_network.source c_sins end -lemma foobar { a b : ℝ } : a + - b = a - b := rfl - lemma f_zero {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (x : V) : afn.f x x = 0 := begin - have hnonsymm : _ := afn.network.hnonsymmetric x x, + have hnonsymm: _ := afn.network.nonsymmetric x x, have hvanish: _ := afn.network.vanishes x x, simp only [not_and, imp_not_self] at hnonsymm, have hnon_edge := hnonsymm, clear hnonsymm, @@ -155,12 +149,11 @@ lemma mk_in_single_node { V : Type* } [fintype V] mk_in (afn.f) {p} = ∑ v in finset.univ, (afn.f) v p := begin rw @sum_eq_sum_diff_singleton_add _ _ _ _ univ p (by simp only [mem_univ]) (λ x, afn.f x p), - have foo : (λ (x : V), afn.f x p) p = afn.f p p := rfl, simp only [congr_fun], rw f_zero afn p, - have bar : ∑ (x : V) in univ \ {p}, afn.f x p + 0 = + have foo: ∑ (x : V) in univ \ {p}, afn.f x p + 0 = (λ p', ∑ (x : V) in univ \ {p'}, afn.f x p') p := by simp only [add_zero], - rw bar, clear bar, + rw foo, clear foo, rw ← @finset.sum_singleton _ _ p (λp', ∑ (x : V) in univ \ {p'}, afn.f x p' ) _, simp only [mk_in, sum_singleton], end @@ -174,12 +167,11 @@ lemma mk_out_single_node { V : Type* } [fintype V] mk_out afn.f {p} = ∑ v in finset.univ, (afn.f) p v := begin rw @sum_eq_sum_diff_singleton_add _ _ _ _ univ p (by simp only [mem_univ]) (λ x, afn.f p x), - have foo : (λ (x : V), afn.f p x) p = afn.f p p := rfl, simp only [congr_fun], rw f_zero afn p, - have bar : ∑ (x : V) in univ \ {p}, afn.f p x + 0 = + have foo: ∑ (x : V) in univ \ {p}, afn.f p x + 0 = (λ p', ∑ (x : V) in univ \ {p'}, afn.f p' x) p := by simp only [add_zero], - rw bar, clear bar, + rw foo, clear foo, rw ← @finset.sum_singleton _ _ p (λp', ∑ (x : V) in univ \ {p'}, afn.f p' x) _, simp only [mk_out, sum_singleton], end @@ -201,10 +193,12 @@ begin intro hx, unfold edge_flow, rw afn.conservation x, - {ring}, - {exact hx,} + { ring }, + { exact hx }, end +lemma foobar { a b : ℝ } : a + - b = a - b := rfl + lemma sub_comm_zero (a b : ℝ) : a - b = 0 → b - a = 0 := by {intro eq, linarith} lemma set_flow_conservation {V : Type*} [inst' : fintype V] @@ -217,7 +211,7 @@ begin rw ← add_zero (mk_in afn.f S), nth_rewrite 0 ← add_neg_self (∑ u in S, (∑ v in S, afn.f u v)), rw ← add_assoc, - have tmp: mk_in afn.f S + ∑ u in S, ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := + have foo: mk_in afn.f S + ∑ u in S, ∑ v in S, afn.f u v = ∑ u in S, ∑ v in V', afn.f v u := begin unfold mk_in, have h: S ⊆ V' := finset.subset_univ S, @@ -228,43 +222,42 @@ begin rw hyp, exact swap, end, - have tmp2: mk_out afn.f S + (∑ u in S, ∑ v in S, afn.f u v) = ∑ u in S, ∑ v in V', afn.f u v := + have bar: mk_out afn.f S + (∑ u in S, ∑ v in S, afn.f u v) = ∑ u in S, ∑ v in V', afn.f u v := begin unfold mk_out, rw finset.sum_comm, have h: S ⊆ V' := finset.subset_univ S, - have hyp: + have baz: ∑ (y : V) in V' \ S, ∑ (x : V) in S, afn.f x y + ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ u in V', ∑ v in S, afn.f v u := finset.sum_sdiff h, - have obvs: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = + have bark: ∑ (u : V) in S, ∑ (v : V) in S, afn.f v u = ∑ (u : V) in S, ∑ (v : V) in S, afn.f u v := finset.sum_comm, have swap: ∑ u in V', ∑ v in S, afn.f v u = ∑ u in S, ∑ v in V', afn.f u v := finset.sum_comm, - rw obvs at hyp, - rw hyp, + rw bark at baz, + rw baz, exact swap, end, - rw tmp, + rw foo, rw add_assoc, rw break_out_neg, nth_rewrite 1 add_comm, - rw tmp2, - clear tmp tmp2, + rw bar, + clear foo bar, rw foobar, rw ← @sum_sub_distrib _ _ S _ _ _, simp only [mk_in_single_node', mk_out_single_node'], - have hseq : S = S := rfl, have h : ∀ (x : V), x ∈ S -> - edge_flow afn x = 0 := begin intros x hx, unfold edge_flow, rw afn.conservation x, - { ring, }, - { exact finset.mem_of_subset stNotInS hx,} + { ring }, + { exact finset.mem_of_subset stNotInS hx }, end, - have foo := finset.sum_congr hseq h, - unfold edge_flow at foo, - simp at foo, - rw ← foo, + have baz := finset.sum_congr rfl h, + unfold edge_flow at baz, + simp at baz, + rw ← baz, simp, end @@ -293,6 +286,223 @@ begin simp end +lemma sdiff_finset_sdiff_singleton_eq_sdiff_singleton {V : Type*} [inst' : fintype V] + (S : finset V) (s : V) : (s ∈ S) → V' \ (S \ {s}) \ {s} = V' \ S := +begin + intro sInS, + have sSubsetS: {s} ⊆ S := (finset.singleton_subset_iff).2 sInS, + ext x, + have eq1: V' \ (S \ {s}) \ {s} = V' \ (S \ {s}) ∩ (V' \ {s}) := + finset.sdiff_sdiff_left' V' (S \ {s}) {s}, + rw eq1, + have xIn: x ∈ V' := finset.mem_univ x, + split, + { + intro hyp, + have xIn1: x ∈ V' \ (S \ {s}) := (finset.mem_inter.1 hyp).1, + have xIn2: x ∈ V' \ {s} := (finset.mem_inter.1 hyp).2, + have xOut: x ∉ S := + begin + have xOut1: x ∉ (S \ {s}) := (finset.mem_sdiff.1 xIn1).2, + have xOut2: x ∉ {s} := (finset.mem_sdiff.1 xIn2).2, + have xOutAnd: x ∉ (S \ {s}) ∧ x ∉ {s} := and.intro xOut1 xOut2, + have eq2: S = (S \ {s}) ∪ {s} := + begin + have inter: S ∩ {s} = {s} := finset.inter_singleton_of_mem sInS, + have eq3: (S \ {s}) ∪ S ∩ {s} = S := by rw finset.sdiff_union_inter S {s}, + calc + S + = (S \ {s}) ∪ S ∩ {s} : eq_comm.1 eq3 + ... = (S \ {s}) ∪ {s} : by rw inter, + end, + rw eq2, + exact finset.not_mem_union.2 xOutAnd, + end, + have concl: x ∈ V' ∧ x ∉ S := and.intro xIn xOut, + exact finset.mem_sdiff.2 concl, + }, + intro hyp, + have xOutS: x ∉ S := (finset.mem_sdiff.1 hyp).2, + have xOut: x ∉ S \ {s} := + begin + by_contradiction h, + have contr: x ∈ S := (finset.mem_sdiff.1 h).1, + exact absurd contr xOutS, + end, + have sdiff: x ∈ V' ∧ x ∉ S \ {s} := and.intro xIn xOut, + have xIn1: x ∈ V' \ (S \ {s}) := finset.mem_sdiff.2 sdiff, + have xNotIns: x ∉ {s} := + begin + by_contradiction h, + have contr: x ∈ S := finset.mem_of_subset sSubsetS h, + exact absurd contr xOutS, + end, + have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, + have xIn2: x ∈ V' \ {s} := finset.mem_sdiff.2 concl, + have member: x ∈ V' \ (S \ {s}) ∧ x ∈ V' \ {s} := and.intro xIn1 xIn2, + exact finset.mem_inter.2 member, +end + +lemma sdiff_finset_union_finset_eq_sdiff_singleton {V : Type*} [inst' : fintype V] + (S : finset V) (s : V) : (s ∈ S) → V' \ S ∪ S \ {s} = V' \ {s} := +begin + intro sInS, + have sSubsetS: {s} ⊆ S := (finset.singleton_subset_iff).2 sInS, + ext x, + have xIn: x ∈ V' := finset.mem_univ x, + split, + { + intro hyp, + have foo: x ∈ V' \ S ∨ x ∈ S \ {s} := finset.mem_union.1 hyp, + have bar: x ∈ V' \ S → x ∈ V' \ {s} := + begin + intro hypo, + have xOutS: x ∉ S := (finset.mem_sdiff.1 hypo).2, + have xNotIns: x ∉ {s} := + begin + by_contradiction h, + have contr: x ∈ S := finset.mem_of_subset sSubsetS h, + exact absurd contr xOutS, + end, + have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, + exact finset.mem_sdiff.2 concl, + end, + have baz: x ∈ S \ {s} → x ∈ V' \ {s} := + begin + intro hypo, + have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hypo).2, + have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, + exact finset.mem_sdiff.2 concl, + end, + exact or.elim foo bar baz, + }, + intro hyp, + have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hyp).2, + by_cases h' : x ∈ S, + { + have and: x ∈ S ∧ x ∉ {s} := and.intro h' xNotIns, + have xInSs: x ∈ S \ {s} := finset.mem_sdiff.2 and, + have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_right (x ∈ V' \ S) xInSs, + exact finset.mem_union.2 conj, + }, + { + have and: x ∈ V' ∧ x ∉ S := and.intro xIn h', + have xInVS: x ∈ V' \ S := finset.mem_sdiff.2 and, + have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_left (x ∈ S \ {s}) xInVS, + exact finset.mem_union.2 conj, + }, +end + +lemma disjoint_sdiff_finset_sdiff_singleton {V : Type*} [inst' : fintype V] + (S : finset V) (s : V) : disjoint (V' \ S) (S \ {s}) := +begin + have foo: (V' \ S) ∩ (S \ {s}) = ∅ := + begin + have noMembers: ∀ (v : V), v ∉ (V' \ S) ∩ (S \ {s}) := + begin + intro v, + by_contradiction h, + have vInVmS: v ∈ (V' \ S) := (finset.mem_inter.1 h).1, + have vNotInS: v ∉ S := (finset.mem_sdiff.1 vInVmS).2, + have vInSms: v ∈ (S \ {s}) := (finset.mem_inter.1 h).2, + have vInS: v ∈ S := (finset.mem_sdiff.1 vInSms).1, + exact absurd vInS vNotInS, + end, + exact finset.eq_empty_of_forall_not_mem noMembers, + end, + have bar: ¬ ((V' \ S) ∩ (S \ {s})).nonempty := + begin + by_contradiction h, + have contr: (V' \ S) ∩ (S \ {s}) ≠ ∅ := finset.nonempty.ne_empty h, + exact absurd foo contr, + end, + by_contradiction notDisjoint, + have contr: ((V' \ S) ∩ (S \ {s})).nonempty := finset.not_disjoint_iff_nonempty_inter.1 notDisjoint, + exact absurd contr bar, +end + +lemma sum_sdiff_singleton_sum_sdiff_finset_sdiff_singleton {V : Type*} [inst' : fintype V] + (f : V → V → ℝ) (S : finset V) (s : V) : + (s ∈ S) → ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = + ∑ (x : V) in (S \ {s}), f x s + ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ S, f x y := +begin + intro sInS, + have singleton: s ∈ {s} := finset.mem_singleton.2 rfl, + have disjS: disjoint {s} (S \ {s}) := + begin + have sOut: s ∉ (S \ {s}) := finset.not_mem_sdiff_of_mem_right singleton, + exact finset.disjoint_singleton_left.2 sOut, + end, + have sInCompl: {s} ⊆ V' \ (S \ {s}) := + begin + have sIn: {s} ⊆ V' := finset.subset_univ {s}, + have conj: {s} ⊆ V' ∧ disjoint {s} (S \ {s}) := and.intro sIn disjS, + exact finset.subset_sdiff.2 conj, + end, + have foo: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = + ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y := finset.sum_comm, + have bar: ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y = + ∑ (y : V) in V' \ S, ∑ (x : V) in (S \ {s}), f x y + ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y := + by {rw ← finset.sum_sdiff sInCompl, rw sdiff_finset_sdiff_singleton_eq_sdiff_singleton S s sInS}, + have baz: ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y = ∑ (x : V) in (S \ {s}), f x s := + by simp, + have swap: ∑ (y : V) in V' \ S, ∑ (x : V) in S \ {s}, f x y = + ∑ (x : V) in S \ {s}, ∑ (y : V) in V' \ S, f x y := finset.sum_comm, + rw baz at bar, + rw [foo, bar, add_comm, swap], +end + +lemma in_expansion {V : Type*} [inst' : fintype V] + (f : V → V → ℝ) (S : finset V) (s : V) : + (s ∈ S) → ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := +begin + intro sInS, + have sSubsetS: {s} ⊆ S := (finset.singleton_subset_iff).2 sInS, + have foo: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y := + finset.sum_comm, + have bar: ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y = + ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y := + by {rw finset.sum_sdiff sSubsetS}, + have swap: + ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := + begin + have swap1: ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y := finset.sum_comm, + have swap2: ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := finset.sum_comm, + linarith, + end, + linarith, +end + +lemma sum_sdiff_finset_sdiff_singleton_sum_sdiff_singleton {V : Type*} [inst' : fintype V] + (f : V → V → ℝ) (S : finset V) (s : V) : + (s ∈ S) → ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (u : V) in S \ {s}, f s u := +begin + intro sInS, + have singleton: s ∈ {s} := finset.mem_singleton.2 rfl, + have disjS: disjoint {s} (S \ {s}) := + begin + have sOut: s ∉ (S \ {s}) := finset.not_mem_sdiff_of_mem_right singleton, + exact finset.disjoint_singleton_left.2 sOut, + end, + have sInCompl: {s} ⊆ V' \ (S \ {s}) := + begin + have sIn: {s} ⊆ V' := finset.subset_univ {s}, + have conj: {s} ⊆ V' ∧ disjoint {s} (S \ {s}) := and.intro sIn disjS, + exact finset.subset_sdiff.2 conj, + end, + have foo: ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y := + by {rw ← finset.sum_sdiff sInCompl, rw sdiff_finset_sdiff_singleton_eq_sdiff_singleton S s sInS}, + have bar: ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y = ∑ (u : V) in S \ {s}, f s u := + by simp, + linarith, +end + lemma flow_value_source_in_S {V : Type*} [inst' : fintype V] (afn : active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network) : @@ -304,10 +514,7 @@ begin set s := afn.network.source, set t := afn.network.sink, set f := afn.f, - have same: s = s := rfl, - have hs : s = afn.network.source := rfl, - have hT : T = ct.T := rfl, - have singleton: s ∈ {s} := finset.mem_singleton.2 same, + have singleton: s ∈ {s} := finset.mem_singleton.2 rfl, have sInS: s ∈ S := begin have same_source: s = ct.network.source := (same_source_and_sink afn ct same_net).1, @@ -330,7 +537,7 @@ begin begin by_contradiction h, have contr: s = t := by rw ← h, - exact absurd contr afn.sourceNotSink, + exact absurd contr afn.source_not_sink, end, have tNotInS: t ∉ S := begin @@ -344,135 +551,14 @@ begin exact finset.not_mem_sdiff_of_mem_right tInT, end, have seteq: V' \ (S \ {s}) \ {s} = V' \ S := - begin - ext x, - have eq1: V' \ (S \ {s}) \ {s} = V' \ (S \ {s}) ∩ (V' \ {s}) := - finset.sdiff_sdiff_left' V' (S \ {s}) {s}, - rw eq1, - have xIn: x ∈ V' := finset.mem_univ x, - split, - { - intro hyp, - have xIn1: x ∈ V' \ (S \ {s}) := (finset.mem_inter.1 hyp).1, - have xIn2: x ∈ V' \ {s} := (finset.mem_inter.1 hyp).2, - have xOut: x ∉ S := - begin - have xOut1: x ∉ (S \ {s}) := (finset.mem_sdiff.1 xIn1).2, - have xOut2: x ∉ {s} := (finset.mem_sdiff.1 xIn2).2, - have xOutAnd: x ∉ (S \ {s}) ∧ x ∉ {s} := and.intro xOut1 xOut2, - have eq2: S = (S \ {s}) ∪ {s} := - begin - have inter: S ∩ {s} = {s} := finset.inter_singleton_of_mem sInS, - have eq3: (S \ {s}) ∪ S ∩ {s} = S := by rw finset.sdiff_union_inter S {s}, - calc - S - = (S \ {s}) ∪ S ∩ {s} : eq_comm.1 eq3 - ... = (S \ {s}) ∪ {s} : by rw inter, - end, - rw eq2, - exact finset.not_mem_union.2 xOutAnd, - end, - have concl: x ∈ V' ∧ x ∉ S := and.intro xIn xOut, - exact finset.mem_sdiff.2 concl, - }, - intro hyp, - have xOutS: x ∉ S := (finset.mem_sdiff.1 hyp).2, - have xOut: x ∉ S \ {s} := - begin - by_contradiction h, - have contr: x ∈ S := (finset.mem_sdiff.1 h).1, - exact absurd contr xOutS, - end, - have sdiff: x ∈ V' ∧ x ∉ S \ {s} := and.intro xIn xOut, - have xIn1: x ∈ V' \ (S \ {s}) := finset.mem_sdiff.2 sdiff, - have xNotIns: x ∉ {s} := - begin - by_contradiction h, - have contr: x ∈ S := finset.mem_of_subset sSubsetS h, - exact absurd contr xOutS, - end, - have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, - have xIn2: x ∈ V' \ {s} := finset.mem_sdiff.2 concl, - have member: x ∈ V' \ (S \ {s}) ∧ x ∈ V' \ {s} := and.intro xIn1 xIn2, - exact finset.mem_inter.2 member, - end, + sdiff_finset_sdiff_singleton_eq_sdiff_singleton S s sInS, have union: V' \ S ∪ S \ {s} = V' \ {s} := - begin - ext x, - have xIn: x ∈ V' := finset.mem_univ x, - split, - { - intro hyp, - have h1: x ∈ V' \ S ∨ x ∈ S \ {s} := finset.mem_union.1 hyp, - have h2: x ∈ V' \ S → x ∈ V' \ {s} := - begin - intro hypo, - have xOutS: x ∉ S := (finset.mem_sdiff.1 hypo).2, - have xNotIns: x ∉ {s} := - begin - by_contradiction h, - have contr: x ∈ S := finset.mem_of_subset sSubsetS h, - exact absurd contr xOutS, - end, - have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, - exact finset.mem_sdiff.2 concl, - end, - have h3: x ∈ S \ {s} → x ∈ V' \ {s} := - begin - intro hypo, - have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hypo).2, - have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, - exact finset.mem_sdiff.2 concl, - end, - exact or.elim h1 h2 h3, - }, - intro hyp, - have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hyp).2, - by_cases h' : x ∈ S, - { - have and: x ∈ S ∧ x ∉ {s} := and.intro h' xNotIns, - have xInSs: x ∈ S \ {s} := finset.mem_sdiff.2 and, - have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_right (x ∈ V' \ S) xInSs, - exact finset.mem_union.2 conj, - }, - { - have and: x ∈ V' ∧ x ∉ S := and.intro xIn h', - have xInVS: x ∈ V' \ S := finset.mem_sdiff.2 and, - have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_left (x ∈ S \ {s}) xInVS, - exact finset.mem_union.2 conj, - }, - end, - have disj: disjoint (V' \ S) (S \ {s}) := - begin - have h1: (V' \ S) ∩ (S \ {s}) = ∅ := - begin - have noMembers: ∀ (v : V), v ∉ (V' \ S) ∩ (S \ {s}) := - begin - intro v, - by_contradiction h, - have vInVmS: v ∈ (V' \ S) := (finset.mem_inter.1 h).1, - have vNotInS: v ∉ S := (finset.mem_sdiff.1 vInVmS).2, - have vInSms: v ∈ (S \ {s}) := (finset.mem_inter.1 h).2, - have vInS: v ∈ S := (finset.mem_sdiff.1 vInSms).1, - exact absurd vInS vNotInS, - end, - exact finset.eq_empty_of_forall_not_mem noMembers, - end, - have h2: ¬ ((V' \ S) ∩ (S \ {s})).nonempty := - begin - by_contradiction h, - have contr: (V' \ S) ∩ (S \ {s}) ≠ ∅ := finset.nonempty.ne_empty h, - exact absurd h1 contr, - end, - by_contradiction notDisjoint, - have contr: ((V' \ S) ∩ (S \ {s})).nonempty := finset.not_disjoint_iff_nonempty_inter.1 notDisjoint, - exact absurd contr h2, - end, + sdiff_finset_union_finset_eq_sdiff_singleton S s sInS, + have disj: disjoint (V' \ S) (S \ {s}) := disjoint_sdiff_finset_sdiff_singleton S s, have disjTS: disjoint {t} {s} := finset.disjoint_singleton.2 (tNots), have expand: mk_out f {s} + (mk_out f (S \ {s}) - mk_in f (S \ {s})) - mk_in f {s} = mk_out f {s} - mk_in f {s} := begin - have h3: s ∉ S \ {s} := finset.not_mem_sdiff_of_mem_right singleton, have eq: mk_out f (S \ {s}) - mk_in f (S \ {s}) = 0 := begin have h: (S \ {s}) ⊆ finset.univ \ {s,t} := @@ -523,24 +609,13 @@ begin have eq2: ∑ (x : V) in {s}, ∑ (y : V) in V' \ S, f x y = ∑ (y : V) in V' \ S, f s y := by simp, have eq3: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = ∑ (x : V) in (S \ {s}), f x s + ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ S, f x y := - begin - have obvs: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = - ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y := finset.sum_comm, - have sdiff: ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y = - ∑ (y : V) in V' \ S, ∑ (x : V) in (S \ {s}), f x y + ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y := - by {rw ← finset.sum_sdiff sInCompl, rw seteq}, - have obs: ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y = ∑ (x : V) in (S \ {s}), f x s := by {simp}, - have swap: ∑ (y : V) in V' \ S, ∑ (x : V) in S \ {s}, f x y = - ∑ (x : V) in S \ {s}, ∑ (y : V) in V' \ S, f x y := finset.sum_comm, - rw obs at sdiff, - rw [obvs, sdiff, add_comm, swap], - end, + sum_sdiff_singleton_sum_sdiff_finset_sdiff_singleton f S s sInS, have eq4: ∑ (x : V) in {s}, ∑ (y : V) in V' \ {s}, f x y = ∑ (y : V) in V' \ S, f s y + ∑ (u : V) in S \ {s}, f s u := begin - have obvs: ∑ (x : V) in {s}, ∑ (y : V) in V' \ {s}, f x y = - ∑ (y : V) in V' \ {s}, f s y := by {simp}, - rw obvs, + have foo: ∑ (x : V) in {s}, ∑ (y : V) in V' \ {s}, f x y = + ∑ (y : V) in V' \ {s}, f s y := by simp, + rw foo, rw ← union, exact finset.sum_union disj, end, @@ -552,41 +627,21 @@ begin unfold mk_in, have eq1: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := - begin - have obvs: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y := finset.sum_comm, - have sdiff: ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y = - ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y := - by {rw finset.sum_sdiff sSubsetS}, - have swap: ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := - begin - have eq11: ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y := finset.sum_comm, - have eq12: ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := finset.sum_comm, - linarith, - end, - linarith, - end, - have eq2: ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y = ∑ (u : V) in V' \ S, f u s := by {simp}, + in_expansion f S s sInS, + have eq2: ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y = ∑ (u : V) in V' \ S, f u s := + by simp, have eq3: ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (u : V) in S \ {s}, f s u := - begin - have eq31: ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y := - by {rw ← finset.sum_sdiff sInCompl, rw seteq}, - have eq32: ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y = ∑ (u : V) in S \ {s}, f s u := by {simp}, - linarith, - end, + sum_sdiff_finset_sdiff_singleton_sum_sdiff_singleton f S s sInS, have eq4: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, f x y = ∑ (u : V) in V' \ S, f u s + ∑ (u : V) in S \ {s}, f u s := begin - have obvs: ∑ (u : V) in V' \ S, f u s = - ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := by {simp}, - have obs: ∑ (u : V) in S \ {s}, f u s = - ∑ (x : V) in S \ {s}, ∑ (y : V) in {s}, f x y := by {simp}, + have foo: ∑ (u : V) in V' \ S, f u s = + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := by simp, + have bar: ∑ (u : V) in S \ {s}, f u s = + ∑ (x : V) in S \ {s}, ∑ (y : V) in {s}, f x y := by simp, rw ← union, - rw [obvs,obs], + rw [foo,bar], exact finset.sum_union disj, end, linarith, @@ -603,7 +658,7 @@ end -/ lemma weak_duality {V: Type*} [inst' : fintype V] - (afn: active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network): + (afn : active_flow_network V) (ct : cut V) (same_net : afn.network = ct.network): F_value afn ≤ cut_cap ct := begin set S := ct.S, @@ -611,38 +666,6 @@ begin set s := afn.network.source, set t := afn.network.sink, unfold cut_cap, - have same: s = s := by {simp}, - have hs : s = afn.network.source := rfl, - have hT : T = ct.T := rfl, - have singleton: s ∈ {s} := finset.mem_singleton.2 same, - have sInS: s ∈ S := - begin - have same_source: s = ct.network.source := (same_source_and_sink afn ct same_net).1, - rw same_source, - exact ct.sins, - end, - have sInCompl: {s} ⊆ V' \ (S \ {s}) := - begin - have sIn: {s} ⊆ V' := finset.subset_univ {s}, - have disjS: disjoint {s} (S \ {s}) := - begin - have sOut: s ∉ (S \ {s}) := finset.not_mem_sdiff_of_mem_right singleton, - exact finset.disjoint_singleton_left.2 sOut, - end, - have conj: {s} ⊆ V' ∧ disjoint {s} (S \ {s}) := and.intro sIn disjS, - exact finset.subset_sdiff.2 conj, - end, - have tNotInS: t ∉ S := - begin - have same_sink: t = ct.network.sink := (same_source_and_sink afn ct same_net).2, - have tInT: t ∈ T := by {rw same_sink, exact ct.tint}, - have Tcomp : T = univ \ S := ct.Tcomp, - have foo: S = univ \ (univ \ S) := - by {simp only [sdiff_sdiff_right_self, finset.inf_eq_inter, finset.univ_inter]}, - have Scomp : S = univ \ T := by {rw ← Tcomp at foo, exact foo}, - rw Scomp at *, - exact finset.not_mem_sdiff_of_mem_right tInT, - end, have lemma1: F_value afn = mk_out afn.f S - mk_in afn.f S := by {unfold F_value, exact flow_value_source_in_S afn ct same_net}, have lemma2: mk_out afn.f S ≤ mk_out ct.network.to_capacity.c S := @@ -676,9 +699,6 @@ begin apply le_trans lemma3 lemma2, end -lemma zero_left_move {a b c d : ℝ} : (0 = a + b - c - d) -> (d - b = a - c) := -by {intro h, linarith} - def is_max_flow {V : Type*} [inst' : fintype V] (fn: active_flow_network V) : Prop := ∀ fn' : active_flow_network V, fn.network = fn'.network → F_value fn' ≤ F_value fn @@ -687,7 +707,7 @@ def is_min_cut {V : Type*} [inst' : fintype V] (fn: cut V) : Prop := ∀ fn' : cut V, fn.network = fn'.network → cut_cap fn ≤ cut_cap fn' lemma max_flow_criterion {V : Type*} [inst' : fintype V] - (afn : active_flow_network V) (ct : cut V) (hsame_network: afn.network = ct.network): + (afn : active_flow_network V) (ct : cut V) (hsame_network : afn.network = ct.network): cut_cap ct = F_value afn -> is_max_flow afn := begin intros eq fn same_net, @@ -716,7 +736,7 @@ def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow (afn : active_flow_network V) (u v : V) : ℝ := if afn.network.is_edge u v - then afn.network.c u v - afn.f u v + then afn.network.c u v - afn.f u v else if afn.network.is_edge v u then afn.f v u else 0 @@ -726,7 +746,7 @@ structure residual_network (V : Type*) [inst' : fintype V] := (f' : V -> V -> ℝ) (f_def : f' = mk_rsf afn) (is_edge : V -> V -> Prop) - (is_edge_def : is_edge = λ u v, f' u v > 0 ) + (is_edge_def : is_edge = λ u v, f' u v > 0) noncomputable def mk_rsn {V : Type*} [fintype V] -- stays for residual network @@ -736,18 +756,20 @@ def mk_rsn {V : Type*} [fintype V] -- stays for residual network universe u /- - We define a path structure indicating if there is a path between two vertices, - given the edges in the graph. + We define a recursive structure returning the path between two vertices, + if such a path exists, given the edges in the graph. -/ - inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) | nil : path a | cons : Π {b c : V}, path b → (is_edge b c) → path c -def no_augumenting_path {V : Type*} [inst' : fintype V] +def no_augmenting_path {V : Type*} [inst' : fintype V] (rsn : residual_network V) : Prop := ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) +/- + Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. +-/ def path.in {V : Type u } {is_edge : V -> V -> Prop} (u v : V) @@ -763,180 +785,465 @@ begin simp only, rw rsn_f_def, unfold mk_rsf, - have tmp := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), - cases tmp, + have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, { - simp only [tmp, if_true, sub_nonneg, rsn_afn.no_overflow], + simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, { - simp only [tmp, if_false], clear tmp, - have tmp := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), - cases tmp, + simp only [foo, if_false], clear foo, + have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), + cases bar, { have h := rsn_afn.non_neg_flow v u, - simp only [tmp, h, if_true], + simp only [bar, h, if_true], linarith, }, { - simp only [tmp, if_false], + simp only [bar, if_false], }, }, end +lemma positive_residual_flow {V : Type*} [inst' : fintype V] + (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := +begin + intro edge, + rw rsn.is_edge_def at edge, + exact edge, +end + /-! Here is our second big lemma, if the active flow is maximum, then no augmenting path exists in the residual network. -/ lemma no_augm_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augumenting_path rsn := + (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := begin - intros max_flow v exists_path, + intros max_flow x exists_path, by_contradiction is_sink, set s := rsn.afn.network.source, set t := rsn.afn.network.sink, - set vertices := {s} ∪ { x | (∃ y: V, exists_path.in x y) }, --all vertices in the augmenting path - set d := 0, - -- set flows := { rsn.f' x y | exists_path.in x y }, -- set of reals, why it doesn't work? - -- set d := flows.min, -- the minimum flow in the augmenting path - have pos: 0 < d := by sorry, -- by definition of is_edge in the residual network + have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, + have exists_augm_path: ¬no_augmenting_path rsn := + begin + unfold no_augmenting_path, + push_neg, + use x, + by_contradiction h, + have contr: x ≠ t := h exists_path, + exact absurd is_sink contr, + end, + --all vertices in the augmenting path + set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), + -- set of all flow values in the augmenting path + set flows := set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), + have nonemp: flows.nonempty := + begin + by_contradiction h, + have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, + have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := + begin + intros v hyp, + have t_in_vertices: t ∈ vertices := by simp, + have v_in_vertices: v ∈ vertices := + begin + simp only [set.mem_to_finset, set.mem_set_of_eq], + have baz: exists_path.in v t := hyp, + have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, + have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + by {simp only [set.mem_set_of_eq], exact exist}, + have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + or.intro_right (v ∈ {t}) mem, + exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, + end, + have contr: rsn.f' v t ∈ flows := + begin + simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, + true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, set.to_finset_insert, + finset.mem_filter, vertices] at v_in_vertices, + apply v_in_vertices.elim; + intro hypo, + { + simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, set.mem_image, + set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, prod.exists, + function.uncurry_apply_pair, set.to_finset_nonempty, set.nonempty_image_iff, + set.to_finset_eq_empty, set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, + prod.forall, eq_self_iff_true, true_or] at *, + use [t, t], + simpa, + }, + { + simp only [set.singleton_union, set.mem_image, set.mem_to_finset, + set.coe_to_finset, prod.exists], + use [v, t], + simp [hypo, hyp] + }, + end, + exact finset.ne_empty_of_mem contr, + end, + have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path + begin + by_contradiction h, + push_neg at h, + have no_augm_path: no_augmenting_path rsn := by sorry, + exact absurd no_augm_path exists_augm_path, + end, + have contr: flows ≠ ∅ := exists.elim bar foo, + exact absurd empty contr, + end, + set d := flows.min' nonemp, -- the minimum flow in the augmenting path + have pos: 0 < d := + begin + have mem: d ∈ flows := finset.min'_mem flows nonemp, + have pos: ∀ f : ℝ , f ∈ flows → f > 0 := + begin + intros f hyp, + simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, + set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, + function.uncurry_apply_pair] at hyp, + obtain ⟨a, b, hyp, hyp'⟩ := hyp, + rw [← hyp'], + apply positive_residual_flow, + sorry, + end, + exact pos d mem, + end, set better_flow: active_flow_network V := ⟨rsn.afn.network, - (λ u v : V, if exists_path.in u v then rsn.afn.f u v + d - else if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v), + (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d + else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), begin -- source ≠ sink - exact rsn.afn.sourceNotSink, + exact rsn.afn.source_not_sink, end, begin -- non_neg_flow intros u v, - by_cases h: exists_path.in u v, - { - have h1: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, - have h2: d ≥ 0 := -- needs to be changed, we can use the definition of rsn and split into cases - begin - by_contradiction h', - have h3: d < 0 := lt_of_not_ge h', - have h4: ¬ d < 0 := not_lt_of_gt pos, - exact absurd h3 h4, - end, - linarith, - }, + by_cases edge: rsn.afn.network.is_edge u v, { - by_cases h': exists_path.in v u, + simp only [edge, if_true], + by_cases h: exists_path.in u v, + { + have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, + simp only [h, if_true], + linarith, + }, + { + by_cases h': exists_path.in v u, { - have h1: rsn.f' v u = rsn.afn.f u v := + simp only [h, if_false, h', if_true], + have ine: d ≤ rsn.afn.f u v := begin - rw rsn.f_def, - have edge: rsn.afn.network.is_edge v u := by sorry,-- use h' and definition of path.in - unfold mk_rsf, - sorry, -- just use edge to get the wanted result + have minimality: d ≤ rsn.f' v u := + begin + have min: ∀ f : ℝ , f ∈ flows → d ≤ f := + by {intros f hf, exact finset.min'_le flows f hf}, + have mem: rsn.f' v u ∈ flows := + begin + have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, + simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], + use [v, u], + simp [foo, h'], + sorry, + end, + exact min (rsn.f' v u) mem, + end, + have eq: rsn.f' v u = rsn.afn.f u v := + begin + rw rsn.f_def, + unfold mk_rsf, + have notAnd := rsn.afn.network.nonsymmetric u v, + simp only [not_and] at notAnd, + have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, + simp only [notEdge, if_false, edge, if_true], + end, + rw ← eq, + exact minimality, end, - have h2: rsn.f' v u ≥ d := by sorry, -- minimality of d - have h3: rsn.afn.f u v ≥ d := by {rw ←h1, exact h2}, linarith, }, { - -- exact rsn.afn.non_neg_flow u v, -- should be correct, why is not working? - linarith, + simp only [h, if_false, h', if_false], + exact rsn.afn.non_neg_flow u v, }, + }, + }, + { + simp only [edge, if_false], + linarith, }, end, begin -- no_overflow intros u v, - by_cases h: exists_path.in u v, + by_cases edge: rsn.afn.network.is_edge u v, { - have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := by sorry, - -- begin - -- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := by def of rsn - -- have h3: d ≤ rsn.f' u v := by minimality of d - -- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, - -- exact le_trans h4 h2 - -- end, - linarith, + simp only [edge, if_true], + by_cases h: exists_path.in u v, + { + have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := + begin + have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := + begin + have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := + by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, + rw eq, + linarith, + end, + have h3: d ≤ rsn.f' u v := + begin + have min: ∀ f : ℝ , f ∈ flows → d ≤ f := + by {intros f hf, exact finset.min'_le flows f hf}, + have mem: rsn.f' u v ∈ flows := + begin + have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, + simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], + use [u, v], + simp [foo, h], + sorry, + end, + exact min (rsn.f' u v) mem, + end, + have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, + exact le_trans h4 h2 + end, + simp only [h, if_true], + exact h1, + }, + { + by_cases h': exists_path.in v u, + { + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := + rsn.afn.no_overflow u v, + simp only [h, if_false, h', if_true], + linarith, + }, + { + simp only [h, if_false, h', if_false], + exact rsn.afn.no_overflow u v, + }, + }, }, { - by_cases h': exists_path.in v u, - { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := rsn.afn.no_overflow u v, - linarith, -- maybe pos will have to be used when d is properly defined - }, - { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := rsn.afn.no_overflow u v, - linarith, - }, + simp only [edge, if_false], + have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, + linarith, }, end, - begin --noEdgesInSource - exact rsn.afn.noEdgesInSource, + begin --no_edges_in_source + exact rsn.afn.no_edges_in_source, end, - begin --noEdgesOutSink - exact rsn.afn.noEdgesOutSink, + begin --no_edges_out_sink + exact rsn.afn.no_edges_out_sink, end, begin -- conservation intros v vNotSinkSource, + have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, + have vNotSource: v ≠ rsn.afn.network.source := + begin + by_contradiction h, + have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := + begin + have vSource: v ∈ {s} := finset.mem_singleton.2 h, + have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, + exact finset.mem_union.2 vOR, + end, + rw union at vIn, + have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := + by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, + exact absurd vIn vNotIn, + end, + have vNotSink: v ≠ rsn.afn.network.sink := + begin + by_contradiction h, + have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := + begin + have vSink: v ∈ {t} := finset.mem_singleton.2 h, + have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, + exact finset.mem_union.2 vOR, + end, + rw union at vIn, + have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := + by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, + exact absurd vIn vNotIn, + end, + set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) + (ite (path.in u v exists_path) (rsn.afn.f u v + d) + (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), by_cases h: v ∈ vertices, { - -- Issues: How are we proving the cardinality of predecessor and ancestor is 1? - -- How exactly do we use that within the code to prove h2 and h3? - set predecessor := {u | exists_path.in u v}, - set ancestor := {w | exists_path.in v w}, - have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := rsn.afn.conservation v vNotSinkSource, - -- have h2: mk_in f {v} = rsn.afn.mk_in {v} + d := by sorry, -- use the predecessor - -- have h3: mk_out f {v} = rsn.afn.mk_out {v} + d := by sorry, -- use the ancestor - -- rw [h2,h3,h1], - -- rfl, + -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? + -- How do we procced after for picking these edges? + -- Need to use the fact that x=t to show that there are always two edges for e given vertex outside {s,t} + -- set predecessor := {u | exists_path.in u v}, + -- set ancestor := {w | exists_path.in v w}, + -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := rsn.afn.conservation v vNotSinkSource, + -- rw [h2,h3,h1] sorry, }, { - sorry, - -- have h1: ∀ u : V, ¬exists_path.in u v := - -- begin - -- by_contradiction h', - -- have ancestor: ∃w: exists_path.in v w := by v ≠ t, - -- have contr: v ∈ vertives := by def of vertices and ancestor, - -- contradiction -- with ¬v ∈ vertices, - -- end, - -- have h2: ∀ w : V, ¬exists_path.in u w := - -- begin - -- by_contradiction h', - -- have contr: v ∈ vertives := by def of vertices, - -- contradiction -- with ¬v ∈ vertices - -- end, - -- have h3: ∀ u : V, better_flow.f u v = rsn.afn.f u v := by h1 and h2 - -- have h4: ∀ w : V, better_flow.f v w = rsn.afn.f v w := by h1 and h2 - -- rw [h3,h4], - -- exact rsn.afn.conservation v vNotSinkSource, + -- Problems in next two: How do we use the condition in the definition of the set to show inclusion? + have h1: ∀ u : V, ¬exists_path.in u v := + begin + by_contradiction h', + push_neg at h', + have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t + have contr: v ∈ vertices := + begin + simp only [set.mem_to_finset, set.mem_set_of_eq], + have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + by {simp only [set.mem_set_of_eq], exact ancestor}, + have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + or.intro_right (v ∈ {t}) mem, + exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, + end, + exact absurd contr h, + end, + have h2: ∀ w : V, ¬exists_path.in v w := + begin + by_contradiction h', + push_neg at h', + have contr: v ∈ vertices := + begin + simp only [set.mem_to_finset, set.mem_set_of_eq], + have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + by {simp only [set.mem_set_of_eq], exact h'}, + have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + or.intro_right (v ∈ {t}) mem, + exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, + end, + exact absurd contr h, + end, + have h3: ∀ u : V, newf u v = rsn.afn.f u v := + begin + intro u, + by_cases edge: rsn.afn.network.is_edge u v, + { + have noEdge: ¬exists_path.in u v := h1 u, + have noReversedEdge: ¬exists_path.in v u := h2 u, + have simplify: newf u v = ite (rsn.afn.network.is_edge u v) + (ite (path.in u v exists_path) (rsn.afn.f u v + d) + (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, + rw simplify, + simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], + }, + { + have simplify: newf u v = ite (rsn.afn.network.is_edge u v) + (ite (path.in u v exists_path) (rsn.afn.f u v + d) + (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, + rw simplify, + simp only [edge, if_false], + have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, + linarith, + }, + end, + have h4: ∀ w : V, newf v w = rsn.afn.f v w := + begin + intro w, + by_cases edge: rsn.afn.network.is_edge v w, + { + have noEdge: ¬exists_path.in w v := h1 w, + have noReversedEdge: ¬exists_path.in v w := h2 w, + have simplify: newf v w = ite (rsn.afn.network.is_edge v w) + (ite (path.in v w exists_path) (rsn.afn.f v w + d) + (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, + rw simplify, + simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], + }, + { + have simplify: newf v w = ite (rsn.afn.network.is_edge v w) + (ite (path.in v w exists_path) (rsn.afn.f v w + d) + (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, + rw simplify, + simp only [edge, if_false], + have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, + linarith, + }, + end, + have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := + begin + unfold mk_in, + have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = + ∑ (x : V) in V' \ {v}, newf x v := by simp, + have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = + ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, + rw [eq1, eq2], + exact finset.sum_congr rfl (λ u h, h3 u), + end, + have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := + begin + unfold mk_out, + have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = + ∑ (y : V) in V' \ {v}, newf v y := by simp, + have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = + ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, + rw [eq1, eq2], + exact finset.sum_congr rfl (λ u h, h4 u), + end, + rw [eqIn,eqOut], + exact rsn.afn.conservation v vNotSinkSource, }, end ⟩, have flow_value: F_value better_flow = F_value rsn.afn + d := begin unfold F_value, - have h1: mk_out better_flow.f {better_flow.network.source} = - mk_out rsn.afn.f {rsn.afn.network.source} + d := + set source := better_flow.network.source, + have h1: mk_out better_flow.f {source} = + mk_out rsn.afn.f {source} + d := by sorry, -- take the edge with the added flow - -- Issue: How do we prove that there is exactly one edge? How do we use it to prove h1? - have h2: mk_in better_flow.f {better_flow.network.source} = - mk_in rsn.afn.f {rsn.afn.network.source} := by {linarith}, + -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? + have h2: mk_in better_flow.f {source} = + mk_in rsn.afn.f {source} := + begin + have h3: mk_in better_flow.f {source} = 0 := + begin + unfold mk_in, + have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = + ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, + have zeroFlow: ∀ x : V, better_flow.f x source = 0 := + begin + intro x, + have noEdge: ¬better_flow.network.is_edge x source := + better_flow.no_edges_in_source x, + exact f_vanishes_outside_edge better_flow x source noEdge, + end, + rw eq, + exact finset.sum_eq_zero (λ x h, zeroFlow x), + end, + have h4: mk_in rsn.afn.f {source} = 0 := + begin + unfold mk_in, + set s := rsn.afn.network.source, + have sameSource: s = source := by refl, + have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = + ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, + have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := + begin + intro x, + have noEdge: ¬rsn.afn.network.is_edge x s := + rsn.afn.no_edges_in_source x, + exact f_vanishes_outside_edge rsn.afn x s noEdge, + end, + rw eq, + exact finset.sum_eq_zero (λ x h, zeroFlow x), + end, + rw ← h4 at h3, + exact h3, + end, rw [h1,h2], linarith end, have le: F_value rsn.afn ≥ F_value better_flow := begin - have same_net: better_flow.network = rsn.afn.network := by {simp}, + have same_net: better_flow.network = rsn.afn.network := by simp, unfold is_max_flow at max_flow, exact max_flow better_flow same_net, end, have lt: F_value rsn.afn < F_value better_flow := begin rw flow_value, - have h1: F_value rsn.afn - F_value rsn.afn < d := - begin - have eq: F_value rsn.afn - F_value rsn.afn = 0 := by ring, - rw eq, - linarith - end, + have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, exact gt_iff_lt.2 h2, end, @@ -957,7 +1264,7 @@ def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimu noncomputable def mk_cut_from_S {V : Type*} [inst' : fintype V] (rsn : residual_network V) - (hno_augumenting_path : no_augumenting_path rsn) + (hno_augmenting_path : no_augmenting_path rsn) (S : finset V) (hS : S = mk_cut_set rsn) : cut V := ⟨rsn.afn.network, S, V' \ S, begin @@ -971,13 +1278,13 @@ def mk_cut_from_S {V : Type*} [inst' : fintype V] unfold mk_cut_set, simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], intro p, - unfold no_augumenting_path at hno_augumenting_path, - specialize hno_augumenting_path rsn.afn.network.sink , - simp only [eq_self_iff_true, not_true] at hno_augumenting_path, + unfold no_augmenting_path at hno_augmenting_path, + specialize hno_augmenting_path rsn.afn.network.sink, + simp only [eq_self_iff_true, not_true] at hno_augmenting_path, apply exists.elim p, intros p h, - specialize hno_augumenting_path p, - exact hno_augumenting_path, + specialize hno_augmenting_path p, + exact hno_augmenting_path, end, rfl⟩ @@ -986,14 +1293,14 @@ lemma s_t_not_connected {V : Type*} [inst' : fintype V] (S : finset V) (hS : S = mk_cut_set rsn) : ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := begin - intros u h_u_in_S v h_v_in_T is_edge_u_v, + intros u uInS v vInT is_edge_u_v, rw hS at *, unfold mk_cut_set at *, simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, - apply exists.elim h_u_in_S, + apply exists.elim uInS, intros p _, have tmp := path.cons p is_edge_u_v, - apply h_v_in_T, + apply vInT, exact exists.intro tmp trivial, end @@ -1004,8 +1311,8 @@ lemma residual_capacity_zero {V : Type*} [inst' : fintype V] (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := begin - intros u h_u_in_S v h_v_in_T, - specialize h u h_u_in_S v h_v_in_T, + intros u uInS v vInT, + specialize h u uInS v vInT, rw rsn.is_edge_def at h, simp only [not_lt] at h, have hge := residual_capacity_non_neg rsn u v, @@ -1026,50 +1333,50 @@ begin specialize h u uInS v vInT, rw rsn.f_def at h, unfold mk_rsf at h, - have tmp := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), - cases tmp, + have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, { - simp only [tmp, if_true] at h, + simp only [foo, if_true] at h, linarith, }, { - simp only [tmp, if_false, ite_eq_right_iff] at h, - have foo := rsn.afn.network.vanishes u v tmp, - rw foo, - clear tmp h, - have foo := rsn.afn.non_neg_flow u v, - have bar := rsn.afn.no_overflow u v, + simp only [foo, if_false, ite_eq_right_iff] at h, + have bar := rsn.afn.network.vanishes u v foo, + rw bar, + clear foo h, + have baz := rsn.afn.non_neg_flow u v, + have bark := rsn.afn.no_overflow u v, linarith, } }, { - intros v h_v_in_T u h_u_in_S, - specialize h u h_u_in_S v h_v_in_T, + intros v vInT u uInS, + specialize h u uInS v vInT, rw rsn.f_def at h, unfold mk_rsf at h, - have tmp := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), - cases tmp, + have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, { - have foo := rsn.afn.network.hnonsymmetric u v, - simp only [not_and] at foo, - specialize foo tmp, + have bark := rsn.afn.network.nonsymmetric u v, + simp only [not_and] at bark, + specialize bark foo, have bar := rsn.afn.non_neg_flow v u, have baz := rsn.afn.no_overflow v u, - have blurg := rsn.afn.network.vanishes v u foo, + have blurg := rsn.afn.network.vanishes v u bark, linarith, }, { - simp only [tmp, if_false, ite_eq_right_iff] at h, - clear tmp, - have tmp := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), - cases tmp, + simp only [foo, if_false, ite_eq_right_iff] at h, + clear foo, + have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), + cases bar, { - exact h tmp, + exact h bar, }, { - have foo := rsn.afn.non_neg_flow v u, - have bar := rsn.afn.no_overflow v u, - have baz := rsn.afn.network.vanishes v u tmp, + have blurg := rsn.afn.non_neg_flow v u, + have bark := rsn.afn.no_overflow v u, + have baz := rsn.afn.network.vanishes v u bar, linarith, }, }, @@ -1112,11 +1419,11 @@ begin cases h with h_flow_eq_cap h_flow_zero, dsimp [cut_cap, mk_out], apply finset.sum_congr rfl, - intros x x_in_S, + intros x xInS, rw ← ct.Tcomp at *, apply finset.sum_congr rfl, - intros y y_in_T, - simp [h_eq_network, h_flow_eq_cap x x_in_S y y_in_T], + intros y yInT, + simp [h_eq_network, h_flow_eq_cap x xInS y yInT], end lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] @@ -1125,10 +1432,10 @@ lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := begin apply finset.sum_congr rfl, - intros a a_in_A, + intros a aInA, apply finset.sum_congr rfl, - intros b b_in_B, - exact eq_on_res a a_in_A b b_in_B, + intros b bInB, + exact eq_on_res a aInA b bInB, end /-! @@ -1138,14 +1445,13 @@ end lemma existence_of_a_cut {V : Type*} [inst' : fintype V] (rsn : residual_network V) - (hno_augumenting_path : no_augumenting_path rsn) : + (hno_augmenting_path : no_augmenting_path rsn) : (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := begin let S : finset V := mk_cut_set rsn, let T := V' \ S, - have SCutSet: S = mk_cut_set rsn := by refl, - let min_cut := mk_cut_from_S (rsn) (hno_augumenting_path) (S) (SCutSet), - have eq_net : rsn.afn.network = min_cut.network := by refl, + let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, + have same_net : rsn.afn.network = min_cut.network := by refl, have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := by {intros x y, split, intro heq, linarith, intro heq, linarith}, have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := @@ -1164,7 +1470,7 @@ begin end, contradiction end, - have notEdge: ¬ rsn.is_edge u v := by {exact s_t_not_connected rsn S SCutSet u uInS v vInNS}, + have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, contradiction end, have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, @@ -1181,33 +1487,27 @@ begin have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = rsn.afn.network.c u v := begin intros u uInS v vInT, - cases classical.em (rsn.afn.network.is_edge u v), + by_cases edge: rsn.afn.network.is_edge u v, { - rw subtract (rsn.afn.f u v) (rsn.afn.network.to_capacity.c u v), - have mk_cf_spec: (rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v) := - begin - rw rsn.f_def, - unfold mk_rsf, - simp only [h, if_true], - end, - rw ← mk_cf_spec, - exact cf_vanishes_on_pipes u uInS v vInT, + have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := + cf_vanishes_on_pipes_spec u uInS v vInT edge, + linarith, }, { - rw rsn.afn.network.vanishes u v h, - exact f_vanishes_outside_edge (rsn.afn) (u) (v) (h), + rw rsn.afn.network.vanishes u v edge, + exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), }, end, have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := begin intros u v hyp, - exact (min_max_cap_flow rsn min_cut eq_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, + exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, end, have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := begin rw F_value, simp only, - rw flow_value_source_in_S rsn.afn min_cut eq_net, + rw flow_value_source_in_S rsn.afn min_cut same_net, have no_input : mk_in rsn.afn.f min_cut.S = 0 := begin rw mk_in, @@ -1218,14 +1518,15 @@ begin have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := begin unfold mk_out, - rw eq_on_res_then_on_sum (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), + rw eq_on_res_then_on_sum + (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), end, rw flow_eq_cap_on_cut, refl, end, use min_cut, split, - {exact eq_net}, + {exact same_net}, exact cut_eq_flow end @@ -1239,13 +1540,13 @@ theorem max_flow_min_cut {V : Type*} [inst' : fintype V] (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := begin rintros ⟨max_flow, min_cut⟩ , - have noAugPath: no_augumenting_path rsn := by {exact no_augm_path rsn max_flow}, - have existsCut: ∃cut:cut V, rsn.afn.network = cut.network ∧ + have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, + have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, have max_flow_min_cut: ∀ cut : cut V, (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := begin - rintros cut ⟨same_net, eq⟩ , + rintros cut ⟨same_net, eq⟩, have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, have h2: is_min_cut c := min_cut, have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, From 170b6a50fbf7db7d3fbf97a25cbe5e8cedc95129 Mon Sep 17 00:00:00 2001 From: amilchew Date: Tue, 9 May 2023 11:29:28 +0100 Subject: [PATCH 16/28] only no_augm_path proof left --- src/combinatorics/quiver/max_flow_min_cut.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index d84eeef469bc9..53f693391e364 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -32,11 +32,11 @@ then its value is equal to the capacity of a minimum cut in the same network. - `existence_of_a_cut` : there exists a cut with a capacity equal to the value of the maximum flow. - `max_flow_min_cut` : if f is a max flow and c is a min cut in the same network, then their values are equal (max flow min cut theorem). -## Notation +### Notation - Type V is used for the set of all vertices in our graph. It is a finite type. -## References +#### References - Some of the structure ideas and lemmas can be seen in https://github.com/Zetagon/maxflow-mincut. From 3607e4b93857361cef79c9aa17719f297cfb7096 Mon Sep 17 00:00:00 2001 From: amilchew Date: Tue, 9 May 2023 11:36:58 +0100 Subject: [PATCH 17/28] only no_augm_path proof left --- src/combinatorics/quiver/max_flow_min_cut.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 53f693391e364..d84eeef469bc9 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -32,11 +32,11 @@ then its value is equal to the capacity of a minimum cut in the same network. - `existence_of_a_cut` : there exists a cut with a capacity equal to the value of the maximum flow. - `max_flow_min_cut` : if f is a max flow and c is a min cut in the same network, then their values are equal (max flow min cut theorem). -### Notation +## Notation - Type V is used for the set of all vertices in our graph. It is a finite type. -#### References +## References - Some of the structure ideas and lemmas can be seen in https://github.com/Zetagon/maxflow-mincut. From 486af8d9603cca001fa69b753252a1ebf6d28a94 Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 10 May 2023 11:47:25 +0100 Subject: [PATCH 18/28] only no_augm_path left --- .../quiver/max_flow_min_cut.lean | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index d84eeef469bc9..4966f26891068 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -21,16 +21,24 @@ then its value is equal to the capacity of a minimum cut in the same network. ## Main results -- `weak_duality` : the value of every flow is less than or equal to the capacity of every cut. +- `weak_duality` : + The value of every flow is less than or equal to the capacity of every cut. - direct consequences : - - the value of a max flow is always less than or equal to the capacity of a min cut. - - `max_flow_criterion` : if a flow value is equal to a cut capacity in the same flow network, then the flow is maximum. - - `min_cut_criterion` : if a capacity of a cut is equal to a flow value in the same network, then the cut is minimum. + direct consequences : + - The value of a max flow is always less than or equal to the capacity of a min cut. + - `max_flow_criterion`: + If a flow value is equal to a cut capacity in the same flow network, then the flow is maximum. + - `min_cut_criterion` : + If a capacity of a cut is equal to a flow value in the same network, then the cut is minimum. -- `no_augm_path` : if the active flow gives a maximum flow, then there is no augmenting path in the residual network. -- `existence_of_a_cut` : there exists a cut with a capacity equal to the value of the maximum flow. -- `max_flow_min_cut` : if f is a max flow and c is a min cut in the same network, then their values are equal (max flow min cut theorem). +- `no_augm_path` : + If the active flow gives a maximum flow, then there is no augmenting path in the residual network. +- `existence_of_a_cut` : + there exists a cut with a capacity equal to the value of the maximum flow. +- `max_flow_min_cut` : + If f is a max flow and c is a min cut in the same network, then their values are equal. + +The `max_flow_min_cut` lemma is the statement of the max-flow min-cut theorem. ## Notation @@ -417,7 +425,8 @@ begin exact absurd foo contr, end, by_contradiction notDisjoint, - have contr: ((V' \ S) ∩ (S \ {s})).nonempty := finset.not_disjoint_iff_nonempty_inter.1 notDisjoint, + have contr: ((V' \ S) ∩ (S \ {s})).nonempty := + finset.not_disjoint_iff_nonempty_inter.1 notDisjoint, exact absurd contr bar, end @@ -442,7 +451,8 @@ begin have foo: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y := finset.sum_comm, have bar: ∑ (y : V) in V' \ (S \ {s}), ∑ (x : V) in (S \ {s}), f x y = - ∑ (y : V) in V' \ S, ∑ (x : V) in (S \ {s}), f x y + ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y := + ∑ (y : V) in V' \ S, ∑ (x : V) in (S \ {s}), f x y + + ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y := by {rw ← finset.sum_sdiff sInCompl, rw sdiff_finset_sdiff_singleton_eq_sdiff_singleton S s sInS}, have baz: ∑ (y : V) in {s}, ∑ (x : V) in (S \ {s}), f x y = ∑ (x : V) in (S \ {s}), f x s := by simp, @@ -455,18 +465,21 @@ end lemma in_expansion {V : Type*} [inst' : fintype V] (f : V → V → ℝ) (S : finset V) (s : V) : (s ∈ S) → ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := begin intro sInS, have sSubsetS: {s} ⊆ S := (finset.singleton_subset_iff).2 sInS, - have foo: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y := - finset.sum_comm, + have foo: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = + ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y := finset.sum_comm, have bar: ∑ (y : V) in S, ∑ (x : V) in V' \ S, f x y = - ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y := - by {rw finset.sum_sdiff sSubsetS}, + ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y := by {rw finset.sum_sdiff sSubsetS}, have swap: - ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := + ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y + + ∑ (y : V) in {s}, ∑ (x : V) in V' \ S, f x y = + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := begin have swap1: ∑ (y : V) in (S \ {s}), ∑ (x : V) in V' \ S, f x y = ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y := finset.sum_comm, @@ -496,7 +509,8 @@ begin exact finset.subset_sdiff.2 conj, end, have foo: ∑ (x : V) in V' \ (S \ {s}), ∑ (y : V) in S \ {s}, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y := + ∑ (x : V) in V' \ S, ∑ (y : V) in S \ {s}, f x y + + ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y := by {rw ← finset.sum_sdiff sInCompl, rw sdiff_finset_sdiff_singleton_eq_sdiff_singleton S s sInS}, have bar: ∑ (x : V) in {s}, ∑ (y : V) in S \ {s}, f x y = ∑ (u : V) in S \ {s}, f s u := by simp, @@ -604,7 +618,8 @@ begin begin unfold mk_out, have eq1: ∑ (x : V) in S, ∑ (y : V) in V' \ S, f x y = - ∑ (x : V) in (S \ {s}) , ∑ (y : V) in V' \ S, f x y + ∑ (x : V) in {s}, ∑ (y : V) in V' \ S, f x y := + ∑ (x : V) in (S \ {s}) , ∑ (y : V) in V' \ S, f x y + + ∑ (x : V) in {s}, ∑ (y : V) in V' \ S, f x y := by {rw finset.sum_sdiff sSubsetS}, have eq2: ∑ (x : V) in {s}, ∑ (y : V) in V' \ S, f x y = ∑ (y : V) in V' \ S, f s y := by simp, have eq3: ∑ (x : V) in (S \ {s}), ∑ (y : V) in V' \ (S \ {s}), f x y = @@ -626,7 +641,8 @@ begin begin unfold mk_in, have eq1: ∑ (x : V) in V' \ S, ∑ (y : V) in S, f x y = - ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := + ∑ (x : V) in V' \ S, ∑ (y : V) in (S \ {s}), f x y + + ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y := in_expansion f S s sInS, have eq2: ∑ (x : V) in V' \ S, ∑ (y : V) in {s}, f x y = ∑ (u : V) in V' \ S, f u s := by simp, @@ -838,7 +854,8 @@ begin --all vertices in the augmenting path set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), -- set of all flow values in the augmenting path - set flows := set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), + set flows := + set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), have nonemp: flows.nonempty := begin by_contradiction h, @@ -1073,15 +1090,14 @@ begin { -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? -- How do we procced after for picking these edges? - -- Need to use the fact that x=t to show that there are always two edges for e given vertex outside {s,t} -- set predecessor := {u | exists_path.in u v}, -- set ancestor := {w | exists_path.in v w}, - -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := rsn.afn.conservation v vNotSinkSource, + -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := + -- rsn.afn.conservation v vNotSinkSource, -- rw [h2,h3,h1] sorry, }, { - -- Problems in next two: How do we use the condition in the definition of the set to show inclusion? have h1: ∀ u : V, ¬exists_path.in u v := begin by_contradiction h', From b1ad75ed6228be43ad1c069dc5bbdc56c8985d8c Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 10 May 2023 13:59:27 +0100 Subject: [PATCH 19/28] tactics fix --- src/combinatorics/quiver/max_flow_min_cut.lean | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 4966f26891068..77ebb6bdcea63 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -5,12 +5,10 @@ Authors: Aleksandar Milchev, Leo Okawa Ericson, Viggo Laakshoharju -/ +import algebra.big_operators.order import data.real.basic -import data.set.basic -import tactic -import data.finset.basic +import data.set.finite import tactic.induction -import algebra.big_operators.order /-! # Max flow Min cut theorem From 16ff8ccdc347b91787132183c35befc66064ecf8 Mon Sep 17 00:00:00 2001 From: amilchew Date: Wed, 10 May 2023 14:07:29 +0100 Subject: [PATCH 20/28] curly braces fix --- src/combinatorics/quiver/max_flow_min_cut.lean | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 77ebb6bdcea63..44292398b8e26 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -76,11 +76,11 @@ structure flow_network (V : Type*) [inst : fintype V] (sink : V) noncomputable -def mk_in {V : Type* } [inst : fintype V] +def mk_in {V : Type*} [inst : fintype V] (f : V -> V -> ℝ) (S : finset V) : ℝ := ∑ x in finset.univ \ S, ∑ y in S, f x y noncomputable -def mk_out {V : Type* } [inst : fintype V] +def mk_out {V : Type*} [inst : fintype V] (f : V -> V -> ℝ) (S : finset V) : ℝ := ∑ x in S, ∑ y in finset.univ \ S, f x y structure active_flow_network (V : Type*) [fintype V] := @@ -150,7 +150,7 @@ begin end -lemma mk_in_single_node { V : Type* } [fintype V] +lemma mk_in_single_node {V : Type*} [fintype V] (p : V) (afn : active_flow_network V) : mk_in (afn.f) {p} = ∑ v in finset.univ, (afn.f) v p := begin @@ -164,11 +164,11 @@ begin simp only [mk_in, sum_singleton], end -@[simp] lemma mk_in_single_node' { V : Type* } [fintype V] +@[simp] lemma mk_in_single_node' {V : Type*} [fintype V] (p : V) (afn : active_flow_network V) : ∑ v in finset.univ, (afn.f) v p = mk_in (afn.f) {p} := by rw mk_in_single_node -lemma mk_out_single_node { V : Type* } [fintype V] +lemma mk_out_single_node {V : Type*} [fintype V] (p : V) (afn : active_flow_network V) : mk_out afn.f {p} = ∑ v in finset.univ, (afn.f) p v := begin @@ -182,7 +182,7 @@ begin simp only [mk_out, sum_singleton], end -@[simp] lemma mk_out_single_node' { V : Type* } [fintype V] +@[simp] lemma mk_out_single_node' {V : Type*} [fintype V] (p : V) (afn : active_flow_network V) : ∑ v in finset.univ, (afn.f) p v = mk_out afn.f {p} := by rw mk_out_single_node @@ -784,7 +784,7 @@ def no_augmenting_path {V : Type*} [inst' : fintype V] /- Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. -/ -def path.in {V : Type u } +def path.in {V : Type u} {is_edge : V -> V -> Prop} (u v : V) {s : V} : ∀ {t : V}, path is_edge s t -> Prop From 526cb5c82ea6db0f729ac80c3a6da79eceb7985b Mon Sep 17 00:00:00 2001 From: amilchew Date: Thu, 11 May 2023 17:17:08 +0100 Subject: [PATCH 21/28] small fixes --- src/combinatorics/quiver/max_flow_min_cut.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 44292398b8e26..37eff72db0045 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -765,7 +765,7 @@ structure residual_network (V : Type*) [inst' : fintype V] := noncomputable def mk_rsn {V : Type*} [fintype V] -- stays for residual network (afn : active_flow_network V) : residual_network V := - ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl ⟩ + ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ universe u From 0579d8a9968a2a0d7ac6de5fded988a2b72976f1 Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 11:15:54 +0100 Subject: [PATCH 22/28] weak duality --- .../quiver/max_flow_min_cut.lean | 1674 ++++++++--------- 1 file changed, 837 insertions(+), 837 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 37eff72db0045..0853e13dd122e 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -741,840 +741,840 @@ begin exact weak_duality (afn) (cut) (h), end -/-! - We now define our residual network. Our goal is to prove no_augm_path. --/ - -noncomputable -def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow - (afn : active_flow_network V) - (u v : V) : ℝ := - if afn.network.is_edge u v - then afn.network.c u v - afn.f u v - else if afn.network.is_edge v u - then afn.f v u - else 0 - -structure residual_network (V : Type*) [inst' : fintype V] := - (afn : active_flow_network V) - (f' : V -> V -> ℝ) - (f_def : f' = mk_rsf afn) - (is_edge : V -> V -> Prop) - (is_edge_def : is_edge = λ u v, f' u v > 0) - -noncomputable -def mk_rsn {V : Type*} [fintype V] -- stays for residual network - (afn : active_flow_network V) : residual_network V := - ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ - -universe u - -/- - We define a recursive structure returning the path between two vertices, - if such a path exists, given the edges in the graph. --/ -inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) -| nil : path a -| cons : Π {b c : V}, path b → (is_edge b c) → path c - -def no_augmenting_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : Prop := - ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) - -/- - Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. --/ -def path.in {V : Type u} - {is_edge : V -> V -> Prop} - (u v : V) - {s : V} : ∀ {t : V}, path is_edge s t -> Prop - | t (@path.nil _ is_edge' a) := u = v - | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) - -lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := -begin - intros u v, - cases rsn, - simp only, - rw rsn_f_def, - unfold mk_rsf, - have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), - cases foo, - { - simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], - }, - { - simp only [foo, if_false], clear foo, - have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), - cases bar, - { - have h := rsn_afn.non_neg_flow v u, - simp only [bar, h, if_true], - linarith, - }, - { - simp only [bar, if_false], - }, - }, -end - -lemma positive_residual_flow {V : Type*} [inst' : fintype V] - (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := -begin - intro edge, - rw rsn.is_edge_def at edge, - exact edge, -end - -/-! - Here is our second big lemma, if the active flow is maximum, - then no augmenting path exists in the residual network. --/ - -lemma no_augm_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := -begin - intros max_flow x exists_path, - by_contradiction is_sink, - set s := rsn.afn.network.source, - set t := rsn.afn.network.sink, - have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, - have exists_augm_path: ¬no_augmenting_path rsn := - begin - unfold no_augmenting_path, - push_neg, - use x, - by_contradiction h, - have contr: x ≠ t := h exists_path, - exact absurd is_sink contr, - end, - --all vertices in the augmenting path - set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), - -- set of all flow values in the augmenting path - set flows := - set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), - have nonemp: flows.nonempty := - begin - by_contradiction h, - have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, - have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := - begin - intros v hyp, - have t_in_vertices: t ∈ vertices := by simp, - have v_in_vertices: v ∈ vertices := - begin - simp only [set.mem_to_finset, set.mem_set_of_eq], - have baz: exists_path.in v t := hyp, - have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, - have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - by {simp only [set.mem_set_of_eq], exact exist}, - have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - or.intro_right (v ∈ {t}) mem, - exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, - end, - have contr: rsn.f' v t ∈ flows := - begin - simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, - true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, set.to_finset_insert, - finset.mem_filter, vertices] at v_in_vertices, - apply v_in_vertices.elim; - intro hypo, - { - simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, set.mem_image, - set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, prod.exists, - function.uncurry_apply_pair, set.to_finset_nonempty, set.nonempty_image_iff, - set.to_finset_eq_empty, set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, - prod.forall, eq_self_iff_true, true_or] at *, - use [t, t], - simpa, - }, - { - simp only [set.singleton_union, set.mem_image, set.mem_to_finset, - set.coe_to_finset, prod.exists], - use [v, t], - simp [hypo, hyp] - }, - end, - exact finset.ne_empty_of_mem contr, - end, - have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path - begin - by_contradiction h, - push_neg at h, - have no_augm_path: no_augmenting_path rsn := by sorry, - exact absurd no_augm_path exists_augm_path, - end, - have contr: flows ≠ ∅ := exists.elim bar foo, - exact absurd empty contr, - end, - set d := flows.min' nonemp, -- the minimum flow in the augmenting path - have pos: 0 < d := - begin - have mem: d ∈ flows := finset.min'_mem flows nonemp, - have pos: ∀ f : ℝ , f ∈ flows → f > 0 := - begin - intros f hyp, - simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, - set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, - function.uncurry_apply_pair] at hyp, - obtain ⟨a, b, hyp, hyp'⟩ := hyp, - rw [← hyp'], - apply positive_residual_flow, - sorry, - end, - exact pos d mem, - end, - set better_flow: active_flow_network V := - ⟨rsn.afn.network, - (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d - else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), - begin -- source ≠ sink - exact rsn.afn.source_not_sink, - end, - begin -- non_neg_flow - intros u v, - by_cases edge: rsn.afn.network.is_edge u v, - { - simp only [edge, if_true], - by_cases h: exists_path.in u v, - { - have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, - simp only [h, if_true], - linarith, - }, - { - by_cases h': exists_path.in v u, - { - simp only [h, if_false, h', if_true], - have ine: d ≤ rsn.afn.f u v := - begin - have minimality: d ≤ rsn.f' v u := - begin - have min: ∀ f : ℝ , f ∈ flows → d ≤ f := - by {intros f hf, exact finset.min'_le flows f hf}, - have mem: rsn.f' v u ∈ flows := - begin - have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, - simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], - use [v, u], - simp [foo, h'], - sorry, - end, - exact min (rsn.f' v u) mem, - end, - have eq: rsn.f' v u = rsn.afn.f u v := - begin - rw rsn.f_def, - unfold mk_rsf, - have notAnd := rsn.afn.network.nonsymmetric u v, - simp only [not_and] at notAnd, - have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, - simp only [notEdge, if_false, edge, if_true], - end, - rw ← eq, - exact minimality, - end, - linarith, - }, - { - simp only [h, if_false, h', if_false], - exact rsn.afn.non_neg_flow u v, - }, - }, - }, - { - simp only [edge, if_false], - linarith, - }, - end, - begin -- no_overflow - intros u v, - by_cases edge: rsn.afn.network.is_edge u v, - { - simp only [edge, if_true], - by_cases h: exists_path.in u v, - { - have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := - begin - have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := - begin - have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := - by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, - rw eq, - linarith, - end, - have h3: d ≤ rsn.f' u v := - begin - have min: ∀ f : ℝ , f ∈ flows → d ≤ f := - by {intros f hf, exact finset.min'_le flows f hf}, - have mem: rsn.f' u v ∈ flows := - begin - have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, - simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], - use [u, v], - simp [foo, h], - sorry, - end, - exact min (rsn.f' u v) mem, - end, - have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, - exact le_trans h4 h2 - end, - simp only [h, if_true], - exact h1, - }, - { - by_cases h': exists_path.in v u, - { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := - rsn.afn.no_overflow u v, - simp only [h, if_false, h', if_true], - linarith, - }, - { - simp only [h, if_false, h', if_false], - exact rsn.afn.no_overflow u v, - }, - }, - }, - { - simp only [edge, if_false], - have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, - linarith, - }, - end, - begin --no_edges_in_source - exact rsn.afn.no_edges_in_source, - end, - begin --no_edges_out_sink - exact rsn.afn.no_edges_out_sink, - end, - begin -- conservation - intros v vNotSinkSource, - have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, - have vNotSource: v ≠ rsn.afn.network.source := - begin - by_contradiction h, - have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := - begin - have vSource: v ∈ {s} := finset.mem_singleton.2 h, - have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, - exact finset.mem_union.2 vOR, - end, - rw union at vIn, - have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := - by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, - exact absurd vIn vNotIn, - end, - have vNotSink: v ≠ rsn.afn.network.sink := - begin - by_contradiction h, - have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := - begin - have vSink: v ∈ {t} := finset.mem_singleton.2 h, - have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, - exact finset.mem_union.2 vOR, - end, - rw union at vIn, - have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := - by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, - exact absurd vIn vNotIn, - end, - set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) - (ite (path.in u v exists_path) (rsn.afn.f u v + d) - (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), - by_cases h: v ∈ vertices, - { - -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? - -- How do we procced after for picking these edges? - -- set predecessor := {u | exists_path.in u v}, - -- set ancestor := {w | exists_path.in v w}, - -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := - -- rsn.afn.conservation v vNotSinkSource, - -- rw [h2,h3,h1] - sorry, - }, - { - have h1: ∀ u : V, ¬exists_path.in u v := - begin - by_contradiction h', - push_neg at h', - have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t - have contr: v ∈ vertices := - begin - simp only [set.mem_to_finset, set.mem_set_of_eq], - have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - by {simp only [set.mem_set_of_eq], exact ancestor}, - have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - or.intro_right (v ∈ {t}) mem, - exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, - end, - exact absurd contr h, - end, - have h2: ∀ w : V, ¬exists_path.in v w := - begin - by_contradiction h', - push_neg at h', - have contr: v ∈ vertices := - begin - simp only [set.mem_to_finset, set.mem_set_of_eq], - have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - by {simp only [set.mem_set_of_eq], exact h'}, - have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - or.intro_right (v ∈ {t}) mem, - exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, - end, - exact absurd contr h, - end, - have h3: ∀ u : V, newf u v = rsn.afn.f u v := - begin - intro u, - by_cases edge: rsn.afn.network.is_edge u v, - { - have noEdge: ¬exists_path.in u v := h1 u, - have noReversedEdge: ¬exists_path.in v u := h2 u, - have simplify: newf u v = ite (rsn.afn.network.is_edge u v) - (ite (path.in u v exists_path) (rsn.afn.f u v + d) - (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, - rw simplify, - simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], - }, - { - have simplify: newf u v = ite (rsn.afn.network.is_edge u v) - (ite (path.in u v exists_path) (rsn.afn.f u v + d) - (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, - rw simplify, - simp only [edge, if_false], - have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, - linarith, - }, - end, - have h4: ∀ w : V, newf v w = rsn.afn.f v w := - begin - intro w, - by_cases edge: rsn.afn.network.is_edge v w, - { - have noEdge: ¬exists_path.in w v := h1 w, - have noReversedEdge: ¬exists_path.in v w := h2 w, - have simplify: newf v w = ite (rsn.afn.network.is_edge v w) - (ite (path.in v w exists_path) (rsn.afn.f v w + d) - (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, - rw simplify, - simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], - }, - { - have simplify: newf v w = ite (rsn.afn.network.is_edge v w) - (ite (path.in v w exists_path) (rsn.afn.f v w + d) - (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, - rw simplify, - simp only [edge, if_false], - have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, - linarith, - }, - end, - have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := - begin - unfold mk_in, - have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = - ∑ (x : V) in V' \ {v}, newf x v := by simp, - have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = - ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, - rw [eq1, eq2], - exact finset.sum_congr rfl (λ u h, h3 u), - end, - have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := - begin - unfold mk_out, - have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = - ∑ (y : V) in V' \ {v}, newf v y := by simp, - have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = - ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, - rw [eq1, eq2], - exact finset.sum_congr rfl (λ u h, h4 u), - end, - rw [eqIn,eqOut], - exact rsn.afn.conservation v vNotSinkSource, - }, - end - ⟩, - have flow_value: F_value better_flow = F_value rsn.afn + d := - begin - unfold F_value, - set source := better_flow.network.source, - have h1: mk_out better_flow.f {source} = - mk_out rsn.afn.f {source} + d := - by sorry, - -- take the edge with the added flow - -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? - have h2: mk_in better_flow.f {source} = - mk_in rsn.afn.f {source} := - begin - have h3: mk_in better_flow.f {source} = 0 := - begin - unfold mk_in, - have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = - ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, - have zeroFlow: ∀ x : V, better_flow.f x source = 0 := - begin - intro x, - have noEdge: ¬better_flow.network.is_edge x source := - better_flow.no_edges_in_source x, - exact f_vanishes_outside_edge better_flow x source noEdge, - end, - rw eq, - exact finset.sum_eq_zero (λ x h, zeroFlow x), - end, - have h4: mk_in rsn.afn.f {source} = 0 := - begin - unfold mk_in, - set s := rsn.afn.network.source, - have sameSource: s = source := by refl, - have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = - ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, - have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := - begin - intro x, - have noEdge: ¬rsn.afn.network.is_edge x s := - rsn.afn.no_edges_in_source x, - exact f_vanishes_outside_edge rsn.afn x s noEdge, - end, - rw eq, - exact finset.sum_eq_zero (λ x h, zeroFlow x), - end, - rw ← h4 at h3, - exact h3, - end, - rw [h1,h2], - linarith - end, - have le: F_value rsn.afn ≥ F_value better_flow := - begin - have same_net: better_flow.network = rsn.afn.network := by simp, - unfold is_max_flow at max_flow, - exact max_flow better_flow same_net, - end, - have lt: F_value rsn.afn < F_value better_flow := - begin - rw flow_value, - have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, - have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, - exact gt_iff_lt.2 h2, - end, - have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, - exact absurd lt nlt, -end - -/-! - Now, we will prove that there exists a cut with value equal to the max flow in the same network. - We will use a constructive proof, so we will construct our minimum cut. --/ - -noncomputable -def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut - (rsn : residual_network V) : finset V := - {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset - -noncomputable -def mk_cut_from_S {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (hno_augmenting_path : no_augmenting_path rsn) - (S : finset V) (hS : S = mk_cut_set rsn) : cut V := -⟨rsn.afn.network, S, V' \ S, - begin - rw hS, - unfold mk_cut_set, - simp only [set.mem_to_finset, set.mem_set_of_eq], - exact exists.intro path.nil trivial, - end, - begin - rw hS, - unfold mk_cut_set, - simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], - intro p, - unfold no_augmenting_path at hno_augmenting_path, - specialize hno_augmenting_path rsn.afn.network.sink, - simp only [eq_self_iff_true, not_true] at hno_augmenting_path, - apply exists.elim p, - intros p h, - specialize hno_augmenting_path p, - exact hno_augmenting_path, - end, -rfl⟩ - -lemma s_t_not_connected {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (S : finset V) (hS : S = mk_cut_set rsn) : - ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := -begin - intros u uInS v vInT is_edge_u_v, - rw hS at *, - unfold mk_cut_set at *, - simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, - apply exists.elim uInS, - intros p _, - have tmp := path.cons p is_edge_u_v, - apply vInT, - exact exists.intro tmp trivial, -end - -lemma residual_capacity_zero {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (ct : cut V) - (h_eq_network : rsn.afn.network = ct.network) - (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : - ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := -begin - intros u uInS v vInT, - specialize h u uInS v vInT, - rw rsn.is_edge_def at h, - simp only [not_lt] at h, - have hge := residual_capacity_non_neg rsn u v, - exact ge_antisymm hge h, -end - -lemma min_max_cap_flow {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (ct : cut V) - (h_eq_network : rsn.afn.network = ct.network) - (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : - (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ - (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := -begin - split, - { - intros u uInS v vInT, - specialize h u uInS v vInT, - rw rsn.f_def at h, - unfold mk_rsf at h, - have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), - cases foo, - { - simp only [foo, if_true] at h, - linarith, - }, - { - simp only [foo, if_false, ite_eq_right_iff] at h, - have bar := rsn.afn.network.vanishes u v foo, - rw bar, - clear foo h, - have baz := rsn.afn.non_neg_flow u v, - have bark := rsn.afn.no_overflow u v, - linarith, - } - }, - { - intros v vInT u uInS, - specialize h u uInS v vInT, - rw rsn.f_def at h, - unfold mk_rsf at h, - have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), - cases foo, - { - have bark := rsn.afn.network.nonsymmetric u v, - simp only [not_and] at bark, - specialize bark foo, - have bar := rsn.afn.non_neg_flow v u, - have baz := rsn.afn.no_overflow v u, - have blurg := rsn.afn.network.vanishes v u bark, - linarith, - }, - { - simp only [foo, if_false, ite_eq_right_iff] at h, - clear foo, - have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), - cases bar, - { - exact h bar, - }, - { - have blurg := rsn.afn.non_neg_flow v u, - have bark := rsn.afn.no_overflow v u, - have baz := rsn.afn.network.vanishes v u bar, - linarith, - }, - }, - } -end - -lemma f_value_eq_out {V : Type*} [inst' : fintype V] - (ct : cut V) - (afn : active_flow_network V) - (h_eq_network : afn.network = ct.network) - (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : - F_value afn = mk_out afn.f ct.S := -begin - dsimp [F_value], - rw flow_value_source_in_S afn ct h_eq_network, - dsimp [mk_in], - simp_rw [← ct.Tcomp], - simp only [sub_eq_self], - have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = - ∑ x in ct.T, ∑ y in ct.S, 0 := - begin - apply finset.sum_congr rfl, - intros x xInT, - apply finset.sum_congr rfl, - intros y yInS, - exact h x xInT y yInS, - end, - rw sum_eq_sum_zero, - simp only [sum_const_zero], -end - -lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] - (ct : cut V) - (afn : active_flow_network V) - (h_eq_network : afn.network = ct.network) - (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ - (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : - mk_out afn.f ct.S = cut_cap ct := -begin - cases h with h_flow_eq_cap h_flow_zero, - dsimp [cut_cap, mk_out], - apply finset.sum_congr rfl, - intros x xInS, - rw ← ct.Tcomp at *, - apply finset.sum_congr rfl, - intros y yInT, - simp [h_eq_network, h_flow_eq_cap x xInS y yInT], -end - -lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] - (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) - (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : - ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := -begin - apply finset.sum_congr rfl, - intros a aInA, - apply finset.sum_congr rfl, - intros b bInB, - exact eq_on_res a aInA b bInB, -end - -/-! - Here is our last big lemma, if there is no augmenting path in the resiual network, - then there exists a cut with a capacity equal to the value of the active flow in the same network. --/ - -lemma existence_of_a_cut {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (hno_augmenting_path : no_augmenting_path rsn) : - (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := -begin - let S : finset V := mk_cut_set rsn, - let T := V' \ S, - let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, - have same_net : rsn.afn.network = min_cut.network := by refl, - have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := - by {intros x y, split, intro heq, linarith, intro heq, linarith}, - have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := - begin - intros u uInS v vInNS, - by_contradiction h, - have edge: rsn.is_edge u v := - begin - by_contradiction h', - have contr: rsn.f' u v = 0 := - begin - rw rsn.is_edge_def at h', - simp only [not_lt] at h', - have hge := residual_capacity_non_neg rsn u v, - exact ge_antisymm hge h', - end, - contradiction - end, - have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, - contradiction - end, - have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, - (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := - begin - intros u uInS v vInT is_edge, - have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := - by {unfold mk_rsf, simp only [is_edge, if_true]}, - rw ← h1, - have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, - rw h2, - exact cf_vanishes_on_pipes u uInS v vInT, - end, - have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = rsn.afn.network.c u v := - begin - intros u uInS v vInT, - by_cases edge: rsn.afn.network.is_edge u v, - { - have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := - cf_vanishes_on_pipes_spec u uInS v vInT edge, - linarith, - }, - { - rw rsn.afn.network.vanishes u v edge, - exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), - }, - end, - have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := - begin - intros u v hyp, - exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, - end, - have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := - begin - rw F_value, - simp only, - rw flow_value_source_in_S rsn.afn min_cut same_net, - have no_input : mk_in rsn.afn.f min_cut.S = 0 := - begin - rw mk_in, - exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), - end, - rw no_input, - simp only [sub_zero], - have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := - begin - unfold mk_out, - rw eq_on_res_then_on_sum - (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), - end, - rw flow_eq_cap_on_cut, - refl, - end, - use min_cut, - split, - {exact same_net}, - exact cut_eq_flow -end - -/-! - Finally, our biggest result, the max-flow min-cut theorem! - If a maximum flow exists, its value is equal to the capacity of the min cut in the same network. --/ - -theorem max_flow_min_cut {V : Type*} [inst' : fintype V] - (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : - (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := -begin - rintros ⟨max_flow, min_cut⟩ , - have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, - have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ - cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, - have max_flow_min_cut: ∀ cut : cut V, - (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := - begin - rintros cut ⟨same_net, eq⟩, - have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, - have h2: is_min_cut c := min_cut, - have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, - have same_net2: c.network = cut.network := by rw ← same_net1, - have same_val: cut_cap cut = cut_cap c := - begin - have le1: cut_cap cut ≤ cut_cap c := - by {unfold is_min_cut at h1, exact h1 c same_net1}, - have le2: cut_cap c ≤ cut_cap cut := - by {unfold is_min_cut at h2, exact h2 cut same_net2}, - exact le_antisymm le1 le2, - end, - rw ← eq, - exact same_val, - end, - exact exists.elim existsCut max_flow_min_cut, -end +-- /-! +-- We now define our residual network. Our goal is to prove no_augm_path. +-- -/ + +-- noncomputable +-- def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow +-- (afn : active_flow_network V) +-- (u v : V) : ℝ := +-- if afn.network.is_edge u v +-- then afn.network.c u v - afn.f u v +-- else if afn.network.is_edge v u +-- then afn.f v u +-- else 0 + +-- structure residual_network (V : Type*) [inst' : fintype V] := +-- (afn : active_flow_network V) +-- (f' : V -> V -> ℝ) +-- (f_def : f' = mk_rsf afn) +-- (is_edge : V -> V -> Prop) +-- (is_edge_def : is_edge = λ u v, f' u v > 0) + +-- noncomputable +-- def mk_rsn {V : Type*} [fintype V] -- stays for residual network +-- (afn : active_flow_network V) : residual_network V := +-- ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ + +-- universe u + +-- /- +-- We define a recursive structure returning the path between two vertices, +-- if such a path exists, given the edges in the graph. +-- -/ +-- inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) +-- | nil : path a +-- | cons : Π {b c : V}, path b → (is_edge b c) → path c + +-- def no_augmenting_path {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) : Prop := +-- ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) + +-- /- +-- Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. +-- -/ +-- def path.in {V : Type u} +-- {is_edge : V -> V -> Prop} +-- (u v : V) +-- {s : V} : ∀ {t : V}, path is_edge s t -> Prop +-- | t (@path.nil _ is_edge' a) := u = v +-- | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) + +-- lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := +-- begin +-- intros u v, +-- cases rsn, +-- simp only, +-- rw rsn_f_def, +-- unfold mk_rsf, +-- have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), +-- cases foo, +-- { +-- simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], +-- }, +-- { +-- simp only [foo, if_false], clear foo, +-- have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), +-- cases bar, +-- { +-- have h := rsn_afn.non_neg_flow v u, +-- simp only [bar, h, if_true], +-- linarith, +-- }, +-- { +-- simp only [bar, if_false], +-- }, +-- }, +-- end + +-- lemma positive_residual_flow {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := +-- begin +-- intro edge, +-- rw rsn.is_edge_def at edge, +-- exact edge, +-- end + +-- /-! +-- Here is our second big lemma, if the active flow is maximum, +-- then no augmenting path exists in the residual network. +-- -/ + +-- lemma no_augm_path {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := +-- begin +-- intros max_flow x exists_path, +-- by_contradiction is_sink, +-- set s := rsn.afn.network.source, +-- set t := rsn.afn.network.sink, +-- have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, +-- have exists_augm_path: ¬no_augmenting_path rsn := +-- begin +-- unfold no_augmenting_path, +-- push_neg, +-- use x, +-- by_contradiction h, +-- have contr: x ≠ t := h exists_path, +-- exact absurd is_sink contr, +-- end, +-- --all vertices in the augmenting path +-- set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), +-- -- set of all flow values in the augmenting path +-- set flows := +-- set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), +-- have nonemp: flows.nonempty := +-- begin +-- by_contradiction h, +-- have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, +-- have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := +-- begin +-- intros v hyp, +-- have t_in_vertices: t ∈ vertices := by simp, +-- have v_in_vertices: v ∈ vertices := +-- begin +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- have baz: exists_path.in v t := hyp, +-- have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, +-- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- by {simp only [set.mem_set_of_eq], exact exist}, +-- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- or.intro_right (v ∈ {t}) mem, +-- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, +-- end, +-- have contr: rsn.f' v t ∈ flows := +-- begin +-- simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, +-- true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, set.to_finset_insert, +-- finset.mem_filter, vertices] at v_in_vertices, +-- apply v_in_vertices.elim; +-- intro hypo, +-- { +-- simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, set.mem_image, +-- set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, prod.exists, +-- function.uncurry_apply_pair, set.to_finset_nonempty, set.nonempty_image_iff, +-- set.to_finset_eq_empty, set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, +-- prod.forall, eq_self_iff_true, true_or] at *, +-- use [t, t], +-- simpa, +-- }, +-- { +-- simp only [set.singleton_union, set.mem_image, set.mem_to_finset, +-- set.coe_to_finset, prod.exists], +-- use [v, t], +-- simp [hypo, hyp] +-- }, +-- end, +-- exact finset.ne_empty_of_mem contr, +-- end, +-- have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path +-- begin +-- by_contradiction h, +-- push_neg at h, +-- have no_augm_path: no_augmenting_path rsn := by sorry, +-- exact absurd no_augm_path exists_augm_path, +-- end, +-- have contr: flows ≠ ∅ := exists.elim bar foo, +-- exact absurd empty contr, +-- end, +-- set d := flows.min' nonemp, -- the minimum flow in the augmenting path +-- have pos: 0 < d := +-- begin +-- have mem: d ∈ flows := finset.min'_mem flows nonemp, +-- have pos: ∀ f : ℝ , f ∈ flows → f > 0 := +-- begin +-- intros f hyp, +-- simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, +-- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, +-- function.uncurry_apply_pair] at hyp, +-- obtain ⟨a, b, hyp, hyp'⟩ := hyp, +-- rw [← hyp'], +-- apply positive_residual_flow, +-- sorry, +-- end, +-- exact pos d mem, +-- end, +-- set better_flow: active_flow_network V := +-- ⟨rsn.afn.network, +-- (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d +-- else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), +-- begin -- source ≠ sink +-- exact rsn.afn.source_not_sink, +-- end, +-- begin -- non_neg_flow +-- intros u v, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- simp only [edge, if_true], +-- by_cases h: exists_path.in u v, +-- { +-- have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, +-- simp only [h, if_true], +-- linarith, +-- }, +-- { +-- by_cases h': exists_path.in v u, +-- { +-- simp only [h, if_false, h', if_true], +-- have ine: d ≤ rsn.afn.f u v := +-- begin +-- have minimality: d ≤ rsn.f' v u := +-- begin +-- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := +-- by {intros f hf, exact finset.min'_le flows f hf}, +-- have mem: rsn.f' v u ∈ flows := +-- begin +-- have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, +-- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], +-- use [v, u], +-- simp [foo, h'], +-- sorry, +-- end, +-- exact min (rsn.f' v u) mem, +-- end, +-- have eq: rsn.f' v u = rsn.afn.f u v := +-- begin +-- rw rsn.f_def, +-- unfold mk_rsf, +-- have notAnd := rsn.afn.network.nonsymmetric u v, +-- simp only [not_and] at notAnd, +-- have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, +-- simp only [notEdge, if_false, edge, if_true], +-- end, +-- rw ← eq, +-- exact minimality, +-- end, +-- linarith, +-- }, +-- { +-- simp only [h, if_false, h', if_false], +-- exact rsn.afn.non_neg_flow u v, +-- }, +-- }, +-- }, +-- { +-- simp only [edge, if_false], +-- linarith, +-- }, +-- end, +-- begin -- no_overflow +-- intros u v, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- simp only [edge, if_true], +-- by_cases h: exists_path.in u v, +-- { +-- have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := +-- begin +-- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := +-- begin +-- have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := +-- by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, +-- rw eq, +-- linarith, +-- end, +-- have h3: d ≤ rsn.f' u v := +-- begin +-- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := +-- by {intros f hf, exact finset.min'_le flows f hf}, +-- have mem: rsn.f' u v ∈ flows := +-- begin +-- have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, +-- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], +-- use [u, v], +-- simp [foo, h], +-- sorry, +-- end, +-- exact min (rsn.f' u v) mem, +-- end, +-- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, +-- exact le_trans h4 h2 +-- end, +-- simp only [h, if_true], +-- exact h1, +-- }, +-- { +-- by_cases h': exists_path.in v u, +-- { +-- have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := +-- rsn.afn.no_overflow u v, +-- simp only [h, if_false, h', if_true], +-- linarith, +-- }, +-- { +-- simp only [h, if_false, h', if_false], +-- exact rsn.afn.no_overflow u v, +-- }, +-- }, +-- }, +-- { +-- simp only [edge, if_false], +-- have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, +-- linarith, +-- }, +-- end, +-- begin --no_edges_in_source +-- exact rsn.afn.no_edges_in_source, +-- end, +-- begin --no_edges_out_sink +-- exact rsn.afn.no_edges_out_sink, +-- end, +-- begin -- conservation +-- intros v vNotSinkSource, +-- have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, +-- have vNotSource: v ≠ rsn.afn.network.source := +-- begin +-- by_contradiction h, +-- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := +-- begin +-- have vSource: v ∈ {s} := finset.mem_singleton.2 h, +-- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, +-- exact finset.mem_union.2 vOR, +-- end, +-- rw union at vIn, +-- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := +-- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, +-- exact absurd vIn vNotIn, +-- end, +-- have vNotSink: v ≠ rsn.afn.network.sink := +-- begin +-- by_contradiction h, +-- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := +-- begin +-- have vSink: v ∈ {t} := finset.mem_singleton.2 h, +-- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, +-- exact finset.mem_union.2 vOR, +-- end, +-- rw union at vIn, +-- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := +-- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, +-- exact absurd vIn vNotIn, +-- end, +-- set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) +-- (ite (path.in u v exists_path) (rsn.afn.f u v + d) +-- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), +-- by_cases h: v ∈ vertices, +-- { +-- -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? +-- -- How do we procced after for picking these edges? +-- -- set predecessor := {u | exists_path.in u v}, +-- -- set ancestor := {w | exists_path.in v w}, +-- -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := +-- -- rsn.afn.conservation v vNotSinkSource, +-- -- rw [h2,h3,h1] +-- sorry, +-- }, +-- { +-- have h1: ∀ u : V, ¬exists_path.in u v := +-- begin +-- by_contradiction h', +-- push_neg at h', +-- have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t +-- have contr: v ∈ vertices := +-- begin +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- by {simp only [set.mem_set_of_eq], exact ancestor}, +-- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- or.intro_right (v ∈ {t}) mem, +-- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, +-- end, +-- exact absurd contr h, +-- end, +-- have h2: ∀ w : V, ¬exists_path.in v w := +-- begin +-- by_contradiction h', +-- push_neg at h', +-- have contr: v ∈ vertices := +-- begin +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- by {simp only [set.mem_set_of_eq], exact h'}, +-- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- or.intro_right (v ∈ {t}) mem, +-- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, +-- end, +-- exact absurd contr h, +-- end, +-- have h3: ∀ u : V, newf u v = rsn.afn.f u v := +-- begin +-- intro u, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- have noEdge: ¬exists_path.in u v := h1 u, +-- have noReversedEdge: ¬exists_path.in v u := h2 u, +-- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) +-- (ite (path.in u v exists_path) (rsn.afn.f u v + d) +-- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], +-- }, +-- { +-- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) +-- (ite (path.in u v exists_path) (rsn.afn.f u v + d) +-- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_false], +-- have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, +-- linarith, +-- }, +-- end, +-- have h4: ∀ w : V, newf v w = rsn.afn.f v w := +-- begin +-- intro w, +-- by_cases edge: rsn.afn.network.is_edge v w, +-- { +-- have noEdge: ¬exists_path.in w v := h1 w, +-- have noReversedEdge: ¬exists_path.in v w := h2 w, +-- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) +-- (ite (path.in v w exists_path) (rsn.afn.f v w + d) +-- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], +-- }, +-- { +-- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) +-- (ite (path.in v w exists_path) (rsn.afn.f v w + d) +-- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_false], +-- have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, +-- linarith, +-- }, +-- end, +-- have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := +-- begin +-- unfold mk_in, +-- have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = +-- ∑ (x : V) in V' \ {v}, newf x v := by simp, +-- have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = +-- ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, +-- rw [eq1, eq2], +-- exact finset.sum_congr rfl (λ u h, h3 u), +-- end, +-- have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := +-- begin +-- unfold mk_out, +-- have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = +-- ∑ (y : V) in V' \ {v}, newf v y := by simp, +-- have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = +-- ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, +-- rw [eq1, eq2], +-- exact finset.sum_congr rfl (λ u h, h4 u), +-- end, +-- rw [eqIn,eqOut], +-- exact rsn.afn.conservation v vNotSinkSource, +-- }, +-- end +-- ⟩, +-- have flow_value: F_value better_flow = F_value rsn.afn + d := +-- begin +-- unfold F_value, +-- set source := better_flow.network.source, +-- have h1: mk_out better_flow.f {source} = +-- mk_out rsn.afn.f {source} + d := +-- by sorry, +-- -- take the edge with the added flow +-- -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? +-- have h2: mk_in better_flow.f {source} = +-- mk_in rsn.afn.f {source} := +-- begin +-- have h3: mk_in better_flow.f {source} = 0 := +-- begin +-- unfold mk_in, +-- have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = +-- ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, +-- have zeroFlow: ∀ x : V, better_flow.f x source = 0 := +-- begin +-- intro x, +-- have noEdge: ¬better_flow.network.is_edge x source := +-- better_flow.no_edges_in_source x, +-- exact f_vanishes_outside_edge better_flow x source noEdge, +-- end, +-- rw eq, +-- exact finset.sum_eq_zero (λ x h, zeroFlow x), +-- end, +-- have h4: mk_in rsn.afn.f {source} = 0 := +-- begin +-- unfold mk_in, +-- set s := rsn.afn.network.source, +-- have sameSource: s = source := by refl, +-- have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = +-- ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, +-- have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := +-- begin +-- intro x, +-- have noEdge: ¬rsn.afn.network.is_edge x s := +-- rsn.afn.no_edges_in_source x, +-- exact f_vanishes_outside_edge rsn.afn x s noEdge, +-- end, +-- rw eq, +-- exact finset.sum_eq_zero (λ x h, zeroFlow x), +-- end, +-- rw ← h4 at h3, +-- exact h3, +-- end, +-- rw [h1,h2], +-- linarith +-- end, +-- have le: F_value rsn.afn ≥ F_value better_flow := +-- begin +-- have same_net: better_flow.network = rsn.afn.network := by simp, +-- unfold is_max_flow at max_flow, +-- exact max_flow better_flow same_net, +-- end, +-- have lt: F_value rsn.afn < F_value better_flow := +-- begin +-- rw flow_value, +-- have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, +-- have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, +-- exact gt_iff_lt.2 h2, +-- end, +-- have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, +-- exact absurd lt nlt, +-- end + +-- /-! +-- Now, we will prove that there exists a cut with value equal to the max flow in the same network. +-- We will use a constructive proof, so we will construct our minimum cut. +-- -/ + +-- noncomputable +-- def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut +-- (rsn : residual_network V) : finset V := +-- {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset + +-- noncomputable +-- def mk_cut_from_S {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (hno_augmenting_path : no_augmenting_path rsn) +-- (S : finset V) (hS : S = mk_cut_set rsn) : cut V := +-- ⟨rsn.afn.network, S, V' \ S, +-- begin +-- rw hS, +-- unfold mk_cut_set, +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- exact exists.intro path.nil trivial, +-- end, +-- begin +-- rw hS, +-- unfold mk_cut_set, +-- simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], +-- intro p, +-- unfold no_augmenting_path at hno_augmenting_path, +-- specialize hno_augmenting_path rsn.afn.network.sink, +-- simp only [eq_self_iff_true, not_true] at hno_augmenting_path, +-- apply exists.elim p, +-- intros p h, +-- specialize hno_augmenting_path p, +-- exact hno_augmenting_path, +-- end, +-- rfl⟩ + +-- lemma s_t_not_connected {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (S : finset V) (hS : S = mk_cut_set rsn) : +-- ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := +-- begin +-- intros u uInS v vInT is_edge_u_v, +-- rw hS at *, +-- unfold mk_cut_set at *, +-- simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, +-- apply exists.elim uInS, +-- intros p _, +-- have tmp := path.cons p is_edge_u_v, +-- apply vInT, +-- exact exists.intro tmp trivial, +-- end + +-- lemma residual_capacity_zero {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (ct : cut V) +-- (h_eq_network : rsn.afn.network = ct.network) +-- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : +-- ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := +-- begin +-- intros u uInS v vInT, +-- specialize h u uInS v vInT, +-- rw rsn.is_edge_def at h, +-- simp only [not_lt] at h, +-- have hge := residual_capacity_non_neg rsn u v, +-- exact ge_antisymm hge h, +-- end + +-- lemma min_max_cap_flow {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (ct : cut V) +-- (h_eq_network : rsn.afn.network = ct.network) +-- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : +-- (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ +-- (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := +-- begin +-- split, +-- { +-- intros u uInS v vInT, +-- specialize h u uInS v vInT, +-- rw rsn.f_def at h, +-- unfold mk_rsf at h, +-- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), +-- cases foo, +-- { +-- simp only [foo, if_true] at h, +-- linarith, +-- }, +-- { +-- simp only [foo, if_false, ite_eq_right_iff] at h, +-- have bar := rsn.afn.network.vanishes u v foo, +-- rw bar, +-- clear foo h, +-- have baz := rsn.afn.non_neg_flow u v, +-- have bark := rsn.afn.no_overflow u v, +-- linarith, +-- } +-- }, +-- { +-- intros v vInT u uInS, +-- specialize h u uInS v vInT, +-- rw rsn.f_def at h, +-- unfold mk_rsf at h, +-- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), +-- cases foo, +-- { +-- have bark := rsn.afn.network.nonsymmetric u v, +-- simp only [not_and] at bark, +-- specialize bark foo, +-- have bar := rsn.afn.non_neg_flow v u, +-- have baz := rsn.afn.no_overflow v u, +-- have blurg := rsn.afn.network.vanishes v u bark, +-- linarith, +-- }, +-- { +-- simp only [foo, if_false, ite_eq_right_iff] at h, +-- clear foo, +-- have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), +-- cases bar, +-- { +-- exact h bar, +-- }, +-- { +-- have blurg := rsn.afn.non_neg_flow v u, +-- have bark := rsn.afn.no_overflow v u, +-- have baz := rsn.afn.network.vanishes v u bar, +-- linarith, +-- }, +-- }, +-- } +-- end + +-- lemma f_value_eq_out {V : Type*} [inst' : fintype V] +-- (ct : cut V) +-- (afn : active_flow_network V) +-- (h_eq_network : afn.network = ct.network) +-- (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : +-- F_value afn = mk_out afn.f ct.S := +-- begin +-- dsimp [F_value], +-- rw flow_value_source_in_S afn ct h_eq_network, +-- dsimp [mk_in], +-- simp_rw [← ct.Tcomp], +-- simp only [sub_eq_self], +-- have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = +-- ∑ x in ct.T, ∑ y in ct.S, 0 := +-- begin +-- apply finset.sum_congr rfl, +-- intros x xInT, +-- apply finset.sum_congr rfl, +-- intros y yInS, +-- exact h x xInT y yInS, +-- end, +-- rw sum_eq_sum_zero, +-- simp only [sum_const_zero], +-- end + +-- lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] +-- (ct : cut V) +-- (afn : active_flow_network V) +-- (h_eq_network : afn.network = ct.network) +-- (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ +-- (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : +-- mk_out afn.f ct.S = cut_cap ct := +-- begin +-- cases h with h_flow_eq_cap h_flow_zero, +-- dsimp [cut_cap, mk_out], +-- apply finset.sum_congr rfl, +-- intros x xInS, +-- rw ← ct.Tcomp at *, +-- apply finset.sum_congr rfl, +-- intros y yInT, +-- simp [h_eq_network, h_flow_eq_cap x xInS y yInT], +-- end + +-- lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] +-- (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) +-- (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : +-- ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := +-- begin +-- apply finset.sum_congr rfl, +-- intros a aInA, +-- apply finset.sum_congr rfl, +-- intros b bInB, +-- exact eq_on_res a aInA b bInB, +-- end + +-- /-! +-- Here is our last big lemma, if there is no augmenting path in the resiual network, +-- then there exists a cut with a capacity equal to the value of the active flow in the same network. +-- -/ + +-- lemma existence_of_a_cut {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (hno_augmenting_path : no_augmenting_path rsn) : +-- (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := +-- begin +-- let S : finset V := mk_cut_set rsn, +-- let T := V' \ S, +-- let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, +-- have same_net : rsn.afn.network = min_cut.network := by refl, +-- have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := +-- by {intros x y, split, intro heq, linarith, intro heq, linarith}, +-- have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := +-- begin +-- intros u uInS v vInNS, +-- by_contradiction h, +-- have edge: rsn.is_edge u v := +-- begin +-- by_contradiction h', +-- have contr: rsn.f' u v = 0 := +-- begin +-- rw rsn.is_edge_def at h', +-- simp only [not_lt] at h', +-- have hge := residual_capacity_non_neg rsn u v, +-- exact ge_antisymm hge h', +-- end, +-- contradiction +-- end, +-- have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, +-- contradiction +-- end, +-- have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, +-- (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := +-- begin +-- intros u uInS v vInT is_edge, +-- have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := +-- by {unfold mk_rsf, simp only [is_edge, if_true]}, +-- rw ← h1, +-- have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, +-- rw h2, +-- exact cf_vanishes_on_pipes u uInS v vInT, +-- end, +-- have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = rsn.afn.network.c u v := +-- begin +-- intros u uInS v vInT, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := +-- cf_vanishes_on_pipes_spec u uInS v vInT edge, +-- linarith, +-- }, +-- { +-- rw rsn.afn.network.vanishes u v edge, +-- exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), +-- }, +-- end, +-- have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := +-- begin +-- intros u v hyp, +-- exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, +-- end, +-- have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := +-- begin +-- rw F_value, +-- simp only, +-- rw flow_value_source_in_S rsn.afn min_cut same_net, +-- have no_input : mk_in rsn.afn.f min_cut.S = 0 := +-- begin +-- rw mk_in, +-- exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), +-- end, +-- rw no_input, +-- simp only [sub_zero], +-- have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := +-- begin +-- unfold mk_out, +-- rw eq_on_res_then_on_sum +-- (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), +-- end, +-- rw flow_eq_cap_on_cut, +-- refl, +-- end, +-- use min_cut, +-- split, +-- {exact same_net}, +-- exact cut_eq_flow +-- end + +-- /-! +-- Finally, our biggest result, the max-flow min-cut theorem! +-- If a maximum flow exists, its value is equal to the capacity of the min cut in the same network. +-- -/ + +-- theorem max_flow_min_cut {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : +-- (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := +-- begin +-- rintros ⟨max_flow, min_cut⟩ , +-- have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, +-- have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ +-- cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, +-- have max_flow_min_cut: ∀ cut : cut V, +-- (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := +-- begin +-- rintros cut ⟨same_net, eq⟩, +-- have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, +-- have h2: is_min_cut c := min_cut, +-- have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, +-- have same_net2: c.network = cut.network := by rw ← same_net1, +-- have same_val: cut_cap cut = cut_cap c := +-- begin +-- have le1: cut_cap cut ≤ cut_cap c := +-- by {unfold is_min_cut at h1, exact h1 c same_net1}, +-- have le2: cut_cap c ≤ cut_cap cut := +-- by {unfold is_min_cut at h2, exact h2 cut same_net2}, +-- exact le_antisymm le1 le2, +-- end, +-- rw ← eq, +-- exact same_val, +-- end, +-- exact exists.elim existsCut max_flow_min_cut, +-- end From 606f375e521c6506d971690cd537d52c1408a893 Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 11:40:02 +0100 Subject: [PATCH 23/28] weak duality --- .../quiver/max_flow_min_cut.lean | 71 ++++++++----------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 0853e13dd122e..c8ba017fad543 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -303,8 +303,7 @@ begin rw eq1, have xIn: x ∈ V' := finset.mem_univ x, split, - { - intro hyp, + { intro hyp, have xIn1: x ∈ V' \ (S \ {s}) := (finset.mem_inter.1 hyp).1, have xIn2: x ∈ V' \ {s} := (finset.mem_inter.1 hyp).2, have xOut: x ∉ S := @@ -325,8 +324,7 @@ begin exact finset.not_mem_union.2 xOutAnd, end, have concl: x ∈ V' ∧ x ∉ S := and.intro xIn xOut, - exact finset.mem_sdiff.2 concl, - }, + exact finset.mem_sdiff.2 concl, }, intro hyp, have xOutS: x ∉ S := (finset.mem_sdiff.1 hyp).2, have xOut: x ∉ S \ {s} := @@ -357,8 +355,7 @@ begin ext x, have xIn: x ∈ V' := finset.mem_univ x, split, - { - intro hyp, + { intro hyp, have foo: x ∈ V' \ S ∨ x ∈ S \ {s} := finset.mem_union.1 hyp, have bar: x ∈ V' \ S → x ∈ V' \ {s} := begin @@ -380,23 +377,18 @@ begin have concl: x ∈ V' ∧ x ∉ {s} := and.intro xIn xNotIns, exact finset.mem_sdiff.2 concl, end, - exact or.elim foo bar baz, - }, + exact or.elim foo bar baz, }, intro hyp, have xNotIns: x ∉ {s} := (finset.mem_sdiff.1 hyp).2, by_cases h' : x ∈ S, - { - have and: x ∈ S ∧ x ∉ {s} := and.intro h' xNotIns, + { have and: x ∈ S ∧ x ∉ {s} := and.intro h' xNotIns, have xInSs: x ∈ S \ {s} := finset.mem_sdiff.2 and, have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_right (x ∈ V' \ S) xInSs, - exact finset.mem_union.2 conj, - }, - { - have and: x ∈ V' ∧ x ∉ S := and.intro xIn h', + exact finset.mem_union.2 conj, }, + { have and: x ∈ V' ∧ x ∉ S := and.intro xIn h', have xInVS: x ∈ V' \ S := finset.mem_sdiff.2 and, have conj: x ∈ V' \ S ∨ x ∈ S \ {s} := or.intro_left (x ∈ S \ {s}) xInVS, - exact finset.mem_union.2 conj, - }, + exact finset.mem_union.2 conj, }, end lemma disjoint_sdiff_finset_sdiff_singleton {V : Type*} [inst' : fintype V] @@ -801,22 +793,14 @@ end -- unfold mk_rsf, -- have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), -- cases foo, --- { --- simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], --- }, --- { --- simp only [foo, if_false], clear foo, +-- { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, +-- { simp only [foo, if_false], clear foo, -- have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), -- cases bar, --- { --- have h := rsn_afn.non_neg_flow v u, +-- { have h := rsn_afn.non_neg_flow v u, -- simp only [bar, h, if_true], --- linarith, --- }, --- { --- simp only [bar, if_false], --- }, --- }, +-- linarith, }, +-- { simp only [bar, if_false] }, }, -- end -- lemma positive_residual_flow {V : Type*} [inst' : fintype V] @@ -876,16 +860,17 @@ end -- have contr: rsn.f' v t ∈ flows := -- begin -- simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, --- true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, set.to_finset_insert, --- finset.mem_filter, vertices] at v_in_vertices, +-- true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, +-- set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, -- apply v_in_vertices.elim; -- intro hypo, -- { --- simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, set.mem_image, --- set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, prod.exists, --- function.uncurry_apply_pair, set.to_finset_nonempty, set.nonempty_image_iff, --- set.to_finset_eq_empty, set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, --- prod.forall, eq_self_iff_true, true_or] at *, +-- simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, +-- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, +-- prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, +-- set.nonempty_image_iff, set.to_finset_eq_empty, +-- set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, +-- eq_self_iff_true, true_or] at *, -- use [t, t], -- simpa, -- }, @@ -1266,7 +1251,7 @@ end -- end -- /-! --- Now, we will prove that there exists a cut with value equal to the max flow in the same network. +-- We will prove that there exists a cut with value equal to the max flow in the same network. -- We will use a constructive proof, so we will construct our minimum cut. -- -/ @@ -1453,8 +1438,8 @@ end -- end -- /-! --- Here is our last big lemma, if there is no augmenting path in the resiual network, --- then there exists a cut with a capacity equal to the value of the active flow in the same network. +-- Here is our last big lemma, if there is no augmenting path in the resiual network, then +-- there exists a cut with a capacity equal to the value of the active flow in the same network. -- -/ -- lemma existence_of_a_cut {V : Type*} [inst' : fintype V] @@ -1498,7 +1483,8 @@ end -- rw h2, -- exact cf_vanishes_on_pipes u uInS v vInT, -- end, --- have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = rsn.afn.network.c u v := +-- have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = +-- rsn.afn.network.c u v := -- begin -- intros u uInS v vInT, -- by_cases edge: rsn.afn.network.is_edge u v, @@ -1546,7 +1532,7 @@ end -- /-! -- Finally, our biggest result, the max-flow min-cut theorem! --- If a maximum flow exists, its value is equal to the capacity of the min cut in the same network. +-- If a maximum flow exists, its value is equal to the capacity of the min-cut. -- -/ -- theorem max_flow_min_cut {V : Type*} [inst' : fintype V] @@ -1558,7 +1544,8 @@ end -- have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ -- cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, -- have max_flow_min_cut: ∀ cut : cut V, --- (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → (F_value rsn.afn = cut_cap c) := +-- (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → +-- (F_value rsn.afn = cut_cap c) := -- begin -- rintros cut ⟨same_net, eq⟩, -- have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, From f224175ef63db1b073aece924d876e02baa179b4 Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 11:44:57 +0100 Subject: [PATCH 24/28] max-flow min-cut --- .../quiver/max_flow_min_cut.lean | 1664 ++++++++--------- 1 file changed, 832 insertions(+), 832 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index c8ba017fad543..8d88a03c7e427 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -733,835 +733,835 @@ begin exact weak_duality (afn) (cut) (h), end --- /-! --- We now define our residual network. Our goal is to prove no_augm_path. --- -/ - --- noncomputable --- def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow --- (afn : active_flow_network V) --- (u v : V) : ℝ := --- if afn.network.is_edge u v --- then afn.network.c u v - afn.f u v --- else if afn.network.is_edge v u --- then afn.f v u --- else 0 - --- structure residual_network (V : Type*) [inst' : fintype V] := --- (afn : active_flow_network V) --- (f' : V -> V -> ℝ) --- (f_def : f' = mk_rsf afn) --- (is_edge : V -> V -> Prop) --- (is_edge_def : is_edge = λ u v, f' u v > 0) - --- noncomputable --- def mk_rsn {V : Type*} [fintype V] -- stays for residual network --- (afn : active_flow_network V) : residual_network V := --- ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ - --- universe u - --- /- --- We define a recursive structure returning the path between two vertices, --- if such a path exists, given the edges in the graph. --- -/ --- inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) --- | nil : path a --- | cons : Π {b c : V}, path b → (is_edge b c) → path c - --- def no_augmenting_path {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) : Prop := --- ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) - --- /- --- Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. --- -/ --- def path.in {V : Type u} --- {is_edge : V -> V -> Prop} --- (u v : V) --- {s : V} : ∀ {t : V}, path is_edge s t -> Prop --- | t (@path.nil _ is_edge' a) := u = v --- | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) - --- lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := --- begin --- intros u v, --- cases rsn, --- simp only, --- rw rsn_f_def, --- unfold mk_rsf, --- have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), --- cases foo, --- { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, --- { simp only [foo, if_false], clear foo, --- have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), --- cases bar, --- { have h := rsn_afn.non_neg_flow v u, --- simp only [bar, h, if_true], --- linarith, }, --- { simp only [bar, if_false] }, }, --- end - --- lemma positive_residual_flow {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := --- begin --- intro edge, --- rw rsn.is_edge_def at edge, --- exact edge, --- end - --- /-! --- Here is our second big lemma, if the active flow is maximum, --- then no augmenting path exists in the residual network. --- -/ - --- lemma no_augm_path {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := --- begin --- intros max_flow x exists_path, --- by_contradiction is_sink, --- set s := rsn.afn.network.source, --- set t := rsn.afn.network.sink, --- have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, --- have exists_augm_path: ¬no_augmenting_path rsn := --- begin --- unfold no_augmenting_path, --- push_neg, --- use x, --- by_contradiction h, --- have contr: x ≠ t := h exists_path, --- exact absurd is_sink contr, --- end, --- --all vertices in the augmenting path --- set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), --- -- set of all flow values in the augmenting path --- set flows := --- set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), --- have nonemp: flows.nonempty := --- begin --- by_contradiction h, --- have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, --- have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := --- begin --- intros v hyp, --- have t_in_vertices: t ∈ vertices := by simp, --- have v_in_vertices: v ∈ vertices := --- begin --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- have baz: exists_path.in v t := hyp, --- have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, --- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- by {simp only [set.mem_set_of_eq], exact exist}, --- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- or.intro_right (v ∈ {t}) mem, --- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, --- end, --- have contr: rsn.f' v t ∈ flows := --- begin --- simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, --- true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, --- set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, --- apply v_in_vertices.elim; --- intro hypo, --- { --- simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, --- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, --- prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, --- set.nonempty_image_iff, set.to_finset_eq_empty, --- set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, --- eq_self_iff_true, true_or] at *, --- use [t, t], --- simpa, --- }, --- { --- simp only [set.singleton_union, set.mem_image, set.mem_to_finset, --- set.coe_to_finset, prod.exists], --- use [v, t], --- simp [hypo, hyp] --- }, --- end, --- exact finset.ne_empty_of_mem contr, --- end, --- have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path --- begin --- by_contradiction h, --- push_neg at h, --- have no_augm_path: no_augmenting_path rsn := by sorry, --- exact absurd no_augm_path exists_augm_path, --- end, --- have contr: flows ≠ ∅ := exists.elim bar foo, --- exact absurd empty contr, --- end, --- set d := flows.min' nonemp, -- the minimum flow in the augmenting path --- have pos: 0 < d := --- begin --- have mem: d ∈ flows := finset.min'_mem flows nonemp, --- have pos: ∀ f : ℝ , f ∈ flows → f > 0 := --- begin --- intros f hyp, --- simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, --- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, --- function.uncurry_apply_pair] at hyp, --- obtain ⟨a, b, hyp, hyp'⟩ := hyp, --- rw [← hyp'], --- apply positive_residual_flow, --- sorry, --- end, --- exact pos d mem, --- end, --- set better_flow: active_flow_network V := --- ⟨rsn.afn.network, --- (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d --- else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), --- begin -- source ≠ sink --- exact rsn.afn.source_not_sink, --- end, --- begin -- non_neg_flow --- intros u v, --- by_cases edge: rsn.afn.network.is_edge u v, --- { --- simp only [edge, if_true], --- by_cases h: exists_path.in u v, --- { --- have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, --- simp only [h, if_true], --- linarith, --- }, --- { --- by_cases h': exists_path.in v u, --- { --- simp only [h, if_false, h', if_true], --- have ine: d ≤ rsn.afn.f u v := --- begin --- have minimality: d ≤ rsn.f' v u := --- begin --- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := --- by {intros f hf, exact finset.min'_le flows f hf}, --- have mem: rsn.f' v u ∈ flows := --- begin --- have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, --- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], --- use [v, u], --- simp [foo, h'], --- sorry, --- end, --- exact min (rsn.f' v u) mem, --- end, --- have eq: rsn.f' v u = rsn.afn.f u v := --- begin --- rw rsn.f_def, --- unfold mk_rsf, --- have notAnd := rsn.afn.network.nonsymmetric u v, --- simp only [not_and] at notAnd, --- have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, --- simp only [notEdge, if_false, edge, if_true], --- end, --- rw ← eq, --- exact minimality, --- end, --- linarith, --- }, --- { --- simp only [h, if_false, h', if_false], --- exact rsn.afn.non_neg_flow u v, --- }, --- }, --- }, --- { --- simp only [edge, if_false], --- linarith, --- }, --- end, --- begin -- no_overflow --- intros u v, --- by_cases edge: rsn.afn.network.is_edge u v, --- { --- simp only [edge, if_true], --- by_cases h: exists_path.in u v, --- { --- have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := --- begin --- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := --- begin --- have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := --- by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, --- rw eq, --- linarith, --- end, --- have h3: d ≤ rsn.f' u v := --- begin --- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := --- by {intros f hf, exact finset.min'_le flows f hf}, --- have mem: rsn.f' u v ∈ flows := --- begin --- have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, --- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], --- use [u, v], --- simp [foo, h], --- sorry, --- end, --- exact min (rsn.f' u v) mem, --- end, --- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, --- exact le_trans h4 h2 --- end, --- simp only [h, if_true], --- exact h1, --- }, --- { --- by_cases h': exists_path.in v u, --- { --- have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := --- rsn.afn.no_overflow u v, --- simp only [h, if_false, h', if_true], --- linarith, --- }, --- { --- simp only [h, if_false, h', if_false], --- exact rsn.afn.no_overflow u v, --- }, --- }, --- }, --- { --- simp only [edge, if_false], --- have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, --- linarith, --- }, --- end, --- begin --no_edges_in_source --- exact rsn.afn.no_edges_in_source, --- end, --- begin --no_edges_out_sink --- exact rsn.afn.no_edges_out_sink, --- end, --- begin -- conservation --- intros v vNotSinkSource, --- have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, --- have vNotSource: v ≠ rsn.afn.network.source := --- begin --- by_contradiction h, --- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := --- begin --- have vSource: v ∈ {s} := finset.mem_singleton.2 h, --- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, --- exact finset.mem_union.2 vOR, --- end, --- rw union at vIn, --- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := --- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, --- exact absurd vIn vNotIn, --- end, --- have vNotSink: v ≠ rsn.afn.network.sink := --- begin --- by_contradiction h, --- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := --- begin --- have vSink: v ∈ {t} := finset.mem_singleton.2 h, --- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, --- exact finset.mem_union.2 vOR, --- end, --- rw union at vIn, --- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := --- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, --- exact absurd vIn vNotIn, --- end, --- set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) --- (ite (path.in u v exists_path) (rsn.afn.f u v + d) --- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), --- by_cases h: v ∈ vertices, --- { --- -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? --- -- How do we procced after for picking these edges? --- -- set predecessor := {u | exists_path.in u v}, --- -- set ancestor := {w | exists_path.in v w}, --- -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := --- -- rsn.afn.conservation v vNotSinkSource, --- -- rw [h2,h3,h1] --- sorry, --- }, --- { --- have h1: ∀ u : V, ¬exists_path.in u v := --- begin --- by_contradiction h', --- push_neg at h', --- have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t --- have contr: v ∈ vertices := --- begin --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- by {simp only [set.mem_set_of_eq], exact ancestor}, --- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- or.intro_right (v ∈ {t}) mem, --- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, --- end, --- exact absurd contr h, --- end, --- have h2: ∀ w : V, ¬exists_path.in v w := --- begin --- by_contradiction h', --- push_neg at h', --- have contr: v ∈ vertices := --- begin --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- by {simp only [set.mem_set_of_eq], exact h'}, --- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- or.intro_right (v ∈ {t}) mem, --- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, --- end, --- exact absurd contr h, --- end, --- have h3: ∀ u : V, newf u v = rsn.afn.f u v := --- begin --- intro u, --- by_cases edge: rsn.afn.network.is_edge u v, --- { --- have noEdge: ¬exists_path.in u v := h1 u, --- have noReversedEdge: ¬exists_path.in v u := h2 u, --- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) --- (ite (path.in u v exists_path) (rsn.afn.f u v + d) --- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, --- rw simplify, --- simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], --- }, --- { --- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) --- (ite (path.in u v exists_path) (rsn.afn.f u v + d) --- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, --- rw simplify, --- simp only [edge, if_false], --- have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, --- linarith, --- }, --- end, --- have h4: ∀ w : V, newf v w = rsn.afn.f v w := --- begin --- intro w, --- by_cases edge: rsn.afn.network.is_edge v w, --- { --- have noEdge: ¬exists_path.in w v := h1 w, --- have noReversedEdge: ¬exists_path.in v w := h2 w, --- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) --- (ite (path.in v w exists_path) (rsn.afn.f v w + d) --- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, --- rw simplify, --- simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], --- }, --- { --- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) --- (ite (path.in v w exists_path) (rsn.afn.f v w + d) --- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, --- rw simplify, --- simp only [edge, if_false], --- have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, --- linarith, --- }, --- end, --- have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := --- begin --- unfold mk_in, --- have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = --- ∑ (x : V) in V' \ {v}, newf x v := by simp, --- have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = --- ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, --- rw [eq1, eq2], --- exact finset.sum_congr rfl (λ u h, h3 u), --- end, --- have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := --- begin --- unfold mk_out, --- have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = --- ∑ (y : V) in V' \ {v}, newf v y := by simp, --- have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = --- ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, --- rw [eq1, eq2], --- exact finset.sum_congr rfl (λ u h, h4 u), --- end, --- rw [eqIn,eqOut], --- exact rsn.afn.conservation v vNotSinkSource, --- }, --- end --- ⟩, --- have flow_value: F_value better_flow = F_value rsn.afn + d := --- begin --- unfold F_value, --- set source := better_flow.network.source, --- have h1: mk_out better_flow.f {source} = --- mk_out rsn.afn.f {source} + d := --- by sorry, --- -- take the edge with the added flow --- -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? --- have h2: mk_in better_flow.f {source} = --- mk_in rsn.afn.f {source} := --- begin --- have h3: mk_in better_flow.f {source} = 0 := --- begin --- unfold mk_in, --- have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = --- ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, --- have zeroFlow: ∀ x : V, better_flow.f x source = 0 := --- begin --- intro x, --- have noEdge: ¬better_flow.network.is_edge x source := --- better_flow.no_edges_in_source x, --- exact f_vanishes_outside_edge better_flow x source noEdge, --- end, --- rw eq, --- exact finset.sum_eq_zero (λ x h, zeroFlow x), --- end, --- have h4: mk_in rsn.afn.f {source} = 0 := --- begin --- unfold mk_in, --- set s := rsn.afn.network.source, --- have sameSource: s = source := by refl, --- have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = --- ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, --- have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := --- begin --- intro x, --- have noEdge: ¬rsn.afn.network.is_edge x s := --- rsn.afn.no_edges_in_source x, --- exact f_vanishes_outside_edge rsn.afn x s noEdge, --- end, --- rw eq, --- exact finset.sum_eq_zero (λ x h, zeroFlow x), --- end, --- rw ← h4 at h3, --- exact h3, --- end, --- rw [h1,h2], --- linarith --- end, --- have le: F_value rsn.afn ≥ F_value better_flow := --- begin --- have same_net: better_flow.network = rsn.afn.network := by simp, --- unfold is_max_flow at max_flow, --- exact max_flow better_flow same_net, --- end, --- have lt: F_value rsn.afn < F_value better_flow := --- begin --- rw flow_value, --- have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, --- have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, --- exact gt_iff_lt.2 h2, --- end, --- have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, --- exact absurd lt nlt, --- end - --- /-! --- We will prove that there exists a cut with value equal to the max flow in the same network. --- We will use a constructive proof, so we will construct our minimum cut. --- -/ - --- noncomputable --- def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut --- (rsn : residual_network V) : finset V := --- {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset - --- noncomputable --- def mk_cut_from_S {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (hno_augmenting_path : no_augmenting_path rsn) --- (S : finset V) (hS : S = mk_cut_set rsn) : cut V := --- ⟨rsn.afn.network, S, V' \ S, --- begin --- rw hS, --- unfold mk_cut_set, --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- exact exists.intro path.nil trivial, --- end, --- begin --- rw hS, --- unfold mk_cut_set, --- simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], --- intro p, --- unfold no_augmenting_path at hno_augmenting_path, --- specialize hno_augmenting_path rsn.afn.network.sink, --- simp only [eq_self_iff_true, not_true] at hno_augmenting_path, --- apply exists.elim p, --- intros p h, --- specialize hno_augmenting_path p, --- exact hno_augmenting_path, --- end, --- rfl⟩ - --- lemma s_t_not_connected {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (S : finset V) (hS : S = mk_cut_set rsn) : --- ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := --- begin --- intros u uInS v vInT is_edge_u_v, --- rw hS at *, --- unfold mk_cut_set at *, --- simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, --- apply exists.elim uInS, --- intros p _, --- have tmp := path.cons p is_edge_u_v, --- apply vInT, --- exact exists.intro tmp trivial, --- end - --- lemma residual_capacity_zero {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (ct : cut V) --- (h_eq_network : rsn.afn.network = ct.network) --- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : --- ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := --- begin --- intros u uInS v vInT, --- specialize h u uInS v vInT, --- rw rsn.is_edge_def at h, --- simp only [not_lt] at h, --- have hge := residual_capacity_non_neg rsn u v, --- exact ge_antisymm hge h, --- end - --- lemma min_max_cap_flow {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (ct : cut V) --- (h_eq_network : rsn.afn.network = ct.network) --- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : --- (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ --- (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := --- begin --- split, --- { --- intros u uInS v vInT, --- specialize h u uInS v vInT, --- rw rsn.f_def at h, --- unfold mk_rsf at h, --- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), --- cases foo, --- { --- simp only [foo, if_true] at h, --- linarith, --- }, --- { --- simp only [foo, if_false, ite_eq_right_iff] at h, --- have bar := rsn.afn.network.vanishes u v foo, --- rw bar, --- clear foo h, --- have baz := rsn.afn.non_neg_flow u v, --- have bark := rsn.afn.no_overflow u v, --- linarith, --- } --- }, --- { --- intros v vInT u uInS, --- specialize h u uInS v vInT, --- rw rsn.f_def at h, --- unfold mk_rsf at h, --- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), --- cases foo, --- { --- have bark := rsn.afn.network.nonsymmetric u v, --- simp only [not_and] at bark, --- specialize bark foo, --- have bar := rsn.afn.non_neg_flow v u, --- have baz := rsn.afn.no_overflow v u, --- have blurg := rsn.afn.network.vanishes v u bark, --- linarith, --- }, --- { --- simp only [foo, if_false, ite_eq_right_iff] at h, --- clear foo, --- have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), --- cases bar, --- { --- exact h bar, --- }, --- { --- have blurg := rsn.afn.non_neg_flow v u, --- have bark := rsn.afn.no_overflow v u, --- have baz := rsn.afn.network.vanishes v u bar, --- linarith, --- }, --- }, --- } --- end - --- lemma f_value_eq_out {V : Type*} [inst' : fintype V] --- (ct : cut V) --- (afn : active_flow_network V) --- (h_eq_network : afn.network = ct.network) --- (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : --- F_value afn = mk_out afn.f ct.S := --- begin --- dsimp [F_value], --- rw flow_value_source_in_S afn ct h_eq_network, --- dsimp [mk_in], --- simp_rw [← ct.Tcomp], --- simp only [sub_eq_self], --- have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = --- ∑ x in ct.T, ∑ y in ct.S, 0 := --- begin --- apply finset.sum_congr rfl, --- intros x xInT, --- apply finset.sum_congr rfl, --- intros y yInS, --- exact h x xInT y yInS, --- end, --- rw sum_eq_sum_zero, --- simp only [sum_const_zero], --- end - --- lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] --- (ct : cut V) --- (afn : active_flow_network V) --- (h_eq_network : afn.network = ct.network) --- (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ --- (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : --- mk_out afn.f ct.S = cut_cap ct := --- begin --- cases h with h_flow_eq_cap h_flow_zero, --- dsimp [cut_cap, mk_out], --- apply finset.sum_congr rfl, --- intros x xInS, --- rw ← ct.Tcomp at *, --- apply finset.sum_congr rfl, --- intros y yInT, --- simp [h_eq_network, h_flow_eq_cap x xInS y yInT], --- end - --- lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] --- (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) --- (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : --- ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := --- begin --- apply finset.sum_congr rfl, --- intros a aInA, --- apply finset.sum_congr rfl, --- intros b bInB, --- exact eq_on_res a aInA b bInB, --- end - --- /-! --- Here is our last big lemma, if there is no augmenting path in the resiual network, then --- there exists a cut with a capacity equal to the value of the active flow in the same network. --- -/ - --- lemma existence_of_a_cut {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (hno_augmenting_path : no_augmenting_path rsn) : --- (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := --- begin --- let S : finset V := mk_cut_set rsn, --- let T := V' \ S, --- let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, --- have same_net : rsn.afn.network = min_cut.network := by refl, --- have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := --- by {intros x y, split, intro heq, linarith, intro heq, linarith}, --- have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := --- begin --- intros u uInS v vInNS, --- by_contradiction h, --- have edge: rsn.is_edge u v := --- begin --- by_contradiction h', --- have contr: rsn.f' u v = 0 := --- begin --- rw rsn.is_edge_def at h', --- simp only [not_lt] at h', --- have hge := residual_capacity_non_neg rsn u v, --- exact ge_antisymm hge h', --- end, --- contradiction --- end, --- have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, --- contradiction --- end, --- have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, --- (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := --- begin --- intros u uInS v vInT is_edge, --- have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := --- by {unfold mk_rsf, simp only [is_edge, if_true]}, --- rw ← h1, --- have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, --- rw h2, --- exact cf_vanishes_on_pipes u uInS v vInT, --- end, --- have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = --- rsn.afn.network.c u v := --- begin --- intros u uInS v vInT, --- by_cases edge: rsn.afn.network.is_edge u v, --- { --- have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := --- cf_vanishes_on_pipes_spec u uInS v vInT edge, --- linarith, --- }, --- { --- rw rsn.afn.network.vanishes u v edge, --- exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), --- }, --- end, --- have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := --- begin --- intros u v hyp, --- exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, --- end, --- have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := --- begin --- rw F_value, --- simp only, --- rw flow_value_source_in_S rsn.afn min_cut same_net, --- have no_input : mk_in rsn.afn.f min_cut.S = 0 := --- begin --- rw mk_in, --- exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), --- end, --- rw no_input, --- simp only [sub_zero], --- have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := --- begin --- unfold mk_out, --- rw eq_on_res_then_on_sum --- (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), --- end, --- rw flow_eq_cap_on_cut, --- refl, --- end, --- use min_cut, --- split, --- {exact same_net}, --- exact cut_eq_flow --- end - --- /-! --- Finally, our biggest result, the max-flow min-cut theorem! --- If a maximum flow exists, its value is equal to the capacity of the min-cut. --- -/ - --- theorem max_flow_min_cut {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : --- (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := --- begin --- rintros ⟨max_flow, min_cut⟩ , --- have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, --- have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ --- cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, --- have max_flow_min_cut: ∀ cut : cut V, --- (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → --- (F_value rsn.afn = cut_cap c) := --- begin --- rintros cut ⟨same_net, eq⟩, --- have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, --- have h2: is_min_cut c := min_cut, --- have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, --- have same_net2: c.network = cut.network := by rw ← same_net1, --- have same_val: cut_cap cut = cut_cap c := --- begin --- have le1: cut_cap cut ≤ cut_cap c := --- by {unfold is_min_cut at h1, exact h1 c same_net1}, --- have le2: cut_cap c ≤ cut_cap cut := --- by {unfold is_min_cut at h2, exact h2 cut same_net2}, --- exact le_antisymm le1 le2, --- end, --- rw ← eq, --- exact same_val, --- end, --- exact exists.elim existsCut max_flow_min_cut, --- end +/-! + We now define our residual network. Our goal is to prove no_augm_path. +-/ + +noncomputable +def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow + (afn : active_flow_network V) + (u v : V) : ℝ := + if afn.network.is_edge u v + then afn.network.c u v - afn.f u v + else if afn.network.is_edge v u + then afn.f v u + else 0 + +structure residual_network (V : Type*) [inst' : fintype V] := + (afn : active_flow_network V) + (f' : V -> V -> ℝ) + (f_def : f' = mk_rsf afn) + (is_edge : V -> V -> Prop) + (is_edge_def : is_edge = λ u v, f' u v > 0) + +noncomputable +def mk_rsn {V : Type*} [fintype V] -- stays for residual network + (afn : active_flow_network V) : residual_network V := + ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ + +universe u + +/- + We define a recursive structure returning the path between two vertices, + if such a path exists, given the edges in the graph. +-/ +inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) +| nil : path a +| cons : Π {b c : V}, path b → (is_edge b c) → path c + +def no_augmenting_path {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : Prop := + ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) + +/- + Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. +-/ +def path.in {V : Type u} + {is_edge : V -> V -> Prop} + (u v : V) + {s : V} : ∀ {t : V}, path is_edge s t -> Prop + | t (@path.nil _ is_edge' a) := u = v + | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) + +lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := +begin + intros u v, + cases rsn, + simp only, + rw rsn_f_def, + unfold mk_rsf, + have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, + { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, + { simp only [foo, if_false], clear foo, + have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), + cases bar, + { have h := rsn_afn.non_neg_flow v u, + simp only [bar, h, if_true], + linarith, }, + { simp only [bar, if_false] }, }, +end + +lemma positive_residual_flow {V : Type*} [inst' : fintype V] + (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := +begin + intro edge, + rw rsn.is_edge_def at edge, + exact edge, +end + +/-! + Here is our second big lemma, if the active flow is maximum, + then no augmenting path exists in the residual network. +-/ + +lemma no_augm_path {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := +begin + intros max_flow x exists_path, + by_contradiction is_sink, + set s := rsn.afn.network.source, + set t := rsn.afn.network.sink, + have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, + have exists_augm_path: ¬no_augmenting_path rsn := + begin + unfold no_augmenting_path, + push_neg, + use x, + by_contradiction h, + have contr: x ≠ t := h exists_path, + exact absurd is_sink contr, + end, + --all vertices in the augmenting path + set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), + -- set of all flow values in the augmenting path + set flows := + set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), + have nonemp: flows.nonempty := + begin + by_contradiction h, + have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, + have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := + begin + intros v hyp, + have t_in_vertices: t ∈ vertices := by simp, + have v_in_vertices: v ∈ vertices := + begin + simp only [set.mem_to_finset, set.mem_set_of_eq], + have baz: exists_path.in v t := hyp, + have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, + have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + by {simp only [set.mem_set_of_eq], exact exist}, + have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + or.intro_right (v ∈ {t}) mem, + exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, + end, + have contr: rsn.f' v t ∈ flows := + begin + simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, + true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, + set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, + apply v_in_vertices.elim; + intro hypo, + { + simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, + set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, + prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, + set.nonempty_image_iff, set.to_finset_eq_empty, + set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, + eq_self_iff_true, true_or] at *, + use [t, t], + simpa, + }, + { + simp only [set.singleton_union, set.mem_image, set.mem_to_finset, + set.coe_to_finset, prod.exists], + use [v, t], + simp [hypo, hyp] + }, + end, + exact finset.ne_empty_of_mem contr, + end, + have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path + begin + by_contradiction h, + push_neg at h, + have no_augm_path: no_augmenting_path rsn := by sorry, + exact absurd no_augm_path exists_augm_path, + end, + have contr: flows ≠ ∅ := exists.elim bar foo, + exact absurd empty contr, + end, + set d := flows.min' nonemp, -- the minimum flow in the augmenting path + have pos: 0 < d := + begin + have mem: d ∈ flows := finset.min'_mem flows nonemp, + have pos: ∀ f : ℝ , f ∈ flows → f > 0 := + begin + intros f hyp, + simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, + set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, + function.uncurry_apply_pair] at hyp, + obtain ⟨a, b, hyp, hyp'⟩ := hyp, + rw [← hyp'], + apply positive_residual_flow, + sorry, + end, + exact pos d mem, + end, + set better_flow: active_flow_network V := + ⟨rsn.afn.network, + (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d + else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), + begin -- source ≠ sink + exact rsn.afn.source_not_sink, + end, + begin -- non_neg_flow + intros u v, + by_cases edge: rsn.afn.network.is_edge u v, + { + simp only [edge, if_true], + by_cases h: exists_path.in u v, + { + have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, + simp only [h, if_true], + linarith, + }, + { + by_cases h': exists_path.in v u, + { + simp only [h, if_false, h', if_true], + have ine: d ≤ rsn.afn.f u v := + begin + have minimality: d ≤ rsn.f' v u := + begin + have min: ∀ f : ℝ , f ∈ flows → d ≤ f := + by {intros f hf, exact finset.min'_le flows f hf}, + have mem: rsn.f' v u ∈ flows := + begin + have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, + simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], + use [v, u], + simp [foo, h'], + sorry, + end, + exact min (rsn.f' v u) mem, + end, + have eq: rsn.f' v u = rsn.afn.f u v := + begin + rw rsn.f_def, + unfold mk_rsf, + have notAnd := rsn.afn.network.nonsymmetric u v, + simp only [not_and] at notAnd, + have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, + simp only [notEdge, if_false, edge, if_true], + end, + rw ← eq, + exact minimality, + end, + linarith, + }, + { + simp only [h, if_false, h', if_false], + exact rsn.afn.non_neg_flow u v, + }, + }, + }, + { + simp only [edge, if_false], + linarith, + }, + end, + begin -- no_overflow + intros u v, + by_cases edge: rsn.afn.network.is_edge u v, + { + simp only [edge, if_true], + by_cases h: exists_path.in u v, + { + have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := + begin + have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := + begin + have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := + by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, + rw eq, + linarith, + end, + have h3: d ≤ rsn.f' u v := + begin + have min: ∀ f : ℝ , f ∈ flows → d ≤ f := + by {intros f hf, exact finset.min'_le flows f hf}, + have mem: rsn.f' u v ∈ flows := + begin + have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, + simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], + use [u, v], + simp [foo, h], + sorry, + end, + exact min (rsn.f' u v) mem, + end, + have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, + exact le_trans h4 h2 + end, + simp only [h, if_true], + exact h1, + }, + { + by_cases h': exists_path.in v u, + { + have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := + rsn.afn.no_overflow u v, + simp only [h, if_false, h', if_true], + linarith, + }, + { + simp only [h, if_false, h', if_false], + exact rsn.afn.no_overflow u v, + }, + }, + }, + { + simp only [edge, if_false], + have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, + linarith, + }, + end, + begin --no_edges_in_source + exact rsn.afn.no_edges_in_source, + end, + begin --no_edges_out_sink + exact rsn.afn.no_edges_out_sink, + end, + begin -- conservation + intros v vNotSinkSource, + have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, + have vNotSource: v ≠ rsn.afn.network.source := + begin + by_contradiction h, + have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := + begin + have vSource: v ∈ {s} := finset.mem_singleton.2 h, + have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, + exact finset.mem_union.2 vOR, + end, + rw union at vIn, + have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := + by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, + exact absurd vIn vNotIn, + end, + have vNotSink: v ≠ rsn.afn.network.sink := + begin + by_contradiction h, + have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := + begin + have vSink: v ∈ {t} := finset.mem_singleton.2 h, + have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, + exact finset.mem_union.2 vOR, + end, + rw union at vIn, + have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := + by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, + exact absurd vIn vNotIn, + end, + set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) + (ite (path.in u v exists_path) (rsn.afn.f u v + d) + (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), + by_cases h: v ∈ vertices, + { + -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? + -- How do we procced after for picking these edges? + -- set predecessor := {u | exists_path.in u v}, + -- set ancestor := {w | exists_path.in v w}, + -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := + -- rsn.afn.conservation v vNotSinkSource, + -- rw [h2,h3,h1] + sorry, + }, + { + have h1: ∀ u : V, ¬exists_path.in u v := + begin + by_contradiction h', + push_neg at h', + have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t + have contr: v ∈ vertices := + begin + simp only [set.mem_to_finset, set.mem_set_of_eq], + have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + by {simp only [set.mem_set_of_eq], exact ancestor}, + have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + or.intro_right (v ∈ {t}) mem, + exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, + end, + exact absurd contr h, + end, + have h2: ∀ w : V, ¬exists_path.in v w := + begin + by_contradiction h', + push_neg at h', + have contr: v ∈ vertices := + begin + simp only [set.mem_to_finset, set.mem_set_of_eq], + have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + by {simp only [set.mem_set_of_eq], exact h'}, + have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := + or.intro_right (v ∈ {t}) mem, + exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, + end, + exact absurd contr h, + end, + have h3: ∀ u : V, newf u v = rsn.afn.f u v := + begin + intro u, + by_cases edge: rsn.afn.network.is_edge u v, + { + have noEdge: ¬exists_path.in u v := h1 u, + have noReversedEdge: ¬exists_path.in v u := h2 u, + have simplify: newf u v = ite (rsn.afn.network.is_edge u v) + (ite (path.in u v exists_path) (rsn.afn.f u v + d) + (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, + rw simplify, + simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], + }, + { + have simplify: newf u v = ite (rsn.afn.network.is_edge u v) + (ite (path.in u v exists_path) (rsn.afn.f u v + d) + (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, + rw simplify, + simp only [edge, if_false], + have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, + linarith, + }, + end, + have h4: ∀ w : V, newf v w = rsn.afn.f v w := + begin + intro w, + by_cases edge: rsn.afn.network.is_edge v w, + { + have noEdge: ¬exists_path.in w v := h1 w, + have noReversedEdge: ¬exists_path.in v w := h2 w, + have simplify: newf v w = ite (rsn.afn.network.is_edge v w) + (ite (path.in v w exists_path) (rsn.afn.f v w + d) + (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, + rw simplify, + simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], + }, + { + have simplify: newf v w = ite (rsn.afn.network.is_edge v w) + (ite (path.in v w exists_path) (rsn.afn.f v w + d) + (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, + rw simplify, + simp only [edge, if_false], + have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, + linarith, + }, + end, + have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := + begin + unfold mk_in, + have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = + ∑ (x : V) in V' \ {v}, newf x v := by simp, + have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = + ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, + rw [eq1, eq2], + exact finset.sum_congr rfl (λ u h, h3 u), + end, + have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := + begin + unfold mk_out, + have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = + ∑ (y : V) in V' \ {v}, newf v y := by simp, + have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = + ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, + rw [eq1, eq2], + exact finset.sum_congr rfl (λ u h, h4 u), + end, + rw [eqIn,eqOut], + exact rsn.afn.conservation v vNotSinkSource, + }, + end + ⟩, + have flow_value: F_value better_flow = F_value rsn.afn + d := + begin + unfold F_value, + set source := better_flow.network.source, + have h1: mk_out better_flow.f {source} = + mk_out rsn.afn.f {source} + d := + by sorry, + -- take the edge with the added flow + -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? + have h2: mk_in better_flow.f {source} = + mk_in rsn.afn.f {source} := + begin + have h3: mk_in better_flow.f {source} = 0 := + begin + unfold mk_in, + have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = + ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, + have zeroFlow: ∀ x : V, better_flow.f x source = 0 := + begin + intro x, + have noEdge: ¬better_flow.network.is_edge x source := + better_flow.no_edges_in_source x, + exact f_vanishes_outside_edge better_flow x source noEdge, + end, + rw eq, + exact finset.sum_eq_zero (λ x h, zeroFlow x), + end, + have h4: mk_in rsn.afn.f {source} = 0 := + begin + unfold mk_in, + set s := rsn.afn.network.source, + have sameSource: s = source := by refl, + have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = + ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, + have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := + begin + intro x, + have noEdge: ¬rsn.afn.network.is_edge x s := + rsn.afn.no_edges_in_source x, + exact f_vanishes_outside_edge rsn.afn x s noEdge, + end, + rw eq, + exact finset.sum_eq_zero (λ x h, zeroFlow x), + end, + rw ← h4 at h3, + exact h3, + end, + rw [h1,h2], + linarith + end, + have le: F_value rsn.afn ≥ F_value better_flow := + begin + have same_net: better_flow.network = rsn.afn.network := by simp, + unfold is_max_flow at max_flow, + exact max_flow better_flow same_net, + end, + have lt: F_value rsn.afn < F_value better_flow := + begin + rw flow_value, + have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, + have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, + exact gt_iff_lt.2 h2, + end, + have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, + exact absurd lt nlt, +end + +/-! + We will prove that there exists a cut with value equal to the max flow in the same network. + We will use a constructive proof, so we will construct our minimum cut. +-/ + +noncomputable +def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut + (rsn : residual_network V) : finset V := + {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset + +noncomputable +def mk_cut_from_S {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (hno_augmenting_path : no_augmenting_path rsn) + (S : finset V) (hS : S = mk_cut_set rsn) : cut V := +⟨rsn.afn.network, S, V' \ S, + begin + rw hS, + unfold mk_cut_set, + simp only [set.mem_to_finset, set.mem_set_of_eq], + exact exists.intro path.nil trivial, + end, + begin + rw hS, + unfold mk_cut_set, + simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], + intro p, + unfold no_augmenting_path at hno_augmenting_path, + specialize hno_augmenting_path rsn.afn.network.sink, + simp only [eq_self_iff_true, not_true] at hno_augmenting_path, + apply exists.elim p, + intros p h, + specialize hno_augmenting_path p, + exact hno_augmenting_path, + end, +rfl⟩ + +lemma s_t_not_connected {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (S : finset V) (hS : S = mk_cut_set rsn) : + ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := +begin + intros u uInS v vInT is_edge_u_v, + rw hS at *, + unfold mk_cut_set at *, + simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, + apply exists.elim uInS, + intros p _, + have tmp := path.cons p is_edge_u_v, + apply vInT, + exact exists.intro tmp trivial, +end + +lemma residual_capacity_zero {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (ct : cut V) + (h_eq_network : rsn.afn.network = ct.network) + (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : + ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := +begin + intros u uInS v vInT, + specialize h u uInS v vInT, + rw rsn.is_edge_def at h, + simp only [not_lt] at h, + have hge := residual_capacity_non_neg rsn u v, + exact ge_antisymm hge h, +end + +lemma min_max_cap_flow {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (ct : cut V) + (h_eq_network : rsn.afn.network = ct.network) + (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : + (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ + (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := +begin + split, + { + intros u uInS v vInT, + specialize h u uInS v vInT, + rw rsn.f_def at h, + unfold mk_rsf at h, + have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, + { + simp only [foo, if_true] at h, + linarith, + }, + { + simp only [foo, if_false, ite_eq_right_iff] at h, + have bar := rsn.afn.network.vanishes u v foo, + rw bar, + clear foo h, + have baz := rsn.afn.non_neg_flow u v, + have bark := rsn.afn.no_overflow u v, + linarith, + } + }, + { + intros v vInT u uInS, + specialize h u uInS v vInT, + rw rsn.f_def at h, + unfold mk_rsf at h, + have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, + { + have bark := rsn.afn.network.nonsymmetric u v, + simp only [not_and] at bark, + specialize bark foo, + have bar := rsn.afn.non_neg_flow v u, + have baz := rsn.afn.no_overflow v u, + have blurg := rsn.afn.network.vanishes v u bark, + linarith, + }, + { + simp only [foo, if_false, ite_eq_right_iff] at h, + clear foo, + have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), + cases bar, + { + exact h bar, + }, + { + have blurg := rsn.afn.non_neg_flow v u, + have bark := rsn.afn.no_overflow v u, + have baz := rsn.afn.network.vanishes v u bar, + linarith, + }, + }, + } +end + +lemma f_value_eq_out {V : Type*} [inst' : fintype V] + (ct : cut V) + (afn : active_flow_network V) + (h_eq_network : afn.network = ct.network) + (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : + F_value afn = mk_out afn.f ct.S := +begin + dsimp [F_value], + rw flow_value_source_in_S afn ct h_eq_network, + dsimp [mk_in], + simp_rw [← ct.Tcomp], + simp only [sub_eq_self], + have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = + ∑ x in ct.T, ∑ y in ct.S, 0 := + begin + apply finset.sum_congr rfl, + intros x xInT, + apply finset.sum_congr rfl, + intros y yInS, + exact h x xInT y yInS, + end, + rw sum_eq_sum_zero, + simp only [sum_const_zero], +end + +lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] + (ct : cut V) + (afn : active_flow_network V) + (h_eq_network : afn.network = ct.network) + (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ + (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : + mk_out afn.f ct.S = cut_cap ct := +begin + cases h with h_flow_eq_cap h_flow_zero, + dsimp [cut_cap, mk_out], + apply finset.sum_congr rfl, + intros x xInS, + rw ← ct.Tcomp at *, + apply finset.sum_congr rfl, + intros y yInT, + simp [h_eq_network, h_flow_eq_cap x xInS y yInT], +end + +lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] + (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) + (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : + ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := +begin + apply finset.sum_congr rfl, + intros a aInA, + apply finset.sum_congr rfl, + intros b bInB, + exact eq_on_res a aInA b bInB, +end + +/-! + Here is our last big lemma, if there is no augmenting path in the resiual network, then + there exists a cut with a capacity equal to the value of the active flow in the same network. +-/ + +lemma existence_of_a_cut {V : Type*} [inst' : fintype V] + (rsn : residual_network V) + (hno_augmenting_path : no_augmenting_path rsn) : + (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := +begin + let S : finset V := mk_cut_set rsn, + let T := V' \ S, + let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, + have same_net : rsn.afn.network = min_cut.network := by refl, + have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := + by {intros x y, split, intro heq, linarith, intro heq, linarith}, + have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := + begin + intros u uInS v vInNS, + by_contradiction h, + have edge: rsn.is_edge u v := + begin + by_contradiction h', + have contr: rsn.f' u v = 0 := + begin + rw rsn.is_edge_def at h', + simp only [not_lt] at h', + have hge := residual_capacity_non_neg rsn u v, + exact ge_antisymm hge h', + end, + contradiction + end, + have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, + contradiction + end, + have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, + (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := + begin + intros u uInS v vInT is_edge, + have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := + by {unfold mk_rsf, simp only [is_edge, if_true]}, + rw ← h1, + have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, + rw h2, + exact cf_vanishes_on_pipes u uInS v vInT, + end, + have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = + rsn.afn.network.c u v := + begin + intros u uInS v vInT, + by_cases edge: rsn.afn.network.is_edge u v, + { + have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := + cf_vanishes_on_pipes_spec u uInS v vInT edge, + linarith, + }, + { + rw rsn.afn.network.vanishes u v edge, + exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), + }, + end, + have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := + begin + intros u v hyp, + exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, + end, + have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := + begin + rw F_value, + simp only, + rw flow_value_source_in_S rsn.afn min_cut same_net, + have no_input : mk_in rsn.afn.f min_cut.S = 0 := + begin + rw mk_in, + exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), + end, + rw no_input, + simp only [sub_zero], + have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := + begin + unfold mk_out, + rw eq_on_res_then_on_sum + (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), + end, + rw flow_eq_cap_on_cut, + refl, + end, + use min_cut, + split, + {exact same_net}, + exact cut_eq_flow +end + +/-! + Finally, our biggest result, the max-flow min-cut theorem! + If a maximum flow exists, its value is equal to the capacity of the min-cut. +-/ + +theorem max_flow_min_cut {V : Type*} [inst' : fintype V] + (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : + (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := +begin + rintros ⟨max_flow, min_cut⟩ , + have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, + have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ + cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, + have max_flow_min_cut: ∀ cut : cut V, + (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → + (F_value rsn.afn = cut_cap c) := + begin + rintros cut ⟨same_net, eq⟩, + have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, + have h2: is_min_cut c := min_cut, + have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, + have same_net2: c.network = cut.network := by rw ← same_net1, + have same_val: cut_cap cut = cut_cap c := + begin + have le1: cut_cap cut ≤ cut_cap c := + by {unfold is_min_cut at h1, exact h1 c same_net1}, + have le2: cut_cap c ≤ cut_cap cut := + by {unfold is_min_cut at h2, exact h2 cut same_net2}, + exact le_antisymm le1 le2, + end, + rw ← eq, + exact same_val, + end, + exact exists.elim existsCut max_flow_min_cut, +end From 5f224502ffe0c2b3276f2d6b59cfed83445b4075 Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 11:48:24 +0100 Subject: [PATCH 25/28] max-flow min-cut --- src/combinatorics/quiver/max_flow_min_cut.lean | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 8d88a03c7e427..ada747c43518f 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -1348,8 +1348,7 @@ begin linarith, } }, - { - intros v vInT u uInS, + { intros v vInT u uInS, specialize h u uInS v vInT, rw rsn.f_def at h, unfold mk_rsf at h, @@ -1364,22 +1363,15 @@ begin have blurg := rsn.afn.network.vanishes v u bark, linarith, }, - { - simp only [foo, if_false, ite_eq_right_iff] at h, + { simp only [foo, if_false, ite_eq_right_iff] at h, clear foo, have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), cases bar, - { - exact h bar, - }, - { - have blurg := rsn.afn.non_neg_flow v u, + { exact h bar, }, + { have blurg := rsn.afn.non_neg_flow v u, have bark := rsn.afn.no_overflow v u, have baz := rsn.afn.network.vanishes v u bar, - linarith, - }, - }, - } + linarith, }, }, } end lemma f_value_eq_out {V : Type*} [inst' : fintype V] From 2f7752017349f08338d4256682d83441293faddb Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 11:51:16 +0100 Subject: [PATCH 26/28] weak duality --- .../quiver/max_flow_min_cut.lean | 1648 ++++++++--------- 1 file changed, 824 insertions(+), 824 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index ada747c43518f..f27d7876e2186 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -733,827 +733,827 @@ begin exact weak_duality (afn) (cut) (h), end -/-! - We now define our residual network. Our goal is to prove no_augm_path. --/ - -noncomputable -def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow - (afn : active_flow_network V) - (u v : V) : ℝ := - if afn.network.is_edge u v - then afn.network.c u v - afn.f u v - else if afn.network.is_edge v u - then afn.f v u - else 0 - -structure residual_network (V : Type*) [inst' : fintype V] := - (afn : active_flow_network V) - (f' : V -> V -> ℝ) - (f_def : f' = mk_rsf afn) - (is_edge : V -> V -> Prop) - (is_edge_def : is_edge = λ u v, f' u v > 0) - -noncomputable -def mk_rsn {V : Type*} [fintype V] -- stays for residual network - (afn : active_flow_network V) : residual_network V := - ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ - -universe u - -/- - We define a recursive structure returning the path between two vertices, - if such a path exists, given the edges in the graph. --/ -inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) -| nil : path a -| cons : Π {b c : V}, path b → (is_edge b c) → path c - -def no_augmenting_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : Prop := - ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) - -/- - Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. --/ -def path.in {V : Type u} - {is_edge : V -> V -> Prop} - (u v : V) - {s : V} : ∀ {t : V}, path is_edge s t -> Prop - | t (@path.nil _ is_edge' a) := u = v - | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) - -lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := -begin - intros u v, - cases rsn, - simp only, - rw rsn_f_def, - unfold mk_rsf, - have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), - cases foo, - { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, - { simp only [foo, if_false], clear foo, - have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), - cases bar, - { have h := rsn_afn.non_neg_flow v u, - simp only [bar, h, if_true], - linarith, }, - { simp only [bar, if_false] }, }, -end - -lemma positive_residual_flow {V : Type*} [inst' : fintype V] - (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := -begin - intro edge, - rw rsn.is_edge_def at edge, - exact edge, -end - -/-! - Here is our second big lemma, if the active flow is maximum, - then no augmenting path exists in the residual network. --/ - -lemma no_augm_path {V : Type*} [inst' : fintype V] - (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := -begin - intros max_flow x exists_path, - by_contradiction is_sink, - set s := rsn.afn.network.source, - set t := rsn.afn.network.sink, - have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, - have exists_augm_path: ¬no_augmenting_path rsn := - begin - unfold no_augmenting_path, - push_neg, - use x, - by_contradiction h, - have contr: x ≠ t := h exists_path, - exact absurd is_sink contr, - end, - --all vertices in the augmenting path - set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), - -- set of all flow values in the augmenting path - set flows := - set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), - have nonemp: flows.nonempty := - begin - by_contradiction h, - have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, - have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := - begin - intros v hyp, - have t_in_vertices: t ∈ vertices := by simp, - have v_in_vertices: v ∈ vertices := - begin - simp only [set.mem_to_finset, set.mem_set_of_eq], - have baz: exists_path.in v t := hyp, - have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, - have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - by {simp only [set.mem_set_of_eq], exact exist}, - have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - or.intro_right (v ∈ {t}) mem, - exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, - end, - have contr: rsn.f' v t ∈ flows := - begin - simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, - true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, - set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, - apply v_in_vertices.elim; - intro hypo, - { - simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, - set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, - prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, - set.nonempty_image_iff, set.to_finset_eq_empty, - set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, - eq_self_iff_true, true_or] at *, - use [t, t], - simpa, - }, - { - simp only [set.singleton_union, set.mem_image, set.mem_to_finset, - set.coe_to_finset, prod.exists], - use [v, t], - simp [hypo, hyp] - }, - end, - exact finset.ne_empty_of_mem contr, - end, - have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path - begin - by_contradiction h, - push_neg at h, - have no_augm_path: no_augmenting_path rsn := by sorry, - exact absurd no_augm_path exists_augm_path, - end, - have contr: flows ≠ ∅ := exists.elim bar foo, - exact absurd empty contr, - end, - set d := flows.min' nonemp, -- the minimum flow in the augmenting path - have pos: 0 < d := - begin - have mem: d ∈ flows := finset.min'_mem flows nonemp, - have pos: ∀ f : ℝ , f ∈ flows → f > 0 := - begin - intros f hyp, - simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, - set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, - function.uncurry_apply_pair] at hyp, - obtain ⟨a, b, hyp, hyp'⟩ := hyp, - rw [← hyp'], - apply positive_residual_flow, - sorry, - end, - exact pos d mem, - end, - set better_flow: active_flow_network V := - ⟨rsn.afn.network, - (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d - else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), - begin -- source ≠ sink - exact rsn.afn.source_not_sink, - end, - begin -- non_neg_flow - intros u v, - by_cases edge: rsn.afn.network.is_edge u v, - { - simp only [edge, if_true], - by_cases h: exists_path.in u v, - { - have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, - simp only [h, if_true], - linarith, - }, - { - by_cases h': exists_path.in v u, - { - simp only [h, if_false, h', if_true], - have ine: d ≤ rsn.afn.f u v := - begin - have minimality: d ≤ rsn.f' v u := - begin - have min: ∀ f : ℝ , f ∈ flows → d ≤ f := - by {intros f hf, exact finset.min'_le flows f hf}, - have mem: rsn.f' v u ∈ flows := - begin - have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, - simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], - use [v, u], - simp [foo, h'], - sorry, - end, - exact min (rsn.f' v u) mem, - end, - have eq: rsn.f' v u = rsn.afn.f u v := - begin - rw rsn.f_def, - unfold mk_rsf, - have notAnd := rsn.afn.network.nonsymmetric u v, - simp only [not_and] at notAnd, - have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, - simp only [notEdge, if_false, edge, if_true], - end, - rw ← eq, - exact minimality, - end, - linarith, - }, - { - simp only [h, if_false, h', if_false], - exact rsn.afn.non_neg_flow u v, - }, - }, - }, - { - simp only [edge, if_false], - linarith, - }, - end, - begin -- no_overflow - intros u v, - by_cases edge: rsn.afn.network.is_edge u v, - { - simp only [edge, if_true], - by_cases h: exists_path.in u v, - { - have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := - begin - have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := - begin - have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := - by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, - rw eq, - linarith, - end, - have h3: d ≤ rsn.f' u v := - begin - have min: ∀ f : ℝ , f ∈ flows → d ≤ f := - by {intros f hf, exact finset.min'_le flows f hf}, - have mem: rsn.f' u v ∈ flows := - begin - have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, - simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], - use [u, v], - simp [foo, h], - sorry, - end, - exact min (rsn.f' u v) mem, - end, - have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, - exact le_trans h4 h2 - end, - simp only [h, if_true], - exact h1, - }, - { - by_cases h': exists_path.in v u, - { - have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := - rsn.afn.no_overflow u v, - simp only [h, if_false, h', if_true], - linarith, - }, - { - simp only [h, if_false, h', if_false], - exact rsn.afn.no_overflow u v, - }, - }, - }, - { - simp only [edge, if_false], - have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, - linarith, - }, - end, - begin --no_edges_in_source - exact rsn.afn.no_edges_in_source, - end, - begin --no_edges_out_sink - exact rsn.afn.no_edges_out_sink, - end, - begin -- conservation - intros v vNotSinkSource, - have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, - have vNotSource: v ≠ rsn.afn.network.source := - begin - by_contradiction h, - have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := - begin - have vSource: v ∈ {s} := finset.mem_singleton.2 h, - have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, - exact finset.mem_union.2 vOR, - end, - rw union at vIn, - have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := - by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, - exact absurd vIn vNotIn, - end, - have vNotSink: v ≠ rsn.afn.network.sink := - begin - by_contradiction h, - have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := - begin - have vSink: v ∈ {t} := finset.mem_singleton.2 h, - have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, - exact finset.mem_union.2 vOR, - end, - rw union at vIn, - have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := - by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, - exact absurd vIn vNotIn, - end, - set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) - (ite (path.in u v exists_path) (rsn.afn.f u v + d) - (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), - by_cases h: v ∈ vertices, - { - -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? - -- How do we procced after for picking these edges? - -- set predecessor := {u | exists_path.in u v}, - -- set ancestor := {w | exists_path.in v w}, - -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := - -- rsn.afn.conservation v vNotSinkSource, - -- rw [h2,h3,h1] - sorry, - }, - { - have h1: ∀ u : V, ¬exists_path.in u v := - begin - by_contradiction h', - push_neg at h', - have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t - have contr: v ∈ vertices := - begin - simp only [set.mem_to_finset, set.mem_set_of_eq], - have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - by {simp only [set.mem_set_of_eq], exact ancestor}, - have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - or.intro_right (v ∈ {t}) mem, - exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, - end, - exact absurd contr h, - end, - have h2: ∀ w : V, ¬exists_path.in v w := - begin - by_contradiction h', - push_neg at h', - have contr: v ∈ vertices := - begin - simp only [set.mem_to_finset, set.mem_set_of_eq], - have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - by {simp only [set.mem_set_of_eq], exact h'}, - have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := - or.intro_right (v ∈ {t}) mem, - exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, - end, - exact absurd contr h, - end, - have h3: ∀ u : V, newf u v = rsn.afn.f u v := - begin - intro u, - by_cases edge: rsn.afn.network.is_edge u v, - { - have noEdge: ¬exists_path.in u v := h1 u, - have noReversedEdge: ¬exists_path.in v u := h2 u, - have simplify: newf u v = ite (rsn.afn.network.is_edge u v) - (ite (path.in u v exists_path) (rsn.afn.f u v + d) - (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, - rw simplify, - simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], - }, - { - have simplify: newf u v = ite (rsn.afn.network.is_edge u v) - (ite (path.in u v exists_path) (rsn.afn.f u v + d) - (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, - rw simplify, - simp only [edge, if_false], - have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, - linarith, - }, - end, - have h4: ∀ w : V, newf v w = rsn.afn.f v w := - begin - intro w, - by_cases edge: rsn.afn.network.is_edge v w, - { - have noEdge: ¬exists_path.in w v := h1 w, - have noReversedEdge: ¬exists_path.in v w := h2 w, - have simplify: newf v w = ite (rsn.afn.network.is_edge v w) - (ite (path.in v w exists_path) (rsn.afn.f v w + d) - (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, - rw simplify, - simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], - }, - { - have simplify: newf v w = ite (rsn.afn.network.is_edge v w) - (ite (path.in v w exists_path) (rsn.afn.f v w + d) - (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, - rw simplify, - simp only [edge, if_false], - have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, - linarith, - }, - end, - have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := - begin - unfold mk_in, - have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = - ∑ (x : V) in V' \ {v}, newf x v := by simp, - have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = - ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, - rw [eq1, eq2], - exact finset.sum_congr rfl (λ u h, h3 u), - end, - have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := - begin - unfold mk_out, - have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = - ∑ (y : V) in V' \ {v}, newf v y := by simp, - have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = - ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, - rw [eq1, eq2], - exact finset.sum_congr rfl (λ u h, h4 u), - end, - rw [eqIn,eqOut], - exact rsn.afn.conservation v vNotSinkSource, - }, - end - ⟩, - have flow_value: F_value better_flow = F_value rsn.afn + d := - begin - unfold F_value, - set source := better_flow.network.source, - have h1: mk_out better_flow.f {source} = - mk_out rsn.afn.f {source} + d := - by sorry, - -- take the edge with the added flow - -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? - have h2: mk_in better_flow.f {source} = - mk_in rsn.afn.f {source} := - begin - have h3: mk_in better_flow.f {source} = 0 := - begin - unfold mk_in, - have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = - ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, - have zeroFlow: ∀ x : V, better_flow.f x source = 0 := - begin - intro x, - have noEdge: ¬better_flow.network.is_edge x source := - better_flow.no_edges_in_source x, - exact f_vanishes_outside_edge better_flow x source noEdge, - end, - rw eq, - exact finset.sum_eq_zero (λ x h, zeroFlow x), - end, - have h4: mk_in rsn.afn.f {source} = 0 := - begin - unfold mk_in, - set s := rsn.afn.network.source, - have sameSource: s = source := by refl, - have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = - ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, - have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := - begin - intro x, - have noEdge: ¬rsn.afn.network.is_edge x s := - rsn.afn.no_edges_in_source x, - exact f_vanishes_outside_edge rsn.afn x s noEdge, - end, - rw eq, - exact finset.sum_eq_zero (λ x h, zeroFlow x), - end, - rw ← h4 at h3, - exact h3, - end, - rw [h1,h2], - linarith - end, - have le: F_value rsn.afn ≥ F_value better_flow := - begin - have same_net: better_flow.network = rsn.afn.network := by simp, - unfold is_max_flow at max_flow, - exact max_flow better_flow same_net, - end, - have lt: F_value rsn.afn < F_value better_flow := - begin - rw flow_value, - have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, - have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, - exact gt_iff_lt.2 h2, - end, - have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, - exact absurd lt nlt, -end - -/-! - We will prove that there exists a cut with value equal to the max flow in the same network. - We will use a constructive proof, so we will construct our minimum cut. --/ - -noncomputable -def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut - (rsn : residual_network V) : finset V := - {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset - -noncomputable -def mk_cut_from_S {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (hno_augmenting_path : no_augmenting_path rsn) - (S : finset V) (hS : S = mk_cut_set rsn) : cut V := -⟨rsn.afn.network, S, V' \ S, - begin - rw hS, - unfold mk_cut_set, - simp only [set.mem_to_finset, set.mem_set_of_eq], - exact exists.intro path.nil trivial, - end, - begin - rw hS, - unfold mk_cut_set, - simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], - intro p, - unfold no_augmenting_path at hno_augmenting_path, - specialize hno_augmenting_path rsn.afn.network.sink, - simp only [eq_self_iff_true, not_true] at hno_augmenting_path, - apply exists.elim p, - intros p h, - specialize hno_augmenting_path p, - exact hno_augmenting_path, - end, -rfl⟩ - -lemma s_t_not_connected {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (S : finset V) (hS : S = mk_cut_set rsn) : - ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := -begin - intros u uInS v vInT is_edge_u_v, - rw hS at *, - unfold mk_cut_set at *, - simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, - apply exists.elim uInS, - intros p _, - have tmp := path.cons p is_edge_u_v, - apply vInT, - exact exists.intro tmp trivial, -end - -lemma residual_capacity_zero {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (ct : cut V) - (h_eq_network : rsn.afn.network = ct.network) - (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : - ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := -begin - intros u uInS v vInT, - specialize h u uInS v vInT, - rw rsn.is_edge_def at h, - simp only [not_lt] at h, - have hge := residual_capacity_non_neg rsn u v, - exact ge_antisymm hge h, -end - -lemma min_max_cap_flow {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (ct : cut V) - (h_eq_network : rsn.afn.network = ct.network) - (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : - (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ - (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := -begin - split, - { - intros u uInS v vInT, - specialize h u uInS v vInT, - rw rsn.f_def at h, - unfold mk_rsf at h, - have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), - cases foo, - { - simp only [foo, if_true] at h, - linarith, - }, - { - simp only [foo, if_false, ite_eq_right_iff] at h, - have bar := rsn.afn.network.vanishes u v foo, - rw bar, - clear foo h, - have baz := rsn.afn.non_neg_flow u v, - have bark := rsn.afn.no_overflow u v, - linarith, - } - }, - { intros v vInT u uInS, - specialize h u uInS v vInT, - rw rsn.f_def at h, - unfold mk_rsf at h, - have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), - cases foo, - { - have bark := rsn.afn.network.nonsymmetric u v, - simp only [not_and] at bark, - specialize bark foo, - have bar := rsn.afn.non_neg_flow v u, - have baz := rsn.afn.no_overflow v u, - have blurg := rsn.afn.network.vanishes v u bark, - linarith, - }, - { simp only [foo, if_false, ite_eq_right_iff] at h, - clear foo, - have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), - cases bar, - { exact h bar, }, - { have blurg := rsn.afn.non_neg_flow v u, - have bark := rsn.afn.no_overflow v u, - have baz := rsn.afn.network.vanishes v u bar, - linarith, }, }, } -end - -lemma f_value_eq_out {V : Type*} [inst' : fintype V] - (ct : cut V) - (afn : active_flow_network V) - (h_eq_network : afn.network = ct.network) - (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : - F_value afn = mk_out afn.f ct.S := -begin - dsimp [F_value], - rw flow_value_source_in_S afn ct h_eq_network, - dsimp [mk_in], - simp_rw [← ct.Tcomp], - simp only [sub_eq_self], - have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = - ∑ x in ct.T, ∑ y in ct.S, 0 := - begin - apply finset.sum_congr rfl, - intros x xInT, - apply finset.sum_congr rfl, - intros y yInS, - exact h x xInT y yInS, - end, - rw sum_eq_sum_zero, - simp only [sum_const_zero], -end - -lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] - (ct : cut V) - (afn : active_flow_network V) - (h_eq_network : afn.network = ct.network) - (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ - (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : - mk_out afn.f ct.S = cut_cap ct := -begin - cases h with h_flow_eq_cap h_flow_zero, - dsimp [cut_cap, mk_out], - apply finset.sum_congr rfl, - intros x xInS, - rw ← ct.Tcomp at *, - apply finset.sum_congr rfl, - intros y yInT, - simp [h_eq_network, h_flow_eq_cap x xInS y yInT], -end - -lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] - (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) - (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : - ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := -begin - apply finset.sum_congr rfl, - intros a aInA, - apply finset.sum_congr rfl, - intros b bInB, - exact eq_on_res a aInA b bInB, -end - -/-! - Here is our last big lemma, if there is no augmenting path in the resiual network, then - there exists a cut with a capacity equal to the value of the active flow in the same network. --/ - -lemma existence_of_a_cut {V : Type*} [inst' : fintype V] - (rsn : residual_network V) - (hno_augmenting_path : no_augmenting_path rsn) : - (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := -begin - let S : finset V := mk_cut_set rsn, - let T := V' \ S, - let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, - have same_net : rsn.afn.network = min_cut.network := by refl, - have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := - by {intros x y, split, intro heq, linarith, intro heq, linarith}, - have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := - begin - intros u uInS v vInNS, - by_contradiction h, - have edge: rsn.is_edge u v := - begin - by_contradiction h', - have contr: rsn.f' u v = 0 := - begin - rw rsn.is_edge_def at h', - simp only [not_lt] at h', - have hge := residual_capacity_non_neg rsn u v, - exact ge_antisymm hge h', - end, - contradiction - end, - have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, - contradiction - end, - have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, - (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := - begin - intros u uInS v vInT is_edge, - have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := - by {unfold mk_rsf, simp only [is_edge, if_true]}, - rw ← h1, - have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, - rw h2, - exact cf_vanishes_on_pipes u uInS v vInT, - end, - have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = - rsn.afn.network.c u v := - begin - intros u uInS v vInT, - by_cases edge: rsn.afn.network.is_edge u v, - { - have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := - cf_vanishes_on_pipes_spec u uInS v vInT edge, - linarith, - }, - { - rw rsn.afn.network.vanishes u v edge, - exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), - }, - end, - have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := - begin - intros u v hyp, - exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, - end, - have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := - begin - rw F_value, - simp only, - rw flow_value_source_in_S rsn.afn min_cut same_net, - have no_input : mk_in rsn.afn.f min_cut.S = 0 := - begin - rw mk_in, - exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), - end, - rw no_input, - simp only [sub_zero], - have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := - begin - unfold mk_out, - rw eq_on_res_then_on_sum - (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), - end, - rw flow_eq_cap_on_cut, - refl, - end, - use min_cut, - split, - {exact same_net}, - exact cut_eq_flow -end - -/-! - Finally, our biggest result, the max-flow min-cut theorem! - If a maximum flow exists, its value is equal to the capacity of the min-cut. --/ - -theorem max_flow_min_cut {V : Type*} [inst' : fintype V] - (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : - (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := -begin - rintros ⟨max_flow, min_cut⟩ , - have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, - have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ - cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, - have max_flow_min_cut: ∀ cut : cut V, - (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → - (F_value rsn.afn = cut_cap c) := - begin - rintros cut ⟨same_net, eq⟩, - have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, - have h2: is_min_cut c := min_cut, - have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, - have same_net2: c.network = cut.network := by rw ← same_net1, - have same_val: cut_cap cut = cut_cap c := - begin - have le1: cut_cap cut ≤ cut_cap c := - by {unfold is_min_cut at h1, exact h1 c same_net1}, - have le2: cut_cap c ≤ cut_cap cut := - by {unfold is_min_cut at h2, exact h2 cut same_net2}, - exact le_antisymm le1 le2, - end, - rw ← eq, - exact same_val, - end, - exact exists.elim existsCut max_flow_min_cut, -end +-- /-! +-- We now define our residual network. Our goal is to prove no_augm_path. +-- -/ + +-- noncomputable +-- def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow +-- (afn : active_flow_network V) +-- (u v : V) : ℝ := +-- if afn.network.is_edge u v +-- then afn.network.c u v - afn.f u v +-- else if afn.network.is_edge v u +-- then afn.f v u +-- else 0 + +-- structure residual_network (V : Type*) [inst' : fintype V] := +-- (afn : active_flow_network V) +-- (f' : V -> V -> ℝ) +-- (f_def : f' = mk_rsf afn) +-- (is_edge : V -> V -> Prop) +-- (is_edge_def : is_edge = λ u v, f' u v > 0) + +-- noncomputable +-- def mk_rsn {V : Type*} [fintype V] -- stays for residual network +-- (afn : active_flow_network V) : residual_network V := +-- ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ + +-- universe u + +-- /- +-- We define a recursive structure returning the path between two vertices, +-- if such a path exists, given the edges in the graph. +-- -/ +-- inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) +-- | nil : path a +-- | cons : Π {b c : V}, path b → (is_edge b c) → path c + +-- def no_augmenting_path {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) : Prop := +-- ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) + +-- /- +-- Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. +-- -/ +-- def path.in {V : Type u} +-- {is_edge : V -> V -> Prop} +-- (u v : V) +-- {s : V} : ∀ {t : V}, path is_edge s t -> Prop +-- | t (@path.nil _ is_edge' a) := u = v +-- | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) + +-- lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := +-- begin +-- intros u v, +-- cases rsn, +-- simp only, +-- rw rsn_f_def, +-- unfold mk_rsf, +-- have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), +-- cases foo, +-- { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, +-- { simp only [foo, if_false], clear foo, +-- have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), +-- cases bar, +-- { have h := rsn_afn.non_neg_flow v u, +-- simp only [bar, h, if_true], +-- linarith, }, +-- { simp only [bar, if_false] }, }, +-- end + +-- lemma positive_residual_flow {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := +-- begin +-- intro edge, +-- rw rsn.is_edge_def at edge, +-- exact edge, +-- end + +-- /-! +-- Here is our second big lemma, if the active flow is maximum, +-- then no augmenting path exists in the residual network. +-- -/ + +-- lemma no_augm_path {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := +-- begin +-- intros max_flow x exists_path, +-- by_contradiction is_sink, +-- set s := rsn.afn.network.source, +-- set t := rsn.afn.network.sink, +-- have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, +-- have exists_augm_path: ¬no_augmenting_path rsn := +-- begin +-- unfold no_augmenting_path, +-- push_neg, +-- use x, +-- by_contradiction h, +-- have contr: x ≠ t := h exists_path, +-- exact absurd is_sink contr, +-- end, +-- --all vertices in the augmenting path +-- set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), +-- -- set of all flow values in the augmenting path +-- set flows := +-- set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), +-- have nonemp: flows.nonempty := +-- begin +-- by_contradiction h, +-- have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, +-- have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := +-- begin +-- intros v hyp, +-- have t_in_vertices: t ∈ vertices := by simp, +-- have v_in_vertices: v ∈ vertices := +-- begin +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- have baz: exists_path.in v t := hyp, +-- have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, +-- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- by {simp only [set.mem_set_of_eq], exact exist}, +-- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- or.intro_right (v ∈ {t}) mem, +-- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, +-- end, +-- have contr: rsn.f' v t ∈ flows := +-- begin +-- simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, +-- true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, +-- set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, +-- apply v_in_vertices.elim; +-- intro hypo, +-- { +-- simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, +-- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, +-- prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, +-- set.nonempty_image_iff, set.to_finset_eq_empty, +-- set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, +-- eq_self_iff_true, true_or] at *, +-- use [t, t], +-- simpa, +-- }, +-- { +-- simp only [set.singleton_union, set.mem_image, set.mem_to_finset, +-- set.coe_to_finset, prod.exists], +-- use [v, t], +-- simp [hypo, hyp] +-- }, +-- end, +-- exact finset.ne_empty_of_mem contr, +-- end, +-- have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path +-- begin +-- by_contradiction h, +-- push_neg at h, +-- have no_augm_path: no_augmenting_path rsn := by sorry, +-- exact absurd no_augm_path exists_augm_path, +-- end, +-- have contr: flows ≠ ∅ := exists.elim bar foo, +-- exact absurd empty contr, +-- end, +-- set d := flows.min' nonemp, -- the minimum flow in the augmenting path +-- have pos: 0 < d := +-- begin +-- have mem: d ∈ flows := finset.min'_mem flows nonemp, +-- have pos: ∀ f : ℝ , f ∈ flows → f > 0 := +-- begin +-- intros f hyp, +-- simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, +-- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, +-- function.uncurry_apply_pair] at hyp, +-- obtain ⟨a, b, hyp, hyp'⟩ := hyp, +-- rw [← hyp'], +-- apply positive_residual_flow, +-- sorry, +-- end, +-- exact pos d mem, +-- end, +-- set better_flow: active_flow_network V := +-- ⟨rsn.afn.network, +-- (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d +-- else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), +-- begin -- source ≠ sink +-- exact rsn.afn.source_not_sink, +-- end, +-- begin -- non_neg_flow +-- intros u v, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- simp only [edge, if_true], +-- by_cases h: exists_path.in u v, +-- { +-- have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, +-- simp only [h, if_true], +-- linarith, +-- }, +-- { +-- by_cases h': exists_path.in v u, +-- { +-- simp only [h, if_false, h', if_true], +-- have ine: d ≤ rsn.afn.f u v := +-- begin +-- have minimality: d ≤ rsn.f' v u := +-- begin +-- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := +-- by {intros f hf, exact finset.min'_le flows f hf}, +-- have mem: rsn.f' v u ∈ flows := +-- begin +-- have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, +-- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], +-- use [v, u], +-- simp [foo, h'], +-- sorry, +-- end, +-- exact min (rsn.f' v u) mem, +-- end, +-- have eq: rsn.f' v u = rsn.afn.f u v := +-- begin +-- rw rsn.f_def, +-- unfold mk_rsf, +-- have notAnd := rsn.afn.network.nonsymmetric u v, +-- simp only [not_and] at notAnd, +-- have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, +-- simp only [notEdge, if_false, edge, if_true], +-- end, +-- rw ← eq, +-- exact minimality, +-- end, +-- linarith, +-- }, +-- { +-- simp only [h, if_false, h', if_false], +-- exact rsn.afn.non_neg_flow u v, +-- }, +-- }, +-- }, +-- { +-- simp only [edge, if_false], +-- linarith, +-- }, +-- end, +-- begin -- no_overflow +-- intros u v, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- simp only [edge, if_true], +-- by_cases h: exists_path.in u v, +-- { +-- have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := +-- begin +-- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := +-- begin +-- have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := +-- by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, +-- rw eq, +-- linarith, +-- end, +-- have h3: d ≤ rsn.f' u v := +-- begin +-- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := +-- by {intros f hf, exact finset.min'_le flows f hf}, +-- have mem: rsn.f' u v ∈ flows := +-- begin +-- have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, +-- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], +-- use [u, v], +-- simp [foo, h], +-- sorry, +-- end, +-- exact min (rsn.f' u v) mem, +-- end, +-- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, +-- exact le_trans h4 h2 +-- end, +-- simp only [h, if_true], +-- exact h1, +-- }, +-- { +-- by_cases h': exists_path.in v u, +-- { +-- have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := +-- rsn.afn.no_overflow u v, +-- simp only [h, if_false, h', if_true], +-- linarith, +-- }, +-- { +-- simp only [h, if_false, h', if_false], +-- exact rsn.afn.no_overflow u v, +-- }, +-- }, +-- }, +-- { +-- simp only [edge, if_false], +-- have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, +-- linarith, +-- }, +-- end, +-- begin --no_edges_in_source +-- exact rsn.afn.no_edges_in_source, +-- end, +-- begin --no_edges_out_sink +-- exact rsn.afn.no_edges_out_sink, +-- end, +-- begin -- conservation +-- intros v vNotSinkSource, +-- have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, +-- have vNotSource: v ≠ rsn.afn.network.source := +-- begin +-- by_contradiction h, +-- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := +-- begin +-- have vSource: v ∈ {s} := finset.mem_singleton.2 h, +-- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, +-- exact finset.mem_union.2 vOR, +-- end, +-- rw union at vIn, +-- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := +-- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, +-- exact absurd vIn vNotIn, +-- end, +-- have vNotSink: v ≠ rsn.afn.network.sink := +-- begin +-- by_contradiction h, +-- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := +-- begin +-- have vSink: v ∈ {t} := finset.mem_singleton.2 h, +-- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, +-- exact finset.mem_union.2 vOR, +-- end, +-- rw union at vIn, +-- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := +-- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, +-- exact absurd vIn vNotIn, +-- end, +-- set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) +-- (ite (path.in u v exists_path) (rsn.afn.f u v + d) +-- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), +-- by_cases h: v ∈ vertices, +-- { +-- -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? +-- -- How do we procced after for picking these edges? +-- -- set predecessor := {u | exists_path.in u v}, +-- -- set ancestor := {w | exists_path.in v w}, +-- -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := +-- -- rsn.afn.conservation v vNotSinkSource, +-- -- rw [h2,h3,h1] +-- sorry, +-- }, +-- { +-- have h1: ∀ u : V, ¬exists_path.in u v := +-- begin +-- by_contradiction h', +-- push_neg at h', +-- have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t +-- have contr: v ∈ vertices := +-- begin +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- by {simp only [set.mem_set_of_eq], exact ancestor}, +-- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- or.intro_right (v ∈ {t}) mem, +-- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, +-- end, +-- exact absurd contr h, +-- end, +-- have h2: ∀ w : V, ¬exists_path.in v w := +-- begin +-- by_contradiction h', +-- push_neg at h', +-- have contr: v ∈ vertices := +-- begin +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- by {simp only [set.mem_set_of_eq], exact h'}, +-- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := +-- or.intro_right (v ∈ {t}) mem, +-- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, +-- end, +-- exact absurd contr h, +-- end, +-- have h3: ∀ u : V, newf u v = rsn.afn.f u v := +-- begin +-- intro u, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- have noEdge: ¬exists_path.in u v := h1 u, +-- have noReversedEdge: ¬exists_path.in v u := h2 u, +-- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) +-- (ite (path.in u v exists_path) (rsn.afn.f u v + d) +-- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], +-- }, +-- { +-- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) +-- (ite (path.in u v exists_path) (rsn.afn.f u v + d) +-- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_false], +-- have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, +-- linarith, +-- }, +-- end, +-- have h4: ∀ w : V, newf v w = rsn.afn.f v w := +-- begin +-- intro w, +-- by_cases edge: rsn.afn.network.is_edge v w, +-- { +-- have noEdge: ¬exists_path.in w v := h1 w, +-- have noReversedEdge: ¬exists_path.in v w := h2 w, +-- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) +-- (ite (path.in v w exists_path) (rsn.afn.f v w + d) +-- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], +-- }, +-- { +-- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) +-- (ite (path.in v w exists_path) (rsn.afn.f v w + d) +-- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, +-- rw simplify, +-- simp only [edge, if_false], +-- have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, +-- linarith, +-- }, +-- end, +-- have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := +-- begin +-- unfold mk_in, +-- have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = +-- ∑ (x : V) in V' \ {v}, newf x v := by simp, +-- have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = +-- ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, +-- rw [eq1, eq2], +-- exact finset.sum_congr rfl (λ u h, h3 u), +-- end, +-- have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := +-- begin +-- unfold mk_out, +-- have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = +-- ∑ (y : V) in V' \ {v}, newf v y := by simp, +-- have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = +-- ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, +-- rw [eq1, eq2], +-- exact finset.sum_congr rfl (λ u h, h4 u), +-- end, +-- rw [eqIn,eqOut], +-- exact rsn.afn.conservation v vNotSinkSource, +-- }, +-- end +-- ⟩, +-- have flow_value: F_value better_flow = F_value rsn.afn + d := +-- begin +-- unfold F_value, +-- set source := better_flow.network.source, +-- have h1: mk_out better_flow.f {source} = +-- mk_out rsn.afn.f {source} + d := +-- by sorry, +-- -- take the edge with the added flow +-- -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? +-- have h2: mk_in better_flow.f {source} = +-- mk_in rsn.afn.f {source} := +-- begin +-- have h3: mk_in better_flow.f {source} = 0 := +-- begin +-- unfold mk_in, +-- have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = +-- ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, +-- have zeroFlow: ∀ x : V, better_flow.f x source = 0 := +-- begin +-- intro x, +-- have noEdge: ¬better_flow.network.is_edge x source := +-- better_flow.no_edges_in_source x, +-- exact f_vanishes_outside_edge better_flow x source noEdge, +-- end, +-- rw eq, +-- exact finset.sum_eq_zero (λ x h, zeroFlow x), +-- end, +-- have h4: mk_in rsn.afn.f {source} = 0 := +-- begin +-- unfold mk_in, +-- set s := rsn.afn.network.source, +-- have sameSource: s = source := by refl, +-- have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = +-- ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, +-- have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := +-- begin +-- intro x, +-- have noEdge: ¬rsn.afn.network.is_edge x s := +-- rsn.afn.no_edges_in_source x, +-- exact f_vanishes_outside_edge rsn.afn x s noEdge, +-- end, +-- rw eq, +-- exact finset.sum_eq_zero (λ x h, zeroFlow x), +-- end, +-- rw ← h4 at h3, +-- exact h3, +-- end, +-- rw [h1,h2], +-- linarith +-- end, +-- have le: F_value rsn.afn ≥ F_value better_flow := +-- begin +-- have same_net: better_flow.network = rsn.afn.network := by simp, +-- unfold is_max_flow at max_flow, +-- exact max_flow better_flow same_net, +-- end, +-- have lt: F_value rsn.afn < F_value better_flow := +-- begin +-- rw flow_value, +-- have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, +-- have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, +-- exact gt_iff_lt.2 h2, +-- end, +-- have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, +-- exact absurd lt nlt, +-- end + +-- /-! +-- We will prove that there exists a cut with value equal to the max flow in the same network. +-- We will use a constructive proof, so we will construct our minimum cut. +-- -/ + +-- noncomputable +-- def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut +-- (rsn : residual_network V) : finset V := +-- {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset + +-- noncomputable +-- def mk_cut_from_S {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (hno_augmenting_path : no_augmenting_path rsn) +-- (S : finset V) (hS : S = mk_cut_set rsn) : cut V := +-- ⟨rsn.afn.network, S, V' \ S, +-- begin +-- rw hS, +-- unfold mk_cut_set, +-- simp only [set.mem_to_finset, set.mem_set_of_eq], +-- exact exists.intro path.nil trivial, +-- end, +-- begin +-- rw hS, +-- unfold mk_cut_set, +-- simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], +-- intro p, +-- unfold no_augmenting_path at hno_augmenting_path, +-- specialize hno_augmenting_path rsn.afn.network.sink, +-- simp only [eq_self_iff_true, not_true] at hno_augmenting_path, +-- apply exists.elim p, +-- intros p h, +-- specialize hno_augmenting_path p, +-- exact hno_augmenting_path, +-- end, +-- rfl⟩ + +-- lemma s_t_not_connected {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (S : finset V) (hS : S = mk_cut_set rsn) : +-- ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := +-- begin +-- intros u uInS v vInT is_edge_u_v, +-- rw hS at *, +-- unfold mk_cut_set at *, +-- simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, +-- apply exists.elim uInS, +-- intros p _, +-- have tmp := path.cons p is_edge_u_v, +-- apply vInT, +-- exact exists.intro tmp trivial, +-- end + +-- lemma residual_capacity_zero {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (ct : cut V) +-- (h_eq_network : rsn.afn.network = ct.network) +-- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : +-- ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := +-- begin +-- intros u uInS v vInT, +-- specialize h u uInS v vInT, +-- rw rsn.is_edge_def at h, +-- simp only [not_lt] at h, +-- have hge := residual_capacity_non_neg rsn u v, +-- exact ge_antisymm hge h, +-- end + +-- lemma min_max_cap_flow {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (ct : cut V) +-- (h_eq_network : rsn.afn.network = ct.network) +-- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : +-- (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ +-- (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := +-- begin +-- split, +-- { +-- intros u uInS v vInT, +-- specialize h u uInS v vInT, +-- rw rsn.f_def at h, +-- unfold mk_rsf at h, +-- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), +-- cases foo, +-- { +-- simp only [foo, if_true] at h, +-- linarith, +-- }, +-- { +-- simp only [foo, if_false, ite_eq_right_iff] at h, +-- have bar := rsn.afn.network.vanishes u v foo, +-- rw bar, +-- clear foo h, +-- have baz := rsn.afn.non_neg_flow u v, +-- have bark := rsn.afn.no_overflow u v, +-- linarith, +-- } +-- }, +-- { intros v vInT u uInS, +-- specialize h u uInS v vInT, +-- rw rsn.f_def at h, +-- unfold mk_rsf at h, +-- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), +-- cases foo, +-- { +-- have bark := rsn.afn.network.nonsymmetric u v, +-- simp only [not_and] at bark, +-- specialize bark foo, +-- have bar := rsn.afn.non_neg_flow v u, +-- have baz := rsn.afn.no_overflow v u, +-- have blurg := rsn.afn.network.vanishes v u bark, +-- linarith, +-- }, +-- { simp only [foo, if_false, ite_eq_right_iff] at h, +-- clear foo, +-- have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), +-- cases bar, +-- { exact h bar, }, +-- { have blurg := rsn.afn.non_neg_flow v u, +-- have bark := rsn.afn.no_overflow v u, +-- have baz := rsn.afn.network.vanishes v u bar, +-- linarith, }, }, } +-- end + +-- lemma f_value_eq_out {V : Type*} [inst' : fintype V] +-- (ct : cut V) +-- (afn : active_flow_network V) +-- (h_eq_network : afn.network = ct.network) +-- (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : +-- F_value afn = mk_out afn.f ct.S := +-- begin +-- dsimp [F_value], +-- rw flow_value_source_in_S afn ct h_eq_network, +-- dsimp [mk_in], +-- simp_rw [← ct.Tcomp], +-- simp only [sub_eq_self], +-- have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = +-- ∑ x in ct.T, ∑ y in ct.S, 0 := +-- begin +-- apply finset.sum_congr rfl, +-- intros x xInT, +-- apply finset.sum_congr rfl, +-- intros y yInS, +-- exact h x xInT y yInS, +-- end, +-- rw sum_eq_sum_zero, +-- simp only [sum_const_zero], +-- end + +-- lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] +-- (ct : cut V) +-- (afn : active_flow_network V) +-- (h_eq_network : afn.network = ct.network) +-- (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ +-- (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : +-- mk_out afn.f ct.S = cut_cap ct := +-- begin +-- cases h with h_flow_eq_cap h_flow_zero, +-- dsimp [cut_cap, mk_out], +-- apply finset.sum_congr rfl, +-- intros x xInS, +-- rw ← ct.Tcomp at *, +-- apply finset.sum_congr rfl, +-- intros y yInT, +-- simp [h_eq_network, h_flow_eq_cap x xInS y yInT], +-- end + +-- lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] +-- (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) +-- (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : +-- ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := +-- begin +-- apply finset.sum_congr rfl, +-- intros a aInA, +-- apply finset.sum_congr rfl, +-- intros b bInB, +-- exact eq_on_res a aInA b bInB, +-- end + +-- /-! +-- Here is our last big lemma, if there is no augmenting path in the resiual network, then +-- there exists a cut with a capacity equal to the value of the active flow in the same network. +-- -/ + +-- lemma existence_of_a_cut {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) +-- (hno_augmenting_path : no_augmenting_path rsn) : +-- (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := +-- begin +-- let S : finset V := mk_cut_set rsn, +-- let T := V' \ S, +-- let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, +-- have same_net : rsn.afn.network = min_cut.network := by refl, +-- have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := +-- by {intros x y, split, intro heq, linarith, intro heq, linarith}, +-- have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := +-- begin +-- intros u uInS v vInNS, +-- by_contradiction h, +-- have edge: rsn.is_edge u v := +-- begin +-- by_contradiction h', +-- have contr: rsn.f' u v = 0 := +-- begin +-- rw rsn.is_edge_def at h', +-- simp only [not_lt] at h', +-- have hge := residual_capacity_non_neg rsn u v, +-- exact ge_antisymm hge h', +-- end, +-- contradiction +-- end, +-- have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, +-- contradiction +-- end, +-- have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, +-- (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := +-- begin +-- intros u uInS v vInT is_edge, +-- have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := +-- by {unfold mk_rsf, simp only [is_edge, if_true]}, +-- rw ← h1, +-- have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, +-- rw h2, +-- exact cf_vanishes_on_pipes u uInS v vInT, +-- end, +-- have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = +-- rsn.afn.network.c u v := +-- begin +-- intros u uInS v vInT, +-- by_cases edge: rsn.afn.network.is_edge u v, +-- { +-- have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := +-- cf_vanishes_on_pipes_spec u uInS v vInT edge, +-- linarith, +-- }, +-- { +-- rw rsn.afn.network.vanishes u v edge, +-- exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), +-- }, +-- end, +-- have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := +-- begin +-- intros u v hyp, +-- exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, +-- end, +-- have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := +-- begin +-- rw F_value, +-- simp only, +-- rw flow_value_source_in_S rsn.afn min_cut same_net, +-- have no_input : mk_in rsn.afn.f min_cut.S = 0 := +-- begin +-- rw mk_in, +-- exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), +-- end, +-- rw no_input, +-- simp only [sub_zero], +-- have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := +-- begin +-- unfold mk_out, +-- rw eq_on_res_then_on_sum +-- (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), +-- end, +-- rw flow_eq_cap_on_cut, +-- refl, +-- end, +-- use min_cut, +-- split, +-- {exact same_net}, +-- exact cut_eq_flow +-- end + +-- /-! +-- Finally, our biggest result, the max-flow min-cut theorem! +-- If a maximum flow exists, its value is equal to the capacity of the min-cut. +-- -/ + +-- theorem max_flow_min_cut {V : Type*} [inst' : fintype V] +-- (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : +-- (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := +-- begin +-- rintros ⟨max_flow, min_cut⟩ , +-- have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, +-- have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ +-- cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, +-- have max_flow_min_cut: ∀ cut : cut V, +-- (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → +-- (F_value rsn.afn = cut_cap c) := +-- begin +-- rintros cut ⟨same_net, eq⟩, +-- have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, +-- have h2: is_min_cut c := min_cut, +-- have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, +-- have same_net2: c.network = cut.network := by rw ← same_net1, +-- have same_val: cut_cap cut = cut_cap c := +-- begin +-- have le1: cut_cap cut ≤ cut_cap c := +-- by {unfold is_min_cut at h1, exact h1 c same_net1}, +-- have le2: cut_cap c ≤ cut_cap cut := +-- by {unfold is_min_cut at h2, exact h2 cut same_net2}, +-- exact le_antisymm le1 le2, +-- end, +-- rw ← eq, +-- exact same_val, +-- end, +-- exact exists.elim existsCut max_flow_min_cut, +-- end From 8e0a45c5eabc839b025e0046118bf3bdccd7390f Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 12:15:24 +0100 Subject: [PATCH 27/28] braces fix in comented out code --- .../quiver/max_flow_min_cut.lean | 286 +++++++----------- 1 file changed, 117 insertions(+), 169 deletions(-) diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index f27d7876e2186..5563754f3eea8 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -733,83 +733,83 @@ begin exact weak_duality (afn) (cut) (h), end --- /-! --- We now define our residual network. Our goal is to prove no_augm_path. --- -/ +/-! + We now define our residual network. Our goal is to prove no_augm_path. +-/ --- noncomputable --- def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow --- (afn : active_flow_network V) --- (u v : V) : ℝ := --- if afn.network.is_edge u v --- then afn.network.c u v - afn.f u v --- else if afn.network.is_edge v u --- then afn.f v u --- else 0 - --- structure residual_network (V : Type*) [inst' : fintype V] := --- (afn : active_flow_network V) --- (f' : V -> V -> ℝ) --- (f_def : f' = mk_rsf afn) --- (is_edge : V -> V -> Prop) --- (is_edge_def : is_edge = λ u v, f' u v > 0) +noncomputable +def mk_rsf {V : Type*} [inst' : fintype V] -- stays for residual flow + (afn : active_flow_network V) + (u v : V) : ℝ := + if afn.network.is_edge u v + then afn.network.c u v - afn.f u v + else if afn.network.is_edge v u + then afn.f v u + else 0 + +structure residual_network (V : Type*) [inst' : fintype V] := + (afn : active_flow_network V) + (f' : V -> V -> ℝ) + (f_def : f' = mk_rsf afn) + (is_edge : V -> V -> Prop) + (is_edge_def : is_edge = λ u v, f' u v > 0) --- noncomputable --- def mk_rsn {V : Type*} [fintype V] -- stays for residual network --- (afn : active_flow_network V) : residual_network V := --- ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ +noncomputable +def mk_rsn {V : Type*} [fintype V] -- stays for residual network + (afn : active_flow_network V) : residual_network V := + ⟨afn, mk_rsf afn, rfl, λ u v, mk_rsf afn u v > 0 , rfl⟩ --- universe u +universe u --- /- --- We define a recursive structure returning the path between two vertices, --- if such a path exists, given the edges in the graph. --- -/ --- inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) --- | nil : path a --- | cons : Π {b c : V}, path b → (is_edge b c) → path c +/- + We define a recursive structure returning the path between two vertices, + if such a path exists, given the edges in the graph. +-/ +inductive path {V : Type u } (is_edge : V -> V -> Prop) (a : V) : V → Type (u + 1) +| nil : path a +| cons : Π {b c : V}, path b → (is_edge b c) → path c --- def no_augmenting_path {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) : Prop := --- ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) +def no_augmenting_path {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : Prop := + ∀ t : V, ∀ p : path rsn.is_edge rsn.afn.network.source t, ¬ (t = rsn.afn.network.sink) --- /- --- Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. --- -/ --- def path.in {V : Type u} --- {is_edge : V -> V -> Prop} --- (u v : V) --- {s : V} : ∀ {t : V}, path is_edge s t -> Prop --- | t (@path.nil _ is_edge' a) := u = v --- | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) - --- lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := --- begin --- intros u v, --- cases rsn, --- simp only, --- rw rsn_f_def, --- unfold mk_rsf, --- have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), --- cases foo, --- { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, --- { simp only [foo, if_false], clear foo, --- have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), --- cases bar, --- { have h := rsn_afn.non_neg_flow v u, --- simp only [bar, h, if_true], --- linarith, }, --- { simp only [bar, if_false] }, }, --- end +/- + Given two vertices $u and $v, returns true if and only if (u,v) is an edge in a given path. +-/ +def path.in {V : Type u} + {is_edge : V -> V -> Prop} + (u v : V) + {s : V} : ∀ {t : V}, path is_edge s t -> Prop + | t (@path.nil _ is_edge' a) := u = v + | t (@path.cons _ _ _ t' _ p _) := (u = t' ∧ v = t) ∨ (@path.in t' p) + +lemma residual_capacity_non_neg {V : Type*} [inst' : fintype V] + (rsn : residual_network V) : ∀ u v : V, 0 ≤ rsn.f' u v := +begin + intros u v, + cases rsn, + simp only, + rw rsn_f_def, + unfold mk_rsf, + have foo := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge u v), + cases foo, + { simp only [foo, if_true, sub_nonneg, rsn_afn.no_overflow], }, + { simp only [foo, if_false], clear foo, + have bar := classical.em (rsn_afn.network.to_capacity.to_digraph.is_edge v u), + cases bar, + { have h := rsn_afn.non_neg_flow v u, + simp only [bar, h, if_true], + linarith, }, + { simp only [bar, if_false] }, }, +end --- lemma positive_residual_flow {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := --- begin --- intro edge, --- rw rsn.is_edge_def at edge, --- exact edge, --- end +lemma positive_residual_flow {V : Type*} [inst' : fintype V] + (rsn : residual_network V) (u v : V) : rsn.is_edge u v → rsn.f' u v > 0 := +begin + intro edge, + rw rsn.is_edge_def at edge, + exact edge, +end -- /-! -- Here is our second big lemma, if the active flow is maximum, @@ -864,22 +864,18 @@ end -- set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, -- apply v_in_vertices.elim; -- intro hypo, --- { --- simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, +-- { simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, -- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, -- prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, -- set.nonempty_image_iff, set.to_finset_eq_empty, -- set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, -- eq_self_iff_true, true_or] at *, -- use [t, t], --- simpa, --- }, --- { --- simp only [set.singleton_union, set.mem_image, set.mem_to_finset, +-- simpa, }, +-- { simp only [set.singleton_union, set.mem_image, set.mem_to_finset, -- set.coe_to_finset, prod.exists], -- use [v, t], --- simp [hypo, hyp] --- }, +-- simp [hypo, hyp], }, -- end, -- exact finset.ne_empty_of_mem contr, -- end, @@ -920,18 +916,13 @@ end -- begin -- non_neg_flow -- intros u v, -- by_cases edge: rsn.afn.network.is_edge u v, --- { --- simp only [edge, if_true], +-- { simp only [edge, if_true], -- by_cases h: exists_path.in u v, --- { --- have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, +-- { have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, -- simp only [h, if_true], --- linarith, --- }, --- { --- by_cases h': exists_path.in v u, --- { --- simp only [h, if_false, h', if_true], +-- linarith, }, +-- { by_cases h': exists_path.in v u, +-- { simp only [h, if_false, h', if_true], -- have ine: d ≤ rsn.afn.f u v := -- begin -- have minimality: d ≤ rsn.f' v u := @@ -960,27 +951,18 @@ end -- rw ← eq, -- exact minimality, -- end, --- linarith, --- }, --- { --- simp only [h, if_false, h', if_false], --- exact rsn.afn.non_neg_flow u v, --- }, --- }, --- }, --- { --- simp only [edge, if_false], --- linarith, --- }, +-- linarith, }, +-- { simp only [h, if_false, h', if_false], +-- exact rsn.afn.non_neg_flow u v, }, }, }, +-- { simp only [edge, if_false], +-- linarith, }, -- end, -- begin -- no_overflow -- intros u v, -- by_cases edge: rsn.afn.network.is_edge u v, --- { --- simp only [edge, if_true], +-- { simp only [edge, if_true], -- by_cases h: exists_path.in u v, --- { --- have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := +-- { have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := -- begin -- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := -- begin @@ -1007,27 +989,17 @@ end -- exact le_trans h4 h2 -- end, -- simp only [h, if_true], --- exact h1, --- }, --- { --- by_cases h': exists_path.in v u, --- { --- have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := +-- exact h1, }, +-- { by_cases h': exists_path.in v u, +-- { have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := -- rsn.afn.no_overflow u v, -- simp only [h, if_false, h', if_true], --- linarith, --- }, --- { --- simp only [h, if_false, h', if_false], --- exact rsn.afn.no_overflow u v, --- }, --- }, --- }, --- { --- simp only [edge, if_false], +-- linarith, }, +-- { simp only [h, if_false, h', if_false], +-- exact rsn.afn.no_overflow u v, }, }, }, +-- { simp only [edge, if_false], -- have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, --- linarith, --- }, +-- linarith, }, -- end, -- begin --no_edges_in_source -- exact rsn.afn.no_edges_in_source, @@ -1070,18 +1042,15 @@ end -- (ite (path.in u v exists_path) (rsn.afn.f u v + d) -- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), -- by_cases h: v ∈ vertices, --- { --- -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? +-- { -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? -- -- How do we procced after for picking these edges? -- -- set predecessor := {u | exists_path.in u v}, -- -- set ancestor := {w | exists_path.in v w}, -- -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := -- -- rsn.afn.conservation v vNotSinkSource, -- -- rw [h2,h3,h1] --- sorry, --- }, --- { --- have h1: ∀ u : V, ¬exists_path.in u v := +-- sorry, }, +-- { have h1: ∀ u : V, ¬exists_path.in u v := -- begin -- by_contradiction h', -- push_neg at h', @@ -1116,47 +1085,39 @@ end -- begin -- intro u, -- by_cases edge: rsn.afn.network.is_edge u v, --- { --- have noEdge: ¬exists_path.in u v := h1 u, +-- { have noEdge: ¬exists_path.in u v := h1 u, -- have noReversedEdge: ¬exists_path.in v u := h2 u, -- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) -- (ite (path.in u v exists_path) (rsn.afn.f u v + d) -- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, -- rw simplify, --- simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], --- }, --- { --- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) +-- simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], }, +-- { have simplify: newf u v = ite (rsn.afn.network.is_edge u v) -- (ite (path.in u v exists_path) (rsn.afn.f u v + d) -- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, -- rw simplify, -- simp only [edge, if_false], -- have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, --- linarith, --- }, +-- linarith, }, -- end, -- have h4: ∀ w : V, newf v w = rsn.afn.f v w := -- begin -- intro w, -- by_cases edge: rsn.afn.network.is_edge v w, --- { --- have noEdge: ¬exists_path.in w v := h1 w, +-- { have noEdge: ¬exists_path.in w v := h1 w, -- have noReversedEdge: ¬exists_path.in v w := h2 w, -- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) -- (ite (path.in v w exists_path) (rsn.afn.f v w + d) -- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, -- rw simplify, --- simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], --- }, --- { --- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) +-- simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], }, +-- { have simplify: newf v w = ite (rsn.afn.network.is_edge v w) -- (ite (path.in v w exists_path) (rsn.afn.f v w + d) -- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, -- rw simplify, -- simp only [edge, if_false], -- have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, --- linarith, --- }, +-- linarith, }, -- end, -- have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := -- begin @@ -1179,8 +1140,7 @@ end -- exact finset.sum_congr rfl (λ u h, h4 u), -- end, -- rw [eqIn,eqOut], --- exact rsn.afn.conservation v vNotSinkSource, --- }, +-- exact rsn.afn.conservation v vNotSinkSource, }, -- end -- ⟩, -- have flow_value: F_value better_flow = F_value rsn.afn + d := @@ -1327,42 +1287,34 @@ end -- (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := -- begin -- split, --- { --- intros u uInS v vInT, +-- { intros u uInS v vInT, -- specialize h u uInS v vInT, -- rw rsn.f_def at h, -- unfold mk_rsf at h, -- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), -- cases foo, --- { --- simp only [foo, if_true] at h, --- linarith, --- }, --- { --- simp only [foo, if_false, ite_eq_right_iff] at h, +-- { simp only [foo, if_true] at h, +-- linarith, }, +-- { simp only [foo, if_false, ite_eq_right_iff] at h, -- have bar := rsn.afn.network.vanishes u v foo, -- rw bar, -- clear foo h, -- have baz := rsn.afn.non_neg_flow u v, -- have bark := rsn.afn.no_overflow u v, --- linarith, --- } --- }, +-- linarith, }, }, -- { intros v vInT u uInS, -- specialize h u uInS v vInT, -- rw rsn.f_def at h, -- unfold mk_rsf at h, -- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), -- cases foo, --- { --- have bark := rsn.afn.network.nonsymmetric u v, +-- { have bark := rsn.afn.network.nonsymmetric u v, -- simp only [not_and] at bark, -- specialize bark foo, -- have bar := rsn.afn.non_neg_flow v u, -- have baz := rsn.afn.no_overflow v u, -- have blurg := rsn.afn.network.vanishes v u bark, --- linarith, --- }, +-- linarith, }, -- { simp only [foo, if_false, ite_eq_right_iff] at h, -- clear foo, -- have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), @@ -1480,15 +1432,11 @@ end -- begin -- intros u uInS v vInT, -- by_cases edge: rsn.afn.network.is_edge u v, --- { --- have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := +-- { have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := -- cf_vanishes_on_pipes_spec u uInS v vInT edge, --- linarith, --- }, --- { --- rw rsn.afn.network.vanishes u v edge, --- exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), --- }, +-- linarith, }, +-- { rw rsn.afn.network.vanishes u v edge, +-- exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), }, -- end, -- have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := -- begin From f6b33bccfaeebe4a53722bc0c300b05ccc72e228 Mon Sep 17 00:00:00 2001 From: amilchew Date: Fri, 12 May 2023 12:24:39 +0100 Subject: [PATCH 28/28] first fixes --- leanpkg.toml | 1 - .../quiver/max_flow_min_cut.lean | 695 ------------------ 2 files changed, 696 deletions(-) diff --git a/leanpkg.toml b/leanpkg.toml index f443084a23bb5..98c2e9e127eb3 100644 --- a/leanpkg.toml +++ b/leanpkg.toml @@ -5,4 +5,3 @@ lean_version = "leanprover-community/lean:3.50.3" path = "src" [dependencies] -mathlib = {git = "https://github.com/leanprover-community/mathlib", rev = "290a7ba01fbcab1b64757bdaa270d28f4dcede35"} diff --git a/src/combinatorics/quiver/max_flow_min_cut.lean b/src/combinatorics/quiver/max_flow_min_cut.lean index 5563754f3eea8..d02081743168a 100644 --- a/src/combinatorics/quiver/max_flow_min_cut.lean +++ b/src/combinatorics/quiver/max_flow_min_cut.lean @@ -810,698 +810,3 @@ begin rw rsn.is_edge_def at edge, exact edge, end - --- /-! --- Here is our second big lemma, if the active flow is maximum, --- then no augmenting path exists in the residual network. --- -/ - --- lemma no_augm_path {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) : (is_max_flow rsn.afn) -> no_augmenting_path rsn := --- begin --- intros max_flow x exists_path, --- by_contradiction is_sink, --- set s := rsn.afn.network.source, --- set t := rsn.afn.network.sink, --- have augm_path: path rsn.is_edge s t := by {rw is_sink at exists_path, exact exists_path}, --- have exists_augm_path: ¬no_augmenting_path rsn := --- begin --- unfold no_augmenting_path, --- push_neg, --- use x, --- by_contradiction h, --- have contr: x ≠ t := h exists_path, --- exact absurd is_sink contr, --- end, --- --all vertices in the augmenting path --- set vertices := set.to_finset ({t} ∪ { x | (∃ y: V, exists_path.in x y) }), --- -- set of all flow values in the augmenting path --- set flows := --- set.to_finset (function.uncurry rsn.f' '' {e ∈ vertices ×ˢ vertices | exists_path.in e.1 e.2}), --- have nonemp: flows.nonempty := --- begin --- by_contradiction h, --- have empty: flows = ∅ := finset.not_nonempty_iff_eq_empty.1 h, --- have foo: ∀ v : V, exists_path.in v t → flows ≠ ∅ := --- begin --- intros v hyp, --- have t_in_vertices: t ∈ vertices := by simp, --- have v_in_vertices: v ∈ vertices := --- begin --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- have baz: exists_path.in v t := hyp, --- have exist: ∃ (y : V), path.in v y exists_path := by {use t, exact hyp}, --- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- by {simp only [set.mem_set_of_eq], exact exist}, --- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- or.intro_right (v ∈ {t}) mem, --- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, --- end, --- have contr: rsn.f' v t ∈ flows := --- begin --- simp only [true_and, set.singleton_union, finset.mem_univ, set.to_finset_congr, --- true_or, eq_self_iff_true, set.to_finset_set_of, finset.mem_insert, --- set.to_finset_insert, finset.mem_filter, vertices] at v_in_vertices, --- apply v_in_vertices.elim; --- intro hypo, --- { simp only [hypo, set.mem_to_finset, set.coe_to_finset, set.singleton_union, --- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, set.mem_set_of_eq, --- prod.exists, function.uncurry_apply_pair, set.to_finset_nonempty, --- set.nonempty_image_iff, set.to_finset_eq_empty, --- set.image_eq_empty,set.sep_eq_empty_iff_mem_false, and_imp, prod.forall, --- eq_self_iff_true, true_or] at *, --- use [t, t], --- simpa, }, --- { simp only [set.singleton_union, set.mem_image, set.mem_to_finset, --- set.coe_to_finset, prod.exists], --- use [v, t], --- simp [hypo, hyp], }, --- end, --- exact finset.ne_empty_of_mem contr, --- end, --- have bar: ∃ v : V, exists_path.in v t := -- exists augmenting path --- begin --- by_contradiction h, --- push_neg at h, --- have no_augm_path: no_augmenting_path rsn := by sorry, --- exact absurd no_augm_path exists_augm_path, --- end, --- have contr: flows ≠ ∅ := exists.elim bar foo, --- exact absurd empty contr, --- end, --- set d := flows.min' nonemp, -- the minimum flow in the augmenting path --- have pos: 0 < d := --- begin --- have mem: d ∈ flows := finset.min'_mem flows nonemp, --- have pos: ∀ f : ℝ , f ∈ flows → f > 0 := --- begin --- intros f hyp, --- simp only [set.mem_to_finset, set.mem_set_of_eq, set.coe_to_finset, set.singleton_union, --- set.mem_image, set.mem_sep_iff, set.mem_prod, set.mem_insert_iff, prod.exists, --- function.uncurry_apply_pair] at hyp, --- obtain ⟨a, b, hyp, hyp'⟩ := hyp, --- rw [← hyp'], --- apply positive_residual_flow, --- sorry, --- end, --- exact pos d mem, --- end, --- set better_flow: active_flow_network V := --- ⟨rsn.afn.network, --- (λ u v : V, if rsn.afn.network.is_edge u v then (if exists_path.in u v then rsn.afn.f u v + d --- else (if exists_path.in v u then rsn.afn.f u v - d else rsn.afn.f u v)) else 0), --- begin -- source ≠ sink --- exact rsn.afn.source_not_sink, --- end, --- begin -- non_neg_flow --- intros u v, --- by_cases edge: rsn.afn.network.is_edge u v, --- { simp only [edge, if_true], --- by_cases h: exists_path.in u v, --- { have nonneg: rsn.afn.f u v ≥ 0 := rsn.afn.non_neg_flow u v, --- simp only [h, if_true], --- linarith, }, --- { by_cases h': exists_path.in v u, --- { simp only [h, if_false, h', if_true], --- have ine: d ≤ rsn.afn.f u v := --- begin --- have minimality: d ≤ rsn.f' v u := --- begin --- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := --- by {intros f hf, exact finset.min'_le flows f hf}, --- have mem: rsn.f' v u ∈ flows := --- begin --- have foo: ∃ y : V, exists_path.in v y := by {use u, exact h'}, --- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], --- use [v, u], --- simp [foo, h'], --- sorry, --- end, --- exact min (rsn.f' v u) mem, --- end, --- have eq: rsn.f' v u = rsn.afn.f u v := --- begin --- rw rsn.f_def, --- unfold mk_rsf, --- have notAnd := rsn.afn.network.nonsymmetric u v, --- simp only [not_and] at notAnd, --- have notEdge: ¬ rsn.afn.network.is_edge v u := notAnd edge, --- simp only [notEdge, if_false, edge, if_true], --- end, --- rw ← eq, --- exact minimality, --- end, --- linarith, }, --- { simp only [h, if_false, h', if_false], --- exact rsn.afn.non_neg_flow u v, }, }, }, --- { simp only [edge, if_false], --- linarith, }, --- end, --- begin -- no_overflow --- intros u v, --- by_cases edge: rsn.afn.network.is_edge u v, --- { simp only [edge, if_true], --- by_cases h: exists_path.in u v, --- { have h1: rsn.afn.f u v + d ≤ rsn.afn.network.to_capacity.c u v := --- begin --- have h2: rsn.afn.f u v + rsn.f' u v ≤ rsn.afn.network.to_capacity.c u v := --- begin --- have eq: rsn.f' u v = rsn.afn.network.c u v - rsn.afn.f u v := --- by {rw rsn.f_def, unfold mk_rsf, simp only [edge, if_true, h, if_true]}, --- rw eq, --- linarith, --- end, --- have h3: d ≤ rsn.f' u v := --- begin --- have min: ∀ f : ℝ , f ∈ flows → d ≤ f := --- by {intros f hf, exact finset.min'_le flows f hf}, --- have mem: rsn.f' u v ∈ flows := --- begin --- have foo: ∃ y : V, exists_path.in u y := by {use v, exact h}, --- simp only [set.mem_image, set.mem_to_finset, set.coe_to_finset, prod.exists], --- use [u, v], --- simp [foo, h], --- sorry, --- end, --- exact min (rsn.f' u v) mem, --- end, --- have h4: rsn.afn.f u v + d ≤ rsn.afn.f u v + rsn.f' u v := by {linarith}, --- exact le_trans h4 h2 --- end, --- simp only [h, if_true], --- exact h1, }, --- { by_cases h': exists_path.in v u, --- { have h1: rsn.afn.f u v ≤ rsn.afn.network.to_capacity.c u v := --- rsn.afn.no_overflow u v, --- simp only [h, if_false, h', if_true], --- linarith, }, --- { simp only [h, if_false, h', if_false], --- exact rsn.afn.no_overflow u v, }, }, }, --- { simp only [edge, if_false], --- have cap: rsn.afn.network.c u v = 0 := rsn.afn.network.vanishes u v edge, --- linarith, }, --- end, --- begin --no_edges_in_source --- exact rsn.afn.no_edges_in_source, --- end, --- begin --no_edges_out_sink --- exact rsn.afn.no_edges_out_sink, --- end, --- begin -- conservation --- intros v vNotSinkSource, --- have union: ({s}: finset V) ∪ ({t}: finset V) = {s,t} := by refl, --- have vNotSource: v ≠ rsn.afn.network.source := --- begin --- by_contradiction h, --- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := --- begin --- have vSource: v ∈ {s} := finset.mem_singleton.2 h, --- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_left (v ∈ {t}) vSource, --- exact finset.mem_union.2 vOR, --- end, --- rw union at vIn, --- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := --- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, --- exact absurd vIn vNotIn, --- end, --- have vNotSink: v ≠ rsn.afn.network.sink := --- begin --- by_contradiction h, --- have vIn: v ∈ ({s}: finset V) ∪ ({t}: finset V) := --- begin --- have vSink: v ∈ {t} := finset.mem_singleton.2 h, --- have vOR: v ∈ {s} ∨ v ∈ {t} := or.intro_right (v ∈ {s}) vSink, --- exact finset.mem_union.2 vOR, --- end, --- rw union at vIn, --- have vNotIn: v ∉ ({s}: finset V) ∪ ({t}: finset V) := --- by {rw union, exact (finset.mem_sdiff.1 vNotSinkSource).2}, --- exact absurd vIn vNotIn, --- end, --- set newf := (λ (u v : V), ite (rsn.afn.network.is_edge u v) --- (ite (path.in u v exists_path) (rsn.afn.f u v + d) --- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0), --- by_cases h: v ∈ vertices, --- { -- Issues: How are we looking into cases for the cardinality of predecessor and ancestor? --- -- How do we procced after for picking these edges? --- -- set predecessor := {u | exists_path.in u v}, --- -- set ancestor := {w | exists_path.in v w}, --- -- have h1: mk_out rsn.afn.f {v} = mk_in rsn.afn.f {v} := --- -- rsn.afn.conservation v vNotSinkSource, --- -- rw [h2,h3,h1] --- sorry, }, --- { have h1: ∀ u : V, ¬exists_path.in u v := --- begin --- by_contradiction h', --- push_neg at h', --- have ancestor: ∃w : V, exists_path.in v w := by sorry, -- v ≠ t --- have contr: v ∈ vertices := --- begin --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- by {simp only [set.mem_set_of_eq], exact ancestor}, --- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- or.intro_right (v ∈ {t}) mem, --- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, --- end, --- exact absurd contr h, --- end, --- have h2: ∀ w : V, ¬exists_path.in v w := --- begin --- by_contradiction h', --- push_neg at h', --- have contr: v ∈ vertices := --- begin --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- have mem: v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- by {simp only [set.mem_set_of_eq], exact h'}, --- have or: v ∈ {t} ∨ v ∈ {x_1 : V | ∃ (y : V), path.in x_1 y exists_path} := --- or.intro_right (v ∈ {t}) mem, --- exact (set.mem_union v {t} ({x_1 : V | ∃ (y : V), path.in x_1 y exists_path})).2 or, --- end, --- exact absurd contr h, --- end, --- have h3: ∀ u : V, newf u v = rsn.afn.f u v := --- begin --- intro u, --- by_cases edge: rsn.afn.network.is_edge u v, --- { have noEdge: ¬exists_path.in u v := h1 u, --- have noReversedEdge: ¬exists_path.in v u := h2 u, --- have simplify: newf u v = ite (rsn.afn.network.is_edge u v) --- (ite (path.in u v exists_path) (rsn.afn.f u v + d) --- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, --- rw simplify, --- simp only [edge, if_true, noEdge, if_false, noReversedEdge, if_false], }, --- { have simplify: newf u v = ite (rsn.afn.network.is_edge u v) --- (ite (path.in u v exists_path) (rsn.afn.f u v + d) --- (ite (path.in v u exists_path) (rsn.afn.f u v - d) (rsn.afn.f u v))) 0 := by simp, --- rw simplify, --- simp only [edge, if_false], --- have zeroFlow: rsn.afn.f u v = 0 := f_vanishes_outside_edge rsn.afn u v edge, --- linarith, }, --- end, --- have h4: ∀ w : V, newf v w = rsn.afn.f v w := --- begin --- intro w, --- by_cases edge: rsn.afn.network.is_edge v w, --- { have noEdge: ¬exists_path.in w v := h1 w, --- have noReversedEdge: ¬exists_path.in v w := h2 w, --- have simplify: newf v w = ite (rsn.afn.network.is_edge v w) --- (ite (path.in v w exists_path) (rsn.afn.f v w + d) --- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, --- rw simplify, --- simp only [edge, if_true, noReversedEdge, if_false, noEdge, if_false], }, --- { have simplify: newf v w = ite (rsn.afn.network.is_edge v w) --- (ite (path.in v w exists_path) (rsn.afn.f v w + d) --- (ite (path.in w v exists_path) (rsn.afn.f v w - d) (rsn.afn.f v w))) 0 := by simp, --- rw simplify, --- simp only [edge, if_false], --- have zeroFlow: rsn.afn.f v w = 0 := f_vanishes_outside_edge rsn.afn v w edge, --- linarith, }, --- end, --- have eqIn: mk_in newf {v} = mk_in rsn.afn.f {v} := --- begin --- unfold mk_in, --- have eq1: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, newf x y = --- ∑ (x : V) in V' \ {v}, newf x v := by simp, --- have eq2: ∑ (x : V) in V' \ {v}, ∑ (y : V) in {v}, rsn.afn.f x y = --- ∑ (x : V) in V' \ {v}, rsn.afn.f x v := by simp, --- rw [eq1, eq2], --- exact finset.sum_congr rfl (λ u h, h3 u), --- end, --- have eqOut: mk_out newf {v} = mk_out rsn.afn.f {v} := --- begin --- unfold mk_out, --- have eq1: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, newf x y = --- ∑ (y : V) in V' \ {v}, newf v y := by simp, --- have eq2: ∑ (x : V) in {v}, ∑ (y : V) in V' \ {v}, rsn.afn.f x y = --- ∑ (y : V) in V' \ {v}, rsn.afn.f v y := by simp, --- rw [eq1, eq2], --- exact finset.sum_congr rfl (λ u h, h4 u), --- end, --- rw [eqIn,eqOut], --- exact rsn.afn.conservation v vNotSinkSource, }, --- end --- ⟩, --- have flow_value: F_value better_flow = F_value rsn.afn + d := --- begin --- unfold F_value, --- set source := better_flow.network.source, --- have h1: mk_out better_flow.f {source} = --- mk_out rsn.afn.f {source} + d := --- by sorry, --- -- take the edge with the added flow --- -- Issue: How do we prove that there is exactly one edge? How do we pick exactly that edge? --- have h2: mk_in better_flow.f {source} = --- mk_in rsn.afn.f {source} := --- begin --- have h3: mk_in better_flow.f {source} = 0 := --- begin --- unfold mk_in, --- have eq: ∑ (x : V) in V' \ {source}, ∑ (y : V) in {source}, better_flow.f x y = --- ∑ (x : V) in V' \ {source}, better_flow.f x source := by simp, --- have zeroFlow: ∀ x : V, better_flow.f x source = 0 := --- begin --- intro x, --- have noEdge: ¬better_flow.network.is_edge x source := --- better_flow.no_edges_in_source x, --- exact f_vanishes_outside_edge better_flow x source noEdge, --- end, --- rw eq, --- exact finset.sum_eq_zero (λ x h, zeroFlow x), --- end, --- have h4: mk_in rsn.afn.f {source} = 0 := --- begin --- unfold mk_in, --- set s := rsn.afn.network.source, --- have sameSource: s = source := by refl, --- have eq: ∑ (x : V) in V' \ {s}, ∑ (y : V) in {s}, rsn.afn.f x y = --- ∑ (x : V) in V' \ {s}, rsn.afn.f x s := by simp, --- have zeroFlow: ∀ x : V, rsn.afn.f x s = 0 := --- begin --- intro x, --- have noEdge: ¬rsn.afn.network.is_edge x s := --- rsn.afn.no_edges_in_source x, --- exact f_vanishes_outside_edge rsn.afn x s noEdge, --- end, --- rw eq, --- exact finset.sum_eq_zero (λ x h, zeroFlow x), --- end, --- rw ← h4 at h3, --- exact h3, --- end, --- rw [h1,h2], --- linarith --- end, --- have le: F_value rsn.afn ≥ F_value better_flow := --- begin --- have same_net: better_flow.network = rsn.afn.network := by simp, --- unfold is_max_flow at max_flow, --- exact max_flow better_flow same_net, --- end, --- have lt: F_value rsn.afn < F_value better_flow := --- begin --- rw flow_value, --- have h1: F_value rsn.afn - F_value rsn.afn < d := by linarith, --- have h2: F_value rsn.afn < F_value rsn.afn + d := lt_add_of_sub_left_lt h1, --- exact gt_iff_lt.2 h2, --- end, --- have nlt: ¬F_value rsn.afn < F_value better_flow := not_lt_of_ge le, --- exact absurd lt nlt, --- end - --- /-! --- We will prove that there exists a cut with value equal to the max flow in the same network. --- We will use a constructive proof, so we will construct our minimum cut. --- -/ - --- noncomputable --- def mk_cut_set {V : Type u} [inst' : fintype V] -- The source set for the minimum cut --- (rsn : residual_network V) : finset V := --- {x | (∃ p : path rsn.is_edge rsn.afn.network.source x, true)}.to_finset - --- noncomputable --- def mk_cut_from_S {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (hno_augmenting_path : no_augmenting_path rsn) --- (S : finset V) (hS : S = mk_cut_set rsn) : cut V := --- ⟨rsn.afn.network, S, V' \ S, --- begin --- rw hS, --- unfold mk_cut_set, --- simp only [set.mem_to_finset, set.mem_set_of_eq], --- exact exists.intro path.nil trivial, --- end, --- begin --- rw hS, --- unfold mk_cut_set, --- simp only [mem_sdiff, mem_univ, set.mem_to_finset, set.mem_set_of_eq, true_and], --- intro p, --- unfold no_augmenting_path at hno_augmenting_path, --- specialize hno_augmenting_path rsn.afn.network.sink, --- simp only [eq_self_iff_true, not_true] at hno_augmenting_path, --- apply exists.elim p, --- intros p h, --- specialize hno_augmenting_path p, --- exact hno_augmenting_path, --- end, --- rfl⟩ - --- lemma s_t_not_connected {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (S : finset V) (hS : S = mk_cut_set rsn) : --- ∀ u ∈ S, ∀ v ∈ (V' \ S), ¬ rsn.is_edge u v := --- begin --- intros u uInS v vInT is_edge_u_v, --- rw hS at *, --- unfold mk_cut_set at *, --- simp only [set.mem_to_finset, set.mem_set_of_eq, mem_sdiff, mem_univ, true_and] at *, --- apply exists.elim uInS, --- intros p _, --- have tmp := path.cons p is_edge_u_v, --- apply vInT, --- exact exists.intro tmp trivial, --- end - --- lemma residual_capacity_zero {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (ct : cut V) --- (h_eq_network : rsn.afn.network = ct.network) --- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, ¬ rsn.is_edge u v) : --- ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 := --- begin --- intros u uInS v vInT, --- specialize h u uInS v vInT, --- rw rsn.is_edge_def at h, --- simp only [not_lt] at h, --- have hge := residual_capacity_non_neg rsn u v, --- exact ge_antisymm hge h, --- end - --- lemma min_max_cap_flow {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (ct : cut V) --- (h_eq_network : rsn.afn.network = ct.network) --- (h: ∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.f' u v = 0 ) : --- (∀ u ∈ ct.S, ∀ v ∈ ct.T, rsn.afn.f u v = rsn.afn.network.c u v) ∧ --- (∀ u ∈ ct.T, ∀ v ∈ ct.S, rsn.afn.f u v = 0) := --- begin --- split, --- { intros u uInS v vInT, --- specialize h u uInS v vInT, --- rw rsn.f_def at h, --- unfold mk_rsf at h, --- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), --- cases foo, --- { simp only [foo, if_true] at h, --- linarith, }, --- { simp only [foo, if_false, ite_eq_right_iff] at h, --- have bar := rsn.afn.network.vanishes u v foo, --- rw bar, --- clear foo h, --- have baz := rsn.afn.non_neg_flow u v, --- have bark := rsn.afn.no_overflow u v, --- linarith, }, }, --- { intros v vInT u uInS, --- specialize h u uInS v vInT, --- rw rsn.f_def at h, --- unfold mk_rsf at h, --- have foo := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge u v), --- cases foo, --- { have bark := rsn.afn.network.nonsymmetric u v, --- simp only [not_and] at bark, --- specialize bark foo, --- have bar := rsn.afn.non_neg_flow v u, --- have baz := rsn.afn.no_overflow v u, --- have blurg := rsn.afn.network.vanishes v u bark, --- linarith, }, --- { simp only [foo, if_false, ite_eq_right_iff] at h, --- clear foo, --- have bar := classical.em (rsn.afn.network.to_capacity.to_digraph.is_edge v u), --- cases bar, --- { exact h bar, }, --- { have blurg := rsn.afn.non_neg_flow v u, --- have bark := rsn.afn.no_overflow v u, --- have baz := rsn.afn.network.vanishes v u bar, --- linarith, }, }, } --- end - --- lemma f_value_eq_out {V : Type*} [inst' : fintype V] --- (ct : cut V) --- (afn : active_flow_network V) --- (h_eq_network : afn.network = ct.network) --- (h : (∀ u ∈ ct.T, ∀ v ∈ ct.S, afn.f u v = 0)) : --- F_value afn = mk_out afn.f ct.S := --- begin --- dsimp [F_value], --- rw flow_value_source_in_S afn ct h_eq_network, --- dsimp [mk_in], --- simp_rw [← ct.Tcomp], --- simp only [sub_eq_self], --- have sum_eq_sum_zero : ∑ (x : V) in ct.T, ∑ y in ct.S, (afn.f x y) = --- ∑ x in ct.T, ∑ y in ct.S, 0 := --- begin --- apply finset.sum_congr rfl, --- intros x xInT, --- apply finset.sum_congr rfl, --- intros y yInS, --- exact h x xInT y yInS, --- end, --- rw sum_eq_sum_zero, --- simp only [sum_const_zero], --- end - --- lemma cut_cap_eq_out {V : Type*} [inst' : fintype V] --- (ct : cut V) --- (afn : active_flow_network V) --- (h_eq_network : afn.network = ct.network) --- (h : (∀ u ∈ ct.S, ∀ v ∈ V' \ ct.S, afn.f u v = afn.network.c u v) ∧ --- (∀ u ∈ V' \ ct.S, ∀ v ∈ ct.S, afn.f u v = 0)) : --- mk_out afn.f ct.S = cut_cap ct := --- begin --- cases h with h_flow_eq_cap h_flow_zero, --- dsimp [cut_cap, mk_out], --- apply finset.sum_congr rfl, --- intros x xInS, --- rw ← ct.Tcomp at *, --- apply finset.sum_congr rfl, --- intros y yInT, --- simp [h_eq_network, h_flow_eq_cap x xInS y yInT], --- end - --- lemma eq_on_res_then_on_sum {V : Type*} [inst' : fintype V] --- (A : finset V) (B : finset V) (f : V → V → ℝ) (g : V → V → ℝ) --- (eq_on_res : ∀ u ∈ A, ∀ v ∈ B, f u v = g u v) : --- ∑ (u : V) in A, ∑ (v : V) in B, f u v = ∑ (u : V) in A, ∑ (v : V) in B, g u v := --- begin --- apply finset.sum_congr rfl, --- intros a aInA, --- apply finset.sum_congr rfl, --- intros b bInB, --- exact eq_on_res a aInA b bInB, --- end - --- /-! --- Here is our last big lemma, if there is no augmenting path in the resiual network, then --- there exists a cut with a capacity equal to the value of the active flow in the same network. --- -/ - --- lemma existence_of_a_cut {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) --- (hno_augmenting_path : no_augmenting_path rsn) : --- (∃c : cut V, rsn.afn.network = c.network ∧ cut_cap c = F_value rsn.afn) := --- begin --- let S : finset V := mk_cut_set rsn, --- let T := V' \ S, --- let min_cut := mk_cut_from_S (rsn) (hno_augmenting_path) (S) rfl, --- have same_net : rsn.afn.network = min_cut.network := by refl, --- have subtract: ∀ x y : ℝ, (x=y) ↔ y-x=0 := --- by {intros x y, split, intro heq, linarith, intro heq, linarith}, --- have cf_vanishes_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.f' u v = 0 := --- begin --- intros u uInS v vInNS, --- by_contradiction h, --- have edge: rsn.is_edge u v := --- begin --- by_contradiction h', --- have contr: rsn.f' u v = 0 := --- begin --- rw rsn.is_edge_def at h', --- simp only [not_lt] at h', --- have hge := residual_capacity_non_neg rsn u v, --- exact ge_antisymm hge h', --- end, --- contradiction --- end, --- have notEdge: ¬ rsn.is_edge u v := s_t_not_connected rsn S rfl u uInS v vInNS, --- contradiction --- end, --- have cf_vanishes_on_pipes_spec: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, --- (rsn.afn.network.is_edge u v) → (rsn.afn.network.c u v - rsn.afn.f u v = 0) := --- begin --- intros u uInS v vInT is_edge, --- have h1: mk_rsf rsn.afn u v = rsn.afn.network.c u v - rsn.afn.f u v := --- by {unfold mk_rsf, simp only [is_edge, if_true]}, --- rw ← h1, --- have h2: mk_rsf rsn.afn u v = rsn.f' u v := by {rw rsn.f_def}, --- rw h2, --- exact cf_vanishes_on_pipes u uInS v vInT, --- end, --- have eq_on_pipes: ∀ u ∈ min_cut.S, ∀ v ∈ V' \ min_cut.S, rsn.afn.f u v = --- rsn.afn.network.c u v := --- begin --- intros u uInS v vInT, --- by_cases edge: rsn.afn.network.is_edge u v, --- { have h: rsn.afn.network.to_capacity.c u v - rsn.afn.f u v = 0 := --- cf_vanishes_on_pipes_spec u uInS v vInT edge, --- linarith, }, --- { rw rsn.afn.network.vanishes u v edge, --- exact f_vanishes_outside_edge (rsn.afn) (u) (v) (edge), }, --- end, --- have no_backflow: ∀ (u v : V), (u ∈ V' \ min_cut.S ∧ v ∈ min_cut.S) → rsn.afn.f u v = 0 := --- begin --- intros u v hyp, --- exact (min_max_cap_flow rsn min_cut same_net cf_vanishes_on_pipes).2 u hyp.1 v hyp.2, --- end, --- have cut_eq_flow: cut_cap min_cut = F_value rsn.afn := --- begin --- rw F_value, --- simp only, --- rw flow_value_source_in_S rsn.afn min_cut same_net, --- have no_input : mk_in rsn.afn.f min_cut.S = 0 := --- begin --- rw mk_in, --- exact finset.sum_eq_zero (λ i hi, finset.sum_eq_zero $ λ j hj, no_backflow i j ⟨hi, hj⟩), --- end, --- rw no_input, --- simp only [sub_zero], --- have flow_eq_cap_on_cut : mk_out rsn.afn.f min_cut.S = mk_out rsn.afn.network.c min_cut.S := --- begin --- unfold mk_out, --- rw eq_on_res_then_on_sum --- (min_cut.S) (V' \ min_cut.S) (rsn.afn.f) (rsn.afn.network.to_capacity.c) (eq_on_pipes), --- end, --- rw flow_eq_cap_on_cut, --- refl, --- end, --- use min_cut, --- split, --- {exact same_net}, --- exact cut_eq_flow --- end - --- /-! --- Finally, our biggest result, the max-flow min-cut theorem! --- If a maximum flow exists, its value is equal to the capacity of the min-cut. --- -/ - --- theorem max_flow_min_cut {V : Type*} [inst' : fintype V] --- (rsn : residual_network V) (c: cut V) (same_network: rsn.afn.network = c.network) : --- (is_max_flow rsn.afn ∧ is_min_cut c) → (F_value rsn.afn = cut_cap c) := --- begin --- rintros ⟨max_flow, min_cut⟩ , --- have noAugPath: no_augmenting_path rsn := no_augm_path rsn max_flow, --- have existsCut: ∃cut : cut V, rsn.afn.network = cut.network ∧ --- cut_cap cut = F_value rsn.afn := existence_of_a_cut rsn noAugPath, --- have max_flow_min_cut: ∀ cut : cut V, --- (rsn.afn.network = cut.network ∧ cut_cap cut = F_value rsn.afn) → --- (F_value rsn.afn = cut_cap c) := --- begin --- rintros cut ⟨same_net, eq⟩, --- have h1: is_min_cut cut := min_cut_criterion rsn.afn cut same_net eq, --- have h2: is_min_cut c := min_cut, --- have same_net1: cut.network = c.network := by {rw ← same_network, rw ← same_net}, --- have same_net2: c.network = cut.network := by rw ← same_net1, --- have same_val: cut_cap cut = cut_cap c := --- begin --- have le1: cut_cap cut ≤ cut_cap c := --- by {unfold is_min_cut at h1, exact h1 c same_net1}, --- have le2: cut_cap c ≤ cut_cap cut := --- by {unfold is_min_cut at h2, exact h2 cut same_net2}, --- exact le_antisymm le1 le2, --- end, --- rw ← eq, --- exact same_val, --- end, --- exact exists.elim existsCut max_flow_min_cut, --- end

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�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Ǔ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 literal 0 HcmV?d00001 From 8a6277d17db6ec5e552534b716a1431c23554659 Mon Sep 17 00:00:00 2001 From: Aleksandar Milchev <98773527+amilchew@users.noreply.github.com> Date: Sat, 8 Apr 2023 03:15:00 +0100 Subject: [PATCH 14/28] Delete Max-Flow-Min-Cut-Proof.pdf --- Max-Flow-Min-Cut-Proof.pdf | Bin 144217 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Max-Flow-Min-Cut-Proof.pdf diff --git a/Max-Flow-Min-Cut-Proof.pdf b/Max-Flow-Min-Cut-Proof.pdf deleted file mode 100644 index 9ba8d3272ce4512d934a8d30184cb7bdbacf5c30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144217 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 z zwXs0pIah2X{V@J~BGxP>ePd>Ku1qIqe8sHoZ(RAlrT)u}0lX6jc)gRl#GH`blGJ2t zQsXqmU_Z^@4p6W1bJEiV#EHRpzUFcoyPgfQdj`Sp+#8rJR$s-EYy^H?-SqjMY2#>< z^Kw%o|NQ5g$oY1xq06uVjC##tz$!(~m5LytCj|Gkxzb~MGo?NKavcEObu-<%of>p8 zIg3q+t{sv>QvkMAOss#>T<<9asl>E~CmB#jwH93E%2-@>8bo0#c&%Uyc0ShdfSY2J z1QRZG1&+!(fxruN0+g~pF&BvggS3nFB{qzw zy(vN*r8IK;N$>%Rcfzmk)frH7v@AU!Bf7N6gh^;5n=GY8PIe<%hL?gPkCY=#%%IA? z;?EJ207$V7bRNeExYI(@YK{N{0VAVu;uG?dKpr+cdy4vqW-g<`DLJZ1e6fYqU! zv4KH8W6w*g+dRXs1WcFd+oXa9aEShknV1}k`arQoTtm~IW(FrVSz0XviiXb(5QO#8 zX5yX38tr9UU$mW0)UWv}WO@9;`S~O=w~i*VF-J2tRocV_*=6zUcWbnPMsE)jl*QM=x%tr@Dbk_3J`aVo*vLFNW`N+2zQo(h4t1-+H~&3+o zVp8N<0&Kc-BB>c8M?79Uu5=2ChXgv5xtE%PI<#&HQ7>yoCvX*CtADo=Mc-i;yjf9X z1pQJ6c44L{$u`D8mWTP|CCKiLPt$7I(;H^k|=mk>|_^K1DN1W@a zYvHv8u}V{IbiFD<#o!bTF;W0@Iw38Eef=RxbeP_I$EK9qE%diBcuylAvDSQ_P(uT8 z6=t+&a&NVQ@uz3VwCz~u?3Y7m%VglQL-e(fu*fOVw;rW*ynzLL1npOS%^+d@oEls1 zC;UqA57+vPSnEM*~Ibp+uFd{MA*d0&iMC6?tcx5V!&r$Vq^F} zSB&^99E`00=jwm={~&-Au_<^a6Dk%_iKi0g0nH1v)n_?f`)y+#bj33yT(%u+dR2Fwd?M=7 z>ioTc60d@lM2YOvK?~_O1|XpUMsffELkjNKC&bs)6=I%-d_n`e+ZJkTE38LP{}GXQ z6zX$um&S-0cxbFc=N}k=L_h@%A~6mkG0~^z2LVg`M*DL?3QRu0Gbhdu4P~y+K<A0&8OyJ7D)vTMNJ^2!N21k`na!dyLLfur&w41~%_=cqTXdjDcuH()Sn1Q(({i zwfReJ8rjn}4hrh*?98(_b0c4#x=sNA`MsUH1oTPb8lOT62JwZ3F(1fQ@FV>j=ng34 z)%fvi&0`h$5ZI9qz`YwJnn!>A3Ih*=cm%e~1`e}$1Heg3K8bgq%?AQ;`(h1XPh4$S%zaB|3<+r9zLI2D;ZR8n@1kd=eOH#E>&C| zy}vM#y+78ddp~x?KeBH-#d3dL@;imTyLKwyDS$00~dPGk#2y;J>{Zhd^t;k1ar94KR7BQeRsU_y{mgo z-a6_qP)Hwt3%69}w#kcVF+=Nq3e)&rxAbJ41dZg|)!iOz#h`hi!9Hryw{;=JJ`V