-
Notifications
You must be signed in to change notification settings - Fork 2
/
RandomWalkSolver.cs
125 lines (107 loc) · 3.8 KB
/
RandomWalkSolver.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
using System;
using System.Collections.Generic;
using System.Linq;
using lib.Models;
using lib.Models.Actions;
namespace lib.Solvers.RandomWalk
{
public class RandomWalkSolver : ISolver
{
public string GetName()
{
return $"random-walk-{depth}/{tryCount}/{usePalka}/{estimator.Name}";
}
public int GetVersion()
{
return 1;
}
private readonly int depth;
private readonly IEstimator estimator;
private readonly Random random;
private readonly int tryCount;
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 bool usePalka;
private readonly bool useWheels;
public RandomWalkSolver(int depth, IEstimator estimator, Random random, int tryCount, bool usePalka, bool useWheels)
{
this.depth = depth;
this.estimator = estimator;
this.random = random;
this.tryCount = tryCount;
this.usePalka = usePalka;
this.useWheels = useWheels;
}
public Solved Solve(State state)
{
var solution = new List<ActionBase>();
if (usePalka)
BoosterMaster.CreatePalka(state, solution);
while (state.UnwrappedLeft > 0)
{
if (useWheels && state.FastWheelsCount > 0)
{
var useFastWheels = new UseFastWheels();
solution.Add(useFastWheels);
state.Apply(useFastWheels);
}
var part = SolvePart(state);
solution.AddRange(part);
state.ApplyRange(part);
}
return new Solved {Actions = new List<List<ActionBase>> {solution}};
}
public List<ActionBase> SolvePart(State state)
{
//Console.Out.WriteLine("START PART");
var bestEstimation = double.MinValue;
List<ActionBase> bestSolution = null;
for (int i = 0; i < tryCount; i++)
{
var clone = state;//.Clone();
var undoes = new List<Action>();
var solution = SolveStep(clone, undoes);
var estimation = estimator.Estimate(clone, state.SingleWorker);
undoes.Reverse();
foreach (var undo in undoes)
{
undo();
}
//Console.Out.Write($" {estimation} {solution.Format()}");
if (estimation > bestEstimation)
{
bestEstimation = estimation;
bestSolution = solution;
//Console.Out.WriteLine(" -- better");
}
// else
// Console.Out.WriteLine();
}
return bestSolution;
}
private List<ActionBase> SolveStep(State state, List<Action> undoes)
{
var actions = new List<ActionBase>();
while (actions.Count < depth && state.UnwrappedLeft > 0)
{
var action = availableActions[random.Next(availableActions.Length)];
if (action is Move moveAction)
{
var nextPosition = state.SingleWorker.Position + moveAction.Shift;
if (!nextPosition.Inside(state.Map) || state.Map[nextPosition] == CellState.Obstacle)
continue;
}
undoes.Add(state.Apply(action));
actions.Add(action);
}
return actions;
}
}
}