Inference¶
InferenceEngine¶
A single class that wraps a trained PPO checkpoint and exposes three search methods through one solve() call.
from ipps_drl import InferenceEngine
engine = InferenceEngine(
checkpoint="checkpoints/0605.pt",
device="auto", # also accepts "cuda:0" / "cpu"
config=None, # None = repo-root config.yaml
)
result = engine.solve("problem.ipps", method="greedy")
Constructor¶
| arg | type | default | meaning |
|---|---|---|---|
checkpoint |
str / path |
required | path to a .pt file produced by scripts/train_drl.py |
device |
str |
"auto" |
"auto" picks cuda:0 when available, else cpu |
config |
path / DictConfig / None |
None |
only the env_paras / nn_paras sections are consulted; None loads the repo-root config.yaml |
engine.solve(problem, method, **kwargs)¶
| method | extra kwargs (defaults) | description |
|---|---|---|
"greedy" |
return_schedule=True |
Deterministic argmax rollout. One trajectory. |
"sampling" |
num_sample=25, num_average=1, return_schedule=True |
Build a batch of num_sample copies, sample stochastically, keep best. Repeat num_average times and keep the global best. |
"mcts" |
time_limit=60, iteration_limit=None, exploration=5.0, lower_bound=-1, strong=False, return_schedule=True |
Search with the policy as a prior. Time-bounded by default; supply iteration_limit instead for a fixed-budget search. Pass strong=True for the strong-mode improvements. |
Returns an InferenceResult.
engine.solve_many(problems, method, **kwargs)¶
Convenience loop:
results = engine.solve_many(
["problem01.ipps", "problem02.ipps", "problem03.ipps"],
method="sampling", num_sample=16,
)
InferenceResult¶
@dataclass
class InferenceResult:
makespan: float
schedule: np.ndarray | None # (n_ops, 5) — [ope, ma, job, start, end]
method: str # "greedy" / "sampling" / "mcts"
wall_time_s: float
problem: str | None
extras: dict # method-specific extras
extras contents per method:
greedy,sampling:per_run_makespans,batch_sizemcts:action_list,best_makespan_trace,round_makespan_trace
CLI¶
The shipped scripts/test.py is a thin wrapper over InferenceEngine for batch evaluation:
python scripts/test.py --method greedy
python scripts/test.py --method sampling --num_sample 25 --num_average 2
python scripts/test.py --checkpoint checkpoints/0605.pt --num_ins 3 --save_solutions
It iterates every .pt under --checkpoint_dir × every problem under --data_dir, writes one CSV per checkpoint to --save_dir. See python scripts/test.py --help for the full flag list.
For MCTS batch evaluation, use scripts/run_mcts_batch.py (same flags + --time_limit, --exploration, --use_kim_lb, --strong).
Strong-mode MCTS¶
strong=True enables a bundle of search-quality improvements aimed at the harder Kim instances (problem20+):
- AlphaZero PUCT — replaces the original
c * P * sqrt((Np+1)/(Nc+1))with the standardc * P * sqrt(Np) / (1 + Nc). - Max-reward child selection — for a makespan-minimisation problem, the best simulation that ever passed through a child is more informative than the mean.
selection_mode='max'is forced understrong;'mixed'smoothly interpolates from mean to max as visits accumulate. - Root Dirichlet noise (
Dir(0.3)mixed in atepsilon=0.25) — breaks policy over-confidence so the search actually explores moves the policy thinks are weak. - Rollout cache — repeats of the same action-prefix re-use the cached rollout makespan instead of running the 5 greedy strategies again. Mostly helps on the "node revisited because
numVisits == 0" case that's common in the early iterations of the search.
Each lever is independently overridable via selection_mode, puct_mode, dirichlet_alpha, dirichlet_eps, cache_rollouts. See the docstring of ipps_drl.inference.mcts.mcts.__init__ for the full list.
Parallel rollouts
parallel_rollouts=True clones the C++ env once per greedy strategy and
runs runGreedyMakespan (which releases the GIL) in a ThreadPoolExecutor.
Off by default. After the lazy IPPSEnv-sync optimisation cut per-iteration
cost, sequential beats parallel even on Kim 23/24 because the per-rollout
CyEnv copy + thread-launch overhead now exceeds the rollout-side speedup.
Pass parallel_rollouts=True to opt in if your problem has slow enough
rollouts to amortise the copy.