let1 nextsingle (step:Step) (i:int) (solution: Solution) (fullGrid: Map<char,Map<char,Grid>>) : Solutionreceives =
as input which is letthe branchesmove =index solution.tree.branchesi
let2 distancethen =it solution.tree.distanceupdates +the branches.[i].distance
let area = branches.[i].area
//let newbranches, back, keys =
match step with
| SpaceStep ->
of failwiththe "notcurrent expectedsolution withdraft smartby grid"
summing the distance to |the KeyStepvertex ->I
3 it updates the letcurrent keysposition =as areaof ::vertex solution.keysI
4 it also updates the list of predecessors letby gridincluding =vertex fullGrid.[area]i
5 it computes the new tree letof treereachable =vertices grid2treestarting areafrom distancethe keys`fullGrid` grid
and taking into account the newly updated list {keys=keys;of tree=tree}predecessors
Notice that this is a constrained version of the TSP where each vertex can have as constraint a list of predecessors.
let findSolution (keynum:int) (solution: Solution) (fullGrid: Map<char,Map<char,Grid>>) : Solution option =
let mutable solution_queue : queue<Solution> = MyQueue.empty
Start by receiving the solution_queuegraph <-topology enqueueand solution_queuestarting solutionpoint
letDefine mutablea mindistance : int option = Nonevariable
letand mutablea alternativeslist :of Solutioncompleted listsolutions, =initially List.empty
while (MyQueue.length solution_queue > 0) do
Start looping at letthe solutionqueue =of dequeuepartial &solution_queuesolutions
let solution = {solution with tree =So grid2treea solution.tree.areasingle solution.tree.distancepartial solution.keys fullGrid.[solution.tree.area]}
let branches =is solution.tree.branchesdequeued
ifIt computes (branchespossible =vertices [||]based )on thencurrent predecessors
Check if solution.keys.Length = keynum
then updateMin &mindistance &alternatives solution
nothing remains else
and adds it to the completed alternatives otherwise matchupdating mindistance with
| Some d when d < solution.tree.distance + (solution.tree.branches |> Array.map (fun t -> t.distance) |> Array.min) -> ()
| _ ->
let indexes =
[|0..branches.Length-1|]
|> Array.sortBy(fun idx -> ((if isKey branches.[idx].area then 0 else 1) , branches.[idx].distance))
Otherwise forloop ias in indexes do
if branches.[i].area = '#' then
failwith "not expected with smart grid"
classical elseBFS
For all ifpossible branches.[i].areamoves = Space then
failwith "not expected with smartreachable grid"vertices
else
if (Char.IsLower branches.[i].area) then
let solutionNext = next KeyStep i solution fullGrid
For each one applies ifabove solutionNext.keys.Lengthsaid =single keynumstep
then updateMin &mindistance &alternatives solutionNext
If done updates mindistance and completed alternatives else
solution_queue <-Otherwise enqueue solution_queue solutionNext
else
ifsuch (Char.IsUpperpartial branches.[i].area)solution then
failwith "not expected with smart grid"
match alternatives with
| [] -> None
| alternatives ->
Finally alternativesselect |>the List.minBy(funmin aalternative ->by a.tree.distance) |> Some.