Error: Cannot guess decreasing argument of fix. Coq - coq

I have the following definition for terms :
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Require Import Coq.Strings.String.
Import ListNotations.
Definition VarIndex:Type := nat.
Inductive Term : Type :=
|Var : VarIndex -> Term
|Comb: string -> (list Term) -> Term.
(*compare two list *)
Fixpoint beq_list {X:Type} (l l' :list X) (EqX :X -> X -> bool): bool :=
match l with
| [] => match l' with
| [] => true
| a => false
end
| (x::xs) =>
match l' with
|[] => false
|(y::ys) => if (EqX x y) then beq_list xs ys EqX else false
end
end.
Fixpoint length {X : Type} (l : list X) : nat :=
match l with
| nil => 0
| cons _ l' => S (length l')
end.
and a function beq_term to compare two terms define as follow :
Fixpoint beq_term (t1:Term) (t2:Term) : bool :=
match t1, t2 with
| Var i, Var j => beq_nat i j
| Var _, Comb _ _ => false
|Comb _ _, Var _ => false
|(Comb s1 ts1), Comb s2 ts2 => if(beq_nat (length ts1) (length ts2))
then beq_list ts1 ts2 beq_term
else false
end.
The definition of the function beq_term yields the error message:
Error: Cannot guess decreasing argument of fix.
So I am interested in how to convince Coq of the termination.

