How to prove code correctness lemmas with the "undefined" constant - code-generation

Given I have a very simple definition for code generation. It is only defined for certain cases and throws a runtime exception otherwise.
definition "blubb a = (if P a then True else undefined)"
Now I want to show blubb correct. The case in which the exception is thrown should be ignored (from my point of view, not the mathematical point of view). However, I end up with a subgoal that assumes that some arbitrary value X is undefined. The following lemma is more or less equivalent to the subgoal. I want to show False as I want to ignore the case in which the exception is thrown (i.e., undefined is returned).
lemma "X = undefined ⟹ False"
This is not provable.
try
Nitpick found a counterexample for card 'a = 1:
Free variable:
X = a1
What is the best way to show correctness of functions that might throw exceptions or deal with undefined?
This relates to this question.

undefined is a constant in Isabelle which you don't know anything about. In particular, you can not in general prove that X ≠ undefined.
If you want to write functions that are only valid for certain inputs, you might consider using the 'a option type, as follows:
definition "blubb a ≡ (if P a then Some True else None)"
and then in your proofs assume that blubb a is defined as follows:
lemma "∃x. blubb a = Some x ⟹ Q (blubb a)"
...
or simply:
lemma "a ∈ dom blubb ⟹ Q (blubb a)"
...
The value of blubb a can then be extracted using the (blubb a).

Related

Coq: Bypassing the uniform inheritance condition

