theory Prelude_List_E4
imports "$HETS_LIB/Isabelle/MainHCPairs"
uses "$HETS_LIB/Isabelle/prelude"
begin

ML "Header.initialize
    [\"ga_selector_pre\", \"ga_injective_suc\", \"ga_disjoint_0_suc\",
     \"ga_selector_undef_pre_0\", \"X1_def_Nat\", \"X2_def_Nat\",
     \"X3_def_Nat\", \"X4_def_Nat\", \"X5_def_Nat\", \"X6_def_Nat\",
     \"X7_def_Nat\", \"X8_def_Nat\", \"X9_def_Nat\", \"decimal_def\",
     \"ga_comm___XPlus__\", \"ga_assoc___XPlus__\",
     \"ga_right_unit___XPlus__\", \"ga_left_unit___XPlus__\",
     \"ga_left_comm___XPlus__\", \"ga_comm___Xx__\",
     \"ga_assoc___Xx__\", \"ga_right_unit___Xx__\",
     \"ga_left_unit___Xx__\", \"ga_left_comm___Xx__\", \"ga_comm_min\",
     \"ga_assoc_min\", \"ga_left_comm_min\", \"ga_comm_max\",
     \"ga_assoc_max\", \"ga_right_unit_max\", \"ga_left_unit_max\",
     \"ga_left_comm_max\", \"leq_def1_Nat\", \"leq_def2_Nat\",
     \"leq_def3_Nat\", \"geq_def_Nat\", \"less_def_Nat\",
     \"greater_def_Nat\", \"even_0_Nat\", \"even_suc_Nat\",
     \"odd_def_Nat\", \"factorial_0\", \"factorial_suc\", \"add_0_Nat\",
     \"add_suc_Nat\", \"mult_0_Nat\", \"mult_suc_Nat\", \"power_0_Nat\",
     \"power_suc_Nat\", \"min_def_Nat\", \"max_def_Nat\",
     \"subTotal_def1_Nat\", \"subTotal_def2_Nat\", \"sub_dom_Nat\",
     \"sub_def_Nat\", \"divide_dom_Nat\", \"divide_0_Nat\",
     \"divide_Pos_Nat\", \"div_dom_Nat\", \"div_Nat\", \"mod_dom_Nat\",
     \"mod_Nat\", \"distr1_Nat\", \"distr2_Nat\", \"min_0\",
     \"div_mod_Nat\", \"power_Nat\", \"Comp1\", \"IdDef\", \"FlipDef\",
     \"FstDef\", \"SndDef\", \"CurryDef\", \"UncurryDef\", \"NotFalse\",
     \"NotTrue\", \"AndFalse\", \"AndTrue\", \"AndSym\", \"OrDef\",
     \"OtherwiseDef\", \"NotFalse1\", \"NotTrue1\", \"notNot1\",
     \"notNot2\", \"EqualTDef\", \"EqualSymDef\", \"EqualReflex\",
     \"EqualTransT\", \"DiffDef\", \"DiffSymDef\", \"DiffTDef\",
     \"DiffFDef\", \"TE1\", \"TE2\", \"TE3\", \"TE4\", \"IUE1\",
     \"IUE2\", \"IBE1\", \"IBE2\", \"IBE3\", \"IBE4\", \"IBE5\",
     \"IBE6\", \"IBE7\", \"IBE8\", \"IOE01\", \"IOE02\", \"IOE03\",
     \"IOE04\", \"IOE05\", \"IOE06\", \"IOE07\", \"IOE08\", \"IOE09\",
     \"LeIrreflexivity\", \"LeTAsymmetry\", \"LeTTransitive\",
     \"LeTTotal\", \"GeDef\", \"GeIrreflexivity\", \"GeTAsymmetry\",
     \"GeTTransitive\", \"GeTTotal\", \"LeqDef\", \"LeqReflexivity\",
     \"LeqTTransitive\", \"LeqTTotal\", \"GeqDef\", \"GeqReflexivity\",
     \"GeqTTransitive\", \"GeqTTotal\", \"EqTSOrdRel\", \"EqFSOrdRel\",
     \"EqTOrdRel\", \"EqFOrdRel\", \"EqTOrdTSubstE\", \"EqTOrdFSubstE\",
     \"EqTOrdTSubstD\", \"EqTOrdFSubstD\", \"LeTGeFEqFRel\",
     \"LeFGeTEqTRel\", \"LeTGeTRel\", \"LeFGeFRel\", \"LeqTGetTRel\",
     \"LeqFGetFRel\", \"GeTLeTRel\", \"GeFLeFRel\", \"GeqTLeqTRel\",
     \"GeqFLeqFRel\", \"LeqTGeFRel\", \"LeqFGeTRel\", \"GeTLeFEqFRel\",
     \"GeFLeTEqTRel\", \"GeqTLeFRel\", \"GeqFLeTRel\",
     \"LeqTLeTEqTRel\", \"LeqFLeFEqFRel\", \"GeqTGeTEqTRel\",
     \"GeqFGeFEqFRel\", \"LeTGeqFRel\", \"GeTLeqFRel\", \"LeLeqDiff\",
     \"CmpLTDef\", \"CmpEQDef\", \"CmpGTDef\", \"MaxYDef\", \"MaxXDef\",
     \"MinXDef\", \"MinYDef\", \"MaxSym\", \"MinSym\", \"TO1\", \"TO2\",
     \"TO3\", \"TO4\", \"TO5\", \"TO6\", \"TO7\", \"IUO01\", \"IUO02\",
     \"IUO03\", \"IUO04\", \"IUO05\", \"IUO06\", \"IUO07\", \"IOO13\",
     \"IOO14\", \"IOO15\", \"IOO16\", \"IOO17\", \"IOO18\", \"IOO19\",
     \"IOO20\", \"IOO21\", \"IOO22\", \"IOO23\", \"IOO24\", \"IOO25\",
     \"IOO26\", \"IOO27\", \"IOO28\", \"IOO29\", \"IOO30\", \"IOO31\",
     \"IOO32\", \"IOO33\", \"IBO5\", \"IBO6\", \"IBO7\", \"IBO8\",
     \"IBO9\", \"IBO10\", \"IBO11\", \"IBO12\", \"LengthNil\",
     \"LengthCons\", \"NotDefHead\", \"HeadDef\", \"NotDefTail\",
     \"TailDef\", \"FoldrNil\", \"FoldrCons\", \"FoldlNil\",
     \"FoldlCons\", \"MapNil\", \"MapCons\", \"XPlusXPlusNil\",
     \"XPlusXPlusCons\", \"XPlusXPlusPrefixDef\", \"FilterNil\",
     \"FilterConsT\", \"FilterConsF\", \"ZipNil\", \"ZipConsNil\",
     \"ZipConsCons\", \"UnzipNil\", \"UnzipCons\", \"ILE02\", \"ILO05\",
     \"ILO06\", \"ILO07\", \"ILE01\", \"ILO01\", \"ILO02\", \"ILO03\",
     \"ILO04\", \"ILO08\", \"ILO09\", \"ILO10\", \"ILO11\", \"ILO12\",
     \"ILO13\", \"ILO14\", \"ILO15\", \"ILO16\", \"ILO17\", \"ILO18\",
     \"ILO19\", \"ILO20\", \"ILO21\", \"ILO22\", \"FoldlDecomp\",
     \"MapDecomp\", \"MapFunctor\", \"FilterProm\", \"LengthNil1\",
     \"LengthEqualNil\", \"LengthEqualCons\", \"ZipSpec\"]"

typedecl Bool
typedecl Unit

datatype X_Nat = X0 ("0''") | X_suc "X_Nat" ("suc/'(_')" [3] 999)
datatype Ordering = EQ | GT | LT
datatype 'a List = X_Cons 'a "'a List" | X_Nil ("Nil''")

consts
Not__X :: "bool => bool" ("(Not''/ _)" [56] 56)
X1 :: "X_Nat" ("1''")
X2 :: "X_Nat" ("2''")
X3 :: "X_Nat" ("3''")
X4 :: "X_Nat" ("4''")
X5 :: "X_Nat" ("5''")
X6 :: "X_Nat" ("6''")
X7 :: "X_Nat" ("7''")
X8 :: "X_Nat" ("8''")
X9 :: "X_Nat" ("9''")
XLtXPlusXPlusXGt :: "'a List => 'a List => 'a List"
X__XAmpXAmp__X :: "bool => bool => bool" ("(_/ &&/ _)" [54,54] 52)
X__XAtXAt__X :: "X_Nat => X_Nat => X_Nat" ("(_/ @@/ _)" [54,54] 52)
X__XCaret__X :: "X_Nat => X_Nat => X_Nat" ("(_/ ^''/ _)" [54,54] 52)
X__XEqXEq__X :: "'a => 'a => bool" ("(_/ ==''/ _)" [54,54] 52)
X__XExclam :: "X_Nat => X_Nat" ("(_/ !'')" [58] 58)
X__XGtXEq__XX1 :: "X_Nat => X_Nat => bool" ("(_/ >=''/ _)" [44,44] 42)
X__XGtXEq__XX2 :: "'a => 'a => bool" ("(_/ >=''''/ _)" [54,54] 52)
X__XGt__XX1 :: "X_Nat => X_Nat => bool" ("(_/ >''/ _)" [44,44] 42)
X__XGt__XX2 :: "'a => 'a => bool" ("(_/ >''''/ _)" [54,54] 52)
X__XLtXEq__XX1 :: "X_Nat => X_Nat => bool" ("(_/ <=''/ _)" [44,44] 42)
X__XLtXEq__XX2 :: "'a => 'a => bool" ("(_/ <=''''/ _)" [54,54] 52)
X__XLt__XX1 :: "X_Nat => X_Nat => bool" ("(_/ <''/ _)" [44,44] 42)
X__XLt__XX2 :: "'a => 'a => bool" ("(_/ <''''/ _)" [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__XPlusXPlus__X :: "'a List => 'a List => 'a List" ("(_/ ++''/ _)" [54,54] 52)
X__XPlus__X :: "X_Nat => X_Nat => X_Nat" ("(_/ +''/ _)" [54,54] 52)
X__XSlashXEq__X :: "'a => 'a => bool" ("(_/ '/=/ _)" [54,54] 52)
X__XSlashXQuest__X :: "X_Nat => X_Nat => X_Nat partial" ("(_/ '/?/ _)" [54,54] 52)
X__XVBarXVBar__X :: "bool => bool => bool" ("(_/ ||/ _)" [54,54] 52)
X__Xx__X :: "X_Nat => X_Nat => X_Nat" ("(_/ *''/ _)" [54,54] 52)
X__div__X :: "X_Nat => X_Nat => X_Nat partial" ("(_/ div''/ _)" [54,54] 52)
X__mod__X :: "X_Nat => X_Nat => X_Nat partial" ("(_/ mod''/ _)" [54,54] 52)
X__o__X :: "('b => 'c) * ('a => 'b) => 'a => 'c"
X_curry :: "('a * 'b => 'c) => 'a => 'b => 'c"
X_even :: "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"
X_foldr :: "('a => 'b => 'b) => 'b => 'a List => 'b"
X_fst :: "'a => 'b => 'a" ("fst''/'(_,/ _')" [3,3] 999)
X_head :: "'a List => 'a partial" ("head/'(_')" [3] 999)
X_id :: "'a => 'a" ("id''/'(_')" [3] 999)
X_length :: "'a List => X_Nat" ("length''/'(_')" [3] 999)
X_map :: "('a => 'b) => 'a List => 'b List"
X_maxX1 :: "X_Nat => X_Nat => X_Nat" ("max''/'(_,/ _')" [3,3] 999)
X_maxX2 :: "'a => 'a => 'a"
X_minX1 :: "X_Nat => X_Nat => X_Nat" ("min''/'(_,/ _')" [3,3] 999)
X_minX2 :: "'a => 'a => 'a"
X_odd :: "X_Nat => bool" ("odd''/'(_')" [3] 999)
X_pre :: "X_Nat => X_Nat partial" ("pre/'(_')" [3] 999)
X_snd :: "'a => 'b => 'b" ("snd''/'(_,/ _')" [3,3] 999)
X_tail :: "'a List => 'a List partial" ("tail/'(_')" [3] 999)
X_unzip :: "('a * 'b) List => 'a List * 'b List" ("unzip/'(_')" [3] 999)
X_zip :: "'a List => 'b List => ('a * 'b) List"
compare :: "'a => 'a => Ordering"
otherwiseH :: "bool"
uncurry :: "('a => 'b => 'c) => 'a * 'b => 'c"

axioms
ga_selector_pre [rule_format] :
"ALL XX1. pre(suc(XX1)) = makePartial XX1"

ga_injective_suc [rule_format] :
"ALL XX1. ALL Y1. suc(XX1) = suc(Y1) = (XX1 = Y1)"

ga_disjoint_0_suc [rule_format] : "ALL Y1. ~ 0' = suc(Y1)"

ga_selector_undef_pre_0 [rule_format] : "~ defOp (pre(0'))"

X1_def_Nat [rule_format] : "1' = suc(0')"

X2_def_Nat [rule_format] : "2' = suc(1')"

X3_def_Nat [rule_format] : "3' = suc(2')"

X4_def_Nat [rule_format] : "4' = suc(3')"

X5_def_Nat [rule_format] : "5' = suc(4')"

X6_def_Nat [rule_format] : "6' = suc(5')"

X7_def_Nat [rule_format] : "7' = suc(6')"

X8_def_Nat [rule_format] : "8' = suc(7')"

X9_def_Nat [rule_format] : "9' = suc(8')"

decimal_def [rule_format] :
"ALL m. ALL X_n. m @@ X_n = (m *' suc(9')) +' X_n"

ga_comm___XPlus__ [rule_format] : "ALL x. ALL y. x +' y = y +' x"

ga_assoc___XPlus__ [rule_format] :
"ALL x. ALL y. ALL z. (x +' y) +' z = x +' (y +' z)"

ga_right_unit___XPlus__ [rule_format] : "ALL x. x +' 0' = x"

ga_left_unit___XPlus__ [rule_format] : "ALL x. 0' +' x = x"

ga_left_comm___XPlus__ [rule_format] :
"ALL x. ALL y. ALL z. x +' (y +' z) = y +' (x +' z)"

ga_comm___Xx__ [rule_format] : "ALL x. ALL y. x *' y = y *' x"

ga_assoc___Xx__ [rule_format] :
"ALL x. ALL y. ALL z. (x *' y) *' z = x *' (y *' z)"

ga_right_unit___Xx__ [rule_format] : "ALL x. x *' 1' = x"

ga_left_unit___Xx__ [rule_format] : "ALL x. 1' *' x = x"

ga_left_comm___Xx__ [rule_format] :
"ALL x. ALL y. ALL z. x *' (y *' z) = y *' (x *' z)"

ga_comm_min [rule_format] : "ALL x. ALL y. min'(x, y) = min'(y, x)"

ga_assoc_min [rule_format] :
"ALL x. ALL y. ALL z. min'(min'(x, y), z) = min'(x, min'(y, z))"

ga_left_comm_min [rule_format] :
"ALL x. ALL y. ALL z. min'(x, min'(y, z)) = min'(y, min'(x, z))"

ga_comm_max [rule_format] : "ALL x. ALL y. max'(x, y) = max'(y, x)"

ga_assoc_max [rule_format] :
"ALL x. ALL y. ALL z. max'(max'(x, y), z) = max'(x, max'(y, z))"

ga_right_unit_max [rule_format] : "ALL x. max'(x, 0') = x"

ga_left_unit_max [rule_format] : "ALL x. max'(0', x) = x"

ga_left_comm_max [rule_format] :
"ALL x. ALL y. ALL z. max'(x, max'(y, z)) = max'(y, max'(x, z))"

leq_def1_Nat [rule_format] : "ALL X_n. 0' <=' X_n"

leq_def2_Nat [rule_format] : "ALL X_n. ~ suc(X_n) <=' 0'"

leq_def3_Nat [rule_format] :
"ALL m. ALL X_n. (suc(m) <=' suc(X_n)) = (m <=' X_n)"

geq_def_Nat [rule_format] :
"ALL m. ALL X_n. (m >=' X_n) = (X_n <=' m)"

less_def_Nat [rule_format] :
"ALL m. ALL X_n. (m <' X_n) = (m <=' X_n & ~ m = X_n)"

greater_def_Nat [rule_format] :
"ALL m. ALL X_n. (m >' X_n) = (X_n <' m)"

even_0_Nat [rule_format] : "even'(0')"

even_suc_Nat [rule_format] : "ALL m. even'(suc(m)) = odd'(m)"

odd_def_Nat [rule_format] : "ALL m. odd'(m) = (~ even'(m))"

factorial_0 [rule_format] : "0' !' = 1'"

factorial_suc [rule_format] :
"ALL X_n. suc(X_n) !' = suc(X_n) *' X_n !'"

add_0_Nat [rule_format] : "ALL m. 0' +' m = m"

add_suc_Nat [rule_format] :
"ALL m. ALL X_n. suc(X_n) +' m = suc(X_n +' m)"

mult_0_Nat [rule_format] : "ALL m. 0' *' m = 0'"

mult_suc_Nat [rule_format] :
"ALL m. ALL X_n. suc(X_n) *' m = (X_n *' m) +' m"

power_0_Nat [rule_format] : "ALL m. m ^' 0' = 1'"

power_suc_Nat [rule_format] :
"ALL m. ALL X_n. m ^' suc(X_n) = m *' (m ^' X_n)"

min_def_Nat [rule_format] :
"ALL m. ALL X_n. min'(m, X_n) = (if m <=' X_n then m else X_n)"

max_def_Nat [rule_format] :
"ALL m. ALL X_n. max'(m, X_n) = (if m <=' X_n then X_n else m)"

subTotal_def1_Nat [rule_format] :
"ALL m. ALL X_n. m >' X_n --> X_n -! m = 0'"

subTotal_def2_Nat [rule_format] :
"ALL m. ALL X_n. m <=' X_n --> makePartial (X_n -! m) = X_n -? m"

sub_dom_Nat [rule_format] :
"ALL m. ALL X_n. defOp (m -? X_n) = (m >=' X_n)"

sub_def_Nat [rule_format] :
"ALL m. ALL X_n. ALL r. m -? X_n = makePartial r = (m = r +' X_n)"

divide_dom_Nat [rule_format] :
"ALL m.
 ALL X_n.
 defOp (m /? X_n) = (~ X_n = 0' & m mod' X_n = makePartial 0')"

divide_0_Nat [rule_format] : "ALL m. ~ defOp (m /? 0')"

divide_Pos_Nat [rule_format] :
"ALL m.
 ALL X_n.
 ALL r. X_n >' 0' --> m /? X_n = makePartial r = (m = r *' X_n)"

div_dom_Nat [rule_format] :
"ALL m. ALL X_n. defOp (m div' X_n) = (~ X_n = 0')"

div_Nat [rule_format] :
"ALL m.
 ALL X_n.
 ALL r.
 m div' X_n = makePartial r =
 (EX s. m = (X_n *' r) +' s & s <' X_n)"

mod_dom_Nat [rule_format] :
"ALL m. ALL X_n. defOp (m mod' X_n) = (~ X_n = 0')"

mod_Nat [rule_format] :
"ALL m.
 ALL X_n.
 ALL s.
 m mod' X_n = makePartial s =
 (EX r. m = (X_n *' r) +' s & s <' X_n)"

distr1_Nat [rule_format] :
"ALL r. ALL s. ALL t. (r +' s) *' t = (r *' t) +' (s *' t)"

distr2_Nat [rule_format] :
"ALL r. ALL s. ALL t. t *' (r +' s) = (t *' r) +' (t *' s)"

min_0 [rule_format] : "ALL m. min'(m, 0') = 0'"

div_mod_Nat [rule_format] :
"ALL m.
 ALL X_n.
 ~ X_n = 0' -->
 makePartial m =
 restrictOp
 (makePartial
  ((makeTotal (m div' X_n) *' X_n) +' makeTotal (m mod' X_n)))
 (defOp (m div' X_n) & defOp (m mod' X_n))"

power_Nat [rule_format] :
"ALL m. ALL r. ALL s. m ^' (r +' s) = (m ^' r) *' (m ^' s)"

Comp1 [rule_format] :
"ALL f. ALL g. ALL y. X__o__X (f, g) y = f (g y)"

IdDef [rule_format] : "ALL x. id'(x) = x"

FlipDef [rule_format] : "ALL f. ALL x. ALL y. X_flip f y x = f x y"

FstDef [rule_format] : "ALL x. ALL y. fst'(x, y) = x"

SndDef [rule_format] : "ALL x. ALL y. snd'(x, y) = y"

CurryDef [rule_format] :
"ALL g. ALL x. ALL y. X_curry g x y = g (x, y)"

UncurryDef [rule_format] :
"ALL f. ALL x. ALL y. uncurry f (x, y) = f x y"

NotFalse [rule_format] : "Not' False"

NotTrue [rule_format] : "~ Not' True"

AndFalse [rule_format] : "ALL x. ~ False && x"

AndTrue [rule_format] : "ALL x. True && x = x"

AndSym [rule_format] : "ALL x. ALL y. x && y = y && x"

OrDef [rule_format] :
"ALL x. ALL y. x || y = Not' (Not' x && Not' y)"

OtherwiseDef [rule_format] : "otherwiseH"

NotFalse1 [rule_format] : "ALL x. Not' x = (~ x)"

NotTrue1 [rule_format] : "ALL x. ~ Not' x = x"

notNot1 [rule_format] : "ALL x. (~ x) = Not' x"

notNot2 [rule_format] : "ALL x. (~ ~ x) = (~ Not' x)"

EqualTDef [rule_format] : "ALL x. ALL y. x = y --> x ==' y"

EqualSymDef [rule_format] : "ALL x. ALL y. x ==' y = y ==' x"

EqualReflex [rule_format] : "ALL x. x ==' x"

EqualTransT [rule_format] :
"ALL x. ALL y. ALL z. x ==' y & y ==' z --> x ==' z"

DiffDef [rule_format] : "ALL x. ALL y. x /= y = Not' (x ==' y)"

DiffSymDef [rule_format] : "ALL x. ALL y. x /= y = y /= x"

DiffTDef [rule_format] : "ALL x. ALL y. x /= y = Not' (x ==' y)"

DiffFDef [rule_format] : "ALL x. ALL y. (~ x /= y) = x ==' y"

TE1 [rule_format] : "ALL x. ALL y. ~ x ==' y --> ~ x = y"

TE2 [rule_format] : "ALL x. ALL y. Not' (x ==' y) = (~ x ==' y)"

TE3 [rule_format] : "ALL x. ALL y. (~ Not' (x ==' y)) = x ==' y"

TE4 [rule_format] : "ALL x. ALL y. (~ x ==' y) = (~ x ==' y)"

IUE1 [rule_format] : "() ==' ()"

IUE2 [rule_format] : "~ () /= ()"

IBE1 [rule_format] : "() ==' ()"

IBE2 [rule_format] : "False & () ==' ()"

IBE3 [rule_format] : "~ (False & () ==' ())"

IBE4 [rule_format] : "~ (False & () ==' ())"

IBE5 [rule_format] : "False & () /= ()"

IBE6 [rule_format] : "False & () /= ()"

IBE7 [rule_format] : "Not' (False & () ==' ())"

IBE8 [rule_format] : "~ Not' Not' (False & () ==' ())"

IOE01 [rule_format] : "LT ==' LT"

IOE02 [rule_format] : "EQ ==' EQ"

IOE03 [rule_format] : "GT ==' GT"

IOE04 [rule_format] : "~ LT ==' EQ"

IOE05 [rule_format] : "~ LT ==' GT"

IOE06 [rule_format] : "~ EQ ==' GT"

IOE07 [rule_format] : "LT /= EQ"

IOE08 [rule_format] : "LT /= GT"

IOE09 [rule_format] : "EQ /= GT"

LeIrreflexivity [rule_format] :
"ALL x. ALL y. x ==' y --> ~ x <'' y"

LeTAsymmetry [rule_format] : "ALL x. ALL y. x <'' y --> ~ y <'' x"

LeTTransitive [rule_format] :
"ALL x. ALL y. ALL z. x <'' y & y <'' z --> x <'' z"

LeTTotal [rule_format] :
"ALL x. ALL y. (x <'' y | y <'' x) | x ==' y"

GeDef [rule_format] : "ALL x. ALL y. x >'' y = y <'' x"

GeIrreflexivity [rule_format] :
"ALL x. ALL y. x ==' y --> ~ x >'' y"

GeTAsymmetry [rule_format] : "ALL x. ALL y. x >'' y --> ~ y >'' x"

GeTTransitive [rule_format] :
"ALL x. ALL y. ALL z. (x >'' y) && (y >'' z) --> x >'' z"

GeTTotal [rule_format] :
"ALL x. ALL y. ((x >'' y) || (y >'' x)) || (x ==' y)"

LeqDef [rule_format] :
"ALL x. ALL y. x <='' y = (x <'' y) || (x ==' y)"

LeqReflexivity [rule_format] : "ALL x. x <='' x"

LeqTTransitive [rule_format] :
"ALL x. ALL y. ALL z. (x <='' y) && (y <='' z) --> x <='' z"

LeqTTotal [rule_format] :
"ALL x. ALL y. (x <='' y) && (y <='' x) = x ==' y"

GeqDef [rule_format] :
"ALL x. ALL y. x >='' y = (x >'' y) || (x ==' y)"

GeqReflexivity [rule_format] : "ALL x. x >='' x"

GeqTTransitive [rule_format] :
"ALL x. ALL y. ALL z. (x >='' y) && (y >='' z) --> x >='' z"

GeqTTotal [rule_format] :
"ALL x. ALL y. (x >='' y) && (y >='' x) = x ==' y"

EqTSOrdRel [rule_format] :
"ALL x. ALL y. x ==' y = (~ x <'' y & ~ x >'' y)"

EqFSOrdRel [rule_format] :
"ALL x. ALL y. (~ x ==' y) = (x <'' y | x >'' y)"

EqTOrdRel [rule_format] :
"ALL x. ALL y. x ==' y = (x <='' y & x >='' y)"

EqFOrdRel [rule_format] :
"ALL x. ALL y. (~ x ==' y) = (x <='' y | x >='' y)"

EqTOrdTSubstE [rule_format] :
"ALL x. ALL y. ALL z. x ==' y & y <'' z --> x <'' z"

EqTOrdFSubstE [rule_format] :
"ALL x. ALL y. ALL z. x ==' y & ~ y <'' z --> ~ x <'' z"

EqTOrdTSubstD [rule_format] :
"ALL x. ALL y. ALL z. x ==' y & z <'' y --> z <'' x"

EqTOrdFSubstD [rule_format] :
"ALL x. ALL y. ALL z. x ==' y & ~ z <'' y --> ~ z <'' x"

LeTGeFEqFRel [rule_format] :
"ALL x. ALL y. x <'' y = (~ x >'' y & ~ x ==' y)"

LeFGeTEqTRel [rule_format] :
"ALL x. ALL y. (~ x <'' y) = (x >'' y | x ==' y)"

LeTGeTRel [rule_format] : "ALL x. ALL y. x <'' y = y >'' x"

LeFGeFRel [rule_format] : "ALL x. ALL y. (~ x <'' y) = (~ y >'' x)"

LeqTGetTRel [rule_format] : "ALL x. ALL y. x <='' y = y >='' x"

LeqFGetFRel [rule_format] :
"ALL x. ALL y. (~ x <='' y) = (~ y >='' x)"

GeTLeTRel [rule_format] : "ALL x. ALL y. x >'' y = y <'' x"

GeFLeFRel [rule_format] : "ALL x. ALL y. (~ x >'' y) = (~ y <'' x)"

GeqTLeqTRel [rule_format] : "ALL x. ALL y. x >='' y = y <='' x"

GeqFLeqFRel [rule_format] :
"ALL x. ALL y. (~ x >='' y) = (~ y <='' x)"

LeqTGeFRel [rule_format] : "ALL x. ALL y. x <='' y = (~ x >'' y)"

LeqFGeTRel [rule_format] : "ALL x. ALL y. (~ x <='' y) = x >'' y"

GeTLeFEqFRel [rule_format] :
"ALL x. ALL y. x >'' y = (~ x <'' y & ~ x ==' y)"

GeFLeTEqTRel [rule_format] :
"ALL x. ALL y. (~ x >'' y) = (x <'' y | x ==' y)"

GeqTLeFRel [rule_format] : "ALL x. ALL y. x >='' y = (~ x <'' y)"

GeqFLeTRel [rule_format] : "ALL x. ALL y. (~ x >='' y) = x <'' y"

LeqTLeTEqTRel [rule_format] :
"ALL x. ALL y. x <='' y = (x <'' y | x ==' y)"

LeqFLeFEqFRel [rule_format] :
"ALL x. ALL y. (~ x <='' y) = (~ x <'' y & ~ x ==' y)"

GeqTGeTEqTRel [rule_format] :
"ALL x. ALL y. x >='' y = (x >'' y | x ==' y)"

GeqFGeFEqFRel [rule_format] :
"ALL x. ALL y. (~ x >='' y) = (~ x >'' y & ~ x ==' y)"

LeTGeqFRel [rule_format] : "ALL x. ALL y. x <'' y = (~ x >='' y)"

GeTLeqFRel [rule_format] : "ALL x. ALL y. x >'' y = (~ x <='' y)"

LeLeqDiff [rule_format] :
"ALL x. ALL y. x <'' y = (x <='' y) && (x /= y)"

CmpLTDef [rule_format] :
"ALL x. ALL y. compare x y ==' LT = x <'' y"

CmpEQDef [rule_format] :
"ALL x. ALL y. compare x y ==' EQ = x ==' y"

CmpGTDef [rule_format] :
"ALL x. ALL y. compare x y ==' GT = x >'' y"

MaxYDef [rule_format] :
"ALL x. ALL y. X_maxX2 x y ==' y = x <='' y"

MaxXDef [rule_format] :
"ALL x. ALL y. X_maxX2 x y ==' x = y <='' x"

MinXDef [rule_format] :
"ALL x. ALL y. X_minX2 x y ==' x = x <='' y"

MinYDef [rule_format] :
"ALL x. ALL y. X_minX2 x y ==' y = y <='' x"

MaxSym [rule_format] :
"ALL x. ALL y. X_maxX2 x y ==' y = X_maxX2 y x ==' y"

MinSym [rule_format] :
"ALL x. ALL y. X_minX2 x y ==' y = X_minX2 y x ==' y"

TO1 [rule_format] : "ALL x. ALL y. (x ==' y | x <'' y) = x <='' y"

TO2 [rule_format] : "ALL x. ALL y. x ==' y --> ~ x <'' y"

TO3 [rule_format] :
"ALL x. ALL y. Not' Not' (x <'' y) | Not' (x <'' y)"

TO4 [rule_format] : "ALL x. ALL y. x <'' y --> Not' (x ==' y)"

TO5 [rule_format] :
"ALL w.
 ALL x. ALL y. ALL z. (x <'' y & y <'' z) & z <'' w --> x <'' w"

TO6 [rule_format] : "ALL x. ALL z. z <'' x --> Not' (x <'' z)"

TO7 [rule_format] : "ALL x. ALL y. x <'' y = y >'' x"

IUO01 [rule_format] : "() <='' ()"

IUO02 [rule_format] : "bool2partial (() <'' ()) = undefinedOp"

IUO03 [rule_format] : "() >='' ()"

IUO04 [rule_format] : "bool2partial (() >'' ()) = undefinedOp"

IUO05 [rule_format] : "X_maxX2 () () ==' ()"

IUO06 [rule_format] : "X_minX2 () () ==' ()"

IUO07 [rule_format] : "compare () () ==' EQ"

IOO13 [rule_format] : "LT <'' EQ"

IOO14 [rule_format] : "EQ <'' GT"

IOO15 [rule_format] : "LT <'' GT"

IOO16 [rule_format] : "LT <='' EQ"

IOO17 [rule_format] : "EQ <='' GT"

IOO18 [rule_format] : "LT <='' GT"

IOO19 [rule_format] : "EQ >='' LT"

IOO20 [rule_format] : "GT >='' EQ"

IOO21 [rule_format] : "GT >='' LT"

IOO22 [rule_format] : "EQ >'' LT"

IOO23 [rule_format] : "GT >'' EQ"

IOO24 [rule_format] : "GT >'' LT"

IOO25 [rule_format] : "X_maxX2 LT EQ ==' EQ"

IOO26 [rule_format] : "X_maxX2 EQ GT ==' GT"

IOO27 [rule_format] : "X_maxX2 LT GT ==' GT"

IOO28 [rule_format] : "X_minX2 LT EQ ==' LT"

IOO29 [rule_format] : "X_minX2 EQ GT ==' EQ"

IOO30 [rule_format] : "X_minX2 LT GT ==' LT"

IOO31 [rule_format] : "compare LT LT ==' EQ"

IOO32 [rule_format] : "compare EQ EQ ==' EQ"

IOO33 [rule_format] : "compare GT GT ==' EQ"

IBO5 [rule_format] : "False & () <'' ()"

IBO6 [rule_format] : "~ (False & () >='' ())"

IBO7 [rule_format] : "False & () >='' ()"

IBO8 [rule_format] : "~ (False & () <'' ())"

IBO9 [rule_format] : "False & X_maxX2 () () ==' ()"

IBO10 [rule_format] : "False & X_minX2 () () ==' ()"

IBO11 [rule_format] : "compare () () ==' EQ"

IBO12 [rule_format] : "False & compare () () ==' EQ"

LengthNil [rule_format] : "length'(Nil') = 0'"

LengthCons [rule_format] :
"ALL x. ALL xs. length'(X_Cons x xs) = suc(length'(xs))"

NotDefHead [rule_format] : "~ defOp (head(Nil'))"

HeadDef [rule_format] :
"ALL x. ALL xs. head(X_Cons x xs) = makePartial x"

NotDefTail [rule_format] : "~ defOp (tail(Nil'))"

TailDef [rule_format] :
"ALL x. ALL xs. tail(X_Cons x xs) = makePartial xs"

FoldrNil [rule_format] : "ALL f. ALL s. X_foldr f s Nil' = s"

FoldrCons [rule_format] :
"ALL f.
 ALL s.
 ALL x. ALL xs. X_foldr f s (X_Cons x xs) = f x (X_foldr f s xs)"

FoldlNil [rule_format] : "ALL g. ALL t. X_foldl g t Nil' = t"

FoldlCons [rule_format] :
"ALL g.
 ALL t.
 ALL z. ALL zs. X_foldl g t (X_Cons z zs) = X_foldl g (g t z) zs"

MapNil [rule_format] : "ALL h. X_map h Nil' = Nil'"

MapCons [rule_format] :
"ALL h.
 ALL x. ALL xs. X_map h (X_Cons x xs) = X_Cons (h x) (X_map h xs)"

XPlusXPlusNil [rule_format] : "ALL l. Nil' ++' l = l"

XPlusXPlusCons [rule_format] :
"ALL l. ALL x. ALL xs. X_Cons x xs ++' l = X_Cons x (xs ++' l)"

XPlusXPlusPrefixDef [rule_format] :
"ALL xs. ALL ys. XLtXPlusXPlusXGt xs ys = xs ++' ys"

FilterNil [rule_format] : "ALL p. X_filter p Nil' = Nil'"

FilterConsT [rule_format] :
"ALL p.
 ALL x.
 ALL xs.
 p x --> X_filter p (X_Cons x xs) = X_Cons x (X_filter p xs)"

FilterConsF [rule_format] :
"ALL p.
 ALL x.
 ALL xs.
 bool2partial (p x) = undefinedOp -->
 X_filter p (X_Cons x xs) = X_filter p xs"

ZipNil [rule_format] : "ALL l. X_zip Nil' l = Nil'"

ZipConsNil [rule_format] :
"ALL l. ALL x. ALL xs. l = Nil' --> X_zip (X_Cons x xs) l = Nil'"

ZipConsCons [rule_format] :
"ALL l.
 ALL x.
 ALL xs.
 ALL y.
 ALL ys.
 l = X_Cons y ys -->
 X_zip (X_Cons x xs) l = X_Cons (x, y) (X_zip xs ys)"

UnzipNil [rule_format] : "unzip(Nil') = (Nil', Nil')"

UnzipCons [rule_format] :
"ALL ps.
 ALL x.
 ALL z.
 unzip(X_Cons (x, z) ps) =
 (let (ys, zs) = unzip(ps) in (X_Cons x ys, X_Cons z zs))"

ILE02 [rule_format] :
"ALL x.
 ALL xs.
 ALL y.
 ALL ys. X_Cons x xs ==' X_Cons y ys = (x ==' y) && (xs ==' ys)"

ILO05 [rule_format] :
"ALL w.
 ALL ws. ALL z. ALL zs. z <'' w --> X_Cons z zs <'' X_Cons w ws"

ILO06 [rule_format] :
"ALL w.
 ALL ws.
 ALL z. ALL zs. z ==' w --> X_Cons z zs <'' X_Cons w ws = zs <'' ws"

ILO07 [rule_format] :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 bool2partial (z <'' w) = undefinedOp &
 bool2partial (z ==' w) = undefinedOp -->
 bool2partial (X_Cons z zs <'' X_Cons w ws) = undefinedOp"

declare ga_selector_pre [simp]
declare ga_selector_undef_pre_0 [simp]
declare ga_comm___XPlus__ [simp]
declare ga_assoc___XPlus__ [simp]
declare ga_right_unit___XPlus__ [simp]
declare ga_left_unit___XPlus__ [simp]
declare ga_left_comm___XPlus__ [simp]
declare ga_comm___Xx__ [simp]
declare ga_assoc___Xx__ [simp]
declare ga_right_unit___Xx__ [simp]
declare ga_left_unit___Xx__ [simp]
declare ga_left_comm___Xx__ [simp]
declare ga_comm_min [simp]
declare ga_assoc_min [simp]
declare ga_left_comm_min [simp]
declare ga_comm_max [simp]
declare ga_assoc_max [simp]
declare ga_right_unit_max [simp]
declare ga_left_unit_max [simp]
declare ga_left_comm_max [simp]
declare leq_def1_Nat [simp]
declare leq_def2_Nat [simp]
declare leq_def3_Nat [simp]
declare even_0_Nat [simp]
declare even_suc_Nat [simp]
declare factorial_0 [simp]
declare add_0_Nat [simp]
declare mult_0_Nat [simp]
declare power_0_Nat [simp]
declare subTotal_def1_Nat [simp]
declare subTotal_def2_Nat [simp]
declare sub_dom_Nat [simp]
declare divide_0_Nat [simp]
declare min_0 [simp]
declare Comp1 [simp]
declare IdDef [simp]
declare FlipDef [simp]
declare FstDef [simp]
declare SndDef [simp]
declare CurryDef [simp]
declare UncurryDef [simp]
declare NotFalse [simp]
declare NotTrue [simp]
declare AndFalse [simp]
declare AndTrue [simp]
declare OtherwiseDef [simp]
declare NotTrue1 [simp]
declare EqualReflex [simp]
declare IUE1 [simp]
declare IUE2 [simp]
declare IBE1 [simp]
declare IBE2 [simp]
declare IBE5 [simp]
declare IBE6 [simp]
declare IOE01 [simp]
declare IOE02 [simp]
declare IOE03 [simp]
declare IOE04 [simp]
declare IOE05 [simp]
declare IOE06 [simp]
declare IOE07 [simp]
declare IOE08 [simp]
declare IOE09 [simp]
declare LeIrreflexivity [simp]
declare LeTAsymmetry [simp]
declare GeIrreflexivity [simp]
declare GeTAsymmetry [simp]
declare GeTTransitive [simp]
declare GeTTotal [simp]
declare LeqReflexivity [simp]
declare LeqTTransitive [simp]
declare LeqTTotal [simp]
declare GeqReflexivity [simp]
declare GeqTTransitive [simp]
declare GeqTTotal [simp]
declare CmpLTDef [simp]
declare CmpEQDef [simp]
declare CmpGTDef [simp]
declare MaxYDef [simp]
declare MaxXDef [simp]
declare MinXDef [simp]
declare MinYDef [simp]
declare TO2 [simp]
declare TO4 [simp]
declare TO6 [simp]
declare IUO01 [simp]
declare IUO02 [simp]
declare IUO03 [simp]
declare IUO04 [simp]
declare IUO05 [simp]
declare IUO06 [simp]
declare IUO07 [simp]
declare IOO13 [simp]
declare IOO14 [simp]
declare IOO15 [simp]
declare IOO16 [simp]
declare IOO17 [simp]
declare IOO18 [simp]
declare IOO19 [simp]
declare IOO20 [simp]
declare IOO21 [simp]
declare IOO22 [simp]
declare IOO23 [simp]
declare IOO24 [simp]
declare IOO25 [simp]
declare IOO26 [simp]
declare IOO27 [simp]
declare IOO28 [simp]
declare IOO29 [simp]
declare IOO30 [simp]
declare IOO31 [simp]
declare IOO32 [simp]
declare IOO33 [simp]
declare IBO5 [simp]
declare IBO7 [simp]
declare IBO9 [simp]
declare IBO10 [simp]
declare IBO11 [simp]
declare IBO12 [simp]
declare LengthNil [simp]
declare LengthCons [simp]
declare NotDefHead [simp]
declare HeadDef [simp]
declare NotDefTail [simp]
declare TailDef [simp]
declare FoldrNil [simp]
declare FoldlNil [simp]
declare MapNil [simp]
declare XPlusXPlusNil [simp]
declare FilterNil [simp]
declare FilterConsF [simp]
declare ZipNil [simp]
declare ILO05 [simp]
declare ILO06 [simp]

theorem ILE01 : "Nil' ==' Nil'"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"ILE01\""

theorem ILO01 : "bool2partial (Nil' <'' Nil') = undefinedOp"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"ILO01\""

theorem ILO02 : "Nil' <='' Nil'"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"ILO02\""

theorem ILO03 : "bool2partial (Nil' >'' Nil') = undefinedOp"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"ILO03\""

theorem ILO04 : "Nil' >='' Nil'"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"ILO04\""

theorem ILO08 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons z zs <='' X_Cons w ws =
 (X_Cons z zs <'' X_Cons w ws) || (X_Cons z zs ==' X_Cons w ws)"
apply(rule allI)+
apply(simp only: LeqDef)
done

ML "Header.record \"ILO08\""

theorem ILO09 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs. X_Cons z zs >'' X_Cons w ws = X_Cons w ws <'' X_Cons z zs"
apply(rule allI)+
apply(case_tac "X_Cons z zs >'' X_Cons w ws")
apply(simp only: GeFLeFRel)
apply(simp only: GeTLeTRel)
done

ML "Header.record \"ILO09\""

theorem ILO10 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons z zs >='' X_Cons w ws =
 (X_Cons z zs >'' X_Cons w ws) || (X_Cons z zs ==' X_Cons w ws)"
apply(rule allI)+
apply(simp only: GeqDef)
done

ML "Header.record \"ILO10\""

theorem ILO11 : "compare Nil' Nil' ==' EQ = Nil' ==' Nil'"
by (auto)

ML "Header.record \"ILO11\""

theorem ILO12 : "compare Nil' Nil' ==' LT = Nil' <'' Nil'"
by (auto)

ML "Header.record \"ILO12\""

theorem ILO13 : "compare Nil' Nil' ==' GT = Nil' >'' Nil'"
by (auto)

ML "Header.record \"ILO13\""

theorem ILO14 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 compare (X_Cons z zs) (X_Cons w ws) ==' EQ =
 X_Cons z zs ==' X_Cons w ws"
apply(rule allI)+
apply(simp only: CmpEQDef)
done

ML "Header.record \"ILO14\""

theorem ILO15 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 compare (X_Cons z zs) (X_Cons w ws) ==' LT =
 X_Cons z zs <'' X_Cons w ws"
apply(rule allI)+
apply(simp only: CmpLTDef)
done

ML "Header.record \"ILO15\""

theorem ILO16 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 compare (X_Cons z zs) (X_Cons w ws) ==' GT =
 X_Cons z zs >'' X_Cons w ws"
apply(rule allI)+
apply(simp only: CmpGTDef)
done

ML "Header.record \"ILO16\""

theorem ILO17 : "X_maxX2 Nil' Nil' ==' Nil' = Nil' <='' Nil'"
by (auto)

ML "Header.record \"ILO17\""

theorem ILO18 : "X_minX2 Nil' Nil' ==' Nil' = Nil' <='' Nil'"
by (auto)

ML "Header.record \"ILO18\""

theorem ILO19 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons z zs <='' X_Cons w ws =
 X_maxX2 (X_Cons z zs) (X_Cons w ws) ==' X_Cons w ws"
apply(rule allI)+
apply(simp add: LeqDef)
done

ML "Header.record \"ILO19\""

theorem ILO20 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons w ws <='' X_Cons z zs =
 X_maxX2 (X_Cons z zs) (X_Cons w ws) ==' X_Cons z zs"
apply(rule allI)+
apply(simp add: LeqDef)
done

ML "Header.record \"ILO20\""

theorem ILO21 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons z zs <='' X_Cons w ws =
 X_minX2 (X_Cons z zs) (X_Cons w ws) ==' X_Cons z zs"
apply(rule allI)+
apply(simp add: LeqDef)
done

ML "Header.record \"ILO21\""

theorem ILO22 :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons w ws <='' X_Cons z zs =
 X_minX2 (X_Cons z zs) (X_Cons w ws) ==' X_Cons w ws"
apply(rule allI)+
apply(simp add: LeqDef)
done

ML "Header.record \"ILO22\""

theorem FoldlDecomp :
"ALL e.
 ALL i.
 ALL ts.
 ALL ys. X_foldl i e (ys ++' ts) = X_foldl i (X_foldl i e ys) ts"
apply(auto)
apply(case_tac "ys ++' ts")
apply(auto)
apply(simp add: FoldlCons)
apply(induct_tac List)
apply(simp add: FoldlCons)
oops

ML "Header.record \"FoldlDecomp\""

theorem MapDecomp :
"ALL f.
 ALL xs. ALL zs. X_map f (xs ++' zs) = X_map f xs ++' X_map f zs"
apply(auto)
apply(induct_tac xs)
apply(auto)
apply(simp add: MapCons XPlusXPlusCons)
done

ML "Header.record \"MapDecomp\""

theorem MapFunctor :
"ALL f.
 ALL g. ALL xs. X_map (X__o__X (g, f)) xs = X_map g (X_map f xs)"
apply(auto)
apply(induct_tac xs)
apply(auto)
apply(simp add: MapNil MapCons Comp1)
done

ML "Header.record \"MapFunctor\""

theorem FilterProm :
"ALL f.
 ALL p.
 ALL xs.
 X_filter p (X_map f xs) =
 X_map f (X_filter (constTrue o X__o__X (constNil o p, f)) xs)"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"FilterProm\""

theorem LengthNil1 : "ALL xs. length'(xs) = 0' = (xs = Nil')"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"LengthNil1\""

theorem LengthEqualNil :
"ALL ys. length'(Nil') = length'(ys) --> ys = Nil'"
using X1_def_Nat X2_def_Nat X3_def_Nat X4_def_Nat X5_def_Nat
      X6_def_Nat X7_def_Nat X8_def_Nat X9_def_Nat decimal_def
by (auto)

ML "Header.record \"LengthEqualNil\""

theorem LengthEqualCons :
"ALL x.
 ALL xs.
 ALL y.
 ALL ys.
 length'(X_Cons x xs) = length'(X_Cons y ys) -->
 length'(xs) = length'(ys)"
by (auto)

ML "Header.record \"LengthEqualCons\""

theorem ZipSpec :
"ALL xs.
 ALL ys.
 length'(xs) = length'(ys) --> unzip(X_zip xs ys) = (xs, ys)"
oops
(*
theorem ZipSpec:
assumes "length'(xs) = length'(ys)"
 shows "unzip(X_zip xs ys) = (xs, ys)"
using assms proof (induct xs arbitrary: ys)
 fix ys
 assume "length'(Nil') = length'(ys)"
 then have "ys = Nil'" by (simp add: LengthEqualNil)
 then show "unzip(X_zip Nil' ys) = (Nil', ys)" by (simp add: ZipNil UnzipNil)
next
 fix x
 fix xs::"'a List"
 fix ys::"'b List"
 assume 1: "!!ys::'b List. length'(xs) = length'(ys) ==>
   unzip(X_zip xs ys) = (xs, ys)"
 assume 2: "length'(X_Cons x xs) = length'(ys)"
 then obtain z zs where ys: "ys = X_Cons z zs" and
   length: "length'(xs) = length'(zs)"
   sorry
 hence H: "unzip(X_zip xs zs) = (xs, zs)" using 1 by simp
 have "unzip(X_zip (X_Cons x xs) ys) = unzip(X_zip (X_Cons x xs) (X_Cons z zs))"
   using ys by simp
 also have "... = unzip(X_Cons (x, z) (X_zip xs zs))"
   by (metis ZipConsCons ys)
 also have "... = (X_Cons x xs, X_Cons z zs)"
   using H by (simp add: UnzipCons Let_def)
 also have "... = (X_Cons x xs, ys)" using ys by simp
 finally show "unzip(X_zip (X_Cons x xs) ys) = (X_Cons x xs, ys)" .
qed
*)

ML "Header.record \"ZipSpec\""

end


theory Array_Iterator
imports Iterator "../Lib/Diff_Array"
begin

lemma idx_iteratei_aux_array_get_Array_conv_nth:
  "idx_iteratei_aux array_get sz i (Array xs) c f \<sigma> =
   idx_iteratei_aux op ! sz i xs c f \<sigma>"
apply(induct get\<equiv>"op ! :: 'b list \<Rightarrow> nat \<Rightarrow> 'b" sz i xs c f \<sigma> rule: idx_iteratei_aux.induct)
apply(subst (1 2) idx_iteratei_aux.simps)
apply simp
done

lemma idx_iteratei_array_get_Array_conv_nth:
  "idx_iteratei array_get array_length (Array xs) = idx_iteratei nth length xs"
by(simp add: idx_iteratei_def fun_eq_iff idx_iteratei_aux_array_get_Array_conv_nth)

end


(*<*)
theory Framework
imports Main
begin
(*>*)

section\<open>{On the framework used \label{sec:Framework}}\<close>

text\<open>\noindent %
To start off, we shall give an overview on the framework this thesis was written in, that is,
enlist the relevant software components used and explain the core features of Isabelle/HOL since it is the most important component. \<close>

subsection\<open>{The components \label{subsec:Components}}\<close>
text\<open>
There are three main tools used to write this thesis:
\begin{description}
\item [Isabelle/HOL] A proof assistant that provides an environment to axiomatize and utilize deduction systems with which one can formulate
theorems and prove them. It was used to represent the Constitution's model on the computer and conduct reasoning with it.
\item [\LaTeX] A typesetting software. It is very convenient for mathematical formulas. Isabelle has an inbuilt tool to use \LaTeX. This was used
to typeset the code written with Isabelle.
\item [Git] Version control software to keep track of changes and return to older versions where necessary.
\end{description}
\<close>

subsection\<open>{Short introduction to Isabelle/HOL \label{subsec:Isabelle}}\<close>

text\<open>\noindent %
 Depending on the context, the way Isabelle is used can vary greatly. The following shall illustrate how we will be using it%
\footnote{For a general introduction see the manual \cite{isabelle-reference}}.
First we give an outline of the steps taken and then illustrate those with examples.

\noindent Here is the outline:
\begin{enumerate}
\item Provide definitions of types, concepts, operators used.
\item State all assumptions in the form of axioms.
\item State theorems.
\item Test your theory by trying to refute/prove the theorems. Use tools Sledgehammer and Nitpick%
\footnote{See also the manuals on Sledgehammer \cite{isabelle-sledgehammer} and on Nitpick \cite{isabelle-nitpick}} to do so.
\end{enumerate}
\<close>

text\<open>\noindent %
 \textbf{ 1. Provide definitions of types, concepts, operators used.}

\noindent We can define our own data types or work with predefined ones. Here we introduce a data type @{text "bvg"} (\emph{beverage}) and a type
@{text "temp"} (\emph{temperature}). The latter is just a synonym for predefined type @{text "int"}.
\<close>
datatype bvg = tea | coffee | juice
type_synonym temp="int"

text\<open>\noindent %
 Next we define predicates and operators.\<close>

consts tempOf::"bvg\<Rightarrow>temp"
  \<comment> \<open>determines temperature of bvg\<close>

definition totalTemp::"temp"
  where "totalTemp \<equiv> (tempOf tea) + (tempOf coffee) + (tempOf juice)"
  \<comment> \<open>determines total temperature of all bvg-instances\<close>

definition tooHot::"bvg\<Rightarrow>bool"
  where "tooHot b \<equiv> if(b=juice)then(tempOf b > 5) else (tempOf b > 20)"
  \<comment> \<open>determines if a beverage is too hot. For @{text "juice"} this is the case iff its temperature is @{text ">5"}, for @{text "tea"}
and @{text "coffee"} iff the temperature is @{text ">20"}\<close>

text\<open>\noindent %
 \textbf{2. State all assumptions in the form of axioms.}

\noindent Note that we introduce a contradiction with the two axioms @{text "teaHot tea"} and @{text "tempOf tea = 10"}
\<close>

axiomatization where
teaHot:     "tooHot tea"         and
teaTemp10:  "(tempOf tea)=10"    and
coffeeTemp5:"(tempOf coffee)=5"  and
juiceTemp2: "(tempOf juice)=2"

text\<open>\noindent %
 \textbf{3. State theorems and 4. Test your theory by trying to refute/prove the theorems.}

\noindent These steps have to be conducted together since Isabelle requires theorems to be proven. It is not possible
to enumerate theorems without proofs unless you use keyword @{command "oops"} to signify that a theorem has not been proven yet.\\

\noindent \emph{Sledgehammer} can be used to find proofs and \emph{Nitpick} to find counter models and satisfying models.
\<close>

theorem totalTemp17:"totalTemp = 17" sledgehammer
  by (simp add: coffeeTemp5 juiceTemp2 teaTemp10 totalTemp_def)

lemma basic_unsat:"False" using teaHot teaTemp10 tooHot_def sledgehammer
  by simp

lemma basic_sat:"True" nitpick[show_all,user_axioms] oops

text\<open>\noindent %
Note that our axioms are inconsistent, so we can prove @{text "basic_unsat"}. Nitpick can neither find a counter model nor a satisfying one.
However, if we remove axiom @{text "teaHot"} or @{text "teaTemp10"} lemma @{text "basic_unsat"} becomes unprovable and Nitpick will find a
satisfying model for lemma @{text "basic_sat"}. To look for a satisfying model rather than a refuting one, we simply add option
@{text "satifsy"}.
   \<close>

(*<*)
end
(*>*)


header {* \isachapter{The Framework}

  As slicing is a program analysis that can be completely based on the
  information given in the CFG, we want to provide a framework which
  allows us to formalize and prove properties of slicing regardless of
  the actual programming language. So the starting point for the formalization
  is the definition of an abstract CFG, i.e.\ without considering features
  specific for certain languages. By doing so we ensure that our framework
  is as generic as possible since all proofs hold for every language whose
  CFG conforms to this abstract CFG.

  Static Slicing analyses a CFG prior to execution. Whereas dynamic
  slicing can provide better results for certain inputs (i.e.\ trace and
  initial state), static slicing is more conservative but provides
  results independent of inputs.

  Correctness for static slicing is defined using a weak
  simulation between nodes and states when traversing the original and
  the sliced graph. The weak simulation property demands that if a
  (node,state) tuples $(n_1,s_1)$ simulates $(n_2,s_2)$
  and making an observable move in the original graph leads from
  $(n_1,s_1)$ to $(n_1',s_1')$, this tuple simulates a
  tuple $(n_2,s_2)$ which is the result of making an
  observable move in the sliced graph beginning in $(n_2',s_2')$.

  \isaheader{Basic Definitions} *}

theory BasicDefs imports AuxLemmas begin

fun fun_upds :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a list \<Rightarrow> 'b list \<Rightarrow> ('a \<Rightarrow> 'b)"
where "fun_upds f [] ys = f"
  | "fun_upds f xs [] = f"
  | "fun_upds f (x#xs) (y#ys) = (fun_upds f xs ys)(x := y)"

notation fun_upds ("_'(_ /[:=]/ _')")

lemma fun_upds_nth:
  "\<lbrakk>i < length xs; length xs = length ys; distinct xs\<rbrakk>
  \<Longrightarrow> f(xs [:=] ys)(xs!i) = (ys!i)"
proof(induct xs arbitrary:ys i)
  case Nil thus ?case by simp
next
  case (Cons x' xs')
  note IH = `\<And>ys i. \<lbrakk>i < length xs'; length xs' = length ys; distinct xs'\<rbrakk>
    \<Longrightarrow> f(xs' [:=] ys) (xs'!i) = ys!i`
  from `distinct (x'#xs')` have "distinct xs'" and "x' \<notin> set xs'" by simp_all
  from `length (x'#xs') = length ys` obtain y' ys' where [simp]:"ys = y'#ys'"
    and "length xs' = length ys'"
    by(cases ys) auto
  show ?case
  proof(cases i)
    case 0 thus ?thesis by simp
  next
    case (Suc j)
    with `i < length (x'#xs')` have "j < length xs'" by simp
    from IH[OF this `length xs' = length ys'` `distinct xs'`]
    have "f(xs' [:=] ys') (xs'!j) = ys'!j" .
    with `x' \<notin> set xs'` `j < length xs'`
    have "f((x'#xs') [:=] ys) ((x'#xs')!(Suc j)) = ys!(Suc j)" by fastforce
    with Suc show ?thesis by simp
  qed
qed

lemma fun_upds_eq:
  assumes "V \<in> set xs" and "length xs = length ys" and "distinct xs"
  shows "f(xs [:=] ys) V = f'(xs [:=] ys) V"
proof -
  from `V \<in> set xs` obtain i where "i < length xs" and "xs!i = V"
    by(fastforce simp:in_set_conv_nth)
  with `length xs = length ys` `distinct xs`
  have "f(xs [:=] ys)(xs!i) = (ys!i)" by -(rule fun_upds_nth)
  moreover
  from `i < length xs` `xs!i = V` `length xs = length ys` `distinct xs`
  have "f'(xs [:=] ys)(xs!i) = (ys!i)" by -(rule fun_upds_nth)
  ultimately show ?thesis using `xs!i = V` by simp
qed

lemma fun_upds_notin:"x \<notin> set xs \<Longrightarrow> f(xs [:=] ys) x = f x"
by(induct xs arbitrary:ys,auto,case_tac ys,auto)

subsection {*@{text distinct_fst}*}

definition distinct_fst :: "('a \<times> 'b) list \<Rightarrow> bool" where
  "distinct_fst  \<equiv>  distinct \<circ> map fst"

lemma distinct_fst_Nil [simp]:
  "distinct_fst []"
  by(simp add:distinct_fst_def)

lemma distinct_fst_Cons [simp]:
  "distinct_fst ((k,x)#kxs) = (distinct_fst kxs \<and> (\<forall>y. (k,y) \<notin> set kxs))"
by(auto simp:distinct_fst_def image_def)

lemma distinct_fst_isin_same_fst:
  "\<lbrakk>(x,y) \<in> set xs; (x,y') \<in> set xs; distinct_fst xs\<rbrakk>
  \<Longrightarrow> y = y'"
by(induct xs,auto simp:distinct_fst_def image_def)

subsection{* Edge kinds *}

text {* Every procedure has a unique name, e.g. in object oriented languages
  @{text pname} refers to class + procedure. *}

text {* A state is a call stack of tuples, which consists of:
  \begin{enumerate}
  \item data information, i.e.\ a mapping from the local variables in the call
  frame to their values, and
  \item control flow information, e.g.\ which node called the current procedure.
  \end{enumerate}

  Update and predicate edges check and manipulate only the data information
  of the top call stack element. Call and return edges however may use the data and
  control flow information present in the top stack element to state if this edge is
  traversable. The call edge additionally has a list of functions to determine what
  values the parameters have in a certain call frame and control flow information for
  the return. The return edge is concerned with passing the values
  of the return parameter values to the underlying stack frame. See the funtions
  @{text transfer} and @{text pred} in locale @{text CFG}. *}

datatype (dead 'var, dead 'val, dead 'ret, dead 'pname) edge_kind =
    UpdateEdge "('var \<rightharpoonup> 'val) \<Rightarrow> ('var \<rightharpoonup> 'val)"                  ("\<Up>_")
  | PredicateEdge "('var \<rightharpoonup> 'val) \<Rightarrow> bool"                         ("'(_')\<^sub>\<surd>")
  | CallEdge "('var \<rightharpoonup> 'val) \<times> 'ret \<Rightarrow> bool" "'ret" "'pname"
             "(('var \<rightharpoonup> 'val) \<rightharpoonup> 'val) list"                       ("_:_\<hookrightarrow>\<^bsub>_\<^esub>_" 70)
  | ReturnEdge "('var \<rightharpoonup> 'val) \<times> 'ret \<Rightarrow> bool" "'pname"
               "('var \<rightharpoonup> 'val) \<Rightarrow> ('var \<rightharpoonup> 'val) \<Rightarrow> ('var \<rightharpoonup> 'val)" ("_\<hookleftarrow>\<^bsub>_\<^esub>_" 70)

definition intra_kind :: "('var,'val,'ret,'pname) edge_kind \<Rightarrow> bool"
where "intra_kind et \<equiv> (\<exists>f. et = \<Up>f) \<or> (\<exists>Q. et = (Q)\<^sub>\<surd>)"

lemma edge_kind_cases [case_names Intra Call Return]:
  "\<lbrakk>intra_kind et \<Longrightarrow> P; \<And>Q r p fs. et = Q:r\<hookrightarrow>\<^bsub>p\<^esub>fs \<Longrightarrow> P;
    \<And>Q p f. et = Q\<hookleftarrow>\<^bsub>p\<^esub>f \<Longrightarrow> P\<rbrakk> \<Longrightarrow> P"
by(cases et,auto simp:intra_kind_def)

end


theory TheoremD6
imports TheoremD5
begin

context LocalLexing begin

definition inc_dot :: "nat \<Rightarrow>  ('a, 'b) item \<Rightarrow>  ('a, 'b) item"
where
  "inc_dot d x = Item (item_rule x) (item_dot x + d) (item_origin x) (item_end x)"

lemma inc_dot_0[simp]: "inc_dot 0 x = x"
  by (simp add: inc_dot_def)

lemma Predict_mk_regular1:
  "\<exists> (P ::  ('a, 'b) rule \<Rightarrow>  ('a, 'b) item \<Rightarrow> bool) F. Predict k = mk_regular1 P F"
proof -
  let ?P = "\<lambda> r x:: ('a, 'b) item. r \<in> \<RR> \<and> item_end x = k \<and> next_symbol x = Some(fst r)"
  let ?F = "\<lambda> r (x::  ('a, 'b) item). init_item r k"
  show ?thesis
    apply (rule_tac x="?P" in exI)
    apply (rule_tac x="?F" in exI)
    apply (rule_tac ext)
    by (auto simp add: mk_regular1_def bin_def Predict_def)
qed

lemma Complete_mk_regular2:
  "\<exists> (P :: dummy \<Rightarrow>  ('a, 'b) item \<Rightarrow>  ('a, 'b) item \<Rightarrow> bool) F. Complete k = mk_regular2 P F"
proof -
  let ?P = "\<lambda> (r::dummy) x y. item_end x = item_origin y \<and> item_end y = k \<and> is_complete y \<and>
     next_symbol x = Some (item_nonterminal y)"
  let ?F = "\<lambda> (r::dummy) x y. inc_item x k"
  show ?thesis
    apply (rule_tac x="?P" in exI)
    apply (rule_tac x="?F" in exI)
    apply (rule_tac ext)
    by (auto simp add: mk_regular2_def bin_def Complete_def)
qed

lemma Scan_mk_regular1:
  "\<exists> (P ::  ('a, 'b, 'c) token \<Rightarrow>  ('a, 'b) item \<Rightarrow> bool) F. Scan T k = mk_regular1 P F"
proof -
  let ?P = "\<lambda> (tok:: ('a, 'b, 'c)token) (x:: ('a, 'b)item). item_end x = k \<and> tok \<in> T \<and> next_symbol x = Some (fst tok)"
  let ?F = "\<lambda> (tok:: ('a, 'b, 'c)token) (x:: ('a, 'b)item). inc_item x (k + length (snd tok))"
  show ?thesis
    apply (rule_tac x="?P" in exI)
    apply (rule_tac x="?F" in exI)
    apply (rule_tac ext)
    by (auto simp add: mk_regular1_def bin_def Scan_def)
qed

lemma Predict_regular: "regular (Predict k)"
  by (metis Predict_mk_regular1 regular1)

lemma Complete_regular: "regular (Complete k)"
  by (metis Complete_mk_regular2 regular2)

lemma Scan_regular: "regular (Scan T k)"
  by (metis Scan_mk_regular1 regular1)

lemma \<pi>_functional: "\<pi> k T = limit ((Scan T k) o (Complete k) o (Predict k))"
proof -
  have "\<pi> k T = limit (\<lambda> I. Scan T k (Complete k (Predict k I)))"
    using \<pi>_def by blast
  moreover have "(\<lambda> I. Scan T k (Complete k (Predict k I))) =
     (Scan T k) o (Complete k) o (Predict k)"
     apply (rule ext)
     by simp
  ultimately show ?thesis by simp
qed

lemma \<pi>_step_regular: "regular ((Scan T k) o (Complete k) o (Predict k))"
  by (simp add: Complete_regular Predict_regular Scan_regular regular_comp)

lemma \<pi>_regular: "regular (\<pi> k T)"
  by (simp add: \<pi>_functional \<pi>_step_regular regular_limit)

lemma \<pi>_fix: "Scan T k (Complete k (Predict k (\<pi> k T I))) = \<pi> k T I"
  using \<pi>_functional \<pi>_step_regular regular_fixpoint by fastforce

lemma \<pi>_fix': "((Scan T k) o (Complete k) o (Predict k)) (\<pi> k T I) = \<pi> k T I"
  using \<pi>_functional \<pi>_step_regular regular_fixpoint by fastforce

lemma setmonotone_cases:
  assumes "setmonotone f"
  shows "f X = X \<or> X \<subset> f X"
using assms elem_setmonotone by fastforce

lemma distribute_fixpoint_over_setmonotone_comp:
  assumes f: "setmonotone f"
  assumes g: "setmonotone g"
  assumes fixpoint: "(f o g) I = I"
  shows "f I = I \<and> g I = I"
proof -
  from setmonotone_cases[OF g, where X=I] show ?thesis
  proof(induct rule: disjCases2)
    case 1
      thus ?case using fixpoint by simp
  next
    case 2
      with f have "I \<subset> (f o g) I"
        by (metis comp_apply fixpoint less_asym' setmonotone_cases)
      with fixpoint have "False" by simp
      then show ?case by blast
  qed
qed

lemma distribute_fixpoint_over_setmonotone_comp_3:
  assumes f: "setmonotone f"
  assumes g: "setmonotone g"
  assumes h: "setmonotone h"
  assumes fixpoint: "(f o g o h) I = I"
  shows "f I = I \<and> g I = I \<and> h I = I"
by (meson distribute_fixpoint_over_setmonotone_comp f fixpoint g h setmonotone_comp)

lemma Predict_\<pi>_fix: "Predict k (\<pi> k T I) = \<pi> k T I"
by (meson Complete_regular Predict_regular Scan_regular \<pi>_fix'
  distribute_fixpoint_over_setmonotone_comp_3 regular_implies_setmonotone)

lemma Scan_\<pi>_fix: "Scan T k (\<pi> k T I) = \<pi> k T I"
by (meson Complete_regular Predict_regular Scan_regular \<pi>_fix'
  distribute_fixpoint_over_setmonotone_comp_3 regular_implies_setmonotone)

lemma Complete_\<pi>_fix: "Complete k (\<pi> k T I) = \<pi> k T I"
by (meson Complete_regular Predict_regular Scan_regular \<pi>_fix'
  distribute_fixpoint_over_setmonotone_comp_3 regular_implies_setmonotone)

lemma \<pi>_idempotent: "\<pi> k T (\<pi> k T I) = \<pi> k T I"
  by (simp add: \<pi>_functional \<pi>_step_regular limit_is_idempotent)

lemma derivation_shift_identity[simp]: "derivation_shift D 0 0 = D"
  by (simp add: derivation_shift_def)

lemma Derivation_skip_prefix: "Derivation (u@v) D w \<Longrightarrow> derivation_ge D (length u) \<Longrightarrow>
  Derivation v (derivation_shift D (length u) 0) (drop (length u) w)"
proof (induct D arbitrary: u v w)
  case Nil
    thus ?case by (simp add: append_eq_conv_conj)
next
  case (Cons d D)
    from Cons have "\<exists>x. Derives1 (u@v) (fst d) (snd d) x \<and> Derivation x D w" by auto
    then obtain x where x: "Derives1 (u@v) (fst d) (snd d) x \<and> Derivation x D w" by blast
    from Cons have d: "fst d \<ge> length u" and D: "derivation_ge D (length u)"
      using derivation_ge_cons apply blast
      using Cons.prems(2) derivation_ge_cons by blast
    have "\<exists> x'. x = u@x'" by (metis append_eq_conv_conj d le_Derives1_take x)
    then obtain x' where x': "x = u@x'" by blast
    show ?case
      apply simp
      apply (rule_tac x="x'" in exI)
      using Cons.hyps D Derives1_skip_prefix d x x' by blast
qed

lemma leftmost_skip_prefix: "leftmost i (u@v) \<Longrightarrow> i \<ge> length u \<Longrightarrow> leftmost (i - length u) v"
by (simp add: leftmost_def less_diff_conv2 nth_append)

lemma LeftDerivation_skip_prefix: "LeftDerivation (u@v) D w \<Longrightarrow> derivation_ge D (length u) \<Longrightarrow>
  LeftDerivation v (derivation_shift D (length u) 0) (drop (length u) w)"
proof (induct D arbitrary: u v w)
  case Nil
    thus ?case by (simp add: append_eq_conv_conj)
next
  case (Cons d D)
    from Cons have "\<exists>x. LeftDerives1 (u@v) (fst d) (snd d) x \<and> LeftDerivation x D w" by auto
    then obtain x where x: "LeftDerives1 (u@v) (fst d) (snd d) x \<and> LeftDerivation x D w" by blast
    from Cons have d: "fst d \<ge> length u" and D: "derivation_ge D (length u)"
      using derivation_ge_cons apply blast
      using Cons.prems(2) derivation_ge_cons by blast
    have "\<exists> x'. x = u@x'"
      by (metis LeftDerives1_implies_Derives1 append_eq_conv_conj d le_Derives1_take x)
    then obtain x' where x': "x = u@x'" by blast
    have leftmost: "leftmost (fst d) (u@v)" using LeftDerives1_def x by blast
    have 1: "LeftDerives1 v (fst d - length u) (snd d) x'"
      apply (auto simp add: LeftDerives1_def)
      apply (simp add: leftmost d leftmost_skip_prefix)
      using Derives1_skip_prefix LeftDerives1_implies_Derives1 d x x' by blast
    have 2: "LeftDerivation x' (derivation_shift D (length u) 0) (drop (length u) w)"
      using Cons.hyps D x x' by blast
    show ?case
      apply simp
      apply (rule_tac x="x'" in exI)
      using 1 2 by blast
qed

lemma splits_at_append: "splits_at u i u1 N u2 \<Longrightarrow> splits_at (u@v) i u1 N (u2@v)"
by (auto simp add: splits_at_def)

lemma LeftDerives1_append_leftmost_unique: "LeftDerives1 (a@b) i r c \<Longrightarrow> leftmost j a \<Longrightarrow> i = j"
  by (meson LeftDerives1_def leftmost_cons_less leftmost_def leftmost_unique)

lemma drop_derivation_shift:
  "drop n (derivation_shift D left right) = derivation_shift (drop n D) left right"
by (auto simp add: derivation_shift_def drop_map)

lemma take_derivation_shift:
  "take n (derivation_shift D left right) = derivation_shift (take n D) left right"
by (auto simp add: derivation_shift_def take_map)

lemma derivation_shift_0_shift: "derivation_shift (derivation_shift D left1 0) left2 right2 =
  derivation_shift D (left1 + left2) right2"
by (auto simp add: derivation_shift_def)

lemma splits_at_append_prefix:
  "splits_at v i \<alpha> N \<beta> \<Longrightarrow> splits_at (u@v) (i + length u) (u@\<alpha>) N \<beta>"
  apply (auto simp add: splits_at_def)
  by (simp add: nth_append)

lemma splits_at_implies_Derives1: "splits_at \<delta> i \<alpha> N \<beta> \<Longrightarrow> is_sentence \<delta> \<Longrightarrow> r\<in> \<RR> \<Longrightarrow> fst r = N
 \<Longrightarrow> Derives1 \<delta> i r (\<alpha>@(snd r)@\<beta>)"
by (metis (no_types, lifting) Derives1_def is_sentence_concat length_take
  less_or_eq_imp_le min.absorb2 prod.collapse splits_at_combine splits_at_def)

lemma Derives1_append_prefix:
  assumes Derives1: "Derives1 v i r w"
  assumes u: "is_sentence u"
  shows "Derives1 (u@v) (i + length u) r (u@w)"
proof -
  have "\<exists> \<alpha> N \<beta>. splits_at v i \<alpha> N \<beta>" using assms splits_at_ex by auto
  then obtain \<alpha> N \<beta> where split_v: "splits_at v i \<alpha> N \<beta>" by blast
  have split_w: "w = \<alpha>@(snd r)@\<beta>" using assms split_v splits_at_combine_dest by blast
  have split_uv: "splits_at (u@v) (i + length u) (u@\<alpha>) N \<beta>"
    by (simp add: split_v splits_at_append_prefix)
  with  Derives1 split_v have r:"fst r = N" using Derives1_nonterminal by fast
  have rule:"r \<in> \<RR>" using Derives1 Derives1_rule by fast
  have is_sentence_uv: "is_sentence (u@v)"
    using Derives1 Derives1_sentence1 is_sentence_concat u by blast

  with split_uv rule split_w r  show ?thesis using  splits_at_implies_Derives1 by fastforce
qed

lemma leftmost_prepend_word: "leftmost i v \<Longrightarrow> is_word u \<Longrightarrow> leftmost (i + length u) (u@v)"
by (simp add: leftmost_def nth_append)

lemma LeftDerives1_append_prefix:
  assumes Derives1: "LeftDerives1 v i r w"
  assumes u: "is_word u"
  shows "LeftDerives1 (u@v) (i + length u) r (u@w)"
proof -
  have 1: "Derives1 v i r w"
    by (simp add: Derives1 LeftDerives1_implies_Derives1)
  have 2: "leftmost i v"
    using Derives1 LeftDerives1_def by blast
  have 3: "is_sentence u" using u by fastforce
  have 4: "Derives1 (u@v) (i + length u) r (u@w)"
    by (simp add: "1" "3" Derives1_append_prefix)
  have 5: "leftmost (i + length u) (u@v)"
    by (simp add: "2" leftmost_prepend_word u)
  show ?thesis
    by (simp add: "4" "5" LeftDerives1_def)
qed

lemma Derivation_append_prefix: "Derivation v D w \<Longrightarrow> is_sentence u \<Longrightarrow>
  Derivation (u@v) (derivation_shift D 0 (length u)) (u@w)"
proof (induct D arbitrary: u v w)
  case Nil thus ?case by auto
next
  case (Cons d D)
    then have "\<exists> x. Derives1 v (fst d) (snd d) x \<and> Derivation x D w" by auto
    then obtain x where x: "Derives1 v (fst d) (snd d) x \<and> Derivation x D w" by blast
    with Cons have induct: "Derivation (u@x) (derivation_shift D 0 (length u)) (u@w)" by auto
    have Derives1: "Derives1 (u@v) ((fst d) + length u) (snd d) (u@x)"
      by (simp add: Cons.prems(2) Derives1_append_prefix x)
    show ?case
      apply simp
      apply (rule_tac x="u@x" in exI)
      by (simp add: Cons.hyps Cons.prems(2) Derives1 x)
qed

lemma LeftDerivation_append_prefix: "LeftDerivation v D w \<Longrightarrow> is_word u \<Longrightarrow>
  LeftDerivation (u@v) (derivation_shift D 0 (length u)) (u@w)"
proof (induct D arbitrary: u v w)
  case Nil thus ?case by auto
next
  case (Cons d D)
    then have "\<exists> x. LeftDerives1 v (fst d) (snd d) x \<and> LeftDerivation x D w" by auto
    then obtain x where x: "LeftDerives1 v (fst d) (snd d) x \<and> LeftDerivation x D w" by blast
    with Cons have induct: "LeftDerivation (u@x) (derivation_shift D 0 (length u)) (u@w)" by auto
    have Derives1: "LeftDerives1 (u@v) ((fst d) + length u) (snd d) (u@x)"
      by (simp add: Cons.prems(2) LeftDerives1_append_prefix x)
    show ?case
      apply simp
      apply (rule_tac x="u@x" in exI)
      by (simp add: Cons.hyps Cons.prems(2) Derives1 x)
qed

lemma derivation_ge_shift_simp: "derivation_ge D i \<Longrightarrow> i \<ge> l \<Longrightarrow> r \<ge> l \<Longrightarrow>
   derivation_shift D l r = derivation_shift D 0 (r - l)"
proof (induct D)
  case Nil thus ?case by auto
next
  case (Cons d D)
  have fst_d: "fst d \<ge> l"
    using Cons.prems(1) Cons.prems(2) derivation_ge_cons le_trans by blast
  show ?case
    apply auto
    using Cons fst_d apply arith
    using Cons derivation_ge_cons apply auto
    done
qed

lemma append_dropped_prefix: "is_prefix u v \<Longrightarrow> drop (length u) v = w \<Longrightarrow> u@w = v"
using is_prefix_unsplit by blast

lemma derivation_ge_shift_plus:
  assumes "derivation_ge D u"
  assumes "derivation_ge (derivation_shift D u 0) v"
  shows "derivation_ge D (u + v)"
proof -
  from assms show ?thesis
    apply (auto simp add: derivation_ge_def derivation_shift_def)
    by fastforce
qed

lemma LeftDerivation_breakdown:
  "LeftDerivation (u@v) D w \<Longrightarrow> \<exists> n w1 w2. w = w1 @ w2 \<and>
     LeftDerivation u (take n D) w1 \<and>
     derivation_ge (drop n D) (length w1) \<and>
     LeftDerivation v (derivation_shift (drop n D) (length w1) 0) w2"
proof (induct "length D" arbitrary: u v D w)
  case 0
    then have D: "D = []" by auto
    with 0 have "u@v = w" by auto
    with D show ?case
      apply (rule_tac x=0 in exI)
      apply (rule_tac x="u" in exI)
      apply (rule_tac x="v" in exI)
      by auto
next
  case (Suc l)
    then have "\<exists> d D'. D = d#D'"
      by (metis LeftDerivation.elims(2) length_0_conv nat.simps(3))
    then obtain d D' where D_split: "D = d#D'" by blast
    from Suc have is_sentence_uv: "is_sentence (u@v)"
      by (metis D_split Derives1_sentence1 LeftDerivation.simps(2) LeftDerives1_implies_Derives1)
    then have is_sentence_u: "is_sentence u" and is_sentence_v: "is_sentence v"
      by (simp add: is_sentence_concat)+
    have "is_word u \<or> (\<not> is_word u)" by blast
    then show ?case
      proof(induct rule: disjCases2)
        case 1
          then have derivation_ge_u: "derivation_ge D (length u)"
            using LeftDerivation_implies_Derivation Suc.prems is_word_Derivation_derivation_ge by blast
          have is_prefix: "is_prefix u w"
            using "1.hyps" LeftDerivation_implies_leftderives Suc.prems
              derives_word_is_prefix leftderives_implies_derives by blast
          have u_w: "w = u @ (drop (length u) w)"
            by (metis "1.hyps" LeftDerivation_implies_leftderives Suc.prems
              derives_word_is_prefix is_prefix_unsplit leftderives_implies_derives)
          show ?case
            apply (rule_tac x="0" in exI)
            apply (rule_tac x="u" in exI)
            apply (rule_tac x="drop (length u) w" in exI)
            apply (auto)
            apply (rule u_w)
            apply (rule derivation_ge_u)
            by (simp add: LeftDerivation_skip_prefix Suc.prems derivation_ge_u)
      next
        case 2
          with is_sentence_u have "\<exists> i u1 N u2. splits_at u i u1 N u2 \<and> leftmost i u"
            using leftmost_def nonword_leftmost_exists splits_at_def by auto
          then obtain i u1 N u2 where split_u: "splits_at u i u1 N u2 \<and> leftmost i u" by blast
          have is_word_u1: "is_word u1" by (metis leftmost_def split_u splits_at_def)
          have "LeftDerivation (u@v) (d#D') w"  using D_split Suc.prems by blast
          then have "\<exists> x. LeftDerives1 (u@v) (fst d) (snd d) x \<and> LeftDerivation x D' w"
            by simp
          then obtain x where x: "LeftDerives1 (u@v) (fst d) (snd d) x \<and> LeftDerivation x D' w"
            by blast
          then have fst_d_eq_i: "fst d = i" using
            splits_at_combine LeftDerives1_append_leftmost_unique split_u
            by metis
          have split_uv: "splits_at (u@v) i u1 N (u2@v)" by (simp add: split_u splits_at_append)
          have split_x: "x = u1 @ ((snd (snd d)) @ u2 @ v)"
            using LeftDerives1_implies_Derives1 fst_d_eq_i split_uv
              splits_at_combine_dest x by blast
          have derivation_ge_D': "derivation_ge D' (length u1)"
            using LeftDerivation_implies_Derivation is_word_Derivation_derivation_ge
              leftmost_def split_u split_x splits_at_def x by fastforce
          have D1: "LeftDerivation ((snd (snd d)) @ u2 @ v) (derivation_shift D' (length u1) 0)
            (drop (length u1) w)"
            using LeftDerivation_skip_prefix derivation_ge_D' split_x x by blast
          then have D2: "LeftDerivation (((snd (snd d)) @ u2) @ v) (derivation_shift D' (length u1) 0)
            (drop (length u1) w)" by auto
          have "l = length (derivation_shift D' (length u1) 0)"
            using D_split Suc.hyps(2) by auto
          from Suc(1)[OF this D2] obtain n w1 w2 where induct:
            "drop (length u1) w = w1 @ w2 \<and>
             LeftDerivation (snd (snd d) @ u2)
               (take n (derivation_shift D' (length u1) 0)) w1 \<and>
             derivation_ge (drop n (derivation_shift D' (length u1) 0)) (length w1) \<and>
             LeftDerivation v (derivation_shift (drop n (derivation_shift D' (length u1) 0))
               (length w1) 0) w2" by blast
          have derivation_ge_D'_u1_w1: "derivation_ge (drop n D') (length u1 + length w1)"
          proof -
            from induct have 1: "derivation_ge (derivation_shift (drop n D') (length u1) 0) (length w1)"
              apply (subst drop_derivation_shift[symmetric])
              by blast
            have 2: "derivation_ge (drop n D') (length u1)"
              by (metis append_take_drop_id derivation_ge_D' derivation_ge_append)
            show ?thesis using 1 2 derivation_ge_shift_plus by blast
          qed
          have "LeftDerivation (u1@(snd (snd d) @ u2)) (derivation_shift
                (take n (derivation_shift D' (length u1) 0)) 0 (length u1)) (u1@w1)"
          using induct LeftDerivation_append_prefix is_word_u1 by blast
          then have der1: "LeftDerivation (u1@(snd (snd d) @ u2))
              (derivation_shift (take n D') (length u1) (length u1)) (u1@w1)"
            using take_derivation_shift derivation_shift_0_shift by auto
          have eq1: "derivation_shift (take n D') (length u1) (length u1) = take n D'"
            apply (subst derivation_ge_shift_simp[where i = "length u1"])
            apply auto
            by (metis append_take_drop_id derivation_ge_D' derivation_ge_append)
          from der1 eq1 have der2: "LeftDerivation (u1@(snd (snd d) @ u2)) (take n D') (u1@w1)"
            by auto
          have eq2: "take (Suc n) D = d#(take n D')"
            by (simp add: D_split)
          have der3: "LeftDerivation u (take (Suc n) D) (u1@w1)"
            apply (simp add: eq2)
            apply (rule_tac x="u1@(snd (snd d) @ u2)" in exI)
            by (metis Derives1_skip_suffix LeftDerives1_def append_assoc der2 fst_d_eq_i
              split_u split_x splits_at_def x)
          have "is_prefix u1 w"
            using LeftDerivation_implies_leftderives derives_word_is_prefix is_word_u1
              leftderives_implies_derives split_x x by blast
          then have eq3: "u1 @ (w1@w2) = w"
            apply (rule_tac append_dropped_prefix)
            apply (auto simp add: induct)
            done
          show ?case
            apply (rule_tac x="Suc n" in exI)
            apply (rule_tac x="u1@w1" in exI)
            apply (rule_tac x="w2" in exI)
            apply auto
            apply (simp add: eq3)
            apply (simp add: der3)
            apply (simp add: D_split)
            apply (rule derivation_ge_D'_u1_w1)
            apply (simp add: D_split)
            using induct derivation_shift_0_shift drop_derivation_shift apply auto
            done
      qed
qed

lemma Derives1_terminals_stay:
  assumes Derives1: "Derives1 u i r v"
  assumes t_dom: "t \<in> set u"
  assumes terminal: "is_terminal t"
  shows "t \<in> set v"
proof -
  have "\<exists> \<alpha> \<beta> N. splits_at u i \<alpha> N \<beta>" using Derives1 splits_at_ex by blast
  then obtain \<alpha> \<beta> N where split_u: "splits_at u i \<alpha> N \<beta>" by blast
  then have "t \<in> set (\<alpha> @ [N] @ \<beta>)" using splits_at_combine t_dom by auto
  then have t_possible_locations: "t \<in> set \<alpha> \<or> t = N \<or> t \<in> set \<beta>" by auto
  have is_nonterminal: "is_nonterminal N" using Derives1 Derives1_nonterminal split_u by auto
  with t_possible_locations terminal have t_locations: "t \<in> set \<alpha> \<or> t \<in> set \<beta>"
    using is_terminal_nonterminal by blast
  from Derives1 split_u have "v = \<alpha> @ (snd r) @ \<beta>" by (simp add: splits_at_combine_dest)
  with t_locations show ?thesis by auto
qed

lemma Derivation_terminals_stay: "Derivation u D v \<Longrightarrow> t \<in> set u \<Longrightarrow> is_terminal t \<Longrightarrow> t \<in> set v"
proof (induct D arbitrary: u v)
  case Nil thus ?case by auto
next
  case (Cons d D)
  then have "\<exists> x. Derives1 u (fst d) (snd d) x \<and> Derivation x D v" by auto
  then obtain x where x: "Derives1 u (fst d) (snd d) x \<and> Derivation x D v" by auto
  show ?case using Cons Derives1_terminals_stay x by blast
qed

lemma Derivation_empty_no_terminals: "Derivation u D [] \<Longrightarrow> t \<in> set u \<Longrightarrow> is_nonterminal t"
  by (metis Ball_set Derivation_implies_derives Derivation_terminals_stay
    derives_is_sentence is_sentence_def is_symbol_distinct list.pred_inject(1))

lemma mono_subset_elem: "mono f \<Longrightarrow> A \<subseteq> B \<Longrightarrow> x \<in> f A \<Longrightarrow> x \<in> f B" using mono_def by blast

lemma wellformed_inc_dot: "wellformed_item x \<Longrightarrow> item_dot x + d \<le> length (item_rhs x) \<Longrightarrow>
  wellformed_item(inc_dot d x)"
by (simp add: inc_dot_def item_rhs_def wellformed_item_def)

lemma init_item_dot[simp]: "item_dot (init_item r k) = 0"
  by (simp add: init_item_def)

lemma init_item_rhs[simp]: "item_rhs (init_item r k) = snd r"
  by (simp add: init_item_def item_rhs_def)

lemma init_item_\<beta>[simp]: "item_\<beta> (init_item r k) = snd r"
  by (simp add: item_\<beta>_def)

lemma mono_\<pi>: "mono (\<pi> k T)"
  by (simp add: \<pi>_regular regular_implies_mono)

lemma \<pi>_subset_elem_trans:
  assumes Y: "Y \<subseteq> \<pi> k T X"
  assumes z: "z \<in> \<pi> k T Y"
  shows "z \<in>  \<pi> k T X"
proof -
  from Y have "\<pi> k T Y \<subseteq> \<pi> k T (\<pi> k T X)" by (simp add: monoD mono_\<pi>)
  then have "\<pi> k T Y \<subseteq> \<pi> k T X" using \<pi>_idempotent by blast
  with z show ?thesis using contra_subsetD by blast
qed

lemma inc_dot_end[simp]: "item_end (inc_dot d x) = item_end x"
  by (simp add: inc_dot_def)

lemma inc_dot_rhs[simp]: "item_rhs (inc_dot d x) = item_rhs x"
  by (simp add: inc_dot_def item_rhs_def)

lemma inc_dot_dot[simp]: "item_dot (inc_dot d x) = item_dot x + d"
  by (simp add: inc_dot_def)

lemma inc_dot_nonterminal[simp]: "item_nonterminal (inc_dot d x) = item_nonterminal x"
  by (simp add: inc_dot_def item_nonterminal_def)

lemma Predict_subset_\<pi>: "Predict k X \<subseteq> \<pi> k T X"
proof -
  have "setmonotone (\<pi> k T)"
    by (simp add: \<pi>_regular regular_implies_setmonotone)
  then have s: "X \<subseteq> \<pi> k T X" by (simp add: subset_setmonotone)
  have "mono (Predict k)" by (simp add: Predict_regular regular_implies_mono)
  with s have "Predict k X \<subseteq> Predict k (\<pi> k T X)" by (simp add: monoD)
  then show "Predict k X \<subseteq> \<pi> k T X" by (simp add: Predict_\<pi>_fix)
qed

lemma Complete_subset_\<pi>: "Complete k X \<subseteq> \<pi> k T X"
proof -
  have "setmonotone (\<pi> k T)"
    by (simp add: \<pi>_regular regular_implies_setmonotone)
  then have s: "X \<subseteq> \<pi> k T X" by (simp add: subset_setmonotone)
  have "mono (Complete k)" by (simp add: Complete_regular regular_implies_mono)
  with s have "Complete k X \<subseteq> Complete k (\<pi> k T X)" by (simp add: monoD)
  then show "Complete k X \<subseteq> \<pi> k T X" by (simp add: Complete_\<pi>_fix)
qed

lemma inc_inc_dot[simp]: "inc_dot a (inc_dot b x) = inc_dot (a + b) x"
  by (simp add: inc_dot_def)

lemma thmD6_Left: "wellformed_item x \<Longrightarrow> item_\<beta> x = \<delta> @ \<omega> \<Longrightarrow> item_end x = k \<Longrightarrow>
  LeftDerivation \<delta> D [] \<Longrightarrow> inc_dot (length \<delta>) x \<in> \<pi> k {} {x}"
proof (induct "length D" arbitrary: x \<delta> \<omega> D rule: less_induct)
  case less
    have "length \<delta> = 0 \<or> length \<delta> = 1 \<or> length \<delta> \<ge> 2" by arith
    then show ?case
    proof (induct rule: disjCases3)
      case 1
        then have "\<delta> = []" by auto
        then show ?case by (simp add: \<pi>_regular elem_setmonotone regular_implies_setmonotone)
    next
      case 2
        then have "\<exists> N. \<delta> = [N]"
          by (metis One_nat_def append_self_conv2 drop_all id_take_nth_drop
            le_numeral_extra(4) lessI take_0)
        then obtain N where N: "\<delta> = [N]" by blast
        then have "N \<in> set \<delta>" by auto
        then have is_nonterminal_N: "is_nonterminal N" using Derivation_empty_no_terminals
          LeftDerivation_implies_Derivation less.prems(4) by blast
        have "D \<noteq> []" using LeftDerivation.elims(2) N less.prems(4) by blast
        then have "\<exists> e E. D = e#E" using LeftDerivation.elims(2) less.prems(4) by blast
        then obtain e E where eE: "D = e#E" by blast
        then have "\<exists> \<gamma>. LeftDerives1 \<delta> (fst e) (snd e) \<gamma> \<and>
          LeftDerivation \<gamma> E []" using LeftDerivation.simps(2) less.prems(4) by blast
        then obtain \<gamma> where \<gamma>: "LeftDerives1 \<delta> (fst e) (snd e) \<gamma> \<and> LeftDerivation \<gamma> E []" by blast
        with N have \<gamma>_def: "\<gamma> = snd (snd e)"
          by (metis "2.hyps" Derives1_split LeftDerives1_def One_nat_def append_Cons
            append_Nil append_Nil2 leftmost_def length_0_conv less_nat_zero_code linorder_neqE_nat
            list.inject not_less_eq)
        have "next_symbol x = Some t \<Longrightarrow> \<exists>\<delta>. item_\<beta> x = t # \<delta>" using less.prems(1)  next_symbol_starts_item_\<beta> by blast
        have "is_complete x \<Longrightarrow> item_\<beta> x = []" using less.prems(1)  wellformed_complete_item_\<beta>  by blast
        then have "\<not>(item_\<beta> x = []) \<Longrightarrow> \<not> (is_complete x)" by blast
        with less.prems(2) N have "\<not> is_complete x" by simp
        then have "next_symbol x  = Some (item_rhs x ! item_dot x)" using next_symbol_def by metis
        then have next_symbol_x: "next_symbol x = Some N"
          using N less.prems(1) less.prems(2)  next_symbol_starts_item_\<beta>
              by fastforce
        have x_subset: "{x} \<subseteq> \<pi> k {} {x}"
          using \<pi>_regular regular_implies_setmonotone subset_setmonotone by blast
        let ?y = "init_item (snd e) k"
        have "?y \<in> Predict k {x}"
          apply (simp add: Predict_def)
          apply (rule disjI2)
          apply (rule_tac x="fst (snd e)" in exI)
          apply (rule_tac x="snd (snd e)" in exI)
          apply auto
          using Derives1_rule LeftDerives1_implies_Derives1 \<gamma> apply blast
          apply (rule_tac x=x in exI)
          by (metis (mono_tags, lifting) Derives1_split LeftDerives1_def N \<gamma>
              append.simps(1) append.simps(2) bin_def is_nonterminal_N leftmost_cons_nonterminal
              leftmost_unique length_greater_0_conv less.prems(3) less_nat_zero_code
              list.inject mem_Collect_eq next_symbol_x singletonI)
       then have y_dom: "?y \<in> \<pi> k {} {x}" using Predict_subset_\<pi> by blast
       let ?z = "inc_dot (length \<gamma>) ?y"
       have "item_dot ?y = 0" and "item_rhs ?y = \<gamma>" by (auto simp add: \<gamma>_def)
       note y_props = this
       then have wellformed_y: "wellformed_item ?y"
        using Derives1_rule LeftDerives1_implies_Derives1 \<gamma> less.prems(1) less.prems(3)
          wellformed_init_item wellformed_item_def by blast
       with y_props have wellformed_z: "wellformed_item ?z" by (simp add: wellformed_inc_dot)
       have item_\<beta>_y: "item_\<beta> ?y = \<gamma> @ []" using item_rhs_split y_props(2) by auto
       have is_complete_z: "is_complete ?z" by (simp add: is_complete_def \<gamma>_def)
       have "?z \<in> \<pi> k {} {?y}"
         apply (rule less(1)[where D="E"])
         apply (auto simp add: eE wellformed_y \<gamma>)
         apply (simp add: \<gamma>_def)
         done
       with y_dom have z_dom: "?z \<in> \<pi> k {} {x}"
         using \<pi>_subset_elem_trans empty_subsetI insert_subset by blast
       let ?w = "inc_dot (length \<delta>) x"
       have "?w \<in> Complete k {x, ?z}"
        apply (simp add: Complete_def)
        apply (rule_tac disjI2)+
        apply (rule_tac x=x in exI)
        apply (auto simp add: 2)
        apply (simp add: inc_dot_def inc_item_def less)
        apply (rule_tac x="?z" in exI)
        apply (auto simp add: bin_def less is_complete_z next_symbol_x)
        by (metis Derives1_split LeftDerives1_def N \<gamma> append_Cons append_self_conv2
          is_nonterminal_N leftmost_cons_nonterminal leftmost_unique length_0_conv list.inject)
       then have "?w \<in> \<pi> k {} {x, ?z}" using Complete_subset_\<pi> by blast
       then show ?case by (meson \<pi>_subset_elem_trans insert_subset x_subset z_dom)
    next
      case 3
       then have "\<exists> N \<alpha>. \<delta> = [N] @ \<alpha>"
         by (metis append_Cons append_Nil count_terminals.cases le0 le_0_eq list.size(3)
           numeral_le_iff semiring_norm(69))
       then obtain N \<alpha> where \<delta>_split: "\<delta> = [N] @ \<alpha>" by blast
       with 3 have \<alpha>_nonempty: "\<alpha> \<noteq> []"
         by (metis (full_types) One_nat_def Suc_eq_plus1 append_Nil2 impossible_Cons length_Cons
          list.size(3) nat_1_add_1)
       have "LeftDerivation ([N] @ \<alpha>) D []" using \<delta>_split less.prems(4) by blast
       from LeftDerivation_breakdown[OF this, simplified]
       obtain n where n: "LeftDerivation [N] (take n D) [] \<and> LeftDerivation \<alpha> (drop n D) []" by blast
       let ?E = "take n D"
       from n have E: "LeftDerivation [N] ?E []" by auto
       let ?F = "drop n D"
       from n have F: "LeftDerivation \<alpha> ?F []" by auto
       have length_add: "length ?E + length ?F = length D" by simp
       have "?E \<noteq> []" using E by force
       then have length_E_0: "length ?E > 0" by auto
       have "?F \<noteq> []" using F \<alpha>_nonempty by force
       then have length_F_0: "length ?F > 0" by auto
       from length_add length_E_0 length_F_0
       have "length ?E < length D \<and> length ?F < length D"
         using add.commute nat_add_left_cancel_less nat_neq_iff not_add_less2 by linarith
       then have length_E: "length ?E < length D" and length_F: "length ?F < length D" by auto
       let ?y = "inc_dot (length [N]) x"
       have y_dom: "?y \<in> \<pi> k {} {x}"
        apply (rule_tac less(1)[where D="?E" and \<omega>="\<alpha>@\<omega>"])
        apply (rule length_E)
        by (auto simp add: less \<delta>_split E)
      let ?z = "inc_dot (length \<alpha>) ?y"
      have wellformed_y: "wellformed_item ?y"
        using \<delta>_split is_complete_def less.prems(1) less.prems(2) wellformed_complete_item_\<beta>
          wellformed_inc_dot by fastforce
      have "?z \<in> \<pi> k {} {?y}"
        apply (rule_tac less(1)[where D="?F" and \<omega>="\<omega>"])
        apply (rule length_F)
        apply (rule wellformed_y)
        apply (auto simp add: F less)
        by (metis \<delta>_split add.commute append_assoc append_eq_conv_conj drop_drop inc_dot_dot
          inc_dot_rhs item_\<beta>_def length_Cons less.prems(2) list.size(3))
      then have z_dom: "?z \<in> \<pi> k {} {x}" using \<pi>_subset_elem_trans y_dom by blast
      have "?z = inc_dot (length \<delta>) x" by (simp add: \<delta>_split)
      with z_dom show ?case by auto
    qed
qed

lemma derives_empty_implies_LeftDerivation: "derives \<delta> [] \<Longrightarrow> \<exists> D. LeftDerivation \<delta> D []"
  using derives_implies_leftderives is_word_def leftderives_implies_LeftDerivation
    list.pred_inject(1) by blast

lemma thmD6: "wellformed_item x \<Longrightarrow> item_\<beta> x = \<delta> @ \<omega> \<Longrightarrow> item_end x = k \<Longrightarrow>
  derives \<delta> [] \<Longrightarrow> inc_dot (length \<delta>) x \<in> \<pi> k {} {x}"
using derives_empty_implies_LeftDerivation thmD6_Left by blast

end

end


theory prop_10
imports Main
        "../../TestTheories/Listi"
        "../../TestTheories/Naturals"
        "$HIPSTER_HOME/IsaHipster"

begin

theorem unknown02 : "init (tail x) = tail (init x)"
by hipster_induct_schemes

end


(*  Title:      HOL/HOLCF/Tutorial/Domain_ex.thy
    Author:     Brian Huffman
*)

section \<open>Domain package examples\<close>

theory Domain_ex
imports HOLCF
begin

text \<open>Domain constructors are strict by default.\<close>

domain d1 = d1a | d1b "d1" "d1"

lemma "d1b\<cdot>\<bottom>\<cdot>y = \<bottom>" by simp

text \<open>Constructors can be made lazy using the \<open>lazy\<close> keyword.\<close>

domain d2 = d2a | d2b (lazy "d2")

lemma "d2b\<cdot>x \<noteq> \<bottom>" by simp

text \<open>Strict and lazy arguments may be mixed arbitrarily.\<close>

domain d3 = d3a | d3b (lazy "d2") "d2"

lemma "P (d3b\<cdot>x\<cdot>y = \<bottom>) \<longleftrightarrow> P (y = \<bottom>)" by simp

text \<open>Selectors can be used with strict or lazy constructor arguments.\<close>

domain d4 = d4a | d4b (lazy d4b_left :: "d2") (d4b_right :: "d2")

lemma "y \<noteq> \<bottom> \<Longrightarrow> d4b_left\<cdot>(d4b\<cdot>x\<cdot>y) = x" by simp

text \<open>Mixfix declarations can be given for data constructors.\<close>

domain d5 = d5a | d5b (lazy "d5") "d5" (infixl ":#:" 70)

lemma "d5a \<noteq> x :#: y :#: z" by simp

text \<open>Mixfix declarations can also be given for type constructors.\<close>

domain ('a, 'b) lazypair (infixl ":*:" 25) =
  lpair (lazy lfst :: 'a) (lazy lsnd :: 'b) (infixl ":*:" 75)

lemma "\<forall>p::('a :*: 'b). p \<sqsubseteq> lfst\<cdot>p :*: lsnd\<cdot>p"
by (rule allI, case_tac p, simp_all)

text \<open>Non-recursive constructor arguments can have arbitrary types.\<close>

domain ('a, 'b) d6 = d6 "int lift" "'a \<oplus> 'b u" (lazy "('a :*: 'b) \<times> ('b \<rightarrow> 'a)")

text \<open>
  Indirect recusion is allowed for sums, products, lifting, and the
  continuous function space.  However, the domain package does not
  generate an induction rule in terms of the constructors.
\<close>

domain 'a d7 = d7a "'a d7 \<oplus> int lift" | d7b "'a \<otimes> 'a d7" | d7c (lazy "'a d7 \<rightarrow> 'a")
  \<comment> \<open>Indirect recursion detected, skipping proofs of (co)induction rules\<close>

text \<open>Note that \<open>d7.induct\<close> is absent.\<close>

text \<open>
  Indirect recursion is also allowed using previously-defined datatypes.
\<close>

domain 'a slist = SNil | SCons 'a "'a slist"

domain 'a stree = STip | SBranch "'a stree slist"

text \<open>Mutually-recursive datatypes can be defined using the \<open>and\<close> keyword.\<close>

domain d8 = d8a | d8b "d9" and d9 = d9a | d9b (lazy "d8")

text \<open>Non-regular recursion is not allowed.\<close>
(*
domain ('a, 'b) altlist = ANil | ACons 'a "('b, 'a) altlist"
  -- "illegal direct recursion with different arguments"
domain 'a nest = Nest1 'a | Nest2 "'a nest nest"
  -- "illegal direct recursion with different arguments"
*)

text \<open>
  Mutually-recursive datatypes must have all the same type arguments,
  not necessarily in the same order.
\<close>

domain ('a, 'b) list1 = Nil1 | Cons1 'a "('b, 'a) list2"
   and ('b, 'a) list2 = Nil2 | Cons2 'b "('a, 'b) list1"

text \<open>Induction rules for flat datatypes have no admissibility side-condition.\<close>

domain 'a flattree = Tip | Branch "'a flattree" "'a flattree"

lemma "\<lbrakk>P \<bottom>; P Tip; \<And>x y. \<lbrakk>x \<noteq> \<bottom>; y \<noteq> \<bottom>; P x; P y\<rbrakk> \<Longrightarrow> P (Branch\<cdot>x\<cdot>y)\<rbrakk> \<Longrightarrow> P x"
by (rule flattree.induct) \<comment> \<open>no admissibility requirement\<close>

text \<open>Trivial datatypes will produce a warning message.\<close>

domain triv = Triv triv triv
  \<comment> \<open>domain \<open>Domain_ex.triv\<close> is empty!\<close>

lemma "(x::triv) = \<bottom>" by (induct x, simp_all)

text \<open>Lazy constructor arguments may have unpointed types.\<close>

domain natlist = nnil | ncons (lazy "nat discr") natlist

text \<open>Class constraints may be given for type parameters on the LHS.\<close>

domain ('a::predomain) box = Box (lazy 'a)

domain ('a::countable) stream = snil | scons (lazy "'a discr") "'a stream"

subsection \<open>Generated constants and theorems\<close>

domain 'a tree = Leaf (lazy 'a) | Node (left :: "'a tree") (right :: "'a tree")

lemmas tree_abs_bottom_iff =
  iso.abs_bottom_iff [OF iso.intro [OF tree.abs_iso tree.rep_iso]]

text \<open>Rules about ismorphism\<close>
term tree_rep
term tree_abs
thm tree.rep_iso
thm tree.abs_iso
thm tree.iso_rews

text \<open>Rules about constructors\<close>
term Leaf
term Node
thm Leaf_def Node_def
thm tree.nchotomy
thm tree.exhaust
thm tree.compacts
thm tree.con_rews
thm tree.dist_les
thm tree.dist_eqs
thm tree.inverts
thm tree.injects

text \<open>Rules about case combinator\<close>
term tree_case
thm tree.tree_case_def
thm tree.case_rews

text \<open>Rules about selectors\<close>
term left
term right
thm tree.sel_rews

text \<open>Rules about discriminators\<close>
term is_Leaf
term is_Node
thm tree.dis_rews

text \<open>Rules about monadic pattern match combinators\<close>
term match_Leaf
term match_Node
thm tree.match_rews

text \<open>Rules about take function\<close>
term tree_take
thm tree.take_def
thm tree.take_0
thm tree.take_Suc
thm tree.take_rews
thm tree.chain_take
thm tree.take_take
thm tree.deflation_take
thm tree.take_below
thm tree.take_lemma
thm tree.lub_take
thm tree.reach
thm tree.finite_induct

text \<open>Rules about finiteness predicate\<close>
term tree_finite
thm tree.finite_def
thm tree.finite (* only generated for flat datatypes *)

text \<open>Rules about bisimulation predicate\<close>
term tree_bisim
thm tree.bisim_def
thm tree.coinduct

text \<open>Induction rule\<close>
thm tree.induct

subsection \<open>Known bugs\<close>

text \<open>Declaring a mixfix with spaces causes some strange parse errors.\<close>
(*
domain xx = xx ("x y")
  -- "Inner syntax error: unexpected end of input"
*)

end