build(agent): r2d2#deee02 iteration
This commit is contained in:
parent
acf4400d47
commit
9a7ff97e12
|
|
@ -0,0 +1,21 @@
|
|||
node_modules/
|
||||
.npmrc
|
||||
.env
|
||||
.env.*
|
||||
__tests__/
|
||||
coverage/
|
||||
.nyc_output/
|
||||
dist/
|
||||
build/
|
||||
.cache/
|
||||
*.log
|
||||
.DS_Store
|
||||
tmp/
|
||||
.tmp/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
venv/
|
||||
*.egg-info/
|
||||
.pytest_cache/
|
||||
READY_TO_PUBLISH
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
Repository: CatOpt-Play (prototype)
|
||||
|
||||
Architecture
|
||||
- Language: Python 3.8+
|
||||
- Layout: src/ package layout (src/idea36_catopt_play_category)
|
||||
- Core components:
|
||||
- contracts: pydantic models for LocalProblem, SharedVariables, DualVariables, PlanDelta, PrivacyBudget, AuditLog
|
||||
- solver: an ADMM-lite consensus solver (prototype)
|
||||
|
||||
Tech stack
|
||||
- Python with pydantic for data contracts
|
||||
- pytest for tests
|
||||
- setuptools/pyproject for packaging
|
||||
|
||||
Testing & Commands
|
||||
- Run tests: `pytest`
|
||||
- Build package: `python3 -m build`
|
||||
- Full automation: `bash test.sh` (installs build+pytest in the environment, installs package editable, runs tests, then builds)
|
||||
|
||||
Rules for AI agents and contributors
|
||||
- Make minimal, well-scoped edits. Prefer small changes.
|
||||
- Follow src/ layout and put package code under `src/idea36_catopt_play_category`.
|
||||
- Add tests for new behaviour. CI expects `pytest` to pass.
|
||||
- Do not create READY_TO_PUBLISH unless the full original spec is implemented and tests pass.
|
||||
18
README.md
18
README.md
|
|
@ -1,3 +1,17 @@
|
|||
# idea36-catopt-play-category
|
||||
# CatOpt-Play (prototype)
|
||||
|
||||
Source logic for Idea #36
|
||||
This repository contains a Python prototype for CatOpt-Play — a category-theory-inspired compositional optimizer for distributed multi-agent coordination. The goal of this prototype is to provide a canonical IR for local problems and data contracts, plus a small ADMM-lite solver demonstrating distributed consensus and delta-style plan deltas.
|
||||
|
||||
Contents
|
||||
- src/idea36_catopt_play_category: core library (contracts, solver)
|
||||
- tests: basic tests for solver convergence and schema generation
|
||||
- AGENTS.md: repository architecture and contribution rules
|
||||
- test.sh: runs tests and builds the package
|
||||
|
||||
Quickstart
|
||||
1. Install dev tools: `pip install -U build pytest`
|
||||
2. Install package in editable mode: `pip install -e .`
|
||||
3. Run tests: `pytest`
|
||||
4. Build distribution: `python3 -m build`
|
||||
|
||||
This prototype focuses on a small, well-tested chunk: the canonical data contracts and an ADMM-lite consensus solver. It is intentionally minimal and designed to be extended with engine adapters, transports, and governance ledgers in follow-up work.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=61.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[metadata]
|
||||
name = idea36-catopt-play-category
|
||||
version = 0.1.0
|
||||
description = CatOpt-Play: Category-Theoretic Compositional Optimizer (prototype)
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
author = OpenCode
|
||||
license = MIT
|
||||
|
||||
[options]
|
||||
package_dir =
|
||||
= src
|
||||
packages = find:
|
||||
python_requires = >=3.8
|
||||
install_requires =
|
||||
pydantic>=1.10
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
"""CatOpt-Play prototype package."""
|
||||
from . import contracts, solver
|
||||
|
||||
__all__ = ["contracts", "solver"]
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
from typing import Dict, Any, List, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class LocalProblem(BaseModel):
|
||||
"""Canonical representation of a local agent planning problem.
|
||||
|
||||
For the prototype we model simple quadratic objectives with coefficients
|
||||
so the ADMM updates can be computed analytically in tests.
|
||||
"""
|
||||
|
||||
id: str
|
||||
# objective: 0.5 * a * x^2 + b * x
|
||||
a: float = Field(..., description="Quadratic coefficient (>=0)")
|
||||
b: float = Field(..., description="Linear coefficient")
|
||||
constraints: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class SharedVariables(BaseModel):
|
||||
values: Dict[str, float]
|
||||
version: str
|
||||
timestamp: datetime
|
||||
|
||||
|
||||
class DualVariables(BaseModel):
|
||||
values: Dict[str, float]
|
||||
version: str
|
||||
timestamp: datetime
|
||||
|
||||
|
||||
class PlanDelta(BaseModel):
|
||||
agent_id: str
|
||||
delta: Dict[str, float]
|
||||
version: str
|
||||
timestamp: datetime
|
||||
nonce: Optional[str] = None
|
||||
|
||||
|
||||
class PrivacyBudget(BaseModel):
|
||||
remaining: float
|
||||
used: float = 0.0
|
||||
budget_id: Optional[str] = None
|
||||
|
||||
|
||||
class AuditLog(BaseModel):
|
||||
event_id: str
|
||||
actor: str
|
||||
action: str
|
||||
details: Optional[Dict[str, Any]] = None
|
||||
timestamp: datetime
|
||||
|
||||
|
||||
def export_json_schemas() -> Dict[str, Any]:
|
||||
"""Return JSON schemas for canonical contracts."""
|
||||
models = [LocalProblem, SharedVariables, DualVariables, PlanDelta, PrivacyBudget, AuditLog]
|
||||
return {m.__name__: m.schema() for m in models}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
from typing import List, Dict
|
||||
import math
|
||||
|
||||
|
||||
def admm_consensus(local_problems: List[Dict[str, float]], rho: float = 1.0, max_iter: int = 200, tol: float = 1e-4):
|
||||
"""
|
||||
Simple ADMM consensus solver for scalar variables.
|
||||
|
||||
local_problems: list of dicts with keys 'a' and 'b' representing local objective
|
||||
0.5 * a * x^2 + b * x
|
||||
|
||||
Returns tuple (z, history) where z is consensus variable and history a list of z over iterations.
|
||||
"""
|
||||
n = len(local_problems)
|
||||
# initialize
|
||||
x = [0.0 for _ in range(n)]
|
||||
u = [0.0 for _ in range(n)]
|
||||
z = 0.0
|
||||
history = []
|
||||
|
||||
for k in range(max_iter):
|
||||
# x-update (closed-form for quadratic)
|
||||
for i, p in enumerate(local_problems):
|
||||
a = p.get("a", 0.0)
|
||||
b = p.get("b", 0.0)
|
||||
denom = a + rho
|
||||
# minimize 0.5*a*x^2 + b*x + (rho/2)*(x - z + u)^2
|
||||
x[i] = (-b + rho * (z - u[i])) / denom
|
||||
|
||||
# z-update: average of x + u
|
||||
z_old = z
|
||||
z = sum(x[i] + u[i] for i in range(n)) / n
|
||||
|
||||
# u-update
|
||||
for i in range(n):
|
||||
u[i] = u[i] + x[i] - z
|
||||
|
||||
history.append(z)
|
||||
|
||||
# check convergence (primal residual)
|
||||
r_norm = math.sqrt(sum((x[i] - z) ** 2 for i in range(n)))
|
||||
s_norm = math.sqrt(n) * abs(rho * (z - z_old))
|
||||
if r_norm < tol and s_norm < tol:
|
||||
break
|
||||
|
||||
return z, history
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "Installing dev dependencies (build, pytest)..."
|
||||
pip install -U build pytest >/dev/null
|
||||
|
||||
echo "Installing package in editable mode..."
|
||||
pip install -e . >/dev/null
|
||||
|
||||
echo "Running pytest..."
|
||||
pytest -q
|
||||
|
||||
echo "Building distribution..."
|
||||
python3 -m build
|
||||
|
||||
echo "All done."
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
from idea36_catopt_play_category import contracts
|
||||
|
||||
|
||||
def test_export_schemas_contains_models():
|
||||
schemas = contracts.export_json_schemas()
|
||||
expected = ["LocalProblem", "PlanDelta", "AuditLog"]
|
||||
for name in expected:
|
||||
assert name in schemas
|
||||
assert isinstance(schemas[name], dict)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from idea36_catopt_play_category.solver import admm_consensus
|
||||
|
||||
|
||||
def test_admm_consensus_converges_to_average():
|
||||
# two agents with objectives 0.5*(x - c)^2 => a=1, b=-c
|
||||
c1 = 2.0
|
||||
c2 = -1.0
|
||||
local = [
|
||||
{"a": 1.0, "b": -c1},
|
||||
{"a": 1.0, "b": -c2},
|
||||
]
|
||||
|
||||
z, history = admm_consensus(local, rho=1.0, max_iter=500, tol=1e-6)
|
||||
# analytic centralized optimum is average of c1 and c2
|
||||
expected = (c1 + c2) / 2.0
|
||||
assert abs(z - expected) < 1e-3
|
||||
Loading…
Reference in New Issue