theory Prelude_SortingPrograms__E3
imports "$HETS_ISABELLE_LIB/MainHC"
uses "$HETS_ISABELLE_LIB/prelude"
begin

setup "Header.initialize
       [\"ga_monotonicity\", \"ga_monotonicity_1\", \"ga_monotonicity_2\",
        \"ga_monotonicity_3\", \"ga_monotonicity_4\",
        \"ga_monotonicity_5\", \"ga_monotonicity_6\",
        \"ga_monotonicity_7\", \"ga_monotonicity_8\",
        \"ga_monotonicity_9\", \"ga_monotonicity_10\",
        \"ga_monotonicity_11\", \"ga_monotonicity_12\",
        \"ga_monotonicity_13\", \"ga_monotonicity_14\",
        \"ga_monotonicity_15\", \"ga_monotonicity_16\",
        \"ga_monotonicity_17\", \"ga_monotonicity_18\",
        \"ga_monotonicity_19\", \"ga_monotonicity_20\",
        \"ga_monotonicity_21\", \"ga_monotonicity_22\",
        \"ga_monotonicity_23\", \"ga_monotonicity_24\",
        \"ga_monotonicity_25\", \"ga_monotonicity_26\",
        \"ga_monotonicity_27\", \"ga_monotonicity_28\",
        \"ga_monotonicity_29\", \"ga_monotonicity_30\",
        \"ga_monotonicity_31\", \"ga_monotonicity_32\",
        \"ga_monotonicity_33\", \"ga_monotonicity_34\",
        \"ga_monotonicity_35\", \"ga_monotonicity_36\",
        \"ga_monotonicity_37\", \"ga_monotonicity_38\",
        \"ga_monotonicity_39\", \"ga_monotonicity_40\",
        \"ga_monotonicity_41\", \"ga_monotonicity_42\",
        \"ga_monotonicity_43\", \"ga_monotonicity_44\",
        \"ga_monotonicity_45\", \"ga_monotonicity_46\",
        \"ga_monotonicity_47\", \"ga_monotonicity_48\",
        \"ga_monotonicity_49\", \"ga_monotonicity_50\",
        \"ga_monotonicity_51\", \"ga_monotonicity_52\",
        \"ga_monotonicity_53\", \"ga_monotonicity_54\",
        \"ga_monotonicity_55\", \"ga_monotonicity_56\",
        \"ga_monotonicity_57\", \"ga_monotonicity_58\",
        \"ga_monotonicity_59\", \"ga_monotonicity_60\",
        \"ga_monotonicity_61\", \"ga_monotonicity_62\",
        \"ga_monotonicity_63\", \"ga_monotonicity_64\",
        \"ga_monotonicity_65\", \"ga_monotonicity_66\",
        \"ga_monotonicity_67\", \"ga_monotonicity_68\",
        \"ga_monotonicity_69\", \"ga_monotonicity_70\",
        \"ga_monotonicity_71\", \"ga_monotonicity_72\",
        \"ga_monotonicity_73\", \"ga_monotonicity_74\",
        \"ga_monotonicity_75\", \"ga_monotonicity_76\",
        \"ga_monotonicity_77\", \"ga_monotonicity_78\",
        \"ga_monotonicity_79\", \"ga_monotonicity_80\",
        \"ga_monotonicity_81\", \"ga_monotonicity_82\",
        \"ga_monotonicity_83\", \"ga_monotonicity_84\",
        \"ga_monotonicity_85\", \"ga_monotonicity_86\",
        \"ga_monotonicity_87\", \"ga_monotonicity_88\",
        \"ga_monotonicity_89\", \"ga_monotonicity_90\",
        \"ga_subt_reflexive\", \"ga_subt_transitive\",
        \"ga_subt_inj_proj\", \"ga_inj_transitive\",
        \"ga_subt_Int_XLt_Rat\", \"ga_subt_Nat_XLt_Int\",
        \"ga_subt_Pos_XLt_Nat\", \"GenSortT1\", \"GenSortT2\",
        \"GenSortF\", \"SplitInsertionSort\", \"JoinInsertionSort\",
        \"InsertionSort\", \"SplitQuickSort\", \"JoinQuickSort\",
        \"QuickSort\", \"SplitSelectionSort\", \"JoinSelectionSort\",
        \"SelectionSort\", \"SplitMergeSort\", \"MergeNil\",
        \"MergeConsNil\", \"MergeConsConsT\", \"MergeConsConsF\",
        \"JoinMergeSort\", \"MergeSort\", \"ElemNil\", \"ElemCons\",
        \"IsOrderedNil\", \"IsOrderedCons\", \"IsOrderedConsCons\",
        \"PermutationNil\", \"PermutationConsCons\", \"PermutationCons\",
        \"Theorem01\", \"Theorem02\", \"Theorem03\", \"Theorem04\",
        \"Theorem05\", \"Theorem06\", \"Theorem07\", \"Theorem08\",
        \"Theorem09\", \"Theorem10\", \"Theorem11\", \"Theorem12\",
        \"Theorem13\", \"Theorem14\"]"

typedecl Bool
typedecl ('a1) List
typedecl Ordering
typedecl Pos
typedecl Rat
typedecl Unit
typedecl X_Int
typedecl X_Nat

datatype ('a, 'b) Split = X_Split 'b "'a List List"

consts
EQ :: "Ordering"
GT :: "Ordering"
LT :: "Ordering"
X0X1 :: "X_Int" ("0''")
X0X2 :: "X_Nat" ("0''''")
X0X3 :: "Rat" ("0'_3")
X1X1 :: "X_Int" ("1''")
X1X2 :: "X_Nat" ("1''''")
X1X3 :: "Pos" ("1'_3")
X1X4 :: "Rat" ("1'_4")
X2X1 :: "X_Int" ("2''")
X2X2 :: "X_Nat" ("2''''")
X2X3 :: "Rat" ("2'_3")
X3X1 :: "X_Int" ("3''")
X3X2 :: "X_Nat" ("3''''")
X3X3 :: "Rat" ("3'_3")
X4X1 :: "X_Int" ("4''")
X4X2 :: "X_Nat" ("4''''")
X4X3 :: "Rat" ("4'_3")
X5X1 :: "X_Int" ("5''")
X5X2 :: "X_Nat" ("5''''")
X5X3 :: "Rat" ("5'_3")
X6X1 :: "X_Int" ("6''")
X6X2 :: "X_Nat" ("6''''")
X6X3 :: "Rat" ("6'_3")
X7X1 :: "X_Int" ("7''")
X7X2 :: "X_Nat" ("7''''")
X7X3 :: "Rat" ("7'_3")
X8X1 :: "X_Int" ("8''")
X8X2 :: "X_Nat" ("8''''")
X8X3 :: "Rat" ("8'_3")
X9X1 :: "X_Int" ("9''")
X9X2 :: "X_Nat" ("9''''")
X9X3 :: "Rat" ("9'_3")
XMinus__XX1 :: "X_Int => X_Int" ("(-''/ _)" [56] 56)
XMinus__XX2 :: "Rat => Rat" ("(-''''/ _)" [56] 56)
X_Cons :: "'a => 'a List => 'a List"
X_False :: "Bool" ("False''")
X_Nil :: "'a List" ("Nil''")
X_True :: "Bool" ("True''")
X__XAmpXAmp__X :: "Bool => Bool => Bool" ("(_/ &&/ _)" [54,54] 52)
X__XAtXAt__X :: "X_Nat => X_Nat => X_Nat" ("(_/ @@/ _)" [54,54] 52)
X__XCaret__XX1 :: "X_Int => X_Nat => X_Int" ("(_/ ^''/ _)" [54,54] 52)
X__XCaret__XX2 :: "X_Nat => X_Nat => X_Nat" ("(_/ ^''''/ _)" [54,54] 52)
X__XCaret__XX3 :: "Rat => X_Int => Rat partial" ("(_/ ^'_3/ _)" [54,54] 52)
X__XEqXEq__X :: "'a => 'a => Bool" ("(_/ ==''/ _)" [54,54] 52)
X__XExclam :: "X_Nat => X_Nat" ("(_/ !'')" [58] 58)
X__XGtXEq__XX1 :: "X_Int => X_Int => bool" ("(_/ >=''/ _)" [44,44] 42)
X__XGtXEq__XX2 :: "X_Nat => X_Nat => bool" ("(_/ >=''''/ _)" [44,44] 42)
X__XGtXEq__XX3 :: "Rat => Rat => bool" ("(_/ >='_3/ _)" [44,44] 42)
X__XGtXEq__XX4 :: "'a => 'a => Bool" ("(_/ >='_4/ _)" [54,54] 52)
X__XGt__XX1 :: "X_Int => X_Int => bool" ("(_/ >''/ _)" [44,44] 42)
X__XGt__XX2 :: "X_Nat => X_Nat => bool" ("(_/ >''''/ _)" [44,44] 42)
X__XGt__XX3 :: "Rat => Rat => bool" ("(_/ >'_3/ _)" [44,44] 42)
X__XGt__XX4 :: "'a => 'a => Bool" ("(_/ >'_4/ _)" [54,54] 52)
X__XLtXEq__XX1 :: "X_Int => X_Int => bool" ("(_/ <=''/ _)" [44,44] 42)
X__XLtXEq__XX2 :: "X_Nat => X_Nat => bool" ("(_/ <=''''/ _)" [44,44] 42)
X__XLtXEq__XX3 :: "Rat => Rat => bool" ("(_/ <='_3/ _)" [44,44] 42)
X__XLtXEq__XX4 :: "'a => 'a => Bool" ("(_/ <='_4/ _)" [54,54] 52)
X__XLt__XX1 :: "X_Int => X_Int => bool" ("(_/ <''/ _)" [44,44] 42)
X__XLt__XX2 :: "X_Nat => X_Nat => bool" ("(_/ <''''/ _)" [44,44] 42)
X__XLt__XX3 :: "Rat => Rat => bool" ("(_/ <'_3/ _)" [44,44] 42)
X__XLt__XX4 :: "'a => 'a => Bool" ("(_/ <'_4/ _)" [54,54] 52)
X__XMinusXExclam__X :: "X_Nat => X_Nat => X_Nat" ("(_/ -!/ _)" [54,54] 52)
X__XMinusXQuest__X :: "X_Nat => X_Nat => X_Nat partial" ("(_/ -?/ _)" [54,54] 52)
X__XMinus__XX1 :: "X_Int => X_Int => X_Int" ("(_/ -''/ _)" [54,54] 52)
X__XMinus__XX2 :: "X_Nat => X_Nat => X_Int" ("(_/ -''''/ _)" [54,54] 52)
X__XMinus__XX3 :: "Rat => Rat => Rat" ("(_/ -'_3/ _)" [54,54] 52)
X__XMinus__XX4 :: "'a => 'a => 'a" ("(_/ -'_4/ _)" [54,54] 52)
X__XPlusXPlus__X :: "'a List => 'a List => 'a List" ("(_/ ++''/ _)" [54,54] 52)
X__XPlus__XX1 :: "X_Int => X_Int => X_Int" ("(_/ +''/ _)" [54,54] 52)
X__XPlus__XX2 :: "X_Nat => X_Nat => X_Nat" ("(_/ +''''/ _)" [54,54] 52)
X__XPlus__XX3 :: "X_Nat => Pos => Pos" ("(_/ +'_3/ _)" [54,54] 52)
X__XPlus__XX4 :: "Pos => X_Nat => Pos" ("(_/ +'_4/ _)" [54,54] 52)
X__XPlus__XX5 :: "Rat => Rat => Rat" ("(_/ +'_5/ _)" [54,54] 52)
X__XPlus__XX6 :: "'a => 'a => 'a" ("(_/ +'_6/ _)" [54,54] 52)
X__XSlashXEq__X :: "'a => 'a => Bool" ("(_/ '/=/ _)" [54,54] 52)
X__XSlashXQuest__XX1 :: "X_Int => X_Int => X_Int partial" ("(_/ '/?''/ _)" [54,54] 52)
X__XSlashXQuest__XX2 :: "X_Nat => X_Nat => X_Nat partial" ("(_/ '/?''''/ _)" [54,54] 52)
X__XSlash__XX1 :: "X_Int => Pos => Rat" ("(_/ '/''/ _)" [54,54] 52)
X__XSlash__XX2 :: "Rat => Rat => Rat partial" ("(_/ '/''''/ _)" [54,54] 52)
X__XSlash__XX3 :: "'a => 'a => 'a" ("(_/ '/'_3/ _)" [54,54] 52)
X__XVBarXVBar__X :: "Bool => Bool => Bool" ("(_/ ||/ _)" [54,54] 52)
X__Xx__XX1 :: "X_Int => X_Int => X_Int" ("(_/ *''/ _)" [54,54] 52)
X__Xx__XX2 :: "X_Nat => X_Nat => X_Nat" ("(_/ *''''/ _)" [54,54] 52)
X__Xx__XX3 :: "Pos => Pos => Pos" ("(_/ *'_3/ _)" [54,54] 52)
X__Xx__XX4 :: "Rat => Rat => Rat" ("(_/ *'_4/ _)" [54,54] 52)
X__Xx__XX5 :: "'a => 'a => 'a" ("(_/ *'_5/ _)" [54,54] 52)
X__div__XX1 :: "X_Int => X_Int => X_Int partial" ("(_/ div''/ _)" [54,54] 52)
X__div__XX2 :: "X_Nat => X_Nat => X_Nat partial" ("(_/ div''''/ _)" [54,54] 52)
X__div__XX3 :: "'a => 'a => 'a" ("(_/ div'_3/ _)" [54,54] 52)
X__dvd__X :: "X_Nat => X_Nat => bool" ("(_/ dvd''/ _)" [44,44] 42)
X__elem__X :: "'a => 'a List => bool" ("(_/ elem/ _)" [44,44] 42)
X__mod__XX1 :: "X_Int => X_Int => X_Nat partial" ("(_/ mod''/ _)" [54,54] 52)
X__mod__XX2 :: "X_Nat => X_Nat => X_Nat partial" ("(_/ mod''''/ _)" [54,54] 52)
X__mod__XX3 :: "'a => 'a => 'a" ("(_/ mod'_3/ _)" [54,54] 52)
X__o__X :: "('b => 'c) * ('a => 'b) => 'a => 'c"
X__quot__XX1 :: "X_Int => X_Int => X_Int partial" ("(_/ quot''/ _)" [54,54] 52)
X__quot__XX2 :: "'a => 'a => 'a" ("(_/ quot''''/ _)" [54,54] 52)
X__rem__XX1 :: "X_Int => X_Int => X_Int partial" ("(_/ rem''/ _)" [54,54] 52)
X__rem__XX2 :: "'a => 'a => 'a" ("(_/ rem''''/ _)" [54,54] 52)
X_absX1 :: "X_Int => X_Nat" ("abs''/'(_')" [3] 999)
X_absX2 :: "Rat => Rat" ("abs''''/'(_')" [3] 999)
X_absX3 :: "'a => 'a" ("abs'_3/'(_')" [3] 999)
X_all :: "('a => Bool) => 'a List => Bool"
X_andL :: "Bool List => Bool" ("andL/'(_')" [3] 999)
X_any :: "('a => Bool) => 'a List => Bool"
X_concat :: "'a List List => 'a List" ("concat''/'(_')" [3] 999)
X_curry :: "('a * 'b => 'c) => 'a => 'b => 'c"
X_drop :: "X_Int => 'a List => 'a List"
X_dropWhile :: "('a => Bool) => 'a List => 'a List"
X_evenX1 :: "X_Int => bool" ("even''/'(_')" [3] 999)
X_evenX2 :: "X_Nat => bool" ("even''''/'(_')" [3] 999)
X_filter :: "('a => Bool) => 'a List => 'a List"
X_flip :: "('a => 'b => 'c) => 'b => 'a => 'c"
X_foldl :: "('a => 'b => 'a) => 'a => 'b List => 'a partial"
X_foldr :: "('a => 'b => 'b) => 'b => 'a List => 'b partial"
X_fromInteger :: "X_Int => 'a" ("fromInteger/'(_')" [3] 999)
X_fst :: "'a => 'b => 'a" ("fst''/'(_,/ _')" [3,3] 999)
X_gn_inj :: "'a => 'b" ("gn'_inj/'(_')" [3] 999)
X_gn_proj :: "'a => 'b partial" ("gn'_proj/'(_')" [3] 999)
X_gn_subt :: "'a => 'b => bool" ("gn'_subt/'(_,/ _')" [3,3] 999)
X_head :: "'a List => 'a partial" ("head/'(_')" [3] 999)
X_id :: "'a => 'a" ("id''/'(_')" [3] 999)
X_init :: "'a List => 'a List partial" ("init/'(_')" [3] 999)
X_insert :: "'d => 'd List => 'd List"
X_insertionSort :: "'a List => 'a List" ("insertionSort/'(_')" [3] 999)
X_isOrdered :: "'a List => bool" ("isOrdered/'(_')" [3] 999)
X_joinInsertionSort :: "('a, 'a) Split => 'a List" ("joinInsertionSort/'(_')" [3] 999)
X_joinMergeSort :: "('a, unit) Split => 'a List" ("joinMergeSort/'(_')" [3] 999)
X_joinQuickSort :: "('b, 'b) Split => 'b List" ("joinQuickSort/'(_')" [3] 999)
X_joinSelectionSort :: "('b, 'b) Split => 'b List" ("joinSelectionSort/'(_')" [3] 999)
X_last :: "'a List => 'a partial" ("last''/'(_')" [3] 999)
X_length :: "'a List => X_Int" ("length''/'(_')" [3] 999)
X_map :: "('a => 'b) => 'a List => 'b List"
X_maxX1 :: "X_Int => X_Int => X_Int" ("max''/'(_,/ _')" [3,3] 999)
X_maxX2 :: "X_Nat => X_Nat => X_Nat" ("max''''/'(_,/ _')" [3,3] 999)
X_maxX3 :: "Rat => Rat => Rat" ("max'_3/'(_,/ _')" [3,3] 999)
X_maxX4 :: "'a => 'a => 'a"
X_maximum :: "'d List => 'd partial" ("maximum/'(_')" [3] 999)
X_mergeSort :: "'a List => 'a List" ("mergeSort/'(_')" [3] 999)
X_minX1 :: "X_Int => X_Int => X_Int" ("min''/'(_,/ _')" [3,3] 999)
X_minX2 :: "X_Nat => X_Nat => X_Nat" ("min''''/'(_,/ _')" [3,3] 999)
X_minX3 :: "Rat => Rat => Rat" ("min'_3/'(_,/ _')" [3,3] 999)
X_minX4 :: "'a => 'a => 'a"
X_minimum :: "'d List => 'd partial" ("minimum/'(_')" [3] 999)
X_negate :: "'a => 'a" ("negate/'(_')" [3] 999)
X_null :: "'a List => Bool" ("null''/'(_')" [3] 999)
X_oddX1 :: "X_Int => bool" ("odd''/'(_')" [3] 999)
X_oddX2 :: "X_Nat => bool" ("odd''''/'(_')" [3] 999)
X_orL :: "Bool List => Bool" ("orL/'(_')" [3] 999)
X_permutation :: "'a List => 'a List => bool" ("permutation/'(_,/ _')" [3,3] 999)
X_pre :: "X_Nat => X_Nat partial" ("pre/'(_')" [3] 999)
X_product :: "'c List => 'c" ("product/'(_')" [3] 999)
X_quickSort :: "'a List => 'a List" ("quickSort/'(_')" [3] 999)
X_recip :: "'a => 'a" ("recip/'(_')" [3] 999)
X_reverse :: "'a List => 'a List" ("reverse/'(_')" [3] 999)
X_selectionSort :: "'a List => 'a List" ("selectionSort/'(_')" [3] 999)
X_sign :: "X_Int => X_Int" ("sign/'(_')" [3] 999)
X_signum :: "'a => 'a" ("signum/'(_')" [3] 999)
X_snd :: "'a => 'b => 'b" ("snd''/'(_,/ _')" [3,3] 999)
X_splitInsertionSort :: "'b List => ('b, 'b) Split" ("splitInsertionSort/'(_')" [3] 999)
X_splitMergeSort :: "'b List => ('b, unit) Split" ("splitMergeSort/'(_')" [3] 999)
X_splitQuickSort :: "'a List => ('a, 'a) Split" ("splitQuickSort/'(_')" [3] 999)
X_splitSelectionSort :: "'a List => ('a, 'a) Split" ("splitSelectionSort/'(_')" [3] 999)
X_sum :: "'c List => 'c" ("sum/'(_')" [3] 999)
X_tail :: "'a List => 'a List partial" ("tail/'(_')" [3] 999)
X_take :: "X_Int => 'a List => 'a List"
X_takeWhile :: "('a => Bool) => 'a List => 'a List"
X_toInteger :: "'a => X_Int" ("toInteger/'(_')" [3] 999)
X_unzip :: "('a * 'b) List => 'a List * 'b List" ("unzip/'(_')" [3] 999)
X_zip :: "'a List => 'b List => ('a * 'b) List"
break :: "('a => Bool) => 'a List => 'a List * 'a List"
compare :: "'a => 'a => Ordering"
concatMap :: "('a => 'b List) => 'a List => 'b List"
delete :: "'e => 'e List => 'e List"
divMod :: "'a => 'a => 'a * 'a"
foldl1 :: "('a => 'a => 'a) => 'a List => 'a partial"
foldr1 :: "('a => 'a => 'a) => 'a List => 'a partial"
genSort :: "('a List => ('a, 'b) Split) => (('a, 'b) Split => 'a List) => 'a List => 'a List"
merge :: "'a List => 'a List => 'a List"
notH__X :: "Bool => Bool" ("(notH/ _)" [56] 56)
otherwiseH :: "Bool"
partition :: "('a => Bool) => 'a List => 'a List * 'a List"
quotRem :: "'a => 'a => 'a * 'a"
scanl :: "('a => 'b => 'a) => 'a => 'b List => 'a List"
scanl1 :: "('a => 'a => 'a) => 'a List => 'a List"
scanr :: "('a => 'b => 'b) => 'b => 'a List => 'b List"
scanr1 :: "('a => 'a => 'a) => 'a List => 'a List"
select :: "('a => Bool) => 'a => 'a List * 'a List => 'a List * 'a List"
span :: "('a => Bool) => 'a List => 'a List * 'a List"
splitAt :: "X_Int => 'a List => 'a List * 'a List"
sucX1 :: "X_Nat => X_Nat" ("suc''/'(_')" [3] 999)
sucX2 :: "X_Nat => Pos" ("suc''''/'(_')" [3] 999)
uncurry :: "('a => 'b => 'c) => 'a * 'b => 'c"

axioms
ga_monotonicity [rule_format] :
"(X_gn_inj :: (X_Int => X_Int) => X_Int => Rat) XMinus__XX1 =
 (X_gn_inj :: (Rat => Rat) => X_Int => Rat) XMinus__XX2"

ga_monotonicity_1 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 0' =
 (X_gn_inj :: X_Nat => X_Int) 0''"

ga_monotonicity_2 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 0' = (X_gn_inj :: Rat => Rat) 0_3"

ga_monotonicity_3 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 0'' = (X_gn_inj :: Rat => Rat) 0_3"

ga_monotonicity_4 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 1' =
 (X_gn_inj :: X_Nat => X_Int) 1''"

ga_monotonicity_5 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 1' = (X_gn_inj :: Pos => X_Int) 1_3"

ga_monotonicity_6 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 1' = (X_gn_inj :: Rat => Rat) 1_4"

ga_monotonicity_7 [rule_format] :
"(X_gn_inj :: X_Nat => X_Nat) 1'' = (X_gn_inj :: Pos => X_Nat) 1_3"

ga_monotonicity_8 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 1'' = (X_gn_inj :: Rat => Rat) 1_4"

ga_monotonicity_9 [rule_format] :
"(X_gn_inj :: Pos => Rat) 1_3 = (X_gn_inj :: Rat => Rat) 1_4"

ga_monotonicity_10 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 2' =
 (X_gn_inj :: X_Nat => X_Int) 2''"

ga_monotonicity_11 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 2' = (X_gn_inj :: Rat => Rat) 2_3"

ga_monotonicity_12 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 2'' = (X_gn_inj :: Rat => Rat) 2_3"

ga_monotonicity_13 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 3' =
 (X_gn_inj :: X_Nat => X_Int) 3''"

ga_monotonicity_14 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 3' = (X_gn_inj :: Rat => Rat) 3_3"

ga_monotonicity_15 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 3'' = (X_gn_inj :: Rat => Rat) 3_3"

ga_monotonicity_16 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 4' =
 (X_gn_inj :: X_Nat => X_Int) 4''"

ga_monotonicity_17 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 4' = (X_gn_inj :: Rat => Rat) 4_3"

ga_monotonicity_18 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 4'' = (X_gn_inj :: Rat => Rat) 4_3"

ga_monotonicity_19 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 5' =
 (X_gn_inj :: X_Nat => X_Int) 5''"

ga_monotonicity_20 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 5' = (X_gn_inj :: Rat => Rat) 5_3"

ga_monotonicity_21 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 5'' = (X_gn_inj :: Rat => Rat) 5_3"

ga_monotonicity_22 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 6' =
 (X_gn_inj :: X_Nat => X_Int) 6''"

ga_monotonicity_23 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 6' = (X_gn_inj :: Rat => Rat) 6_3"

ga_monotonicity_24 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 6'' = (X_gn_inj :: Rat => Rat) 6_3"

ga_monotonicity_25 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 7' =
 (X_gn_inj :: X_Nat => X_Int) 7''"

ga_monotonicity_26 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 7' = (X_gn_inj :: Rat => Rat) 7_3"

ga_monotonicity_27 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 7'' = (X_gn_inj :: Rat => Rat) 7_3"

ga_monotonicity_28 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 8' =
 (X_gn_inj :: X_Nat => X_Int) 8''"

ga_monotonicity_29 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 8' = (X_gn_inj :: Rat => Rat) 8_3"

ga_monotonicity_30 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 8'' = (X_gn_inj :: Rat => Rat) 8_3"

ga_monotonicity_31 [rule_format] :
"(X_gn_inj :: X_Int => X_Int) 9' =
 (X_gn_inj :: X_Nat => X_Int) 9''"

ga_monotonicity_32 [rule_format] :
"(X_gn_inj :: X_Int => Rat) 9' = (X_gn_inj :: Rat => Rat) 9_3"

ga_monotonicity_33 [rule_format] :
"(X_gn_inj :: X_Nat => Rat) 9'' = (X_gn_inj :: Rat => Rat) 9_3"

ga_monotonicity_34 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__Xx__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__Xx__XX2)"

ga_monotonicity_35 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => Pos * Pos => X_Int)
 (uncurryOp X__Xx__XX1) =
 (X_gn_inj :: (Pos * Pos => Pos) => Pos * Pos => X_Int)
 (uncurryOp X__Xx__XX3)"

