LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
LinearExpression.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Xml.Serialization;
5
7
8/// <summary>
9/// Represents a linear expression composed of variable terms
10/// and a constant value.
11/// </summary>
12[Serializable]
13[XmlType(TypeName = "linearExpression")]
14public sealed class LinearExpression
15{
16 private readonly List<LinearTerm> _terms =
17 new();
18
19 /// <summary>
20 /// Initializes an empty linear expression.
21 /// </summary>
23 {
24 }
25
26 /// <summary>
27 /// Initializes a linear expression with a constant value.
28 /// </summary>
29 /// <param name="constant">
30 /// Constant value of the expression.
31 /// </param>
33 double constant)
34 {
35 Constant =
36 constant;
37
38 EnsureFiniteValue(
39 constant,
40 nameof(constant));
41 }
42
43 /// <summary>
44 /// Gets the linear terms of the expression.
45 /// </summary>
46 [XmlArray("terms")]
47 [XmlArrayItem("term")]
48 public List<LinearTerm> Terms =>
49 _terms;
50
51 /// <summary>
52 /// Gets or sets the constant value of the expression.
53 /// </summary>
54 [XmlAttribute("constant")]
55 public double Constant
56 {
57 get;
58 set;
59 }
60
61 /// <summary>
62 /// Gets a value indicating whether the expression contains
63 /// no variable term.
64 /// </summary>
65 [XmlIgnore]
66 public bool IsConstant =>
67 _terms.Count == 0;
68
69 /// <summary>
70 /// Gets the number of variable terms.
71 /// </summary>
72 [XmlIgnore]
73 public int TermCount =>
74 _terms.Count;
75
76 /// <summary>
77 /// Adds a linear term to the expression.
78 /// </summary>
79 /// <param name="variableId">
80 /// Identifier of the referenced mathematical variable.
81 /// </param>
82 /// <param name="coefficient">
83 /// Linear coefficient.
84 /// </param>
85 /// <remarks>
86 /// If the expression already contains a term for the same
87 /// variable, both coefficients are combined.
88 /// </remarks>
89 public void AddTerm(
90 int variableId,
91 double coefficient)
92 {
93 var term =
94 new LinearTerm(
95 variableId,
96 coefficient);
97
98 AddTerm(
99 term);
100 }
101
102 /// <summary>
103 /// Adds a linear term to the expression.
104 /// </summary>
105 /// <param name="term">
106 /// Term to add.
107 /// </param>
108 /// <remarks>
109 /// If the expression already contains a term for the same
110 /// variable, both coefficients are combined.
111 /// </remarks>
112 /// <exception cref="ArgumentNullException">
113 /// Thrown when <paramref name="term"/> is
114 /// <see langword="null"/>.
115 /// </exception>
116 public void AddTerm(
117 LinearTerm term)
118 {
119 ArgumentNullException.ThrowIfNull(
120 term);
121
122 term.EnsureValid();
123
124 LinearTerm? existingTerm =
125 _terms.FirstOrDefault(
126 currentTerm =>
127 currentTerm.VariableId ==
128 term.VariableId);
129
130 if (existingTerm is null)
131 {
132 if (term.Coefficient != 0.0)
133 {
134 _terms.Add(
135 new LinearTerm(
136 term.VariableId,
137 term.Coefficient));
138 }
139
140 return;
141 }
142
143 double combinedCoefficient =
144 existingTerm.Coefficient +
145 term.Coefficient;
146
147 EnsureFiniteValue(
148 combinedCoefficient,
149 nameof(term));
150
151 if (combinedCoefficient == 0.0)
152 {
153 _terms.Remove(
154 existingTerm);
155
156 return;
157 }
158
159 existingTerm.Coefficient =
160 combinedCoefficient;
161 }
162
163 /// <summary>
164 /// Adds another linear expression to this expression.
165 /// </summary>
166 /// <param name="expression">
167 /// Expression to add.
168 /// </param>
169 /// <exception cref="ArgumentNullException">
170 /// Thrown when <paramref name="expression"/> is
171 /// <see langword="null"/>.
172 /// </exception>
173 public void Add(
174 LinearExpression expression)
175 {
176 ArgumentNullException.ThrowIfNull(
177 expression);
178
179 foreach (
180 LinearTerm term
181 in expression.Terms)
182 {
183 AddTerm(
184 term);
185 }
186
188 expression.Constant);
189 }
190
191 /// <summary>
192 /// Adds a constant value to the expression.
193 /// </summary>
194 /// <param name="value">
195 /// Constant value to add.
196 /// </param>
197 public void AddConstant(
198 double value)
199 {
200 EnsureFiniteValue(
201 value,
202 nameof(value));
203
204 double updatedConstant =
205 Constant +
206 value;
207
208 EnsureFiniteValue(
209 updatedConstant,
210 nameof(value));
211
212 Constant =
213 updatedConstant;
214 }
215
216 /// <summary>
217 /// Multiplies the entire expression by a scalar.
218 /// </summary>
219 /// <param name="factor">
220 /// Scalar multiplier.
221 /// </param>
222 public void MultiplyBy(
223 double factor)
224 {
225 EnsureFiniteValue(
226 factor,
227 nameof(factor));
228
229 Constant *=
230 factor;
231
232 foreach (
233 LinearTerm term
234 in _terms)
235 {
236 term.Coefficient *=
237 factor;
238 }
239
240 _terms.RemoveAll(
241 term =>
242 term.Coefficient == 0.0);
243 }
244
245 /// <summary>
246 /// Removes all terms and resets the constant to zero.
247 /// </summary>
248 public void Clear()
249 {
250 _terms.Clear();
251
252 Constant =
253 0.0;
254 }
255
256 /// <summary>
257 /// Creates an independent copy of this expression.
258 /// </summary>
259 /// <returns>
260 /// Cloned linear expression.
261 /// </returns>
263 {
264 var clone =
266 Constant);
267
268 foreach (
269 LinearTerm term
270 in _terms)
271 {
272 clone.Terms.Add(
273 new LinearTerm(
274 term.VariableId,
275 term.Coefficient));
276 }
277
278 return clone;
279 }
280
281 /// <summary>
282 /// Validates the linear expression.
283 /// </summary>
284 /// <exception cref="InvalidOperationException">
285 /// Thrown when the expression contains an invalid value or
286 /// duplicate variable reference.
287 /// </exception>
288 public void EnsureValid()
289 {
290 EnsureFiniteValue(
291 Constant,
292 nameof(Constant));
293
294 var variableIds =
295 new HashSet<int>();
296
297 foreach (
298 LinearTerm term
299 in _terms)
300 {
301 if (term is null)
302 {
303 throw new InvalidOperationException(
304 "A linear expression cannot contain a null " +
305 "term.");
306 }
307
308 term.EnsureValid();
309
310 if (!variableIds.Add(
311 term.VariableId))
312 {
313 throw new InvalidOperationException(
314 $"Variable identifier '{term.VariableId}' " +
315 "appears more than once in the linear " +
316 "expression.");
317 }
318 }
319 }
320
321 private static void EnsureFiniteValue(
322 double value,
323 string valueName)
324 {
325 if (double.IsNaN(
326 value) ||
327 double.IsInfinity(
328 value))
329 {
330 throw new InvalidOperationException(
331 $"{valueName} must be a finite number.");
332 }
333 }
334}
void MultiplyBy(double factor)
Multiplies the entire expression by a scalar.
LinearExpression Clone()
Creates an independent copy of this expression.
void AddTerm(int variableId, double coefficient)
Adds a linear term to the expression.
void AddConstant(double value)
Adds a constant value to the expression.
LinearExpression()
Initializes an empty linear expression.
List< LinearTerm > Terms
Gets the linear terms of the expression.
void Clear()
Removes all terms and resets the constant to zero.
bool IsConstant
Gets a value indicating whether the expression contains no variable term.
void AddTerm(LinearTerm term)
Adds a linear term to the expression.
void Add(LinearExpression expression)
Adds another linear expression to this expression.
LinearExpression(double constant)
Initializes a linear expression with a constant value.
double Constant
Gets or sets the constant value of the expression.
int TermCount
Gets the number of variable terms.
void EnsureValid()
Validates the linear expression.
Represents one coefficient-variable term in a linear expression.
Definition LinearTerm.cs:13
int VariableId
Gets or sets the identifier of the referenced mathematical variable.
Definition LinearTerm.cs:49
double Coefficient
Gets or sets the coefficient multiplying the referenced variable.
Definition LinearTerm.cs:60
void EnsureValid()
Validates the linear term.
Definition LinearTerm.cs:72