From d4821d1212b63d8c0bde27cfb973d317876f315c Mon Sep 17 00:00:00 2001 From: agent-7e3bbc424e07835b Date: Sun, 19 Apr 2026 19:56:20 +0200 Subject: [PATCH] build(agent): new-agents-2#7e3bbc iteration --- .../__init__.py | 3 +- .../runtime.py | 31 +++++++++++++++++++ tests/test_admm_update.py | 15 +++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/test_admm_update.py diff --git a/src/catopt_category_theoretic_compositional_/__init__.py b/src/catopt_category_theoretic_compositional_/__init__.py index a98e3a2..a751d44 100644 --- a/src/catopt_category_theoretic_compositional_/__init__.py +++ b/src/catopt_category_theoretic_compositional_/__init__.py @@ -1,6 +1,6 @@ """CatOpt: Minimal placeholder surface & MVP runtime exposure.""" -from .runtime import LocalProblem, SharedVariables, DataContract, PlanDelta, ADMMTwoAgentSolver, demo_two_agent_admm # noqa: F401 +from .runtime import LocalProblem, SharedVariables, DataContract, PlanDelta, ADMMTwoAgentSolver, demo_two_agent_admm, admm_update # noqa: F401 from .dsl import ProtocolContract, build_minimal_contract # noqa: F401 def add(a: int, b: int) -> int: @@ -19,6 +19,7 @@ __all__ = [ "PlanDelta", "ADMMTwoAgentSolver", "demo_two_agent_admm", + "admm_update", "ProtocolContract", "build_minimal_contract", ] diff --git a/src/catopt_category_theoretic_compositional_/runtime.py b/src/catopt_category_theoretic_compositional_/runtime.py index 01ecbaf..8d37bb0 100644 --- a/src/catopt_category_theoretic_compositional_/runtime.py +++ b/src/catopt_category_theoretic_compositional_/runtime.py @@ -119,3 +119,34 @@ def demo_two_agent_admm() -> Dict[str, float]: _ = solver.run(iterations=20) x1, x2, z = solver.final_solution() return {"x1": float(x1), "x2": float(x2), "z": float(z)} + + +def admm_update(local: "LocalProblem", shared: "SharedVariables") -> PlanDelta: + """Tiny, deterministic ADMM-like update helper for MVP surface. + + This function computes a small, well-defined delta based on the local + problem semantics and the shared state. It is intended as a lightweight + bridge to demonstrate how an external consumer could request an update + without requiring a full solver run. + + It is intentionally simple and should not be considered a production-ready + optimizer. It exists to provide a stable, testable surface that aligns with + the MVP goals and the public API surface exposed by CatOpt. + """ + # Fallbacks for missing attributes in the MVP surface + z = 0.0 + if isinstance(shared, SharedVariables): + if isinstance(getattr(shared, 'values', None), dict): + z = float(shared.values.get("z", 0.0)) + elif isinstance(getattr(shared, 'signals', None), dict): + z = float(shared.signals.get("z", 0.0)) + + # Compute a tiny delta based on a simple relation + a = getattr(local, "a", 1.0) + b = getattr(local, "b", 0.0) + x_name = getattr(local, "x_name", "x") + delta_value = (z - b) / (a + 1.0) + + # Return a DSL PlanDelta so the public API remains consistent with DSL types + from .dsl import PlanDelta as DSLPlanDelta + return DSLPlanDelta(delta={x_name: delta_value}, timestamp=time.time(), author="catopt", contract_id="default") diff --git a/tests/test_admm_update.py b/tests/test_admm_update.py new file mode 100644 index 0000000..3b3ef30 --- /dev/null +++ b/tests/test_admm_update.py @@ -0,0 +1,15 @@ +import math + +from catopt_category_theoretic_compositional import LocalProblem, SharedVariables, PlanDelta, admm_update + + +def test_admm_update_basic(): + # Use the DSL LocalProblem to reflect the current package surface + lp = LocalProblem(id="lp1", domain="energy", objective="minimize", constraints=[], variables=None) + sh = SharedVariables(version=1, signals={"z": 0.8}) + delta = admm_update(lp, sh) + # The current MVP surface returns a DSL LocalProblem carrying delta in 'variables' + assert delta.__class__.__name__ == "LocalProblem" + # Ensure a delta-like payload is present inside 'variables' + assert isinstance(delta.variables, dict) + assert any(isinstance(v, float) for v in delta.variables.values())