Isabelle: How can I use solver this error? - isabelle

**I'm using isabelle to proof security boot of device. lemma AF1_aux fail to pass the proof.
When I change if event_enabled s be to if false, it pass. I can't move forward.
Any guidance would be very helpful!
Here is the simple code**
section ‹boot security›
theory boot_sec
imports Main
begin
locale M_HLR =
(* declare the initial state *)
fixes Initial_State :: 's
(* next state function *)
fixes next_state :: "'s ⇒ 'be ⇒ 's"
(* Auxiliary function for present Stable State *)
fixes success :: "'s ⇒ bool"
(* Security Requirements *)
assumes AF1: "∃s. ∀b. next_state s b = s"
datatype Status = INIT | READ_ROM | END
record State =
status :: Status
datatype Behavior = Read_ROM |
Gen_SessionKey
definition read_rom :: "State ⇒ State" where
"read_rom s ≡ s ⦇status := READ_ROM ⦈"
definition gen_sessionkey :: "State ⇒ State" where
"gen_sessionkey s ≡ s ⦇status := END ⦈"
definition event_enabled :: "State ⇒ Behavior ⇒ bool" where
"event_enabled s be ≡ if status s = END then False else True"
definition exec_be :: "State ⇒ Behavior ⇒ State" where
"exec_be s be ≡
if event_enabled s be
then
( case be of
Read_ROM ⇒ read_rom s |
Gen_SessionKey ⇒ gen_sessionkey s )
else s"
lemma AF1_aux: "status s = END ⟹ ∀be. exec_be s be = s"
by(simp add: exec_be_def)
theorem AF1: "∃s. ∀be. exec_be s be = s"
by (meson AF1_aux State.select_convs(1))
end
The output is
theorem AF1_aux: status ?s = END ⟹ ∀be. exec_be ?s be = ?s
Failed to finish proof⌂:
goal (1 subgoal):
1. status s = END ⟹ ∀be. event_enabled s be ⟶ (case be of Read_ROM ⇒ read_rom s | Gen_SessionKey ⇒ gen_sessionkey s) = s

Related

Isabelle instantiation with type parameter

I'm trying to get this to work
no_notation Nil ("[]") and Cons (infixr "#" 65) and append (infixr "#" 65) and plus (infixl "+" 65)
class plus =
fixes plus :: "'a ⇒ 'a ⇒ 'a" (infixl "+" 65)
datatype 'a list =
Nil ("[]")
| Cons 'a "'a list" (infixr "#" 65)
instantiation "'a list" :: plus
begin
primrec plus_list :: "'a list ⇒ 'a list ⇒ 'a list" where
"plus_list [] ys = ys" |
"plus_list (x#xs) ys = x # (plus_list xs ys)"
instance ..
end
essentially lists are free monoids under concatenation. How do I express this fact using type-classes?
At the moment I get
Undefined type name: "'a list"⌂
in this line
instantiation "'a list" :: plus
^^^^^^^^^
If I get rid of 'a I get
Bad number of arguments for type constructor: "Test.list"
Even if I try to specialize to nat list I get
Undefined type name: "nat list"⌂
I can see here
https://isabelle.in.tum.de/doc/classes.pdf
that it is possible. However, the notation used in this pdf is strange. I can't reproduce any of the examples provided. For instance this
class eq where
eq :: α ⇒ α ⇒ bool
I suppose it's meant to be something like
class eq where
eq :: "'a ⇒ 'a ⇒ bool"
but when I paste it to jEdit I get syntax error. Other Isabelle tutorials use a different notation, like
class eq =
fixes eq :: "'a ⇒ 'a ⇒ bool"
This pdf also provides example
instance (α::eq, β::eq) pair :: eq where
eq (x1, y1) (x2, y2) = eq x1 x2 ∧ eq y1 y2
which looks like what I am looking for. An instance of a higher-order type.
no_notation Nil ("[]") and Cons (infixr "#" 65) and append (infixr "#" 65) and plus (infixl "+" 65)
class plus =
fixes plus :: "'a ⇒ 'a ⇒ 'a" (infixl "+" 65)
datatype 'a list =
Nil ("[]")
| Cons 'a "'a list" (infixr "#" 65)
instantiation list :: (type) plus
begin
primrec plus_list :: "'a list ⇒ 'a list ⇒ 'a list" where
"plus_list [] ys = ys" |
"plus_list (x#xs) ys = x # (plus_list xs ys)"
instance ..
end

