Skip to content

Repository files navigation

PDCE — Process-Dynamics & Control Engine

Implementation of build features F1–F3 from the sprint scope (05_Srikanth_sprint_scope.docx), backed by the proofs in PDCE_Research_Document_R1-R3.pdf and PDCE_Research_R1-R3.md.

A self-contained engine for systems that run in repeating, multi-phase stochastic cycles. It delivers three coupled, proven guarantees and exposes each as one API feature:

Feature API Research result Guarantee
F1 pdce.dynamics.run R1 Colored Stochastic Petri Net — bounded, live, convergent
F2 pdce.control.act R2 Active-inference selection = descent on the supplied objective
F3 pdce.consistency.check R3 Variational consistency guard with a detection bound

pdce.dynamics is an alias for pdce.cspn, matching the §5 naming.

The controller treats the objective as opaque (§4.2): it consumes only the scalar value and gradient through the interface, never the objective's meaning. The consistency guard runs ahead of any state-propagating action (§6/§7). The engine is deterministic given the same inputs and seed.

Three Coupled Pieces (§3 Design)

The Engine.run_coupled() method wires all three as three coupled pieces over the running process: each CSPN phase transition (F1) triggers a guarded control step (F2+F3).

  • R1 ↔ R2: the CSPN's stable marking (stationary π, Theorem 3.8) is the operating point the controller drives toward; the controller's fixed point ∇J = 0 (Theorem 4.1) coincides with it — one gradient, not two competing dynamics (Remark 4.3).
  • R3 → R2: consistency.check precedes control.act; a flagged configuration blocks propagation and surfaces the implicated schema element for repair.
  • R1 ↔ R3: boundedness makes RS(M₀) finite, so the ELBO and its detection bound are well-defined on the markings the system can actually reach.

Layout

pdce/
  __init__.py      dynamics = cspn alias (§5 naming), exports
  contract.py      §6 interface records + Objective / ModularDecomposition
  cspn.py          F1 — CSPN model, Gillespie sim, boundedness/liveness/convergence
  control.py       F2 — EFE = steepest admissible descent (Theorem 4.1)
  consistency.py   F3 — ELBO score, log-evidence-ratio test, threshold calibration
  engine.py        wires F1+F2+F3: guard-ahead-of-act, run_coupled, seeded determinism
app.py             FastAPI service exposing F1, F2, F3, and run_coupled as REST endpoints
fixtures/
  quadratic.py     §4.5 published R2 contract fixture (d=4 quadratic, A=diag(4,3,2,1))
  injection.py     §5.5 published R3 contract fixture (valid gen + violation injection)
tests/             contract-conformance tests for F1, F2, F3 and the engine

API Service

The PDCE engine is fully exposed as a RESTful service via FastAPI. It provides individual endpoints for F1, F2, and F3, plus a coupled endpoint that wires all three together over the running process.

Run the Server:

uvicorn app:app --reload --port 8000
  • Swagger UI: http://localhost:8000/docs
  • Documentation: See PDCE_API_Implementation.md for full request/response schemas, failure modes, and architectural details.

Run

pip install -r requirements.txt
python -m pytest -q          # 42 contract-conformance tests
python demo.py               # end-to-end multi-module run

Quick API

import numpy as np
from pdce import dynamics, control, consistency
from pdce.contract import CallableObjective, ModularDecomposition

# F1 — run the cyclic CSPN, get trajectory + diagnostics + convergence
net = dynamics.cyclic_net(K=3, n_mod=2, rates=[1.0, 2.0, 4.0])
traj = dynamics.run(net, horizon=200, seed=0)
traj.bounded, traj.live, traj.converged  # -> (True, True, True)
traj.spectral_gap                        # -> positive (Theorem 3.8)
traj.stationary_distribution             # -> {marking: probability}

# F2 — next objective-reducing move (action + predicted delta)
J  = lambda x: 0.5 * float(x @ np.diag([4,3,2,1]) @ x)
gJ = lambda x: np.diag([4,3,2,1]) @ x
obj = CallableObjective(J, gJ)
rec = control.act(np.ones(4), obj, ModularDecomposition.trivial(4), eta=0.1)
rec.action, rec.predicted_delta          # Delta s(a*) = -eta grad J

# F3 — score a configuration for consistency
from pdce.consistency import GaussianField, Schema
schema = Schema([GaussianField("timeout", mean=30, sigma=2, tau=2)])
out = consistency.check(schema, {"timeout": 31.0}, theta=0.0)
out.p_violation, out.element, out.confidence

# F1+F2+F3 coupled — three pieces wired over the running process
from pdce.engine import Engine
eng = Engine(
    objective=obj, schema=schema,
    decomposition=ModularDecomposition.trivial(4),
    config_from_state=lambda x: {"timeout": float(x[0])},
    net=net, theta=1e6, eta=0.1, seed=0,
)
steps, traj = eng.run_coupled(np.ones(4), horizon=50)

See pdce/*.py docstrings for the equation-by-equation crosswalk to the research document (Appendix B symbol-to-code map).

About

Process Dynamics and Control Engine

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages