mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-07 06:25:44 -05:00
fix(planning): re-plan the last kept part when a learned rule changes what follows it
When a blocked approach teaches an order rule, the search backs up to the earliest part that approach crossed, keeps the parts before it and re-plans the rest. The last kept part was planned facing the part that followed it in the old order. If the new order puts another part after it, its entry and exit still face the old one, so the plan ends with a stale exit that a kept-order re-plan of the same order would fix. Now that part is planned again, in the same place, facing its new successor; when its successor is unchanged nothing is re-planned. The locked-among-regenerated fixture's plan changes: rapid 67.60 -> 60.22, expansions 528 -> 268 (digest updated). Learning "cut the cutoff first" now takes 40 expansions rather than 22, because B is planned again to face the cutoff; retrying every entry of B took 60.
This commit is contained in:
1 parent
d57678ecee
commit
277719a1d6
4 files changed
+14
-6
No files matched your search
@@ -155,9 +155,14 @@ internal static class JointCuttingPlanSearch
|
||||
}
|
||||
// Back up to just before the earliest part the blocked approach crossed, keep the
|
||||
// parts cut before it, and re-plan the rest from where the tool is at that point.
|
||||
// The last kept part was planned facing the part that followed it in the old
|
||||
// order; when another part follows it now, it is planned again, in the same
|
||||
// place, facing that one.
|
||||
var back = attempt.Crossed.Min(part => Array.IndexOf(sequence, part));
|
||||
resume = attempt.BoundaryAt(back);
|
||||
sequence = [.. sequence.Take(back), .. CuttingNestedOrder.Plan(sequence[back..], resume.Position, nesting)];
|
||||
var rest = CuttingNestedOrder.Plan(sequence[back..], attempt.BoundaryAt(back).Position, nesting);
|
||||
var replan = back > 0 && rest.Length != 0 && rest[0] != sequence[back] ? back - 1 : back;
|
||||
resume = attempt.BoundaryAt(replan);
|
||||
sequence = [.. sequence.Take(back), .. rest];
|
||||
}
|
||||
}
|
||||
catch (BudgetExceededException)
|
||||
|
||||
@@ -147,8 +147,9 @@ public class CuttingDependencyTests
|
||||
Assert.True(result.Status == CuttingPlanStatus.Ready, Describe(result));
|
||||
var order = result.ProposedOrder.Select(o => o.SourcePart).ToList();
|
||||
Assert.True(order.IndexOf(cut) < order.IndexOf(a), string.Join(",", result.ProposedOrder.Select(o => o.SourceOrdinal)));
|
||||
// Learning at once took 22 expansions; retrying every entry of B first took 60.
|
||||
Assert.True(result.Expansions < 40, Describe(result));
|
||||
// Learning at once takes 40 expansions (22, then B planned again to face the cutoff that
|
||||
// now follows it); retrying every entry of B first took 60.
|
||||
Assert.True(result.Expansions < 50, Describe(result));
|
||||
}
|
||||
|
||||
// 100 x 100 sheet: squares at X 1-11 and 60-70; a cutoff at X 5 is trimmed around the left
|
||||
|
||||
@@ -45,7 +45,7 @@ public class PlanningCharacterizationTests
|
||||
[InlineData("holes-grid-kept-order", "07B70B43549E95C65407B24944DA8F7262B784CFC4ABF86241C10DD8272B1780")]
|
||||
[InlineData("rounded-circle-leads", "73677429BFC950669D238E834CAE48F54A483759BE4E0BB1437D096F0AF7F3DA")]
|
||||
[InlineData("tabbed-perimeters", "6858C09A02D73E4531D0D59B6CD1CFFFA2C9C8BA5F48CF4943D9C4AEC17195BA")]
|
||||
[InlineData("locked-among-regenerated", "D7914712F87513E38AA93776886AAFD5025EC89A0D4D7314F900A1163F830019")]
|
||||
[InlineData("locked-among-regenerated", "42AFCF0DE942F501D8542C091C9D4407EAE41DE9442F75300348DCDB4FF0C733")]
|
||||
public void FocusedFixture_PlansExactlyAsBefore(string name, string expected)
|
||||
{
|
||||
var nest = new Nest();
|
||||
|
||||
@@ -218,7 +218,9 @@ from the start point. Its 2-opt and Or-opt passes would grow with the square of
|
||||
part count. Replans after a learned rule use the plain tour. If a part on that order cannot be
|
||||
reached without crossing parts already cut, the search learns "cut this part
|
||||
before those", backs up to just before the earliest of them and re-plans the rest
|
||||
from the tool position there; parts cut before that point are kept. When the approach
|
||||
from the tool position there; parts cut before that point are kept. The last of them was
|
||||
planned facing the part that followed it; when another part follows it now, it is
|
||||
planned again, in the same place, facing that one. When the approach
|
||||
crossed the part cut just before the one it left from, the tool went on past that part
|
||||
and came back across it, so the search learns "cut those two the other way round"
|
||||
instead: the tool then leaves from the nearer one, as with two stacked strips cut far
|
||||
|
||||
Reference in new issue
Block a user