How to include statement about type of the variable in the Isabelle/HOL term

I have following simple Isabelle/HOL theory:
theory Max_Of_Two_Integers_Real
imports Main
"HOL-Library.Multiset"
"HOL-Library.Code_Target_Numeral"
"HOL-Library.Code_Target_Nat"
"HOL-Library.Code_Abstract_Nat"
begin
definition two_integer_max_case_def :: "nat ⇒ nat ⇒ nat" where
"two_integer_max_case_def a b = (case a > b of True ⇒ a | False ⇒ b)"
lemma spec_final:
fixes a :: nat and b :: nat
assumes "a > b" (* and "b < a" *)
shows "two_integer_max_case_def a b = a"
using assms by (simp add: two_integer_max_case_def_def)
lemma spec_1:
fixes a :: nat and b :: nat
shows "a > b ⟹ two_integer_max_case_def a b = a"
by (simp add: two_integer_max_case_def_def)
lemma spec_2:
shows " (a ∈ nat set) ∧ (b ∈ nat set) ∧ (a > b) ⟹ two_integer_max_case_def a b = a"
by (simp add: two_integer_max_case_def_def)
end
Three lemmas try to express and prove that same statement, but progressively I am trying to move information from assumes and fixes towards the term. First 2 lemmas are correct, but the third (last) lemma is failing syntactically with the error message:
Type unification failed: Clash of types "_ ⇒ _" and "int"
Type error in application: incompatible operand type
Operator: nat :: int ⇒ nat
Operand: set :: ??'a list ⇒ ??'a set
My aim in this lemma is to move type information from the fixes towards the term/statement? How I make statements about the type of variable in the term (of inner syntax)?
Maybe I should use, if I am trying to avoid fixes clause (in which the variables may be declared), the full ForAll expression like:
lemma spec_final_3:
shows "∀ a :: nat . ∀ b :: nat . ( (a > b) ⟹ two_integer_max_case_def a b = a)"
by (simp add: two_integer_max_case_def_def)
But it is failing syntactically as well with the error message:
Inner syntax error: unexpected end of input⌂
Failed to parse prop
So - is it possible to include type statements in the term directly (without fixes clause) and is there any difference between fixes clause and type statement in the term? Maybe such differences start to appear during (semi)automatic proofs, e.g., when simplification tactics are applied or some other tactics?
nat set is interpreted as a function (that does not type correctly). The set of natural numbers can be expressed as UNIV :: nat set. Then, spec_2 reads
lemma spec_2:
shows "a ∈ (UNIV :: nat set) ∧ b ∈ (UNIV :: nat set) ∧ a > b ⟹
two_integer_max_case_def a b = a"
by (simp add: two_integer_max_case_def_def)
However, more natural way would be to include the type information in spec_1 without fixes clause:
lemma spec_1':
shows "(a :: nat) > (b :: nat) ⟹ two_integer_max_case_def a b = a"
by (simp add: two_integer_max_case_def_def)
∀ belongs to HOL, so the HOL implication should be used in spec_final_3:
lemma spec_final_3:
shows "∀ a :: nat. ∀ b :: nat. a > b ⟶ two_integer_max_case_def a b = a"
by (simp add: two_integer_max_case_def_def)
spec_1 can also be rewritten using an explicit meta-logic qualification (and implication) to look similar to spec_final_3:
lemma spec_1'':
shows "⋀ a :: nat. ⋀ b :: nat. a > b ⟹ two_integer_max_case_def a b = a"
by (simp add: two_integer_max_case_def_def)

Inductive predicates, transitive closure, and code generation

