theory Prelude_ListNoNumbers_E1
imports "$HETS_LIB/Isabelle/MainHC"
uses "$HETS_LIB/Isabelle/prelude"
begin

ML "Header.initialize
    [\"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\", \"IBE1\", \"IBE2\", \"IBE3\", \"IBE4\",
     \"IBE5\", \"IBE6\", \"IBE7\", \"IBE8\", \"IUE1\", \"IUE2\",
     \"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\", \"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\", \"IUO01\", \"IUO02\", \"IUO03\",
     \"IUO04\", \"IUO05\", \"IUO06\", \"IUO07\", \"NotDefHead\",
     \"HeadDef\", \"NotDefTail\", \"TailDef\", \"FoldrNil\",
     \"FoldrCons\", \"FoldlNil\", \"FoldlCons\", \"MapNil\",
     \"MapCons\", \"XPlusXPlusNil\", \"XPlusXPlusCons\", \"FilterNil\",
     \"FilterConsT\", \"FilterConsF\", \"ZipNil\", \"ZipConsNil\",
     \"ZipConsCons\", \"UnzipNil\", \"UnzipCons\", \"ILE01\", \"ILE02\",
     \"ILO01\", \"ILO02\", \"ILO03\", \"ILO04\", \"ILO05\", \"ILO06\",
     \"ILO07\", \"ILO08\", \"ILO09\", \"ILO10\", \"ILO11\", \"ILO12\",
     \"ILO13\", \"ILO14\", \"ILO15\", \"ILO16\", \"ILO17\", \"ILO18\",
     \"ILO19\", \"ILO20\", \"ILO21\", \"ILO22\", \"FoldlDecomp\",
     \"MapDecomp\", \"MapFunctor\", \"FilterProm\", \"InitNil\",
     \"InitConsNil\", \"InitConsCons\", \"LastNil\", \"LastConsNil\",
     \"LastConsCons\", \"NullNil\", \"NullCons\", \"ReverseNil\",
     \"ReverseCons\", \"Foldr1Nil\", \"Foldr1ConsNil\",
     \"Foldr1ConsCons\", \"Foldl1Nil\", \"Foldl1ConsNil\",
     \"Foldl1ConsCons\", \"ScanlNil\", \"ScanlCons\", \"Scanl1Nil\",
     \"Scanl1Cons\", \"ScanrNil\", \"ScanrCons\", \"Scanr1Nil\",
     \"Scanr1ConsNil\", \"Scanr1ConsCons\", \"ScanlProperty\",
     \"ScanrProperty\", \"AndLNil\", \"AndLCons\", \"OrLNil\",
     \"OrLCons\", \"AnyDef\", \"AllDef\", \"ConcatDef\",
     \"ConcatMapDef\", \"MaximunNil\", \"MaximumDef\", \"MinimunNil\",
     \"MinimumDef\", \"TakeWhileNil\", \"TakeWhileConsT\",
     \"TakeWhileConsF\", \"DropWhileNil\", \"DropWhileConsT\",
     \"DropWhileConsF\", \"SpanNil\", \"SpanConsT\", \"SpanConsF\",
     \"BreakDef\", \"SpanThm\", \"BreakThm\"]"

typedecl Unit

datatype Bool = X_False ("False''") | X_True ("True''")
datatype Ordering = EQ | GT | LT
datatype 'a List = X_Cons 'a "'a List" | X_Nil ("Nil''")

consts
Not__X :: "Bool => Bool" ("(Not''/ _)" [56] 56)
X__XAmpXAmp__X :: "Bool => Bool => Bool" ("(_/ &&/ _)" [54,54] 52)
X__XEqXEq__X :: "'a => 'a => Bool" ("(_/ ==''/ _)" [54,54] 52)
X__XGtXEq__X :: "'a => 'a => Bool" ("(_/ >=''/ _)" [54,54] 52)
X__XGt__X :: "'a => 'a => Bool" ("(_/ >''/ _)" [54,54] 52)
X__XLtXEq__X :: "'a => 'a => Bool" ("(_/ <=''/ _)" [54,54] 52)
X__XLt__X :: "'a => 'a => Bool" ("(_/ <''/ _)" [54,54] 52)
X__XPlusXPlus__X :: "'a List => 'a List => 'a List" ("(_/ ++''/ _)" [54,54] 52)
X__XSlashXEq__X :: "'a => 'a => Bool" ("(_/ '/=/ _)" [54,54] 52)
X__XVBarXVBar__X :: "Bool => Bool => Bool" ("(_/ ||/ _)" [54,54] 52)
X__o__X :: "('b => 'c) * ('a => 'b) => 'a => 'c"
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_dropWhile :: "('a => Bool) => 'a List => 'a List"
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_init :: "'a List => 'a List partial" ("init/'(_')" [3] 999)
X_last :: "'a List => 'a partial" ("last''/'(_')" [3] 999)
X_map :: "('a => 'b) => 'a List => 'b List"
X_max :: "'a => 'a => 'a"
X_maximum :: "'d List => 'd partial" ("maximum/'(_')" [3] 999)
X_min :: "'a => 'a => 'a"
X_minimum :: "'d List => 'd partial" ("minimum/'(_')" [3] 999)
X_null :: "'a List => Bool" ("null''/'(_')" [3] 999)
X_orL :: "Bool List => Bool" ("orL/'(_')" [3] 999)
X_reverse :: "'a List => 'a List" ("reverse/'(_')" [3] 999)
X_snd :: "'a => 'b => 'b" ("snd''/'(_,/ _')" [3,3] 999)
X_tail :: "'a List => 'a List partial" ("tail/'(_')" [3] 999)
X_takeWhile :: "('a => Bool) => 'a List => 'a List"
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"
foldl1 :: "('a => 'a => 'a) => 'a List => 'a partial"
foldr1 :: "('a => 'a => 'a) => 'a List => 'a partial"
otherwiseH :: "Bool"
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"
span :: "('a => Bool) => 'a List => 'a List * 'a List"
uncurry :: "('a => 'b => 'c) => 'a * 'b => 'c"

axioms
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' = True'"

NotTrue [rule_format] : "Not' True' = False'"

AndFalse [rule_format] : "ALL x. False' && x = False'"

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 = True'"

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

NotTrue1 [rule_format] : "ALL x. Not' x = False' = (x = True')"

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

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

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

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

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

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

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 = True' = (Not' (x ==' y) = True')"

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

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

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

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

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

IBE1 [rule_format] : "True' ==' True' = True'"

IBE2 [rule_format] : "False' ==' False' = True'"

IBE3 [rule_format] : "False' ==' True' = False'"

IBE4 [rule_format] : "True' ==' False' = False'"

IBE5 [rule_format] : "True' /= False' = True'"

IBE6 [rule_format] : "False' /= True' = True'"

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

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

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

IUE2 [rule_format] : "() /= () = False'"

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

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

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

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

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

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

IOE07 [rule_format] : "LT /= EQ = True'"

IOE08 [rule_format] : "LT /= GT = True'"

IOE09 [rule_format] : "EQ /= GT = True'"

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

LeTAsymmetry [rule_format] :
"ALL x. ALL y. x <' y = True' --> y <' x = False'"

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

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

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

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

GeTAsymmetry [rule_format] :
"ALL x. ALL y. x >' y = True' --> y >' x = False'"

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

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

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

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

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

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 = True'"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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_max x y ==' y = x <=' y"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

IOO25 [rule_format] : "X_max LT EQ ==' EQ = True'"

IOO26 [rule_format] : "X_max EQ GT ==' GT = True'"

IOO27 [rule_format] : "X_max LT GT ==' GT = True'"

IOO28 [rule_format] : "X_min LT EQ ==' LT = True'"

IOO29 [rule_format] : "X_min EQ GT ==' EQ = True'"

IOO30 [rule_format] : "X_min LT GT ==' LT = True'"

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

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

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

IBO5 [rule_format] : "False' <' True' = True'"

IBO6 [rule_format] : "False' >=' True' = False'"

IBO7 [rule_format] : "True' >=' False' = True'"

IBO8 [rule_format] : "True' <' False' = False'"

IBO9 [rule_format] : "X_max False' True' ==' True' = True'"

IBO10 [rule_format] : "X_min False' True' ==' False' = True'"

IBO11 [rule_format] : "compare True' True' ==' EQ = True'"

IBO12 [rule_format] : "compare False' False' ==' EQ = True'"

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

IUO02 [rule_format] : "() <' () = False'"

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

IUO04 [rule_format] : "() >' () = False'"

IUO05 [rule_format] : "X_max () () ==' () = True'"

IUO06 [rule_format] : "X_min () () ==' () = True'"

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

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)"

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

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

