Theory Tarski_Euclidean_2D

(* IsaGeoCoq - Tarski_Euclidean_2D.thy

Port part of GeoCoq 3.4.0 (https://geocoq.github.io/GeoCoq/) in Isabelle/Hol 

Copyright (C) 2021-2025  Roland Coghetto roland.coghetto (at) cafr-msa2p.be

License: LGPL

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*)

theory Tarski_Euclidean_2D

imports
  Tarski_Neutral
  Tarski_Postulate_Parallels
  Tarski_Euclidean
  Tarski_Neutral_2D

begin

section "Tarski Euclidean 2D"

subsection "Tarski's axiom system for Euclidean 2D"

locale Tarski_Euclidean_2D = Tarski_Euclidean +
  assumes upper_dim: " a b c p q.
                      p  q 
                      Cong a p a q 
                      Cong b p b q 
                      Cong c p c q
                      
                      (Bet a b c  Bet b c a  Bet c a b)"

sublocale Tarski_Euclidean_2D  Tarski_neutral_2D
proof 
  show " a b c p q.
                      p  q 
                      Cong a p a q 
                      Cong b p b q 
                      Cong c p c q
                      
                      (Bet a b c  Bet b c a  Bet c a b)" 
    using upper_dim by blast
qed

context Tarski_Euclidean_2D

begin

subsection "Definitions"

subsection "Propositions"

lemma l12_16_2D:
  assumes "A1 A2 Par B1 B2" and
    "X Inter A1 A2 C1 C2"
  shows " Y. Y Inter B1 B2 C1 C2" 
proof -
  have "Coplanar B1 B2 C1 C2" 
    using all_coplanar by blast
  thus ?thesis 
    using l12_16 using assms(1) assms(2) by blast
qed

lemma par_inter:
  assumes "A B Par C D" and
    "¬ A B Par P Q"
  shows " Y. Col P Q Y  Col C D Y" 
  using all_coplanar assms(1) assms(2) cop_par__inter by blast

lemma not_par_inter:
  assumes "¬  A B Par A' B'" 
  shows " P. Col P X Y  (Col P A B  Col P A' B')" 
proof -
  have "Coplanar A B X Y" 
    by (simp add: all_coplanar)
  moreover
  have "Coplanar A' B' X Y" 
    by (simp add: all_coplanar)
  ultimately
  show ?thesis 
    by (simp add: assms cop2_npar__inter)
qed

lemma par_perp__perp: 
  assumes "A B Par C D" and
    "A B Perp P Q" 
  shows "C D Perp P Q" 
  using all_coplanar assms(1) assms(2) cop_par_perp__perp by blast

lemma par_perp2__par:
  assumes "A B Par C D" and
    "A B Perp E F" and
    "C D Perp G H"
  shows "E F Par G H" 
  using all_coplanar assms(1) assms(2) assms(3) cop4_par_perp2__par by blast

lemma perp3__perp:
  assumes "A B Perp B C" and
    "B C Perp C D" and
    "C D Perp D A" 
  shows "D A Perp A B" 
proof -
  have "Coplanar A B C D" 
    by (simp add: all_coplanar)
  thus ?thesis 
    using assms(1) assms(2) assms(3) cop_perp3__perp by blast
qed

lemma perp3__rect:
  assumes "A B Perp B C" and
    "B C Perp C D" and
    "C D Perp D A"
  shows "Rectangle A B C D" 
proof -
  have "Coplanar A B C D" 
    by (simp add: all_coplanar)
  thus ?thesis  
    using assms(1) assms(2) assms(3) cop_perp3__rect by blast
qed

lemma projp_is_project:
  assumes "P P' Projp A B"
  shows " X Y. P P' Proj A B X Y" 
proof -
  have "A  B" 
    using Projp_def assms by blast
  moreover
  then obtain X Y where "A B Perp X Y" 
    using perp_vector by blast
  have "X  Y" 
    using A B Perp X Y perp_not_eq_2 by auto
  moreover have "¬ A B Par X Y" 
    by (simp add: A B Perp X Y perp_not_par)
  moreover have "Col A B P'" 
    using Projp_def assms by fastforce
  moreover have "(P P' Par X Y)  P = P'" 
    by (metis Projp_def A B Perp X Y assms par_perp2__par par_reflexivity)
  ultimately show ?thesis 
    using Proj_def by blast
qed

lemma projp_is_project_perp:
  assumes "P P' Projp A B" 
  shows " X Y. P P' Proj A B X Y  A B Perp X Y" 
proof -
  have "A  B" 
    using Projp_def assms by blast
  moreover
  then obtain X Y where "A B Perp X Y" 
    using perp_vector by blast
  moreover
  have "X  Y" 
    using A B Perp X Y perp_not_eq_2 by auto
  moreover have "¬ A B Par X Y" 
    by (simp add: A B Perp X Y perp_not_par)
  moreover have "Col A B P'" 
    using Projp_def assms by fastforce
  moreover have "(P P' Par X Y)  P = P'" 
    by (metis Projp_def A B Perp X Y assms par_perp2__par par_reflexivity)
  ultimately show ?thesis 
    using Proj_def by blast
qed

lemma projp_to_project:
  assumes "A B Perp X Y" and
    "P P' Projp A B"
  shows "P P' Proj A B X Y" 
proof -
  have "A  B" 
    using assms(1) perp_distinct by auto
  moreover have "X  Y" 
    using assms(1) perp_distinct by blast
  moreover have "¬ A B Par X Y" 
    by (simp add: A B Perp X Y perp_not_par)
  moreover have "Col A B P'" 
    using Projp_def assms(2) by fastforce
  moreover have "(P P' Par X Y)  P = P'" 
    by (metis Projp_def A B Perp X Y assms(2) par_perp2__par par_reflexivity)
  ultimately show ?thesis 
    using Proj_def by blast
qed

lemma project_to_projp:
  assumes "P P' Proj A B X Y" and
    "A B Perp X Y" 
  shows "P P' Projp A B" 
proof -
  have "A  B" 
    using assms(2) perp_not_eq_1 by auto
  moreover have "Col A B P'" 
    using Proj_def assms(1) by force
  moreover
  {
    assume "P P' Par X Y"
    have "Col A B P'" 
      using calculation(2) by blast
    moreover have "A B Perp P P'" 
      using Perp_cases P P' Par X Y assms(2) par_perp__perp par_symmetry by blast
    ultimately have "Col A B P'  A B Perp P P'" 
      by blast
  }
  ultimately show ?thesis 
    using Proj_def Projp_def assms(1) by auto
qed

lemma projp_project_to_perp:
  assumes "P  P'" and
    "P P' Projp A B" and 
    "P P' Proj A B X Y"
  shows "A B Perp X Y" 
  by (metis Perp_perm Projp_def assms(1) assms(2) assms(3) par_perp__perp project_par_dir)

lemma project_par_project:
  assumes "P P' Proj A B X Y" and
    "X Y Par X' Y'"
  shows "P P' Proj A B X' Y'" 
  by (metis Proj_def assms(1) assms(2) not_par_one_not_par par_neq2 par_symmetry)


lemma project_project_par :
  assumes "P  P'" and
    "P P' Proj A B X Y" and
    "P P' Proj A B X' Y'"
  shows "X Y Par X' Y'" 
proof -
  have "P P' Par X Y  ?thesis" 
    using assms(1) assms(3) par_not_par par_symmetry project_par_dir by blast
  thus ?thesis 
    using assms(1) assms(2) project_par_dir by blast
qed

lemma projp_preserves_bet:
  assumes "Bet A B C" and
    "A A' Projp X Y" and
    "B B' Projp X Y" and
    "C C' Projp X Y"
  shows "Bet A' B' C'" 
proof -
  obtain T U where "A A' Proj X Y T U" and "X Y Perp T U" 
    using assms(2) projp_is_project_perp by blast
  thus ?thesis 
    using assms(1) assms(3) assms(4) project_preserves_bet projp_to_project by blast
qed

lemma projp_preserves_eqv:
  assumes "A B EqV C D" and
    "A A' Projp X Y" and
    "B B' Projp X Y" and
    "C C' Projp X Y" and
    "D D' Projp X Y"
  shows "A' B' EqV C' D'" 
proof -
  obtain T U where "A A' Proj X Y T U" and "X Y Perp T U" 
    using assms(2) projp_is_project_perp by blast
  thus ?thesis 
    using assms(1) assms(3) assms(4) assms(5) project_preserves_eqv projp_to_project by blast
qed

lemma projp2_col:
  assumes "P A Projp B C" and
    "Q A Projp B C"
  shows "Col A P Q" 
proof -
  {
    assume "Col B C A" and "B C Perp P A" 
    {
      assume "Col B C A" and "B C Perp Q A"
      have ?thesis 
      proof (rule perp2__col [where ?A="B" and ?B="C"])
        show "A P Perp B C"   
          using Perp_cases B C Perp P A by auto
        show "A Q Perp B C"
          using Perp_perm B C Perp Q A by blast
      qed
    }
    moreover
    have "Col B C Q  Q = A  ?thesis" 
      by (simp add: col_trivial_3)
    ultimately have ?thesis 
      using Projp_def assms(2) by force
  }
  moreover have "Col B C P  P = A  ?thesis" 
    by (simp add: col_trivial_1)
  ultimately show ?thesis 
    using Projp_def assms(1) by force
qed

lemma projp_projp_perp:
  assumes "P1  P2" and
    "P1 P Projp Q1 Q2" and
    "P2 P Projp Q1 Q2" 
  shows "P1 P2 Perp Q1 Q2" 
proof -
  have "Col P1 P P2" 
    by (metis Col_cases Perp_cases Projp_def assms(2) assms(3) not_col_distincts perp2__col)
  thus ?thesis 
    by (metis Perp_cases Projp_def assms(1) assms(2) assms(3) not_col_distincts perp_col2_bis)
qed

lemma perp_projp2_eq:
  assumes "A A' Projp C D" and 
    "B B' Projp C D" and
    "A B Perp C D"
  shows "A' = B'" 
proof -
  {
    assume "Col C D A'" and "C D Perp A A'"
    {
      assume "Col C D B'" and "C D Perp B B'" 
      {
        assume "¬ Col A B C" 
        have "Col A B A'" 
          using Perp_cases C D Perp A A' assms(3) perp2__col by blast
        moreover have "Col A B B'" 
          using Col_cases Perp_cases C D Perp B B' assms(3) perp2__col by meson
        ultimately have "A' = B'" 
          using Col C D A' Col C D B' assms(3) l8_14_1 perp_col4 by blast
      }
      moreover {
        assume "¬ Col A B D" 
        have "Col A B A'" 
          using Perp_cases C D Perp A A' assms(3) perp2__col by blast
        moreover have "Col A B B'" 
          using Col_cases Perp_cases C D Perp B B' assms(3) perp2__col by meson
        ultimately have  "A' = B'" 
          using Col C D A' Col C D B' assms(3) perp_col0 perp_not_col2 by blast
      }
      ultimately have ?thesis 
        using assms(3) perp_not_col2 by blast
    }
    moreover have "Col C D B  B = B'  ?thesis" 
      using Perp_cases C D Perp A A' Col C D A' assms(3) l8_18_uniqueness by blast
    ultimately have ?thesis 
      using Projp_def assms(2) by force
  }
  moreover have "Col C D A  A = A' ?thesis" 
    by (metis Perp_cases Projp_def assms(2) assms(3) l8_18_uniqueness perp_not_col2)
  ultimately show ?thesis 
    using Projp_def assms(1) by force
qed

lemma col_par_projp2_eq:
  assumes "Col L11 L12 P" and
    "L11 L12 Par L21 L22" and
    "P P' Projp L21 L22" and
    "P' P'' Projp L11 L12" 
  shows "P = P''" 
proof -
  {
    assume "Col L21 L22 P'" and "L21 L22 Perp P P'" and
      "Col L11 L12 P''" and "L11 L12 Perp P' P''"
    have "P P' Par P' P''" 
      using Par_cases L11 L12 Perp P' P'' L21 L22 Perp P P' assms(2) 
        par_perp2__par by blast
    have "¬ Col L11 L12 P'  ?thesis" 
      by (metis Par_perm Perp_perm Col L11 L12 P'' L11 L12 Perp P' P'' 
          L21 L22 Perp P P' assms(1) assms(2) l8_18_uniqueness par_perp__perp)
    moreover have "¬ Col L11 L12 P''  ?thesis" 
      using Col L11 L12 P'' by blast
    ultimately have "P = P''" 
      using perp_not_col2 L11 L12 Perp P' P'' by blast
  }
  thus ?thesis 
    by (metis Projp_def assms(1) assms(2) assms(3) assms(4) col_not_col_not_par 
        col_projp_eq par_symmetry)
qed

lemma col_2_par_projp2_cong:
  assumes "Col L11 L12 A'" and
    "Col L11 L12 B'" and
    "L11 L12 Par L21 L22" and
    "A' A Projp L21 L22" and
    "B' B Projp L21 L22"
  shows "Cong A B A' B'" 
proof -
  {
    assume "L11 L12 ParStrict L21 L22" 
    {
      assume "A'  B'" 
      {
        assume "A  B"
        have "L11 L12 ParStrict A B" 
          using A  B L11 L12 ParStrict L21 L22 assms(4) assms(5) 
            par_strict_col2_par_strict projp_col by blast
        hence "A B ParStrict B' A'" 
          by (metis Par_strict_cases A'  B' assms(1) assms(2) par_strict_col2_par_strict)
        moreover have "A A' Par B B'" 
          by (metis Par_perm Projp_def L11 L12 ParStrict L21 L22 
              assms(1) assms(2) assms(3) assms(4) assms(5) not_strict_par2 
              par_perp2__par par_perp__perp par_strict_not_col_4)
        ultimately have "Plg A B B' A'" 
          by (simp add: pars_par_plg)
        hence ?thesis 
          using Plg_perm plg_cong_2 plg_to_parallelogram by blast
      }
      moreover {
        assume "A = B"
        hence "Col A A' B'" 
          using assms(4) assms(5) projp2_col by auto
        moreover have "Col L21 L22 A" 
          using assms(4) projp_col by blast
        ultimately have False using l6_21 
          by (metis A'  B' L11 L12 ParStrict L21 L22 
              assms(1) assms(2) col_trivial_2 not_col_permutation_1 par_not_col)
      }
      ultimately have ?thesis 
        by blast
    }
    hence ?thesis 
      using assms(4) assms(5) cong_trivial_identity projp_id by blast
  }
  thus ?thesis 
    by (metis Par_cases assms(1) assms(2) assms(3) assms(4) assms(5) col_projp_eq 
        cong_reflexivity par_not_col_strict par_strict_symmetry)
qed

lemma project_existence:
  assumes "X   Y"
and "A  B"
and "¬ X Y Par A B"
shows " P'. P P' Proj A B X Y" 
proof -
  obtain x x0 where "x  x0" and "X Y Par x x0" and "Col P x x0"
    by (metis assms(1) not_col_distincts par_distincts parallel_existence1) 
  have "¬ x x0 Par A B"
    using X Y Par x x0 assms(3) par_not_par by blast 
  then obtain P' where "Col P' x x0" and "Col P' A B" 
    using not_par_inter_exists ¬ x x0 Par A B by blast 
  hence "P P' Proj A B X Y"
    by (metis Proj_def Col P x x0 X Y Par x x0 assms(1) assms(2) assms(3) 
not_col_permutation_2 par_col2_par par_symmetry) 
  thus ?thesis
    by auto 
qed

lemma sum_exists:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A"
    and "Col PO E B"
  shows " C. Sum PO E E' A B C" 
proof -
  have "PO  E"
    using col_trivial_1 grid_ok by blast  
  have "PO  E'"
    using col_trivial_3 grid_ok by auto
  show ?thesis 
  proof (cases)
    assume "PO = A"
    thus ?thesis
      by (metis Ar2_def Pj_def Sum_def PO  E assms(3) col_trivial_3 grid_ok not_par_not_col) 
  next
    assume "PO  A"
    obtain A' where "A A' Proj PO E' E E'" 
      using project_existence by (metis Par_cases PO  E' col_trivial_2 grid_ok par_id_2) 
    obtain P where "PO E Par A' P"
      using PO  E parallel_existence1 by presburger
    have "A  A'"
      by (metis NCol_cases Proj_def A A' Proj PO E' E E' PO  A assms(2) 
          col_transitivity_1 grid_ok) 
    show ?thesis 
    proof (cases)
      assume "B = PO"
      have "Sum PO E E' A PO A" 
      proof (unfold Sum_def, standard)
        show "Ar2 PO E E' A PO A"
          using Ar2_def B = PO assms(3) assms(2) grid_ok by blast 
        show "A' C'. E E' Pj A A'  Col PO E' A'  PO E Pj A' C'  PO E' Pj PO C'  E' E Pj C' A"
        proof -
          have "E E' Pj A A'"
            using Pj_def A A' Proj PO E' E E' par_symmetry project_par_dir by blast 
          moreover have "Col PO E' A'"
            using Proj_def A A' Proj PO E' E E' by auto 
          moreover have "PO E Pj A' A'"
            by (simp add: Pj_def) 
          moreover have "PO E' Pj PO A'"
            using Pj_def PO  E' calculation(2) not_par_not_col by blast 
          moreover have "E' E Pj A' A"
            using Par_cases Pj_def calculation(1) by auto 
          ultimately show ?thesis 
            by blast
        qed
      qed
      thus ?thesis
        using B = PO by auto 
    next
      assume "B  PO"
      have " C'. B C' Proj A' P PO E'"
        by (metis PO E Par A' P PO  E' grid_ok not_par_one_not_par par_distincts 
            par_id_3 project_existence) 
      then obtain C' where "B C' Proj A' P PO E'" 
        by blast
      have " C. C' C Proj PO E A A'"
        by (metis Proj_def A A' Proj PO E' E E' A  A' PO  E col_par_par_col 
            col_trivial_3 grid_ok par_left_comm project_existence) 
      then obtain C where "C' C Proj PO E A A'"
        by blast
      have "Sum PO E E' A B C"
      proof (unfold Sum_def, rule+)
        show "Ar2 PO E E' A B C"
          using Ar2_def Proj_def C' C Proj PO E A A' assms(3) assms(2) grid_ok by presburger 
        show "A' C'. E E' Pj A A'  Col PO E' A'  PO E Pj A' C'  PO E' Pj B C'  E' E Pj C' C" 
        proof (intro exI conjI)
          let ?A' = "A'" and ?C'1 = "C'"
          show "E E' Pj A ?A'"
            using Pj_def A A' Proj PO E' E E' par_symmetry project_par_dir by blast 
          show "Col PO E' ?A'"
            using Proj_def A A' Proj PO E' E E' by presburger 
          show "PO E Pj ?A' ?C'1"
            by (metis Pj_def Proj_def B C' Proj A' P PO E' PO E Par A' P par_col_par) 
          show "PO E' Pj B ?C'1"
            using Pj_def B C' Proj A' P PO E' par_symmetry project_par_dir by blast 
          show "E' E Pj ?C'1 C"
            by (metis Par_perm Pj_def Proj_def C' C Proj PO E A A' E E' Pj A A' par_trans) 
        qed
      qed
      thus ?thesis 
        by blast
    qed
  qed
qed

lemma opp_exists:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A"
  shows " MA. Opp PO E E' A MA" 
proof (cases)
  assume "A = PO" 
  thus ?thesis
    by (metis Ar2_def Opp_def Pj_def Sum_def col_trivial_3 grid_ok) 
next
  assume "A  PO"
  obtain MA where "Bet A PO MA" and "Cong PO MA A PO"
    using segment_construction by blast 
  show ?thesis 
  proof (unfold Opp_def, rule exI[of _ "MA"], intro sump_to_sum, unfold Sump_def, rule conjI)
    show "Col PO E MA"
      by (metis Col_def not_col_distincts A  PO  MA A  PO assms 
          between_symmetry not_par_not_col par_col_par par_id) 
    have "A' C' P'. MA A' Proj PO E' E E'  PO E Par A' P'  A C' Proj A' P' PO E'  
                     C' PO Proj PO E E E'" 
    proof -
      obtain A' where "MA A' Proj PO E' E E'"
        by (metis col_trivial_2 col_trivial_3 grid_ok par_comm par_id_4 project_existence)
      have "PO  E"
        using col_trivial_1 grid_ok by force 
      then obtain P' where "PO E Par A' P'"
        using parallel_existence1 by presburger 
      obtain C' where "A C' Proj A' P' PO E'"
        by (metis Col_def PO E Par A' P' between_trivial grid_ok 
            not_par_one_not_par par_distincts par_id project_existence) 
      show ?thesis 
      proof (rule exI[of _ "A'"], rule exI[of _ "C'"], rule exI[of _ "P'"],
          intro conjI, simp add: MA A' Proj PO E' E E', simp add: PO E Par A' P', 
          simp add: A C' Proj A' P' PO E')
        show "C' PO Proj PO E E E'" 
        proof (unfold Proj_def, intro conjI, simp add: PO  E)
          show "E  E'"
            using grid_ok not_col_distincts by presburger 
          show "¬ PO E Par E E'"
            using grid_ok not_col_distincts not_strict_par by blast 
          show "Col PO E PO"
            using not_col_distincts by blast 
          have "C' PO Par E E'" 
          proof -
            have "PO E' Par PO A'"
              by (metis (full_types) Par_cases Proj_def A  PO  MA A  PO 
                  Col PO E MA Cong PO MA A PO MA A' Proj PO E' E E' ¬ PO E Par E E' 
                  bet_cong_eq not_par_not_col par_not_par) 
            have "Plg A C' A' PO" 
            proof (rule pars_par_plg)
              show "A C' ParStrict A' PO"
              proof -
                {
                  assume "A C' Par PO E'"
                  hence "A C' Par A' PO"
                    by (meson PO E' Par PO A' par_right_comm par_trans) 
                  {
                    assume "A C' ParStrict A' PO'"
                    hence ?thesis
                      by (metis Col_cases Par_def A C' Par A' PO col2__eq par_strict_not_col_1) 
                  }
                  moreover {
                    assume "A  C'  A'  PO  Col A A' PO  Col C' A' PO"
                    hence False
                      by (metis A  PO PO E' Par PO A' assms col2__eq 
                          col_permutation_4 col_permutation_5 grid_ok par_id_1) 
                  }
                  ultimately have ?thesis
                    using Par_def A C' Par A' PO by blast
                }
                moreover {
                  assume "A = C'"
                  hence False
                    by (metis A = C' A C' Proj A' P' PO E' Col PO E PO 
                        PO E Par A' P' PO E' Par PO A' PO  E assms grid_ok not_strict_par1 
                        par_col2_par_bis par_id_3 project_col) 
                }
                ultimately show ?thesis
                  using Proj_def A C' Proj A' P' PO E' by fastforce 
              qed
              have "PO A Par A' C'" 
              proof (rule par_col_par [of _ _ _ _ "P'"])
                show "A'  C'"
                  using A C' ParStrict A' PO col_trivial_1 par_strict_not_col_2 by blast 
                show "PO A Par A' P'"
                  using A  PO PO E Par A' P' assms par_col_par_2 by auto 
                show "Col A' P' C'"
                  using Proj_def A C' Proj A' P' PO E' by auto 
              qed
              thus "A PO Par C' A'"
                using par_comm by blast 
            qed
            have "Parallelogram A PO MA PO"
              by (metis Bet_cases Cong_cases A  PO  MA A  PO Cong PO MA A PO 
                  bet_col1 between_cong_3 between_equality_2 between_trivial col_par 
                  par_cong_plg_2 plg_bet1 point_construction_different) 
            hence "Parallelogram C' A' MA PO"
              by (metis Plg_perm Plg A C' A' PO parallelogram_equiv_plg plg_pseudo_trans) 
            hence "C' A' Par MA PO  C' PO Par A' MA"
              by (metis par_distincts A  PO Col PO E MA PO E' Par PO A' 
                  PO  E Parallelogram A PO MA PO grid_ok not_par_not_col par_col_par 
                  par_id_3 plg_par plg_permut) 
            thus ?thesis
              by (metis Par_cases par_distincts MA A' Proj PO E' E E' 
                  not_par_one_not_par project_par_dir) 
          qed
          thus "C' PO Par E E'  C' = PO" 
            by simp
        qed
      qed
    qed
    thus "Col PO E A  
          (A' C' P'. MA A' Proj PO E' E E'  PO E Par A' P'  A C' Proj A' P' PO E'  
                      C' PO Proj PO E E E')" 
      using assms by blast
  qed
qed

lemma sum_A_O:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A"
  shows "Sum PO E E' A PO A" 
proof (unfold Sum_def,rule conjI)
  show "Ar2 PO E E' A PO A"
    by (simp add: Ar2_def assms(2) col_trivial_3 grid_ok) 
  have "PO  E"
    using grid_ok not_col_distincts by auto 
  have "E  E'"
    using col_trivial_2 grid_ok by blast 
  show "A' C'. E E' Pj A A'  Col PO E' A'  PO E Pj A' C'  PO E' Pj PO C'  E' E Pj C' A"
  proof (cases)
    assume "PO = A"
    thus ?thesis
      using not_col_distincts pj_trivial by blast 
  next
    assume "PO  A"
    have "¬ E E' Par PO E'"
      using grid_ok par_comm par_id_4 by blast
    have " ¬ A PO Par E' E"
      by (meson Par_cases assms col_trivial_1 grid_ok not_col_permutation_4 
          par_trans parallel_uniqueness) 
    then obtain A' where "A A' Proj PO E' E E'" 
      using project_existence [of A PO E' E E'] by (metis E  E' ¬ E E' Par PO E' 
          col_trivial_3 grid_ok project_existence)
    hence "E E' Pj A A'"
      using Pj_def par_symmetry project_par_dir by blast 
    moreover have "Col PO E' A'"
      using Proj_def A A' Proj PO E' E E' by presburger 
    moreover have "PO E Pj A' A'"
      by (simp add: pj_trivial) 
    moreover have "PO E' Pj PO A'"
      using Pj_def calculation(2) grid_ok not_col_distincts not_par_not_col by blast 
    moreover have "E' E Pj A' A"
      using Pj_def calculation(1) par_comm by blast 
    ultimately show ?thesis
      by blast 
  qed
qed

lemma sum_O_B:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E B"
  shows "Sum PO E E' PO B B"
  by (metis Ar2_def Pj_def Sum_def assms grid_ok not_col_distincts not_par_not_col) 

lemma opp0_uniqueness:
  assumes grid_ok: "¬ Col PO E E'"
    and "Opp PO E E' PO M"
  shows "M = PO"
  by (meson Ar2_def Opp_def Sum_def assms sum_A_O sum_uniqueness)

lemma proj_pars:
  assumes grid_ok: "¬ Col PO E E'"
    and "A  PO"
    and "Col PO E A"
    and "PO E Par A' C'"
    and "A A' Proj PO E' E E'"
  shows "PO E ParStrict A' C'" 
proof (unfold ParStrict_def, rule+)
  show "Coplanar PO E A' C'"
    by (simp add: all_coplanar) 
  have "¬ Col PO E E'"
    by (simp add: grid_ok) 
  show "X. Col X PO E  Col X A' C'" 
  proof (rule ccontr, safe)
    fix X
    assume "¬ False" and "Col X PO E" and "Col X A' C'"
    show False 
    proof (cases)
      assume "PO = A'"
      thus ?thesis
        by (metis Par_def Proj_def assms(2) assms(3) assms(5) col_permutation_2 
            grid_ok par_strict_not_col_1) 
    next
      assume "PO  A'"
      hence False 
        by (metis Proj_def Col X A' C' Col X PO E assms(4) assms(5) 
            col_permutation_1 col_transitivity_2 grid_ok not_strict_par) 
      thus ?thesis 
        by simp
    qed
  qed
qed

lemma sum_O_B_eq:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' PO B C"
  shows "B = C"
  by (metis Ar2_def Sum_def assms sum_O_B sum_uniqueness) 

lemma sum_A_O_eq:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A PO C"
  shows "A = C"
  by (metis Ar2_def Sum_def assms sum_A_O sum_uniqueness)

lemma sum_A_B_A:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B A"
  shows "B = PO" 
proof -
  obtain A' C' where "E E' Pj A A'" and "Col PO E' A'" and "PO E Pj A' C'" and 
    "PO E' Pj B C'" and "E' E Pj C' A" 
    using Sum_def assms by blast 
  show ?thesis
  proof (cases)
    assume "A = PO"
    thus ?thesis
      using assms sum_O_B_eq by blast 
  next
    assume "A  PO"
    hence "A'  PO  (PO E ParStrict A' C'  B = PO)"
      using Sum_def Col PO E' A' E E' Pj A A' E' E Pj C' A PO E Pj A' C' 
        PO E' Pj B C' assms(2) grid_ok sum_par_strict by blast
    moreover {
      assume "PO E ParStrict A' C'" and "B  PO"
      hence "A A' Par A C'"
        by (metis Ar2_def NCol_perm Par_cases Par_strict_cases Pj_def Sum_def 
            E E' Pj A A' E' E Pj C' A assms(2) par_strict_not_col_2 par_trans) 
      hence False
        by (metis Ar2_def Sum_def PO E ParStrict A' C' assms(2) not_strict_par1 
            par_id_2 par_strict_not_col_1 par_strict_par) 
    }
    ultimately show ?thesis
      by blast
  qed
qed

lemma sum_A_B_B:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B B"
  shows "A = PO" 
proof -
  obtain A' C' where "E E' Pj A A'" and "Col PO E' A'" and "PO E Pj A' C'" and 
    "PO E' Pj B C'" and "E' E Pj C' B" 
    using Sum_def assms by blast 
  show ?thesis
  proof (cases)
    assume "A = PO"
    thus ?thesis
      using assms sum_O_B_eq by blast 
  next
    assume "A  PO"
    hence "A'  PO  (PO E' ParStrict B C'  B = C')"
      by (metis NCol_perm Par_def Pj_def Sum_def E E' Pj A A' E' E Pj C' B 
          PO E' Pj B C' assms par_not_col_strict par_strict_not_col_3 
          sum_par_strict_a)
    moreover {
      assume "PO E' ParStrict B C'" 
      hence False
        by (metis Par_cases Pj_def E' E Pj C' B PO E' Pj B C' grid_ok 
            not_col_distincts not_par_one_not_par par_id_2 par_strict_not_col_2) 
    }
    ultimately show ?thesis
      by (smt (verit, best) Ar2_def NCol_perm Pj_def Sum_def Col PO E' A' 
          PO E Pj A' C' assms col_trivial_3 grid_ok not_col_permutation_4 
          not_par_not_col parallel_uniqueness) 
  qed
qed

lemma sum_uniquenessB:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A X C"
    and "Sum PO E E' A Y C"
  shows "X = Y" 
proof (cases)
  assume "A = PO"
  thus ?thesis 
    using grid_ok assms(2) assms(3) sum_O_B_eq by blast
next
  assume "A  PO"
  obtain A'' C'' where "E E' Pj A A''" and "Col PO E' A''" and "PO E Pj A'' C''" and 
    "PO E' Pj Y C''" and "E' E Pj C'' C"
    using Sum_def assms(3) by auto
  obtain A' C' where "E E' Pj A A'" and "Col PO E' A'" and "PO E Pj A' C'" and 
    "PO E' Pj X C'" and "E' E Pj C' C"
    using Sum_def assms(2) by blast 
  have "A'  PO  (PO E ParStrict A' C'  X = PO)"
    using Sum_def A  PO Col PO E' A' E E' Pj A A' E' E Pj C' C 
      PO E Pj A' C' PO E' Pj X C' assms(2) grid_ok sum_par_strict by blast
  have "A''  PO  (PO E ParStrict A'' C''  Y = PO)"
    using Sum_def A  PO Col PO E' A'' E E' Pj A A'' E' E Pj C'' C 
      PO E Pj A'' C'' PO E' Pj Y C'' assms(3) grid_ok sum_par_strict by blast
  show ?thesis 
  proof (cases)
    assume "X = PO" 
    thus ?thesis
      using grid_ok assms(2) assms(3) sum_A_B_A sum_A_O_eq by blast 
  next 
    assume "X  PO"
    {
      assume "E E' Par A A''" 
      {
        assume "E E' Par A A'"
        have "A A' Par A A''"
          by (meson E E' Par A A'' E E' Par A A' par_symmetry par_trans) 
        {
          assume "A A' ParStrict A A''"
          hence ?thesis
            using not_par_strict_id by auto 
        }
        moreover
        {
          assume "A  A'" and "A  A''" and "Col A A A''" and "Col A' A A''"
          have "¬ Col PO E' A"
            using grid_ok Col PO E' A'' E E' Par A A'' grid_not_par 
              par_col2_par_bis par_symmetry by blast 
          hence "A' = A''"
            using Col_perm Col A' A A'' Col PO E' A'' Col PO E' A' colx by blast 
          {
            assume "PO E ParStrict A' C''"
            {
              assume "PO E ParStrict A' C'"
              have "A' C' Par A' C''"
                by (meson Par_strict_cases PO E ParStrict A' C'' 
                    PO E ParStrict A' C' par_strict_trans)
              moreover {
                assume "A' C' ParStrict A' C''"
                hence ?thesis
                  using A' C' ParStrict A' C'' not_par_strict_id by auto 
              }
              moreover {
                assume "A'  C'" and "A'  C''" and "Col A' A' C''" and "Col C' A' C''"
                {
                  assume "E' E Par C' C"
                  have "C C' Par C C''"
                    by (metis Ar2_def Par_strict_cases Pj_def Sum_def 
                        E' E Par C' C E' E Pj C'' C PO E ParStrict A' C'' assms(2) 
                        par_not_par par_right_comm par_strict_not_col_1 par_symmetry) 
                  moreover {
                    assume "C C' ParStrict C C''"
                    hence ?thesis
                      by (simp add: not_par_strict_id) 
                  }
                  moreover {
                    assume "C  C'" and "C  C''" and "Col C C C''" and "Col C' C C''"
                    hence "C' = C''"
                      by (metis Pj_def A' C' Par A' C'' E' E Pj C'' C 
                          PO E ParStrict A' C' calculation(1) col2__eq col_par_par_col grid_ok 
                          par_id par_right_comm par_strict_par par_symmetry par_trans) 
                    {
                      assume "PO E' Par Y C'"
                      {
                        assume "PO E' Par X C'"
                        hence "Y C' Par X C'"
                          using Par_cases PO E' Par Y C' par_trans by blast 
                        {
                          assume "Y C' ParStrict X C'"
                          hence ?thesis
                            using not_par_strict_id par_strict_comm by blast 
                        }
                        moreover {
                          assume "Y  C'" and "X  C'" and "Col Y X C'" and "Col C' X C'"
                          have "¬ Col PO E C'"
                            using PO E ParStrict A' C' par_strict_not_col_4 by blast 
                          hence ?thesis
                            by (metis Ar2_def Sum_def Col Y X C' grid_ok assms(2)
                                assms(3) col3 not_col_distincts) 
                        }
                        ultimately have ?thesis
                          using Par_def Y C' Par X C' by blast 
                      }
                      moreover {
                        assume "X = C'"
                        hence ?thesis
                          using Ar2_def Sum_def A'  PO  (PO E ParStrict A' C'  X = PO) 
                            X  PO assms(2) par_strict_not_col_4 by blast 
                      }
                      ultimately have ?thesis
                        using Pj_def PO E' Pj X C' by blast 
                    }
                    moreover {
                      assume "Y = C'"
                      hence False
                        using Ar2_def Sum_def A'  PO  (PO E ParStrict A' C'  X = PO) 
                          X  PO assms(3) par_strict_not_col_4 by blast 
                    }
                    ultimately have ?thesis
                      using Pj_def C' = C'' PO E' Pj Y C'' by blast
                  }
                  ultimately have ?thesis
                    using Par_def by blast 
                }
                moreover {
                  assume "C' = C"
                  hence ?thesis
                    using Ar2_def Sum_def A'  PO  (PO E ParStrict A' C'  X = PO) 
                      X  PO assms(2) par_strict_not_col_4 by force 
                }
                ultimately have ?thesis
                  using Pj_def E' E Pj C' C by blast 
              }
              ultimately have ?thesis
                using Par_def by blast 
            } 
            moreover {
              assume "X = PO"
              hence ?thesis
                by (simp add: X  PO) 
            }
            ultimately have ?thesis
              using A'  PO  (PO E ParStrict A' C'  X = PO) by blast 
          }
          moreover {
            assume "Y = PO"
            hence ?thesis
              using grid_ok assms(2) assms(3) sum_A_B_A sum_A_O_eq by blast 
          }
          ultimately have ?thesis
            using A' = A'' A''  PO  (PO E ParStrict A'' C''  Y = PO) by blast           
        }
        ultimately have ?thesis
          using Par_def A A' Par A A'' by blast 
      }
      hence ?thesis
        by (metis grid_ok Pj_def Col PO E' A'' Col PO E' A' E E' Par A A'' 
            E E' Pj A A' grid_not_par par_col2_par_bis par_symmetry) 
    }
    thus ?thesis
      by (metis Ar2_def Pj_def Sum_def A''  PO  (PO E ParStrict A'' C''  Y = PO) 
          E E' Pj A A'' assms(2) assms(3) par_strict_not_col_1 sum_A_B_A sum_A_O_eq) 
  qed
qed

lemma sum_uniquenessA:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' X B C"
    and "Sum PO E E' Y B C"
  shows "X = Y" 
proof (cases)
  assume "B = PO"
  thus ?thesis
    using grid_ok assms(2) assms(3) sum_A_O_eq by blast 
next
  assume "B  PO"
  obtain A'' C'' where "E E' Pj Y A''" and "Col PO E' A''" and "PO E Pj A'' C''" and 
    "PO E' Pj B C''" and "E' E Pj C'' C"
    using Sum_def assms(3) by blast 
  obtain A' C' where "E E' Pj X A'" and "Col PO E' A'" and "PO E Pj A' C'" and 
    "PO E' Pj B C'" and "E' E Pj C' C"
    using Sum_def assms(2) by blast 
  show ?thesis 
  proof (cases)
    assume "X = PO"
    thus ?thesis
      using grid_ok assms(2) assms(3) sum_A_B_B sum_O_B_eq by blast 
  next
    assume "X  PO"
    show ?thesis 
    proof (cases)
      assume "Y = PO"
      thus ?thesis
        using grid_ok assms(2) assms(3) sum_A_B_B sum_O_B_eq by blast 
    next
      assume "Y  PO"
      have "A'  PO  (PO E ParStrict A' C'  B = PO)"
        using Sum_def E E' Pj X A' X  PO grid_ok assms(2) sum_par_strict_a by blast 
      have "A''  PO  (PO E ParStrict A'' C''  B = PO)"
        using Sum_def E E' Pj Y A'' Y  PO grid_ok assms(3) sum_par_strict_a by blast
      {
        assume "PO E' Par B C''"
        {
          assume "PO E' Par B C'"
          {
            assume "B C' ParStrict B C''"
            hence ?thesis
              by (simp add: not_par_strict_id) 
          }
          moreover {
            assume "B  C'" and "B  C''" and "Col B B C''" and "Col C' B C''"
            {
              assume "E' E Par C'' C"
              {
                assume "E' E Par C' C"
                have "C C' Par C C''"
                  by (meson E' E Par C' C E' E Par C'' C par_left_comm par_symmetry par_trans) 
                {
                  assume "C C' ParStrict C C''"
                  hence ?thesis
                    by (simp add: not_par_strict_id) 
                }
                moreover {
                  assume "C  C'" and "C  C''" and "Col C C C''" and "Col C' C C''"
                  have "¬ Col C C' B"
                    by (metis grid_ok B  C' C  C' E' E Par C' C 
                        PO E' Par B C' col_par col_permutation_3 grid_not_par 
                        not_par_one_not_par par_left_comm) 
                  hence "C' = C''"
                    using Col_cases C C' Par C C'' Col C' B C'' 
                      col2__eq par_id by blast 
                  {
                    assume "PO E ParStrict A' C'"
                    {
                      assume "PO E ParStrict A'' C'"
                      have "A' C' Par A'' C'"
                        using Par_strict_perm PO E ParStrict A' C' 
                          PO E ParStrict A'' C' par_strict_trans by blast 
                      {
                        assume "A' C' ParStrict A'' C'" 
                        hence ?thesis
                          using not_par_strict_id par_strict_comm by blast 
                      }
                      moreover {
                        assume "A'  C'" and "A''  C'" and "Col A' A'' C'" and "Col C' A'' C'"
                        have "¬ Col PO E' C'"
                          by (metis grid_ok Col PO E' A' PO E ParStrict A' C' 
                              col2__eq col_permutation_2 grid_not_par_5 
                              par_strict_not_col_3)  
                        hence "A' = A''"
                          using Col A' A'' C' Col PO E' A'' Col PO E' A' colx by blast 
                        {
                          assume "E E' Par Y A'"
                          {
                            assume "E E' Par X A'"
                            have "Y A' Par X A'"
                              by (meson E E' Par X A' E E' Par Y A' par_symmetry par_trans)
                            {
                              assume "Y A' ParStrict X A'"
                              hence ?thesis
                                using not_col_distincts par_strict_not_col_2 by blast 
                            }
                            moreover {
                              assume "Y  A'" and "X  A'" and "Col Y X A'" and "Col A' X A'"
                              have "¬ Col PO E A'"
                                using PO E ParStrict A' C' par_strict_not_col_1 by auto
                              hence ?thesis 
                                using Sum_def Ar2_def Col Y X A' E E' Par X A' 
                                  grid_not_par not_col_distincts par_col2_par_bis par_symmetry 
                                by (smt (verit, ccfv_threshold) assms(2) assms(3)) 
                            }
                            ultimately have ?thesis
                              using Par_def Y A' Par X A' by blast 
                          }
                          moreover {
                            assume "X = A'"
                            hence ?thesis
                              using Ar2_def Sum_def PO E ParStrict A' C' 
                                par_strict_not_col_1 by (metis assms(2)) 
                          }
                          ultimately have ?thesis
                            using Pj_def E E' Pj X A' by blast 
                        }
                        moreover {
                          assume "Y = A'"
                          hence ?thesis
                            using Ar2_def Sum_def PO E ParStrict A' C' assms(3) 
                              par_strict_not_col_1 by auto 
                        }
                        ultimately have ?thesis
                          using Pj_def A' = A'' E E' Pj Y A'' by blast 
                      }
                      ultimately have ?thesis
                        using Par_def A' C' Par A'' C' by presburger 
                    }
                    moreover {
                      assume "B = PO"
                      hence ?thesis
                        by (simp add: B  PO) 
                    }
                    ultimately have ?thesis
                      using Sum_def C' = C'' Col PO E' A'' E E' Pj Y A'' 
                        E' E Pj C'' C PO E Pj A'' C'' PO E' Pj B C'' Y  PO 
                        sum_par_strict_b 
                        assms(3) grid_ok by blast 
                  }
                  moreover {
                    assume "B = PO"
                    hence ?thesis
                      by (simp add: B  PO) 
                  }
                  ultimately have ?thesis
                    using Sum_def Col PO E' A' E E' Pj X A' E' E Pj C' C 
                      PO E Pj A' C' PO E' Pj B C' X  PO sum_par_strict_b 
                      assms(2) grid_ok by blast 
                }
                ultimately have ?thesis
                  using Par_def C C' Par C C'' by blast 
              }
              moreover {
                assume "C' = C"
                hence False
                  by (metis Ar2_def Sum_def PO E' Par B C' assms(2) 
                      grid_not_par par_col2_par_bis par_symmetry) 
              }
              ultimately have ?thesis
                using Pj_def E' E Pj C' C by blast 
            }
            moreover {
              assume "C'' = C"
              hence ?thesis
                by (metis Ar2_def Sum_def PO E' Par B C'' assms(2) 
                    grid_not_par par_col2_par_bis par_symmetry) 
            }
            ultimately have ?thesis
              using Pj_def E' E Pj C'' C by blast 
          }
          ultimately have ?thesis
            by (metis not_col_distincts PO E' Par B C'' PO E' Par B C' 
                par_distinct par_id_1 par_symmetry par_trans) 
        }
        moreover {
          assume "B = C'"
          hence ?thesis
            using Ar2_def Par_cases Pj_def Sum_def E' E Pj C' C grid_ok 
              assms(2) assms(3) grid_not_par par_col2_par_bis sum_A_B_B 
            by (smt (verit, ccfv_threshold)) 
        }
        ultimately have ?thesis
          using Pj_def PO E' Pj B C' by blast 
      } 
      moreover {
        assume "B = C''"
        hence ?thesis
          using Ar2_def Par_cases Pj_def Sum_def E' E Pj C'' C X  PO 
            assms(1) grid_not_par par_col2_par_bis sum_A_B_B 
          by (smt (verit, del_insts) assms(2)) 
      }
      ultimately show ?thesis
        using Pj_def PO E' Pj B C'' by blast 
    qed
  qed
qed

lemma sum_B_null:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B A"
  shows "B = PO"
  using assms sum_A_B_A by auto 

lemma sum_A_null:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B B"
  shows "A = PO"
  using assms sum_A_B_B by force 

lemma sum_plg:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B C"
    and "(A  PO )  ( B  PO)"
  shows " A' C'. Plg PO B C' A'  Plg C' A' A C" 
proof -
  obtain A' C' where "E E' Pj A A'" 
    and "Col PO E' A'"
    and "PO E Pj A' C'"
    and "PO E' Pj B C'" 
    and "E' E Pj C' C"
    using Sum_def assms(2) by auto
  show ?thesis 
  proof (cases)
    assume "B = PO"
    thus ?thesis
      by (metis Plg_triv assms(2) bet_col between_trivial between_trivial2 
          grid_not_par_5 grid_ok sum_A_O_eq) 
  next
    assume "B  PO"
    show ?thesis 
    proof (cases)
      assume "A = PO"
      thus ?thesis
        by (metis grid_ok Plg_triv B  PO assms(2) parallelogram_equiv_plg 
            plg_permut sum_O_B_eq) 
    next
      assume "A  PO"
      have "A'  PO"
        using Sum_def A  PO E E' Pj A A' grid_ok assms(2) sum_par_strict_a by blast 
      have "PO E ParStrict A' C'  B = PO"
        using Sum_def A  PO Col PO E' A' E E' Pj A A' E' E Pj C' C 
          PO E Pj A' C' PO E' Pj B C' grid_ok assms(2) sum_par_strict_b by blast 
      moreover {
        assume "PO E ParStrict A' C'" 
        have "PO B Par C' A'"
          by (metis Sump_def par_col_par_2 B  PO PO E ParStrict A' C' 
              assms(2) par_right_comm par_strict_par sum_to_sump) 
        hence "PO B ParStrict C' A'"
          using Par_def Par_strict_cases PO E ParStrict A' C' par_strict_not_col_2 by blast 
        {
          assume "PO E' Par B C'"
          hence "PO A' Par B C'"
            using A'  PO Col PO E' A' par_col_par_2 by auto 
          hence "Plg PO B C' A'"
            by (simp add: PO B ParStrict C' A' pars_par_plg) 
          have "C' A' Par A C"
          proof (rule par_col_par [of _ _ _ _ "PO"])
            show "A  C"
              using B  PO assms(2) sum_B_null grid_ok by blast
            show "C' A' Par A PO"
              by (metis Ar2_def Par_cases Sum_def A  PO PO E ParStrict A' C' 
                  assms(2) par_col_par_2 par_strict_par) 
            show "Col A PO C"
              by (metis Ar2_def Sum_def grid_ok assms(2) col3 grid_not_par) 
          qed
          have "C' A' ParStrict A C"
            by (metis Ar2_def Par_def Sum_def C' A' Par A C PO E ParStrict A' C' 
                assms(2) colx not_col_permutation_2 par_strict_not_col_1)
          {
            assume "E E' Par A A'"
            hence ?thesis
              by (metis Par_cases Pj_def C' A' ParStrict A C E' E Pj C' C 
                  Plg PO B C' A' not_col_distincts par_not_par 
                  par_strict_not_col_4 pars_par_plg) 
          }
          moreover {
            assume "A = A'"
            hence ?thesis
              using C' A' ParStrict A C col_trivial_2 par_strict_not_col_1 by blast 
          }
          ultimately have ?thesis
            using Pj_def E E' Pj A A' by blast 
        }
        moreover {
          assume "B = C'"
          hence ?thesis
            using PO B ParStrict C' A' not_col_distincts par_strict_not_col_2 by blast 
        }
        ultimately have ?thesis
          using Pj_def PO E' Pj B C' by blast 
      }
      ultimately show ?thesis
        using B  PO by blast 
    qed
  qed
qed

lemma sum_cong:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B C"
    and "(A  PO  B  PO)"
  shows "ParallelogramFlat PO A C B" 
proof (cases)
  assume "A = PO"
  thus ?thesis
    using grid_ok assms(2) assms(3) plgf_permut plgf_trivial1 sum_O_B_eq by blast 
next
  assume "A  PO"
  obtain A' C' where "Plg PO B C' A'" and "Plg C' A' A C"
    using A  PO grid_ok assms(2) sum_plg by blast 
  have "Parallelogram PO B C' A'"
    by (simp add: Plg PO B C' A' parallelogram_equiv_plg) 
  have "Parallelogram C' A' A C"
    using Plg C' A' A C plg_to_parallelogram by auto
  hence "Parallelogram PO B C A  PO = B  C' = A'  A = C  PO = A"
    by (simp add: Parallelogram PO B C' A' plg_pseudo_trans) 
  moreover {
    assume "Parallelogram PO B C A"
    moreover {
      assume "ParallelogramStrict PO B C A"
      hence ?thesis
        by (metis Ar2_def Plg_perm Sum_def col_transitivity_1 A  PO 
            Parallelogram PO B C A  PO = B  C' = A'  A = C  PO = A assms(2) 
            grid_not_par plg_col_plgf) 
    }
    moreover {
      assume "ParallelogramFlat PO B C A"
      hence ?thesis
        using plgf_comm2 plgf_permut by blast 
    }
    ultimately have ?thesis
      using Parallelogram_def by blast 
  }
  moreover {
    assume "PO = B  C' = A'  A = C  PO = A"
    hence ?thesis
      using A  PO by auto 
  }
  ultimately show ?thesis 
    by blast
qed

lemma sum_cong2:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B C"
    and "(A  PO  B  PO)"
  shows "Cong PO A B C  Cong PO B A C"
  using grid_ok assms(3) assms(2) not_cong_1243 plgf_cong sum_cong by blast 

lemma sum_comm:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B C"
  shows "Sum PO E E' B A C" 
proof (cases "B = PO")
  show "B = PO  Sum PO E E' B A C"
    by (metis Ar2_def Sum_def assms sum_A_O_eq sum_O_B) 
  show "B  PO  Sum PO E E' B A C" 
  proof (cases "A = PO")
    show "B  PO  A = PO  Sum PO E E' B A C"
      by (metis Ar2_def Sum_def assms sum_A_O sum_O_B_eq) 
    show "B  PO  A  PO  Sum PO E E' B A C" 
    proof -
      obtain A' C' where "Plg PO B C' A'" and "Plg C' A' A C"
        by (metis Plg_triv assms grid_not_par sum_A_O_eq sum_plg)
      obtain B' where "B B' Proj PO E' E E'"
        by (metis grid_ok Par_cases grid_not_par project_existence)
      obtain P' where "PO E Par B' P'"
        using grid_ok grid_not_par parallel_existence1 by presburger
      obtain D' where "A D' Proj B' P' PO E'"
        by (metis PO E Par B' P' grid_ok grid_not_par not_par_one_not_par 
            par_neq2 project_existence)
      have "Ar2 PO E E' A B C"
        using Sum_def assms by blast
      moreover have "D' C Proj PO E E E'" 
      proof (unfold Proj_def, intro conjI)
        show "PO  E"
          using PO E Par B' P' par_neq1 by auto 
        show "E  E'"
          using grid_ok not_col_distincts by blast
        show "¬ PO E Par E E'"
          using grid_ok grid_not_par by auto 
        show "Col PO E C"
          using Ar2_def calculation by blast 
        show "D' C Par E E'  D' = C" 
        proof -
          have "B'  P'  PO  E'  ¬ B' P' Par PO E'  (A D' Par PO E'  A = D')"
            using Proj_def A D' Proj B' P' PO E' by presburger
          moreover {
            assume "A D' Par PO E'"
            hence "A D' ParStrict PO E'  (A  D'  PO  E'  Col A PO E'  Col D' PO E')"
              by (simp add: Par_def) 
            moreover {
              assume "A D' ParStrict PO E'"
              have "Col B' P' D'"
                using Proj_def A D' Proj B' P' PO E' by presburger 
              have "D' C Proj PO E E E'" 
              proof -
                {
                  assume "PO A ParStrict B' D'"
                  hence "PO B' Par A D'"
                    by (metis Par_cases Proj_def A D' Par PO E' B B' Proj PO E' E E' 
                        col_trivial_3 par_col_par_2 par_strict_not_col_3) 
                  hence "Plg PO A D' B'"
                    by (simp add: PO A ParStrict B' D' par_strict_right_comm pars_par_plg) 
                  hence "Parallelogram D' B' B C  D' = B'  PO = A  C = B  D' = C"
                    by (metis Plg_perm Plg C' A' A C Plg PO B C' A' 
                        plg_pseudo_trans plg_to_parallelogram) 
                  moreover {
                    assume "Parallelogram D' B' B C" 
                    hence "B' B Par C D'"
                      by (metis Ar2_def Par_cases par_distincts Ar2 PO E E' A B C 
                          B B' Proj PO E' E E' PO A ParStrict B' D' PO B' Par A D' 
                          par_strict_distinct plg_par_2 proj_id) 
                    hence "D' C Par E E'  D' = C"
                      by (metis Par_cases par_distincts 
                          B B' Proj PO E' E E' par_not_par project_par_dir) 
                    hence ?thesis
                      using B' B Par C D' Col PO E C PO  E ¬ PO E Par E E' 
                        par_col_project par_distinct by blast 
                  }
                  moreover {
                    assume "D' = B'  PO = A  C = B  D' = C" 
                    hence ?thesis
                      using A D' ParStrict PO E' not_par_strict_id by force 
                  }
                  ultimately have ?thesis 
                    by blast
                }
                moreover {
                  assume "PO  A" and "B'  D'" and "Col PO B' D'" and "Col A B' D'"
                  hence False
                    by (meson Col_perm Proj_def A D' ParStrict PO E' 
                        B B' Proj PO E' E E' par_not_col) 
                }
                ultimately show ?thesis
                  by (metis Ar2_def Par_def Proj_def A D' ParStrict PO E' 
                      Ar2 PO E E' A B C B B' Proj PO E' E E' Col B' P' D' PO E Par B' P' 
                      col_trivial_2 not_par_strict_id not_strict_par2 par_col_par par_col_par_2 
                      par_strict_not_col_4) 
              qed
              hence ?thesis
                using Proj_def by auto 
            }
            moreover {
              assume "A  D'" and "PO  E'" and "Col A PO E'" and "Col D' PO E'"
              hence ?thesis
                by (smt (verit, ccfv_threshold) Ar2_def NCol_cases Par_cases Pj_def 
                    Proj_def Sum_def A D' Proj B' P' PO E' Ar2 PO E E' A B C B B' Proj PO E' E E' 
                    assms l6_16_1 par_col2_par_bis par_id) 
            }
            ultimately have ?thesis
              by blast 
          }
          moreover {
            assume "A = D'"
            hence ?thesis
              by (metis Ar2_def Proj_def A D' Proj B' P' PO E' Ar2 PO E E' A B C 
                  B B' Proj PO E' E E' PO E Par B' P' assms inter_uniqueness_not_par 
                  proj_id sum_A_O_eq) 
          }
          ultimately show ?thesis 
            by blast
        qed
      qed
      ultimately show ?thesis
        using B B' Proj PO E' E E' PO E Par B' P' A D' Proj B' P' PO E' 
          Ar2_def Sump_def sump_to_sum by blast
    qed
  qed
qed

lemma cong_sum:
  assumes grid_ok: "¬ Col PO E E'"
    and "PO  C  B  A"
    and "Ar2 PO E E' A B C"
    and "Cong PO A B C"
    and "Cong PO B A C"
  shows "Sum PO E E' A B C" 
proof (cases)
  assume "A = PO"
  thus ?thesis
    using Ar2_def assms(3) assms(4) cong_reverse_identity sum_O_B by blast 
next
  assume "A  PO"
  show ?thesis 
  proof (cases)
    assume "B = PO"
    thus ?thesis
      using Ar2_def assms(3) assms(5) cong_reverse_identity sum_A_O by blast 
  next
    assume "B  PO"
    have " ¬ Col PO E E'"
      by (simp add: grid_ok) 
    have "Col PO E A"
      using Ar2_def assms(3) by blast 
    have "Col PO E B"
      using Ar2_def assms(3) by force 
    have "Col PO E C"
      using Ar2_def assms(3) by blast 
    have "¬ PO E Par E E'  ¬ PO E Par PO E'  ¬ PO E' Par E E'  PO  E  PO  E'  E  E'"
      using grid_ok grid_not_par by blast
    hence "¬ E E' Par PO E'"
      using Par_cases by auto
    then obtain A' where "A A' Proj PO E' E E'"
      using project_existence [of A PO E' E E'] grid_ok grid_not_par 
        project_existence by presburger 
    hence "Col PO E' A'  (A A' Par E E'  A = A')"
      using Proj_def by simp
    then obtain P' where "PO E Par A' P'"
      using grid_ok grid_not_par parallel_existence1 by presburger 
    obtain C' where "B C' Proj A' P' PO E'"
      by (metis PO E Par A' P' grid_ok grid_not_par not_par_one_not_par 
          par_neq2 project_existence) 
    have "E E' Pj A A'"
      using Pj_def Col PO E' A'  (A A' Par E E'  A = A') par_symmetry by blast 
    moreover have "Col PO E' A'"
      by (simp add: Col PO E' A'  (A A' Par E E'  A = A')) 
    moreover have "PO E Pj A' C'"
      by (metis Pj_def Proj_def B C' Proj A' P' PO E' PO E Par A' P' par_col_par) 
    moreover have "PO E' Pj B C'"
      by (metis Pj_def Proj_def B C' Proj A' P' PO E' par_symmetry) 
    moreover have "E' E Pj C' C" 
    proof -
      {
        assume "A' = C'"
        {
          assume "B A' Par PO E'"
          moreover {
            assume "B A' ParStrict PO E'"
            hence False
              using Col PO E' A' not_col_permutation_1 par_strict_not_col_2 by blast 
          }
          moreover {
            assume "B  A'" and "PO   E'" and "Col B PO E'" and "Col A' PO E'"
            hence False
              using B  PO Col PO E B col_transitivity_2 grid_ok 
                not_col_permutation_1 by blast 
          }
          ultimately have False
            using Par_def by blast 
        }
        moreover {
          assume "B = A'"
          hence False
            using A A' Proj PO E' E E' A  PO Col PO E A Col PO E B 
              grid_ok proj_id by blast 
        }
        ultimately have False
          using Proj_def A' = C' B C' Proj A' P' PO E' by force 
      }
      have "PO B ParStrict A' C'"
        by (metis NCol_perm Par_def Pj_def par_col_par_2 A  PO A' = C'  False 
            B  PO Col PO E B assms(3) calculation(1) calculation(2) calculation(3) 
            col_trivial_3 colx grid_ok sum_par_strict_a) 
      hence "PO B ParStrict C' A'"
        using par_strict_right_comm by blast 
      moreover have "PO A' Par B C'"
        by (metis Pj_def Proj_def A A' Proj PO E' E E' A  PO B C' Proj A' P' PO E' 
            Col PO E A Col PO E B grid_ok PO E Par A' P' PO E' Pj B C' col_trivial_3 
            not_strict_par1 par_col_par_2 proj_id) 
      ultimately have "Plg PO B C' A'"
        using pars_par_plg by auto 
      have "ParallelogramFlat PO B C A"
        by (metis Ar2_def ParallelogramFlat_def col_transitivity_1 assms(2) assms(3) 
            assms(4) assms(5) grid_not_par not_cong_1243) 
      hence "Parallelogram PO B C A"
        using Parallelogram_def by blast 
      hence "Plg PO B C A"
        by (simp add: parallelogram_equiv_plg) 
      have "Parallelogram A C C' A'"
        using plg_to_parallelogram B  PO Parallelogram PO B C A Plg PO B C' A' 
          plg_pseudo_trans plg_sym by blast 
      have "A C Par C' A'"
        by (metis ParallelogramFlat_def B  PO PO B ParStrict A' C' 
            Parallelogram A C C' A' Parallelogram PO B C A ParallelogramFlat PO B C A 
            par_strict_not_col_4 plg_not_comm_R1 plg_par_1) 
      hence "A A' Par C C'"
        by (metis ParallelogramFlat_def PO B ParStrict A' C' Parallelogram A C C' A' 
            ParallelogramFlat PO B C A par_neq1 par_strict_not_col_4 plg_par) 
      {
        assume "A A' Par E E'"
        hence ?thesis
          by (metis Par_perm Pj_def A A' Par C C' par_trans) 
      }
      moreover {
        assume "A = A'"
        hence ?thesis
          using A A' Par C C' par_neq1 by blast 
      }
      ultimately show ?thesis
        using Col PO E' A'  (A A' Par E E'  A = A') by blast 
    qed
    ultimately show ?thesis
      unfolding Sum_def using assms(3) by blast 
  qed
qed

lemma sum_iff_cong_a:
  assumes grid_ok: "¬ Col PO E E'"
    and "Ar2 PO E E' A B C"
    and "PO  C  B  A"
    and "Cong PO A B C"
    and "Cong PO B A C"
  shows "Sum PO E E' A B C"
  using grid_ok assms(5) assms(2) assms(3) assms(4) cong_sum by blast 

lemma sum_iff_cong_b:
  assumes grid_ok: "¬ Col PO E E'"
    and (*"Ar2 PO E E' A B C"
and*) "PO  C  B  A"
    and "Sum PO E E' A B C"
  shows "Cong PO A B C  Cong PO B A C"
  using grid_ok assms(3) assms(2) sum_A_O_eq sum_cong2 by blast 

lemma sum_iff_cong:
  assumes grid_ok: "¬ Col PO E E'"
    and "Ar2 PO E E' A B C"
    and "PO  C  B  A"
  shows "(Cong PO A B C  Cong PO B A C)  Sum PO E E' A B C"
  using grid_ok assms(3) assms(2) cong_sum sum_iff_cong_b by blast 

lemma opp_comm:
  assumes grid_ok: "¬ Col PO E E'"
    and "Opp PO E E' X Y"
  shows "Opp PO E E' Y X"
  using Opp_def assms sum_comm by presburger 

lemma opp_uniqueness:
  assumes grid_ok: "¬ Col PO E E'"
    and "Opp PO E E' A MA1"
    and "Opp PO E E' A MA2" 
  shows "MA1 = MA2"
  using grid_ok Opp_def assms(3) assms(2) sum_uniquenessA by presburger 

(** lemma 14.13 *)
(** Parallel projection on the second axis preserves sums. *)

lemma proj_preserves_sum:
  assumes grid_ok: "¬ Col PO E E'"
    and "Sum PO E E' A B C"
    and "Ar1 PO E' A' B' C'"
    and "E E' Pj A A'"
    and "E E' Pj B B'"
    and "E E' Pj C C'"
  shows "Sum PO E' E A' B' C'" 
proof -
  obtain A0 C0 where "E E' Pj A A0" and "Col PO E' A0" and "PO E Pj A0 C0" and 
    "PO E' Pj B C0" and "E' E Pj C0 C"
    using Sum_def assms(2) by blast
  have "Col PO E A"
    using Ar2_def Sum_def assms(2) by presburger 
  have "Col PO E B"
    using Ar2_def Sum_def assms(2) by presburger 
  have "¬ PO E' Par E E'"
    using grid_not_par_3 grid_ok by auto 
  have "PO  E"
    using grid_ok not_col_distincts by blast 
  have "PO  E'"
    using grid_ok not_col_distincts by blast 
  show ?thesis 
  proof (cases)
    assume "A = PO"
    {
      assume "E E' Par PO A'"
      hence False
        by (metis Ar1_def ¬ PO E' Par E E' assms(3) l6_16_1 par_col2_par_bis par_symmetry) 
    }
    moreover {
      assume "PO = A'"
      have "B = C" 
      proof -
        have "¬ Col PO E E'"
          by (simp add: grid_ok) 
        moreover have "Sum PO E E' PO B C"
          using A = PO assms(2) by blast 
        ultimately show ?thesis
          using sum_O_B_eq by blast 
      qed
      have "B' = C'"
        using Ar1_def B = C Col PO E B assms(3) assms(5) assms(6) grid_ok 
          pj_uniqueness by presburger 
      hence "Sum PO E' E PO B' B'"
        by (meson Ar1_def assms(3) grid_ok not_col_permutation_5 sum_O_B) 
      hence "Sum PO E' E PO B' C'"
        by (simp add: B' = C') 
      hence ?thesis
        using PO = A' by auto 
    }
    ultimately show ?thesis
      using Pj_def A = PO assms(4) by blast
  next
    assume "A  PO"
    show ?thesis
    proof (cases)
      assume "B' = PO"
      thus ?thesis
        by (smt (verit, ccfv_threshold) Ar1_def Ar2_def Par_cases Pj_def 
            Sum_def assms(2) assms(3) assms(4) assms(5) assms(6) not_col_distincts 
            not_col_permutation_5 pj_uniqueness sum_A_O sum_A_O_eq)
    next
      assume "B'  PO"
      obtain D where "Parallelogram A PO B' D"
        using A  PO plg_existence by blast 
      hence "A PO Par B' D"
        using A  PO B'  PO plg_par by auto 
      have "Ar2 PO E' E A' B' C'"
        using Ar1_def Ar2_def assms(3) grid_ok not_col_permutation_5 by presburger 
      moreover have "E' E Pj A' A"
        using assms(4) pj_comm by blast 
      moreover have "A D Par PO E'" 
      proof (rule par_col_par [of PO E' A D B'])
        show "PO  E'"
          by (simp add: PO  E') 
        show "A D Par PO B'"
          using A  PO B'  PO Parallelogram A PO B' D plg_par by force 
        show "Col PO B' E'"
          using Ar2_def calculation(1) col_permutation_5 by presburger 
      qed
      hence "PO E' Par A D"
        using Par_cases by blast 
      hence "PO E' Pj A D"
        using Pj_def by auto 
      moreover have "PO E Pj B' D"
        by (metis Pj_def A PO Par B' D A  PO Col PO E A PO  E 
            not_par_not_col par_left_comm par_trans) 
      moreover have "E E' Pj D C'" 
      proof -
        have "ParallelogramFlat PO A C B"
          using A  PO assms(2) grid_ok sum_cong by blast 
        have "Parallelogram B' D C B  (B' = D  A = PO  B = C  B' = B)"
          by (metis Parallelogram_def Parallelogram A PO B' D 
              ParallelogramFlat PO A C B plg_pseudo_trans plg_sym)
        moreover
        {
          assume "Parallelogram B' D C B"
          have "B' D Par C B"
            by (metis Par_cases Plg_perm A PO Par B' D Parallelogram B' D C B 
                par_neq2 par_reflexivity plg_par_1) 
          have "B' B Par D C"
            by (metis Ar1_def NCol_perm ParallelogramFlat_def Plg_perm A  PO 
                B' D Par C B B'  PO Col PO E A Parallelogram B' D C B 
                ParallelogramFlat PO A C B assms(3) col_transitivity_1 grid_ok par_neq1 plg_par_2) 
          {
            assume "E E' Par B B'"
            {
              assume "E E' Par C C'"
              hence ?thesis
                by (smt (verit, best) Par_perm Pj_def B' B Par D C E E' Par B B' 
                    col_par_par_col col_trivial_3 not_par_one_not_par par_col2_par) 
            }
            moreover {
              assume "C = C'"
              hence ?thesis
                by (metis Par_cases Pj_def B' B Par D C E E' Par B B' not_par_one_not_par) 
            }
            ultimately have ?thesis
              using Pj_def assms(6) by blast 
          }
          moreover {
            assume "B = B'"
            hence ?thesis
              using B' B Par D C par_neq1 by blast 
          }
          ultimately have ?thesis
            using Pj_def assms(5) by blast 
        }
        moreover {
          assume "B' = D  A = PO  B = C  B' = B" 
          hence False
            using A  PO by blast 
        }
        ultimately show ?thesis 
          by blast
      qed
      ultimately show ?thesis
        using Sum_def Col PO E A by blast 
    qed
  qed
qed

lemma sum_assoc_1:
  assumes "Sum PO E E' A B AB"
    and "Sum PO E E' B C BC"
    and "Sum PO E E' A BC ABC"
  shows "Sum PO E E' AB C ABC" 
proof -
  have "¬ Col PO E E'"
    using Ar2_def Sum_def assms(2) by presburger 
  have "Col PO E AB"
    using Ar2_def Sum_def assms(1) by presburger 
  have "Col PO E C"
    using Ar2_def Sum_def assms(2) by presburger 
  have "Col PO E ABC"
    using Ar2_def Sum_def assms(3) by presburger 
  {
    assume "A = PO"
    hence ?thesis
      using ¬ Col PO E E' assms(1) assms(2) assms(3) sum_O_B_eq by blast 
  }
  moreover {
    assume "A  PO"
    {
      assume "B = PO"
      hence ?thesis
        using ¬ Col PO E E' assms(1) assms(2) assms(3) sum_A_O_eq sum_O_B_eq by blast 
    }
    moreover {
      assume "B  PO"
      {
        assume "C = PO"
        hence ?thesis
          using Col PO E AB ¬ Col PO E E' assms(1) assms(2) assms(3) sum_A_O 
            sum_A_O_eq sum_uniqueness by blast 
      }
      moreover {
        assume "C  PO"
        have "PO  E"
          using ¬ Col PO E E' col_trivial_1 by auto
        have "PO  E'"
          using ¬ Col PO E E' not_col_distincts by blast 
        obtain AB2' where "AB AB2' Proj PO E' E E'"
          using Sump_def Col PO E AB ¬ Col PO E E' sum_A_O sum_to_sump by blast
        hence "Col PO E' AB2'"
          by (simp add: Proj_def) 
        have "AB AB2' Par E E'  AB = AB2'"
          using Proj_def AB AB2' Proj PO E' E E' by presburger
        moreover have "A  AB"
          using B  PO ¬ Col PO E E' assms(1) sum_B_null by force
        have "ABC  AB"
          using C  PO ¬ Col PO E E' assms(1) assms(2) assms(3) sum_B_null 
            sum_uniquenessB by blast 
        obtain C2 where "Parallelogram C PO AB2' C2"
          using C  PO plg_existence by presburger 
        {
          assume "AB AB2' Par E E'"
          hence "AB  AB2'"
            using par_distinct by blast 
          have "PO  AB2'"
            using AB AB2' Proj PO E' E E' AB  AB2' Col PO E AB ¬ Col PO E E' 
              grid_not_par_5 proj_id by blast 
          have "C PO Par AB2' C2"
            by (simp add: C  PO PO  AB2' Parallelogram C PO AB2' C2 plg_par) 
          have "C C2 Par PO AB2'"
            by (simp add: C  PO PO  AB2' Parallelogram C PO AB2' C2 plg_par) 
          have "E E' Pj AB AB2'"
            using Par_perm Pj_def AB AB2' Par E E' by blast 
          moreover have "PO E Pj AB2' C2"
            by (metis Pj_def C PO Par AB2' C2 C  PO Col PO E C PO  E 
                not_par_not_col par_left_comm par_trans) 
          moreover have "PO E' Pj C C2"
            by (meson Pj_def C C2 Par PO AB2' Col PO E' AB2' PO  AB2' 
                PO  E' not_par_not_col not_par_one_not_par) 
          moreover have "E' E Pj C2 ABC" 
          proof -
            have "Parallelogram PO BC ABC A"
              using Parallelogram_def A  PO ¬ Col PO E E' assms(3) 
                sum_comm sum_cong by blast
            have "Parallelogram PO B AB A"
              using Parallelogram_def B  PO ¬ Col PO E E' assms(1) 
                sum_comm sum_cong by blast 
            have "Parallelogram PO B BC C"
              using Parallelogram_def B  PO ¬ Col PO E E' assms(2) sum_cong by blast 
            have "Parallelogram B AB ABC BC  (B = AB  A = PO  BC = ABC  B = BC)"
              by (simp add: Parallelogram PO B AB A Parallelogram PO BC ABC A 
                  plg_permut plg_pseudo_trans)
            hence "Parallelogram B AB ABC BC"
              using A  PO by auto 
            have "Parallelogram PO C ABC AB"
              by (metis Plg_perm ABC  AB 
                  Parallelogram B AB ABC BC  B = AB  A = PO  BC = ABC  B = BC 
                  Parallelogram PO B BC C plg_pseudo_trans)
            hence "Parallelogram ABC AB AB2' C2"
              by (metis par_distinct C PO Par AB2' C2 Parallelogram C PO AB2' C2
                  plg_pseudo_trans plg_sym)
            thus ?thesis
              by (metis Par_perm Pj_def AB AB2' Par E E' AB  AB2' ABC  AB 
                  par_not_par plg_par_2) 
          qed
          ultimately have ?thesis
            using Ar2_def Sum_def Col PO E' AB2' Col PO E ABC Col PO E AB 
              Col PO E C ¬ Col PO E E' by auto 
        }
        moreover {
          assume "AB = AB2'"
          have "AB = PO"
            using AB = AB2' AB AB2' Proj PO E' E E' Col PO E AB 
              ¬ Col PO E E' proj_id by blast 
          hence "C = C2"
            using AB = AB2' Parallelogram C PO AB2' C2 cong_identity_inv plg_cong by blast 
          have "ParallelogramFlat PO B BC C"
            using B  PO ¬ Col PO E E' assms(2) sum_cong by blast 
          have "ParallelogramFlat PO BC ABC A"
            using A  PO ¬ Col PO E E' assms(3) sum_comm sum_cong by blast 
          have "ParallelogramFlat PO B PO A"
            using A  PO AB = PO ¬ Col PO E E' assms(1) plgf_sym sum_cong by blast 
          have "Parallelogram BC C A PO  (BC = C  PO = B  PO = A  BC = PO)"
            by (metis Parallelogram_def ParallelogramFlat PO B BC C 
                ParallelogramFlat PO B PO A ¬ Col PO E E' assms(2) plgf_plgf_plgf 
                plgf_sym sum_A_B_B) 
          hence "Parallelogram BC C A PO"
            using B  PO by auto
          have "Parallelogram PO BC ABC A"
            using Parallelogram_def ParallelogramFlat PO BC ABC A by auto 
          hence ?thesis
            by (metis Plg_perm AB = PO Col PO E C Parallelogram BC C A PO 
                ¬ Col PO E E' plg_uniqueness sum_O_B) 
        }
        ultimately have ?thesis 
          by blast
      }
      ultimately have ?thesis
        by blast 
    }
    ultimately have ?thesis 
      by blast
  }
  ultimately show ?thesis
    by blast
qed

lemma sum_assoc_2: 
  assumes "Sum PO E E' A B AB"
    and "Sum PO E E' B C BC"
    and "Sum PO E E' AB C ABC"
  shows "Sum PO E E' A BC ABC"
  by (smt (verit, best) Ar2_def Sum_def assms(1) assms(2) assms(3) sum_assoc_1 sum_comm) 

lemma sum_assoc:
  assumes "Sum PO E E' A B AB"
    and "Sum PO E E' B C BC"
  shows "Sum PO E E' A BC ABC  Sum PO E E' AB C ABC"
  by (smt (verit, ccfv_SIG) assms(1) assms(2) sum_assoc_1 sum_assoc_2) 

(** lemma 14.15 *)
(** The choice of E' does not affect sum. *)
lemma sum_y_axis_change:
  assumes "Sum PO E E' A B C"
    and "¬ Col PO E E''"
  shows "Sum PO E E'' A B C"
  by (smt (verit) Ar2_def ParallelogramFlat_def Sum_def assms(1) 
      assms(2) sum_A_O sum_cong sum_iff_cong) 

(** lemma 14.16 *)
(** The choice of E does not affect sum. *)
lemma sum_x_axis_unit_change:
  assumes "Sum PO E E' A B C"
    and "Col PO E U"
    and "U  PO"
  shows "Sum PO U E' A B C"
proof (cases)
  assume "U = E"
  thus ?thesis
    using assms(1) by blast 
next
  assume "U  E"
  have "Ar2 PO E E' A B C"
    using Sum_def assms(1) by blast
  have "¬ Col PO E E'"
    using Ar2_def Ar2 PO E E' A B C by blast 
  have "Col PO E A"
    using Ar2_def Ar2 PO E E' A B C by blast 
  have "Col PO E B"
    using Ar2_def Ar2 PO E E' A B C by blast 
  have "Col PO E C"
    using Ar2_def Ar2 PO E E' A B C by blast 
  have "PO  E" 
    using ¬ Col PO E E' grid_not_par by blast 
  have "PO  E'"
    using ¬ Col PO E E' grid_not_par by blast 
  have "¬ Col PO U E'"
    by (metis ¬ Col PO E E' assms(2) assms(3) col_trivial_3 colx) 
  {
    assume "A = PO"
    hence ?thesis
      by (metis Col PO E C PO  E ¬ Col PO U E' assms(1) assms(2) 
          col_transitivity_1 sum_O_B sum_O_B_eq) 
  }
  moreover {
    assume "A  PO"
    have ?thesis 
    proof (cases)
      assume "B = PO"
      thus ?thesis
        by (metis Col PO E C PO  E ¬ Col PO U E' assms(1) assms(2) 
            col_transitivity_1 sum_A_O sum_A_O_eq) 
    next
      assume "B  PO"
      have "Ar2 PO U E' A B C"
        using Ar2_def Col PO E A Col PO E B Col PO E C PO  E 
          ¬ Col PO U E' assms(2) col_transitivity_1 by presburger 
      have "Col PO U A"
        using Col PO E A PO  E assms(2) col_transitivity_1 by presburger 
      have "Col PO U B"
        using Col PO E B PO  E assms(2) col_transitivity_1 by blast 
      obtain A'' where "A A'' Proj PO E' U E'"
        by (meson Sump_def Col PO U A ¬ Col PO U E' sum_A_O sum_to_sump) 
      hence "Col PO E' A''"
        using Proj_def by blast
      have "A A'' Par U E'  A = A''"
        using Proj_def A A'' Proj PO E' U E' by presburger 
      hence "A A'' Par U E'"
        using A A'' Proj PO E' U E' A  PO Col PO U A ¬ Col PO U E' proj_id by blast 
      obtain C'' where "Parallelogram B PO A'' C''"
        using B  PO plg_existence by presburger 
      have "PO  A''"
        using A A'' Proj PO E' U E' A  PO Col PO U A ¬ Col PO U E' 
          not_col_distincts proj_id by blast
      have "B PO Par A'' C''"
        by (simp add: B  PO PO  A'' Parallelogram B PO A'' C'' plg_par) 
      have "B C'' Par PO A''"
        by (simp add: B  PO PO  A'' Parallelogram B PO A'' C'' plg_par) 
      have "U E' Pj A A''"
        using Par_perm Pj_def A A'' Par U E' by blast 
      moreover have "PO U Pj A'' C''"
        by (metis Pj_def B PO Par A'' C'' B  PO Col PO U B assms(3) 
            not_par_not_col par_left_comm par_trans) 
      moreover have "PO E' Pj B C''"
        by (meson Pj_def B C'' Par PO A'' Col PO E' A'' PO  E' 
            not_col_distincts par_col2_par_bis par_symmetry) 
      moreover have "E' U Par C'' C" 
      proof -
        have "ParallelogramFlat PO A C B"
          using A  PO ¬ Col PO E E' assms(1) sum_cong by blast 
        hence "Parallelogram PO A C B"
          by (simp add: Parallelogram_def)
        hence "Parallelogram A C C'' A''"
          using Plg_perm B  PO Parallelogram B PO A'' C'' plg_pseudo_trans by blast 
        hence "A C Par C'' A''"
          by (metis Tarski_neutral_dimensionless.par_distincts 
              Tarski_neutral_dimensionless_axioms A A'' Par U E' B PO Par A'' C'' 
              par_symmetry plg_par_1 plg_sym) 
        hence "A A'' Par C C''"
          by (metis Plg_perm Tarski_neutral_dimensionless.par_distincts 
              Tarski_neutral_dimensionless_axioms A A'' Par U E' Parallelogram A C C'' A'' plg_par) 
        thus ?thesis
          by (metis Par_perm A A'' Par U E' par_trans) 
      qed
      hence "E' U Pj C'' C"
        by (simp add: Pj_def) 
      ultimately show ?thesis
        using Sum_def Col PO E' A'' Ar2 PO U E' A B C by blast 
    qed
  }
  ultimately show ?thesis 
    by blast
qed

lemma change_grid_sum_0:
  assumes "PO E ParStrict O' E'"
    and "Ar1 PO E A B C"
    and "Ar1 O' E' A' B' C'"
    and "PO O' Pj E E'"
    and "PO O' Pj A A'"
    and "PO O' Pj B B'"
    and "PO O' Pj C C'"
    and "Sum PO E E' A B C"
    and "A = PO"
  shows "Sum O' E' E A' B' C'" 
proof -
  {
    assume "Ar2 PO E E' A B C"
    obtain A1 C1 where "E E' Pj A A1" and
      "Col PO E' A1" and
      "PO E Pj A1 C1" and
      "PO E' Pj B C1" and
      "E' E Pj C1 C"
      using Sum_def assms(8) by blast 
    have "A' = O'"
    proof (rule l6_21 [of O' E' PO O'])
      show "¬ Col O' E' PO"
        using assms(1) par_strict_not_col_3 by auto 
      show "PO  O'"
        using ¬ Col O' E' PO col_trivial_3 by blast 
      show "Col O' E' A'" 
        using assms(3) Ar1_def by auto 
      show "Col O' E' O'"
        using grid_not_par_5 by auto 
      show "Col PO O' A'"
        using Pj_def not_col_distincts assms(5) assms(9) par_id by blast 
      show "Col PO O' O'"
        by (simp add: col_trivial_2) 
    qed
    have "Sum PO E E' PO B B"
      using Ar2_def Ar2 PO E E' A B C sum_O_B by presburger
    have "B = C"
      using assms(1) assms(8) assms(9) par_strict_not_col_4 sum_O_B_eq by blast 
    have "B' = C'" 
    proof (rule l6_21 [of O' E' B B'])
      show "¬ Col O' E' B"
        by (metis Ar1_def assms(1) assms(2) par_strict_col_par_strict 
            par_strict_not_col_1 par_strict_not_col_4) 
      show "B  B'"
        using Ar1_def ¬ Col O' E' B assms(3) by blast 
      show "Col O' E' B'"
        using Ar1_def assms(3) by presburger 
      show "Col O' E' C'"
        using Ar1_def assms(3) by presburger 
      show "Col B B' B'"
        by (simp add: col_trivial_2) 
      show "Col B B' C'"
        by (metis Col_def Par_perm Pj_def B = C B  B' assms(6) assms(7) 
            grid_not_par_1 par_trans) 
    qed
    hence ?thesis
      by (metis Ar1_def NCol_cases A' = O' assms(1) assms(3) par_strict_not_col_2 sum_O_B) 
  }
  thus ?thesis
    using Sum_def assms(8) by blast 
qed

lemma change_grid_sum:
  assumes "PO E ParStrict O' E'"
    and "Ar1 PO E A B C"
    and "Ar1 O' E' A' B' C'" 
    and "PO O' Pj E E'"
    and "PO O' Pj A A'"
    and "PO O' Pj B B'"
    and "PO O' Pj C C'"
    and "Sum PO E E' A B C"
  shows "Sum O' E' E A' B' C'" 
proof (cases)
  assume "A = PO"
  thus ?thesis
    using assms(1) assms(2) assms(3) assms(4) assms(5) assms(6) assms(7) assms(8) 
      change_grid_sum_0 by blast 
next
  assume "A  PO"
  {
    assume "Ar2 PO E E' A B C"
    obtain A1 C1 where "E E' Pj A A1" and "Col PO E' A1" and "PO E Pj A1 C1" and 
      "PO E' Pj B C1" and "E' E Pj C1 C"
      using Sum_def assms(8) by blast 
    have "¬ PO E Par E E'  ¬ PO E Par PO E'  ¬ PO E' Par E E'  PO  E  PO  E'  E  E'"
      using assms(1) grid_not_par par_strict_not_col_4 by blast 
    have "¬ Col O' E' E"
      using assms(1) col_permutation_2 par_strict_not_col_2 by blast 
    hence "¬ O' E' Par E' E  ¬ O' E' Par O' E  ¬ O' E Par E' E  O'  E'  O'  E  E'  E"
      using grid_not_par by presburger 
    have ?thesis 
    proof (cases)
      assume "B = PO"
      thus ?thesis
        using Ar1_def Ar2_def Ar2 PO E E' A B C ¬ Col O' E' E assms(1) assms(2) assms(3) 
          assms(4) assms(5) assms(6) assms(7) assms(8) change_grid_sum_0 sum_comm by auto 
    next
      assume "B  PO"
      have "A'  PO"
        using Ar1_def assms(1) assms(3) par_strict_not_col_3 by force
      have "¬ Col PO A A'"
        by (metis Ar1_def Col_cases A  PO assms(1) assms(2) assms(3) l6_16_1 par_not_col) 
      have "A'  O'"
        using Pj_def ¬ Col PO A A' assms(5) grid_not_par by blast
      have "ParallelogramFlat PO A C B"
        using A  PO assms(1) assms(8) par_strict_not_col_4 sum_cong by blast 
      have "PO O' Proj O' E' E E'"
        by (metis Par_perm Pj_def 
            ¬ O' E' Par E' E  ¬ O' E' Par O' E  ¬ O' E Par E' E  O'  E'  O'  E  E'  E 
            assms(4) grid_not_par_4 pj_col_project)
      have "A A' Proj O' E' E E'"
        by (metis Ar1_def Pj_def Proj_def 
            ¬ O' E' Par E' E  ¬ O' E' Par O' E  ¬ O' E Par E' E  O'  E'  O'  E  E'  E 
            assms(3) assms(4) assms(5) par_right_comm par_symmetry par_trans) 
      have "C C' Proj O' E' E E'"
      proof -
        have "¬ O' E' Par E E'"
          by (meson ¬ Col O' E' E grid_not_par not_strict_par1) 
        moreover have "C C' Par E E'  C = C'"
          by (metis Pj_def 
              ¬ PO E Par E E'  ¬ PO E Par PO E'  ¬ PO E' Par E E'  PO  E  PO  E'  E  E' 
              assms(4) assms(7) par_symmetry par_trans) 
        ultimately show ?thesis
          using Ar1_def Proj_def 
            ¬ O' E' Par E' E  ¬ O' E' Par O' E  ¬ O' E Par E' E  O'  E'  O'  E  E'  E 
            assms(3) by auto 
      qed
      have "B B' Proj O' E' E E'" 
      proof -
        have "¬ O' E' Par E E'"
          using ¬ Col O' E' E col_trivial_2 inter_uniqueness_not_par by blast 
        moreover have "B B' Par E E'  B = B'"
          by (metis Par_def Pj_def 
              ¬ O' E' Par E' E  ¬ O' E' Par O' E  ¬ O' E Par E' E  O'  E'  O'  E  E'  E 
              assms(4) assms(6) not_par_inter_exists parallel_uniqueness)
        ultimately show ?thesis
          using Ar1_def Proj_def 
            ¬ O' E' Par E' E  ¬ O' E' Par O' E  ¬ O' E Par E' E  O'  E'  O'  E  E'  E 
            assms(3) by auto 
      qed
      have "PO A EqV B C"
        by (simp add: EqV_def Parallelogram_def ParallelogramFlat PO A C B)
      hence "O' A' EqV B' C'"
        using A A' Proj O' E' E E' B B' Proj O' E' E E' C C' Proj O' E' E E' 
          PO O' Proj O' E' E E' project_preserves_eqv by blast
      moreover {
        assume "Parallelogram O' A' C' B'"
        hence ?thesis
          by (metis Ar1_def Ar2_def Plg_perm ¬ Col O' E' E assms(3) plg_cong_2 
              plg_irreflexive sum_iff_cong) 
      }
      moreover {
        assume "O' = A'" and "B' = C'"
        hence ?thesis
          using A'  O' by auto 
      }
      ultimately show ?thesis
        using EqV_def by blast 
    qed
  }
  thus ?thesis
    using Sum_def assms(8) by blast 

qed

lemma double_null_null: 
  assumes "Sum PO E E' A A PO"
  shows "A = PO" 
proof (rule ccontr)
  assume "A  PO"
  hence "ParallelogramFlat PO A PO A"
    using Ar2_def Sum_def assms sum_cong by blast 
  thus False
    using plgf_irreflexive by blast 
qed

lemma not_null_double_not_null: 
  assumes "Sum PO E E' A A C"
    and "A  PO"
  shows "C  PO"
  using assms(1) assms(2) double_null_null by blast

lemma double_not_null_not_nul:
  assumes "Sum PO E E' A A C"
    and "C  PO"
  shows "A  PO"
  using Ar2_def Sum_def assms(1) assms(2) sum_O_B_eq by blast 

lemma diff_ar2:
  assumes "Diff PO E E' A B AMB"
  shows "Ar2 PO E E' A B AMB" 
proof -
  obtain MA where "Opp PO E E' B MA" and "Sum PO E E' A MA AMB"
    using Diff_def assms by blast
  thus ?thesis
    by (simp add: Ar2_def Opp_def Sum_def) 
qed

lemma diff_null:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A"
  shows "Diff PO E E' A A PO"
  by (meson Diff_def Opp_def grid_ok assms(2) opp_exists sum_comm)

lemma diff_exists: 
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A"
    and "Col PO E B"
  shows " D. Diff PO E E' A B D" 
proof -
  obtain MB where "Opp PO E E' B MB"
    using grid_ok assms(3) opp_exists by blast
  then obtain C where "Sum PO E E' A MB C"
    by (meson Ar2_def Opp_def Sum_def assms(2) sum_exists)
  thus ?thesis
    using Diff_def Opp PO E E' B MB by blast 
qed

lemma diff_uniqueness:
  assumes "Diff PO E E' A B D1"
    and "Diff PO E E' A B D2"
  shows "D1 = D2"
  by (metis Ar2_def Diff_def assms(1) assms(2) diff_ar2 opp_uniqueness sum_uniqueness)

lemma sum_ar2:
  assumes "Sum PO E E' A B C"
  shows "Ar2 PO E E' A B C"
  using Sum_def assms by blast 

lemma diff_A_O:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A"
  shows "Diff PO E E' A PO A"
  using Diff_def grid_ok assms(2) opp0 sum_A_O by blast 

lemma diff_O_A:
  assumes (*"¬ Col PO E E'"
and*) "Opp PO E E' A mA"
  shows "Diff PO E E' PO A mA"
  by (meson Ar2_def Diff_def Opp_def assms sum_O_B sum_ar2) 

lemma diff_O_A_opp:
  assumes "Diff PO E E' PO A mA"
  shows "Opp PO E E' A mA"
  by (metis Ar2_def Diff_def assms diff_ar2 sum_O_B_eq) 

lemma diff_uniquenessA:
  assumes "Diff PO E E' A B C"
    and "Diff PO E E' A' B C"
  shows "A = A'"
  by (metis Ar2_def Diff_def assms(1) assms(2) diff_ar2 opp_uniqueness sum_uniquenessA)

lemma diff_uniquenessB:
  assumes "Diff PO E E' A B C"
    and "Diff PO E E' A B' C"
  shows "B = B'"
  by (metis Ar2_def Diff_def assms(1) assms(2) diff_ar2 opp_comm opp_uniqueness sum_uniquenessB) 

lemma diff_null_eq:
  assumes "Diff PO E E' A B PO"
  shows "A = B"
  by (meson Ar2_def assms diff_ar2 diff_null diff_uniquenessB) 

lemma midpoint_opp: 
  assumes "Ar2 PO E E' PO A B"
    and "PO Midpoint A B"
  shows "Opp PO E E' A B" 
proof (cases)
  assume "A = B"
  thus ?thesis
    using Ar2_def assms(1) assms(2) l8_20_2 opp0 by blast 
next
  assume "A  B"
  moreover have "Ar2 PO E E' B A PO"
    using Ar2_def assms(1) by force 
  moreover have "Cong PO B A PO"
    using assms(2) cong_symmetry midpoint_cong by blast 
  moreover have "Cong PO A B PO"
    using calculation(3) cong_4321 by blast 
  ultimately show ?thesis
    by (simp add: Ar2_def Opp_def cong_sum) 
qed

lemma sum_diff:
  assumes "Sum PO E E' A B S"
  shows "Diff PO E E' S A B" 
proof -
  have "Ar2 PO E E' A B S"
    using assms sum_ar2 by auto 
  then obtain mA where "Opp PO E E' A mA"
    by (meson Ar2_def opp_exists) 
  moreover have "Sum PO E E' S mA B"
    by (meson Ar2_def Opp_def Ar2 PO E E' A B S assms calculation sum_O_B sum_assoc_2 sum_comm) 
  ultimately show ?thesis
    using Diff_def by auto 
qed

lemma diff_sum:
  assumes "Diff PO E E' S A B"
  shows "Sum PO E E' A B S"
  by (meson Ar2_def Diff_def Opp_def assms diff_ar2 sum_A_O sum_assoc_1 sum_comm) 

lemma diff_opp:
  assumes "Diff PO E E' A B AmB"
    and "Diff PO E E' B A BmA"
  shows "Opp PO E E' AmB BmA"
  by (meson Ar2_def Diff_def Opp_def assms(1) assms(2) diff_ar2 diff_sum sum_assoc sum_comm) 

lemma sum_stable:
  assumes "A = B" 
    and "Sum PO E E' A C S1"
    and "Sum PO E E' B C S2"
  shows "S1 = S2"
  using assms(1) assms(2) assms(3) diff_uniquenessA sum_diff by blast 

lemma diff_stable:
  assumes "A = B"
    and "Diff PO E E' A C D1"
    and "Diff PO E E' B C D2"
  shows "D1 = D2"
  using assms(1) assms(2) assms(3) diff_uniqueness by blast 

lemma plg_to_sum:
  assumes "Ar2 PO E E' A B C"
    and "ParallelogramFlat PO A C B"
  shows "Sum PO E E' A B C"
  by (metis Ar2_def assms(1) assms(2) not_cong_1243 plgf_cong plgf_irreflexive sum_iff_cong_a) 

lemma opp_midpoint:
  assumes "Opp PO E E' A MA"
  shows "PO Midpoint A MA" 
proof (cases)
  assume "A = PO"
  hence "MA = PO"
    by (metis Opp_def assms diff_null_eq local.sum_diff) 
  thus ?thesis
    by (simp add: A = PO l7_3_2) 
next
  assume "A  PO"
  thus ?thesis
    by (meson Ar2_def Mid_cases Opp_def assms plgf3_mid sum_ar2 sum_cong) 
qed

lemma diff_to_plg:
  assumes "A  PO  B  PO"
    and "Diff PO E E' B A dBA"
  shows "ParallelogramFlat PO A B dBA"
  by (metis Ar2_def assms(1) assms(2) diff_null_eq diff_sum sum_ar2 sum_cong) 

lemma sum3_col:
  assumes "sum3 PO E E' A B C S"
  shows "¬ Col PO E E'  Col PO E A  Col PO E B  Col PO E C  Col PO E S"
  by (meson Ar2_def assms sum3_def sum_ar2) 

lemma sum3_permut:
  assumes "sum3 PO E E' A B C S"
  shows "sum3 PO E E' C A B S"
  by (smt (verit, ccfv_SIG) assms sum3_col sum3_def sum_assoc sum_comm sum_exists) 

lemma sum3_comm_1_2:
  assumes "sum3 PO E E' A B C S"
  shows "sum3 PO E E' B A C S"
  by (meson assms sum3_col sum3_def sum_comm) 

lemma sum3_comm_2_3:
  assumes "sum3 PO E E' A B C S"
  shows "sum3 PO E E' A C B S"
  using assms sum3_comm_1_2 sum3_permut by blast 

lemma sum3_exists:
  assumes "Ar2 PO E E' A B C"
  shows " S. sum3 PO E E' A B C S"
  by (metis Ar2_def Sum_def assms sum3_def sum_exists) 

lemma sum3_uniqueness:
  assumes "sum3 PO E E' A B C S1"
    and "sum3 PO E E' A B C S2"
  shows "S1 = S2"
  by (metis assms(1) assms(2) sum3_def sum_stable) 

lemma sum4_col:
  assumes "Sum4 PO E E' A B C D S"
  shows "¬ Col PO E E'  Col PO E A  Col PO E B  Col PO E C  Col PO E D  Col PO E S"
  by (meson assms sum3_col sum3_def sum4_def) 

lemma sum22_col:
  assumes "sum22 PO E E' A B C D S"
  shows "¬ Col PO E E'  Col PO E A  Col PO E B  Col PO E C  Col PO E D  Col PO E S"
  by (meson Ar2_def assms sum22_def sum_ar2) 

lemma sum_to_sum3:
  assumes "Sum PO E E' A B AB"
    and "Sum PO E E' AB X S"
  shows "sum3 PO E E' A B X S"
  using assms(1) assms(2) sum3_def by blast 

lemma sum3_to_sum4:
  assumes "sum3 PO E E' A B C ABC"
    and "Sum PO E E' ABC X S"
  shows "Sum4 PO E E' A B C X S"
  using assms(1) assms(2) sum4_def by blast 

lemma sum_A_exists:
  assumes "Ar2 PO E E' A AB PO"
  shows " B. Sum PO E E' A B AB"
  by (meson Ar2_def assms diff_exists diff_sum) 

lemma sum_B_exists:
  assumes "Ar2 PO E E' B AB PO"
  shows " A. Sum PO E E' A B AB"
  using Ar2_def assms sum_A_exists sum_comm by blast 

lemma sum4_equiv_a:
  assumes "Sum4 PO E E' A B C D S"
  shows "sum22 PO E E' A B C D S" 
proof -
  obtain AB where "Sum PO E E' A B AB"
    using assms sum4_col sum_exists by blast 
  obtain CD where "Sum PO E E' C D CD"
    using assms sum4_col sum_exists by blast 
  have "Sum PO E E' AB CD S" 
  proof -
    have "Ar2 PO E E' A B AB"
      by (simp add: Sum PO E E' A B AB sum_ar2) 
    moreover have "Ar2 PO E E' C D CD"
      by (simp add: Sum PO E E' C D CD sum_ar2) 
    ultimately show ?thesis
      by (smt (verit, best) Sum PO E E' A B AB Sum PO E E' C D CD assms 
          sum4_col sum3_def sum4_def sum_assoc_2 sum_uniqueness) 
  qed
  thus ?thesis
    using Sum PO E E' A B AB Sum PO E E' C D CD sum22_def by blast 
qed

lemma sum4_equiv_b:
  assumes "sum22 PO E E' A B C D S"
  shows "Sum4 PO E E' A B C D S"
proof -
  obtain AB CD where "Sum PO E E' A B AB" and "Sum PO E E' C D CD" and "Sum PO E E' AB CD S"
    using assms sum22_def by blast 
  have "Ar2 PO E E' A B AB"
    using Sum_def Sum PO E E' A B AB by blast 
  have "Ar2 PO E E' C D CD"
    by (simp add: Sum PO E E' C D CD sum_ar2) 
  obtain ABC where "Sum PO E E' AB C ABC"
    using Ar2_def Ar2 PO E E' A B AB Ar2 PO E E' C D CD sum_exists by presburger
  thus ?thesis
    by (meson Sum PO E E' A B AB Sum PO E E' AB CD S Sum PO E E' C D CD 
        sum3_to_sum4 sum_assoc_1 sum_to_sum3) 
qed

lemma sum4_equiv:
  shows "Sum4 PO E E' A B C D S  sum22 PO E E' A B C D S"
  using sum4_equiv_a sum4_equiv_b by blast 

lemma sum4_permut: 
  assumes "Sum4 PO E E' A B C D S"
  shows "Sum4 PO E E' D A B C S" 
proof -
  have "sum22 PO E E' A B C D S"
    using assms sum4_equiv by auto 
  then obtain AB CD where "Sum PO E E' A B AB" and "Sum PO E E' C D CD" and 
    "Sum PO E E' AB CD S"
    using sum22_def by blast 
  obtain ABC where "sum3 PO E E' A B C ABC" and "Sum PO E E' ABC D S"
    using assms sum4_def by blast 
  then obtain AC where "Sum PO E E' C A AC" and "Sum PO E E' AC B ABC"
    using sum3_def sum3_permut by blast 
  obtain AD where "Sum PO E E' D A AD"
    using assms sum4_col sum_exists by blast
  then obtain ABD where "Sum PO E E' AD B ABD"
    using Ar2_def Sum PO E E' AC B ABC sum_ar2 sum_exists by presburger 
  thus ?thesis
    by (smt (verit, ccfv_threshold) Sum PO E E' ABC D S Sum PO E E' D A AD 
        sum3 PO E E' A B C ABC sum3_col sum3_def sum4_def sum_assoc_2 sum_comm) 
qed

(* a + b + c + d = d + a + b + c *)
lemma sum22_permut: 
  assumes "sum22 PO E E' A B C D S"
  shows "sum22 PO E E' D A B C S"
  using assms sum4_equiv sum4_permut by presburger 

lemma sum4_comm:
  assumes "Sum4 PO E E' A B C D S"
  shows "Sum4 PO E E' B A C D S"
  by (meson assms sum3_comm_1_2 sum4_def) 

(* a + b + c + d = b + a + c + d *)
lemma sum22_comm: 
  assumes "sum22 PO E E' A B C D S"
  shows "sum22 PO E E' B A C D S"
  by (meson assms sum4_comm sum4_equiv_a sum4_equiv_b) 

(* a + b + c + d = b  c + a + d *)
lemma sum_abcd:
  assumes "Sum PO E E' A B AB"
    and "Sum PO E E' C D CD"
    and "Sum PO E E' B C BC"
    and "Sum PO E E' A D AD"
    and "Sum PO E E' AB CD S"
  shows "Sum PO E E' BC AD S" 
proof -
  have "sum22 PO E E' A B C D S"
    using assms(1) assms(2) assms(5) sum22_def by blast 
  then obtain AD' BC' where "Sum PO E E' D A AD'" and "Sum PO E E' B C BC'" and 
    "Sum PO E E' AD' BC' S"
    using sum22_def sum22_permut by blast 
  thus ?thesis
    by (metis sum22 PO E E' A B C D S assms(3) assms(4) sum22_col sum_comm sum_stable) 
qed

(* (b - a) + (c - b) = (c - a) *)
lemma sum_diff_diff_a:
  assumes "Diff PO E E' B A dBA"
    and "Diff PO E E' C B dCB"
    and "Diff PO E E' C A dCA"
  shows "Sum PO E E' dCB dBA dCA"
  by (smt (verit) Ar2_def Diff_def assms(1) assms(2) assms(3) diff_ar2 diff_sum 
      opp_uniqueness sum_assoc sum_comm) 

lemma sum_diff_diff_b:
  assumes "Diff PO E E' B A dBA"
    and "Diff PO E E' C B dCB"
    and "Sum PO E E' dCB dBA dCA"
  shows "Diff PO E E' C A dCA"
  by (meson Ar2_def assms(1) assms(2) assms(3) diff_sum sum_diff sum_ar2 sum_assoc_2 sum_comm) 

(* (x + y) - (a + b) = (x - a) + (y - b) *)
lemma sum_diff2_diff_sum2_a:
  assumes "Sum PO E E' A B C"
    and "Sum PO E E' X Y Z"
    and "Diff PO E E' X A dXA"
    and "Diff PO E E' Y B dYB"
    and "Sum PO E E' dXA dYB dZC"
  shows "Diff PO E E' Z C dZC" 
proof -
  obtain Z' where "Sum PO E E' C dZC Z'"
    using Ar2_def Sum_def assms(1) assms(5) sum_exists by presburger 
  then obtain Y' X' where "Sum PO E E' B dYB Y'" and "Sum PO E E' A dXA X'" and 
    "Sum PO E E' Y' X' Z'"
    by (smt (verit, ccfv_threshold) Ar2_def assms(1) assms(3) assms(4) assms(5) diff_sum 
        sum_abcd sum_ar2 sum_comm)
  thus ?thesis
    by (metis Sum PO E E' C dZC Z' assms(2) assms(3) assms(4) diff_sum sum_diff sum3_col 
        sum_comm sum_stable sum_to_sum3) 
qed

lemma sum_diff2_diff_sum2_b:
  assumes "Sum PO E E' A B C"
    and "Sum PO E E' X Y Z"
    and "Diff PO E E' X A dXA"
    and "Diff PO E E' Y B dYB"
    and "Diff PO E E' Z C dZC"
  shows "Sum PO E E' dXA dYB dZC" 
proof -
  obtain dZC' where "Sum PO E E' dXA dYB dZC'"
    by (meson Ar2_def diff_sum Tarski_Euclidean_2D_axioms assms(3) assms(4) sum_ar2 sum_exists) 
  thus ?thesis
    by (smt (verit, ccfv_SIG) assms(1) assms(2) assms(3) assms(4) assms(5) diff_stable 
        sum_diff2_diff_sum2_a) 
qed

lemma sum_opp:
  assumes "Sum PO E E' X MX PO"
  shows "Opp PO E E' X MX"
  by (simp add: Opp_def assms diff_O_A diff_sum) 

lemma sum_diff_diff:
  assumes "Diff PO E E' AX BX AXMBX"
    and "Diff PO E E' AX CX AXMCX"
    and "Diff PO E E' BX CX BXMCX"
  shows "Sum PO E E' AXMBX BXMCX AXMCX"
  using assms(1) assms(2) assms(3) sum_diff_diff_a by blast 

lemma prod_to_prodp:
  assumes "Prod PO E E' A B C"
  shows "Prodp PO E E' A B C" 
proof -
  obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' C"
    using Prod_def assms by blast 
  hence "B B' Proj PO E' E E'"
    by (metis Ar2_def Prod_def assms grid_not_par not_col_permutation_1 pj_col_project) 
  moreover have "B' C Proj PO E A E'" 
  proof (cases)
    assume "A = PO"
    thus ?thesis
      by (metis Ar2_def Prod_def E' A Pj B' C assms grid_not_par 
          not_col_permutation_1 pj_col_project pj_left_comm) 
  next
    assume " A  PO"
    thus ?thesis
      by (metis Ar2_def Col_cases Par_cases Par_def Pj_def Prod_def E' A Pj B' C
          assms col_trivial_1 par_col_project par_strict_not_col_2 project_trivial) 
  qed
  ultimately show ?thesis
    using Ar2_def Prod_def Prodp_def assms by auto 
qed

lemma project_pj:
  assumes "P P' Proj A B X Y"
  shows "X Y Pj P P'"
  using Par_cases Pj_def Proj_def assms by auto 

lemma prodp_to_prod:
  assumes "Prodp PO E E' A B C"
  shows "Prod PO E E' A B C" 
proof -
  obtain B' where "B B' Proj PO E' E E'" and "B' C Proj PO E A E'"
    using Prodp_def assms by blast
  have "E E' Pj B B'"
    using B B' Proj PO E' E E' project_pj by auto 
  moreover have "Col PO E' B'"
    using Proj_def B B' Proj PO E' E E' by presburger 
  moreover have "E' A Pj B' C"
    using B' C Proj PO E A E' pj_left_comm project_pj by blast 
  ultimately show ?thesis
    by (metis Ar2_def Par_def Prod_def Prodp_def Proj_def assms grid_not_par_5) 
qed

lemma prod_exists:
  assumes grid_ok: "¬ Col PO E E'"
    and "Col PO E A" 
    and "Col PO E B"
  shows " C. Prod PO E E' A B C"
  by (metis Prodp_def Par_def assms(2) assms(3) grid_not_par grid_ok not_col_permutation_2 
      par_strict_not_col_3 prodp_to_prod project_existence) 

lemma prod_uniqueness:
  assumes grid_ok: "¬ Col PO E E'"
    and "Prod PO E E' A B C1" 
    and "Prod PO E E' A B C2"
  shows "C1 = C2" 
proof -
  obtain B' where "B B' Proj PO E' E E'" and "B' C1 Proj PO E A E'"
    using Prodp_def assms(2) prod_to_prodp by blast
  obtain B'' where "B B'' Proj PO E' E E'" and "B'' C2 Proj PO E A E'"
    using Prodp_def assms(3) prod_to_prodp by blast 
  thus ?thesis
    by (metis B B' Proj PO E' E E' B' C1 Proj PO E A E' project_uniqueness) 
qed

(** Lemma 14.17 *)
lemma prod_0_l:
  assumes "¬ Col PO E E'"
    and "Col PO E A"
  shows "Prod PO E E' PO A PO" 
proof (cases)
  assume "A = PO"
  thus ?thesis
    by (metis Ar2_def Pj_def Prod_def assms(1) grid_not_par_5) 
next
  assume "A  PO"
  obtain B' where "A B' Proj PO E' E E'"
    by (metis Par_cases assms(1) grid_not_par project_existence) 
  hence "E E' Pj A B'"
    using project_pj by auto 
  moreover have "Col PO E' B'"
    using Proj_def A B' Proj PO E' E E' by presburger 
  moreover have "E' PO Pj B' PO"
    by (metis Par_cases Pj_def not_col_distincts assms(1) calculation(2) not_par_not_col) 
  ultimately show ?thesis
    using Ar2_def Prod_def assms(1) assms(2) col_trivial_3 by auto 
qed

lemma prod_0_r:
  assumes "¬ Col PO E E'"
    and "Col PO E A"
  shows "Prod PO E E' A PO PO"
  using Ar2_def Pj_def Prod_def assms(1,2) col_trivial_3 by auto 

(** Lemma 14.18 *)
lemma prod_1_l:
  assumes "¬ Col PO E E'"
    and "Col PO E A"
  shows "Prod PO E E' E A A" 
proof -
  obtain B' where "A B' Proj PO E' E E'"
    by (metis assms(1) grid_not_par par_symmetry project_existence)
  moreover
  {
    assume "A B' Par E E'"
    hence "Prod PO E E' E A A"
      by (metis Par_cases Prodp_def assms(1,2) calculation not_col_distincts par_col_project
          par_id_5 prodp_to_prod)
  }
  moreover
  {
    assume "A = B'"
    hence "Prod PO E E' E A A"
      by (metis assms(1,2) calculation(1) not_col_distincts prod_0_r proj_id) 
  }
  ultimately show ?thesis
    using project_par_dir by blast 
qed

lemma prod_1_r:
  assumes "¬ Col PO E E'"
    and "Col PO E A"
  shows "Prod PO E E' A E A"
  by (metis Ar2_def Pj_def Prod_def assms(1,2) grid_not_par not_par_not_col) 

(** Lemma 14.19 *)
lemma inv_exists:
  assumes "¬ Col PO E E'"
    and "Col PO E A"
    and "A  PO"
  shows " IA. Prod PO E E' IA A E" 
proof -
  obtain B' where "A B' Proj PO E' E E'"
    by (meson Prodp_def assms(1,2) prod_0_l prod_to_prodp) 
  have "B'  PO"
    using A B' Proj PO E' E E' assms(1,2,3) grid_not_par_5 proj_id by blast
  obtain IA where "E' IA Proj PO E B' E"
    by (metis NCol_cases A B' Proj PO E' E E' assms(1,2,3) grid_not_par proj_id
        project_existence) 
  moreover have "E E' Pj A B'"
    using A B' Proj PO E' E E' project_pj by auto 
  moreover have "Col PO E' B'"
    using Proj_def A B' Proj PO E' E E' by auto 
  moreover have "E' IA Pj B' E"
    using Pj_def Proj_def assms(1) calculation(1) by auto 
  ultimately show ?thesis
    using Ar2_def Prod_def Proj_def assms(1,2) col_trivial_2 by auto 
qed

(** Lemma 14.20 *)
(** The choice of E' does not affect product *)
lemma prod_null:
  assumes "Prod PO E E' A B PO"
  shows "A = PO  B = PO" 
proof -
  obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' PO"
    using Prod_def assms by blast
  show ?thesis
  proof (cases)
    assume "B = PO"
    thus ?thesis
      by simp 
  next
    assume "B  PO"
    {
      assume "E E' Par B B'"
      {
        assume "E' A Par B' PO"
        hence "A = PO"
          by (metis Ar2_def Col_cases Par_def Prod_def Col PO E' B' assms col_trivial_3
              not_strict_par2) 
      }
      moreover
      {
        assume "B' = PO"
        hence "A = PO"
          by (metis Ar2_def Prod_def E E' Par B B' assms col_permutation_2 grid_not_par
              par_col2_par_bis) 
      }
      ultimately have "A = PO"
        using Pj_def E' A Pj B' PO by blast 
    }
    moreover {
      assume "B = B'"
      hence "A = PO"
        by (metis Ar2_def NCol_cases Prod_def B  PO Col PO E' B' assms
            colx) 
    }
    ultimately have "A = PO"
      using Pj_def E E' Pj B B' by blast 
    thus ?thesis
      by simp 
  qed
qed

lemma prod_y_axis_change:
  assumes "Prod PO E E' A B C"
    and "¬ Col PO E E''"
  shows "Prod PO E E'' A B C" 
proof (cases "B = PO")
  show "B = PO  Prod PO E E'' A B C"
    by (metis Ar2_def Prod_def assms(1,2) prod_0_r
        prod_uniqueness) 
  {
    assume "B  PO"
    obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' C"
      using Prod_def assms(1) by blast 
    show "Prod PO E E'' A B C" 
    proof (cases "A = PO")
      show "A = PO  Prod PO E E'' A B C"
        by (metis Ar2_def Prod_def assms(1,2) prod_0_l
            prod_uniqueness) 
      {
        assume "A  PO"
        have "C  PO"
          using A  PO B  PO assms(1) prod_null by blast 
        obtain B'' where "B B'' Proj PO E'' E E''"
          by (metis Par_cases assms(2) col_trivial_2 col_trivial_3
              grid_not_par_3 project_existence) 
        hence "B B'' Par E E''"
          by (metis Prodp_def B  PO assms(1,2) prod_to_prodp proj_id
              project_par_dir)
        have "E E'' Pj B B''"
          using B B'' Proj PO E'' E E'' project_pj by auto 
        moreover have "Col PO E'' B''"
          using Proj_def B B'' Proj PO E'' E E'' by force 
        moreover have "E'' A Pj B'' C" 
        proof (cases "B = E")
          show "B = E  E'' A Pj B'' C"
            by (metis Ar2_def Col_cases Par_def Pj_def Prod_def
                B B'' Par E E'' assms(1,2) calculation(2) col2__eq
                par_id_3 prod_1_r prod_uniqueness) 
          {
            assume "B  E"
            have "E' A Par B' C"
              by (metis Ar2_def NCol_cases Pj_def Prod_def C  PO
                  Col PO E' B' E' A Pj B' C assms(1) col_trivial_3
                  colx) 
            have "B B'' ParStrict E E''"
              by (meson Par_def Prodp_def B B'' Par E E'' B  E
                  assms(1,2) col_trivial_2 colx prod_to_prodp)
            have "E E' Par B B'"
              by (metis Ar2_def NCol_cases Pj_def Prod_def B  PO
                  Col PO E' B' E E' Pj B B' assms(1) col_trivial_3
                  colx)
            hence "E E' ParStrict B B'"
              by (metis Ar2_def NCol_cases Par_def Prod_def B  E
                  assms(1) col_trivial_3 colx)
            have "E' A ParStrict B' C"
              by (metis (no_types, lifting) Ar2_def Par_def Prod_def
                  C  PO Col PO E' B' E E' ParStrict B B'
                  E' A Par B' C assms(1) grid_not_par l6_21
                  par_strict_not_col_1) 
            show "E'' A Pj B'' C" 
            proof (cases "A = E")
              show "A = E  E'' A Pj B'' C"
                by (metis Ar2_def Prod_def assms(1) calculation(1) pj_comm
                    prod_uniqueness) 
              {
                assume "A  E"
                have "B'  PO"
                  by (metis NCol_cases Prodp_def E E' ParStrict B B' assms(1)
                      par_strict_not_col_3 prod_to_prodp) 
                show "E'' A Pj B'' C" 
                proof (cases "E' = E''")
                  show "E' = E''  E'' A Pj B'' C"
                    by (metis Prodp_def Col PO E' B' E E' Pj B B'
                        E' A Pj B' C assms(1,2) calculation(1,2) pj_uniqueness
                        prod_to_prodp) 
                  {
                    assume "E'  E''"
                    show "E'' A Pj B'' C" 
                    proof (cases "Col E E' E''")
                      {
                        assume "Col E E' E''" 
                        hence "¬ Col E' E'' A"
                          by (metis Prodp_def A  E E'  E''
                              assms(1,2) col2__eq col_permutation_1
                              prod_to_prodp) 
                        have "B'  B''"
                          by (metis B'  PO Col E E' E'' Col PO E' B' E'  E''
                              assms(2) calculation(2) col2__eq col_permutation_5
                              colx)
                        have "E' E'' Par B' B''"
                          by (smt (verit, ccfv_threshold) Par_perm B B'' Par E E''
                              B'  B'' Col E E' E'' E E' Par B B' E'  E''
                              col_par_par_col col_trivial_2 not_col_permutation_2
                              par_col4__par)
                        have "B'  E'"
                          using E' A ParStrict B' C not_par_strict_id by auto 
                        have "E' E'' ParStrict B' B''"
                          by (metis NCol_cases Par_def Col E E' E''
                              E E' ParStrict B B' E' E'' Par B' B'' l6_16_1
                              par_strict_not_col_4) 
                        have "Coplanar PO E'' E' A"
                          by (simp add: all_coplanar) 
                        moreover have "Col PO A C"
                          by (metis Ar2_def Col_cases Prod_def assms(1) col3
                              col_trivial_3)
                        ultimately have "E'' A Par B'' C" 
                          using l13_15 [of E' _ _ PO B'] ¬ Col E' E'' A 
                            E' E'' ParStrict B' B'' E' A ParStrict B' C 
                            Col PO E' B' Col PO E'' B'' by blast
                        thus "E'' A Pj B'' C"
                          by (simp add: Pj_def) 
                      }
                      {
                        assume "¬ Col E E' E''"
                        have "E'' E' Par B'' B'" 
                          using l13_15 [of E E'' _ PO B]
                          by (meson Par_strict_cases Prodp_def B B'' ParStrict E E''
                              Col PO E' B' E E' ParStrict B B' ¬ Col E E' E''
                              all_coplanar assms(1) calculation(2) col_permutation_5
                              prod_to_prodp) 
                        show "E'' A Pj B'' C" 
                        proof (cases "Col A E' E''")
                          {
                            assume"Col A E' E''"
                            hence "B' C Par E' E''"
                              by (metis Par_cases E' A Par B' C E'  E''
                                  col_par par_distinct par_not_par)
                            have "B' C Par B' B''"
                            proof (rule par_trans [of B' C E' E'' B' B''])
                              show "B' C Par E' E''"
                                by (simp add: B' C Par E' E'') 
                              show "E' E'' Par B' B''"
                                by (simp add: E'' E' Par B'' B' par_comm) 
                            qed
                            show "E'' A Pj B'' C"
                              by (smt (verit, best) Ar2_def Pj_def Prod_def
                                  B' C Par B' B'' Col A E' E'' E' A Par B' C assms(1,2)
                                  col_par_par_col col_permutation_4 l6_16_1 par_col4__par
                                  par_comm par_right_comm par_trans) 
                          }
                          {
                            assume "¬ Col A E' E''"
                            have "B'  E'"
                              using E' A ParStrict B' C not_par_strict_id by blast 
                            have "B''  E''"
                              using B B'' ParStrict E E'' col_trivial_2 
                                par_strict_not_col_4 by blast 
                            {
                              assume "E'' E' ParStrict B'' B'"
                              have "E'' A Par B'' C" 
                                using l13_15 [of E' E'' A PO B' B'' C]
                                by (metis Ar2_def NCol_cases Par_strict_cases Prod_def
                                    Col PO E' B' E' A ParStrict B' C
                                    E'' E' ParStrict B'' B' ¬ Col A E' E''
                                    all_coplanar assms(1) calculation(2)
                                    col_transitivity_1 col_trivial_3) 
                              hence "E'' A Pj B'' C"
                                by (simp add: Pj_def) 
                            }
                            moreover
                            {
                              assume "E''  E'" and "B''  B'" and "Col E'' B'' B'" and 
                                "Col E' B'' B'"
                              have "E'' A Pj B'' C" 
                              proof (cases "Col PO E' E''")
                                {
                                  assume "Col PO E' E''"
                                  have "A E'' Par C B''"
                                  proof (rule l13_19 [of PO E E' B])
                                    show "¬ Col PO E E'"
                                      using Ar2_def Prod_def assms(1) by presburger 
                                    show "PO  E"
                                      using Col PO E' E'' ¬ Col E E' E'' by auto 
                                    show "PO  B"
                                      using B  PO by auto 
                                    show "PO  A"
                                      using A  PO by auto 
                                    show "PO  C"
                                      using C  PO by auto
                                    show "PO  E'"
                                      using ¬ Col PO E E' grid_not_par_5 by blast
                                    show "PO  B'"
                                      using B'  PO by auto 
                                    show "PO  E''"
                                      using assms(2) grid_not_par_5 by auto 
                                    show "PO  B''"
                                      by (metis Prodp_def B B'' Proj PO E'' E E'' 
                                          B  PO assms(1,2)
                                          col_trivial_3 prod_to_prodp proj_id) 
                                    show "Col PO E A"
                                      using Prodp_def assms(1) prod_to_prodp by blast 
                                    show "Col PO E B"
                                      using Prodp_def assms(1) prod_to_prodp by blast 
                                    show "Col PO E C"
                                      using Ar2_def Prod_def assms(1) by presburger 
                                    show "Col PO E' E''"
                                      by (simp add: Col PO E' E'') 
                                    show "Col PO E' B'"
                                      by (simp add: Col PO E' B') 
                                    show "Col PO E' B''"
                                      by (metis Col PO E' E'' Col PO E'' B'' assms(2) 
                                          col_trivial_3
                                          colx) 
                                    show "E E' Par B B'"
                                      by (simp add: E E' Par B B') 
                                    show "E E'' Par B B''"
                                      by (simp add: B B'' Par E E'' par_symmetry) 
                                    show "E' A Par B' C"
                                      by (simp add: E' A Par B' C) 
                                  qed
                                  hence "E'' A Par B'' C"
                                    using par_comm by blast 
                                  thus "E'' A Pj B'' C"
                                    by (simp add: Pj_def)

                                }
                                show "¬ Col PO E' E''  E'' A Pj B'' C"
                                  by (metis B''  B' B''  E'' Col E' B'' B' 
                                      Col E'' B'' B' Col PO E'' B'' 
                                      col2__eq col_permutation_2) 
                              qed
                            }
                            ultimately show "E'' A Pj B'' C"
                              using Par_def E'' E' Par B'' B' by presburger 
                          }
                        qed
                      }
                    qed
                  }
                qed
              }
            qed
          }
        qed
        show "Prod PO E E'' A B C"
          using Ar2_def Prod_def E'' A Pj B'' C assms(1,2)
            calculation(1,2) by auto 
      }
    qed
  }
qed

(** Lemma 14.22 *)
(** Parallel projection on the second axis preserves products. *)
lemma proj_preserves_prod:
  assumes "Prod PO E E' A B C"
    and "Ar1 PO E' A' B' C'"
    and "E E' Pj A A'"
    and "E E' Pj B B'"
    and "E E' Pj C C'"
  shows "Prod PO E' E A' B' C'" 
proof (cases "A = PO")
  have "Ar2 PO E E' A B C"
    using Prod_def assms(1) by blast 
  show "A = PO  Prod PO E' E A' B' C'"
    by (metis Ar1_def Ar2_def Col_cases Prod_def assms(1,2,3,5) pj_comm
        prod_0_l prod_uniqueness sum_par_strict_a) 
  {
    assume "A  PO"
    show "Prod PO E' E A' B' C'" 
    proof (cases "B = PO")
      show "B = PO  Prod PO E' E A' B' C'"
        by (metis Ar1_def Ar2_def Col_cases Ar2 PO E E' A B C assms(1,2,4,5)
            col_trivial_3 pj_trivial pj_uniqueness prod_0_r
            prod_uniqueness) 
      {
        assume "B  PO"
        show "Prod PO E' E A' B' C'" 
        proof(cases "C = PO")
          show "C = PO  Prod PO E' E A' B' C'"
            using A  PO B  PO assms(1) prod_null by blast
          {
            assume "C  PO"
            show "Prod PO E' E A' B' C'" 
            proof (cases "A' = PO")
              show "A' = PO  Prod PO E' E A' B' C'"
                using Ar2_def A  PO Ar2 PO E E' A B C assms(3) sum_par_strict_a
                by blast 
              {
                assume "A'  PO"
                show "Prod PO E' E A' B' C'" 
                proof (cases "B' = PO")
                  show "B' = PO  Prod PO E' E A' B' C'"
                    by (metis Ar2_def NCol_cases Ar2 PO E E' A B C B  PO assms(4)
                        col_trivial_3 pj_comm pj_trivial pj_uniqueness) 
                  {
                    assume "B'  PO"
                    show "Prod PO E' E A' B' C'"
                    proof (cases "C' = PO")
                      show "C' = PO  Prod PO E' E A' B' C'"
                        by (metis Ar2_def Col_cases Par_cases Par_def Pj_def Ar2 PO E E' A B C
                            C  PO assms(5) par_strict_not_col_1) 
                      {
                        assume "C'  PO"
                        obtain B'' where "E E' Pj B B''" and "Col PO E' B''" and "E' A Pj B'' C"
                          using Prod_def assms(1) by blast
                        hence "B' = B''"
                          by (meson Ar1_def Ar2_def Prod_def assms(1,2,4) pj_uniqueness)
                        have "E' E Pj B' B"
                          by (simp add: B' = B'' E E' Pj B B'' pj_comm) 
                        moreover have "Col PO E B"
                          using Ar2_def Ar2 PO E E' A B C by blast 
                        moreover have "A' E Par C' B"
                        proof (rule l13_19 [of PO E' A B'])
                          show "¬ Col PO E' A"
                            by (metis Ar2_def Col_cases A  PO
                                Ar2 PO E E' A B C col2__eq) 
                          show "PO  E'"
                            using ¬ Col PO E' A col_trivial_1 by blast 
                          show "PO  B'"
                            using B'  PO by auto 
                          show "PO  A'"
                            using A'  PO by auto 
                          show "PO  C'"
                            using C'  PO by auto 
                          show "PO  A"
                            using A  PO by auto 
                          show "PO  C"
                            using C  PO by blast 
                          show "PO  E"
                            using Ar2_def Ar2 PO E E' A B C col_trivial_1 by force 
                          show "PO  B"
                            using B  PO by auto 
                          show "Col PO E' A'"
                            using Ar1_def assms(2) by force 
                          show "Col PO E' B'"
                            by (simp add: B' = B'' Col PO E' B'') 
                          show "Col PO E' C'"
                            using Ar1_def assms(2) by auto 
                          show "Col PO A E"
                            by (meson Ar2_def Col_cases Ar2 PO E E' A B C) 
                          show "Col PO A C"
                            by (metis Ar2_def Col_cases Ar2 PO E E' A B C PO  E
                                col2__eq) 
                          show "Col PO A B"
                            using Col PO A E PO  E calculation(2) col_trivial_3 colx
                            by blast 
                          show "E' A Par B' C"
                            by (smt (verit, ccfv_threshold) Pj_def B' = B'' Col PO A C
                                Col PO E' B'' E' A Pj B'' C PO  B'
                                ¬ Col PO E' A grid_not_par
                                not_par_not_col not_par_one_not_par) 
                          show "E' E Par B' B"
                            by (smt (verit, ccfv_threshold) Pj_def B' = B'' Col PO A B
                                Col PO E' B'' PO  B' ¬ Col PO E' A
                                calculation(1) grid_not_par
                                not_par_not_col not_par_one_not_par) 
                          show "A A' Par C C'"
                            by (smt (verit, best) Ar1_def Par_cases Pj_def E' A Par B' C
                                ¬ Col PO E' A assms(2,3,5) grid_not_par not_par_one_not_par
                                par_col2_par_bis) 
                        qed
                        hence "E A' Par B C'"
                          using par_comm by blast 
                        hence "E A' Pj B C'"
                          by (simp add: Pj_def) 
                        ultimately show "Prod PO E' E A' B' C'"
                          by (metis Ar1_def Ar2_def Col_cases Prod_def assms(1,2)) 
                      }
                    qed
                  }
                qed
              }
            qed
          }
        qed
      }
    qed
  }
qed

(** Lemma 14.23 *)
(** Product is associative.*)
lemma prod_assoc1:
  assumes "Prod PO E E' A B AB"
    and "Prod PO E E' B C BC"
    and "Prod PO E E' A BC ABC"
  shows "Prod PO E E' AB C ABC" 
proof (cases "A = PO")
  have "Ar2 PO E E' A B AB" 
    using Prod_def assms(1) by blast 
  have "Ar2 PO E E' B C BC"
    using Prod_def assms(2) by blast 
  have "Ar2 PO E E' A BC ABC" 
    using Prod_def assms(3) by auto 
  show "A = PO  Prod PO E E' AB C ABC"
    by (metis Ar2_def Ar2 PO E E' B C BC assms(1,3) prod_0_l
        prod_uniqueness)
  {
    assume "A  PO"
    show "Prod PO E E' AB C ABC" 
    proof (cases "B = PO")
      show "B = PO  Prod PO E E' AB C ABC"
        by (metis Ar2_def Ar2 PO E E' A B AB Ar2 PO E E' B C BC assms(1,2,3)
            prod_0_l prod_0_r prod_uniqueness) 
      {
        assume "B  PO"
        show "Prod PO E E' AB C ABC" 
        proof (cases "C = PO")
          show "C = PO  Prod PO E E' AB C ABC"
            by (metis Ar2_def Ar2 PO E E' A B AB assms(2,3) prod_0_r
                prod_uniqueness) 
          {
            assume "C  PO"
            have "¬ PO E Par E E'"
              using Ar2_def Ar2 PO E E' B C BC grid_not_par
              by blast 
            have "¬ PO E Par PO E'"
              using Ar2_def Ar2 PO E E' B C BC grid_not_par_2 by blast 
            have "PO  E"
              using Ar2_def Ar2 PO E E' A B AB not_col_distincts by blast 
            hence "PO  E'"
              using Par_cases ¬ PO E Par E E' par_reflexivity by blast 
            hence "E  E'"
              using ¬ PO E Par PO E' par_reflexivity by blast 
            obtain C' where "C C' Proj PO E' E E'"
              using Prodp_def assms(2) prod_to_prodp by blast 
            hence "C C' Par E E'"
              by (metis Ar2_def Ar2 PO E E' B C BC C  PO proj_id
                  project_par_dir) 
            hence "E E' Pj C C'"
              by (simp add: Pj_def par_symmetry) 
            moreover have "Col PO E' C'"
              using Proj_def C C' Proj PO E' E E' by presburger 
            moreover have "E' AB Pj C' ABC" 
            proof -
              obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' AB"
                using Prod_def assms(1) by blast
              obtain C'' where "E E' Pj C C''" and "Col PO E' C''" and "E' B Pj C'' BC"
                using Prod_def assms(2) by blast
              hence "C' = C''"
                using Ar2_def Ar2 PO E E' B C BC calculation(1,2) pj_uniqueness by auto 
              obtain BC' where "E E' Pj BC BC'" and "Col PO E' BC'" and "E' A Pj BC' ABC"
                using Prod_def assms(3) by blast
              have "B'  PO"
                using Ar2_def Ar2 PO E E' B C BC B  PO E E' Pj B B'
                  sum_par_strict_a by blast
              have "BC  PO"
                using B  PO C  PO assms(2) prod_null by blast
              have "E' AB Par C' ABC"
              proof (rule l13_19 [of PO B' B BC'])
                show "¬ Col PO B' B"
                  by (metis Ar2_def Ar2 PO E E' A B AB B  PO
                      B'  PO Col PO E' B' l6_16_1
                      not_col_permutation_4) 
                show "PO  B'"
                  using B'  PO by auto 
                show "PO  BC'"
                  by (metis Ar2_def Col_cases Par_cases Par_def Pj_def
                      Ar2 PO E E' B C BC BC  PO E E' Pj BC BC'
                      par_strict_not_col_1) 
                show "PO  E'"
                  by (simp add: PO  E') 
                show "PO  C'"
                  by (metis Ar2_def Ar2 PO E E' B C BC
                      C C' Proj PO E' E E' C  PO grid_not_par
                      proj_id) 
                show "PO  B"
                  using B  PO by auto 
                show "PO  BC"
                  using BC  PO by auto 
                show "PO  AB"
                  using A  PO PO  B assms(1) prod_null
                  by blast 
                show "PO  ABC"
                  using A  PO BC  PO assms(3) prod_null
                  by blast 
                show "Col PO B' E'"
                  by (simp add: Col PO E' B' col_permutation_5) 
                show "Col PO B' BC'"
                  using Col PO E' B' Col PO E' BC' PO  E'
                    col_transitivity_1 by blast 
                show "Col PO B' C'"
                  using C' = C'' Col PO E' B' Col PO E' C''
                    PO  E' col_transitivity_1 by blast 
                show "Col PO B AB"
                  using Ar2_def Prod_def PO  E assms(1)
                    col_transitivity_1 by presburger 
                show "Col PO B BC"
                  by (metis Ar2_def Ar2 PO E E' B C BC PO  E l6_16_1
                      not_col_permutation_2) 
                show "Col PO B ABC"
                  by (meson Ar2_def Prod_def Col PO B BC PO  BC
                      PO  E assms(3) col_permutation_5
                      col_transitivity_1) 
                show "B' B Par BC' BC"
                  by (smt (verit, best) Ar2_def Par_cases Pj_def
                      Ar2 PO E E' B C BC B  PO Col PO B' BC'
                      Col PO E' BC' E E' Pj B B' E E' Pj BC BC'
                      PO  BC' PO  E' col_transitivity_2 l6_16_1
                      par_trans) 
                show "B' AB Par BC' ABC"
                  by (smt (verit) Par_def Pj_def B  PO Col PO B ABC
                      Col PO B AB Col PO E' B' Col PO E' BC'
                      E' A Pj B' AB E' A Pj BC' ABC PO  ABC PO  E'
                      ¬ Col PO B' B col_permutation_4
                      not_col_permutation_2 not_par_inter_exists
                      not_par_not_col parallel_uniqueness) 
                show "B E' Par BC C'"
                  by (metis Ar2_def Par_cases Pj_def Ar2 PO E E' B C BC
                      C C' Proj PO E' E E' C  PO C' = C''
                      E' B Pj C'' BC proj_id) 
              qed
              thus ?thesis
                by (simp add: Pj_def)
            qed
            ultimately show "Prod PO E E' AB C ABC"
              using Ar2_def Prod_def Ar2 PO E E' A B AB Ar2 PO E E' A BC ABC
                Ar2 PO E E' B C BC by auto 
          }
        qed
      }
    qed
  }
qed

lemma prod_assoc2: 
  assumes "Prod PO E E' A B AB" and
    "Prod PO E E' B C BC"
    and "Prod PO E E' AB C ABC"
  shows "Prod PO E E' A BC ABC"
proof (cases "A = PO")
  have "Ar2 PO E E' A B AB"
    using Prod_def assms(1) by blast 
  have "Ar2 PO E E' B C BC" 
    using Prod_def assms(2) by blast 
  have "Ar2 PO E E' AB C ABC" 
    using Prod_def assms(3) by blast 
  show "A = PO  Prod PO E E' A BC ABC"
    by (metis Ar2_def Ar2 PO E E' B C BC assms(1,3)
        prod_0_l prod_uniqueness) 
  show "A  PO  Prod PO E E' A BC ABC" 
  proof (cases "B = PO")
    show "A  PO  B = PO  Prod PO E E' A BC ABC"
      by (metis Ar2_def Ar2 PO E E' A B AB
          Ar2 PO E E' B C BC assms(1,2,3) prod_0_l prod_0_r
          prod_uniqueness) 
    show "A  PO  B  PO  Prod PO E E' A BC ABC" 
    proof (cases "C = PO")
      show "A  PO  B  PO  C = PO  Prod PO E E' A BC ABC"
        by (metis Ar2_def Ar2 PO E E' A B AB assms(2,3)
            prod_0_r prod_uniqueness) 
      {
        assume "A  PO" and "B  PO" and "C  PO"
        show "Prod PO E E' A BC ABC" 
        proof -
          have "¬ PO E Par E E'"
            using Ar2_def Ar2 PO E E' AB C ABC grid_not_par by blast 
          have "¬ PO E Par PO E'"
            using Ar2_def Ar2 PO E E' B C BC grid_not_par by auto 
          have "¬ PO E' Par E E'"
            using Ar2_def Ar2 PO E E' B C BC grid_not_par_3 by blast 
          have "PO  E"
            using Ar2_def Ar2 PO E E' AB C ABC col_trivial_1 by blast 
          hence "PO  E'"
            using Par_cases ¬ PO E Par E E' par_reflexivity by blast 
          hence "E  E'"
            using ¬ PO E Par PO E' par_reflexivity by blast 
          have "BC  PO"
            using B  PO C  PO assms(2) prod_null by blast 
          obtain BC' where "BC BC' Proj PO E' E E'"
            using E  E' PO  E' ¬ PO E' Par E E'
              par_symmetry project_existence by blast 
          hence "BC BC' Par E E'  BC = BC'"
            using Proj_def by auto 
          moreover have "BC = BC'  BC BC' Par E E'"
            using Ar2_def Ar2 PO E E' B C BC
              BC BC' Proj PO E' E E' BC  PO proj_id
            by blast 
          ultimately have "BC BC' Par E E'" by blast
          have "E E' Pj BC BC'"
            by (simp add: Pj_def BC BC' Par E E'
                par_symmetry) 
          moreover have "Col PO E' BC'"
            using Proj_def BC BC' Proj PO E' E E'
            by presburger 
          moreover have "E' A Pj BC' ABC" 
          proof -
            obtain B' where "E E' Pj B B'" and
              "Col PO E' B'" and "E' A Pj B' AB"
              using Prod_def assms(1) by blast 
            obtain C' where "E E' Pj C C'" and
              "Col PO E' C'" and "E' B Pj C' BC"
              using Prod_def assms(2) by blast 
            obtain C'' where "E E' Pj C C''" and 
              "Col PO E' C''" and "E' AB Pj C'' ABC"
              using Prod_def assms(3) by blast 
            hence "C' = C''"
              using Ar2_def Ar2 PO E E' AB C ABC Col PO E' C'
                E E' Pj C C' pj_uniqueness by force 
            have "E' A Par BC' ABC" 
            proof -
              have "B'  PO"
                by (metis Ar2_def Prod_def BC  PO E E' Pj B B'
                    assms(2) prod_0_l prod_uniqueness
                    sum_par_strict_a) 
              hence "E' A Par B' AB"
                by (metis Ar2_def Pj_def Ar2 PO E E' AB C ABC
                    Col PO E' B' E  E' E' A Pj B' AB
                    not_col_permutation_1 par_col2_par_bis par_reflexivity
                    sum_par_strict_a) 
              moreover have "B' AB Par BC' ABC" 
              proof (rule l13_19 [of PO E' B C'], insert PO  E'Col PO E' B' 
                  Col PO E' C' Col PO E' BC')
                show "¬ Col PO E' B"
                  by (metis Ar2_def Col_cases Par_cases Par_def Pj_def
                      Ar2 PO E E' A B AB B'  PO Col PO E' B'
                      E E' Pj B B' col2__eq par_strict_not_col_4) 
                show "PO  C'"
                  by (smt (verit, ccfv_threshold) Ar2_def Par_cases Pj_def
                      Ar2 PO E E' B C BC BC  PO E' B Pj C' BC
                      PO  E col_par col_trivial_3 not_strict_par
                      par_not_par) 
                show "PO  B'"
                  using B'  PO by auto 
                show "PO  BC'"
                  by (metis Ar2_def Ar2 PO E E' B C BC
                      BC BC' Proj PO E' E E' BC  PO not_col_distincts
                      proj_id) 
                show "PO  B"
                  using ¬ Col PO E' B grid_not_par_5 by auto 
                show "PO  BC"
                  using BC  PO by auto 
                show "PO  AB"
                  using A  PO B  PO assms(1) prod_null by blast 
                show "PO  ABC"
                  using C  PO PO  AB assms(3) prod_null by blast 
                show "Col PO B AB"
                  using Ar2_def Prod_def PO  E assms(1)
                    col_transitivity_1 by presburger 
                show "Col PO B BC"
                  using Ar2_def Prod_def PO  E assms(2)
                    col_transitivity_1 by presburger 
                show "Col PO B ABC"
                  using Ar2_def Prod_def PO  E assms(2,3)
                    col_transitivity_1 by presburger 
                show "E' B Par C' BC"
                  by (metis Pj_def BC = BC'  BC BC' Par E E'
                      BC BC' Proj PO E' E E' C' = C'' Col PO E' C''
                      E' B Pj C' BC par_distinct project_not_col) 
                show "E' AB Par C' ABC"
                  by (metis Col_cases Pj_def C' = C'' Col PO B ABC
                      Col PO E' C' E' AB Pj C'' ABC PO  C'
                      ¬ Col PO E' B col2__eq) 
                show "B B' Par BC BC'"
                  by (metis Ar2_def Par_cases Pj_def Ar2 PO E E' B C BC
                      BC BC' Proj PO E' E E' BC  PO Col PO E' B'
                      E E' Pj B B' E E' Pj BC BC' ¬ Col PO E' B
                      par_trans proj_id) 
              qed
              ultimately show ?thesis
                using postulate_of_transitivity_of_parallelism_def
                  postulate_of_transitivity_of_parallelism_thm
                by blast
            qed
            thus ?thesis
              by (simp add: Pj_def) 
          qed
          ultimately show ?thesis
            using Ar2_def Prod_def assms(1,2,3) by auto 
        qed
      }
    qed
  qed
qed

lemma prod_assoc:
  assumes "Prod PO E E' A B AB"
    and "Prod PO E E' B C BC"
  shows "Prod PO E E' A BC ABC  Prod PO E E' AB C ABC"
  by (meson assms(1,2) prod_assoc1 prod_assoc2) 

lemma prod_comm:
  assumes "Prod PO E E' A B C"
  shows "Prod PO E E' B A C"
proof (cases "A = PO")
  have "Ar2 PO E E' A B C"
    using Prod_def assms by blast 
  thus "A = PO  Prod PO E E' B A C"
    by (metis Ar2_def assms prod_0_l
        prod_0_r prod_uniqueness) 
  show "A  PO  Prod PO E E' B A C" 
  proof (cases "B = PO")
    show "A  PO  B = PO  Prod PO E E' B A C"
      by (metis Ar2_def Ar2 PO E E' A B C assms prod_0_l
          prod_0_r prod_uniqueness) 
    show "A  PO  B  PO  Prod PO E E' B A C" 
    proof (cases "C = PO")
      show "A  PO  B  PO  C = PO  Prod PO E E' B A C"
        using assms prod_null by blast 
      {
        assume "A  PO" and "B  PO" and "C  PO"
        obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' C"
          using Prod_def assms by blast
        have "¬ PO E Par E E'"
          using Ar2_def Ar2 PO E E' A B C grid_not_par by blast 
        have "¬ PO E Par PO E'"
          using Ar2_def Ar2 PO E E' A B C par_id by blast 
        have "¬ PO E' Par E E'"
          using Ar2_def Ar2 PO E E' A B C grid_not_par by blast 
        have "PO  E"
          using Ar2_def Ar2 PO E E' A B C grid_not_par by blast 
        hence "PO  E'"
          using Par_cases ¬ PO E Par E E' par_reflexivity by blast 
        hence "E  E'"
          using ¬ PO E Par PO E' par_reflexivity by blast 
        then obtain A' where "A A' Proj PO E' E E'"
          using PO  E' ¬ PO E' Par E E'
            par_symmetry project_existence by blast 
        hence "A A' Par E E'  A = A'"
          using project_par_dir by blast 
        moreover have "A = A'  A A' Par E E'"
          using Ar2_def A A' Proj PO E' E E' A  PO Ar2 PO E E' A B C proj_id by blast 
        ultimately have "A A' Par E E'" 
          by blast
        have "E E' Pj A A'"
          using A A' Proj PO E' E E' project_pj by auto 
        moreover have "Col PO E' A'"
          using Proj_def A A' Proj PO E' E E' by presburger 
        moreover 
        have "C A' Par B E'"  
        proof (rule l13_11 [of PO], insert A  POB  PO)
          show "¬ Col PO C E'"
            by (metis Ar2_def Col_cases Ar2 PO E E' A B C
                C  PO col3 col_trivial_3) 
          show "Col PO C B"
            by (metis Ar2_def Col_cases Ar2 PO E E' A B C
                col_transitivity_1 col_trivial_3) 
          show "Col PO B A"
            by (metis Ar2_def Col_cases Ar2 PO E E' A B C
                col_transitivity_1 col_trivial_3)
          show "A'  PO"
            using Ar2_def A  PO Ar2 PO E E' A B C
              calculation(1) sum_par_strict_a by blast 
          show "B'  PO"
            by (metis Ar2_def Col_cases Par_cases Par_def Pj_def
                Ar2 PO E E' A B C B  PO E E' Pj B B'
                par_strict_not_col_1) 
          show "Col PO E' A'"
            using calculation(2) by auto 
          show "Col PO A' B'"
            using Col PO E' B' PO  E' calculation(2)
              col_transitivity_1 by blast 
          show "B B' Par A A'"
            by (metis Ar2_def Col_cases Par_cases Pj_def
                A A' Par E E' Ar2 PO E E' A B C B  PO
                Col PO E' B' E E' Pj B B' col_transitivity_1
                not_par_one_not_par) 
          show "A E' Par C B'"
            by (metis NCol_cases Par_cases Pj_def Col PO E' B'
                E' A Pj B' C ¬ Col PO C E') 
        qed
        hence "E' B Pj A' C"
          using Par_cases Pj_def by auto 
        ultimately show "Prod PO E E' B A C"
          using Ar2_def Prod_def Ar2 PO E E' A B C by auto 
      }
    qed
  qed
qed

(** Lemma 14.24 *)
(** Left distributivity of product over sum.*)
lemma prod_O_l_eq:
  assumes "Prod PO E E' PO B C"
  shows "C = PO"
  by (metis Ar2_def Prod_def assms prod_0_l prod_uniqueness) 

lemma prod_O_r_eq: 
  assumes "Prod PO E E' A PO C"
  shows "C = PO"
  using assms prod_O_l_eq prod_comm by blast 

lemma prod_uniquenessA:
  assumes "B  PO" 
    and "Prod PO E E' A B C"
    and "Prod PO E E' A' B C"
  shows "A = A'" 
proof (cases "A' = PO")
  show "A' = PO  A = A'"
    using assms(1,2,3) prod_O_l_eq prod_null by blast 
  {
    assume "A'  PO"
    obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' C"
      using Prod_def assms(2) by blast 
    obtain B'' where "E E' Pj B B''" and "Col PO E' B''" and "E' A' Pj B'' C"
      using Prod_def assms(3) by blast 
    hence "B' = B''"
      using Ar2_def Prod_def Col PO E' B' E E' Pj B B'
        assms(3) pj_uniqueness by auto 
    {
      assume "E' A Par B' C" and "E' A' Par B' C"
      hence "E' A' Par E' A"
        using not_par_one_not_par by blast 
      have "E' A' ParStrict E' A  A = A'"
        by (simp add: not_par_strict_id) 
      hence "A = A'"
        by (metis Ar2_def Prod_def E' A' Par E' A assms(2,3) colx par_id_4) 
    }
    thus "A = A'"
      by (metis Ar2_def NCol_perm Pj_def Prod_def B' = B''
          Col PO E' B'' E' A Pj B' C E' A' Pj B'' C
          assms(1,2,3) col_transitivity_2 prod_null) 
  }
qed

lemma prod_uniquenessB:
  assumes "A  PO"
    and "Prod PO E E' A B C"
    and "Prod PO E E' A B' C"
  shows "B = B'"
  by (meson assms(1,2,3) prod_comm prod_uniquenessA) 

(** Lemma 14.25 *)
(** Left distributivity of product over sum.*)
lemma distr_l:
  assumes "Sum PO E E' B C D"
    and "Prod PO E E' A B AB"
    and "Prod PO E E' A C AC"
    and "Prod PO E E' A D AD"
  shows "Sum PO E E' AB AC AD" 
proof (cases "A = PO")
  obtain B' C1 where "E E' Pj B B'" and "Col PO E' B'" and "PO E Pj B' C1" and 
    "PO E' Pj C C1" and "E' E Pj C1 D"
    using Sum_def assms(1) by blast
  obtain B'' where "E E' Pj B B''" and "Col PO E' B''" and "E' A Pj B'' AB"
    using Prod_def assms(2) by blast
  have "¬ Col PO E E'"
    using Ar2_def assms(1) sum_ar2 by presburger 
  have "Col PO E A"
    using Ar2_def Prod_def assms(3) by auto 
  have "Col PO E B"
    using Ar2_def assms(1) sum_ar2 by presburger 
  have "PO  E"
    using ¬ Col PO E E' grid_not_par_4 by auto 
  have "PO  E'"
    using ¬ Col PO E E' grid_not_par_5 by presburger 
  have "B' = B''"
    using Col PO E B Col PO E' B'' Col PO E' B'
      E E' Pj B B'' E E' Pj B B' ¬ Col PO E E'
      pj_uniqueness by blast 
  obtain C' where "E E' Pj C C'" and "Col PO E' C'" and "E' A Pj C' AC"
    using Prod_def assms(3) by blast
  obtain D' where "E E' Pj D D'" and "Col PO E' D'" and "E' A Pj D' AD"
    using Prod_def assms(4) by blast
  have "Sum PO E' E B' C' D'"
    using Ar1_def Col PO E' B' Col PO E' C'
      Col PO E' D' E E' Pj B B' E E' Pj C C'
      E E' Pj D D' PO  E' ¬ Col PO E E' assms(1)
      proj_preserves_sum by force 
  show "A = PO  Sum PO E E' AB AC AD"
    by (metis ¬ Col PO E E' assms(2,3,4) prod_O_l_eq sum_O_O) 
  {
    assume "A  PO"
    have "Sum PO E' A B' C' D'"
      by (metis A  PO Col PO E A Sum PO E' E B' C' D'
          ¬ Col PO E E' col_trivial_3 colx
          not_col_permutation_5 sum_y_axis_change) 
    have "Sum PO A E' AB AC AD" 
    proof (rule proj_preserves_sum [of _ _ _ B' C' D'], insert E' A Pj C' AC 
        E' A Pj D' AD Sum PO E' A B' C' D')
      show "¬ Col PO E' A"
        using Col_perm A  PO Col PO E A ¬ Col PO E E' col_trivial_3 colx by blast 
      show "Ar1 PO A AB AC AD"
        using Ar1_def Ar2_def Prod_def A  PO PO  E assms(2,3,4) 
          col_transitivity_1 by presburger 
      show "E' A Pj B' AB"
        by (simp add: B' = B'' E' A Pj B'' AB) 
    qed
    thus "Sum PO E E' AB AC AD"
      using Col PO E A PO  E not_col_permutation_5 sum_x_axis_unit_change by blast 
  }
qed

(** Lemma 14.24 *)
(** Right distributivity of product over sum.*)
lemma distr_r:
  assumes "Sum PO E E' A B D"
    and "Prod PO E E' A C AC"
    and "Prod PO E E' B C BC"
    and "Prod PO E E' D C DC"
  shows "Sum PO E E' AC BC DC"
  using assms(1,2,3,4) distr_l prod_comm by blast 

(** We omit lemma 14.26 which states that we have a division ring. *)

(** Lemma 14.27. *)
(** Sum and product are preserved by parallel projection on a different x-axis.*)
(** This lemma is used to prove that there is an isomorphism between number lines.*)
lemma prod_1_l_eq:
  assumes "Prod PO E E' A B B"
  shows "A = E  B = PO"
  by (meson Ar2_def Prod_def assms prod_1_r prod_comm prod_uniquenessB) 

lemma prod_1_r_eq:
  assumes "Prod PO E E' A B A"
  shows "B = E  A = PO"
  using assms prod_1_l_eq prod_comm by blast 

lemma change_grid_prod_l_O:
  assumes "PO E ParStrict O' E'"
    and "Ar1 PO E PO B C"
    and "Ar1 O' E' A' B' C'"
    (*and "PO O' Pj E E'"*)
    and "PO O' Pj PO A'"
    (*and "PO O' Pj B B'"*)
    and "PO O' Pj C C'"
    and "Prod PO E E' PO B C"
  shows "Prod O' E' E A' B' C'"
  by (smt (verit) Ar1_def NCol_cases Pj_def
      assms(1,2,3,4,5,6) grid_not_par not_par_not_col
      par_strict_not_col_1 par_strict_par
      parallel_uniqueness prod_0_r prod_O_l_eq
      prod_comm) 

lemma change_grid_prod1:
  assumes "PO E ParStrict O' E'"
    and "Ar1 PO E E B C"
    and "Ar1 O' E' A' B' C'"
    and "PO O' Pj E E'"
    and "PO O' Pj E A'" 
    and "PO O' Pj B B'"
    and "PO O' Pj C C'"
    and "Prod PO E E' E B C"
  shows "Prod O' E' E A' B' C'" 
proof (cases "B = PO")
  show "B = PO  Prod O' E' E A' B' C'"
    by (smt (verit, ccfv_SIG) Ar1_def Par_strict_cases
        Pj_def assms(1,3,6,7,8) grid_not_par
        not_col_permutation_2 not_par_not_col
        par_strict_not_col_1 parallel_uniqueness prod_0_r
        prod_O_r_eq) 
  show "B  PO  Prod O' E' E A' B' C'" 
  proof (cases "C = PO")
    show "B  PO  C = PO  Prod O' E' E A' B' C'"
      by (metis Ar1_def assms(2,8) prod_null) 
    {
      assume "B  PO" and "C  PO"
      have "Prod PO E E' E B B"
        using Ar1_def assms(1,2) par_strict_not_col_4 prod_1_l by presburger 
      have "B = C"
        using Prod PO E E' E B B assms(1,8) par_strict_not_col_4 prod_uniqueness by blast 
      have "A' = E'" 
      proof (rule l6_21 [of E E' O' E'])
        show "¬ Col E E' O'"
          using Col_cases assms(1) par_strict_not_col_2 by blast 
        show "O'  E'"
          using assms(1) par_strict_distinct by blast 
        show "Col E E' A'"
          by (metis Col_cases Pj_def assms(4,5) col_trivial_3 parallel_uniqueness) 
        show "Col E E' E'"
          by (simp add: col_trivial_2) 
        show "Col O' E' A'"
          using Ar1_def assms(3) by presburger 
        show "Col O' E' E'"
          using not_col_distincts by auto 
      qed
      have "C' = B'"
      proof (rule l6_21 [of B' B O' E'])
        show "¬ Col B' B O'"
          by (metis Ar1_def Par_def Pj_def B = C B  PO
              assms(1,2,3,6) l6_16_1 not_col_permutation_3
              not_col_permutation_4 not_par_strict_id par_not_col
              pj_comm) 
        show "O'  E'"
          using assms(1) par_strict_distinct by blast 
        show "Col B' B C'"
          by (metis Col_cases Pj_def B = C assms(6,7) col_trivial_3 parallel_uniqueness) 
        show "Col B' B B'"
          using grid_not_par_5 by blast 
        show "Col O' E' C'"
          using Ar1_def assms(3) by auto 
        show "Col O' E' B'"
          using Ar1_def assms(3) by auto 
      qed
      thus "Prod O' E' E A' B' C'"
        by (metis Ar1_def Col_cases A' = E' assms(1,3) par_strict_not_col_2 prod_1_l) 
    }
  qed
qed

lemma change_grid_prod:
  assumes "PO E ParStrict O' E'"
    and "Ar1 PO E A B C"
    and "Ar1 O' E' A' B' C'"
    and "PO O' Pj E E'"
    and "PO O' Pj A A'"
    and "PO O' Pj B B'"
    and "PO O' Pj C C'"
    and "Prod PO E E' A B C" 
  shows "Prod O' E' E A' B' C'"
proof (cases "A = PO")
  show "A = PO  Prod O' E' E A' B' C'"
    using assms(1,2,3,5,7,8) change_grid_prod_l_O by blast 
  show "A  PO  Prod O' E' E A' B' C'" 
  proof (cases "B = PO")
    show "A  PO  B = PO  Prod O' E' E A' B' C'"
      by (smt (verit) Ar1_def Col_cases Par_strict_cases
          Pj_def assms(1,3,6,7,8) grid_not_par not_par_not_col
          par_strict_not_col_1 parallel_uniqueness prod_0_r
          prod_O_r_eq) 
    show "A  PO  B  PO  Prod O' E' E A' B' C'" 
    proof (cases "C = PO")
      show "A  PO  B  PO  C = PO  Prod O' E' E A' B' C'"
        using assms(8) prod_null by blast 
      show "A  PO  B  PO  C  PO  Prod O' E' E A' B' C'" 
      proof (cases "A = E")
        show "A  PO  B  PO  C  PO  A = E  Prod O' E' E A' B' C'"
          using assms(1,2,3,4,5,6,7,8) change_grid_prod1 by blast 
        {
          assume "A  PO" and "B  PO" and "C  PO" and "A  E" 
          obtain E'' where "Bet PO O' E''" and "Cong O' E'' PO O'"
            using segment_construction by blast
          hence "E''  PO"
            using assms(1) bet_neq12__neq not_par_strict_id by blast 
          have "¬ Col PO E E''"
            by (metis Col_cases E''  PO PO  O'  E''
                assms(1) bet_col col2__eq par_strict_not_col_1) 
          have "Prod PO E E'' A B C"
            using ¬ Col PO E E'' assms(8) prod_y_axis_change by blast 
          then obtain B'' where "E E'' Pj B B''" and "Col PO E'' B''" and "E'' A Pj B'' C"
            using Prod_def by blast
          obtain C2 where "Sum PO E'' E E'' O' C2"
            by (metis Col_cases Col_def PO  O'  E'' ¬ Col PO E E'' 
                col_trivial_1 sum_exists) 
          have "¬ Col PO E'' A"
            by (metis Ar1_def Col_cases A  PO ¬ Col PO E E'' assms(2) col_trivial_3 colx) 
          have "Sum PO E'' A E'' O' C2"
            using Sum PO E'' E E'' O' C2 ¬ Col PO E'' A sum_y_axis_change by blast 
          obtain A0 A0' where "E'' A Pj E'' A0" and "Col PO A A0" and 
            "PO E'' Pj A0 A0'" and "PO A Pj O' A0'" and "A E'' Pj A0' C2"
            using Sum_def Sum PO E'' A E'' O' C2 by blast 
          hence "A = A0"
            by (metis Col_cases Pj_def ¬ Col PO E'' A col2__eq grid_not_par) 
          have "PO O' Par E E'"
            using Pj_def assms(1,4) grid_not_par par_strict_not_col_2 by blast 
          have "PO O' Par A A'"
            by (metis Ar1_def Pj_def assms(1,2,3,5) not_col_permutation_1 par_not_col) 
          have "PO O' Par B B'"
            by (metis Ar1_def Pj_def assms(1,2,3,6) not_strict_par2 
                par_strict_not_col_4 par_strict_par) 
          have "PO O' Par C C'"
            by (metis Ar1_def Pj_def assms(1,2,3,7) not_strict_par2 
                par_strict_not_col_4 par_strict_par)
          have "PO  O'"
            using assms(1) not_par_strict_id by blast
          have "A0' = A'" 
          proof (rule l6_21 [of O' E' A A'])
            show "¬ Col O' E' A"
              by (meson Ar1_def Col_cases assms(1,2) par_not_col) 
            show "A  A'"
              using PO O' Par A A' par_distincts by auto 
            show "Col O' E' A0'" 
            proof -
              {
                assume "PO A Par O' A0'"
                hence "O' E' Par O' A0'"
                  by (metis Ar1_def Col_cases Par_cases Par_def assms(1,2) 
                      col_par_par_col col_trivial_1 par_neq2) 
                hence "Col O' E' A0'"
                  using grid_not_par by blast 
              }
              moreover have "O' = A0'  Col O' E' A0'"
                by (simp add: col_trivial_3) 
              ultimately show ?thesis 
                using PO A Pj O' A0' Pj_def by blast
            qed
            show "Col O' E' A'"
              using Ar1_def assms(3) by auto 
            show "Col A A' A0'" 
            proof -
              have "PO E'' Par A A0'  Col A A' A0'"
                using Col_def Par_cases PO O' Par A A' PO  O'  E'' col_par_par_col by blast 
              moreover have "A = A0'  Col A A' A0'"
                using col_trivial_3 by blast 
              ultimately show ?thesis
                using Pj_def A = A0 PO E'' Pj A0 A0' by blast
            qed
            show "Col A A' A'"
              by (simp add: col_trivial_2) 
          qed
          hence "PO E'' Par A A'"
            using Pj_def A = A0 PO E'' Pj A0 A0' PO O' Par A A' par_distincts by blast 
          hence "PO A Par O' A'"
            by (metis Par_cases Pj_def A0' = A' PO A Pj O' A0' PO O' Par A A' 
                ¬ Col PO E'' A col_trivial_3 not_strict_par2) 
          have "A E'' Par A' C2" 
          proof -
            have "A' = C2  A E'' Par A' C2"
              by (metis Ar2_def Par_cases PO E'' Par A A' Sum PO E'' A E'' O' C2
                  col_trivial_3 not_strict_par2 sum_ar2) 
            thus ?thesis
              using Pj_def A E'' Pj A0' C2 A0' = A' by blast 
          qed
          obtain E0 E0' where "E'' E Pj E'' E0" and "Col PO E E0" and 
            "PO E'' Pj E0 E0'" and "PO E Pj O' E0'" and "E E'' Pj E0' C2"
            using Sum_def Sum PO E'' E E'' O' C2 by blast 
          hence "E0 = E"
            by (metis Pj_def ¬ Col PO E E'' col2__eq grid_not_par) 
          have "E0' = E'" 
          proof (rule l6_21 [of O' E' E E'])
            show "¬ Col O' E' E"
              using Col_cases assms(1) par_strict_not_col_2 by blast 
            show "E  E'"
              using PO O' Par E E' par_distinct by auto 
            show "Col O' E' E0'" 
            proof -
              have "PO E Par O' E0'  Col O' E' E0'"
                using Par_cases assms(1) par_id_3 par_not_par par_strict_par by blast 
              moreover have "O' = E0'  Col O' E' E0'"
                using not_col_distincts by blast 
              ultimately show ?thesis
                using Pj_def PO E Pj O' E0' by blast 
            qed
            show "Col O' E' E'"
              by (simp add: col_trivial_2) 
            show "Col E E' E0'"
              by (smt (verit, ccfv_threshold) Par_cases Pj_def
                  E0 = E PO E'' Pj E0 E0' PO O' Par E E'
                  PO  O'  E'' bet_col col_permutation_4
                  not_par_inter_exists par_col_par_2 par_id_5
                  par_trans_implies_playfair playfair_s_postulate_def
                  postulate_of_transitivity_of_parallelism_thm) 
            show "Col E E' E'" 
              by (simp add: col_trivial_2) 
          qed
          have "E E'' Par E' C2"
            by (metis Ar1_def Pj_def A E'' Par A' C2 E E'' Pj E0' C2 E0' = E' 
                PO A Par O' A' ¬ Col PO E'' A assms(3) col_par_par_col 
                col_permutation_5 par_symmetry)
          have "E E'' Par B B''"
            by (metis Ar1_def Col_cases Pj_def B  PO Col PO E E0 Col PO E'' B''
                E E'' Pj B B'' E0 = E ¬ Col PO E E'' assms(2) colx) 
          obtain C3 where "Sum PO E'' E B'' O' C3"
            by (metis Col_def NCol_cases Col PO E'' B'' PO  O'  E'' ¬ Col PO E E''
                sum_exists)
          then obtain B0 B0' where "E'' E Pj B'' B0" and "Col PO E B0" and 
            "PO E'' Pj B0 B0'" and "PO E Pj O' B0'" and "E E'' Pj B0' C3"
            using Sum_def by blast
          have "B''  PO"
            by (metis Ar1_def Col_cases Par_cases Par_def E E'' Par B B'' ¬ Col PO E E''
                assms(2) par_strict_not_col_1) 
          have "B0 = B"
            by (meson Ar1_def Col PO E B0 Col PO E'' B'' E E'' Pj B B'' E'' E Pj B'' B0
                ¬ Col PO E E'' assms(2) col_permutation_5 pj_comm pj_uniqueness)
          have "B0' = B'" 
          proof (rule l6_21 [of O' E' B B'])
            show "¬ Col O' E' B"
              using Col_cases B0 = B Col PO E B0 assms(1) par_not_col by blast 
            show "B  B'"
              using PO O' Par B B' par_distinct by auto 
            show "Col O' E' B0'"
              by (metis Par_cases Pj_def PO E Pj O' B0' assms(1) grid_not_par 
                  par_not_par par_strict_par) 
            show "Col O' E' B'"
            proof -
              have "PO E'' Par B B0'  Col O' E' B'"
                using Ar1_def assms(3) by auto 
              moreover have "B = B0'  Col O' E' B'"
                using Col O' E' B0' ¬ Col O' E' B by auto 
              ultimately show ?thesis
                using Ar1_def assms(3) by blast 
            qed
            show "Col B B' B0'" 
            proof -
              have "PO E'' Par B B0'  Col B B' B0'"
                using Col_def Par_perm PO O' Par B B' PO  O'  E'' col_par_par_col by blast 
              moreover have "B = B0'  Col B B' B0'"
                using Col O' E' B0' ¬ Col O' E' B by auto 
              ultimately show ?thesis
                using Pj_def B0 = B PO E'' Pj B0 B0' by blast 
            qed
            show "Col B B' B'"
              by (simp add: col_trivial_2) 
          qed
          have "B'  O'"
            by (metis B  PO B0 = B Col PO E B0 PO O' Par B B' assms(1) 
                col2__eq col_permutation_4 grid_not_par par_strict_not_col_1) 
          hence "E E'' Par B' C3"
            by (smt (verit, ccfv_threshold) Ar2_def Col_def Pj_def B0' = B'
                E E'' Pj B0' C3 PO E Pj O' B0' PO  O'  E'' Sum PO E'' E B'' O' C3
                assms(1) bet3__bet between_inner_transitivity col_trivial_3
                inter_uniqueness_not_par l5_3 par_strict_not_col_1 sum_ar2
                third_point) 
          have "E'' E Par B'' B"
            using Par_perm E E'' Par B B'' by blast 
          have "Sum PO E'' A B'' O' C3"
            using Sum PO E'' E B'' O' C3 ¬ Col PO E'' A sum_y_axis_change by blast 
          then obtain C0 C0' where "E'' A Pj B'' C0" and "Col PO A C0" and 
            "PO E'' Pj C0 C0'" and "PO A Pj O' C0'" and "A E'' Pj C0' C3"
            using Sum_def by blast 
          have "E'' A Par B'' C"
            by (metis Ar1_def Par_cases Pj_def E'' A Pj B'' C E'' E Par B'' B 
                ¬ Col PO E E'' assms(2) grid_not_par_1 par_col2_par_bis) 
          have "C0 = C" 
          proof (rule l6_21 [of PO E B'' C])
            show "¬ Col PO E B''"
              using B''  PO Col PO E'' B'' ¬ Col PO E E'' col2__eq 
                col_permutation_4 by blast 
            show "B''  C"
              using E'' A Par B'' C par_distinct by blast 
            show "Col PO E C0"
              by (metis Ar1_def A  PO Col PO A C0 assms(2) col_trivial_3 colx) 
            show "Col PO E C"
              using Ar1_def assms(2) by auto 
            show "Col B'' C C0"
              by (metis Pj_def E'' A Par B'' C E'' A Pj B'' C0
                  col_par_par_col grid_not_par_5 not_col_permutation_2 pj_comm) 
            show "Col B'' C C"
              using grid_not_par_6 by blast 
          qed
          have "C0' = C'" 
          proof (rule l6_21 [of O' E' C C'])
            show "¬ Col O' E' C"
              by (meson Ar1_def Col_cases assms(1,2) par_not_col) 
            show "C  C'"
              using PO O' Par C C' par_distinct by auto 
            show "Col O' E' C0'" 
            proof -
              {
                assume "PO A Par O' C0'"
                have "O' C' Par O' C0'" 
                proof -
                  have "PO E Par O' C'" 
                  proof (rule par_col_par [of _ _ _ _ E'])
                    show "O'  C'"
                      by (metis Ar1_def Col_cases C  PO PO O' Par C C' assms(1,2)
                          col2__eq grid_not_par par_strict_not_col_1) 
                    show "PO E Par O' E'"
                      by (simp add: Par_def assms(1)) 
                    show "Col O' E' C'"
                      using Ar1_def assms(3) by auto 
                  qed
                  hence "O' C' Par PO E"
                    using Par_cases by blast 
                  moreover have "PO E Par O' C0'"
                    by (metis Ar1_def Col_cases PO A Par O' C0' assms(2) par_col_par_2) 
                  ultimately show ?thesis
                    using par_not_par by blast 
                qed
                hence "Col O' E' C0'"
                  by (metis Ar1_def Col_cases Par_cases assms(3) not_par_strict_id 
                      par_not_col_strict) 
              }
              moreover have "O' = C0'  Col O' E' C0'"
                by (simp add: col_trivial_3) 
              ultimately show ?thesis
                using Pj_def PO A Pj O' C0' by blast 
            qed
            show "Col O' E' C'"
              using Ar1_def assms(3) by auto 
            show "Col C C' C0'"
            proof -
              have "PO A Par O' C0'  Col C C' C0'"
                by (smt (verit, ccfv_SIG) Pj_def A = A0 C0 = C
                    PO E'' Pj C0 C0' PO O' Par C C' PO  O'  E'' bet_col
                    col_permutation_4 grid_not_par par_col_par_2
                    parallel_uniqueness) 
              moreover have "O' = C0'  Col C C' C0'"
                by (metis Pj_def C0 = C PO E'' Pj C0 C0' PO O' Par C C'
                    PO  O'  E'' bet_col col_par_par_col grid_not_par_5
                    not_col_permutation_4 par_comm) 
              ultimately show ?thesis
                using Pj_def PO A Pj O' C0' by blast 
            qed
            show "Col C C' C'"
              by (simp add: col_trivial_2) 
          qed
          have "B B'' Par B' C3"
            using Par_cases E E'' Par B B'' E E'' Par B' C3 not_par_one_not_par by blast
          have "A E'' Par C' C3" 
          proof -
            {
              assume "C' = C3"
              have "E'' E Par C' O'"
              proof (rule par_col_par [of _ _ _ _ B'])
                show "C'  O'"
                  by (metis Ar1_def Col_cases C  PO PO O' Par C C' assms(1,2)
                      col2__eq grid_not_par par_strict_not_col_1) 
                show "E'' E Par C' B'"
                  using Par_cases C' = C3 E E'' Par B' C3 by blast
                show "Col C' B' O'"
                  by (metis Ar1_def Col_cases assms(3) col_transitivity_1) 
              qed
              hence "E E'' Par O' C'"
                using Par_cases by auto 
              hence "E E'' Par O' E'"
                by (metis Ar1_def Col_cases assms(3) par_col_par)
              hence "E E'' Par PO E"
                using assms(1) not_par_one_not_par par_strict_par by blast
              hence "A E'' Par C' C3"
                using Par_cases ¬ Col PO E E'' par_id_1 by blast 
            }
            thus ?thesis
              using Pj_def A E'' Pj C0' C3 C0' = C' by blast 
            hence "C B'' Par C' C3"
              by (metis Par_cases E'' A Par B'' C par_trans) 
          qed

          have "Prod O' E' C2 A' B' C'" 
          proof -
            {
              assume "Col O' E' C2" 
              have "C2  O'"
                using E''  PO Sum PO E'' A E'' O' C2 ¬ Col PO E'' A sum_A_null by blast 
              have "Col PO O' C2"
                by (metis Ar2_def NCol_perm E''  PO Sum PO E'' A E'' O' C2
                    col_transitivity_2 sum_ar2) 
              have "Col PO O' E'"
                using C2  O' Col O' E' C2 Col PO O' C2 col2__eq col_permutation_4 by blast 
              hence False
                using Col_cases assms(1) par_strict_not_col_3 by blast 
            }
            moreover have "E' C2 Pj B' C3"
              by (metis Par_perm Pj_def E E'' Par B' C3 E E'' Par E' C2 par_not_par) 
            moreover have "Col O' C2 C3"
              by (metis Ar2_def E''  PO Sum PO E'' A E'' O' C2 
                  Sum PO E'' E B'' O' C3 col_transitivity_2 sum_ar2) 
            moreover have "C2 A' Pj C3 C'"
              by (metis Par_perm Pj_def A E'' Par A' C2 A E'' Par C' C3 par_trans) 
            ultimately show ?thesis
              using Ar1_def Ar2_def Prod_def assms(3) by auto 
          qed
          thus "Prod O' E' E A' B' C'"
            using assms(1) not_col_permutation_1 par_strict_not_col_2 prod_y_axis_change by blast 
        }
      qed
    qed
  qed
qed


(** Lemma
 14.28 is something like
  ∃ f,
  prod O E X A B C ->
  prod O' E' f(X) f(A') f(B') f(C') ?
*)


(** Lemma 14.29 *)
(** From Pappus-Pascal we can derive that the product is symmetric, hence we have a field. *)

(* already done : prod_comm *)

lemma prod_sym:
  assumes "Prod PO E E' A B C"
  shows "Prod PO E E' B A C"
  by (simp add: assms prod_comm) 

(** Lemma 14.31 *)
lemma l14_31_1:
  assumes "Ar2p4 PO E E' A B C D" 
    and "C  PO"
    and " X. Prod PO E E' A B X  Prod PO E E' C D X"
  shows "Prod PO C E' A B D" 
proof (cases "A = PO")
  obtain X where "Prod PO E E' A B X" and "Prod PO E E' C D X"
    using assms(3) by blast
  show "A = PO  Prod PO C E' A B D"
    by (metis Ar2_def Prod_def Prod PO E E' A B X
        Prod PO E E' C D X assms(2) col_transitivity_1 prod_0_l
        prod_1_r prod_O_l_eq prod_null) 
  show "A  PO  Prod PO C E' A B D" 
  proof (cases "B = PO")
    show "A  PO  B = PO  Prod PO C E' A B D"
      by (metis Ar2_def Prod_def assms(2,3) col_transitivity_1 prod_0_r
          prod_1_r prod_O_r_eq prod_null) 
    show "A  PO  B  PO  Prod PO C E' A B D" 
    proof (cases "D = PO")
      show "A  PO  B  PO  D = PO  Prod PO C E' A B D"
        using assms(3) prod_O_r_eq prod_null by blast 
      {
        assume "A  PO" and "B  PO" and "D  PO"
        have "¬ PO E Par E E'"
          using Ar2_def Prod_def Prod PO E E' A B X grid_not_par by auto 
        have "¬ PO E Par PO E'"
          using Ar2_def Prod_def Prod PO E E' C D X par_id by blast 
        have "PO  E"
          using Ar2_def Prod_def assms(3) grid_not_par by blast 
        hence "PO  E'"
          using Par_cases ¬ PO E Par E E' par_reflexivity by blast 
        obtain B'' where "B B'' Proj PO E' E' C"
          by (metis Ar2_def Col_def Par_cases Prod_def assms(2,3) col2__eq
              grid_not_par project_existence) 
        hence "B B'' Par E' C"
          by (metis Ar2_def Prod_def Proj_def B  PO assms(3) col_permutation_2 
              col_transitivity_2)
        have "C E' Par B B''"
          using Par_cases B B'' Par E' C by blast 
        hence "C E' Pj B B''"
          using Pj_def by blast 
        moreover have "Col PO E' B''"
          using Proj_def B B'' Proj PO E' E' C by auto 
        moreover have "E' A Pj B'' D" 
        proof -
          obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' X"
            using Prod_def Prod PO E E' A B X by blast 
          obtain D' where "E E' Pj D D'" and "Col PO E' D'" and "E' C Pj D' X"
            using Prod_def Prod PO E E' C D X by blast
          have "B'  PO"
            by (metis Ar2_def Prod_def B  PO E E' Pj B B' assms(3) sum_par_strict_a) 
          have "E B'' Par C B'" 
          proof (rule l13_11 [of PO _ _ _ B _ E'], insert C E' Par B B'' B  PO assms(2))
            show "¬ Col PO E B'"
              by (metis Col_cases Par_def B'  PO Col PO E' B' PO  E'
                  PO  E ¬ PO E Par PO E' col2__eq col_trivial_3) 
            show "Col PO E C"
              using Ar2_def Prod_def assms(3) by auto 
            show "Col PO C B"
              by (meson Ar2_def Prod_def PO  E assms(3) col3 col_trivial_3) 
            show "B''  PO"
              by (metis Par_cases Proj_def B B'' Proj PO E' E' C B  PO
                  Col PO C B grid_not_par not_par_not_col par_trans) 
            show "Col PO B' B''"
              using Col PO E' B' PO  E' calculation(2) col_transitivity_1 by blast 
            show "Col PO B'' E'"
              using Col_cases calculation(2) by blast
            show "B B' Par E E'"
              by (metis Par_cases Pj_def B B'' Proj PO E' E' C C E' Par B B'' 
                  Col PO E' B' E E' Pj B B' par_distinct project_not_col) 
            show "E'  PO"
              using PO  E' by auto 
          qed
          have "X  PO"
            using D  PO Prod PO E E' C D X assms(2) prod_null by blast 
          have "A D' Par C B'" 
          proof (rule l13_11 [of PO _ _ _ X _ E'], insert X  PO assms(2))
            show "¬ Col PO A B'"
              by (metis Ar2_def Prod_def A  PO B'  PO Col PO E' B'
                  assms(3) col_permutation_5 col_transitivity_1) 
            show "Col PO A C"
              by (meson Ar2_def Prod_def PO  E assms(3) col_transitivity_1) 
            show "Col PO C X"
              by (meson Ar2_def Prod_def PO  E Prod PO E E' A B X assms(3)
                  col_transitivity_1) 
            show "D'  PO"
              by (metis Ar2_def Col_def Par_cases Par_def Pj_def Prod_def
                  A  PO B  PO E E' Pj D D' assms(3) par_strict_not_col_1
                  prod_O_r_eq prod_null)
            show "E'  PO"
              using PO  E' by auto 
            show "Col PO B' D'"
              using Col PO E' B' Col PO E' D' PO  E' col_transitivity_1 by blast 
            show "Col PO D' E'"
              using Col_cases Col PO E' D' by blast 
            show "C E' Par X D'"
              by (metis Pj_def Col PO A C Col PO C X Col PO D' E'
                  Col PO E' B' E' C Pj D' X PO  E' X  PO
                  ¬ Col PO A B' assms(2) col_trivial_3 colx pj_comm) 
            show "X B' Par A E'"
              by (metis Par_cases Pj_def Col PO A C Col PO C X E' A Pj B' X 
                  ¬ Col PO A B' assms(2) col_trivial_3 colx) 
          qed
          have "D B'' Par A E'" 
          proof  (rule l13_11 [of PO _ _ _ E _ D'], insert A  PO)
            show "¬ Col PO D E'"
              by (metis Ar2_def Prod_def Proj_def B B'' Proj PO E' E' C
                  D  PO assms(3) col_par col_transitivity_1 col_trivial_3) 
            show "E  PO"
              using PO  E by auto 
            show "Col PO D A"
              by (metis Ar2_def Col_cases Prod_def assms(3) col_transitivity_1
                  col_trivial_3) 
            show "Col PO A E"
              by (meson Col_cases Prodp_def assms(3) prod_to_prodp) 
            show "B''  PO"
              by (smt (verit, ccfv_SIG) Ar2_def NCol_cases Par_def Prod_def
                  B'  PO Col PO E' B' E B'' Par C B' assms(3) colx
                  par_strict_not_col_1) 
            show "D'  PO"
              by (metis Col_cases Par_cases Pj_def A  PO Col PO A E
                  Col PO D A E E' Pj D D' ¬ Col PO D E' col2__eq
                  col_trivial_3 not_strict_par2) 
            show "Col PO E' B''"
              by (simp add: calculation(2)) 
            show "Col PO B'' D'"
              using Col PO E' D' PO  E' calculation(2) col_transitivity_1
              by blast 
            show "A D' Par E B''"
              using A D' Par C B' E B'' Par C B' not_par_one_not_par by blast 
            show "E E' Par D D'"
              using Col_cases Pj_def Col PO E' D' E E' Pj D D' ¬ Col PO D E' by blast 
          qed
          thus ?thesis
            using Par_perm Pj_def by blast 
        qed
        ultimately show "Prod PO C E' A B D"
          by (smt (verit, ccfv_threshold) Ar2_def Prod_def Proj_def
              B B'' Proj PO E' E' C PO  E assms(3) col_par
              col_permutation_1 col_transitivity_2) 
      }
    qed
  qed
qed

lemma l14_31_2:
  assumes "Ar2p4 PO E E' A B C D"
    and "C  PO"
    and "Prod PO C E' A B D"
  shows " X. Prod PO E E' A B X  Prod PO E E' C D X"
proof (cases "A = PO")
  show "A = PO  X. Prod PO E E' A B X  Prod PO E E' C D X"
    by (metis Ar2p4_def assms(1,3) prod_0_l prod_0_r prod_O_l_eq) 
  show "A  PO  X. Prod PO E E' A B X  Prod PO E E' C D X" 
  proof (cases "B = PO")
    show "A  PO  B = PO  X. Prod PO E E' A B X  Prod PO E E' C D X"
      by (metis Ar2p4_def assms(1,3) prod_0_r prod_O_r_eq) 
    show "A  PO  B  PO  X. Prod PO E E' A B X  Prod PO E E' C D X" 
    proof (cases "D = PO")
      show "A  PO  B  PO  D = PO  X. Prod PO E E' A B X  Prod PO E E' C D X"
        using assms(3) prod_null by blast 
      {
        assume "A  PO" and "B  PO" and "D  PO"
        obtain B' where "B B' Proj PO E' E E'"
          by (metis Ar2p4_def Col_perm assms(1) grid_not_par project_existence) 
        hence "B B' Par E E'"
          by (metis Ar2p4_def B  PO assms(1) proj_id project_par_dir) 
        obtain X where "B' X Proj PO E E' A"
          by (metis Ar2p4_def Par_cases assms(1) col_trivial_1 col_trivial_2
              not_strict_par1 project_existence)
        have "X  PO"
          by (metis Ar2p4_def Proj_def A  PO B B' Proj PO E' E E'
              B  PO B' X Proj PO E E' A assms(1) col_permutation_2
              not_col_distincts not_strict_par project_col_project
              project_id) 
        have "B' X Par E' A"
          by (metis Ar2p4_def Proj_def B B' Proj PO E' E E' B  PO
              B' X Proj PO E E' A assms(1) proj_id) 
        obtain B'' where "C E' Pj B B''" and "Col PO E' B''" and "E' A Pj B'' D"
          using Prod_def assms(3) by blast
        have "E E' Pj B B'"
          using B B' Proj PO E' E E' project_pj by auto 
        moreover have "Col PO E' B'"
          using Proj_def B B' Proj PO E' E E' by force 
        moreover have "E' A Pj B' X"
          using B' X Proj PO E E' A project_pj by auto 
        ultimately have "Prod PO E E' A B X"
          using Ar2_def Ar2p4_def Prod_def Proj_def B' X Proj PO E E' A assms(1) by auto 
        obtain D' where "D D' Proj PO E' E E'"
          by (meson Ar2p4_def Prodp_def assms(1) prod_exists prod_to_prodp) 
        hence "D D' Par E E'"
          by (metis Ar2p4_def D  PO assms(1) proj_id project_par_dir) 
        moreover have "Prod PO E E' C D X" 
        proof -
          have "E E' Pj D D'"
            using D D' Proj PO E' E E' project_pj by auto 
          moreover have "Col PO E' D'"
            using Proj_def D D' Proj PO E' E E' by presburger 
          moreover have "E' C Pj D' X" 
          proof -
            have "E' C Par D' X" 
            proof -
              have "X D' Par B B''" 
              proof (rule l13_11 [of PO _ _ _ D _ B'])
                show "¬ Col PO X B''"
                  by (metis Ar2_def Col_cases Prod_def B  PO C E' Pj B B''
                      Col PO E' B'' Prod PO E E' A B X X  PO assms(3)
                      col_trivial_3 colx sum_par_strict_a) 
                show "B  PO"
                  using B  PO by auto 
                show "D  PO"
                  by (simp add: D  PO) 
                show "Col PO X B"
                  by (metis Ar2p4_def Proj_def B' X Proj PO E E' A assms(1)
                      col_transitivity_1) 
                show "Col PO B D"
                  by (metis Ar2p4_def Proj_def B' X Proj PO E E' A assms(1)
                      col_transitivity_1) 
                show "D'  PO"
                  using Ar2p4_def D D' Proj PO E' E E' D  PO assms(1)
                    col_trivial_3 proj_id by auto 
                show "B'  PO"
                  using B' X Proj PO E E' A X  PO not_col_distincts project_not_col by blast 
                show "Col PO B'' D'"
                  by (metis Proj_def B B' Proj PO E' E E' Col PO E' B'' 
                      calculation(2) col_transitivity_1) 
                show "Col PO D' B'"
                  by (metis Proj_def B B' Proj PO E' E E' calculation(2) col_transitivity_1) 
                show "B B' Par D D'"
                  using B B' Par E E' D D' Par E E' not_par_one_not_par by blast 
                show "D B'' Par X B'"
                  by (metis Par_cases Pj_def Proj_def B B' Proj PO E' E E'
                      B' X Par E' A Col PO E' B'' D D' Par E E' E' A Pj B'' D
                      calculation(2) par_distinct par_not_par project_id) 
              qed
              thus ?thesis
                by (metis Par_cases Pj_def C E' Pj B B'' not_par_one_not_par par_distinct) 
            qed
            thus ?thesis
              using Pj_def by blast 
          qed
          ultimately show ?thesis
            using Ar2_def Ar2p4_def Prod_def Proj_def B' X Proj PO E E' A assms(1) by auto 
        qed
        ultimately show "X. Prod PO E E' A B X  Prod PO E E' C D X"
          using Prod PO E E' A B X by blast
      }
    qed
  qed
qed

lemma prod_x_axis_unit_change:
  assumes "Ar2p4 PO E E' A B C D"
    and "Col PO E U"
    and "U  PO"
    and " X. Prod PO E E' A B X  Prod PO E E' C D X"
  shows " Y. Prod PO U E' A B Y  Prod PO U E' C D Y" 
proof (cases "A = PO")
  obtain X where "Prod PO E E' A B X" and "Prod PO E E' C D X"
    using assms(4) by auto 
  {
    assume "A = PO"
    hence "X = PO"
      using Prod PO E E' A B X prod_O_l_eq by blast 
    have "C = PO  D = PO"
      using Prod PO E E' C D X X = PO prod_null by blast 
    moreover {
      assume "C = PO"
      have "Prod PO U E' PO B PO"
        by (metis Ar2_def Prod_def Prod PO E E' A B X assms(2,3) col_transitivity_1
            grid_not_par prod_0_l) 
      moreover have "Prod PO U E' PO D PO"
        by (metis Ar2_def Prod_def Prod PO E E' C D X assms(2) calculation 
            col_transitivity_1 grid_not_par prod_0_l) 
      ultimately have "Y. Prod PO U E' A B Y  Prod PO U E' C D Y"
        using A = PO C = PO by auto         
    }
    moreover {
      assume "D = PO"
      have "Prod PO U E' PO B PO"
        by (metis Ar2_def Prod_def Prod PO E E' A B X assms(2,3) col_transitivity_1
            grid_not_par prod_0_l) 
      moreover have "Prod PO U E' C PO PO"
        by (metis Ar2_def Prod_def Prod PO E E' C D X assms(2) calculation 
            col_transitivity_1 grid_not_par prod_0_r) 
      ultimately have "Y. Prod PO U E' A B Y  Prod PO U E' C D Y"
        using A = PO D = PO by auto 
    }
    ultimately show "Y. Prod PO U E' A B Y  Prod PO U E' C D Y"
      by blast
  }
  show "A  PO  Y. Prod PO U E' A B Y  Prod PO U E' C D Y" 
  proof (cases "B = PO")
    {
      assume "A  PO" and"B = PO"
      have "X = PO"
        using B = PO Prod PO E E' A B X prod_O_r_eq by auto 
      have "C = PO  D = PO"
        using Prod PO E E' C D X X = PO prod_null by auto 
      moreover have "C = PO  Prod PO U E' A B PO  Prod PO U E' C D PO"
        by (metis Ar2_def Prod_def B = PO Prod PO E E' A B X Prod PO E E' C D X
            assms(2,3) col_transitivity_1 grid_not_par prod_0_l prod_0_r) 
      moreover have "D = PO  Prod PO U E' A B PO  Prod PO U E' C D PO"
        by (metis Ar2_def Prod_def B = PO Prod PO E E' A B X Prod PO E E' C D X
            assms(2,3) col_transitivity_1 not_col_permutation_5 prod_0_r) 
      ultimately show "Y. Prod PO U E' A B Y  Prod PO U E' C D Y"
        by blast 
    }
    show "A  PO  B  PO  Y. Prod PO U E' A B Y  Prod PO U E' C D Y" 
    proof (cases "C = PO")
      show "A  PO  B  PO  C = PO  Y. Prod PO U E' A B Y  Prod PO U E' C D Y"
        using assms(4) prod_O_l_eq prod_null by blast 
      show "A  PO  B  PO  C  PO  Y. Prod PO U E' A B Y  Prod PO U E' C D Y" 
      proof (cases "D = PO")
        show "A  PO  B  PO  C  PO  D = PO  
               Y. Prod PO U E' A B Y  Prod PO U E' C D Y"
          using assms(4) prod_O_r_eq prod_null by blast 
        {
          assume "A  PO" and "B  PO" and "C  PO" and "D  PO"
          obtain Bu where "B Bu Proj PO E' U E'" 
            by (metis Ar2_def Col_def Prod_def Prod PO E E' A B X assms(2,3) 
                col_transitivity_1 grid_not_par project_existence) 
          hence "B Bu Par U E'"
            by (metis Par_def Prodp_def Proj_def B  PO Prod PO E E' A B X 
                not_col_distincts prod_to_prodp proj_id) 
          obtain Xu where "Bu Xu Proj PO E A E'"
            by (metis Prodp_def Proj_def Prod PO E E' A B X prod_to_prodp project_existence) 
          hence "Bu Xu Par A E'"
            by (metis Ar2_def Prod_def Proj_def B Bu Proj PO E' U E' B  PO assms(2,3,4) 
                col_permutation_5 col_transitivity_1 proj_id) 
          have "Prod PO U E' A B Xu"
            by (smt (verit) Prodp_def Proj_def B Bu Proj PO E' U E' Bu Xu Proj PO E A E'
                assms(2,3,4) col2__eq col3 prod_to_prodp prodp_to_prod
                project_col_project) 
          moreover have "Prod PO U E' C D Xu" 
          proof -
            obtain Du where "D Du Proj PO E' U E'"
              using Proj_def B Bu Proj PO E' U E' project_existence by presburger
            hence "D Du Par U E'"
              by (metis Ar2_def Prod_def Proj_def Bu Xu Proj PO E A E' D  PO assms(2,4)
                  calculation col_transitivity_1 proj_id)
            have "E' C Pj Du Xu" 
            proof -
              have "Prod PO C E' A B D"
                using C  PO Prod PO E E' A B X Prod PO E E' C D X assms(1) l14_31_1 
                by blast
              obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' X"
                using Prod_def Prod PO E E' A B X by auto
              obtain D' where "E E' Pj D D'" and "Col PO E' D'" and "E' C Pj D' X"
                using Prod_def Prod PO E E' C D X by auto 
              obtain D'' where "C E' Pj B D''" and "Col PO E' D''" and "E' A Pj D'' D"
                using Prod_def Prod PO C E' A B D by blast
              have "Xu  PO"
                using A  PO B  PO calculation prod_null by blast 
              have "D''  PO"
                by (metis Ar2_def Par_cases Par_def Pj_def Prod_def B  PO C E' Pj B D''
                    Prod PO C E' A B D col_permutation_5 par_strict_not_col_1)
              have "Xu Du Par B D''" 
              proof (rule l13_11 [of PO _ _ _ D _ Bu], insert D  PO B  PO)
                show "¬ Col PO Xu D''"
                  by (metis Proj_def B Bu Proj PO E' U E' Bu Xu Par A E' 
                      Bu Xu Proj PO E A E' Col PO E' D''
                      D''  PO Xu  PO col_permutation_5 col_transitivity_1
                      par_distinct project_id) 
                show "Col PO Xu B"
                  by (metis Ar2_def Prod_def Proj_def Bu Xu Proj PO E A E' assms(4)
                      col_transitivity_1) 
                show "Col PO B D"
                  by (metis Ar2_def Prod_def Proj_def Bu Xu Proj PO E A E' assms(4)
                      col_transitivity_1) 
                show "Du  PO"
                  by (metis Proj_def B Bu Proj PO E' U E' Bu Xu Proj PO E A E' Col PO B D
                      D Du Proj PO E' U E' D  PO Xu  PO col2__eq col_permutation_3
                      project_col_eq project_id) 
                show "Bu  PO"
                  using Bu Xu Proj PO E A E' Xu  PO not_col_distincts project_id
                  by blast
                show "Col PO D'' Du"
                  by (metis Proj_def Col PO E' D'' D Du Proj PO E' U E' 
                      col3 not_col_distincts) 
                show "Col PO Du Bu"
                  by (metis Proj_def B Bu Proj PO E' U E' D Du Proj PO E' U E' l6_16_1
                      not_col_permutation_3 not_col_permutation_5) 
                show "B Bu Par D Du"
                  using B Bu Par U E' D Du Par U E' not_par_one_not_par by blast 
                show "D D'' Par Xu Bu"
                  by (metis Par_cases Pj_def B Bu Par D Du Bu Xu Par A E' Col PO E' D''
                      D Du Proj PO E' U E' E' A Pj D'' D par_distinct par_not_par
                      project_id) 
              qed
              thus ?thesis
                by (metis Par_cases Pj_def C E' Pj B D'' par_neq2 par_trans) 
            qed
            moreover have "U E' Pj D Du"
              using D Du Proj PO E' U E' project_pj by auto 
            moreover have "Col PO E' Du"
              using Proj_def D Du Proj PO E' U E' by auto 
            moreover have "Ar2 PO U E' C D Xu"
              by (metis Ar2_def Prod_def Proj_def Bu Xu Proj PO E A E' Prod PO U E' A B Xu
                  assms(2,4) col_transitivity_1) 
            ultimately show ?thesis
              using Prod_def by blast 
          qed
          ultimately show "Y. Prod PO U E' A B Y  Prod PO U E' C D Y" 
            by blast
        }
      qed
    qed
  qed
qed

lemma opp_prod:
  assumes "Opp PO E E' E ME" 
    and "Opp PO E E' X MX"
  shows "Prod PO E E' X ME MX" 
proof -
  obtain EPME where "Sum PO E E' E ME EPME"
    using Opp_def assms(1) sum_opp by blast 
  hence "PO = EPME"
    by (meson Opp_def assms(1) sum_opp sum_stable) 
  obtain X' where "Prod PO E E' X E X'"
    by (meson Ar2_def Opp_def assms(2) prod_1_r sum_ar2)
  hence "X = X'"
    by (meson Ar2_def Prod_def prod_1_r prod_uniqueness)
  obtain O' where "Prod PO E E' X PO O'"
    by (meson Ar2_def Prodp_def Prod PO E E' X E X' Sum PO E E' E ME EPME prod_0_r
        prod_to_prodp sum_ar2)
  hence "PO = O'"
    using prod_O_r_eq by blast 
  obtain MX' where "Prod PO E E' X ME MX'"
    by (metis Ar2_def Prodp_def Prod PO E E' X E X' Sum PO E E' E ME EPME
        prod_exists prod_to_prodp sum_ar2) 
  hence "Sum PO E E' X MX' PO"
    using PO = EPME PO = O' Prod PO E E' X E X' Prod PO E E' X PO O'
      Sum PO E E' E ME EPME X = X' distr_l by blast 
  thus ?thesis
    by (metis Prod PO E E' X ME MX' assms(2) opp_uniqueness sum3_col sum3_exists
        sum_ar2 sum_opp) 
qed

lemma distr_l_diff:
  assumes "Diff PO E E' B C BMC"
    and "Prod PO E E' A B AB"
    and "Prod PO E E' A C AC"
    and "Prod PO E E' A BMC ABMC"
  shows "Diff PO E E' AB AC ABMC"
  by (meson assms(1,2,3,4) diff_sum distr_l sum_diff) 

lemma diff_of_squares:
  assumes "Prod PO E E' A A A2"
    and "Prod PO E E' B B B2"
    and "Diff PO E E' A2 B2 A2MB2"
    and "Sum PO E E' A B APB"
    and "Diff PO E E' A B AMB"
    and "Prod PO E E' APB AMB F"
  shows "A2MB2 = F" 
proof -
  obtain F1 where "Prod PO E E' A AMB F1"
    by (metis Ar2_def Prodp_def assms(4,6) prod_exists prod_to_prodp sum_ar2) 
  moreover obtain F2 where "Prod PO E E' B AMB F2"
    by (meson Ar2_def Prod_def assms(2,6) prod_exists) 
  ultimately obtain F' where "Sum PO E E' F1 F2 F'"
    using assms(4,6) distr_r by blast 
  hence "F = F'"
    using Prod PO E E' A AMB F1 Prod PO E E' B AMB F2 assms(4,6) distr_r sum_stable
    by blast
  obtain AB where "Prod PO E E' A B AB"
    by (meson Ar2_def assms(4) prod_exists sum_ar2)
  then obtain A2MAB where "Diff PO E E' A2 AB A2MAB"
    by (metis Ar2_def Prod_def assms(3) col_trivial_3 diff_ar2 sum_diff sum_A_exists) 
  hence "A2MAB = F1"
    using Prod PO E E' A AMB F1 Prod PO E E' A B AB assms(1,5) diff_uniqueness
      distr_l_diff by blast
  obtain BA where "Prod PO E E' B A BA"
    using Prod PO E E' A B AB prod_sym by blast
  obtain BAMB2 where "Diff PO E E' BA B2 BAMB2"
    using Ar2_def Prod_def Prod PO E E' B A BA assms(2) diff_exists by presburger 
  hence "BAMB2 = F2"
    using Prod PO E E' B A BA Prod PO E E' B AMB F2 assms(2,5) diff_uniqueness
      distr_l_diff by blast
  have "BA = AB"
    by (meson Ar2_def Prod PO E E' A B AB Prod PO E E' B A BA Sum PO E E' F1 F2 F'
        prod_sym prod_uniqueness sum_ar2) 
  thus ?thesis
    by (metis A2MAB = F1 BAMB2 = F2 Diff PO E E' A2 AB A2MAB
        Diff PO E E' BA B2 BAMB2 F = F' Sum PO E E' F1 F2 F' assms(3) diff_stable
        sum_diff_diff_b) 
qed

lemma eq_squares_eq_or_opp:
  assumes "Prod PO E E' A A A2"
    and "Prod PO E E' B B A2"
  shows "A = B  Opp PO E E' A B" 
proof -
  obtain O' where "Diff PO E E' A A O'"
    by (meson Ar2_def Prod_def assms(1) diff_null) 
  hence "PO = O'"
    by (metis Ar2_def Prod_def assms(1) diff_sum sum_B_null) 
  obtain APB where "Sum PO E E' A B APB"
    by (meson Ar2_def Prodp_def Diff PO E E' A A O' assms(2) diff_sum prod_to_prodp
        sum_ar2 sum_exists) 
  then obtain AMB where "Diff PO E E' A B AMB"
    by (meson Ar2_def diff_exists sum_ar2) 
  then obtain PO' where "Prod PO E E' APB AMB PO'"
    by (meson Ar2_def Sum PO E E' A B APB diff_ar2 prod_exists sum_ar2)
  hence "PO = PO'"
    using diff_of_squares [of PO E E' A A2 B A2 _ APB AMB] Ar2_def Prod_def 
      Diff PO E E' A B AMB Sum PO E E' A B APB assms(1,2)
      diff_null by force
  thus ?thesis
    using Diff PO E E' A B AMB Prod PO E E' APB AMB PO'
      Sum PO E E' A B APB diff_null_eq prod_null sum_opp
    by blast 
qed

lemma diff_2_prod:
  assumes "Opp PO E E' E ME"
    and "Diff PO E E' A B AMB"
    and "Diff PO E E' B A BMA"
  shows "Prod PO E E' AMB ME BMA"
  using assms(1,2,3) diff_opp opp_prod by blast 

lemma l14_36_a:
  assumes "Sum PO E E' A B C" and
    "PO Out A B" 
  shows "Bet PO A C" 
proof (cases "A = B")
  have "ParallelogramFlat PO A C B"
    by (metis assms(1,2) between_trivial diff_to_plg l6_6 sum_diff
        not_bet_and_out) 
  hence "Parallelogram PO A C B"
    by (simp add: Parallelogram_def) 
  show "A = B  (PO  A  C)"
    by (metis Out_def ParallelogramFlat_def ParallelogramFlat PO A C B
        between_cong l6_4_2 plgf_permut) 
  show "A  B  (PO  A  C)"
    by (smt (z3) Ar2_def ParallelogramFlat_def ParallelogramFlat PO A C B
        assms(1,2) bet_cong_eq between_trivial2 col_cong2_bet2 l6_4_2 l6_6
        not_bet_and_out out_col outer_transitivity_between2 plgf_permut sum_ar2
        sum_cong2 third_point)
qed

lemma l14_36_b:
  assumes "Sum PO E E' A B C"
    and "PO Out A B"
  shows "PO  A  PO  C  A  C"
  by (metis Ar2_def Out_def assms(1,2) between_equality_2 between_trivial2
      cong3_id l14_36_a out_col sum_ar2 sum_iff_cong_b) 

lemma pos_null_neg: 
  assumes "Opp PO E E' A MA"
  shows "Ps PO E A  PO = A  Ps PO E MA"
  by (metis Ar2_def Col_def Opp_def Ps_def assms between_trivial l14_36_b l6_3_2
      l6_4_2 sum_B_null sum_ar2) 

lemma sum_pos_pos:
  assumes "Ps PO E A"
    and "Ps PO E B"
    and "Sum PO E E' A B AB"
  shows "Ps PO E AB" 
proof -
  have "PO Out A B"
    using Out_cases Ps_def assms(1,2) l6_7 by presburger 
  hence "PO  A  PO  AB  A  AB"
    using assms(3) l14_36_b by blast 
  thus ?thesis
    by (metis Out_def Ps_def PO Out A B assms(1,3) l14_36_a l6_7) 
qed

lemma prod_pos_pos:
  assumes "Ps PO E A"
    and "Ps PO E B"
    and "Prod PO E E' A B AB"
  shows "Ps PO E AB" 
proof -
  obtain B' where "E E' Pj B B'" and "Col PO E' B'" and "E' A Pj B' AB"
    using Prod_def assms(3) by auto 
  have "E'  A"
    using Ar2_def Prod_def assms(3) by blast 
  have "¬ Col PO E' A"
    by (metis Ar2_def Col_cases O_not_positive Prod_def assms(1,3) col_trivial_3 colx) 
  hence "¬ PO E Par E' A"
    by (meson Par_def Prodp_def assms(3) par_strict_not_col_4 prod_to_prodp) 
  have "E E' Proj PO E' E E'"
    by (metis Ar2_def Prod_def Proj_def assms(3) grid_not_par par_reflexivity) 
  have "B B' Proj PO E' E E'"
    by (metis Proj_def Col PO E' B' E E' Pj B B' E E' Proj PO E' E E' not_col_permutation_4
        not_col_permutation_5 pj_col_project) 
  have "PO PO Proj PO E' E E'"
    by (metis Proj_def E E' Proj PO E' E E' not_col_distincts) 
  have "E' A Proj PO E E' A"
    by (metis Par_def Prodp_def Proj_def ¬ PO E Par E' A assms(3) not_col_distincts
        prod_to_prodp) 
  hence "B' AB Proj PO E E' A"
    using Ar2_def Pj_def Prod_def Proj_def E' A Pj B' AB assms(3) par_symmetry by metis
  hence "PO PO Proj PO E E' A"
    by (metis Proj_def not_col_distincts) 
  have "AB  PO"
    using O_not_positive ¬ Col PO E' A assms(2,3) col_trivial_3 prod_null by blast 
  {
    assume "Bet PO B E"
    hence "Bet PO B' E'"
      using B B' Proj PO E' E E' E E' Proj PO E' E E' PO PO Proj PO E' E E' 
        project_preserves_bet by blast 
    hence "Bet PO AB A"
      using B' AB Proj PO E E' A E' A Proj PO E E' A PO PO Proj PO E E' A
        project_preserves_bet by blast 
    hence "Ps PO E AB"
      using Ps_def AB  PO assms(1) bet_out l6_7 by blast 
  }
  moreover 
  {
    assume "Bet PO E B"
    hence "Bet PO E' B'"
      using B B' Proj PO E' E E' E E' Proj PO E' E E' PO PO Proj PO E' E E' 
        project_preserves_bet
      by blast 
    hence "Bet PO A AB"
      using B' AB Proj PO E E' A E' A Proj PO E E' A PO PO Proj PO E E' A 
        project_preserves_bet
      by blast 
    hence "Ps PO E AB"
      by (metis O_not_positive Out_cases Ps_def assms(1) bet_out l6_7) 
  }
  ultimately show ?thesis
    using Out_def Ps_def assms(2) by auto 
qed

lemma pos_not_neg:
  assumes "Ps PO E A"
  shows "¬ Ng PO E A"
  by (metis Ng_def Ps_def assms not_bet_and_out) 

lemma neg_not_pos:
  assumes "Ng PO E A"
  shows "¬ Ps PO E A"
  using assms pos_not_neg by blast 

lemma opp_pos_neg: 
  assumes "Ps PO E A"
    and "Opp PO E E' A MA"
  shows "Ng PO E MA"
  by (metis (full_types) Bet_cases Ng_def Out_def Ps_def assms(1,2) 
      bet_out__bet is_midpoint_id_2 midpoint_bet opp_midpoint) 

lemma opp_neg_pos:
  assumes "Ng PO E A"
    and "Opp PO E E' A MA"
  shows "Ps PO E MA"
  by (metis Ng_def assms(1,2) neg_not_pos pos_null_neg) 

lemma ltP_ar2:
  assumes "LtP PO E E' A B"
  shows "Ar2 PO E E' A B A"
  by (meson Ar2_def LtP_def assms diff_ar2) 

lemma ltP_neq:
  assumes "LtP PO E E' A B"
  shows "A  B"
  using LtP_def assms diff_opp opp_pos_neg pos_not_neg by blast 

lemma leP_refl:
  shows "LeP PO E E' A A"
  using LeP_def by auto 

lemma ltP_sum_pos:
  assumes "Ps PO E B"
    and "Sum PO E E' A B C"
  shows "LtP PO E E' A C"
  using LtP_def assms(1,2) local.sum_diff by blast 

lemma pos_opp_neg:
  assumes "Ps PO E A"
    and "Opp PO E E' A mA"
  shows "Ng PO E mA"
  using assms(1,2) opp_pos_neg by auto

lemma diff_pos_diff_neg:
  assumes "Diff PO E E' A B AmB"
    and "Diff PO E E' B A BmA"
    and "Ps PO E AmB"
  shows "Ng PO E BmA"
  using assms(1,2,3) diff_opp pos_opp_neg by blast 

lemma not_pos_and_neg:
  shows "¬(Ps PO E A  Ng PO E A)"
  using neg_not_pos by auto 

lemma leP_asym:
  assumes "LeP PO E E' A B" 
    and "LeP PO E E' B A"
  shows "A = B" 
proof -
  have "LtP PO E E' A B  A = B"
    by (metis LeP_def LtP_def assms(2) diff_pos_diff_neg pos_not_neg) 
  moreover have "LtP PO E E' B A  A = B"
    using LeP_def assms(1) calculation by auto 
  ultimately show ?thesis
    using LeP_def assms(1) by auto 
qed

lemma leP_trans:
  assumes "LeP PO E E' A B"
    and "LeP PO E E' B C"
  shows "LeP PO E E' A C" 
proof -
  {
    assume "LtP PO E E' A B"
    have "LeP PO E E' A C" 
    proof -
      {
        assume "LtP PO E E' B C"
        obtain dBA where "Diff PO E E' B A dBA" and "Ps PO E dBA"
          using LtP_def LtP PO E E' A B by auto
        obtain dCB where "Diff PO E E' C B dCB" and "Ps PO E dCB"
          using LtP_def LtP PO E E' B C by auto 
        have "Ar2 PO E E' B A dBA"
          by (simp add: Diff PO E E' B A dBA diff_ar2) 
        have "Ar2 PO E E' C B dCB"
          by (simp add: Diff PO E E' C B dCB diff_ar2) 
        then obtain dCA where "Sum PO E E' dBA dCB dCA"
          using Ar2_def Ar2 PO E E' B A dBA sum_exists by blast
        hence "LeP PO E E' A C"
          by (meson LeP_def Diff PO E E' B A dBA Diff PO E E' C B dCB Ps PO E dBA
              Ps PO E dCB diff_sum ltP_sum_pos sum_assoc_2 sum_pos_pos) 
      }
      moreover have "B = C  LeP PO E E' A C" 
        using assms(1) by auto 
      ultimately show ?thesis
        using LeP_def assms(2) by auto 
    qed
  }
  moreover have "A = B  LeP PO E E' A C"
    by (simp add: assms(2)) 
  ultimately show ?thesis
    using LeP_def assms(1) by blast 
qed

(* sum_preserves leP : a <= x /\ b <= y => a + b <= x + y *)

lemma leP_sum_leP:
  assumes "LeP PO E E' A X"
    and "LeP PO E E' B Y"
    and "Sum PO E E' A B C"
    and "Sum PO E E' X Y Z"
  shows "LeP PO E E' C Z" 
proof -
  have "Ar2 PO E E' A B C"
    by (simp add: assms(3) sum_ar2) 
  have "Ar2 PO E E' X Y Z"
    by (simp add: assms(4) sum_ar2) 
  {
    assume "LtP PO E E' A X"
    have "LeP PO E E' C Z" 
    proof -
      {
        assume "LtP PO E E' B Y"
        obtain dXA where "Diff PO E E' X A dXA"
          using LtP_def LtP PO E E' A X by auto 
        obtain dYB where "Diff PO E E' Y B dYB"
          using LtP_def LtP PO E E' B Y by auto 
        obtain dZC where "Diff PO E E' Z C dZC"
          using Ar2_def Ar2 PO E E' A B C Ar2 PO E E' X Y Z diff_exists
          by presburger  
        have "Ps PO E dZC" 
        proof -
          have "Sum PO E E' dXA dYB dZC"
            using Diff PO E E' X A dXA Diff PO E E' Y B dYB Diff PO E E' Z C dZC
              assms(3,4) sum_diff2_diff_sum2_b by blast 
          thus ?thesis
            by (metis LtP_def Diff PO E E' X A dXA Diff PO E E' Y B dYB
                LtP PO E E' A X LtP PO E E' B Y diff_uniqueness sum_pos_pos) 
        qed
        hence "LeP PO E E' C Z"
          using LeP_def LtP_def Diff PO E E' Z C dZC by blast 
      }
      moreover 
      {
        assume "B = Y"
        hence "LtP PO E E' C Z"
          by (smt (verit, best) Ar2_def LtP_def Ar2 PO E E' X Y Z LtP PO E E' A X
              assms(3,4) diff_sum local.sum_diff sum_assoc_1 sum_comm) 
        hence "LeP PO E E' C Z"
          by (simp add: LeP_def) 
      }
      ultimately show ?thesis
        using LeP_def assms(2) by auto 
    qed
  }
  moreover {
    assume "A = X"
    hence "LeP PO E E' C Z"
    proof -
      {
        assume "LtP PO E E' B Y"
        have "LtP PO E E' C Z"
          by (smt (z3) LtP_def A = X LtP PO E E' B Y assms(3,4) diff_sum
              local.sum_diff sum_assoc_1) 
      }
      hence "LtP PO E E' B Y  LeP PO E E' C Z"
        by (simp add: LeP_def) 
      moreover have "B = Y  LeP PO E E' C Z"
        using A = X assms(3,4) leP_refl sum_stable by blast 
      ultimately show ?thesis
        using LeP_def assms(2) by blast 
    qed
  }
  ultimately show ?thesis
    using LeP_def assms(1) by blast 
qed

lemma square_pos:
  assumes "PO  A"
    and "Prod PO E E' A A A2"
  shows "Ps PO E A2" 
proof -
  have "¬ Col PO E E'"
    using Ar2_def Prod_def assms(2) by blast 
  have "Col PO E A"
    using Ar2_def Prod_def assms(2) by force 
  then obtain MA where "Opp PO E E' A MA"
    using ¬ Col PO E E' opp_exists by blast 
  hence "Ps PO E A  PO = A  Ps PO E MA"
    by (simp add: pos_null_neg)
  moreover have "Ps PO E A  Ps PO E A2"
    using assms(2) prod_pos_pos by blast 
  moreover have "PO = A  Ps PO E A2"
    by (simp add: assms(1)) 
  moreover 
  {
    assume "Ps PO E MA"
    obtain ME where "Opp PO E E' E ME"
      using ¬ Col PO E E' col_trivial_2 opp_exists by blast 
    have "Prod PO E E' MA MA A2"
      by (meson Opp PO E E' A MA Opp PO E E' E ME ¬ Col PO E E' assms(2)
          opp_comm opp_prod prod_assoc prod_sym) 
    hence "Ps PO E A2"
      using Ps PO E MA prod_pos_pos by blast 
  }
  ultimately show ?thesis
    by blast 
qed

lemma ltP_neg:
  assumes "LtP PO E E' A PO"
  shows "Ng PO E A" 
proof -
  obtain MA where "Diff PO E E' PO A MA"
    using LtP_def assms by blast 
  hence "Opp PO E E' MA A"
    by (simp add: Opp_def diff_sum) 
  have "¬ Col PO E E'"
    using Ar2_def assms ltP_ar2 by blast 
  thus ?thesis
    using LtP_def Diff PO E E' PO A MA Opp PO E E' MA A assms diff_uniqueness
      pos_opp_neg by blast 
qed

lemma ps_le:
  assumes "¬ Col PO E E'"
    and "Bet PO X E  Bet PO E X"
  shows "LeP PO E E' PO X" 
proof (cases "PO = X")
  show "PO = X  LeP PO E E' PO X"
    by (simp add: leP_refl) 
  {
    assume "PO  X"
    have "Diff PO E E' X PO X"
      using assms(1,2) bet_col diff_A_O not_col_permutation_5 by blast 
    moreover have "Ps PO E X"
      by (metis Bet_cases Col_def Ps_def PO  X assms(1,2) between_equality_2
          col_trivial_1 or_bet_out) 
    ultimately show "LeP PO E E' PO X"
      using LeP_def LtP_def by auto 
  }
qed

lemma lt_diff_ps:
  assumes (*"Col PO E X"
and "Col PO E Y"
and*) "LtP PO E E' Y X"
    and "Diff PO E E' X Y XMY"
  shows "Ps PO E XMY"
  using LtP_def assms(1,2) diff_stable by blast 

lemma col_2_le_or_ge:
  assumes "¬ Col PO E E'"
    and "Col PO E A"
    and "Col PO E B"
  shows "LeP PO E E' A B  LeP PO E E' B A" 
proof (cases "A = B")
  have "PO  E"
    using assms(1) col_trivial_1 by auto 
  show "A = B  LeP PO E E' A B  LeP PO E E' B A"
    by (simp add: leP_refl) 
  {
    assume "A  B"
    obtain D where "Diff PO E E' B A D"
      using assms(1,2,3) diff_exists by blast
    hence "PO  D"
      using A  B diff_null_eq by blast 
    hence "Ps PO E D  Ng PO E D"
      using Ar2_def Diff PO E E' B A D PO  E col_pos_or_neg diff_ar2
      by presburger 
    moreover have "Ps PO E D  LeP PO E E' A B"
      using LeP_def LtP_def Diff PO E E' B A D by blast 
    moreover 
    {
      assume "Ng PO E D"
      obtain MD where "Diff PO E E' A B MD"
        using assms(1,2,3) diff_exists by blast 
      hence "Opp PO E E' D MD"
        using Diff PO E E' B A D diff_opp by auto 
      hence "LeP PO E E' B A"
        using LeP_def LtP_def Diff PO E E' A B MD Ng PO E D opp_neg_pos
        by blast 
    }
    ultimately show "LeP PO E E' A B  LeP PO E E' B A" 
      by blast
  }
qed

lemma compatibility_of_sum_with_order:
  assumes "LeP PO E E' A B"
    and "Sum PO E E' A C APC"
    and "Sum PO E E' B C BPC"
  shows "LeP PO E E' APC BPC"
  using assms(1,2,3) leP_refl leP_sum_leP by blast 

lemma compatibility_of_prod_with_order:
  assumes "LeP PO E E' PO A"
    and "LeP PO E E' PO B"
    and "Prod PO E E' A B AB"
  shows "LeP PO E E' PO AB" 
proof -
  have "PO = A  ?thesis"
    using assms(3) leP_refl prod_O_l_eq by blast 
  moreover {
    assume "LtP PO E E' PO A"
    have "PO = B  LeP PO E E' PO AB"
      using assms(3) leP_refl prod_O_r_eq by blast 
    moreover 
    {
      assume "LtP PO E E' PO B"
      have "Ps PO E AB"
        by (metis Ar2_def LtP PO E E' PO A LtP PO E E' PO B assms(3) diff_A_O
            ltP_ar2 lt_diff_ps prod_pos_pos) 
      hence "LeP PO E E' PO AB"
        by (metis Ar2_def LeP_def Prod_def assms(3) col_2_le_or_ge col_trivial_3
            ltP_neg pos_not_neg) 
    }
    ultimately have "LeP PO E E' PO AB"
      using LeP_def assms(2) by auto 
  } 
  ultimately show ?thesis
    using LeP_def assms(1) by blast 
qed

lemma pos_inv_pos:
  assumes "PO  A"
    and "LeP PO E E' PO A"
    and "Prod PO E E' IA A E"
  shows "LeP PO E E' PO IA" 
proof -
  have "PO = A  LeP PO E E' PO IA"
    by (simp add: assms(1)) 
  moreover 
  {
    assume "LtP PO E E' PO A"
    then obtain IA' where "Diff PO E E' IA PO IA'"
      by (meson Ar2_def Prodp_def assms(3) diff_A_O ltP_ar2 prod_to_prodp) 
    hence "IA = IA'"
      by (meson Ar2_def diff_A_O diff_ar2 diff_stable)
    obtain A' where "Diff PO E E' A PO A'" and "Ps PO E A'"
      using LtP_def LtP PO E E' PO A by blast 
    hence "A = A'"
      by (metis Ar2_def diff_ar2 diff_sum sum_O_B_eq) 
    obtain MIA where "Opp PO E E' IA MIA"
      by (metis Ar2_def Diff PO E E' IA PO IA' diff_ar2 opp_exists) 
    have "Ps PO E IA  PO = IA  Ps PO E MIA"
      using Opp PO E E' IA MIA pos_null_neg by auto
    moreover have "PO = IA  LeP PO E E' PO IA"
      by (simp add: leP_refl) 
    moreover {
      assume "Ps PO E MIA"
      obtain ME where "Opp PO E E' E ME"
        by (meson Ar2_def Diff PO E E' A PO A' diff_ar2 not_col_distincts
            opp_exists)
      moreover have "Prod PO E E' IA ME MIA"
        by (simp add: Opp PO E E' IA MIA calculation opp_prod) 
      moreover have "Prod PO E E' MIA A ME"
        by (meson assms(3) calculation(1,2) opp_prod prod_assoc prod_sym) 
      ultimately have False
        by (metis Ar2_def Ng_def A = A' Diff PO E E' IA PO IA'
            Ps PO E A' Ps PO E MIA bet_neq12__neq diff_ar2
            opp_comm pos_opp_neg prod_pos_pos) 
    }
    moreover have "Ps PO E IA  LeP PO E E' PO IA"
      using LeP_def LtP_def Diff PO E E' IA PO IA' IA = IA' by auto 
    ultimately have "LeP PO E E' PO IA" 
      by blast
  }
  ultimately show ?thesis
    using LeP_def assms(2) by auto 
qed

lemma le_pos_prod_le:
  assumes "LeP PO E E' A B"
    and "LeP PO E E' PO C"
    and "Prod PO E E' A C AC"
    and "Prod PO E E' B C BC"
  shows "LeP PO E E' AC BC" 
proof -
  obtain BCMAC where "Diff PO E E' BC AC BCMAC"
    using Ar2_def Prod_def assms(3,4) diff_exists by presburger 
  obtain BMA where "Diff PO E E' B A BMA"
    by (metis Ar2_def LeP_def LtP_def Prod_def assms(1,3) diff_null)
  then obtain BCMAC' where "Prod PO E E' BMA C BCMAC'"
    using Ar2_def Prodp_def assms(4) diff_ar2 prod_exists
      prod_to_prodp by presburger 
  hence "Diff PO E E' BC AC BCMAC'"
    using Diff PO E E' B A BMA assms(3,4) distr_l_diff prod_sym by blast 
  hence "BCMAC = BCMAC'"
    using Diff PO E E' BC AC BCMAC diff_uniqueness
    by auto 
  hence "LeP PO E E' PO BCMAC"
    by (metis Ar2_def LeP_def Out_def Ps_def
        Diff PO E E' B A BMA Prod PO E E' BMA C BCMAC' assms(1,2)
        compatibility_of_prod_with_order cong_identity_inv diff_ar2 diff_sum
        lt_diff_ps ps_le sum_iff_cong_b) 
  thus ?thesis
    by (metis Ar2_def LeP_def LtP_def Diff PO E E' BC AC BCMAC diff_A_O
        diff_null_eq ltP_ar2 lt_diff_ps) 
qed

lemma bet_lt12_le23:
  assumes "Bet A B C"
    and "LtP PO E E' A B"
  shows "LeP PO E E' B C" 
proof (cases "B = C")
  show "B = C  LeP PO E E' B C"
    by (simp add: leP_refl) 
  {
    assume "B  C"
    have "A  B"
      using assms(2) ltP_neq by auto 
    have "Col PO E A"
      using Ar2_def assms(2) ltP_ar2 by blast 
    have "Col PO E B"
      using Ar2_def assms(2) ltP_ar2 by blast 
    then obtain CMB where "Diff PO E E' C B CMB" 
      using diff_exists by (metis Ar2_def Col_def A  B assms(1,2) col_transitivity_1
          col_trivial_1 ltP_ar2) 
    show "LeP PO E E' B C" 
    proof (cases "PO = A")
      show "PO = A  LeP PO E E' B C" 
      proof (cases "PO = B")
        show "PO = A  PO = B  LeP PO E E' B C"
          using A  B by fastforce 
        show "PO = A  PO  B  LeP PO E E' B C" 
        proof (cases "PO = C")
          show "PO = A  PO  B  PO = C  LeP PO E E' B C"
            using assms(1) bet_neq12__neq by auto 
          {
            assume "PO = A" and "PO  B" and "PO  C"
            obtain B' where "Diff PO E E' B PO B'" and "Ps PO E B'"
              using LtP_def PO = A assms(2) by auto
            hence "B = B'"
              by (metis Ar2_def diff_ar2 diff_sum sum_O_B_eq)
            have "E  PO"
              using Ar2_def Diff PO E E' B PO B' col_trivial_1 diff_ar2 by blast 
            moreover 
            have "ParallelogramFlat PO B C CMB"
              using Diff PO E E' C B CMB PO  C diff_to_plg by force 
            hence "Bet CMB C PO  Bet C PO B  Bet CMB PO C  Bet PO C B  
                   Bet PO CMB B  Bet CMB B C  Bet PO B CMB  Bet B CMB C"
              by (simp add: plgf_bet) 
            moreover have "Bet CMB C PO  Bet C PO B  Bet PO CMB E  Bet PO E CMB"
              using Bet_cases PO = A PO  B assms(1) between_equality_2
              by blast 
            moreover have "Bet CMB PO C  Bet PO C B  Bet PO CMB E  Bet PO E CMB"
              using B  C PO = A assms(1) between_equality_2 by auto 
            moreover have "Bet PO CMB B  Bet CMB B C  Bet PO CMB E  Bet PO E CMB"
              by (metis Ar2_def Bet_cases Ps_def B = B' Diff PO E E' C B CMB
                  Ps PO E B' bet_out__bet between_equality_2 diff_sum l6_6 sum_ar2
                  third_point) 
            moreover have "Bet PO B CMB  Bet B CMB C  Bet PO CMB E  Bet PO E CMB"
              by (metis Bet_cases Col_def Ng_def B = B' Col PO E B PO  B
                  Ps PO E B' between_inner_transitivity col2__eq col_permutation_4
                  pos_not_neg) 
            ultimately have "Bet PO CMB E  Bet PO E CMB"
              by blast 
            have "E  PO  (Bet PO CMB E  Bet PO E CMB)"
              by (simp add: E  PO (PO  CMB  E)  (PO  E  CMB))
            hence "Ps PO E CMB"
              by (metis Out_cases Ps_def B  C Diff PO E E' C B CMB bet_out_1
                  between_symmetry diff_null_eq) 
            thus "LeP PO E E' B C"
              using LeP_def LtP_def Diff PO E E' C B CMB by blast 
          }
        qed
      qed
      show "PO  A  LeP PO E E' B C" 
      proof (cases "PO = B")
        show "PO  A  PO = B  LeP PO E E' B C"
          by (metis Ar2_def Ng_def assms(1,2) l5_2 ltP_ar2 ltP_neg ps_le) 
        show "PO  A  PO  B  LeP PO E E' B C" 
        proof (cases "PO = C")
          {
            assume "PO  A" and "PO  B" and "PO = C"
            have "Ps PO E B  Ng PO E B"
              using LtP_def Diff PO E E' C B CMB PO = C PO  B diff_O_A_opp ltP_neg
                pos_null_neg by blast 
            {
              assume "Ps PO E B"
              have "Ps PO E A  Ng PO E A"
                by (metis NCol_cases Ng_def Ps_def Col PO E A PO  A Ps PO E B
                    or_bet_out out_distinct)
              moreover {
                assume "Ps PO E A"
                obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                  using LtP_def assms(2) diff_sum by blast 
                have "False" 
                proof (cases "A = BMA")
                  show "A = BMA  False"
                    by (metis Bet_cases A  B PO = C Sum PO E E' A BMA B assms(1) bet_out
                        between_equality_2 between_trivial l14_36_a) 
                  {
                    assume "A  BMA"
                    hence "ParallelogramFlat PO A B BMA"
                      by (metis Ar2_def Sum PO E E' A BMA B sum_ar2 sum_cong) 
                    hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A  
                           Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B" 
                      using plgf_bet by simp 
                    moreover have "Bet BMA B PO  Bet B PO A  False"
                      using Bet_cases PO = C PO  B assms(1) between_equality
                      by blast 
                    moreover have "Bet BMA PO B  Bet PO B A  False"
                      by (meson Ps_def Ps PO E BMA Ps PO E B bet_out__bet l6_6
                          not_bet_and_out) 
                    moreover have "Bet PO BMA A  Bet BMA A B  False"
                      by (metis Bet_cases A  BMA A  B PO = C assms(1) between_equality_2
                          outer_transitivity_between2) 
                    moreover have " Bet PO A BMA  Bet A BMA B  False"
                      by (metis Bet_cases A  BMA PO = C assms(1) between_equality_2
                          outer_transitivity_between) 
                    ultimately show False 
                      by blast
                  }
                qed
              }
              moreover have "Ng PO E A  False"
                by (metis Ng_def PO = C PO  B Ps PO E B assms(1) between_exchange3
                    pos_not_neg) 
              ultimately have "False"
                by auto 
            }
            hence "Ng PO E B"
              using Ps PO E B  Ng PO E B by auto 
            thus "LeP PO E E' B C"
              by (metis LeP_def LtP_def Diff PO E E' C B CMB PO = C diff_O_A_opp
                  opp_neg_pos) 
          }
          {
            assume "PO  A" and "PO  B" and "PO  C"
            have "Sum PO E E' B CMB C"
              by (simp add: Diff PO E E' C B CMB diff_sum) 
            have "ParallelogramFlat PO B C CMB"
              using Diff PO E E' C B CMB PO  C diff_to_plg by presburger 
            hence "Bet CMB C PO  Bet C PO B  Bet CMB PO C  Bet PO C B  
                   Bet PO CMB B  Bet CMB B C  Bet PO B CMB  Bet B CMB C" 
              using  plgf_bet by simp 
            have "E  PO"
              using Ar2_def Diff PO E E' C B CMB col_trivial_1 diff_ar2 by blast 
            moreover have "Bet PO CMB E  Bet PO E CMB" 
            proof -
              have "Ps PO E A  Ng PO E A"
                using Col PO E A PO  A calculation col_pos_or_neg by auto 
              moreover have "Ps PO E B  Ng PO E B"
                using Col PO E B E  PO PO  B col_pos_or_neg by auto
              moreover 
              {
                assume "Ps PO E A" and "Ps PO E B"
                hence "Bet PO A E  Bet PO E A"
                  by (metis Ng_def Col PO E A E  PO pos_not_neg third_point) 
                have "Bet PO B E  Bet PO E B"
                  by (metis Bet_cases Col_def Ng_def Col PO E B Ps PO E B pos_not_neg) 
                {
                  assume "Bet CMB C PO  Bet C PO B" 
                  {
                    assume "Ps PO E A"
                    {
                      assume "Bet PO A E"
                      {
                        assume "Bet PO B E"
                        hence "Bet PO A B  Bet PO B A"
                          using PO  A  E l5_3 by auto 
                        moreover {
                          assume "Bet PO A B  Bet PO B A"
                          moreover have "Bet PO A B  Bet PO CMB E  Bet PO E CMB"
                            by (metis Bet_cases A  B (CMB  C  PO)  (C  PO  B) 
                                assms(1) between_equality_2 between_exchange2) 
                          moreover {
                            assume "Bet PO B A"
                            obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                              using LtP_def assms(2) diff_sum by blast 
                            have "Bet PO CMB E  Bet PO E CMB" 
                            proof (cases "A = BMA")
                              show "A = BMA  (PO  CMB  E)  (PO  E  CMB)"
                                by (metis Sum PO E E' A BMA B bet_out_1 between_trivial2 
                                    calculation(2) l14_36_a) 
                              have "ParallelogramFlat PO A B BMA"
                                by (metis PO  A Sum PO E E' A BMA B 
                                    diff_to_plg local.sum_diff) 
                              hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A  
                                     Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B"
                                by (simp add: plgf_bet) 
                              {
                                assume "A  BMA"
                                have "Bet BMA B PO  Bet B PO A  
                                       (PO  CMB  E)  (PO  E  CMB)"
                                  using PO  B  A PO  B between_equality by auto 
                                moreover have "Bet BMA PO B  Bet PO B A  
                                                (PO  CMB  E)  (PO  E  CMB)"
                                  by (meson Bet_cases Ps_def Ps PO E BMA Ps PO E B 
                                      bet_out__bet not_bet_and_out) 
                                moreover have "Bet PO BMA A  Bet BMA A B  
                                                (PO  CMB  E)  (PO  E  CMB)"
                                  using A  BMA 
                                    (PO  A  B)  (PO  CMB  E)  (PO  E  CMB)
                                    outer_transitivity_between2 by blast 
                                moreover have "Bet PO A BMA  Bet A BMA B  
                                                (PO  CMB  E)  (PO  E  CMB)"
                                  using A  BMA 
                                    (PO  A  B)  (PO  CMB  E)  (PO  E  CMB) 
                                    outer_transitivity_between by blast 
                                ultimately show "(PO  CMB  E)  (PO  E  CMB)"
                                  using Bet BMA B PO  Bet B PO A  
                                         Bet BMA PO B  Bet PO B A  
                                         Bet PO BMA A  Bet BMA A B  
                                         Bet PO A BMA  Bet A BMA B by blast 
                              }
                            qed
                          }
                          ultimately have "Bet PO CMB E  Bet PO E CMB"
                            by auto 
                        }
                        ultimately have "Bet PO CMB E  Bet PO E CMB"
                          by simp 
                      }
                      moreover have "Bet PO E B  Bet PO CMB E  Bet PO E CMB"
                        by (metis Bet_cases (CMB  C  PO)  (C  PO  B) 
                            PO  A  E assms(1) between_exchange3 calculation) 
                      ultimately have "Bet PO CMB E  Bet PO E CMB"
                        using (PO  B  E)  (PO  E  B) by blast 
                    }
                    moreover {
                      assume "Bet PO E A"
                      hence "Bet PO A B  Bet PO B A"
                        by (metis E  PO (PO  B  E)  (PO  E  B) 
                            between_exchange4 l5_1)
                      moreover have "Bet PO A B  Bet PO CMB E  Bet PO E CMB"
                        by (meson A  B (CMB  C  PO)  (C  PO  B) PO  B
                            assms(1) between_equality between_symmetry
                            outer_transitivity_between2) 
                      moreover {
                        assume "Bet PO B A"
                        obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                          using LtP_def assms(2) diff_sum by blast 
                        have "Bet PO CMB E  Bet PO E CMB" 
                        proof (cases "A = BMA")
                          show "A = BMA  (PO  CMB  E)  (PO  E  CMB)"
                            by (metis Sum PO E E' A BMA B bet_out_1 between_trivial2 
                                calculation(2) l14_36_a) 
                          {
                            assume "A  BMA"
                            have "ParallelogramFlat PO A B BMA"
                              by (metis PO  A Sum PO E E' A BMA B diff_to_plg 
                                  local.sum_diff) 
                            hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A  
                                   Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B"
                              by (simp add: plgf_bet) 
                            moreover have "Bet BMA B PO  Bet B PO A  
                                            (PO  CMB  E)  (PO  E  CMB)"
                              using PO  B  A PO  B between_equality by auto 
                            moreover have "Bet BMA PO B  Bet PO B A  
                                            (PO  CMB  E)  (PO  E  CMB)"
                              using Out_cases Ps_def Ps PO E BMA Ps PO E B 
                                bet_out__bet not_bet_and_out by blast
                            moreover have "Bet PO BMA A  Bet BMA A B  
                                            (PO  CMB  E)  (PO  E  CMB)"
                              using A  BMA 
                                (PO  A  B)  (PO  CMB  E)  (PO  E  CMB) 
                                outer_transitivity_between2 by blast
                            moreover have "Bet PO A BMA  Bet A BMA B  
                                            (PO  CMB  E)  (PO  E  CMB)"
                              using A  BMA 
                                (PO  A  B)  (PO  CMB  E)  (PO  E  CMB)
                                outer_transitivity_between by blast
                            ultimately show "(PO  CMB  E)  (PO  E  CMB)"
                              by blast 
                          }
                        qed
                      }
                      ultimately have "Bet PO CMB E  Bet PO E CMB" 
                        by blast
                    }
                    ultimately have "Bet PO CMB E  Bet PO E CMB"
                      using (PO  A  E)  (PO  E  A) by blast 
                  }
                  moreover have "Ng PO E A  Bet PO CMB E  Bet PO E CMB"
                    by (simp add: Ps PO E A calculation) 
                  ultimately have "Bet PO CMB E  Bet PO E CMB"
                    by (simp add: Ps PO E A) 
                }
                moreover {
                  assume "Bet CMB PO C"  and "Bet PO C B"
                  {
                    assume "Bet PO A E" and "Bet PO B E"
                    have "Bet PO A B  Bet PO B A"
                      using PO  A  E PO  B  E l5_3 by auto 
                    moreover have "Bet PO A B  Bet PO CMB E  Bet PO E CMB"
                      using A  B B  C PO  C  B assms(1) between_equality_2 
                        outer_transitivity_between2
                      by blast 
                    moreover {
                      assume "Bet PO B A"
                      obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                        using LtP_def assms(2) diff_sum by blast 
                      have "Bet PO CMB E  Bet PO E CMB" 
                      proof (cases "A = BMA")
                        show "A = BMA  (PO  CMB  E)  (PO  E  CMB)"
                          using PO  A Sum PO E E' A BMA B bet_out between_trivial 
                            calculation(2) l14_36_a
                          by auto 
                        {
                          assume "A  BMA"
                          have "ParallelogramFlat PO A B BMA"
                            by (metis PO  A Sum PO E E' A BMA B 
                                diff_to_plg local.sum_diff) 
                          hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A  
                                 Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B"
                            using plgf_bet by blast
                          moreover have "Bet BMA B PO  Bet B PO A  
                                          Bet PO CMB E  Bet PO E CMB"
                            using PO  B  A PO  B between_equality by auto 
                          moreover have "Bet BMA PO B  Bet PO B A  
                                          Bet PO CMB E  Bet PO E CMB"
                            using Ps_def PO  B  E PO  B Ps PO E BMA 
                              not_bet_and_out outer_transitivity_between by blast 
                          moreover have "Bet PO BMA A  Bet BMA A B  
                                          Bet PO CMB E  Bet PO E CMB"
                            using A  BMA (PO  A  B)  (PO  CMB  E)  (PO  E  CMB) 
                              outer_transitivity_between2 by blast 
                          moreover have "Bet PO A BMA  Bet A BMA B  
                                          Bet PO CMB E  Bet PO E CMB"
                            using A  BMA (PO  A  B)  (PO  CMB  E)  (PO  E  CMB) 
                              outer_transitivity_between by blast 
                          ultimately show "(PO  CMB  E)  (PO  E  CMB)" 
                            by blast
                        }
                      qed
                    }
                    ultimately have "Bet PO CMB E  Bet PO E CMB"
                      by blast 
                  }
                  moreover have "Bet PO A E  Bet PO E B  Bet PO CMB E  Bet PO E CMB"
                    by (metis Bet_cases A  B B  C PO  C  B assms(1) 
                        between_equality between_exchange2 outer_transitivity_between) 
                  moreover {
                    assume "Bet PO E A" and "Bet PO B E"
                    obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                      using LtP_def assms(2) diff_sum by blast 
                    have "Bet PO CMB E  Bet PO E CMB" 
                    proof (cases "A = BMA")
                      show "A = BMA  (PO  CMB  E)  (PO  E  CMB)"
                        by (metis A  B PO  B  E PO  E  A Sum PO E E' A BMA B 
                            bet_out_1 between_equality_2 between_exchange4 
                            between_trivial2 l14_36_a) 
                      {
                        assume "A  BMA"
                        have "ParallelogramFlat PO A B BMA"
                          by (metis PO  A Sum PO E E' A BMA B diff_to_plg local.sum_diff) 
                        hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A  
                               Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B" 
                          using plgf_bet by blast
                        moreover have "Bet BMA B PO  Bet B PO A  Bet PO CMB E  Bet PO E CMB"
                          using PO  B  E PO  E  A PO  B between_equality 
                            between_inner_transitivity by blast 
                        moreover have "Bet BMA PO B  Bet PO B A  Bet PO CMB E  Bet PO E CMB"
                          by (metis Bet_cases Ng_def O_not_positive E  PO PO  B  E 
                              PO  B Ps PO E BMA
                              neg_not_pos outer_transitivity_between2) 
                        moreover have "Bet PO BMA A  Bet BMA A B  Bet PO CMB E  Bet PO E CMB"
                          using A  BMA 
                            (PO  A  E)  (PO  B  E)  (PO  CMB  E)  (PO  E  CMB) 
                            PO  B  E between_exchange4 outer_transitivity_between2 by blast 
                        moreover have "Bet PO A BMA  Bet A BMA B  Bet PO CMB E  Bet PO E CMB"
                          using A  BMA 
                            (PO  A  E)  (PO  B  E)  (PO  CMB  E)  (PO  E  CMB) 
                            PO  B  E
                            between_exchange4 outer_transitivity_between2 by blast 
                        ultimately show "(PO  CMB  E)  (PO  E  CMB)" 
                          by blast
                      }
                    qed
                  }
                  moreover {
                    assume "Bet PO E A" and "Bet PO E B"
                    obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                      by (meson LtP_def assms(2) diff_sum) 
                    have "Bet PO CMB E  Bet PO E CMB" 
                    proof (cases "A = BMA")
                      show "A = BMA  (PO  CMB  E)  (PO  E  CMB)"
                        by (metis A  B B  C PO  C  B Sum PO E E' A BMA B 
                            assms(1) bet_out between_equality_2
                            between_exchange2 between_trivial l14_36_a outer_transitivity_between) 
                      {
                        assume "A  BMA"
                        have "ParallelogramFlat PO A B BMA"
                          by (metis PO  A Sum PO E E' A BMA B diff_to_plg local.sum_diff)
                        hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A  
                               Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B" 
                          using plgf_bet by blast
                        moreover have "Bet BMA B PO  Bet B PO A  Bet PO CMB E  Bet PO E CMB"
                          by (meson Bet_cases B  C PO  C  B assms(1) 
                              between_equality_2 between_exchange3) 
                        moreover have "Bet BMA PO B  Bet PO B A  Bet PO CMB E  Bet PO E CMB"
                          by (metis Bet_cases Ps_def PO  E  B Ps PO E BMA 
                              between_exchange3 not_bet_and_out) 
                        moreover have "Bet PO BMA A  Bet BMA A B  Bet PO CMB E  Bet PO E CMB"
                          by (metis A  BMA A  B B  C PO  C  B assms(1) 
                              between_equality_2 outer_transitivity_between2) 
                        moreover have "Bet PO A BMA  Bet A BMA B  Bet PO CMB E  Bet PO E CMB"
                          by (metis A  BMA B  C PO  C  B assms(1) 
                              between_equality_2 between_exchange3 outer_transitivity_between2) 
                        ultimately show "(PO  CMB  E)  (PO  E  CMB)" 
                          by blast
                      }
                    qed
                  }
                  ultimately have "Bet PO CMB E  Bet PO E CMB"
                    using (PO  A  E)  (PO  E  A) (PO  B  E)  (PO  E  B) by auto 
                }
                moreover have "Bet PO CMB B  Bet CMB B C  Bet PO CMB E  Bet PO E CMB"
                  by (meson (PO  B  E)  (PO  E  B) between_exchange4 l5_3) 
                moreover have "Bet PO B CMB  Bet B CMB C  Bet PO CMB E  Bet PO E CMB"
                  using (PO  B  E)  (PO  E  B) PO  B between_exchange4 l5_1 by blast 
                ultimately have "Bet PO CMB E  Bet PO E CMB" 
                  using Bet CMB C PO  Bet C PO B  Bet CMB PO C  Bet PO C B  
                         Bet PO CMB B  Bet CMB B C  Bet PO B CMB  Bet B CMB C by blast
              }
              moreover have "Ps PO E A  Ng PO E B  Bet PO CMB E  Bet PO E CMB"
                using LtP_def assms(2) calculation(3) diff_sum sum_pos_pos by blast  
              moreover {
                assume "Ng PO E A" and "Ps PO E B"
                have "Bet CMB C PO  Bet C PO B  Bet PO CMB E  Bet PO E CMB"
                  by (meson Bet_cases Ng_def Out_cases Ps_def Ng PO E A PO  B Ps PO E B 
                      assms(1)
                      bet_out__bet between_equality between_inner_transitivity) 
                moreover have "Bet CMB PO C  Bet PO C B  Bet PO CMB E  Bet PO E CMB"
                  by (smt (verit, ccfv_threshold) Bet_cases Ng_def B  C Ng PO E A PO  B 
                      Ps PO E B
                      assms(1) between_inner_transitivity outer_transitivity_between2 pos_not_neg)
                moreover have "Bet PO CMB B  Bet CMB B C  Bet PO CMB E  Bet PO E CMB"
                  by (meson Bet_cases Col_def Ps_def Col PO E B Ps PO E B between_exchange2 
                      l5_3 not_bet_and_out) 
                moreover have "Bet PO B CMB  Bet B CMB C  Bet PO CMB E  Bet PO E CMB"
                  by (meson Ar2_def Bet_cases Ps_def Ps PO E B Sum PO E E' B CMB C 
                      between_inner_transitivity
                      not_bet_and_out sum_ar2 third_point) 
                ultimately have "Bet PO CMB E  Bet PO E CMB" 
                  using Bet CMB C PO  Bet C PO B  Bet CMB PO C  Bet PO C B  
                         Bet PO CMB B  Bet CMB B C  Bet PO B CMB  Bet B CMB C
                  by blast
              }
              moreover 
              {
                assume "Ng PO E A" and "Ng PO E B"
                have "Bet CMB C PO  Bet C PO B  Bet PO CMB E  Bet PO E CMB"
                  by (metis Ng_def Ng PO E B PO  C between_symmetry l5_2 
                      outer_transitivity_between2)
                moreover have "Bet CMB PO C  Bet PO C B  Bet PO CMB E  Bet PO E CMB"
                  by (smt (verit, ccfv_SIG) Bet_cases Col_def Ng_def Ng PO E B PO  C
                      between_equality_2 between_inner_transitivity l6_16_1) 
                moreover {
                  assume "Bet PO CMB B" and "Bet CMB B C"
                  {
                    assume "Bet A PO E"
                    {
                      assume "Bet B PO E"
                      have "Bet PO A B  Bet PO B A"
                        by (meson A  PO  E B  PO  E E  PO between_symmetry l5_2) 
                      moreover {
                        assume "Bet PO A B"
                        obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                          using LtP_def assms(2) diff_sum by blast 
                        hence "ParallelogramFlat PO A B BMA"
                          by (metis PO  A diff_to_plg local.sum_diff) 
                        hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A 
                                Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B" 
                          using plgf_bet by blast
                        have "Bet PO CMB E  Bet PO E CMB" 
                        proof (cases "A = BMA")
                          show "A = BMA  (PO  CMB  E)  (PO  E  CMB)"
                            using Ng PO E B 
                              Ps PO E A  Ng PO E B  (PO  CMB  E)  (PO  E  CMB)
                              Ps PO E BMA by auto 
                          {
                            assume "A  BMA"
                            have "Bet BMA B PO  Bet B PO A  Bet PO CMB E  Bet PO E CMB"
                              using Bet_cases PO  A  B PO  A between_equality by blast 
                            moreover have "Bet BMA PO B  Bet PO B A  
                                            Bet PO CMB E  Bet PO E CMB"
                              using A  B PO  A  B between_equality_2 by auto 
                            moreover have "Bet PO BMA A  Bet BMA A B  
                                            Bet PO CMB E  Bet PO E CMB"
                              using Bet_cases Ps_def A  PO  E Ps PO E BMA 
                                between_exchange3 not_bet_and_out by blast 
                            moreover have "Bet PO A BMA  Bet A BMA B  
                                            Bet PO CMB E  Bet PO E CMB"
                              by (metis Bet_cases Ng_def A  PO  E E  PO PO  A
                                  Ps PO E BMA between_equality neg_not_pos 
                                  outer_transitivity_between2) 
                            ultimately show "(PO  CMB  E)  (PO  E  CMB)" 
                              using Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A 
                                     Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B
                              by blast
                          }
                        qed
                      }
                      moreover {
                        assume "Bet PO B A"
                        have "Bet PO B C"
                          by (metis Out_def CMB  B  C PO  CMB  B PO  B 
                              Sum PO E E' B CMB C l14_36_a)
                        have "Bet B A C  Bet PO CMB E  Bet PO E CMB"
                          using A  B assms(1) between_equality by blast 
                        hence "Bet PO CMB E  Bet PO E CMB"
                          by (meson Bet_cases B  C PO  B  A PO  B  C PO  B 
                              assms(1) between_equality l5_2) 
                      }
                      ultimately have "Bet PO CMB E  Bet PO E CMB" 
                        by blast
                    }
                    hence "Bet PO CMB E  Bet PO E CMB"
                      using Ng_def Ng PO E B by blast 
                  }
                  hence "Bet PO CMB E  Bet PO E CMB"
                    using Ng_def Ng PO E A by auto 
                }
                moreover {
                  assume "Bet PO B CMB" and "Bet B CMB C"
                  {
                    assume "Bet A PO E"
                    {
                      assume "Bet B PO E"
                      obtain BMA where "Sum PO E E' A BMA B" and "Ps PO E BMA"
                        using LtP_def assms(2) diff_sum by blast 
                      hence "ParallelogramFlat PO A B BMA"
                        by (metis PO  A diff_to_plg local.sum_diff) 
                      hence "Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A 
                             Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B" 
                        using plgf_bet by blast
                      {
                        assume "Bet PO A B"
                        have "Bet BMA B PO  Bet B PO A  Bet PO CMB E  Bet PO E CMB"
                          by (meson Bet_cases PO  A  B PO  A between_equality) 
                        moreover have "Bet BMA PO B  Bet PO B A  Bet PO CMB E  Bet PO E CMB"
                          using A  B PO  A  B between_equality_2 by auto 
                        moreover have "Bet PO BMA A  Bet BMA A B  Bet PO CMB E  Bet PO E CMB"
                          by (metis Bet_cases Ng_def O_not_positive A  PO  E E  PO 
                              Ps PO E BMA between_exchange3 pos_not_neg) 
                        moreover have "Bet PO A BMA  Bet A BMA B  Bet PO CMB E  Bet PO E CMB"
                          by (meson Bet_cases Ps_def A  PO  E PO  A Ps PO E BMA 
                              not_bet_and_out outer_transitivity_between) 
                        ultimately have "Bet PO CMB E  Bet PO E CMB" 
                          using Bet BMA B PO  Bet B PO A  Bet BMA PO B  Bet PO B A 
                                 Bet PO BMA A  Bet BMA A B  Bet PO A BMA  Bet A BMA B 
                          by blast
                      }
                      moreover {
                        assume "Bet PO B A"
                        have "Bet PO B C"
                          using B  CMB  C B  PO  E E  PO PO  B  CMB
                            (PO  CMB  B)  (CMB  B  C)  (PO  CMB  E)  (PO  E  CMB) 
                            between_equality
                            outer_transitivity_between by blast 
                        have "Bet PO CMB E  Bet PO E CMB" 
                        proof (cases "B = CMB")
                          show "B = CMB  (PO  CMB  E)  (PO  E  CMB)"
                            using B  CMB  C PO  B  CMB
                              (PO  CMB  B)  (CMB  B  C)  (PO  CMB  E)  (PO  E  CMB) 
                            by auto 
                          show "B  CMB  (PO  CMB  E)  (PO  E  CMB)"
                            by (metis B  C PO  B  A PO  B  C PO  B assms(1) 
                                between_equality between_symmetry calculation l5_2) 
                        qed
                      }
                      ultimately have "Bet PO CMB E  Bet PO E CMB"
                        using A  PO  E B  PO  E E  PO between_symmetry l5_2 by blast 
                    }
                    hence "Bet PO CMB E  Bet PO E CMB"
                      using Ng_def Ng PO E B by blast 
                  }
                  hence "Bet PO CMB E  Bet PO E CMB"
                    using Ng_def Ng PO E A by auto 
                }
                ultimately have "Bet PO CMB E  Bet PO E CMB"   
                  using Bet CMB C PO  Bet C PO B  Bet CMB PO C  Bet PO C B  
                         Bet PO CMB B  Bet CMB B C  Bet PO B CMB  Bet B CMB C
                  by blast
              }
              ultimately show ?thesis 
                by blast
            qed
            ultimately have "Ps PO E CMB"
              by (metis Out_cases Ps_def B  C Diff PO E E' C B CMB bet_out_1
                  between_symmetry diff_null_eq) 
            thus "LeP PO E E' B C"
              using LeP_def LtP_def Diff PO E E' C B CMB by auto 
          }
        qed
      qed
    qed
  }
qed

lemma bet_lt12_le13:
  assumes "Bet A B C"
    and "LtP PO E E' A B"
  shows "LeP PO E E' A C"
  using LeP_def assms(1,2) bet_lt12_le23 leP_trans by blast 

lemma bet_lt21_le32:
  assumes "Bet A B C"
    and "LtP PO E E' B A"
  shows "LeP PO E E' C B" 
proof  (cases "B = C")
  show "B = C  LeP PO E E' C B"
    by (simp add: leP_refl) 
  {
    assume "B  C"
    have "¬ Col PO E E'"
      using Ar2_def assms(2) ltP_ar2 by blast 
    moreover have "Col PO E B"
      using Ar2_def assms(2) ltP_ar2 by auto 
    moreover have "Col PO E C"
      by (metis Ar2_def assms(1,2) bet_col colx ltP_ar2 ltP_neq) 
    ultimately obtain BMC where "Diff PO E E' B C BMC"
      using diff_exists by blast
    obtain MA where "Opp PO E E' A MA"
      using Ar2_def assms(2) ltP_ar2 opp_exists by presburger
    obtain MB where "Opp PO E E' B MB"
      using Col PO E B ¬ Col PO E E' opp_exists by blast 
    obtain MC where "Opp PO E E' C MC"
      using Diff_def Diff PO E E' B C BMC by auto
    have "Col PO E MA" 
      by (meson Ar2_def Opp PO E E' A MA diff_O_A diff_ar2) 
    have "Col PO E MB" 
      by (meson Ar2_def Opp PO E E' B MB diff_O_A diff_ar2) 
    have "Col PO E MC"
      by (meson Ar2_def Opp PO E E' C MC diff_O_A diff_ar2) 
    have "Col PO E BMC"
      using Ar2_def Diff PO E E' B C BMC diff_ar2 by force
    obtain AMB where "Diff PO E E' A B AMB"
      using LtP_def assms(2) by auto 
    obtain MAMMB where "Diff PO E E' MA MB MAMMB"
      using Col PO E MA Col PO E MB ¬ Col PO E E' diff_exists by blast 
    have "Col PO E MAMMB"
      by (meson Ar2_def Diff PO E E' MA MB MAMMB diff_ar2)
    have "Opp PO E E' AMB MAMMB" 
    proof -
      have "Sum PO E E' MB A AMB"
        using Diff_def Diff PO E E' A B AMB Opp PO E E' B MB ¬ Col PO E E' 
          opp_uniqueness sum_comm by blast 
      moreover have "Sum PO E E' A MAMMB B"
        by (metis Diff_def Diff PO E E' MA MB MAMMB Opp PO E E' A MA Opp PO E E' B MB
            ¬ Col PO E E' diff_sum sum_comm) 
      ultimately show ?thesis
        using Diff PO E E' A B AMB diff_opp local.sum_diff by presburger 
    qed
    obtain MBMMA where "Diff PO E E' MB MA MBMMA"
      using Col PO E MA Col PO E MB ¬ Col PO E E' diff_exists by blast
    hence "Col PO E MBMMA"
      by (meson Ar2_def diff_ar2) 
    have "AMB = MBMMA"
      by (meson Diff PO E E' MA MB MAMMB Diff PO E E' MB MA MBMMA Opp PO E E' AMB MAMMB
          ¬ Col PO E E' diff_opp opp_comm opp_uniqueness)
    have "Bet MA MB MC" 
    proof (rule l7_15 [of PO A _ B _ C], insert assms(1))
      show "PO Midpoint A MA" 
        using opp_midpoint[of PO E E' A MA] by (simp add: Opp PO E E' A MA) 
      show "PO Midpoint B MB" 
        using opp_midpoint [of PO E E' B MB] by (simp add: Opp PO E E' B MB) 
      show "PO Midpoint C MC" 
        using opp_midpoint [of PO E E' C MC] by (simp add: Opp PO E E' C MC) 
    qed
    obtain MBMMC where "Diff PO E E' MB MC MBMMC"
      using Col PO E MB Col PO E MC ¬ Col PO E E' diff_exists by blast 
    hence "Col PO E MBMMC"
      using Ar2_def diff_ar2 by force 
    have "Opp PO E E' BMC MBMMC" 
    proof -
      have "Sum PO E E' MC B BMC"
        using Diff_def Diff PO E E' B C BMC Opp PO E E' C MC ¬ Col PO E E' opp_uniqueness
          sum_comm by blast 
      moreover have "Sum PO E E' B MBMMC C" 
      proof -
        have "Sum PO E E' MB C MBMMC"
          by (meson Col PO E MB Diff PO E E' MB MC MBMMC Opp PO E E' C MC ¬ Col PO E E'
              diff_A_O diff_O_A opp_comm sum_diff_diff) 
        moreover have "Sum PO E E' B MB PO"
          using Opp_def Opp PO E E' B MB sum_opp by blast 
        moreover have "Sum PO E E' PO C C"
          by (simp add: Col PO E C ¬ Col PO E E' sum_O_B) 
        ultimately show ?thesis 
          using sum_assoc_2 by blast 
      qed
      ultimately show ?thesis
        using Diff PO E E' B C BMC diff_opp local.sum_diff by auto 
    qed
    obtain MCMMB where "Diff PO E E' MC MB MCMMB"
      using Col PO E MB Col PO E MC ¬ Col PO E E' diff_exists by blast 
    hence "Opp PO E E' MBMMC MCMMB"
      using Diff PO E E' MB MC MBMMC diff_opp by auto 
    hence "BMC = MCMMB"
      using Opp PO E E' BMC MBMMC ¬ Col PO E E' opp_comm opp_uniqueness by blast 
    have "LtP PO E E' MA MB"
      using LtP_def AMB = MBMMA Diff PO E E' A B AMB Diff PO E E' MB MA MBMMA assms(2)
        lt_diff_ps by blast
    have "LeP PO E E' MB MC"
      using LtP PO E E' MA MB MA  MB  MC bet_lt12_le23 by auto 
    thus "LeP PO E E' C B"
      by (metis LeP_def LtP_def BMC = MCMMB Diff PO E E' B C BMC
          Diff PO E E' MB MC MBMMC Diff PO E E' MC MB MCMMB
          Opp PO E E' BMC MBMMC diff_null_eq lt_diff_ps pos_null_neg) 
  }
qed

lemma bet_lt21_le31:
  assumes "Bet A B C"
    and "LtP PO E E' B A"
  shows "LeP PO E E' C A"
  using LeP_def assms(1,2) bet_lt21_le32 leP_trans by blast 

lemma opp_2_le_le:
  assumes "Opp PO E E' A MA"
    and "Opp PO E E' B MB"
    and "LeP PO E E' A B"
  shows "LeP PO E E' MB MA" 
proof -
  obtain MAMB where "Sum PO E E' MA MB MAMB"
    by (meson Ar2_def Opp_def assms(1,2) sum_ar2 sum_exists) 
  have "Sum PO E E' B MAMB MA"
    using Diff_def Sum PO E E' MA MB MAMB assms(2) diff_sum by blast 
  moreover have "Sum PO E E' A MAMB MB"
    by (meson Diff_def Sum PO E E' MA MB MAMB assms(1) calculation diff_sum sum3_col sum_comm
        sum_to_sum3) 
  ultimately show ?thesis
    using assms(3) compatibility_of_sum_with_order by blast 
qed

lemma diff_2_le_le:
  assumes "Diff PO E E' A C AMC"
    and "Diff PO E E' B C BMC"
    and "LeP PO E E' A B"
  shows "LeP PO E E' AMC BMC"
  by (metis Ar2_def Diff_def assms(1,2,3) compatibility_of_sum_with_order diff_ar2
      opp_uniqueness) 

  (** Lemma 15.2 *)
  (** Cong corresponds to length equality.*)
  (** Le corresponds to length inequality.*)

lemma length_pos:
  assumes "Length PO E E' A B L"
  shows "LeP PO E E' PO L"
  using Length_def assms by force 

lemma length_id_1:
  assumes "Length PO E E' A B PO"
  shows "A = B"
  by (meson Length_def assms cong_reverse_identity) 

lemma length_id_2:
  assumes "PO  E"
  shows "Length PO E E' A A PO"
  by (meson Length_def assms cong_trivial_identity leP_refl
      not_col_distincts) 

lemma length_id:
  shows "Length PO E E' A B PO  (A = B  PO  E)"
  by (metis Length_def length_id_1 length_id_2) 

lemma length_eq_cong_1:
  assumes "Length PO E E' A B AB"
    and "Length PO E E' C D AB"
  shows "Cong A B C D"
  by (meson Length_def assms(1,2) cong_inner_transitivity) 

lemma length_eq_cong_2:
  assumes "Length PO E E' A B AB"
    and "Cong A B C D"
  shows "Length PO E E' C D AB"
  by (metis Length_def assms(1,2) cong_transitivity) 

lemma ltP_pos:
  assumes "LtP PO E E' PO A"
  shows "Ps PO E A"
  using Ar2_def assms diff_A_O ltP_ar2 lt_diff_ps by presburger 

lemma bet_leP:
  assumes "Bet PO AB CD"
    and "LeP PO E E' PO AB"
    and "LeP PO E E' PO CD"
  shows "LeP PO E E' AB CD"
  using LeP_def assms(1,2,3) bet_lt12_le23 by blast 

lemma leP_bet:
  assumes "LeP PO E E' AB CD" 
    and "LeP PO E E' PO AB"
    and "LeP PO E E' PO CD"
  shows "Bet PO AB CD"
proof -
  {
    assume "LtP PO E E' AB CD"
    then obtain X where "Diff PO E E' CD AB X" and "Ps PO E X"
      using LtP_def by auto 
    hence "PO Out AB X  AB = PO"
      by (metis LeP_def Ps_def assms(2) l6_6 l6_7 ltP_pos) 
    moreover have "PO Out AB X  Bet PO AB CD"
      using Diff PO E E' CD AB X diff_sum l14_36_a by blast 
    moreover have "AB = PO  Bet PO AB CD"
      by (simp add: between_trivial2) 
    ultimately have "Bet PO AB CD" 
      by blast
  }
  moreover have "AB = CD  Bet PO AB CD"
    by (simp add: between_trivial) 
  ultimately show ?thesis
    using LeP_def assms(1) by blast
qed

lemma length_Ar2:
  assumes "Length PO E E' A B AB"
  shows "(Col PO E AB  ¬ Col PO E E')  AB = PO" 
proof -
  have "LtP PO E E' PO AB  PO = AB"
    using LeP_def assms length_pos by auto 
  moreover have "LtP PO E E' PO AB  (Col PO E AB  ¬ Col PO E E')"
    using Ar2_def ltP_ar2 by presburger 
  ultimately show ?thesis by blast
qed

lemma length_leP_le_1:
  assumes "Length PO E E' A B AB"
    and "Length PO E E' C D CD"
    and "LeP PO E E' AB CD"
  shows "A B Le C D" 
proof -
  have "Bet PO AB CD"
    using assms(1,2,3) leP_bet length_pos by blast
  obtain M' where "Bet D C M'" and "Cong C M' A B"
    using segment_construction by blast 
  then obtain M where "C Midpoint M' M"
    using symmetric_point_construction by auto 
  hence "Cong A B C M"
    using Cong_cases Midpoint_def Cong C M' A B cong_inner_transitivity by blast 
  show ?thesis 
  proof (rule le_transitivity [of _ _ C M])
    show "A B Le C M"
      by (simp add: Cong A B C M cong__le) 
    have "PO AB Le PO CD"
      by (simp add: PO  AB  CD bet__le1213) 
    thus "C M Le C D"
      by (meson Length_def Cong A B C M assms(1,2) cong_transitivity l5_6) 
  qed
qed

lemma length_leP_le_2:
  assumes "Length PO E E' A B AB"
    and "Length PO E E' C D CD"
    and "A B Le C D"
  shows "LeP PO E E' AB CD" 
proof -
  have "Col PO E AB  ¬ Col PO E E'  AB = PO"
    using assms(1) length_Ar2 by auto 
  have "Col PO E CD  ¬ Col PO E E'  CD = PO"
    using assms(2) length_Ar2 by auto 
  have "Bet PO AB CD"
  proof (cases "PO = CD")
    {
      assume "PO = CD"
      hence "C = D"
        using assms(2) length_id_1 by blast 
      obtain X where "Bet C X C" and "Cong A B C X"
        using Le_def C = D assms(3) by blast 
      hence "C = X"
        by (simp add: between_identity) 
      hence "A = B"
        using Cong A B C X cong_diff by blast
      hence "PO = AB"
        by (metis Length_def assms(1) cong_identity) 
      thus "PO  AB  CD"
        using between_trivial2 by auto 
    }
    {
      assume "PO  CD"
      have "PO AB Le PO CD"
        by (meson Length_def assms(1,2,3) cong_symmetry l5_6) 
      then obtain M where "Bet PO M CD" and "Cong PO AB PO M"
        using Le_def by blast 
      {
        assume "Col PO E AB" and "¬ Col PO E E'" and "Col PO E CD" and "¬ Col PO E E'"
        obtain P where "Bet C P D" and "Cong A B C P"
          using Le_def assms(3) by blast
        {
          assume "LtP PO E E' PO AB"

          {
            assume "LtP PO E E' PO CD"
            obtain X where "Diff PO E E' AB PO X" and "Ps PO E X"
              using LtP_def LtP PO E E' PO AB by blast 
            obtain Y where "Diff PO E E' CD PO Y" and "Ps PO E Y"
              using LtP_def LtP PO E E' PO CD by blast 
            have "ParallelogramFlat PO PO AB X"
              by (metis O_not_positive ParallelogramFlat_def Col PO E AB
                  Diff PO E E' AB PO X Ps PO E X ¬ Col PO E E' col_trivial_1
                  cong_pseudo_reflexivity cong_trivial_identity diff_A_O
                  diff_uniqueness) 
            have "ParallelogramFlat PO PO CD Y"
              using Diff PO E E' CD PO Y PO  CD diff_to_plg by auto 
            have "PO  AB  PO  X"
              using O_not_positive Ps PO E X by blast 
            have "PO  CD  PO  Y"
              by (simp add: PO  CD) 
            have "Col AB PO M" 
            proof -
              have "PO Out AB CD"
                by (metis Bet_cases[of CD M PO] Bet_cases[of _ PO AB]
                    Bet_cases[of _ PO CD] Out_cases[of PO E CD] Ps_def[of PO E CD]
                    Ps_def[of PO E AB] Cong PO AB PO M PO  M  CD
                    ParallelogramFlat PO PO AB X ParallelogramFlat PO PO CD Y
                    Ps PO E X Ps PO E Y bet_out_1[of AB PO CD]
                    bet_out__bet[of E PO _ CD] bet_out__bet[of AB PO _ E]
                    between_cong_3[of _ PO AB M]
                    between_inner_transitivity[of _ PO CD M]
                    plgf_trivial_neq[of PO CD Y] plgf_trivial_neq[of PO AB X]
                    point_construction_different[of AB PO]) 
              thus ?thesis
                using Col_def Cong PO AB PO M PO AB Le PO CD PO  M  CD between_cong
                  l5_3 l6_13_1 by blast 
            qed
            hence "AB = M  PO Midpoint AB M" 
              using l7_20 Cong PO AB PO M by simp
            hence "PO  AB  CD"
              by (metis Bet_cases Cong_cases Midpoint_def Out_cases Ps_def PO  M  CD
                  ParallelogramFlat PO PO AB X ParallelogramFlat PO PO CD Y Ps PO E X
                  Ps PO E Y bet_cong_eq bet_out__bet between_equality_2
                  plgf_trivial_neq) 
          }
          moreover have "PO = CD  (PO  AB  CD)"
            by (simp add: PO  CD)
          ultimately have "PO  AB  CD"
            using LeP_def assms(2) length_pos by blast 
        }
        moreover have "PO = AB  (PO  AB  CD)"
          using between_trivial2 by auto 
        ultimately have "PO  AB  CD"
          using LeP_def assms(1) length_pos by blast 
      }
      moreover have "Col PO E AB  ¬ Col PO E E'  CD = PO  (PO  AB  CD)"
        using PO  CD by blast 
      moreover have "AB = PO  Col PO E CD  ¬ Col PO E E'  (PO  AB  CD)"
        using between_trivial2 by blast 
      moreover have "AB = PO  CD = PO  (PO  AB  CD)"
        using PO  CD by blast 
      ultimately show "PO  AB  CD"
        using Col PO E AB  ¬ Col PO E E'  AB = PO
          Col PO E CD  ¬ Col PO E E'  CD = PO by presburger 
    }
  qed
  thus ?thesis
    using assms(1,2) bet_leP length_pos by force 
qed

lemma l15_3:
  assumes "Sum PO E E' A B C"
  shows "Cong PO B A C"
  by (metis Ar2_def assms cong_reflexivity sum_ar2 sum_cong2 sum_iff_cong_b) 

(** Lemma 15.4. *)
(** Triangular equality. *)
lemma length_uniqueness:
  assumes "Length PO E E' A B AB"
    and "Length PO E E' A B AB'"
  shows "AB = AB'"
  by (meson assms(1,2) leP_asym leP_refl length_leP_le_1 length_leP_le_2) 

lemma length_Ps:
  assumes "AB  PO"
    and "Length PO E E' A B AB"
  shows "Ps PO E AB"
  using LeP_def assms(1,2) length_pos ltP_pos by blast 

lemma length_not_col_null:
  assumes "Col PO E E'"
    and "Length PO E E' A B AB"
  shows "AB = PO"
  using assms(1,2) length_Ar2 by blast 

lemma not_triangular_equality1:
  assumes "PO  E" 
  shows "¬ ( E' B C AB BC AC. Bet A B C  Length PO E E' A B AB  Length PO E E' B C BC  
                               Length PO E E' A C AC  Sum PO E E' AB BC AC)"
  by (metis Ar2_def Sum_def assms between_trivial length_id) 

lemma triangular_equality:
  assumes "PO  E" 
    and "Bet A B C"
    and "IsLength PO E E' A B AB"
    and "IsLength PO E E' B C BC"
    and "IsLength PO E E' A C AC"
  shows "Sumg PO E E' AB BC AC" 
proof -
  have "Length PO E E' A B AB  PO = E  PO = AB"
    using IsLength_def assms(3) by auto 
  moreover 
  {
    assume "Length PO E E' A B AB"
    have "Length PO E E' B C BC  PO = E  PO = BC"
      using IsLength_def assms(4) by presburger 
    moreover {
      assume "Length PO E E' B C BC"
      have "Length PO E E' A C AC  PO = E  PO = AC"
        using IsLength_def assms(5) by auto 
      moreover {
        assume "Length PO E E' A C AC"
        have "LtP PO E E' PO AB  PO = AB"
          using LeP_def Length_def Length PO E E' A B AB by presburger 
        moreover 
        {
          assume "LtP PO E E' PO AB"
          have "LtP PO E E' PO BC  PO = BC"
            using LeP_def Length_def Length PO E E' B C BC by presburger 
          moreover {
            assume "LtP PO E E' PO BC"
            have "LtP PO E E' PO AC  PO = AC"
              using LeP_def Length_def Length PO E E' A C AC by presburger 
            moreover 
            {
              assume "LtP PO E E' PO AC"
              obtain X where "Diff PO E E' AB PO X" and "Ps PO E X"
                using LtP_def LtP PO E E' PO AB by blast 
              obtain Y where "Diff PO E E' BC PO Y" and "Ps PO E Y"
                using LtP_def LtP PO E E' PO BC by blast 
              obtain Z where "Diff PO E E' AC PO Z" and "Ps PO E Z"
                using LtP_def LtP PO E E' PO AC by blast 
              have "AB = X"
                by (meson Ar2_def Diff PO E E' AB PO X LtP PO E E' PO AB diff_A_O
                    diff_uniqueness ltP_ar2)
              have "BC = Y"
                by (meson Ar2_def Diff PO E E' BC PO Y LtP PO E E' PO BC diff_A_O
                    diff_uniqueness ltP_ar2)
              have "AC = Z"
                by (meson Ar2_def Diff PO E E' AC PO Z LtP PO E E' PO AC diff_A_O
                    diff_uniqueness ltP_ar2) 
              obtain AC' where "Sum PO E E' AB BC AC'"
                by (metis Ar2_def Ps_def BC = Y LtP PO E E' PO AB Ps PO E Y
                    col_permutation_2 col_permutation_3 ltP_ar2 out_col sum_exists)
              have "Bet PO AB AC'"
                by (metis Out_cases Ps_def AB = X BC = Y Ps PO E X Ps PO E Y
                    Sum PO E E' AB BC AC' l14_36_a l6_7)
              have "Cong PO BC AB AC'"
                using Sum PO E E' AB BC AC' l15_3 by auto
              have "Cong PO AC' A C"
                by (smt (verit, ccfv_threshold) Cong_cases Cong PO BC AB AC'
                    Length PO E E' A B AB Length PO E E' B C BC PO  AB  AC' assms(2)
                    cong_transitivity l2_11_b length_cong) 
              have "Ps PO E AC'"
                using AB = X BC = Y Ps PO E X Ps PO E Y Sum PO E E' AB BC AC'
                  sum_pos_pos by blast
              hence "AC = AC'"
                by (smt (verit, ccfv_SIG) Cong_cases Out_def Ps_def Cong PO AC' A C
                    Length PO E E' A C AC LtP PO E E' PO AC between_cong
                    cong_inner_transitivity l6_7 length_cong ltP_pos) 
              hence "Sumg PO E E' AB BC AC"
                by (simp add: Sumg_def Sum PO E E' AB BC AC') 
            }
            moreover have "PO = AC  Sumg PO E E' AB BC AC"
              by (metis O_not_positive Length PO E E' A B AB  PO = E  PO = AB
                  Length PO E E' A C AC LtP PO E E' PO AB assms(2) between_identity
                  cong_reverse_identity length_cong length_id_1 ltP_pos) 
            ultimately have "Sumg PO E E' AB BC AC" 
              by blast
          }
          moreover have "PO = BC  Sumg PO E E' AB BC AC"
            by (metis Ar2_def Sumg_def Length PO E E' A B AB Length PO E E' A C AC
                Length PO E E' B C BC LtP PO E E' PO AB length_id length_uniqueness
                ltP_ar2 sum_A_O) 
          ultimately have "Sumg PO E E' AB BC AC" 
            by blast
        }
        moreover have "PO = AB  Sumg PO E E' AB BC AC"
          by (metis Ar2_def Length_def Sumg_def Length PO E E' A B AB
              Length PO E E' A C AC Length PO E E' B C BC length_id
              length_not_col_null length_uniqueness sum_O_B)
        ultimately have "Sumg PO E E' AB BC AC" 
          by blast
      }
      moreover have "PO = E  PO = AC  Sumg PO E E' AB BC AC"
        using assms(1) by blast 
      ultimately have "Sumg PO E E' AB BC AC" 
        by blast
    }
    moreover have "PO = E  PO = BC  Sumg PO E E' AB BC AC"
      by (simp add: assms(1)) 
    ultimately have "Sumg PO E E' AB BC AC" 
      by blast
  }
  moreover have " PO = E  PO = AB  Sumg PO E E' AB BC AC"
    using assms(1) by auto 
  ultimately show "Sumg PO E E' AB BC AC" 
    by blast
qed

lemma length_O:
  assumes "PO  E"
  shows "Length PO E E' PO PO PO"
  by (simp add: assms length_id)

lemma triangular_equality_bis:
  assumes "A  B  A  C  B  C"
    and "PO  E"
    and "Bet A B C"
    and "Length PO E E' A B AB"
    and "Length PO E E' B C BC"
    and "Length PO E E' A C AC"
  shows "Sum PO E E' AB BC AC" 
proof -
  have "LtP PO E E' PO AB  PO = AB"
    using LeP_def Length_def assms(4) by presburger 
  moreover have "LtP PO E E' PO BC  PO = BC"
    using LeP_def Length_def assms(5) by presburger 
  moreover have "LtP PO E E' PO AC  PO = AC"
    using LeP_def Length_def assms(6) by presburger 
  moreover {
    assume "LtP PO E E' PO AB" and "LtP PO E E' PO BC" and "LtP PO E E' PO AC"
    obtain X where "Diff PO E E' AB PO X" and "Ps PO E X"
      using LtP_def LtP PO E E' PO AB by blast 
    obtain Y where "Diff PO E E' BC PO Y" and "Ps PO E Y"
      using LtP_def LtP PO E E' PO BC by blast 
    obtain Z where "Diff PO E E' AC PO Z" and "Ps PO E Z"
      using LtP_def LtP PO E E' PO AC by blast 
    have "AB = X"
      by (meson Ar2_def Diff PO E E' AB PO X LtP PO E E' PO AB diff_A_O
          diff_stable ltP_ar2)
    have "BC = Y"
      by (meson Ar2_def Diff PO E E' BC PO Y LtP PO E E' PO BC diff_A_O
          diff_stable ltP_ar2) 
    have "AC = Z"
      by (meson Ar2_def Diff PO E E' AC PO Z LtP PO E E' PO AC diff_A_O
          diff_stable ltP_ar2) 
    obtain AC' where "Sum PO E E' AB BC AC'"
      by (metis Ar2_def Ps_def BC = Y LtP PO E E' PO AB Ps PO E Y
          col_permutation_5 ltP_ar2 out_col sum_exists) 
    hence "Bet PO AB AC'"
      by (metis Ps_def AB = X BC = Y Ps PO E X Ps PO E Y l14_36_a l6_6
          l6_7) 
    have "Cong PO BC AB AC'"
      using Sum PO E E' AB BC AC' l15_3 by auto
    have "Cong PO AC' A C"
      by (smt (verit, ccfv_threshold) Cong_cases Cong PO BC AB AC'
          PO  AB  AC' assms(3,4,5) cong_transitivity l2_11_b
          length_cong)
    have "Ps PO E AC'"
      using AB = X BC = Y Ps PO E X Ps PO E Y Sum PO E E' AB BC AC'
        sum_pos_pos by blast
    have "AC = AC'"
      by (smt (verit, ccfv_threshold) Col_cases Cong_cases Out_cases Out_def
          Ps_def AC = Z Cong PO AC' A C Ps PO E AC' Ps PO E Z assms(6)
          bet_cong_eq bet_out__bet col_permutation_2 col_transitivity_2
          cong_inner_transitivity l6_4_2 length_cong not_bet_and_out
          out_col)
    hence "Sum PO E E' AB BC AC"
      by (simp add: Sum PO E E' AB BC AC') 
  }
  moreover have "LtP PO E E' PO AB  LtP PO E E' PO BC  PO = AC  Sum PO E E' AB BC AC"
    using assms(1,3,6) between_equality between_trivial length_id by force 
  moreover have "LtP PO E E' PO AB  PO = BC  LtP PO E E' PO AC  Sum PO E E' AB BC AC"
    by (metis assms(4,5,6) calculation(4) length_Ar2 length_id_1 length_uniqueness sum_A_O) 
  moreover have "PO = AB  LtP PO E E' PO BC  LtP PO E E' PO AC  Sum PO E E' AB BC AC"
    by (metis Ar2_def assms(4,5,6) length_id_1 length_uniqueness ltP_ar2
        sum_O_B)
  moreover have "PO = AB  PO = BC  LtP PO E E' PO AC  Sum PO E E' AB BC AC"
    by (metis Ps_def assms(4,5,6) between_trivial2 cong_reverse_identity
        length_cong length_id_1 ltP_pos not_bet_and_out) 
  moreover have "PO = AB  LtP PO E E' PO BC  PO = AC  Sum PO E E' AB BC AC"
    by (metis Ps_def assms(4,5,6) between_trivial2 cong_reverse_identity
        length_cong length_id_1 ltP_pos not_bet_and_out) 
  moreover have "LtP PO E E' PO AB  PO = BC  PO = AC  Sum PO E E' AB BC AC"
    using assms(1,3,6) between_equality between_trivial length_id_1
    by blast 
  moreover have "PO = AB  PO = BC  PO = AC  Sum PO E E' AB BC AC"
    using assms(1,4,6) length_id_1 by blast 
  ultimately show ?thesis 
    by blast
qed

(** Lemma 15.5. *)
(** Known as Thales theorem or intercept theorem. *)
lemma length_out:
  assumes "A  B"
    and "C  D"
    and "Length PO E E' A B AB"
    and "Length PO E E' C D CD"
  shows "PO Out AB CD"
  by (metis (full_types) Length_def Ps_def assms(1,2,3,4) bet_out__bet
      cong_reverse_identity l6_3_2 length_Ps
      point_construction_different) 

lemma image_preserves_bet1:
  assumes "Bet A B C"
    and "A A' Reflect X Y"
    and "B B' Reflect X Y"
    and "C C' Reflect X Y"
  shows "Bet A' B' C'"
  using assms(1,2,3,4) image_gen_preserves_bet by blast 

lemma image_preserves_col:
  assumes "Col A B C"
    and "A A' Reflect X Y"
    and "B B' Reflect X Y"
    and "C C' Reflect X Y"
  shows "Col A' B' C'"
  using Col_def assms(1,2,3,4) image_gen_preserves_bet by presburger 

lemma image_preserves_out:
  assumes "A Out B C"
    and "A A' Reflect X Y"
    and "B B' Reflect X Y"
    and "C C' Reflect X Y"
  shows "A' Out B' C'" 
proof -
  have "B'  A'"
    using assms(1,2,3) l10_2_uniqueness out_distinct by blast 
  moreover have "C'  A'"
    using assms(1,2,4) l10_2_uniqueness out_diff2 by blast 
  moreover have "Bet A' B' C'  Bet A' C' B'"
    by (meson Out_def assms(1,2,3,4) image_preserves_bet1) 
  ultimately show ?thesis
    using Out_def by blast 
qed

lemma project_preserves_out:
  assumes "A Out B C"
    and "¬ A B Par X Y"
    and "A A' Proj P Q X Y"
    and "B B' Proj P Q X Y"
    and "C C' Proj P Q X Y"
  shows "A' Out B' C'" 
proof -
  have "B'  A'"
    by (metis assms(1,2,3,4) ker_par out_distinct) 
  moreover have "C'  A'"
    by (metis Out_def assms(1,2,3,5) ker_par not_par_not_col out_col
        par_trans) 
  moreover have "Bet A' B' C'  Bet A' C' B'"
    by (meson Out_def assms(1,3,4,5) project_preserves_bet)
  ultimately show ?thesis
    using Out_def by blast 
qed

lemma conga_bet_conga:
  assumes "A B C CongA D E F"
    and "A'  B"
    and "C'  B"
    and "D'  E"
    and "F'  E"
    and "Bet A B A'"
    and "Bet C B C'"
    and "Bet D E D'"
    and "Bet F E F'"
  shows "A' B C' CongA D' E F'"
  by (meson assms(1,2,3,4,5,6,7,8,9) conga_comm l11_13) 

lemma thales:
  assumes "PO  E"
    and "Col P A B"
    and "Col P C D"
    and "¬ Col P A C"
    and "A C Pj B D" 
    and "Length PO E E' P A A1"
    and "Length PO E E' P B B1"
    and "Length PO E E' P C C1"
    and "Length PO E E' P D D1"
    and "Prodg PO E E' A1 D1 AD"
  shows "Prodg PO E E' C1 B1 AD"
proof (cases "Col PO E E'")
  show "Col PO E E'  Prodg PO E E' C1 B1 AD"
    using Ar2_def Prod_def Prodg_def assms(10) by presburger 
  {
    assume "¬ Col PO E E'"
    have "Prod PO E E' A1 D1 AD  (¬ Ar2 PO E E' A1 D1 D1  AD = PO)"
      using Prodg_def assms(10) by blast 
    moreover 
    {
      assume "Prod PO E E' A1 D1 AD"
      have "Prodg PO E E' C1 B1 AD"
      proof (cases "P = B")
        show "P = B  Prodg PO E E' C1 B1 AD"
          by (metis (mono_tags, lifting) Length_def Prodg_def
              Prod PO E E' A1 D1 AD ¬ Col PO E E'
              assms(3,4,5,7,8,9) length_id_2 length_uniqueness
              not_col_distincts pj_trivial pj_uniqueness prod_0_r
              prod_O_l_eq prod_sym) 
        {
          assume "P  B"
          show "Prodg PO E E' C1 B1 AD" 
          proof (cases "A = B")
            {
              assume "A = B"
              have "A C ParStrict A D  Prodg PO E E' C1 B1 AD"
                by (simp add: not_par_strict_id) 
              hence "A C Par A D  Prodg PO E E' C1 B1 AD"
                by (metis Col_def Prodg_def A = B
                    Prod PO E E' A1 D1 AD assms(3,4,6,7,8,9) col2__eq
                    length_uniqueness par_id prod_sym) 
              thus "Prodg PO E E' C1 B1 AD"
                using NCol_perm Pj_def A = B assms(3,4,5) by blast 
            }
            {
              assume "A  B"
              have "¬ Col PO A1 E'"
                by (metis assms(4,6) col_permutation_5 col_trivial_3 colx length_Ar2
                    length_id_1) 
              then obtain C1' where "P A C Cong3 PO A1 C1'" and "PO A1 OS E' C1'"
                using assms(4,6) l10_16 length_cong by meson
              have "P A C CongA PO A1 C1'"
                by (metis P A C Cong3 PO A1 C1' assms(4) col_trivial_1 col_trivial_2
                    cong3_conga) 
              have "¬ Col PO C1 C1'"
                by (metis PO A1 OS E' C1' assms(1,4,6,8) col_transitivity_1 col_trivial_3
                    length_Ar2 length_id_1 one_side_not_col124)
              obtain M where "M Midpoint C1 C1'"
                using MidR_uniq_aux by blast
              obtain D1' where "D1' D1 Reflect PO M"
                using l10_2_existence by fastforce
              moreover {
                assume "PO  M" and "D1' D1 ReflectL PO M"
                then obtain N where "N Midpoint D1 D1'" and "Col PO M N"
                  using ReflectL_def by blast 
                have "PO Out C1 D1" 
                proof (rule length_out [of P C P D _ E E'])
                  show "P  C"
                    using assms(4) not_col_distincts by blast 
                  {
                    assume "P = D"
                    have "PO = AD"
                      using P = D Prod PO E E' A1 D1 AD assms(9)
                        cong_reverse_identity length_cong prod_O_r_eq
                      by blast 
                    have "A C Par B P  False"
                      by (metis assms(2,4) not_col_distincts par_col2_par_bis par_id_5) 
                    hence False
                      using Pj_def P = D P  B assms(5) by blast 
                  }
                  thus "P  D" 
                    by blast
                  show "Length PO E E' P C C1"
                    by (simp add: assms(8)) 
                  show "Length PO E E' P D D1"
                    by (simp add: assms(9)) 
                qed
                have "PO Out A1 C1"
                  by (metis assms(4,6,8) col_trivial_1 col_trivial_3 length_out) 
                have "M  C1"
                  using M Midpoint C1 C1' ¬ Col PO C1 C1' col_trivial_2 is_midpoint_id 
                  by blast 
                have "Per PO M C1" 
                proof -
                  have "Cong PO C1 PO C1'"
                    by (meson Cong3_def P A C Cong3 PO A1 C1' assms(8) 
                        cong_inner_transitivity length_cong) 
                  thus ?thesis
                    using Per_def M Midpoint C1 C1' by blast 
                qed
                have "M PO Perp C1 M  M M Perp C1 M"
                  using Perp_cases M  C1 PO  M Per PO M C1
                    col_per_perp col_trivial_3 by blast 
                have "PO Out C1' D1'" 
                proof (rule image_preserves_out [of PO C1 D1 _ PO M], 
                    insert PO Out C1 D1 image_triv)
                  show "C1 C1' Reflect PO M"
                    by (meson Cong3_def M Midpoint C1 C1'
                        P A C Cong3 PO A1 C1' assms(8) cong_inner_transitivity
                        cong_midpoint__image l7_2 length_cong) 
                  show "D1 D1' Reflect PO M"
                    by (simp add: calculation l10_4) 
                qed
                have "PO N Perp D1 N" 
                proof (rule perp_col [of _ _ M], insert Col PO M N)
                  show "PO  N"
                    by (metis Out_def N Midpoint D1 D1' PO Out C1 D1
                        PO Out C1' D1' ¬ Col PO C1 C1' col_transitivity_1
                        not_col_sym_not_col out_col) 
                  show "PO M Perp D1 N" 
                  proof -
                    have  "D1  N"
                      using N Midpoint D1 D1' PO Out C1 D1 PO Out C1' D1'
                        ¬ Col PO C1 C1' is_midpoint_id l6_6 l6_7 out_col
                      by blast 
                    moreover have "D1 D1' Perp PO M"
                      by (metis Perp_perm ReflectL_def D1' D1 ReflectL PO M
                          N Midpoint D1 D1' calculation l7_3) 
                    moreover have "Col D1 D1' N"
                      using N Midpoint D1 D1' bet_col1 between_trivial midpoint_bet by blast 
                    ultimately show ?thesis
                      by (metis Perp_cases perp_col) 
                  qed
                qed
                have "Cong PO D1 PO D1'"
                  using calculation image_triv l10_10 by blast 
                have "C1 C1' Par D1 D1'" 
                proof -
                  have "PO M Perp D1 D1'  D1 = D1'"
                    using ReflectL_def D1' D1 ReflectL PO M by blast 
                  moreover {
                    assume "PO M Perp D1 D1'"
                    have "C1 C1' Par D1 D1'"
                    proof -
                      {
                        assume "M PO Perp C1 M"
                        have "C1 C1' Par D1 D1'" 
                        proof (rule l12_9_2D [of _ _ PO M])
                          show "C1 C1' Perp PO M"
                            by (metis M Midpoint C1 C1' M  C1 PO  M
                                Per PO M C1 bet_cong_eq between_trivial2 col_per_perp
                                midpoint_bet midpoint_col midpoint_cong
                                not_cong_3412) 
                          show "D1 D1' Perp PO M"
                            using Perp_cases PO M Perp D1 D1' by blast 
                        qed
                      }
                      moreover have "M M Perp C1 M  C1 C1' Par D1 D1'"
                        using perp_distinct by blast
                      ultimately show ?thesis
                        using M PO Perp C1 M  M M Perp C1 M by blast 
                    qed
                  }
                  moreover have "D1 = D1'  C1 C1' Par D1 D1'"
                    using PO Out C1 D1 PO Out C1' D1' ¬ Col PO C1 C1' l6_6
                      l6_7 out_col by blast 
                  ultimately show ?thesis 
                    by blast
                qed
                hence "C1 C1' Pj D1 D1'"
                  by (simp add: Pj_def) 
                have "P C A Cong3 PO C1' A1"
                  by (simp add: P A C Cong3 PO A1 C1' cong_3_swap_2)
                have "P C A CongA PO C1' A1"
                  using P C A Cong3 PO C1' A1 assms(4) cong3_conga
                    not_col_distincts by auto
                have "Cong P A PO A1  (P  A  C P A CongA C1' PO A1  C A P CongA C1' A1 PO)" 
                  using l11_49 Cong3_def P C A Cong3 PO C1' A1
                    P C A CongA PO C1' A1 cong_3_swap by blast 
                moreover have "P  A"
                  using assms(4) col_trivial_1 by blast
                ultimately have "C P A CongA C1' PO A1  C A P CongA C1' A1 PO" 
                  by blast
                have "C A P CongA D B P" 
                proof -
                  {
                    assume "Bet C P D"
                    have "Bet A P B" 
                    proof (rule project_preserves_bet [of C P D _ A P A C], insert C  P  D)
                      show "C A Proj A P A C"
                        by (metis Par_def assms(4) grid_not_par par_col_project) 
                      show "P P Proj A P A C"
                        by (metis P  A assms(4) col_trivial_2 par_id_1 project_trivial) 
                      show "D B Proj A P A C"
                        by (metis NCol_perm assms(2,4,5) grid_not_par 
                            pj_col_project pj_right_comm) 
                    qed
                    have "A B TS C D" 
                    proof -
                      have "¬ Col C A B"
                        using A  B assms(2,4) col2__eq by blast 
                      moreover have "¬ Col D A B"
                        by (metis P  B assms(2,3,4,5) calculation col_permutation_2 
                            colx sum_ar2 sum_exists sum_par_strict_a) 
                      moreover have " T. Col T A B  Bet C T D" 
                      proof -
                        have "Col P A B"
                          using assms(2) by auto 
                        moreover have "Bet C P D"
                          by (simp add: C  P  D) 
                        ultimately show ?thesis 
                          by fast
                      qed
                      ultimately show ?thesis
                        using TS_def by blast 
                    qed
                    hence "C A B CongA D B A  A C Par B D" 
                      using l12_21 by simp
                    have "A C Par B D  C A P CongA D B P"
                      by (metis NCol_perm Par_cases TS_def A B TS C D P  A P  B
                          assms(2,3,4) not_par_not_col triangle_par) 
                    moreover have "B = D  C A P CongA D B P"
                      using TS_def A B TS C D not_col_distincts by blast 
                    ultimately have "C A P CongA D B P"
                      using Pj_def assms(5) by blast 
                  }
                  moreover have "¬ Bet C P D  C A P CongA D B P"
                    by (metis Pj_def P  B assms(2,3,4,5) between_trivial col_transitivity_2
                        conga_comm not_col_distincts not_par_not_col triangle_par) 
                  ultimately show ?thesis 
                    by blast
                qed

                have "A  C"
                  using assms(4) col_trivial_2 by auto
                have "¬ P A Par C A"
                  by (simp add: assms(4) grid_not_par_3 not_col_permutation_5)
                have "C P A CongA D P B"
                  by (metis Pj_def C A P CongA D B P assms(2,3,4,5) ncol_conga_ncol 
                      not_col_distincts not_col_permutation_2 not_col_permutation_3 
                      not_par_not_col par_comm triangle_par) 
                have "C1  C1'"
                  using ¬ Col PO C1 C1' col_trivial_2 by auto 
                have "PO  C1'"
                  using ¬ Col PO C1 C1' col_trivial_3 by auto
                have "¬ PO C1' Par C1 C1'"
                  by (simp add: ¬ Col PO C1 C1' grid_not_par_3) 
                have "¬ PO C1 Par C1 C1'"
                  by (simp add: ¬ Col PO C1 C1' grid_not_par_1) 
                have "C1' PO A1 CongA D1' PO B1"
                proof (rule out2__conga)
                  show "PO Out D1' C1'"
                    using Out_cases PO Out C1' D1' by auto 
                  show "PO Out B1 A1"
                    using P  A P  B assms(6,7) length_out by auto 
                qed
                have "D1' PO B1 CongA D P B"
                  using C P A CongA D P B C1' PO A1 CongA D1' PO B1
                    Cong P A PO A1  (P  A  C P A CongA C1' PO A1  C A P CongA C1' A1 PO)
                    P  A conga_sym conga_trans by blast
                have "D1'  B1  PO D1' B1 CongA P D B  PO B1 D1' CongA P B D"
                  by (meson Cong PO D1 PO D1' D1' PO B1 CongA D P B assms(7,9) 
                      cong_transitivity l11_49 length_cong not_cong_3412) 
                moreover have "D1'  B1"
                  by (metis Col_def C1' PO A1 CongA D1' PO B1 PO A1 OS E' C1' col124__nos
                      grid_not_par_5 ncol_conga_ncol) 
                ultimately have "PO D1' B1 CongA P D B  PO B1 D1' CongA P B D"
                  by simp
                have "C1' A1 PO CongA D1' B1 PO  A1 C1' Par B1 D1'" 
                proof (rule l12_22)
                  show "PO Out A1 B1"
                    using P  A P  B assms(6,7) length_out by auto 
                  show "PO A1 OS C1' D1'"
                    using PO A1 OS E' C1' PO Out C1' D1' col124__nos out_one_side by blast 
                qed
                moreover have "C1' A1 PO CongA D1' B1 PO" 
                proof (rule conga_trans [of _ _ _ D B P])
                  show "C1' A1 PO CongA D B P"
                    using C A P CongA D B P C P A CongA C1' PO A1  C A P CongA C1' A1 PO 
                      not_conga not_conga_sym by blast 
                  show "D B P CongA D1' B1 PO"
                    by (simp add: PO D1' B1 CongA P D B  PO B1 D1' CongA P B D conga_comm
                        conga_sym) 
                qed
                ultimately have "A1 C1' Par B1 D1'" 
                  by blast
                have "Prod PO C1 C1' A1 D1 B1" 
                proof (unfold Prod_def, intro strip conjI, unfold Ar2_def, intro strip conjI)
                  show "¬ Col PO C1 C1'"
                    by (simp add: ¬ Col PO C1 C1') 
                  show "Col PO C1 A1"
                    by (simp add: PO Out A1 C1 l6_6 out_col) 
                  show "Col PO C1 D1"
                    by (simp add: PO Out C1 D1 out_col) 
                  show "Col PO C1 B1"
                    by (metis Col PO C1 A1 ¬ Col PO A1 E' assms(6,7) col_trivial_3 
                        l6_16_1 length_Ar2 not_col_permutation_3 not_col_permutation_4) 
                  show "B'. C1 C1' Pj D1 B'  Col PO C1' B'  C1' A1 Pj B' B1"
                    by (meson Pj_def A1 C1' Par B1 D1' C1 C1' Pj D1 D1' PO Out C1' D1'
                        out_col par_comm) 
                qed
                have " Y. Prod PO E C1' A1 D1 Y  Prod PO E C1' C1 B1 Y"
                proof (rule prod_x_axis_unit_change [of _ C1], insert assms(1))
                  show "Ar2p4 PO C1 C1' A1 D1 C1 B1"
                    by (metis Ar2_def Ar2p4_def Prod_def Prod PO C1 C1' A1 D1 B1
                        not_col_distincts) 
                  show "Col PO C1 E"
                    using Col_cases Col_def assms(8) between_trivial length_Ar2
                    by blast 
                  show "E  PO"
                    using assms(1) by auto 
                  show "X. Prod PO C1 C1' A1 D1 X  Prod PO C1 C1' C1 B1 X" 
                    using Ar2p4_def Ar2p4 PO C1 C1' A1 D1 C1 B1 Prod PO C1 C1' A1 D1 B1
                      prod_1_l by blast 
                qed
                hence "Prodg PO E E' C1 B1 AD"
                  by (metis Prodg_def Prod PO E E' A1 D1 AD ¬ Col PO E E'
                      prod_uniqueness prod_y_axis_change) 
              }
              moreover have "PO = M  PO Midpoint D1 D1'  Prodg PO E E' C1 B1 AD"
                using M Midpoint C1 C1' ¬ Col PO C1 C1' midpoint_col by auto 
              ultimately show "Prodg PO E E' C1 B1 AD"
                using Reflect_def by auto 
            }
          qed
        }
      qed
    }
    moreover have "¬ Ar2 PO E E' A1 D1 D1  AD = PO  Prodg PO E E' C1 B1 AD"
      by (meson Ar2_def Length_def ¬ Col PO E E' assms(6,9)) 
    ultimately show "Prodg PO E E' C1 B1 AD"
      by blast 
  }
qed

lemma length_existence:
  assumes "¬ Col PO E E'"
  shows " AB. Length PO E E' A B AB" 
proof -
  have "E  PO"
    using assms col_trivial_1 by auto 
  obtain AB where "Bet PO E AB  Bet PO AB E" and "Cong PO AB A B"
    using E  PO segment_construction_2 by blast
  hence "AB = PO  PO Out E AB" 
    by (simp add: Out_def E  PO)
  moreover have "AB = PO  ?thesis"
    using Cong PO AB A B E  PO cong_diff_3 length_id by blast 
  moreover {
    assume "PO Out E AB"
    hence "Col PO E AB"
      by (simp add: out_col) 
    moreover have "LeP PO E E' PO AB"
      using Bet PO E AB  Bet PO AB E assms ps_le by blast 
    ultimately have ?thesis
      using Length_def Cong PO AB A B E  PO by auto 
  }
  ultimately show ?thesis 
    by blast
qed

(** Known as Euklid *)
lemma l15_7:
  assumes "PO  E"
    and "Per A C B"
    and "H PerpAt C H A B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' A H AH"
  shows "Prod PO E E' AC AC AC2  Prod PO E E' AB AH AC2" 
proof (cases "AB = PO")
  {
    assume "AB = PO"
    hence "A = B"
      using assms(4) length_id by auto 
    hence "C  H  A  A" 
      using perp_in_distinct assms(3) by auto 
    thus "Prod PO E E' AC AC AC2  Prod PO E E' AB AH AC2" 
      by simp
  }
  {
    assume "AB  PO"
    have "LtP PO E E' PO AB  ¬ Col PO E E'  Col PO E AB"
      using Ar2_def ltP_ar2 by blast 
    moreover have "PO = AB  ¬ Col PO E E'  Col PO E AB"
      using AB  PO by auto 
    ultimately have "¬ Col PO E E'  Col PO E AB" 
      using assms(4) length_Ar2 by blast 
    show "Prod PO E E' AC AC AC2  Prod PO E E' AB AH AC2" 
    proof (cases "H = A")
      show "H = A  (Prod PO E E' AC AC AC2) = (Prod PO E E' AB AH AC2)"
        using assms(2,3) l11_47 by blast 
      {
        assume "H  A"
        hence "C  A"
          using assms(3) l8_8 perp_in_per_1 by blast 
        obtain C' where "Bet A H C'  Bet A C' H" and "Cong A C' A C"
          using H  A segment_construction_2 by blast
        have "A Out H C'"
          by (metis Out_def (A  H  C')  (A  C'  H) C  A Cong A C' A C H  A
              cong_reverse_identity) 
        obtain H' where "Bet A C H'  Bet A H' C" and "Cong A H' A H"
          using C  A segment_construction_2 by blast 
        have "H  C"
          using assms(3) perp_in_distinct by blast 
        moreover have "Cong H C H' C'  (H  C  A H C CongA A H' C'  A C H CongA A C' H')" 
        proof (rule l11_49)
          show "H A C CongA H' A C'"
            by (metis Out_cases A Out H C' (A  C  H')  (A  H'  C) C  A 
                Cong A H' A H H  A bet_out
                between_cong between_trivial2 conga_left_comm out2__conga) 
          show "Cong A H A H'"
            using Cong A H' A H not_cong_3412 by blast 
          show "Cong A C A C'"
            by (simp add: Cong A C' A C cong_symmetry) 
        qed
        ultimately have "A H C CongA A H' C'  A C H CongA A C' H'"  
          by blast
        have "A H Perp H C"
          by (metis Per_cases H  A H  C assms(3) per_perp perp_in_per_1) 
        hence "H PerpAt A H H C"
          using l8_14_2_1b_bis not_col_distincts by blast 
        hence "Per A H C"
          by (simp add: perp_in_per) 
        have "Per A H' C'"
          using A H C CongA A H' C'  A C H CongA A C' H' Per A H C l11_17 by blast 
        have "C B Par H' C'" 
        proof (rule l12_9_2D [of _ _ A C])
          show "C B Perp A C"
            by (metis Perp_cases C  A H  C assms(2,3) per_perp perp_in_id) 
          show "H' C' Perp A C"
            by (metis Col_def Per_perm Perp_cases A H C CongA A H' C'  A C H CongA A C' H' 
                A H Perp H C (A  C  H')  (A  H'  C) Per A H' C' 
                bet_conga__bet between_symmetry between_trivial col_per_perp
                not_conga_sym perp_not_col2) 
        qed
        obtain AH' where "Length PO E E' A H' AH'"
          using ¬ Col PO E E'  Col PO E AB length_existence by presburger
        obtain AC' where "Length PO E E' A C' AC'"
          using ¬ Col PO E E'  Col PO E AB length_existence by blast
        obtain P where "Prod PO E E' AC' AC P"
          by (metis Length PO E E' A C' AC' ¬ Col PO E E'  Col PO E AB assms(5) 
              col_trivial_3 length_Ar2 prod_exists)
        have "C H Perp A B"
          using assms(3) perp_in_perp by auto
        have "Prodg PO E E' AH' AB P" 
        proof (rule thales [of _ _ A C' B H' C _ AC' _ _ AC])
          show "PO  E"
            using assms(1) by blast 
          show "Col A C' B"
            by (metis Col_def Perp_cases Perp_in_cases A Out H C' C H Perp A B assms(2,3)
                col_out2_col out_bet__out out_trivial perp_in_col perp_not_col2
                perp_per_bet) 
          show "Col A H' C"
            using Col_def (A  C  H')  (A  H'  C) between_symmetry by blast 
          show "¬ Col A C' H'"
            by (metis A H C CongA A H' C'  A C H CongA A C' H' Per A H' C' conga_diff45
                conga_diff56 l8_9 not_col_permutation_1 not_col_permutation_3) 
          show "C' H' Pj B C"
            using Par_cases Pj_def C B Par H' C' by blast 
          show "Length PO E E' A C' AC'"
            using Length PO E E' A C' AC' by auto 
          show "Length PO E E' A B AB"
            by (simp add: assms(4)) 
          show "Length PO E E' A H' AH'"
            by (simp add: Length PO E E' A H' AH') 
          show "Length PO E E' A C AC"
            by (simp add: assms(5)) 
          show "Prodg PO E E' AC' AC P"
            by (simp add: Prodg_def Prod PO E E' AC' AC P) 
        qed
        hence "Prod PO E E' AH' AB P"
          by (metis Ar2_def Prodg_def Length PO E E' A H' AH' 
              ¬ Col PO E E'  Col PO E AB col_trivial_3 length_Ar2) 
        have "Length PO E E' A H' AH"
          using Cong A H' A H assms(6) length_eq_cong_2 not_cong_3412 by blast
        have "Length PO E E' A C' AC"
          using Cong_cases Cong A C' A C assms(5) length_eq_cong_2 by blast
        hence "(Prod PO E E' AC AC AC2)  (Prod PO E E' AB AH AC2)"
          by (metis Length PO E E' A C' AC' Length PO E E' A H' AH' 
              Length PO E E' A H' AH Prod PO E E' AC' AC P
              Prod PO E E' AH' AB P ¬ Col PO E E'  Col PO E AB length_uniqueness
              prod_sym prod_uniqueness) 
        moreover have "(Prod PO E E' AB AH AC2)  (Prod PO E E' AC AC AC2)"
          by (metis Length PO E E' A C' AC' Length PO E E' A C' AC
              Length PO E E' A H' AH' Length PO E E' A H' AH Prod PO E E' AC' AC P
              Prod PO E E' AH' AB P ¬ Col PO E E'  Col PO E AB length_uniqueness
              prod_sym prod_uniqueness) 
        ultimately show "(Prod PO E E' AC AC AC2) = (Prod PO E E' AB AH AC2)" 
          by blast
      }
    qed
  }
qed

lemma l15_7_1:
  assumes "PO  E"
    and "Per A C B"
    and "H PerpAt C H A B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' A H AH"
    and "Prod PO E E' AC AC AC2"
  shows "Prod PO E E' AB AH AC2" 
  using l15_7 [of PO E A C B H E' AB AC AH AC2] assms(1,2,3,4,5,6,7) by blast

lemma l15_7_2:
  assumes "PO  E"
    and "Per A C B"
    and "H PerpAt C H A B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' A H AH"
    and "Prod PO E E' AB AH AC2"
  shows "Prod PO E E' AC AC AC2" 
  using l15_7 [of PO E A C B H E' AB AC AH AC2] assms(1,2,3,4,5,6,7) by blast

lemma length_sym:
  assumes "Length PO E E' A B AB"
  shows "Length PO E E' B A AB"
  using assms cong_pseudo_reflexivity length_eq_cong_2 by blast 

lemma pythagoras:
  assumes "PO  E"
    and "Per A C B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' B C BC"
    and "Prod PO E E' AC AC AC2"
    and "Prod PO E E' BC BC BC2"
    and "Prod PO E E' AB AB AB2"
  shows "Sum PO E E' AC2 BC2 AB2"
proof (cases "Col A C B")
  {
    assume "Col A C B"
    moreover have "A = C  Sum PO E E' AC2 BC2 AB2"
      by (metis Ar2_def Prod_def assms(3,4,5,6,7,8) cong_reverse_identity length_cong
          length_sym length_uniqueness prod_O_r_eq prod_uniqueness sum_O_B) 
    moreover have "B = C  Sum PO E E' AC2 BC2 AB2"
      by (metis Ar2_def Prod_def assms(1,3,4,5,6,7,8) length_id length_uniqueness
          prod_O_r_eq prod_uniqueness sum_A_O) 
    ultimately show "Sum PO E E' AC2 BC2 AB2"
      using assms(2) per_not_col by force 
  }
  {
    assume "¬ Col A C B"
    then obtain P where "Col A B P" and "A B Perp C P"
      using col_permutation_5 l8_18_existence by blast 
    hence "P PerpAt A B C P"
      by (simp add: l8_15_1) 
    obtain AP where "Length PO E E' A P AP"
      by (metis ¬ Col A C B assms(3,5) col_trivial_1 length_existence length_id_1
          length_not_col_null) 
    obtain BP where "Length PO E E' B P BP"
      by (metis Length PO E E' A P AP assms(3) length_Ar2
          length_existence length_id_1)
    have "Sum PO E E' AP BP AB" 
      using triangular_equality_bis [of PO E E']
      by (metis Perp_in_cases Length PO E E' A P AP
          Length PO E E' B P BP P PerpAt A B C P ¬ Col A C B
          assms(1,2,3) grid_not_par length_sym perp_per_bet
          triangular_equality_bis)
    moreover have "Prod PO E E' AB AP AC2"
      using Perp_in_cases Length PO E E' A P AP P PerpAt A B C P
        assms(1,2,3,4,6) l15_7 by blast
    moreover have "Prod PO E E' AB BP BC2"
      by (meson Per_cases Perp_in_cases Length PO E E' B P BP
          P PerpAt A B C P assms(1,2,3,5,7) l15_7 length_sym)
    ultimately show "Sum PO E E' AC2 BC2 AB2"
      using assms(8) distr_l by blast 
  }
qed

lemma is_length_exists:
  assumes "¬ Col PO E E'"
  shows " XY. IsLength PO E E' X Y XY" 
proof(cases "X = Y")
  {
    assume "X = Y"
    hence "IsLength PO E E' X Y PO"
      by (simp add: IsLength_def length_id) 
    thus " XY. IsLength PO E E' X Y XY"
      by auto 
  }
  show "X  Y  XY. IsLength PO E E' X Y XY" 
    using length_existence IsLength_def assms by blast
qed

(********************************************************)

lemma lt_to_ltp:
  assumes "Length PO E E' A B L"
    and "Length PO E E' C D M" 
    and "A B Lt C D"
  shows "LtP PO E E' L M"
  by (metis LeP_def Lt_def assms(1,2,3) length_eq_cong_1 length_leP_le_2) 

lemma ltp_to_lep:
  assumes "LtP PO E E' L M"
  shows "LeP PO E E' L M"
  by (simp add: LeP_def assms) 

lemma ltp_to_lt:
  assumes "Length PO E E' A B L"
    and "Length PO E E' C D M" 
    and "LtP PO E E' L M"
  shows "A B Lt C D" 
proof -
  have "LeP PO E E' L M"
    by (simp add: LeP_def assms(3)) 
  have "A B Le C D"
    using LeP PO E E' L M assms(1,2) length_leP_le_1 by auto 
  moreover {
    assume "Cong A B C D" 
    hence "Length PO E E' C D L"
      using assms(1) length_eq_cong_2 by blast 
    hence "L = M" 
      using length_uniqueness [of PO E E' C D L M] assms(2) by auto
    hence False
      using assms(3) ltP_neq by auto 
  }
  ultimately show ?thesis
    using Lt_def by auto 
qed

lemma prod_col:
  assumes "Ar2 PO E E' A B A"
    and "Prod PO E E' A B AB"
  shows "Col PO E AB"
  using Ar2_def Prod_def assms(2) by auto 

lemma square_increase_strict:
  assumes "Ar2 PO E E' A B A"
    and "Ps PO E A"
    and "Ps PO E B" 
    and "LtP PO E E' A B" 
    and "Prod PO E E' A A A2"
    and "Prod PO E E' B B B2" 
  shows "LtP PO E E' A2 B2" 
proof -
  obtain BmA where "Diff PO E E' B A BmA"
    using LtP_def assms(4) by blast
  obtain BpA where "Sum PO E E' B A BpA"
    by (meson Diff PO E E' B A BmA diff_ar2 sum3_def sum3_exists)
  obtain B2mA2 where "Diff PO E E' B2 A2 B2mA2"
    by (metis Ar2_def assms(1,5,6) diff_exists prod_col)
  obtain F where "Prod PO E E' BpA BmA F"
    by (metis Ar2_def Ps_def Diff PO E E' B A BmA Sum PO E E' B A BpA
        assms(1,2,3,4) col_permutation_5 lt_diff_ps out_col prod_exists
        sum_pos_pos)
  thus ?thesis
    by (metis LtP_def Diff PO E E' B A BmA Diff PO E E' B2 A2 B2mA2
        Sum PO E E' B A BpA assms(2,3,4,5,6) diff_of_squares lt_diff_ps prod_pos_pos
        sum_pos_pos) 
qed

lemma square_increase:
  assumes "Ar2 PO E E' A B A"
    and "Ps PO E A"
    and "Ps PO E B" 
    and "LeP PO E E' A B" 
    and "Prod PO E E' A A A2"
    and "Prod PO E E' B B B2" 
  shows "LeP PO E E' A2 B2"
  by (metis Ar2_def LeP_def assms(1,2,3,4,5,6) prod_uniqueness
      square_increase_strict) 

lemma signeq__prod_pos:
  assumes "SignEq PO E A B"
    and "Prod PO E E' A B C"
  shows "Ps PO E C" 
proof -
  have "Ps PO E A  Ps PO E B  Ps PO E C"
    using assms(2) prod_pos_pos by blast 
  moreover {
    assume "Ng PO E A" and "Ng PO E B"
    obtain B' where "B B' Proj PO E' E E'"
      using Prodp_def assms(2) prod_to_prodp by blast 
    have "Bet B' PO E'"
    proof -
      have "Bet B PO E"
        using Ng_def Ng PO E B by auto 
      moreover have "PO PO Proj PO E' E E'"
        by (metis Proj_def B B' Proj PO E' E E' not_col_distincts) 
      moreover have "E E' Proj PO E' E E'"
        by (metis Proj_def calculation(2) not_col_distincts par_reflexivity) 
      ultimately show ?thesis
        using B B' Proj PO E' E E' project_preserves_bet by blast 
    qed
    moreover have "Bet A PO C"
    proof (rule project_preserves_bet [of E' PO B' _ PO E A E'])
      show "E'  PO  B'"
        using Bet_cases calculation by blast 
      show "E' A Proj PO E A E'" 
      proof -
        have "PO  E"
          using Ng_def Ng PO E A by force 
        moreover have "A  E'"
          using Ar2_def Prod_def assms(2) by auto 
        moreover have "¬ PO E Par A E'"
          by (metis Ar2_def Prod_def assms(2) col_trivial_3 not_strict_par2) 
        moreover have "E' A Par A E'  E' = A"
          using Par_cases par_reflexivity by blast 
        ultimately show ?thesis
          using Col_def Ng_def Ng PO E A par_col_project by force 
      qed
      show "PO PO Proj PO E A E'"
        by (metis NCol_perm Proj_def E' A Proj PO E A E' col_trivial_1) 
      show "B' C Proj PO E A E'"
        using Prodp_def B B' Proj PO E' E E' assms(2) prod_to_prodp project_uniqueness
        by blast 
    qed
    ultimately have "PO Out C E"
      using Ng_def Out_def Ng PO E A Ng PO E B assms(2) l5_2 prod_null
      by fastforce 
    hence "Ps PO E C"
      by (simp add: Ps_def) 
  }
  ultimately show ?thesis
    using SignEq_def assms(1) by blast 
qed

lemma pos_neg__prod_neg:
  assumes "Ps PO E A" 
    and "Ng PO E B"
    and "Prod PO E E' A B C"
  shows "Ng PO E C" 
proof -
  obtain B' where "B B' Proj PO E' E E'" and "B' C Proj PO E A E'"
    using Prodp_def assms(3) prod_to_prodp by blast
  show ?thesis 
  proof (unfold Ng_def, intro conjI)
    show "C  PO"
      by (metis Ng_def O_not_positive assms(1,2,3) prod_null) 
    show "E  PO"
      using Ng_def assms(2) by auto 
    show "Bet C PO E" 
    proof -
      have "Bet A PO C"
      proof (rule project_preserves_bet [of E' PO B' _ PO E A E'])
        have "Bet B' PO E'"
        proof (rule project_preserves_bet [of B PO E _ PO E' E E'])
          show "B  PO  E"
            using Ng_def assms(2) by auto 
          show "B B' Proj PO E' E E'"
            by (simp add: B B' Proj PO E' E E') 
          show "PO PO Proj PO E' E E'"
            using Proj_def B B' Proj PO E' E E' col_trivial_3 by presburger 
          show "E E' Proj PO E' E E'"
            by (metis NCol_perm Proj_def PO PO Proj PO E' E E' col_trivial_3
                par_reflexivity) 
        qed
        thus "E'  PO  B'"
          using Bet_perm by blast 
        show "E' A Proj PO E A E'"
          by (metis Par_cases Prodp_def Proj_def assms(3) par_reflexivity
              prod_to_prodp) 
        show "PO PO Proj PO E A E'"
          by (metis NCol_perm Proj_def E' A Proj PO E A E' col_trivial_1) 
        show "B' C Proj PO E A E'"
          by (simp add: B' C Proj PO E A E') 
      qed
      thus ?thesis
        using Bet_cases Ps_def assms(1) bet_out__bet by blast 
    qed
  qed
qed

lemma not_signEq_prod_neg:
  assumes "A  PO"
    and "B  PO"
    and "¬ SignEq PO E A B"
    and "Prod PO E E' A B C"
  shows "Ng PO E C"
  by (metis Ar2_def Prod_def SignEq_def assms(1,2,3,4) col_pos_or_neg
      pos_neg__prod_neg prod_1_r prod_O_r_eq prod_sym) 

lemma prod_pos__signeq:
  assumes "A  PO"
    and "B  PO"
    and "Prod PO E E' A B C"
    and "Ps PO E C"
  shows "SignEq PO E A B"
  using assms(1,2,3,4) neg_not_pos not_signEq_prod_neg by blast 

lemma prod_ng___not_signeq:
  assumes (* "A ≠ PO"
and "B ≠ PO"
and*) "Prod PO E E' A B C"
    and "Ng PO E C"
  shows "¬ SignEq PO E A B"
  using assms(1,2) neg_not_pos signeq__prod_pos by blast 

lemma ltp__diff_pos:
  assumes "LtP PO E E' A B"
    and "Diff PO E E' B A D"
  shows "Ps PO E D"
  using assms(1,2) lt_diff_ps by auto

lemma diff_pos__ltp: 
  assumes "Diff PO E E' B A D"
    and "Ps PO E D"
  shows "LtP PO E E' A B"
  using LtP_def assms(1,2) by blast 

lemma square_increase_rev:
  assumes "Ps PO E A"
    and "Ps PO E B"
    and "LtP PO E E' A2 B2" 
    and "Prod PO E E' A A A2"
    and "Prod PO E E' B B B2" 
  shows "LtP PO E E' A B"
  by (metis Ar2_def LeP_def Prod_def assms(1,2,3,4,5) col_2_le_or_ge leP_asym
      ltP_neq square_increase) 

lemma ltp__ltps: 
  assumes "LtP PO E E' A B"
  shows "LtPs PO E E' A B"
  using LtP_def LtPs_def assms diff_sum by blast 

lemma ltps__ltp: 
  assumes "LtPs PO E E' A B"
  shows "LtP PO E E' A B"
  using LtPs_def assms ltP_sum_pos by blast 

lemma ltp__lep_neq:
  assumes "LtP PO E E' A B"
  shows "LeP PO E E' A B  A  B"
  using assms ltP_neq ltp_to_lep by auto 

lemma lep_neq__ltp:
  assumes "LeP PO E E' A B"
    and "A  B"
  shows "LtP PO E E' A B"
  using LeP_def assms(1,2) by force 

lemma sum_preserves_ltp:
  assumes "LtP PO E E' A B"
    and "Sum PO E E' A C AC"
    and "Sum PO E E' B C BC"
  shows "LtP PO E E' AC BC"
  by (metis Ar2_def assms(1,2,3) compatibility_of_sum_with_order lep_neq__ltp
      ltP_ar2 ltP_neq ltp_to_lep sum_uniquenessA) 

lemma sum_preserves_lep: 
  assumes "LeP PO E E' A B"
    and "Sum PO E E' A C AC"
    and "Sum PO E E' B C BC"
  shows "LeP PO E E' AC BC"
  using assms(1,2,3) compatibility_of_sum_with_order by blast 

lemma sum_preserves_ltp_rev:
  assumes "Sum PO E E' A C AC"
    and "Sum PO E E' B C BC"
    and "LtP PO E E' AC BC" 
  shows "LtP PO E E' A B"
  by (metis Ar2_def assms(1,2,3) col_2_le_or_ge leP_asym lep_neq__ltp ltP_neq
      ltp_to_lep sum_ar2 sum_preserves_lep) 

lemma sum_preserves_lep_rev:
  assumes "Sum PO E E' A C AC"
    and "Sum PO E E' B C BC"
    and "LeP PO E E' AC BC"
  shows "LeP PO E E' A B"
  by (metis Ar2_def Sum_def assms(1,2,3) col_2_le_or_ge
      compatibility_of_sum_with_order leP_asym sum_uniquenessA)

lemma cong2_lea__le:
  assumes "Cong A B D E"
    and "Cong A C D F"
    and "F D E LeA C A B"
  shows "E F Le B C" 
proof -
  have "F D E LtA C A B  F D E CongA C A B"
    using LtA_def assms(3) by auto 
  moreover have "F D E LtA C A B   E F Le B C"
    using Lt_def assms(1,2) t18_18 by blast 
  moreover have "F D E CongA C A B  E F Le B C"
    by (meson assms(1,2) cong2_conga_cong cong_4321 cong__le cong_symmetry) 
  ultimately show ?thesis 
    by blast
qed

lemma lea_out_lea:
  assumes "B Out A A'"
    and "B Out C C'"
    and "E Out D D'"
    and "E Out F F'"
    and "A B C LeA D E F"
  shows "A' B C' LeA D' E F'"
  using assms(1,2,3,4,5) lea_out4__lea by blast 

lemma lta_out_lta: 
  assumes "B Out A A'"
    and "B Out C C'"
    and "E Out D D'"
    and "E Out F F'"
    and "A B C LtA D E F"
  shows "A' B C' LtA D' E F'"
  by (smt (verit) Out_def assms(1,2,3,4,5) lea_out_lea lta__nlea
      nlta__lea)

lemma pythagoras_obtuse:
  assumes "PO  E"
    and "Obtuse A C B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' B C BC"
    and "Prod PO E E' AC AC AC2"
    and "Prod PO E E' BC BC BC2"
    and "Prod PO E E' AB AB AB2"
    and "Sum PO E E' AC2 BC2 S2"
  shows "LtP PO E E' S2 AB2" 
proof -
  obtain A' B' C' where "Per A' B' C'" and "A' B' C' LtA A C B"
    using Obtuse_def assms(2) by blast 
  obtain AA where "B' Out AA A'" and "Cong B' AA C A"
    by (metis A' B' C' LtA A C B l6_11_existence lta_distincts) 
  obtain CC where "B' Out CC C'" and "Cong B' CC C B"
    by (metis A' B' C' LtA A C B l6_11_existence lta_distincts) 
  have "AA CC Lt A B" 
  proof (rule t18_18 [of C A B' AA B CC])
    show "Cong C A B' AA"
      using Cong_perm Cong B' AA C A by blast 
    show "Cong C B B' CC"
      using Cong B' CC C B not_cong_3412 by blast 
    show "CC B' AA LtA B C A"
      by (smt (verit, best) Out_cases A' B' C' LtA A C B B' Out AA A' B' Out CC C' 
          lta_comm lta_distincts lta_out_lta out_trivial) 
  qed
  obtain S1 where "Length PO E E' AA CC S1"
    by (metis A' B' C' LtA A C B assms(3) cong_identity length_Ar2 length_cong 
        length_existence lta_distincts)
  then obtain SS where "Prod PO E E' S1 S1 SS" 
    using prod_exists [of PO E E' S1 S1] assms(4,6) col_trivial_3 length_Ar2 by blast 
  have "B'  C'"
    using Out_def B' Out CC C' by force 
  hence "Per A' B' CC" 
    using per_col [of B' C' A' CC] B' Out CC C' Per A' B' C' col_permutation_5 
      out_col by blast
  have "B'  A'"
    using Out_def B' Out AA A' by blast 
  hence "Per CC B' AA" 
    using per_col [of B' A' CC AA] Out_cases B' Out AA A' Per A' B' CC l8_2 out_col by blast 
  have "Sum PO E E' AC2 BC2 SS" 
    using pythagoras [of _ _ AA B' CC _ S1 AC BC] by (meson Per_cases Cong B' AA C A 
        Cong B' CC C B Length PO E E' AA CC S1 Per CC B' AA
        Prod PO E E' S1 S1 SS assms(1,4,5,6,7) cong_4321 length_eq_cong_2)
  have "S2 = SS"
    using Sum PO E E' AC2 BC2 SS assms(9) sum_stable by blast
  moreover have "LtP PO E E' S1 AB"
    using lt_to_ltp [of PO E E' AA CC S1 A B AB]
    using AA CC Lt A B Length PO E E' AA CC S1 assms(3) by blast
  moreover have "Ps PO E S1"
    by (metis A' B' C' LtA A C B Length PO E E' AA CC S1 Prod PO E E' S1 S1 SS 
        assms(4,5,6,7,9) calculation(1) length_id_1 length_pos lep_neq__ltp ltP_pos 
        lta_distincts prod_O_l_eq square_pos sum_pos_pos) 
  ultimately show ?thesis 
    using square_increase_strict [of PO E E' S1 AB S2 AB2]
    by (metis SignEq_def Prod PO E E' S1 S1 SS assms(3,8)
        length_pos lep_neq__ltp ltP_ar2 ltP_neg ltP_pos pos_neg__prod_neg prod_ng___not_signeq) 
qed

lemma pythagoras_obtuse_or_per:
  assumes "PO  E"
    and "Obtuse A C B  Per A C B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' B C BC"
    and "Prod PO E E' AC AC AC2"
    and "Prod PO E E' BC BC BC2"
    and "Prod PO E E' AB AB AB2"
    and "Sum PO E E' AC2 BC2 S2"
  shows "LeP PO E E' S2 AB2" 
proof -
  have "Obtuse A C B  LeP PO E E' S2 AB2"
    using assms(1,3,4,5,6,7,8,9) ltp_to_lep pythagoras_obtuse by blast
  moreover have  "Per A C B  LeP PO E E' S2 AB2"
    by (meson assms(1,3,4,5,6,7,8,9) leP_refl pythagoras sum_preserves_lep) 
  ultimately show ?thesis
    using assms(2) by blast
qed

lemma pythagoras_acute:
  assumes "PO  E"
    and "Acute A C B"
    and "Length PO E E' A B AB"
    and "Length PO E E' A C AC"
    and "Length PO E E' B C BC"
    and "Prod PO E E' AC AC AC2"
    and "Prod PO E E' BC BC BC2"
    and "Prod PO E E' AB AB AB2"
    and "Sum PO E E' AC2 BC2 S2"
  shows "LtP PO E E' AB2 S2"
proof (cases "A = B")
  show "A = B  LtP PO E E' AB2 S2"
    by (smt (verit, ccfv_SIG) LtPs_def acute_distincts assms(1,2,3,4,5,6,7,8,9) between_trivial2
        distr_r length_Ar2 length_id_1 ltps__ltp prod_0_r prod_sym square_pos sum_A_null 
        sum_assoc_2 sum_pos_pos triangular_equality_bis) 
  {
    assume "A  B"
    obtain A' B' C' where "Per A' B' C'" and "A C B LtA A' B' C'"
      using Acute_def assms(2) by blast 
    have "A'  B'" 
      using A C B LtA A' B' C' lta_distincts by blast
    then obtain AA where "B' Out AA A'" and "Cong B' AA C A"
      by (metis assms(2) between_trivial2 flat_not_acute l6_11_existence) 
    have "C'  B'"
      using A C B LtA A' B' C' lta_distincts by blast 
    then obtain CC where "B' Out CC C'" and "Cong B' CC C B"
      by (metis Out_def C'  B' acute_col__out assms(2) l6_11_existence not_col_distincts) 
    obtain S1 where "Length PO E E' AA CC S1"
      using Ar2_def assms(9) length_existence sum_ar2 by presburger
    obtain SS where "Prod PO E E' S1 S1 SS"
      using Ar2_def Length_def Prod_def Length PO E E' AA CC S1 assms(7) prod_exists
      by presburger
    have "Per A' B' CC" 
    proof (rule per_col [of B' C' A' CC ], insert Per A' B' C')
      show "B'  C'"
        using C'  B' by auto 
      show "Col B' C' CC"
        using Col_cases B' Out CC C' out_col by blast 
    qed
    have "Per CC B' AA"
      using per_col [of _ A'] by (metis NCol_perm A'  B' B' Out AA A' 
          Per A' B' CC l8_2 out_col)
    hence "A B Lt AA CC" 
      using t18_18 [of B' AA C A CC B] by (metis Out_def B' Out AA A' B' Out CC C' 
          Cong B' AA C A Cong B' CC C B  acute_per__lta acute_sym assms(2))
    hence "LtP PO E E' AB S1" 
      using lt_to_ltp [of PO E E' A B AB AA CC S1] Length PO E E' AA CC S1 assms(3) by linarith 
    show "LtP PO E E' AB2 S2"
    proof (rule square_increase_strict [of PO E E' AB S1 AB2 S2], insert 
        LtP PO E E' AB S1 assms(8))
      show "Ar2 PO E E' AB S1 AB"
        by (simp add: LtP PO E E' AB S1 ltP_ar2) 
      show "Ps PO E AB"
        by (metis A  B assms(3) between_trivial2 length_out length_pos lep_neq__ltp ltP_pos
            not_bet_and_out) 
      show "Ps PO E S1"
        by (metis A B Lt AA CC Length PO E E' AA CC S1 length_Ps length_id lt_diff)
      have "S2 = SS" 
      proof (rule sum_uniqueness [of PO E E' AC2 BC2 S2 SS], insert assms(9))
        show "¬ Col PO E E'"
          using Ar2_def Ar2 PO E E' AB S1 AB by blast 
        show "Sum PO E E' AC2 BC2 SS" 
          using pythagoras [of _ _ AA B' CC _ S1 AC BC]
          by (meson Per_cases Cong B' AA C A Cong B' CC C B 
              Length PO E E' AA CC S1 Per CC B' AA
              Prod PO E E' S1 S1 SS assms(1,4,5,6,7) cong_4321 length_eq_cong_2) 
      qed
      thus "Prod PO E E' S1 S1 S2"
        by (simp add: Prod PO E E' S1 S1 SS) 
    qed
  }
qed

lemma pyth_context:
  assumes "¬ Col PO E E'"
  shows " AB BC AC AB2 BC2 AC2 SS. Col PO E AB  Col PO E BC  Col PO E AC  
                                    Col PO E AB2  Col PO E BC2  Col PO E AC2   
                                    Length PO E E' A B AB  Length PO E E' B C BC  
                                    Length PO E E' A C AC  Prod PO E E' AB AB AB2  
                                    Prod PO E E' BC BC BC2  Prod PO E E' AC AC AC2  
                                    Sum PO E E' AB2 BC2 SS" 
proof -
  obtain AB where "Length PO E E' A B AB"
    using assms length_existence by blast 
  obtain BC where "Length PO E E' B C BC" 
    using assms length_existence by blast 
  obtain AC where "Length PO E E' A C AC" 
    using assms length_existence by blast 
  have "Col PO E AB"
    using Length_def Length PO E E' A B AB by auto 
  then obtain AB2 where "Prod PO E E' AB AB AB2"
    using assms prod_exists by blast 
  hence "Col PO E AB2"
    by (metis Ar2_def Col PO E AB assms prod_col) 
  have "Col PO E BC" 
    using Length_def Length PO E E' B C BC by auto 
  then obtain BC2 where "Prod PO E E' BC BC BC2" 
    using assms prod_exists by blast 
  hence "Col PO E BC2"
    by (metis Ar2_def Col PO E BC assms prod_col) 
  have "Col PO E AC" 
    using Length_def Length PO E E' A C AC by auto 
  then obtain AC2 where "Prod PO E E' AC AC AC2"
    using assms prod_exists by blast 
  hence "Col PO E AC2"
    by (metis Ar2_def Col PO E AC assms prod_col)
  obtain SS where "Sum PO E E' AB2 BC2 SS"
    using Col PO E AB2 Col PO E BC2 assms sum_exists by blast 
  thus ?thesis
    by (metis Col PO E AB2 Col PO E AB Col PO E AC2 Col PO E AC 
        Col PO E BC2 Col PO E BC Length PO E E' A B AB Length PO E E' A C AC 
        Length PO E E' B C BC Prod PO E E' AB AB AB2
        Prod PO E E' AC AC AC2 Prod PO E E' BC BC BC2)  
qed

lemma length_pos_or_null:
  assumes "Length PO E E' A B AB"
  shows "Ps PO E AB  A = B"
  by (metis assms cong_identity length_Ps length_cong) 

lemma sum_pos_null: 
  assumes "¬ Ng PO E A"
    and "¬ Ng PO E B"
    and "Sum PO E E' A B PO"
  shows "A = PO  B = PO"
  by (metis Ar2_def O_not_positive assms(1,2,3) col_pos_or_neg col_trivial_1 sum_A_null 
      sum_B_null sum_ar2 sum_pos_pos)

lemma length_not_neg:
  assumes "Length PO E E' A B AB"
  shows "¬ Ng PO E AB"
  by (metis Ng_def assms cong_reverse_identity length_cong length_pos_or_null neg_not_pos) 

lemma signEq_refl:
  assumes "PO  E"
    and "Col PO E A"
  shows "A = PO  SignEq PO E A A"
  by (metis SignEq_def assms(1,2) col_pos_or_neg) 

lemma square_not_neg:
  assumes "Prod PO E E' A A A2"
  shows "¬ Ng PO E A2"
  by (metis Ng_def assms pos_not_neg prod_O_r_eq square_pos) 

lemma root_uniqueness:
  assumes "¬ Ng PO E A"
    and "¬ Ng PO E B"
    and "Prod PO E E' A A C"
    and "Prod PO E E' B B C"
  shows "A = B"
  by (metis Ar2_def Prod_def assms(1,2,3,4) col_pos_or_neg eq_squares_eq_or_opp 
      opp_pos_neg prod_1_r prod_O_r_eq) 

lemma inter_tangent_circle:
  assumes "P  Q"
    and "Cong P PO Q PO"
    and "Col P PO Q"
    and "P M Le P PO"
    and "Q M Le Q PO"
  shows "M = PO" 
proof -
  have "P = Q  PO Midpoint P Q"
    using assms(2,3) cong_commutativity l7_20_bis by blast
  moreover 
  { 
    assume "PO Midpoint P Q"
    obtain A where "Bet PO A P" and "Cong P M PO A"
      using Le_def assms(4) le_right_comm by blast 
    obtain B where "Bet PO B Q" and "Cong Q M PO B"
      using Le_cases Le_def assms(5) by blast 
    have "P Q Le A B" 
      using triangle_inequality_2 [of A PO B P M Q] by (meson Bet_cases Cong P M PO A 
          Cong Q M PO B PO Midpoint P Q PO  A  P PO  B  Q
          between_exchange3 midpoint_bet not_cong_4312 not_cong_4321)
    have "A B Le P Q"
      by (meson PO Midpoint P Q PO  A  P PO  B  Q bet2_le2__le2356_R1 
          between_exchange2 between_inner_transitivity between_symmetry 
          between_trivial2 l5_12_a midpoint_bet) 
    have "Cong A B P Q"
      by (simp add: A B Le P Q P Q Le A B le_anti_symmetry) 
    hence "M = PO"
      by (smt (verit) Bet_cases Col_def Cong_cases Midpoint_def Cong P M PO A Cong Q M PO B
          PO Midpoint P Q PO  A  P PO  B  Q assms(1) bet_cong_eq between_exchange3
          between_exchange4 l4_18) 
  }
  ultimately show ?thesis 
    using assms(1) by blast
qed

lemma inter_circle_per:
  assumes "Cong P A Q A"
    and "P M Le P A" 
    and "Q M Le Q A"
    and "A T Projp P Q"
    and "Per P T M"
  shows "T M Le T A" 
proof (cases "P = T")
  have " ¬ (Bet TPA TPB TPC  Bet TPB TPC TPA  Bet TPC TPA TPB)"
    by (simp add: lower_dim)
  let ?O = "TPA" and ?E = "TPB" and ?E' = "TPC"
  have "¬ Col ?O ?E ?E'"
    by (simp add: Col_def ¬ ((TPA  TPB  TPC)  (TPB  TPC  TPA)  (TPC  TPA  TPB)))
  show "P = T  T M Le T A"
    using assms(2) by auto 
  {
    assume "P  T"
    have "Col P Q T  P Q Perp A T  Col P Q A  A = T"
      using Projp_def assms(4) by presburger 
    moreover {
      assume "Col P Q T" and "P Q Perp A T"
      have "Per P T A"
        using Per_perm Col P Q T P Q Perp A T col_trivial_3 l8_16_1 by blast 
      obtain PT TA AP PT2 TA2 AP2 SS where "Col ?O ?E PT" and "Col ?O ?E TA" and 
        "Col ?O ?E AP" and "Col ?O ?E PT2" and "Col ?O ?E TA2" and "Col ?O ?E AP2" and 
        "Length ?O ?E ?E' P T PT" and "Length ?O ?E ?E' T A TA" and 
        "Length ?O ?E ?E' P A AP" and "Prod ?O ?E ?E' PT PT PT2" and 
        "Prod ?O ?E ?E' TA TA TA2" and "Prod ?O ?E ?E' AP AP AP2" and 
        "Sum ?O ?E ?E' PT2 TA2 SS" 
        using pyth_context [of ?O ?E ?E'] ¬ Col ?O ?E ?E' by metis
      have "Sum ?O ?E ?E' PT2 TA2 AP2" 
        using pythagoras [of ?O ?E P T A ?E' AP PT TA PT2 TA2 AP2] 
          Length TPA TPB TPC P A AP Length TPA TPB TPC P T PT 
          Length TPA TPB TPC T A TA Per P T A Prod TPA TPB TPC AP AP AP2 
          Prod TPA TPB TPC PT PT PT2 Prod TPA TPB TPC TA TA TA2
          between_trivial2 length_sym lower_dim by blast 
      hence "SS = AP2"
        using Sum TPA TPB TPC PT2 TA2 SS sum_stable by blast 
      obtain PT' TM PM PT2' TM2 PM2 SS' where "Col ?O ?E PT'" and "Col ?O ?E TM" and 
        "Col ?O ?E PM" and "Col ?O ?E PT2'" and "Col ?O ?E TM2" and "Col ?O ?E PM2" and 
        "Length ?O ?E ?E' P T PT'" and "Length ?O ?E ?E' T M TM" and 
        "Length ?O ?E ?E' P M PM" and "Prod ?O ?E ?E' PT' PT' PT2'" and 
        "Prod ?O ?E ?E' TM TM TM2" and "Prod ?O ?E ?E' PM PM PM2" and 
        "Sum ?O ?E ?E' PT2' TM2 SS'" 
        using pyth_context [of ?O ?E ?E'] ¬ Col ?O ?E ?E' by metis
      hence "PT = PT'"
        using Length TPA TPB TPC P T PT length_uniqueness by blast
      hence "PT2 = PT2'"
        using Prod TPA TPB TPC PT PT PT2 Prod TPA TPB TPC PT' PT' PT2' ¬ Col TPA TPB TPC
          prod_uniqueness by blast
      have "Sum ?O ?E ?E' PT2 TM2 PM2" 
        using pythagoras [of ?O ?E P T M ?E' PM PT TM PT2 TM2 PM2] 
          Length TPA TPB TPC P M PM Length TPA TPB TPC P T PT
          Length TPA TPB TPC T M TM Prod TPA TPB TPC PM PM PM2
          Prod TPA TPB TPC PT PT PT2 Prod TPA TPB TPC TM TM TM2 assms(5) between_trivial
          length_sym lower_dim by blast
      have "SS' = PM2"
        using PT2 = PT2' Sum TPA TPB TPC PT2 TM2 PM2 Sum TPA TPB TPC PT2' TM2 SS'
          ¬ Col TPA TPB TPC sum_uniqueness by blast
      have "T M Le T A" 
      proof (cases "T = M")
        show "T = M  T M Le T A"
          by (simp add: le_trivial) 
        show "T  M  T M Le T A"
          by (meson Per P T A assms(2,5) cong_lt_per2__lt cong_reflexivity lt__nle
              nlt__le) 
      qed
    }
    moreover have "Col P Q A  A = T  T M Le T A"
      by (metis Col_cases Projp_def assms(1,2,3,4) inter_tangent_circle
          le_reflexivity)
    ultimately show "T M Le T A" 
      by blast
  }
qed

lemma inter_circle_obtuse:
  assumes "Cong P A Q A "
    and "P M Le P A"
    and "Q M Le Q A"
    and "A T Projp P Q"
    and "Obtuse P T M  Per P T M"
  shows "T M Le T A" 
proof (cases "P = T")
  have " ¬ (Bet TPA TPB TPC  Bet TPB TPC TPA  Bet TPC TPA TPB)"
    by (simp add: lower_dim)
  let ?O = "TPA" and ?E = "TPB" and ?E' = "TPC"
  have "¬ Col ?O ?E ?E'"
    by (simp add: Col_def ¬ ((TPA  TPB  TPC)  (TPB  TPC  TPA)  (TPC  TPA  TPB)))
  show "P = T  T M Le T A"
    using assms(2) by auto 
  {
    assume "P  T"
    have "?O  ?E"
      using ¬ ((TPA  TPB  TPC)  (TPB  TPC  TPA)  (TPC  TPA  TPB))
        not_bet_distincts by blast 
    have "Per P T A"
      by (metis Per_cases Projp_def assms(4) l8_16_1 l8_5 not_col_distincts) 
    obtain PT TA AP PT2 TA2 AP2 SS where "Col ?O ?E PT" and "Col ?O ?E TA" and 
      "Col ?O ?E AP" and "Col ?O ?E PT2" and "Col ?O ?E TA2" and "Col ?O ?E AP2" and 
      "Length ?O ?E ?E' P T PT" and "Length ?O ?E ?E' T A TA" and 
      "Length ?O ?E ?E' P A AP" and "Prod ?O ?E ?E' PT PT PT2" and 
      "Prod ?O ?E ?E' TA TA TA2" and "Prod ?O ?E ?E' AP AP AP2" and 
      "Sum ?O ?E ?E' PT2 TA2 SS" 
      using pyth_context [of ?O ?E ?E'] ¬ Col ?O ?E ?E' by metis
    have "Sum ?O ?E ?E' PT2 TA2 AP2" 
      using pythagoras [of ?O ?E P T A ?E' AP PT TA PT2 TA2 AP2] 
        Length TPA TPB TPC P A AP Length TPA TPB TPC P T PT 
        Length TPA TPB TPC T A TA Per P T A
        Prod TPA TPB TPC AP AP AP2 Prod TPA TPB TPC PT PT PT2 Prod TPA TPB TPC TA TA TA2
        between_trivial2 length_sym lower_dim by blast 
    hence "SS = AP2"
      using Sum TPA TPB TPC PT2 TA2 SS sum_stable by blast 
    obtain PT' TM PM PT2' TM2 PM2 SS' where "Col ?O ?E PT'" and "Col ?O ?E TM" and 
      "Col ?O ?E PM" and "Col ?O ?E PT2'" and "Col ?O ?E TM2" and "Col ?O ?E PM2" and 
      "Length ?O ?E ?E' P T PT'" and "Length ?O ?E ?E' T M TM" and 
      "Length ?O ?E ?E' P M PM" and "Prod ?O ?E ?E' PT' PT' PT2'" and 
      "Prod ?O ?E ?E' TM TM TM2" and "Prod ?O ?E ?E' PM PM PM2" and 
      "Sum ?O ?E ?E' PT2' TM2 SS'" 
      using pyth_context [of ?O ?E ?E'] ¬ Col ?O ?E ?E' by metis
    hence "PT = PT'"
      using Length TPA TPB TPC P T PT length_uniqueness by blast
    hence "PT2 = PT2'"
      using Prod TPA TPB TPC PT PT PT2 Prod TPA TPB TPC PT' PT' PT2' ¬ Col TPA TPB TPC
        prod_uniqueness by blast
    have "LeP ?O ?E ?E' SS' PM2"
      using pythagoras_obtuse_or_per [of ?O ?E P T M ?E' PM PT TM PT2 TM2 PM2 SS'] 
      by (simp add: Length TPA TPB TPC P M PM Length TPA TPB TPC P T PT'
          Length TPA TPB TPC T M TM PT = PT' PT2 = PT2' Prod TPA TPB TPC PM PM PM2
          Prod TPA TPB TPC PT' PT' PT2' Prod TPA TPB TPC TM TM TM2
          Sum TPA TPB TPC PT2' TM2 SS' TPA  TPB assms(5) length_sym) 
    show "T M Le T A" 
    proof (cases "T = M")
      show "T = M  T M Le T A"
        by (simp add: le_trivial) 
      {
        assume "T  M"
        show "T M Le T A" 
        proof (cases "P = M")
          show "P = M  T M Le T A"
            using T  M assms(5) l8_8 obtuse_distincts by blast
          {
            assume "P  M"
            have "LeP ?O ?E ?E' PM AP" 
              using length_leP_le_2 [of ?O ?E ?E' P M PM P A AP] 
              by (simp add: Length TPA TPB TPC P A AP Length TPA TPB TPC P M PM
                  assms(2)) 
            have "Ar2 ?O ?E ?E' PM AP PM"
              by (simp add: Ar2_def Col TPA TPB AP Col TPA TPB PM
                  ¬ Col TPA TPB TPC) 
            moreover have "Ps ?O ?E PM" 
            proof -
              have "P = M  Ps ?O ?E PM"
                by (simp add: P  M) 
              thus ?thesis
                by (meson Length TPA TPB TPC P M PM length_pos_or_null) 
            qed
            moreover 
            have "P = A  Ps ?O ?E AP"
              using P  T Per P T A l8_8 by blast
            hence "Ps ?O ?E AP"
              using Length TPA TPB TPC P A AP length_pos_or_null by blast 
            ultimately have "LeP ?O ?E ?E' PM2 AP2" 
              using square_increase [of ?O ?E ?E' PM AP PM PM2] LeP TPA TPB TPC PM AP 
                Prod TPA TPB TPC AP AP AP2
                Prod TPA TPB TPC PM PM PM2 square_increase by blast 
            have "LeP ?O ?E ?E' SS' AP2"
              using LeP TPA TPB TPC PM2 AP2 LeP TPA TPB TPC SS' PM2 leP_trans by blast
            have "LeP ?O ?E ?E' TM2 TA2"
              by (metis Col TPA TPB TA2 Col TPA TPB TM2 LeP TPA TPB TPC SS' AP2 
                  PT2 = PT2' SS = AP2 Sum TPA TPB TPC PT2 TA2 SS 
                  Sum TPA TPB TPC PT2' TM2 SS'
                  ¬ Col TPA TPB TPC col_2_le_or_ge leP_asym sum_comm sum_preserves_lep
                  sum_uniquenessB)
            have "T = M  Ps ?O ?E TM"
              using T  M by blast 
            hence "Ps ?O ?E TM"
              using Length TPA TPB TPC T M TM length_pos_or_null by blast 
            have "Ps ?O ?E TA"
              by (metis NCol_perm Ng_def Out_def Ps_def Col TPA TPB TA 
                  LeP TPA TPB TPC TM2 TA2
                  Length TPA TPB TPC T A TA Prod TPA TPB TPC TA TA TA2
                  Prod TPA TPB TPC TM TM TM2 Ps TPA TPB TM ¬ Col TPA TPB TPC leP_asym
                  length_not_neg or_bet_out prod_O_l_eq prod_pos_pos ps_le)
            have "LeP ?O ?E ?E' TM TA"
              by (metis LeP_def LeP TPA TPB TPC TM2 TA2 Prod TPA TPB TPC TA TA TA2
                  Prod TPA TPB TPC TM TM TM2 Ps TPA TPB TA Ps TPA TPB TM pos_not_neg
                  root_uniqueness square_increase_rev)
            have "A T Projp P Q"
              by (simp add: assms(4)) 
            hence "(Col P Q T  P Q Perp A T)  (Col P Q A  A = T)"
              using Projp_def by auto
            moreover {
              assume "Col P Q T" and "P Q Perp A T"
              have "T M Le T A" 
                using length_leP_le_1 [of ?O ?E ?E' _ _ TM _ _ TA]
                using LeP TPA TPB TPC TM TA Length TPA TPB TPC T A TA
                  Length TPA TPB TPC T M TM by blast    
            }
            moreover {
              assume "Col P Q A" and "A = T"
              have "T M Le T A" 
              proof -
                have "(Col P A Q  P M Le P A  Q M Le Q A)  M = A"
                  by (metis Projp_def assms(1,4) inter_tangent_circle) 
                hence "M = A"
                  using Col_cases Col P Q A assms(2,3) by blast  
                thus ?thesis
                  using A = T T  M by auto 
              qed
            }
            ultimately show "T M Le T A"
              by blast
          }
        qed
      }
    qed
  }
qed

lemma circle_projp_between:
  assumes "Cong P A Q A"
    and "A T Projp P Q"
  shows "Bet P T Q" 
proof (cases "P = T")
  show "P = T  (P  T  Q)"
    using not_bet_distincts by blast 
  {
    assume "P  T"
    have "Col P Q T  P Q Perp A T  Col P Q A  A = T"
      using Projp_def assms(2) by auto 
    moreover {
      assume "Col P Q T" and "P Q Perp A T"
      hence "Per A T P"
        using col_trivial_3 l8_16_1 by blast
      obtain T' where "T' Midpoint P Q"
        using midpoint_existence by blast
      hence "Per A T' P"
        using Per_def assms(1) cong_commutativity by blast
      have "T' = T  ¬ Col T P Q"
        by (metis Projp_def P  T Per A T P Per A T' P T' Midpoint P Q assms(2)
            col_per2_cases midpoint_col midpoint_distinct_1) 
      moreover have "T' = T  Bet P T Q"
        using T' Midpoint P Q midpoint_bet by blast 
      moreover have "¬ Col T P Q  Bet P T Q"
        using Col_cases Col P Q T by auto 
      ultimately have "Bet P T Q"  
        by blast
    }
    moreover have "Col P Q A  A = T  Bet P T Q"
      by (metis NCol_perm Projp_def assms(1,2) bet_cong_eq between_trivial col_bet2_cong1
          col_trivial_2 cong_identity third_point) 
    ultimately show "P  T  Q" 
      by blast
  }
qed

lemma inter_circle:
  assumes "Cong P A Q A"
    and "P M Le P A"
    and "Q M Le Q A"
    and "A T Projp P Q"
  shows "T M Le T A" 
proof (cases "T = M")
  have "Bet P T Q"
    using assms(1,4) circle_projp_between by auto
  show "T = M  T M Le T A"
    using le_trivial by blast 
  {
    assume "T  M"
    show "T M Le T A" 
    proof (cases "P = T")
      show "P = T  T M Le T A"
        using assms(2) by blast 
      {
        assume "P  T"
        hence "Acute P T M  Per P T M  Obtuse P T M"
          using T  M angle_partition by auto 
        show "T M Le T A"
        proof (cases "Q = T")
          show "Q = T  T M Le T A"
            using assms(3) by auto 
          {
            assume "Q  T"
            {
              assume "Acute P T M"
              have "Obtuse Q T M"
                using Acute P T M P  T  Q Q  T acute_bet__obtuse by blast
              moreover have "A T Projp Q P"
                by (metis Col_cases Perp_cases Projp_def assms(4)) 
              ultimately have "T M Le T A"
                using Cong_cases assms(1,2,3) inter_circle_obtuse by blast 
            }
            moreover have "Per P T M  T M Le T A"
              using assms(1,2,3,4) inter_circle_per by blast 
            moreover have "Obtuse P T M  T M Le T A"
              using assms(1,2,3,4) inter_circle_obtuse by blast 
            ultimately show "T M Le T A"
              using Acute P T M  Per P T M  Obtuse P T M by blast 
          }
        qed
      }
    qed
  }
qed

lemma projp_lt:
  assumes "Cong P A Q A"
    and "A T Projp P Q"
  shows "T A Lt P A" 
proof -
  have "Col P Q T  P Q Perp A T  Col P Q A  A = T"
    using Projp_def assms(2) by auto 
  moreover {
    assume "Col P Q T" and "P Q Perp A T"
    have ?thesis
    proof (cases "P = T")
      show "P = T  T A Lt P A"
        by (metis Perp_cases P Q Perp A T assms(1) cong__nlt l11_46 l8_16_1
            not_col_distincts) 
      show "P  T  T A Lt P A"
        by (metis Lt_cases Col P Q T P Q Perp A T col_trivial_3 l8_16_1 per_lt) 
    qed
  } 
  moreover have "Col P Q A  A = T  ?thesis"
    by (metis Projp_def assms(1,2) cong_reverse_identity lt1123) 
  ultimately show ?thesis 
    by blast
qed

lemma Ps_Col:
  assumes "Ps PO E A"
  shows "Col PO E A"
  using Col_cases Ps_def assms out_col by blast 

lemma PythRel_exists:
  assumes "¬ Col PO E  E'"
  shows " A B. Col PO E A  Col PO E B  ( C. PythRel PO E E' A B C)" 
proof -
  {
    fix A B
    assume "Col PO E A" and "Col PO E B"
    have " C. PythRel PO E E' A B C" 
    proof (cases "B = PO")
      show "B = PO   C. PythRel PO E E' A B C"
        using Ar2_def PythRel_def Col PO E A assms col_trivial_3 by auto 
      {
        assume "B  PO"
        obtain X where "PO X Perp E PO"
          using Perp_cases assms l8_21_aux by blast 
        obtain B' where "Bet PO X B'  Bet PO B' X" and "Cong PO B' PO B"
          by (metis PO X Perp E PO perp_distinct segment_construction_2)
        obtain C where "Bet PO E C  Bet PO C E" and "Cong PO C A B'"
          by (metis segment_construction segment_construction_2)
        have "Col PO E C"
          using Bet_cases Col_def (PO  E  C)  (PO  C  E) by blast
        moreover have "PO B' Perp PO B  Cong PO B' PO B  Cong PO C A B'"
          by (metis Col_cases Col_def B  PO Col PO E B Cong PO B' PO B Cong PO C A B'
              PO X Perp E PO (PO  X  B')  (PO  B'  X) col_trivial_2 
              cong_reverse_identity perp_col0)
        hence "PO = B  (A = C  Opp PO E E' A C)  
                 ( B'0. PO B'0 Perp PO B  Cong PO B'0 PO B  Cong PO C A B'0)" 
          by blast
        ultimately have "PythRel PO E E' A B C"
          by (simp add: assms Col PO E A Col PO E B Ar2_def PythRel_def) 
        thus " C. PythRel PO E E' A B C" 
          by fast
      }
    qed
  }
  thus ?thesis
    by blast
qed

lemma opp_same_square:
  assumes "Opp PO E E' A B"
    and "Prod PO E E' A A A2"
  shows "Prod PO E E' B B A2" 
proof -
  obtain ME where "Opp PO E E' E ME"
    using Ar2_def Prod_def assms(2) col_trivial_2 opp_exists by presburger
  hence "Prod PO E E' A ME B"
    using assms(1) opp_prod by blast
  moreover have "Prod PO E E' B ME A"
    by (meson Ar2_def Prod_def Opp PO E E' E ME assms(1) opp_comm opp_prod)
  hence "Prod PO E E' ME B A"
    by (simp add: prod_sym)
  ultimately show ?thesis
    using assms(2) prod_assoc by blast 
qed

(**********)

lemma PythOK:
  assumes "PythRel PO E E' A B C"
    and "Prod PO E E' A A A2"
    and "Prod PO E E' B B B2"
    and "Prod PO E E' C C C2"
  shows "Sum PO E E' A2 B2 C2" 
proof -
  have "PO  E"
    using Ar2_def PythRel_def assms(1) col_trivial_1 by force 
  have "PO = B  
        (A = C  Opp PO E E' A C)  ( B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C A B')"
    using PythRel_def assms(1) by auto 
  moreover { 
    assume "PO = B" and "A = C  Opp PO E E' A C"
    hence "PO = B2"
      using assms(3) prod_O_l_eq by blast 
    have "A = C  A2 = C2"
      by (metis Ar2_def Prod_def assms(2,4) prod_uniqueness) 
    moreover have "Opp PO E E' A C  A2 = C2"
      by (meson Ar2_def PythRel_def assms(1,2,4) opp_same_square prod_uniqueness) 
    ultimately have "A2 = C2"
      using A = C  Opp PO E E' A C by blast 
    hence "Col PO E A2"
      by (metis Col_def Ps_Col assms(4) between_trivial prod_O_r_eq
          square_pos) 
    hence "Sum PO E E' A2 B2 C2"
      using Ar2_def PythRel_def A2 = C2 PO = B2 assms(1) sum_A_O by auto 
  }
  moreover {
    assume " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C A B'"
    then obtain B' where "PO B' Perp PO B" and "Cong PO B' PO B" and "Cong PO C A B'"
      by blast
    have "Per A PO B'" 
    proof -
      have "PO  B"
        using PO B' Perp PO B perp_distinct by blast 
      moreover have "Per B' PO B"
        by (simp add: PO B' Perp PO B perp_per_2) 
      moreover have "Col PO B A"
        using Ar2_def PythRel_def PO  E assms(1) col_transitivity_1 by presburger 
      ultimately show ?thesis
        using Per_cases per_col by blast 
    qed
    have "Sum PO E E' A2 B2 C2"
    proof (cases "A = PO")
      {
        assume "A = PO"
        hence "Cong PO B PO C"
          using B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C A B'
            cong_inner_transitivity cong_symmetry by blast 
        have "B = C  PO Midpoint B C" 
          using l7_20 [of B PO C] Ar2_def PythRel_def Cong PO B PO C PO  E 
            assms(1) col_permutation_4 col_transitivity_1 by presburger 
        moreover {
          assume "B = C"
          have "B2 = C2" 
            using prod_uniqueness [of PO E E' B B B2 C2] Ar2_def PythRel_def B = C 
              assms(1,3,4) by presburger
          have "A2 = PO" 
            using prod_uniqueness [of PO E E' PO PO A2 PO] A = PO assms(2) prod_O_l_eq by blast 
          have "Col PO E B2"
            by (metis Ps_Col assms(3) grid_not_par_5 prod_O_r_eq square_pos) 
          hence "Sum PO E E' A2 B2 C2"
            using Ar2_def PythRel_def A2 = PO B2 = C2 assms(1) sum_O_B by auto 
        }
        moreover {
          assume "PO Midpoint B C"
          have "A2 = PO" 
            using prod_uniqueness [of PO E E' PO PO A2 PO] A = PO assms(2) prod_O_l_eq by blast 
          have "Ar2 PO E E' PO B C"
            using PythRel_def A = PO assms(1) by blast
          hence "Opp PO E E' B C"
            by (simp add: PO Midpoint B C midpoint_opp) 
          have "C2 = B2" 
            using prod_uniqueness [of PO E E' C C C2 B2] Ar2_def Ar2 PO E E' PO B C 
              Opp PO E E' B C assms(3,4) opp_same_square
            by presburger
          have "Col PO E B2"
            by (metis Col_def Ps_Col C2 = B2 assms(4) between_trivial2 prod_O_r_eq
                square_pos) 
          hence "Sum PO E E' A2 B2 C2"
            using Ar2_def A2 = PO Ar2 PO E E' PO B C C2 = B2 sum_O_B by presburger 
        }
        ultimately show "Sum PO E E' A2 B2 C2" 
          by blast
      }
      {
        assume "A  PO"
        show "Sum PO E E' A2 B2 C2" 
        proof (cases "PO Out A E")
          {
            assume "PO Out A E"
            show "Sum PO E E' A2 B2 C2" 
            proof (cases "PO Out B E")
              {
                assume "PO Out B E"
                show "Sum PO E E' A2 B2 C2" 
                proof (cases "PO Out C E")
                  {
                    assume "PO Out C E"
                    show "Sum PO E E' A2 B2 C2" 
                    proof (rule pythagoras [of _ _ A PO B' _ C A B], insert PO  E 
                        Per A PO B'assms(2,3,4))
                      have "LeP PO E E' PO C"
                      proof -
                        have "Diff PO E E' C PO C"
                          using Ar2_def Prod_def assms(4) diff_A_O by presburger 
                        moreover have "Ps PO E C"
                          by (simp add: Ps_def PO Out C E) 
                        ultimately show ?thesis
                          by (simp add: diff_pos__ltp ltp_to_lep) 
                      qed
                      thus "Length PO E E' A B' C"
                        by (meson Length_def NCol_cases Cong PO C A B' PO Out C E PO  E
                            out_col) 
                      show "Length PO E E' A PO A"
                        by (metis Ar2_def Cong_cases Length_def Out_def PythRel_def 
                            PO Out A E assms(1)
                            cong_reflexivity ps_le) 
                      show "Length PO E E' B' PO B"
                        by (metis Length_def Out_def Cong PO B' PO B Length PO E E' A B' C 
                            PO Out B E PO Out C E cong_3421 length_Ar2 out_col ps_le) 
                    qed
                  }
                  {
                    assume "¬ PO Out C E"
                    obtain OC where "Opp PO E E' C OC"
                      by (meson Ar2_def Diff_def Prod_def assms(4) diff_null) 
                    have "Ng PO E C"
                      by (metis Col_def Ps_def SignEq_def A  PO Cong PO C A B' Per A PO B'
                          ¬ PO Out C E assms(4) between_trivial2 cong_reverse_identity 
                          not_signEq_prod_neg per_not_col square_not_neg)
                    hence "Ps PO E OC"
                      using Opp PO E E' C OC opp_neg_pos by auto
                    show "Sum PO E E' A2 B2 C2" 
                    proof (rule pythagoras [of _ _ A PO B' _ OC A B], insert PO  E 
                        Per A PO B' assms(2,3))
                      show "Length PO E E' A B' OC" 
                      proof -
                        have "Col PO E OC"
                          by (simp add: Ps_Col Ps PO E OC) 
                        moreover have "LeP PO E E' PO OC"
                          by (metis Ar2_def Prod_def Ps_def Ps PO E OC assms(2) 
                              calculation not_bet_and_out ps_le third_point) 
                        moreover have "Cong PO OC A B'" 
                        proof -
                          have "PO Midpoint C OC" 
                            using opp_midpoint Opp PO E E' C OC by auto 
                          thus ?thesis
                            using Cong_cases Midpoint_def Cong PO C A B' cong_inner_transitivity
                            by blast 
                        qed
                        ultimately show ?thesis
                          by (simp add: Length_def PO  E) 
                      qed
                      show "Length PO E E' A PO A"
                        using Ar2_def Length_def Out_def Prod_def PO Out A E assms(2)
                          cong_pseudo_reflexivity ps_le by force 
                      show "Length PO E E' B' PO B"
                        by (metis Ar2_def Length_def Out_def Prod_def Cong PO B' PO B 
                            PO Out B E assms(3) cong_3421 ps_le) 
                      show "Prod PO E E' OC OC C2"
                        using Opp PO E E' C OC assms(4) opp_same_square by auto 
                    qed
                  }
                qed
              }
              {
                assume "¬ PO Out B E"
                obtain OB where "Opp PO E E' B OB"
                  using Ar2_def Prod_def assms(3) opp_exists by presburger 
                    (*319*)
                have "Ng PO E B"
                  by (metis Ps_def SignEq_def
                      B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C A B' 
                      ¬ PO Out B E assms(3) not_col_distincts not_signEq_prod_neg 
                      perp_not_col2 square_not_neg)
                hence "Ps PO E OB"
                  using Opp PO E E' B OB opp_neg_pos by auto 
                {
                  assume "PO Out C E"
                  have "Sum PO E E' A2 B2 C2" 
                  proof (rule pythagoras [of _ _ A PO B' _ C A OB], insert PO  E 
                      Per A PO B' assms(2,4))
                    have "LeP PO E E' PO C" 
                    proof -
                      have "PO Out OB E"
                        using Ps_def Ps PO E OB by auto 
                      have "LtP PO E E' PO C" 
                      proof -
                        have "Diff PO E E' C PO C"
                          using Ar2_def Prod_def assms(4) diff_A_O by presburger 
                        moreover have "Ps PO E C"
                          by (simp add: Ps_def PO Out C E) 
                        ultimately show ?thesis
                          using diff_pos__ltp by blast 
                      qed
                      thus ?thesis
                        using ltp_to_lep by auto 
                    qed
                    thus "Length PO E E' A B' C"
                      by (metis Length_def Ps_Col Cong PO C A B' PO  E length_O lep_neq__ltp
                          ltP_pos) 
                    show "Length PO E E' A PO A"
                      by (metis Ar2_def Cong_cases Length_def Out_def PythRel_def 
                          PO Out A E assms(1) cong_reflexivity ps_le) 
                    show "Length PO E E' B' PO OB" 
                    proof -
                      have "LeP PO E E' PO OB"
                        using Ar2_def Out_def Ps_def PythRel_def Ps PO E OB 
                          assms(1) ps_le by force 
                      moreover have "PO Midpoint B OB" 
                        using opp_midpoint Opp PO E E' B OB by auto 
                      hence "Cong PO OB B' PO" 
                        by (meson Midpoint_def Cong PO B' PO B cong_4312 cong_inner_transitivity) 
                      moreover have "Prod PO E E' OB OB B2"
                        using Opp PO E E' B OB assms(3) opp_same_square by blast 
                      ultimately show ?thesis
                        by (simp add: Length_def Ps_Col PO  E Ps PO E OB) 
                    qed
                    show "Prod PO E E' OB OB B2"
                      using Opp PO E E' B OB assms(3) opp_same_square by blast 
                  qed
                }
                moreover {
                  assume "¬ PO Out C E"
                  obtain OC where "Opp PO E E' C OC"
                    using Ar2_def Prod_def assms(4) opp_exists by presburger 
                  have "Ng PO E C"
                    by (metis Ps_def SignEq_def A  PO Cong PO C A B' Per A PO B' 
                        ¬ PO Out C E assms(4) cong_reverse_identity l8_20_1_R1 l8_7 
                        not_signEq_prod_neg square_not_neg) 
                  hence "Ps PO E OC"
                    using Opp PO E E' C OC opp_neg_pos by auto
                  obtain OB where "Opp PO E E' B OB"
                    using Opp PO E E' B OB by auto
                  have "Ps PO E OB"
                    using Ng PO E B Opp PO E E' B OB opp_neg_pos by auto
                  have "Sum PO E E' A2 B2 C2"
                  proof (rule pythagoras [of _ _ A PO B' _ OC A OB], insert PO  E 
                      Per A PO B' assms(2))
                    show "Length PO E E' A B' OC" 
                    proof -
                      have "Col PO E OC"
                        by (simp add: Ps_Col Ps PO E OC) 
                      moreover have "LeP PO E E' PO OC"
                        by (meson Ar2_def Ps_def PythRel_def Ps PO E OC assms(1) calculation
                            not_bet_and_out ps_le third_point) 
                      moreover have "PO Midpoint C OC" 
                        using opp_midpoint  Opp PO E E' C OC by auto 
                      hence "Cong PO OC A B'"
                        using Cong_cases Midpoint_def Cong PO C A B' cong_inner_transitivity
                        by blast 
                      ultimately show ?thesis
                        by (simp add: Length_def PO  E) 
                    qed
                    show "Length PO E E' A PO A"
                      using Ar2_def Length_def Out_def Prod_def PO Out A E assms(2)
                        cong_pseudo_reflexivity ps_le by auto 
                    show "Length PO E E' B' PO OB" 
                    proof -
                      have "LeP PO E E' PO OB"
                        using Ar2_def Out_def Prod_def Ps_def Ps PO E OB assms(2) ps_le by force 
                      moreover have "PO Midpoint B OB"
                        using opp_midpoint Opp PO E E' B OB by blast 
                      hence "Cong PO OB B' PO"
                        by (meson Midpoint_def Cong PO B' PO B cong_4312 cong_inner_transitivity) 
                      ultimately show ?thesis
                        by (simp add: Length_def Ps_Col PO  E Ps PO E OB) 
                    qed
                    show "Prod PO E E' OB OB B2"
                      using Opp PO E E' B OB assms(3) opp_same_square by blast 
                    show "Prod PO E E' OC OC C2"
                      using Opp PO E E' C OC assms(4) opp_same_square by auto 
                  qed
                }
                ultimately show "Sum PO E E' A2 B2 C2" 
                  by blast
              }
            qed
          }
          {
            assume "¬ PO Out A E"
            show "Sum PO E E' A2 B2 C2" 
            proof (cases "PO Out B E")
              {
                assume "PO Out B E"
                show "Sum PO E E' A2 B2 C2" 
                proof (cases "PO Out C E")
                  {
                    assume "PO Out C E"
                    obtain OA where "Opp PO E E' A OA"
                      by (meson Ar2_def Diff_def Prod_def assms(2) diff_null)
                    have "Ng PO E A"
                      by (metis Ps_def SignEq_def A  PO ¬ PO Out A E assms(2) 
                          not_signEq_prod_neg square_not_neg) 
                    show "Sum PO E E' A2 B2 C2" 
                    proof (rule pythagoras [of _ _ A PO B' _ C OA B], insert PO  E 
                        Per A PO B' assms(3,4))
                      show "Length PO E E' A B' C"
                        using Ar2_def Length_def Out_def Prod_def Cong PO C A B' 
                          PO Out C E assms(4) ps_le by force 
                      show "Length PO E E' A PO OA" 
                      proof -
                        have "Col PO E OA"
                          using Ps_Col Ng PO E A Opp PO E E' A OA opp_neg_pos by blast 
                        moreover have "LtP PO E E' PO OA"
                          by (metis Ar2_def Out_def Ps_def Ng PO E A Opp PO E E' A OA 
                              diff_O_A diff_ar2 lep_neq__ltp opp_neg_pos ps_le) 
                        ultimately show ?thesis
                          by (meson Length_def Opp_def Opp PO E E' A OA PO  E l15_3
                              ltp_to_lep not_cong_4321) 
                      qed
                      show "Length PO E E' B' PO B"
                        by (metis Ar2_def Length_def Out_def Prod_def Cong PO B' PO B 
                            PO Out B E assms(3) cong_3421 ps_le) 
                      show "Prod PO E E' OA OA A2"
                        using Opp PO E E' A OA assms(2) opp_same_square by force 
                    qed
                  }
                  {
                    assume "¬ PO Out C E"
                    obtain OC where "Opp PO E E' C OC"
                      by (meson Diff_def Prod_def assms(4) sum_diff sum3_def sum3_exists)
                    have "Ng PO E C"
                      by (metis Ps_def SignEq_def A  PO Cong PO C A B' Per A PO B' 
                          ¬ PO Out C E assms(4) cong_reverse_identity not_col_distincts 
                          not_signEq_prod_neg per_not_col square_not_neg) 
                    hence "Ps PO E OC"
                      using Opp PO E E' C OC opp_neg_pos by auto
                    obtain OA where "Opp PO E E' A OA"
                      by (meson Diff_def Prod_def assms(2) sum_diff sum3_def sum3_exists) 
                    have "Ng PO E A"
                      by (metis Ps_def SignEq_def A  PO ¬ PO Out A E assms(2) 
                          not_signEq_prod_neg square_not_neg) 
                    show "Sum PO E E' A2 B2 C2" 
                    proof (rule pythagoras [of _ _ A PO B' _ OC OA B], insert PO  E 
                        Per A PO B' assms(3))
                      show "Length PO E E' A B' OC" 
                      proof (unfold Length_def, intro strip conjI, insert PO  E)
                        show "Col PO E OC"
                          by (simp add: Ps_Col Ps PO E OC) 
                        show "LeP PO E E' PO OC"
                          by (metis Ar2_def Prod_def Ps_def Col PO E OC Ps PO E OC 
                              assms(2) not_bet_and_out ps_le third_point) 
                        have "PO Midpoint C OC"
                          using opp_midpoint Opp PO E E' C OC by blast 
                        thus "Cong PO OC A B'"
                          using Cong_cases Midpoint_def Cong PO C A B' cong_inner_transitivity
                          by blast 
                      qed
                      show "Length PO E E' A PO OA" 
                      proof -
                        have "LeP PO E E' PO OA"
                          by (meson Ar2_def Out_def Prod_def Ps_def Ng PO E A 
                              Opp PO E E' A OA assms(2) opp_neg_pos ps_le) 
                        moreover have "Cong PO OA A PO"
                          using Cong_cases Opp_def Opp PO E E' A OA l15_3 by blast 
                        ultimately show ?thesis
                          by (metis Length_def Ps_Col A  PO Ng PO E A Opp PO E E' A OA 
                              PO  E neg_not_pos pos_null_neg) 
                      qed
                      show "Length PO E E' B' PO B"
                        by (metis Ar2_def Length_def Out_def Prod_def Cong PO B' PO B 
                            PO Out B E assms(3) cong_3421 ps_le) 
                      show "Prod PO E E' OA OA A2"
                        using Opp PO E E' A OA assms(2) opp_same_square by auto 
                      show "Prod PO E E' OC OC C2"
                        using Opp PO E E' C OC assms(4) opp_same_square by auto 
                    qed
                  }
                qed
              }
              {
                assume "¬ PO Out B E"
                show "Sum PO E E' A2 B2 C2" 
                proof (cases "PO Out C E")
                  {
                    assume "PO Out C E"
                    obtain OB where "Opp PO E E' B OB"
                      by (metis Diff_def Prod_def assms(3) sum_diff sum3_def sum3_exists) 
                    have "Ng PO E B"
                      by (metis Ps_def SignEq_def PO B' Perp PO B ¬ PO Out B E assms(3)
                          not_signEq_prod_neg perp_not_eq_2 square_not_neg)
                    hence "Ps PO E OB"
                      using Opp PO E E' B OB opp_neg_pos by blast 
                    obtain OA where "Opp PO E E' A OA"
                      by (meson Diff_def Prod_def assms(2) sum_diff sum3_def sum3_exists) 
                    have "Ng PO E A"
                      by (metis Ps_def SignEq_def A  PO ¬ PO Out A E assms(2) 
                          not_signEq_prod_neg square_not_neg) 
                    show "Sum PO E E' A2 B2 C2" 
                    proof (rule pythagoras [of _ _ A PO B' _ C OA OB], insert PO  E 
                        Per A PO B' assms(4))
                      have "LtP PO E E' PO C"
                        by (metis Ar2_def Out_def PythRel_def PO Out C E assms(1) lep_neq__ltp
                            ps_le) 
                      thus "Length PO E E' A B' C"
                        by (simp add: Length_def Ps_Col Cong PO C A B' PO  E 
                            ltP_pos ltp_to_lep) 
                      show "Length PO E E' A PO OA"
                      proof -
                        have "LtP PO E E' PO OA"
                          by (metis Ar2_def Out_def Ps_def LtP PO E E' PO C Ng PO E A 
                              Opp PO E E' A OA lep_neq__ltp ltP_ar2 opp_neg_pos ps_le) 
                        moreover have "Cong PO OA A PO"
                          using Cong_cases Opp_def Opp PO E E' A OA l15_3 by blast 
                        ultimately show ?thesis
                          by (simp add: Length_def Ps_Col PO  E ltP_pos ltp_to_lep) 
                      qed
                      show "Length PO E E' B' PO OB" 
                      proof -
                        have "LtP PO E E' PO OB"
                          by (metis Ar2_def Out_def Prod_def Ps_def Ps PO E OB assms(4)
                              lep_neq__ltp ps_le) 
                        moreover have "Cong PO OB B' PO"
                          by (metis Cong_cases Midpoint_def Cong PO B' PO B Opp PO E E' B OB
                              cong_inner_transitivity opp_midpoint) 
                        ultimately show ?thesis
                          by (simp add: Length_def Ps_Col PO  E Ps PO E OB ltp_to_lep) 
                      qed
                      show "Prod PO E E' OA OA A2"
                        using Opp PO E E' A OA assms(2) opp_same_square by blast 
                      show "Prod PO E E' OB OB B2"
                        using Opp PO E E' B OB assms(3) opp_same_square by auto 
                    qed
                  }
                  {
                    assume "¬ PO Out C E"
                    obtain OC where "Opp PO E E' C OC"
                      by (meson Diff_def Prod_def assms(4) sum_diff sum3_def sum3_exists)
                    have "Ng PO E C"
                      by (metis Ar2_def Ng_def Out_def PythRel_def A  PO Cong PO C A B' 
                          Per A PO B' ¬ PO Out C E assms(1) cong_reverse_identity 
                          not_col_distincts per_not_col third_point)
                    hence "Ps PO E OC"
                      using Opp PO E E' C OC opp_neg_pos by auto 
                    obtain OA where "Opp PO E E' A OA"
                      by (meson Diff_def Prod_def assms(2) sum_diff sum3_def sum3_exists) 
                    have "Ng PO E A"
                      by (metis Ps_def SignEq_def A  PO ¬ PO Out A E assms(2) 
                          not_signEq_prod_neg square_not_neg) 
                    obtain OB where "Opp PO E E' B OB"
                      by (meson Ar2_def Diff_def Prod_def assms(3) diff_null) 
                    have "Ng PO E B"
                      by (metis Ps_def SignEq_def PO B' Perp PO B ¬ PO Out B E assms(3)
                          not_col_distincts not_signEq_prod_neg perp_not_col2 square_not_neg)
                    hence "Ps PO E OB"
                      using Opp PO E E' B OB opp_neg_pos by auto 
                    show "Sum PO E E' A2 B2 C2" 
                    proof (rule pythagoras [of _ _ A PO B' _ OC OA OB], insert PO  E 
                        Per A PO B')
                      show "Length PO E E' A B' OC" 
                      proof -
                        have "Col PO E OC"
                          by (simp add: Ps_Col Ps PO E OC) 
                        moreover have "LeP PO E E' PO OC"
                          by (metis Ar2_def Ps_def PythRel_def Ps PO E OC assms(1) calculation
                              not_bet_and_out ps_le third_point) 
                        moreover have "Cong PO OC A B'"
                          by (metis Cong_cases Opp_def Cong PO C A B' Opp PO E E' C OC 
                              cong_transitivity l15_3) 
                        ultimately show ?thesis
                          by (simp add: Length_def PO  E) 
                      qed
                      show "Length PO E E' A PO OA" 
                      proof -
                        have "LtP PO E E' PO OA"
                          by (metis Ar2_def Out_def Prod_def Ps_def Ng PO E A 
                              Opp PO E E' A OA assms(2) lep_neq__ltp 
                              opp_neg_pos ps_le) 
                        moreover have "Cong PO OA A PO"
                          using Cong_cases Opp_def Opp PO E E' A OA l15_3 by blast 
                        ultimately show ?thesis
                          by (simp add: Length_def Ps_Col PO  E ltP_pos ltp_to_lep) 
                      qed
                      show "Length PO E E' B' PO OB" 
                      proof -
                        have "LtP PO E E' PO OB"
                          by (metis Ar2_def Out_def Ps_def Opp PO E E' B OB Ps PO E OB
                              diff_O_A diff_ar2 lep_neq__ltp ps_le) 
                        moreover have "Cong PO OB B' PO"
                          by (metis Cong_cases Midpoint_def Cong PO B' PO B Opp PO E E' B OB
                              cong_inner_transitivity opp_midpoint) 
                        ultimately show ?thesis
                          by (simp add: Length_def Ps_Col PO  E Ps PO E OB ltp_to_lep) 
                      qed
                      show "Prod PO E E' OA OA A2"
                        using Opp PO E E' A OA assms(2) opp_same_square by auto 
                      show "Prod PO E E' OB OB B2"
                        using Opp PO E E' B OB assms(3) opp_same_square by blast 
                      show "Prod PO E E' OC OC C2"
                        using Opp PO E E' C OC assms(4) opp_same_square by auto 
                    qed
                  }
                qed
              }
            qed
          }
        qed
      }
    qed
  }
  ultimately show ?thesis 
    by blast
qed

lemma PythRel_uniqueness:
  assumes "PythRel PO E E' A B C1"
    and "PythRel PO E E' A B C2"
    and "(Ps PO E C1  Ps PO E C2)  C1 = PO"
  shows "C1 = C2" 
proof -
  have "¬ Col PO E E'"
    using Ar2_def PythRel_def assms(1) by presburger 
  have "Col PO E A"
    using Ar2_def PythRel_def assms(1) by presburger 
  have "Col PO E B"
    using Ar2_def PythRel_def assms(1) by presburger 
  have "Col PO E C1"
    using Ps_Col assms(3) col_trivial_3 by blast 
  have "Col PO E C2"
    using Ar2_def PythRel_def assms(2) by presburger
  have "PO = B  
        (A = C1  Opp PO E E' A C1)  ( B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C1 A B')"
    using PythRel_def assms(1) by auto 
  moreover 
  have "PO = B  
        (A = C2  Opp PO E E' A C2)  ( B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C2 A B')"
    using PythRel_def assms(2) by presburger
  moreover
  {
    assume "PO = B" and  "A = C1  Opp PO E E' A C1" and "A = C2  Opp PO E E' A C2"
    moreover have "A = C1  A = C2  C1 = C2"
      by auto 
    moreover have "A = C1  Opp PO E E' A C2  C1 = C2"
      using ¬ Col PO E E' assms(3) neg_not_pos opp0_uniqueness pos_opp_neg by blast 
    moreover have "Opp PO E E' A C1  A = C2  C1 = C2"
      by (metis ¬ Col PO E E' assms(3) not_pos_and_neg opp0_uniqueness opp_comm opp_pos_neg) 
    moreover have "Opp PO E E' A C1  Opp PO E E' A C2  C1 = C2"
      using ¬ Col PO E E' opp_uniqueness by blast 
    ultimately have "C1 = C2" 
      by argo
  }
  moreover {
    assume "PO = B" and "A = C1  Opp PO E E' A C1" and 
      " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C2 A B'"
    moreover {
      assume "A = C1" and " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C2 A B'"
      then obtain B' where "PO B' Perp PO B" and "Cong PO B' PO B" and "Cong PO C2 A B'"
        by blast 
      hence "C1 = C2"
        using calculation(1) perp_distinct by blast
    }
    moreover {
      assume "Opp PO E E' A C1" and " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C2 A B'" 
      then obtain B' where "PO B' Perp PO B" and "Cong PO B' PO B" and "Cong PO C2 A B'"
        by blast 
      hence "C1 = C2"
        using calculation(1) perp_distinct by blast 
    }
    ultimately have "C1 = C2"
      by argo
  }
  moreover {
    assume " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C1 A B'" and "PO = B" and 
      "A = C2  Opp PO E E' A C2"
    then obtain B' where "PO B' Perp PO B" and "Cong PO B' PO B" and "Cong PO C1 A B'"
      by blast 
    hence "C1 = C2"
      using PO = B perp_not_eq_2 by blast 
  }
  moreover {
    assume " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C1 A B'" and 
      " B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C2 A B'"
    then obtain B1 where "PO B1 Perp PO B" and "Cong PO B1 PO B" and "Cong PO C1 A B1"
      by blast 
    obtain B2 where "PO B2 Perp PO B" and "Cong PO B2 PO B" and "Cong PO C2 A B2"
      using B'. PO B' Perp PO B  Cong PO B' PO B  Cong PO C2 A B' by blast
    have "Cong PO B1 PO B2"
      by (meson Cong PO B1 PO B Cong PO B2 PO B cong_4312 cong_inner_transitivity) 
    have "Col PO B1 B2"
      using PO B1 Perp PO B PO B2 Perp PO B perp2__col by auto 
    hence "B1 = B2  PO Midpoint B1 B2"
      using Cong PO B1 PO B2 col_permutation_4 l7_20_bis by blast
    moreover {
      assume "B1 = B2"
      hence "Cong PO C2 PO C1"
        using Cong_cases Cong PO C1 A B1 Cong PO C2 A B2 cong_inner_transitivity by blast 
      have "C1 = C2  PO Midpoint C1 C2"
        by (metis Mid_perm Col PO E C1 Col PO E C2 Cong PO C2 PO C1 ¬ Col PO E E' 
            bet_col between_trivial col_transitivity_1 l7_20 not_col_permutation_4)
      moreover {
        assume "PO Midpoint C1 C2"
        hence " Ps PO E C1  Ps PO E C2  C1 = C2"
          by (meson Bet_cases Midpoint_def Ps_def bet_out__bet not_bet_and_out) 
        moreover have "C1 = PO  C1 = C2"
          using Cong PO C2 PO C1 cong_diff by blast 
        ultimately have "C1 = C2"
          using assms(3) by blast 
      }
      ultimately have "C1 = C2" 
        by argo
    }
    moreover {
      assume "PO Midpoint B1 B2"
      have "C1 = C2" 
      proof (cases "A = PO") 
        {
          assume "A = PO"
          hence "Cong PO C1 PO C2"
            by (metis Cong_cases Cong PO B1 PO B2 Cong PO C1 A B1 Cong PO C2 A B2 
                cong_inner_transitivity)
          thus "C1 = C2"
            by (metis Bet_cases Ps_def assms(3) bet_out__bet between_cong_3 between_trivial l6_6
                point_construction_different) 
        }
        {
          assume "A  PO"
          hence "PO A Perp B1 PO" 
            using perp_col [of PO A B B1 PO] by (metis Perp_cases Col PO E A Col PO E B
                PO B1 Perp PO B ¬ Col PO E E' col_transitivity_1
                grid_not_par_4) 
          hence "Per A PO B1"
            using perp_per_1 by auto
          then obtain B2' where "PO Midpoint B1 B2'" and "Cong A B1 A B2'"
            using Per_def by blast 
          hence "B2 = B2'"
            using PO Midpoint B1 B2 symmetric_point_uniqueness by blast 
          hence "Cong PO C1 PO C2"
            by (metis Cong A B1 A B2' Cong PO C1 A B1 Cong PO C2 A B2
                cong_transitivity not_cong_3412) 
          have "PO Midpoint C1 C2  C1 = C2"
            by (metis Ps_def Cong PO C1 PO C2 assms(3) bet_cong_eq bet_out__bet between_trivial
                l6_6 midpoint_bet not_bet_and_out) 
          thus "C1 = C2"
            by (metis Col_def Col PO E C1 Col PO E C2 Cong PO C1 PO C2 ¬ Col PO E E'
                between_trivial col_transitivity_1 l7_20) 
        }
      qed
    }
    ultimately have "C1 = C2" 
      by argo
  }
  ultimately show ?thesis 
    by argo
qed

end
end