(* zero_le_one_elem — hol-light *)

let one_matrix = new_definition
  `one_matrix (decEq:M->M->bool) (oneA:A) (zeroA:A) =
     (\i j. if decEq i j then oneA else zeroA)`;;

let zero_matrix = new_definition
  `zero_matrix (zeroA:A) = (\i j. zeroA)`;;

let matrix_le = new_definition
  `matrix_le (le:A->A->bool) (A0:M->M->A) (B0:M->M->A) <=>
     !i j. le (A0 i j) (B0 i j)`;;

let matrix_eq = new_definition
  `matrix_eq (A0:M->M->A) (B0:M->M->A) <=> !i j. A0 i j = B0 i j`;;

let zero_le_one_elem = prove
  (`!decEq (zeroA:A) oneA (le:A->A->bool) i j.
      le zeroA oneA ==> le zeroA zeroA ==> le zeroA (one_matrix decEq oneA zeroA i j)`,
   REWRITE_TAC[one_matrix] THEN
   REPEAT GEN_TAC THEN STRIP_TAC THEN
   COND_CASES_TAC THEN ASM_REWRITE_TAC[]);;

let zero_le_one_matrix = prove
  (`!decEq (zeroA:A) oneA (le:A->A->bool).
      le zeroA oneA ==> le zeroA zeroA ==>
      matrix_le le (zero_matrix zeroA) (one_matrix decEq oneA zeroA)`,
   REWRITE_TAC[matrix_le; zero_matrix] THEN
   REPEAT GEN_TAC THEN STRIP_TAC THEN
   REPEAT GEN_TAC THEN
   ASM_MESON_TAC[zero_le_one_elem]);;

let matrix_le_refl = prove
  (`!le:A->A->bool. (!x. le x x) ==> !A0:M->M->A. matrix_le le A0 A0`,
   REWRITE_TAC[matrix_le] THEN
   REPEAT GEN_TAC THEN DISCH_TAC THEN
   REPEAT GEN_TAC THEN ASM_REWRITE_TAC[]);;

let matrix_le_trans = prove
  (`!le:A->A->bool.
      (!x y z. le x y ==> le y z ==> le x z) ==>
      !A0 B0 C0:M->M->A.
        matrix_le le A0 B0 ==> matrix_le le B0 C0 ==> matrix_le le A0 C0`,
   REWRITE_TAC[matrix_le] THEN MESON_TAC[]);;

let matrix_eq_refl = prove
  (`!A0:M->M->A. matrix_eq A0 A0`,
   REWRITE_TAC[matrix_eq] THEN REPEAT GEN_TAC THEN REFL_TAC);;

let matrix_eq_sym = prove
  (`!A0 B0:M->M->A. matrix_eq A0 B0 ==> matrix_eq B0 A0`,
   REWRITE_TAC[matrix_eq] THEN MESON_TAC[]);;

let matrix_eq_trans = prove
  (`!A0 B0 C0:M->M->A. matrix_eq A0 B0 ==> matrix_eq B0 C0 ==> matrix_eq A0 C0`,
   REWRITE_TAC[matrix_eq] THEN MESON_TAC[]);;

let matrix_eq_le = prove
  (`!le:A->A->bool.
      (!x. le x x) ==>
      !A0 B0:M->M->A. matrix_eq A0 B0 ==> matrix_le le A0 B0 /\ matrix_le le B0 A0`,
   REWRITE_TAC[matrix_eq; matrix_le] THEN
   REPEAT GEN_TAC THEN DISCH_TAC THEN
   REPEAT GEN_TAC THEN DISCH_TAC THEN
   CONJ_TAC THEN REPEAT GEN_TAC THEN
   ASM_MESON_TAC[]);;

let matrix_le_antisymm = prove
  (`!le:A->A->bool.
      (!x y. le x y ==> le y x ==> x = y) ==>
      !A0 B0:M->M->A.
        matrix_le le A0 B0 ==> matrix_le le B0 A0 ==> matrix_eq A0 B0`,
   REWRITE_TAC[matrix_le; matrix_eq] THEN MESON_TAC[]);;