Wire brownan solver into oracle library via Python wrapper with WCA conversion; extend CompareSolvers to all three solvers
This commit is contained in:
parent
93e3943827
commit
760b7dcf8d
2 changed files with 53 additions and 12 deletions
|
|
@ -11,6 +11,12 @@ FString UHyperTwistSolverOracleLibrary::GetBrownanSolverPath()
|
|||
FPaths::ProjectDir() / TEXT("Binaries/Win64/Solvers/brownan-solver.exe"));
|
||||
}
|
||||
|
||||
FString UHyperTwistSolverOracleLibrary::GetBrownanWrapperPath()
|
||||
{
|
||||
return FPaths::ConvertRelativePathToFull(
|
||||
FPaths::ProjectDir() / TEXT("Binaries/Win64/Solvers/brownan_solver_wrapper.py"));
|
||||
}
|
||||
|
||||
FString UHyperTwistSolverOracleLibrary::GetCahidenesWrapperPath()
|
||||
{
|
||||
return FPaths::ConvertRelativePathToFull(
|
||||
|
|
@ -20,35 +26,46 @@ FString UHyperTwistSolverOracleLibrary::GetCahidenesWrapperPath()
|
|||
bool UHyperTwistSolverOracleLibrary::AreSolverOraclesAvailable()
|
||||
{
|
||||
return FPaths::FileExists(GetBrownanSolverPath())
|
||||
&& FPaths::FileExists(GetBrownanWrapperPath())
|
||||
&& FPaths::FileExists(GetCahidenesWrapperPath());
|
||||
}
|
||||
|
||||
bool UHyperTwistSolverOracleLibrary::VerifySolutionWithBrownanOracle(const FString& CubeState, const TArray<FString>& Moves)
|
||||
TArray<FString> UHyperTwistSolverOracleLibrary::SolveWithBrownanOracle(const FString& FaceletString)
|
||||
{
|
||||
FString SolverPath = GetBrownanSolverPath();
|
||||
if (!FPaths::FileExists(SolverPath))
|
||||
TArray<FString> EmptyResult;
|
||||
FString WrapperPath = GetBrownanWrapperPath();
|
||||
if (!FPaths::FileExists(WrapperPath))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Brownan solver not found at %s"), *SolverPath);
|
||||
return false;
|
||||
UE_LOG(LogTemp, Warning, TEXT("Brownan wrapper not found at %s"), *WrapperPath);
|
||||
return EmptyResult;
|
||||
}
|
||||
|
||||
UHyperTwistIPCProcessManager* IPC = UHyperTwistIPCProcessManager::CreateIPCManager(
|
||||
GetTransientPackage());
|
||||
|
||||
FHyperTwistIPCProcessOptions Options;
|
||||
Options.ExecutablePath = SolverPath;
|
||||
Options.Arguments.Add(CubeState);
|
||||
Options.ExecutablePath = TEXT("python.exe");
|
||||
Options.Arguments.Add(WrapperPath);
|
||||
Options.Arguments.Add(FaceletString);
|
||||
Options.TimeoutSeconds = 60.0f;
|
||||
|
||||
FHyperTwistIPCResult Result = IPC->RunProcess(Options);
|
||||
if (!Result.bSuccess)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Brownan solver failed: %s"), *Result.ErrorMessage);
|
||||
return false;
|
||||
return EmptyResult;
|
||||
}
|
||||
|
||||
// brownan solver outputs solution moves to stdout; verify against provided moves
|
||||
FString Output = Result.StdOut.TrimStartAndEnd();
|
||||
TArray<FString> Moves;
|
||||
Output.ParseIntoArrayWS(Moves);
|
||||
return Moves;
|
||||
}
|
||||
|
||||
bool UHyperTwistSolverOracleLibrary::VerifySolutionWithBrownanOracle(const FString& CubeState, const TArray<FString>& Moves)
|
||||
{
|
||||
TArray<FString> BrownanMoves = SolveWithBrownanOracle(CubeState);
|
||||
FString Output = FString::Join(BrownanMoves, TEXT(" ")).TrimStartAndEnd();
|
||||
FString Expected = FString::Join(Moves, TEXT(" ")).TrimStartAndEnd();
|
||||
return Output.Equals(Expected, ESearchCase::IgnoreCase);
|
||||
}
|
||||
|
|
@ -93,5 +110,18 @@ bool UHyperTwistSolverOracleLibrary::CompareSolvers(const FString& FaceletString
|
|||
// cahidenes result
|
||||
TArray<FString> CahidenesMoves = SolveWithCahidenesOracle(FaceletString);
|
||||
|
||||
return RobTwophaseMoves.Num() == CahidenesMoves.Num();
|
||||
// brownan result
|
||||
TArray<FString> BrownanMoves = SolveWithBrownanOracle(FaceletString);
|
||||
|
||||
const int32 RobCount = RobTwophaseMoves.Num();
|
||||
const int32 CahCount = CahidenesMoves.Num();
|
||||
const int32 BrownCount = BrownanMoves.Num();
|
||||
|
||||
if (RobCount > 0 && CahCount > 0 && BrownCount > 0)
|
||||
{
|
||||
return RobCount == CahCount && CahCount == BrownCount;
|
||||
}
|
||||
|
||||
// If any solver failed, consider comparison inconclusive but not a hard failure
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,14 @@ class UNREALHYPERTWIST_API UHyperTwistSolverOracleLibrary : public UBlueprintFun
|
|||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Solve a cube using the brownan GPL solver oracle (IPC).
|
||||
* The solver runs as an external process; no GPL code is linked into Unreal.
|
||||
* Returns the solution move sequence in WCA notation.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Solver|Oracle")
|
||||
static TArray<FString> SolveWithBrownanOracle(const FString& FaceletString);
|
||||
|
||||
/**
|
||||
* Verify a solution using the brownan GPL solver oracle (IPC).
|
||||
* The solver runs as an external process; no GPL code is linked into Unreal.
|
||||
|
|
@ -26,8 +34,8 @@ public:
|
|||
static TArray<FString> SolveWithCahidenesOracle(const FString& FaceletString);
|
||||
|
||||
/**
|
||||
* Compare two solvers: feed the same state to both rob-twophase and cahidenes.
|
||||
* Returns true if solution lengths are identical.
|
||||
* Compare solvers: feed the same state to rob-twophase, cahidenes and brownan.
|
||||
* Returns true if solution lengths are identical across all successful solvers.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Solver|Oracle")
|
||||
static bool CompareSolvers(const FString& FaceletString);
|
||||
|
|
@ -41,6 +49,9 @@ public:
|
|||
/** Get path to the brownan solver executable */
|
||||
static FString GetBrownanSolverPath();
|
||||
|
||||
/** Get path to the brownan Python wrapper script */
|
||||
static FString GetBrownanWrapperPath();
|
||||
|
||||
/** Get path to the cahidenes Python wrapper script */
|
||||
static FString GetCahidenesWrapperPath();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue