feat(solver): Phase 4 — second solver plugin (API validation) #290

Closed
opened 2026-02-19 21:02:07 +00:00 by forbes · 0 comments
Owner

Summary

Implement a second solver plugin to validate that the IKCSolver API genuinely supports different solving strategies.

Scope

Pure-Python solver implementation

  • Subclass kcsolve.IKCSolver (the abstract base class from Phase 2)
  • Implement the three required methods: name(), supported_joints(), solve(ctx)
  • Register at runtime via kcsolve.register_solver("relaxation", RelaxationSolver)
  • Simple relaxation or gradient-descent approach operating on SolveContext (parts with Transform placements, constraints with marker-based attachment points)

API validation

  • Verify SolverRegistry handles multiple solvers: kcsolve.available() returns both "ondsel" and the new solver
  • Test solver switching: same SolveContext solves with either solver, results match within tolerance
  • Validate kcsolve.load("relaxation") and kcsolve.load("ondsel") return independent instances
  • Confirm joints_for() returns different capability sets per solver
  • Verify set_default() / get_default() work correctly with multiple solvers

Benchmarking

  • Correctness: compare SolveResult.placements between OndselAdapter and the new solver within tolerance
  • Performance: measure solve() wall time on representative assemblies
  • Report SolveResult.dof and SolveResult.diagnostics parity

Solver capabilities

The new solver need not support all 20 joint types that OndselAdapter handles. A minimal subset (e.g. Fixed, Revolute, Coincident, Slider) is sufficient to validate the multi-solver architecture.

Example

import kcsolve

class RelaxationSolver(kcsolve.IKCSolver):
    def name(self):
        return "Iterative Relaxation"

    def supported_joints(self):
        return [
            kcsolve.BaseJointKind.Fixed,
            kcsolve.BaseJointKind.Revolute,
            kcsolve.BaseJointKind.Coincident,
        ]

    def solve(self, ctx):
        result = kcsolve.SolveResult()
        # ... iterative relaxation on ctx.parts / ctx.constraints ...
        result.status = kcsolve.SolveStatus.Success
        return result

kcsolve.register_solver("relaxation", RelaxationSolver)

Deliverable

Two interchangeable solvers, selectable per-assembly via SolverRegistry.

Dependencies

  • #287 — Phase 1: C++ API (merged, PR #297)
  • #288 — Phase 2: Python bindings (PR #298)

References

  • docs/INTER_SOLVER.md §6.3 — pure-Python solver support
  • docs/INTER_SOLVER.md §9 — Phase 4
  • docs/src/reference/kcsolve-python.md — full Python API reference
## Summary Implement a second solver plugin to validate that the `IKCSolver` API genuinely supports different solving strategies. ## Scope ### Pure-Python solver implementation - Subclass `kcsolve.IKCSolver` (the abstract base class from Phase 2) - Implement the three required methods: `name()`, `supported_joints()`, `solve(ctx)` - Register at runtime via `kcsolve.register_solver("relaxation", RelaxationSolver)` - Simple relaxation or gradient-descent approach operating on `SolveContext` (parts with `Transform` placements, constraints with marker-based attachment points) ### API validation - Verify `SolverRegistry` handles multiple solvers: `kcsolve.available()` returns both `"ondsel"` and the new solver - Test solver switching: same `SolveContext` solves with either solver, results match within tolerance - Validate `kcsolve.load("relaxation")` and `kcsolve.load("ondsel")` return independent instances - Confirm `joints_for()` returns different capability sets per solver - Verify `set_default()` / `get_default()` work correctly with multiple solvers ### Benchmarking - Correctness: compare `SolveResult.placements` between OndselAdapter and the new solver within tolerance - Performance: measure `solve()` wall time on representative assemblies - Report `SolveResult.dof` and `SolveResult.diagnostics` parity ### Solver capabilities The new solver need not support all 20 joint types that OndselAdapter handles. A minimal subset (e.g. `Fixed`, `Revolute`, `Coincident`, `Slider`) is sufficient to validate the multi-solver architecture. ## Example ```python import kcsolve class RelaxationSolver(kcsolve.IKCSolver): def name(self): return "Iterative Relaxation" def supported_joints(self): return [ kcsolve.BaseJointKind.Fixed, kcsolve.BaseJointKind.Revolute, kcsolve.BaseJointKind.Coincident, ] def solve(self, ctx): result = kcsolve.SolveResult() # ... iterative relaxation on ctx.parts / ctx.constraints ... result.status = kcsolve.SolveStatus.Success return result kcsolve.register_solver("relaxation", RelaxationSolver) ``` ## Deliverable Two interchangeable solvers, selectable per-assembly via `SolverRegistry`. ## Dependencies - #287 — Phase 1: C++ API (merged, PR #297) - #288 — Phase 2: Python bindings (PR #298) ## References - `docs/INTER_SOLVER.md` §6.3 — pure-Python solver support - `docs/INTER_SOLVER.md` §9 — Phase 4 - `docs/src/reference/kcsolve-python.md` — full Python API reference
forbes added the enhancement label 2026-02-19 21:02:07 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/create#290