1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.math4.legacy.linear;
18
19 import org.apache.commons.math4.legacy.core.IntegerSequence;
20
21 import java.util.Collection;
22 import java.util.concurrent.CopyOnWriteArrayList;
23
24 /**
25 * This abstract class provides a general framework for managing iterative
26 * algorithms. The maximum number of iterations can be set, and methods are
27 * provided to monitor the current iteration count. A lightweight event
28 * framework is also provided.
29 *
30 */
31 public class IterationManager {
32 /** The collection of all listeners attached to this iterative algorithm. */
33 private final Collection<IterationListener> listeners;
34 /** Maximum number of iterations. */
35 private final int maxIterations;
36 /** Callback. */
37 private final IntegerSequence.Incrementor.MaxCountExceededCallback callback;
38 /** Keeps a count of the number of iterations. */
39 private IntegerSequence.Incrementor iterations;
40
41 /**
42 * Creates a new instance of this class.
43 *
44 * @param maxIterations Maximum number of iterations.
45 * {@link org.apache.commons.math4.legacy.exception.MaxCountExceededException}
46 * will be raised at counter exhaustion.
47 */
48 public IterationManager(final int maxIterations) {
49 this(maxIterations, null);
50 }
51
52 /**
53 * Creates a new instance of this class.
54 *
55 * @param maxIterations the maximum number of iterations
56 * @param callback the function to be called when the maximum number of
57 * iterations has been reached.
58 * If {@code null}, {@link org.apache.commons.math4.legacy.exception.MaxCountExceededException}
59 * will be raised at counter exhaustion.
60 *
61 * @since 3.1
62 */
63 public IterationManager(final int maxIterations,
64 final IntegerSequence.Incrementor.MaxCountExceededCallback callback) {
65 this.maxIterations = maxIterations;
66 this.callback = callback;
67 this.listeners = new CopyOnWriteArrayList<>();
68 resetCounter();
69 }
70
71 /**
72 * Attaches a listener to this manager.
73 *
74 * @param listener A {@code IterationListener} object.
75 */
76 public void addIterationListener(final IterationListener listener) {
77 listeners.add(listener);
78 }
79
80 /**
81 * Informs all registered listeners that the initial phase (prior to the
82 * main iteration loop) has been completed.
83 *
84 * @param e The {@link IterationEvent} object.
85 */
86 public void fireInitializationEvent(final IterationEvent e) {
87 for (IterationListener l : listeners) {
88 l.initializationPerformed(e);
89 }
90 }
91
92 /**
93 * Informs all registered listeners that a new iteration (in the main
94 * iteration loop) has been performed.
95 *
96 * @param e The {@link IterationEvent} object.
97 */
98 public void fireIterationPerformedEvent(final IterationEvent e) {
99 for (IterationListener l : listeners) {
100 l.iterationPerformed(e);
101 }
102 }
103
104 /**
105 * Informs all registered listeners that a new iteration (in the main
106 * iteration loop) has been started.
107 *
108 * @param e The {@link IterationEvent} object.
109 */
110 public void fireIterationStartedEvent(final IterationEvent e) {
111 for (IterationListener l : listeners) {
112 l.iterationStarted(e);
113 }
114 }
115
116 /**
117 * Informs all registered listeners that the final phase (post-iterations)
118 * has been completed.
119 *
120 * @param e The {@link IterationEvent} object.
121 */
122 public void fireTerminationEvent(final IterationEvent e) {
123 for (IterationListener l : listeners) {
124 l.terminationPerformed(e);
125 }
126 }
127
128 /**
129 * Returns the number of iterations of this solver, 0 if no iterations has
130 * been performed yet.
131 *
132 * @return the number of iterations.
133 */
134 public int getIterations() {
135 return iterations.getCount();
136 }
137
138 /**
139 * Returns the maximum number of iterations.
140 *
141 * @return the maximum number of iterations.
142 */
143 public int getMaxIterations() {
144 return iterations.getMaximalCount();
145 }
146
147 /**
148 * Increments the iteration count by one, and throws an exception if the
149 * maximum number of iterations is reached. This method should be called at
150 * the beginning of a new iteration.
151 *
152 * @throws org.apache.commons.math4.legacy.exception.MaxCountExceededException
153 * if the maximum number of iterations is reached.
154 */
155 public void incrementIterationCount() {
156 iterations.increment();
157 }
158
159 /**
160 * Removes the specified iteration listener from the list of listeners
161 * currently attached to {@code this} object. Attempting to remove a
162 * listener which was <em>not</em> previously registered does not cause any
163 * error.
164 *
165 * @param listener The {@link IterationListener} to be removed.
166 */
167 public void removeIterationListener(final IterationListener listener) {
168 listeners.remove(listener);
169 }
170
171 /**
172 * Sets the iteration count to 0. This method must be called during the
173 * initial phase.
174 */
175 public void resetIterationCount() {
176 resetCounter();
177 }
178
179 /** Reset counter. */
180 private void resetCounter() {
181 iterations = IntegerSequence.Incrementor.create()
182 .withMaximalCount(maxIterations);
183 if (callback != null) {
184 iterations = iterations.withCallback(callback);
185 }
186 }
187 }