ga_monotonicity_36 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => Rat)
 (uncurryOp X__Xx__XX1) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Int * X_Int => Rat)
 (uncurryOp X__Xx__XX4)"

ga_monotonicity_37 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => X_Int)
 (uncurryOp X__Xx__XX1) =
 (X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => X_Int)
 (uncurryOp X__Xx__XX5)"

ga_monotonicity_38 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => Pos * Pos => X_Nat)
 (uncurryOp X__Xx__XX2) =
 (X_gn_inj :: (Pos * Pos => Pos) => Pos * Pos => X_Nat)
 (uncurryOp X__Xx__XX3)"

ga_monotonicity_39 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => Rat)
 (uncurryOp X__Xx__XX2) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Nat * X_Nat => Rat)
 (uncurryOp X__Xx__XX4)"

ga_monotonicity_40 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Nat)
 (uncurryOp X__Xx__XX2) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Nat)
 (uncurryOp X__Xx__XX5)"

ga_monotonicity_41 [rule_format] :
"(X_gn_inj :: (Pos * Pos => Pos) => Pos * Pos => Rat)
 (uncurryOp X__Xx__XX3) =
 (X_gn_inj :: (Rat * Rat => Rat) => Pos * Pos => Rat)
 (uncurryOp X__Xx__XX4)"

