Can't do backtrack research in OCaml - search

I am trying to solve the puzzle 15 game in OCaml. I almost did everything.. except for the core function of the program, the depth first search function.
This is what my function looks like now:
let df_search_path (Graph next) start =
let rec from_node visited a =
print(a);
if List.mem a visited then raise Fail
else if goal(a) then [a]
else a::from_list (a::visited) (next a)
and from_list visited nextA = match visited with
[] -> raise Fail
| nextA::rest -> try from_node visited nextA
with Fail -> from_list visited rest
in from_node [] start;;
Graph is a graph, next is a function that searches for the 2,3 or 4 next moves (I move the empty space), goal is a function to check if current a state is the goal and Fail is a normal exception.
I tried a lot all the other functions and they works well.
This function endlessy loops always in the starting state, and I can't understand why.
print is a custom function to print the state a in a friendly form.
What am I doing wrong? I'm making my test using a state "1 move" far from the solution, just a "go down" will solve this.. but it is stuck in the first state, always printing the start configuration!

I suspect your error is only the match visited with .. instead of match nextA with ... in from_list.
let df_search_path (Graph next) start =
let rec from_node visited a =
print(a);
if List.mem a visited then raise Fail
else if goal(a) then [a]
else a::from_list (a::visited) (next a)
and from_list visited nextA = match nextA with
| [] -> raise Fail
| nextA::rest -> try from_node visited nextA
with Fail -> from_list visited rest
in from_node [] start;;
That said, there are other ways the code could be improved: currently, "visited" only stores the node that have been visited by this search path, instead of all the nods visited so far; moving to a data structure that is preserved globally and shared between all the "children searches" of any node would reduce the number of useless searches (if you only want a path that leads to the goal).
Finally, using a list here is a rather bad idea as List.mem takes time linear in the size of the list; this gives an overall quadratic behavior. You should rather use a data structure specialized in membership checking, such as Set (or maybe a datastructure that corresponds to your problem domain: in labyrinth-like searches for example, a matrix of booleans is usually simpler and more efficient).

It's difficult to see exactly how this code is supposed to work. Here's something I see:
You calculate a list of nodes to visit (it appears) with next a. In the from_list function, you don't use this list. Instead you rename the first element of the visited list as nextA and revisit that. It seems you're simply revisiting the first already visited node over and over. I don't see why from_list would care about the visited nodes at all. Most likely it would just pass the list along to from_node.

Related

Permutation to disjoint cycles in Haskell

