Use Raphael's application of MacroSolver
This commit is contained in:
@@ -151,7 +151,7 @@ public sealed class Settings : Window, IDisposable
|
|||||||
SolverAlgorithm.Stepwise => "Stepwise",
|
SolverAlgorithm.Stepwise => "Stepwise",
|
||||||
SolverAlgorithm.StepwiseForked => "Stepwise Forked",
|
SolverAlgorithm.StepwiseForked => "Stepwise Forked",
|
||||||
SolverAlgorithm.StepwiseGenetic => "Stepwise Genetic",
|
SolverAlgorithm.StepwiseGenetic => "Stepwise Genetic",
|
||||||
SolverAlgorithm.Raphael => "Optimal (Slow)",
|
SolverAlgorithm.Raphael => "Optimal",
|
||||||
_ => "Unknown",
|
_ => "Unknown",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -652,7 +652,15 @@ public sealed class Settings : Window, IDisposable
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Ensure 100% Reliability",
|
"Quick Solve",
|
||||||
|
"Speeds up solve times. Backloads all Progress " +
|
||||||
|
"actions to the end of the rotation.",
|
||||||
|
config.BackloadProgress,
|
||||||
|
v => config = config with { BackloadProgress = v },
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
DrawOption(
|
||||||
|
"Ensure Reliability",
|
||||||
"Find a rotation that can reach the target quality no matter " +
|
"Find a rotation that can reach the target quality no matter " +
|
||||||
"how unlucky the random conditions are.",
|
"how unlucky the random conditions are.",
|
||||||
config.Adversarial,
|
config.Adversarial,
|
||||||
@@ -660,13 +668,24 @@ public sealed class Settings : Window, IDisposable
|
|||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Backload Progress",
|
"Minimize Steps",
|
||||||
"Find a rotation that only uses Progress-increasing actions " +
|
"Minimizes the number of crafting steps.",
|
||||||
"at the end of the rotation. May speed up solve times.",
|
config.MinimizeSteps,
|
||||||
config.BackloadProgress,
|
v => config = config with { MinimizeSteps = v },
|
||||||
v => config = config with { BackloadProgress = v },
|
|
||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (config.MinimizeSteps && config.Adversarial)
|
||||||
|
{
|
||||||
|
ImGui.SameLine();
|
||||||
|
using (var color = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange))
|
||||||
|
{
|
||||||
|
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||||
|
ImGui.TextUnformatted(FontAwesomeIcon.ExclamationCircle.ToIconString());
|
||||||
|
}
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGuiUtils.TooltipWrapped("Combining \"Minimize Steps\" and \"Ensure Reliability\" will significantly increase solve times.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,15 +732,6 @@ public sealed class Settings : Window, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Provide better option name than this lol
|
|
||||||
//DrawOption(
|
|
||||||
// "Unsound Branch Pruning",
|
|
||||||
// "TBD",
|
|
||||||
// config.UnsoundBranchPruning,
|
|
||||||
// v => config = config with { UnsoundBranchPruning = v },
|
|
||||||
// ref isDirty
|
|
||||||
//);
|
|
||||||
|
|
||||||
if (config.Algorithm != SolverAlgorithm.Raphael)
|
if (config.Algorithm != SolverAlgorithm.Raphael)
|
||||||
{
|
{
|
||||||
using (var panel = ImRaii2.GroupPanel("Score Weights (Advanced)", -1, out _))
|
using (var panel = ImRaii2.GroupPanel("Score Weights (Advanced)", -1, out _))
|
||||||
|
|||||||
+66
-31
@@ -156,15 +156,6 @@ public sealed class Solver : IDisposable
|
|||||||
|
|
||||||
maxProgress = 2000;
|
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 s = new SimulatorNoRandom() { State = State };
|
||||||
var pool = RaphaelUtils.ConvertToRawActions(Config.ActionPool.Where(a => a.Base().IsPossible(s)).ToArray());
|
var pool = RaphaelUtils.ConvertToRawActions(Config.ActionPool.Where(a => a.Base().IsPossible(s)).ToArray());
|
||||||
var input = new Raphael.SolverInput()
|
var input = new Raphael.SolverInput()
|
||||||
@@ -178,33 +169,83 @@ public sealed class Solver : IDisposable
|
|||||||
JobLevel = checked((byte)State.Input.Stats.Level),
|
JobLevel = checked((byte)State.Input.Stats.Level),
|
||||||
};
|
};
|
||||||
|
|
||||||
using Raphael.Solver solver = new(in config, input, pool);
|
SimulationState ExecuteActions(IEnumerable<ActionType> actions)
|
||||||
|
|
||||||
solver.OnFinish += s => solution = RaphaelUtils.ConvertRawActions(s);
|
|
||||||
solver.OnSuggestSolution += s =>
|
|
||||||
{
|
{
|
||||||
var steps = RaphaelUtils.ConvertRawActions(s);
|
|
||||||
var sim = new SimulatorNoRandom();
|
var sim = new SimulatorNoRandom();
|
||||||
var (resp, outState, failedIdx) = sim.ExecuteMultiple(State, steps);
|
var (resp, outState, failedIdx) = sim.ExecuteMultiple(State, actions);
|
||||||
if (resp != ActionResponse.SimulationComplete)
|
if (resp != ActionResponse.SimulationComplete)
|
||||||
{
|
{
|
||||||
if (failedIdx != -1)
|
if (failedIdx != -1)
|
||||||
OnLog?.Invoke($"Invalid state; simulation failed to execute solution: {string.Join(',', s)}");
|
throw new ArgumentException($"Invalid state; simulation failed to execute solution: {string.Join(',', actions)}", nameof(actions));
|
||||||
}
|
}
|
||||||
|
return outState;
|
||||||
|
}
|
||||||
|
|
||||||
OnSuggestSolution?.Invoke(new(steps, in outState));
|
ActionType[]? solution = null;
|
||||||
};
|
|
||||||
solver.OnProgress += p =>
|
void OnFinish(Raphael.Action[] s) =>
|
||||||
|
solution = RaphaelUtils.ConvertRawActions(s);
|
||||||
|
|
||||||
|
void OnSuggestSolution(Raphael.Action[] s)
|
||||||
|
{
|
||||||
|
var steps = RaphaelUtils.ConvertRawActions(s);
|
||||||
|
var outState = ExecuteActions(steps);
|
||||||
|
this.OnSuggestSolution?.Invoke(new(steps, in outState));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnProgress(nuint p)
|
||||||
{
|
{
|
||||||
var prog = checked((int)p);
|
var prog = checked((int)p);
|
||||||
var stage = prog / maxProgress;
|
var stage = prog / maxProgress;
|
||||||
while (stage != progressStage)
|
while (stage != progressStage)
|
||||||
ResetProgress();
|
ResetProgress();
|
||||||
progress = prog % maxProgress;
|
progress = prog % maxProgress;
|
||||||
};
|
}
|
||||||
|
|
||||||
await using var registration = Token.Register(solver.Cancel).ConfigureAwait(true);
|
if (!Config.MinimizeSteps)
|
||||||
await Task.Run(solver.Solve, Token).ConfigureAwait(true);
|
{
|
||||||
|
Raphael.SolverConfig config = new()
|
||||||
|
{
|
||||||
|
Adversarial = Config.Adversarial,
|
||||||
|
BackloadProgress = true,
|
||||||
|
UnsoundBranchPruning = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using var solver = new Raphael.Solver(in config, in input, pool);
|
||||||
|
|
||||||
|
solver.OnFinish += OnFinish;
|
||||||
|
solver.OnSuggestSolution += OnSuggestSolution;
|
||||||
|
solver.OnProgress += OnProgress;
|
||||||
|
|
||||||
|
progressStage = 0;
|
||||||
|
progress = 0;
|
||||||
|
await using var registration = Token.Register(solver.Cancel).ConfigureAwait(true);
|
||||||
|
await Task.Run(solver.Solve, Token).ConfigureAwait(true);
|
||||||
|
Token.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (solution == null || ExecuteActions(solution).HQPercent != 100)
|
||||||
|
{
|
||||||
|
Raphael.SolverConfig config = new()
|
||||||
|
{
|
||||||
|
Adversarial = Config.Adversarial,
|
||||||
|
BackloadProgress = Config.BackloadProgress,
|
||||||
|
UnsoundBranchPruning = false
|
||||||
|
};
|
||||||
|
|
||||||
|
using var solver = new Raphael.Solver(in config, in input, pool);
|
||||||
|
|
||||||
|
solver.OnFinish += OnFinish;
|
||||||
|
solver.OnSuggestSolution += OnSuggestSolution;
|
||||||
|
solver.OnProgress += OnProgress;
|
||||||
|
|
||||||
|
progressStage = 0;
|
||||||
|
progress = 0;
|
||||||
|
await using var registration = Token.Register(solver.Cancel).ConfigureAwait(true);
|
||||||
|
await Task.Run(solver.Solve, Token).ConfigureAwait(true);
|
||||||
|
Token.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
|
||||||
if (solution == null)
|
if (solution == null)
|
||||||
return new([], State);
|
return new([], State);
|
||||||
@@ -212,14 +253,8 @@ public sealed class Solver : IDisposable
|
|||||||
foreach (var action in solution)
|
foreach (var action in solution)
|
||||||
InvokeNewAction(action);
|
InvokeNewAction(action);
|
||||||
|
|
||||||
var sim = new SimulatorNoRandom();
|
var outState = ExecuteActions(solution);
|
||||||
var (resp, outState, failedIdx) = sim.ExecuteMultiple(State, solution);
|
return new(solution, in outState);
|
||||||
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()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public enum SolverAlgorithm
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public readonly record struct SolverConfig
|
public readonly record struct SolverConfig
|
||||||
{
|
{
|
||||||
|
// MCTS configuration
|
||||||
public int Iterations { get; init; }
|
public int Iterations { get; init; }
|
||||||
public int MaxIterations { get; init; }
|
public int MaxIterations { get; init; }
|
||||||
public float MaxScoreWeightingConstant { get; init; }
|
public float MaxScoreWeightingConstant { get; init; }
|
||||||
@@ -28,15 +29,17 @@ public readonly record struct SolverConfig
|
|||||||
public int FurcatedActionCount { get; init; }
|
public int FurcatedActionCount { get; init; }
|
||||||
public bool StrictActions { get; init; }
|
public bool StrictActions { get; init; }
|
||||||
|
|
||||||
|
// MCTS score weights
|
||||||
public float ScoreProgress { get; init; }
|
public float ScoreProgress { get; init; }
|
||||||
public float ScoreQuality { get; init; }
|
public float ScoreQuality { get; init; }
|
||||||
public float ScoreDurability { get; init; }
|
public float ScoreDurability { get; init; }
|
||||||
public float ScoreCP { get; init; }
|
public float ScoreCP { get; init; }
|
||||||
public float ScoreSteps { get; init; }
|
public float ScoreSteps { get; init; }
|
||||||
|
|
||||||
|
// Raphael/A* configuration
|
||||||
public bool Adversarial { get; init; }
|
public bool Adversarial { get; init; }
|
||||||
public bool BackloadProgress { get; init; }
|
public bool BackloadProgress { get; init; }
|
||||||
public bool UnsoundBranchPruning { get; init; }
|
public bool MinimizeSteps { get; init; }
|
||||||
|
|
||||||
public ActionType[] ActionPool { get; init; }
|
public ActionType[] ActionPool { get; init; }
|
||||||
public SolverAlgorithm Algorithm { get; init; }
|
public SolverAlgorithm Algorithm { get; init; }
|
||||||
@@ -190,7 +193,8 @@ public readonly record struct SolverConfig
|
|||||||
|
|
||||||
public static readonly SolverConfig EditorDefault = new SolverConfig() with
|
public static readonly SolverConfig EditorDefault = new SolverConfig() with
|
||||||
{
|
{
|
||||||
Iterations = 500000
|
Algorithm = SolverAlgorithm.Raphael,
|
||||||
|
Adversarial = true
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly SolverConfig SynthHelperDefault = new SolverConfig() with
|
public static readonly SolverConfig SynthHelperDefault = new SolverConfig() with
|
||||||
|
|||||||
Reference in New Issue
Block a user