Ocaml - Path between two nodes (How to debug) - graph

I need to make an algorithm to solve this problem using a BFS :
given an oriented weighted graph, a start node, a stop node, and a integer K, say if exist a path between start and stop with wight at least k.
So, first I declared my weighted oriented graph type, a list of triples:
type 'a graph = Gr of ('a * 'a * 'a) list;;
let grafo1 = Gr [(1,3,2);(1,1,5);(2,2,3);(5,5,3);(5,4,6);(3,1,6);(3,7,4);(6,2,7);(4,4,6)];;
In (x,y,z), x is the starting node, y the edge weight and z the arrive node.
Then I made a succ function:
let succ (Gr arcs) n=
let rec aux = function
[] -> []
| (x,y,z):: rest ->
if n = x then z::(aux rest)
else aux rest
in aux arcs;;
This function give me the successors of a node as oputput, so:
succ grafo1 1
gives me
int list = [2; 5]
as output.
In the end, I made this bf_path function, it's a modified BFS that can find a path between 2 nodes (otherwise it raises an exception) and it takes 3 inputs: a graph, a predicate and a starting node
let bf_path g p start =
let rec aux visited = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then [x]
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
The predicate specifies the condition, so the call:
bf_path grafo1 ((=)7)1
gives me int list = [1; 5; 6; 7] as output, the path between nodes 1 and 7.
Now, I can find a path but I need to find a path with at least weight K, so I made a little function that takes a list of triples as input and it sum the weight value:
let rec tot = function
[] -> 0
|(v,c,p)::t -> c + (tot t);;
So, call and output:
tot [(2,2,3);(4,5,6);(8,9,0)]
- : int = 16
I thought all I needed was to add the condition inside the function so I made this function where I add an int K as input and a condition: (tot path >= k)
let bf_path_final g p start k =
let rec aux visited = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then
if (tot [x]) >= k then [x]
else aux visited rest
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
The function compiles without problem:
val bf_path_final : ('a * int * 'b) graph ->
('a * int * 'b -> bool) -> 'a * int * 'b -> int -> ('a * int * 'b) list = <fun>
However, I get an error when I try to call it:
bf_path_final grafo1 ((=)4)1,13;;
^^^^^^
Error: This expression has type int graph_w
but an expression was expected of type ('a * int * 'b) graph_w
So, is the function wrong or do I have to call it on another way?
Another solution was to give the function bf_path output (the path) as input to my tot function, but my output is a list of int, not a list of triples, so i tried to convert my first function to give an output of triplees:
(ex: instead of [1;5;6;7] it should give [(1,1,5);(5,4,6);(6,2,7)])
let bf_path_tr g p start =
let rec aux visited = function
[] -> raise Not_found
| (x,y,z)::rest -> if List.mem x visited then aux visited rest
else if p x then [(x,y,z)]
else try aux (x::visited) rest
with Not_found ->
(x,y,z):: aux (x::visited) (succ_w g (x,y,z))
in aux [] [start];;
Same results, the function is compiled
val bf_path_tr :
('a * 'b * 'c) graph ->
('a -> bool) -> 'a * 'b * 'c -> ('a * 'b * 'c) list = <fun>
but I get the same error:
bf_path_tr grafo1 ((=)7)2
Characters 11-18:
bf_path_tr grafo1 ((=)7)2;;
^^^^^^
Error: This expression has type int graph
but an expression was expected of type ('a * 'b * 'c) graph
Any ideas to solve at least one of these two problems?

The best way to debug this sort of thing is to start adding explicit type annotations everywhere, till you find the place where your expectations don't match the inferred type.
let bf_path_final (g : int graph) (p : int -> bool) (start : int) (k : int) =
let rec aux (visited : int list) = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then (
if (tot [x]) >= k then [x]
else aux visited rest )
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
raises the error
File "test.ml", line 32, characters 17-18:
Error: This expression has type int but an expression was expected of type
'a * int * 'b
which points to if (tot [x]) where indeed tot expects a list of triples, but you have passed it an int list.
Also did you really mean to call tot [x]? It's not totaling anything; x is just a single node there.

Related

Dfs to find visited nodes in sml

What is wrong with this part of code ? I'm trying to make a function which (given a graph) returns a list with all visited nodes, but the compiler keeps saying that there are some erros. Can the code be fixed ?The succesors function is used to find all nodes that are connected to the node which is takes as a parameter. I need dfs function in order to check if the returned "visited" list has all nodes, or in other words if the graph has all nodes connected to each other with a path. -The parameter tuple is a list with tuples of form (weight,node1,node1).
fun succesors n e =
List.map (fn (_,v ,_) => v) (List.filter (fn (u,_,_) => n = u) e)
fun dfs tuples node start =
let
fun find_visited visited node =
if not (List.exists node visited) then
let
val s = (succesors node tuples)
in
List.foldl find_visited (node::visited) s
end
else visited
in
find_visited [] start
end
Those were the errors that were printed :
ask2_ml.sml:75.18-75.39 Error: operator and operand don't agree
[equality type required]
operator domain: ''Z
operand: 'Y -> bool
in expression:
succesors node
ask2_ml.sml:77.35-77.48 Error: operator and operand don't agree
[circularity]
operator domain: ('Z -> bool) * ('Z -> bool) list
operand: ('Z -> bool) * 'Z list
in expression:
node :: visited
ask2_ml.sml:72.7-79.16 Error: case object and rules don't agree [tycon
mismatch]
rule domain: _ list * (_ -> bool)
object: (_ * _) * 'Z
in expression:
(case (arg,arg)
of (visited,node) =>
if not (<exp> <exp>)
then let val <binding> in <exp> <exp> end
else visited)
ask2_ml.sml:81.3-81.24 Error: operator and operand don't agree [tycon
mismatch]
operator domain: _ * _
operand: 'Z list
in expression:
find_visited nil
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:292.17-292.20
There were two problems in your code.
First, List.exists is defined as:
val exists : ('a -> bool) -> 'a list -> bool
So List.exists node visited is incorrect as node is not a
function. You should instead do something like List.exists (fn n => n = node) visited.
Second, List.foldl is defined as:
val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
Here again List.foldl find_visited (node::visited) s is incorrect since
find_visited is of type 'a -> 'b -> 'a.
By fixing these two issues I get the following:
fun successors n e =
List.map (fn (_,v ,_) => v) (List.filter (fn (u,_,_) => n = u) e);
fun dfs tuples node start = let
fun find_visited (node, visited) =
if List.exists (fn n => n = node) visited
then visited
else let
val s = successors node tuples
in
List.foldl find_visited (node::visited) s
end
in
find_visited (start, [])
end;
On a side note, it's extremely inefficient to implement visited as a
list: each time you meet a node you will look at all previously
visited nodes to check if it's new (List.exists). Same for your
implementation of your successor relation: traversing all edges of
your graph to find the successors of n will be too slow.

Combine a list of functions into a single function using fold

Lets say I have a list of functions
let plus_one (x: int) : int = x + 1 in
let double (x: int) : int = x * 2 in
let square (x: int) : int = x * x in
let fun_list = [square, double, plus_one] ;;
Using fold, I want to take this list of functions and combine them into a single function. Something like,
let combined (x: int) : int = x * (2 * (x + 1))
This is what I have:
let combine_functions (fun_list : ('a -> 'a) list) : ('a -> 'a) =
List.fold_right (fun f acc -> f acc) fun_list (fun x -> x)
;;
I would think this would work, however when I try to run this, it tells me that this expression has type 'a -> 'a when it should have type ('a -> 'a) -> ('a -> 'a)
I've solved this by changing the second line of code from
List.fold_right (fun f acc -> f acc) fun_list (fun x -> x)
to
List.fold_right (fun f acc -> (fun x -> f (acc x))) fun_list (fun x -> x)
I'm a bit unclear on what sort of combination you want, do you mean functional composition? If that's the case, then your combined function would look something like this:
square (double (plus_one x))
or
((x + 1) * 2) * ((x + 1) * 2)
which could be achieved by the function
let combine_functions ls =
List.fold_right (fun f x -> f x) ls;;
However I'm not totally sure if this is really what you're trying to do. As an aside, you don't need to explicitly type all your OCaml code, and I personally find that I'm more productive when I let the type inference do it for me.

ML Types for function, a litle tips?

I prepare for GATE Exam. one of the oldest question is unfamiliar with us. some experts please clarify this for us.
Which of the following can be a type for following ML function ?
my f(g, nil)=nil | f(g,x::xs)=(fn a ⇒ g(a,x))::f(g, xs);
1) (int *book → real) * bool list → (int → real) list
2) (bool *int → int) * real list → (bool → int) list
3) (int *int → real) * real list → (real → bool) list
4) (bool *real → int) * int list → (int → int) list
The Answer Sheets say (1) Is corrects. comments or short description for better understanding?
One of the first things you should do is rewrite the function definition yourself. This will force you to actually parse and understand it.
fun f (g, nil) = nil
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
So, f is a function, even the question says that, it must have type ... -> ...:
val f : ... -> ...
What does it receive? Let's take a look at the first pattern of the function:
fun f (g, nil) = nil
It's something of the form (a, b), which is a 2-tuple. The function's argument must be a tuple then:
val f : (... * ...) -> ...
Just by looking at the definition, we can't figure out what type g must have, but it uses nil for the second element of the tuple and nil is the empty list. That means the second component of the tuple must be a list of something:
val f : (... * ... list) -> ...
What else can we deduce? The return value is nil as well, which means that the function returns a list of something, unclear what that something is yet.
val f : (... * ... list) -> ... list
Ok, let's jump to the second pattern of the function definition now:
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
We don't find anything more about the type of the argument, we just got confirmation that the second element of the tuple must indeed be a list, because it uses the :: constructor.
Let's take a look at the body:
(fn a => g (a, x)) :: f (g, xs)
It looks like it's building a list, so it must return a list, which is in accordance with the return type we've sketched so far, i.e., ... list. Let's
try to figure out the type of elements.
It seems to add a function object as the head of the list built by recursively calling the function f, which we're currently investigating. So the elements of the list we're returning must be functions:
val f : (... * ... list) -> (... -> ...) list
What does that function do, though? It calls g with a 2-tuple argument. Now we can fill in some information about the first element of the 2-tuple f receives. It must be a function that receives a 2-tuple as well:
val f : (((... * ...) -> ...) * ... list) -> (... -> ...) list
Can we say anything about the a parameter received by the function literal added to the return list? Not really, just that it's passed to g. Can we tell anything about the type of x? Not really, just that it's passed to g. Moreover, is there any constraint between a and x? Doesn't look like it. So far, we can only tell that g's type must be looking something like this:
('a * 'b) -> 'c'
Where 'a, 'b and 'c are polymorphic types, i.e., any concrete type can satisfy them. You can view them as wholes. We can now fill in more of the type for the f function:
val f : ((('a * 'b) -> 'c) * ... list) -> (... -> ...) list
We can do more actually, we've already assign a type to the x variable, but that comes from the second argument of the 2-tuple received by f, so let's fill in that too:
val f : ((('a * 'b) -> 'c) * 'b list) -> (... -> ...) list
And we can even fill in the element type of the returned list, because we've already assigned types for that, too.
val f : ((('a * 'b) -> 'c) * 'b list) -> ('a -> 'c) list
We can remove some extra parenthesis from the type we came up with without changing the meaning, because of the type operator precedence rules:
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
Now, our function's type is complete. However, this type can't be found in the list of possible answers, so we'll have to see if any of them can be used instead of what we've determined. Why? Because our function type uses type variables, which can be filled in by concrete types. Let's take them one by one:
Choice 1
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (int * bool -> real) * bool list -> (int -> real) list
It looks like 'a could be int, 'b could be a bool (it's book in what you've pasted, but I'm assuming it was a typo) and 'c could be a real. All the replacements match these correspondences, so we declare that, yes, the first choice can be a possible type for the given function, even though not the most general. Let's take the second choice:
Choice 2
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (bool * int -> int) * real list -> (bool -> int) list
The type-variable to concrete -type correspondence table could be this:
'a -> bool
'b -> int
'c -> int
'b -> real
We can stop here because we can see that 'b was assigned to different types, so this function signature can't be assigned to the implementation we've been given.
Choice 3 and 4
They are similar to choice 2, but I'll let them as an exercise to the reader :)

OCaml Explicit polymorphic type annotations

I would enjoy to receive some helpful comments concerning an example given on:
http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc79
7.12 Explicit polymorphic type annotations
type 'a t = Leaf of 'a | Node of ('a * 'a) t
let rec depth : 'a. 'a t -> 'b = function
|Leaf _ -> 1
| Node x -> 1 + depth x
I understand this example function, but when I try to define a 'map-like' function of type
'a. 'a t -> ('a -> 'b) -> 'b t
e.g.:
let rec tmap: 'a. 'a t ->(f:'a->'b) -> 'b t = function
|Leaf x -> Leaf( f x)
|Node x -> let res = tmap x in Node(res);;
I get the following error:
Characters 67-77:
|Leaf x -> Leaf( f x)
^^^^^^^^^^
Error: This expression has type 'c t but an expression was expected of type
(f:'a -> 'b) -> 'b t
which I do not completely understand.
I would appreciate any helpful comment.
You forgot to get the second argument.
let rec tmap:
'a. 'a t ->(f:'a->'b) -> 'b t = (* asking for two arguments *)
function (* takes only the first argument *)
|Leaf x -> Leaf( f x)
|Node x -> let res = tmap x in Node(res);;
Also, 'b must be polymorphic too, as you want to generate nested tuples as long as you descend through the tree.
This should be, thanks to ivg:
let rec tmap : 'a 'b. 'a t -> f:('a->'b) -> 'b t = fun t ~f ->
match t with
|Leaf x -> Leaf( f x)
|Node x -> let f (a,b) = (f a, f b) in Node ( tmap x ~f ) ;;
You have a few problems, like improperly placed parenthesis around f, forgotten argument to the tmap function in the Node branch, and you've forget the quantifier for 'b. So, finally, with the help of PatJ we can write the following:
type 'a t = Leaf of 'a | Node of ('a * 'a) t
let rec depth : 'a. 'a t -> 'b = function
| Leaf _ -> 1
| Node x -> 1 + depth x
let rec tmap: 'a 'b. 'a t -> f:('a -> 'b) -> 'b t =
fun t ~f -> match t with
| Leaf x -> Leaf (f x)
| Node x ->
Node (tmap ~f:(fun (x,y) -> f x, f y) x)
tmap (Node (Leaf (7,8))) ~f:(fun x -> x + 1, x + 2);;
- : (int * int) t = Node (Leaf ((8, 9), (9, 10)))
many thanks for your great help.
Now my test cases work out as intended:
let int_tree = Node(Node(Leaf((3,-1),(0,4))));;
let char_tree = Node(Node(Leaf(('a','c'),('d','c'))));;
tmap int_tree ~f:(fun x -> x*x);;
- : int t = Node (Node (Leaf ((9, 1), (0, 16))))
tmap char_tree ~f:(fun x -> Char.uppercase x);;
- : char t = Node (Node (Leaf (('A', 'C'), ('D', 'C'))))

What is the difference between function type ('a -> 'a) -> int -> 'a -> 'a and ('a -> 'a) -> int -> ('a -> 'a)?

When I write an Ocaml function to recursively compose the same function n times, I did this:
let rec compose f n =
(fun x -> if n = 1 then f x else ((compose f (n-1))) (f x));;
It gives the type
val compose : ('a -> 'a) -> int -> 'a -> 'a = <fun>
what is the difference between type
('a -> 'a) -> int -> 'a -> 'a
and type
('a -> 'a) -> int -> ('a -> 'a)
?
How would a similar compose function look with the latter type?
There is no difference between them. But sometimes authors of libraries use parens to denote, that the computation is actually staged, so that it is better to apply it partially, so that you can get a more efficient function, rather then applying it every time. But from the type system perspective this functions are exactly the same, since -> type operator associates to the right.
As an addition to #ivg's answer, here is a mistake i made. Consider these two functions which have the same type int -> int -> int. (;; added for pasting in the toplevel)
let f a b =
let ai =
Printf.printf "incrementing %d to %d\n" a (a + 1);
a + 1 in
b + ai;;
let f' a =
let ai =
Printf.printf "incrementing %d to %d\n" a (a + 1);
a + 1 in
function b -> b + ai;;
If you partially apply
let f_1 = f 1;;
let f'_1 = f' 1;;
you'll see the difference. What I thought is that f does what f' does. In reality, Ocaml is eager but not so eager as to start evaluating away in partial function applications until it runs out of arguments. To point out the difference, it can make sense to write f''s type as int -> (int -> int).

Resources