From 424ff15ebc26dfb8717037420a68dcccaec4862c Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sat, 19 Sep 2026 08:25:57 -0400 Subject: [PATCH] docs: describe INestingEngine-based benchmark comparison --- CLAUDE.md | 9 +++++---- README.md | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a2dd99e..f2c29e4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -74,12 +74,13 @@ GPU-accelerated pair evaluation for best-fit nesting. `GpuPairEvaluator` impleme Training data collection for ML angle prediction. `TrainingDatabase` stores per-angle nesting results in SQLite via EF Core for offline model training. ### OpenNest.Benchmark (console app, depends on Core + Engine + IO) -Compares registered `NestEngineBase` implementations against each other on real `.nest` files. Fully generic — it never hardcodes drawing geometry, just reads whatever drawings/quantities/plate settings each input file already has. +Compares registered `INestingEngine` implementations against each other on real `.nest` files. Each engine solves the whole job — it owns its own multi-plate/size strategy rather than being handed one already-sized plate at a time. Fully generic — it never hardcodes drawing geometry, just reads whatever drawings/quantities/plate settings each input file already has. - `JobLoader` builds `BenchmarkJob`s from a `.nest` file or a folder of them via `NestReader`, using every drawing with `Quantity.Required > 0`. `--sheet-sizes` can sweep a fixed list of plate sizes instead of each file's own. -- `BenchmarkRunner` gives each (job, engine) pair a fresh `Plate`/`NestItem` list (`BenchmarkJob.CreatePlate()`/`CreateItems()`) so engines can't see each other's mutated state, then calls the engine's `Nest()` and times it. -- `NestValidator` checks the returned layout: every part inside `Plate.WorkArea()`, every pair at least `Plate.PartSpacing` apart (checked geometrically via each part's own world-space polygon, inflated by the spacing — works on arbitrary concave/holed shapes, not just bounding boxes), and no drawing over its requested quantity. An invalid or throwing run scores zero for that job. -- Scoring matches `Plate.Utilization()` (placed drawing area / full sheet area, `Plate.Area()`). If an engine placed every requested part, ties are broken by the smaller used-bounding-box (`Report`'s ranking rule) — a more compact layout leaves a bigger usable remnant. +- `BenchmarkJob.BuildNestJob(maxPlates)` converts the job into a `NestJob`: one `NestJobPart` per requested drawing (via `DrawingJobMapper.FromDrawing`) and one `NestPlateStock` per candidate sheet size (unlimited quantity — the engine decides how many of each size it uses). +- `BenchmarkRunner` calls each engine's `INestingEngine.Solve(NestJob)` once per job, under a wall-clock timeout so a runaway or hanging engine can't stall the whole benchmark run, then materializes the result back into legacy `Plate`/`Part` objects via `NestResultMaterializer` for scoring. +- `NestValidator` checks the returned layout: every part inside `Plate.WorkArea()`, every pair at least `Plate.PartSpacing` apart (checked geometrically via each part's own world-space polygon, inflated by the spacing — works on arbitrary concave/holed shapes, not just bounding boxes), and no drawing over its requested quantity. An invalid, throwing, or timed-out run scores zero for that job. +- Scoring matches `Plate.Utilization()` (placed drawing area / full sheet area, `Plate.Area()`). If an engine placed every requested part, ties are broken by fewer plates used (`Report`'s ranking rule) — using fewer sheets to do the same job wastes less material. - `--engines Name1,Name2` filters to specific registered engines (default: all); `--csv ` writes a flat per-job CSV alongside the console report. ### OpenNest.Mcp (console app, depends on Core + Engine + IO) diff --git a/README.md b/README.md index 9e2fd1e..2b27ab3 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ dotnet run --project OpenNest.Console/OpenNest.Console.csproj -- project.zip ext ## Benchmarking Nest Engines -`OpenNest.Benchmark` compares every registered `NestEngineBase` implementation against each other on a set of `.nest` files, scoring by material utilization: +`OpenNest.Benchmark` compares every registered `INestingEngine` implementation against each other on a set of `.nest` files, scoring by material utilization. Each engine owns its own multi-plate/size strategy for the whole job — how many plates it uses, of which sizes, and how demand splits across them: ```bash # Benchmark all registered engines against every .nest file in a folder @@ -179,7 +179,7 @@ dotnet run --project OpenNest.Benchmark/OpenNest.Benchmark.csproj -- job.nest \ --sheet-sizes 48x96,60x96,60x120,72x120,72x144 --engines Default,Astra,Claude --csv results.csv ``` -An engine's layout is rejected (scoring zero for that job) if any part falls outside the work area, any two parts are closer than the required spacing, or a drawing gets more parts placed than requested. +An engine's layout is rejected (scoring zero for that job) if any part falls outside the work area, any two parts are closer than the required spacing, or a drawing gets more parts placed than requested. A run that doesn't finish within its time budget also scores zero, as a timeout. ## Project Structure @@ -213,7 +213,7 @@ OpenNest.sln | **OpenNest.Gpu** | GPU-accelerated bitmap overlap detection for best-fit pair evaluation using ILGPU. | | **OpenNest.Posts.Cincinnati** | Post-processor plugin for Cincinnati CL-707/800/900/940/CLX laser cutting machines. Outputs Cincinnati-format G-code with material library, kerf compensation, and pierce logic. | | **OpenNest.Mcp** | MCP (Model Context Protocol) server exposing nesting operations as tools for AI assistants. | -| **OpenNest.Benchmark** | Runs every registered nest engine against a set of `.nest` files and scores them by material utilization, so engine implementations can be compared head-to-head. | +| **OpenNest.Benchmark** | Runs every registered whole-job nesting engine (`INestingEngine`) against a set of `.nest` files and scores them by material utilization, so competing engines — each owning its own multi-plate strategy — can be compared head-to-head. | | **OpenNest.Tests** | 89 test files covering core geometry, fill strategies, splitting, bending, BOM import, post-processing, and the API. | ## Nesting Engines