24package umontreal.ssj.simexp;
26import java.lang.ref.SoftReference;
27import cern.colt.list.DoubleArrayList;
28import cern.colt.matrix.DoubleMatrix1D;
29import cern.colt.matrix.DoubleMatrix2D;
30import umontreal.ssj.simevents.Event;
31import umontreal.ssj.simevents.Simulator;
32import umontreal.ssj.util.Misc;
157 private DoubleArrayList batchTimes =
new DoubleArrayList();
158 private boolean batchLengths;
159 private boolean aggregation;
160 private int minBatches;
161 private int maxBatches;
162 private double warmupTime;
163 private EndSimEvent endSimEvent;
165 private boolean warmupDone;
166 private int targetBatches;
167 private int doneBatches;
168 private int droppedBatches;
169 private double batchFraction;
170 private double batchSizeMultiplier;
171 private boolean aggregateUpdated;
172 private double batchSize;
190 this(minBatches, Integer.MAX_VALUE, batchSize, warmupTime);
207 public BatchMeansSim(
int minBatches,
int maxBatches,
double batchSize,
double warmupTime) {
223 this(sim, minBatches, Integer.MAX_VALUE, batchSize, warmupTime);
241 throw new IllegalArgumentException(
"minBatches <= 0");
242 if (maxBatches < minBatches)
243 throw new IllegalArgumentException(
"maxBatches < minBatches");
245 throw new IllegalArgumentException(
"Warmup time must not be negative");
247 throw new IllegalArgumentException(
"Batch size must not be 0 or negative");
248 this.minBatches = minBatches;
249 this.maxBatches = maxBatches;
250 this.warmupTime = warmupTime;
251 this.batchSize = batchSize;
252 targetBatches = minBatches;
277 throw new IllegalStateException(
"Cannot change the aggregation status during simulation");
302 throw new IllegalStateException(
"Cannot change the aggregation status during simulation");
326 throw new IllegalArgumentException(
"minBatches <= 0");
327 this.minBatches = minBatches;
328 if (maxBatches < minBatches)
329 maxBatches = minBatches;
354 if (maxBatches < minBatches)
355 throw new IllegalArgumentException(
"maxBatches < minBatches");
356 this.maxBatches = maxBatches;
379 throw new IllegalArgumentException(
"batchSize <= 0");
380 this.batchSize = batchSize;
403 throw new IllegalArgumentException(
"warmupTime < 0");
404 this.warmupTime = warmupTime;
428 return batchFraction;
444 return batchSizeMultiplier;
457 return targetBatches;
471 if (targetBatches < minBatches)
472 throw new IllegalArgumentException(
"Target number of batches too small");
473 if (targetBatches > maxBatches)
474 throw new IllegalArgumentException(
"Target number of batches too large");
475 this.targetBatches = targetBatches;
498 return droppedBatches;
510 if (n < 0 || n > doneBatches - droppedBatches)
511 throw new IllegalArgumentException(
512 "Cannot drop less than 0 or more than " + (doneBatches - droppedBatches) +
" real batches");
513 if (batchLengths || aggregation)
514 batchTimes.removeFromTo(0, n - 1);
529 if (!batchLengths && !aggregation)
531 if (batchTimes.size() == 0)
557 throw new IllegalStateException(
"Number of real batches not available");
574 if (batchLengths || aggregation)
578 return batchTimes.get(batch + 1 - droppedBatches) - batchTimes.getQuick(batch - droppedBatches);
579 else if (batch != doneBatches - 1)
580 throw new IllegalArgumentException(
"Unavailable batch length");
582 return batchTimes.getQuick(1) - batchTimes.getQuick(0);
592 if (batchLengths || aggregation)
593 return batchTimes.get(batch);
594 else if (batch != doneBatches - 1)
595 throw new IllegalArgumentException(
"Unavailable batch time");
597 return batchTimes.getQuick(0);
607 if (batchLengths || aggregation)
608 return batchTimes.get(batch + 1);
609 else if (batch != doneBatches - 1)
610 throw new IllegalArgumentException(
"Unavailable batch time");
612 return batchTimes.getQuick(1);
634 throw new UnsupportedOperationException();
669 throw new UnsupportedOperationException();
686 SoftReference<?> softRef =
new SoftReference<double[]>(
new double[50000]);
688 batchSizeMultiplier = 1.0;
689 int currentCapacity = doneBatches;
690 while (currentCapacity < targetBatches && softRef.get() !=
null) {
692 int newCapacity = Math.min(2 * currentCapacity + 1, targetBatches);
696 if (aggregation || batchLengths)
697 batchTimes.ensureCapacity(newCapacity + 1);
700 }
catch (UnsupportedOperationException use) {
703 currentCapacity = newCapacity;
705 if (currentCapacity < targetBatches && softRef.get() ==
null) {
707 throw new IllegalStateException(
"Cannot increase batch size");
713 double ftargetBatches = targetBatches;
714 double fdoneBatches = doneBatches;
715 while (targetBatches > currentCapacity) {
716 batchSizeMultiplier *= 2;
720 targetBatches = (int) ftargetBatches;
721 doneBatches = (int) fdoneBatches;
722 if (aggregation || batchLengths) {
723 for (
int i = 0; i < batchTimes.size() / 2; i++)
724 batchTimes.setQuick(i, batchTimes.getQuick(2 * i));
725 batchTimes.setSize(batchTimes.size() / 2);
729 batchFraction = 1.0 - (fdoneBatches - doneBatches);
733 if (targetBatches % minBatches != 0) {
734 targetBatches /= minBatches;
735 targetBatches *= minBatches;
736 targetBatches += minBatches;
807 throw new IllegalStateException(
"Already simulating");
812 if (targetBatches < minBatches)
813 targetBatches = minBatches;
814 if (aggregation && targetBatches % minBatches != 0) {
815 targetBatches /= minBatches;
816 targetBatches += minBatches;
817 if (targetBatches + minBatches <= maxBatches)
818 targetBatches += minBatches;
820 aggregateUpdated =
false;
822 endSimEvent =
new EndSimEvent(
simulator());
858 throw new IllegalStateException(
"Warmup already done");
859 if (!Double.isInfinite(warmupTime) && !Double.isNaN(warmupTime))
860 endSimEvent.schedule(warmupTime);
862 endSimEvent.cancel();
866 if (aggregation || batchLengths) {
867 batchTimes.setSize(0);
870 batchTimes.setSize(2);
871 batchTimes.trimToSize();
872 batchTimes.setQuick(0,
simulator().time());
873 batchTimes.setQuick(1,
simulator().time());
908 endSimEvent.schedule(batchLength);
910 endSimEvent.cancel();
912 batchSizeMultiplier = 1.0;
913 aggregateUpdated =
false;
915 if (batchLengths || aggregation)
918 batchTimes.setQuick(0, batchTimes.getQuick(1));
919 batchTimes.setQuick(1,
simulator().time());
936 if (doneBatches + numNewBatches > maxBatches) {
937 numNewBatches = maxBatches - doneBatches;
938 if (aggregation && numNewBatches < minBatches)
949 if (numNewBatches % minBatches != 0) {
950 numNewBatches /= minBatches;
951 numNewBatches *= minBatches;
952 if (doneBatches + numNewBatches + minBatches <= maxBatches)
953 numNewBatches += minBatches;
956 targetBatches = doneBatches + numNewBatches;
968 if (doneBatches < targetBatches)
973 while (doneBatches < targetBatches)
980 makeAggregateBatches();
994 while (doneBatches < targetBatches) {
998 if (aggregation && !aggregateUpdated)
999 makeAggregateBatches();
1005 private final void makeAggregateBatches() {
1011 nAgr = (doneBatches - droppedBatches) / minBatches;
1013 int tnb = minBatches;
1019 tnb = doneBatches - droppedBatches;
1021 for (
int i = 0; i < tnb; i++) {
1022 int startAgr = i * nAgr + droppedBatches;
1024 batchTimes.getQuick(startAgr - droppedBatches + nAgr) - batchTimes.getQuick(startAgr - droppedBatches));
1026 aggregateUpdated =
true;
1029 private static final class EndSimEvent
extends Event {
1030 public EndSimEvent(Simulator sim) {
1039 public String toString() {
1040 StringBuffer sb =
new StringBuffer(getClass().
getName());
1042 sb.append(
"minimal number of batches: ").append(minBatches);
1043 if (maxBatches < Integer.MAX_VALUE)
1044 sb.append(
", maximal number of batches: ").append(maxBatches);
1045 sb.append(
", target number of batches: ").append(targetBatches);
1046 sb.append(
", warmup time: ").append(warmupTime);
1048 sb.append(
", simulation in progress");
1050 sb.append(
", simulation stopped");
1052 sb.append(
", number of completed batches: ").append(doneBatches);
1054 sb.append(
", warmup not completed");
1056 sb.append(
", batch aggregation turned ON");
1058 sb.append(
", batch aggregation turned OFF");
1060 sb.append(
", batch lengths are kept");
1062 sb.append(
", batch lengths are not kept");
1065 return sb.toString();
1083 public static double getSum(
double[] a,
int start,
int length) {
1085 throw new IndexOutOfBoundsException(
"start must not be negative");
1087 throw new IllegalArgumentException(
"length is negative");
1088 if (start + length > a.length)
1089 throw new IndexOutOfBoundsException(
"Not enough elements in the array");
1091 for (
int i = start; i < start + length; i++)
1110 public static double getSum(DoubleArrayList l,
int start,
int length) {
1112 throw new IndexOutOfBoundsException(
"start must not be negative");
1114 throw new IllegalArgumentException(
"length is negative");
1115 if (start + length > l.size())
1116 throw new IndexOutOfBoundsException(
"Not enough elements in the array list");
1118 for (
int i = start; i < start + length; i++)
1137 public static double getSum(DoubleMatrix1D m,
int start,
int length) {
1139 throw new IndexOutOfBoundsException(
"start must not be negative");
1141 throw new IllegalArgumentException(
"length is negative");
1142 if (start + length > m.size())
1143 throw new IndexOutOfBoundsException(
"Not enough elements in the matrix");
1145 for (
int i = start; i < start + length; i++)
1168 public static double[]
getSum(
double[][] a,
int startColumn,
int numColumns) {
1170 return new double[0];
1171 if (startColumn < 0)
1172 throw new IndexOutOfBoundsException(
"startColumn must not be negative");
1174 throw new IllegalArgumentException(
"numColumns is negative");
1175 if (startColumn + numColumns > a[0].length)
1176 throw new IndexOutOfBoundsException(
"Not enough elements in the array");
1177 double[] res =
new double[a.length];
1178 for (
int i = 0; i < res.length; i++)
1179 for (
int j = startColumn; j < startColumn + numColumns; j++)
1199 public static double[]
getSum(DoubleMatrix2D m,
int startColumn,
int numColumns) {
1200 if (startColumn < 0)
1201 throw new IndexOutOfBoundsException(
"startColumn must not be negative");
1203 throw new IllegalArgumentException(
"numColumns is negative");
1204 if (startColumn + numColumns > m.columns())
1205 throw new IndexOutOfBoundsException(
"Not enough columns in the matrix");
1206 double[] res =
new double[m.rows()];
1207 for (
int i = 0; i < res.length; i++)
1208 for (
int j = startColumn; j < startColumn + numColumns; j++)
1209 res[i] += m.getQuick(i, j);
1228 throw new IllegalArgumentException(
"x < 1");
1229 int gs = a.length / x;
1230 for (
int i = 0; i < gs; i++) {
1232 for (
int j = 0; j < x; j++)
1236 int m = a.length % x;
1239 int r = a.length - x * gs;
1240 for (
int j = 0; j < r; j++)
1245 for (
int i = gs; i < a.length; i++)
1260 throw new IllegalArgumentException(
"x < 1");
1261 int gs = l.size() / x;
1262 for (
int i = 0; i < gs; i++) {
1264 for (
int j = 0; j < x; j++)
1265 o += l.getQuick(i * x + j);
1268 int m = l.size() % x;
1271 int r = l.size() - x * gs;
1272 for (
int j = 0; j < r; j++)
1273 o += l.getQuick(gs * x + j);
1290 throw new IllegalArgumentException(
"x < 1");
1291 int gs = mat.size() / x;
1292 for (
int i = 0; i < gs; i++) {
1294 for (
int j = 0; j < x; j++)
1295 o += mat.getQuick(i * x + j);
1298 int m = mat.size() % x;
1301 int r = mat.size() - x * gs;
1302 for (
int j = 0; j < r; j++)
1303 o += mat.getQuick(gs * x + j);
1304 mat.setQuick(gs, o);
1307 for (
int i = gs; i < mat.size(); i++)
1322 throw new IllegalArgumentException(
"x < 1");
1323 int gs = mat.columns() / x;
1324 for (
int i = 0; i < gs; i++) {
1325 for (
int r = 0; r < mat.rows(); r++) {
1327 for (
int j = 0; j < x; j++)
1328 o += mat.getQuick(r, i * x + j);
1329 mat.setQuick(r, i, o);
1332 int m = mat.columns() % x;
1334 int r = mat.columns() - x * gs;
1335 for (
int row = 0; row < mat.rows(); row++) {
1337 for (
int j = 0; j < r; j++)
1338 o += mat.getQuick(row, gs * x + j);
1339 mat.setQuick(row, gs, o);
1343 for (
int row = 0; row < mat.rows(); row++)
1344 for (
int i = gs; i < mat.columns(); i++)
1345 mat.setQuick(row, i, 0);
This abstract class provides event scheduling tools.
abstract void actions()
This is the method that is executed when this event occurs.
final Simulator simulator()
Returns the simulator linked to this event.
Represents the executive of a discrete-event simulator.
void stop()
Tells the simulation executive to stop as soon as it takes control, and to return control to the prog...
void start()
Starts the simulation executive.
void init()
Reinitializes the simulation executive by clearing up the event list, and resetting the simulation cl...
static Simulator getDefaultSimulator()
Returns the default simulator instance used by the deprecated class.
boolean getBatchAggregation()
Returns true if the aggregation of batches is turned ON.
void setBatchLengthsKeeping(boolean b)
Sets the batch lengths keeping indicator to b.
void warmup()
Performs a warmup by calling warmup(double).
void dropFirstRealBatches(int n)
Drops the n first real batches to save memory.
double getRealBatchEndingTime(int batch)
Returns the ending simulation time of batch batch.
Event getEndSimEvent()
Returns the event used to stop the simulation at the end of the warmup or batches.
static void regroupElements(DoubleMatrix2D mat, int x)
Same as regroupElements(double[],int) for a 2D matrix.
abstract void initRealBatchProbes()
Initializes any statistical collector for real batches.
void setBatchAggregation(boolean a)
Sets the batch aggregation indicator to a.
double getBatchFraction()
Returns the remaining fraction of batch to be simulated.
abstract void initBatchStat()
Resets the counters used for computing observations during the simulation at the beginning of a new b...
void setWarmupTime(double warmupTime)
Sets the warmup time to warmupTime.
void simulateBatch(double batchLength)
Simulates a batch with length batchLength.
BatchMeansSim(int minBatches, double batchSize, double warmupTime)
Constructs a new batch means simulator using at least minBatches batches with size batchSize,...
BatchMeansSim(Simulator sim, int minBatches, double batchSize, double warmupTime)
Equivalent to the first constructor, with a user-defined simulator sim.
abstract void addEffectiveBatchObs(int s, int h, double l)
Adds an observation to each statistical collector corresponding to an effective batch.
double getRealBatchLength(int batch)
Returns the length, in simulation time units, of the real batch batch.
double getBatchSize()
Returns the current batch size as defined for this simulator.
int getMaxBatches()
Returns , the maximal number of batches to be used for estimating the steady-state performance measur...
int getTargetBatches()
Returns the target number of simulated real batches at the next time the stopping condition is checke...
void allocateCapacity(int capacity)
Allocates the necessary memory for storing capacity real batches.
static void regroupElements(DoubleMatrix1D mat, int x)
Same as regroupElements(double[],int) for a 1D matrix.
int getBatch(double time)
Returns the real batch corresponding to simulation time time when batch lengths are kept.
static double getSum(DoubleArrayList l, int start, int length)
Returns the sum of elements start, …, start + length - 1, in the array list l.
static void regroupElements(double[] a, int x)
Regroups the elements in array a by summing each successive x values.
int getMinBatches()
Returns the minimal number of batches required for estimating the steady-state performance measures o...
static double getSum(DoubleMatrix1D m, int start, int length)
Returns the sum of elements start, …, start + length - 1, in the 1D matrix m.
void setMaxBatches(int maxBatches)
Sets the maximal number of batches to maxBatches.
void setMinBatches(int minBatches)
Sets the minimal number of batches to minBatches.
int getCompletedRealBatches()
Returns the number of completed real batches since the beginning of the run.
static double getSum(double[] a, int start, int length)
Returns the sum of elements start, …, start + length - 1, in the array a.
abstract void addRealBatchObs()
Collects values of a vector concerning the last simulated real batch.
void simulateBatch()
Simulate a new batch with default length.
abstract void initEffectiveBatchProbes()
Initializes any statistical collector for effective batches.
boolean getBatchLengthsKeeping()
Indicates that the length, in simulation time units, of each real batch has to be kept.
static double[] getSum(double[][] a, int startColumn, int numColumns)
Returns an array containing the sum of columns startColumn, …, startColumn + numColumns - 1,...
BatchMeansSim(int minBatches, int maxBatches, double batchSize, double warmupTime)
Constructs a batch means simulator with a maximum of maxBatches batches to avoid excessive memory usa...
void init()
Initializes the simulator for a new experiment.
void simulateBatches()
Simulates batches until the number of completed real batches corresponds to the target number of batc...
double getRealBatchStartingTime(int batch)
Returns the starting simulation time of batch batch.
boolean isWarmupDone()
Determines if the warmup period for the simulation is over.
static void regroupElements(DoubleArrayList l, int x)
Same as regroupElements(double[],int) for an array list.
abstract void initSimulation()
Initializes the simulator for a new run.
void setBatchSize(double batchSize)
Sets the batch size to batchSize.
void setTargetBatches(int targetBatches)
Sets the target number of simulated batches before an error check or the end of the simulation to tar...
static double[] getSum(DoubleMatrix2D m, int startColumn, int numColumns)
Returns an array containing the sum of columns startColumn, …, startColumn + numColumns - 1,...
void warmup(double warmupTime)
Performs a warmup of fixed duration warmupTime.
double getBatchSizeMultiplier()
Returns the batch size multiplier after the simulation of a new batch.
BatchMeansSim(Simulator sim, int minBatches, int maxBatches, double batchSize, double warmupTime)
Equivalent to the second constructor, with a user-defined simulator sim.
void regroupRealBatches(int x)
Regroups real batches x by x.
int getDroppedRealBatches()
Returns the number of real batches dropped.
int getNumAggregates()
Returns , the number of real batches contained into an effective batch.
void simulate()
Performs a batch means simulation.
void adjustTargetBatches(int numNewBatches)
Adjusts the target number of real batches to simulate numNewBatches additionnal real batches.
int getRequiredNewBatches()
Computes the approximate number of required real batches to be simulated before the simulation can be...
double getWarmupTime()
Returns the duration of the warmup period for the simulation.
boolean simulating
Determines if the simulation is in progress.
SimExp()
Constructs a new object for performing experiments using the default simulator returned by Simulator....
final Simulator simulator()
Returns the simulator linked to this experiment object.
This class provides miscellaneous functions that are hard to classify.
static int getTimeInterval(double[] times, int start, int end, double t)
Returns the index of the time interval corresponding to time t.
String getName(int series)
Gets the current name of the selected series.