### 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

How to generate html version of Isabelle theory

Establishing that a record type belongs to a given class

Generating Isabelle HTML documentation *without proofs*

When would you use `presume` in an Isar proof?

how to create an object logic via thf

What Isabelle library to reuse for expressing that some function is a linear order (on some set)

Isabelle: how to print result of 1 + 2?

Inductive Set with Non-fixed Parameters

What Kind of Type Definitions are Legal in Local Contexts?

Isabelle: Sledgehammer finds a proof but it fails

How to hide defined constants

Inductive predicates for a fixed tuple parameter

proof (rule disjE) for nested disjunction

Canonical way to get a more specific lemma

Can I define multiple names for a theorem?

How do I remove duplicate subgoals in Isabelle?