circlarity error in ml - ml

I'm trying to run a function subst(tr, v1, v2) which returns a new ntree where all the values of v1 are replaced by v2 in the output tree.
datatype 'a ntree = leaf of 'a | node of 'a ntree list;
fun map(f, []) = [] | map(f,x::t)=f(x) :: map(f,t);
fun subst(leaf(d), v1, v2) = if d=v1 then v2 else d
| subst(node(q), v1, v2) = let fun w(k) =
if k=v1 then subst(v2, v1, v2) else subst(k, v1, v2)
in map(w, q)
end;
but i get a circularity error b/c my rhs of clause does not agree w/ the function result type. my expression is ''Z list and my result type is ''Z

You've forgotten to wrap the results of subst with the appropriate ntree constructors again, and consequently, the type system is trying to equate the type of d with a list. Also, your function w does not make a hell lot of sense, given that you map it over a list of ntrees (i.e., k is an ntree, and you cannot compare it to v1).
General hint: if you have strange type errors that you cannot make sense of at first it often helps to narrow them down by adding type annotation, e.g. on function arguments or results.
The following code should work (untested):
fun subst(leaf d, v1, v2) = leaf(if d = v1 then v2 else d)
| subst(node q, v1, v2) = node(map(fn k => subst(k, v1, v2), q))
With the right amount of currying, and using the standard map function, it can be even simpler:
fun subst v1 v2 (leaf d) = leaf(if d = v1 then v2 else d)
| subst v1 v2 (node q) = node(map (subst v1 v2) q)
Also, as stylistic nit, it is good practice to capitalise constructors (Leaf and Node), to ease distinguishing them from variables in patterns.

Related

Why does my implementation of Dijkstra's algorithm not behave as it should?

