LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
SmallBucketSchedulingApplicabilityService.cs
Go to the documentation of this file.
1using LotSizingDataModel.Core.DecisionModel.Scheduling;
2using LotSizingDataModel.Core.PhysicalModel;
3using LotSizingDataModel.Core.Relationships;
4using LotSizingDataModel.Instance;
5using LotSizingDataModel.Instance.Classification;
6
8
10{
11 public bool CanBuild(
12 LotSizingInstance instance,
14 {
15 if(instance is null || instance.PlanningHorizon<=0) return false;
16
17 var entries=
18 instance.SupplyChain.Plants
19 .SelectMany(
20 plant =>
21 plant.WorkCenters.Select(
22 workCenter =>
23 (PlantId:plant.Id,WorkCenter:workCenter)))
24 .Where(entry=>entry.WorkCenter.SchedulingProfile is not null)
25 .Take(2)
26 .ToArray();
27
28 if(entries.Length!=1) return false;
29
30 int plantId=entries[0].PlantId;
31 WorkCenter wc=entries[0].WorkCenter;
32 ProductionSchedulingProfile profile=wc.SchedulingProfile!;
33
34 if(profile.BucketMode!=SchedulingBucketMode.SmallBucket ||
35 profile.MaximumProducedItemCount is null ||
36 profile.MaximumProducedItemCount.PlanningHorizon!=instance.PlanningHorizon ||
37 profile.HasSequenceDependentChangeoverTimes ||
38 profile.HasSequenceDependentChangeoverCosts ||
39 profile.Changeovers.Count>0) return false;
40
42 profile.SetupCarryOverPolicy==SetupCarryOverPolicy.Forbidden) return false;
43
44 if(!ValidCore(profile,instance.PlanningHorizon,kind)) return false;
45
46 var capacityConstraint=wc.CapacityConstraint;
47 if(capacityConstraint is null ||
48 capacityConstraint.PlanningHorizon!=instance.PlanningHorizon) return false;
49
50 if(wc.AdditionalCapacity is not null &&
52 wc.AdditionalCapacity.PlanningHorizon!=instance.PlanningHorizon)) return false;
53
54 LotSizingProblemFeatures features;
55 try
56 {
57 features=LotSizingProblemFeatureExtractor.Extract(instance.SupplyChain);
58 }
59 catch(InvalidOperationException)
60 {
61 return false;
62 }
63
64 if(features.HasMinimumLotSizes ||
65 features.HasMaximumLotSizes ||
66 features.HasLotSizeMultiples ||
67 features.IsMultiSite) return false;
68
69 // DLSP all-or-nothing production has no proven exact residual-capacity
70 // reformulation for setup/start-up time in this implementation.
72 (features.HasSetupTimes ||
73 features.HasStartUpTimes ||
74 features.HasAdditionalProductionCapacity)) return false;
75
76 var routings=instance.SupplyChain.ProductionRoutings.ToArray();
77 if(routings.Length==0 ||
78 routings.GroupBy(routing=>routing.ItemId).Any(group=>group.Count()!=1)) return false;
79
80 var itemIds=routings.Select(routing=>routing.ItemId).ToHashSet();
81 if(profile.HasInitialSetupState &&
82 !itemIds.Contains(profile.InitialSetupItemId)) return false;
83
84 if(profile.MaximumSetupCount is not null &&
85 profile.MaximumSetupCount.PlanningHorizon!=instance.PlanningHorizon) return false;
86
87 foreach(ProductionRouting routing in routings)
88 {
89 if(routing.WorkCenters.Count!=1 ||
90 routing.WorkCenters[0].PlantId!=plantId ||
91 routing.WorkCenters[0].WorkCenterId!=wc.Id) return false;
92
93 if(routing.GroupingConstraint is not null &&
94 routing.GroupingConstraint.PlanningHorizon!=instance.PlanningHorizon) return false;
95
96 var matches=
97 instance.SupplyChain.ProductionCharacteristics
98 .Where(
99 characteristic =>
100 characteristic.ItemId==routing.ItemId &&
101 characteristic.WorkCenter.PlantId==plantId &&
102 characteristic.WorkCenter.WorkCenterId==wc.Id)
103 .Take(2)
104 .ToArray();
105
106 if(matches.Length!=1) return false;
107
108 var characteristic=matches[0];
109 var unitCapacityConsumption=characteristic.UnitCapacityConsumption;
110
111 if(unitCapacityConsumption is null ||
112 unitCapacityConsumption.PlanningHorizon!=instance.PlanningHorizon) return false;
113
114 if(characteristic.SetupTime is not null &&
115 characteristic.SetupTime.PlanningHorizon!=instance.PlanningHorizon) return false;
116
117 if(characteristic.FixedSetupCost is not null &&
118 characteristic.FixedSetupCost.PlanningHorizon!=instance.PlanningHorizon) return false;
119
120 if(characteristic.StartUpTime is not null &&
121 characteristic.StartUpTime.PlanningHorizon!=instance.PlanningHorizon) return false;
122
123 if(characteristic.StartUpCost is not null &&
124 characteristic.StartUpCost.PlanningHorizon!=instance.PlanningHorizon) return false;
125
126 for(int period=1;
127 period<=instance.PlanningHorizon;
128 period++)
129 {
130 double cap=capacityConstraint[period];
131 double consumption=unitCapacityConsumption[period];
132
133 if(!double.IsFinite(cap) ||
134 cap<0 ||
135 !double.IsFinite(consumption) ||
136 consumption<=0) return false;
137
138 double startUpTime=characteristic.StartUpTime?[period]??0.0;
139 double startUpCost=characteristic.StartUpCost?[period]??0.0;
140
141 if(!double.IsFinite(startUpTime) ||
142 startUpTime<0 ||
143 !double.IsFinite(startUpCost) ||
144 startUpCost<0) return false;
145 }
146 }
147
148 return true;
149 }
150
151 private static bool ValidCore(
152 ProductionSchedulingProfile profile,
153 int horizon,
155 {
156 var required=
158 ? SmallBucketProductionMode.AllOrNothing
159 : SmallBucketProductionMode.Continuous;
160
161 if(profile.SmallBucketProductionMode!=required) return false;
162
163 int max=
165 ? 2
166 : 1;
167
168 for(int period=1;period<=horizon;period++)
169 {
170 int count=profile.MaximumProducedItemCount!.GetCount(period);
171 if(count<0||count>max) return false;
172 }
173
174 if(kind!=SmallBucketSchedulingFormulationKind.Plsp) return true;
175 if(profile.MaximumSetupCount is null) return false;
176
177 for(int period=1;period<=horizon;period++)
178 {
179 int count=profile.MaximumSetupCount.GetCount(period);
180 if(count<0||count>1) return false;
181 if(period==1&&count==0&&!profile.HasInitialSetupState) return false;
182 }
183
184 return true;
185 }
186}
bool CanBuild(LotSizingInstance instance, SmallBucketSchedulingFormulationKind kind)
SmallBucketSchedulingFormulationKind
Executable small-bucket scheduling formulation variants.