Archived
fix(qwen38flashnext): make layouts deterministic and use host services
The gap-fill pass stopped on a 120 ms stopwatch and QWEN_* environment variables switched strategies, so the same job could nest differently with machine load or environment. Gap fill now stops after eight failed insertion sweeps, and the switches are internal properties with the old defaults. Part reading, work area, rotation angles, scoring and result assembly now use the host APIs; its collision gate is unchanged. Synthetic benchmark (5 jobs, salvage 0.5): all valid, cost 7660.01 -> 7572.05, time 839 -> 553 ms. Not yet calibrated on production-size jobs. Co-Authored-By: Codex <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,8 +7,7 @@ or select over any built-in engine, nester, filler, or runner.
|
||||
## Algorithm
|
||||
|
||||
Bottom-left greedy insertion over convex No-Fit-Polygons, with an exact material-clearance
|
||||
gate, driven sheet by sheet by a greedy demand scheduler. All geometry math is the engine's
|
||||
own (`Engine/`); it calls no built-in nester, filler, or runner.
|
||||
gate, driven sheet by sheet by a greedy demand scheduler. Placement and collision preparation remain in `Engine/`; it calls no built-in nester, filler, or runner.
|
||||
|
||||
- **`PartPreparation`** rebuilds each snapshot into a closed contour topology (perimeter +
|
||||
cutouts; rapids/scribe marks dropped), flattens it circumscribed (the collision polygon
|
||||
@@ -46,9 +45,9 @@ own (`Engine/`); it calls no built-in nester, filler, or runner.
|
||||
- **`JobSolver`** walks demands in its own order (priority, then largest material area -
|
||||
big parts first lay down the sheet skeleton the small parts fill against; measured 12%
|
||||
lower job cost than smallest-extent-first on the production job below) and drains each greedily,
|
||||
then a time-boxed gap-fill pass. For the next sheet it trials *every* available stock
|
||||
size independently and commits the trial delivering the cheapest plate area per unit of
|
||||
part area placed (the benchmark's cost function), breaking ties by priority coverage,
|
||||
then a gap-fill pass capped at eight failed insertion sweeps. For the next sheet it trials *every* available stock
|
||||
size independently and commits the trial delivering the cheapest `NestJobCost.NetSheetArea` per unit of
|
||||
material area placed (the benchmark's cost function), breaking ties by priority coverage,
|
||||
instance count, then plate area; lost trials change no job state. The job stops on met
|
||||
demand, exhausted stock, no further placement, or the plate cap. Deterministic:
|
||||
identical input, identical layout.
|
||||
@@ -82,7 +81,7 @@ to ~110 s via the cached-triangulation exact gate and the fast shell prefilter.
|
||||
## Tests
|
||||
|
||||
`tests/` holds acceptance tests whose layouts are checked by the benchmark's own
|
||||
`NestValidator` (bounds, spacing, quantities, stock, rotation), plus NFP geometry tests and a
|
||||
`NestLayoutCheck` through the shared `Engine.Testing` kit (bounds, spacing, quantities, stock, rotation and accounting), plus NFP geometry tests and a
|
||||
rotated-concave spacing regression test.
|
||||
|
||||
```bash
|
||||
@@ -107,3 +106,23 @@ dotnet <OpenNest>/OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll <
|
||||
`<OpenNest>` is the OpenNest checkout root. Or build and deploy in one step with
|
||||
`./Build-Engines.ps1 -Engines Qwen38FlashNext`. The engine appears in reports as
|
||||
`Qwen38FlashNextNestingEngine`.
|
||||
|
||||
## Shared services and determinism
|
||||
|
||||
`JobPartGeometry.TryRead` provides normalized material topology. Stock bounds/fit and
|
||||
result accounting/progress use the shared stock API and `NestJobResultBuilder`.
|
||||
`ForShape` supplies Automatic rotations; `EnumerateAngles(maxSamples: 4000)` preserves
|
||||
the sweep effort cap. Solid parts use cached `DistinctOutlines`; holed parts retain every
|
||||
legal candidate because perimeter symmetry alone cannot establish cutout symmetry.
|
||||
CollisionTolerance remains 0.0005, below `NestTolerances.ValidationOutline`.
|
||||
|
||||
Gap fill now counts failed insertion sweeps (default eight), with successful insertions
|
||||
bounded by demand. Internal test settings replace every QWEN environment switch. No
|
||||
stopwatch affects placement or diagnostics. Only the host cancellation token limits wall
|
||||
time. The shared determinism contract compares repeated and fresh solves.
|
||||
|
||||
On the five synthetic salvage jobs, every layout remained valid and complete; total cost
|
||||
fell from 7660.01 to 7572.05, with no job worse. Aggregate measured solve time remained
|
||||
below one second. These small fixtures do not calibrate production-scale retry costs;
|
||||
the eight-sweep default bounds effort independently of hardware. See
|
||||
[PR 5 results](../MIGRATION-PR5.md); older production numbers above describe the old version.
|
||||
|
||||
Reference in New Issue
Block a user