Beta expansion in coq: can I make a term into a function, abstracting over another given term? - coq

I want to rewrite a term, as a function in a sort of beta expansion (inverse of beta reduction).
So, for example in the term a + 1 = RHS I would like to replace it as (fun x => x + 1) a = RHS. Obviously, the two terms are equal by betta reduction, but I can't figure out how to automate it.
The tactic pattern comes very close to what I want, except it only applies to a full goal, and I can't see how I would use it in a term inside an equality.
Similarly, I thought I could use the context holes. Here is my best attempt
Ltac betaExpansion term a:=
let T:= type of a in
match term with
context hole [a] =>
idtac hole;
let f:= fun x => context hole [x] in
remember ( fun x:T => f x ) as f'
end.
Goal forall a: nat, a + 1 = 0.
intros a.
match goal with
|- ?LHS = _ =>
betaExpansion LHS a (*Error: Variable f should be bound to a term but is bound to a tacvalue.*)
end.
This obviously fails, because f is a tacvalue when I really need a normal value. Can I somehow evaluate the expression to make it a value?

You should have a look at the pattern tactic. pattern t replaced all occurrences of t in the goal by a beta expanded variable.

You may also use the change ... with ... at tactic.
Goal forall (a:nat) , a+1 = 2* (a+1) - (a+1).
intro x; change (x+1) with ((fun z => z) (x+1)) at 1 3.
(*
x : nat
============================
(fun z : nat => z) (x + 1) = 2 * (x + 1) - (fun z : nat => z) (x + 1)
*)
Or, more automatically
Ltac betaexp term i :=
let x := fresh "x" in
let T := type of term in
change term with ((fun x : T => x) term) at i.
Goal forall (a:nat) , a+1 = a+1 .
intro x; betaexp (x+1) ltac:(1).

Related

Computing with a finite subset of an infinite representation in Coq

