1 | package de.uka.ipd.sdq.tcfmoop.tcmanager; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.LinkedList; |
5 | import java.util.List; |
6 | |
7 | import org.opt4j.core.Archive; |
8 | import org.opt4j.core.Population; |
9 | import org.opt4j.core.optimizer.Control; |
10 | import org.opt4j.core.optimizer.Optimizer; |
11 | |
12 | import de.uka.ipd.sdq.tcfmoop.config.IConfiguration; |
13 | import de.uka.ipd.sdq.tcfmoop.config.TerminationCriteriaNames; |
14 | import de.uka.ipd.sdq.tcfmoop.outputtree.Node; |
15 | import de.uka.ipd.sdq.tcfmoop.outputtree.Tree; |
16 | import de.uka.ipd.sdq.tcfmoop.outputtree.Node.NodeType; |
17 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.ElapsedTimeCriterion; |
18 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.GivenParetoFrontIsReachedCriterion; |
19 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.ITerminationCriterion; |
20 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.InsignificantParetoFrontChangeCriterion; |
21 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.InsignificantSetQualityImprovementCriterion; |
22 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.MaxGenerationNumber; |
23 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.MinimalQualityCriteriaValueCriterion; |
24 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.NoNewParetoOptimalCandidatesFoundCriterion; |
25 | import de.uka.ipd.sdq.tcfmoop.terminationcriteria.ParetoOptimalSetStabilityCriterion; |
26 | |
27 | import com.google.inject.Inject; |
28 | import com.google.inject.Singleton; |
29 | |
30 | import bsh.EvalError; |
31 | import bsh.Interpreter; |
32 | |
33 | /** |
34 | * The main goal of the Termination Criteria Manager is to create termination |
35 | * criteria, call them so that they can evaluate the current optimization state |
36 | * and then evaluate their decisions, on which it must base its own decision |
37 | * whether to stop the optimization or not. |
38 | * |
39 | * @author Atanas Dimitrov |
40 | */ |
41 | @Singleton |
42 | public class TerminationCriteriaManager implements ITerminationCriteriaManager { |
43 | |
44 | /** |
45 | * List of all currently configured Termination Criteria |
46 | */ |
47 | private List<ITerminationCriterion> terminationCriteria = new LinkedList<ITerminationCriterion>(); |
48 | |
49 | /** |
50 | * Defines the Termination Criteria manager has been initialized |
51 | */ |
52 | private boolean isInitialized = false; |
53 | |
54 | /** |
55 | * So that all termination criteria can work with the same time. |
56 | */ |
57 | private long currentTime; |
58 | |
59 | // Required resources |
60 | private Control control; |
61 | private Optimizer optimizer; |
62 | private Population population; |
63 | private Archive archive; |
64 | private int iteration; |
65 | |
66 | /** |
67 | * if true - the manager will evaluate the termination criteria and report |
68 | * their output but this will not influence the evaluation in any way |
69 | */ |
70 | private boolean isInComparisionMode = false; |
71 | |
72 | /** |
73 | * if true - Composed Criterion are on. If false a standard || Criterion is |
74 | * used |
75 | */ |
76 | private boolean isComposedCriterionActive = false; |
77 | |
78 | /** |
79 | * if true, the optimization will be stopped the next time the manager runs. |
80 | */ |
81 | private boolean performManualStop = false; |
82 | |
83 | /** |
84 | * Composed Criterion Expression |
85 | */ |
86 | private String composedCriterionExpression = ""; |
87 | |
88 | // Event Listeners |
89 | private List<IOutputChangedListener> outputChangedListeners; |
90 | private static List<ITerminationCriteriaManagerInitializedListener> terminationCriteriaManagerInitializedListeners = new ArrayList<ITerminationCriteriaManagerInitializedListener>(); |
91 | private List<IOptimizationTerminatedListener> optimizationTerminatedListener; |
92 | |
93 | // Output |
94 | private Tree outputTree = new Tree("Termination Criteria Manager", |
95 | NodeType.MANAGER); |
96 | private Tree managerTree = new Tree("Manager", NodeType.MANAGER); |
97 | private Tree tCriteriaTree = new Tree("Termination Criteria", |
98 | NodeType.PARAMETER_GROUP); |
99 | private Tree warningsTree = new Tree("Warnings", NodeType.WARNING); |
100 | |
101 | // Output Nodes: |
102 | private Node iterationNummberNode; |
103 | private Node candidatesInPopulationNode; |
104 | private Node candidatesInArchiveNode; |
105 | private Node useComposedCriterionNode; |
106 | private Node ComposedCriterionExpressionNode; |
107 | private Node isRunningInComparisionModeNode; |
108 | private Node manualTerminationRequestedNode; |
109 | private Node optimizationStoppedNode; |
110 | |
111 | /** |
112 | * Warning flags to prevent more warning than are required |
113 | */ |
114 | private boolean substituteWarningShown = false; |
115 | |
116 | @Inject |
117 | public TerminationCriteriaManager(Control control, Population population, |
118 | Archive archive) { |
119 | this.control = control; |
120 | this.population = population; |
121 | this.archive = archive; |
122 | |
123 | this.outputChangedListeners = new ArrayList<IOutputChangedListener>(); |
124 | this.optimizationTerminatedListener = new ArrayList<IOptimizationTerminatedListener>(); |
125 | |
126 | } |
127 | |
128 | /** |
129 | * {@inheritDoc} |
130 | */ |
131 | @Override |
132 | public void initialize(List<IConfiguration> tcConfigurations) { |
133 | for (IConfiguration conf : tcConfigurations) { |
134 | if (!conf.validateConfiguration()) { |
135 | this.warningsTree.addChild("The configuration for : " |
136 | + conf.getTerminationCriterionName() |
137 | + " cannot be veryfied successfully. " |
138 | + "The criterion will not be created.", |
139 | NodeType.WARNING); |
140 | continue; |
141 | } |
142 | |
143 | ITerminationCriterion tc = null; |
144 | |
145 | switch (conf.getTerminationCriterionName()) { |
146 | case MAXIMUM_NUMBER_OF_GENERATIONS: |
147 | tc = new MaxGenerationNumber(conf, population, archive); |
148 | break; |
149 | case ELAPSED_TIME: |
150 | tc = new ElapsedTimeCriterion(conf, population, archive); |
151 | break; |
152 | case PARETO_OPTIMAL_SET_STABILITY: |
153 | tc = new ParetoOptimalSetStabilityCriterion(conf, population, archive); |
154 | break; |
155 | case NO_NEW_PARETO_OPTIMAL_CANDIDATES_FOUND: |
156 | tc = new NoNewParetoOptimalCandidatesFoundCriterion(conf, population, archive); |
157 | break; |
158 | case MINIMAL_QUALITY_CIRTERIA_VALUE: |
159 | tc = new MinimalQualityCriteriaValueCriterion(conf, population, archive); |
160 | break; |
161 | case INSIGNIFICANT_SET_QUALITY_IMPROVEMENT: |
162 | tc = new InsignificantSetQualityImprovementCriterion(conf, population, archive); |
163 | break; |
164 | case GIVEN_PARETO_FRONT_IS_REACHED: |
165 | tc = new GivenParetoFrontIsReachedCriterion(conf, population, archive); |
166 | break; |
167 | case INSIGNIFICANT_PARETO_FRONT_CHANGE: |
168 | tc = new InsignificantParetoFrontChangeCriterion(conf, population, archive); |
169 | break; |
170 | default: |
171 | this.warningsTree.addChild("Unknown Termination Criterion: " |
172 | + conf.getTerminationCriterionName(), NodeType.WARNING); |
173 | } |
174 | if (tc != null) { |
175 | terminationCriteria.add(tc); |
176 | } |
177 | |
178 | } |
179 | this.initializeOutputTree(); |
180 | this.isInitialized = true; |
181 | |
182 | this.fireTerminationCriteriaManagerInitializedEvent(); |
183 | this.fireOutputInformationChangedEvent(); |
184 | } |
185 | |
186 | /** |
187 | * Initializes the output tree |
188 | */ |
189 | private void initializeOutputTree() { |
190 | this.outputTree.attachSubtree(managerTree); |
191 | this.outputTree.attachSubtree(tCriteriaTree); |
192 | this.outputTree.attachSubtree(warningsTree); |
193 | |
194 | this.iterationNummberNode = managerTree.addChild("Iteration Number: " |
195 | + this.iteration, NodeType.PARAMETER); |
196 | this.candidatesInPopulationNode = managerTree.addChild( |
197 | "Candidates in Population: " + this.population.size(), |
198 | NodeType.PARAMETER); |
199 | this.candidatesInArchiveNode = managerTree.addChild( |
200 | "All Pareto Optimal Candidates: " + this.archive.size(), |
201 | NodeType.PARAMETER); |
202 | this.useComposedCriterionNode = managerTree.addChild( |
203 | "Use Composed Criterion: " + this.isComposedCriterionActive, |
204 | NodeType.PARAMETER); |
205 | this.ComposedCriterionExpressionNode = managerTree |
206 | .addChild("Composed Criterion Expression: " |
207 | + this.composedCriterionExpression, NodeType.EXPRESSION); |
208 | this.isRunningInComparisionModeNode = managerTree.addChild( |
209 | "Running in Comparision Mode: " + this.isInComparisionMode, |
210 | NodeType.PARAMETER); |
211 | this.manualTerminationRequestedNode = managerTree.addChild( |
212 | "Manual Termination requested: " + this.performManualStop, |
213 | NodeType.PARAMETER); |
214 | this.optimizationStoppedNode = managerTree.addChild( |
215 | "Optimization Stopped: " + control.isStopped(), |
216 | NodeType.PARAMETER); |
217 | |
218 | } |
219 | |
220 | /** |
221 | * {@inheritDoc} |
222 | */ |
223 | @Override |
224 | public void activateTCComparisionMode() { |
225 | this.isInComparisionMode = true; |
226 | this.fireOutputInformationChangedEvent(); |
227 | } |
228 | |
229 | /** |
230 | * {@inheritDoc} |
231 | */ |
232 | @Override |
233 | public void deactivateTCComparisionMode() { |
234 | this.isInComparisionMode = false; |
235 | this.fireOutputInformationChangedEvent(); |
236 | } |
237 | |
238 | /** |
239 | * {@inheritDoc} |
240 | */ |
241 | @Override |
242 | public void activateComposedCriterion() { |
243 | this.isComposedCriterionActive = true; |
244 | this.fireOutputInformationChangedEvent(); |
245 | |
246 | } |
247 | |
248 | /** |
249 | * {@inheritDoc} |
250 | */ |
251 | @Override |
252 | public void deactivateComposedCriterion() { |
253 | this.isComposedCriterionActive = false; |
254 | this.fireOutputInformationChangedEvent(); |
255 | } |
256 | |
257 | /** |
258 | * {@inheritDoc} |
259 | */ |
260 | @Override |
261 | public void setComposedCriterionExpression( |
262 | String composedCriterionExpression) { |
263 | if (isComposedCriterionActive && !composedCriterionExpression.isEmpty()) { |
264 | |
265 | /* |
266 | * Checks the supplied boolean expression for consistency before |
267 | * using it It will be checked whether the expression can be |
268 | * evaluated and whether it contains illegal symbol in order to |
269 | * prevent execution of unwanted Java code |
270 | */ |
271 | |
272 | String exprTemp = composedCriterionExpression + ""; |
273 | exprTemp = exprTemp.replace(TerminationCriteriaNames.ELAPSED_TIME.name(), ""); |
274 | exprTemp = exprTemp.replace(TerminationCriteriaNames.GIVEN_PARETO_FRONT_IS_REACHED.name(), ""); |
275 | exprTemp = exprTemp.replace(TerminationCriteriaNames.INSIGNIFICANT_PARETO_FRONT_CHANGE.name(), ""); |
276 | exprTemp = exprTemp.replace(TerminationCriteriaNames.INSIGNIFICANT_SET_QUALITY_IMPROVEMENT.name(), ""); |
277 | exprTemp = exprTemp.replace(TerminationCriteriaNames.MAXIMUM_NUMBER_OF_GENERATIONS.name(), ""); |
278 | exprTemp = exprTemp.replace(TerminationCriteriaNames.MINIMAL_QUALITY_CIRTERIA_VALUE.name(), ""); |
279 | exprTemp = exprTemp.replace(TerminationCriteriaNames.NO_NEW_PARETO_OPTIMAL_CANDIDATES_FOUND.name(), ""); |
280 | exprTemp = exprTemp.replace(TerminationCriteriaNames.PARETO_OPTIMAL_SET_STABILITY.name(), ""); |
281 | |
282 | exprTemp = exprTemp.replace("true", ""); |
283 | exprTemp = exprTemp.replace("false", ""); |
284 | |
285 | exprTemp = exprTemp.replace("&&", ""); |
286 | exprTemp = exprTemp.replace("||", ""); |
287 | exprTemp = exprTemp.replace("!", ""); |
288 | |
289 | exprTemp = exprTemp.replace("(", ""); |
290 | exprTemp = exprTemp.replace(")", ""); |
291 | |
292 | exprTemp = exprTemp.replaceAll(" ", ""); |
293 | |
294 | if (!exprTemp.isEmpty()) { |
295 | isComposedCriterionActive = false; |
296 | this.warningsTree |
297 | .addChild( |
298 | "Composed Criterion Expression cannot be set because of the following reason: " |
299 | + "1. The expression contains symbols that are not allowed. " |
300 | + "A Standard 'OR' Expression will be used instead.", |
301 | NodeType.WARNING); |
302 | |
303 | return; |
304 | } |
305 | |
306 | Interpreter i = new Interpreter(); // Construct an interpreter |
307 | |
308 | try { |
309 | |
310 | i.set(TerminationCriteriaNames.ELAPSED_TIME.name(), true); |
311 | i.set(TerminationCriteriaNames.GIVEN_PARETO_FRONT_IS_REACHED.name(), true); |
312 | i.set(TerminationCriteriaNames.INSIGNIFICANT_PARETO_FRONT_CHANGE.name(), true); |
313 | i.set(TerminationCriteriaNames.INSIGNIFICANT_SET_QUALITY_IMPROVEMENT.name(), true); |
314 | i.set(TerminationCriteriaNames.MAXIMUM_NUMBER_OF_GENERATIONS.name(), true); |
315 | i.set(TerminationCriteriaNames.MINIMAL_QUALITY_CIRTERIA_VALUE.name(), true); |
316 | i.set(TerminationCriteriaNames.NO_NEW_PARETO_OPTIMAL_CANDIDATES_FOUND.name(), true); |
317 | i.set(TerminationCriteriaNames.PARETO_OPTIMAL_SET_STABILITY.name(), true); |
318 | |
319 | /* |
320 | * If eval() and get() can be successfully executed at this |
321 | * point with this form of the composed criteria expression, |
322 | * then the expression is correct. If an exception is thrown |
323 | * now, then the expression is malformed and cannot be used. |
324 | */ |
325 | i.eval("boolean evalResult = " + composedCriterionExpression + ";"); |
326 | i.get("evalResult"); |
327 | |
328 | this.composedCriterionExpression = composedCriterionExpression; |
329 | |
330 | } catch (EvalError e) { |
331 | isComposedCriterionActive = false; |
332 | this.warningsTree |
333 | .addChild( |
334 | "Composed Criterion Expression cannot be set because of the following reason: " |
335 | + "1. The Expression cannot be evaluated because it is malformed. " |
336 | + "A Standard 'OR' Expression will be used instead.", |
337 | NodeType.WARNING); |
338 | } |
339 | } else { |
340 | this.warningsTree |
341 | .addChild( |
342 | "Composed Criterion Expression cannot be set because of one of the following reasons: " |
343 | + "1. The Composed Criterion is deactivated. " |
344 | + "2. The Expression is empty. " |
345 | + "A Standard 'OR' Expression will be used instead.", |
346 | NodeType.WARNING); |
347 | } |
348 | |
349 | this.fireOutputInformationChangedEvent(); |
350 | |
351 | } |
352 | |
353 | /** |
354 | * {@inheritDoc} |
355 | */ |
356 | @Override |
357 | public void evaluateTerminationCriteria() { |
358 | if (this.isInitialized) { |
359 | this.iteration = this.optimizer.getIteration(); |
360 | |
361 | this.currentTime = System.currentTimeMillis(); |
362 | |
363 | boolean doStop = false; |
364 | |
365 | if (!this.performManualStop) { |
366 | for (ITerminationCriterion tc : this.terminationCriteria) { |
367 | tc.evaluate(this.optimizer.getIteration(),this.currentTime); |
368 | } |
369 | |
370 | if (this.isComposedCriterionActive) { |
371 | |
372 | doStop = this.evaluateExpression(); |
373 | |
374 | } else { |
375 | for (ITerminationCriterion tc : this.terminationCriteria) { |
376 | if (tc.getEvaluationResult() && !doStop) { |
377 | doStop = true; |
378 | } |
379 | } |
380 | } |
381 | } |
382 | |
383 | if (this.performManualStop || (doStop && !this.isInComparisionMode)) { |
384 | control.doStop(); |
385 | this.fireOutputInformationChangedEvent(); |
386 | this.fireOptimizationTerminatedEvent(); |
387 | } else { |
388 | this.fireOutputInformationChangedEvent(); |
389 | } |
390 | } |
391 | } |
392 | |
393 | /** |
394 | * Perform final Expression consistency check and evaluate it using |
395 | * BeanShell. If the check or the evaluation fail, then a simple OR |
396 | * Expression is used. |
397 | * |
398 | * @return the result of the evaluation. True - the optimization must be |
399 | * stopped. False - must not be stopped. |
400 | */ |
401 | private boolean evaluateExpression() { |
402 | |
403 | String expressionCopy = this.composedCriterionExpression.trim(); |
404 | |
405 | for (ITerminationCriterion tc : this.terminationCriteria) { |
406 | if (expressionCopy.contains(tc.getName().name())) { |
407 | expressionCopy = expressionCopy.replace(tc.getName().name(), |
408 | Boolean.toString(tc.getEvaluationResult())); |
409 | } |
410 | } |
411 | |
412 | if (expressionCopy.contains("_")) { |
413 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.ELAPSED_TIME.name(), Boolean.toString(false)); |
414 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.GIVEN_PARETO_FRONT_IS_REACHED.name(), Boolean.toString(false)); |
415 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.INSIGNIFICANT_PARETO_FRONT_CHANGE.name(), Boolean.toString(false)); |
416 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.INSIGNIFICANT_SET_QUALITY_IMPROVEMENT.name(), Boolean.toString(false)); |
417 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.MAXIMUM_NUMBER_OF_GENERATIONS.name(), Boolean.toString(false)); |
418 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.MINIMAL_QUALITY_CIRTERIA_VALUE.name(), Boolean.toString(false)); |
419 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.NO_NEW_PARETO_OPTIMAL_CANDIDATES_FOUND.name(), Boolean.toString(false)); |
420 | expressionCopy = expressionCopy.replace(TerminationCriteriaNames.PARETO_OPTIMAL_SET_STABILITY.name(), Boolean.toString(false)); |
421 | if (!this.substituteWarningShown) { |
422 | this.substituteWarningShown = true; |
423 | this.warningsTree.addChild("There is an inactive Termination Criterion referensed in the Composed Criterion Expression. " |
424 | + "Its value has been substituted with false.", NodeType.WARNING); |
425 | } |
426 | } |
427 | |
428 | Interpreter i = new Interpreter(); // Construct an interpreter |
429 | boolean evaluationResult = false; |
430 | |
431 | try { |
432 | |
433 | i.eval("boolean evalResult = " + expressionCopy + ";"); |
434 | evaluationResult = (Boolean) (i.get("evalResult")); |
435 | |
436 | } catch (EvalError e) { |
437 | isComposedCriterionActive = false; |
438 | |
439 | for (ITerminationCriterion tc : this.terminationCriteria) { |
440 | if (tc.getEvaluationResult() && !evaluationResult) { |
441 | evaluationResult = true; |
442 | } |
443 | } |
444 | |
445 | this.warningsTree.addChild("Composed Criterion Expression cannot be set because of the following reason: " |
446 | + "1. The Expression cannot be evaluated because it is malformed. " |
447 | + "A Standard 'OR' Expression will be used instead.", NodeType.WARNING); |
448 | } |
449 | |
450 | return evaluationResult; |
451 | } |
452 | |
453 | /** |
454 | * {@inheritDoc} |
455 | */ |
456 | private void fireOutputInformationChangedEvent() { |
457 | if (this.isInitialized) { |
458 | this.iterationNummberNode.updateValue("Iteration Number: " + this.iteration); |
459 | this.candidatesInPopulationNode.updateValue("Candidates in Population: " + this.population.size()); |
460 | this.candidatesInArchiveNode.updateValue("All Pareto Optimal Candidates: " + this.archive.size()); |
461 | this.useComposedCriterionNode.updateValue("Use Composed Criterion: " + this.isComposedCriterionActive); |
462 | this.ComposedCriterionExpressionNode.updateValue("Composed Criterion Expression: " + this.composedCriterionExpression); |
463 | this.isRunningInComparisionModeNode.updateValue("Running in Comparision Mode: " + this.isInComparisionMode); |
464 | this.manualTerminationRequestedNode.updateValue("Manual Termination requested: " + this.performManualStop); |
465 | this.optimizationStoppedNode.updateValue("Optimization Stopped: " + control.isStopped()); |
466 | |
467 | this.tCriteriaTree.clearChildren(); |
468 | for (ITerminationCriterion tc : terminationCriteria) { |
469 | tCriteriaTree.attachSubtree(tc.getOutputInformation()); |
470 | } |
471 | |
472 | } |
473 | |
474 | for (IOutputChangedListener listener : outputChangedListeners) { |
475 | listener.handleOutputChangedEvent(outputTree); |
476 | } |
477 | } |
478 | |
479 | /** |
480 | * Fires a Termination Criteria Manager Initialized event when the TCM is |
481 | * initialized. |
482 | */ |
483 | private void fireTerminationCriteriaManagerInitializedEvent() { |
484 | for (ITerminationCriteriaManagerInitializedListener listener : terminationCriteriaManagerInitializedListeners) { |
485 | listener.handleTerminationCriteriaManagerInitializedEvent(this); |
486 | } |
487 | } |
488 | |
489 | /** |
490 | * Fires a Optimization Terminated Event when the Termination Criteria |
491 | * Manager decides to stop the optimization. |
492 | */ |
493 | private void fireOptimizationTerminatedEvent() { |
494 | List<IOptimizationTerminatedListener> tempList = new ArrayList<IOptimizationTerminatedListener>( |
495 | this.optimizationTerminatedListener); |
496 | for (IOptimizationTerminatedListener listener : tempList) { |
497 | listener.handleOptimizationTerminatedListener(this); |
498 | } |
499 | } |
500 | |
501 | /** |
502 | * {@inheritDoc} |
503 | * |
504 | * If the listener is also a IRequestManualTerminationProvider. the TCM will |
505 | * add itself as a listener to that event. |
506 | */ |
507 | @Override |
508 | public void addOutputChangedListener(IOutputChangedListener listener) { |
509 | this.outputChangedListeners.add(listener); |
510 | if (listener instanceof IRequestManualTerminationProvider) { |
511 | ((IRequestManualTerminationProvider) (listener)) |
512 | .addRequestManualTerminationListener(this); |
513 | } |
514 | } |
515 | |
516 | /** |
517 | * {@inheritDoc} |
518 | * |
519 | * If the listener is also a IRequestManualTerminationProvider. the TCM will |
520 | * remove itself as a listener from that event. |
521 | */ |
522 | @Override |
523 | public void removeOutputChangedListener(IOutputChangedListener listener) { |
524 | this.outputChangedListeners.remove(listener); |
525 | if (listener instanceof IRequestManualTerminationProvider) { |
526 | ((IRequestManualTerminationProvider) (listener)) |
527 | .removeRequestManualTerminationListener(this); |
528 | } |
529 | } |
530 | |
531 | /** |
532 | * Adds a new listener for the static TerminationCriteriaManagerInitialized |
533 | * event. |
534 | * |
535 | * @param listener |
536 | * ITerminationCriteriaManagerInitializedListener listener |
537 | */ |
538 | public static void addTerminationCriteriaManagerInitializedListener( |
539 | ITerminationCriteriaManagerInitializedListener listener) { |
540 | terminationCriteriaManagerInitializedListeners.add(listener); |
541 | } |
542 | |
543 | /** |
544 | * Removes a listener from the static TerminationCriteriaManagerInitialized |
545 | * event. |
546 | * |
547 | * @param listener |
548 | * ITerminationCriteriaManagerInitializedListener listener |
549 | */ |
550 | public static void removeTerminationCriteriaManagerInitializedListener( |
551 | ITerminationCriteriaManagerInitializedListener listener) { |
552 | terminationCriteriaManagerInitializedListeners.remove(listener); |
553 | } |
554 | |
555 | /** |
556 | * {@inheritDoc} |
557 | */ |
558 | @Override |
559 | public void iterationComplete(Optimizer optimizer, int iteration) { |
560 | if (this.isInitialized) { |
561 | this.optimizer = optimizer; |
562 | this.evaluateTerminationCriteria(); |
563 | } |
564 | } |
565 | |
566 | /** |
567 | * {@inheritDoc} |
568 | */ |
569 | @Override |
570 | public void addOptimizationTerminatedListener( |
571 | IOptimizationTerminatedListener listener) { |
572 | this.optimizationTerminatedListener.add(listener); |
573 | } |
574 | |
575 | /** |
576 | * {@inheritDoc} |
577 | */ |
578 | @Override |
579 | public void removeOptimizationTerminatedListener( |
580 | IOptimizationTerminatedListener listener) { |
581 | this.optimizationTerminatedListener.remove(listener); |
582 | } |
583 | |
584 | /** |
585 | * {@inheritDoc} |
586 | */ |
587 | @Override |
588 | public void handleManualTerminationRequest() { |
589 | this.performManualStop = true; |
590 | this.fireOutputInformationChangedEvent(); |
591 | } |
592 | |
593 | } |