I am writing an implementation of Dijkstra's algorithm to learn about cool graph algorithms (this isn't a homework assignment, FYI). I am using Wikipedia's description of the algorithm as my main resource.
I have tested different traversal paths and gotten the following results ((foo, bar) means foo to bar):
crashes:
(e, f)
(f, d)
(c, a)
(f, g)
incorrect:
(a, c)
(g, f)
working:
(d, f)
My graph that I am working with looks like this:
F - H
| |
A ---- B - C
| /
| /
E - G - D
By tracing the path from E to F, I understand mostly why my code is failing. The other problem is that I don't know how to implement the algorithm using my way of doing it otherwise. Here's a tracing from E to F:
At node E, my neighbors are A and G. The shortest tentative distance is G, so that's the next current node. G's neighbors are E and D, but E was already traversed, so C is the next one. For C, its neighbor D was traversed, so we now arrive at B (B and H are equidistant, but it was chosen first in C's list of edges). Here is where my problem lies:
A's tentative distance was already calculated by E to be 2. Since the new tentative distance from B to A is much larger than just two, its distance stays at 2. For F, its distance is set to the tentative distance, since it was initialized as infinity. A's distance is smaller, so it's chosen as the next node. A's only neighbors are E and B, which have already been traversed, so all nodes around it have already been explored. The variable closest (see my code below) was initialized to a node with no other filled-in fields than a distance of infinity, so for the next iteration, it has no edges, and I get a segmentation fault.
I know that this is what happened in my code because of its output, shown below:
Current: e
New neighbor: a
New neighbor: g
g, closest, distance of 1
Current: g
New neighbor: d
d, closest, distance of 2
Current: d
New neighbor: c
c, closest, distance of 4
Current: c
New neighbor: b
New neighbor: h
b, closest, distance of 5
Current: b
New neighbor: a
New neighbor: f
a, closest, distance of 2
Current: a
?, closest, distance of 1000
Current: ?
Segmentation fault: 11
Where did I step wrong in implementing this algorithm? I have tried to follow Wikipedia's 6-step description of it very carefully. The only difference between their description and mine is that I am not using sets to keep track of explored and unexplored nodes (rather, that data is kept in the nodes themselves). Please provide any insight you can.
Note: I am compiling with Clang on a Mac with no optimization (-O0). I've noticed that with higher optimization, my program recurs infinitely and then gives me another segmentation fault, but I prioritize fixing the central problem with my algorithm before dealing with that.
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#define infinity 1000
struct Node {
unsigned char value;
int visited, distance, edge_count;
int* weights, weight_assign_index, freed;
struct Node** edges;
};
typedef struct Node Node;
Node* init_node(const unsigned char value, const int edge_count) {
Node* node = malloc(sizeof(Node));
node -> value = value;
node -> visited = 0;
node -> distance = infinity;
node -> edge_count = edge_count;
node -> weights = malloc(edge_count * sizeof(int));
node -> weight_assign_index = 0;
node -> freed = 0;
node -> edges = malloc(edge_count * sizeof(Node*));
return node;
}
void assign_edges(Node* node, const int amount, ...) {
va_list edges;
va_start(edges, amount);
for (int i = 0; i < amount; i++)
node -> edges[i] = va_arg(edges, Node*);
va_end(edges);
}
void assign_weight(Node* node_1, Node* node_2, const int weight) {
for (int i = 0; i < node_1 -> edge_count; i++) {
if (node_1 -> edges[i] == node_2) {
node_1 -> weights[node_1 -> weight_assign_index++] = weight;
node_2 -> weights[node_2 -> weight_assign_index++] = weight;
}
}
}
void deinit_graph(Node* node) {
if (!node -> freed) {
node -> freed = 1;
free(node -> weights);
for (int i = 0; i < node -> edge_count; i++)
deinit_graph(node -> edges[i]);
free(node -> edges);
}
}
void dijkstra(Node* current, Node* goal) {
Node local_closest;
local_closest.distance = infinity;
Node* closest = &local_closest;
printf("Current: %c\n", current -> value);
for (int i = 0; i < current -> edge_count; i++) {
Node* neighbor = current -> edges[i];
if (!neighbor -> visited) {
printf("New neighbor: %c\n", neighbor -> value);
const int tentative_distance = current -> distance + current -> weights[i];
if (tentative_distance < neighbor -> distance)
neighbor -> distance = tentative_distance;
if (neighbor -> distance < closest -> distance)
closest = neighbor;
}
}
printf("%c, closest, distance of %d\n", closest -> value, closest -> distance);
current -> visited = 1;
if (closest == goal) printf("Shortest distance is %d\n", closest -> distance);
else dijkstra(closest, goal);
}
int main() {
Node
*a = init_node('a', 2),
*b = init_node('b', 3),
*c = init_node('c', 3),
*d = init_node('d', 2),
*e = init_node('e', 2),
*f = init_node('f', 2),
*g = init_node('g', 2),
*h = init_node('h', 2);
assign_edges(a, 2, e, b);
assign_edges(b, 3, a, f, c);
assign_edges(c, 3, b, h, d);
assign_edges(d, 2, c, g);
assign_edges(e, 2, a, g);
assign_edges(f, 2, b, h);
assign_edges(g, 2, e, d);
assign_edges(h, 2, f, c);
assign_weight(a, e, 2);
assign_weight(a, b, 4);
assign_weight(b, c, 1);
assign_weight(b, f, 1);
assign_weight(f, h, 1);
assign_weight(h, c, 1);
assign_weight(c, d, 2);
assign_weight(d, g, 1);
assign_weight(g, e, 1);
e -> distance = 0;
dijkstra(e, f);
deinit_graph(a);
}
Read Step 6 of Wikipedia's algorithm again:
Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
The "select" here means "among all the unvisited nodes in the entire graph", not just among the unvisited neighbors of the current node, which is what your code is doing. So if the unvisited node of smallest tentative distance is not a neighbor of the current node, your code goes astray. And if the current node has no unvisited neighbors at all (which is entirely possible, either with a situation like what you encountered, or more simply with a dead-end node), your code absurdly visits the local_closest node, which isn't in the graph at all and whose edges are uninitialized, naturally causing a crash.
So you diverged from the correct algorithm sooner than the visit to A which you are focusing on. When you finished visiting D, the remaining unvisited nodes were A at tentative distance 2, C at tentative distance 4, and B,F,H at tentative distance infinity. So by the algorithm, you ought to visit A next. But instead you visit C, again because your code wrongly only considers neighbors of the current node as candidates for the next node to visit.
Frankly I don't see how a recursive algorithm is going to be workable at all here. You need to have access to some data structure that tracks all the unvisited nodes, so that at any time you can find the one at minimum tentative distance, even if it's very far away from your current node. Your idea of keeping track of visited status on the nodes themselves has a problem with this, because you have no good way to search them all, except by going back to the starting node and doing some kind of DFS/BFS. That's (1) not possible in your current implementation, because the recursive calls to dijkstra no longer have a pointer to the starting node, and (2) very inefficient, because it's O(N) on every visit.
There's a good reason why the Wikipedia algorithm suggests using a set here. And I think it lends itself better to an iterative than to a recursive algorithm.

Boxing Double during Array.tabulate

I am experiencing a boxing issue which affects negatively performance of my Scala code. I have extracted the relevant code, which still shows the issue, with some added strangeness. I have the following representation of a 2D Double array which allows me to perform transformations on it by providing my functions:
case class Container(
a: Array[Array[Double]] = Array.tabulate[Double](10000, 10000)((x,y) => x.toDouble * y)
) {
def transformXY(f: (Double, Double, Double) => Double): Container = {
Container(Array.tabulate[Double](a.length, a.length) { (x, y) =>
f(x, y, a(x)(y))
})
}
def transform(f: Double => Double): Container = {
Container(Array.tabulate[Double](a.length, a.length) { (x, y) =>
f(a(x)(y))
})
}
}
Following code reproduces the issue for me:
object Main extends App {
def now = System.currentTimeMillis()
val iters = 3
def doTransformsXY() = {
var t = Container()
for (i <- 0 until iters) {
val start = now
t = t.transformXY { (x, y, h) =>
h + math.sqrt(x * x + y * y)
}
println(s"transformXY: Duration ${now - start}")
}
}
def doTransforms() = {
var t = Container()
for (i <- 0 until iters) {
val start = now
t = t.transform { h =>
h + math.sqrt(h * h * h)
}
println(s"transform: Duration ${now - start}")
}
}
if (true) { // Shows a lot of boxing if enabled
doTransformsXY()
}
if (true) { // Shows a lot of boxing again - if enabled
doTransformsXY()
}
if (true) { // Shows java8.JFunction...apply()
doTransforms()
}
if (true) { // Shows java8.JFunction...apply() if doTransforms() is enabled
doTransformsXY()
}
}
When I run this code and sample it using Java VisualVM, I experience the following:
while doTransformsXY is running, I see a lot of time spent in scala.runtime.BoxesRunTime.boxToDouble()
once doTransforms is running, there is no more significant time spend it boxing, samples show scala.runtime.java8.JFunction2$mcDII$sp.apply() instead
I run doTransformsXY again, there is still no significant boxing, again time grows in scala.runtime.java8.JFunction2$mcDII$sp.apply()
This is with Scala 2.12.4, Windows x64 jdk1.8.0_92
My primary question is about the boxing, which I see in my production code as well:
why is there Double boxing happening in Array.tabulate? Do I need to go procedural (while loops, manual Array creation) to avoid it?
My secondary question is:
why is no more boxing done once I call the transform variant?
why is no more boxing done once I call the transform variant?
I did not reproduce that. If I carefully pause VMs and check with JProfiler, it still does a lot of boxing and allocation of Doubles. Which is what I expected, and I have an explanation for.
Looking at the Function1 and Function2 traits in standard library, we can see #specialized annotations:
trait Function1[#specialized(Int, Long, Float, Double) -T1, #specialized(Unit, Boolean, Int, Float, Long, Double) +R]
trait Function2[#specialized(Int, Long, Double) -T1, #specialized(Int, Long, Double) -T2, #specialized(Unit, Boolean, Int, Float, Long, Double) +R]
but the Function3 is just
trait Function3[-T1, -T2, -T3, +R]
#specialized is how Scala lets you avoid boxing on generics with primitives. But this comes at a price of compiler having to generate additional methods and classes, so beyond a certain threshold it will just produce a ridiculous amount of code (if not crash outright). So Function has, if my math is correct, 4 (specs on T1) x 6 (specs on R) = 24 copies of each specialized method and 24 extra classes in addition to just apply and a generic trait.
Oh, and by the way, those methods are postfixed with $mc and the JNI type signatures. So method ending in $mcDII is a specialized overload that returns a Double, and accepts two Ints as parameters. This is the type of function you're passing into tabulate inside transform, i.e. this part
(x, y) => f(a(x)(y))
While calls to f should show up with $mcDD postfix (returns a Double and accepts a Double).
However, calling
f(x, y, a(x)(y))
will become something like
unbox(f(box(x), box(y), box(a(x)(y))))
So I bothered you enough with the explanation. It's time for solution. To bring boxing of both methods to equivalent shape, create a specialized interface:
trait DoubleFunction3 {
def apply(a: Double, b: Double, c: Double): Double
}
and rewrite your signature in transformXY
def transformXY(f: DoubleFunction3): Container = //... same code
Since it's Scala 2.12 and you have just one abstract method in the trait, you can still pass lambdas, so this code:
t = t.transformXY { (x, y, h) =>
h + math.sqrt(x * x + y * y)
}
requires no change.
Now you might notice that this does not fully eliminate boxing because tabulate causes it too. This is definition of a single-dimensional tabulate:
def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = {
val b = newBuilder[T]
b.sizeHint(n)
var i = 0
while (i < n) {
b += f(i)
i += 1
}
b.result()
}
Note that it works with a generic Builder[T], calling a method +=(elem: T). Builder itself is not specialized, so it will do wasteful boxing/unboxing when creating your arrays. Your fix for this is to write a version that directly uses Double instead of T, for the dimensions you need.

SML NJ , able to find max real of array, cant get index

i have an array of real values like [|1.2, 3.4, 5.3, 2.5|]
fun max_arr arr = foldl Real.max (sub (arr, 0)) arr;
works fine to find the max value 5.3 .
Then i would expect something like
fun max_arri arr = foldli (Real.max(sub (arr, 0))) arr;
to successfully return the location of max value 2.but it doesn't work.
(Error: unbound variable or constructor: max_arri)
I went through everything I could find online but the documentation about sml seems small...
according to the manual they both take the same data. so what would i need to change?
foldli f init arr
foldl f init arr
also i dont want to use lists because i change the data alot
They do not take the same input.
foldl :: ( 'a * 'b -> 'b) -> 'b -> 'a array -> 'b
foldli :: (int * 'a * 'b -> 'b) -> 'b -> 'a array -> 'b
As we can see from the types, the difference is that foldli takes a function that also takes an integer -- the index of the element.
The return type of the two functions are both 'b, so foldli does not return the index. Rather, this expression:
foldli (fn (i, a, b) => f (a, b)) init arr
Is the exact equivalent of this expression:
foldl f init arr
Now, if we want to return the index of an element, we need the 'b in the type of foldli to become int. However, finding the maximum relies on comparison of elements, so we also need the current maximum, just like in your max_arr function. The obvious solution is to use a tuple. 'b now becomes (real * int).
(* cElem = current element
* cI = current index
*)
fun fmax (i, elem : real, (cElem, cI)) =
if cElem > elem
then (cElem, cI)
else (elem, i)
fun max_arri arr = foldli fmax (sub (arr, 0), 0) arr
Of course, this is not the type we want our max_arri to return - we only want the index. The loose helper function isn't very nice either, but it's a bit long to have as a lambda. Instead, we wrap it all in a local:
local
fun fmax (i, elem : real, (cElem, cI)) =
if cElem > elem
then (cElem, cI)
else (elem, i)
fun max_arri' arr = foldli fmax (sub (arr, 0), 0) arr
in
fun max_arri arr = let val (_, i) = max_arri' arr
in i end
end

Finding two minimum values out of four?

So, I have four integers and I need to find out the lowest two out of those four. What would be the most efficient way of doing so in C (or any other language)?
Edit: I need a fixed implementation, for the sake of efficiency as this is a very critical operation that is going to be performed thousands of times.
Here's an efficient implementation using sorting networks:
inline void Sort2(int *p0, int *p1)
{
if (*p0 > *p1)
{
const int temp = *p0;
*p0 = *p1;
*p1 = temp;
}
}
inline void Sort4(int *p0, int *p1, int *p2, int *p3)
{
Sort2(p0, p1);
Sort2(p2, p3);
Sort2(p0, p2);
Sort2(p1, p3);
Sort2(p1, p2);
}
This takes only 5 compares and up to 5 swaps. You can just ignore the results for p2, p3.
Note that for a performance-critical application Sort2 can be implemented without branches in one or two instructions on some architectures.
Just write a loop and keep track of the lowes 2 values ?
Should be at max O(2N) which is i think the best achievable complexity.
The most efficient way? Trying to avoid any extra steps, I got this (in pseudo-code). This will avoid any unnecessary comparisons that you'll get with other more general solutions (specifically ones that don't advantage of the transitive nature of comparison operations).
Bear in mind that this is only thinking about efficiency, not at all aiming for beautiful code.
if a<=b:
if b<=c:
# c too big, which of b and d is smaller?
if b<=d:
return (a,b)
else:
return (a,d)
else if b<=d:
# a and c both < b, and b < d
return (a,c)
else:
# b is > a, c and d. Down to just those three.
if a<=c:
if c<=d:
# a < c < d
return (a,c)
else:
# a and d both < c
return (a,d)
else if d<=a:
# Both c and d < a
return (c,d)
else:
# c < a < d
return (a,c)
else:
# b < a
if a<=c:
# c too big, which of a and d is smaller?
if a<=d:
return (a,b)
else:
return (b,d)
else if a<=d:
# b and c both < a, and a < d
return (b,c)
else:
# a is > b, c and d. Down to just those three.
if b<=c:
if c<=d:
# b < c < d
return (b,c)
else:
# b and d both < c
return (b,d)
else if d<=b:
# Both c and d < b
return (c,d)
else:
# c < b < d
return (b,c)
I think this has a worst case of 5 comparisons and a best case of 3 (obviously there's no way of doing it in less than 3 comparison).
You can get away with exactly 4 comparisons and maximally 4 swaps.
inline void swap(int* i, int* j) {
static int buffer;
buffer = *j;
*j = *i;
*i = buffer;
}
inline void sort2(int* a, int* s) {
if (*s < a[1])
swap(s,a+1);
if (*s < a[0]) // it is NOT sufficient to say "else if" here
swap(s,a);
}
inline void sort4(int* a) {
sort2(a,a+2);
sort2(a,a+3);
}
The result will be sitting the the first to cells, but note that these cells are not necessarily sorted! They're just the smallest elements.
I would make an array out of them, sort and take the first two values.
You can accomplish it with at most 4 comparisons:
compare the first pair of numbers and let the smaller be a1 and the larger be a2
compare the second pair of numbers and let the smaller be a3 and the larger be a4
if a1 >= a4 return (a3, a4)
(now we know that that a1 < a4)
if a3 >= a2 return (a1, a2)
(now we also know that a3 < a2)
return (a1, a3)
To see that this is true, you can check all the combinations of possible returns:
(a1, a2) (a1, a3) (a1, a4)
(a2, a3) (a2, a4)
(a3, a4)
I think you can sort the array and pick the first two elements.

How to apply a function to individual elements of a array/vector

I have a function f(x,a,b,c) and i want to use plot() to display it. That means i have to compute f(x) for each of my x and store them in a vector to use plot().
How can i apply my function to each element of x individually? My function requires 3 arguments aside from the value of x. I've tried arrayfun() but can't seem to get it working...
x = linspace(0.008,0.08);
a = 0.005;
b = 0.0015;
re = (1.23*40*0.005)/(1.79*10^-5);
y = arrayfun(#f, x, a, b, re);
plot(y);
Any ideas?
You could use an anonymous function:
y = arrayfun(#(x) f(x, a, b, re), x);

Resources