I have a function Z -> Z -> whatever which I treat as a sort of a map from (Z, Z) to whatever, let's type it as FF.
With whatever being a simple sum constructible from nix or inj_whatever.
This map I initialize with some data, in the fashion of:
Definition i (x y : Z) (f : FF) : FF :=
fun x' y' =>
if andb (x =? x') (y =? y')
then inj_whatever
else f x y.
The =? represents boolean decidable equality on Z, from Coq's ZArith.
Now I would like to have equality on two of such FFs, I don't mind invoking functional_extensionality. What I would like to do now is to have Coq computationally decide equality of two FFs.
For example, suppose we do something along the lines of:
Definition empty : FF := fun x y => nix.
Now we add some arbitrary values to make foo and foo', those are equivalent under functional extensionality:
Definition foo := i 0 0 (i 0 (-42) (i 56 1 empty)).
Definition foo' := i 0 (-42) (i 56 1 (i 0 0 empty)).
What is a good way to automatically have Coq determine foo = foo'. Ltac level stuff? Actual terminating computation? Do I need domain restriction to a finite one?
The domain restriction is a bit of an intricate one. I manipulate the maps in a way f : FF -> FF, where f can extend the subset of Z x Z that the computation is defined on. As such, come to think of it, it can't be f : FF -> FF, but more like f : FF -> FF_1 where FF_1 is a subset of Z x Z that is extended by a small constant. As such, when one applies f n times, one ends up with FF_n which is equivalent to domain restriction of FF plus n * constant to the domain. So the function f slowly (by a constant factor) expands the domain FF is defined on.
As I said in the comment more specifics are needed in order to elaborate a satisfactory answer. See the below example --- intended for a step by step description --- on how to play with equality on restricted function ranges using mathcomp:
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
(* We need this in order for the computation to work. *)
Section AllU.
Variable n : nat.
(* Bounded and unbounded fun *)
Definition FFb := {ffun 'I_n -> nat}.
Implicit Type (f : FFb).
Lemma FFP1 f1 f2 : reflect (f1 = f2) [forall x : 'I_n, f1 x == f2 x].
Proof. exact/(equivP eqfunP)/ffunP. Qed.
Lemma FFP2 f1 f2 :
[forall x : 'I_n, f1 x == f2 x] = all [fun x => f1 x == f2 x] (enum 'I_n).
Proof.
by apply/eqfunP/allP=> [eqf x he|eqf x]; apply/eqP/eqf; rewrite ?enumT.
Qed.
Definition f_inj (f : nat -> nat) : FFb := [ffun x => f (val x)].
Lemma FFP3 (f1 f2 : nat -> nat) :
all [fun x => f1 x == f2 x] (iota 0 n) -> f_inj f1 = f_inj f2.
Proof.
move/allP=> /= hb; apply/FFP1; rewrite FFP2; apply/allP=> x hx /=.
by rewrite !ffunE; apply/hb; rewrite mem_iota ?ltn_ord.
Qed.
(* Exercise, derive bounded eq from f_inj f1 = f_inj f2 *)
End AllU.
The final lemma should indeed allow you reduce equality of functions to a computational, fully runnable Gallina function.
A simpler version of the above, and likely more useful to you is:
Lemma FFP n (f1 f2 : nat -> nat) :
[forall x : 'I_n, f1 x == f2 x] = all [pred x | f1 x == f2 x] (iota 0 n).
Proof.
apply/eqfunP/allP=> eqf x; last by apply/eqP/eqf; rewrite mem_iota /=.
by rewrite mem_iota; case/andP=> ? hx; have /= -> := eqf (Ordinal hx).
Qed.
But it depends on how you (absent) condition on range restriction is specified.
After your edit, I think I should add a note on the more general topic of map equality, indeed you can define a more specific type of maps other than A -> B and then build a decision procedure.
Most typical map types [including the ones in the stdlib] will work, as long as they support the operation of "binding retrieval", so you can reduce equality to the check of finitely-many bound values.
In fact, the maps in Coq's standard library do already provide you such computational equality function.
Ok, this is a rather brutal solution which does not attempt to avoid doing the same case distinctions multiple times but it's fully automated.
We start with a tactic which inspects whether two integers are equal (using Z.eqb) and translates the results to a proposition which omega can deal with.
Ltac inspect_eq y x :=
let p := fresh "p" in
let q := fresh "q" in
let H := fresh "H" in
assert (p := proj1 (Z.eqb_eq x y));
assert (q := proj1 (Z.eqb_neq x y));
destruct (Z.eqb x y) eqn: H;
[apply (fun p => p eq_refl) in p; clear q|
apply (fun p => p eq_refl) in q; clear p].
We can then write a function which fires the first occurence of i it can find. This may introduce contradictory assumptions in the context e.g. if a previous match has revealed x = 0 but we now call inspect x 0, the second branch will have both x = 0 and x <> 0 in the context. It will be automatically dismissed by omega.
Ltac fire_i x y := match goal with
| [ |- context[i ?x' ?y' _ _] ] =>
unfold i at 1; inspect_eq x x'; inspect_eq y y'; (omega || simpl)
end.
We can then put everything together: call functional extensionality twice, repeat fire_i until there's nothing else to inspect and conclude by reflexivity (indeed all the branches with contradictions have been dismissed automatically!).
Ltac eqFF :=
let x := fresh "x" in
let y := fresh "y" in
intros;
apply functional_extensionality; intro x;
apply functional_extensionality; intro y;
repeat fire_i x y; reflexivity.
We can see that it discharges your lemma without any issue:
Lemma foo_eq : foo = foo'.
Proof.
unfold foo, foo'; eqFF.
Qed.
Here is a self-contained gist with all the imports and definitions.

Using 'convoy pattern' to obtain proof inside code of equality of pattern match

It is a standard example of beginner's textbooks on category theory to argue that a preorder gives rise to a category (where the hom-set hom(x,y) is a singleton or empty depending on whether x <= y). When attempting to formalize this idea in coq, it is natural to view an arrow of as a triple (x,y,pxy) where x y:A (A being a type on which we have a preorder) and pxy is a proof that x <= y. So naturally, when attempting to define a composition of two arrows (x,y,pxy) and (y',z,pyz), we need to returnSome arrow whenever y = y' (or None otherwise). This implies that we are able to test for equality within the function, and compute a proof (the last field of our triple, which may rely on the fact that things are equal).
For the sake of this question, suppose I have:
Parameter eq_dec : forall {A:Type}, A -> A -> bool.
and:
Axiom eq_dec_correct : forall (A:Type) (x y:A),
eq_dec x y = true -> x = y. (* don't care about equivalence here *)
and let us assume I am attempting something simpler than defining composition between arrows, by writing a function which returns a proof that x = y whenever x = y.
Definition test {A:Type} (x y : A) : option (x = y) :=
match eq_dec x y with
| true => Some (eq_dec_correct A x y _)
| false => None
end.
This doesn't work of course, but probably gives you the idea of what I am trying to achieve. Any suggestion is greatly appreciated.
EDIT: Ok it seems this is a case of 'convoy pattern'. I have found this link which suggested to me:
Definition test (A:Type) (x y:A) : option (x = y) :=
match eq_dec x y as b return eq_dec x y = b -> option (x = y) with
| true => fun p => Some (eq_dec_correct A x y p)
| false => fun _ => None
end (eq_refl (eq_dec x y)).
This seems to be working. It is a bit magical and confusing but I'll get my head round it.

Merge duplicate cases in match Coq

I have come by this problem many times: I have a proof state in Coq that includes matches on both sides of an equality that are the same.
Is there a standard way to rewrite multiple matches into one?
Eg.
match expression_evaling_to_Z with
Zarith.Z0 => something
Zartih.Pos _ => something_else
Zarith.Neg _ => something_else
end = yet_another_thing.
And if I destruct on expresion_evaling_to_Z I get two identical goals. I would like to find a way to get only one of the goals.
A standard solution is to define "a view" of your datatype using a type family that will introduce the proper conditions and cases when destructed. For your particular case, you could do:
Require Import Coq.ZArith.ZArith.
Inductive zero_view_spec : Z -> Type :=
| Z_zero : zero_view_spec Z0
| Z_zeroN : forall z, z <> Z0 -> zero_view_spec z.
Lemma zero_viewP z : zero_view_spec z.
Proof. now destruct z; [constructor|constructor 2|constructor 2]. Qed.
Lemma U z : match z with
Z0 => 0
| Zpos _ | Zneg _ => 1
end = 0.
Proof.
destruct (zero_viewP z).
Abort.
This is a common idiom in some libraries like math-comp, which provides special support for instantiating the z argument of the type family.
You can write the match expression more succinctly:
match expression_evaling_to_Z with
| Z0 => something
| Zpos _ | Zneg _ => something_else
end = yet_another_thing.
But that will give you 3 subgoals when using destruct.
In this particular case we may use the fact that you actually need to distinguish the zero and non-zero cases, and it looks like a job for the Z.abs_nat : Z -> nat function.
Require Import Coq.ZArith.BinIntDef.
match Z.abs_nat (expression_evaling_to_Z) with
| O => something
| S _ => something_else
end = yet_another_thing.
This will get you only two subcases, but you need to destruct on Z.abs_nat (expression_evaling_to_Z) or introduce a new variable. If you choose the 1st variant, then you'll probably need destruct (...) eqn:Heq. to put the equation into context.
Basically this approach is about finding a new datatype (or defining one) and a suitable function to map from the old type to the new one.
If you don't mind typing you can use replace to replace the RHS with the LHS of your goal, which makes it trivial to solve, and then you just have to prove once that the rewrite is indeed ok.
Open Scope Z.
Lemma L a b :
match a + b with
Z0 => a + b
| Zpos _ => b + a
| Zneg _ => b + a
end = a + b.
replace (b+a) with (a+b). (* 1. replace the RHS with something trivially true *)
destruct (a+b); auto. (* 2. solve the branches in one fell swoop *)
apply Z.add_comm. (* 3. solve only once what is required for the two brances *)
Qed.
Perhaps you can use some Ltac-fu or other lemma to not have to type in the RHS manually too.

How to destruct/generalize over Program's rewritten match statements

When using Program, match statements are rewritten into a "proof-passing" style. This makes evidence of the match available in the branches—which can be critical.
However, it also seems to make case analysis more difficult. For example:
Require Import ZArith.
Open Scope Z_scope.
Program Definition test (x:Z) : option (x <= 100) :=
match Z_le_gt_dec x 100 with
| left bound => Some _
| right bound => None
end.
Lemma test_gt_100 : forall x:Z, x > 100 -> test x = None.
Proof.
intros x bound.
unfold test.
At this point, one would normally destruct (Z_le_gt_dec x 100) and the proof is then easy. However, the rewritten match gives this context:
x : Z
bound : x > 100
============================
match
Z_le_gt_dec x 100 as x0
return (x0 = Z_le_gt_dec x 100 -> option (x <= 100))
with
| left bound0 =>
fun Heq_anonymous : left bound0 = Z_le_gt_dec x 100 =>
Some (test_obligation_1 x bound0 Heq_anonymous)
| right bound0 => fun _ : right bound0 = Z_le_gt_dec x 100 => None
end eq_refl = None
With this, the destruct fails:
Toplevel input, characters 20-48:
Error: Abstracting over the term "s" leads to a term
"fun s : {x <= 100} + {x > 100} =>
match s as x0 return (x0 = s -> option (x <= 100)) with
| left bound =>
fun Heq_anonymous : left bound = s =>
Some (test_obligation_1 x bound Heq_anonymous)
| right bound => fun _ : right bound = s => None
end eq_refl = None" which is ill-typed.
Going more slowly and trying just to generalize (Z_le_gt_dec x 100) shows why:
Toplevel input, characters 0-30:
Error: Illegal application (Type Error):
The term "test_obligation_1" of type
"forall x : Z,
let filtered_var := Z_le_gt_dec x 100 in
forall bound : x <= 100, left bound = filtered_var -> x <= 100"
cannot be applied to the terms
"x" : "Z"
"bound0" : "x <= 100"
"Heq_anonymous" : "left bound0 = s"
The 3rd term has type "left bound0 = s" which should be coercible to
"left bound0 = Z_le_gt_dec x 100".
While that makes some sense, I'm at a loss about what to do about it.
(I've put this in collacoq if it's helpful. Don't forget to execute just the Comment line at first and then wait until all the libraries have loaded before importing ZArith.)
The problem here is that you depend on a specific equality term, abstracting over it should allow you to proceed. (It is is general good practice to state lemmas that are independent of proofs).
Here's your example, using ssreflect's rewrite. Sorry, I was unable to instruct Coq's one to do the proper pattern selection.
Comments "pkgs: coq-reals".
From mathcomp Require Import ssreflect.
Require Import Coq.ZArith.ZArith.
Open Scope Z_scope.
Program Definition test (x:Z) : option (x <= 100) :=
match Z_le_gt_dec x 100 with
| left bound => Some _
| right bound => None
end.
Lemma test_gt_100 : forall x:Z, x > 100 -> test x = None.
Proof.
intros x hb; unfold test.
assert (Z_le_gt_dec x 100 = right hb) as Hz. admit.
move: eq_refl; rewrite {1 3}Hz.
done.
[Also at https://x80.org/collacoq/xareboqura.coq ]
Best regards, E.
EDIT: A bit more detail: At the beginning, the argument of the match is eq_refl : forall x, x = x which is ok as the function inside the match expects a term of type Z.le .... = Z.le ..... However, when performing the rewrite, the type in the match annotation will become of the form Z_le ... = right ..., but if argument is still eq_refl this will result in a badly typed term, as eq_refl can never be typed as Z.le ... = right ...!
Thus, we modify our goal so that the proof for the equality doesn't necessarily have to be eq_refl, then we rewrite.
Why the proof was done with eq_refl in the first place? This is usually done to have good reduction behavior in the presence of equality proofs.
It would be interesting to add proof-irrelevance support to Program thou. (I ignore if there's already some).

Coordinates in Coq

I apologize if this is obviously posted somewhere, but I have been trying Google search and SO search and found nothing on this yet.
Part A.
Is there a standard library for defining coordinates/vectors and points in R^2 and R^3 in Coq? I pretty much want to do standard stuff, like adding vectors, cross products, scaling, etc.
If not, how is this for a start:
Require Import Coq.Reals.Reals.
Inductive Coordinate2 : Type := Point2: R -> R -> Coordinate2.
Definition R2plus (u:Coordinate2) (v:Coordinate2) : Coordinate2 :=
match u, v with
| (Point2 ux uy),(Point2 vx vy)=>(Point2 ((ux+vx)%R) ((uy+vy)%R))
end.
(* etc. *)
Notation "x + y" := (R2plus x y).
Also, why when I run:
Eval compute in ((2%R) < (3%R))%R.
Do I get
= (2 < 3)%R
: Prop
rather than
True
or something?
Part B.
Is this even a good idea? I want to build an algorithm which computes some things using real numbers, and prove the algorithm correct in Coq. Is Coq.Reals.Reals the right thing to be using, or is it really too abstract?
Instead of defining Coordinate2 you could also use (R * R)%type, list R, or t R 2, where t A n, defined in Vector, is a list of size n.
You might want to give your notations a scope and a delimiting key to avoid clashes with other notations.
Notation "x + y" := (R2plus x y) : r2_scope.
Delimit Scope r2_scope with R2.
Eval compute in ((Point2 0 1) + (Point2 2 3))%R2.
Prop, Set, and Type are sorts, which means something of type Prop might be defined inductively.
For example, for the nats, le is defined as
Inductive le : nat -> nat -> Prop :=
| le_n : forall n, le n n
| le_S : forall n m : nat, le n m -> le n (S m).
2 <= 2 is true because it's inhabited by le_n 2
2 <= 3 is true because it's inhabited by le_S 2 2 (le_n 2)
2 <= 4 is true because it's inhabited by le_S 2 3 (le_S 2 2 (le_n 2))
3 <= 2 is false because it's not inhabited
For 2 <= 3 to reduce to True, le would have to be defined like, for example,
Fixpoint le (n m : nat) : Prop :=
match n with
| 0 => True
| S n =>
match m with
| 0 => False
| S m => le n m
end
end.
Coq's definition of Rplus and Rlt are actually axioms. To check the definition of something use the Print command.
To answer part B, I guess it depends on how well you understand mathematical analysis and the various ways of defining the reals. If you're more familiar with numerical methods, you might want to use the rationals instead.