ga_monotonicity_42 [rule_format] :
"(X_gn_inj :: (Pos * Pos => Pos) => Pos * Pos => Pos)
 (uncurryOp X__Xx__XX3) =
 (X_gn_inj :: (Pos * Pos => Pos) => Pos * Pos => Pos)
 (uncurryOp X__Xx__XX5)"

ga_monotonicity_43 [rule_format] :
"(X_gn_inj :: (Rat * Rat => Rat) => Rat * Rat => Rat)
 (uncurryOp X__Xx__XX4) =
 (X_gn_inj :: (Rat * Rat => Rat) => Rat * Rat => Rat)
 (uncurryOp X__Xx__XX5)"

ga_monotonicity_44 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XPlus__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XPlus__XX2)"

ga_monotonicity_45 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * Pos => X_Int)
 (uncurryOp X__XPlus__XX1) =
 (X_gn_inj :: (X_Nat * Pos => Pos) => X_Nat * Pos => X_Int)
 (uncurryOp X__XPlus__XX3)"

ga_monotonicity_46 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => Pos * X_Nat => X_Int)
 (uncurryOp X__XPlus__XX1) =
 (X_gn_inj :: (Pos * X_Nat => Pos) => Pos * X_Nat => X_Int)
 (uncurryOp X__XPlus__XX4)"

