null: exact budgeted task planner with brute-force cross-check tests

This commit is contained in:
null committed 2026-10-23 06:53:33 +00:00
1 parent 9cda8f49ef
commit 9e4c8417fd
4 files changed
+600

No files matched your search

@@ -0,0 +1,66 @@
# budgeted_planner — exact optimal task selection under a token budget
Lane: Codeforge. Artifact: `budgeted_planner.py` (+ `test_budgeted_planner.py` test suite).
Pure stdlib, no dependencies, deterministic.
## Problem
Pick a subset S of tasks, each with `cost` (tokens), `value`, and `requires` (prerequisite ids),
such that S is **closed** under prerequisites and `sum(cost) <= budget`, maximising `sum(value)`.
This is the shape of "what work fits in my context window" for an agentic run: a step whose
prerequisites are not in the window is worthless, so a greedy scan is not safe.
## Why the answer is exact, not heuristic
1. `topo_order` orders tasks so every prerequisite precedes its dependents (Kahn; cycles raise).
2. DP over `(index, remaining_budget, bitmask_of_relevant_earlier_selections)`.
A bit is *relevant* at index i iff it is a prerequisite of some task at index >= i.
Restricting the mask to relevant bits is lossless: a non-relevant earlier selection can never
influence a later decision, and every prerequisite of task i is relevant at i, so the mask fully
determines whether task i may be taken.
3. The DP explores the entire include/exclude decision space; no sampling, no rounding.
## Evidence (measured, this machine, Python 3.14.7)
Command: `python3 /root/.hermes/wizard-outputs/null/test_budgeted_planner.py` -> exit 0, 18 tests OK.
```
OK
n=40 dense instance solved in 0.223s
cross-check: 300 instances, 160 with positive optimum
```
- **Optimality**: 300 seeded random DAG instances (n = 1..11, budgets 0..total_cost+5, edge
densities 0.0/0.15/0.3/0.5) — solver optimum == `brute_force` optimum on every instance.
`brute_force` is an independent oracle: it enumerates all 2^n subsets and tests closure by set
containment, with no topological order and no DP.
- 40 dense instances (n = 8, edge density 0.6) and 60 zero-value-task instances also cross-checked.
- Hand-computed cases: chain forces prerequisites; prerequisite blows budget; zero budget;
empty input; value-0 filler + deterministic include tie-break.
- Validation: duplicate id, dangling prerequisite, 2-cycle, self-cycle, cost <= 0, value < 0,
negative budget, non-int budget -> `SpecError` (CLI exits 2).
- Large instances (n = 60 chain, n = 60 independent) checked for closure, budget feasibility and
self-consistent accounting; greedy is a verified lower bound on value.
- Determinism: identical output across repeated runs on the same input.
- CLI smoke test: budget 9, tasks ingest(4,3), index(7,10)->ingest, report(5,6)
-> `{"cost": 9, "selected": ["ingest", "report"], "value": 9}` (index is unreachable: 4+7 > 9).
## Limits (claimed, not measured beyond n=40)
Exponential in the number of *relevant* earlier selections per step. Measured 0.223s at n=40 dense;
fine for tens of tasks, not for hundreds of deeply interdependent ones. `brute_force` is 2^n and
is only usable for n <= ~15.
## Bugs the suite caught during development
1. DP table keyed by `Task` object instead of task id -> `KeyError` in `_relevant_masks` (11 test
errors). The CLI's `except KeyError` also silently turned this into exit 2, which is why the
CLI exit-code test exists.
2. A wrong test expectation (budget 2 cannot hold tasks costing 1 and 2).
## Usage
```
echo '{"budget": 9, "tasks": [{"id":"a","cost":4,"value":3},{"id":"b","cost":7,"value":10,"requires":["a"]}]}' \
| python3 budgeted_planner.py
```
@@ -0,0 +1,27 @@
test_cli_exit_codes (__main__.TestCliAndJson.test_cli_exit_codes) ... ok
test_json_roundtrip (__main__.TestCliAndJson.test_json_roundtrip) ... ok
test_chain_forces_prerequisites (__main__.TestHandComputed.test_chain_forces_prerequisites) ... ok
test_prereq_blows_budget (__main__.TestHandComputed.test_prereq_blows_budget) ... ok
test_tie_is_deterministic_include (__main__.TestHandComputed.test_tie_is_deterministic_include) ... ok
test_zero_budget_and_empty (__main__.TestHandComputed.test_zero_budget_and_empty) ... ok
test_zero_value_task_free_inclusion (__main__.TestHandComputed.test_zero_value_task_free_inclusion) ... ok
test_runtime_bounded (__main__.TestLargeInstances.test_runtime_bounded) ... ok
test_wide_and_deep_invariants (__main__.TestLargeInstances.test_wide_and_deep_invariants) ... ok
test_300_random_instances (__main__.TestOptimalityAgainstOracle.test_300_random_instances) ... ok
test_dense_graphs_match_oracle (__main__.TestOptimalityAgainstOracle.test_dense_graphs_match_oracle) ... ok
test_zero_value_and_zero_cost_edges (__main__.TestOptimalityAgainstOracle.test_zero_value_and_zero_cost_edges) ... ok
test_bad_cost_value_budget (__main__.TestValidation.test_bad_cost_value_budget) ... ok
test_brute_force_also_validates (__main__.TestValidation.test_brute_force_also_validates) ... ok
test_cycle (__main__.TestValidation.test_cycle) ... ok
test_dangling_prerequisite (__main__.TestValidation.test_dangling_prerequisite) ... ok
test_duplicate_id (__main__.TestValidation.test_duplicate_id) ... ok
test_self_cycle (__main__.TestValidation.test_self_cycle) ... ok
----------------------------------------------------------------------
Ran 18 tests in 1.585s
OK
n=40 dense instance solved in 0.223s
cross-check: 300 instances, 160 with positive optimum
@@ -0,0 +1,277 @@
#!/usr/bin/env python3
"""budgeted_planner.py — exact optimal task selection under a cost budget and prerequisite closure.
Lane: Codeforge. Pure stdlib.
Problem
-------
Given tasks with a token `cost`, an integer `value`, and prerequisite ids `requires`,
choose a subset S that is
* CLOSED: every prerequisite of every task in S is also in S,
* FEASIBLE: sum(cost(t) for t in S) <= budget,
maximising sum(value(t) for t in S).
Exactness
---------
`topo_order` imposes an order where every prerequisite precedes its dependents.
A task's prerequisites are therefore all earlier in that order. The solver does a
memoised DP over (index, remaining budget, bitmask of *relevant* earlier selections).
A bit is "relevant" at index i iff it is the prerequisite of some task at index >= i;
restricting the mask to relevant bits is lossless because a non-relevant earlier
selection can never influence any future decision. No heuristic, no sampling: the DP
enumerates the whole decision space, so the returned value is the true optimum.
`brute_force` is an independent oracle (enumerate all 2**n subsets, test closure by set
containment, no topo order, no DP) used by the tests as the correctness reference.
Determinism
-----------
For a fixed input the output is byte-identical across runs. Among equally optimal
selections the solver deterministically prefers the one that includes a task when the
include/exclude values tie.
Limits
------
Exponential in the number of *relevant* earlier selections per step; comfortable for
tens of tasks. `brute_force` is 2**n and is only usable for n <= ~15.
"""
from __future__ import annotations
import json
import sys
from dataclasses import dataclass
from typing import Iterable, Mapping, Sequence
__all__ = [
"Task",
"SpecError",
"solve",
"brute_force",
"greedy",
"topo_order",
"check_selection",
"plan_from_json",
"main",
]
class SpecError(ValueError):
"""Raised for malformed input: duplicate ids, dangling/cyclic prerequisites,
non-positive costs, negative values, negative budget."""
@dataclass(frozen=True)
class Task:
id: str
cost: int
value: int
requires: tuple[str, ...]
@classmethod
def of(cls, obj: Mapping) -> "Task":
return cls(
id=str(obj["id"]),
cost=int(obj["cost"]),
value=int(obj["value"]),
requires=tuple(str(r) for r in obj.get("requires", ())),
)
def _validate(tasks: Sequence[Task], budget: int) -> None:
if not isinstance(budget, int) or isinstance(budget, bool):
raise SpecError(f"budget must be an int, got {type(budget).__name__}")
if budget < 0:
raise SpecError(f"budget must be >= 0, got {budget}")
seen: set[str] = set()
for t in tasks:
if not t.id:
raise SpecError("task id must be non-empty")
if t.id in seen:
raise SpecError(f"duplicate task id: {t.id!r}")
seen.add(t.id)
if t.cost <= 0:
raise SpecError(f"task {t.id!r} cost must be > 0, got {t.cost}")
if t.value < 0:
raise SpecError(f"task {t.id!r} value must be >= 0, got {t.value}")
for t in tasks:
for r in t.requires:
if r not in seen:
raise SpecError(f"task {t.id!r} requires unknown task {r!r}")
def topo_order(ids: Iterable[str], requires: Mapping[str, Sequence[str]]) -> list[str]:
"""Return an order in which every prerequisite precedes its dependent.
Raises SpecError if the prerequisite graph has a cycle.
"""
pending = list(ids)
emitted: list[str] = []
done: set[str] = set()
while pending:
ready = sorted(
t for t in pending if all(r in done for r in requires.get(t, ()))
)
if not ready:
raise SpecError(
"prerequisite cycle among: " + ", ".join(sorted(pending))
)
for t in ready:
emitted.append(t)
done.add(t)
pending.remove(t)
return emitted
def _relevant_masks(order: Sequence[str], req_idx: Mapping[str, tuple[int, ...]]) -> list[frozenset[int]]:
"""relevant[i] = indices < i that are a prerequisite of some task at index >= i."""
n = len(order)
rel: list[frozenset[int]] = []
for i in range(n + 1):
acc: set[int] = set()
for j in range(i, n):
acc.update(req_idx[order[j]])
rel.append(frozenset(j for j in acc if j < i))
return rel
def solve(tasks: Sequence[Task], budget: int) -> dict:
"""Exact optimum. Returns {'selected', 'cost', 'value'}."""
tasks = list(tasks)
_validate(tasks, budget)
order = topo_order([t.id for t in tasks], {t.id: t.requires for t in tasks})
idx = {t: i for i, t in enumerate(order)}
cost = {t.id: t.cost for t in tasks}
value = {t.id: t.value for t in tasks}
req_idx = {t.id: tuple(sorted(idx[r] for r in t.requires)) for t in tasks}
rel = _relevant_masks(order, req_idx)
n = len(order)
memo: dict[tuple[int, int, int], int] = {}
def f(i: int, rem: int, mask: int) -> int:
if i == n:
return 0
key = (i, rem, mask)
hit = memo.get(key)
if hit is not None:
return hit
best = f(i + 1, rem, mask & _bits(rel[i + 1]))
t = order[i]
if cost[t] <= rem and all(mask >> r & 1 for r in req_idx[t]):
cand = value[t] + f(i + 1, rem - cost[t], (mask | (1 << i)) & _bits(rel[i + 1]))
if cand > best:
best = cand
memo[key] = best
return best
chosen: list[str] = []
def build(i: int, rem: int, mask: int) -> None:
if i == n:
return
t = order[i]
excl = f(i + 1, rem, mask & _bits(rel[i + 1]))
if cost[t] <= rem and all(mask >> r & 1 for r in req_idx[t]):
inc = value[t] + f(i + 1, rem - cost[t], (mask | (1 << i)) & _bits(rel[i + 1]))
if inc >= excl: # deterministic tie-break: include
chosen.append(t)
build(i + 1, rem - cost[t], (mask | (1 << i)) & _bits(rel[i + 1]))
return
build(i + 1, rem, mask & _bits(rel[i + 1]))
build(0, budget, 0)
out = sorted(chosen)
result = {
"selected": out,
"cost": sum(cost[t] for t in out),
"value": sum(value[t] for t in out),
}
if result["value"] != f(0, budget, 0): # internal consistency assertion
raise AssertionError("reconstruction diverged from DP value")
return result
def _bits(fs: frozenset[int]) -> int:
b = 0
for j in fs:
b |= 1 << j
return b
def brute_force(tasks: Sequence[Task], budget: int) -> int:
"""Independent oracle: enumerate every subset, keep closed+feasible ones, return max value."""
tasks = list(tasks)
_validate(tasks, budget)
ids = [t.id for t in tasks]
cost = {t.id: t.cost for t in tasks}
value = {t.id: t.value for t in tasks}
req = {t.id: frozenset(t.requires) for t in tasks}
best = 0
for mask in range(1 << len(ids)):
chosen = {ids[i] for i in range(len(ids)) if mask >> i & 1}
if not chosen:
continue
if any(not req[i] <= chosen for i in chosen):
continue
if sum(cost[i] for i in chosen) > budget:
continue
v = sum(value[i] for i in chosen)
if v > best:
best = v
return best
def greedy(tasks: Sequence[Task], budget: int) -> dict:
"""Cheap lower bound: scan in id order, take any task whose prerequisites are
all already taken and whose cost fits. Not exact; used as a sanity floor."""
tasks = list(tasks)
_validate(tasks, budget)
order = topo_order([t.id for t in tasks], {t.id: t.requires for t in tasks})
by_id = {t.id: t for t in tasks}
taken: set[str] = set()
spent = 0
gained = 0
for tid in order:
t = by_id[tid]
if all(r in taken for r in t.requires) and spent + t.cost <= budget:
taken.add(tid)
spent += t.cost
gained += t.value
return {"selected": sorted(taken), "cost": spent, "value": gained}
def check_selection(tasks: Sequence[Task], budget: int, selected: Sequence[str]) -> None:
"""Raise AssertionError unless `selected` is closed, feasible and internally consistent."""
by_id = {t.id: t for t in tasks}
s = set(selected)
assert len(s) == len(selected), "selected contains duplicates"
assert s <= set(by_id), f"unknown task(s): {sorted(s - set(by_id))}"
for t in s:
missing = set(by_id[t].requires) - s
assert not missing, f"task {t!r} is missing prerequisites {sorted(missing)}"
assert sum(by_id[t].cost for t in s) <= budget, "selection exceeds budget"
def plan_from_json(payload: Mapping) -> dict:
tasks = [Task.of(o) for o in payload.get("tasks", ())]
return solve(tasks, int(payload.get("budget", 0)))
def main(argv: Sequence[str] | None = None) -> int:
argv = list(sys.argv[1:] if argv is None else argv)
raw = open(argv[0], "r", encoding="utf-8").read() if argv else sys.stdin.read()
try:
payload = json.loads(raw)
result = plan_from_json(payload)
except (json.JSONDecodeError, SpecError, KeyError) as exc:
print(json.dumps({"error": f"{type(exc).__name__}: {exc}"}), file=sys.stderr)
return 2
print(json.dumps(result, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""test_budgeted_planner.py — real test suite for budgeted_planner.
Exits 0 iff every test passes; exits 1 on any failure (unittest semantics).
Evidence: the optimality claim is checked against an INDEPENDENT brute-force oracle
on hundreds of randomly generated instances, plus hand-computed cases, malformed
inputs, cycle detection, determinism, and a large-instance invariant sweep.
Run: python3 /root/.hermes/wizard-outputs/null/test_budgeted_planner.py
"""
from __future__ import annotations
import json
import random
import subprocess
import sys
import tempfile
import time
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from budgeted_planner import ( # noqa: E402
SpecError,
Task,
brute_force,
check_selection,
greedy,
plan_from_json,
solve,
topo_order,
)
MODULE = Path(__file__).resolve().parent / "budgeted_planner.py"
def rand_instance(rng: random.Random, n: int, edge_p: float = 0.25):
perm = [f"t{k}" for k in range(n)]
rng.shuffle(perm) # topological order
requires: dict[str, list[str]] = {t: [] for t in perm}
for a in range(n):
for b in range(a + 1, n):
if rng.random() < edge_p:
requires[perm[b]].append(perm[a])
tasks = [
Task(
id=t,
cost=rng.randint(1, 9),
value=rng.randint(0, 20),
requires=tuple(requires[t]),
)
for t in perm
]
return tasks, sum(t.cost for t in tasks)
class TestHandComputed(unittest.TestCase):
def test_chain_forces_prerequisites(self):
# t2 needs t1; budget 10. t2(7,10)+t1(4,3)=11 > 10 -> must drop t2.
tasks = [
Task("t1", 4, 3, ()),
Task("t2", 7, 10, ("t1",)),
Task("t3", 5, 6, ()),
]
r = solve(tasks, 10)
self.assertEqual(r["value"], 9) # t1 + t3
check_selection(tasks, 10, r["selected"])
def test_prereq_blows_budget(self):
tasks = [Task("a", 6, 9, ()), Task("b", 5, 100, ("a",))]
r = solve(tasks, 9)
self.assertEqual(r["value"], 9) # b unreachable: 6+5 > 9
def test_zero_budget_and_empty(self):
self.assertEqual(solve([], 5), {"selected": [], "cost": 0, "value": 0})
self.assertEqual(solve([Task("a", 1, 1, ())], 0)["value"], 0)
def test_zero_value_task_free_inclusion(self):
# budget 3 fits both; value-0 task 'a' adds nothing but is taken because the
# solver's deterministic tie-break prefers include on equal value.
tasks = [Task("a", 1, 0, ()), Task("b", 2, 5, ())]
r = solve(tasks, 3)
self.assertEqual(r["value"], 5)
self.assertEqual(r["cost"], 3)
self.assertIn("a", r["selected"])
# budget 2 cannot hold both (1+2=3): only b fits, optimum 5 either way.
self.assertEqual(solve(tasks, 2)["selected"], ["b"])
def test_tie_is_deterministic_include(self):
tasks = [Task("a", 5, 5, ()), Task("b", 5, 5, ())]
r1 = solve(tasks, 5)
r2 = solve(tasks, 5)
self.assertEqual(r1, r2)
self.assertEqual(len(r1["selected"]), 1)
class TestValidation(unittest.TestCase):
def _must_raise(self, fn, *a, **kw):
with self.assertRaises(SpecError):
fn(*a, **kw)
def test_duplicate_id(self):
self._must_raise(solve, [Task("a", 1, 1, ()), Task("a", 1, 2, ())], 5)
def test_dangling_prerequisite(self):
self._must_raise(solve, [Task("a", 1, 1, ("ghost",))], 5)
def test_cycle(self):
tasks = [Task("a", 1, 1, ("b",)), Task("b", 1, 1, ("a",))]
self._must_raise(solve, tasks, 5)
with self.assertRaises(SpecError):
topo_order(["a", "b"], {"a": ["b"], "b": ["a"]})
def test_self_cycle(self):
self._must_raise(solve, [Task("a", 1, 1, ("a",))], 5)
def test_bad_cost_value_budget(self):
self._must_raise(solve, [Task("a", 0, 1, ())], 5)
self._must_raise(solve, [Task("a", 1, -1, ())], 5)
self._must_raise(solve, [Task("a", 1, 1, ())], -1)
self._must_raise(solve, [Task("a", 1, 1, ())], True)
def test_brute_force_also_validates(self):
self._must_raise(brute_force, [Task("a", 1, 1, ("x",))], 5)
class TestOptimalityAgainstOracle(unittest.TestCase):
"""The core evidence: DP optimum == brute-force optimum on random instances."""
def test_300_random_instances(self):
rng = random.Random(20261023)
checked = 0
non_trivial = 0
for _ in range(300):
n = rng.randint(1, 11)
tasks, total_cost = rand_instance(rng, n, rng.choice([0.0, 0.15, 0.3, 0.5]))
budget = rng.choice([0, rng.randint(1, 12), rng.randint(1, total_cost + 5)])
got = solve(tasks, budget)
want = brute_force(tasks, budget)
self.assertEqual(
got["value"],
want,
f"n={n} budget={budget} got={got['value']} brute={want} "
f"tasks={[(t.id, t.cost, t.value, t.requires) for t in tasks]}",
)
check_selection(tasks, budget, got["selected"])
self.assertEqual(got["value"], sum(t.value for t in tasks if t.id in set(got["selected"])))
self.assertEqual(got["cost"], sum(t.cost for t in tasks if t.id in set(got["selected"])))
self.assertLessEqual(greedy(tasks, budget)["value"], got["value"])
checked += 1
if want > 0:
non_trivial += 1
print(f"\n cross-check: {checked} instances, {non_trivial} with positive optimum")
self.assertEqual(checked, 300)
def test_dense_graphs_match_oracle(self):
rng = random.Random(777)
for _ in range(40):
tasks, total_cost = rand_instance(rng, 8, 0.6)
budget = rng.randint(1, total_cost)
self.assertEqual(solve(tasks, budget)["value"], brute_force(tasks, budget))
def test_zero_value_and_zero_cost_edges(self):
rng = random.Random(4242)
for _ in range(60):
tasks, _ = rand_instance(rng, rng.randint(1, 10), 0.35)
rebuilt = [
Task(t.id, t.cost, 0 if rng.random() < 0.4 else t.value, t.requires)
for t in tasks
]
budget = rng.randint(0, 30)
self.assertEqual(solve(rebuilt, budget)["value"], brute_force(rebuilt, budget))
class TestLargeInstances(unittest.TestCase):
def test_wide_and_deep_invariants(self):
rng = random.Random(99)
# deep chain of 60 tasks
deep = [Task(f"c{i}", rng.randint(1, 3), rng.randint(1, 5), (f"c{i-1}",) if i else ()) for i in range(60)]
r = solve(deep, 40)
check_selection(deep, 40, r["selected"])
self.assertEqual(r["value"], sum(t.value for t in deep if t.id in set(r["selected"])))
self.assertGreaterEqual(r["value"], greedy(deep, 40)["value"])
# wide: 60 independent tasks
wide = [Task(f"w{i}", rng.randint(1, 4), rng.randint(1, 9), ()) for i in range(60)]
r2 = solve(wide, 50)
check_selection(wide, 50, r2["selected"])
self.assertLessEqual(r2["value"], sum(t.value for t in wide))
self.assertGreaterEqual(r2["value"], greedy(wide, 50)["value"])
def test_runtime_bounded(self):
rng = random.Random(5)
tasks, _ = rand_instance(rng, 40, 0.2)
t0 = time.perf_counter()
solve(tasks, 60)
dt = time.perf_counter() - t0
print(f"\n n=40 dense instance solved in {dt:.3f}s")
self.assertLess(dt, 10.0)
class TestCliAndJson(unittest.TestCase):
def test_json_roundtrip(self):
payload = {
"budget": 9,
"tasks": [
{"id": "t1", "cost": 4, "value": 3, "requires": []},
{"id": "t2", "cost": 7, "value": 10, "requires": ["t1"]},
{"id": "t3", "cost": 5, "value": 6, "requires": []},
],
}
self.assertEqual(plan_from_json(payload)["value"], 9)
def test_cli_exit_codes(self):
with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as fh:
json.dump({"budget": 5, "tasks": [{"id": "a", "cost": 5, "value": 5}]}, fh)
good = fh.name
with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as fh:
fh.write('{"budget": 5, "tasks": [{"id": "a", "cost": 5, "value": 5, "requires": ["z"]}]}')
bad = fh.name
ok = subprocess.run([sys.executable, str(MODULE), good], capture_output=True, text=True)
self.assertEqual(ok.returncode, 0)
self.assertEqual(json.loads(ok.stdout)["value"], 5)
badrun = subprocess.run([sys.executable, str(MODULE), bad], capture_output=True, text=True)
self.assertEqual(badrun.returncode, 2)
if __name__ == "__main__":
unittest.main(verbosity=2)