I am having trouble defining a tactic to recursively invert hypotheses in a proof context. For instance, suppose I have a proof context containing a hypothesis like:
H1 : search_tree (node a (node b ll lr) (node c rl rr))
and would like to repeatedly invert the hypothesis to obtain a proof context containing the hypotheses
H1 : search_tree (node a (node b ll lr) (node c rl rr))
H2 : search_tree (node b ll lr)
H3 : search_tree (node c rl rr)
H4 : lt_tree a (node b ll lr)
H5 : gt_tree a (node c rl rr)
H6 : lt_tree b ll
H7 : gt_tree b lr
H8 : lt_tree c rl
H9 : gt_tree c rr
Of course, obtaining this proof context is easy by repeatedly applying the inversion tactic. However, sometimes inverting a hypothesis will put different hypotheses into different subgoals, and whether to invert each depends on the nature of the information provided by inversion.
The obvious problem is that indiscriminately pattern matching against the proof context will cause nontermination. For instance, the following won't work if one wishes to retain the original hypotheses after inverting them:
Ltac invert_all :=
match goal with
| [ H1 : context [ node ?a ?l ?r ] |- ?goal ] => invert H1; invert_all
| _ => idtac
end.
Is there an easy way to do this? The obvious solution would be to keep a stack of already inverted hypotheses. Another solution is to only invert hypotheses up to a particular depth, which would remove recursive calls in Ltac.
If that's really what you want to do, I suspect you want first to prove a helper Fixpoint subtreelist (st : searchtree): list (...) that returns a list of all these subtrees, and then a tactic that calls subtreelist and recursively destructs the list untill you have all the extra hypotheses you want.
Good luck with that!
Related
This question is a request for references or explanation.
The main idea is: What if I add every axiom from standard library of Coq?
Will it raise a contradiction or they are well-adjusted to each other?
What are other reliable sources of information about Coq other than a standard library of Coq. (I saw a bunch papers from nineties, eighties. Obviously there are plenty of variants of type theories. Which one is for contemporary Coq? Or should I think "Everything that is known may be found in https://coq.inria.fr/refman/ , in https://sympa.inria.fr/sympa/arc/coq-club/1993-12/ and in standard library.")
(A) Do you know paper or other source where it is proved that some axioms may be properly added to Coq?
Properly here means that the extended system will be a conservative extension of previous OR will be considered to be safe strengthening.
(B) Personally, I am interested in these axioms:
0) ex2sig (is it consistent?)
Axiom ex2sig : forall (A:Type) (P:A->Prop), #ex A P -> #sig A P.
1) LEM
2) Functional extensionality
Axiom functional_extensionality_dep : forall {A} {B : A -> Type},
forall (f g : forall x : A, B x),
(forall x, f x = g x) -> f = g.
3) Choice
Theorem choice :
forall (A B : Type) (R : A->B->Prop),
(forall x : A, exists y : B, R x y) ->
exists f : A->B, (forall x : A, R x (f x)).
4) "Terms-as-Types"
Definition E := Type.
Axiom R : forall x : E, x -> E.
Axiom R_inj : forall (x : E) (a b : x), R x a = R x b -> a = b.
5) Proof-Irrelevance
Axiom proof_irrelevance : forall (P:Prop) (p1 p2:P), p1 = p2.
6) ... (you may recommend your axiom in comments)
e.g. Markov's principle
Parameter P:nat -> Prop.
Theorem M:((forall n,(P n \/ ~ (P n)))/\ ~(forall n, ~(P n)) -> exists n,P n).
But we are not very much interested in Markov's principle.
Because we need some very strong classic theory with LEM(so the Markov principle is proved), with some strongest form of Choice(which will imply LEM), extensionality, etc. (Which axioms can we also add?) (By the way, there are many variants of choice in Coq: relational)
p.s. Shall extensive use of "noncomputational" axioms in Coq be treated as misuse of it? (I think no, but I am not sure.)
Which properties of Coq will I loose after adding the axioms? (you may say both reference and/or opinion)
p.p.s. The question is big and consist of many connected pieces, so every partial answer is welcome.
Assume you have 2 Integer Variables a and b
How would you swap them only if a > b by using a match expression?
If a <= b do not swap the ints.
In an imperative language:
if (a > b){
int temp=a;
a=b;
b=temp;
}
Doing the same in ocaml seems surprisingly hard.
I tried
let swap a b =
match a,b with
| a,b when a > b -> b,a
| a,b when a <= b -> a,b
I am trying to do this because in the following function call, I want to make sure that x is the bigger of the two variables.
One easy way :
let swap a b =
if (a>b) then (b,a)
else (a,b)
But this is not equivalent to the C code, your C code is swapping the value of the variable - this is how imperative language are doing.
In Ocaml, there is no side-effect (except if you use reference to some int). This swap function will return a tuple whose members are always ordered (the first member will be always smaller than the second order).
Without state, you cannot "swap" the values of the variables since the variables are immutable. Your best bet is to use a tuple and introduce new variables in the scope. Example:
let diff a b =
let (min, max) = if a <= b then (a, b) else (b, a)
in max - min
You can of course use the same identifiers and shadow the original variables:
let diff a b =
let (a, b) = if a <= b then (a, b) else (b, a)
in b - a
It doesn't really help with readability though.
Just for reference, if you'd like to swap the values in two refs, it would look like the following:
let swap a_ref b_ref =
let a, b = !a_ref, !b_ref in
a_ref := b;
b_ref := a
;;
which has the type val swap : 'a ref -> 'a ref -> unit.
I'm trying to perform the following proof based on Finite Maps as defined in CoqExtLib. However, I'm having a problem where the instance of RelDec showing up in the proof is different than the instance that I think is declared.
Require Import ExtLib.Data.Map.FMapAList.
Require ExtLib.Structures.Sets.
Module DSet := ExtLib.Structures.Sets.
Require ExtLib.Structures.Maps.
Module Map := ExtLib.Structures.Maps.
Require Import ExtLib.Data.Nat.
Require Import Coq.Lists.List.
Definition Map k v := alist k v.
Definition loc := nat.
Definition sigma : Type := (Map loc nat).
Lemma not_in_sigma : forall (l l' : loc) (e : nat) (s : sigma),
l <> l' ->
Map.lookup l ((l',e)::s) = Map.lookup l s.
intros. simpl. assert ( RelDec.rel_dec l l' = true -> l = l').
pose (ExtLib.Core.RelDec.rel_dec_correct l l') as i. destruct i.
(*i := RelDec.rel_dec_correct l l' : RelDec.rel_dec l l' = true <-> l >= l'*)
As you can see, I'm trying to use the fact that rel_dec must evaluate to false if its two inputs are not equal. This seems to match the definition given in ExtLib.Data.Nat:
Global Instance RelDec_eq : RelDec (#eq nat) :=
{ rel_dec := EqNat.beq_nat }.
However, in the code I showed above, it's using >= instead of = as the relation that the finite map is parameterized on, so I can't apply the theorem rel_dec_correct.
Why is this happening? How is the instance for RelDec being chosen? Is there something special I need to do when proving theorems about types qualified by typeclasses? How can I get a version of rel_dec_correct that applies to equality, not greater-than?
To resolve this issue you might want to set Debug Typeclasses option:
Set Debug Typeclasses.
assert ( RelDec.rel_dec l l' = true -> l = l').
or, alternatively, use Set Printing Implicit to reveal the instances Coq has picked up.
The latter shows us that it is RelDec_ge as the goal now has the following form:
#RelDec.rel_dec loc ge RelDec_ge l l' = true -> l = l'
Apparently Coq chose the instance which is wrong for your purposes, however you can lock the relation you want like so:
assert ( RelDec.eq_dec l l' = true -> l = l').
Now apply (RelDec.rel_dec_correct l l'). resolves the goal, but pose won't work, since there is no information that would tie the goal to a useful instance. The pose tactic would just find an instance of RelDec nat <rel> (you can list all of them with this vernacular: Print Instances RelDec.RelDec.).
There is a very nice tutorial on typeclasses by B.C. Pierce you might want to have a look at.
The third chapter of CPDT briefly discusses why negative inductive types are forbidden in Coq. If we had
Inductive term : Set :=
| App : term -> term -> term
| Abs : (term -> term) -> term.
then we could easily define a function
Definition uhoh (t : term) : term :=
match t with
| Abs f => f t
| _ => t
end.
so that the term uhoh (Abs uhoh) would be non-terminating, with which "we would be able to prove every theorem".
I understand the non-termination part, but I don't get how we can prove anything with it. How would one prove False using term as defined above?
Reading your question made me realize that I didn't quite understand Adam's argument either. But inconsistency in this case results quite easily from Cantor's usual diagonal argument (a never-ending source of paradoxes and puzzles in logic). Consider the following assumptions:
Section Diag.
Variable T : Type.
Variable test : T -> bool.
Variables x y : T.
Hypothesis xT : test x = true.
Hypothesis yF : test y = false.
Variable g : (T -> T) -> T.
Variable g_inv : T -> (T -> T).
Hypothesis gK : forall f, g_inv (g f) = f.
Definition kaboom (t : T) : T :=
if test (g_inv t t) then y else x.
Lemma kaboom1 : forall t, kaboom t <> g_inv t t.
Proof.
intros t H.
unfold kaboom in H.
destruct (test (g_inv t t)) eqn:E; congruence.
Qed.
Lemma kaboom2 : False.
Proof.
assert (H := #kaboom1 (g kaboom)).
rewrite -> gK in H.
congruence.
Qed.
End Diag.
This is a generic development that could be instantiated with the term type defined in CPDT: T would be term, x and y would be two elements of term that we can test discriminate between (e.g. App (Abs id) (Abs id) and Abs id). The key point is the last assumption: we assume that we have an invertible function g : (T -> T) -> T which, in your example, would be Abs. Using that function, we play the usual diagonalization trick: we define a function kaboom that is by construction different from every function T -> T, including itself. The contradiction results from that.
I am trying to produce the solution for an intersection of two sets using tail recursion and an empty list [] as an accu:
let rec setintersect list list =
let rec setintersect2 a b c =
match a with
| [] -> (match b with [] -> (setsimplify c) | h::t -> (setsimplify c))
| h1::t1 -> (match b with [] -> (setsimplify c) |h2::t2 -> (if (elementof h1 b) then (setintersect2 t1 b (c#[h1])) else (setintersect2 t1 b c))) in
setintersect2 list list [];;
Elementof takes takes "an int and a list" and is correctly working to give true if x is an element of the list, false otherwise..
Here is the problem:
# setintersect [5;2;1] [2;6;9];;
- : int list = [2; 6; 9]
and it should give [2].
What am I doing wrong?
I feel like there's something really simple that I am misunderstanding!
Edit:
Thanks for the responses so far.
setsimplify just removes the duplicates.
so [2,2,3,5,6,6] becomes [2,3,5,6]. Tested and made sure it is working properly.
I am not supposed to use anything from the List library either. Also, I must use "tail recursion" with the accumulator being a list that I build as I go.
Here is the thought:
Check the head element in list1, IF it exists in list2, THEN recurse with the "tail of list1, list2, and list c with that element added to it". ELSE, then recurse with "tail of list1, list2 and list c(as it is)".
end conditions are either list1 or list2 are empty or both together are empty, return list c (as it is).
let rec setintersect list list = is wrong: the two arguments should be named differently (you should of course update the call to setintersect2 accordingly), otherwise the second will shadow the first. I would have thought that OCaml would have at least warned you about this fact, but it appears that it is not the case.
Apart from that, the code seems to do the trick. There are a couple of things that could be improved though:
setintersect itself is not recursive (only setintersect2 is), you thus don't need the rec
you should find a different name for the argument of setintersect2. In particular, it is not obvious which is the accumulator (acc or accu will be understood by most OCaml programmers in these circumstances).
c#[h1] is inefficient: you will traverse c completely each time you append an element. It's better to do h1::c and reverse the result at the end
As a bonus point, if you append element at the beginning of c, and assume that a is ordered, you don't have to call setsimplify at the end of the call: just check whether c is empty, and if this is not the case, append h1 only if it is not equal to the head of c.
First, You didn't list out your setsimplify function.
To write an ocaml function, try to split it first, and then combine if possible.
To solve this task, you just go through all elements in l1, and for every element, you check whether it is in l2 or not, right?
So definitely you need a function to check whether an element is in a list or not, right?
let make one:
let rec mem x = function
| [] -> false
| hd::tl -> hd = x || mem x tl
Then you can do your intersection:
let rec inter l1 l2 =
match l1 with
| [] -> []
| hd::tl -> if mem hd l2 then hd::(inter tl l2) else inter tl l2
Note that the above function is not tail-recursive, I guess you can change it to tail-recursive as an excise.
If you use std library, then it is simple:
let intersection l1 l2 = List.filter (fun x -> List.mem x l2) l1