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.math3.util; 18 19 import org.apache.commons.math3.exception.MaxCountExceededException; 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 algorithms. The maximum 26 * number of iterations can be set, and methods are provided to monitor the current iteration count. 27 * A lightweight event framework is also provided. 28 */ 29 public class IterationManager { 30 31 /** Keeps a count of the number of iterations. */ 32 private IntegerSequence.Incrementor iterations; 33 34 /** The collection of all listeners attached to this iterative algorithm. */ 35 private final Collection<IterationListener> listeners; 36 37 /** 38 * Creates a new instance of this class. 39 * 40 * @param maxIterations the maximum number of iterations 41 */ IterationManager(final int maxIterations)42 public IterationManager(final int maxIterations) { 43 this.iterations = IntegerSequence.Incrementor.create().withMaximalCount(maxIterations); 44 this.listeners = new CopyOnWriteArrayList<IterationListener>(); 45 } 46 47 /** 48 * Creates a new instance of this class. 49 * 50 * @param maxIterations the maximum number of iterations 51 * @param callBack the function to be called when the maximum number of iterations has been 52 * reached 53 * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is 54 * {@code null} 55 * @since 3.1 56 * @deprecated as of 3.6, replaced with {@link #IterationManager(int, 57 * org.apache.commons.math3.util.IntegerSequence.Incrementor.MaxCountExceededCallback)} 58 */ 59 @Deprecated IterationManager( final int maxIterations, final Incrementor.MaxCountExceededCallback callBack)60 public IterationManager( 61 final int maxIterations, final Incrementor.MaxCountExceededCallback callBack) { 62 this( 63 maxIterations, 64 new IntegerSequence.Incrementor.MaxCountExceededCallback() { 65 /** {@inheritDoc} */ 66 public void trigger(final int maximalCount) throws MaxCountExceededException { 67 callBack.trigger(maximalCount); 68 } 69 }); 70 } 71 72 /** 73 * Creates a new instance of this class. 74 * 75 * @param maxIterations the maximum number of iterations 76 * @param callBack the function to be called when the maximum number of iterations has been 77 * reached 78 * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is 79 * {@code null} 80 * @since 3.6 81 */ IterationManager( final int maxIterations, final IntegerSequence.Incrementor.MaxCountExceededCallback callBack)82 public IterationManager( 83 final int maxIterations, 84 final IntegerSequence.Incrementor.MaxCountExceededCallback callBack) { 85 this.iterations = 86 IntegerSequence.Incrementor.create() 87 .withMaximalCount(maxIterations) 88 .withCallback(callBack); 89 this.listeners = new CopyOnWriteArrayList<IterationListener>(); 90 } 91 92 /** 93 * Attaches a listener to this manager. 94 * 95 * @param listener A {@code IterationListener} object. 96 */ addIterationListener(final IterationListener listener)97 public void addIterationListener(final IterationListener listener) { 98 listeners.add(listener); 99 } 100 101 /** 102 * Informs all registered listeners that the initial phase (prior to the main iteration loop) 103 * has been completed. 104 * 105 * @param e The {@link IterationEvent} object. 106 */ fireInitializationEvent(final IterationEvent e)107 public void fireInitializationEvent(final IterationEvent e) { 108 for (IterationListener l : listeners) { 109 l.initializationPerformed(e); 110 } 111 } 112 113 /** 114 * Informs all registered listeners that a new iteration (in the main iteration loop) has been 115 * performed. 116 * 117 * @param e The {@link IterationEvent} object. 118 */ fireIterationPerformedEvent(final IterationEvent e)119 public void fireIterationPerformedEvent(final IterationEvent e) { 120 for (IterationListener l : listeners) { 121 l.iterationPerformed(e); 122 } 123 } 124 125 /** 126 * Informs all registered listeners that a new iteration (in the main iteration loop) has been 127 * started. 128 * 129 * @param e The {@link IterationEvent} object. 130 */ fireIterationStartedEvent(final IterationEvent e)131 public void fireIterationStartedEvent(final IterationEvent e) { 132 for (IterationListener l : listeners) { 133 l.iterationStarted(e); 134 } 135 } 136 137 /** 138 * Informs all registered listeners that the final phase (post-iterations) has been completed. 139 * 140 * @param e The {@link IterationEvent} object. 141 */ fireTerminationEvent(final IterationEvent e)142 public void fireTerminationEvent(final IterationEvent e) { 143 for (IterationListener l : listeners) { 144 l.terminationPerformed(e); 145 } 146 } 147 148 /** 149 * Returns the number of iterations of this solver, 0 if no iterations has been performed yet. 150 * 151 * @return the number of iterations. 152 */ getIterations()153 public int getIterations() { 154 return iterations.getCount(); 155 } 156 157 /** 158 * Returns the maximum number of iterations. 159 * 160 * @return the maximum number of iterations. 161 */ getMaxIterations()162 public int getMaxIterations() { 163 return iterations.getMaximalCount(); 164 } 165 166 /** 167 * Increments the iteration count by one, and throws an exception if the maximum number of 168 * iterations is reached. This method should be called at the beginning of a new iteration. 169 * 170 * @throws MaxCountExceededException if the maximum number of iterations is reached. 171 */ incrementIterationCount()172 public void incrementIterationCount() throws MaxCountExceededException { 173 iterations.increment(); 174 } 175 176 /** 177 * Removes the specified iteration listener from the list of listeners currently attached to 178 * {@code this} object. Attempting to remove a listener which was <em>not</em> previously 179 * registered does not cause any error. 180 * 181 * @param listener The {@link IterationListener} to be removed. 182 */ removeIterationListener(final IterationListener listener)183 public void removeIterationListener(final IterationListener listener) { 184 listeners.remove(listener); 185 } 186 187 /** Sets the iteration count to 0. This method must be called during the initial phase. */ resetIterationCount()188 public void resetIterationCount() { 189 iterations = iterations.withStart(0); 190 } 191 } 192