### isabelle

#### How to prove that addition of a new variable to the expression doesn't change its semantics?

Here is very simple language: type_synonym vname = "string" type_synonym bool3 = "bool option" type_synonym env = "vname ⇒ bool3" datatype exp = Let vname bool exp | Var vname | And exp exp primrec val :: "exp ⇒ env ⇒ bool3" where "val (Let var init body) e = val body (e(var ↦ init))" | "val (Var var) e = e var" | "val (And a b) e = (case (val a e, val b e) of (Some x, Some y) ⇒ Some (x ∧ y) | _ ⇒ None)" I'm trying to prove that if an expression doesn't have any free variables, then I can declare any new variable at the begining of the expression. I've tried 3 approaches to prove it. 1) defined function checks whether the expression's value is well defined (= all used variables are declared): primrec defined :: "exp ⇒ env ⇒ bool" where "defined (Let var init body) e = defined body (e(var ↦ init))" | "defined (Var var) e = (var : dom e)" | "defined (And a b) e = (defined a e ∧ defined b e)" lemma var_intro: "defined exp env ⟹ defined exp (env(x ↦ init))" apply (induct exp) apply (simp_all split: if_splits) 2) The alternative approach is to collect all free variables from the expression. And if the expression doesn't contain any then we can add a new variable to the environment: primrec freeVars :: "exp ⇒ vname set ⇒ vname set" where "freeVars (Let var init body) e = freeVars body (insert var e)" | "freeVars (Var var) e = (if var ∈ e then {} else {var})" | "freeVars (And a b) e = freeVars a e ∪ freeVars b e" lemma var_intro2: "freeVars exp {} = {} ⟹ freeVars exp {x} = {}" apply (induct exp) apply (simp_all split: if_splits) 3) And the last approach is to eliminate all bounded variables from the environment: primrec isFree :: "vname ⇒ exp ⇒ bool" where "isFree x (Let var init body) = (if var = x then False else isFree x body)" | "isFree x (Var var) = (var = x)" | "isFree x (And a b) = (isFree x a ∨ isFree x b)" lemma var_elim: "¬ isFree x exp ⟹ val exp (env(x ↦ init)) = val exp (env)" apply (induct exp) apply (simp_all split: if_splits) I can't prove any of the lemmas. Could you suggest a solution?

Your proofs will probably require you to set env to arbitrary in the induction or the proofs will not work. With that, you will probably be able to prove the properties you stated, but I think it'll be a bit ugly because both your definitions and your lemma statements are unnecessarily specific, which can make proofs more painful. In particular, your notion of ‘free variable w.r.t. an environment’ seems a bit unnecessarily complicated to me. I think it's easier to use the following: primrec freeVars :: "exp ⇒ vname set" where "freeVars (Let var init body) = freeVars body - {var}" | "freeVars (Var var) = {var}" | "freeVars (And a b) = freeVars a ∪ freeVars b" The statement ‘expression exp is well-defined w.r.t. an environment env’ is then simply freeVars exp ⊆ dom env. Then it is obvious that any expression that is well-defined w.r.t. some environment is also well-defined with any bigger environment.

1) You have to lift the communicative property of element insertion on sets into that of state updates on maps, on which your lemma is based. lemma defined_dom: "defined exp env ⟹ dom env = dom env' ⟹ defined exp env'" by (induction exp arbitrary: env env'; auto) lemma defined_comm: "defined exp (env(x↦a, y↦b)) ⟹ defined exp (env(y↦b, x↦a))" by (auto elim!: defined_dom) lemma var_intro: "defined exp env ⟹ defined exp (env(x ↦ init))" by (induction exp arbitrary: env; simp add: defined_comm) 2) If your lemma is based on sets, you will also need the communicative lemma, which is already in the library: lemma var_intro2': "freeVars exp s = {} ⟹ freeVars exp (insert x s) = {}" by (induction exp arbitrary: s x; force simp: insert_commute) lemma var_intro2: "freeVars exp {} = {} ⟹ freeVars exp {x} = {}" using var_intro2' . 3) Similarly: lemma var_elim: "¬ isFree x exp ⟹ val exp (env(x ↦ init)) = val exp (env)" by (induction exp arbitrary: env; simp add: fun_upd_twist split: if_splits)

### Related Links

Defining functions between constants in Isabelle

Using the ordering locale with partial maps

Avoiding assumption with sledgehammer

Discriminant with Inequalities

Instances in locale declaration for Isabelle

How to interactively simplify a formula in a relational theory in Isabelle

Nonnegative Interval Integration

Widening the domain of a partial function

Automatically unfolding a record definition when accessor is used

Creating a datatype with inequalities in Isabelle

Isabelle Logic simple natural deduction test

Instantiating variables ending in a digit using where-attribute (Isabelle)

Using an existing definition in Isabelle/ Hol

Pending sort hypotheses

How can I use proved goals of locale interpretation to prove the remaining ones

Isabelle class obligation prove blue