I am having trouble interpreting one line in the pseudocode for the FRINGE search algorithm. The line is #3 in the following code:
init(start, goal)
fringe F = s
cache C[start] = (0, null)
flimit = h(start)
found = false
while (found == false) AND (F not empty)
fmin = ∞
for node in F, from left to right
(g, parent) = C[node]
f = g + h(node)
if f > flimit
fmin = min(f, fmin)
continue
if node == goal
found = true
break
for child in children(node), from right to left
g_child = g + cost(node, child)
if C[child] != null
(g_cached, parent) = C[child]
if g_child >= g_cached
continue
if child in F
remove child from F
insert child in F past node
C[child] = (g_child, node)
remove node from F
flimit = fmin
if reachedgoal == true
reverse_path(goal)
The pseudocode was taken from this wiki article: https://en.wikipedia.org/wiki/Fringe_search
I can't figure out what that syntax is saying. Thanks for any help!
A little examination of the code finds that a C entry contains (g, link_to_parent). Where
'g' is the value of g(x) at that node. g(x) is the cost of the
search path from the first node to the current
'link_to_parent' is something that gets you back to the parent. A
pointer perhaps or an index value or even perhaps the name of the
parent. What it is exactly depends on your implementation. The
pseudo-code is using 'null' to indicate no parent.
So line 3 is saying that the start node costs nothing to reach and it has no parent.
C itself is a mapping of node to the pair (g,parent_link).
How C (cache) is implemented is up to you but you need to retain the logic whereby the index of C is synonymous with node and the contents at that node are (g, way_to_indicate_parent).
Related
I'm trying to select the minimum element in a list based on the third value of its elements. But there seems to be a problem with my usage of higher-order functions in the min_proc function. (I'm using SML in CPN Tools)
fun min_process(p1: DATA, p2: DATA) =
if (#3 p1 <= #3 p2)
then p1
else p2;
fun min_proc(l) =
if (l = [])
then empty
else
if (List.length(l) = 1)
then List.hd(l)
else min_process(List.hd(l), min_proc(List.tl(l)));
Error at:
../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
I have the two datatypes:
datatype 'a Tree = LEAF of 'a | NODE of ('a Tree) * ('a Tree)
and
datatype 'a myTree = myLEAF of 'a | myNODE of 'a * 'a * 'a myTree * 'a myTree
With these two, I need to be able to find the min and max values of a tree.
For example:
findMin (NODE(NODE(LEAF(5),NODE(LEAF(6),LEAF(8))),LEAF(4)))
will produce 4.
I have been working on this for some time now, and I'm quite confused.
Any guidance would be helpful. Thank you.
You know that there is at least one element in every 'a Tree, so there is always a min/max.
Use pattern matching on each of the two constructors LEAF and NODE, and use recursion in the NODE case, since the two branches might have different min/max values and the min/max for the node is determined by whatever is min/max for its branches. And use the built-in helper functions Int.min and Int.max, if you're finding the min/max integers of a tree. (Your example suggests that this is the case.)
fun findMin (LEAF x) = (* ... *)
| findMin (NODE (leftTree, rightTree)) =
let (* ... use findMin recursively on each branch ... *)
in (* ... find the minimal value of the two branches ... *)
end
I'm not sure what the 'a myTree type is good for: It is a binary tree in that it has two 'a myTree branches per node, but it also has two 'a elements per node? Should you be interested in finding the min/max of either of those values? Or is one a key and another a value in some tree-based dictionary structure? If so, then why is it 'a -> 'a and not 'a -> 'b? It is hard to solve a problem when you don't understand the problem statement, and the datatype is a large portion of that.
Edit: Since you've provided a solution yourself, let me give some feedback on it:
fun findMin (LEAF(v)) = v
| findMin (NODE(left, right)) =
if findMin(left) < findMin(right)
then findMin(left)
else findMin(right)
This solution is very inefficient since it calls itself three times for each node's entire subtree. That means the number of function calls roughly follows the recurrence relation f(0) = 1 and f(n) = 3 ⋅ f(n-1). This is equivalent to 3n or exponentially many calls to find the minimal element in a list of n elements.
Here is a way that take linear time by temporarily storing the result you use twice:
fun findMin (LEAF v) = v
| findMin (NODE (left, right)) =
let val minLeft = findMin left
val minRight = findMin right
in if minLeft < minRight then minLeft else minRight
end
There is no reason to perform the Herculean task of calculating findMin left and findMin right more than once in every node of the tree. Since we refer to it multiple time, a let-in-end is an easy way to bind the results to lexically scoped names, minLeft and minRight.
The expression if minLeft < minRight then minLeft else minRight actually has a name in the standard library: Int.min. So we could do:
fun findMin (LEAF v) = v
| findMin (NODE (left, right)) =
let val minLeft = findMin left
val minRight = findMin right
in Int.min (minLeft, minRight)
end
But the reason for using a let-in-end has actually evaporated, since, with the help of a library function, we're now only referring to findMin left (aka minLeft) and findMin right (aka minRight) once now. (Actually, we are referring to them more than once, but that is inside Int.min in which the result has also been bound to a temporary, lexically scoped name.)
So we ditch the let-in-end for a much shorter:
fun findMin (LEAF v) = v
| findMin (NODE (left, right)) = Int.min (findMin left, findMin right)
In any case, these are all equally optimal: They use only n recursive function calls for n elements in the tree, which is the least you can do when the elements aren't sorted. Now, if you knew the smaller elements were always to the left, you'd have a binary search tree and you could find the min/max much faster. :-)
Edit (again): Just for fun, you could find the min/max simultaneously:
fun findMinMax (LEAF v) = (v, v)
| findMinMax (NODE (left, right)) =
let val (minLeft, maxLeft) = findMinMax left
val (minRight, maxRight) = findMinMax right
in (Int.min (minLeft, minRight), Int.max(maxLeft, maxRight))
end
I think one problem is that you're thinking hard about how to traverse the tree and check all the nodes in some order and keep track of things, but recursion will handle that for you.
Your tree has two cases; it is either a leaf, or a node with two subtrees.
This suggests that the solution will also have two cases: one for leaves and one for internal nodes.
Write down (in your own words, not code) how you would find the minimum in
a leaf; and
an internal node if you already knew the respective minimums of its subtrees -- don't worry about how to find them yet, but pretend that you know what they are.
Then write down how you find the minimums of the subtrees of an internal node.
(This is a recursion, so you've already solved this problem, before you started thinking about it.)
Then you translate it into ML.
I was 100% just overthinking the problem too much. Thank you both for your help! I got my answer.
fun findMin (LEAF(v)) = v
| findMin (NODE(left, right)) =
if findMin(left) < findMin(right)
then findMin(left)
else findMin(right)
fun findMax (LEAF(v)) = v
| findMax (NODE(left, right)) =
if findMax(left) > findMax(right)
then findMax(left)
else findMax(right)
I am new to SML. I am trying to check whether a given value exist in the binary tree or not. Below is the snippet of the code. Upon execution it gives
Warning : match nonexhaustive (n,Node (t1, j, t2)) => ...
I cannot understand why it is showing this way. I guess I have covered all possible case. Can anyone give me hint or link which will be helpful to remove this warning.
datatype inttree = Empty | Node of inttree * int * inttree;
(*find(n,K) here n is the key that we have to find in inttree K*)
val rec find = fn(n, Node(t1,j,t2)) =>
let
val t = Node(t1, j, t2)
val compare = fn(i,j) => i = j
val find' =
fn (n,Empty) => false (* if we have reached the empty node then we are not able to find the key therefore return false *)
| (n,Node(t1,j,t2)) =>
if compare(n,j)
then true (* if value n and j are equal we have found the key n in the tree*)
else find(n,t1) orelse find(n,t2) (* if the value is not equal check in left subtree if found return true else check in the right subtree*)
in
find'(n,t)
end;
Given your datatype declaration, a fairly direct recursive approach is possible. Since this seems to be homework, I don't want to give a complete solution, but here is a function which has a similar flavor:
fun allEven Empty = true
| allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
This function returns true or false depending on whether or not all integers in the tree are even. It has a basis case
allEven Empty = true
(true since there are no odd numbers in an empty tree to serve as counter-examples) and a recursive case
allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
If the integer at the node is odd, return false -- otherwise return true if the recursive call to both branches evaluate to true.
Typical runs:
- allEven (Node(Node(Empty,3,Empty),5,Node(Node(Empty,6,Empty),7,Empty)));
val it = false : bool
- allEven (Node(Node(Empty,4,Empty),2,Node(Node(Empty,6,Empty),8,Empty)));
val it = true : bool
Your function should be about this long and follow the same basic recursive pattern.
Besides val rec, you can also write fun and specify the arguments on the left-hand side of the =.
The helper function compare is largely redundant. You might as well use =. Also, what one would call a compare function in ML is usually one that returns the type order, having the values LESS, EQUALS and GREATER:
- Int.compare (3, 5);
> val it = LESS : order
When writing an if ... then true else ... or similar statement that returns the type bool, you might as well just use the combinators orelse and andalso. For example, you can replace the following:
if compare(n,j)
then true
else find(n,t1) orelse find(n,t2)
with:
n = j orelse find (n, t1) orelse find (n, t2)
Much like the built-in functions List.exists and List.all take a function as predicate and scans a list in the attempt to prove either that at least one element exists for which this is true, or that it is true for all elements, you can make functions treeExists and treeForall:
datatype intTree = Empty | Node of inttree * int * inttree;
fun treeExists f Empty = false
| treeExists f (Node (leftTree, x, rightTree)) =
f x orelse treeExists f leftTree orelse treeExists f rightTree
fun treeForall f Empty = true
| treeForall f (Node (leftTree, x, rightTree)) =
f x andalso treeForall f leftTree andalso treeExists f rightTree
Making functions find and allEven has now become simpler:
fun find (x, tree) = treeExists (fn y => x = y) tree
fun allEven tree = treeForall (fn x => x mod 2 = 0) tree
since all the recursion has been left to new library functions.
In a similar way, you can make treeMap and treeFold:
fun treeMap f Empty = Empty
| treeMap f (Node (leftTree, x, rightTree)) = ...
fun treeFold f e Empty = e
| treeFold f e (Node (leftTree, x, rightTree)) = ...
They could be used to find the largest absolute value in a tree:
fun maxAbsTree tree =
treeFold Int.max 0 (treeMap Int.abs tree)
Given this following code (which does not work):
fun func() =
val decimal = 0 (* the final result *)
val multiple = 0 (* keeps track of multiples, eg. In XXV, X would be a multiple *)
val current = 0 (* the digit currently being processed *)
val top = 0 (* value of the last element in the list *)
val last_add = 0 (* the last digit that wasn't a multiple, or subtraction operation *)
val last_sub = 0
val problem = 0 (* if value is 1 then there is a problem with the input *)
val myList = [1,2,3,4,5] (* the list has more values *)
val current = tl(myList) (* grab the last element from the list *)
val myList = tl(myList) (* remove the last element from the list *)
val top = tl(myList) (* grab the value at the end of the list *)
while (not(myList = [])) (* run while the list is not empty *)
if ( (not(myList = [])) andalso (current > top))
then
val decimal = decimal + current - top
val last_sub = top;
val myList = tl(myList)
else
if ( (myList = []) andalso (current = top))
then val decimal = decimal + current
val multiple = multiple + 1
else
if (last_sub = current)
then val problem = 1
else
val decimal = decimal + current
val multiple = 0
val last_add = current
This is only a partial code , which doesn't work at the moment , since the val is not
possible within an if statement .
I want to run in a while loop , how can I do that in ML ?
How can I assign and reassign values into variables that were previously declared in ML ?
The val keyword is not possible within the IF condition , so I cannot update the variables , any idea how to solve that ?
Regards
How can I assign and reassign values into variables that were
previously declared in ML ?
You cannot assign to variables after they are declared in ML.
The val keyword is not possible within the IF condition , so I cannot
update the variables , any idea how to solve that ?
Except at the top level, you usually use val and fun inside a let:
let
val x = blah blah
val y = blah blah
fun f x y = blah blah
in
some expression
end
However, note that this creates a new variable (which may hide any existing variable of the same name), which exists inside the scope of the body of the let. As said before, you cannot assign to an existing variable.
I want to run in a while loop , how can I do that in ML ?
You are almost there. The syntax is while condition do ( ... ). But a while loop is useless without mutable state.
If you want mutable state, you can use a mutable data structure. The language provides a simple "mutable cell" called ref: you create it by passing the initial value to the ref function, you get the current value with the ! operator, and you set a new value with the := operator. You also have to remember that if you want to run multiple imperative "statements", you must separate them with the ; operator, and possibly enclose the whole "block" of statements in parentheses due to precedence issues.
But using while loops and mutable state is really not the right way to go here. You are using a functional language, and it would be much better for you to re-write your algorithm to be purely functional. It's not hard to do. You would turn the body of your while loop into a tail-recursive helper function, and the "variables" that change between iterations of the loop would become arguments to this function. Instead of trying to "set" the values of these variables, it would simply recursively call itself with the new values for the next iteration. If it's tail-recursive, it's equivalent to iteration memory-wise.
A special type of tree is given, Where all leaf are marked with distinct symbols and all others nodes are marked with dummy character 0. every node can have 0 or at most 2 nodes. Trees inorder traversal is written to file. Please give a algorithm to build tree from this traversal.
the problem as explained in the question is unsolveable, because there can be more then one tree for a given in-order traversal, even if the leaves are well known. (in the example attached, the in order for both trees is 1,2,3,4,5 and 1,3,5 are leaves in both).
you might want to store both inorder traversal and pre-prder traversal, and from there, there is a simple recursive algorithm to reconstruct the tree:
reconstruct(List preOrder,List inOrder):
if preOder.empty() == true:
return nil
root.value<-preOrder[0]
left_in = inOrder.filter(left,root) (*)
left_pre = preOrder.filter(left,root) (*)
root.left = reconstruct(left_pre,left_in)
right_in = inOrder.filter(right,root) (*)
right_pre = preOrder.filter(right,root) (*)
root.right= reconstruct(right_pre,right_in)
return root
(*) the filter finds all elements left/right to the root (in the in-order) and returns it, for pre-order it returns the same set of nodes in-order returned, but as they appear in the pre-order list.
attached: example described above:
EDIT: added stop condition for the recursive algorithm.
EDIT 2:
the filter will look something like that (pseudo code) (assuming each element is unique):
inOrderFilter(list,root):
i <- 0
left <- [] (empty list)
right <- []
while (list[i] != root):
left.add(list[i])
i <- i+1
while (i < list.size):
right.add(list[i[)
i <- i+1
return pair(left,right)
preOrderFilter(list,left_in,right_in):
left <- []
right <- []
for each e in list:
if e in left_in:
left.add(e)
else if e in right_in:
right.add(e)
return pair (left,right)
basically, for the left_in you need everything left of the root, and for right_in you need everything right of the root (left and right according to the in order list).
for left_pre, and right_pre: you need a permutations of left_in,right_in, each of them should have the same elements that XXX_in has, but they should retain the order they had in the original pre-order.