14 private readonly List<SolverProgressSnapshot> _history =
32 ArgumentNullException.ThrowIfNull(
44 public IReadOnlyList<SolverProgressSnapshot>
History =>
70 ArgumentNullException.ThrowIfNull(
79 if (HasReachedMaximumPointCount())
97 _lastRecordedSnapshot =
110 _lastRecordedSnapshot =
114 private bool ShouldRecord(
117 if (_lastRecordedSnapshot is
null)
122 return _options.Mode
switch
124 SolverProgressRecordingMode.IncumbentOnly =>
127 _lastRecordedSnapshot),
129 SolverProgressRecordingMode.TimeInterval =>
130 HasReachedTimeInterval(
132 _lastRecordedSnapshot),
134 SolverProgressRecordingMode.NodeInterval =>
135 HasReachedNodeInterval(
137 _lastRecordedSnapshot),
139 SolverProgressRecordingMode.SignificantChanges =>
140 HasSignificantChange(
142 _lastRecordedSnapshot),
144 SolverProgressRecordingMode.Full =>
152 private bool HasReachedMaximumPointCount()
155 _options.MaximumRecordedPointCount > 0 &&
157 _options.MaximumRecordedPointCount;
160 private static bool IsNewIncumbent(
161 SolverProgressSnapshot current,
162 SolverProgressSnapshot previous)
164 if (!current.IncumbentObjective.HasValue)
169 if (!previous.IncumbentObjective.HasValue)
175 !current.IncumbentObjective.Value.Equals(
176 previous.IncumbentObjective.Value);
179 private bool HasReachedTimeInterval(
180 SolverProgressSnapshot current,
181 SolverProgressSnapshot previous)
184 current.ElapsedSeconds -
185 previous.ElapsedSeconds >=
186 _options.TimeIntervalSeconds;
189 private bool HasReachedNodeInterval(
190 SolverProgressSnapshot current,
191 SolverProgressSnapshot previous)
193 if (!current.ExploredNodeCount.HasValue ||
194 !previous.ExploredNodeCount.HasValue)
200 current.ExploredNodeCount.Value -
201 previous.ExploredNodeCount.Value >=
202 _options.NodeInterval;
205 private bool HasSignificantChange(
206 SolverProgressSnapshot current,
207 SolverProgressSnapshot previous)
211 current.IncumbentObjective,
212 previous.IncumbentObjective,
213 _options.MinimumObjectiveChange) ||
217 _options.MinimumBoundChange) ||
220 previous.RelativeGap,
221 _options.MinimumRelativeGapChange) ||
224 current.SolutionCount !=
225 previous.SolutionCount;
228 private static bool HasChangedByAtLeast(
231 double minimumChange)
233 if (current.HasValue !=
239 if (!current.HasValue ||
252 private static SolverProgressSnapshot CloneSnapshot(
253 SolverProgressSnapshot source)
255 return new SolverProgressSnapshot
261 source.ElapsedSeconds,
264 source.ProcessorSeconds,
267 source.ExploredNodeCount,
270 source.OpenNodeCount,
273 source.IterationCount,
276 source.IncumbentObjective,
288 source.SolutionCount,
290 MemoryUsageMegabytes =
291 source.MemoryUsageMegabytes,