I've trouble understanding the (point of the) gauntlet one has to pass to bypass the uniform inheritance condition (UIC). Per the instruction
Let /.../ f: forall (x₁:T₁)..(xₖ:Tₖ)(y:C u₁..uₙ), D v₁..vₘ be a
function which does not verify the uniform inheritance condition. To
declare f as coercion, one has first to declare a subclass C' of C
/.../
In the code below, f is such a function:
Parameter C: nat -> Type.
Parameter D: nat -> Prop.
Parameter f: forall {x y}(z:C x), D y.
Parameter f':> forall {x y}(z:C x), D y. (*violates uic*)
Print Coercions. (* #f' *)
Yet I do not have to do anything except putting :> to declare it as a coercion. Maybe the gauntlet will somehow help to avoid breaking UIC? Not so:
Definition C' := fun x => C x.
Fail Definition Id_C_f := fun x d (y: C' x) => (y: C d). (*attempt to define Id_C_f as in the manual*)
Identity Coercion Id_C_f: C' >-> C.
Fail Coercion f: C' >-> D. (*Cannot recognize C' as a source class of f*)
Coercion f'' {x y}(z:C' x): D y := f z. (*violates uic*)
Print Coercions. (* #f' #f'' Id_C_f *)
The question: What am I missing here?
I've trouble understanding the (point of the) gauntlet one has to pass to bypass the uniform inheritance condition (UIC).
Intuitively, the uniform inheritance condition says (roughly) "it's syntactically possible to determine every argument to the coercion function just from the type of the source argument".
The developer that added coercions found it easier (I presume) to write the code implementing coercions if the uniform inheritance condition is assumed. I'm sure that a pull request relaxing this constraint and correctly implementing more general coercions would be welcomed!
That said, note that there is a warning message (not an error message) when you declare a coercion that violates the UIC. It will still add it to the table of coercions. Depending on your version of Coq, the coercion might never trigger, or you might get an error message at type inference time when the code applying the coercion builds an ill-typed term because it tries to apply the coercion assuming the UIC holds when it actually doesn't, or (in older versions of Coq) you can get anomalies (see, e.g., bug reports #4114, #4507, #4635, #3373, and #2828).
That said, here is an example where Identity Coercions are useful:
Require Import Coq.PArith.PArith. (* positive *)
Require Import Coq.FSets.FMapPositive.
Definition lookup {A} (map : PositiveMap.t A) (idx : positive) : option A
:= PositiveMap.find idx map.
(* allows us to apply maps as if they were functions *)
Coercion lookup : PositiveMap.t >-> Funclass.
Definition nat_tree := PositiveMap.t nat.
Axiom mymap1 : PositiveMap.t nat.
Axiom mymap2 : nat_tree.
Local Open Scope positive_scope. (* let 1 mean 1:positive *)
Check mymap1 1. (* mymap1 1 : option nat *)
Fail Check mymap2 1.
(* The command has indeed failed with message:
Illegal application (Non-functional construction):
The expression "mymap2" of type "nat_tree"
cannot be applied to the term
"1" : "positive" *)
Identity Coercion Id_nat_tree : nat_tree >-> PositiveMap.t.
Check mymap2 1. (* mymap2 1 : option nat *)
Basically, in the extremely limited case where you have an identifier which would be recognized as the source of an existing coercion if you unfolded its type a bit, you can use Identity Coercion to do that. (You can also do it by defining a copy of your existing coercion with a different type signature, and declaring that a coercion too. But then if you have some lemmas that mention one coercion, and some lemmas that mention the other, rewrite will have issues.)
There is one other use case for Identity Coercions, which is that, when your source is not an inductive type, you can use them for folding and not just unfolding identifiers, by playing tricks with Modules and Module Types; see this comment on #3115 for an example.
In general, though, there isn't a way that I know of to bypass the uniform inheritance condition.

how to figure out what "=" means in different types in coq

Given a type (like List) in Coq, how do I figure out what the equality symbol "=" mean in that type? What commands should I type to figure out the definition?
The equality symbol is just special infix syntax for the eq predicate. Perhaps surprisingly, it is defined the same way for every type, and we can even ask Coq to print it for us:
Print eq.
(* Answer: *)
Inductive eq (A : Type) (x : A) : Prop :=
| eq_refl : eq x x.
This definition is so minimal that it might be hard to understand what is going on. Roughly speaking, it says that the most basic way to show that two expressions are equal is by reflexivity -- that is, when they are exactly the same. For instance, we can use eq_refl to prove that 5 = 5 or [4] = [4]:
Check eq_refl : 5 = 5.
Check eq_refl : [4] = [4].
There is more to this definition than meets the eye. First, Coq considers any two expressions that are equalivalent up to simplification to be equal. In these cases, we can use eq_refl to show that they are equal as well. For instance:
Check eq_refl : 2 + 2 = 4.
This works because Coq knows the definition of addition on the natural numbers and is able to mechanically simplify the expression 2 + 2 until it arrives at 4.
Furthermore, the above definition tells us how to use an equality to prove other facts. Because of the way inductive types work in Coq, we can show the following result:
eq_elim :
forall (A : Type) (x y : A),
x = y ->
forall (P : A -> Prop), P x -> P y
Paraphrasing, when two things are equal, any fact that holds of the first one also holds of the second one. This principle is roughly what Coq uses under the hood when you invoke the rewrite tactic.
Finally, equality interacts with other types in interesting ways. You asked what the definition of equality for list was. We can show that the following lemmas are valid:
forall A (x1 x2 : A) (l1 l2 : list A),
x1 :: l1 = x2 :: l2 -> x1 = x2 /\ l1 = l2
forall A (x : A) (l : list A),
x :: l <> nil.
In words:
if two nonempty lists are equal, then their heads and tails are equal;
a nonempty list is different from nil.
More generally, if T is an inductive type, we can show that:
if two expressions starting with the same constructor are equal, then their arguments are equal (that is, constructors are injective); and
two expressions starting with different constructors are always different (that is, different constructors are disjoint).
These facts are not, strictly speaking, part of the definition of equality, but rather consequences of the way inductive types work in Coq. Unfortunately, it doesn't work as well for other kinds of types in Coq; in particular, the notion of equality for functions in Coq is not very useful, unless you are willing to add extra axioms into the theory.

Equality in COQ for enumerated types

I have a finite enumerated type (say T) in COQ and want to check elements for equality. This means, I need a function
bool beq_T(x:T,y:T)
The only way I managed to define such a function, is with a case by case analysis. This results in lots of match statements and looks very cumbersome. Therefore, I wonder if there is not a simpler way to achieve this.
Even simpler: Scheme Equality for ... generates two functions returning respectively a boolean and a sumbool.
The bad news is that the program that implements beq_T must necessarily consist of a large match statement on both of its arguments. The good news is that you can automatically generate/synthesize this program using Coq's tactic language. For example, given the type:
Inductive T := t0 | t1 | t2 | t3.
You can define beq_T as follows. The first two destruct tactics synthesize the code necessary to match on both x and y. The match tactic inspects the branch of the match that it is in, and depending on whether x = y, the tactic either synthesises the program that returns true or false.
Definition beq_T (x y:T) : bool.
destruct x eqn:?;
destruct y eqn:?;
match goal with
| _:x = ?T, _:y = ?T |- _ => exact true
| _ => exact false
end.
Defined.
If you want to see the synthesized program, run:
Print beq_T.
Thankfully, Coq already comes with a tactic that does almost what you want. It is called decide equality. It automatically synthesizes a program that decides whether two elements of a type T are equal. But instead of just returning a boolean value, the synthesized program returns a proof of the (in)equality of the two elements.
Definition eqDec_T (x y:T) : {x = y} + {x <> y}.
decide equality.
Defined.
With that program synthesized, it is easy to implement beq_T.
Definition beq_T' {x y:T} : bool := if eqDec_T x y then true else false.

Declaring a well colored digraph in coq

I would like to declare a structure in coq which represents a digraph which is well colored. I declared a Register which is accepted by coq if I don't have a condition. However I tried many ways of writing the condition wellColored in coq without exit. Each time I get a new error message:
The condition wellColored is the following:
for every pair of vertices $v1$, $v2$ and every edge $e$, if the source of $e$ is $v1$,
the target of $e$ is $v2$ and the color of $v1$ is $a$ then there is a color $b$ such that $b$ is different from $a$ and the color of $v2$ is $b$.
My attempt is written below. What are the mistakes in the condition wellColored and what is the correct definition?
Record dirgraph:={
V:Set;
E:Set;
s:E->V; (* source function *)
t:E->V; (* target function *)
l:V->nat;
wellColored: forall (v1:V) (v2:V) (e:E) (a:nat),
In V v1 /\ In V v2 /\ In E e /\ s e v1 /\ t e v2 /\ l v1 a-> (exists b, b<>a /\ l v2 b)
}.
For the moment I'm not interested in using packages with formalization of graphs. My main interest is to understand how to define structures and prove things about them. So I would like to define the graph precisely as it is above except with the correct condition.
The problem with your definition is that some conditions that you impose on wellColored do not need to be expressed, or simply cannot be expressed, in Coq's formalism:
I assume that by In V v1 you mean that v1 should be a member of V. Coq (as well as most type theories) is very different from usual set theory in this respect, because it doesn't make sense to assert that an object has some type as a proposition -- types in Coq (including things of type Set, like V in your definition) are not like sets in set theory. Instead, each object in the theory has its own type once and for all, and that type cannot change. When you write forall (v1 : V), ..., it is already assumed that v1 is a member of V.
If you want to say that some object of type T has some special property that not all objects of that type have (e.g., some number n is prime), you would express that with a predicate on that type (i.e., something of type T -> Prop), and not as a "subset" of T, as you would do in set theory.
You defined s, t and l as functions of one argument, but used them as two-argument functions, as in s e v1. I suppose you wanted to say something like v1 = s e, i.e. v1 is the source of edge e. However, there's no need to say that: s e is an expression of type V like any other, and can be used directly, with no need to declare additional variables (see below). Likewise, you don't need to say that there exists some color b that is different from a: you can just refer to the color of that node directly.
Here's a version of your type that avoids those problems:
Record dirgraph:={
V:Set;
E:Set;
s:E->V; (* source function *)
t:E->V; (* target function *)
color: V->nat;
wellColored:
forall e : E, color (s e) <> color (t e)
}.

Isabelle's Code generation: Abstraction lemmas for containers?

I am experimenting with the Code generator. My theory contains a datatype that encodes an invariant:
typedef small = "{x::nat. x < 10}" morphisms to_nat small
by (rule exI[where x = 0], simp)
definition "is_one x ⟷ x = small 1"
Now I want to export code for is_one. It seems that I first have to set up the data type for the code generator as follows:
code_datatype small
instantiation small :: equal
begin
definition "HOL.equal a b ⟷ to_nat a = to_nat b"
instance
apply default
unfolding equal_small_def
apply (rule to_nat_inject)
done
end
lemma [code abstype]: "small (to_nat x) = x" by (rule to_nat_inverse)
And now I am able to define a code equation for is_one that does not violate the abstraction:
definition [code del]:"small_one = small 1"
declare is_one_def[code del]
lemma [code]: "is_one x ⟷ x = small_one" unfolding is_one_def small_one_def..
lemma [code abstract]: "to_nat small_one = 1"
unfolding small_one_def by (rule small_inverse, simp)
export_code is_one in Haskell file -
Question 1: Can I avoid pulling the definition of small_one out of is_one?
Now I have a compound value of small items:
definition foo :: "small set list" where "foo = [ {small (10-i), small i} . i <- [2,3,4] ]"
In that form, I cannot export code using it (“Abstraction violation in code equation foo...”).
Question 2: How do I define an [code abstract] lemma for such a value? It seems that the code generator does not accept lemmas of the form map to_nat foo = ....
For types with invariants declared by code_abstract such as small, no code equation may contain the abstraction function small. Consequently, if you want the equality test in is_one to be expressed on type small, you have to define a constant for small 1 and prove the corresponding code equation with to_nat first. This is what you have done. However, it would be easier to use equality on the representation type nat, i.e., inline the implementation equal_class.equal; then, you do not need to instantiate equal for small either.
lemma is_one_code [code]: "is_one x ⟷ to_nat x = 1"
by(cases x)(simp add: is_one_def small_inject small_inverse)
The lifting package does most of this for you automatically:
setup_lifting type_definition_small
lift_definition is_one :: "small => bool" is "%x. x = 1" ..
export_code is_one in SML file -
Unfortunately, the code generator does not support compound return types that involve abstract types like in small set list. As described in Data Refinement in Isabelle/HOL, sect. 3.2, you have to wrap the type small set list as a type constructor small_set_list of its own and define foo with type small_set_list. The type small_set_list is then represented as nat set list with the invariant list_all (%A. ALL x:A. x < 10).
Besides Andreas' explanation and comprehensive solution, I found a work-around that avoids introducing a new type. Assume foo is not used in many places, say, only in
definition "in_foo x = (∀s ∈ set foo. x ∈ s)"
Trying to export code for in_foo gives the "Abstraction violation" error. But using program refinement, I can avoid the problematic code:
I use code_thms to find out how foo is used and find that it is used as list_all (op ∈ ?x) foo. Now I rewrite this particular use of foo without mentioning small:
lemma [code_unfold]:
"list_all (op ∈ x) foo ⟷
list_all (op ∈ (to_nat x)) [ {(10-i), i} . i <- [2, 3, 4] ]"
unfolding foo_def by (auto simp add: small_inverse small_inject)
(Had I defined foo using lift_definition, the proof after apply transfer would be even simpler.)
After this transformation, which essentially captures that all members of foo fulfill the invariant of small, the code export works as intended:
export_code in_foo in Haskell file -