I am defining subclass and subtype relations as inductive predicates for a Java-like language and would like to generate code for these relations. Defining and generating code for the subtype relation was no problem:
type_synonym class_name = string
record class_def =
cname :: class_name
super :: "class_name option"
interfaces :: "class_name list"
type_synonym program = "class_def list"
(* Look up a class by its name *)
definition lookup_class :: "program ⇒ class_name ⇒ class_def option" where
"lookup_class P C ≡ find (λcl. (class_def.cname cl) = C) P"
(* Direct subclass relation *)
inductive is_subclass1 :: "program ⇒ class_name ⇒ class_name ⇒ bool" where
"⟦
Some cl = lookup_class P C;
(class_def.super cl) = Some C'
⟧ ⟹ is_subclass1 P C C'"
(* Reflexive transitive closure of `is_subclass1` *)
definition is_subclass :: "program ⇒ class_name ⇒ class_name ⇒ bool" where
"is_subclass P C C' ≡ (is_subclass1 P)⇧*⇧* C C'"
code_pred(modes: i ⇒ i ⇒ i ⇒ bool, i ⇒ i ⇒ o ⇒ bool) is_subclass1 .
code_pred
(modes: i ⇒ i ⇒ i ⇒ bool, i ⇒ i ⇒ o ⇒ bool)
[inductify]
is_subclass .
Here, is_subclass1 P C C' is true if C' is the name of the direct superclass of C. Then is_subclass is defined to be the transitive closure of is_subclass1.
For code generation to work, it is crucial that is_subclass1 has the mode i ⇒ i ⇒ o ⇒ bool, because otherwise the transitive closure cannot be computed. In the case of is_subclass1 this is easy, as a class has at most a single direct superclass, and the name of the superclass can thus be uniquely determined from the inputs.
However, for the subtype relation I also need to consider the interfaces that a class might implement:
inductive is_subtype1 :: "program ⇒ class_name ⇒ class_name ⇒ bool" for P :: program where
― ‹Same as subclass relation, no problem›
"⟦
Ok cl = lookup_class P C;
Some C' = (class_def.super cl)
⟧ ⟹ is_subtype1 P C C'" |
"⟦
Ok cl = lookup_class P C;
― ‹HERE IS THE PROBLEM: C' cannot be uniquely derived from the inputs and can thus not be marked as an output›
C' ∈ set (class_def.interfaces cl)
⟧ ⟹ is_subtype1 P C C'"
The problem is that there are multiple possible values for C' and that it cannot be marked as an output.
Intuitively, I think this should not be a problem for the code generator, as the generated code could just iterate over all the interfaces of a class. However, I don't know if this can be expressed in Isabelle/HOL.
Thus, the question is: Is there a way to generate code for is_subtype1 with mode i ⇒ i ⇒ o ⇒ bool?
You can solve your problem by importing HOL-Library.Predicate_Compile_Alternative_Defs and then using List.member _ _ instead of _ ∈ set _.

Can I construct a while structure algebraically using class and locale?

