np-hard -closure - np-hard

if l1 is in NP-HARD, so for every L2!=empty set, l1*l2 is in np-hard.
when:
l1*l2={(w1,w2) , w1 in L1 and w2 in L2}
Is it true or false and why?
I can't approve it but I also don't find counter example.

L1 * L2 is NP-hard.
Proof: Let L be a language in NP, let f be a reduction of L to L1 and let w2 be in L2. Define g(x) = (f(x), w2). Now g is a polynomial time many-to-one reduction of L to L1*L2 because clearly:
x in L <==> (f(x), w(2)) in L1*L2

Related

How do I describe a multiplication of vectorized matrices?

I want to calculate a product of huge (specific) matrices. From a point complexity of view, the product should be taken the form of an elementwise expression.
I tried to "vectorize" the matrices with mxvec / vec_mx and calculate the product via one dimensional streams. But indices access was blocked by the term of enum ('I_p * 'I_q).
I want to know a nth value of enum ('I_p * 'I_q) because I want to decscribe a multiplication of matrices in the form of a primitive expression in an underlying field.
How do I do this? In particular, how do I prove this statement?
From mathcomp Require Import all_ssreflect.
Lemma nth_enum_prod p q (a : 'I_q) :
val a = index (ord0, a) (enum (prod_finType (ordinal_finType p.+1) (ordinal_finType q))).
I'm surprised you need to vectorize the matrices if your definition is point-wise, usually you should be able to define your result as \matrix_(i, j) op, for example the standard definition of matrix multiplication is:
\matrix_(i, k) \sum_j (A i j * B j k).
By the way, a quick "dirty" proof of your lemma is:
Lemma nth_enum_prod p q (a : 'I_q) : val a = index (#ord0 p, a) (enum predT).
Proof.
have /(_ _ 'I_q) pair_snd_inj: injective [eta pair ord0] by move => n T i j [].
have Hfst : (ord0, a) \in [seq (ord0, x2) | x2 <- enum 'I_q].
by move=> n; rewrite mem_map /= ?mem_enum.
rewrite enumT !unlock /= /prod_enum enum_ordS /= index_cat {}Hfst.
by rewrite index_map /= ?index_enum_ord.
Qed.
but indeed if you find yourself using this it means you are into a different kind of problem. I just posted it as an illustration on how to manipulate this kind of expressions.
edit: based on your comment, a more principled way to manipulate the above is to define a lemma about index and products; I've left the full proof as an exercise, but the outline is:
Lemma index_allpairs (T U : eqType) (x : T) (y : U) r s :
(* TODO: Some conditions are missing here *)
index (x,y) [seq (x,y) | x <- r , y <- s] =
size s * (index x r) + index y s.
Proof.
Admitted.
Lemma index_ord_allpairs p q (x : 'I_p) (y : 'I_q) :
index (x,y) [seq (x,y) | x <- enum 'I_p , y <- enum 'I_q] = q * x + y.
Proof. by rewrite index_allpairs ?mem_enum ?size_enum_ord ?index_enum_ord. Qed.
Lemma nth_enum_prod p q (a : 'I_q) : val a = index (#ord0 p, a) (enum predT).
Proof. by rewrite enumT unlock index_ord_allpairs muln0. Qed.

Contradictory hypothesis using coq inversion tactic

From this example:
Example foo : forall (X : Type) (x y z : X) (l j : list X),
x :: y :: l = z :: j ->
y :: l = x :: j ->
x = y.
It can be solved just doing inversion on the second hypothesis:
Proof.
intros X x y z l j eq1 eq2. inversion eq2. reflexivity. Qed.
However, doing inversion also in the first hypothesis, yields apparently contradictory hypothesis:
Proof.
intros X x y z l j eq1 eq2. inversion eq2. inversion eq1. reflexivity. Qed.
Because, in this last proof, the generated hypothesis are:
H0 : y = x
H1 : l = j
H2 : x = z
H3 : y :: l = j
But, if I'm not missing something obvious, it is impossible for both H1 and H3 to be true at the same time.
Can someone explain me what is going on? Is it just that the example is "bad designed" (both hypothesis are contradictory) and that Coq inversion tactic just swallows them? Is it a principle of explosion based on two hypothesis considered together? If so, is it then possible to prove the example just by deriving anything from falsehood? How?
Your example is assuming contradictory hypotheses: they imply that length l + 2 is equal to length l + 1.
Require Import Coq.Lists.List.
Require Import Omega.
Example foo : forall (X : Type) (x y z : X) (l j : list X),
x :: y :: l = z :: j ->
y :: l = x :: j ->
x = y.
Proof.
intros X x y z l j eq1 eq2.
apply (f_equal (#length _)) in eq1.
apply (f_equal (#length _)) in eq2.
simpl in *.
omega.
Qed.
By the principle of explosion, it is not surprising that Coq is able to derive a contradictory context.
Besides this small oddity, there is nothing wrong with the fact that the generated hypotheses are contradictory: such contexts can arise even if the original hypotheses are consistent. Consider the following (admittedly contrived) proof:
Goal forall b c : bool, b = c -> c = b.
Proof.
intros b c e.
destruct b, c.
- reflexivity.
- discriminate.
- discriminate.
- reflexivity.
Qed.
The second and third branches have contradictory hypotheses (true = false and false = true), even if the original hypothesis, b = c, is innocuous. This example is a bit different from the original one, because the contradiction was not obtained by combining hypotheses. Instead, when we call destruct, we promise Coq to prove the conclusion by considering a few subgoals obtained by case analyses. If some of the subgoals happen to be contradictory, even better: there won't be any work to do there.

How to add to both sides of an equality in Coq

This seems like a really simple question, but I wasn't able to find anything useful.
I have the statement
n - x = n
and would like to prove
(n - x) + x = n + x
I haven't been able to find what theorem allows for this.
You should have a look at the rewrite tactic (and then maybe reflexivity).
EDIT: more info about rewrite:
You can rewrite H rewrite -> H to rewrite from left to right
You can rewrite <- H to rewrite from right to left
You can use the pattern tactic to only select specific instances of the goal to rewrite. For example, to only rewrite the second n, you can perform the following steps
pattern n at 2.
rewrite <- H.
In your case, the solution is much simpler.
Building on #gallais' suggestion on using f_equal. We start in the following state:
n : nat
x : nat
H : n - x = n
============================
n - x + x = n + x
(1) First variant via "forward" reasoning (where one applies theorems to hypotheses) using the f_equal lemma.
Check f_equal.
f_equal
: forall (A B : Type) (f : A -> B) (x y : A), x = y -> f x = f y
It needs the function f, so
apply f_equal with (f := fun t => t + x) in H.
This will give you:
H : n - x + x = n + x
This can be solved via apply H. or exact H. or assumption. or auto. ... or some other way which suits you the most.
(2) Or you can use "backward" reasoning (where one applies theorems to the goal).
There is also the f_equal2 lemma:
Check f_equal2.
f_equal2
: forall (A1 A2 B : Type) (f : A1 -> A2 -> B)
(x1 y1 : A1) (x2 y2 : A2),
x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2
We just apply it to the goal, which results in two trivial subgoals.
apply f_equal2. assumption. reflexivity.
or just
apply f_equal2; trivial.
(3) There is also the more specialized lemma f_equal2_plus:
Check f_equal2_plus.
(*
f_equal2_plus
: forall x1 y1 x2 y2 : nat,
x1 = y1 -> x2 = y2 -> x1 + x2 = y1 + y2
*)
Using this lemma we are able to solve the goal with the following one-liner:
apply (f_equal2_plus _ _ _ _ H eq_refl).
There is a powerful search engine in Coq using patterns. You can try for example:
Search (_=_ -> _+_=_+_).

Handling let in hypothesis

As an exercise in Coq, I'm trying to prove that the following function returns a pair of lists of equal length.
Require Import List.
Fixpoint split (A B:Set)(x:list (A*B)) : (list A)*(list B) :=
match x with
|nil => (nil, nil)
|cons (a,b) x1 => let (ta, tb) := split A B x1 in (a::ta, b::tb)
end.
Theorem split_eq_len : forall (A B:Set)(x:list (A*B))(y:list A)(z:list B),(split A B x)=(y,z) -> length y = length z.
Proof.
intros A B x.
elim x.
simpl.
intros y z.
intros H.
injection H.
intros H1 H2.
rewrite <- H1.
rewrite <- H2.
reflexivity.
intros hx.
elim hx.
intros a b tx H y z.
simpl.
intro.
After the last step I get a hypothesis with a let statement inside, which I do not know how to handle:
1 subgoals
A : Set
B : Set
x : list (A * B)
hx : A * B
a : A
b : B
tx : list (A * B)
H : forall (y : list A) (z : list B),
split A B tx = (y, z) -> length y = length z
y : list A
z : list B
H0 : (let (ta, tb) := split A B tx in (a :: ta, b :: tb)) = (y, z)
______________________________________(1/1)
length y = length z
You want to do destruct (split A B tx). This will break it up, binding the two pieces to ta and tb

Proving that a reversible list is a palindrome in Coq

Here is my inductive definition of palindromes:
Inductive pal { X : Type } : list X -> Prop :=
| pal0 : pal []
| pal1 : forall ( x : X ), pal [x]
| pal2 : forall ( x : X ) ( l : list X ), pal l -> pal ( x :: l ++ [x] ).
And the theorem I want to prove, from Software Foundations:
Theorem rev_eq_pal : forall ( X : Type ) ( l : list X ),
l = rev l -> pal l.
My informal outlines of the proof are as follows:
Suppose l0 is an arbitrary list such that l0 = rev l0. Then one of the following three cases must hold. l0 has:
(a) zero elements, in which case it is a palindrome by definition.
(b) one element, in which case it is also a palindrome by definition.
(c) two elements or more, in which case l0 = x :: l1 ++ [x] for some element x and some list l1 such that l1 = rev l1.
Now, since l1 = rev l1, one of the following three cases must hold...
The recursive case analysis will terminate for any finite list l0 because the length of the list analyzed decreases by 2 through each iteration. If it terminates for any list ln, all of its outer lists up to l0 are also palindromes, since a list constructed by appending two identical elements at either end of a palindrome is also a palindrome.
I think the reasoning is sound, but I'm not sure how to formalize it. Can it be turned into a proof in Coq? Some explanations of how the tactics used work would be especially helpful.
This is a nice example where "direct" induction does not work well at all because you don't directly make the recursive call on the tail, but on part of the tail. In such cases, I usually advice to state your lemma with the length of the list, not on the list itself. You can then specialize it. That would be something like:
Lemma rev_eq_pal_length: forall (X: Type) (n: nat) (l: list X), length l <= n -> l = rev l -> pal l.
Proof.
(* by induction on [n], not [l] *)
Qed.
Theorem rev_eq_pal: forall (X: Type) (l: list X), l = rev l -> pal l.
Proof.
(* apply the previous lemma with n = length l *)
Qed.
I can help you in more detail if necessary, just leave a comment.
Good luck !
V.
EDIT: just to help you, I needed the following lemmas to make this proof, you might need them too.
Lemma tool : forall (X:Type) (l l': list X) (a b: X),
a :: l = l' ++ b :: nil -> (a = b /\ l = nil) \/ exists k, l = k ++ b :: nil.
Lemma tool2 : forall (X:Type) (l1 l2 : list X) (a b: X),
l1 ++ a :: nil = l2 ++ b :: nil -> a = b /\ l1 = l2.
You could also derive your induction principle from a form of well-founded induction.
Notation " [ ] " := nil : list_scope.
Notation " [ x1 ; .. ; x2 ] " := (cons x1 .. (cons x2 nil) ..) : list_scope.
Open Scope list_scope.
Conjecture C1 : forall t1 f1 p1, (forall x1, (forall x2, f1 x2 < f1 x1 -> p1 x2) -> p1 x1) -> forall x1 : t1, p1 x1.
Conjecture C2 : forall t1 p1, p1 [] -> (forall x1 l1, p1 ([x1] ++ l1)) -> forall l1 : list t1, p1 l1.
Conjecture C3 : forall t1 p1, p1 [] -> (forall x1 l1, p1 (l1 ++ [x1])) -> forall l1 : list t1, p1 l1.
Conjecture C4 : forall t1 (x1 x2 : t1) l1, length l1 < length ([x1] ++ l1 ++ [x2]).
Theorem T1 : forall t1 p1,
p1 [] ->
(forall x1, p1 [x1]) ->
(forall x1 x2 l1, p1 l1 -> p1 ([x1] ++ l1 ++ [x2])) ->
forall l1 : list t1, p1 l1.
Proof.
intros t1 p1 h1 h2 h3.
induction l1 as [l1 h4] using (C1 (list t1) (#length t1)).
induction l1 as [| x1 l1] using C2.
eapply h1.
induction l1 as [| x2 l1] using C3.
simpl.
eapply h2.
eapply h3.
eapply h4.
eapply C4.
Qed.
You can prove conjecture C1 by first applying the hypothesis to the conclusion, then using structural induction on f1 x1, and then using some facts about <.
To prove C3, which has no induction hypothesis, you first use case analysis on is_empty l1, and then use the facts is_empty l1 = true -> l1 = [] and is_empty l1 = false -> l1 = delete_last l1 ++ [get_last l1] (get_last will need a default value).