-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathssrnat_solution.v
More file actions
308 lines (271 loc) · 9.52 KB
/
ssrnat_solution.v
File metadata and controls
308 lines (271 loc) · 9.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
Require Import magic.
From Corelib Require Import ssreflect.
(** 1. Tutorial *)
(* The aim of a proof assistant is to help the user prove mathematical theorems,
which we call "Goals". In this tutorial we will only prove statements about
natural numbers, some of which have known values (such as [3] below), and
others which have unknown, arbitrary values (such as [n] below).
*)
Goal forall n : nat, n + 3 = n + 3.
Proof.
(* The goal here is the theorem [forall n : nat, n + 3 = n + 3].
We solve goals in Rocq with SSReflect using tactics and tacticals, which are
instructions we give to the proof assistant. Rocq executes these instructions
to make progress in the proof. We end every tactic with a dot [.] to let Rocq
know that we are done writing the tactic.
We will first introduce an arbitrary number [n] and prove [n + 3 = n + 3] on
this number. To introduce objects, we use the tactical [=>], which can be put
after any tactic. Since we only want to introduce objects, we will use a base
tactic [move] which does essentially nothing.
Try [move=> n.].
*)
move=> n.
(* The goal is now [n + 3 = n + 3], where [n] is the natural number we just
introduced.
In this case, [n + 3 = n + 3] can be proved using the reflexivity of
equality, using the tactic [reflexivity].
*)
reflexivity.
Qed.
Goal forall n m : nat, n = 3 * m -> n + 1 = 3 * m + 1.
Proof.
(* Now, the goal is [forall n m : nat, n = 3 * m -> n + 1 = 3 * m + 1].
We will introduce two natural numbers [n] and [m], assume that [n = 3 * m]
and prove that [n + 1 = 3 * m + 1]. The tactical [=>] can be used to
introduce hypotheses, as in [move=> n m nE.].
*)
move=> n m nE.
(* You can check that [n], [m] and [nE] appeared in the list of known objects
and hypotheses.
Thanks to the hypothesis [nE], we know that [n] and [3 * m] are two
expressions designating the same natural number, so we can replace one by the
other in the goal using the [rewrite] tactic.
Write [rewrite nE.] and see what happens.
*)
rewrite nE.
(* Can you conclude the proof? *)
reflexivity.
Qed.
Goal forall n m : nat, n = 3 * m -> n + 1 = 3 * m + 1.
Proof.
move=> n m nE.
(* We can also rewrite equalities backwards, in other words replacing the
right-hand side by the left-hand side in the goal, by adding a minus [-]
sign before the equation to rewrite. Try [rewrite -nE.] and see what
happens. Then conclude the proof as before.
*)
rewrite -nE.
reflexivity.
Qed.
Goal forall n m : nat, n = 2 * m -> m = 6 -> (n - 5) * m = 42.
Proof.
move=> n m nE mE.
(* [rewrite] actually accepts any number of arguments, which are all equalities
that get rewritten one after the other. Try [rewrite nE mE.].
*)
rewrite nE mE.
reflexivity.
Qed.
(** Addition *)
(* Natural numbers are defined by two rules:
- [0] is a natural number, and
- if [n] is a natural number, then its successor [S n] is a natural number.
Not that the natural numbers we have encountered so far are all built using
these two rules. For example, [3] is merely a notation for [S (S (S 0))].
Similarly, the addition is defined by two rules:
- [0 + n = n] for any [n], and
- [S n + m = S (n + m)] for any [n], [m].
We will use the names [add0n] and [addSn] to refer to these rules.
*)
(* We will now start giving names to theorems, so that we may reuse them to make
subsequent proofs easier. When libraries of formalized mathematics become
large, it is hard to remember the name of every theorem. Instead, we can use
the [Search] command, that takes as argument a list of strings and patterns
and prints every theorem whose name matches the given strings and
statement matches the given patterns. A pattern can be any expression with
holes (symbolised with underscores [_]). Give it a try!
*)
Search (_ + _).
Goal forall n m, (0 + n) + (0 + m) = (0 + n) + m.
Proof.
move=> n m.
(* To solve this goal, we would like to rewrite [0 + m] into [m]. However, if we
were to simply write [rewrite add0n], Rocq would replace [0 + n] with [n] (
try it).
So we need to be more precise. [add0n] is a proof of the statement
[forall n, 0 + n = n], and we can write instantiate the variable [n], as in
[add0n m], to get a proof of [0 + m = m]. Since [rewrite] accepts several
arguments, we have to put parentheses around [add0n m], as in
[rewrite (add0n m).], lest [rewrite] interprets the command as rewriting
[add0n] and then [m], which does not make sense.
*)
rewrite (add0n m).
reflexivity.
Qed.
Theorem addn0 n : n + 0 = n.
Proof.
(* Our first theorem is the counterpart of [add0n]. Where [add0n] simplifies
additions by [0] on the left, we prove that we can also simplify on
the right.
Like most of the proof we will do today involving natural numbers, we
reason by induction on [n] using the tactic [elim]. However, [elim] expects
the goal to be of the form [forall n, ...] and does an induction on this [n].
To "revert" the [n] from the context back in the goal, we use the
tactical [:], which can be put after any tactic, and reverts objects before
applying the tactic.
Try [move: n.] and then [elim.].
*)
move: n.
elim.
(* [elim.] leaves two subgoals. The first one is the base case [n = 0],
that is [0 + 0 = 0]. Give it a try, and keep reading when the base case is
proved.
Hint 1: use [add0n].
Hint 2: [rewrite add0n.]
*)
rewrite add0n.
reflexivity.
(* Next, we have the induction case. [elim.] introduces an induction
hypothesis [IHn] stating our goal for [n], that is [n + 0 = n], and we have
to prove the goal for [S n], that is [S n + 0 = S n].
Hint: use [addSn].
*)
move=> n IHn.
rewrite addSn IHn.
reflexivity.
Qed.
Theorem addnS n m : n + S m = S (n + m).
Proof.
(* Let us also do the counterpart of [addSn], where we simplify additions with
a successor on the right.
Can you start the induction proof with just one tactic?
*)
elim: n.
rewrite add0n add0n.
reflexivity.
move=> n IHn.
rewrite addSn addSn IHn.
reflexivity.
Qed.
(* Well done! We are now ready to start looking at the interesting properties
of natural number additions. Let us prove that addition is commutative.
*)
Theorem addC n m : n + m = m + n.
Proof.
elim: n.
rewrite add0n addn0.
reflexivity.
move=> n IHn.
rewrite addSn addnS IHn.
reflexivity.
Qed.
(* On to associativity! When we write an expression like [n + m + k], it is
interpreted by Rocq as [(n + m) + k]. But that is just a convention, and it
is equal to the other reasonable interpretation [n + (m + k)].
*)
Theorem addA n m k : n + (m + k) = n + m + k.
Proof.
(* Just to be sure, do not hesitate to try [reflexivity] and see that it fails.
*)
elim: n.
rewrite add0n add0n.
reflexivity.
move=> n IHn.
rewrite addSn addSn addSn IHn.
reflexivity.
Qed.
(* Before moving on to multiplications, let us put our last two theorems to use.
*)
Theorem addCA n m k : n + m + k = n + k + m.
Proof.
(* Hint: Recall the [-] syntax for rewriting an equality from right to
left. You will also need to make some statements more precise in a rewrite,
so that Rocq finds the correct term you want to rewrite, as in [add0n m]
above.
*)
rewrite -addA (addC m) addA.
reflexivity.
Qed.
(** Multiplication *)
(* Just like the addition, the multiplication is defined with two rules, looking
at the left argument:
- [0 * n = 0] for any [n], and
- [S n * m = m + n * m] for any [n], [m].
We will use the names [add0n] and [addSn] to refer to these rules.
*)
(* Let us start with an example combining the rules defining the multiplication
to warm up.
*)
Theorem mul1n n : 1 * n = n.
Proof.
(* Hint: no induction here, we can simplify multiplications depending on what
the left argument looks like. Here, we know exactly the left argument, so we
can simplify, getting rid of the multiplication completely.
*)
rewrite mulSn mul0n addn0.
reflexivity.
Qed.
(* Before proving the usual results on multiplication, we first do the
simplification rules on the right argument.
*)
Theorem muln0 n : n * 0 = 0.
Proof.
elim: n.
rewrite mul0n.
reflexivity.
move=> n IHn.
rewrite mulSn add0n IHn.
reflexivity.
Qed.
Theorem mulnS n m : n * S m = n * m + n.
Proof.
elim: n.
rewrite mul0n mul0n add0n.
reflexivity.
move=> n IHn.
rewrite mulSn mulSn addSn addnS IHn addA.
reflexivity.
Qed.
(* Just like addition, multiplication is commutative and associative. *)
Theorem mulC n m : n * m = m * n.
Proof.
elim: n.
rewrite mul0n muln0.
reflexivity.
move=> n IHn.
rewrite mulSn mulnS addC IHn.
reflexivity.
Qed.
(* If we were to try to prove the associativity of multiplication now, we would
quickly get stuck. Indeed, when one argument of a multiplication is a
successor, our simplification lemmas turn that multiplication into an
addition. However, when that multiplication was an argument of another
multiplication, we would end up with a multiplication, of which one of the
arguments is an addition, which we do not know how to deal with yet.
What we need is the distributivity of multiplication over addition.
*)
Theorem mulDn n m k : (n + m) * k = n * k + m * k.
Proof.
elim: n.
rewrite add0n mul0n add0n.
reflexivity.
move=> n IHn.
rewrite addSn mulSn mulSn IHn addA.
reflexivity.
Qed.
Theorem mulnD n m k : n * (m + k) = n * m + n * k.
Proof.
(* How would you prove this? Can you do it with just 2 tactics? *)
rewrite mulC mulDn mulC (mulC k).
reflexivity.
Qed.
(* An expression such as [n * m * k] is interpreted as [(n * m) * k]. *)
Theorem mulA n m k : n * (m * k) = n * m * k.
Proof.
elim: n.
rewrite mul0n mul0n.
reflexivity.
move=> n IHn.
rewrite mulSn mulSn mulDn IHn.
reflexivity.
Qed.