19 MathematicalModel model,
22 ArgumentNullException.ThrowIfNull(model);
23 ArgumentException.ThrowIfNullOrWhiteSpace(filePath);
28 Path.GetDirectoryName(filePath);
30 if (!
string.IsNullOrWhiteSpace(directory))
32 Directory.CreateDirectory(directory);
40 encoderShouldEmitUTF8Identifier:
true));
54 WriteObjectiveByCategory(
63 private static void WriteHeader(
65 MathematicalModel model)
68 "LOT SIZING MATHEMATICAL MODEL DUMP");
70 "==================================");
74 $
"Model : {model.Name}");
76 $
"Variables : {model.VariableCount}");
78 $
" continuous : {model.ContinuousVariableCount}");
80 $
" integer : {model.IntegerVariableCount}");
82 $
" binary : {model.BinaryVariableCount}");
84 $
"Enabled constraints : {model.EnabledConstraintCount}");
86 $
"Objective sense : {model.Objective.Sense}");
88 $
"Objective terms : {model.Objective.Expression.TermCount}");
90 $
"Objective constant : {Format(model.Objective.Expression.Constant)}");
94 private static void WriteVariables(
96 MathematicalModel model)
105 MathematicalVariable variable
106 in model.Variables.OrderBy(
111 $
"[{variable.Id}] {variable.Name}");
114 $
" Type : {variable.VariableType}");
117 $
" Bounds : [{FormatBound(variable.LowerBound)}, " +
118 $
"{FormatBound(variable.UpperBound)}]");
121 $
" DomainKey : {variable.DomainKey}");
123 double objectiveCoefficient =
124 GetObjectiveCoefficient(
129 $
" ObjCoeff : {Format(objectiveCoefficient)}");
135 private static void WriteObjective(
137 MathematicalModel model)
146 $
"{model.Objective.Sense} {model.Objective.Name}");
152 in model.Objective.Expression.Terms)
154 MathematicalVariable? variable =
155 model.FindVariableById(
159 $
" {FormatSigned(term.Coefficient)} " +
160 $
"{FormatVariable(variable, term.VariableId)}");
163 if (model.Objective.Expression.Constant != 0.0)
166 $
" {FormatSigned(model.Objective.Expression.Constant)}");
172 private static void WriteObjectiveByCategory(
174 MathematicalModel model)
177 "OBJECTIVE COEFFICIENTS BY DOMAIN CATEGORY");
179 "=========================================");
183 model.Objective.Expression.Terms
187 MathematicalVariable? variable =
188 model.FindVariableById(
193 variable?.DomainKey);
205 StringComparer.OrdinalIgnoreCase)
209 StringComparer.OrdinalIgnoreCase);
211 foreach (var group
in rows)
217 $
" term count : {group.Count()}");
220 $
" coefficient sum : " +
221 $
"{Format(group.Sum(row => row.Term.Coefficient))}");
223 foreach (var row
in group)
226 $
" {FormatSigned(row.Term.Coefficient)} " +
227 $
"{FormatVariable(row.Variable, row.Term.VariableId)}");
234 private static void WriteConstraints(
236 MathematicalModel model)
245 LinearConstraint constraint
249 constraint.IsEnabled)
255 $
"[{constraint.Id}] {constraint.Name}");
258 $
" DomainKey : {constraint.DomainKey}");
268 in constraint.LeftHandSide.Terms)
270 MathematicalVariable? variable =
271 model.FindVariableById(
277 term.Coefficient >= 0.0
281 else if (term.Coefficient < 0.0)
287 $
"{Format(Math.Abs(term.Coefficient))}*" +
288 $
"{FormatVariable(variable, term.VariableId)}");
294 if (constraint.LeftHandSide.Constant != 0.0 ||
298 constraint.LeftHandSide.Constant;
307 else if (constant < 0.0)
314 Math.Abs(constant)));
318 $
" {FormatSense(constraint.Sense)} " +
319 $
"{Format(constraint.RightHandSide)}");
326 private static double GetObjectiveCoefficient(
327 MathematicalModel model,
331 model.Objective.Expression.Terms.FirstOrDefault(
333 term.VariableId == variableId);
335 return term?.Coefficient ?? 0.0;
338 private static string GetCategory(
341 if (
string.IsNullOrWhiteSpace(domainKey))
347 domainKey.IndexOf(
'|');
349 if (separatorIndex < 0)
354 return domainKey[..separatorIndex];
357 private static string FormatVariable(
358 MathematicalVariable? variable,
361 if (variable is
null)
363 return $
"<unknown:{variableId}>";
367 $
"{variable.Name} [id={variable.Id}; key={variable.DomainKey}]";
370 private static string FormatSense(
371 MathematicalConstraintSense sense)
375 MathematicalConstraintSense.LessThanOrEqual =>
378 MathematicalConstraintSense.Equal =>
381 MathematicalConstraintSense.GreaterThanOrEqual =>
389 private static string Format(
392 return value.ToString(
394 CultureInfo.InvariantCulture);
397 private static string FormatBound(
400 if (
double.IsPositiveInfinity(value))
405 if (
double.IsNegativeInfinity(value))
410 return Format(value);
413 private static string FormatSigned(
422 $
"{sign} {Format(Math.Abs(value))}";