FilterConsF [rule_format] :
"ALL p.
 ALL x.
 ALL xs. p x = False' --> 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))"

ILE01 [rule_format] : "Nil' ==' Nil' = True'"

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

ILO01 [rule_format] : "Nil' <' Nil' = False'"

ILO02 [rule_format] : "Nil' <=' Nil' = True'"

ILO03 [rule_format] : "Nil' >' Nil' = False'"

ILO04 [rule_format] : "Nil' >=' Nil' = True'"

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

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

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

ILO08 [rule_format] :
"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)"

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

ILO10 [rule_format] :
"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)"

ILO11 [rule_format] : "compare Nil' Nil' ==' EQ = Nil' ==' Nil'"

ILO12 [rule_format] : "compare Nil' Nil' ==' LT = Nil' <' Nil'"

ILO13 [rule_format] : "compare Nil' Nil' ==' GT = Nil' >' Nil'"

ILO14 [rule_format] :
"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"

ILO15 [rule_format] :
"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"

ILO16 [rule_format] :
"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"

ILO17 [rule_format] : "X_max Nil' Nil' ==' Nil' = Nil' <=' Nil'"

ILO18 [rule_format] : "X_min Nil' Nil' ==' Nil' = Nil' <=' Nil'"

ILO19 [rule_format] :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons z zs <=' X_Cons w ws =
 X_max (X_Cons z zs) (X_Cons w ws) ==' X_Cons w ws"

ILO20 [rule_format] :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons w ws <=' X_Cons z zs =
 X_max (X_Cons z zs) (X_Cons w ws) ==' X_Cons z zs"

ILO21 [rule_format] :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons z zs <=' X_Cons w ws =
 X_min (X_Cons z zs) (X_Cons w ws) ==' X_Cons z zs"

ILO22 [rule_format] :
"ALL w.
 ALL ws.
 ALL z.
 ALL zs.
 X_Cons w ws <=' X_Cons z zs =
 X_min (X_Cons z zs) (X_Cons w ws) ==' X_Cons w ws"

