Skip to content

feat(server): run optimization on the Mechanism - #6

Draft
HugoFara wants to merge 1 commit into
mainfrom
feat/optimization-on-mechanism
Draft

HugoFara wants to merge 1 commit into
mainfrom
feat/optimization-on-mechanism

Conversation

@HugoFara

Copy link
Copy Markdown
Owner

Makes the Optimize tab work, natively and on the Pages demo. Depends on pylinkage 1.2.2 (HugoFara/pylinkage#58); CI stays red until it is on PyPI, then server/uv.lock gets bumped here.

What the stub was about

POST /api/optimization raised NotImplementedError since the server's legacy joint-based Linkage bridge went away with pylinkage.joints. Mechanism has had the optimizer contract since pylinkage 0.8.0, so the service now passes the Mechanism straight to particle_swarm_optimization / differential_evolution_optimization / minimize_linkage (Nelder-Mead) / trials_and_errors_optimization, with the request's objective as eval function and generate_bounds(center, bounds_factor, bounds_factor).

Doing so surfaced that Mechanism.set_constraints never changed the solved geometry (link lengths are cached at build time; the next step() snapped everything back) — every optimizer on a Mechanism was a no-op. Fixed in pylinkage#58.

Results

Each result is rebuilt from the request dict with the optimized constraints and solved once with dt=0 (drivers keep their angle), so its mechanism_dict — geometry is joint positions only — previews on the Optimize canvas and loads with "Send to Design Tab". Results that cannot be assembled keep their score and produce a warning. constraint_names are "<link> (length)" / "<driver> (radius)" in get_constraints() order. ValueErrors (bad joint_index, nothing to optimize) answer 400.

Tests

  • test_optimization_changes_the_mechanism: all four algorithms return a preview whose simulated x-extent is wider than the input's and matches the reported score.
  • check-wasm-backend.mjs: same assertion under Pyodide; PYLINKAGE_WHEEL=… installs a local pylinkage wheel instead of the PyPI pin, which is how this was verified before the release.
  • Headless Chromium against npm run dev + npm run server: load four-bar → Optimize → Run (PSO 30×100, 1.2 s) → 1 result, score 136.46 vs 35 baseline → Send to Design → 62-frame simulation.

POST /api/optimization was a stub raising NotImplementedError since the
legacy Linkage bridge went away with pylinkage.joints. Mechanism has
carried the optimizer contract (get/set_constraints, get/set_coords,
step, get_rotation_period) since pylinkage 0.8.0, so the service now
hands the Mechanism straight to pylinkage's PSO, differential evolution,
Nelder-Mead and grid search, with the request's objective as eval
function and bounds from generate_bounds(bounds_factor).

Each result is rebuilt from the request dict with the optimized
constraints and solved once with dt=0, so its mechanism_dict (geometry
is joint positions only) previews and loads in the Design tab.
Unassemblable results keep their score and get a warning instead.
ValueError (bad joint_index, nothing to optimize) answers 400.

Requires pylinkage >= 1.2.2: before it Mechanism.set_constraints did not
change the solved geometry (pylinkage#58), so every optimizer returned
the input mechanism. The smoke test asserts the optimized preview has a
wider stroke than the input for all four algorithms; the wasm check does
the same in Pyodide, and accepts PYLINKAGE_WHEEL= to test an unreleased
pylinkage.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant