Advertisement
Guest User

Untitled

a guest
May 25th, 2015
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.13 KB | None | 0 0
  1. #light
  2.  
  3. //------------ Generic A* starts here --------------
  4.  
  5. type Graph<'a,'b > =
  6. { H_score: 'a -> 'b;
  7. Separation: 'a -> 'a -> 'b;
  8. Neighbours: 'a -> 'a list;
  9. Zero: 'b;}
  10.  
  11. let rec reconstruct_path came_from node =
  12. match Map.find node came_from with
  13. | None ->
  14.  
  15. node :: []
  16. | value ->
  17. node :: reconstruct_path came_from value;;
  18.  
  19. let rec update graph x y old_f old_g old_from g_value =
  20. let key_f = Map.containsKey y old_f
  21. let key_g = Map.containsKey y old_g
  22. let key_from = Map.containsKey (Some y) old_from
  23. match (key_f, key_g, key_from) with
  24. | ( true ,_,_) -> update graph x y (Map.remove y old_f) old_g old_from g_value
  25. | (_, true ,_) -> update graph x y old_f (Map.remove y old_g) old_from g_value
  26. | (_,_, true ) -> update graph x y old_f old_g (Map.remove (Some y) old_from) g_value
  27. | _ ->
  28. let new_from = Map.add (Some y) (Some x) old_from
  29. let new_g = Map.add y g_value old_g
  30. let new_f = Map.add y (g_value + (graph.H_score y)) old_f // Estimated total distance from start to goal through y.
  31. (new_f, new_g, new_from);;
  32.  
  33. let rec scan graph x neighbours openset closedset f g from =
  34. match neighbours with
  35. | [] -> (openset, f, g, from)
  36. | y::n ->
  37. if Set.contains y closedset then
  38. scan graph x n openset closedset f g from
  39. else
  40. let g0 = Map.find x g
  41. let trial_g = g0 + graph.Separation x y
  42. if Set.contains y openset then
  43. let old_g = Map.find y g
  44. if trial_g < old_g then
  45. let (new_f, new_g, new_from) = update graph x y f g from trial_g
  46. scan graph x n openset closedset new_f new_g new_from
  47. else
  48. scan graph x n openset closedset f g from
  49. else
  50. let new_open = Set.add y openset
  51. let (new_f, new_g, new_from) = update graph x y f g from trial_g
  52. scan graph x n new_open closedset new_f new_g new_from;;
  53.  
  54. let best_step graph openlist score =
  55. let choice score h best best_value =
  56. let v = Map.find h score
  57. match best with
  58. | None -> ((Some h), v)
  59. | _ when Some v < Some best_value -> ((Some h), v)
  60. | _ -> (best, best_value)
  61.  
  62. let rec best_step4 openlist score best best_value =
  63. match openlist with
  64. | [] -> best
  65. | h::tail ->
  66. let pair = choice score h best best_value
  67. match pair with
  68. | (next, next_value) -> best_step4 tail score next next_value
  69.  
  70. match openlist with
  71. | [] -> None
  72. | list ->
  73.  
  74. best_step4 list score None graph.Zero;;
  75.  
  76. let astar graph start goal =
  77. let rec astar_step graph goal closedset openset f_score g_score came_from =
  78. match Set.count openset with
  79. | 0 ->
  80. None;
  81. |_ ->
  82. let l = Set.toList openset
  83. let pt = best_step graph l f_score
  84.  
  85. if (Some goal) = pt then
  86. let path = reconstruct_path came_from (Some goal)
  87. Some path
  88. else
  89. match pt with
  90. | None -> None
  91. | Some x ->
  92. let next_open = Set.remove x openset
  93. let next_closed = Set.add x closedset
  94. let neighbours = graph.Neighbours x
  95.  
  96. let (new_open, new_f, new_g, new_from) = scan graph x neighbours next_open next_closed f_score g_score came_from
  97. astar_step graph goal next_closed new_open new_f new_g new_from
  98.  
  99. let closedset = Set.empty // The set of nodes already evaluated.
  100. let openset = Set.add start Set.empty // The set of tentative nodes to be evaluated
  101.  
  102. let f_score = Map.add start (graph.H_score start) Map.empty
  103. let g_score = Map.add start graph.Zero Map.empty
  104.  
  105. let came_from = Map.add (Some start) None Map.empty
  106.  
  107. astar_step graph goal closedset openset f_score g_score came_from;;
  108.  
  109. //------------ Generic A* ends here ----------------
  110.  
  111. // specialize for the torch-carrier problem
  112. // bits 0-4 represent torch, 1m, 2m, 5m, 10m
  113. // set bit = on the near side
  114.  
  115. // Every possible crossing of one or two
  116. let swaps =
  117. [3;5;9;17; 7; 11;13; 19;21;25];;
  118.  
  119. let crossing_time swap =
  120. match swap with
  121. | x when x > 16 -> 10.0
  122. | x when x > 8 -> 5.0
  123. | x when x > 4 -> 2.0
  124. | _ -> 1.0
  125.  
  126. let neighbour_nodes x =
  127. let equivalent_point x =
  128. match x &&& 1 with
  129. | 1 -> x
  130. | _ -> 31^^^x
  131.  
  132. let rec compatible x y outlist inlist =
  133. match inlist with
  134. | [] -> outlist
  135. | swap::tail when (y &&& swap) = swap ->
  136. let newlist = (x^^^swap)::outlist
  137. compatible x y newlist tail
  138. | swap2::tail2 -> compatible x y outlist tail2
  139.  
  140. compatible x (equivalent_point x) [] swaps;;
  141.  
  142. let dist_between x y =
  143. crossing_time (x^^^y);;
  144.  
  145. // presentation form
  146. let rec display swap =
  147. let decorate value =
  148. match value with
  149. | "" -> value
  150. | _ -> sprintf "+%s" value
  151.  
  152. let rec compound swap bit =
  153. sprintf "%d%s" (int (crossing_time swap)) (decorate (display (swap^^^bit)))
  154.  
  155. match swap with
  156. | x when x > 16 -> compound swap 16
  157. | x when x > 8 -> compound swap 8
  158. | x when x > 4 -> compound swap 4
  159. | x when x > 2 -> compound swap 2
  160. | _ -> "" ;;
  161.  
  162.  
  163.  
  164. let rec print_result path prev time =
  165. let print_swap swap from =
  166. let transition = display swap
  167. match from &&& 1 with
  168. | 1 -> printfn " %s -->" transition
  169. | _ -> printfn "<-- %s" transition
  170.  
  171. match path with
  172. | [] -> time
  173. | (Some h)::trace ->
  174. let swap = h^^^prev
  175. print_swap swap h
  176. let interval = time + (crossing_time swap)
  177. print_result trace h interval
  178. | _ -> failwith "Incomplete route" ;;
  179.  
  180.  
  181. let main =
  182. let g = {H_score=crossing_time;
  183. Separation=dist_between;
  184. Neighbours=neighbour_nodes;
  185. Zero=0.0}
  186. match astar g 31 0 with
  187. | Some((Some h)::trace) ->
  188.  
  189. let time = print_result trace h 0.0
  190. printfn "Time taken = %d minutes" (int time)
  191. | _ -> printfn "No solution" ;;
  192.  
  193. printfn "----" ;;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement