fix(benchmark): rank by sheet cost so engines can't game the score
The benchmark is about to be used as the objective for LLM-designed engines, and several gaps would have rewarded the wrong behavior: - Ranking was utilization-first, so dropping awkward parts raised the score. Rank valid > fully placed > cost > plates, where cost is salvage-credited sheet area plus a largest-sheet penalty per unplaced part; placing a part is never scored worse than omitting it. - Salvage rate was ignored in scoring; cost now uses EstimateNetArea, recomputed from job geometry rather than trusted from the engine. - Rotation constraints were never validated. Add RotationPolicy.Allows (shared with NestJobPlacementValidator) and check every placement. - Returned sheets were trusted, so an engine could loosen spacing or invent a size. Sheets must now match offered stock. - Part-in-part placements were flagged as overlaps; spacing now accounts for cutouts, with an X-sorted sweep to prune distant pairs. - Summary averaged per-job percentages; it now sums areas and cost. - --spacing and sheet sizes parsed with the current culture. - Warn when .nest jobs offer only their original sheet sizes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,29 @@ namespace OpenNest.Benchmark
|
||||
return jobs;
|
||||
}
|
||||
|
||||
/// <summary>Parses "WxL" with invariant-culture numbers, so "48.5x96" means the
|
||||
/// same thing on every machine (Size.Parse follows the current culture).</summary>
|
||||
public static bool TryParseSheetSize(string text, out Size size)
|
||||
{
|
||||
size = default;
|
||||
var dims = text?.Split('x', 'X');
|
||||
|
||||
if (dims == null || dims.Length != 2)
|
||||
return false;
|
||||
|
||||
var style = System.Globalization.NumberStyles.Float;
|
||||
var culture = System.Globalization.CultureInfo.InvariantCulture;
|
||||
|
||||
if (
|
||||
!double.TryParse(dims[0].Trim(), style, culture, out var width)
|
||||
|| !double.TryParse(dims[1].Trim(), style, culture, out var length)
|
||||
)
|
||||
return false;
|
||||
|
||||
size = new Size(width, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<string> ResolveFiles(string inputPath)
|
||||
{
|
||||
if (Directory.Exists(inputPath))
|
||||
|
||||
Reference in New Issue
Block a user