001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math3.util;
018
019 import java.util.Collection;
020 import java.util.concurrent.CopyOnWriteArrayList;
021
022 import org.apache.commons.math3.exception.MaxCountExceededException;
023
024 /**
025 * This abstract class provides a general framework for managing iterative
026 * algorithms. The maximum number of iterations can be set, and methods are
027 * provided to monitor the current iteration count. A lightweight event
028 * framework is also provided.
029 *
030 * @version $Id: IterationManager.java 1422313 2012-12-15 18:53:41Z psteitz $
031 */
032 public class IterationManager {
033
034 /** Keeps a count of the number of iterations. */
035 private final Incrementor iterations;
036
037 /** The collection of all listeners attached to this iterative algorithm. */
038 private final Collection<IterationListener> listeners;
039
040 /**
041 * Creates a new instance of this class.
042 *
043 * @param maxIterations the maximum number of iterations
044 */
045 public IterationManager(final int maxIterations) {
046 this.iterations = new Incrementor(maxIterations);
047 this.listeners = new CopyOnWriteArrayList<IterationListener>();
048 }
049
050 /**
051 * Creates a new instance of this class.
052 *
053 * @param maxIterations the maximum number of iterations
054 * @param callBack the function to be called when the maximum number of
055 * iterations has been reached
056 * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is {@code null}
057 * @since 3.1
058 */
059 public IterationManager(final int maxIterations,
060 final Incrementor.MaxCountExceededCallback callBack) {
061 this.iterations = new Incrementor(maxIterations, callBack);
062 this.listeners = new CopyOnWriteArrayList<IterationListener>();
063 }
064
065 /**
066 * Attaches a listener to this manager.
067 *
068 * @param listener A {@code IterationListener} object.
069 */
070 public void addIterationListener(final IterationListener listener) {
071 listeners.add(listener);
072 }
073
074 /**
075 * Informs all registered listeners that the initial phase (prior to the
076 * main iteration loop) has been completed.
077 *
078 * @param e The {@link IterationEvent} object.
079 */
080 public void fireInitializationEvent(final IterationEvent e) {
081 for (IterationListener l : listeners) {
082 l.initializationPerformed(e);
083 }
084 }
085
086 /**
087 * Informs all registered listeners that a new iteration (in the main
088 * iteration loop) has been performed.
089 *
090 * @param e The {@link IterationEvent} object.
091 */
092 public void fireIterationPerformedEvent(final IterationEvent e) {
093 for (IterationListener l : listeners) {
094 l.iterationPerformed(e);
095 }
096 }
097
098 /**
099 * Informs all registered listeners that a new iteration (in the main
100 * iteration loop) has been started.
101 *
102 * @param e The {@link IterationEvent} object.
103 */
104 public void fireIterationStartedEvent(final IterationEvent e) {
105 for (IterationListener l : listeners) {
106 l.iterationStarted(e);
107 }
108 }
109
110 /**
111 * Informs all registered listeners that the final phase (post-iterations)
112 * has been completed.
113 *
114 * @param e The {@link IterationEvent} object.
115 */
116 public void fireTerminationEvent(final IterationEvent e) {
117 for (IterationListener l : listeners) {
118 l.terminationPerformed(e);
119 }
120 }
121
122 /**
123 * Returns the number of iterations of this solver, 0 if no iterations has
124 * been performed yet.
125 *
126 * @return the number of iterations.
127 */
128 public int getIterations() {
129 return iterations.getCount();
130 }
131
132 /**
133 * Returns the maximum number of iterations.
134 *
135 * @return the maximum number of iterations.
136 */
137 public int getMaxIterations() {
138 return iterations.getMaximalCount();
139 }
140
141 /**
142 * Increments the iteration count by one, and throws an exception if the
143 * maximum number of iterations is reached. This method should be called at
144 * the beginning of a new iteration.
145 *
146 * @throws MaxCountExceededException if the maximum number of iterations is
147 * reached.
148 */
149 public void incrementIterationCount()
150 throws MaxCountExceededException {
151 iterations.incrementCount();
152 }
153
154 /**
155 * Removes the specified iteration listener from the list of listeners
156 * currently attached to {@code this} object. Attempting to remove a
157 * listener which was <em>not</em> previously registered does not cause any
158 * error.
159 *
160 * @param listener The {@link IterationListener} to be removed.
161 */
162 public void removeIterationListener(final IterationListener listener) {
163 listeners.remove(listener);
164 }
165
166 /**
167 * Sets the iteration count to 0. This method must be called during the
168 * initial phase.
169 */
170 public void resetIterationCount() {
171 iterations.resetCount();
172 }
173 }