diff --git a/README.md b/README.md index 2a4d8b0..5b2f04d 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,11 @@ Next steps (high level) - Add delta-sync protocol scaffolding and an auditable reconciliation log This work aligns with the roadmap described in AGENTS.md and is designed to be extended incrementally. +CatOpt Bridge (MVP) +- The CosmosMesh MVP includes a minimal CatOpt-style bridge that maps local optimization primitives + to a canonical representation suitable for cross-domain adapters. This scaffold provides: +- LocalProblem, SharedVariable, and DualVariable primitives and a lightweight round-trip message format. +- A small in-memory contract registry to version primitives and schemas. +- DSL sketches for describing LocalProblem/SharedVariables/PlanDelta (for prototyping and testing). + +- Usage example: see examples/catopt_demo.py for a quick end-to-end round-trip construction. diff --git a/examples/catopt_demo.py b/examples/catopt_demo.py new file mode 100644 index 0000000..1ea0d64 --- /dev/null +++ b/examples/catopt_demo.py @@ -0,0 +1,35 @@ +"""CatOpt Bridge Demo (CosmosMesh MVP) + +Minimal end-to-end example showing how to construct a LocalProblem, SharedVariables, +DualVariables and build a RoundTrip message via the CatOptBridge. +""" +from cosmosmesh_privacy_preserving_federated.catopt_bridge import LocalProblem, SharedVariable, DualVariable, CatOptBridge + + +def main(): + # Define a tiny local problem for a two-asset scenario + lp = LocalProblem( + problem_id="rover1-task-allocation", + objective="minimize energy consumption", + variables=["x1", "x2"], + constraints=["x1 + x2 <= 10", "x1 >= 0", "x2 >= 0"], + version=1, + ) + + # Shared variables (primal signals) between agents + sv1 = SharedVariable(name="eta1", value=0.5, version=1) + sv2 = SharedVariable(name="eta2", value=1.2, version=1) + dual1 = DualVariable(name="lambda1", value=0.1, version=1) + + # Build a round-trip message as the CatOptBridge would prepare for transport + rt = CatOptBridge.build_round_trip( + problem=lp, + shared=[sv1, sv2], + duals=[dual1], + ) + + print("RoundTrip Message:\n", rt) + + +if __name__ == "__main__": + main() diff --git a/tests/test_catopt_demo.py b/tests/test_catopt_demo.py new file mode 100644 index 0000000..7e158fb --- /dev/null +++ b/tests/test_catopt_demo.py @@ -0,0 +1,27 @@ +import json + +from cosmosmesh_privacy_preserving_federated.catopt_bridge import LocalProblem, SharedVariable, DualVariable, CatOptBridge + + +def test_round_trip_construction(): + lp = LocalProblem( + problem_id="test-problem", + objective="maximize throughput", + variables=["x"], + constraints=["x >= 0"], + version=1, + ) + sv = [SharedVariable(name="s", value=3.14, version=1)] + dv = [DualVariable(name="d", value=2.718, version=1)] + + msg = CatOptBridge.build_round_trip(problem=lp, shared=sv, duals=dv) + # Basic sanity checks on the envelope + assert isinstance(msg, dict) + assert msg.get("kind") == "RoundTrip" + payload = msg.get("payload") + assert isinstance(payload, dict) + assert payload.get("object")["id"] == lp.problem_id + # ensure morphisms present + morphisms = payload.get("morphisms") + assert isinstance(morphisms, list) + assert any(isinstance(m, dict) and m.get("name") == "s" for m in morphisms)