You must understand that when you write
List.map (fun x -> find_shortest_path xm) (find_next_step n))
You literally calculate the entire “shortest path from here” from all possible neighbors - then calculate the minimum of all these results.
So, there is an infinite loop in your code: if you start at position A and try to calculate the shortest path from one of your neighbors B , then find_shortest_path called from B will inevitably try to see how long the path will be if its first step was to return to A Thus, among all the possible steps that will also be checked, you will calculate the "length" of the ABABAB... cycle, that is, the cycle is infinite.
There are several ways to avoid this problem (which is not related to OCaml programming per se, this is a mistake in your program logic that will appear in any language):
use the width search instead of the depth search, so that you gradually study all the paths of a given length, stopping at the smallest winning path that you find; if you want, this is consistent with exploring all paths in parallel, so you don't have to have infinite paths until you stop (because you found another solution) before trying to search for the entire infinite path.
mark the places that you have already visited so as not to “return” (this will never be the shortest way to achieve the goal)
If you use a depth search, this is delicate because these labels must be local to the search (you cannot just mutate the matrix of logical elements); for example, you can add an int list parameter to your find_shortest_path functions, which will be a list of places that are part of the path being examined; Before trying to calculate the shortest path from possible neighbors, check to see if there is any in this list. For something more efficient, you can use the set ( module IntSet = Set.Make(struct type t = int let compare = Pervasives.compare) ) (logarithmic, not linear, membership criteria) or use a mutable logical matrix, where you careful to change the return status when you choose a different path.
If you use a breadth-first search, you can use the global logic matrix from the “places you've already visited”, since you simultaneously study all the paths to a certain length; therefore, if you come across a place that is already marked as visited, you know that the other path visited it at an earlier time, so that it is already ahead of you, and there is no point in trying to get the shortest path from there.
So, the short answer is: you should find out about the search in the first place.
source share