From 8a775dd941ff50019e44428d8e09e55d16e98801 Mon Sep 17 00:00:00 2001 From: Pagwin Date: Thu, 11 Jun 2026 19:20:50 -0400 Subject: [PATCH] feat: add objective factors/mode defaults and validation Co-Authored-By: Claude Sonnet 4.6 --- solve.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/solve.py b/solve.py index 302926e..4b3c0ee 100644 --- a/solve.py +++ b/solve.py @@ -67,6 +67,32 @@ FIXED_CHOICES = { # lambda res: res["E"][3] >= 50 # Ensure at least 50 E at step 3 RESOURCE_CONSTRAINTS = [] +# Maximize criteria for solve(). Factor = exponent in "product" mode, +# weight in "sum" mode. Keys: E, B, S, C; missing keys = 0 (resource +# excluded from the objective — it is NOT forced to zero). Negative +# factors are allowed only in "sum" mode (a negative exponent would mean +# division, which integer CP-SAT cannot express). +OBJECTIVE_FACTORS = {"E": 2, "B": 1, "S": 2} +OBJECTIVE_MODE = "product" # "product" or "sum" + + +def _validate_objective(factors, mode): + if mode not in ("product", "sum"): + raise ValueError(f"objective_mode must be 'product' or 'sum', got {mode!r}") + unknown = set(factors) - {"E", "B", "S", "C"} + if unknown: + raise ValueError(f"unknown objective_factors keys: {sorted(unknown)}") + for k, v in factors.items(): + if not isinstance(v, int) or isinstance(v, bool): + raise ValueError(f"objective factor {k}={v!r} must be an int") + if mode == "product" and v < 0: + raise ValueError( + f"objective factor {k}={v} is negative; negative exponents " + "are not expressible in product mode" + ) + if not any(factors.values()): + raise ValueError("objective_factors needs at least one nonzero factor") + # Arrival schedule. Key = step (1..5), value = list of city types that arrive # at the START of that step. Types: 'H' Hub, 'F' Foundry, 'M' Metropolis, 'N' Monument. # Arriving cities act that same step.