How do I add the additional type variables in my specification of an inductive type in Isabelle? - isabelle

I defined an inductive type like this:
inductive I :: "tau ⇒ bool" where
rule0: "I C0" |
rule1: "I x" |
rule2: "Q x ⟹ I x" |
rule3: "Q x ⟹ I x'" |
rule4: "Q x ⟹ I (C1 x)" |
rule5: "Q (C1 x) ⟹ I x" |
rule6: "Q (C1 x) ⟹ I x'" |
rule7: "Q x ⟹ I (C2 x' x'')"
which I thought would be enough but Isabelle complains/warns me with:
Additional type variable(s) in specification of "I": 'a, 'b
I don't understand what this means. I know that it's saying that I should put somewhere that inductive predicate accepts any two type (as shown by the type variables 'a and 'b). But that isn't what I wanted to do. I just want the input to always be of type tau which is:
datatype tau =
C0 |
C1 tau |
C2 tau tau
obviously these definitions are made up, not really meant to prove anything. I'm just curious to inspect the theorems (in particular induction) that it generates with these defintions.
1) How do I have it stop complaining about my variables being arbitrary types and have them always be type tau?
As an addition, I became really curious what the complaint means and how to fix it with the 'a and 'b syntax it is suggestion. Although that was not what I initially intended, I am curious to see a more general definition of my made up inductive predicate and see what iduct theorems it will generate.
2) how do I define my inductive predicate with the arbitrary types Isabelle wants? where do I put 'a and 'b in the definition? If I don't what happens?

To restrict the type in my rules I can decorate the types in the inductive definition of I:
inductive I :: "tau ⇒ bool" where
rule0: "I C0" |
rule1: "I x" |
rule2: "Q x ⟹ I x" |
rule3: "Q (x::tau) ⟹ I x'" |
rule4: "Q x ⟹ I (C1 x)" |
rule5: "Q (C1 x) ⟹ I x" |
rule6: "Q (C1 x) ⟹ I x'" |
rule7: "Q (x::tau) ⟹ I (C2 x' x'')"
now the theorems like this:
thm I.induct
⟦I ?x; ?P C0; ⋀x. ?P x; ⋀Q x. Q x ⟹ ?P x; ⋀Q x x'. Q x ⟹ ?P x'; ⋀Q x. Q x ⟹ ?P (C1 x); ⋀Q x. Q (C1 x) ⟹ ?P x; ⋀Q x x'. Q (C1 x) ⟹ ?P x'; ⋀Q x x' x''. Q x ⟹ ?P (C2 x' x'')⟧ ⟹ ?P ?x
Thanks Manuel Eberl!

Related

Topological filters in Isabelle