I was trying to implement permutation to cycles in Haskell without using Monad. The problem is as follow: given a permutation of numbers [1..n], output the correspondence disjoint cycles. The function is defined like
permToCycles :: [Int] -> [[Int]]
For the input:
permToCycles [3,5,4,1,2]
The output should be
[[3,4,1],[5,2]]
By the definition of cyclic permutation, the algorithm itself is straightforward. Since [3,5,4,1,2] is a permutation of [1,2,3,4,5], we start from the first element 3 and follow the orbit until we get back to 3. In this example, we have two cycles 3 -> 4 -> 1 -> 3. Continue to do so until we traverse all elements. Thus the output is [[3,4,1],[5,2]].
Using this idea, it is fairly easy to implement in any imperative language, but I have trouble with doing it in Haskell. I find something similar in the module Math.Combinat.Permutations, but the implementation of function permutationToDisjointCycles uses Monad, which is not easy to understand as I'm a beginner.
I was wondering if I could implement it without Monad. Any help is appreciated.
UPDATE: Here is the function implemented in Python.
def permToCycles(perm):
pi_dict = {i+1: perm[i]
for i in range(len(perm))} # permutation as a dictionary
cycles = []
while pi_dict:
first_index = next(iter(pi_dict)) # take the first key
this_elem = pi_dict[first_index] # the first element in perm
next_elem = pi_dict[this_elem] # next element according to the orbit
cycle = []
while True:
cycle.append(this_elem)
# delete the item in the dict when adding to cycle
del pi_dict[this_elem]
this_elem = next_elem
if next_elem in pi_dict:
# continue the cycle
next_elem = pi_dict[next_elem]
else:
# end the cycle
break
cycles.append(cycle)
return cycles
print(permToCycles([3, 5, 4, 1, 2]))
The output is
[[3,4,1],[5,2]]
I think the main obstacle when implementing it in Haskell is how to trace the marked (or unmarked) elements. In Python, it can easily be done using a dictionary as I showed above. Also in functional programming, we tend to use recursion to replace loops, but here I have trouble with thinking the recursive structure of this problem.
Let's start with the basics. You hopefully started with something like this:
permutationToDisjointCycles :: [Int] -> [[Int]]
permutationToDisjointCycles perm = ...
We don't actually want to recur on the input list so much as we want to use an index counter. In this case, we'll want a recursive helper function, and the next step is to just go ahead and call it, providing whatever arguments you think you'll need. How about something like this:
permutationToDisjointCycles perm = cycles [] 0
where
cycles :: [Int] -> Int -> [[Int]]
cycles seen ix = ...
Instead of declaring a pi_dict variable like in Python, we'll start with a seen list as an argument (I flipped it around to keeping track of what's been seen because that ends up being a little easier). We do the same with the counting index, which I here called ix. Let's consider the cases:
cycles seen ix
| ix >= length perm = -- we've reached the end of the list
| ix `elem` seen = -- we've already seen this index
| otherwise = -- we need to generate a cycle.
That last case is the interesting one and corresponds to the inner while loop of the Python code. Another while loop means, you guessed it, more recursion! Let's make up another function that we think will be useful, passing along as arguments what would have been variables in Python:
| otherwise = let c = makeCycle ix ix in c : cycles (c ++ seen) (ix+1)
makeCycle :: Int -> Int -> [Int]
makeCycle startIx currentIx = ...
Because it's recursive, we'll need a base case and recursive case (which corresponds to the if statement in the Python code which either breaks the loop or continues it). Rather than use the seen list, it's a little simpler to just check if the next element equals the starting index:
makeCycle startIx currentIx =
if next == start
then -- base case
else -- recursive call, where we attach an index onto the cycle and recur
where next = perm !! i
I left a couple holes that need to be filled in as an exercise, and this version works on 0-indexed lists rather than 1-indexed ones like your example, but the general shape of the algorithm is there.
As a side note, the above algorithm is not super efficient. It uses lists for both the input list and the "seen" list, and lookups in lists are always O(n) time. One very simple performance improvement is to immediately convert the input list perm into an array/vector, which has constant time lookups, and then use that instead of perm !! i at the end.
The next improvement is to change the "seen" list into something more efficient. To match the idea of your Python code, you could change it to a Set (or even a HashSet), which has logarithmic time lookups (or constant with a hashset).
The code you found Math.Combinat.Permutations actually uses an array of Booleans for the "seen" list, and then uses the ST monad to do imperative-like mutation on that array. This is probably even faster than using Set or HashSet, but as you yourself could tell, readability of the code suffers a bit.

Generator in Haskell list comprehension not working

I am trying to generate a list which will contain a list of solutions for the problem I am trying to solve. I am doing this using list comprehension, generating all possible combinations and then using a predicate to filter so that only solutions are included. Here is my code.
solveRow :: Row -> [Row]
solveRow (Row target rowCells) =
[(cellsToRow target cls) | (cls <- (cellPermutations rowCells)), (result cls)==target]
cellPermutations returns [[Cell]] and therefore cls should be of type [Cell]. When I try to compile I get an error.
I thought <- passed each element of right hand side (in this case [Cell]) to the left hand side variable. Why am I getting a parse error for <-?
Don’t put brackets around cls <- (cellPermutations rowCells) — that’s a syntax error. You don’t need brackets around cellsToRow target cls either, although doing so isn’t an error. (And strictly speaking, you don’t need brackets around result cls either, but I personally think that those brackets make it more readable.) So your example should be:
solveRow :: Row -> [Row]
solveRow (Row target rowCells) =
[cellsToRow target cls | cls <- (cellPermutations rowCells), (result cls)==target]

Need help storing the previous element of a list (Haskell)

