Solver: Add Raphael
This commit is contained in:
@@ -21,37 +21,70 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Craftimizer.Test", "Test\Cr
|
|||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
Deterministic|Any CPU = Deterministic|Any CPU
|
||||||
Deterministic|x64 = Deterministic|x64
|
Deterministic|x64 = Deterministic|x64
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.ActiveCfg = Debug|x64
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Deterministic|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Deterministic|Any CPU.Build.0 = Debug|x64
|
||||||
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Deterministic|x64.ActiveCfg = Release|x64
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Deterministic|x64.ActiveCfg = Release|x64
|
||||||
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64
|
||||||
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64
|
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64
|
||||||
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Debug|x64.ActiveCfg = Debug|x64
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Debug|x64.Build.0 = Debug|x64
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Deterministic|Any CPU.ActiveCfg = Deterministic|x64
|
||||||
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Deterministic|Any CPU.Build.0 = Deterministic|x64
|
||||||
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
||||||
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Deterministic|x64.Build.0 = Deterministic|x64
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Deterministic|x64.Build.0 = Deterministic|x64
|
||||||
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Release|x64.ActiveCfg = Release|x64
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Release|x64.ActiveCfg = Release|x64
|
||||||
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Release|x64.Build.0 = Release|x64
|
{057C4B64-4D99-4847-9BCF-966571CAE57C}.Release|x64.Build.0 = Release|x64
|
||||||
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Debug|x64.ActiveCfg = Debug|x64
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Debug|x64.Build.0 = Debug|x64
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Deterministic|Any CPU.ActiveCfg = Deterministic|x64
|
||||||
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Deterministic|Any CPU.Build.0 = Deterministic|x64
|
||||||
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
||||||
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Deterministic|x64.Build.0 = Deterministic|x64
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Deterministic|x64.Build.0 = Deterministic|x64
|
||||||
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Release|x64.ActiveCfg = Release|x64
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Release|x64.ActiveCfg = Release|x64
|
||||||
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Release|x64.Build.0 = Release|x64
|
{172EE849-AC7E-4F2A-ACAB-EF9D065523B3}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Debug|x64.ActiveCfg = Debug|x64
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Debug|x64.Build.0 = Debug|x64
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Deterministic|Any CPU.ActiveCfg = Deterministic|x64
|
||||||
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Deterministic|Any CPU.Build.0 = Deterministic|x64
|
||||||
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
||||||
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Deterministic|x64.Build.0 = Deterministic|x64
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Deterministic|x64.Build.0 = Deterministic|x64
|
||||||
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|x64.ActiveCfg = Release|x64
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|x64.ActiveCfg = Release|x64
|
||||||
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|x64.Build.0 = Release|x64
|
{2B0EA452-6DFC-48DB-9049-EA782E600C21}.Release|x64.Build.0 = Release|x64
|
||||||
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{C3AEA981-9DA8-405C-995B-86528493891B}.Debug|x64.ActiveCfg = Debug|x64
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C3AEA981-9DA8-405C-995B-86528493891B}.Debug|x64.Build.0 = Debug|x64
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Deterministic|Any CPU.ActiveCfg = Deterministic|x64
|
||||||
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Deterministic|Any CPU.Build.0 = Deterministic|x64
|
||||||
{C3AEA981-9DA8-405C-995B-86528493891B}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Deterministic|x64.ActiveCfg = Deterministic|x64
|
||||||
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{C3AEA981-9DA8-405C-995B-86528493891B}.Release|x64.ActiveCfg = Release|x64
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C3AEA981-9DA8-405C-995B-86528493891B}.Release|x64.Build.0 = Release|x64
|
{C3AEA981-9DA8-405C-995B-86528493891B}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Raphael.Net" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
using Craftimizer.Simulator.Actions;
|
||||||
|
using Action = Raphael.Action;
|
||||||
|
|
||||||
|
namespace Craftimizer.Solver;
|
||||||
|
|
||||||
|
internal static unsafe class RaphaelUtils
|
||||||
|
{
|
||||||
|
public static ActionType[] ConvertRawActions(IReadOnlyList<Action> actions)
|
||||||
|
{
|
||||||
|
var result = new ActionType[actions.Count];
|
||||||
|
for (var i = 0; i < actions.Count; i++)
|
||||||
|
result[i] = ConvertRawAction(actions[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Action[] ConvertToRawActions(IReadOnlyList<ActionType> actions)
|
||||||
|
{
|
||||||
|
var result = new List<Action>(actions.Count);
|
||||||
|
foreach(var action in actions)
|
||||||
|
{
|
||||||
|
if (ConvertToRawAction(action) is { } a)
|
||||||
|
result.Add(a);
|
||||||
|
}
|
||||||
|
return [.. result];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActionType ConvertRawAction(Action action)
|
||||||
|
{
|
||||||
|
return action switch
|
||||||
|
{
|
||||||
|
Action.BasicSynthesis => ActionType.BasicSynthesis,
|
||||||
|
Action.BasicTouch => ActionType.BasicTouch,
|
||||||
|
Action.MasterMend => ActionType.MastersMend,
|
||||||
|
Action.Observe => ActionType.Observe,
|
||||||
|
Action.TricksOfTheTrade => ActionType.TricksOfTheTrade,
|
||||||
|
Action.WasteNot => ActionType.WasteNot,
|
||||||
|
Action.Veneration => ActionType.Veneration,
|
||||||
|
Action.StandardTouch => ActionType.StandardTouch,
|
||||||
|
Action.GreatStrides => ActionType.GreatStrides,
|
||||||
|
Action.Innovation => ActionType.Innovation,
|
||||||
|
Action.WasteNot2 => ActionType.WasteNot2,
|
||||||
|
Action.ByregotsBlessing => ActionType.ByregotsBlessing,
|
||||||
|
Action.PreciseTouch => ActionType.PreciseTouch,
|
||||||
|
Action.MuscleMemory => ActionType.MuscleMemory,
|
||||||
|
Action.CarefulSynthesis => ActionType.CarefulSynthesis,
|
||||||
|
Action.Manipulation => ActionType.Manipulation,
|
||||||
|
Action.PrudentTouch => ActionType.PrudentTouch,
|
||||||
|
Action.AdvancedTouch => ActionType.AdvancedTouch,
|
||||||
|
Action.Reflect => ActionType.Reflect,
|
||||||
|
Action.PreparatoryTouch => ActionType.PreparatoryTouch,
|
||||||
|
Action.Groundwork => ActionType.Groundwork,
|
||||||
|
Action.DelicateSynthesis => ActionType.DelicateSynthesis,
|
||||||
|
Action.IntensiveSynthesis => ActionType.IntensiveSynthesis,
|
||||||
|
Action.TrainedEye => ActionType.TrainedEye,
|
||||||
|
Action.HeartAndSoul => ActionType.HeartAndSoul,
|
||||||
|
Action.PrudentSynthesis => ActionType.PrudentSynthesis,
|
||||||
|
Action.TrainedFinesse => ActionType.TrainedFinesse,
|
||||||
|
Action.RefinedTouch => ActionType.RefinedTouch,
|
||||||
|
Action.QuickInnovation => ActionType.QuickInnovation,
|
||||||
|
Action.ImmaculateMend => ActionType.ImmaculateMend,
|
||||||
|
Action.TrainedPerfection => ActionType.TrainedPerfection,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(action), action, $"Invalid action value {action}"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Action? ConvertToRawAction(ActionType action)
|
||||||
|
{
|
||||||
|
return action switch
|
||||||
|
{
|
||||||
|
ActionType.BasicSynthesis => Action.BasicSynthesis,
|
||||||
|
ActionType.BasicTouch => Action.BasicTouch,
|
||||||
|
ActionType.MastersMend => Action.MasterMend,
|
||||||
|
ActionType.Observe => Action.Observe,
|
||||||
|
ActionType.TricksOfTheTrade => Action.TricksOfTheTrade,
|
||||||
|
ActionType.WasteNot => Action.WasteNot,
|
||||||
|
ActionType.Veneration => Action.Veneration,
|
||||||
|
ActionType.StandardTouch => Action.StandardTouch,
|
||||||
|
ActionType.GreatStrides => Action.GreatStrides,
|
||||||
|
ActionType.Innovation => Action.Innovation,
|
||||||
|
ActionType.WasteNot2 => Action.WasteNot2,
|
||||||
|
ActionType.ByregotsBlessing => Action.ByregotsBlessing,
|
||||||
|
ActionType.PreciseTouch => Action.PreciseTouch,
|
||||||
|
ActionType.MuscleMemory => Action.MuscleMemory,
|
||||||
|
ActionType.CarefulSynthesis => Action.CarefulSynthesis,
|
||||||
|
ActionType.Manipulation => Action.Manipulation,
|
||||||
|
ActionType.PrudentTouch => Action.PrudentTouch,
|
||||||
|
ActionType.AdvancedTouch => Action.AdvancedTouch,
|
||||||
|
ActionType.Reflect => Action.Reflect,
|
||||||
|
ActionType.PreparatoryTouch => Action.PreparatoryTouch,
|
||||||
|
ActionType.Groundwork => Action.Groundwork,
|
||||||
|
ActionType.DelicateSynthesis => Action.DelicateSynthesis,
|
||||||
|
ActionType.IntensiveSynthesis => Action.IntensiveSynthesis,
|
||||||
|
ActionType.TrainedEye => Action.TrainedEye,
|
||||||
|
ActionType.HeartAndSoul => Action.HeartAndSoul,
|
||||||
|
ActionType.PrudentSynthesis => Action.PrudentSynthesis,
|
||||||
|
ActionType.TrainedFinesse => Action.TrainedFinesse,
|
||||||
|
ActionType.RefinedTouch => Action.RefinedTouch,
|
||||||
|
ActionType.QuickInnovation => Action.QuickInnovation,
|
||||||
|
ActionType.ImmaculateMend => Action.ImmaculateMend,
|
||||||
|
ActionType.TrainedPerfection => Action.TrainedPerfection,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,8 @@ public sealed class Solver : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsIndeterminate => progress == 0 && progressStage == 0;
|
||||||
|
|
||||||
public delegate void LogDelegate(string text);
|
public delegate void LogDelegate(string text);
|
||||||
public delegate void NewActionDelegate(ActionType action);
|
public delegate void NewActionDelegate(ActionType action);
|
||||||
public delegate void SolutionDelegate(SolverSolution solution);
|
public delegate void SolutionDelegate(SolverSolution solution);
|
||||||
@@ -46,9 +48,16 @@ public sealed class Solver : IDisposable
|
|||||||
// Print to console or plugin log.
|
// Print to console or plugin log.
|
||||||
public event LogDelegate? OnLog;
|
public event LogDelegate? OnLog;
|
||||||
|
|
||||||
|
// Display as notification.
|
||||||
|
public event LogDelegate? OnWarn;
|
||||||
|
|
||||||
// Always called when a new step is generated.
|
// Always called when a new step is generated.
|
||||||
public event NewActionDelegate? OnNewAction;
|
public event NewActionDelegate? OnNewAction;
|
||||||
|
|
||||||
|
// Called when the solver can provide a "probable" solution.
|
||||||
|
// OnNewAction actions precede these proposed solutions. Purely visual.
|
||||||
|
public event SolutionDelegate? OnSuggestSolution;
|
||||||
|
|
||||||
public Solver(in SolverConfig config, in SimulationState state)
|
public Solver(in SolverConfig config, in SimulationState state)
|
||||||
{
|
{
|
||||||
Config = config;
|
Config = config;
|
||||||
@@ -61,6 +70,7 @@ public sealed class Solver : IDisposable
|
|||||||
SolverAlgorithm.Stepwise => (SearchStepwise, true),
|
SolverAlgorithm.Stepwise => (SearchStepwise, true),
|
||||||
SolverAlgorithm.StepwiseForked => (SearchStepwiseForked, true),
|
SolverAlgorithm.StepwiseForked => (SearchStepwiseForked, true),
|
||||||
SolverAlgorithm.StepwiseGenetic => (SearchStepwiseGenetic, true),
|
SolverAlgorithm.StepwiseGenetic => (SearchStepwiseGenetic, true),
|
||||||
|
SolverAlgorithm.Raphael => (SearchRaphael, true),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(config), config, $"Invalid algorithm: {config.Algorithm}")
|
_ => throw new ArgumentOutOfRangeException(nameof(config), config, $"Invalid algorithm: {config.Algorithm}")
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -136,6 +146,82 @@ public sealed class Solver : IDisposable
|
|||||||
Interlocked.Increment(ref progressStage);
|
Interlocked.Increment(ref progressStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<SolverSolution> SearchRaphael()
|
||||||
|
{
|
||||||
|
if (State.ActionCount > 0)
|
||||||
|
{
|
||||||
|
OnWarn?.Invoke("Optimal solver not support existing actions; falling back to Stepwise Genetic.");
|
||||||
|
return await SearchStepwiseGenetic().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
maxProgress = 2000;
|
||||||
|
|
||||||
|
Raphael.SolverConfig config = new()
|
||||||
|
{
|
||||||
|
Adversarial = Config.Adversarial,
|
||||||
|
BackloadProgress = Config.BackloadProgress,
|
||||||
|
UnsoundBranchPruning = Config.UnsoundBranchPruning,
|
||||||
|
};
|
||||||
|
|
||||||
|
ActionType[]? solution = null;
|
||||||
|
|
||||||
|
var s = new SimulatorNoRandom() { State = State };
|
||||||
|
var pool = RaphaelUtils.ConvertToRawActions(Config.ActionPool.Where(a => a.Base().IsPossible(s)).ToArray());
|
||||||
|
var input = new Raphael.SolverInput()
|
||||||
|
{
|
||||||
|
CP = checked((short)State.Input.Stats.CP),
|
||||||
|
Durability = checked((sbyte)State.Input.Recipe.MaxDurability),
|
||||||
|
Progress = checked((ushort)State.Input.Recipe.MaxProgress),
|
||||||
|
Quality = checked((ushort)(State.Input.Recipe.MaxQuality - State.Input.StartingQuality)),
|
||||||
|
BaseProgressGain = checked((ushort)State.Input.BaseProgressGain),
|
||||||
|
BaseQualityGain = checked((ushort)State.Input.BaseQualityGain),
|
||||||
|
JobLevel = checked((byte)State.Input.Stats.Level),
|
||||||
|
};
|
||||||
|
|
||||||
|
using Raphael.Solver solver = new(in config, input, pool);
|
||||||
|
|
||||||
|
solver.OnFinish += s => solution = RaphaelUtils.ConvertRawActions(s);
|
||||||
|
solver.OnSuggestSolution += s =>
|
||||||
|
{
|
||||||
|
var steps = RaphaelUtils.ConvertRawActions(s);
|
||||||
|
var sim = new SimulatorNoRandom();
|
||||||
|
var (resp, outState, failedIdx) = sim.ExecuteMultiple(State, steps);
|
||||||
|
if (resp != ActionResponse.SimulationComplete)
|
||||||
|
{
|
||||||
|
if (failedIdx != -1)
|
||||||
|
OnLog?.Invoke($"Invalid state; simulation failed to execute solution: {string.Join(',', s)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
OnSuggestSolution?.Invoke(new(steps, in outState));
|
||||||
|
};
|
||||||
|
solver.OnProgress += p =>
|
||||||
|
{
|
||||||
|
var prog = checked((int)p);
|
||||||
|
var stage = prog / maxProgress;
|
||||||
|
while (stage != progressStage)
|
||||||
|
ResetProgress();
|
||||||
|
progress = prog % maxProgress;
|
||||||
|
};
|
||||||
|
|
||||||
|
await using var registration = Token.Register(solver.Cancel).ConfigureAwait(true);
|
||||||
|
await Task.Run(solver.Solve, Token).ConfigureAwait(true);
|
||||||
|
|
||||||
|
if (solution == null)
|
||||||
|
return new([], State);
|
||||||
|
|
||||||
|
foreach (var action in solution)
|
||||||
|
InvokeNewAction(action);
|
||||||
|
|
||||||
|
var sim = new SimulatorNoRandom();
|
||||||
|
var (resp, outState, failedIdx) = sim.ExecuteMultiple(State, solution);
|
||||||
|
if (resp != ActionResponse.SimulationComplete)
|
||||||
|
{
|
||||||
|
if (failedIdx != -1)
|
||||||
|
throw new Exception($"Invalid state; simulation failed to execute solution: {string.Join(',', solution)}");
|
||||||
|
}
|
||||||
|
return new(solution, outState);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<SolverSolution> SearchStepwiseGenetic()
|
private async Task<SolverSolution> SearchStepwiseGenetic()
|
||||||
{
|
{
|
||||||
var iterCount = Config.Iterations / Config.ForkCount;
|
var iterCount = Config.Iterations / Config.ForkCount;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public enum SolverAlgorithm
|
|||||||
Stepwise,
|
Stepwise,
|
||||||
StepwiseForked,
|
StepwiseForked,
|
||||||
StepwiseGenetic,
|
StepwiseGenetic,
|
||||||
|
Raphael,
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
@@ -33,6 +34,10 @@ public readonly record struct SolverConfig
|
|||||||
public float ScoreCP { get; init; }
|
public float ScoreCP { get; init; }
|
||||||
public float ScoreSteps { get; init; }
|
public float ScoreSteps { get; init; }
|
||||||
|
|
||||||
|
public bool Adversarial { get; init; }
|
||||||
|
public bool BackloadProgress { get; init; }
|
||||||
|
public bool UnsoundBranchPruning { get; init; }
|
||||||
|
|
||||||
public ActionType[] ActionPool { get; init; }
|
public ActionType[] ActionPool { get; init; }
|
||||||
public SolverAlgorithm Algorithm { get; init; }
|
public SolverAlgorithm Algorithm { get; init; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user