I have been through an issue while I was implementing a function that give me a path from a source node to a destination node using BFS. I'm using BFS to find a path because I want my path to have levels which are growing. For instance, in this graph, I would like to have the following path:[s,2,4,3,t] . But my path current path looks like this: [s,2,4,1,t]
.
Here my bfs implementation:
let rec bft_from dst node_to_string g acc (seen, to_treat) = match G.NodeSet.choose_opt to_treat with | None -> None (* Plus de nœuds à traiter, chemin non trouvé *) | Some (el, elw) -> let _ = Printf.printf "starting new level on %s \n" (node_to_string el) in let seen_after_level, to_treat_next_level = G.NodeSet.fold (fun (s, sw) (seen_before_s, to_treat_next_level_before_s) -> if G.NodeSet.exists (fun (a, _) -> a = s) seen_before_s then (seen_before_s, to_treat_next_level_before_s) else let _ = Printf.printf "visiting %s \n" (node_to_string s) in let seen_before_s_plus_s = G.NodeSet.add (s, sw) seen_before_s in let succs_s = G.succs g s in let to_treat_next_level_after_s = G.NodeSet.fold (fun (t, wt) to_treat_next_level_before_t -> if G.NodeSet.exists (fun(a,_) -> a=t) seen_before_s_plus_s then to_treat_next_level_before_t else let _ = Printf.printf "Ajout de %s à traiter\n" (node_to_string t) in G.NodeSet.add (t, wt) to_treat_next_level_before_t ) succs_s to_treat_next_level_before_s in (seen_before_s_plus_s, to_treat_next_level_after_s) ) to_treat (seen, G.NodeSet.empty) in if G.NodeSet.exists (fun (a, _) -> a = dst) seen_after_level then let _ = Printf.printf "\n" in let _ = Printf.printf "ajout de %s \n" (node_to_string el) in Some (List.rev (el :: acc)) (* Construire le chemin *) else let _ = Printf.printf "\n" in let _ = Printf.printf "ajout de %s \n" (node_to_string el) in bft_from dst node_to_string g (el :: acc) (seen_after_level, to_treat_next_level)
val bft_from : node -> (node->string) -> graph -> node list ->(G.NodeSet.t*G.NodeSet.t) -> node list option
It is an implementation for a weighted graph. To implement weighted graph, I decided that G.NodeSet.elt
would be of type (node*int)
with int
the weight. So if I have to take all the successors of "4" for instance , I will have a NodeSet
with {("1",6),("3,6)}
.
Now, the problem is the path that the bfs give me.I have tried to put some Printf.printf
to know what it happens. Always in this graph, I tried to use my function to find a path from s
to t
and here what happens:
starting new level on svisiting sAdd 2 in to_treatAdd s in liststarting new level on 2visiting 2Add 4 in to_treatAdd 2 in liststarting new level on 4visiting 4Add 1 in to_treatAdd 3 in to_treatAdd 4 in liststarting new level on 1visiting 1visiting 3Add t in to_treatAdd 1 in liststarting new level on tvisiting tAdd t in list
and here my path: [s 2 4 1 t]
. Why is there a starting new level on "1" and not on "3" ? How can I go to a starting new level on "3" instead of "1" ? Because if we see the graph, there is no path from "1" to "t" .