LotSizingDataModel.Instance 2.0.1
Lot-sizing instance representation, descriptors and problem characterization.
Loading...
Searching...
No Matches
SolutionMethodDefinition.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Xml.Serialization;
5using LotSizingDataModel.Core.Common;
7using LotSizingDataModel.Solution.Common;
8
10
11/// <summary>
12/// Describes the applicability, capabilities and limitations
13/// of a solution method for lot-sizing problem instances.
14/// </summary>
15/// <remarks>
16/// A method definition is independent from a particular
17/// instance. It specifies:
18/// <list type="bullet">
19/// <item>
20/// <description>
21/// the problem families supported by the method;
22/// </description>
23/// </item>
24/// <item>
25/// <description>
26/// the product structures accepted by the method;
27/// </description>
28/// </item>
29/// <item>
30/// <description>
31/// required, supported, partially supported and unsupported
32/// problem features;
33/// </description>
34/// </item>
35/// <item>
36/// <description>
37/// whether the method applies to complete problems,
38/// relaxations or subproblems;
39/// </description>
40/// </item>
41/// <item>
42/// <description>
43/// hard and recommended instance-size limits;
44/// </description>
45/// </item>
46/// <item>
47/// <description>
48/// the type of result or bound that the method can provide.
49/// </description>
50/// </item>
51/// </list>
52///
53/// Feature codes normally refer to properties of
54/// <c>LotSizingProblemFeatures</c>.
55/// </remarks>
56[Serializable]
57[XmlType(TypeName = "solutionMethodDefinition")]
58public sealed class SolutionMethodDefinition : ModelObject
59{
60 private string _methodCode =
61 string.Empty;
62
63 private string _name =
64 string.Empty;
65
66 private string _methodVersion =
67 string.Empty;
68
69 private SolutionMethodKind _methodKind =
70 default;
71
72 private string _description =
73 string.Empty;
74
75 private bool _isEnabled =
76 true;
77
78 private int _priority;
79
80 private bool _supportsAnyProblemFamily;
81
82 private bool _supportsAnyProductStructure;
83
84 private bool _supportsUnclassifiedProblems;
85
86 private bool _supportsAmbiguousClassifications;
87
88 private bool _supportsCompleteProblems =
89 true;
90
91 private bool _supportsRelaxations;
92
93 private bool _supportsSubproblems;
94
95 private bool _canProduceFeasibleSolution =
96 true;
97
98 private bool _canProveOptimality;
99
100 private bool _canProvideLowerBound;
101
102 private bool _canProvideUpperBound =
103 true;
104
105 private int? _maximumItemCount;
106
107 private int? _maximumPlanningHorizon;
108
109 private int? _maximumPlantCount;
110
111 private int? _maximumWorkCenterCount;
112
113 private int? _maximumWarehouseCount;
114
115 private int? _maximumSupplierCount;
116
117 private int? _maximumTransportResourceCount;
118
119 private int? _maximumBillOfMaterialsRelationshipCount;
120
121 private int? _maximumProductStructureDepth;
122
123 private int? _recommendedMaximumItemCount;
124
125 private int? _recommendedMaximumPlanningHorizon;
126
127 private int?
128 _recommendedMaximumBillOfMaterialsRelationshipCount;
129
130 private int? _recommendedMaximumProductStructureDepth;
131
132 private string _implementationName =
133 string.Empty;
134
135 private string _implementationVersion =
136 string.Empty;
137
138 private string _comment =
139 string.Empty;
140
141 /// <summary>
142 /// Initializes an empty solution-method definition.
143 /// </summary>
144 /// <remarks>
145 /// This constructor is required for XML serialization.
146 /// </remarks>
148 {
149 }
150
151 /// <summary>
152 /// Initializes a solution-method definition.
153 /// </summary>
154 /// <param name="methodCode">
155 /// Stable code identifying the solution method.
156 /// </param>
157 /// <param name="name">
158 /// Human-readable method name.
159 /// </param>
160 /// <param name="methodKind">
161 /// General category of the solution method.
162 /// </param>
163 /// <exception cref="ArgumentException">
164 /// Thrown when <paramref name="methodCode"/> or
165 /// <paramref name="name"/> is empty.
166 /// </exception>
168 string methodCode,
169 string name,
170 SolutionMethodKind methodKind)
171 {
172 if (string.IsNullOrWhiteSpace(methodCode))
173 {
174 throw new ArgumentException(
175 "A solution-method code is required.",
176 nameof(methodCode));
177 }
178
179 if (string.IsNullOrWhiteSpace(name))
180 {
181 throw new ArgumentException(
182 "A solution-method name is required.",
183 nameof(name));
184 }
185
186 MethodCode =
187 methodCode;
188
189 Name =
190 name;
191
192 MethodKind =
193 methodKind;
194 }
195
196 /// <summary>
197 /// Gets or sets the stable code identifying the solution
198 /// method.
199 /// </summary>
200 /// <remarks>
201 /// Examples include <c>WW-DP</c>,
202 /// <c>MILP-GENERIC</c>, <c>MLLP-DP</c> and
203 /// <c>FIX-AND-OPTIMIZE</c>.
204 /// </remarks>
205 [XmlAttribute("methodCode")]
206 public string MethodCode
207 {
208 get => _methodCode;
209 set
210 {
211 if (SetProperty(
212 ref _methodCode,
213 NormalizeCode(value)))
214 {
215 OnPropertyChanged(
216 nameof(HasMethodCode));
217
218 OnPropertyChanged(
219 nameof(IsValidDefinition));
220
221 OnPropertyChanged(
222 nameof(CanBeEvaluated));
223 }
224 }
225 }
226
227 /// <summary>
228 /// Gets or sets the human-readable name of the method.
229 /// </summary>
230 [XmlAttribute("name")]
231 public string Name
232 {
233 get => _name;
234 set
235 {
236 if (SetProperty(
237 ref _name,
238 value?.Trim() ?? string.Empty))
239 {
240 OnPropertyChanged(
241 nameof(HasName));
242
243 OnPropertyChanged(
244 nameof(IsValidDefinition));
245
246 OnPropertyChanged(
247 nameof(CanBeEvaluated));
248 }
249 }
250 }
251
252 /// <summary>
253 /// Gets or sets the version of the method definition.
254 /// </summary>
255 /// <remarks>
256 /// This version describes the method capabilities stored
257 /// in the catalog. It does not necessarily identify a
258 /// software implementation version.
259 /// </remarks>
260 [XmlAttribute("methodVersion")]
261 public string MethodVersion
262 {
263 get => _methodVersion;
264 set
265 {
266 if (SetProperty(
267 ref _methodVersion,
268 value?.Trim() ?? string.Empty))
269 {
270 OnPropertyChanged(
271 nameof(HasMethodVersion));
272 }
273 }
274 }
275
276 /// <summary>
277 /// Gets or sets the general category of the solution
278 /// method.
279 /// </summary>
280 [XmlAttribute("methodKind")]
281 public SolutionMethodKind MethodKind
282 {
283 get => _methodKind;
284 set => SetProperty(
285 ref _methodKind,
286 value);
287 }
288
289 /// <summary>
290 /// Gets or sets a human-readable description of the
291 /// method and its principal assumptions.
292 /// </summary>
293 [XmlElement("description")]
294 public string Description
295 {
296 get => _description;
297 set
298 {
299 if (SetProperty(
300 ref _description,
301 value?.Trim() ?? string.Empty))
302 {
303 OnPropertyChanged(
304 nameof(HasDescription));
305 }
306 }
307 }
308
309 /// <summary>
310 /// Gets or sets a value indicating whether this method
311 /// definition is enabled in the catalog.
312 /// </summary>
313 [XmlAttribute("isEnabled")]
314 public bool IsEnabled
315 {
316 get => _isEnabled;
317 set
318 {
319 if (SetProperty(
320 ref _isEnabled,
321 value))
322 {
323 OnPropertyChanged(
324 nameof(CanBeEvaluated));
325 }
326 }
327 }
328
329 /// <summary>
330 /// Gets or sets the catalog priority of the method.
331 /// </summary>
332 /// <remarks>
333 /// A greater value gives the method preference when two
334 /// recommendations otherwise have equivalent scores.
335 /// </remarks>
336 [XmlAttribute("priority")]
337 public int Priority
338 {
339 get => _priority;
340 set => SetProperty(
341 ref _priority,
342 value);
343 }
344
345 /// <summary>
346 /// Gets or sets a value indicating whether the method is
347 /// independent from a specific classified problem family.
348 /// </summary>
349 /// <remarks>
350 /// This property is appropriate for generic mathematical
351 /// programming methods whose applicability is primarily
352 /// determined by features and model size.
353 /// </remarks>
354 [XmlAttribute("supportsAnyProblemFamily")]
356 {
357 get => _supportsAnyProblemFamily;
358 set
359 {
360 if (SetProperty(
361 ref _supportsAnyProblemFamily,
362 value))
363 {
364 NotifyDefinitionValidityProperties();
365 }
366 }
367 }
368
369 /// <summary>
370 /// Gets or sets a value indicating whether the method
371 /// supports any valid product structure.
372 /// </summary>
373 /// <remarks>
374 /// When this property is <see langword="false"/>, the
375 /// accepted structures must be listed in
376 /// <see cref="SupportedProductStructureTypes"/>.
377 /// </remarks>
378 [XmlAttribute("supportsAnyProductStructure")]
380 {
381 get => _supportsAnyProductStructure;
382 set
383 {
384 if (SetProperty(
385 ref _supportsAnyProductStructure,
386 value))
387 {
388 NotifyDefinitionValidityProperties();
389 }
390 }
391 }
392
393 /// <summary>
394 /// Gets or sets a value indicating whether the method may
395 /// be evaluated for a problem that has not been assigned
396 /// to a known family.
397 /// </summary>
398 [XmlAttribute("supportsUnclassifiedProblems")]
400 {
401 get => _supportsUnclassifiedProblems;
402 set => SetProperty(
403 ref _supportsUnclassifiedProblems,
404 value);
405 }
406
407 /// <summary>
408 /// Gets or sets a value indicating whether the method may
409 /// be evaluated when the problem-family classification is
410 /// ambiguous.
411 /// </summary>
412 [XmlAttribute("supportsAmbiguousClassifications")]
414 {
415 get => _supportsAmbiguousClassifications;
416 set => SetProperty(
417 ref _supportsAmbiguousClassifications,
418 value);
419 }
420
421 /// <summary>
422 /// Gets or sets a value indicating whether the method can
423 /// solve a complete problem instance.
424 /// </summary>
425 [XmlAttribute("supportsCompleteProblems")]
427 {
428 get => _supportsCompleteProblems;
429 set
430 {
431 if (SetProperty(
432 ref _supportsCompleteProblems,
433 value))
434 {
435 NotifyScopeProperties();
436 }
437 }
438 }
439
440 /// <summary>
441 /// Gets or sets a value indicating whether the method can
442 /// solve a relaxation of a complete problem.
443 /// </summary>
444 [XmlAttribute("supportsRelaxations")]
446 {
447 get => _supportsRelaxations;
448 set
449 {
450 if (SetProperty(
451 ref _supportsRelaxations,
452 value))
453 {
454 NotifyScopeProperties();
455 }
456 }
457 }
458
459 /// <summary>
460 /// Gets or sets a value indicating whether the method can
461 /// solve subproblems extracted from a complete instance.
462 /// </summary>
463 [XmlAttribute("supportsSubproblems")]
465 {
466 get => _supportsSubproblems;
467 set
468 {
469 if (SetProperty(
470 ref _supportsSubproblems,
471 value))
472 {
473 NotifyScopeProperties();
474 }
475 }
476 }
477
478 /// <summary>
479 /// Gets or sets a value indicating whether the method can
480 /// produce a feasible solution to the problem scope being
481 /// solved.
482 /// </summary>
483 [XmlAttribute("canProduceFeasibleSolution")]
485 {
486 get => _canProduceFeasibleSolution;
487 set => SetProperty(
488 ref _canProduceFeasibleSolution,
489 value);
490 }
491
492 /// <summary>
493 /// Gets or sets a value indicating whether the method can
494 /// prove optimality under its stated assumptions.
495 /// </summary>
496 [XmlAttribute("canProveOptimality")]
498 {
499 get => _canProveOptimality;
500 set => SetProperty(
501 ref _canProveOptimality,
502 value);
503 }
504
505 /// <summary>
506 /// Gets or sets a value indicating whether the method can
507 /// produce a valid lower bound for a minimization problem.
508 /// </summary>
509 [XmlAttribute("canProvideLowerBound")]
511 {
512 get => _canProvideLowerBound;
513 set => SetProperty(
514 ref _canProvideLowerBound,
515 value);
516 }
517
518 /// <summary>
519 /// Gets or sets a value indicating whether the method can
520 /// produce a valid upper bound for a minimization problem.
521 /// </summary>
522 /// <remarks>
523 /// A feasible solution normally provides an upper bound
524 /// for a minimization problem.
525 /// </remarks>
526 [XmlAttribute("canProvideUpperBound")]
528 {
529 get => _canProvideUpperBound;
530 set => SetProperty(
531 ref _canProvideUpperBound,
532 value);
533 }
534
535 /// <summary>
536 /// Gets the problem-family codes directly supported by
537 /// the method.
538 /// </summary>
539 /// <remarks>
540 /// Codes are compared case-insensitively.
541 ///
542 /// Examples include <c>LS-U</c>, <c>LS-C</c>,
543 /// <c>CLSP</c>, <c>MLLP</c> and <c>MLCLSP</c>.
544 /// </remarks>
545 [XmlArray("supportedProblemTypeCodes")]
546 [XmlArrayItem("problemTypeCode")]
547 public List<string> SupportedProblemTypeCodes { get; } =
548 new();
549
550 /// <summary>
551 /// Gets the problem-family codes for which the method is
552 /// considered particularly appropriate.
553 /// </summary>
554 [XmlArray("preferredProblemTypeCodes")]
555 [XmlArrayItem("problemTypeCode")]
556 public List<string> PreferredProblemTypeCodes { get; } =
557 new();
558
559 /// <summary>
560 /// Gets the product structures supported by the method.
561 /// </summary>
562 /// <remarks>
563 /// This collection is used when
564 /// <see cref="SupportsAnyProductStructure"/> is
565 /// <see langword="false"/>.
566 /// </remarks>
567 [XmlArray("supportedProductStructureTypes")]
568 [XmlArrayItem("productStructureType")]
569 public List<ProductStructureType>
572 new();
573
574 /// <summary>
575 /// Gets the feature codes that must be active for the
576 /// method to be applicable.
577 /// </summary>
578 /// <remarks>
579 /// A required feature is expected to represent a Boolean
580 /// property whose value must be <see langword="true"/>.
581 /// </remarks>
582 [XmlArray("requiredFeatureCodes")]
583 [XmlArrayItem("featureCode")]
584 public List<string> RequiredFeatureCodes { get; } =
585 new();
586
587 /// <summary>
588 /// Gets the active feature codes explicitly supported by
589 /// the method.
590 /// </summary>
591 /// <remarks>
592 /// This collection is primarily intended for optional
593 /// extensions such as backlogging, transportation or
594 /// additional capacity.
595 /// </remarks>
596 [XmlArray("supportedFeatureCodes")]
597 [XmlArrayItem("featureCode")]
598 public List<string> SupportedFeatureCodes { get; } =
599 new();
600
601 /// <summary>
602 /// Gets the feature codes supported only through an
603 /// adaptation, approximation, decomposition or
604 /// implementation-specific extension.
605 /// </summary>
606 [XmlArray("partiallySupportedFeatureCodes")]
607 [XmlArrayItem("featureCode")]
609 {
610 get;
611 } = new();
612
613 /// <summary>
614 /// Gets the active feature codes that make the method
615 /// incompatible with the complete problem.
616 /// </summary>
617 [XmlArray("unsupportedFeatureCodes")]
618 [XmlArrayItem("featureCode")]
619 public List<string> UnsupportedFeatureCodes { get; } =
620 new();
621
622 /// <summary>
623 /// Gets the feature codes that make the method
624 /// particularly attractive when they are active.
625 /// </summary>
626 [XmlArray("preferredFeatureCodes")]
627 [XmlArrayItem("featureCode")]
628 public List<string> PreferredFeatureCodes { get; } =
629 new();
630
631 /// <summary>
632 /// Gets or sets the hard maximum number of items accepted
633 /// by the method or its current implementation.
634 /// </summary>
635 [XmlElement("maximumItemCount", IsNullable = true)]
637 {
638 get => _maximumItemCount;
639 set => SetHardLimit(
640 ref _maximumItemCount,
641 value,
642 nameof(MaximumItemCount));
643 }
644
645 /// <summary>
646 /// Gets or sets the hard maximum number of planning
647 /// periods accepted by the method.
648 /// </summary>
649 [XmlElement("maximumPlanningHorizon", IsNullable = true)]
651 {
652 get => _maximumPlanningHorizon;
653 set => SetHardLimit(
654 ref _maximumPlanningHorizon,
655 value,
656 nameof(MaximumPlanningHorizon));
657 }
658
659 /// <summary>
660 /// Gets or sets the hard maximum number of plants
661 /// accepted by the method.
662 /// </summary>
663 [XmlElement("maximumPlantCount", IsNullable = true)]
665 {
666 get => _maximumPlantCount;
667 set => SetHardLimit(
668 ref _maximumPlantCount,
669 value,
670 nameof(MaximumPlantCount));
671 }
672
673 /// <summary>
674 /// Gets or sets the hard maximum number of work centers
675 /// accepted by the method.
676 /// </summary>
677 [XmlElement("maximumWorkCenterCount", IsNullable = true)]
679 {
680 get => _maximumWorkCenterCount;
681 set => SetHardLimit(
682 ref _maximumWorkCenterCount,
683 value,
684 nameof(MaximumWorkCenterCount));
685 }
686
687 /// <summary>
688 /// Gets or sets the hard maximum number of warehouses
689 /// accepted by the method.
690 /// </summary>
691 [XmlElement("maximumWarehouseCount", IsNullable = true)]
693 {
694 get => _maximumWarehouseCount;
695 set => SetHardLimit(
696 ref _maximumWarehouseCount,
697 value,
698 nameof(MaximumWarehouseCount));
699 }
700
701 /// <summary>
702 /// Gets or sets the hard maximum number of suppliers
703 /// accepted by the method.
704 /// </summary>
705 [XmlElement("maximumSupplierCount", IsNullable = true)]
707 {
708 get => _maximumSupplierCount;
709 set => SetHardLimit(
710 ref _maximumSupplierCount,
711 value,
712 nameof(MaximumSupplierCount));
713 }
714
715 /// <summary>
716 /// Gets or sets the hard maximum number of transport
717 /// resources accepted by the method.
718 /// </summary>
719 [XmlElement(
720 "maximumTransportResourceCount",
721 IsNullable = true)]
723 {
724 get => _maximumTransportResourceCount;
725 set => SetHardLimit(
726 ref _maximumTransportResourceCount,
727 value,
729 }
730
731 /// <summary>
732 /// Gets or sets the hard maximum number of
733 /// bill-of-materials relationships accepted by the
734 /// method.
735 /// </summary>
736 [XmlElement(
737 "maximumBillOfMaterialsRelationshipCount",
738 IsNullable = true)]
740 {
741 get => _maximumBillOfMaterialsRelationshipCount;
742 set => SetHardLimit(
743 ref _maximumBillOfMaterialsRelationshipCount,
744 value,
745 nameof(
747 }
748
749 /// <summary>
750 /// Gets or sets the hard maximum product-structure depth
751 /// accepted by the method.
752 /// </summary>
753 [XmlElement(
754 "maximumProductStructureDepth",
755 IsNullable = true)]
757 {
758 get => _maximumProductStructureDepth;
759 set => SetHardLimit(
760 ref _maximumProductStructureDepth,
761 value,
763 }
764
765 /// <summary>
766 /// Gets or sets the recommended maximum number of items
767 /// for effective use of the method.
768 /// </summary>
769 /// <remarks>
770 /// Exceeding this value does not make the method
771 /// incompatible, but may reduce its recommendation score.
772 /// </remarks>
773 [XmlElement(
774 "recommendedMaximumItemCount",
775 IsNullable = true)]
777 {
778 get => _recommendedMaximumItemCount;
779 set => SetRecommendedLimit(
780 ref _recommendedMaximumItemCount,
781 value,
783 }
784
785 /// <summary>
786 /// Gets or sets the recommended maximum planning horizon
787 /// for effective use of the method.
788 /// </summary>
789 [XmlElement(
790 "recommendedMaximumPlanningHorizon",
791 IsNullable = true)]
793 {
794 get => _recommendedMaximumPlanningHorizon;
795 set => SetRecommendedLimit(
796 ref _recommendedMaximumPlanningHorizon,
797 value,
799 }
800
801 /// <summary>
802 /// Gets or sets the recommended maximum number of
803 /// bill-of-materials relationships.
804 /// </summary>
805 [XmlElement(
806 "recommendedMaximumBillOfMaterialsRelationshipCount",
807 IsNullable = true)]
808 public int?
810 {
811 get =>
812 _recommendedMaximumBillOfMaterialsRelationshipCount;
813
814 set => SetRecommendedLimit(
815 ref
816 _recommendedMaximumBillOfMaterialsRelationshipCount,
817 value,
818 nameof(
820 }
821
822 /// <summary>
823 /// Gets or sets the recommended maximum product-structure
824 /// depth.
825 /// </summary>
826 [XmlElement(
827 "recommendedMaximumProductStructureDepth",
828 IsNullable = true)]
830 {
831 get => _recommendedMaximumProductStructureDepth;
832 set => SetRecommendedLimit(
833 ref _recommendedMaximumProductStructureDepth,
834 value,
835 nameof(
837 }
838
839 /// <summary>
840 /// Gets or sets the name of an implementation associated
841 /// with this method definition.
842 /// </summary>
843 /// <remarks>
844 /// This property is optional because a method definition
845 /// may describe an algorithm independently from any
846 /// software implementation.
847 /// </remarks>
848 [XmlElement("implementationName")]
849 public string ImplementationName
850 {
851 get => _implementationName;
852 set
853 {
854 if (SetProperty(
855 ref _implementationName,
856 value?.Trim() ?? string.Empty))
857 {
858 OnPropertyChanged(
860 }
861 }
862 }
863
864 /// <summary>
865 /// Gets or sets the version of the associated method
866 /// implementation.
867 /// </summary>
868 [XmlAttribute("implementationVersion")]
870 {
871 get => _implementationVersion;
872 set
873 {
874 if (SetProperty(
875 ref _implementationVersion,
876 value?.Trim() ?? string.Empty))
877 {
878 OnPropertyChanged(
880 }
881 }
882 }
883
884 /// <summary>
885 /// Gets the documentary or bibliographic references
886 /// associated with the method.
887 /// </summary>
888 [XmlArray("references")]
889 [XmlArrayItem("reference")]
890 public List<string> References { get; } =
891 new();
892
893 /// <summary>
894 /// Gets or sets an optional explanatory comment.
895 /// </summary>
896 [XmlElement("comment")]
897 public string Comment
898 {
899 get => _comment;
900 set
901 {
902 if (SetProperty(
903 ref _comment,
904 value?.Trim() ?? string.Empty))
905 {
906 OnPropertyChanged(
907 nameof(HasComment));
908 }
909 }
910 }
911
912 /// <summary>
913 /// Gets a value indicating whether a stable method code
914 /// has been recorded.
915 /// </summary>
916 [XmlIgnore]
917 public bool HasMethodCode =>
918 !string.IsNullOrWhiteSpace(
919 MethodCode);
920
921 /// <summary>
922 /// Gets a value indicating whether a human-readable name
923 /// has been recorded.
924 /// </summary>
925 [XmlIgnore]
926 public bool HasName =>
927 !string.IsNullOrWhiteSpace(
928 Name);
929
930 /// <summary>
931 /// Gets a value indicating whether a method-definition
932 /// version has been recorded.
933 /// </summary>
934 [XmlIgnore]
935 public bool HasMethodVersion =>
936 !string.IsNullOrWhiteSpace(
938
939 /// <summary>
940 /// Gets a value indicating whether a description has been
941 /// recorded.
942 /// </summary>
943 [XmlIgnore]
944 public bool HasDescription =>
945 !string.IsNullOrWhiteSpace(
947
948 /// <summary>
949 /// Gets a value indicating whether the method explicitly
950 /// supports at least one problem family.
951 /// </summary>
952 [XmlIgnore]
954 SupportedProblemTypeCodes.Count > 0;
955
956 /// <summary>
957 /// Gets a value indicating whether the method identifies
958 /// at least one preferred problem family.
959 /// </summary>
960 [XmlIgnore]
962 PreferredProblemTypeCodes.Count > 0;
963
964 /// <summary>
965 /// Gets a value indicating whether the method explicitly
966 /// supports at least one product-structure type.
967 /// </summary>
968 [XmlIgnore]
970 SupportedProductStructureTypes.Count > 0;
971
972 /// <summary>
973 /// Gets a value indicating whether the method has at least
974 /// one explicit feature capability or restriction.
975 /// </summary>
976 [XmlIgnore]
977 public bool HasFeatureRules =>
978 RequiredFeatureCodes.Count > 0 ||
979 SupportedFeatureCodes.Count > 0 ||
980 PartiallySupportedFeatureCodes.Count > 0 ||
981 UnsupportedFeatureCodes.Count > 0 ||
982 PreferredFeatureCodes.Count > 0;
983
984 /// <summary>
985 /// Gets a value indicating whether the method supports at
986 /// least one problem scope.
987 /// </summary>
988 [XmlIgnore]
989 public bool HasSupportedScope =>
993
994 /// <summary>
995 /// Gets a value indicating whether at least one hard size
996 /// limit has been specified.
997 /// </summary>
998 [XmlIgnore]
999 public bool HasHardSizeLimits =>
1000 MaximumItemCount.HasValue ||
1001 MaximumPlanningHorizon.HasValue ||
1002 MaximumPlantCount.HasValue ||
1003 MaximumWorkCenterCount.HasValue ||
1004 MaximumWarehouseCount.HasValue ||
1005 MaximumSupplierCount.HasValue ||
1006 MaximumTransportResourceCount.HasValue ||
1007 MaximumBillOfMaterialsRelationshipCount.HasValue ||
1009
1010 /// <summary>
1011 /// Gets a value indicating whether at least one
1012 /// recommended size limit has been specified.
1013 /// </summary>
1014 [XmlIgnore]
1016 RecommendedMaximumItemCount.HasValue ||
1017 RecommendedMaximumPlanningHorizon.HasValue ||
1019 .HasValue ||
1021
1022 /// <summary>
1023 /// Gets a value indicating whether implementation
1024 /// information has been recorded.
1025 /// </summary>
1026 [XmlIgnore]
1028 !string.IsNullOrWhiteSpace(
1030 !string.IsNullOrWhiteSpace(
1032
1033 /// <summary>
1034 /// Gets a value indicating whether at least one reference
1035 /// has been recorded.
1036 /// </summary>
1037 [XmlIgnore]
1038 public bool HasReferences =>
1039 References.Count > 0;
1040
1041 /// <summary>
1042 /// Gets a value indicating whether an explanatory comment
1043 /// has been recorded.
1044 /// </summary>
1045 [XmlIgnore]
1046 public bool HasComment =>
1047 !string.IsNullOrWhiteSpace(
1048 Comment);
1049
1050 /// <summary>
1051 /// Gets a value indicating whether the method definition
1052 /// contains the minimum information required for
1053 /// evaluation.
1054 /// </summary>
1055 [XmlIgnore]
1056 public bool IsValidDefinition =>
1057 Validate().Count == 0;
1058
1059 /// <summary>
1060 /// Gets a value indicating whether this method can be
1061 /// considered by the solution-method advisor.
1062 /// </summary>
1063 [XmlIgnore]
1064 public bool CanBeEvaluated =>
1065 IsEnabled &&
1067
1068 /// <summary>
1069 /// Determines whether this method supports a problem
1070 /// family code.
1071 /// </summary>
1072 /// <param name="problemTypeCode">
1073 /// Problem-family code to test.
1074 /// </param>
1075 /// <returns>
1076 /// <see langword="true"/> when every family is supported
1077 /// or when the supplied family appears in the supported
1078 /// family collection; otherwise,
1079 /// <see langword="false"/>.
1080 /// </returns>
1082 string problemTypeCode)
1083 {
1085 {
1086 return true;
1087 }
1088
1089 return ContainsCode(
1091 problemTypeCode);
1092 }
1093
1094 /// <summary>
1095 /// Determines whether this method identifies a problem
1096 /// family as particularly appropriate.
1097 /// </summary>
1098 /// <param name="problemTypeCode">
1099 /// Problem-family code to test.
1100 /// </param>
1101 /// <returns>
1102 /// <see langword="true"/> when the code appears in
1103 /// <see cref="PreferredProblemTypeCodes"/>.
1104 /// </returns>
1106 string problemTypeCode)
1107 {
1108 return ContainsCode(
1110 problemTypeCode);
1111 }
1112
1113 /// <summary>
1114 /// Determines whether this method supports a given
1115 /// product-structure type.
1116 /// </summary>
1117 /// <param name="productStructureType">
1118 /// Product-structure type to test.
1119 /// </param>
1120 /// <returns>
1121 /// <see langword="true"/> when every product structure is
1122 /// supported or when the supplied structure appears in
1123 /// the supported structure collection.
1124 /// </returns>
1126 ProductStructureType productStructureType)
1127 {
1128 return
1131 productStructureType);
1132 }
1133
1134 /// <summary>
1135 /// Determines whether an active feature is explicitly
1136 /// supported by the method.
1137 /// </summary>
1138 /// <param name="featureCode">
1139 /// Feature code to test.
1140 /// </param>
1141 /// <returns>
1142 /// <see langword="true"/> when the feature is required or
1143 /// explicitly supported.
1144 /// </returns>
1146 string featureCode)
1147 {
1148 return
1149 ContainsCode(
1151 featureCode) ||
1152 ContainsCode(
1154 featureCode);
1155 }
1156
1157 /// <summary>
1158 /// Determines whether a feature is only partially
1159 /// supported.
1160 /// </summary>
1161 /// <param name="featureCode">
1162 /// Feature code to test.
1163 /// </param>
1164 /// <returns>
1165 /// <see langword="true"/> when the feature appears in the
1166 /// partially supported feature collection.
1167 /// </returns>
1169 string featureCode)
1170 {
1171 return ContainsCode(
1173 featureCode);
1174 }
1175
1176 /// <summary>
1177 /// Determines whether a feature is explicitly unsupported.
1178 /// </summary>
1179 /// <param name="featureCode">
1180 /// Feature code to test.
1181 /// </param>
1182 /// <returns>
1183 /// <see langword="true"/> when the feature appears in the
1184 /// unsupported feature collection.
1185 /// </returns>
1187 string featureCode)
1188 {
1189 return ContainsCode(
1191 featureCode);
1192 }
1193
1194 /// <summary>
1195 /// Replaces the supported problem-family codes.
1196 /// </summary>
1197 /// <param name="problemTypeCodes">
1198 /// New supported problem-family codes.
1199 /// </param>
1201 IEnumerable<string> problemTypeCodes)
1202 {
1203 ReplaceCodeCollection(
1205 problemTypeCodes);
1206
1207 NotifyProblemTypeProperties();
1208 }
1209
1210 /// <summary>
1211 /// Replaces the preferred problem-family codes.
1212 /// </summary>
1213 /// <param name="problemTypeCodes">
1214 /// New preferred problem-family codes.
1215 /// </param>
1217 IEnumerable<string> problemTypeCodes)
1218 {
1219 ReplaceCodeCollection(
1221 problemTypeCodes);
1222
1223 NotifyProblemTypeProperties();
1224 }
1225
1226 /// <summary>
1227 /// Replaces the product structures supported by the
1228 /// method.
1229 /// </summary>
1230 /// <param name="productStructureTypes">
1231 /// New supported product structures.
1232 /// </param>
1234 IEnumerable<ProductStructureType>
1235 productStructureTypes)
1236 {
1237 ArgumentNullException.ThrowIfNull(
1238 productStructureTypes);
1239
1240 ProductStructureType[] normalizedValues =
1241 productStructureTypes
1242 .Distinct()
1243 .OrderBy(
1244 value =>
1245 value)
1246 .ToArray();
1247
1249
1251 normalizedValues);
1252
1253 OnPropertyChanged(
1255
1256 OnPropertyChanged(
1257 nameof(
1259
1260 NotifyDefinitionValidityProperties();
1261 }
1262
1263 /// <summary>
1264 /// Replaces the required feature codes.
1265 /// </summary>
1266 /// <param name="featureCodes">
1267 /// New required feature codes.
1268 /// </param>
1270 IEnumerable<string> featureCodes)
1271 {
1272 ReplaceFeatureCodeCollection(
1274 featureCodes);
1275
1276 NotifyFeatureProperties();
1277 }
1278
1279 /// <summary>
1280 /// Replaces the explicitly supported feature codes.
1281 /// </summary>
1282 /// <param name="featureCodes">
1283 /// New supported feature codes.
1284 /// </param>
1286 IEnumerable<string> featureCodes)
1287 {
1288 ReplaceFeatureCodeCollection(
1290 featureCodes);
1291
1292 NotifyFeatureProperties();
1293 }
1294
1295 /// <summary>
1296 /// Replaces the partially supported feature codes.
1297 /// </summary>
1298 /// <param name="featureCodes">
1299 /// New partially supported feature codes.
1300 /// </param>
1302 IEnumerable<string> featureCodes)
1303 {
1304 ReplaceFeatureCodeCollection(
1306 featureCodes);
1307
1308 NotifyFeatureProperties();
1309 }
1310
1311 /// <summary>
1312 /// Replaces the unsupported feature codes.
1313 /// </summary>
1314 /// <param name="featureCodes">
1315 /// New unsupported feature codes.
1316 /// </param>
1318 IEnumerable<string> featureCodes)
1319 {
1320 ReplaceFeatureCodeCollection(
1322 featureCodes);
1323
1324 NotifyFeatureProperties();
1325 }
1326
1327 /// <summary>
1328 /// Replaces the preferred feature codes.
1329 /// </summary>
1330 /// <param name="featureCodes">
1331 /// New preferred feature codes.
1332 /// </param>
1334 IEnumerable<string> featureCodes)
1335 {
1336 ReplaceFeatureCodeCollection(
1338 featureCodes);
1339
1340 NotifyFeatureProperties();
1341 }
1342
1343 /// <summary>
1344 /// Replaces the documentary or bibliographic references
1345 /// associated with the method.
1346 /// </summary>
1347 /// <param name="references">
1348 /// New references.
1349 /// </param>
1351 IEnumerable<string> references)
1352 {
1353 ArgumentNullException.ThrowIfNull(
1354 references);
1355
1356 string[] normalizedReferences =
1357 references
1358 .Where(
1359 reference =>
1360 !string.IsNullOrWhiteSpace(
1361 reference))
1362 .Select(
1363 reference =>
1364 reference.Trim())
1365 .Distinct(
1366 StringComparer.OrdinalIgnoreCase)
1367 .OrderBy(
1368 reference =>
1369 reference,
1370 StringComparer.OrdinalIgnoreCase)
1371 .ToArray();
1372
1373 References.Clear();
1374
1375 References.AddRange(
1376 normalizedReferences);
1377
1378 OnPropertyChanged(
1379 nameof(References));
1380
1381 OnPropertyChanged(
1382 nameof(HasReferences));
1383 }
1384
1385 /// <summary>
1386 /// Returns the distinct feature codes referenced by this
1387 /// method definition.
1388 /// </summary>
1389 /// <returns>
1390 /// Ordered feature-code collection.
1391 /// </returns>
1392 public IReadOnlyList<string> GetAllFeatureCodes()
1393 {
1395 .Concat(
1397 .Concat(
1399 .Concat(
1401 .Concat(
1403 .Where(
1404 featureCode =>
1405 !string.IsNullOrWhiteSpace(
1406 featureCode))
1407 .Select(
1408 featureCode =>
1409 featureCode.Trim())
1410 .Distinct(
1411 StringComparer.OrdinalIgnoreCase)
1412 .OrderBy(
1413 featureCode =>
1414 featureCode,
1415 StringComparer.OrdinalIgnoreCase)
1416 .ToArray();
1417 }
1418
1419 /// <summary>
1420 /// Validates the structural consistency of this method
1421 /// definition.
1422 /// </summary>
1423 /// <returns>
1424 /// Ordered validation-error collection. An empty
1425 /// collection indicates that the definition is valid.
1426 /// </returns>
1427 public IReadOnlyList<string> Validate()
1428 {
1429 var errors =
1430 new List<string>();
1431
1432 if (!HasMethodCode)
1433 {
1434 errors.Add(
1435 "The solution-method code is missing.");
1436 }
1437
1438 if (!HasName)
1439 {
1440 errors.Add(
1441 "The solution-method name is missing.");
1442 }
1443
1444 if (!HasSupportedScope)
1445 {
1446 errors.Add(
1447 "The solution method does not support a " +
1448 "complete problem, relaxation or subproblem.");
1449 }
1450
1454 {
1455 errors.Add(
1456 "The method does not declare any supported " +
1457 "problem family and is not marked as generic.");
1458 }
1459
1462 {
1463 errors.Add(
1464 "The method does not declare any supported " +
1465 "product structure.");
1466 }
1467
1468 ValidateStringCollection(
1470 "supported problem-family code",
1471 errors);
1472
1473 ValidateStringCollection(
1475 "preferred problem-family code",
1476 errors);
1477
1478 ValidateStringCollection(
1480 "required feature code",
1481 errors);
1482
1483 ValidateStringCollection(
1485 "supported feature code",
1486 errors);
1487
1488 ValidateStringCollection(
1490 "partially supported feature code",
1491 errors);
1492
1493 ValidateStringCollection(
1495 "unsupported feature code",
1496 errors);
1497
1498 ValidateStringCollection(
1500 "preferred feature code",
1501 errors);
1502
1503 ValidateProductStructureCollection(
1504 errors);
1505
1506 ValidateProblemTypeRelationships(
1507 errors);
1508
1509 ValidateFeatureRelationships(
1510 errors);
1511
1512 ValidateRecommendedLimits(
1513 errors);
1514
1515 return errors
1516 .Distinct(
1517 StringComparer.Ordinal)
1518 .OrderBy(
1519 error =>
1520 error,
1521 StringComparer.Ordinal)
1522 .ToArray();
1523 }
1524
1525 /// <summary>
1526 /// Validates the method definition and throws an exception
1527 /// when at least one error is found.
1528 /// </summary>
1529 /// <exception cref="InvalidOperationException">
1530 /// Thrown when the method definition is invalid.
1531 /// </exception>
1532 public void EnsureValid()
1533 {
1534 IReadOnlyList<string> errors =
1535 Validate();
1536
1537 if (errors.Count == 0)
1538 {
1539 return;
1540 }
1541
1542 throw new InvalidOperationException(
1543 "The solution-method definition is invalid:" +
1544 Environment.NewLine +
1545 string.Join(
1546 Environment.NewLine,
1547 errors.Select(
1548 error =>
1549 "- " + error)));
1550 }
1551
1552 /// <inheritdoc/>
1553 public override string ToString()
1554 {
1555 string familyDescription =
1557 ? "any problem family"
1558 : $"{SupportedProblemTypeCodes.Count} " +
1559 "supported family code(s)";
1560
1561 return
1562 $"{MethodCode} — {Name}; " +
1563 $"{MethodKind}; " +
1564 $"{familyDescription}";
1565 }
1566
1567 private static string NormalizeCode(
1568 string? value)
1569 {
1570 return string.IsNullOrWhiteSpace(value)
1571 ? string.Empty
1572 : value.Trim().ToUpperInvariant();
1573 }
1574
1575 private static bool ContainsCode(
1576 IEnumerable<string> codes,
1577 string code)
1578 {
1579 if (string.IsNullOrWhiteSpace(code))
1580 {
1581 return false;
1582 }
1583
1584 string normalizedCode =
1585 code.Trim();
1586
1587 return codes.Any(
1588 candidate =>
1589 string.Equals(
1590 candidate,
1591 normalizedCode,
1592 StringComparison.OrdinalIgnoreCase));
1593 }
1594
1595 private static void ReplaceCodeCollection(
1596 ICollection<string> destination,
1597 IEnumerable<string> source)
1598 {
1599 ArgumentNullException.ThrowIfNull(source);
1600
1601 string[] normalizedCodes =
1602 source
1603 .Where(
1604 code =>
1605 !string.IsNullOrWhiteSpace(code))
1606 .Select(
1607 NormalizeCode)
1608 .Distinct(
1609 StringComparer.OrdinalIgnoreCase)
1610 .OrderBy(
1611 code =>
1612 code,
1613 StringComparer.OrdinalIgnoreCase)
1614 .ToArray();
1615
1616 destination.Clear();
1617
1618 foreach (string code in normalizedCodes)
1619 {
1620 destination.Add(code);
1621 }
1622 }
1623
1624 private static void ReplaceFeatureCodeCollection(
1625 ICollection<string> destination,
1626 IEnumerable<string> source)
1627 {
1628 ArgumentNullException.ThrowIfNull(source);
1629
1630 string[] normalizedCodes =
1631 source
1632 .Where(
1633 code =>
1634 !string.IsNullOrWhiteSpace(code))
1635 .Select(
1636 code =>
1637 code.Trim())
1638 .Distinct(
1639 StringComparer.OrdinalIgnoreCase)
1640 .OrderBy(
1641 code =>
1642 code,
1643 StringComparer.OrdinalIgnoreCase)
1644 .ToArray();
1645
1646 destination.Clear();
1647
1648 foreach (string code in normalizedCodes)
1649 {
1650 destination.Add(code);
1651 }
1652 }
1653
1654 private static void ValidateStringCollection(
1655 IEnumerable<string> values,
1656 string valueDescription,
1657 ICollection<string> errors)
1658 {
1659 string[] materializedValues =
1660 values.ToArray();
1661
1662 if (materializedValues.Any(
1663 value =>
1664 string.IsNullOrWhiteSpace(value)))
1665 {
1666 errors.Add(
1667 $"Every {valueDescription} must be " +
1668 "non-empty.");
1669 }
1670
1671 string[] duplicateValues =
1672 materializedValues
1673 .Where(
1674 value =>
1675 !string.IsNullOrWhiteSpace(value))
1676 .GroupBy(
1677 value =>
1678 value.Trim(),
1679 StringComparer.OrdinalIgnoreCase)
1680 .Where(
1681 group =>
1682 group.Count() > 1)
1683 .Select(
1684 group =>
1685 group.Key)
1686 .OrderBy(
1687 value =>
1688 value,
1689 StringComparer.OrdinalIgnoreCase)
1690 .ToArray();
1691
1692 if (duplicateValues.Length > 0)
1693 {
1694 errors.Add(
1695 $"Duplicate {valueDescription} values: " +
1696 string.Join(
1697 ", ",
1698 duplicateValues) +
1699 ".");
1700 }
1701 }
1702
1703 private void ValidateProductStructureCollection(
1704 ICollection<string> errors)
1705 {
1706 ProductStructureType[] duplicateTypes =
1708 .GroupBy(
1709 productStructureType =>
1710 productStructureType)
1711 .Where(
1712 group =>
1713 group.Count() > 1)
1714 .Select(
1715 group =>
1716 group.Key)
1717 .OrderBy(
1718 productStructureType =>
1719 productStructureType)
1720 .ToArray();
1721
1722 if (duplicateTypes.Length > 0)
1723 {
1724 errors.Add(
1725 "Duplicate supported product-structure " +
1726 "types: " +
1727 string.Join(
1728 ", ",
1729 duplicateTypes) +
1730 ".");
1731 }
1732
1733 if (SupportedProductStructureTypes.Contains(
1734 ProductStructureType.Unknown))
1735 {
1736 errors.Add(
1737 "Unknown cannot be declared as a supported " +
1738 "product-structure type.");
1739 }
1740 }
1741
1742 private void ValidateProblemTypeRelationships(
1743 ICollection<string> errors)
1744 {
1746 {
1747 return;
1748 }
1749
1750 string[] unsupportedPreferredCodes =
1752 .Where(
1753 preferredCode =>
1754 !ContainsCode(
1756 preferredCode))
1757 .OrderBy(
1758 code =>
1759 code,
1760 StringComparer.OrdinalIgnoreCase)
1761 .ToArray();
1762
1763 if (unsupportedPreferredCodes.Length > 0)
1764 {
1765 errors.Add(
1766 "Preferred problem-family codes must also be " +
1767 "supported: " +
1768 string.Join(
1769 ", ",
1770 unsupportedPreferredCodes) +
1771 ".");
1772 }
1773 }
1774
1775 private void ValidateFeatureRelationships(
1776 ICollection<string> errors)
1777 {
1778 AddOverlapError(
1781 "required",
1782 "unsupported",
1783 errors);
1784
1785 AddOverlapError(
1788 "required",
1789 "partially supported",
1790 errors);
1791
1792 AddOverlapError(
1795 "supported",
1796 "unsupported",
1797 errors);
1798
1799 AddOverlapError(
1802 "supported",
1803 "partially supported",
1804 errors);
1805
1806 AddOverlapError(
1809 "preferred",
1810 "unsupported",
1811 errors);
1812
1813 AddOverlapError(
1816 "preferred",
1817 "partially supported",
1818 errors);
1819 }
1820
1821 private void ValidateRecommendedLimits(
1822 ICollection<string> errors)
1823 {
1824 ValidateRecommendedLimit(
1827 "item count",
1828 errors);
1829
1830 ValidateRecommendedLimit(
1833 "planning horizon",
1834 errors);
1835
1836 ValidateRecommendedLimit(
1839 "bill-of-materials relationship count",
1840 errors);
1841
1842 ValidateRecommendedLimit(
1845 "product-structure depth",
1846 errors);
1847 }
1848
1849 private static void ValidateRecommendedLimit(
1850 int? recommendedLimit,
1851 int? hardLimit,
1852 string limitDescription,
1853 ICollection<string> errors)
1854 {
1855 if (recommendedLimit.HasValue &&
1856 hardLimit.HasValue &&
1857 recommendedLimit.Value >
1858 hardLimit.Value)
1859 {
1860 errors.Add(
1861 $"The recommended maximum " +
1862 $"{limitDescription} cannot exceed its hard " +
1863 "maximum.");
1864 }
1865 }
1866
1867 private static void AddOverlapError(
1868 IEnumerable<string> firstCollection,
1869 IEnumerable<string> secondCollection,
1870 string firstDescription,
1871 string secondDescription,
1872 ICollection<string> errors)
1873 {
1874 string[] overlappingCodes =
1875 firstCollection
1876 .Intersect(
1877 secondCollection,
1878 StringComparer.OrdinalIgnoreCase)
1879 .OrderBy(
1880 code =>
1881 code,
1882 StringComparer.OrdinalIgnoreCase)
1883 .ToArray();
1884
1885 if (overlappingCodes.Length == 0)
1886 {
1887 return;
1888 }
1889
1890 errors.Add(
1891 $"Feature codes cannot be both " +
1892 $"{firstDescription} and {secondDescription}: " +
1893 string.Join(
1894 ", ",
1895 overlappingCodes) +
1896 ".");
1897 }
1898
1899 private void SetHardLimit(
1900 ref int? storage,
1901 int? value,
1902 string propertyName)
1903 {
1904 ValidatePositiveNullableLimit(
1905 value,
1906 propertyName);
1907
1908 if (SetProperty(
1909 ref storage,
1910 value,
1911 propertyName))
1912 {
1913 OnPropertyChanged(
1914 nameof(HasHardSizeLimits));
1915
1916 NotifyDefinitionValidityProperties();
1917 }
1918 }
1919
1920 private void SetRecommendedLimit(
1921 ref int? storage,
1922 int? value,
1923 string propertyName)
1924 {
1925 ValidatePositiveNullableLimit(
1926 value,
1927 propertyName);
1928
1929 if (SetProperty(
1930 ref storage,
1931 value,
1932 propertyName))
1933 {
1934 OnPropertyChanged(
1935 nameof(HasRecommendedSizeLimits));
1936
1937 NotifyDefinitionValidityProperties();
1938 }
1939 }
1940
1941 private static void ValidatePositiveNullableLimit(
1942 int? value,
1943 string parameterName)
1944 {
1945 if (value.HasValue &&
1946 value.Value <= 0)
1947 {
1948 throw new ArgumentOutOfRangeException(
1949 parameterName,
1950 value,
1951 "A method size limit must be strictly " +
1952 "positive when specified.");
1953 }
1954 }
1955
1956 private void NotifyProblemTypeProperties()
1957 {
1958 OnPropertyChanged(
1960
1961 OnPropertyChanged(
1963
1964 OnPropertyChanged(
1965 nameof(HasSupportedProblemTypes));
1966
1967 OnPropertyChanged(
1968 nameof(HasPreferredProblemTypes));
1969
1970 NotifyDefinitionValidityProperties();
1971 }
1972
1973 private void NotifyFeatureProperties()
1974 {
1975 OnPropertyChanged(
1976 nameof(RequiredFeatureCodes));
1977
1978 OnPropertyChanged(
1979 nameof(SupportedFeatureCodes));
1980
1981 OnPropertyChanged(
1983
1984 OnPropertyChanged(
1985 nameof(UnsupportedFeatureCodes));
1986
1987 OnPropertyChanged(
1988 nameof(PreferredFeatureCodes));
1989
1990 OnPropertyChanged(
1991 nameof(HasFeatureRules));
1992
1993 NotifyDefinitionValidityProperties();
1994 }
1995
1996 private void NotifyScopeProperties()
1997 {
1998 OnPropertyChanged(
1999 nameof(HasSupportedScope));
2000
2001 NotifyDefinitionValidityProperties();
2002 }
2003
2004 private void NotifyDefinitionValidityProperties()
2005 {
2006 OnPropertyChanged(
2007 nameof(IsValidDefinition));
2008
2009 OnPropertyChanged(
2010 nameof(CanBeEvaluated));
2011 }
2012}
void ReplaceSupportedFeatureCodes(IEnumerable< string > featureCodes)
Replaces the explicitly supported feature codes.
bool PrefersProblemTypeCode(string problemTypeCode)
Determines whether this method identifies a problem family as particularly appropriate.
bool HasRecommendedSizeLimits
Gets a value indicating whether at least one recommended size limit has been specified.
List< string > RequiredFeatureCodes
Gets the feature codes that must be active for the method to be applicable.
bool HasReferences
Gets a value indicating whether at least one reference has been recorded.
List< string > PreferredFeatureCodes
Gets the feature codes that make the method particularly attractive when they are active.
bool HasMethodCode
Gets a value indicating whether a stable method code has been recorded.
List< string > PartiallySupportedFeatureCodes
Gets the feature codes supported only through an adaptation, approximation, decomposition or implemen...
int? MaximumTransportResourceCount
Gets or sets the hard maximum number of transport resources accepted by the method.
List< string > SupportedFeatureCodes
Gets the active feature codes explicitly supported by the method.
List< ProductStructureType > SupportedProductStructureTypes
Gets the product structures supported by the method.
void ReplaceUnsupportedFeatureCodes(IEnumerable< string > featureCodes)
Replaces the unsupported feature codes.
bool SupportsSubproblems
Gets or sets a value indicating whether the method can solve subproblems extracted from a complete in...
int? MaximumSupplierCount
Gets or sets the hard maximum number of suppliers accepted by the method.
bool HasSupportedScope
Gets a value indicating whether the method supports at least one problem scope.
string MethodCode
Gets or sets the stable code identifying the solution method.
List< string > SupportedProblemTypeCodes
Gets the problem-family codes directly supported by the method.
List< string > PreferredProblemTypeCodes
Gets the problem-family codes for which the method is considered particularly appropriate.
string ImplementationVersion
Gets or sets the version of the associated method implementation.
bool SupportsAnyProductStructure
Gets or sets a value indicating whether the method supports any valid product structure.
void EnsureValid()
Validates the method definition and throws an exception when at least one error is found.
bool HasName
Gets a value indicating whether a human-readable name has been recorded.
SolutionMethodDefinition(string methodCode, string name, SolutionMethodKind methodKind)
Initializes a solution-method definition.
bool SupportsCompleteProblems
Gets or sets a value indicating whether the method can solve a complete problem instance.
int? RecommendedMaximumItemCount
Gets or sets the recommended maximum number of items for effective use of the method.
void ReplacePreferredFeatureCodes(IEnumerable< string > featureCodes)
Replaces the preferred feature codes.
int? MaximumPlantCount
Gets or sets the hard maximum number of plants accepted by the method.
string Description
Gets or sets a human-readable description of the method and its principal assumptions.
bool SupportsAmbiguousClassifications
Gets or sets a value indicating whether the method may be evaluated when the problem-family classific...
int? RecommendedMaximumBillOfMaterialsRelationshipCount
Gets or sets the recommended maximum number of bill-of-materials relationships.
bool CanProvideUpperBound
Gets or sets a value indicating whether the method can produce a valid upper bound for a minimization...
bool SupportsProblemTypeCode(string problemTypeCode)
Determines whether this method supports a problem family code.
bool SupportsUnclassifiedProblems
Gets or sets a value indicating whether the method may be evaluated for a problem that has not been a...
string ImplementationName
Gets or sets the name of an implementation associated with this method definition.
void ReplaceSupportedProblemTypeCodes(IEnumerable< string > problemTypeCodes)
Replaces the supported problem-family codes.
bool ExcludesFeatureCode(string featureCode)
Determines whether a feature is explicitly unsupported.
bool CanProduceFeasibleSolution
Gets or sets a value indicating whether the method can produce a feasible solution to the problem sco...
bool IsEnabled
Gets or sets a value indicating whether this method definition is enabled in the catalog.
bool CanProvideLowerBound
Gets or sets a value indicating whether the method can produce a valid lower bound for a minimization...
bool HasFeatureRules
Gets a value indicating whether the method has at least one explicit feature capability or restrictio...
SolutionMethodKind MethodKind
Gets or sets the general category of the solution method.
int? MaximumBillOfMaterialsRelationshipCount
Gets or sets the hard maximum number of bill-of-materials relationships accepted by the method.
List< string > References
Gets the documentary or bibliographic references associated with the method.
bool SupportsRelaxations
Gets or sets a value indicating whether the method can solve a relaxation of a complete problem.
bool SupportsProductStructureType(ProductStructureType productStructureType)
Determines whether this method supports a given product-structure type.
void ReplaceSupportedProductStructureTypes(IEnumerable< ProductStructureType > productStructureTypes)
Replaces the product structures supported by the method.
bool HasDescription
Gets a value indicating whether a description has been recorded.
void ReplaceRequiredFeatureCodes(IEnumerable< string > featureCodes)
Replaces the required feature codes.
bool IsValidDefinition
Gets a value indicating whether the method definition contains the minimum information required for e...
bool SupportsAnyProblemFamily
Gets or sets a value indicating whether the method is independent from a specific classified problem ...
int? RecommendedMaximumProductStructureDepth
Gets or sets the recommended maximum product-structure depth.
int? MaximumWarehouseCount
Gets or sets the hard maximum number of warehouses accepted by the method.
bool HasSupportedProductStructureTypes
Gets a value indicating whether the method explicitly supports at least one product-structure type.
void ReplacePartiallySupportedFeatureCodes(IEnumerable< string > featureCodes)
Replaces the partially supported feature codes.
bool CanProveOptimality
Gets or sets a value indicating whether the method can prove optimality under its stated assumptions.
int? MaximumPlanningHorizon
Gets or sets the hard maximum number of planning periods accepted by the method.
bool HasPreferredProblemTypes
Gets a value indicating whether the method identifies at least one preferred problem family.
bool HasMethodVersion
Gets a value indicating whether a method-definition version has been recorded.
bool HasHardSizeLimits
Gets a value indicating whether at least one hard size limit has been specified.
void ReplacePreferredProblemTypeCodes(IEnumerable< string > problemTypeCodes)
Replaces the preferred problem-family codes.
bool HasSupportedProblemTypes
Gets a value indicating whether the method explicitly supports at least one problem family.
int? MaximumProductStructureDepth
Gets or sets the hard maximum product-structure depth accepted by the method.
int? RecommendedMaximumPlanningHorizon
Gets or sets the recommended maximum planning horizon for effective use of the method.
bool SupportsFeatureCode(string featureCode)
Determines whether an active feature is explicitly supported by the method.
void ReplaceReferences(IEnumerable< string > references)
Replaces the documentary or bibliographic references associated with the method.
List< string > UnsupportedFeatureCodes
Gets the active feature codes that make the method incompatible with the complete problem.
SolutionMethodDefinition()
Initializes an empty solution-method definition.
int? MaximumWorkCenterCount
Gets or sets the hard maximum number of work centers accepted by the method.
string Name
Gets or sets the human-readable name of the method.
bool HasImplementationInformation
Gets a value indicating whether implementation information has been recorded.
IReadOnlyList< string > Validate()
Validates the structural consistency of this method definition.
IReadOnlyList< string > GetAllFeatureCodes()
Returns the distinct feature codes referenced by this method definition.
bool CanBeEvaluated
Gets a value indicating whether this method can be considered by the solution-method advisor.
string MethodVersion
Gets or sets the version of the method definition.
int? MaximumItemCount
Gets or sets the hard maximum number of items accepted by the method or its current implementation.
bool HasComment
Gets a value indicating whether an explanatory comment has been recorded.
bool PartiallySupportsFeatureCode(string featureCode)
Determines whether a feature is only partially supported.
ProductStructureType
Identifies the structural category of a product bill-of-materials graph.