2 (** {1 Theory of integers}
4 This file provides the basic theory of integers, and several additional
5 theories for classical functions.
9 (** {2 Integers and the basic operators} *)
13 let constant zero : int = 0
14 let constant one : int = 1
16 val (=) (x y : int) : bool ensures { result <-> x = y }
18 val function (-_) int : int
19 val function (+) int int : int
20 val function (*) int int : int
21 val predicate (<) int int : bool
23 let function (-) (x y : int) = x + -y
24 let predicate (>) (x y : int) = y < x
25 let predicate (<=) (x y : int) = x < y || x = y
26 let predicate (>=) (x y : int) = y <= x
28 clone export algebra.OrderedUnitaryCommutativeRing with
29 type t = int, constant zero = zero, constant one = one,
30 function (-_) = (-_), function (+) = (+),
31 function (*) = (*), predicate (<=) = (<=)
33 meta "remove_unused:keep" function (+)
34 meta "remove_unused:keep" function (-)
35 (* do not necessarily keep, to allow for linear arithmetic only
36 meta "remove_unused:keep" function (*)
38 meta "remove_unused:keep" function (-_)
39 meta "remove_unused:keep" predicate (<)
40 meta "remove_unused:keep" predicate (<=)
41 meta "remove_unused:keep" predicate (>)
42 meta "remove_unused:keep" predicate (>=)
46 (** {2 Absolute Value} *)
52 let function abs (x:int) : int = if x >= 0 then x else -x
54 lemma Abs_le: forall x y:int. abs x <= y <-> -y <= x <= y
55 meta "remove_unused:dependency" lemma Abs_le, function abs
57 lemma Abs_pos: forall x:int. abs x >= 0
58 meta "remove_unused:dependency" lemma Abs_pos, function abs
61 lemma Abs_zero: forall x:int. abs x = 0 -> x = 0
66 (** {2 Minimum and Maximum} *)
72 clone export relations.MinMax with type t = int, predicate le = (<=), goal .
74 let min (x y : int) : int
75 ensures { result = min x y }
76 = if x <= y then x else y
78 let max (x y : int) : int
79 ensures { result = max x y }
80 = if x <= y then y else x
85 (** {2 The Basic Well-Founded Order on Integers} *)
91 predicate lt_nat (x y: int) = 0 <= y /\ x < y
93 clone export relations.Lex with type t1 = int, type t2 = int,
94 predicate rel1 = lt_nat, predicate rel2 = lt_nat
98 (** {2 Euclidean Division}
100 Division and modulo operators with the convention
101 that modulo is always non-negative.
103 It implies that division rounds down when divisor is positive, and
104 rounds up when divisor is negative.
108 module EuclideanDivision
113 function div (x y: int) : int
114 function mod (x y: int) : int
117 forall x y:int. y <> 0 -> x = y * div x y + mod x y
118 meta "remove_unused:dependency" axiom Div_mod, function div
119 meta "remove_unused:dependency" axiom Div_mod, function mod
122 forall x y:int. y <> 0 -> 0 <= mod x y < abs y
123 meta "remove_unused:dependency" axiom Mod_bound, function mod
126 forall x y q:int. y > 0 -> q * y <= x < q * y + y -> div x y = q
127 meta "remove_unused:dependency" lemma Div_unique, function div
130 forall x y:int. x >= 0 /\ y > 0 -> 0 <= div x y <= x
131 meta "remove_unused:dependency" lemma Div_bound, function div
133 lemma Mod_1: forall x:int. mod x 1 = 0
134 meta "remove_unused:dependency" lemma Mod_1, function mod
136 lemma Div_1: forall x:int. div x 1 = x
137 meta "remove_unused:dependency" lemma Div_1, function div
139 lemma Div_inf: forall x y:int. 0 <= x < y -> div x y = 0
140 meta "remove_unused:dependency" lemma Div_inf, function div
142 lemma Div_inf_neg: forall x y:int. 0 < x <= y -> div (-x) y = -1
143 meta "remove_unused:dependency" lemma Div_inf_neg, function div
145 lemma Mod_0: forall y:int. y <> 0 -> mod 0 y = 0
146 meta "remove_unused:dependency" lemma Mod_0, function mod
148 lemma Div_1_left: forall y:int. y > 1 -> div 1 y = 0
149 meta "remove_unused:dependency" lemma Div_1_left, function div
151 lemma Div_minus1_left: forall y:int. y > 1 -> div (-1) y = -1
152 meta "remove_unused:dependency" lemma Div_minus1_left, function div
154 lemma Mod_1_left: forall y:int. y > 1 -> mod 1 y = 1
155 meta "remove_unused:dependency" lemma Mod_1_left, function mod
157 lemma Mod_minus1_left: forall y:int. y > 1 -> mod (-1) y = y - 1
158 meta "remove_unused:dependency" lemma Mod_minus1_left, function mod
160 lemma Div_mult: forall x y z:int [div (x * y + z) x].
162 div (x * y + z) x = y + div z x
163 meta "remove_unused:dependency" lemma Div_mult, function div
165 lemma Mod_mult: forall x y z:int [mod (x * y + z) x].
167 mod (x * y + z) x = mod z x
168 meta "remove_unused:dependency" lemma Mod_mult, function mod
170 val div (x y:int) : int
172 ensures { result = div x y }
174 val mod (x y:int) : int
176 ensures { result = mod x y }
181 (** {2 Division by 2}
183 The particular case of Euclidean division by 2
192 forall x: int. exists y: int. x = 2*y \/ x = 2*y+1
196 (** {2 Computer Division}
198 Division and modulo operators with the same conventions as mainstream
199 programming language such as C, Java, OCaml, that is, division rounds
200 towards zero, and thus `mod x y` has the same sign as `x`.
204 module ComputerDivision
209 function div (x y: int) : int
210 function mod (x y: int) : int
213 forall x y:int. y <> 0 -> x = y * div x y + mod x y
214 meta "remove_unused:dependency" axiom Div_mod, function div
215 meta "remove_unused:dependency" axiom Div_mod, function mod
218 forall x y:int. x >= 0 /\ y > 0 -> 0 <= div x y <= x
219 meta "remove_unused:dependency" axiom Div_bound, function div
220 meta "remove_unused:dependency" axiom Div_bound, function mod
223 forall x y:int. y <> 0 -> - abs y < mod x y < abs y
224 meta "remove_unused:dependency" axiom Mod_bound, function div
225 meta "remove_unused:dependency" axiom Mod_bound, function mod
228 forall x y:int. x >= 0 /\ y > 0 -> div x y >= 0
229 meta "remove_unused:dependency" axiom Div_sign_pos, function div
230 meta "remove_unused:dependency" axiom Div_sign_pos, function mod
233 forall x y:int. x <= 0 /\ y > 0 -> div x y <= 0
234 meta "remove_unused:dependency" axiom Div_sign_neg, function div
235 meta "remove_unused:dependency" axiom Div_sign_neg, function mod
238 forall x y:int. x >= 0 /\ y <> 0 -> mod x y >= 0
239 meta "remove_unused:dependency" axiom Mod_sign_pos, function div
240 meta "remove_unused:dependency" axiom Mod_sign_pos, function mod
243 forall x y:int. x <= 0 /\ y <> 0 -> mod x y <= 0
244 meta "remove_unused:dependency" axiom Mod_sign_neg, function div
245 meta "remove_unused:dependency" axiom Mod_sign_neg, function mod
247 lemma Rounds_toward_zero:
248 forall x y:int. y <> 0 -> abs (div x y * y) <= abs x
249 meta "remove_unused:dependency" lemma Rounds_toward_zero, function div
250 meta "remove_unused:dependency" lemma Rounds_toward_zero, function mod
252 lemma Div_1: forall x:int. div x 1 = x
253 meta "remove_unused:dependency" lemma Div_1, function div
254 meta "remove_unused:dependency" lemma Div_1, function mod
256 lemma Mod_1: forall x:int. mod x 1 = 0
257 meta "remove_unused:dependency" lemma Mod_1, function div
258 meta "remove_unused:dependency" lemma Mod_1, function mod
260 lemma Div_inf: forall x y:int. 0 <= x < y -> div x y = 0
261 meta "remove_unused:dependency" lemma Div_inf, function div
262 meta "remove_unused:dependency" lemma Div_inf, function mod
264 lemma Mod_inf: forall x y:int. 0 <= x < y -> mod x y = x
265 meta "remove_unused:dependency" lemma Mod_inf, function div
266 meta "remove_unused:dependency" lemma Mod_inf, function mod
268 lemma Div_mult: forall x y z:int [div (x * y + z) x].
269 x > 0 /\ y >= 0 /\ z >= 0 ->
270 div (x * y + z) x = y + div z x
271 meta "remove_unused:dependency" lemma Div_mult, function div
272 meta "remove_unused:dependency" lemma Div_mult, function mod
274 lemma Mod_mult: forall x y z:int [mod (x * y + z) x].
275 x > 0 /\ y >= 0 /\ z >= 0 ->
276 mod (x * y + z) x = mod z x
277 meta "remove_unused:dependency" lemma Mod_mult, function div
278 meta "remove_unused:dependency" lemma Mod_mult, function mod
280 val div (x y:int) : int
282 ensures { result = div x y }
284 val mod (x y:int) : int
286 ensures { result = mod x y }
290 (** {2 Generic Exponentiation of something to an integer exponent} *)
292 module Exponentiation
300 clone export algebra.Monoid
301 with type t = t, constant unit = one, function op = (*), axiom .
303 (* TODO: implement with let rec once let cloning is done *)
304 function power t int : t
306 axiom Power_0 : forall x: t. power x 0 = one
308 axiom Power_s : forall x: t, n: int. n >= 0 -> power x (n+1) = x * power x n
310 lemma Power_s_alt: forall x: t, n: int. n > 0 -> power x n = x * power x (n-1)
312 lemma Power_1 : forall x : t. power x 1 = x
314 lemma Power_sum : forall x: t, n m: int. 0 <= n -> 0 <= m ->
315 power x (n+m) = power x n * power x m
317 lemma Power_mult : forall x:t, n m : int. 0 <= n -> 0 <= m ->
318 power x (Int.(*) n m) = power (power x n) m
320 lemma Power_comm1 : forall x y: t. x * y = y * x ->
321 forall n:int. 0 <= n ->
322 power x n * y = y * power x n
324 lemma Power_comm2 : forall x y: t. x * y = y * x ->
325 forall n:int. 0 <= n ->
326 power (x * y) n = power x n * power y n
332 lemma Power_even : forall x:t, n:int. n >= 0 -> mod n 2 = 0 ->
333 power x n = power (x*x) (div n 2)
335 lemma power_odd : forall x:t, n:int. n >= 0 -> mod n 2 <> 0 ->
336 power x n = x * power (x*x) (div n 2)
341 (** {2 Power of an integer to an integer } *)
347 (* TODO: remove once power is implemented in Exponentiation *)
348 val function power int int : int
350 clone export Exponentiation with
351 type t = int, constant one = one,
352 function (*) = (*), function power = power,
353 goal Assoc, goal Unit_def_l, goal Unit_def_r,
354 axiom Power_0, axiom Power_s
357 forall x y. x >= 0 /\ y >= 0 -> power x y >= 0
360 forall x y. x > 0 /\ y >= 0 -> power x y > 0
362 lemma Power_monotonic:
363 forall x n m:int. 0 < x /\ 0 <= n <= m -> power x n <= power x m
367 (** {2 Number of integers satisfying a given predicate} *)
373 (** number of `n` such that `a <= n < b` and `p n` *)
374 let rec function numof (p: int -> bool) (a b: int) : int
376 = if b <= a then 0 else
377 if p (b - 1) then 1 + numof p a (b - 1)
378 else numof p a (b - 1)
381 forall p : int -> bool, a b : int. a < b -> 0 <= numof p a b <= b - a
382 (* direct when a>=b, by induction on b when a <= b *)
385 forall p : int -> bool, a b c : int.
386 a <= b <= c -> numof p a c = numof p a b + numof p b c
387 (* by induction on c *)
389 lemma Numof_left_no_add :
390 forall p : int -> bool, a b : int.
391 a < b -> not p a -> numof p a b = numof p (a+1) b
392 (* by Numof_append *)
393 lemma Numof_left_add :
394 forall p : int -> bool, a b : int.
395 a < b -> p a -> numof p a b = 1 + numof p (a+1) b
396 (* by Numof_append *)
399 forall p : int -> bool, a b : int.
400 (forall n : int. a <= n < b -> not p n) -> numof p a b = 0
401 (* by induction on b *)
404 forall p : int -> bool, a b : int. a <= b ->
405 (forall n : int. a <= n < b -> p n) -> numof p a b = b - a
406 (* by induction on b *)
408 lemma numof_increasing:
409 forall p : int -> bool, i j k : int.
410 i <= j <= k -> numof p i j <= numof p i k
411 (* by Numof_append and Numof_non_negative *)
413 lemma numof_strictly_increasing:
414 forall p: int -> bool, i j k l: int.
415 i <= j <= k < l -> p k -> numof p i j < numof p i l
416 (* by Numof_append and numof_increasing *)
418 lemma numof_change_any:
419 forall p1 p2: int -> bool, a b: int.
420 (forall j: int. a <= j < b -> p1 j -> p2 j) ->
421 numof p2 a b >= numof p1 a b
423 lemma numof_change_some:
424 forall p1 p2: int -> bool, a b i: int. a <= i < b ->
425 (forall j: int. a <= j < b -> p1 j -> p2 j) ->
426 not (p1 i) -> p2 i ->
427 numof p2 a b > numof p1 a b
429 lemma numof_change_equiv:
430 forall p1 p2: int -> bool, a b: int.
431 (forall j: int. a <= j < b -> p1 j <-> p2 j) ->
432 numof p2 a b = numof p1 a b
442 (** sum of `f n` for `a <= n < b` *)
443 let rec function sum (f: int -> int) (a b: int) : int
445 = if b <= a then 0 else sum f a (b - 1) + f (b - 1)
448 forall f: int -> int, a b: int.
449 a < b -> sum f a b = f a + sum f (a + 1) b
452 forall f g: int -> int, a b: int.
453 (forall i. a <= i < b -> f i = g i) ->
454 sum f a b = sum g a b
457 forall f g: int -> int, a b: int.
458 (forall i. a <= i < b -> f i <= g i) ->
459 sum f a b <= sum g a b
462 forall f: int -> int, a b: int.
463 (forall i. a <= i < b -> f i = 0) ->
467 forall f: int -> int, a b: int.
468 (forall i. a <= i < b -> 0 <= f i) ->
472 forall f: int -> int, a b c: int. a <= b <= c ->
473 sum f a c = sum f a b + sum f b c
475 let rec lemma shift_left (f g: int -> int) (a b c d: int)
476 requires { b - a = d - c }
477 requires { forall i. a <= i < b -> f i = g (c + i - a) }
479 ensures { sum f a b = sum g c d }
480 = if a < b then shift_left f g (a+1) b (c+1) d
484 (** A similar theory, but with a polymorphic parameter passed
485 to function `f` and to function `sum`. *)
490 (** sum of `f x n` for `a <= n < b` *)
491 let rec function sum (f: 'a -> int -> int) (x: 'a) (a b: int) : int
493 = if b <= a then 0 else sum f x a (b - 1) + f x (b - 1)
496 forall f: 'a -> int -> int, x: 'a, a b: int.
497 a < b -> sum f x a b = f x a + sum f x (a + 1) b
500 forall f: 'a -> int -> int, x: 'a, g: 'b -> int -> int, y: 'b, a b: int.
501 (forall i. a <= i < b -> f x i = g y i) ->
502 sum f x a b = sum g y a b
505 forall f: 'a -> int -> int, x: 'a, g: 'b -> int -> int, y: 'b, a b: int.
506 (forall i. a <= i < b -> f x i <= g y i) ->
507 sum f x a b <= sum g y a b
510 forall f: 'a -> int -> int, x: 'a, a b: int.
511 (forall i. a <= i < b -> f x i = 0) ->
515 forall f: 'a -> int -> int, x: 'a, a b: int.
516 (forall i. a <= i < b -> 0 <= f x i) ->
520 forall f: 'a -> int -> int, x: 'a, a b c: int. a <= b <= c ->
521 sum f x a c = sum f x a b + sum f x b c
523 let rec lemma shift_left
524 (f: 'a -> int -> int) (x: 'a)
525 (g: 'b -> int -> int) (y: 'b) (a b c d: int)
526 requires { b - a = d - c }
527 requires { forall i. a <= i < b -> f x i = g y (c + i - a) }
529 ensures { sum f x a b = sum g y c d }
530 = if a < b then shift_left f x g y (a+1) b (c+1) d
532 let rec lemma sum_middle_change (f:'a -> int -> int) (c1 c2:'a) (i j l: int)
533 requires { i <= l < j }
534 ensures { (forall k : int. i <= k < j -> k <> l -> f c1 k = f c2 k) ->
535 sum f c1 i j - f c1 l = sum f c2 i j - f c2 l }
537 = if l = (j-1) then () else sum_middle_change f c1 c2 i (j-1) l
541 (** {2 Factorial function} *)
547 let rec function fact (n: int) : int
550 = if n = 0 then 1 else n * fact (n-1)
554 (** {2 Generic iteration of a function} *)
560 (** `iter k x` is `f^k(x)` *)
561 let rec function iter (f: 'a -> 'a) (k: int) (x: 'a) : 'a
564 = if k = 0 then x else iter f (k - 1) (f x)
566 lemma iter_1: forall f, x: 'a. iter f 1 x = f x
568 lemma iter_s: forall f, k, x: 'a. 0 < k -> iter f k x = f (iter f (k - 1) x)
572 (** {2 Integers extended with an infinite value} *)
578 type t = Finite int | Infinite
580 let function add (x: t) (y: t) : t =
582 | Infinite -> Infinite
585 | Infinite -> Infinite
586 | Finite y -> Finite (x + y)
590 let predicate eq (x y: t) =
592 | Infinite, Infinite -> true
593 | Finite x, Finite y -> x = y
597 let predicate lt (x y: t) =
607 let predicate le (x y: t) = lt x y || eq x y
609 clone export relations.TotalOrder with type t = t, predicate rel = le,
610 lemma Refl, lemma Antisymm, lemma Trans, lemma Total
614 (** {2 Induction principle on integers}
616 This theory can be cloned with the wanted predicate, to perform an
617 induction, either on nonnegative integers, or more generally on
618 integers greater or equal a given bound.
622 module SimpleInduction
630 axiom induction_step: forall n:int. 0 <= n -> p n -> p (n+1)
632 lemma SimpleInduction : forall n:int. 0 <= n -> p n
643 (forall n:int. 0 <= n -> (forall k:int. 0 <= k < n -> p k) -> p n) ->
644 forall n:int. 0 <= n -> p n
648 lemma Induction_bound :
649 (forall n:int. bound <= n ->
650 (forall k:int. bound <= k < n -> p k) -> p n) ->
651 forall n:int. bound <= n -> p n
659 let lemma induction (p: int -> bool)
661 requires { forall n. 0 <= n >= 0 -> p n -> p (n+1) }
662 ensures { forall n. 0 <= n -> p n }
663 = let rec lemma f (n: int) requires { n >= 0 } ensures { p n } variant {n}
664 = if n > 0 then f (n-1) in f 0
668 (** {2 Fibonacci numbers} *)
674 let rec function fib (n: int) : int
677 = if n = 0 then 0 else
679 fib (n-1) + fib (n-2)
685 use relations.WellFounded
690 axiom f_nonneg: forall x. 0 <= f x
692 predicate ltof (x y: t) = f x < f y
694 let rec lemma acc_ltof (n: int)
696 ensures { forall x. f x < n -> acc ltof x }
698 = if n > 0 then acc_ltof (n-1)
700 lemma wf_ltof: well_founded ltof