This question is about TLA+ using toolbox (https://github.com/tlaplus/tlaplus/releases)
I haven't been able to find any tag about it. Sorry about that. This is why I only tagged with Primes. If I am missing something please be kind to add better tags or create the missing ones.
Here is the issue
There is a well known function and algorithm for GCD. Here it is.
------------------ MODULE Euclid -------------------------------
EXTENDS Naturals, TLC
CONSTANT K
Divides(i,j) == \E k \in 0..j: j = i * k
IsGCD(i,j,k) ==
Divides(i,j)
/\ Divides(i,k)
/\ \A r \in 0..j \cup 0..k :
(Divides(r,j ) /\ Divides(r,k)) => Divides(r,i)
(* --algorithm EuclidSedgewick
{
variables m \in 1..K, n \in 1..m, u = m, v = n;
{
L1: while (u # 0) {
if (u < v) { u := v || v := u };
L2: u := u - v
};
assert IsGCD(v, m, n)
}
}
*)
This is a well known solution which is working.
I'm now trying to write a isPrime function using this one. But I think what I'm doing is wrong. I would like to know if you have an idea.
isPrime(nb) ==
\E k \in 2..nb: isGCD(nb,k,1) \/ isGCD(nb,k,nb)
Thanks
There are many way to express the notion that an integer is prime, however your attempt says that an integer N is prime if there exists some integer k in 2..N for which the gcd(k,n) = 1 or gcd(k,n) = n. This is easily seen to be incorrect, as 4 is clearly composite but gcd(3,4) = 1. And, of course, for every N prime or not, gcd(N, N) = N.
I'm not sure about the rules for TLA+, but I had a quick read of some documentation and here's my try at IsPrime
isPrime(nb) == \A k in 2..nb-1: ~Divides(k, nb)
or
isPrime(nb) == \A k in 1..nb: Divides(k, nb) => ( (k = 1) \/ (k=nb) )
or, if you really want to work IsGCD in there for some reason
isPrime(nb) == \A k in 1..nb: IsGCD(k, nb, d) => ( (d = 1) \/ (d = nb) )
or
isPrime(nb) == \A k in 2..nb-1: IsGCD(k, nb, d) => (d = 1)
Related
I wrote a simple recursive fibonacci program that works fine without an assert statement, but when I add an assert statement, even with various permutations of parentheses, spaces, and double semicolons, I keep getting a syntax error during compilation.
Working function:
let rec fib n =
if n = 1
then 1
else
n*(fib (n-1))
Not working:
let rec fib n =
assert (n>=0)
if n = 1
then 1
else
n*(fib (n-1))
Any thoughts appreciated.
Thanks.
You have two expressions: assert (n >= 0) and if ... then ... else .... If you want the two expressions to be evaluated in sequence (which you do), you need to separate them with a semicolon:
let rec fib n =
assert (n >= 0);
if n = 1 then 1
else n * fib (n - 1);;
val fib : int -> int = <fun>
# fib 3;;
- : int = 6
# fib (-3);;
Exception: Assert_failure ("//toplevel//", 2, 4).
Extra spaces do not affect the semantics of OCaml programs. There are also no statements per se in OCaml - everything is an expression. To evaluate two expressions in a sequence you may use the semicolon, e.g.,
print_endline "Hello";
assert (1 > 2);
print_endline "World";
You can also use let .. in .. to chain expressions, especially, if you need to the expression values, e.g.,
let x = 1 + 2 in
let y = 3 + 4 in
Format.printf "%d + %d = %d\n" x y (x + y)
Going back to your example, it should be
let rec fib n =
assert (n >= 0);
if n = 1 then 1
else n * fib (n - 1)
P.S. The double semicolons are not really a part of the language but a special input sequence to be used in the interactive toplevel.
I have a Coq function that classifies prime numbers.
I exported it to Haskell and tested it; it works fine.
I want to rigorously prove it indeed classifies primes,
so I tried to prove the following theorem isPrimeCorrect:
(************)
(* helper'' *)
(************)
Fixpoint helper' (p m n : nat) : bool :=
match m with
| 0 => false
| 1 => false
| S m' => (orb ((mult m n) =? p) (helper' p m' n))
end.
(**********)
(* helper *)
(**********)
Fixpoint helper (p m : nat) : bool :=
match m with
| 0 => false
| S m' => (orb ((mult m m) =? p) (orb (helper' p m' m) (helper p m')))
end.
(***********)
(* isPrime *)
(***********)
Fixpoint isPrime (p : nat) : bool :=
match p with
| 0 => false
| 1 => false
| S p' => (negb (helper p p'))
end.
(***********)
(* divides *)
(***********)
Definition divides (n p : nat) : Prop :=
exists (m : nat), ((mult m n) = p).
(*********)
(* prime *)
(*********)
Definition prime (p : nat) : Prop :=
(p > 1) /\ (forall (n : nat), ((divides n p) -> ((n = 1) \/ (n = p)))).
(*****************************)
(* isPrime correctness proof *)
(*****************************)
Theorem isPrimeCorrect: forall (p : nat),
((isPrime p) = true) <-> (prime p).
I spent a good few hours on this theorem today with no actual progress.
Actually, I was a bit surprised how difficult it is since I previously
managed to prove pretty similar stuff. Any hints/clues how to proceed?
You must explicitely write lemmas for each of the helping functions, which state exactly what you think this function does for you. For instance, I tried to do this for your helper' function and I came up with the following lemma:
Require Import Arith Psatz.
(************)
(* helper'' *)
(************)
Fixpoint helper' (p m n : nat) : bool :=
match m with
| 0 => false
| 1 => false
| S m' => (orb ((mult m n) =? p) (helper' p m' n))
end.
Lemma helper'_correct :
forall p m n,
helper' p m n = true <-> exists k, (1 < k <= m /\ p = k * n).
Proof.
intros p; induction m as [ | m' IH]; intros n.
split;[discriminate | ].
intros [k [abs _]].
lia. (* Here the hypothesis abs has statement 1 <= k < 0
and lia recognizes that it is absurd. *)
destruct m' as [ | m''] eqn: E.
split;[discriminate | intros [k [abs _]]; lia].
change (helper' p (S (S m'')) n) with (orb ((mult (S (S m'')) n) =? p)
(helper' p (S m'') n)).
rewrite Bool.orb_true_iff.
split.
intros [it | later].
now exists (S (S m'')); split;[lia | symmetry; apply beq_nat_true ].
rewrite IH in later; destruct later as [k [k1 k2]].
exists k.
(* here hypothesis k1 states 1 < k <= S m''
k2 states p = k * n
and we need to prove 1 < k <= S (S m'') /\ p = k * n
lia can do that automatically. *)
lia.
intros [k [[k1 km] k2]].
apply le_lt_or_eq in km; rewrite or_comm in km; destruct km as [km | km].
now left; rewrite <- km; rewrite Nat.eqb_eq, k2.
right; apply lt_n_Sm_le in km.
change (helper' p (S m'') n = true); rewrite IH.
exists k.
lia.
Qed.
Obviously there should also be a way to link the helper function wih the divides predicate.
This F# code is an attempt to solve Project Euler problem #58:
let inc = function
| n -> n + 1
let is_prime = function
| 2 -> true
| n when n < 2 || n%2=0-> false
| n ->
[3..2..(int (sqrt (float n)))]
|> List.tryFind (fun i -> n%i=0)
|> Option.isNone
let spir = Seq.initInfinite (fun i ->
let n = i%4
let a = 2 * (i/4 + 1)
(a*n) + a + (a-1)*(a-1))
let rec accum se p n =
match se with
| x when p*10 < n && p <> 0 -> 2*(n/4) + 1
| x when is_prime (Seq.head x) -> accum (Seq.tail x) (inc p) (inc n)
| x -> accum (Seq.tail x) p (inc n)
| _ -> 0
printfn "%d" (accum spir 0 1)
I do not know the running time of this program because I refused to wait for it to finish. Instead, I wrote this code imperatively in C++:
#include "stdafx.h"
#include "math.h"
#include <iostream>
using namespace std;
int is_prime(int n)
{
if (n % 2 == 0) return 0;
for (int i = 3; i <= sqrt(n); i+=2)
{
if (n%i == 0)
{
return 0;
}
}
return 1;
}
int spir(int i)
{
int n = i % 4;
int a = 2 * (i / 4 + 1);
return (a*n) + a + ((a - 1)*(a - 1));
}
int main()
{
int n = 1, p = 0, i = 0;
cout << "start" << endl;
while (p*10 >= n || p == 0)
{
p += is_prime(spir(i));
n++; i++;
}
cout << 2*(i/4) + 1;
return 0;
}
The above code runs in less than 2 seconds and gets the correct answer.
What is making the F# code run so slowly? Even after using some of the profiling tools mentioned in an old Stackoverflow post, I still cannot figure out what expensive operations are happening.
Edit #1
With rmunn's post, I was able to come up with a different implementation that gets the answer in a little under 30 seconds:
let inc = function
| n -> n + 1
let is_prime = function
| 2 -> true
| n when n < 2 || n%2=0-> false
| n ->
[3..2..(int (sqrt (float n)))]
|> List.tryFind (fun i -> n%i=0)
|> Option.isNone
let spir2 =
List.unfold (fun state ->
let p = fst state
let i = snd state
let n = i%4
let a = 2 * (i/4 + 1)
let diag = (a*n) + a + (a-1)*(a-1)
if p*10 < (i+1) && p <> 0 then
printfn "%d" (2*((i+1)/4) + 1)
None
elif is_prime diag then
Some(diag, (inc p, inc i))
else Some(diag, (p, inc i))) (0, 0)
Edit #2
With FuleSnabel's informative post, his is_prime function makes the above code run in under a tenth of a second, making it faster than the C++ code:
let inc = function
| n -> n + 1
let is_prime = function
| 1 -> false
| 2 -> true
| v when v % 2 = 0 -> false
| v ->
let stop = v |> float |> sqrt |> int
let rec loop vv =
if vv <= stop then
if (v % vv) <> 0 then
loop (vv + 2)
else
false
else
true
loop 3
let spir2 =
List.unfold (fun state ->
let p = fst state
let i = snd state
let n = i%4
let a = 2 * (i/4 + 1)
let diag = (a*n) + a + (a-1)*(a-1)
if p*10 < (i+1) && p <> 0 then
printfn "%d" (2*((i+1)/4) + 1)
None
elif i <> 3 && is_prime diag then
Some(diag, (inc p, inc i))
else Some(diag, (p, inc i))) (0, 0)
There is no Seq.tail function in the core F# library (UPDATE: Yes there is, see comments), so I assume you're using the Seq.tail function from FSharpx.Collections. If you're using a different implementation of Seq.tail, it's probably similar -- and it's almost certainly the cause of your problems, because it's not O(1) like you think it is. Getting the tail of a List is O(1) because of how List is implemented (as a series of cons cells). But getting the tail of a Seq ends up creating a brand new Seq from the original enumerable, discarding one item from it, and returning the rest of its items. When you go through your accum loop a second time, you call Seq.tail on that "skip 1 then return" seq. So now you have a Seq which I'll call S2, which asks S1 for an IEnumerable, skips the first item of S1, and returns the rest of it. S1, when asked for its first item, asks S0 (the original Seq) for an enumerable, skips its first item, then returns the rest of it. So for S2 to skip two items, it had to create two seqs. Now on your next run through when you ask for the Seq.tail of S2, you create S3 that asks S2 for an IEnumerable, which asks S1 for an IEnumerable, which asks S0 for an IEnumerable... and so on. This is effectively O(N^2), when you thought you were writing an O(N) operation.
I'm afraid I don't have time right now to figure out a solution for you; using List.tail won't help since you need an infinite sequence. But perhaps just knowing about the Seq.tail gotcha is enough to get you started, so I'll post this answer now even though it's not complete.
If you need more help, comment on this answer and I'll come back to it when I have time -- but that might not be for several days, so hopefully others will also answer your question.
Writing performant F# is very possible but requires some knowledge of patterns that have high relative CPU cost in a tight loop. I recommend using tools like ILSpy to find hidden overhead.
For instance one could imagine F# exands this expression into an effective for loop:
[3..2..(int (sqrt (float n)))]
|> List.tryFind (fun i -> n%i=0)
|> Option.isNone
However it currently doesn't. Instead it creates a List that spans the range using intrinsic operators and passes that to List.tryFind. This is expensive when compared to the actual work we like to do (the modulus operation). ILSpy decompiles the code above into something like this:
public static bool is_prime(int _arg1)
{
switch (_arg1)
{
case 2:
return true;
default:
return _arg1 >= 2 && _arg1 % 2 != 0 && ListModule.TryFind<int>(new Program.Original.is_prime#10(_arg1), SeqModule.ToList<int>(Operators.CreateSequence<int>(Operators.OperatorIntrinsics.RangeInt32(3, 2, (int)Math.Sqrt((double)_arg1))))) == null;
}
}
These operators aren't as performant as they could be (AFAIK this is currently being improved) but no matter how effecient allocating a List and then search it won't beat a for loop.
This means the is_prime is not as effective as it could be. Instead one could do something like this:
let is_prime = function
| 1 -> false
| 2 -> true
| v when v % 2 = 0 -> false
| v ->
let stop = v |> float |> sqrt |> int
let rec loop vv =
if vv <= stop then
(v % vv) <> 0 && loop (vv + 2)
else
true
loop 3
This version of is_prime relies on tail call optimization in F# to expand the loop into an efficient for loop (you can see this using ILSpy). ILSpy decompile the loop into something like this:
while (vv <= stop)
{
if (_arg1 % vv == 0)
{
return false;
}
int arg_13_0 = _arg1;
int arg_11_0 = stop;
vv += 2;
stop = arg_11_0;
_arg1 = arg_13_0;
}
This loop doesn't allocate memory and is just a rather efficient loop. One see some non-sensical assignments but hopefully the JIT:er eliminate those. I am sure is_prime can be improved even further.
When using Seq in performant code one have to keep in mind it's lazy and it doesn't use memoization by default (see Seq.cache). Therefore one might easily end up doing the same work over and over again (see #rmunn answer).
In addition Seq isn't especially effective because of how IEnumerable/IEnumerator are designed. Better options are for instance Nessos Streams (available on nuget).
In case you are interested I did a quick implementation that relies on a simple Push Stream which seems decently performant:
// Receiver<'T> is a callback that receives a value.
// Returns true if it wants more values, false otherwise.
type Receiver<'T> = 'T -> bool
// Stream<'T> is function that accepts a Receiver<'T>
// This means Stream<'T> is a push stream (as opposed to Seq that uses pull)
type Stream<'T> = Receiver<'T> -> unit
// is_prime returns true if the input is prime, false otherwise
let is_prime = function
| 1 -> false
| 2 -> true
| v when v % 2 = 0 -> false
| v ->
let stop = v |> float |> sqrt |> int
let rec loop vv =
if vv <= stop then
(v % vv) <> 0 && loop (vv + 2)
else
true
loop 3
// tryFind looks for the first value in the input stream for f v = true.
// If found tryFind returns Some v, None otherwise
let tryFind f (s : Stream<'T>) : 'T option =
let res = ref None
s (fun v -> if f v then res := Some v; false else true)
!res
// diagonals generates a tuple stream of all diagonal values
// The first value is the side length, the second value is the diagonal value
let diagonals : Stream<int*int> =
fun r ->
let rec loop side v =
let step = side - 1
if r (side, v + 1*step) && r (side, v + 2*step) && r (side, v + 3*step) && r (side, v + 4*step) then
loop (side + 2) (v + 4*step)
if r (1, 1) then loop 3 1
// ratio computes the streaming ratio for f v = true
let ratio f (s : Stream<'T>) : Stream<float*'T> =
fun r ->
let inc r = r := !r + 1.
let acc = ref 0.
let count = ref 0.
s (fun v -> (inc count; if f v then inc acc); r (!acc/(!count), v))
let result =
diagonals
|> ratio (snd >> is_prime)
|> tryFind (fun (r, (_, v)) -> v > 1 && r < 0.1)
I am trying to make a program to compute the length of the Collatz sequence on all numbers from 1 to 100. Basically if I have an odd number I have to multiply it by 3 and add 1(n*3+1), and if I have a even number I need to divide it by 2(n/2) and then keep doing it untill it gets to 1 and in the end print out the count of times the number was either divided by 2 or multiplyed by 3 and added 1.
Here is what i have so far:
let stevec = ref 0;
let n = ref 1;
for i = 1 to 100 do
n := i;
while !n != 1 do
if (n mod 2 = 0) then
stevec := !stevec + 1;
n := !n / 2;
if (n mod 2 = 1) then
stevec := !stevec + 1;
n := 3 * !n + 1;
done
print_int (stevec);
done;;
After I run the code I get a syntax error and the print_int get underlined so i guess there is a problem with that but I'm not even sure about that.
There are several problems with your code, so let's take a look at it.
let stevec = ref 0;
let n = ref 1;
You shouldn't write that kind of code, as ; is an expression separator (and you are using it here as a declaration separator).
The right approach depends on wether you want your declaration to be local or toplevel.
(* local declaration *)
let stevec = ref 0 in
let n = ref 1 in
(* toplevel declaration *)
let stevec = ref 0;;
let n = ref 1;;
Then you typed while !n != 1 do. This shouldn't be used as you do physical inequality between your integers, whereas you want structural equality. Well, it will work too because of OCaml's behavior on integers but good practice requires you to use <> instead of !=.
Now let's look at your loop's body:
if (!n mod 2 = 0) then
stevec := !stevec + 1;
n := !n / 2;
if (!n mod 2 = 1) then
stevec := !stevec + 1;
n := 3 * !n + 1;
Notice the absence of any fi or closing bracket? That's because in OCaml, only the next expression after the then is executed. And precedence over ; doesn't go as you want it to. You can use parens or the more explicit begin ... end construction. To prove that the begin ... end works, I replaced your second test by a else statement.
if (!n mod 2 = 0) then
begin
stevec := !stevec + 1;
n := !n / 2;
end
else
begin
stevec := !stevec + 1;
n := 3 * !n + 1;
end
Finally while ... done being itself an expression, you should put a ; at the end of it.
And that's how you remove the errors from your code.
Yet...
This is clearly not the "right way" to do it in OCaml. The main perk of FP is its closeness to maths and you are here trying to define a mathematical function. So let's do this in a functionnal way:
let is_even x = (x mod 2) = 0;;
let rec collatz counter n =
if n = 1
then counter
else collatz (counter+1) (if is_even n then n/2 else 3*n+1);;
let () =
for i = 1 to 100 do
print_int (collatz 0 i);
print_newline ();
done;;
Doesn't that look nicer? Feel free to ask for any clarification of course.
I'm writing a program in OCaml which should calculate the first 100 Bell numbers.
Here is my code (I'm using the Num module):
open Num
let one = num_of_int 1;;
let zero = num_of_int 0;;
calculate factorial:
let rec factorial n =
if n < 2
then one
else (num_of_int n) */ factorial(n-1)
calculate Newton:
let rec newton n k =
factorial n // (factorial k */ factorial (n-k))
let bell = Array.make 101 zero;;
bell.(0) <- one;;
bell.(1) <- one;;
let i = ref 2
let k = ref 0
let x = ref zero
let suma = ref zero
let n = ref 100
if !n != 0 || !n != 1 then
while !i <= !n do
while !k <= (!i-1) do
x := newton (!i-1) !k;
suma := !suma +/ (!x */ bell.(!k));
k := !k + 1
done;
bell.(int_of_num !k) <- (!suma);
suma:= zero;
k:=0;
i:= !i + 1;
done;;
bell.(int_of_num 20)
This is my first program in this language. I have some problems with compiling it.
You miss a ;; at the end of the last let n = ref 100. But it is considered bad style anyway to use global variables as helper variables of an algorithm. The code below is a minimal fix of the code from the question and not an endorsement of other aspects of bad style, like not using for loops mentioned in comments.
(* #load "nums.cma";; if in toplevel *)
open Num
let one = num_of_int 1;;
let zero = num_of_int 0;;
let rec factorial n =
if n < 2
then one
else (num_of_int n) */ factorial(n-1)
let rec newton n k =
factorial n // (factorial k */ factorial (n-k))
let bell input =
let bell = Array.make (input+1) zero in
bell.(0) <- one;
bell.(1) <- one;
let i = ref 2 in
let k = ref 0 in
let x = ref zero in
let suma = ref zero in
let n = ref input in
if !n <> 0 || !n <> 1 then
while !i <= !n do
while !k <= (!i-1) do
x := newton (!i-1) !k;
suma := !suma +/ (!x */ bell.(!k));
k := !k + 1
done;
bell.(!k) <- (!suma);
suma:= zero;
k:=0;
i:= !i + 1;
done;
bell.(input)