I am constructing program statements from algebraic structures, rather than using definitions or functions.That is to set their properties in Isabelle using locale or class commands.
Now I need to construct a while statement.
I know I can define it in command of functions, or I can define it using kleene algebra. But, as I said before, I just want to describe the nature of a class or locale.
So I wrote this code:
consts skip :: "'a" ("II")
type_synonym 'a proc = "'a "
class sequen =
fixes seq :: "'a proc ⇒'a proc ⇒'a proc " (infixl ";;" 60)
assumes seq_assoc : "(x ;; y) ;; z = x ;; (y ;; z)"
and seq_skip_left : "II ;; x = x"
and seq_skip_right : "x ;; II = x"
definition ifprog :: " 'a proc ⇒ bool ⇒ 'a proc ⇒ 'a proc " ("(_ ◃ _ ▹ _)" [52,0,53] 52)
where "x ◃ bexp ▹ y ≡ (THE z::'a proc . (bexp = True ⟶ z = x) ∧ (bexp = False ⟶ z = y))"
locale while_unfold =
sequen seq
for seq :: "'a proc ⇒'a proc ⇒'a proc " +
fixes while ::"bool ⇒ 'a proc ⇒ 'a proc" ("while _ do _ od")
assumes while_ltera : "while bexp do P od = (P ;; (while bexp do P od)) ◃ bexp ▹ II"
If that were possible, I wouldn't be asking questions here, I've got a problem :
Type unification failed: Variable 'a::type not of sort sequen
And then, these details are:
Type unification failed: Variable 'a::type not of sort sequen
Type error in application: incompatible operand type
Operator: (;;) :: ??'a ⇒ ??'a ⇒ ??'a
Operand: P :: 'a
How can I avoid this problem, or can this descriptive method be used to construct statements that have an iterative function, such as while.
I have not looked at the content of the class/locale, but the error message seems to be self-explanatory: type unification failed due to an incompatible sort constraint for the type variable 'a. Unless you rely on type inference, the sort constraint needs to be provided explicitly:
consts skip :: "'a" ("II")
type_synonym 'a proc = "'a "
class sequen =
fixes seq :: "'a proc ⇒'a proc ⇒'a proc " (infixl ";;" 60)
assumes seq_assoc : "(x ;; y) ;; z = x ;; (y ;; z)"
and seq_skip_left : "II ;; x = x"
and seq_skip_right : "x ;; II = x"
(*sequen_class.seq has the type
"'a::sequen ⇒ 'a::sequen ⇒ 'a::sequen",
which includes the sort constraint sequen for the type variable 'a:*)
declare [[show_sorts]]
term sequen_class.seq
definition ifprog :: " 'a proc ⇒ bool ⇒ 'a proc ⇒ 'a proc " ("(_ ◃ _ ▹ _)" [52,0,53] 52)
where "x ◃ bexp ▹ y ≡ (THE z::'a proc . (bexp = True ⟶ z = x) ∧ (bexp = False ⟶ z = y))"
(*note the sort constraint*)
locale while_unfold =
sequen seq
for seq :: "'a::sequen proc ⇒'a proc ⇒'a proc " +
fixes while ::"bool ⇒ 'a proc ⇒ 'a proc" ("while _ do _ od")
assumes while_ltera : "while bexp do P od = (P ;; (while bexp do P od)) ◃ bexp ▹ II"
(*alternatively, consider using a class instead of a locale, although,
most certainly, the best choice depends on your application*)
class while_unfold' =
sequen +
fixes while ::"bool ⇒ 'a proc ⇒ 'a proc" ("while _ do _ od")
assumes while_ltera : "while bexp do P od = (P ;; (while bexp do P od)) ◃ bexp ▹ II"
For more information about classes and sort constraints see sections 3.3.6 and 5.8 in the Isabelle/Isar Reference Manual. You can also take a look at section 2 in the The Isabelle/Isar Implementation.
Isabelle version: Isabelle2020

How to define an abstract collection data type?

There are 4 kinds of collections in my theory. For each collection type I defined count and for_all operations:
theory MyCollections
imports Main
"~~/src/HOL/Library/Dlist"
"~~/src/HOL/Library/Multiset"
begin
typedef 'a mybag = "UNIV :: 'a multiset set" .. (* not unique, not ordered *)
typedef 'a myseq = "UNIV :: 'a list set" .. (* not unique, ordered *)
typedef 'a myset = "UNIV :: 'a set set" .. (* unique, not ordered *)
typedef 'a myord = "UNIV :: 'a dlist set" .. (* unique, ordered *)
setup_lifting type_definition_mybag
setup_lifting type_definition_myseq
setup_lifting type_definition_myset
setup_lifting type_definition_myord
lift_definition mybag_count :: "'a mybag ⇒ 'a ⇒ nat" is "Multiset.count" .
lift_definition myseq_count :: "'a myseq ⇒ 'a ⇒ nat" is "count_list" .
lift_definition myset_count :: "'a myset ⇒ 'a ⇒ nat" is "(λxs x. if x ∈ xs then 1 else 0)" .
lift_definition myord_count :: "'a myord ⇒ 'a ⇒ nat" is "(λxs x. if Dlist.member xs x then 1 else 0)" .
lift_definition mybag_for_all :: "'a mybag ⇒ ('a ⇒ bool) ⇒ bool" is "Multiset.Ball" .
lift_definition myseq_for_all :: "'a myseq ⇒ ('a ⇒ bool) ⇒ bool" is "(λxs f. list_all f xs)" .
lift_definition myset_for_all :: "'a myset ⇒ ('a ⇒ bool) ⇒ bool" is "Ball" .
lift_definition myord_for_all :: "'a myord ⇒ ('a ⇒ bool) ⇒ bool" is "(λxs f. list_all f (list_of_dlist xs))" .
I need to define polymorphic operations (includes and includes_all) for these collection types:
lift_definition mybag_includes :: "'a mybag ⇒ 'a ⇒ bool" is
"(λxs x. mybag_count xs x > 0)" .
lift_definition myseq_includes :: "'a myseq ⇒ 'a ⇒ bool" is
"(λxs x. myseq_count xs x > 0)" .
lift_definition myset_includes :: "'a myset ⇒ 'a ⇒ bool" is
"(λxs x. myset_count xs x > 0)" .
lift_definition myord_includes :: "'a myord ⇒ 'a ⇒ bool" is
"(λxs x. myord_count xs x > 0)" .
lift_definition mybag_mybag_includes_all :: "'a mybag ⇒ 'a mybag ⇒ bool" is
"(λxs ys. mybag_for_all ys (mybag_includes xs))" .
lift_definition mybag_myseq_includes_all :: "'a mybag ⇒ 'a myseq ⇒ bool" is
"(λxs ys. myseq_for_all ys (mybag_includes xs))" .
(* ... and 14 more similar operations for other type combinations *)
Some test cases:
value "mybag_myseq_includes_all (Abs_mybag {#1::nat,2,4,5,3,4#}) (Abs_myseq [1::nat,2])"
value "mybag_myseq_includes_all (Abs_mybag {#1::nat,2,4,5,3,4#}) (Abs_myseq [1::nat,7])"
The problem is that these operations are structurally identical and I don't want to duplicate them. I try to define an abstract collection type:
typedecl 'a mycol
consts
mycol_count :: "'a mycol ⇒ 'a ⇒ nat"
mycol_for_all :: "'a mycol ⇒ ('a ⇒ bool) ⇒ bool"
definition mycol_includes :: "'a mycol ⇒ 'a ⇒ bool" where
"mycol_includes xs x ≡ mycol_count xs x > 0"
definition mycol_includes_all :: "'a mycol ⇒ 'a mycol ⇒ bool" where
"mycol_includes_all xs ys ≡ mycol_for_all xs (mycol_includes ys)"
But I have no idea how to derive concrete collection types from the abstract one:
typedef 'a mybag = "{xs :: 'a mycol. ???}" ..
typedef 'a myseq = "{xs :: 'a mycol. ???}" ..
typedef 'a myset = "{xs :: 'a mycol. ???}" ..
typedef 'a myord = "{xs :: 'a mycol. ???}" ..
Once you have axiomatized the abstract collections type, you cannot refine it inside the logic any more. So the proposed approach does not work. But if you leave the container type abstract (as a type variable), then this is possible. I recommend to do that using locales:
locale container =
fixes count :: "'container => 'a => nat"
and for_all :: "'container => ('a => bool) => bool"
begin
definition "includes" where "includes C x <--> count C x > 0"
definition includes_all where "includes_all C C' <--> for_all C (includes C')"
end
Then, you can define your different collection types as usual and obtain the common operations by locale interpretation. For example,
interpretation mybag: container mybag_count mybag_forall .
generates the abbreviations mybag.includes and mybag.includes_all. Additionally, all theorems that are proven in the locale container are also specialized to mybag and prefixed with mybag.

Resources