Defining isomorphism classes in Coq - coq

How to define isomorphism classes in Coq?
Suppose I have a record ToyRec:
Record ToyRec {Labels : Set} := {
X:Set;
r:X->Labels
}.
And a definition of isomorphisms between two objects of type ToyRec, stating that two
objects T1 and T2 are isomorphic if there exists a bijection f:T1.(X)->T2.(X) which preserves the label of mapped elements.
Definition Isomorphic{Labels:Set} (T1 T2 : #ToyRec Labels) : Prop :=
exists f:T1.(X)->T2.(X), (forall x1 x2:T1.(X), f x1 <> f x2) /\
(forall x2:T2.(X), exists x1:T1.(X), f x1 = f x2) /\
(forall x1:T1.(X) T1.(r) x1 = T2.(r) (f x1)).
Now I would like to define a function that takes an object T1 and returns a set
containing all objects that are isomorphic to T1.
g(T1) = {T2 | Isomorphic T1 T2}
How one does such a thing in coq? I know that I might be reasoning too set theoretically
here, but what would be the right type theoretic notion of isomorphism class? Or even more basically, how one would define a set (or type) of all elemenets satisfying a given property?

It really depends on what you want to do with it. In Coq, there is a comprehension type {x : T | P x} which is the type of all elements x in type T that satisfy property P. However, it is a type, meaning that it is used to classify other terms, and not a data-structure you can compute with in the traditional sense. Thus, you can use it, for instance, to write a function on T that only works on elements that satisfy P (in which case the type of the function would be {x : T | P x} -> Y, where Y is its result type), but you can't use it to, say, write a function that computes how many elements of T satisfy P.
If you want to compute with this set, things become a bit more complicated. Let's suppose P is a decidable property so that things become a bit easier. If T is a finite type, then you can a set data-structure that has a comprehension operator (have a look at the Ssreflect library, for instance). However, this breaks when T is infinite, which is the case of your ToyRec type. As Vinz said, there's no generic way of constructively building this set as a data-structure.
Perhaps it would be easier to have a complete answer if you explained what you want to do with this type exactly.

Related

Proof that two isomorphic types are different

Given these two types,
Inductive unit : Set := tt.
Inductive otherUnit : Set := ttt.
Can Coq prove they are different, ie unit <> otherUnit ?
Both are singleton types in sort Set so it is not easy to find a Set -> Prop that differentiates them. For example, this does not even type check
Definition singletonTT (A : Set) : Prop := forall x : A, x = tt.
because tt has type unit instead of A.
It's actually admissible in Coq that these two types are equal; that is, you can neither prove they are equal or different, and it's consistent to assume either.
You can't express singletonTT in terms of tt because as you point out, it only type checks for the unit type. Instead you need to treat A opaquely; for example, you can express the property of being a singleton as A /\ forall (x y:A), x = y. Of course, both types are singletons so this doesn't distinguish them.
If you do assume Axiom unit_otherUnit : unit = otherUnit, then you can express something like singletonTT by casting tt to otherUnit: eq_rec _ (fun S => S) tt otherUnit ax = ttt.
When types have different cardinalities (which means they aren't isomorphic) you can use their cardinality to distinguish them and prove the types are distinct. Easy examples include False <> True and unit <> bool, and a more complicated example is nat <> (nat -> nat).

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.

Strong Induction on Lists

I'm trying to prove that a proposition P holds for every element of a type A. Unfortunately, I only know how to prove P for a given a:A if I have access to proofs of P for all a' less than a.
This should be provable by induction on a list containing all elements of A, starting with the smallest element in A and then incrementally proving that P holds for all other elements, but I just can't get it to work.
Formally, the problem is the following:
Parameter A : Type.
Parameter lt : A -> A -> Prop.
Notation "a < b" := (lt a b).
Parameter P : A -> Prop.
Parameter lma : forall a, (forall a', a' < a -> P a') -> P a.
Goal forall a, P a.
I may have made a mistake formalizing this problem. Feel free to assume reasonable constraints on the inputs, e.g. A can be assumed to be enumerable, lt can be transitive, decidable ...
This looks at lot like well founded induction. If you can prove that your lt function is well-founded, then your goal becomes trivial. You can find example of such proofs on naturals here
You also have to prove that the relation is well-founded. There's a relevant standard library module. From there, you should prove well_founded A for your A type, and then you can use well_founded_ind to prove P for all values.

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)
}.