85 SupplyChain supplyChain,
87 productStructureAnalysis,
88 double numericalTolerance =
91 ArgumentNullException.ThrowIfNull(supplyChain);
93 ArgumentNullException.ThrowIfNull(
94 productStructureAnalysis);
99 WorkCenter[] workCenters =
100 EnumerateWorkCenters(
104 Warehouse[] warehouses =
109 bool hasTransportLanes =
110 supplyChain.TransportResources.Any(
112 supplyChain.TransportAssignments.Any(a => a.TransportResourceId == resource.Id));
118 supplyChain.Items.Count,
121 supplyChain.PlanningHorizon,
124 supplyChain.Plants.Count,
133 supplyChain.Suppliers.Count,
135 DistributionCenterCount =
140 TransportResourceCount =
145 ProductStructureRelationshipCount =
146 productStructureAnalysis
149 MaximumProductStructureDepth =
150 productStructureAnalysis
153 ProductStructureType =
154 productStructureAnalysis
158 supplyChain.Demands.Count > 0,
167 HasDeterministicDemand =
168 supplyChain.Demands.Count > 0,
170 HasTimeVaryingDemand =
171 supplyChain.Demands.Any(
175 numericalTolerance)),
177 HasInitialInventory =
178 supplyChain.Inventories.Any(
180 inventory.InitialInventory >
183 HasSafetyStockRequirements =
184 supplyChain.Inventories.Any(
186 inventory.SafetyStock is not
null),
190 .DistributionCenterSourcings
193 sourcing.BacklogConstraint
198 .DistributionCenterSourcings
201 sourcing.ShortageConstraint
209 .ProductionCharacteristics
212 HasProductionCapacityConstraints =
215 workCenter.CapacityConstraint
218 HasSharedProductionCapacity =
219 DetectSharedProductionCapacity(
222 HasTimeVaryingProductionCapacity =
225 workCenter.CapacityConstraint
231 numericalTolerance)),
235 .ProductionCharacteristics
238 characteristic.FixedSetupCost
243 .ProductionCharacteristics
246 characteristic.SetupTime
251 .ProductionCharacteristics
254 characteristic.StartUpCost
259 .ProductionCharacteristics
262 characteristic.StartUpTime
265 HasProductionSetupFamilies =
266 supplyChain.ProductionSetupFamilies.Count > 0,
268 HasProductionSetupFamilyTimes =
269 supplyChain.ProductionSetupFamilies.Any(
270 family => family.SetupTime is not
null),
272 HasProductionLeadTimes =
277 routing.LeadTime > 0),
284 routing.MinimumLotSize
292 routing.MaximumLotSize
295 HasLotSizeMultiples =
300 routing.LotSizeMultiple
303 HasGroupingConstraints =
304 supplyChain.ProductionRoutings.Any(
305 routing => routing.GroupingConstraint is not
null),
307 HasAdditionalProductionCapacity =
310 workCenter.AdditionalCapacity
318 HasSupplierCapacityConstraints =
323 delivery.CapacityConstraint
326 HasSupplierLeadTimes =
331 delivery.LeadTime > 0),
336 .TransportCharacteristics
339 HasTransportCapacityConstraints =
340 DetectTransportCapacityConstraints(
343 HasTransportLeadTimes =
348 supplyChain.GetTransportLanes(resource.Id))
353 HasAdditionalTransportCapacity =
354 DetectAdditionalTransportCapacity(
359 .DistributionCenterSourcings
365 HasWarehouseCapacityConstraints =
366 DetectWarehouseCapacityConstraints(
370 HasAdditionalWarehouseCapacity =
371 DetectAdditionalWarehouseCapacity(
383 supplyChain.Plants.Count +
385 .StandaloneWarehouses
389 HasFinancialConstraints =
390 supplyChain.PeriodicOperatingExpenditureBudget
393 HasMultipleObjectives =
394 supplyChain.ObjectivePolicy?
395 .HasMultipleEnabledCriteria ??
398 ObjectiveCriterionCount =
399 supplyChain.ObjectivePolicy?
400 .EnabledCriterionCount ??
403 PrimaryObjectiveKind =
404 supplyChain.ObjectivePolicy?
405 .PrimaryObjectiveKind ??
406 OptimizationObjectiveKind.Economic,
408 ObjectiveAggregationMode =
409 supplyChain.ObjectivePolicy?
411 ObjectiveAggregationMode.Single,
413 HasIntegratedScheduling =
414 supplyChain.WorkCenters.Any(
416 workCenter.SchedulingProfile is not
null),
418 SchedulingBucketMode =
419 supplyChain.WorkCenters
422 workCenter.SchedulingProfile?
424 SchedulingBucketMode.Unspecified)
427 mode != SchedulingBucketMode.Unspecified),
429 HasInitialSetupState =
430 supplyChain.WorkCenters.Any(
432 workCenter.SchedulingProfile?
433 .HasInitialSetupState ==
true),
436 supplyChain.WorkCenters.Any(
438 workCenter.SchedulingProfile?
439 .HasSetupCarryOver ==
true),
441 SetupCarryOverPolicy =
442 supplyChain.WorkCenters
443 .Where(workCenter => workCenter.SchedulingProfile is not
null)
444 .Select(workCenter => workCenter.SchedulingProfile!.SetupCarryOverPolicy)
447 .ToArray() is var carryOverPolicies &&
448 carryOverPolicies.Length == 1
449 ? carryOverPolicies[0]
450 : SetupCarryOverPolicy.Unspecified,
452 HasSequenceDependentChangeoverTimes =
453 supplyChain.WorkCenters.Any(
455 workCenter.SchedulingProfile?
456 .HasSequenceDependentChangeoverTimes ==
true),
458 HasSequenceDependentChangeoverCosts =
459 supplyChain.WorkCenters.Any(
461 workCenter.SchedulingProfile?
462 .HasSequenceDependentChangeoverCosts ==
true),
464 HasMaximumSetupCountConstraints =
465 supplyChain.WorkCenters.Any(
467 workCenter.SchedulingProfile?
468 .MaximumSetupCount is not
null),
470 SmallBucketProductionMode =
471 supplyChain.WorkCenters
474 workCenter.SchedulingProfile is not
null)
477 workCenter.SchedulingProfile!
478 .SmallBucketProductionMode)
481 .ToArray() is var schedulingModes &&
482 schedulingModes.Length == 1
484 : SmallBucketProductionMode.Unspecified,
486 SchedulingResourceCount =
487 supplyChain.WorkCenters.Count(
489 workCenter.SchedulingProfile is not
null),
491 HasMaximumProducedItemCountConstraint =
492 supplyChain.WorkCenters.Any(
494 workCenter.SchedulingProfile?
495 .MaximumProducedItemCount is not
null),
497 MaximumProducedItemCountPerBucket =
498 supplyChain.WorkCenters
501 workCenter.SchedulingProfile?
502 .MaximumProducedItemCountPerBucket ?? 0)
506 MaximumSetupTransitionsPerBucket =
507 supplyChain.WorkCenters
510 workCenter.SchedulingProfile?
511 .MaximumSetupTransitionsPerBucket ?? 0)
515 MicroPeriodLengthMode =
516 supplyChain.WorkCenters
517 .Where(workCenter => workCenter.SchedulingProfile is not
null)
518 .Select(workCenter => workCenter.SchedulingProfile!.MicroPeriodLengthMode)
519 .Distinct().Take(2).ToArray() is var microLengthModes &&
520 microLengthModes.Length == 1
521 ? microLengthModes[0]
522 : MicroPeriodLengthMode.Unspecified,
524 MicroPeriodAssignmentMode =
525 supplyChain.WorkCenters
526 .Where(workCenter => workCenter.SchedulingProfile is not
null)
527 .Select(workCenter => workCenter.SchedulingProfile!.MicroPeriodAssignmentMode)
528 .Distinct().Take(2).ToArray() is var microAssignmentModes &&
529 microAssignmentModes.Length == 1
530 ? microAssignmentModes[0]
531 : MicroPeriodAssignmentMode.Unspecified,
533 HasExplicitMicroPeriodGrid =
534 supplyChain.WorkCenters.Any(workCenter => workCenter.SchedulingProfile?.HasExplicitMicroPeriodGrid ==
true),
536 TotalMicroPeriodCount =
537 supplyChain.WorkCenters.Sum(workCenter => workCenter.SchedulingProfile?.TotalMicroPeriodCount ?? 0),
539 MaximumMicroPeriodCountPerMacroPeriod =
540 supplyChain.WorkCenters.Select(workCenter => workCenter.SchedulingProfile?.MaximumMicroPeriodCountPerMacroPeriod ?? 0).DefaultIfEmpty(0).Max(),
542 HasVariableMicroPeriodCount =
543 supplyChain.WorkCenters.Any(workCenter => workCenter.SchedulingProfile?.HasVariableMicroPeriodCount ==
true)