/* *
* Title:
* Description:
* Copyright: Copyright (c)
* Company:
* @author
* @version 1.0
*/
package umontreal.iro.lecuyer.stat;
import java.util.List;
import java.util.ArrayList;
import umontreal.iro.lecuyer.util.PrintfFormat;
/**
* The objects of this class are statistical probes or
* collectors, which are elementary devices for collecting
* statistics. Each probe collects statistics on a given variable.
* The subclasses {@link Tally}, {@link TallyStore}, and
* {@link umontreal.iro.lecuyer.simevents.Accumulate Accumulate} (from package
* {@link umontreal.iro.lecuyer.simevents simevents})
* implement two kinds of probes, for the case of successive observations
*
* X1, X2, X3,..., and for the case of a variable whose value
* evolves in time, respectively.
*
*
* Each instance of
* {@link StatProbe} contains a list of {@link ObservationListener} that can listen
* to individual observations.
* When a probe is updated, i.e., receives a new statistical observation,
* it broadcasts this new data to all registered observers.
* The broadcasting of observations to registered observers can be turned
* ON or OFF at any time.
* It is initially OFF by default and should stay OFF when there are
* no registered observers, to avoid unnecessary overhead.
*
*
* The data collection by the statistical probe itself can also be turned
* ON or OFF. By default, it is initially ON.
* We can turn it OFF, for example, if we want to use the statistical probe
* only to pass data to the observers, and do not need it to store
* any information.
*
*
* In the simplest programs, collection is ON, broadcast is OFF, and the overall
* stats are accessed via the methods
* min, max, sum, average, ... of the
* collector.
*
*/
public abstract class StatProbe {
private List listeners = new ArrayList();
protected String name;
protected double maxValue;
protected double minValue;
protected double sumValue;
protected boolean collect = true;
protected boolean broadcast = false;
protected boolean showNobs = true;
/**
* Initializes the statistical collector.
*
*/
abstract public void init();
/**
* Sets the name of this statistical collector to name.
*
*/
public void setName (String name) {
this.name = name;
}
/**
* Returns the name associated with this probe,
* or null if no name was specified upon construction.
*
* @return the name associated to this collector,
* or null if not specified
*
*/
public String getName() {
return name;
}
/**
* Returns the smallest value taken by the variable
* since the last initialization
* of this probe.
* This returns Double.POSITIVE_INFINITY
* if the probe was not updated since the last initialization.
*
* @return the smallest value taken by the collector since last initialization
*
*/
public double min() {
return minValue;
}
/**
* Returns the largest value taken by the variable
* since the last initialization
* of this probe.
* This returns Double.NEGATIVE_INFINITY
* if the probe was not updated since the last initialization.
*
* @return the largest value taken by the collector since last initialization
*
*/
public double max() {
return maxValue;
}
/**
* Returns the sum cumulated so far for this probe.
* The meaning of this sum depends on the subclass (e.g., {@link Tally} or
* {@link umontreal.iro.lecuyer.simevents.Accumulate Accumulate}).
* This returns 0
* if the probe was not updated since the last initialization.
*
* @return the sum for this probe
*
*/
public double sum() {
return sumValue;
}
/**
* Returns the average for this collector.
* This returns Double.NaN
* if the probe was not updated since the last initialization.
*
* @return the average value of the collected observations
*
*/
abstract public double average();
/**
* Returns a string containing a report for this statistical
* collector. The contents of this report depends on the statistical probe as
* well as on the parameters set by the user through probe-specific methods.
*
* @return a report for this probe, represented as a string
*
*/
abstract public String report();
/**
* Formats and returns a short, one-line report
* about this statistical probe. This line is composed of
* whitespace-separated fields which must
* correspond to the column names given by {@link #shortReportHeader shortReportHeader}().
* This report should not contain any end-of-line character, and does not
* include the name of the probe.
* Its contents depends on the statistical probe as well as on the
* parameters set by the user through probe-specific methods.
*
* @return the short report for the probe.
*
*/
abstract public String shortReport();
/**
* Returns a string containing
* the name of the values returned in the report
* strings. The returned string must depend on the type of probe and on
* the reporting options only. It must not depend on the observations
* received by the probe.
* This can be used as header when printing
* several reports. For example,
*
* System.out.println (probe1.shortReportHeader());
* System.out.println (probe1.getName() + " " + probe1.shortReport());
* System.out.println (probe2.getName() + " " + probe2.shortReport());
* ...
*
* Alternatively, one can use {@link #report report} (String,StatProbe[])
* to get a report with aligned probe names.
*
* @return the header string for the short reports.
*
*/
abstract public String shortReportHeader();
/**
* Formats short reports for each statistical probe in the array
* probes while aligning the probes' names.
* This method first formats the given global name.
* It then determines the maximum length
of the names of probes in the
* given array.
* The first line of the report is composed of [tex2html_wrap_inline223] + 3 spaces followed by the
* string returned by {@link #shortReportHeader shortReportHeader} called on the first probe in
* probes. Each remaining line corresponds to a statistical probe; it
* contains the probe's name followed by the contents returned by
* {@link #shortReport shortReport}. Note that this method assumes that probes
* contains no null element.
*
* @param globalName the global name given to the formatted report.
*
* @param probes the probes to include in the report.
*
* @return the formatted report.
*
*/
public static String report (String globalName, StatProbe[] probes) {
int maxn = 0;
StatProbe firstProbe = null;
for (StatProbe probe : probes) {
if (firstProbe == null)
firstProbe = probe;
String s = probe.getName();
if (s != null && s.length() > maxn)
maxn = s.length();
}
if (firstProbe == null)
return "";
StringBuffer sb = new StringBuffer ("Report for ");
sb.append (globalName).append (PrintfFormat.NEWLINE);
for (int i = 0; i < maxn; i++)
sb.append (' ');
sb.append (" ");
sb.append (firstProbe.shortReportHeader()).append (PrintfFormat.NEWLINE);
for (StatProbe probe : probes) {
sb.append
(PrintfFormat.s (-maxn, probe.getName()));
sb.append (" ");
sb.append (probe.shortReport()).append (PrintfFormat.NEWLINE);
}
return sb.toString();
}
/**
* Equivalent to {@link #report((String,StatProbe[])) report}, except that
* probes is an {@link Iterable} object instead of an array.
* Of course, the iterator returned by probes should enumerate the
* statistical probes to include in the report in a consistent and sensible order.
*
* @param globalName the global name given to the formatted report.
*
* @param probes the probes to include in the report.
*
* @return the formatted report.
*
*/
public static String report (String globalName,
Iterable extends StatProbe> probes) {
int maxn = 0;
StatProbe firstProbe = null;
for (StatProbe probe : probes) {
if (firstProbe == null)
firstProbe = probe;
String s = probe.getName();
int sl = s == null ? 4 : s.length();
if (sl > maxn)
maxn = sl;
}
if (firstProbe == null)
return "";
StringBuffer sb = new StringBuffer ("Report for ");
sb.append (globalName).append (PrintfFormat.NEWLINE);
for (int i = 0; i < maxn; i++)
sb.append (' ');
sb.append (" ");
sb.append (firstProbe.shortReportHeader()).append (PrintfFormat.NEWLINE);
for (StatProbe probe : probes) {
sb.append
(PrintfFormat.s (-maxn, probe.getName()));
sb.append (" ");
sb.append (probe.shortReport()).append (PrintfFormat.NEWLINE);
}
return sb.toString();
}
/**
* Determines if this statistical probe
* is broadcasting observations to registered observers.
* The default is false.
*
* @return the status of broadcasting.
*
*/
public boolean isBroadcasting() {
return broadcast;
}
/**
* Instructs the probe to turn its broadcasting ON or OFF.
* The default value is OFF.
*
*
* Warning: To avoid useless overhead and performance degradation, broadcasting
* should never be turned ON when there are no registered observers.
*
* @param b true to turn broadcasting ON, false to turn it OFF
*
*
*/
public void setBroadcasting (boolean b) {
broadcast = b;
}
/**
* Determines if this statistical probe
* is collecting values. The default is true.
*
* @return the status of statistical collecting.
*
*/
public boolean isCollecting() {
return collect;
}
/**
* Turns ON or OFF the collection of statistical
* observations. The default value is ON.
* When statistical collection is turned OFF,
* observations added to the probe are passed to the
* registered observers if broadcasting is turned ON, but are not
* counted as observations by the probe itself.
*
* @param b true to activate statistical collection,
* false to deactivate it
*
*
*/
public void setCollecting (boolean b) {
collect = b;
}
/**
* Adds the observation listener l to the list of observers of
* this statistical probe.
*
* @param l the new observation listener.
*
* @exception NullPointerException if l is null.
*
*
*/
public void addObservationListener (ObservationListener l) {
if (l == null)
throw new NullPointerException();
if (!listeners.contains (l))
listeners.add (l);
}
/**
* Removes the observation listener l from the list of observers of
* this statistical probe.
*
* @param l the observation listener to be deleted.
*
*
*/
public void removeObservationListener (ObservationListener l) {
listeners.remove (l);
}
/**
* Removes all observation listeners from the list of observers of
* this statistical probe.
*
*/
public void clearObservationListeners() {
listeners.clear();
}
/**
* Notifies the observation x to all registered observers
* if broadcasting is ON. Otherwise, does nothing.
*
*/
public void notifyListeners (double x) {
if (!broadcast)
return;
// We could also use the enhanced for loop here, but this is less efficient.
final int nl = listeners.size();
for (int i = 0; i < nl; i++)
listeners.get (i).newObservation (this, x);
}
public StatProbe clone() throws CloneNotSupportedException {
StatProbe s = (StatProbe)super.clone();
s.listeners = new ArrayList(listeners);
return s;
}
}
Ads help maintain this website.