If you want to be able to use Coq's syntactic check in this simple example in particular, it is enough to write beq_list and beq_term into a single function.
Fixpoint beq_list (l l' :list Term) : bool :=
match l, l' with
| [], [] => true
| (Var i)::xs, (Var j)::ys => beq_nat i j && beq_list xs ys
| (Comb s1 ts1)::xs, (Comb s2 ts2)::ys => beq_list xs ys
| _,_ => false
end.

Related

Lemma related to the counting of numbers in list

I want to solve a lemma which relate two lists after removing a number from the list with the help of following functions. Here is code
Theorem remove_decr_count: forall (l : list nat),
leb (count 0 (remove_one 0 s)) (count 0 s) = true.
Used functions are
Fixpoint remove_one (v:nat) (l:list nat) : list nat:=
match l with
| [] => []
| h :: t => if beq_nat v h then t else h :: remove_one v t
end.
Fixpoint leb (n m:nat) : bool :=
match n, m with
| O, _ => true
| S _, O => false
| S n', S m' => leb n' m'
end.
Fixpoint count (v:nat) (l:list nat) : nat :=
match l with
| [] => 0
| h :: t => (if beq_nat h v then 1 else 0) + (count v t)
end.
One way to proceed is by induction on the list l (warning: you used s in the theorem's definition, though), and then by case, on whether the head of the list is 0 or not. Rewrites are used to guide the proof.
Using the SSReflect tactics language, the proof could proceed like this (I replaced beq_nat by ==, and added the leb1 lemma, which is also proved by induction, here on n).
From Coq Require Import Init.Prelude Unicode.Utf8.
From mathcomp Require Import all_ssreflect.
Fixpoint remove_one (v:nat) (l:list nat) : list nat:=
match l with
| nil => nil
| cons h t => if v == h then t else cons h (remove_one v t)
end.
Fixpoint count (v:nat) (l:list nat) : nat :=
match l with
| nil => 0
| cons h t => (if h == v then 1 else 0) + (count v t)
end.
Fixpoint leb (n m:nat) : bool :=
match n, m with
| O, _ => true
| S _, O => false
| S n', S m' => leb n' m'
end.
Lemma leb1 (n : nat) : leb n (S n).
Proof. by elim: n. Qed.
Theorem remove_decr_count: forall (l : list nat),
leb (count 0 (remove_one 0 l)) (count 0 l).
Proof.
elim=> [|h t IH] //=.
- have [] := boolP (h == 0) => eqh0.
by rewrite eq_sym eqh0 leb1.
- by rewrite eq_sym ifN //= ifN.
Qed.

How to simplify lemma

I have problem in solving the lemma list_value.
Destruct command gives complicated situation. How I
can proceed? Any sub_lemma could be
helpful? Function G_value is zero only, when list is empty.
Therefore I have put constraint that list cannot be nil.
current_value function confirms that, all elemnts in
list nat are less or equal to the greatest value determine by G_value.
Definition change_h (n: nat) (l: list nat) : list nat:=
match l with
| nil => l
| h::tl => if n <=? h then l else n::tl
end.
Fixpoint G_value (n: nat) (l: list nat) {struct n}: nat :=
match l with
| nil => 0
| cons s nil => s
| cons h l => match n with
| O => h
| S n' => G_value n' (change_h h l)
end
end.
Theorem list_value :forall(n n0:nat) ( l:list nat),
(length l=?0)=false ->
(length l - length l =? 0)=true ->
(current_value 0 0 (n :: l) <=? n) = true.
Proof.
intros. unfold current_value.
simpl in *.
1 subgoal
n, n0 : nat
l : list nat
H : (length l =? 0) = false
H0 : (length l - length l =? 0) = true
______________________________________(1/1)
( (if
match l with
| [ ] => n
| _ :: _ => G_value (length l) (change_h n l)
end =? 0
then 0
else
match l with
| [ ] => n
| _ :: _ => G_value (length l) (change_h n l)
end) <=? n) = true

Searching a list by List.filter

In my program, I use List.filter to search a list for finding specific elements. I am proving if List.filter finds some elements in a list, then by appenindg another list we still get those elements that were in the first list before appending. I am a bit stuck in provingfilterKeepSameElementsAfterAppending. To make my program shorter, I changed my program's data to customType and mydata.
Require Import List Nat.
Inductive customType : Type :=
|Const1: nat -> customType
|Const2: list nat -> customType.
Inductive mydata : Set :=
|Set1: customType * customType ->mydata
|Set2: customType ->mydata.
Fixpoint custome_Equal (c1 c2:customType) :bool:=
match c1 with
|Const1 nt => match c2 with
|Const1 mt => eqb nt mt
|Const2 (hm::lmt) => eqb nt hm
| _ => false
end
|Const2 (hn::lnt) => match c2 with
|Const1 mt => eqb hn mt
|Const2 (hm:: lmt) => eqb hn hm
| _ => false
end
| _ => false
end.
Fixpoint Search (l: mydata) (t:customType): bool :=
match l with
|Set1 (a1, a2) => if (custome_Equal a2 t) then true else false
| _=>false
end.
Lemma filterKeepSameElementsAfterAppending(l1 l2: list mydata)(x:mydata)(ta:customType):
In x (filter (fun n => Search n ta) (l1)) -> In x (filter (fun n => Search n ta) (l2++ l1)).
Proof.
intro.
The filter_cat lemma should provide you some inspiration:
filter_cat
forall (T : Type) (a : pred T) (s1 s2 : seq T),
[seq x <- s1 ++ s2 | a x] = [seq x <- s1 | a x] ++ [seq x <- s2 | a x]
together with mem_cat should do what you want:
mem_cat
forall (T : eqType) (x : T) (s1 s2 : seq T),
(x \in s1 ++ s2) = (x \in s1) || (x \in s2)
Complete code:
From mathcomp Require Import all_ssreflect.
Lemma mem_filter_cat (T : eqType) p (l1 l2 : seq T) x :
x \in filter p l1 -> x \in filter p (l1 ++ l2).
Proof. by rewrite filter_cat mem_cat => ->. Qed.

Intersection of lists using List.filter

Following my question here, I'm proving if the intersection of two lists is not empty then by adding another list to each of the lists, still the intersection will be not empty. I wonder how I should prove the lemma filterKeepIntersection. I try to solve it by filter_cat tactic from seq library but it seems it is not enough to prove this lemma.
Require Import List Nat.
Inductive customType : Type :=
|Const1: nat -> customType
|Const2: list nat -> customType.
Inductive mydata : Set :=
|Set1: customType * customType ->mydata
|Set2: customType ->mydata.
Fixpoint custome_Equal (c1 c2:customType) :bool:=
match c1 with
|Const1 nt => match c2 with
|Const1 mt => eqb nt mt
|Const2 (hm::lmt) => eqb nt hm
| _ => false
end
|Const2 (hn::lnt) => match c2 with
|Const1 mt => eqb hn mt
|Const2 (hm:: lmt) => eqb hn hm
| _ => false
end
| _ => false
end.
Fixpoint Search (l: mydata) (t:customType): bool :=
match l with
|Set1 (a1, a2) => if (custome_Equal a2 t) then true else false
| _=>false
end.
Fixpoint search2 (c1 c2:mydata) :bool:=
match c1,c2 with
|Set1 (a1, a2) ,Set1(a3,a4)=> if (custome_Equal a2 a4) then true else false
| _,_=>false
end.
Lemma filterKeepIntersection(l1 l2 l3 l4: list mydata):
(List.filter (fun n => List.existsb (search2 n) l2) l1) <> nil->
(List.filter (fun n => List.existsb (search2 n) (l3++l2)) (l4++l1))<>nil.
Proof.
A slight reformulation of your internal predicate in terms of predI plus the use of filter_predI does make the proof immediate, but can just use mem_filter directly.

Proving a property of Subset relation on list of pairs

I'm proving a simple mathematical property about subsets, for example : A subset B; which is about the fact that adding a member to set B cannot affect this relation. In the program, A and B are list of pairs. entity_IN_listPair checks if a specific pair is in a list of pair and listPairEqual checks equality of two list of pairs. I am a bit stuck how to proceed in the proof of lemma Lemma addtolistPairSUB:
Require Import List.
Require Import Bool.
Definition entity := nat.
Definition entityID := nat.
Definition listPair : Set :=
list (entity * entityID).
(* Nat equality *)
Fixpoint Entity_eq (X:_) (a b:_) : bool :=
match a with
| O => match b with
| O => true
| S m' => false
end
| S n' => match b with
| O => false
| S m' => ( Entity_eq nat (n')( m'))
end
end.
(* checking if an entity is in an listPair *)
Fixpoint entity_IN_listPair
(entit: entity ) (lispair: listPair) : bool :=
match lispair with
|first::body => match first with
|(p_one,ptwo)=> (Entity_eq (nat)(entit)(p_one ))
|| entity_IN_listPair entit body
end
|nil => false
end.
(* checking the equality of two listPair *)
Fixpoint listPairSUB
(first second: listPair) : bool :=
match first with
|head::tail => match head with
|(part1,part2)=> if (entity_IN_listPair part1 second)
then listPairSUB tail second
else false
end
|nil => true
end.
Definition listPairEqual (firstL secondL:listPair) :=
(listPairSUB firstL secondL) && (listPairSUB secondL firstL).
Lemma addtolistPairSUB:
forall (a b: listPair ) (c:entity * entityID),
listPairSUB a b = true->listPairSUB (a) (c::b) = true .
Proof.
induction a.
Here it is. (I took the liberty of refactoring your code a little bit.)
Require Import List.
Require Import Bool.
Definition entity := nat.
Definition entityID := nat.
Definition listPair : Set :=
list (entity * entityID).
Fixpoint in_listpair e (l : listPair) :=
match l with
| nil => false
| (x, y) :: l' => Nat.eqb e x || in_listpair e l'
end.
Fixpoint subset_listpair (l1 l2 : listPair) :=
match l1 with
| nil => true
| (x1, _) :: l1 => in_listpair x1 l2 && subset_listpair l1 l2
end.
Lemma subset_listpair_cons l1 l2 p :
subset_listpair l1 l2 = true ->
subset_listpair l1 (p :: l2) = true.
Proof.
induction l1 as [|[x1 y1] l1 IH]; simpl; trivial.
destruct p as [x2 y2]; simpl.
destruct (in_listpair x1 l2); simpl; try easy.
intros H; rewrite IH; trivial.
now rewrite orb_true_r.
Qed.