How to make algebraic manipulations in Coq easier?How to end this Proof in CoqProving a theorem in Coq using almost only rewrites - no “cleverness”Defining interval function in CoqProof by case analysis in CoqCannot rewrite subterm in CoqNot equal succesors in CoqProof automation in Coq how to factorize a proofCoq modular arithmeticProving a contradiction in CoqProving (~A -> ~B)-> (~A -> B) -> A in Coq
Could Boris Johnson face criminal charges for illegally proroguing Parliament?
What is the difference between increasing volume and increasing gain?
How to say "respectively" in German when listing (enumerating) things
Does publication of the phone call ruin the basis for impeachment?
Using RECURSIVE in Virtual Layer
Is "weekend warrior" derogatory?
Bothered by watching coworkers slacking off
Did Joe Biden "stop a prosecution" into his son in Ukraine? And did he brag about stopping the prosecution?
Is there a way to replace Smite with Sharpness on a weapon?
When Vesuvan Shapeshifter copies turn face up replacement effects, why do they work?
What's the correct way to determine turn order in this situation?
Re-entering the UK after overstaying in 2008
What does a textbook look like while you are writing it?
How do we know Nemesis is not a black hole (or neutron star)?
Writing about real people - not giving offence
Should I be an author on another PhD student's paper if I went to their meetings and gave advice?
Quote to show students don't have to fear making mistakes
Booting Ubuntu from USB drive on MSI motherboard -- EVERYTHING fails
Airport Security - advanced check, 4th amendment breach
Is there an in-universe explanation of how Frodo's arrival in Valinor was recorded in the Red Book?
Where does the image of a data connector as a sharp metal spike originate from?
Why not add cuspidal curves in the moduli space of stable curves?
Everyone Gets a Window Seat
How to "Start as close to the end as possible", and why to do so?
How to make algebraic manipulations in Coq easier?
How to end this Proof in CoqProving a theorem in Coq using almost only rewrites - no “cleverness”Defining interval function in CoqProof by case analysis in CoqCannot rewrite subterm in CoqNot equal succesors in CoqProof automation in Coq how to factorize a proofCoq modular arithmeticProving a contradiction in CoqProving (~A -> ~B)-> (~A -> B) -> A in Coq
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
I'm experimenting with Coq's standard libraries for integers and rationals. So far my proofs are very time-consuming and look terrible.
I guess I miss some important proof techniques. Such simple lemmas shouldn't be so long to prove. Any hints?
Here is an example:
Require Import ZArith.
Require Import QArith.
Open Scope Q_scope.
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof. intros. destruct H as [Hl Hr]. rewrite (Zle_Qle x y) in Hr.
rewrite <- (Qmult_le_l (inject_Z x) (inject_Z y) (/ inject_Z (Zpos z))) in Hr. simpl in Hr.
- rewrite Qmult_comm in Hr. rewrite Qmult_comm with (x := / inject_Z (Z.pos z)) in Hr.
unfold inject_Z in Hr. unfold Qinv in Hr. destruct (Qnum (Z.pos z # 1)) eqn:ZV.
+ simpl in ZV. discriminate.
+ simpl in Hr. simpl in ZV. injection ZV. intro ZP. unfold Qmult in Hr. simpl in Hr.
rewrite <- ZP in Hr. rewrite Z.mul_1_r in Hr. rewrite Z.mul_1_r in Hr. exact Hr.
+ simpl in ZV. discriminate.
- unfold Qinv. simpl. apply Z.lt_0_1.
Qed.
coq proof rational-number
add a comment
|
I'm experimenting with Coq's standard libraries for integers and rationals. So far my proofs are very time-consuming and look terrible.
I guess I miss some important proof techniques. Such simple lemmas shouldn't be so long to prove. Any hints?
Here is an example:
Require Import ZArith.
Require Import QArith.
Open Scope Q_scope.
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof. intros. destruct H as [Hl Hr]. rewrite (Zle_Qle x y) in Hr.
rewrite <- (Qmult_le_l (inject_Z x) (inject_Z y) (/ inject_Z (Zpos z))) in Hr. simpl in Hr.
- rewrite Qmult_comm in Hr. rewrite Qmult_comm with (x := / inject_Z (Z.pos z)) in Hr.
unfold inject_Z in Hr. unfold Qinv in Hr. destruct (Qnum (Z.pos z # 1)) eqn:ZV.
+ simpl in ZV. discriminate.
+ simpl in Hr. simpl in ZV. injection ZV. intro ZP. unfold Qmult in Hr. simpl in Hr.
rewrite <- ZP in Hr. rewrite Z.mul_1_r in Hr. rewrite Z.mul_1_r in Hr. exact Hr.
+ simpl in ZV. discriminate.
- unfold Qinv. simpl. apply Z.lt_0_1.
Qed.
coq proof rational-number
add a comment
|
I'm experimenting with Coq's standard libraries for integers and rationals. So far my proofs are very time-consuming and look terrible.
I guess I miss some important proof techniques. Such simple lemmas shouldn't be so long to prove. Any hints?
Here is an example:
Require Import ZArith.
Require Import QArith.
Open Scope Q_scope.
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof. intros. destruct H as [Hl Hr]. rewrite (Zle_Qle x y) in Hr.
rewrite <- (Qmult_le_l (inject_Z x) (inject_Z y) (/ inject_Z (Zpos z))) in Hr. simpl in Hr.
- rewrite Qmult_comm in Hr. rewrite Qmult_comm with (x := / inject_Z (Z.pos z)) in Hr.
unfold inject_Z in Hr. unfold Qinv in Hr. destruct (Qnum (Z.pos z # 1)) eqn:ZV.
+ simpl in ZV. discriminate.
+ simpl in Hr. simpl in ZV. injection ZV. intro ZP. unfold Qmult in Hr. simpl in Hr.
rewrite <- ZP in Hr. rewrite Z.mul_1_r in Hr. rewrite Z.mul_1_r in Hr. exact Hr.
+ simpl in ZV. discriminate.
- unfold Qinv. simpl. apply Z.lt_0_1.
Qed.
coq proof rational-number
I'm experimenting with Coq's standard libraries for integers and rationals. So far my proofs are very time-consuming and look terrible.
I guess I miss some important proof techniques. Such simple lemmas shouldn't be so long to prove. Any hints?
Here is an example:
Require Import ZArith.
Require Import QArith.
Open Scope Q_scope.
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof. intros. destruct H as [Hl Hr]. rewrite (Zle_Qle x y) in Hr.
rewrite <- (Qmult_le_l (inject_Z x) (inject_Z y) (/ inject_Z (Zpos z))) in Hr. simpl in Hr.
- rewrite Qmult_comm in Hr. rewrite Qmult_comm with (x := / inject_Z (Z.pos z)) in Hr.
unfold inject_Z in Hr. unfold Qinv in Hr. destruct (Qnum (Z.pos z # 1)) eqn:ZV.
+ simpl in ZV. discriminate.
+ simpl in Hr. simpl in ZV. injection ZV. intro ZP. unfold Qmult in Hr. simpl in Hr.
rewrite <- ZP in Hr. rewrite Z.mul_1_r in Hr. rewrite Z.mul_1_r in Hr. exact Hr.
+ simpl in ZV. discriminate.
- unfold Qinv. simpl. apply Z.lt_0_1.
Qed.
coq proof rational-number
coq proof rational-number
asked Mar 28 at 21:18
Dmitry VyalDmitry Vyal
1,6681 gold badge20 silver badges20 bronze badges
1,6681 gold badge20 silver badges20 bronze badges
add a comment
|
add a comment
|
1 Answer
1
active
oldest
votes
I did not have the courage to analyze your lengthy proof, but I see you choose to use a forward proof style. The telltale sign is the fact that you have several rewrite ... in ...
in your script. Most libraries of theorems are designed to work in backward proof style.
Contrast this with my proposal for the same proof:
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof.
intros x y z cmp; rewrite !Qmake_Qdiv.
apply Qmult_le_compat_r.
rewrite <- Zle_Qle; tauto.
apply Qinv_le_0_compat; replace 0 with (inject_Z 0) by easy.
now rewrite <- Zle_Qle; apply Zle_0_pos.
Qed.
Here is how I proceed. First, x # z
is a notation for a very specific form of division: the one that appears in a basic fraction. There are many chances that this specific form of division is less well covered by theorems in the library, so I choose to replace it by a regular division between rational numbers. To find the theorem, I just use the Search
query with the patterns (_ # _) (_ / _)
. This gives me Qmake_Qdiv
.
Then I simply expect that there is a theorem expressing a <= b -> a / c <= b / c
under suitable conditions. I use Search (_ / _ <= _ / _).
to find such a theorem. Alas, none is found. So I remember that division is often described as multiplication by the inverse so I search for the other possibility Search (_ * _ <= _ * _).
This gives me Qmult_le_compat_r
. I try applying it and it works.
Here is what I mean by working in a backward proof style: I look at the conclusion and I think what theorem could help me obtain this conclusion? I will then try to fulfill its conditions.
There are two conditions. The first one is (inject_Z x <= inject_Z y)
. So now I need a theorem relating comparison in Z
and comparison in Q
through function inject_Z
. To find it I type Search inject_Z (_ <= _).
This gives me Qmult_le_compat_r
. Please note that your hypothesis is too strong: you don't need x
to be positive. The automatic tactic tauto
obtains the right condition from your hypothesis (which I named cmp
).
The last condition is (0 <= inject_Z (Z.pos z))
. I can re-use the same theorem as above, because surely 0
must be the same thing as inject_Z 0
.
All this being said, I do not recommend using QArith
for mathematical reasoning (the kind of algebraic reasoning that you show here), because it is less well populated than other libraries. If you want to work with numbers and reason on them, you should use math-comp
or Reals
: you will find more theorems that are already proved for you.
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were norewrite ... in ...
orapply ... in ...
tactics, so that the backward style was practically imposed on you.
– Yves
Mar 30 at 18:53
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55406985%2fhow-to-make-algebraic-manipulations-in-coq-easier%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I did not have the courage to analyze your lengthy proof, but I see you choose to use a forward proof style. The telltale sign is the fact that you have several rewrite ... in ...
in your script. Most libraries of theorems are designed to work in backward proof style.
Contrast this with my proposal for the same proof:
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof.
intros x y z cmp; rewrite !Qmake_Qdiv.
apply Qmult_le_compat_r.
rewrite <- Zle_Qle; tauto.
apply Qinv_le_0_compat; replace 0 with (inject_Z 0) by easy.
now rewrite <- Zle_Qle; apply Zle_0_pos.
Qed.
Here is how I proceed. First, x # z
is a notation for a very specific form of division: the one that appears in a basic fraction. There are many chances that this specific form of division is less well covered by theorems in the library, so I choose to replace it by a regular division between rational numbers. To find the theorem, I just use the Search
query with the patterns (_ # _) (_ / _)
. This gives me Qmake_Qdiv
.
Then I simply expect that there is a theorem expressing a <= b -> a / c <= b / c
under suitable conditions. I use Search (_ / _ <= _ / _).
to find such a theorem. Alas, none is found. So I remember that division is often described as multiplication by the inverse so I search for the other possibility Search (_ * _ <= _ * _).
This gives me Qmult_le_compat_r
. I try applying it and it works.
Here is what I mean by working in a backward proof style: I look at the conclusion and I think what theorem could help me obtain this conclusion? I will then try to fulfill its conditions.
There are two conditions. The first one is (inject_Z x <= inject_Z y)
. So now I need a theorem relating comparison in Z
and comparison in Q
through function inject_Z
. To find it I type Search inject_Z (_ <= _).
This gives me Qmult_le_compat_r
. Please note that your hypothesis is too strong: you don't need x
to be positive. The automatic tactic tauto
obtains the right condition from your hypothesis (which I named cmp
).
The last condition is (0 <= inject_Z (Z.pos z))
. I can re-use the same theorem as above, because surely 0
must be the same thing as inject_Z 0
.
All this being said, I do not recommend using QArith
for mathematical reasoning (the kind of algebraic reasoning that you show here), because it is less well populated than other libraries. If you want to work with numbers and reason on them, you should use math-comp
or Reals
: you will find more theorems that are already proved for you.
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were norewrite ... in ...
orapply ... in ...
tactics, so that the backward style was practically imposed on you.
– Yves
Mar 30 at 18:53
add a comment
|
I did not have the courage to analyze your lengthy proof, but I see you choose to use a forward proof style. The telltale sign is the fact that you have several rewrite ... in ...
in your script. Most libraries of theorems are designed to work in backward proof style.
Contrast this with my proposal for the same proof:
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof.
intros x y z cmp; rewrite !Qmake_Qdiv.
apply Qmult_le_compat_r.
rewrite <- Zle_Qle; tauto.
apply Qinv_le_0_compat; replace 0 with (inject_Z 0) by easy.
now rewrite <- Zle_Qle; apply Zle_0_pos.
Qed.
Here is how I proceed. First, x # z
is a notation for a very specific form of division: the one that appears in a basic fraction. There are many chances that this specific form of division is less well covered by theorems in the library, so I choose to replace it by a regular division between rational numbers. To find the theorem, I just use the Search
query with the patterns (_ # _) (_ / _)
. This gives me Qmake_Qdiv
.
Then I simply expect that there is a theorem expressing a <= b -> a / c <= b / c
under suitable conditions. I use Search (_ / _ <= _ / _).
to find such a theorem. Alas, none is found. So I remember that division is often described as multiplication by the inverse so I search for the other possibility Search (_ * _ <= _ * _).
This gives me Qmult_le_compat_r
. I try applying it and it works.
Here is what I mean by working in a backward proof style: I look at the conclusion and I think what theorem could help me obtain this conclusion? I will then try to fulfill its conditions.
There are two conditions. The first one is (inject_Z x <= inject_Z y)
. So now I need a theorem relating comparison in Z
and comparison in Q
through function inject_Z
. To find it I type Search inject_Z (_ <= _).
This gives me Qmult_le_compat_r
. Please note that your hypothesis is too strong: you don't need x
to be positive. The automatic tactic tauto
obtains the right condition from your hypothesis (which I named cmp
).
The last condition is (0 <= inject_Z (Z.pos z))
. I can re-use the same theorem as above, because surely 0
must be the same thing as inject_Z 0
.
All this being said, I do not recommend using QArith
for mathematical reasoning (the kind of algebraic reasoning that you show here), because it is less well populated than other libraries. If you want to work with numbers and reason on them, you should use math-comp
or Reals
: you will find more theorems that are already proved for you.
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were norewrite ... in ...
orapply ... in ...
tactics, so that the backward style was practically imposed on you.
– Yves
Mar 30 at 18:53
add a comment
|
I did not have the courage to analyze your lengthy proof, but I see you choose to use a forward proof style. The telltale sign is the fact that you have several rewrite ... in ...
in your script. Most libraries of theorems are designed to work in backward proof style.
Contrast this with my proposal for the same proof:
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof.
intros x y z cmp; rewrite !Qmake_Qdiv.
apply Qmult_le_compat_r.
rewrite <- Zle_Qle; tauto.
apply Qinv_le_0_compat; replace 0 with (inject_Z 0) by easy.
now rewrite <- Zle_Qle; apply Zle_0_pos.
Qed.
Here is how I proceed. First, x # z
is a notation for a very specific form of division: the one that appears in a basic fraction. There are many chances that this specific form of division is less well covered by theorems in the library, so I choose to replace it by a regular division between rational numbers. To find the theorem, I just use the Search
query with the patterns (_ # _) (_ / _)
. This gives me Qmake_Qdiv
.
Then I simply expect that there is a theorem expressing a <= b -> a / c <= b / c
under suitable conditions. I use Search (_ / _ <= _ / _).
to find such a theorem. Alas, none is found. So I remember that division is often described as multiplication by the inverse so I search for the other possibility Search (_ * _ <= _ * _).
This gives me Qmult_le_compat_r
. I try applying it and it works.
Here is what I mean by working in a backward proof style: I look at the conclusion and I think what theorem could help me obtain this conclusion? I will then try to fulfill its conditions.
There are two conditions. The first one is (inject_Z x <= inject_Z y)
. So now I need a theorem relating comparison in Z
and comparison in Q
through function inject_Z
. To find it I type Search inject_Z (_ <= _).
This gives me Qmult_le_compat_r
. Please note that your hypothesis is too strong: you don't need x
to be positive. The automatic tactic tauto
obtains the right condition from your hypothesis (which I named cmp
).
The last condition is (0 <= inject_Z (Z.pos z))
. I can re-use the same theorem as above, because surely 0
must be the same thing as inject_Z 0
.
All this being said, I do not recommend using QArith
for mathematical reasoning (the kind of algebraic reasoning that you show here), because it is less well populated than other libraries. If you want to work with numbers and reason on them, you should use math-comp
or Reals
: you will find more theorems that are already proved for you.
I did not have the courage to analyze your lengthy proof, but I see you choose to use a forward proof style. The telltale sign is the fact that you have several rewrite ... in ...
in your script. Most libraries of theorems are designed to work in backward proof style.
Contrast this with my proposal for the same proof:
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof.
intros x y z cmp; rewrite !Qmake_Qdiv.
apply Qmult_le_compat_r.
rewrite <- Zle_Qle; tauto.
apply Qinv_le_0_compat; replace 0 with (inject_Z 0) by easy.
now rewrite <- Zle_Qle; apply Zle_0_pos.
Qed.
Here is how I proceed. First, x # z
is a notation for a very specific form of division: the one that appears in a basic fraction. There are many chances that this specific form of division is less well covered by theorems in the library, so I choose to replace it by a regular division between rational numbers. To find the theorem, I just use the Search
query with the patterns (_ # _) (_ / _)
. This gives me Qmake_Qdiv
.
Then I simply expect that there is a theorem expressing a <= b -> a / c <= b / c
under suitable conditions. I use Search (_ / _ <= _ / _).
to find such a theorem. Alas, none is found. So I remember that division is often described as multiplication by the inverse so I search for the other possibility Search (_ * _ <= _ * _).
This gives me Qmult_le_compat_r
. I try applying it and it works.
Here is what I mean by working in a backward proof style: I look at the conclusion and I think what theorem could help me obtain this conclusion? I will then try to fulfill its conditions.
There are two conditions. The first one is (inject_Z x <= inject_Z y)
. So now I need a theorem relating comparison in Z
and comparison in Q
through function inject_Z
. To find it I type Search inject_Z (_ <= _).
This gives me Qmult_le_compat_r
. Please note that your hypothesis is too strong: you don't need x
to be positive. The automatic tactic tauto
obtains the right condition from your hypothesis (which I named cmp
).
The last condition is (0 <= inject_Z (Z.pos z))
. I can re-use the same theorem as above, because surely 0
must be the same thing as inject_Z 0
.
All this being said, I do not recommend using QArith
for mathematical reasoning (the kind of algebraic reasoning that you show here), because it is less well populated than other libraries. If you want to work with numbers and reason on them, you should use math-comp
or Reals
: you will find more theorems that are already proved for you.
edited Mar 29 at 16:20
answered Mar 29 at 16:01
YvesYves
2,2287 silver badges11 bronze badges
2,2287 silver badges11 bronze badges
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were norewrite ... in ...
orapply ... in ...
tactics, so that the backward style was practically imposed on you.
– Yves
Mar 30 at 18:53
add a comment
|
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were norewrite ... in ...
orapply ... in ...
tactics, so that the backward style was practically imposed on you.
– Yves
Mar 30 at 18:53
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
thanks for the elaborate explanation. I repeated your steps. Makes sense! How did you acquire such a strategy? Is it just the experience?
– Dmitry Vyal
Mar 30 at 7:31
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were no
rewrite ... in ...
or apply ... in ...
tactics, so that the backward style was practically imposed on you.– Yves
Mar 30 at 18:53
I don't remember, I learned by trials and errors, too long ago (28 years). But I remember that in the beginning there were no
rewrite ... in ...
or apply ... in ...
tactics, so that the backward style was practically imposed on you.– Yves
Mar 30 at 18:53
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55406985%2fhow-to-make-algebraic-manipulations-in-coq-easier%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown