-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPlanSolver.cs
107 lines (92 loc) · 3.28 KB
/
PlanSolver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System;
using System.Collections.Generic;
using System.Linq;
using lib.Models;
using lib.Models.Actions;
namespace lib.Solvers.RandomWalk
{
public class PlanSolver : ISolver
{
private readonly int depth;
public string GetName()
{
return $"plan-{depth}";
}
public int GetVersion()
{
return 1;
}
private readonly ActionBase[] availableActions =
{
new Rotate(true),
new Rotate(false),
new Move("0,1"),
new Move("0,-1"),
new Move("1,0"),
new Move("-1,0")
};
private readonly List<List<ActionBase>> chains;
private readonly PlanWorkerEstimator estimator;
public PlanSolver(int depth)
{
this.depth = depth;
chains = availableActions.Select(x => new List<ActionBase> {x}).ToList();
for (int i = 1; i < depth; i++)
{
chains = chains.SelectMany(c => availableActions.Select(a => c.Concat(new[] {a}).ToList())).ToList();
}
estimator = new PlanWorkerEstimator();
}
public Solved Solve(State state)
{
var solution = new List<ActionBase>();
foreach (var clusterId in state.ClustersState.Path)
{
while (state.ClustersState.Unwrapped[(0, clusterId)] != 0)
{
var part = SolvePart(state, clusterId);
state.ApplyRange(part);
solution.AddRange(part);
}
}
return new Solved {Actions = new List<List<ActionBase>> {solution}};
}
public List<ActionBase> SolvePart(State state, int clusterId)
{
var bestEstimation = double.MinValue;
List<ActionBase> bestSolution = null;
foreach (var chain in chains)
{
var undos = new List<Action>();
var solution = new List<ActionBase>();
foreach (var action in chain)
{
if (action is Move moveAction)
{
var nextPosition = state.SingleWorker.Position + moveAction.Shift;
if (!nextPosition.Inside(state.Map) || state.Map[nextPosition] == CellState.Obstacle)
continue;
}
undos.Add(state.Apply(action));
solution.Add(action);
if (state.UnwrappedLeft == 0 || state.ClustersState.Unwrapped[(0, clusterId)] == 0)
break;
}
var estimation = estimator.Estimate(state, state.SingleWorker, clusterId);
//Console.Out.Write($" {estimation} {solution.Format()}");
if (estimation > bestEstimation)
{
bestEstimation = estimation;
bestSolution = solution;
//Console.Out.WriteLine(" -- better");
}
// else
// Console.Out.WriteLine();
undos.Reverse();
foreach (var undo in undos)
undo();
}
return bestSolution;
}
}
}