Commit 26d05648 by Jean-Christophe Filliâtre

### new example euler290

parent 4850f8fb
 ... ... @@ -10,10 +10,12 @@ In the following, we prove the correctness of a recursive function f which takes m, a, and b as arguments and returns the number of such n. Memoization must be added if one wants to solve the initial problem. Memoization must be added if one wants to solve the initial problem in a reasonable amount of time. (See for instance fib_memo.mlw for an example of memoized function.) *) module M module Euler290 use import int.Int use import ref.Ref use import int.EuclideanDivision ... ... @@ -21,68 +23,70 @@ module M function sum_digits int : int axiom Sum_digits_def : forall n : int. sum_digits n = axiom Sum_digits_def: forall n : int. sum_digits n = if n <= 0 then 0 else sum_digits (div n 10) + mod n 10 (* the number of n st 0 <= n mod 10 < c and sd(n) = sd(137n+a)+b *) type int3 = (int,int,int) predicate p (d:int3) (n:int) = predicate p (d: int3) (n: int) = let (a,b,c) = d in 0 <= mod n 10 < c /\ sum_digits n = sum_digits (137 * n + a) + b clone int.NumOfParam as P with type param = int3, predicate pr = p function solution(a b m : int) : int = P.num_of (a,b,10) 0 (power 10 m) function solution(a b m: int) : int = P.num_of (a,b,10) 0 (power 10 m) (* short cut for the number of n st n mod 10 = c and ... *) function num_of_modc (d:int3) (x y:int) : int = function num_of_modc (d: int3) (x y: int) : int = let (a,b,c) = d in P.num_of (a,b,c+1) x y - P.num_of (a,b,c) x y (* helper lemmas *) lemma Base: forall a b : int. 0 <= a -> sum_digits a + b = 0 -> p (a,b,10) 0 forall a b: int. 0 <= a -> sum_digits a + b = 0 -> p (a,b,10) 0 lemma Empty: forall a b x y : int. P.num_of (a,b,0) x y = 0 forall a b x y: int. P.num_of (a,b,0) x y = 0 lemma Induc: forall a b c : int. 0 <= a -> 0 <= c < 10 -> forall a b c: int. 0 <= a -> 0 <= c < 10 -> let x = 137 * c + a in let a' = div x 10 in let b' = mod x 10 + b - c in forall m : int. m > 0 -> forall m: int. m > 0 -> solution a' b' (m-1) = num_of_modc (a,b,c) 0 (power 10 m) (* code *) use import int.ComputerDivision let rec sd n requires { n >= 0 } ensures { result = sum_digits n } let rec sd (n: int) : int requires { n >= 0 } ensures { result = sum_digits n } variant { n } = if n = 0 then 0 else sd (div n 10) + mod n 10 (* f(m,a,b) = the number of 0 <= n < 10^m such that digitsum(137n+a) + b = digitsum(n). *) let rec f m a b digitsum(137n + a) + b = digitsum(n). *) let rec f (m a b: int) : int requires { 0 <= m /\ 0 <= a } ensures { result = solution a b m } ensures { result = solution a b m } variant { m } = if m = 0 then begin (* only n = 0 is possible *) if sd a + b = 0 then 1 else 0 end else begin let sum = ref 0 in let c = ref 0 in while !c <= 9 do (* n = 10n' + c *) invariant { 0 <= !c <= 10 /\ !sum = P.num_of (a,b,!c) 0 (power 10 m) } variant { 10 - !c } let x = 137 * !c + a in for c = 0 to 9 do (* count the n st n mod 10 = c *) invariant { !sum = P.num_of (a,b,c) 0 (power 10 m) } let x = 137 * c + a in let q = div x 10 in let r = mod x 10 in sum := !sum + f (m-1) q (r + b - !c); c := !c + 1 sum := !sum + f (m-1) q (r + b - c) done; !sum end ... ...

Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!