refactor: Redesign nesting engines with pipeline pattern and add exhaustive search

- Rename Result to PackResult to avoid confusion with Result<T>
- Add PackingRequest as immutable configuration replacing mutable engine state
- Add PackingStrategy enum (AdvancedFit, BestFit, Exhaustive)
- Implement pipeline pattern for composable packing steps
- Rewrite AdvancedFitEngine as stateless using pipeline
- Rewrite BestFitEngine as stateless
- Add ExhaustiveFitEngine with symmetry breaking for optimal solutions
  - Tries all bin assignments to find minimum bins
  - Falls back to AdvancedFit for >20 items
  - Configurable threshold via constructor
- Update IEngine/IEngineFactory interfaces for new pattern
- Add strategy parameter to MCP tools

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-01 15:16:40 -05:00
parent 6e8469be4b
commit b19ecf3610
22 changed files with 898 additions and 351 deletions

View File

@@ -0,0 +1,54 @@
namespace CutList.Core.Nesting
{
/// <summary>
/// Represents the result of a bin packing operation.
/// Contains the packed bins and any items that could not be placed.
/// </summary>
public class PackResult
{
private readonly List<BinItem> _itemsNotUsed;
private readonly List<Bin> _bins;
public PackResult()
{
_itemsNotUsed = new List<BinItem>();
_bins = new List<Bin>();
}
public PackResult(IEnumerable<Bin> bins, IEnumerable<BinItem> itemsNotUsed)
{
_bins = bins?.ToList() ?? new List<Bin>();
_itemsNotUsed = itemsNotUsed?.ToList() ?? new List<BinItem>();
}
/// <summary>
/// Items that could not be placed in any bin (e.g., too large for stock).
/// </summary>
public IReadOnlyList<BinItem> ItemsNotUsed => _itemsNotUsed;
/// <summary>
/// The bins containing packed items.
/// </summary>
public IReadOnlyList<Bin> Bins => _bins;
public void AddItemNotUsed(BinItem item)
{
_itemsNotUsed.Add(item);
}
public void AddItemsNotUsed(IEnumerable<BinItem> items)
{
_itemsNotUsed.AddRange(items);
}
public void AddBin(Bin bin)
{
_bins.Add(bin);
}
public void AddBins(IEnumerable<Bin> bins)
{
_bins.AddRange(bins);
}
}
}