Theory Syntax

theory Syntax
imports
  Complex_Main
  "Ids"
begin 
section ‹Syntax›
text ‹
  We define the syntax of dL terms, formulas and hybrid programs. As in
  CADE'15, the syntax allows arbitrarily nested differentials. However, 
  the semantics of such terms is very surprising (e.g. (x')' is zero in
  every state), so we define predicates dfree and dsafe to describe terms
  with no differentials and no nested differentials, respectively.

  In keeping with the CADE'15 presentation we currently make the simplifying
  assumption that all terms are smooth, and thus division and arbitrary
  exponentiation are absent from the syntax. Several other standard logical
  constructs are implemented as derived forms to reduce the soundness burden.
  
  The types of formulas and programs are parameterized by three finite types 
  ('a, 'b, 'c) used as identifiers for function constants, context constants, and
  everything else, respectively. These type variables are distinct because some
  substitution operations affect one type variable while leaving the others unchanged.
  Because these types will be finite in practice, it is more useful to think of them
  as natural numbers that happen to be represented as types (due to HOL's lack of dependent types).
  The types of terms and ODE systems follow the same approach, but have only two type 
  variables because they cannot contain contexts.
›
datatype ('a, 'c) trm =
― ‹Real-valued variables given meaning by the state and modified by programs.›
  Var 'c
― ‹N.B. This is technically more expressive than true dL since most reals›
― ‹can't be written down.›
| Const real
― ‹A function (applied to its arguments) consists of an identifier for the function›
― ‹and a function 'c ⇒ ('a, 'c) trm› (where 'c› is a finite type) which specifies one›
― ‹argument of the function for each element of type 'c›. To simulate a function with›
― ‹less than 'c› arguments, set the remaining arguments to a constant, such as Const 0›
| Function 'a "'c  ('a, 'c) trm" ("$f")
| Plus "('a, 'c) trm" "('a, 'c) trm"
| Times "('a, 'c) trm" "('a, 'c) trm"
― ‹A (real-valued) variable standing for a differential, such as x'›, given meaning by the state›
― ‹and modified by programs.›
| DiffVar 'c ("$''")
― ‹The differential of an arbitrary term (θ)'›
| Differential "('a, 'c) trm"

datatype('a, 'c) ODE =
― ‹Variable standing for an ODE system, given meaning by the interpretation›
OVar 'c
― ‹Singleton ODE defining x' = θ›, where θ› may or may not contain x›
― ‹(but must not contain differentials)›
| OSing 'c "('a, 'c) trm"
― ‹The product OProd ODE1 ODE2› composes two ODE systems in parallel, e.g.›
― ‹OProd (x' = y) (y' = -x)› is the system {x' = y, y' = -x}›
| OProd "('a, 'c) ODE" "('a, 'c) ODE"

datatype ('a, 'b, 'c) hp =
― ‹Variables standing for programs, given meaning by the interpretation.›
  Pvar 'c                           ("")
― ‹Assignment to a real-valued variable x := θ›
| Assign 'c "('a, 'c) trm"                (infixr ":=" 10)
― ‹Assignment to a differential variable›
| DiffAssign 'c "('a, 'c) trm"
― ‹Program ?φ› succeeds iff φ› holds in current state.›
| Test "('a, 'b, 'c) formula"                 ("?")
― ‹An ODE program is an ODE system with some evolution domain.›
| EvolveODE "('a, 'c) ODE" "('a, 'b, 'c) formula"
― ‹Non-deterministic choice between two programs a› and b›
| Choice "('a, 'b, 'c) hp" "('a, 'b, 'c) hp"            (infixl "∪∪" 10)
― ‹Sequential composition of two programs a› and b›
| Sequence "('a, 'b, 'c) hp"  "('a, 'b, 'c) hp"         (infixr ";;" 8)
― ‹Nondeterministic repetition of a program a›, zero or more times.›
| Loop "('a, 'b, 'c) hp"                      ("_**")

and ('a, 'b, 'c) formula =
  Geq "('a, 'c) trm" "('a, 'c) trm"
| Prop 'c "'c  ('a, 'c) trm"      ("")
| Not "('a, 'b, 'c) formula"            ("!")
| And "('a, 'b, 'c) formula" "('a, 'b, 'c) formula"    (infixl "&&" 8)
| Exists 'c "('a, 'b, 'c) formula"
― ‹⟨α⟩φ› iff exists run of α› where φ› is true in end state›
| Diamond "('a, 'b, 'c) hp" "('a, 'b, 'c) formula"         ("( _  _)" 10)
― ‹Contexts C› are symbols standing for functions from (the semantics of) formulas to›
― ‹(the semantics of) formulas, thus C(φ)› is another formula. While not necessary›
― ‹in terms of expressiveness, contexts allow for more efficient reasoning principles.›
| InContext 'b "('a, 'b, 'c) formula"
    
― ‹Derived forms›
definition Or :: "('a, 'b, 'c) formula  ('a, 'b, 'c) formula  ('a, 'b, 'c) formula" (infixl "||" 7)
where "Or P Q = Not (And (Not P) (Not Q))"

definition Implies :: "('a, 'b, 'c) formula  ('a, 'b, 'c) formula  ('a, 'b, 'c) formula" (infixr "" 10)
where "Implies P Q = Or Q (Not P)"

definition Equiv :: "('a, 'b, 'c) formula  ('a, 'b, 'c) formula  ('a, 'b, 'c) formula" (infixl "" 10)
where "Equiv P Q = Or (And P Q) (And (Not P) (Not Q))"

definition Forall :: "'c  ('a, 'b, 'c) formula  ('a, 'b, 'c) formula"
where "Forall x P = Not (Exists x (Not P))"

definition Equals :: "('a, 'c) trm  ('a, 'c) trm  ('a, 'b, 'c) formula"
where "Equals θ θ' = ((Geq θ θ') && (Geq θ' θ))"

definition Greater :: "('a, 'c) trm  ('a, 'c) trm  ('a, 'b, 'c) formula"
where "Greater θ θ' = ((Geq θ θ') && (Not (Geq θ' θ)))"
  
definition Box :: "('a, 'b, 'c) hp  ('a, 'b, 'c) formula  ('a, 'b, 'c) formula" ("([[_]]_)" 10)
where "Box α P = Not (Diamond α (Not P))"
  
definition TT ::"('a,'b,'c) formula" 
where "TT = Geq (Const 0) (Const 0)"

definition FF ::"('a,'b,'c) formula" 
where "FF = Geq (Const 0) (Const 1)"

type_synonym ('a,'b,'c) sequent = "('a,'b,'c) formula list * ('a,'b,'c) formula list"
― ‹Rule: assumptions, then conclusion›
type_synonym ('a,'b,'c) rule = "('a,'b,'c) sequent list * ('a,'b,'c) sequent"

  
― ‹silliness to enable proving disequality lemmas›
primrec sizeF::"('sf,'sc, 'sz) formula  nat"
  and   sizeP::"('sf,'sc, 'sz) hp  nat"
where 
  "sizeP (Pvar a) = 1"
| "sizeP (Assign x θ) = 1"
| "sizeP (DiffAssign x θ) = 1"
| "sizeP (Test φ) = Suc (sizeF φ)"
| "sizeP (EvolveODE ODE φ) = Suc (sizeF φ)"
| "sizeP (Choice α β) = Suc (sizeP α + sizeP β)"
| "sizeP (Sequence α β) = Suc (sizeP α + sizeP β)"
| "sizeP (Loop α) = Suc (sizeP α)"
| "sizeF (Geq p q) = 1"
| "sizeF (Prop p args) = 1"
| "sizeF (Not p) = Suc (sizeF p)"
| "sizeF (And p q) = sizeF p + sizeF q"
| "sizeF (Exists x p) = Suc (sizeF p)"
| "sizeF (Diamond p q) = Suc (sizeP p + sizeF q)"
| "sizeF (InContext C φ) = Suc (sizeF φ)"

lemma sizeF_diseq:"sizeF p  sizeF q  p  q" by auto
  
named_theorems "expr_diseq" "Structural disequality rules for expressions"  
lemma [expr_diseq]:"p  And p q" by(induction p, auto)
lemma [expr_diseq]:"q  And p q" by(induction q, auto)
lemma [expr_diseq]:"p  Not p" by(induction p, auto)
lemma [expr_diseq]:"p  Or p q" by(rule sizeF_diseq, auto simp add: Or_def)
lemma [expr_diseq]:"q  Or p q" by(rule sizeF_diseq, auto simp add: Or_def)
lemma [expr_diseq]:"p  Implies p q" by(rule sizeF_diseq, auto simp add: Implies_def Or_def)
lemma [expr_diseq]:"q  Implies p q" by(rule sizeF_diseq, auto simp add: Implies_def Or_def)
lemma [expr_diseq]:"p  Equiv p q" by(rule sizeF_diseq, auto simp add: Equiv_def Or_def)
lemma [expr_diseq]:"q  Equiv p q" by(rule sizeF_diseq, auto simp add: Equiv_def Or_def)
lemma [expr_diseq]:"p  Exists x p" by(induction p, auto)
lemma [expr_diseq]:"p  Diamond a p" by(induction p, auto)
lemma [expr_diseq]:"p  InContext C p" by(induction p, auto)

― ‹A predicational is like a context with no argument, i.e. a variable standing for a›
― ‹state-dependent formula, given meaning by the interpretation. This differs from a predicate›
― ‹because predicates depend only on their arguments (which might then indirectly depend on the state).›
― ‹We encode a predicational as a context applied to a formula whose truth value is constant with›
― ‹respect to the state (specifically, always true)›
fun Predicational :: "'b  ('a, 'b, 'c) formula" ("Pc")
where "Predicational P = InContext P (Geq (Const 0) (Const 0))"

― ‹Abbreviations for common syntactic constructs in order to make axiom definitions, etc. more›
― ‹readable.›
context ids begin
― ‹"Empty" function argument tuple, encoded as tuple where all arguments assume a constant value.›
definition empty::" 'b  ('a, 'b) trm"
where "empty  λi.(Const 0)"

― ‹Function argument tuple with (effectively) one argument, where all others have a constant value.›
fun singleton :: "('a, 'sz) trm  ('sz  ('a, 'sz) trm)"
where "singleton t i = (if i = vid1 then t else (Const 0))"

lemma expand_singleton:"singleton t = (λi. (if i = vid1 then t else (Const 0)))"
  by auto

― ‹Function applied to one argument›
definition f1::"'sf  'sz  ('sf,'sz) trm"
where "f1 f x = Function f (singleton (Var x))"

― ‹Function applied to zero arguments (simulates a constant symbol given meaning by the interpretation)›
definition f0::"'sf  ('sf,'sz) trm"
where "f0 f = Function f empty"

― ‹Predicate applied to one argument›
definition p1::"'sz  'sz  ('sf, 'sc, 'sz) formula"
where "p1 p x = Prop p (singleton (Var x))"

― ‹Predicational›
definition P::"'sc  ('sf, 'sc, 'sz) formula"
where "P p = Predicational p"
end

subsection ‹Well-Formedness predicates›
inductive dfree :: "('a, 'c) trm  bool"
where
  dfree_Var: "dfree (Var i)"
| dfree_Const: "dfree (Const r)"
| dfree_Fun: "(i. dfree (args i))  dfree (Function i args)"
| dfree_Plus: "dfree θ1  dfree θ2  dfree (Plus θ1 θ2)"
| dfree_Times: "dfree θ1  dfree θ2  dfree (Times θ1 θ2)"
  
inductive dsafe :: "('a, 'c) trm  bool"
where
  dsafe_Var: "dsafe (Var i)"
| dsafe_Const: "dsafe (Const r)"
| dsafe_Fun: "(i. dsafe (args i))  dsafe (Function i args)"
| dsafe_Plus: "dsafe θ1  dsafe θ2  dsafe (Plus θ1 θ2)"
| dsafe_Times: "dsafe θ1  dsafe θ2  dsafe (Times θ1 θ2)"
| dsafe_Diff: "dfree θ  dsafe (Differential θ)"
| dsafe_DiffVar: "dsafe ($' i)"

― ‹Explictly-written variables that are bound by the ODE. Needed to compute whether›
― ‹ODE's are valid (e.g. whether they bind the same variable twice)›
fun ODE_dom::"('a, 'c) ODE  'c set"
where 
  "ODE_dom (OVar c) =  {}"
| "ODE_dom (OSing x θ) = {x}"
| "ODE_dom (OProd ODE1 ODE2) = ODE_dom ODE1  ODE_dom ODE2"

inductive osafe:: "('a, 'c) ODE  bool"
where
  osafe_Var:"osafe (OVar c)"
| osafe_Sing:"dfree θ  osafe (OSing x θ)"
| osafe_Prod:"osafe ODE1  osafe ODE2  ODE_dom ODE1  ODE_dom ODE2 = {}  osafe (OProd ODE1 ODE2)"

― ‹Programs/formulas without any differential terms. This definition not currently used but may›
― ‹be useful in the future.›
inductive hpfree:: "('a, 'b, 'c) hp  bool"
  and     ffree::  "('a, 'b, 'c) formula  bool"
where
  "hpfree (Pvar x)"
| "dfree e  hpfree (Assign x e)"
― ‹Differential programs allowed but not differential terms›
| "dfree e  hpfree (DiffAssign x e)"
| "ffree P  hpfree (Test P)" 
― ‹Differential programs allowed but not differential terms›
| "osafe ODE  ffree P  hpfree (EvolveODE ODE P)"
| "hpfree a  hpfree b  hpfree (Choice a b )"
| "hpfree a  hpfree b  hpfree (Sequence a b)"
| "hpfree a  hpfree (Loop a)"
| "ffree f  ffree (InContext C f)"
| "(arg. arg  range args  dfree arg)  ffree (Prop p args)"
| "ffree p  ffree (Not p)"
| "ffree p  ffree q  ffree (And p q)"
| "ffree p  ffree (Exists x p)"
| "hpfree a  ffree p  ffree (Diamond a p)"
| "ffree (Predicational P)"
| "dfree t1  dfree t2  ffree (Geq t1 t2)"

inductive hpsafe:: "('a, 'b, 'c) hp  bool"
  and     fsafe::  "('a, 'b, 'c) formula  bool"
where
   hpsafe_Pvar:"hpsafe (Pvar x)"
 | hpsafe_Assign:"dsafe e  hpsafe (Assign x e)"
 | hpsafe_DiffAssign:"dsafe e  hpsafe (DiffAssign x e)"
 | hpsafe_Test:"fsafe P  hpsafe (Test P)" 
 | hpsafe_Evolve:"osafe ODE  fsafe P  hpsafe (EvolveODE ODE P)"
 | hpsafe_Choice:"hpsafe a  hpsafe b  hpsafe (Choice a b )"
 | hpsafe_Sequence:"hpsafe a  hpsafe b  hpsafe (Sequence a b)"
 | hpsafe_Loop:"hpsafe a  hpsafe (Loop a)"

 | fsafe_Geq:"dsafe t1  dsafe t2  fsafe (Geq t1 t2)"
 | fsafe_Prop:"(i. dsafe (args i))  fsafe (Prop p args)"
 | fsafe_Not:"fsafe p  fsafe (Not p)"
 | fsafe_And:"fsafe p  fsafe q  fsafe (And p q)"
 | fsafe_Exists:"fsafe p  fsafe (Exists x p)"
 | fsafe_Diamond:"hpsafe a  fsafe p  fsafe (Diamond a p)"
 | fsafe_InContext:"fsafe f  fsafe (InContext C f)"

― ‹Auto-generated simplifier rules for safety predicates›
inductive_simps
      dfree_Plus_simps[simp]: "dfree (Plus a b)"
  and dfree_Times_simps[simp]: "dfree (Times a b)"
  and dfree_Var_simps[simp]: "dfree (Var x)"
  and dfree_DiffVar_simps[simp]: "dfree (DiffVar x)"
  and dfree_Differential_simps[simp]: "dfree (Differential x)"
  and dfree_Fun_simps[simp]: "dfree (Function i args)"
  and dfree_Const_simps[simp]: "dfree (Const r)"

inductive_simps
      dsafe_Plus_simps[simp]: "dsafe (Plus a b)"
  and dsafe_Times_simps[simp]: "dsafe (Times a b)"
  and dsafe_Var_simps[simp]: "dsafe (Var x)"
  and dsafe_DiffVar_simps[simp]: "dsafe (DiffVar x)"
  and dsafe_Fun_simps[simp]: "dsafe (Function i args)"
  and dsafe_Diff_simps[simp]: "dsafe (Differential a)"
  and dsafe_Const_simps[simp]: "dsafe (Const r)"

inductive_simps
      osafe_OVar_simps[simp]:"osafe (OVar c)"
  and osafe_OSing_simps[simp]:"osafe (OSing x θ)"
  and osafe_OProd_simps[simp]:"osafe (OProd ODE1 ODE2)"

inductive_simps
      hpsafe_Pvar_simps[simp]: "hpsafe (Pvar a)"
  and hpsafe_Sequence_simps[simp]: "hpsafe (a ;; b)"
  and hpsafe_Loop_simps[simp]: "hpsafe (a**)"
  and hpsafe_ODE_simps[simp]: "hpsafe (EvolveODE ODE p)"
  and hpsafe_Choice_simps[simp]: "hpsafe (a ∪∪ b)"
  and hpsafe_Assign_simps[simp]: "hpsafe (Assign x e)"
  and hpsafe_DiffAssign_simps[simp]: "hpsafe (DiffAssign x e)"
  and hpsafe_Test_simps[simp]: "hpsafe (? p)"
  
  and fsafe_Geq_simps[simp]: "fsafe (Geq t1 t2)"
  and fsafe_Prop_simps[simp]: "fsafe (Prop p args)"
  and fsafe_Not_simps[simp]: "fsafe (Not p)"
  and fsafe_And_simps[simp]: "fsafe (And p q)"
  and fsafe_Exists_simps[simp]: "fsafe (Exists x p)"
  and fsafe_Diamond_simps[simp]: "fsafe (Diamond a p)"
  and fsafe_Context_simps[simp]: "fsafe (InContext C p)"

definition Ssafe::"('sf,'sc,'sz) sequent  bool"
where "Ssafe S ((i. i  0  i < length (fst S)  fsafe (nth (fst S) i))
                 (i. i  0  i < length (snd S)  fsafe (nth (snd S) i)))"

definition Rsafe::"('sf,'sc,'sz) rule  bool"
where "Rsafe R  ((i. i  0  i < length (fst R)  Ssafe (nth (fst R) i)) 
                     Ssafe (snd R))"
  
― ‹Basic reasoning principles about syntactic constructs, including inductive principles›
lemma dfree_is_dsafe: "dfree θ  dsafe θ"
  by (induction rule: dfree.induct) (auto intro: dsafe.intros)
  
lemma hp_induct [case_names Var Assign DiffAssign Test Evolve Choice Compose Star]:
   "(x. P ( x)) 
    (x1 x2. P (x1 := x2)) 
    (x1 x2. P (DiffAssign x1 x2)) 
    (x. P (? x)) 
    (x1 x2. P (EvolveODE x1 x2)) 
    (x1 x2. P x1  P x2  P (x1 ∪∪ x2)) 
    (x1 x2. P x1  P x2  P (x1 ;; x2)) 
    (x. P x  P x**) 
     P hp"
  by(induction rule: hp.induct) (auto)

lemma fml_induct:
  "(t1 t2. P (Geq t1 t2))
   (p args. P (Prop p args))
   (p. P p  P (Not p))
   (p q. P p  P q  P (And p q))
   (x p. P p  P (Exists x p))
   (a p. P p  P (Diamond a p))
   (C p. P p  P (InContext C p))
   P φ"
  by (induction rule: formula.induct) (auto)

context ids begin
lemma proj_sing1:"(singleton θ vid1) = θ"
  by (auto)

lemma proj_sing2:"vid1  y   (singleton θ y) = (Const 0)"
  by (auto)
end

end