I have written myPercolation.ml.
open MyUnionFind
module type MyPercolationSig = sig
type percolation
val create_percolation : int -> percolation
val open_site : percolation -> int -> int -> unit
val is_open : percolation -> int -> int -> bool
val is_full : percolation -> int -> int -> bool
val can_percolates : percolation -> bool
end
module MyPercolation : MyPercolationSig = struct
exception IndexOutOfBounds;;
type percolation =
{n : int;
sites: bool array;
union : MyUnionFind.union_find};;
let create_percolation n =
{n = n; sites = Array.make (n*n) false; union = MyUnionFind.create_union (n*n)};;
let open_site p i j =
let {n;_;union} = p
in
if not (is_open p i j) then
begin
sites.(index_of n i j) <- true;
if i - 1 >= 1 && i - 1 <= n && is_open n (i-1) j then
MyUnionFind.union union (index_of n i j) (index_of n (i-1) j)
else if i + 1 >= 1 && i + 1 <= n && is_open n (i+1) j then
MyUnionFind.union union (index_of n i j) (index_of n (i+1) j)
else if j - 1 >= 1 && j - 1 <= n && is_open n i (j-1) then
MyUnionFind.union union (index_of n i j) (index_of n i (j-1))
else if j + 1 >= 1 && j + 1 <= n && is_open n i (j+1) then
MyUnionFind.union union (index_of n i j) (index_of n i (j+1))
end;;
let index_of n i j = n * (i - 1) + j;;
let is_open {n;sites;_} i j =
if i < 1 || i > n || j < 1 || j > n then
raise IndexOutOfBounds
else
sites.(index_of n i j);;
let is_full {n;_;union} i j =
let rec is_connected_top j' =
if j = 0 then false
else
if MyUnionFind.is_connected union (index_of n i j) (index_of n 0 j') then true
else is_connected_top (j'-1)
in is_connected_top n;;
let can_percolates p =
let {n;_;_} = p
in
let rec is_full_bottom j =
if j = 0 then false
else
if is_full p n j then true
else is_full_bottom (j-1)
end
Please ignore the package MyUnionFind package. It is just a homemade implementation for union-find algorithm.
when I try to compile the myPercolation.ml, I got such an error:
$ ocamlc -c myPercolation.ml
File "myPercolation.ml", line 25, characters 11-12:
Error: Syntax error: '}' expected
File "myPercolation.ml", line 25, characters 8-9:
Error: This '{' might be unmatched
I think the error is talking about let {n;_;union} = p in function of let open_site p i j.
I have read through that line and all code many times, but I still don't see any mismatched {} in that line.
can anyone help please?
Another possible error: {n;_;_} should be {n;_} Only 1 underscore is necessary. Think of it like the _ wildcard in a match statement.
The expression let {n; _; union} = p is not well formed OCaml. I think what you want is let {n; union} = p. The way to handle fields you don't care about in a record pattern is not to mention them.
Update:
As rgrinberg points out, a much better way to describe the problem is that the _ has to appear as the last field. That's why the compiler is expecting to see } afterward. It might be good style to include the _ as an indicator that you're purposely matching only a subset of the fields of the record. You can, in fact, turn on a compiler option that checks for this.
Update 2:
The warning for incomplete record patterns is warning number 9, and also is associated with the letter R. Here's how to use R:
$ ocaml -w +R
OCaml version 4.00.0
# type r = { a: int; b: char };;
type r = { a : int; b : char; }
# let {a} = {a=3; b='x'} in a;;
Warning 9: the following labels are not bound in this record pattern:
b
Either bind these labels explicitly or add '; _' to the pattern.
- : int = 3
The command-line syntax is the same for the compiler.
Related
is there a way to optimize this? It is taking way too long to run
let counter2 = ref 0
let rec s2 num =
counter2 := !counter2 + 1;
match num with
| 0 -> 1
| 1 -> 2
| _ -> (((((6*num)-3) * (s2 (num-1))) / (num+1))) - (((num-2)* (s2 (num-2))/(num+1)))
Here is the highly recursive definition of the Fibonacci sequence:
let rec fib n =
if n < 2 then n
else fib (n - 2) + fib (n - 1)
Here is the not so recursive definition of the Fibonacci sequence.
let nfib n =
let rec helper pprev prev i =
if i = n then
pprev + prev
else
helper prev (pprev + prev) (i + 1)
in
if n < 2 then n
else helper 0 1 2
Here is a function for timing things:
let time f x =
let st = Unix.gettimeofday () in
let res = f x in
Printf.printf "%f seconds\n" (Unix.gettimeofday () -. st);
res
Here are times for the fib and nfib functions:
# time fib 42;;
7.694294 seconds
- : int = 267914296
# time nfib 42;;
0.000002 seconds
- : int = 267914296
We have to program the knapsack problem in for a school project in different programming types. One is functional programming and I am trying it in F#.
I am using a recursive function to always get the items with the highest value to put into my knapsack. At the end I want to have the highest total value of all elements combined. Here is the solution in Python and I just hoped I could transfer it to F#.
let names = ["Zahnbürste","Zahnpasta", "Teller", "Duschgel", "Shampoo", "Handtuch", "Besteck", "Trinkflasche", "Becher", "Taschenlampe", "Sonnenschutz", "Medikamente"]
let volumes = [2,4,5,2,2.5,10,5,3,3,9,2,1]
let values = [3,19,17,15,13,3,2,8,5,6,17,15]
maxVol = 20;
def rucksackProblem(restVol, i) :
if (i < (len(volumes))) :
dontPack = rucksackProblem(restVol, i + 1)
pack = 0
if (restVol - volumes[i] >= 0) :
pack = values[i] + rucksackProblem(restVol - volumes[i], i + 1)
if (dontPack > pack) :
return dontPack
else :
return pack
else :
return 0
result = rucksackProblem(maxVol, 0)
print(result)
This is what I tried in F#. Please help me figuring out my problems. I am new to F# and functional programming and other solutions to the knapsack problem with hundreds of code lines seem overcomplicated. This doesn´t really print the end result I want to get from this function. It just returns 0:
open System
let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20
let rec rucksackProblem (restVol : int, i : int) =
if i < volumes_list.Length then
let dontPack = rucksackProblem(restVol, i + 1)
let pack = 0
let currentVolumeItem = volumes_list.Item(i)
if restVol - volumes_list.Item(i) >= 0 then
let mutable pack = values_list.Item(i) + rucksackProblem(restVol - volumes_list.Item(i), i + 1)
printf "%i" (volumes_list.Item(i))
else()
if dontPack > pack then
dontPack
else
pack
else
0
let result = rucksackProblem(maxVolume, 0)
printfn "%i" result
Console.ReadKey() |> ignore
I took the liberty to rewrite your code and I ended up with this.
let names = ["Zahnbürste"; "Zahnpasta"; "Teller"; "Duschgel"; "Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher"; "Taschenlampe"; "Sonnenschutz"; "Medikamente"]
let weights = [2; 4; 5; 2; 3; 10; 5; 3; 3; 9; 2; 1]
let profits = [3; 19; 17; 15; 13; 3; 2; 8; 5; 6; 17; 15]
let cap = 20
type Product = { Name: string; Profit: int; Weight: int }
let knappsack names profits weights cap =
let sortItemsInDecreasingOrder =
List.zip3 names profits weights
|> List.map (fun x -> { Name=x.Item1; Profit=x.Item2; Weight=x.Item3 })
|> List.sortBy (fun p -> p.Profit / p.Weight)
|> List.rev
let products = sortItemsInDecreasingOrder
let rec pack bag totalWeight idx =
if idx > List.length names - 1 then bag
else
let p = products.[idx]
if (totalWeight + p.Weight) > cap then bag
else
pack (bag # [p]) (totalWeight + p.Weight) (idx + 1)
pack List.empty 0 1
knappsack names profits weights cap
|> Dump
|> ignore
The result I get is
Name Profit Weight
Sonnenschutz 17 2
Duschgel 15 2
Shampoo 13 3
Zahnpasta 19 4
Teller 17 5
Trinkflasche 8 3
89 19
Btw. if you are interested in learning functional programming using f# I can highly recommend https://fsharpforfunandprofit.com/.
I can't vouch for the correctness or efficiency of the algorithm but this should do what you're looking for:
open System
let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20
let rec rucksackProblem (restVol : int) (i : int) =
if i < volumes_list.Length then
let dontPack = rucksackProblem restVol (i + 1)
let currentVolumeItem = volumes_list.[i]
let pack =
if restVol - volumes_list.[i] >= 0 then
values_list.[i] + rucksackProblem (restVol - volumes_list.[i]) (i + 1)
else 0
if dontPack > pack then
dontPack
else
pack
else
0
let result = rucksackProblem maxVolume 0
printfn "%i" result
Note that because your mutable pack was defined inside of the scope of an if it was inaccessible outside that branch of the if. I moved that definition above so it could be accessed outside.
I also did a few other changes. In F# items in a list can be accessed as list.[index]. Parameters are passed separated by spaces not commas as this is a more flexible approach, for example allows currying.
I'm working on an implementation of prime decomposition in OCaml. I am not a functional programmer; Below is my code. The prime decomposition happens recursively in the prime_part function. primes is the list of primes from 0 to num. The goal here being that I could type prime_part into the OCaml interpreter and have it spit out when n = 20, k = 1.
2 + 3 + 7
5 + 7
I adapted is_prime and all_primes from an OCaml tutorial. all_primes will need to be called to generate a list of primes up to b prior to prime_part being called.
(* adapted from http://www.ocaml.org/learn/tutorials/99problems.html *)
let is_prime n =
let n = abs n in
let rec is_not_divisor d =
d * d > n || (n mod d <> 0 && is_not_divisor (d+1)) in
n <> 1 && is_not_divisor 2;;
let rec all_primes a b =
if a > b then [] else
let rest = all_primes (a + 1) b in
if is_prime a then a :: rest else rest;;
let f elem =
Printf.printf "%d + " elem
let rec prime_part n k lst primes =
let h elem =
if elem > k then
append_item lst elem;
prime_part (n-elem) elem lst primes in
if n == 0 then begin
List.iter f lst;
Printf.printf "\n";
()
end
else
if n <= k then
()
else
List.iter h primes;
();;
let main num =
prime_part num 1 [] (all_primes 2 num)
I'm largely confused with the reclusive nature with the for loop. I see that List.ittr is the OCaml way, but I lose access to my variables if I define another function for List.ittr. I need access to those variables to recursively call prime_part. What is a better way of doing this?
I can articulate in Ruby what I'm trying to accomplish with OCaml. n = any number, k = 1, lst = [], primes = a list of prime number 0 to n
def prime_part_constructive(n, k, lst, primes)
if n == 0
print(lst.join(' + '))
puts()
end
if n <= k
return
end
primes.each{ |i|
next if i <= k
prime_part_constructive(n - i, i, lst+[i], primes)
}
end
Here are a few comments on your code.
You can define nested functions in OCaml. Nested functions have access to all previously defined names. So you can use List.iter without losing access to your local variables.
I don't see any reason that your function prime_part_constructive returns an integer value. It would be more idiomatic in OCaml for it to return the value (), known as "unit". This is the value returned by functions that are called for their side effects (such as printing values).
The notation a.(i) is for accessing arrays, not lists. Lists and arrays are not the same in OCaml. If you replace your for with List.iter you won't have to worry about this.
To concatenate two lists, use the # operator. The notation lst.concat doesn't make sense in OCaml.
Update
Here's how it looks to have a nested function. This made up function takes a number n and a list of ints, then writes out the value of each element of the list multiplied by n.
let write_mults n lst =
let write1 m = Printf.printf " %d" (m * n) in
List.iter write1 lst
The write1 function is a nested function. Note that it has access to the value of n.
Update 2
Here's what I got when I wrote up the function:
let prime_part n primes =
let rec go residue k lst accum =
if residue < 0 then
accum
else if residue = 0 then
lst :: accum
else
let f a p =
if p <= k then a
else go (residue - p) p (p :: lst) a
in
List.fold_left f accum primes
in
go n 1 [] []
It works for your example:
val prime_part : int -> int list -> int list list = <fun>
# prime_part 12 [2;3;5;7;11];;
- : int list list = [[7; 5]; [7; 3; 2]]
Note that this function returns the list of partitions. This is much more useful (and functional) than writing them out (IMHO).
I'm trying to implement multiply in SML with a few restrictions. I'm given the following add function:
fun add (0 : int, m : int) : int = m
| add (n : int, m : int) : int = 1 + add(n-1, m)
I'm trying to write a function such that mult (m, n) recursively calculates the product of m and n, for any two natural numbers m and n. Your implementation may use the function add mentioned above and - (subtraction), but it may not use + or *.
Here's my attempt:
fun multiply(0 : int, m : int) = 0
| multiply(n : int, 0 : int) = 0
| multiply(1 : int, m : int) = m
| multiply(n : int, 1 : int) = n
| multiply(~1 : int, m : int) = ~m
| multiply(n : int, ~1 : int) = ~n
| multiply(n : int, m : int) =
if (n > 0 andalso m > 0) then
add(add(0, n), multiply(n, m - 1))
else
if (n < 0 andalso m < 0) then
multiply(~n, ~m)
else
if (n < 0 andalso m > 0) then
n - multiply(n, m - 1)
(* n > 0 and m < 0 *)
else
m - multiply(m, n - 1);
It works when n and m are both positive or both negative but not when one is positive and the other negative but I can't seem to figure out my bug. For instance,
multiply(3, ~10) evaluates to 0. So I think my recursive call is getting to 0 and causing it to evaluate to 0. Having said that, my base cases take care of this so I'm not sure how it'd be possible.
Ideas?
Change the m - multiply(m, n - 1); to m - multiply(~m, n - 1);. (and the same for the other n -... line) The way you have it, you're subtracting a negative number from itself, so you're effectively canceling it out, and triggering a base case of 0.
Trace:
= multiply (3, -10)
= -10 - multiply (2, -10)
= -10 - (-10) - multiply (1, -10)
= -10 - (-10) - (-10)
As soon as there's a (-10) - (-10) you're setting off multiply(0 : int, m : int) which results in the 0, so your intuition about it being triggered was correct.
I realized you can't use +, so here's code that follows that. Becaase you need to multiply, we keep the basic logic the same, but instead of recursing with the same numbers, we turn the negative number positive before passing it to the recursive call.
fun multiply(0 : int, m : int) = 0
| multiply(n : int, 0 : int) = 0
| multiply(1 : int, m : int) = m
| multiply(n : int, 1 : int) = n
| multiply(~1 : int, m : int) = ~m
| multiply(n : int, ~1 : int) = ~n
| multiply(n : int, m : int) =
if (n > 0 andalso m > 0) then
add(add(0, n), multiply(n, m - 1))
else if (n < 0 andalso m < 0) then
multiply(~n, ~m)
else if (n < 0 andalso m > 0) then
n - multiply(~n, m - 1)
else (* n > 0 and m < 0 *)
m - multiply(n - 1, ~m);
Also, a minor nitpick, but you can change add(add(0, n), multiply(n, m - 1)) to add(n, multiply(n, m - 1))
I have a linear programming model, for the problem of minimum path. This is the model:
/* Min path problem
file: minPath.mod */
set V;
set E within V cross V;
param cost{E};
param S symbolic;
param T symbolic;
var flow{E} integer, >= 0;
minimize min_path: sum{(a,b) in E} cost[a,b] * flow[a,b];
s.t. conservazione{v in V: v != S and v != T}:
sum{(a,b) in E: a == v} flow[a,b] ==
sum{(a,b) in E: b == v} flow[a,b];
s.t. sorgente: sum{(a,b) in E: a == S} flow[a,b] == 1;
s.t. destinazione: sum{(a,b) in E: b == T} flow[a,b] == 1;
display {(a,b) in E} flow[a,b];
data;
set V := A B C D E;
set E := (A,B) (A,C) (B,D) (B,E) (C,D) (D,E);
param S := A;
param T := D;
param cost := [A,B] 2 [A,C] 1 [B,D] 3 [B,E] 1 [C,D] 1 [D,E] 1;
end;
The objective value is 3 for my example, and the minimum path is:
A -> C -> D -> E
For this reason, the vector flow has to be 1 on the edges, that i written here above. By the way, when i display the vector flow with the statement:
display {(a,b) in E} flow[a,b];
the vector is 0 in all the position.
flow[A,B].val = 0
flow[A,C].val = 0
flow[B,D].val = 0
flow[B,E].val = 0
flow[C,D].val = 0
flow[D,E].val = 0
I tried to change the syntax, but i couldn't force glpsol to print the real value.
Am I missing something?
you have to put the statement:
solve;
before the display statement!