ga_monotonicity_47 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => Rat)
 (uncurryOp X__XPlus__XX1) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Int * X_Int => Rat)
 (uncurryOp X__XPlus__XX5)"

ga_monotonicity_48 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => X_Int)
 (uncurryOp X__XPlus__XX1) =
 (X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => X_Int)
 (uncurryOp X__XPlus__XX6)"

ga_monotonicity_49 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * Pos => X_Nat)
 (uncurryOp X__XPlus__XX2) =
 (X_gn_inj :: (X_Nat * Pos => Pos) => X_Nat * Pos => X_Nat)
 (uncurryOp X__XPlus__XX3)"

ga_monotonicity_50 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => Pos * X_Nat => X_Nat)
 (uncurryOp X__XPlus__XX2) =
 (X_gn_inj :: (Pos * X_Nat => Pos) => Pos * X_Nat => X_Nat)
 (uncurryOp X__XPlus__XX4)"

ga_monotonicity_51 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => Rat)
 (uncurryOp X__XPlus__XX2) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Nat * X_Nat => Rat)
 (uncurryOp X__XPlus__XX5)"

ga_monotonicity_52 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Nat)
 (uncurryOp X__XPlus__XX2) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Nat)
 (uncurryOp X__XPlus__XX6)"

ga_monotonicity_53 [rule_format] :
"(X_gn_inj :: (X_Nat * Pos => Pos) => Pos * Pos => Pos)
 (uncurryOp X__XPlus__XX3) =
 (X_gn_inj :: (Pos * X_Nat => Pos) => Pos * Pos => Pos)
 (uncurryOp X__XPlus__XX4)"

ga_monotonicity_54 [rule_format] :
"(X_gn_inj :: (X_Nat * Pos => Pos) => X_Nat * Pos => Rat)
 (uncurryOp X__XPlus__XX3) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Nat * Pos => Rat)
 (uncurryOp X__XPlus__XX5)"

ga_monotonicity_55 [rule_format] :
"(X_gn_inj :: (Pos * X_Nat => Pos) => Pos * X_Nat => Rat)
 (uncurryOp X__XPlus__XX4) =
 (X_gn_inj :: (Rat * Rat => Rat) => Pos * X_Nat => Rat)
 (uncurryOp X__XPlus__XX5)"

ga_monotonicity_56 [rule_format] :
"(X_gn_inj :: (Rat * Rat => Rat) => Rat * Rat => Rat)
 (uncurryOp X__XPlus__XX5) =
 (X_gn_inj :: (Rat * Rat => Rat) => Rat * Rat => Rat)
 (uncurryOp X__XPlus__XX6)"

ga_monotonicity_57 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XMinus__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XMinus__XX2)"

ga_monotonicity_58 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => Rat)
 (uncurryOp X__XMinus__XX1) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Int * X_Int => Rat)
 (uncurryOp X__XMinus__XX3)"

ga_monotonicity_59 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => X_Int)
 (uncurryOp X__XMinus__XX1) =
 (X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => X_Int)
 (uncurryOp X__XMinus__XX4)"

ga_monotonicity_60 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Int) => X_Nat * X_Nat => Rat)
 (uncurryOp X__XMinus__XX2) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Nat * X_Nat => Rat)
 (uncurryOp X__XMinus__XX3)"

ga_monotonicity_61 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XMinus__XX2) =
 (X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XMinus__XX4)"

ga_monotonicity_62 [rule_format] :
"(X_gn_inj :: (Rat * Rat => Rat) => Rat * Rat => Rat)
 (uncurryOp X__XMinus__XX3) =
 (X_gn_inj :: (Rat * Rat => Rat) => Rat * Rat => Rat)
 (uncurryOp X__XMinus__XX4)"

ga_monotonicity_63 [rule_format] :
"(X_gn_inj :: (X_Int * Pos => Rat) => X_Int * Pos => Rat)
 (uncurryOp X__XSlash__XX1) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Int * Pos => Rat)
 (uncurryOp X__XSlash__XX3)"

ga_monotonicity_64 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int partial) => X_Nat * X_Nat => X_Int partial)
 (uncurryOp X__XSlashXQuest__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat partial) => X_Nat * X_Nat => X_Int partial)
 (uncurryOp X__XSlashXQuest__XX2)"

ga_monotonicity_65 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLt__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLt__XX2)"

ga_monotonicity_66 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XLt__XX1) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XLt__XX3)"

ga_monotonicity_67 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLt__XX2) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLt__XX3)"

ga_monotonicity_68 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLtXEq__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLtXEq__XX2)"

ga_monotonicity_69 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XLtXEq__XX1) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XLtXEq__XX3)"

ga_monotonicity_70 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLtXEq__XX2) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XLtXEq__XX3)"

ga_monotonicity_71 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGt__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGt__XX2)"

ga_monotonicity_72 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XGt__XX1) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XGt__XX3)"

ga_monotonicity_73 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGt__XX2) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGt__XX3)"

ga_monotonicity_74 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGtXEq__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGtXEq__XX2)"

ga_monotonicity_75 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XGtXEq__XX1) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Int * X_Int => bool)
 (uncurryOp X__XGtXEq__XX3)"

ga_monotonicity_76 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGtXEq__XX2) =
 (X_gn_inj :: (Rat * Rat => bool) => X_Nat * X_Nat => bool)
 (uncurryOp X__XGtXEq__XX3)"

ga_monotonicity_77 [rule_format] :
"(X_gn_inj :: (X_Int * X_Nat => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XCaret__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Int)
 (uncurryOp X__XCaret__XX2)"

ga_monotonicity_78 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int partial) => X_Nat * X_Nat => X_Int partial)
 (uncurryOp X__div__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat partial) => X_Nat * X_Nat => X_Int partial)
 (uncurryOp X__div__XX2)"

ga_monotonicity_79 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Nat partial) => X_Nat * X_Nat => X_Nat partial)
 (uncurryOp X__mod__XX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat partial) => X_Nat * X_Nat => X_Nat partial)
 (uncurryOp X__mod__XX2)"

ga_monotonicity_80 [rule_format] :
"(X_gn_inj :: (X_Int => X_Nat) => X_Int => Rat) X_absX1 =
 (X_gn_inj :: (Rat => Rat) => X_Int => Rat) X_absX2"

ga_monotonicity_81 [rule_format] :
"(X_gn_inj :: (Rat => Rat) => Rat => Rat) X_absX2 =
 (X_gn_inj :: (Rat => Rat) => Rat => Rat) X_absX3"

ga_monotonicity_82 [rule_format] :
"(X_gn_inj :: (X_Int => bool) => X_Nat => bool) X_evenX1 =
 (X_gn_inj :: (X_Nat => bool) => X_Nat => bool) X_evenX2"

ga_monotonicity_83 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X_maxX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Int)
 (uncurryOp X_maxX2)"

ga_monotonicity_84 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => Rat)
 (uncurryOp X_maxX1) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Int * X_Int => Rat)
 (uncurryOp X_maxX3)"

ga_monotonicity_85 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => Rat)
 (uncurryOp X_maxX2) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Nat * X_Nat => Rat)
 (uncurryOp X_maxX3)"

ga_monotonicity_86 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Nat * X_Nat => X_Int)
 (uncurryOp X_minX1) =
 (X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => X_Int)
 (uncurryOp X_minX2)"

