import json
import math
import os
import subprocess
from typing import Any
import optuna
def generate_params(trial: optuna.trial.Trial) -> dict[str, str]:
params = {
"AHC_X": str(trial.suggest_int("x", -10, 10)),
"AHC_Y": str(trial.suggest_float("y", -10.0, 10.0)),
}
return params
def extract_score(result: dict[str, Any]) -> float:
absolute_score = result["score"] log10_score = math.log10(absolute_score) if absolute_score > 0.0 else 0.0 relative_score = result["relative_score"]
score = absolute_score
return score
def get_direction() -> str:
direction = "minimize"
return direction
def run_optimization(study: optuna.study.Study) -> None:
study.optimize(Objective(), timeout=300)
class Objective:
def __init__(self) -> None:
pass
def __call__(self, trial: optuna.trial.Trial) -> float:
params = generate_params(trial)
env = os.environ.copy()
env.update(params)
scores = []
cmd = [
"pahcer",
"run",
"--json",
"--shuffle",
"--no-result-file",
"--freeze-best-scores",
]
if trial.number != 0:
cmd.append("--no-compile")
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
env=env,
)
for line in process.stdout:
result = json.loads(line)
if result["error_message"] != "":
process.send_signal(subprocess.signal.SIGINT)
raise RuntimeError(result["error_message"])
score = extract_score(result)
seed = result["seed"]
scores.append(score)
trial.report(score, seed)
if trial.should_prune():
print(f"Trial {trial.number} pruned.")
process.send_signal(subprocess.signal.SIGINT)
objective_value = sum(scores) / len(scores)
is_better_than_best = (
trial.study.direction == optuna.study.StudyDirection.MINIMIZE
and objective_value < trial.study.best_value
) or (
trial.study.direction == optuna.study.StudyDirection.MAXIMIZE
and objective_value > trial.study.best_value
)
if is_better_than_best:
raise optuna.TrialPruned()
else:
return sum(scores) / len(scores)
return sum(scores) / len(scores)
study = optuna.create_study(
direction=get_direction(),
study_name="optuna-study",
pruner=optuna.pruners.WilcoxonPruner(),
sampler=optuna.samplers.TPESampler(),
)
run_optimization(study)
print(f"best params = {study.best_params}")
print(f"best score = {study.best_value}")