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 */ 017package org.apache.commons.math3.util; 018 019import java.util.Collection; 020import java.util.concurrent.CopyOnWriteArrayList; 021 022import 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 */ 031public class IterationManager { 032 033 /** Keeps a count of the number of iterations. */ 034 private IntegerSequence.Incrementor iterations; 035 036 /** The collection of all listeners attached to this iterative algorithm. */ 037 private final Collection<IterationListener> listeners; 038 039 /** 040 * Creates a new instance of this class. 041 * 042 * @param maxIterations the maximum number of iterations 043 */ 044 public IterationManager(final int maxIterations) { 045 this.iterations = IntegerSequence.Incrementor.create().withMaximalCount(maxIterations); 046 this.listeners = new CopyOnWriteArrayList<IterationListener>(); 047 } 048 049 /** 050 * Creates a new instance of this class. 051 * 052 * @param maxIterations the maximum number of iterations 053 * @param callBack the function to be called when the maximum number of 054 * iterations has been reached 055 * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is {@code null} 056 * @since 3.1 057 * @deprecated as of 3.6, replaced with {@link #IterationManager(int, 058 * org.apache.commons.math3.util.IntegerSequence.Incrementor.MaxCountExceededCallback)} 059 */ 060 @Deprecated 061 public IterationManager(final int maxIterations, 062 final Incrementor.MaxCountExceededCallback callBack) { 063 this(maxIterations, new IntegerSequence.Incrementor.MaxCountExceededCallback() { 064 /** {@inheritDoc} */ 065 public void trigger(final int maximalCount) throws MaxCountExceededException { 066 callBack.trigger(maximalCount); 067 } 068 }); 069 } 070 071 /** 072 * Creates a new instance of this class. 073 * 074 * @param maxIterations the maximum number of iterations 075 * @param callBack the function to be called when the maximum number of 076 * iterations has been reached 077 * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is {@code null} 078 * @since 3.6 079 */ 080 public IterationManager(final int maxIterations, 081 final IntegerSequence.Incrementor.MaxCountExceededCallback callBack) { 082 this.iterations = IntegerSequence.Incrementor.create().withMaximalCount(maxIterations).withCallback(callBack); 083 this.listeners = new CopyOnWriteArrayList<IterationListener>(); 084 } 085 086 /** 087 * Attaches a listener to this manager. 088 * 089 * @param listener A {@code IterationListener} object. 090 */ 091 public void addIterationListener(final IterationListener listener) { 092 listeners.add(listener); 093 } 094 095 /** 096 * Informs all registered listeners that the initial phase (prior to the 097 * main iteration loop) has been completed. 098 * 099 * @param e The {@link IterationEvent} object. 100 */ 101 public void fireInitializationEvent(final IterationEvent e) { 102 for (IterationListener l : listeners) { 103 l.initializationPerformed(e); 104 } 105 } 106 107 /** 108 * Informs all registered listeners that a new iteration (in the main 109 * iteration loop) has been performed. 110 * 111 * @param e The {@link IterationEvent} object. 112 */ 113 public void fireIterationPerformedEvent(final IterationEvent e) { 114 for (IterationListener l : listeners) { 115 l.iterationPerformed(e); 116 } 117 } 118 119 /** 120 * Informs all registered listeners that a new iteration (in the main 121 * iteration loop) has been started. 122 * 123 * @param e The {@link IterationEvent} object. 124 */ 125 public void fireIterationStartedEvent(final IterationEvent e) { 126 for (IterationListener l : listeners) { 127 l.iterationStarted(e); 128 } 129 } 130 131 /** 132 * Informs all registered listeners that the final phase (post-iterations) 133 * has been completed. 134 * 135 * @param e The {@link IterationEvent} object. 136 */ 137 public void fireTerminationEvent(final IterationEvent e) { 138 for (IterationListener l : listeners) { 139 l.terminationPerformed(e); 140 } 141 } 142 143 /** 144 * Returns the number of iterations of this solver, 0 if no iterations has 145 * been performed yet. 146 * 147 * @return the number of iterations. 148 */ 149 public int getIterations() { 150 return iterations.getCount(); 151 } 152 153 /** 154 * Returns the maximum number of iterations. 155 * 156 * @return the maximum number of iterations. 157 */ 158 public int getMaxIterations() { 159 return iterations.getMaximalCount(); 160 } 161 162 /** 163 * Increments the iteration count by one, and throws an exception if the 164 * maximum number of iterations is reached. This method should be called at 165 * the beginning of a new iteration. 166 * 167 * @throws MaxCountExceededException if the maximum number of iterations is 168 * reached. 169 */ 170 public void incrementIterationCount() 171 throws MaxCountExceededException { 172 iterations.increment(); 173 } 174 175 /** 176 * Removes the specified iteration listener from the list of listeners 177 * currently attached to {@code this} object. Attempting to remove a 178 * listener which was <em>not</em> previously registered does not cause any 179 * error. 180 * 181 * @param listener The {@link IterationListener} to be removed. 182 */ 183 public void removeIterationListener(final IterationListener listener) { 184 listeners.remove(listener); 185 } 186 187 /** 188 * Sets the iteration count to 0. This method must be called during the 189 * initial phase. 190 */ 191 public void resetIterationCount() { 192 iterations = iterations.withStart(0); 193 } 194}