section ‹The Theorem of Farkas, Minkowsky and Weyl› text ‹We prove the theorem of Farkas, Minkowsky and Weyl that a cone is finitely generated iff it is polyhedral. Moreover, we provide quantative bounds via determinant bounds.› theory Farkas_Minkowsky_Weyl imports Fundamental_Theorem_Linear_Inequalities begin context gram_schmidt begin text ‹We first prove the one direction of the theorem for the case that the span of the vectors is the full n-dimensional space.› lemma farkas_minkowsky_weyl_theorem_1_full_dim: assumes X: "X ⊆ carrier_vec n" and fin: "finite X" and span: "span X = carrier_vec n" shows "∃ nr A. A ∈ carrier_mat nr n ∧ cone X = polyhedral_cone A ∧ (is_det_bound db ⟶ X ⊆ ℤ⇩_{v}∩ Bounded_vec (of_int Bnd) ⟶ A ∈ ℤ⇩_{m}∩ Bounded_mat (of_int (db (n-1) Bnd)))" proof - define cond where "cond = (λ W. Suc (card W) = n ∧ lin_indpt W ∧ W ⊆ X)" let ?oi = "of_int :: int ⇒ 'a" { fix W assume "cond W" hence *: "finite W" "Suc (card W) = n" "lin_indpt W" "W ⊆ carrier_vec n" and WX: "W ⊆ X" unfolding cond_def using finite_subset[OF _ fin] X by auto note nv = normal_vector[OF *] hence "normal_vector W ∈ carrier_vec n" "⋀ w. w ∈ W ⟹ normal_vector W ∙ w = 0" "normal_vector W ≠ 0⇩_{v}n" "is_det_bound db ⟹ X ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd) ⟹ normal_vector W ∈ ℤ⇩_{v}∩ Bounded_vec (?oi (db (n - 1) Bnd))" using WX by blast+ } note condD = this define Ns where "Ns = { normal_vector W | W. cond W ∧ (∀ w ∈ X. normal_vector W ∙ w ≥ 0) } ∪ { - normal_vector W | W. cond W ∧ (∀ w ∈ X. (- normal_vector W) ∙ w ≥ 0)}" have "Ns ⊆ normal_vector ` {W . W ⊆ X} ∪ (λ W. - normal_vector W) ` {W. W ⊆ X}" unfolding Ns_def cond_def by blast moreover have "finite …" using ‹finite X› by auto ultimately have "finite Ns" by (metis finite_subset) from finite_list[OF this] obtain ns where ns: "set ns = Ns" by auto have Ns: "Ns ⊆ carrier_vec n" unfolding Ns_def using condD by auto define A where "A = mat_of_rows n ns" define nr where "nr = length ns" have A: "- A ∈ carrier_mat nr n" unfolding A_def nr_def by auto show ?thesis proof (intro exI conjI impI, rule A) have not_conj: "¬ (a ∧ b) ⟷ (a ⟶ ¬ b)" for a b by auto have id: "Ns = { nv . ∃ W. W ⊆ X ∧ nv ∈ {normal_vector W, - normal_vector W} ∧ Suc (card W) = n ∧ lin_indpt W ∧ (∀a⇩_{i}∈X. 0 ≤ nv ∙ a⇩_{i})}" unfolding Ns_def cond_def by auto have "polyhedral_cone (- A) = { b. b ∈ carrier_vec n ∧ (- A) *⇩_{v}b ≤ 0⇩_{v}nr}" unfolding polyhedral_cone_def using A by auto also have "… = {b. b ∈ carrier_vec n ∧ (∀ i < nr. row (- A) i ∙ b ≤ 0)}" unfolding less_eq_vec_def using A by auto also have "… = {b. b ∈ carrier_vec n ∧ (∀ i < nr. - (ns ! i) ∙ b ≤ 0)}" using A Ns[folded ns] by (intro Collect_cong conj_cong refl all_cong arg_cong[of _ _ "λ x. x ∙ _ ≤ _"], force simp: A_def mat_of_rows_def nr_def set_conv_nth) also have "… = {b. b ∈ carrier_vec n ∧ (∀ n ∈ Ns. - n ∙ b ≤ 0)}" unfolding ns[symmetric] nr_def by (auto simp: set_conv_nth) also have "… = {b. b ∈ carrier_vec n ∧ (∀ n ∈ Ns. n ∙ b ≥ 0)}" by (intro Collect_cong conj_cong refl ball_cong, insert Ns, auto) also have "… = cone X" unfolding fundamental_theorem_of_linear_inequalities_full_dim(2)[OF X fin span] by (intro Collect_cong conj_cong refl, unfold not_le[symmetric] not_ex not_conj not_not id, blast) finally show "cone X = polyhedral_cone (- A)" .. { assume XI: "X ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd)" and db: "is_det_bound db" { fix v assume "v ∈ set (rows (- A))" hence "-v ∈ set (rows A)" unfolding rows_def by auto hence "-v ∈ Ns" unfolding A_def using ns Ns by auto from this[unfolded Ns_def] obtain W where cW: "cond W" and v: "-v = normal_vector W ∨ v = normal_vector W" by auto from cW[unfolded cond_def] have WX: "W ⊆ X" by auto from v have v: "v = normal_vector W ∨ v = - normal_vector W" by (metis uminus_uminus_vec) from condD(4)[OF cW db XI] have "normal_vector W ∈ ℤ⇩_{v}∩ Bounded_vec (?oi (db (n - 1) Bnd))" by auto hence "v ∈ ℤ⇩_{v}∩ Bounded_vec (?oi (db (n - 1) Bnd))" using v by auto } hence "set (rows (- A)) ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi (db (n - 1) Bnd))" by blast thus "- A ∈ ℤ⇩_{m}∩ Bounded_mat (?oi (db (n - 1) Bnd))" by simp } qed qed text ‹We next generalize the theorem to the case where X does not span the full space. To this end, we extend X by unit-vectors until the full space is spanned, and then add the normal-vectors of these unit-vectors which are orthogonal to span X as additional constraints to the resulting matrix.› lemma farkas_minkowsky_weyl_theorem_1: assumes X: "X ⊆ carrier_vec n" and finX: "finite X" shows "∃ nr A. A ∈ carrier_mat nr n ∧ cone X = polyhedral_cone A ∧ (is_det_bound db ⟶ X ⊆ ℤ⇩_{v}∩ Bounded_vec (of_int Bnd) ⟶ A ∈ ℤ⇩_{m}∩ Bounded_mat (of_int (db (n-1) (max 1 Bnd))))" proof - let ?oi = "of_int :: int ⇒ 'a" from exists_lin_indpt_sublist[OF X] obtain Ls where lin_Ls: "lin_indpt_list Ls" and spanL: "span (set Ls) = span X" and LX: "set Ls ⊆ X" by auto define Ns where "Ns = normal_vectors Ls" define Bs where "Bs = basis_extension Ls" from basis_extension[OF lin_Ls, folded Bs_def] have BU: "set Bs ⊆ set (unit_vecs n)" and lin_Ls_Bs: "lin_indpt_list (Ls @ Bs)" and len_Ls_Bs: "length (Ls @ Bs) = n" by auto note nv = normal_vectors[OF lin_Ls, folded Ns_def] from nv(1-6) nv(7)[of db Bnd] have N: "set Ns ⊆ carrier_vec n" and LN': "lin_indpt_list (Ls @ Ns)" "length (Ls @ Ns) = n" and ortho: "⋀ l w. l ∈ set Ls ⟹ w ∈ set Ns ⟹ w ∙ l = 0" and Ns_bnd: "is_det_bound db ⟹ set Ls ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd) ⟹ set Ns ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi (db (n-1) (max 1 Bnd)))" by auto from lin_indpt_list_length_eq_n[OF LN'] have spanLN: "span (set Ls ∪ set Ns) = carrier_vec n" by auto let ?Bnd = "Bounded_vec (?oi (db (n-1) (max 1 Bnd)))" let ?Bndm = "Bounded_mat (?oi (db (n-1) (max 1 Bnd)))" define Y where "Y = X ∪ set Bs" from lin_Ls_Bs[unfolded lin_indpt_list_def] have Ls: "set Ls ⊆ carrier_vec n" and Bs: "set Bs ⊆ carrier_vec n" and distLsBs: "distinct (Ls @ Bs)" and lin': "lin_indpt (set (Ls @ Bs))" by auto have LN: "set Ls ∩ set Ns = {}" proof (rule ccontr) assume "¬ ?thesis" then obtain x where xX: "x ∈ set Ls" and xW: "x ∈ set Ns" by auto from ortho[OF xX xW] have "x ∙ x = 0" by auto hence "sq_norm x = 0" by (auto simp: sq_norm_vec_as_cscalar_prod) with xX LX X have "x = 0⇩_{v}n" by auto with vs_zero_lin_dep[OF _ lin'] Ls Bs xX show False by auto qed have Y: "Y ⊆ carrier_vec n" using X Bs unfolding Y_def by auto have CLB: "carrier_vec n = span (set (Ls @ Bs))" using lin_Ls_Bs len_Ls_Bs lin_indpt_list_length_eq_n by blast also have "… ⊆ span Y" by (rule span_is_monotone, insert LX, auto simp: Y_def) finally have span: "span Y = carrier_vec n" using Y by auto have finY: "finite Y" using finX unfolding Y_def by auto from farkas_minkowsky_weyl_theorem_1_full_dim[OF Y finY span] obtain A nr where A: "A ∈ carrier_mat nr n" and YA: "cone Y = polyhedral_cone A" and Y_Ints: "is_det_bound db ⟹ Y ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi (max 1 Bnd)) ⟹ A ∈ ℤ⇩_{m}∩ ?Bndm" by blast have fin: "finite ({row A i | i. i < nr} ∪ set Ns ∪ uminus ` set Ns)" by auto from finite_list[OF this] obtain rs where rs_def: "set rs = {row A i |i. i < nr} ∪ set Ns ∪ uminus ` set Ns" by auto from A N have rs: "set rs ⊆ carrier_vec n" unfolding rs_def by auto let ?m = "length rs" define B where "B = mat_of_rows n rs" have B: "B ∈ carrier_mat ?m n" unfolding B_def by auto show ?thesis proof (intro exI conjI impI, rule B) have id: "(∀r∈{rs ! i |i. i < ?m}. P r) = (∀ r < ?m. P (rs ! r))" for P by auto have "polyhedral_cone B = { x ∈ carrier_vec n. B *⇩_{v}x ≤ 0⇩_{v}?m}" unfolding polyhedral_cone_def using B by auto also have "… = { x ∈ carrier_vec n. ∀ i < ?m. row B i ∙ x ≤ 0}" unfolding less_eq_vec_def using B by auto also have "… = { x ∈ carrier_vec n. ∀ r ∈ set rs. r ∙ x ≤ 0}" using rs unfolding set_conv_nth id by (intro Collect_cong conj_cong refl all_cong arg_cong[of _ _ "λ x. x ∙ _ ≤ 0"], auto simp: B_def) also have "… = {x ∈ carrier_vec n. ∀ i < nr. row A i ∙ x ≤ 0} ∩ {x ∈ carrier_vec n. ∀ w ∈ set Ns ∪ uminus ` set Ns. w ∙ x ≤ 0}" unfolding rs_def by blast also have "{x ∈ carrier_vec n. ∀ i < nr. row A i ∙ x ≤ 0} = polyhedral_cone A" unfolding polyhedral_cone_def using A by (auto simp: less_eq_vec_def) also have "… = cone Y" unfolding YA .. also have "{x ∈ carrier_vec n. ∀ w ∈ set Ns ∪ uminus ` set Ns. w ∙ x ≤ 0} = {x ∈ carrier_vec n. ∀ w ∈ set Ns. w ∙ x = 0}" (is "?l = ?r") proof show "?r ⊆ ?l" using N by auto { fix x w assume "x ∈ ?l" "w ∈ set Ns" with N have x: "x ∈ carrier_vec n" and w: "w ∈ carrier_vec n" and one: "w ∙ x ≤ 0" and two: "(-w) ∙ x ≤ 0" by auto from two have "w ∙ x ≥ 0" by (subst (asm) scalar_prod_uminus_left, insert w x, auto) with one have "w ∙ x = 0" by auto } thus "?l ⊆ ?r" by blast qed finally have "polyhedral_cone B = cone Y ∩ {x ∈ carrier_vec n. ∀w∈set Ns. w ∙ x = 0}" . also have "… = cone X" unfolding Y_def by (rule orthogonal_cone(1)[OF X N finX spanLN ortho refl spanL LX lin_Ls_Bs len_Ls_Bs]) finally show "cone X = polyhedral_cone B" .. assume X_I: "X ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd)" and db: "is_det_bound db" with LX have "set Ls ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd)" by auto from Ns_bnd[OF db this] have N_I_Bnd: "set Ns ⊆ ℤ⇩_{v}∩ ?Bnd" by auto from lin_Ls_Bs have linLs: "lin_indpt_list Ls" unfolding lin_indpt_list_def using subset_li_is_li[of _ "set Ls"] by auto from X_I LX have L_I: "set Ls ⊆ ℤ⇩_{v}" by auto have Y_I: "Y ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi (max 1 Bnd))" unfolding Y_def using X_I order.trans[OF BU unit_vec_int_bounds, of Bnd] Bounded_vec_mono[of "?oi Bnd" "?oi (max 1 Bnd)"] by auto from Y_Ints[OF db Y_I] have A_I_Bnd: "set (rows A) ⊆ ℤ⇩_{v}∩ ?Bnd" by auto have "set (rows B) = set (rows (mat_of_rows n rs))" unfolding B_def by auto also have "… = set rs" using rs by auto also have "… = set (rows A) ∪ set Ns ∪ uminus ` set Ns" unfolding rs_def rows_def using A by auto also have "… ⊆ ℤ⇩_{v}∩ ?Bnd" using A_I_Bnd N_I_Bnd by auto finally show "B ∈ ℤ⇩_{m}∩ ?Bndm" by simp qed qed text ‹Now for the other direction.› lemma farkas_minkowsky_weyl_theorem_2: assumes A: "A ∈ carrier_mat nr n" shows "∃ X. X ⊆ carrier_vec n ∧ finite X ∧ polyhedral_cone A = cone X ∧ (is_det_bound db ⟶ A ∈ ℤ⇩_{m}∩ Bounded_mat (of_int Bnd) ⟶ X ⊆ ℤ⇩_{v}∩ Bounded_vec (of_int (db (n-1) (max 1 Bnd))))" proof - let ?oi = "of_int :: int ⇒ 'a" let ?rows_A = "{row A i | i. i < nr}" let ?Bnd = "Bounded_vec (?oi (db (n-1) (max 1 Bnd)))" have rows_A_n: "?rows_A ⊆ carrier_vec n" using row_carrier_vec A by auto hence "∃ mr B. B ∈ carrier_mat mr n ∧ cone ?rows_A = polyhedral_cone B ∧ (is_det_bound db ⟶ ?rows_A ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd) ⟶ set (rows B) ⊆ ℤ⇩_{v}∩ ?Bnd)" using farkas_minkowsky_weyl_theorem_1[of ?rows_A] by auto then obtain mr B where mr: "B ∈ carrier_mat mr n" and B: "cone ?rows_A = polyhedral_cone B" and Bnd: "is_det_bound db ⟹ ?rows_A ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd) ⟹ set (rows B) ⊆ ℤ⇩_{v}∩ ?Bnd" by blast let ?rows_B = "{row B i | i. i < mr}" have rows_B: "?rows_B ⊆ carrier_vec n" using mr by auto have "cone ?rows_B = polyhedral_cone A" proof have "?rows_B ⊆ polyhedral_cone A" proof fix r assume "r ∈ ?rows_B" then obtain j where r: "r = row B j" and j: "j < mr" by auto then have rn: "r ∈ carrier_vec n" using mr row_carrier by auto moreover have "A *⇩_{v}r ≤ 0⇩_{v}nr" unfolding less_eq_vec_def proof (standard, unfold index_zero_vec) show "dim_vec (A *⇩_{v}r) = nr" using A by auto next show "∀i< nr. (A *⇩_{v}r) $ i ≤ 0⇩_{v}nr $ i" proof (standard, rule impI) fix i assume i: "i < nr" then have "row A i ∈ ?rows_A" by auto then have "row A i ∈ cone ?rows_A" using set_in_cone rows_A_n by blast then have "row A i ∈ polyhedral_cone B" using B by auto then have Br: "B *⇩_{v}(row A i) ≤ 0⇩_{v}mr" unfolding polyhedral_cone_def using rows_A_n mr by auto then have "(A *⇩_{v}r) $ i = (row A i) ∙ r" using A i index_mult_mat_vec by auto also have "… = r ∙ (row A i)" using comm_scalar_prod[OF _ rn] row_carrier A by auto also have "… = (row B j) ∙ (row A i)" using r by auto also have "… = (B *⇩_{v}(row A i)) $ j" using index_mult_mat_vec mr j by auto also have "… ≤ 0" using Br j unfolding less_eq_vec_def by auto also have "… = 0⇩_{v}nr $ i" using i by auto finally show "(A *⇩_{v}r) $ i ≤ 0⇩_{v}nr $ i" by auto qed qed then show "r ∈ polyhedral_cone A" unfolding polyhedral_cone_def using A rn by auto qed then show "cone ?rows_B ⊆ polyhedral_cone A" using cone_in_polyhedral_cone A by auto next show "polyhedral_cone A ⊆ cone ?rows_B" proof (rule ccontr) assume "¬ polyhedral_cone A ⊆ cone ?rows_B" then obtain y where yA: "y ∈ polyhedral_cone A" and yB: "y ∉ cone ?rows_B" by auto then have yn: "y ∈ carrier_vec n" unfolding polyhedral_cone_def by auto have finRB: "finite ?rows_B" by auto from farkas_minkowsky_weyl_theorem_1[OF rows_B finRB] obtain nr' A' where A': "A' ∈ carrier_mat nr' n" and cone: "cone ?rows_B = polyhedral_cone A'" by blast from yB[unfolded cone polyhedral_cone_def] yn A' have "¬ (A' *⇩_{v}y ≤ 0⇩_{v}nr')" by auto then obtain i where i: "i < nr'" and "row A' i ∙ y > 0" unfolding less_eq_vec_def using A' yn by auto define w where "w = row A' i" have w: "w ∈ carrier_vec n" using i A' yn unfolding w_def by auto from ‹row A' i ∙ y > 0› comm_scalar_prod[OF w yn] have wy: "w ∙ y > 0" "y ∙ w > 0" unfolding w_def by auto { fix b assume "b ∈ ?rows_B" hence "b ∈ cone ?rows_B" using set_in_cone[OF rows_B] by auto from this[unfolded cone polyhedral_cone_def] A' have b: "b ∈ carrier_vec n" and "A' *⇩_{v}b ≤ 0⇩_{v}nr'" by auto from this(2)[unfolded less_eq_vec_def, THEN conjunct2, rule_format, of i] have "w ∙ b ≤ 0" unfolding w_def using i A' by auto hence "b ∙ w ≤ 0" using comm_scalar_prod[OF b w] by auto } hence wA: "w ∈ cone ?rows_A" unfolding B polyhedral_cone_def using mr w by (auto simp: less_eq_vec_def) from wy have yw: "-y ∙ w < 0" by (subst scalar_prod_uminus_left, insert yn w, auto) have "?rows_A ⊆ carrier_vec n" "finite ?rows_A" using assms by auto from fundamental_theorem_of_linear_inequalities_A_imp_D[OF this wA, unfolded not_ex, rule_format, of "-y" ] yn yw obtain i where i: "i < nr" and "- y ∙ row A i < 0" by auto hence "y ∙ row A i > 0" by (subst (asm) scalar_prod_uminus_left, insert i assms yn, auto) hence "row A i ∙ y > 0" using comm_scalar_prod[OF _ yn, of "row A i"] i assms yn by auto with yA show False unfolding polyhedral_cone_def less_eq_vec_def using i assms by auto qed qed moreover have "?rows_B ⊆ carrier_vec n" using row_carrier_vec mr by auto moreover have "finite ?rows_B" by auto moreover { have rA: "set (rows A) = ?rows_A" using A unfolding rows_def by auto have rB: "set (rows B) = ?rows_B" using mr unfolding rows_def by auto assume "A ∈ ℤ⇩_{m}∩ Bounded_mat (?oi Bnd)" and db: "is_det_bound db" hence "set (rows A) ⊆ ℤ⇩_{v}∩ Bounded_vec (?oi Bnd)" by simp from Bnd[OF db this[unfolded rA]] have "?rows_B ⊆ ℤ⇩_{v}∩ ?Bnd" unfolding rA rB . } ultimately show ?thesis by blast qed lemma farkas_minkowsky_weyl_theorem: "(∃ X. X ⊆ carrier_vec n ∧ finite X ∧ P = cone X) ⟷ (∃ A nr. A ∈ carrier_mat nr n ∧ P = polyhedral_cone A)" using farkas_minkowsky_weyl_theorem_1 farkas_minkowsky_weyl_theorem_2 by metis end end