Decoupled simulator instance from solver

multithread soon, but holy crap multithreaded tree stuff is annoying
This commit is contained in:
Asriel Camora
2023-07-03 21:01:18 +02:00
parent ec596f400d
commit 2e9d1e899e
3 changed files with 38 additions and 37 deletions
+10 -11
View File
@@ -19,17 +19,7 @@ public class Simulator
public bool IsFirstStep => State.StepCount == 0; public bool IsFirstStep => State.StepCount == 0;
public CompletionState CompletionState public CompletionState CompletionState => CalculateCompletionState(State);
{
get
{
if (Progress >= Input.Recipe.MaxProgress)
return CompletionState.ProgressComplete;
if (Durability <= 0)
return CompletionState.NoMoreDurability;
return CompletionState.Incomplete;
}
}
public virtual bool IsComplete => CompletionState != CompletionState.Incomplete; public virtual bool IsComplete => CompletionState != CompletionState.Incomplete;
public IEnumerable<ActionType> AvailableActions => ActionUtils.AvailableActions(this); public IEnumerable<ActionType> AvailableActions => ActionUtils.AvailableActions(this);
@@ -276,4 +266,13 @@ public class Simulator
public void IncreaseQuality(float efficiency) => public void IncreaseQuality(float efficiency) =>
IncreaseQualityRaw(CalculateQualityGain(efficiency, false)); IncreaseQualityRaw(CalculateQualityGain(efficiency, false));
public static CompletionState CalculateCompletionState(SimulationState state)
{
if (state.Progress >= state.Input.Recipe.MaxProgress)
return CompletionState.ProgressComplete;
if (state.Durability <= 0)
return CompletionState.NoMoreDurability;
return CompletionState.Incomplete;
}
} }
+6 -4
View File
@@ -9,10 +9,7 @@ public sealed class Simulator : SimulatorNoRandom
{ {
private readonly int maxStepCount; private readonly int maxStepCount;
public new CompletionState CompletionState => public new CompletionState CompletionState => CalculateCompletionState(State, maxStepCount);
(ActionCount + 1) >= maxStepCount ?
CompletionState.MaxActionCountReached :
(CompletionState)base.CompletionState;
public override bool IsComplete => CompletionState != CompletionState.Incomplete; public override bool IsComplete => CompletionState != CompletionState.Incomplete;
public Simulator(SimulationState state, int maxStepCount) : base(state) public Simulator(SimulationState state, int maxStepCount) : base(state)
@@ -168,4 +165,9 @@ public sealed class Simulator : SimulatorNoRandom
ret.AddAction(action); ret.AddAction(action);
return ret; return ret;
} }
public static CompletionState CalculateCompletionState(SimulationState state, int maxStepCount) =>
(state.ActionCount + 1) >= maxStepCount ?
CompletionState.MaxActionCountReached :
(CompletionState)CalculateCompletionState(state);
} }
+22 -22
View File
@@ -4,8 +4,6 @@ using System.Diagnostics.Contracts;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using Node = Craftimizer.Solver.Crafty.ArenaNode<Craftimizer.Solver.Crafty.SimulationNode>; using Node = Craftimizer.Solver.Crafty.ArenaNode<Craftimizer.Solver.Crafty.SimulationNode>;
namespace Craftimizer.Solver.Crafty; namespace Craftimizer.Solver.Crafty;
@@ -14,39 +12,39 @@ namespace Craftimizer.Solver.Crafty;
public class Solver public class Solver
{ {
public SolverConfig Config; public SolverConfig Config;
public Simulator Simulator;
public Node RootNode; public Node RootNode;
public Random Random => Simulator.Input.Random; public Random Random;
public Solver(SolverConfig config, SimulationState state, bool strict) public Solver(SolverConfig config, SimulationState state, bool strict)
{ {
Config = config; Config = config;
Simulator = new(state, config.MaxStepCount); Simulator sim = new(state, config.MaxStepCount);
RootNode = new(new( RootNode = new(new(
state, state,
null, null,
Simulator.CompletionState, sim.CompletionState,
Simulator.AvailableActionsHeuristic(strict) sim.AvailableActionsHeuristic(strict)
)); ));
Random = state.Input.Random;
} }
public Solver(SolverConfig config, SimulationInput input, bool strict) : this(config, new SimulationState(input), strict) public Solver(SolverConfig config, SimulationInput input, bool strict) : this(config, new SimulationState(input), strict)
{ {
} }
private SimulationNode Execute(SimulationState state, ActionType action, bool strict) private static SimulationNode Execute(Simulator simulator, SimulationState state, ActionType action, bool strict)
{ {
(_, var newState) = Simulator.Execute(state, action); (_, var newState) = simulator.Execute(state, action);
return new( return new(
newState, newState,
action, action,
Simulator.CompletionState, simulator.CompletionState,
Simulator.AvailableActionsHeuristic(strict) simulator.AvailableActionsHeuristic(strict)
); );
} }
public (Node EndNode, CompletionState State) ExecuteActions(Node startNode, ReadOnlySpan<ActionType> actions, bool strict = false) public static (Node EndNode, CompletionState State) ExecuteActions(Simulator simulator, Node startNode, ReadOnlySpan<ActionType> actions, bool strict = false)
{ {
foreach (var action in actions) foreach (var action in actions)
{ {
@@ -58,7 +56,7 @@ public class Solver
return (startNode, CompletionState.InvalidAction); return (startNode, CompletionState.InvalidAction);
state.AvailableActions.RemoveAction(action); state.AvailableActions.RemoveAction(action);
startNode = startNode.Add(Execute(state.State, action, strict)); startNode = startNode.Add(Execute(simulator, state.State, action, strict));
} }
return (startNode, startNode.State.CompletionState); return (startNode, startNode.State.CompletionState);
@@ -160,7 +158,7 @@ public class Solver
} }
} }
public (Node ExpandedNode, CompletionState State, float Score) ExpandAndRollout(Node initialNode) public (Node ExpandedNode, CompletionState State, float Score) ExpandAndRollout(Simulator simulator, Node initialNode)
{ {
ref var initialState = ref initialNode.State; ref var initialState = ref initialNode.State;
// expand once // expand once
@@ -169,7 +167,7 @@ public class Solver
var randomAction = initialState.AvailableActions.SelectRandom(Random); var randomAction = initialState.AvailableActions.SelectRandom(Random);
initialState.AvailableActions.RemoveAction(randomAction); initialState.AvailableActions.RemoveAction(randomAction);
var expandedNode = initialNode.Add(Execute(initialState.State, randomAction, true)); var expandedNode = initialNode.Add(Execute(simulator, initialState.State, randomAction, true));
// playout to a terminal state // playout to a terminal state
var currentState = expandedNode.State.State; var currentState = expandedNode.State.State;
@@ -184,9 +182,9 @@ public class Solver
break; break;
randomAction = currentActions.SelectRandom(Random); randomAction = currentActions.SelectRandom(Random);
actions[actionCount++] = randomAction; actions[actionCount++] = randomAction;
(_, currentState) = Simulator.Execute(currentState, randomAction); (_, currentState) = simulator.Execute(currentState, randomAction);
currentCompletionState = Simulator.CompletionState; currentCompletionState = simulator.CompletionState;
currentActions = Simulator.AvailableActionsHeuristic(true); currentActions = simulator.AvailableActionsHeuristic(true);
} }
// store the result if a max score was reached // store the result if a max score was reached
@@ -195,7 +193,7 @@ public class Solver
{ {
if (score >= Config.ScoreStorageThreshold && score >= RootNode.State.Scores.MaxScore) if (score >= Config.ScoreStorageThreshold && score >= RootNode.State.Scores.MaxScore)
{ {
(var terminalNode, _) = ExecuteActions(expandedNode, actions[..actionCount], true); (var terminalNode, _) = ExecuteActions(simulator, expandedNode, actions[..actionCount], true);
return (terminalNode, currentCompletionState, score); return (terminalNode, currentCompletionState, score);
} }
} }
@@ -217,13 +215,14 @@ public class Solver
public void Search(CancellationToken token) public void Search(CancellationToken token)
{ {
Simulator simulator = new(RootNode.State.State, Config.MaxStepCount);
for (var i = 0; i < Config.Iterations; i++) for (var i = 0; i < Config.Iterations; i++)
{ {
if (token.IsCancellationRequested) if (token.IsCancellationRequested)
break; break;
var selectedNode = Select(); var selectedNode = Select();
var (endNode, _, score) = ExpandAndRollout(selectedNode); var (endNode, _, score) = ExpandAndRollout(simulator, selectedNode);
Backpropagate(endNode, score); Backpropagate(endNode, score);
} }
@@ -251,8 +250,9 @@ public class Solver
public static (List<ActionType> Actions, SimulationState State) SearchStepwise(SolverConfig config, SimulationState state, Action<ActionType>? actionCallback, CancellationToken token = default) public static (List<ActionType> Actions, SimulationState State) SearchStepwise(SolverConfig config, SimulationState state, Action<ActionType>? actionCallback, CancellationToken token = default)
{ {
var actions = new List<ActionType>(); var actions = new List<ActionType>();
Simulator sim = new(state, config.MaxStepCount);
var solver = new Solver(config, state, true); var solver = new Solver(config, state, true);
while (!solver.Simulator.IsComplete) while (!sim.IsComplete)
{ {
if (token.IsCancellationRequested) if (token.IsCancellationRequested)
break; break;
@@ -267,7 +267,7 @@ public class Solver
} }
var chosen_action = solution_actions[0]; var chosen_action = solution_actions[0];
(_, state) = solver.Simulator.Execute(state, chosen_action); (_, state) = sim.Execute(state, chosen_action);
actions.Add(chosen_action); actions.Add(chosen_action);
actionCallback?.Invoke(chosen_action); actionCallback?.Invoke(chosen_action);