I'm currently working on an assignment. I have a function called gamaTipo that converts the values of a tuple into a data type previously defined by my professor.
The problem is: in order for gamaTipo to work, it needs to receive some preceding element. gamaTipo is defined like this: gamaTipo :: Peca -> (Int,Int) -> Peca where Peca is the data type defined by my professor.
What I need to do is to create a funcion that takes a list of tuples and converts it into Peca data type. The part that im strugling with is taking the preceding element of the list. i.e : let's say we have a list [(1,2),(3,4)] where the first element of the list (1,2) always corresponds to Dirt Ramp (data type defined by professor). I have to create a function convert :: [(Int,Int)] -> [Peca] where in order to calculate the element (3,4) i need to first translate (1,2) into Peca, and use it as the previous element to translate (3,4)
Here's what I've tried so far:
updateTuple :: [(Int,Int)] -> [Peca]
updateTuple [] = []
updateTuple ((x,y):xs) = let previous = Dirt Ramp
in (gamaTipo previous (x,y)): updateTuple xs
Although I get no error messages with this code, the expected output isn't correct. I'm also sorry if it's not easy to understand what I'm asking, English isn't my native tongue and it's hard to express my self. Thank you in advance! :)
If I understand correctly, your program needs to have a basic structure something like this:
updateTuple :: [(Int, Int)] -> [Peca]
updateTuple = go initialValue
where
go prev (xy:xys) =
let next = getNextValue prev xy
in prev : (go next xys)
go prev [] = prev
Basically, what’s happening here is:
updateTuple is defined in terms of a helper function go. (Note that ‘helper function’ isn’t standard terminology, it’s just what I’ve decided to call it).
go has an extra argument, which is used to store the previous value.
The implementation of go can then make use of the previous value.
When go recurses, the recursive call can then pass the newly-calculated value as the new ‘previous value’.
This is a reasonably common pattern in Haskell: if a recursive function requires an extra argument, then a new function (often named go) can be defined which has that extra argument. Then the original function can be defined in terms of go.

How to guard this case

I have this function to try and "register" matches in a list of lists :
processMatch :: String -> POSIXTime -> [[(String, POSIXTime)]] -> [[(String, POSIXTime)]]
processMatch host time hostList =
case hostList of
[] -> [[(host, time)]]
((host, t):x):tail -> ((host, t):(host, time):x):tail
x:t -> x:(processMatch host time t)
The problem with this is that host is re-declared with a new value, instead of being a condition. So whatever host matches, I end up just adding it to the first matche's list.
I imagine I need to use a guard instead, but I can't figure out how to deconstruct my lists like that in a guard, is it even possible ?
I could just do it another way with a few conditions but I'm curious to know if it's even possible to do it simply like that.
Thanks !
I would start by defining a helper function that closes over host and time. Along side that, you can name the pair (host, time) as it will be used in two different places in the definition of the helper.
The helper uses a case expression to pattern-match only the head of an inner list, rather than trying to match the entire host list.
In the pattern that matches a host/time pair, you need to use a separate variable to capture the existing host, then compare that to host in a guard. You can only match literals directly in a pattern
processMatch :: String -> POSIXTime -> [[(String, POSIXTime)]] -> [[(String, POSIXTime)]]
processmatch host time lst = go lst
where newPair = (host, time)
go [] = [[newPair]]
go (head:tail) = case head of
(h,t):rest | h == host ->((h,t):newPair:rest):tail
otherwise -> head : go tail
As an aside, a previous typo used an undefined name first, which came from an at-pattern in a previous version of the answer. It's probably actually worth using, but I'll mention here rather than edit the main answer:
first#(h,_):rest | h == host -> (first:newPair:rest):tail
This accomplishes two things: 1) it avoids the repetition of (h,t) on both sides; 2) it avoids giving a name to the matched time, which you don't really care about as long as you have first to refer to the pair itself.

Test for positions- function

positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (x',i) <- zip xs [0..], x == x']
i need to create a Test function for the positions function, which passes the quickcheck.
Does someone has an idea?
A possible test could perform the following operations:
randomly generate xs, ys :: [Int] and y :: Int
define list = xs ++ y : ys
test length xs `elem` positions y list
You might also want to write tests for missing elements.
That being said, it's weird to craft tests from the code. One should design test using the specification used to write the code instead. Otherwise, if the code has some quirks, they end up in tests as well: instead of checking for what the code should do, we check for what the code does, which can be pointless.
Good question! I had a bit of trouble with this too when I started using QuickCheck, but as I used it more I started to get a feel for what sort of properties you should test. Often, a good place to start is to think about what sort of relationships should hold between the input(s) and output. Your function finds the indices of an element in a list; now what properties should hold in this case? Here's two which I can think of:
The list of indices should have the same number of elements as there are occurrences of the value in the list.
Each index should correspond to the correct value.
And here's an outline of how these properties could be tested:
Generate a random list, apply positions to it, then count the number of indices returned and check that it matches with the number of occurrences of the searched value.
Generate a random list, then apply positions to it and check that the element at each of the returned indices is the value which was searched for.
I also think that #chi's answer makes a good point in saying that you should design tests from the specification rather than the code; this ties in with what I was saying above, in that a specification can help you find relationships between input(s) and output which may not be immediately apparent from the code.

Resources