ga_monotonicity_87 [rule_format] :
"(X_gn_inj :: (X_Int * X_Int => X_Int) => X_Int * X_Int => Rat)
 (uncurryOp X_minX1) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Int * X_Int => Rat)
 (uncurryOp X_minX3)"

ga_monotonicity_88 [rule_format] :
"(X_gn_inj :: (X_Nat * X_Nat => X_Nat) => X_Nat * X_Nat => Rat)
 (uncurryOp X_minX2) =
 (X_gn_inj :: (Rat * Rat => Rat) => X_Nat * X_Nat => Rat)
 (uncurryOp X_minX3)"

ga_monotonicity_89 [rule_format] :
"(X_gn_inj :: (X_Int => bool) => X_Nat => bool) X_oddX1 =
 (X_gn_inj :: (X_Nat => bool) => X_Nat => bool) X_oddX2"

ga_monotonicity_90 [rule_format] :
"(X_gn_inj :: (X_Nat => X_Nat) => X_Nat => X_Nat) sucX1 =
 (X_gn_inj :: (X_Nat => Pos) => X_Nat => X_Nat) sucX2"

ga_subt_reflexive [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). gn_subt(x, y)"

ga_subt_transitive [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'b).
 ALL (z :: 'c). gn_subt(x, y) & gn_subt(y, z) --> gn_subt(x, z)"

ga_subt_inj_proj [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'b).
 gn_subt(x, y) -->
 y = (X_gn_inj :: 'a => 'b) x =
 (makePartial x = (X_gn_proj :: 'b => 'a partial) y)"

ga_inj_transitive [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'b).
 ALL (z :: 'c).
 gn_subt(x, y) & gn_subt(y, z) & y = (X_gn_inj :: 'a => 'b) x -->
 z = (X_gn_inj :: 'a => 'c) x = (z = (X_gn_inj :: 'b => 'c) y)"

ga_subt_Int_XLt_Rat [rule_format] :
"ALL (x :: X_Int). ALL (y :: Rat). gn_subt(x, y)"

ga_subt_Nat_XLt_Int [rule_format] :
"ALL (x :: X_Nat). ALL (y :: X_Int). gn_subt(x, y)"

ga_subt_Pos_XLt_Nat [rule_format] :
"ALL (x :: Pos). ALL (y :: X_Nat). gn_subt(x, y)"

GenSortT1 [rule_format] :
"ALL (join :: ('a, 'b) Split => 'a List).
 ALL (r :: 'b).
 ALL (X_split :: 'a List => ('a, 'b) Split).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 ALL (xxs :: 'a List List).
 ALL (y :: 'a).
 ALL (ys :: 'a List).
 xs = X_Cons x (X_Cons y ys) & X_split xs = X_Split r xxs -->
 genSort X_split join xs =
 join (X_Split r (X_map (genSort X_split join) xxs))"

GenSortT2 [rule_format] :
"ALL (join :: ('a, 'b) Split => 'a List).
 ALL (r :: 'b).
 ALL (X_split :: 'a List => ('a, 'b) Split).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 ALL (xxs :: 'a List List).
 ALL (y :: 'a).
 xs = X_Cons x (X_Cons y Nil') & X_split xs = X_Split r xxs -->
 genSort X_split join xs =
 join (X_Split r (X_map (genSort X_split join) xxs))"

GenSortF [rule_format] :
"ALL (join :: ('a, 'b) Split => 'a List).
 ALL (X_split :: 'a List => ('a, 'b) Split).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 xs = X_Cons x Nil' | xs = Nil' --> genSort X_split join xs = xs"

SplitInsertionSort [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 splitInsertionSort(X_Cons x xs) = X_Split x (X_Cons xs Nil')"

JoinInsertionSort [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 joinInsertionSort(X_Split x (X_Cons xs Nil')) = X_insert x xs"

InsertionSort [rule_format] :
"ALL (xs :: 'a List).
 insertionSort(xs) =
 genSort X_splitInsertionSort X_joinInsertionSort xs"

SplitQuickSort [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 splitQuickSort(X_Cons x xs) =
 (let (ys, zs) = partition (% t. x <_4 t) xs
  in X_Split x (X_Cons ys (X_Cons zs Nil')))"

JoinQuickSort [rule_format] :
"ALL (x :: 'a).
 ALL (ys :: 'a List).
 ALL (zs :: 'a List).
 joinQuickSort(X_Split x (X_Cons ys (X_Cons zs Nil'))) =
 ys ++' X_Cons x zs"

QuickSort [rule_format] :
"ALL (xs :: 'a List).
 quickSort(xs) = genSort X_splitQuickSort X_joinQuickSort xs"

SplitSelectionSort [rule_format] :
"ALL (xs :: 'a List).
 makePartial (splitSelectionSort(xs)) =
 restrictOp
 (makePartial
  (let x = minimum(xs)
   in X_Split (makeTotal x) (X_Cons (delete (makeTotal x) xs) Nil')))
 (defOp x)"

JoinSelectionSort [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 joinSelectionSort(X_Split x (X_Cons xs Nil')) = X_Cons x xs"

SelectionSort [rule_format] :
"ALL (xs :: 'a List).
 selectionSort(xs) =
 genSort X_splitSelectionSort X_joinSelectionSort xs"

SplitMergeSort [rule_format] :
"ALL (X_n :: X_Nat).
 ALL (xs :: 'a List).
 defOp (length'(xs) div' (X_gn_inj :: X_Nat => X_Int) 2'') &
 makePartial ((X_gn_inj :: X_Nat => X_Int) X_n) =
 length'(xs) div' (X_gn_inj :: X_Nat => X_Int) 2'' -->
 splitMergeSort(xs) =
 (let (ys, zs) = splitAt ((X_gn_inj :: X_Nat => X_Int) X_n) xs
  in X_Split () (X_Cons ys (X_Cons zs Nil')))"

MergeNil [rule_format] :
"ALL (xs :: 'a List).
 ALL (ys :: 'a List). xs = Nil' --> merge xs ys = ys"

MergeConsNil [rule_format] :
"ALL (v :: 'a).
 ALL (vs :: 'a List).
 ALL (xs :: 'a List).
 ALL (ys :: 'a List).
 xs = X_Cons v vs & ys = Nil' --> merge xs ys = xs"

MergeConsConsT [rule_format] :
"ALL (v :: 'a).
 ALL (vs :: 'a List).
 ALL (w :: 'a).
 ALL (ws :: 'a List).
 ALL (xs :: 'a List).
 ALL (ys :: 'a List).
 (xs = X_Cons v vs & ys = X_Cons w ws) & v <_4 w = True' -->
 merge xs ys = X_Cons v (merge vs ys)"

MergeConsConsF [rule_format] :
"ALL (v :: 'a).
 ALL (vs :: 'a List).
 ALL (w :: 'a).
 ALL (ws :: 'a List).
 ALL (xs :: 'a List).
 ALL (ys :: 'a List).
 (xs = X_Cons v vs & ys = X_Cons w ws) & v <_4 w = False' -->
 merge xs ys = X_Cons w (merge xs ws)"

JoinMergeSort [rule_format] :
"ALL (ys :: 'a List).
 ALL (zs :: 'a List).
 joinMergeSort(X_Split () (X_Cons ys (X_Cons zs Nil'))) =
 merge ys zs"

MergeSort [rule_format] :
"ALL (xs :: 'a List).
 mergeSort(xs) = genSort X_splitMergeSort X_joinMergeSort xs"

ElemNil [rule_format] : "ALL (x :: 'a). ~ x elem Nil'"

ElemCons [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (ys :: 'a List). (x elem X_Cons y ys) = (x = y | x elem ys)"

IsOrderedNil [rule_format] : "isOrdered(Nil')"

IsOrderedCons [rule_format] :
"ALL (x :: 'a). isOrdered(X_Cons x Nil')"

IsOrderedConsCons [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (ys :: 'a List).
 isOrdered(X_Cons x (X_Cons y ys)) =
 (x <=_4 y = True' & isOrdered(X_Cons y ys))"

PermutationNil [rule_format] : "permutation(Nil', Nil')"

PermutationConsCons [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 ALL (y :: 'a).
 ALL (ys :: 'a List).
 permutation(X_Cons x xs, X_Cons y ys) =
 (x = y & permutation(xs, ys) |
  x elem ys & permutation(xs, X_Cons y (delete x ys)))"

declare ga_subt_reflexive [simp]
declare ga_subt_Int_XLt_Rat [simp]
declare ga_subt_Nat_XLt_Int [simp]
declare ga_subt_Pos_XLt_Nat [simp]
declare JoinInsertionSort [simp]
declare JoinQuickSort [simp]
declare JoinSelectionSort [simp]
declare JoinMergeSort [simp]
declare ElemNil [simp]
declare IsOrderedNil [simp]
declare IsOrderedCons [simp]
declare PermutationNil [simp]

theorem PermutationCons :
"ALL (x :: 'a).
 ALL (y :: 'a). permutation(X_Cons x Nil', X_Cons y Nil') = (x = y)"
apply(auto)
apply(simp add: PermutationConsCons)+
done

setup "Header.record \"PermutationCons\""

theorem Theorem01 :
"ALL (xs :: 'a List). insertionSort(xs) = quickSort(xs)"
apply(auto)
oops

setup "Header.record \"Theorem01\""

theorem Theorem02 :
"ALL (xs :: 'a List). insertionSort(xs) = mergeSort(xs)"
oops

setup "Header.record \"Theorem02\""

theorem Theorem03 :
"ALL (xs :: 'a List). insertionSort(xs) = selectionSort(xs)"
oops

setup "Header.record \"Theorem03\""

theorem Theorem04 :
"ALL (xs :: 'a List). quickSort(xs) = mergeSort(xs)"
oops

setup "Header.record \"Theorem04\""

theorem Theorem05 :
"ALL (xs :: 'a List). quickSort(xs) = selectionSort(xs)"
oops

setup "Header.record \"Theorem05\""

theorem Theorem06 :
"ALL (xs :: 'a List). mergeSort(xs) = selectionSort(xs)"
oops

setup "Header.record \"Theorem06\""

theorem Theorem07 :
"ALL (xs :: 'a List). isOrdered(insertionSort(xs))"
oops

setup "Header.record \"Theorem07\""

theorem Theorem08 : "ALL (xs :: 'a List). isOrdered(quickSort(xs))"
oops

setup "Header.record \"Theorem08\""

theorem Theorem09 : "ALL (xs :: 'a List). isOrdered(mergeSort(xs))"
oops

setup "Header.record \"Theorem09\""

theorem Theorem10 :
"ALL (xs :: 'a List). isOrdered(selectionSort(xs))"
oops

setup "Header.record \"Theorem10\""

theorem Theorem11 :
"ALL (xs :: 'a List). permutation(xs, insertionSort(xs))"
oops

setup "Header.record \"Theorem11\""

theorem Theorem12 :
"ALL (xs :: 'a List). permutation(xs, quickSort(xs))"
oops

setup "Header.record \"Theorem12\""

theorem Theorem13 :
"ALL (xs :: 'a List). permutation(xs, mergeSort(xs))"
oops

setup "Header.record \"Theorem13\""

theorem Theorem14 :
"ALL (xs :: 'a List). permutation(xs, selectionSort(xs))"
oops

setup "Header.record \"Theorem14\""

end


(* Author: Alexander Maletzky *)

section \<open>Sample Computations of Reduced Gr\"obner Bases\<close>

theory Reduced_GB_Examples
  imports Buchberger Reduced_GB Polynomials.MPoly_Type_Class_OAlist Code_Target_Rat
begin

context gd_term
begin

definition rgb :: "('t \<Rightarrow>\<^sub>0 'b) list \<Rightarrow> ('t \<Rightarrow>\<^sub>0 'b::field) list"
  where "rgb bs = comp_red_monic_basis (map fst (gb (map (\<lambda>b. (b, ())) bs) ()))"

definition rgb_punit :: "('a \<Rightarrow>\<^sub>0 'b) list \<Rightarrow> ('a \<Rightarrow>\<^sub>0 'b::field) list"
  where "rgb_punit bs = punit.comp_red_monic_basis (map fst (gb_punit (map (\<lambda>b. (b, ())) bs) ()))"

lemma compute_trd_aux [code]:
  "trd_aux fs p r =
    (if is_zero p then
      r
    else
      case find_adds fs (lt p) of
        None   \<Rightarrow> trd_aux fs (tail p) (plus_monomial_less r (lc p) (lt p))
      | Some f \<Rightarrow> trd_aux fs (tail p - monom_mult (lc p / lc f) (lp p - lp f) (tail f)) r
    )"
  by (simp only: trd_aux.simps[of fs p r] plus_monomial_less_def is_zero_def)

end

text \<open>We only consider scalar polynomials here, but vector-polynomials could be handled, too.\<close>

global_interpretation punit': gd_powerprod "ord_pp_punit cmp_term" "ord_pp_strict_punit cmp_term"
  rewrites "punit.adds_term = (adds)"
  and "punit.pp_of_term = (\<lambda>x. x)"
  and "punit.component_of_term = (\<lambda>_. ())"
  and "punit.monom_mult = monom_mult_punit"
  and "punit.mult_scalar = mult_scalar_punit"
  and "punit'.punit.min_term = min_term_punit"
  and "punit'.punit.lt = lt_punit cmp_term"
  and "punit'.punit.lc = lc_punit cmp_term"
  and "punit'.punit.tail = tail_punit cmp_term"
  and "punit'.punit.ord_p = ord_p_punit cmp_term"
  and "punit'.punit.ord_strict_p = ord_strict_p_punit cmp_term"
  for cmp_term :: "('a::nat, 'b::{nat,add_wellorder}) pp nat_term_order"

  defines find_adds_punit = punit'.punit.find_adds
  and trd_aux_punit = punit'.punit.trd_aux
  and trd_punit = punit'.punit.trd
  and spoly_punit = punit'.punit.spoly
  and count_const_lt_components_punit = punit'.punit.count_const_lt_components
  and count_rem_components_punit = punit'.punit.count_rem_components
  and const_lt_component_punit = punit'.punit.const_lt_component
  and full_gb_punit = punit'.punit.full_gb
  and add_pairs_single_sorted_punit = punit'.punit.add_pairs_single_sorted
  and add_pairs_punit = punit'.punit.add_pairs
  and canon_pair_order_aux_punit = punit'.punit.canon_pair_order_aux
  and canon_basis_order_punit = punit'.punit.canon_basis_order
  and new_pairs_sorted_punit = punit'.punit.new_pairs_sorted
  and product_crit_punit = punit'.punit.product_crit
  and chain_ncrit_punit = punit'.punit.chain_ncrit
  and chain_ocrit_punit = punit'.punit.chain_ocrit
  and apply_icrit_punit = punit'.punit.apply_icrit
  and apply_ncrit_punit = punit'.punit.apply_ncrit
  and apply_ocrit_punit = punit'.punit.apply_ocrit
  and trdsp_punit = punit'.punit.trdsp
  and gb_sel_punit = punit'.punit.gb_sel
  and gb_red_aux_punit = punit'.punit.gb_red_aux
  and gb_red_punit = punit'.punit.gb_red
  and gb_aux_punit = punit'.punit.gb_aux_punit
  and gb_punit = punit'.punit.gb_punit \<comment>\<open>Faster, because incorporates product criterion.\<close>
  and comp_min_basis_punit = punit'.punit.comp_min_basis
  and comp_red_basis_aux_punit = punit'.punit.comp_red_basis_aux
  and comp_red_basis_punit = punit'.punit.comp_red_basis
  and monic_punit = punit'.punit.monic
  and comp_red_monic_basis_punit = punit'.punit.comp_red_monic_basis
  and rgb_punit = punit'.punit.rgb_punit
  subgoal by (fact gd_powerprod_ord_pp_punit)
  subgoal by (fact punit_adds_term)
  subgoal by (simp add: id_def)
  subgoal by (fact punit_component_of_term)
  subgoal by (simp only: monom_mult_punit_def)
  subgoal by (simp only: mult_scalar_punit_def)
  subgoal using min_term_punit_def by fastforce
  subgoal by (simp only: lt_punit_def ord_pp_punit_alt)
  subgoal by (simp only: lc_punit_def ord_pp_punit_alt)
  subgoal by (simp only: tail_punit_def ord_pp_punit_alt)
  subgoal by (simp only: ord_p_punit_def ord_pp_strict_punit_alt)
  subgoal by (simp only: ord_strict_p_punit_def ord_pp_strict_punit_alt)
  done

lemma compute_spoly_punit [code]:
  "spoly_punit to p q = (let t1 = lt_punit to p; t2 = lt_punit to q; l = lcs t1 t2 in
         (monom_mult_punit (1 / lc_punit to p) (l - t1) p) - (monom_mult_punit (1 / lc_punit to q) (l - t2) q))"
  by (simp add: punit'.punit.spoly_def Let_def punit'.punit.lc_def)

lemma compute_trd_punit [code]: "trd_punit to fs p = trd_aux_punit to fs p (change_ord to 0)"
  by (simp only: punit'.punit.trd_def change_ord_def)

experiment begin interpretation trivariate\<^sub>0_rat .

lemma
  "rgb_punit DRLEX
    [
     X ^ 3 - X * Y * Z\<^sup>2,
     Y\<^sup>2 * Z - 1
    ] =
    [
     X ^ 3 * Y - X * Z,
     - (X ^ 3) + X * Y * Z\<^sup>2,
     Y\<^sup>2 * Z - 1,
     - (X * Z ^ 3) + X ^ 5
    ]"
  by eval

lemma
  "rgb_punit DRLEX
    [
     X\<^sup>2 + Y\<^sup>2 + Z\<^sup>2 - 1,
     X * Y - Z - 1,
     Y\<^sup>2 + X,
     Z\<^sup>2 + X
    ] =
    [
     1
    ]"
  by eval

text \<open>Note: The above computations have been cross-checked with Mathematica 11.1.\<close>

end

end (* theory *)


theory State_Ops
imports Sep_Generic_Wp
begin

section \<open>Generic State Ops\<close>

datatype ('c, 'r) state_op =
    Read "'c \<Rightarrow> 'r" | Update "'c \<Rightarrow> 'c"
  | Maybe "'r option" | ReadMaybe "'c \<Rightarrow> 'r option" | UpdateMaybe "'c \<Rightarrow> 'c option"
  | ReadUpdate "'c \<Rightarrow> 'c \<times> 'r"

definition "r_dummy \<equiv> undefined"

fun wp_stateop where
  "wp_stateop (Read f) Q s = Q (f s) s"
| "wp_stateop (Update f) Q s = Q r_dummy (f s)"
| "wp_stateop (Maybe opt) Q s = (case opt of Some r \<Rightarrow> Q r s | None \<Rightarrow> False)"
| "wp_stateop (ReadMaybe f) Q s = (case f s of Some r \<Rightarrow> Q r s | None \<Rightarrow> False)"
| "wp_stateop (UpdateMaybe f) Q s = (case f s of Some s' \<Rightarrow> Q r_dummy s' | None \<Rightarrow> False)"
| "wp_stateop (ReadUpdate f) Q s = (case f s of (s', r) \<Rightarrow> Q r s')"

lemma wp_stateopI:
  "\<And>f. Q (f s) s \<Longrightarrow> wp_stateop (Read f) Q s"
  "\<And>f. Q r_dummy (f s) \<Longrightarrow> wp_stateop (Update f) Q s"
  "\<And>opt r. opt = Some r \<Longrightarrow> Q r s \<Longrightarrow> wp_stateop (Maybe opt) Q s"
  "\<And>f r. f s = Some r \<Longrightarrow> Q r s \<Longrightarrow> wp_stateop (ReadMaybe f) Q s"
  "\<And>f s'. f s = Some s' \<Longrightarrow> Q r_dummy s' \<Longrightarrow> wp_stateop (UpdateMaybe f) Q s"
  "\<And>f s' r. f s = (s', r) \<Longrightarrow> Q r s' \<Longrightarrow> wp_stateop (ReadUpdate f) Q s"
  by (auto)

lemma wp_stateopE[elim!]:
  assumes "wp_stateop c Q s"
  obtains
    ("Read") f r where "c = Read f" and "r = f s" and "Q r s"
  | ("Update") f s' where "c = Update f" and "s' = f s" and "Q r_dummy s'"
  | ("Maybe") opt r where "c = Maybe opt" and "opt = Some r" and "Q r s"
  | ("ReadMaybe") f r where "c = ReadMaybe f" and "f s = Some r" and "Q r s"
  | ("UpdateMaybe") f s' where "c = UpdateMaybe f" and "f s = Some s'" and "Q r_dummy s'"
  | ("ReadUpdate") f s' r where "c = ReadUpdate f" and "f s = (s', r)" and "Q r s'"
  apply (rule wp_stateop.elims(2)[OF assms])
  by (auto split: option.splits)

interpretation state_op: generic_wp "\<lambda>_. wp_stateop"
  apply standard
  subgoal for e c Q Q'
    apply (cases c; standard+)
    by (auto split: option.splits)
  done

abbreviation "state_ht \<equiv> state_op.htriple ()"

lemmas state_htI = state_op.htripleI

inductive readonly_op where
  "readonly_op (Read f)" | "readonly_op (Maybe opt)" | "readonly_op (ReadMaybe f)"
declare readonly_op.cases[elim]
declare readonly_op.intros[intro]

inductive_simps [iff]: "readonly_op (Read f)"
inductive_simps [iff]: "readonly_op (Maybe opt)"
inductive_simps [iff]: "readonly_op (ReadMaybe f)"

lemma wp_readonly_op:
  "readonly_op c \<Longrightarrow> wp_stateop c Q s \<longleftrightarrow> wp_stateop c (\<lambda>r _. Q r s) s"
  apply (erule readonly_op.cases)
  by auto

end


theory Balance_Adapted
  imports "../Abstract_Rbt"
begin

subsection \<open>Balance Cases\<close>

definition "rbt_balance_ad_case_1 lhs k v rhs \<equiv>
  case (lhs, k, v, rhs) of
  ((Branch color.R a w x b), s, t, (Branch color.R c y z d)) \<Rightarrow>
   Branch color.R (Branch color.B a w x b) s t (Branch color.B c y z d)"

definition "rbt_balance_ad_case_2 lhs k v rhs \<equiv>
  case (lhs, k, v, rhs) of
  ((Branch color.R (Branch color.R a w x b) s t c), y, z, d) \<Rightarrow>
   Branch color.R (Branch color.B a w x b) s t (Branch color.B c y z d)"

definition "rbt_balance_ad_case_3 lhs k v rhs \<equiv>
  case (lhs, k, v, rhs) of
  ((Branch color.R a w x (Branch color.R b s t c)), y, z, d) \<Rightarrow>
   Branch color.R (Branch color.B a w x b) s t (Branch color.B c y z d)"

definition "rbt_balance_ad_case_4 lhs k v rhs \<equiv>
  case (lhs, k, v, rhs) of
  (a, w, x, (Branch color.R b s t (Branch color.R c y z d))) \<Rightarrow>
   Branch color.R (Branch color.B a w x b) s t (Branch color.B c y z d)"

definition "rbt_balance_ad_case_5 lhs k v rhs \<equiv>
  case (lhs, k, v, rhs) of
  (a, w, x, (Branch color.R (Branch color.R b s t c) y z d)) \<Rightarrow>
   Branch color.R (Branch color.B a w x b) s t (Branch color.B c y z d)"

definition "rbt_balance_ad_case_6 lhs k v rhs \<equiv>
  case (lhs, k, v, rhs) of
  (a, s, t, b) \<Rightarrow> Branch color.B a s t b"

subsection \<open>Case Checks\<close>

definition "rbt_check_1 lhs rhs \<equiv> rbt_is_red lhs \<and> rbt_is_red rhs"
definition "rbt_check_2 lhs rhs \<equiv> rbt_is_red lhs \<and> rbt_is_red (rbt_left lhs)"
definition "rbt_check_3 lhs rhs \<equiv> rbt_is_red lhs \<and> rbt_is_red (rbt_right lhs)"
definition "rbt_check_4 lhs rhs \<equiv> rbt_is_red rhs \<and> rbt_is_red (rbt_right rhs)"
definition "rbt_check_5 lhs rhs \<equiv> rbt_is_red rhs \<and> rbt_is_red (rbt_left rhs)"

subsubsection \<open>unfold lemmas for checks\<close>

lemma rbt_check_1_unfold:
  assumes "rbt_check_1 lhs rhs"
  obtains ll k_l v_l lr
    rl k_r v_r rr where
    "lhs = (Branch color.R ll k_l v_l lr)"
    "rhs = (Branch color.R rl k_r v_r rr)"
  using assms by (meson rbt_is_red_unfold_branch rbt_check_1_def)

lemma rbt_check_2_unfold:
  assumes "rbt_check_2 lhs rhs"
  obtains k_l v_l lr
    lll k_ll v_ll llr where
    "lhs = (Branch color.R (Branch color.R lll k_ll v_ll llr) k_l v_l lr)"
  using assms
  unfolding rbt_check_2_def rbt_left_def
  by fastforce

lemma rbt_check_3_unfold:
  assumes "rbt_check_3 lhs rhs"
  obtains ll k_l v_l
    lrl k_lr v_lr lrr where
    "lhs = (Branch color.R ll k_l v_l (Branch color.R lrl k_lr v_lr lrr))"
  using assms
  unfolding rbt_check_3_def rbt_right_def
  by fastforce

lemma rbt_check_4_unfold:
  assumes "rbt_check_4 lhs rhs"
  obtains rl k_r v_r
    rrl k_rr v_rr rrr where
    "rhs = (Branch color.R rl k_r v_r (Branch color.R rrl k_rr v_rr rrr))"
  using assms
  unfolding rbt_check_4_def rbt_right_def
  by fastforce

lemma rbt_check_5_unfold:
  assumes "rbt_check_5 lhs rhs"
  obtains k_r v_r rr
    rll k_rl v_rl rlr where
    "rhs = (Branch color.R (Branch color.R rll k_rl v_rl rlr) k_r v_r rr)"
  using assms
  unfolding rbt_check_5_def rbt_left_def
  by fastforce

subsubsection \<open>Adapted Balance Function\<close>

fun rbt_balance_ad where
  "rbt_balance_ad lhs k v rhs =
  (
    if rbt_check_1 lhs rhs
      then rbt_balance_ad_case_1 lhs k v rhs
    else if rbt_check_2 lhs rhs
      then rbt_balance_ad_case_2 lhs k v rhs
    else if rbt_check_3 lhs rhs
      then rbt_balance_ad_case_3 lhs k v rhs
    else if rbt_check_4 lhs rhs
      then rbt_balance_ad_case_4 lhs k v rhs
    else if rbt_check_5 lhs rhs
      then rbt_balance_ad_case_5 lhs k v rhs
    else rbt_balance_ad_case_6 lhs k v rhs
  )
  "

lemma rbt_balance_ad_correct:
  "rbt_balance_ad lhs k v rhs = rbt_balance lhs k v rhs"
  apply (induction lhs k v rhs rule: balance.induct)
  by (auto simp add:
      rbt_is_red_def
      rbt_left_def
      rbt_right_def
      rbt_balance_ad_case_1_def
      rbt_balance_ad_case_2_def
      rbt_balance_ad_case_3_def
      rbt_balance_ad_case_4_def
      rbt_balance_ad_case_5_def
      rbt_balance_ad_case_6_def
      rbt_check_1_def
      rbt_check_2_def
      rbt_check_3_def
      rbt_check_4_def
      rbt_check_5_def
      )

end


section \<open>Weak Order Dependence\<close>

theory WeakOrderDependence imports "../Basic/CFG" DataDependence begin

text \<open>Weak order dependence is just defined as a static control dependence\<close>

subsection\<open>Definition and some lemmas\<close>

definition (in CFG) weak_order_dependence :: "'node \<Rightarrow> 'node \<Rightarrow> 'node \<Rightarrow> bool"
   ("_ \<longrightarrow>\<^sub>w\<^sub>o\<^sub>d _,_")
where wod_def:"n \<longrightarrow>\<^sub>w\<^sub>o\<^sub>d n\<^sub>1,n\<^sub>2 \<equiv> ((n\<^sub>1 \<noteq> n\<^sub>2) \<and>
   (\<exists>as. (n -as\<rightarrow>* n\<^sub>1) \<and> (n\<^sub>2 \<notin> set (sourcenodes as))) \<and>
   (\<exists>as. (n -as\<rightarrow>* n\<^sub>2) \<and> (n\<^sub>1 \<notin> set (sourcenodes as))) \<and>
   (\<exists>a. (valid_edge a) \<and> (n = sourcenode a) \<and>
        ((\<exists>as. (targetnode a -as\<rightarrow>* n\<^sub>1) \<and>
               (\<forall>as'. (targetnode a -as'\<rightarrow>* n\<^sub>2) \<longrightarrow> n\<^sub>1 \<in> set(sourcenodes as'))) \<or>
         (\<exists>as. (targetnode a -as\<rightarrow>* n\<^sub>2) \<and>
               (\<forall>as'. (targetnode a -as'\<rightarrow>* n\<^sub>1) \<longrightarrow> n\<^sub>2 \<in> set(sourcenodes as'))))))"

inductive_set (in CFG_wf) wod_backward_slice :: "'node set \<Rightarrow> 'node set"
for S :: "'node set"
  where refl:"\<lbrakk>valid_node n; n \<in> S\<rbrakk> \<Longrightarrow> n \<in> wod_backward_slice S"

  | cd_closed:
  "\<lbrakk>n' \<longrightarrow>\<^sub>w\<^sub>o\<^sub>d n\<^sub>1,n\<^sub>2; n\<^sub>1 \<in> wod_backward_slice S; n\<^sub>2 \<in> wod_backward_slice S\<rbrakk>
  \<Longrightarrow> n' \<in> wod_backward_slice S"

  | dd_closed:"\<lbrakk>n' influences V in n''; n'' \<in> wod_backward_slice S\<rbrakk>
  \<Longrightarrow> n' \<in> wod_backward_slice S"

lemma (in CFG_wf)
  wod_backward_slice_valid_node:"n \<in> wod_backward_slice S \<Longrightarrow> valid_node n"
by(induct rule:wod_backward_slice.induct,
   auto dest:path_valid_node simp:wod_def data_dependence_def)

end


(*  Title:      HOL/HOLCF/IOA/NTP/Receiver.thy
    Author:     Tobias Nipkow & Konrad Slind
*)

section \<open>The implementation: receiver\<close>

theory Receiver
imports IOA.IOA Action
begin

type_synonym

'm receiver_state
= "'m list * bool multiset * 'm packet multiset * bool * bool"
(* messages  #replies        #received            header mode *)

definition rq :: "'m receiver_state => 'm list" where "rq == fst"
definition rsent :: "'m receiver_state => bool multiset" where "rsent == fst \<circ> snd"
definition rrcvd :: "'m receiver_state => 'm packet multiset" where "rrcvd == fst \<circ> snd \<circ> snd"
definition rbit :: "'m receiver_state => bool" where "rbit == fst \<circ> snd \<circ> snd \<circ> snd"
definition rsending :: "'m receiver_state => bool" where "rsending == snd \<circ> snd \<circ> snd \<circ> snd"

definition
  receiver_asig :: "'m action signature" where
  "receiver_asig =
   (UN pkt. {R_pkt(pkt)},
    (UN m. {R_msg(m)}) Un (UN b. {S_ack(b)}),
    insert C_m_r (UN m. {C_r_r(m)}))"

definition
  receiver_trans:: "('m action, 'm receiver_state)transition set" where
"receiver_trans =
 {tr. let s = fst(tr);
          t = snd(snd(tr))
      in
      case fst(snd(tr))
      of
      S_msg(m) => False |
      R_msg(m) => rq(s) = (m # rq(t))   &
                  rsent(t)=rsent(s)     &
                  rrcvd(t)=rrcvd(s)     &
                  rbit(t)=rbit(s)       &
                  rsending(t)=rsending(s) |
      S_pkt(pkt) => False |
      R_pkt(pkt) => rq(t) = rq(s)                        &
                       rsent(t) = rsent(s)                  &
                       rrcvd(t) = addm (rrcvd s) pkt        &
                       rbit(t) = rbit(s)                    &
                       rsending(t) = rsending(s) |
      S_ack(b) => b = rbit(s)                        &
                     rq(t) = rq(s)                      &
                     rsent(t) = addm (rsent s) (rbit s) &
                     rrcvd(t) = rrcvd(s)                &
                     rbit(t)=rbit(s)                    &
                     rsending(s)                        &
                     rsending(t) |
      R_ack(b) => False |
      C_m_s => False |
 C_m_r => count (rsent s) (~rbit s) < countm (rrcvd s) (%y. hdr(y)=rbit(s)) &
             rq(t) = rq(s)                        &
             rsent(t)=rsent(s)                    &
             rrcvd(t)=rrcvd(s)                    &
             rbit(t)=rbit(s)                      &
             rsending(s)                          &
             ~rsending(t) |
    C_r_s => False |
 C_r_r(m) => count (rsent s) (rbit s) <= countm (rrcvd s) (%y. hdr(y)=rbit(s)) &
             count (rsent s) (~rbit s) < count (rrcvd s) (rbit(s),m) &
             rq(t) = rq(s)@[m]                         &
             rsent(t)=rsent(s)                         &
             rrcvd(t)=rrcvd(s)                         &
             rbit(t) = (~rbit(s))                      &
             ~rsending(s)                              &
             rsending(t)}"

definition
  receiver_ioa  :: "('m action, 'm receiver_state)ioa" where
  "receiver_ioa =
    (receiver_asig, {([],{|},{|},False,False)}, receiver_trans,{},{})"

lemma in_receiver_asig:
  "S_msg(m) \<notin> actions(receiver_asig)"
  "R_msg(m) \<in> actions(receiver_asig)"
  "S_pkt(pkt) \<notin> actions(receiver_asig)"
  "R_pkt(pkt) \<in> actions(receiver_asig)"
  "S_ack(b) \<in> actions(receiver_asig)"
  "R_ack(b) \<notin> actions(receiver_asig)"
  "C_m_s \<notin> actions(receiver_asig)"
  "C_m_r \<in> actions(receiver_asig)"
  "C_r_s \<notin> actions(receiver_asig)"
  "C_r_r(m) \<in> actions(receiver_asig)"
  by (simp_all add: receiver_asig_def actions_def asig_projections)

lemmas receiver_projections = rq_def rsent_def rrcvd_def rbit_def rsending_def

end


(*  Title:       Deriving class instances for datatypes
    Author:      René Thiemann       <rene.thiemann@uibk.ac.at>
    Maintainer:  René Thiemann
    License:     LGPL
*)

(*
Copyright 2013 René Thiemann

This file is part of IsaFoR/CeTA.

IsaFoR/CeTA 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 3 of the License, or (at your option) any later
version.

IsaFoR/CeTA 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 IsaFoR/CeTA. If not, see <http://www.gnu.org/licenses/>.
*)

header {* Hash functions *}

theory Hash_Generator
imports "../Collections/Lib/HashCode"
  Derive_Manager
begin

subsection "Introduction"

text {*
The interface for hash-functions is defined in the class @{class hashable} which has been developed
as part of the Isabelle Collection Framework \cite{rbt}. It requires a hash-function
(@{const hashcode}), a bounded hash-function (@{const bounded_hashcode}),
and a default hash-table size (@{const def_hashmap_size}).

The @{const hashcode} function for each datatype are created by instantiating the recursors of that
datatype appropriately. E.g., for \texttt{datatype 'a test = C1 'a 'a | C2 "'a test list"}
we get a hash-function which is equivalent to
\begin{verbatim}
hashcode (C1 a b) = c1 * hashcode a + c2 * hashcode b
hashcode (C2 Nil) = c3
hashcode (C2 (a # as)) = c4 * hashcode a + c5 * hashcode as
\end{verbatim}
where each \texttt{c$_{i}$} is a non-negative 32-bit number which is dependent on the
datatype name, the constructor name, and the occurence of the argument (i.e.,
in the example \texttt{c1} and \texttt{c2} will usually be different numbers.)
These parameters are used in linear combination with prime numbers to hopefully
get some useful hash-function.

The @{const bounded_hashcode} functions are constructed in the same way, except that after each
arithmetic operation a modulo operation is performed.

Finally, the default hash-table size is just set to 10, following Java's default
hash-table constructor.
*}

subsection "Features and Limitations"

text {*
We get same limitation as for the order generator.
For mutual recursive datatypes, only
for the first mentioned datatype the instantiations of the @{class hashable}-class are
derived.
*}

subsection "Installing the generator"

lemma hash_mod_lemma: "1 < (n :: nat) \<Longrightarrow> x mod n < n" by auto

ML_file "hash_generator.ML"

setup {*
  Hash_Generator.setup
*}

end