(*<*) theory Szpilrajn imports Main begin (*>*) text ‹ We formalize a more general version of Szpilrajn's extension theorem~\<^cite>‹"Szpilrajn:1930"›, employing the terminology of Bossert and Suzumura~\<^cite>‹"Bossert:2010"›. We also formalize Theorem 2.7 of their book. Our extension theorem states that any preorder can be extended to a total preorder while maintaining its structure. The proof of the extension theorem follows the proof presented in the Wikipedia article~\<^cite>‹Wiki›. › section ‹Definitions› subsection ‹Symmetric and asymmetric factor of a relation› text ‹ According to Bossert and Suzumura, every relation can be partitioned into its symmetric and asymmetric factor. The symmetric factor of a relation \<^term>‹r› contains all pairs \<^term>‹(x, y) ∈ r› where \<^term>‹(y, x) ∈ r›. Conversely, the asymmetric factor contains all pairs where this is not the case. In terms of an order \<^term>‹(≤)›, the asymmetric factor contains all \<^term>‹(x, y) ∈ {(x, y) |x y. x ≤ y}› where \<^term>‹x < y›. › definition sym_factor :: "'a rel ⇒ 'a rel" where "sym_factor r ≡ {(x, y) ∈ r. (y, x) ∈ r}" lemma sym_factor_def': "sym_factor r = r ∩ r¯" unfolding sym_factor_def by fast definition asym_factor :: "'a rel ⇒ 'a rel" where "asym_factor r = {(x, y) ∈ r. (y, x) ∉ r}" subsubsection ‹Properties of the symmetric factor› lemma sym_factorI[intro]: "(x, y) ∈ r ⟹ (y, x) ∈ r ⟹ (x, y) ∈ sym_factor r" unfolding sym_factor_def by blast lemma sym_factorE[elim?]: assumes "(x, y) ∈ sym_factor r" obtains "(x, y) ∈ r" "(y, x) ∈ r" using assms[unfolded sym_factor_def] by blast lemma sym_sym_factor[simp]: "sym (sym_factor r)" unfolding sym_factor_def by (auto intro!: symI) lemma trans_sym_factor[simp]: "trans r ⟹ trans (sym_factor r)" unfolding sym_factor_def' using trans_Int by force lemma refl_on_sym_factor[simp]: "refl_on A r ⟹ refl_on A (sym_factor r)" unfolding sym_factor_def by (auto intro!: refl_onI dest: refl_onD refl_onD1) lemma sym_factor_absorb_if_sym[simp]: "sym r ⟹ sym_factor r = r" unfolding sym_factor_def' by (simp add: sym_conv_converse_eq) lemma sym_factor_idem[simp]: "sym_factor (sym_factor r) = sym_factor r" using sym_factor_absorb_if_sym[OF sym_sym_factor] . lemma sym_factor_reflc[simp]: "sym_factor (r⇧^{=}) = (sym_factor r)⇧^{=}" unfolding sym_factor_def by auto lemma sym_factor_Restr[simp]: "sym_factor (Restr r A) = Restr (sym_factor r) A" unfolding sym_factor_def by blast text ‹ In contrast to \<^term>‹asym_factor›, the \<^term>‹sym_factor› is monotone. › lemma sym_factor_mono: "r ⊆ s ⟹ sym_factor r ⊆ sym_factor s" unfolding sym_factor_def by auto subsubsection ‹Properties of the asymmetric factor› lemma asym_factorI[intro]: "(x, y) ∈ r ⟹ (y, x) ∉ r ⟹ (x, y) ∈ asym_factor r" unfolding asym_factor_def by blast lemma asym_factorE[elim?]: assumes "(x, y) ∈ asym_factor r" obtains "(x, y) ∈ r" using assms unfolding asym_factor_def by blast lemma refl_not_in_asym_factor[simp]: "(x, x) ∉ asym_factor r" unfolding asym_factor_def by blast lemma irrefl_asym_factor[simp]: "irrefl (asym_factor r)" unfolding asym_factor_def irrefl_def by fast lemma asym_asym_factor[simp]: "asym (asym_factor r)" using irrefl_asym_factor by (auto intro!: asymI simp: asym_factor_def) lemma trans_asym_factor[simp]: "trans r ⟹ trans (asym_factor r)" unfolding asym_factor_def trans_def by fast lemma asym_if_irrefl_trans: "irrefl r ⟹ trans r ⟹ asym r" by (intro asymI) (auto simp: irrefl_def trans_def) lemma antisym_if_irrefl_trans: "irrefl r ⟹ trans r ⟹ antisym r" using antisym_def asym_if_irrefl_trans by (auto dest: asymD) lemma asym_factor_asym_rel[simp]: "asym r ⟹ asym_factor r = r" unfolding asym_factor_def by (auto dest: asymD) lemma irrefl_trans_asym_factor_id[simp]: "irrefl r ⟹ trans r ⟹ asym_factor r = r" using asym_factor_asym_rel[OF asym_if_irrefl_trans] . lemma asym_factor_id[simp]: "asym_factor (asym_factor r) = asym_factor r" using asym_factor_asym_rel[OF asym_asym_factor] . lemma asym_factor_rtrancl: "asym_factor (r⇧^{*}) = asym_factor (r⇧^{+})" unfolding asym_factor_def by (auto simp add: rtrancl_eq_or_trancl) lemma asym_factor_Restr[simp]: "asym_factor (Restr r A) = Restr (asym_factor r) A" unfolding asym_factor_def by blast lemma acyclic_asym_factor[simp]: "acyclic r ⟹ acyclic (asym_factor r)" unfolding asym_factor_def by (auto intro: acyclic_subset) subsubsection ‹Relations between symmetric and asymmetric factor› text ‹ We prove that \<^term>‹sym_factor› and \<^term>‹asym_factor› partition the input relation. › lemma sym_asym_factor_Un: "sym_factor r ∪ asym_factor r = r" unfolding sym_factor_def asym_factor_def by blast lemma disjnt_sym_asym_factor[simp]: "disjnt (sym_factor r) (asym_factor r)" unfolding disjnt_def unfolding sym_factor_def asym_factor_def by blast lemma Field_sym_asym_factor_Un: "Field (sym_factor r) ∪ Field (asym_factor r) = Field r" using sym_asym_factor_Un Field_Un by metis lemma asym_factor_tranclE: assumes "(a, b) ∈ (asym_factor r)⇧^{+}" shows "(a, b) ∈ r⇧^{+}" using assms sym_asym_factor_Un by (metis UnCI subsetI trancl_mono) subsection ‹Extension of Orders› text ‹ We use the definition of Bossert and Suzumura for ‹extends›. The requirement \<^term>‹r ⊆ R› is obvious. The second requirement \<^term>‹asym_factor r ⊆ asym_factor R› enforces that the extension \<^term>‹R› maintains all strict preferences of \<^term>‹r› (viewing \<^term>‹r› as a preference relation). › definition extends :: "'a rel ⇒ 'a rel ⇒ bool" where "extends R r ≡ r ⊆ R ∧ asym_factor r ⊆ asym_factor R" text ‹ We define a stronger notion of \<^term>‹extends› where we also demand that \<^term>‹sym_factor R ⊆ (sym_factor r)⇧^{=}›. This enforces that the extension does not introduce preference cycles between previously unrelated pairs \<^term>‹(x, y) ∈ R - r›. › definition strict_extends :: "'a rel ⇒ 'a rel ⇒ bool" where "strict_extends R r ≡ extends R r ∧ sym_factor R ⊆ (sym_factor r)⇧^{=}" lemma extendsI[intro]: "r ⊆ R ⟹ asym_factor r ⊆ asym_factor R ⟹ extends R r" unfolding extends_def by (intro conjI) lemma extendsE: assumes "extends R r" obtains "r ⊆ R" "asym_factor r ⊆ asym_factor R" using assms unfolding extends_def by blast lemma trancl_subs_extends_if_trans: "extends r_ext r ⟹ trans r_ext ⟹ r⇧^{+}⊆ r_ext" unfolding extends_def asym_factor_def by (metis subrelI trancl_id trancl_mono) lemma extends_if_strict_extends: "strict_extends r_ext ext ⟹ extends r_ext ext" unfolding strict_extends_def by blast lemma strict_extendsI[intro]: assumes "r ⊆ R" "asym_factor r ⊆ asym_factor R" "sym_factor R ⊆ (sym_factor r)⇧^{=}" shows "strict_extends R r" unfolding strict_extends_def using assms by (intro conjI extendsI) lemma strict_extendsE: assumes "strict_extends R r" obtains "r ⊆ R" "asym_factor r ⊆ asym_factor R" "sym_factor R ⊆ (sym_factor r)⇧^{=}" using assms extendsE unfolding strict_extends_def by blast lemma strict_extends_antisym_Restr: assumes "strict_extends R r" assumes "antisym (Restr r A)" shows "antisym ((R - r) ∪ Restr r A)" proof(rule antisymI, rule ccontr) fix x y assume "(x, y) ∈ (R - r) ∪ Restr r A" "(y, x) ∈ (R - r) ∪ Restr r A" "x ≠ y" with ‹strict_extends R r› have "(x, y) ∈ sym_factor R" unfolding sym_factor_def by (auto elim!: strict_extendsE) with assms ‹x ≠ y› have "(x, y) ∈ sym_factor r" by (auto elim!: strict_extendsE) then have "(x, y) ∈ r" "(y, x) ∈ r" unfolding sym_factor_def by simp_all with ‹antisym (Restr r A)› ‹x ≠ y› ‹(y, x) ∈ R - r ∪ Restr r A› show False using antisymD by fastforce qed text ‹Here we prove that we have no preference cycles between previously unrelated pairs.› lemma antisym_Diff_if_strict_extends: assumes "strict_extends R r" shows "antisym (R - r)" using strict_extends_antisym_Restr[OF assms, where ?A="{}"] by simp lemma strict_extends_antisym: assumes "strict_extends R r" assumes "antisym r" shows "antisym R" using assms strict_extends_antisym_Restr[OF assms(1), where ?A=UNIV] by (auto elim!: strict_extendsE simp: antisym_def) lemma strict_extends_if_strict_extends_reflc: assumes "strict_extends r_ext (r⇧^{=})" shows "strict_extends r_ext r" proof(intro strict_extendsI) from assms show "r ⊆ r_ext" by (auto elim: strict_extendsE) from assms ‹r ⊆ r_ext› show "asym_factor r ⊆ asym_factor r_ext" unfolding strict_extends_def by (auto simp: asym_factor_def sym_factor_def) from assms show "sym_factor r_ext ⊆ (sym_factor r)⇧^{=}" by (auto simp: sym_factor_def strict_extends_def) qed lemma strict_extends_diff_Id: assumes "irrefl r" "trans r" assumes "strict_extends r_ext (r⇧^{=})" shows "strict_extends (r_ext - Id) r" proof(intro strict_extendsI) from assms show "r ⊆ r_ext - Id" by (auto elim: strict_extendsE simp: irrefl_def) note antisym_r = antisym_if_irrefl_trans[OF assms(1,2)] with assms strict_extends_if_strict_extends_reflc show "asym_factor r ⊆ asym_factor (r_ext - Id)" unfolding asym_factor_def by (auto intro: strict_extends_antisym[THEN antisymD] elim: strict_extendsE transE) from assms antisym_r show "sym_factor (r_ext - Id) ⊆ (sym_factor r)⇧^{=}" unfolding sym_factor_def by (auto intro: strict_extends_antisym[THEN antisymD]) qed text ‹ Both \<^term>‹extends› and \<^term>‹strict_extends› form a partial order since they are reflexive, transitive, and antisymmetric. › lemma shows reflp_extends: "reflp extends" and transp_extends: "transp extends" and antisymp_extends: "antisymp extends" unfolding extends_def reflp_def transp_def antisymp_def by auto lemma shows reflp_strict_extends: "reflp strict_extends" and transp_strict_extends: "transp strict_extends" and antisymp_strict_extends: "antisymp strict_extends" using reflp_extends transp_extends antisymp_extends unfolding strict_extends_def reflp_def transp_def antisymp_def by auto subsection ‹Missing order definitions› lemma preorder_onD[dest?]: assumes "preorder_on A r" shows "refl_on A r" "trans r" using assms unfolding preorder_on_def by blast+ lemma preorder_onI[intro]: "refl_on A r ⟹ trans r ⟹ preorder_on A r" unfolding preorder_on_def by (intro conjI) abbreviation "preorder ≡ preorder_on UNIV" lemma preorder_rtrancl: "preorder (r⇧^{*})" by (intro preorder_onI refl_rtrancl trans_rtrancl) definition "total_preorder_on A r ≡ preorder_on A r ∧ total_on A r" abbreviation "total_preorder r ≡ total_preorder_on UNIV r" lemma total_preorder_onI[intro]: "refl_on A r ⟹ trans r ⟹ total_on A r ⟹ total_preorder_on A r" unfolding total_preorder_on_def by (intro conjI preorder_onI) lemma total_preorder_onD[dest?]: assumes "total_preorder_on A r" shows "refl_on A r" "trans r" "total_on A r" using assms unfolding total_preorder_on_def preorder_on_def by blast+ definition "strict_partial_order r ≡ trans r ∧ irrefl r" lemma strict_partial_orderI[intro]: "trans r ⟹ irrefl r ⟹ strict_partial_order r" unfolding strict_partial_order_def by blast lemma strict_partial_orderD[dest?]: assumes "strict_partial_order r" shows "trans r" "irrefl r" using assms unfolding strict_partial_order_def by blast+ lemma strict_partial_order_acyclic: assumes "strict_partial_order r" shows "acyclic r" by (metis acyclic_irrefl assms strict_partial_order_def trancl_id) abbreviation "partial_order ≡ partial_order_on UNIV" lemma partial_order_onI[intro]: "refl_on A r ⟹ trans r ⟹ antisym r ⟹ partial_order_on A r" using partial_order_on_def by blast lemma linear_order_onI[intro]: "refl_on A r ⟹ trans r ⟹ antisym r ⟹ total_on A r ⟹ linear_order_on A r" using linear_order_on_def by blast lemma linear_order_onD[dest?]: assumes "linear_order_on A r" shows "refl_on A r" "trans r" "antisym r" "total_on A r" using assms[unfolded linear_order_on_def] partial_order_onD by blast+ text ‹A typical example is \<^term>‹(⊂)› on sets:› lemma strict_partial_order_subset: "strict_partial_order {(x,y). x ⊂ y}" proof show "trans {(x,y). x ⊂ y}" by (auto simp add: trans_def) show "irrefl {(x, y). x ⊂ y}" by (simp add: irrefl_def) qed text ‹We already have a definition of a strict linear order in \<^term>‹strict_linear_order›.› section ‹Extending preorders to total preorders› text ‹ We start by proving that a preorder with two incomparable elements \<^term>‹x› and \<^term>‹y› can be strictly extended to a preorder where \<^term>‹x < y›. › lemma can_extend_preorder: assumes "preorder_on A r" and "y ∈ A" "x ∈ A" "(y, x) ∉ r" shows "preorder_on A ((insert (x, y) r)⇧^{+})" "strict_extends ((insert (x, y) r)⇧^{+}) r" proof - note preorder_onD[OF ‹preorder_on A r›] then have "insert (x, y) r ⊆ A × A" using ‹y ∈ A› ‹x ∈ A› refl_on_domain by fast with ‹refl_on A r› show "preorder_on A ((insert (x, y) r)⇧^{+})" by (intro preorder_onI refl_onI trans_trancl) (auto simp: trancl_subset_Sigma intro!: r_into_trancl' dest: refl_onD) show "strict_extends ((insert (x, y) r)⇧^{+}) r" proof(intro strict_extendsI) from preorder_onD(2)[OF ‹preorder_on A r›] ‹(y, x) ∉ r› show "asym_factor r ⊆ asym_factor ((insert (x, y) r)⇧^{+})" unfolding asym_factor_def trancl_insert using rtranclD rtrancl_into_trancl1 r_r_into_trancl by fastforce from assms have "(y, x) ∉ (insert (x, y) r)⇧^{+}" unfolding preorder_on_def trancl_insert using refl_onD rtranclD by fastforce with ‹trans r› show "sym_factor ((insert (x, y) r)⇧^{+}) ⊆ (sym_factor r)⇧^{=}" unfolding trancl_insert sym_factor_def by (fastforce intro: rtrancl_trans) qed auto qed text ‹ With this, we can start the proof of our main extension theorem. For this we will use a variant of Zorns Lemma, which only considers nonempty chains: › lemma Zorns_po_lemma_nonempty: assumes po: "Partial_order r" and u: "⋀C. ⟦C ∈ Chains r; C≠{}⟧ ⟹ ∃u∈Field r. ∀a∈C. (a, u) ∈ r" and "r ≠ {}" shows "∃m∈Field r. ∀a∈Field r. (m, a) ∈ r ⟶ a = m" proof - from ‹r ≠ {}› obtain x where "x ∈ Field r" using FieldI2 by fastforce with assms show ?thesis using Zorns_po_lemma by (metis empty_iff) qed theorem strict_extends_preorder_on: assumes "preorder_on A base_r" shows "∃r. total_preorder_on A r ∧ strict_extends r base_r" proof - text ‹ We define an order on the set of strict extensions of the base relation \<^term>‹base_r›, where \<^term>‹r ≤ s› iff \<^term>‹strict_extends r base_r› and \<^term>‹strict_extends s r›: › define order_of_orders :: "('a rel) rel" where "order_of_orders = Restr {(r, s). strict_extends r base_r ∧ strict_extends s r} {r. preorder_on A r}" text ‹ We show that this order consists of those relations that are preorders and that strictly extend the base relation \<^term>‹base_r› › have Field_order_of_orders: "Field order_of_orders = {r. preorder_on A r ∧ strict_extends r base_r}" using transp_strict_extends proof(safe) fix r assume "preorder_on A r" "strict_extends r base_r" with reflp_strict_extends have "(r, r) ∈ {(r, s). strict_extends r base_r ∧ strict_extends s r}" by (auto elim!: reflpE) with ‹preorder_on A r› show "r ∈ Field order_of_orders" unfolding order_of_orders_def by (auto simp: Field_def) qed (auto simp: order_of_orders_def Field_def elim: transpE) text ‹ We now show that this set has a maximum and that any maximum of this set is a total preorder and as thus is one of the extensions we are looking for. We begin by showing the existence of a maximal element using Zorn's lemma. › have "∃m ∈ Field order_of_orders. ∀a ∈ Field order_of_orders. (m, a) ∈ order_of_orders ⟶ a = m" proof (rule Zorns_po_lemma_nonempty) text ‹ Zorn's Lemma requires us to prove that our \<^term>‹order_of_orders› is a nonempty partial order and that every nonempty chain has an upper bound. The partial order property is trivial, since we used \<^term>‹strict_extends› for the relation, which is a partial order as shown above. › from reflp_strict_extends transp_strict_extends have "Refl {(r, s). strict_extends r base_r ∧ strict_extends s r}" unfolding refl_on_def Field_def by (auto elim: transpE reflpE) moreover have "trans {(r, s). strict_extends r base_r ∧ strict_extends s r}" using transp_strict_extends by (auto elim: transpE intro: transI) moreover have "antisym {(r, s). strict_extends r base_r ∧ strict_extends s r}" using antisymp_strict_extends by (fastforce dest: antisympD intro: antisymI) ultimately show "Partial_order order_of_orders" unfolding order_of_orders_def order_on_defs using Field_order_of_orders Refl_Restr trans_Restr antisym_Restr by blast text ‹Also, our order is obviously not empty since it contains \<^term>‹(base_r, base_r)›:› have "(base_r, base_r) ∈ order_of_orders" unfolding order_of_orders_def using assms reflp_strict_extends by (auto dest: reflpD) thus "order_of_orders ≠ {}" by force text ‹ Next we show that each chain has an upper bound. For the upper bound we take the union of all relations in the chain. › show "∃u ∈ Field order_of_orders. ∀a ∈ C. (a, u) ∈ order_of_orders" if C_def: "C ∈ Chains order_of_orders" and C_nonempty: "C ≠ {}" for C proof (rule bexI[where x="⋃C"]) text ‹ Obviously each element in the chain is a strict extension of \<^term>‹base_r› by definition and as such it is also a preorder. › have preorder_r: "preorder_on A r" and extends_r: "strict_extends r base_r" if "r ∈ C" for r using that C_def[unfolded order_of_orders_def Chains_def] by blast+ text ‹ Because a chain is partially ordered, the union of the chain is reflexive and transitive. › have total_subs_C: "r ⊆ s ∨ s ⊆ r" if "r ∈ C" and "s ∈ C" for r s using C_def that unfolding Chains_def order_of_orders_def strict_extends_def extends_def by blast have preorder_UnC: "preorder_on A (⋃C)" proof(intro preorder_onI) show "refl_on A (⋃C)" using preorder_onD(1)[OF preorder_r] C_nonempty unfolding refl_on_def by auto from total_subs_C show "trans (⋃C)" using chain_subset_trans_Union[unfolded chain_subset_def] by (metis preorder_onD(2)[OF preorder_r]) qed text ‹We show that \<^term>‹⋃C› strictly extends the base relation.› have strict_extends_UnC: "strict_extends (⋃C) base_r" proof(intro strict_extendsI) note extends_r_unfolded = extends_r[unfolded extends_def strict_extends_def] show "base_r ⊆ (⋃C)" using C_nonempty extends_r_unfolded by blast then show "asym_factor base_r ⊆ asym_factor (⋃C)" using extends_r_unfolded unfolding asym_factor_def by auto show "sym_factor (⋃C) ⊆ (sym_factor base_r)⇧^{=}" proof(safe) fix x y assume "(x, y) ∈ sym_factor (⋃C)" "(x, y) ∉ sym_factor base_r" then have "(x, y) ∈ ⋃C" "(y, x) ∈ ⋃C" unfolding sym_factor_def by blast+ with extends_r obtain c where "c ∈ C" "(x, y) ∈ c" "(y, x) ∈ c" "strict_extends c base_r" using total_subs_C by blast then have "(x, y) ∈ sym_factor c" unfolding sym_factor_def by blast with ‹strict_extends c base_r› ‹(x, y) ∉ sym_factor base_r› show "x = y" unfolding strict_extends_def by blast qed qed from preorder_UnC strict_extends_UnC show "(⋃C) ∈ Field order_of_orders" unfolding Field_order_of_orders by simp text ‹ Lastly, we prove by contradiction that \<^term>‹⋃C› is an upper bound for the chain. › show "∀a ∈ C. (a, ⋃C) ∈ order_of_orders" proof(rule ccontr) presume "∃a ∈ C. (a, ⋃C) ∉ order_of_orders" then obtain m where m: "m ∈ C" "(m, ⋃C) ∉ order_of_orders" by blast hence strict_extends_m: "strict_extends m base_r" "preorder_on A m" using extends_r preorder_r by blast+ with m have "¬ strict_extends (⋃C) m" using preorder_UnC unfolding order_of_orders_def by blast from m have "m ⊆ ⋃C" by blast moreover have "sym_factor (⋃C) ⊆ (sym_factor m)⇧^{=}" proof(safe) fix a b assume "(a, b) ∈ sym_factor (⋃ C)" "(a, b) ∉ sym_factor m" then have "(a, b) ∈ sym_factor base_r ∨ (a, b) ∈ Id" using strict_extends_UnC[unfolded strict_extends_def] by blast with ‹(a, b) ∉ sym_factor m› strict_extends_m(1) show "a = b" by (auto elim: strict_extendsE simp: sym_factor_mono[THEN in_mono]) qed ultimately have "¬ asym_factor m ⊆ asym_factor (⋃C)" using ‹¬ strict_extends (⋃C) m› unfolding strict_extends_def extends_def by blast then obtain x y where "(x, y) ∈ m" "(y, x) ∉ m" "(x, y) ∈ asym_factor m" "(x, y) ∉ asym_factor (⋃C)" unfolding asym_factor_def by blast then obtain w where "w ∈ C" "(y, x) ∈ w" unfolding asym_factor_def using ‹m ∈ C› by auto with ‹(y, x) ∉ m› have "¬ extends m w" unfolding extends_def by auto moreover from ‹(x, y) ∈ m› have "¬ extends w m" proof(cases "(x, y) ∈ w") case True with ‹(y, x) ∈ w› have "(x, y) ∉ asym_factor w" unfolding asym_factor_def by simp with ‹(x, y) ∈ asym_factor m› show "¬ extends w m" unfolding extends_def by auto qed (auto simp: extends_def) ultimately show False using ‹m ∈ C› ‹w ∈ C› using C_def[unfolded Chains_def order_of_orders_def strict_extends_def] by auto qed blast qed qed text ‹Let our maximal element be named \<^term>‹max›:› from this obtain max where max_field: "max ∈ Field order_of_orders" and is_max: "∀a∈Field order_of_orders. (max, a) ∈ order_of_orders ⟶ a = max" by auto from max_field have max_extends_base: "preorder_on A max" "strict_extends max base_r" using Field_order_of_orders by blast+ text ‹ We still have to show, that \<^term>‹max› is a strict linear order, meaning that it is also a total order: › have "total_on A max" proof fix x y :: 'a assume "x ≠ y" "x ∈ A" "y ∈ A" show "(x, y) ∈ max ∨ (y, x) ∈ max" proof (rule ccontr) text ‹ Assume that \<^term>‹max› is not total, and \<^term>‹x› and \<^term>‹y› are incomparable. Then we can extend \<^term>‹max› by setting $x < y$: › presume "(x, y) ∉ max" and "(y, x) ∉ max" let ?max' = "(insert (x, y) max)⇧^{+}" note max'_extends_max = can_extend_preorder[OF ‹preorder_on A max› ‹y ∈ A› ‹x ∈ A› ‹(y, x) ∉ max›] hence max'_extends_base: "strict_extends ?max' base_r" using ‹strict_extends max base_r› transp_strict_extends by (auto elim: transpE) text ‹The extended relation is greater than \<^term>‹max›, which is a contradiction.› have "(max, ?max') ∈ order_of_orders" using max'_extends_base max'_extends_max max_extends_base unfolding order_of_orders_def by simp thus False using FieldI2 ‹(x, y) ∉ max› is_max by fastforce qed simp_all qed with ‹preorder_on A max› have "total_preorder_on A max" unfolding total_preorder_on_def by simp with ‹strict_extends max base_r› show "?thesis" by blast qed text ‹ With this extension theorem, we can easily prove Szpilrajn's theorem and its equivalent for partial orders. › corollary partial_order_extension: assumes "partial_order_on A r" shows "∃r_ext. linear_order_on A r_ext ∧ r ⊆ r_ext" proof - from assms strict_extends_preorder_on obtain r_ext where r_ext: "total_preorder_on A r_ext" "strict_extends r_ext r" unfolding partial_order_on_def by blast with assms have "antisym r_ext" unfolding partial_order_on_def using strict_extends_antisym by blast with assms r_ext have "linear_order_on A r_ext ∧ r ⊆ r_ext" unfolding total_preorder_on_def order_on_defs strict_extends_def extends_def by blast then show ?thesis .. qed corollary Szpilrajn: assumes "strict_partial_order r" shows "∃r_ext. strict_linear_order r_ext ∧ r ⊆ r_ext" proof - from assms have "partial_order (r⇧^{=})" by (auto simp: antisym_if_irrefl_trans strict_partial_order_def) from partial_order_extension[OF this] obtain r_ext where "linear_order r_ext" "(r⇧^{=}) ⊆ r_ext" by blast with assms have "r ⊆ r_ext - Id" "strict_linear_order (r_ext - Id)" by (auto simp: irrefl_def strict_linear_order_on_diff_Id dest: strict_partial_orderD(2)) then show ?thesis by blast qed corollary acyclic_order_extension: assumes "acyclic r" shows "∃r_ext. strict_linear_order r_ext ∧ r ⊆ r_ext" proof - from assms have "strict_partial_order (r⇧^{+})" unfolding strict_partial_order_def using acyclic_irrefl trans_trancl by blast thus ?thesis by (meson Szpilrajn r_into_trancl' subset_iff) qed section ‹Consistency› text ‹ As a weakening of transitivity, Suzumura introduces the notion of consistency which rules out all preference cycles that contain at least one strict preference. Consistency characterises those order relations which can be extended (in terms of \<^term>‹extends›) to a total order relation. › definition consistent :: "'a rel ⇒ bool" where "consistent r = (∀(x, y) ∈ r⇧^{+}. (y, x) ∉ asym_factor r)" lemma consistentI: "(⋀x y. (x, y) ∈ r⇧^{+}⟹ (y, x) ∉ asym_factor r) ⟹ consistent r" unfolding consistent_def by blast lemma consistent_if_preorder_on[simp]: "preorder_on A r ⟹ consistent r" unfolding preorder_on_def consistent_def asym_factor_def by auto lemma consistent_asym_factor[simp]: "consistent r ⟹ consistent (asym_factor r)" unfolding consistent_def using asym_factor_tranclE by fastforce lemma acyclic_asym_factor_if_consistent[simp]: "consistent r ⟹ acyclic (asym_factor r)" unfolding consistent_def acyclic_def using asym_factor_tranclE by (metis case_prodD trancl.simps) lemma consistent_Restr[simp]: "consistent r ⟹ consistent (Restr r A)" unfolding consistent_def asym_factor_def using trancl_mono by fastforce text ‹ This corresponds to Theorem 2.2~\<^cite>‹"Bossert:2010"›. › theorem trans_if_refl_total_consistent: assumes "refl r" "total r" and "consistent r" shows "trans r" proof fix x y z assume "(x, y) ∈ r" "(y, z) ∈ r" from ‹(x, y) ∈ r› ‹(y, z) ∈ r› have "(x, z) ∈ r⇧^{+}" by simp hence "(z, x) ∉ asym_factor r" using ‹consistent r› unfolding consistent_def by blast hence "x ≠ z ⟹ (x, z) ∈ r" unfolding asym_factor_def using ‹total r› by (auto simp: total_on_def) then show "(x, z) ∈ r" apply(cases "x = z") using refl_onD[OF ‹refl r›] by blast+ qed lemma order_extension_if_consistent: assumes "consistent r" obtains r_ext where "extends r_ext r" "total_preorder r_ext" proof - from assms have extends: "extends (r⇧^{*}) r" unfolding extends_def consistent_def asym_factor_def using rtranclD by (fastforce simp: Field_def) have preorder: "preorder (r⇧^{*})" unfolding preorder_on_def using refl_on_def trans_def by fastforce from strict_extends_preorder_on[OF preorder] extends obtain r_ext where "total_preorder r_ext" "extends r_ext r" using transpE[OF transp_extends] unfolding strict_extends_def by blast then show thesis using that by blast qed lemma consistent_if_extends_trans: assumes "extends r_ext r" "trans r_ext" shows "consistent r" proof(rule consistentI, standard) fix x y assume *: "(x, y) ∈ r⇧^{+}" "(y, x) ∈ asym_factor r" with assms have "(x, y) ∈ r_ext" using trancl_subs_extends_if_trans[OF assms] by blast moreover from * assms have "(x, y) ∉ r_ext" unfolding extends_def asym_factor_def by auto ultimately show False by blast qed text ‹ With Theorem 2.6~\<^cite>‹"Bossert:2010"›, we show that \<^term>‹consistent› characterises the existence of order extensions. › corollary order_extension_iff_consistent: "(∃r_ext. extends r_ext r ∧ total_preorder r_ext) ⟷ consistent r" using order_extension_if_consistent consistent_if_extends_trans by (metis total_preorder_onD(2)) text ‹ The following theorem corresponds to Theorem 2.7~\<^cite>‹"Bossert:2010"›. Bossert and Suzumura claim that this theorem generalises Szpilrajn's theorem; however, we cannot use the theorem to strictly extend a given order \<^term>‹Q›. Therefore, it is not strong enough to extend a strict partial order to a strict linear order. It works for total preorders (called orderings by Bossert and Suzumura). Unfortunately, we were not able to generalise the theorem to allow for strict extensions. › theorem general_order_extension_iff_consistent: assumes "⋀x y. ⟦ x ∈ S; y ∈ S; x ≠ y ⟧ ⟹ (x, y) ∉ Q⇧^{+}" assumes "total_preorder_on S Ord" shows "(∃Ext. extends Ext Q ∧ total_preorder Ext ∧ Restr Ext S = Ord) ⟷ consistent Q" (is "?ExExt ⟷ _") proof assume "?ExExt" then obtain Ext where "extends Ext Q" "refl Ext" "trans Ext" "total Ext" "Restr Ext S = Restr Ord S" using total_preorder_onD by fast show "consistent Q" proof(rule consistentI) fix x y assume "(x, y) ∈ Q⇧^{+}" with ‹extends Ext Q› ‹trans Ext› have "(x, y) ∈ Ext" unfolding extends_def by (metis trancl_id trancl_mono) then have "(y, x) ∉ asym_factor Ext" unfolding asym_factor_def by blast with ‹extends Ext Q› show "(y, x) ∉ asym_factor Q" unfolding extends_def asym_factor_def by blast qed next assume "consistent Q" define Q' where "Q' ≡ Q⇧^{*}∪ Ord ∪ Ord O Q⇧^{*}∪ Q⇧^{*}O Ord ∪ (Q⇧^{*}O Ord) O Q⇧^{*}" have "refl (Q⇧^{*})" "trans (Q⇧^{*})" "refl_on S Ord" "trans Ord" "total_on S Ord" using refl_rtrancl trans_rtrancl total_preorder_onD[OF ‹total_preorder_on S Ord›] by - assumption have preorder_Q': "preorder Q'" proof show "refl Q'" unfolding Q'_def refl_on_def by auto from ‹trans (Q⇧^{*})› ‹refl_on S Ord› ‹trans Ord› show "trans Q'" unfolding Q'_def[simplified] apply(safe intro!: transI) unfolding relcomp.simps by (metis assms(1) refl_on_domain rtranclD transD)+ qed have "consistent Q'" using consistent_if_preorder_on preorder_Q' by blast have "extends Q' Q" proof(rule extendsI) have "Q ⊆ Restr (Q⇧^{*}) (Field Q)" by (auto intro: FieldI1 FieldI2) then show "Q ⊆ Q'" unfolding Q'_def by blast from ‹consistent Q› have consistentD: "(x, y) ∈ Q⇧^{+}⟹ (y, x) ∈ Q ⟹ (x, y) ∈ Q" for x y unfolding consistent_def asym_factor_def using rtranclD by fastforce have refl_on_domainE: "⟦ (x, y) ∈ Ord; x ∈ S ⟹ y ∈ S ⟹ P ⟧ ⟹ P" for x y P using refl_on_domain[OF ‹refl_on S Ord›] by blast show "asym_factor Q ⊆ asym_factor Q'" unfolding Q'_def asym_factor_def Field_def apply(safe) using assms(1) consistentD refl_on_domainE by (metis r_into_rtrancl rtranclD rtrancl_trancl_trancl)+ qed with strict_extends_preorder_on[OF ‹preorder Q'›] obtain Ext where Ext: "extends Ext Q'" "extends Ext Q" "total_preorder Ext" unfolding strict_extends_def by (metis transpE transp_extends) have not_in_Q': "x ∈ S ⟹ y ∈ S ⟹ (x, y) ∉ Ord ⟹ (x, y) ∉ Q'" for x y using assms(1) unfolding Q'_def apply(safe) by (metis ‹refl_on S Ord› refl_on_def refl_on_domain rtranclD)+ have "Restr Ext S = Ord" proof from ‹extends Ext Q'› have "Ord ⊆ Ext" unfolding Q'_def extends_def by auto with ‹refl_on S Ord› show "Ord ⊆ Restr Ext S" using refl_on_domain by fast next have "(x, y) ∈ Ord" if "x ∈ S" and "y ∈ S" and "(x, y) ∈ Ext" for x y proof(rule ccontr) assume "(x, y) ∉ Ord" with that not_in_Q' have "(x, y) ∉ Q'" by blast with ‹refl_on S Ord› ‹total_on S Ord› ‹x ∈ S› ‹y ∈ S› ‹(x, y) ∉ Ord› have "(y, x) ∈ Ord" unfolding refl_on_def total_on_def by fast hence "(y, x) ∈ Q'" unfolding Q'_def by blast with ‹(x, y) ∉ Q'› ‹(y, x) ∈ Q'› ‹extends Ext Q'› have "(x, y) ∉ Ext" unfolding extends_def asym_factor_def by auto with ‹(x, y) ∈ Ext› show False by blast qed then show "Restr Ext S ⊆ Ord" by blast qed with Ext show "?ExExt" by blast qed section ‹Strong consistency› text ‹ We define a stronger version of \<^term>‹consistent› which requires that the relation does not contain hidden preference cycles, i.e. if there is a preference cycle then all the elements in the cycle should already be related (in both directions). In contrast to consistency which characterises relations that can be extended, strong consistency characterises relations that can be extended strictly (cf. \<^term>‹strict_extends›). › definition "strongly_consistent r ≡ sym_factor (r⇧^{+}) ⊆ sym_factor (r⇧^{=})" lemma consistent_if_strongly_consistent: "strongly_consistent r ⟹ consistent r" unfolding strongly_consistent_def consistent_def by (auto simp: sym_factor_def asym_factor_def) lemma strongly_consistentI: "sym_factor (r⇧^{+}) ⊆ sym_factor (r⇧^{=}) ⟹ strongly_consistent r" unfolding strongly_consistent_def by blast lemma strongly_consistent_if_trans_strict_extension: assumes "strict_extends r_ext r" assumes "trans r_ext" shows "strongly_consistent r" proof(unfold strongly_consistent_def, standard) fix x assume "x ∈ sym_factor (r⇧^{+})" then show "x ∈ sym_factor (r⇧^{=})" using assms trancl_subs_extends_if_trans[OF extends_if_strict_extends] by (metis sym_factor_mono strict_extendsE subsetD sym_factor_reflc) qed lemma strict_order_extension_if_consistent: assumes "strongly_consistent r" obtains r_ext where "strict_extends r_ext r" "total_preorder r_ext" proof - from assms have "strict_extends (r⇧^{+}) r" unfolding strongly_consistent_def strict_extends_def extends_def asym_factor_def sym_factor_def by (auto simp: Field_def dest: tranclD) moreover have "strict_extends (r⇧^{*}) (r⇧^{+})" unfolding strict_extends_def extends_def by (auto simp: asym_factor_rtrancl sym_factor_def dest: rtranclD) ultimately have extends: "strict_extends (r⇧^{*}) r" using transpE[OF transp_strict_extends] by blast have "preorder (r⇧^{*})" unfolding preorder_on_def using refl_on_def trans_def by fastforce from strict_extends_preorder_on[OF this] extends obtain r_ext where "total_preorder r_ext" "strict_extends r_ext r" using transpE[OF transp_strict_extends] by blast then show thesis using that by blast qed experiment begin text ‹We can instantiate the above theorem to get Szpilrajn's theorem.› lemma assumes "strict_partial_order r" shows "∃r_ext. strict_linear_order r_ext ∧ r ⊆ r_ext" proof - from assms[unfolded strict_partial_order_def] have "strongly_consistent r" "antisym r" unfolding strongly_consistent_def by (simp_all add: antisym_if_irrefl_trans) from strict_order_extension_if_consistent[OF this(1)] obtain r_ext where "strict_extends r_ext r" "total_preorder r_ext" by blast with assms[unfolded strict_partial_order_def] have "trans (r_ext - Id)" "irrefl (r_ext - Id)" "total (r_ext - Id)" "r ⊆ (r_ext - Id)" using strict_extends_antisym[OF _ ‹antisym r›] by (auto simp: irrefl_def elim: strict_extendsE intro: trans_diff_Id dest: total_preorder_onD) then show ?thesis unfolding strict_linear_order_on_def by blast qed end (*<*) end (*>*)