FoldlDecomp [rule_format] :
"ALL e.
 ALL i.
 ALL ts.
 ALL ys. X_foldl i e (ys ++' ts) = X_foldl i (X_foldl i e ys) ts"

MapDecomp [rule_format] :
"ALL f.
 ALL xs. ALL zs. X_map f (xs ++' zs) = X_map f xs ++' X_map f zs"

MapFunctor [rule_format] :
"ALL f.
 ALL g. ALL xs. X_map (X__o__X (g, f)) xs = X_map g (X_map f xs)"

FilterProm [rule_format] :
"ALL f.
 ALL p.
 ALL xs.
 X_filter p (X_map f xs) = X_map f (X_filter (X__o__X (p, f)) xs)"

InitNil [rule_format] : "~ defOp (init(Nil'))"

InitConsNil [rule_format] :
"ALL x. init(X_Cons x Nil') = makePartial Nil'"

InitConsCons [rule_format] :
"ALL x.
 ALL xs.
 init(X_Cons x xs) =
 restrictOp (makePartial (X_Cons x (makeTotal (init(xs)))))
 (defOp (init(xs)))"

LastNil [rule_format] : "~ defOp (last'(Nil'))"

LastConsNil [rule_format] :
"ALL x. last'(X_Cons x Nil') = makePartial x"

LastConsCons [rule_format] :
"ALL x. ALL xs. last'(X_Cons x xs) = last'(xs)"

NullNil [rule_format] : "null'(Nil') = True'"

NullCons [rule_format] :
"ALL x. ALL xs. null'(X_Cons x xs) = False'"

ReverseNil [rule_format] : "reverse(Nil') = Nil'"

ReverseCons [rule_format] :
"ALL x.
 ALL xs. reverse(X_Cons x xs) = reverse(xs) ++' X_Cons x Nil'"

Foldr1Nil [rule_format] : "ALL f. ~ defOp (foldr1 f Nil')"

Foldr1ConsNil [rule_format] :
"ALL f. ALL x. foldr1 f (X_Cons x Nil') = makePartial x"

Foldr1ConsCons [rule_format] :
"ALL f.
 ALL x.
 ALL xs.
 foldr1 f (X_Cons x xs) =
 restrictOp (makePartial (f x (makeTotal (foldr1 f xs))))
 (defOp (foldr1 f xs))"

Foldl1Nil [rule_format] : "ALL f. ~ defOp (foldl1 f Nil')"

Foldl1ConsNil [rule_format] :
"ALL f. ALL x. foldl1 f (X_Cons x Nil') = makePartial x"

Foldl1ConsCons [rule_format] :
"ALL f.
 ALL x.
 ALL xs.
 foldl1 f (X_Cons x xs) =
 restrictOp (makePartial (f x (makeTotal (foldr1 f xs))))
 (defOp (foldr1 f xs))"

ScanlNil [rule_format] :
"ALL g. ALL q. ALL ys. ys = Nil' --> scanl g q ys = X_Cons q Nil'"

ScanlCons [rule_format] :
"ALL g.
 ALL q.
 ALL ys.
 ALL z.
 ALL zs.
 ys = X_Cons z zs --> scanl g q ys = X_Cons q (scanl g (g q z) zs)"

Scanl1Nil [rule_format] : "ALL f. scanl1 f Nil' = Nil'"

Scanl1Cons [rule_format] :
"ALL f. ALL x. ALL xs. scanl1 f (X_Cons x xs) = scanl f x xs"

ScanrNil [rule_format] :
"ALL h. ALL z. scanr h z Nil' = X_Cons z Nil'"

ScanrCons [rule_format] :
"ALL h.
 ALL x.
 ALL xs.
 ALL y.
 ALL ys.
 ALL z.
 X_Cons y ys = scanr h z xs -->
 scanr h z (X_Cons x xs) = X_Cons (h x y) (X_Cons y ys)"

Scanr1Nil [rule_format] : "ALL f. scanr1 f Nil' = Nil'"

Scanr1ConsNil [rule_format] :
"ALL f. ALL x. scanr1 f (X_Cons x Nil') = X_Cons x Nil'"

Scanr1ConsCons [rule_format] :
"ALL f.
 ALL q.
 ALL qs.
 ALL x.
 ALL xs.
 X_Cons q qs = scanr1 f xs -->
 scanr1 f (X_Cons x xs) = X_Cons (f x q) (X_Cons q qs)"

ScanlProperty [rule_format] :
"ALL g.
 ALL x. ALL ys. last'(scanl g x ys) = makePartial (X_foldl g x ys)"

ScanrProperty [rule_format] :
"ALL h.
 ALL xs. ALL y. head(scanr h y xs) = makePartial (X_foldr h y xs)"

AndLNil [rule_format] : "andL(Nil') = True'"

AndLCons [rule_format] :
"ALL b1. ALL bs. andL(X_Cons b1 bs) = b1 && andL(bs)"

OrLNil [rule_format] : "orL(Nil') = False'"

OrLCons [rule_format] :
"ALL b1. ALL bs. orL(X_Cons b1 bs) = b1 || orL(bs)"

AnyDef [rule_format] :
"ALL p. ALL xs. X_any p xs = orL(X_map p xs)"

AllDef [rule_format] :
"ALL p. ALL xs. X_all p xs = andL(X_map p xs)"

ConcatDef [rule_format] :
"ALL xxs.
 concat'(xxs) =
 X_foldr (X_curry (uncurryOp X__XPlusXPlus__X)) Nil' xxs"

ConcatMapDef [rule_format] :
"ALL g. ALL xs. concatMap g xs = concat'(X_map g xs)"

MaximunNil [rule_format] : "~ defOp (maximum(Nil'))"

MaximumDef [rule_format] : "ALL ds. maximum(ds) = foldl1 X_max ds"

MinimunNil [rule_format] : "~ defOp (minimum(Nil'))"

MinimumDef [rule_format] : "ALL ds. minimum(ds) = foldl1 X_min ds"

TakeWhileNil [rule_format] : "ALL p. X_takeWhile p Nil' = Nil'"

TakeWhileConsT [rule_format] :
"ALL p.
 ALL x.
 ALL xs.
 p x = True' -->
 X_takeWhile p (X_Cons x xs) = X_Cons x (X_takeWhile p xs)"

TakeWhileConsF [rule_format] :
"ALL p.
 ALL x. ALL xs. p x = False' --> X_takeWhile p (X_Cons x xs) = Nil'"

DropWhileNil [rule_format] : "ALL p. X_dropWhile p Nil' = Nil'"

DropWhileConsT [rule_format] :
"ALL p.
 ALL x.
 ALL xs.
 p x = True' --> X_dropWhile p (X_Cons x xs) = X_dropWhile p xs"

DropWhileConsF [rule_format] :
"ALL p.
 ALL x.
 ALL xs. p x = False' --> X_dropWhile p (X_Cons x xs) = X_Cons x xs"

SpanNil [rule_format] : "ALL p. span p Nil' = (Nil', Nil')"

SpanConsT [rule_format] :
"ALL p.
 ALL x.
 ALL xs.
 p x = True' -->
 span p (X_Cons x xs) =
 (let (ys, zs) = span p xs in (X_Cons x ys, zs))"

SpanConsF [rule_format] :
"ALL p.
 ALL x.
 ALL xs.
 p x = False' -->
 span p (X_Cons x xs) =
 (let (ys, zs) = span p xs in (Nil', X_Cons x xs))"

BreakDef [rule_format] :
"ALL p.
 ALL xs. break p xs = (let q = X__o__X (Not__X, p) in span q xs)"

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 EqualReflex [simp]
declare IBE1 [simp]
declare IBE2 [simp]
declare IBE3 [simp]
declare IBE4 [simp]
declare IBE5 [simp]
declare IBE6 [simp]
declare IBE7 [simp]
declare IBE8 [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 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 IBO6 [simp]
declare IBO7 [simp]
declare IBO8 [simp]
declare IBO9 [simp]
declare IBO10 [simp]
declare IBO11 [simp]
declare IBO12 [simp]
declare IUO05 [simp]
declare IUO06 [simp]
declare IUO07 [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 ILE01 [simp]
declare ILO01 [simp]
declare ILO02 [simp]
declare ILO03 [simp]
declare ILO04 [simp]
declare ILO05 [simp]
declare ILO06 [simp]
declare ILO11 [simp]
declare ILO12 [simp]
declare ILO13 [simp]
declare ILO14 [simp]
declare ILO15 [simp]
declare ILO16 [simp]
declare ILO17 [simp]
declare ILO18 [simp]
declare InitNil [simp]
declare InitConsNil [simp]
declare LastNil [simp]
declare LastConsNil [simp]
declare LastConsCons [simp]
declare NullNil [simp]
declare NullCons [simp]
declare ReverseNil [simp]
declare Foldr1Nil [simp]
declare Foldr1ConsNil [simp]
declare Foldl1Nil [simp]
declare Foldl1ConsNil [simp]
declare Scanl1Nil [simp]
declare Scanl1Cons [simp]
declare ScanrNil [simp]
declare Scanr1Nil [simp]
declare Scanr1ConsNil [simp]
declare AndLNil [simp]
declare OrLNil [simp]
declare MaximunNil [simp]
declare MinimunNil [simp]
declare TakeWhileNil [simp]
declare TakeWhileConsF [simp]
declare DropWhileNil [simp]
declare DropWhileConsT [simp]
declare DropWhileConsF [simp]
declare SpanNil [simp]

theorem SpanThm :
"ALL p. ALL xs. span p xs = (X_takeWhile p xs, X_dropWhile p xs)"
apply(auto)
apply(case_tac xs)
apply(auto)
apply(induct_tac List)
apply(case_tac "p a")
apply(simp add: TakeWhileConsF DropWhileConsF SpanConsF)
apply(case_tac "p aa")
apply(simp add: TakeWhileConsT DropWhileConsT SpanConsT TakeWhileConsF DropWhileConsF SpanConsF TakeWhileNil DropWhileNil SpanNil)+
apply(simp only: Let_def)
apply(simp add: split_def)
apply(case_tac "p a")
apply(simp add: TakeWhileConsT DropWhileConsT SpanConsT TakeWhileConsF DropWhileConsF SpanConsF TakeWhileNil DropWhileNil SpanNil)+
done

ML "Header.record \"SpanThm\""

theorem BreakThm :
"ALL p. ALL xs. break p xs = span (X__o__X (Not__X, p)) xs"
apply(auto)
apply(case_tac xs)
apply(auto)
apply(simp add: BreakDef)
apply(simp add: Let_def)
apply(simp add: BreakDef)
done

ML "Header.record \"BreakThm\""

end


section \<open>Singletape Turing Machines\<close>

theory Singletape_TM
  imports
    TM_Common
begin

text \<open>Turing machines can be either defined via a datatype or via a locale.
  We use TMs with left endmarker and dedicated accepting and rejecting state from
  which no further transitions are allowed. Deterministic TMs can be partial.\<close>

datatype ('q,'a)tm = TM
  (Q_tm: "'q set")   (* Q - states *)
  "'a set"   (* Sigma - input alphabet *)
  (\<Gamma>_tm: "'a set")   (* Gamma - tape alphabet *)
  'a         (* blank *)
  'a         (* left endmarker *)
  "('q \<times> 'a \<times> 'q \<times> 'a \<times> dir) set" (* transitions \<delta> *)
  'q         (* start state *)
  'q         (* accept state *)
  'q         (* reject state *)

datatype ('a, 'q) st_config = Config\<^sub>S
  "'q"         (* state *)
  "nat \<Rightarrow> 'a"  (* tape content *)
  "nat"        (* tape position *)

locale singletape_tm =
  fixes
    Q :: "'q set" and
    \<Sigma> :: "'a set" and
    \<Gamma> :: "'a set" and
    blank :: 'a and
    LE :: 'a and
    \<delta> :: "('q \<times> 'a \<times> 'q \<times> 'a \<times> dir) set" and
    s :: 'q and
    t :: 'q and
    r :: 'q
  assumes
    fin_Q: "finite Q" and
    fin_\<Gamma>: "finite \<Gamma>" and
    \<Sigma>_sub_\<Gamma>: "\<Sigma> \<subseteq> \<Gamma>" and
    sQ: "s \<in> Q" and
    tQ: "t \<in> Q" and
    rQ: "r \<in> Q" and
    blank: "blank \<in> \<Gamma>" "blank \<notin> \<Sigma>" and
    LE: "LE \<in> \<Gamma>" "LE \<notin> \<Sigma>" and
    tr: "t \<noteq> r" and
    \<delta>_set: "\<delta> \<subseteq> (Q - {t,r}) \<times> \<Gamma> \<times> Q \<times> \<Gamma> \<times> UNIV" and
    \<delta>LE: "(q, LE, q', a', d) \<in> \<delta> \<Longrightarrow> a' = LE \<and> d \<in> {dir.N,dir.R}"
begin

lemma \<delta>: assumes "(q,a,q',b,d) \<in> \<delta>"
  shows "q \<in> Q" "a \<in> \<Gamma>" "q' \<in> Q" "b \<in> \<Gamma>"
  using assms \<delta>_set by auto

lemma fin\<Sigma>: "finite \<Sigma>"
  using fin_\<Gamma> \<Sigma>_sub_\<Gamma> by (metis finite_subset)

lemmas tm = sQ \<Sigma>_sub_\<Gamma> blank(1) LE(1)

fun valid_config :: "('a, 'q) st_config \<Rightarrow> bool" where
  "valid_config (Config\<^sub>S q w n) = (q \<in> Q \<and> range w \<subseteq> \<Gamma>)"

definition init_config :: "'a list  \<Rightarrow> ('a,'q)st_config" where
  "init_config w = (Config\<^sub>S s (\<lambda> n. if n = 0 then LE else if n \<le> length w then w ! (n-1) else blank) 0)"

lemma valid_init_config: "set w \<subseteq> \<Sigma> \<Longrightarrow> valid_config (init_config w)"
  unfolding init_config_def valid_config.simps using tm by (force simp: set_conv_nth)

inductive_set step :: "('a, 'q) st_config rel" where
  step: "(q, ts n, q', a, dir) \<in> \<delta> \<Longrightarrow>
  (Config\<^sub>S q ts n, Config\<^sub>S q' (ts(n := a)) (go_dir dir n)) \<in> step"

lemma stepI: "(q, a, q', b, dir) \<in> \<delta> \<Longrightarrow> ts n = a \<Longrightarrow> ts' = ts(n := b) \<Longrightarrow> n' = go_dir dir n \<Longrightarrow> q1 = q \<Longrightarrow> q2 = q'
  \<Longrightarrow> (Config\<^sub>S q1 ts n, Config\<^sub>S q2 ts' n') \<in> step"
  using step[of q ts n q' b dir] by auto

lemma valid_step: assumes step: "(\<alpha>,\<beta>) \<in> step"
  and val: "valid_config \<alpha>"
shows "valid_config \<beta>"
  using step
proof (cases rule: step.cases)
  case (step q ts n q' a dir)
  from \<delta>[OF step(3)] val
  show ?thesis unfolding step(1-2) by auto
qed

definition Lang :: "'a list set" where
  "Lang = {w . set w \<subseteq> \<Sigma> \<and> (\<exists> w' n. (init_config w, Config\<^sub>S t w' n) \<in> step^*)}"

definition deterministic where
  "deterministic = (\<forall> q a p1 b1 d1 p2 b2 d2. (q,a,p1,b1,d1) \<in> \<delta> \<longrightarrow> (q,a,p2,b2,d2) \<in> \<delta> \<longrightarrow> (p1,b1,d1) = (p2,b2,d2))"

definition upper_time_bound :: "(nat \<Rightarrow> nat) \<Rightarrow> bool" where
  "upper_time_bound f = (\<forall> w c n. set w \<subseteq> \<Sigma> \<longrightarrow> (init_config w, c) \<in> step^^n \<longrightarrow> n \<le> f (length w))"
end

fun valid_tm :: "('q,'a)tm \<Rightarrow> bool" where
  "valid_tm (TM Q \<Sigma> \<Gamma> bl le \<delta> s t r) = singletape_tm Q \<Sigma> \<Gamma> bl le \<delta> s t r"

fun Lang_tm :: "('q,'a)tm \<Rightarrow> 'a list set" where
  "Lang_tm (TM Q \<Sigma> \<Gamma> bl le \<delta> s t r) = singletape_tm.Lang \<Sigma> bl le \<delta> s t"

fun det_tm :: "('q,'a)tm \<Rightarrow> bool" where
  "det_tm (TM Q \<Sigma> \<Gamma> bl le \<delta> s t r) = singletape_tm.deterministic \<delta>"

fun upperb_time_tm :: "('q,'a)tm \<Rightarrow> (nat \<Rightarrow> nat) \<Rightarrow> bool" where
  "upperb_time_tm (TM Q \<Sigma> \<Gamma> bl le \<delta> s t r) f = singletape_tm.upper_time_bound \<Sigma> bl le \<delta> s f"

context singletape_tm
begin

text \<open>A deterministic step (in a potentially non-determistic TM) is a step without alternatives.
  This will be useful in the translation of multitape TMs. The simulation is mostly deterministic, and
  only at very specific points it is non-determistic, namely at the points where the multitape-TM transition
  is chosen.\<close>

inductive_set dstep :: "('a, 'q) st_config rel" where
  dstep: "(q, ts n, q', a, dir) \<in> \<delta> \<Longrightarrow>
    (\<And> q1' a1 dir1. (q, ts n, q1', a1, dir1) \<in> \<delta> \<Longrightarrow> (q1',a1,dir1) = (q',a,dir)) \<Longrightarrow>
  (Config\<^sub>S q ts n, Config\<^sub>S q' (ts(n := a)) (go_dir dir n)) \<in> dstep"

lemma dstepI: "(q, a, q', b, dir) \<in> \<delta> \<Longrightarrow> ts n = a \<Longrightarrow> ts' = ts(n := b) \<Longrightarrow> n' = go_dir dir n \<Longrightarrow> q1 = q \<Longrightarrow> q2 = q'
  \<Longrightarrow> (\<And> q'' b' dir'. (q, a, q'', b', dir') \<in> \<delta> \<Longrightarrow> (q'', b', dir') = (q',b,dir))
  \<Longrightarrow> (Config\<^sub>S q1 ts n, Config\<^sub>S q2 ts' n') \<in> dstep"
  using dstep[of q ts n q' b dir] by blast

lemma dstep_step: "dstep \<subseteq> step"
proof
  fix st
  assume dstep: "st \<in> dstep"
  obtain s t where st: "st = (s,t)" by force
  have "(s,t) \<in> step" using dstep[unfolded st]
  proof (cases rule: dstep.cases)
    case 1: (dstep q ts n q' a dir)
    show ?thesis unfolding 1(1-2) by (rule stepI[OF 1(3)], auto)
  qed
  thus "st \<in> step" using st by auto
qed

lemma dstep_inj: assumes "(x,y) \<in> dstep"
  and "(x,z) \<in> step"
shows "z = y"
  using assms(2)
proof (cases)
  case 1: (step q ts n p a d)
  show ?thesis using assms(1) unfolding 1(1)
  proof cases
    case 2: (dstep p' a' d')
    from 2(3)[OF 1(3)] have id: "p' = p" "a' = a" "d' = d" by auto
    show ?thesis unfolding 1 2 id ..
  qed
qed

lemma dsteps_inj: assumes "(x,y) \<in> dstep^^n"
  and "(x,z) \<in> step^^m"
  and "\<not> (\<exists> u. (z,u) \<in> step)"
shows "\<exists> k. m = n + k \<and> (y,z) \<in> step^^k"
  using assms(1-2)
proof (induct n arbitrary: m x)
  case (Suc n m x)
  from Suc(2) obtain x' where step: "(x,x') \<in> dstep" and steps: "(x',y) \<in> dstep^^n" by (metis relpow_Suc_E2)
  from step dstep_step have "(x,x') \<in> step" by auto
  with assms(3) have "x \<noteq> z" by auto
  with Suc(3) obtain mm where m: "m = Suc mm" by (cases m, auto)
  from Suc(3)[unfolded this] obtain x'' where step': "(x,x'') \<in> step" and steps': "(x'',z) \<in> step^^mm" by (metis relpow_Suc_E2)
  from dstep_inj[OF step step'] have x'': "x'' = x'" by auto
  from Suc(1)[OF steps steps'[unfolded x'']] obtain k where mm: "mm = n + k" and steps: "(y, z) \<in> step ^^ k" by auto
  thus ?case unfolding m mm by auto
qed auto

lemma dsteps_inj': assumes "(x,y) \<in> dstep^^n"
  and "(x,z) \<in> step^^m"
  and "m \<ge> n"
shows "\<exists> k. m = n + k \<and> (y,z) \<in> step^^k"
  using assms(1-3)
proof (induct n arbitrary: m x)
  case (Suc n m x)
  from Suc(2) obtain x' where step: "(x,x') \<in> dstep" and steps: "(x',y) \<in> dstep^^n" by (metis relpow_Suc_E2)
  from step dstep_step have "(x,x') \<in> step" by auto
  with Suc obtain mm where m: "m = Suc mm" by (cases m, auto)
  from Suc(3)[unfolded this] obtain x'' where step': "(x,x'') \<in> step" and steps': "(x'',z) \<in> step^^mm" by (metis relpow_Suc_E2)
  from dstep_inj[OF step step'] have x'': "x'' = x'" by auto
  from Suc(1)[OF steps steps'[unfolded x'']] m Suc obtain k where mm: "mm = n + k" and steps: "(y, z) \<in> step ^^ k" by auto
  thus ?case unfolding m mm by auto
qed auto
end
end


(* Title:      Regular Algebras
   Author:     Simon Foster, Georg Struth
   Maintainer: Simon Foster <s.foster at york.ac.uk>
               Georg Struth <g.struth at sheffield.ac.uk>
*)

section \<open>Pratt's Counterexamples\<close>

theory Pratts_Counterexamples
  imports Regular_Algebras
begin

text \<open>We create two regular algebra models due to Pratt~\<^cite>\<open>"Pratt"\<close> which are used to
        distinguish K1 algebras from K1l and K1r algebras.\<close>

datatype pratt1 =
  P1Bot ("\<bottom>\<^sub>1") |
  P1Nat nat ("[_]\<^sub>1") |
  P1Infty ("\<infinity>\<^sub>1") |
  P1Top ("\<top>\<^sub>1")

datatype pratt2 =
  P2Bot ("\<bottom>\<^sub>2") |
  P2Nat nat ("[_]\<^sub>2") |
  P2Infty ("\<infinity>\<^sub>2") |
  P2Top ("\<top>\<^sub>2")

fun pratt1_max where
  "pratt1_max [x]\<^sub>1 [y]\<^sub>1 = [max x y]\<^sub>1" |
  "pratt1_max x \<bottom>\<^sub>1 = x" |
  "pratt1_max \<bottom>\<^sub>1 y = y" |
  "pratt1_max \<infinity>\<^sub>1 [y]\<^sub>1 = \<infinity>\<^sub>1" |
  "pratt1_max [y]\<^sub>1 \<infinity>\<^sub>1 = \<infinity>\<^sub>1" |
  "pratt1_max \<infinity>\<^sub>1 \<infinity>\<^sub>1 = \<infinity>\<^sub>1" |
  "pratt1_max \<top>\<^sub>1 x = \<top>\<^sub>1" |
  "pratt1_max x \<top>\<^sub>1 = \<top>\<^sub>1"

fun pratt1_plus :: "pratt1 \<Rightarrow> pratt1 \<Rightarrow> pratt1" (infixl "+\<^sub>1" 65) where
  "[x]\<^sub>1 +\<^sub>1 [y]\<^sub>1 = [x + y]\<^sub>1" |
  "\<bottom>\<^sub>1 +\<^sub>1 x = \<bottom>\<^sub>1" |
  "x +\<^sub>1 \<bottom>\<^sub>1 = \<bottom>\<^sub>1" |
  "\<infinity>\<^sub>1 +\<^sub>1 [0]\<^sub>1 = \<infinity>\<^sub>1" |
  "[0]\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<infinity>\<^sub>1" |
  "\<infinity>\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<top>\<^sub>1" | (* Can be adjusted to PInfty *)
  "\<top>\<^sub>1 +\<^sub>1 x = \<top>\<^sub>1" |
  "x +\<^sub>1 \<top>\<^sub>1 = \<top>\<^sub>1" |
  "[x]\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<infinity>\<^sub>1" |
  "\<infinity>\<^sub>1 +\<^sub>1 x = \<top>\<^sub>1"

lemma plusl_top_infty: "\<top>\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<top>\<^sub>1"
  by (simp)

lemma plusl_infty_top: "\<infinity>\<^sub>1 +\<^sub>1 \<top>\<^sub>1  = \<top>\<^sub>1"
  by (simp)

lemma plusl_bot_infty: "\<bottom>\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<bottom>\<^sub>1"
  by (simp)

lemma plusl_infty_bot: "\<infinity>\<^sub>1 +\<^sub>1 \<bottom>\<^sub>1  = \<bottom>\<^sub>1"
  by (simp)

lemma plusl_zero_infty: "[0]\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<infinity>\<^sub>1"
  by (simp)

lemma plusl_infty_zero: "\<infinity>\<^sub>1 +\<^sub>1 [0]\<^sub>1 = \<infinity>\<^sub>1"
  by (simp)

lemma plusl_infty_num [simp]: "x > 0 \<Longrightarrow> \<infinity>\<^sub>1 +\<^sub>1 [x]\<^sub>1 = \<top>\<^sub>1"
  by (case_tac x, simp_all)

lemma plusl_num_infty [simp]: "x > 0 \<Longrightarrow> [x]\<^sub>1 +\<^sub>1 \<infinity>\<^sub>1 = \<infinity>\<^sub>1"
  by (case_tac x, simp_all)

fun pratt2_max where
  "pratt2_max [x]\<^sub>2 [y]\<^sub>2 = [max x y]\<^sub>2" |
  "pratt2_max x \<bottom>\<^sub>2 = x" |
  "pratt2_max \<bottom>\<^sub>2 y = y" |
  "pratt2_max \<infinity>\<^sub>2 [y]\<^sub>2 = \<infinity>\<^sub>2" |
  "pratt2_max [y]\<^sub>2 \<infinity>\<^sub>2 = \<infinity>\<^sub>2" |
  "pratt2_max \<infinity>\<^sub>2 \<infinity>\<^sub>2 = \<infinity>\<^sub>2" |
  "pratt2_max \<top>\<^sub>2 x = \<top>\<^sub>2" |
  "pratt2_max x \<top>\<^sub>2 = \<top>\<^sub>2"

fun pratt2_plus :: "pratt2 \<Rightarrow> pratt2 \<Rightarrow> pratt2" (infixl "+\<^sub>2" 65) where
  "[x]\<^sub>2 +\<^sub>2 [y]\<^sub>2 = [x + y]\<^sub>2" |
  "\<bottom>\<^sub>2 +\<^sub>2 x = \<bottom>\<^sub>2" |
  "x +\<^sub>2 \<bottom>\<^sub>2 = \<bottom>\<^sub>2" |
  "\<infinity>\<^sub>2 +\<^sub>2 [0]\<^sub>2 = \<infinity>\<^sub>2" |
  "[0]\<^sub>2 +\<^sub>2 \<infinity>\<^sub>2 = \<infinity>\<^sub>2" |
  "\<infinity>\<^sub>2 +\<^sub>2 \<infinity>\<^sub>2 = \<top>\<^sub>2" | (* Can be adjusted to PInfty *)
  "\<top>\<^sub>2 +\<^sub>2 x = \<top>\<^sub>2" |
  "x +\<^sub>2 \<top>\<^sub>2 = \<top>\<^sub>2" |
  "x +\<^sub>2 \<infinity>\<^sub>2 = \<top>\<^sub>2" |
  "\<infinity>\<^sub>2 +\<^sub>2 [x]\<^sub>2 = \<infinity>\<^sub>2"

instantiation pratt1 :: selective_semiring
begin

  definition zero_pratt1_def:
    "0 \<equiv> \<bottom>\<^sub>1"

  definition one_pratt1_def:
    "1 \<equiv> [0]\<^sub>1"

  definition plus_pratt1_def:
    "x + y \<equiv> pratt1_max x y"

  definition times_pratt1_def:
    "x * y \<equiv> x +\<^sub>1 y"

  definition less_eq_pratt1_def:
    "(x::pratt1) \<le> y \<equiv> x + y = y"

  definition less_pratt1_def:
    "(x::pratt1) < y \<equiv> x \<le> y \<and> x \<noteq> y"

  instance
  proof
    fix x y z :: pratt1
    show "x + y + z = x + (y + z)"
      by (case_tac x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt1_def)
    show "x + y = y + x"
      by (cases x, case_tac[!] y, simp_all add: plus_pratt1_def)
    show "x * y * z = x * (y * z)"
      apply (cases x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt1_def times_pratt1_def)
      apply (rename_tac[!] n, case_tac[!] n, auto)
      apply (metis nat.exhaust plusl_zero_infty pratt1_plus.simps(14))
      apply (metis not0_implies_Suc plusl_infty_zero plusl_zero_infty pratt1_plus.simps(14))
      apply (metis neq0_conv plusl_num_infty plusl_zero_infty pratt1_plus.simps(15))
      apply (metis not0_implies_Suc plusl_infty_zero pratt1_plus.simps(15) pratt1_plus.simps(9))
      apply (metis not0_implies_Suc plusl_infty_zero pratt1_plus.simps(15) pratt1_plus.simps(9))
    done
    show "(x + y) * z = x * z + y * z"
      apply (cases x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt1_def times_pratt1_def)
      apply (rename_tac[!] n, case_tac[!] n, auto)
      apply (metis neq0_conv plusl_num_infty plusl_zero_infty pratt1_max.simps(8))+
    done
    show "1 * x = x"
      by (cases x, simp_all add: one_pratt1_def times_pratt1_def)
    show "x * 1 = x"
      by (cases x, simp_all add: one_pratt1_def times_pratt1_def)
    show "0 + x = x"
      by (cases x, simp_all add: plus_pratt1_def zero_pratt1_def)
    show "0 * x = 0"
      by (cases x, simp_all add: times_pratt1_def zero_pratt1_def)
    show "x * 0 = 0"
      by (cases x, simp_all add: times_pratt1_def zero_pratt1_def)
    show "x \<le> y \<longleftrightarrow> x + y = y"
      by (metis less_eq_pratt1_def)
    show "x < y \<longleftrightarrow> x \<le> y \<and> x \<noteq> y"
      by (metis less_pratt1_def)
    show "x + y = x \<or> x + y = y"
      by (cases x, case_tac[!] y, simp_all add: plus_pratt1_def max_def)
    show "x * (y + z) = x * y + x * z"
      apply (cases x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt1_def times_pratt1_def)
      apply (rename_tac[!] n, case_tac[!] n, auto)
      apply (metis nat.exhaust plusl_zero_infty pratt1_max.simps(7) pratt1_plus.simps(14))
      apply (metis neq0_conv plusl_num_infty plusl_zero_infty pratt1_max.simps(7))
      apply (metis nat.exhaust plusl_zero_infty pratt1_max.simps(6) pratt1_plus.simps(14))
      apply (metis neq0_conv plusl_num_infty plusl_zero_infty pratt1_max.simps(6))
      apply (metis neq0_conv plusl_infty_num plusl_infty_zero pratt1_max.simps(10) pratt1_max.simps(8))
      apply (metis not0_implies_Suc plusl_infty_zero pratt1_max.simps(11) pratt1_max.simps(13) pratt1_plus.simps(15))
    done
  qed
end

instance pratt1 :: dioid_one_zero ..

instantiation pratt2 :: selective_semiring
begin

  definition zero_pratt2_def:
    "0 \<equiv> \<bottom>\<^sub>2"

  definition one_pratt2_def:
    "1 \<equiv> [0]\<^sub>2"

  definition times_pratt2_def:
    "x * y \<equiv> x +\<^sub>2 y"

  definition plus_pratt2 :: "pratt2 \<Rightarrow> pratt2 \<Rightarrow> pratt2" where
    "plus_pratt2 x y \<equiv> pratt2_max x y"

  definition less_eq_pratt2_def:
    "(x::pratt2) \<le> y \<equiv> x + y = y"

  definition less_pratt2_def:
    "(x::pratt2) < y \<equiv> x \<le> y \<and> x \<noteq> y"

  instance
  proof
    fix x y z :: pratt2
    show "x + y + z = x + (y + z)"
      by (case_tac x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt2_def)
    show "x + y = y + x"
      by (cases x, case_tac[!] y, simp_all add: plus_pratt2_def)
    show "x * y * z = x * (y * z)"
      apply (cases x, case_tac[!] y, case_tac[!] z, auto simp add: times_pratt2_def)
      apply (rename_tac[!] n, case_tac[!] n, auto)
      apply (metis not0_implies_Suc pratt2_plus.simps(14) pratt2_plus.simps(6) pratt2_plus.simps(7) pratt2_plus.simps(9))
      apply (metis not0_implies_Suc pratt2_plus.simps(14) pratt2_plus.simps(15) pratt2_plus.simps(7) pratt2_plus.simps(9))
      apply (metis not0_implies_Suc pratt2_plus.simps(15) pratt2_plus.simps(6))
      apply (metis not0_implies_Suc pratt2_plus.simps(15) pratt2_plus.simps(6))
    done
    show "(x + y) * z = x * z + y * z"
      apply (cases x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt2_def times_pratt2_def)
      apply (rename_tac[!] n, case_tac[!] n, auto)
      apply (metis not0_implies_Suc pratt2_max.simps(10) pratt2_max.simps(8) pratt2_plus.simps(14) pratt2_plus.simps(7))
      apply (metis max_0L max_0R max.left_idem nat.exhaust pratt2_max.simps(11)
                   pratt2_max.simps(13) pratt2_plus.simps(14) pratt2_plus.simps(7))
    done
    show "1 * x = x"
      by (cases x, simp_all add: one_pratt2_def times_pratt2_def)
    show "x * 1 = x"
      by (cases x, simp_all add: one_pratt2_def times_pratt2_def)
    show "0 + x = x"
      by (cases x, simp_all add: plus_pratt2_def zero_pratt2_def)
    show "0 * x = 0"
      by (cases x, simp_all add: times_pratt2_def zero_pratt2_def)
    show "x * 0 = 0"
      by (cases x, simp_all add: times_pratt2_def zero_pratt2_def)
    show "x \<le> y \<longleftrightarrow> x + y = y"
      by (metis less_eq_pratt2_def)
    show "x < y \<longleftrightarrow> x \<le> y \<and> x \<noteq> y"
      by (metis less_pratt2_def)
    show "x + y = x \<or> x + y = y"
      by (cases x, case_tac[!] y, simp_all add: plus_pratt2_def max_def)
    show "x * (y + z) = x * y + x * z"
      apply (cases x, case_tac[!] y, case_tac[!] z, simp_all add: plus_pratt2_def times_pratt2_def)
      apply (rename_tac[!] n, case_tac[!] n, auto)
      apply (metis not0_implies_Suc pratt2_max.simps(12) pratt2_max.simps(7) pratt2_plus.simps(14) pratt2_plus.simps(7))
      apply (metis nat.exhaust pratt2_max.simps(12) pratt2_max.simps(7) pratt2_plus.simps(14) pratt2_plus.simps(7))
      apply (metis not0_implies_Suc pratt2_max.simps(6) pratt2_max.simps(9) pratt2_plus.simps(14) pratt2_plus.simps(7))
      apply (metis nat.exhaust pratt2_max.simps(6) pratt2_max.simps(9) pratt2_plus.simps(14) pratt2_plus.simps(7))
      apply (metis not0_implies_Suc pratt2_max.simps(8) pratt2_plus.simps(15) pratt2_plus.simps(6))
      apply (metis not0_implies_Suc pratt2_max.simps(8) pratt2_plus.simps(15) pratt2_plus.simps(6))
    done
  qed
end

lemma top_greatest: "x \<le> \<top>\<^sub>1"
  by (case_tac x, auto simp add: less_eq_pratt1_def plus_pratt1_def)

instantiation pratt1 :: star_op
begin

  definition star_pratt1 where
    "x\<^sup>\<star> \<equiv> if (x = \<bottom>\<^sub>1 \<or> x = [0]\<^sub>1) then [0]\<^sub>1 else \<top>\<^sub>1"
  instance ..
end

instantiation pratt2 :: star_op
begin
  definition star_pratt2 where
    "x\<^sup>\<star> \<equiv> if (x = \<bottom>\<^sub>2 \<or> x = [0]\<^sub>2) then [0]\<^sub>2 else \<top>\<^sub>2"
  instance ..
end

instance pratt1 :: K1r_algebra
proof
  fix x :: pratt1
  show "1 + x\<^sup>\<star> \<cdot> x \<le> x\<^sup>\<star>"
    by  (case_tac x, auto simp add: star_pratt1_def one_pratt1_def times_pratt1_def less_eq_pratt1_def plus_pratt1_def)
next
  fix x y :: pratt1
  show "y \<cdot> x \<le> y \<Longrightarrow> y \<cdot> x\<^sup>\<star> \<le> y"
    apply (case_tac x, case_tac[!] y)
    apply (auto simp add:star_pratt1_def one_pratt1_def times_pratt1_def less_eq_pratt1_def plus_pratt1_def)
    apply (rename_tac n, case_tac n)
    apply (simp_all)
    by (metis not0_implies_Suc plusl_zero_infty pratt1.distinct(7) pratt1_max.simps(6) pratt1_plus.simps(14))
qed

instance pratt2 :: K1l_algebra
proof
  fix x :: pratt2
  show "1 + x\<cdot>x\<^sup>\<star> \<le> x\<^sup>\<star>"
    by (case_tac x, auto simp add: star_pratt2_def one_pratt2_def times_pratt2_def less_eq_pratt2_def plus_pratt2_def)
next
  fix x y :: pratt2
  show "x \<cdot> y \<le> y \<Longrightarrow> x\<^sup>\<star> \<cdot> y \<le> y"
    apply (case_tac x, case_tac[!] y)
    apply (auto simp add:star_pratt2_def one_pratt2_def times_pratt2_def less_eq_pratt2_def plus_pratt2_def)
    apply (rename_tac n, case_tac n)
    apply (simp_all)
    apply (rename_tac n, case_tac n)
    apply (auto simp add:star_pratt2_def one_pratt2_def times_pratt2_def less_eq_pratt2_def plus_pratt2_def)
  done
qed

lemma one_star_top: "[1]\<^sub>1\<^sup>\<star> = \<top>\<^sub>1"
  by (simp add:star_pratt1_def one_pratt1_def)

lemma pratt1_kozen_1l_counterexample:
  "\<exists> x y :: pratt1. \<not> (x \<cdot> y \<le> y \<and> x\<^sup>\<star> \<cdot> y \<le> y)"
proof -
  have "\<not> ([1]\<^sub>1 \<cdot> \<infinity>\<^sub>1 \<le> \<infinity>\<^sub>1 \<and> [1]\<^sub>1\<^sup>\<star> \<cdot> \<infinity>\<^sub>1 \<le> \<infinity>\<^sub>1)"
    by (auto simp add: star_pratt1_def times_pratt1_def less_eq_pratt1_def plus_pratt1_def)
  thus ?thesis
    by auto
qed

lemma pratt2_kozen_1r_counterexample:
  "\<exists> x y :: pratt2. \<not> (y \<cdot> x \<le> y \<and> y \<cdot> x\<^sup>\<star> \<le> y)"
proof -
  have "\<not> (\<infinity>\<^sub>2 \<cdot> [1]\<^sub>2 \<le> \<infinity>\<^sub>2 \<and> \<infinity>\<^sub>2 \<cdot> [1]\<^sub>2\<^sup>\<star> \<le> \<infinity>\<^sub>2)"
    by (auto simp add: star_pratt2_def times_pratt2_def less_eq_pratt2_def plus_pratt2_def)
  thus ?thesis
    by auto
qed

end