I'm studying topological filters in Filter.thy
theory Filter
imports Set_Interval Lifting_Set
begin
subsection ‹Filters›
text ‹
This definition also allows non-proper filters.
›
locale is_filter =
fixes F :: "('a ⇒ bool) ⇒ bool"
assumes True: "F (λx. True)"
assumes conj: "F (λx. P x) ⟹ F (λx. Q x) ⟹ F (λx. P x ∧ Q x)"
assumes mono: "∀x. P x ⟶ Q x ⟹ F (λx. P x) ⟹ F (λx. Q x)"
typedef 'a filter = "{F :: ('a ⇒ bool) ⇒ bool. is_filter F}"
proof
show "(λx. True) ∈ ?filter" by (auto intro: is_filter.intro)
qed
I don't get this definition. It's quite convoluted so I'll simplify it first
The expression
F (λx. P x) could be simplified to F P (using eta reduction of lambda calculus). The predicate 'a ⇒ bool is really just a set 'a set. Similarly ('a ⇒ bool) ⇒ bool should be 'a set set. Then we could rewrite the axioms as
assumes conj: "P ∈ F ∧ Q ∈ F ⟹ Q ∩ P ∈ F"
assumes mono: "P ⊆ Q ∧ P ∈ F ⟹ Q ∈ F"
Now my question is about the True axiom. It is equivalent to
assumes True: "UNIV ∈ F"
This does not match with the definitions of filters that I ever saw.
The axiom should be instead
assumes True: "{} ∉ F" (* the name True is not very fitting anymore *)
The statement UNIV ∈ F is unnecessary because it follows from axiom mono.
So what's up with this definition that Isabelle provides?
The link provided by Javier Diaz has lots of explanations.
Turns out this is a definition of improper filter. The axiom True is necessary and does not follow from mono. If this axiom was missing then F could be defined as
F P = False
or in set-theory notation, F could be an empty set and mono and conj would then be satisfied vacuously.

How to lift lemmas

Here is a sample datatype with a deterministic relation.
datatype ty1 = A | B | C ty1 | D ty1
inductive rel1 where
"rel1 A (C B)"
| "rel1 (C B) (D A)"
lemma rel1_det:
"rel1 x y ⟹ rel1 x z ⟹ y = z"
by (elim rel1.cases; auto)
I'm trying to lift the lemma for the following type:
datatype 'a ty2 = E 'a | F 'a
abbreviation "rel2 ≡ rel_ty2 rel1"
lemma rel2_det:
"rel2 x y ⟹ rel2 x z ⟹ y = z"
apply (cases x; cases y; auto)
apply (metis rel1_det right_uniqueD right_uniqueI ty2.rel_intros(1) ty2.right_unique_rel)
by (metis rel1_det right_uniqueD right_uniqueI ty2.rel_intros(2) ty2.right_unique_rel)
But the proof is very ugly. I guess it could be simplified using a transfer method, a lifting package or something else. Could you suggest how to use it?
I don't know about using the transfer package to prove this; however, it is easy to prove if you use the predicate right_unique from the library and the rules for it that the datatype package gives you for free:
lemma right_unique_rel1: "right_unique rel1"
by (auto simp: right_unique_def elim: rel1.cases)
lemma right_unique_rel2: "right_unique rel2"
by (intro ty2.right_unique_rel right_unique_rel1)

How to replace existentially quantified variable?

Here is a simple type system:
datatype type =
VoidType
| IntegerType
| RealType
| StringType
datatype val =
VoidVal
| IntegerVal int
| RealVal real
| StringVal string
fun type_of :: "val ⇒ type" where
"type_of (VoidVal) = VoidType"
| "type_of (IntegerVal _) = IntegerType"
| "type_of (RealVal _) = RealType"
| "type_of (StringVal _) = StringType"
with type conformance relation:
inductive less_type :: "type ⇒ type ⇒ bool" (infix "<" 65) where
"IntegerType < RealType"
Integer values can be casted to corresponding real values:
inductive cast :: "val ⇒ val ⇒ bool" where
"cast (IntegerVal x) (RealVal x)"
I'm trying to prove the following lemma. If type of a variable x conforms to RealType, then there exists a value y with type RealType and x can be casted to y.
lemma is_castable_to_real:
"type_of x < RealType ⟹ ∃y. type_of y = RealType ∧ cast x y"
apply (rule exI[of _ "RealVal v"])
I can prove the generic lemma using cases tactics:
lemma is_castable:
"type_of x < τ ⟹ ∃y. type_of y = τ ∧ cast x y"
by (cases x; cases τ; auto simp add: less_type.simps cast.simps)
But I'm trying to understand how to treat existential quantifiers in lemmas. So I'm trying to provide a concrete example RealVal v for y:
type_of x < RealType ⟹ ∃v. type_of (RealVal v) = RealType ∧ cast x (RealVal v)
The problem is that I get the following proposition instead:
type_of x < RealType ⟹ type_of (RealVal v) = RealType ∧ cast x (RealVal v)
What is the kind of variable v? Is it universally quantified variable? How to make it existentially quantified one?
To prove an existential, you can give a concrete example.
In your case, this example can be derived from the assumption of the lemma.
lemma is_castable_to_real:
assumes subtype_of_real: "type_of x < RealType"
shows "∃y. type_of y = RealType ∧ cast x y"
proof -
have "type_of x = IntegerType"
using subtype_of_real less_type.cases by blast
from this obtain i where x_def: "x = IntegerVal i"
by (cases x, auto)
(* prove it for concrete example (RealVal i) *)
have "type_of (RealVal i) = RealType ∧ cast x (RealVal i)"
by (auto simp add: x_def cast.intros)
(* From the concrete example, the existential statement follows: *)
thus "∃y. type_of y = RealType ∧ cast x y" ..
qed
If you just use v before obtaining or defining it somehow, the value will be similar to undefined. It has the correct type, but you do not know anything about it.
If you start the proof without the dash (-) Isabelle will use the default tactic and you would get the subgoal type_of ?y = RealType ∧ cast x ?y. Here ?y is a schematic variable and you can later provide any value that was already available before starting the proof. Maybe this is the kind of variable you get for v, but it is still not clear how you got to the last line in your question.

How to define a linear ordering on a type?

I'm trying to define a conjunction function for 4-valued logic (false, true, null, and error). In my case the conjunction is equivavlent to min function on linear order false < error < null < true.
datatype bool4 = JF | JT | BN | BE
instantiation bool4 :: linear_order
begin
fun leq_bool4 :: "bool4 ⇒ bool4 ⇒ bool" where
"leq_bool4 JF b = True"
| "leq_bool4 BE b = (b = BE ∨ b = BN ∨ b = JT)"
| "leq_bool4 BN b = (b = BN ∨ b = JT)"
| "leq_bool4 JT b = (b = JT)"
instance proof
fix x y z :: bool4
show "x ⊑ x"
by (induct x) simp_all
show "x ⊑ y ⟹ y ⊑ z ⟹ x ⊑ z"
by (induct x; induct y) simp_all
show "x ⊑ y ⟹ y ⊑ x ⟹ x = y"
by (induct x; induct y) simp_all
show "x ⊑ y ∨ y ⊑ x"
by (induct x; induct y) simp_all
qed
end
definition and4 :: "bool4 ⇒ bool4 ⇒ bool4" where
"and4 a b ≡ minimum a b"
I guess there must be an easier way to define a linear order in Isabelle HOL. Could you suggest a simplification of the theory?
You can use the "Datatype_Order_Generator" AFP entry.
Then it's as simple as importing "$AFP/Datatype_Order_Generator/Order_Generator" and declaring derive linorder "bool4". Note that the constructors must be declared in the order you want them when defining your datatype.
Details on how to download and use the AFP locally can be found here.

Proving a theorem about parser combinators

I've written some simple parser combinators (without backtracking etc.). Here are the important definitions for my problem.
type_synonym ('a, 's) parser = "'s list ⇒ ('a * 's list) option"
definition sequenceP :: "('a, 's) parser
⇒ ('b, 's) parser
⇒ ('b, 's) parser" (infixl ">>P" 60) where
"sequenceP p q ≡ λ i .
(case p i of
None ⇒ None
| Some v ⇒ q (snd v))"
definition consumerP :: "('a, 's) parser ⇒ bool" where
"consumerP p ≡ (∀ i . (case p i of
None ⇒ True |
Some v ⇒ length (snd v) ≤ length i))"
I do want to proof the following lemma.
lemma consumerPI: "consumerP p ⟹ consumerP q ⟹ consumerP (p >>P q)"
apply (unfold sequenceP_def)
apply (simp (no_asm) add:consumerP_def)
apply clarsimp
apply (case_tac "case p i of None ⇒ None | Some v ⇒ q (snd v)")
apply simp
apply clarsimp
apply (case_tac "p i")
apply simp
apply clarsimp
apply (unfold consumerP_def)
I arrive at this proof state, at which I fail to continue.
goal (1 subgoal):
1. ⋀i a b aa ba.
⟦∀i. case p i of None ⇒ True | Some v ⇒ length (snd v) ≤ length i;
∀i. case q i of None ⇒ True | Some v ⇒ length (snd v) ≤ length i; q ba = Some (a, b); p i = Some (aa, ba)⟧
⟹ length b ≤ length i
Can anybody give me a tip how to solve this goal?
Thanks in advance!
It turns out that if you just want to prove the lemma, without further insight, then
lemma consumerPI: "consumerP p ⟹ consumerP q ⟹ consumerP (p >>P q)"
by (smt consumerP_def le_trans option.case_eq_if sequenceP_def)
does the job.
If you want to have insight, you want to go for a structured proof. First identify some useful lemmas about consumerP, and then write a Isar proof that details the necessary steps.
lemma consumerPI[intro!]:
assumes "⋀ i x r . p i = Some (x,r) ⟹ length r ≤ length i"
shows "consumerP p"
unfolding consumerP_def by (auto split: option.split elim: assms)
lemma consumerPE[elim, consumes 1]:
assumes "consumerP p"
assumes "p i = Some (x,r)"
shows "length r ≤ length i"
using assms by (auto simp add: consumerP_def split: option.split_asm)
lemma consumerP_sequencePI: "consumerP p ⟹ consumerP q ⟹ consumerP (p >>P q)"
proof-
assume "consumerP p"
assume "consumerP q"
show "consumerP (p >>P q)"
proof(rule consumerPI)
fix i x r
assume "(p >>P q) i = Some (x, r)"
then obtain x' r' where "p i = Some (x', r')" and "q r' = Some (x,r)"
by (auto simp add: sequenceP_def split:option.split_asm)
from `consumerP q` and `q r' = Some (x, r)`
have "length r ≤ length r'" by (rule consumerPE)
also
from `consumerP p` and `p i = Some (x', r')`
have "length r' ≤ length i" by (rule consumerPE)
finally
show "length r ≤ length i".
qed
qed
In fact, for this definition you can very nicely use the inductive command, and get intro and elim rules for free:
inductive consumerP where
consumerPI: "(⋀ i x r . p i = Some (x,r) ⟹ length r ≤ length i) ⟹ consumerP p"
In the above proof, you can replace by (rule consumerPE) by by cases and it works.

Resources