Class Experiment

  • All Implemented Interfaces:
    Notifier<Experiment,​Experiment.ExperimentEvent>, ValueStore, Serializable, Cloneable
    Direct Known Subclasses:
    AbstractMultiExperiment, SimulationExperiment

    public abstract class Experiment
    extends Object
    implements Notifier<Experiment,​Experiment.ExperimentEvent>, ValueStore, Cloneable, Serializable
    An Experiment is something that produces results depending on various parameters. The usual lifecycle is to create an experiment, set parameters to their proper values, execute the experiment by calling it's runExperiment() method. After execution a set of results are available using the getResults() method.

    Experiments are not supposed to be executed more than once, e.g., to run multiple replications of an experiment (see MultipleReplicationExperiment) you have to create multiple instances. Therefore experiments should be cloneable.

    This class is intended as the base class for Experiments doing something useful. Besides a name this class only has a single parameter "initialSeed" (see getInitialSeed()/setInitialSeed(long)). This parameter is supposed to be used as the starting value for all (pseudo) random number generation activities at experiment runtime. This means two experiments having the same initialSeed and all other experiment parameters being the same should behave deterministically and produce exactly the same results.

    The only results produced by this class are "runTime" (type Double; measuring the real time required to execute an experiment) and "expAborted" (type Integer, a value >0 indicates some problems causing early termination).

    Experiments can have listeners registered (derived from ExperimentListener), which are informed of various events such as an experiment's start and completion and can be used by subclasses to provide additional events.

    Author:
    Torsten Hildebrandt
    See Also:
    Serialized Form
    • Constructor Detail

      • Experiment

        public Experiment()
    • Method Detail

      • starting

        protected void starting()
        This method is called to perform any work that needs to be performed before the experiment can be initialized. It is called before the init() method and can be used to perform additional parameter checks, for instance.
      • init

        protected void init()
        This method is called to perform any initializations required before the experiment is run.
      • beforeRun

        protected void beforeRun()
        This method is called immediately before performRun(), but after init().
      • performRun

        protected abstract void performRun()
        Contains the code to actually do something useful. This is the only abstract method that sub-classes are required to implement.
      • afterRun

        protected void afterRun()
        This method is called immediately after performRun(), but before done().
      • done

        protected void done()
        This method can be overridden to perform any required clean-up. It is executed immediately after afterRun(), but before produceResults() and finish().
      • produceResults

        protected void produceResults()
        Populates the result map resultMap with values produced during experiment execution. The Experiment always adds the two results "runTime" and "expAborted".
      • finish

        protected void finish()
        This method gives experiments and listeners a chance to view/modify results. It is called after produceResults().
      • runExperiment

        public Map<String,​Object> runExperiment()
        Runs the experiment in a synchronous way. This is the main method to call in order to execute an experiment. Sub-classes normally don't have to overwrite this method but create customized behavior by overriding one of the life-cycle methods like init(), beforeRun(), performRun() (this one is required), done(), produceResults() or finish().
        Returns:
        The results of experiment execution.
        See Also:
        runExperimentAsync()
      • runExperimentInternal

        protected Map<String,​Object> runExperimentInternal()
        Runs the experiment. This is the main method to call in order to execute an experiment. Sub-classes normally don't have to overwrite this method but create customized behavior by overriding one of the life-cycle methods like init(), beforeRun(), performRun() (this one is required), done(), produceResults() or finish().
        Returns:
        The results of experiment execution.
      • requireState

        protected void requireState​(Experiment.ExperimentState expected)
        Checks, if an experiment is in a certain state.
        Parameters:
        expected - The expected state of an experiment.
        Throws:
        IllegalStateException - If not in the expected state.
      • handleExecutionError

        protected void handleExecutionError​(Throwable t)
        Lifecycle method that is executed if there was an Exception during experiment execution. In addition an EXPERIMENT_ERROR event is fired.
        Parameters:
        t -
      • finalActions

        protected void finalActions()
        This method can be used for actions like clean-up that should be done irrespectively of whether an exception occurred during experiment execution or not. Any code executed in this method should take care that it is not producing any uncatched exceptions itself.
      • checkCancelledOrInterrupted

        protected void checkCancelledOrInterrupted()
                                            throws CancellationException
        Checks whether the experiment was requested to cancel or the executing Thread was interrupted. If so, a CancellationException (unchecked exception) is thrown.

        Experiments that wan't to be responsive to cancellation requests should call this method frequently from within the main execution Thread.

        Throws:
        CancellationException - If the experiment was cancelled or interrupted.
      • addStandardResults

        protected void addStandardResults()
      • addErrorResults

        protected void addErrorResults()
      • isCancelled

        public boolean isCancelled()
        Checks whether the experiment was requested to cancel() its execution.
        Returns:
        true, if cancel() was called before; false otherwise.
      • abort

        public void abort()
        Marks experiment execution to be aborted by some error condition. This does not necessarily mean it's execution was cancel()led prematurely.
      • getResults

        public final Map<String,​Object> getResults()
        Returns the result map produced when executing this experiment.
        Returns:
        This experiment's results as an unmodifiable map.
      • getError

        public final Throwable getError()
        Returns:
        The exception that terminated this experiment. Might be a CancellationException if this experiment's execution was cancelled.
      • runTimeReal

        protected double runTimeReal()
        Returns the run time (in seconds) of an Experiment. The returned value is only valid after calling runExperiment() and measures the time between calling init() and the completion of done().
        Returns:
        The real time (wall time in seconds) it took to run the experiment.
      • executeSubExperiment

        protected ExperimentCompletableFuture executeSubExperiment​(Experiment sub)
        This is a convenience method to run a sub experiment without having to worry about ExperimentExecutor and nestingLevel.
        Parameters:
        sub - The sub-experiment to run.
        Returns:
        An ExperimentCompletableFuture to access results.
      • getPropsWithValues

        public Map<String,​Object> getPropsWithValues()
        Retrieves a map containing the name and current value for each of this experiment's properties.
        Returns:
        A map of all Java Bean properties and their values.
      • print

        public void print​(String message)
        Triggers a print event of category "info".
        Parameters:
        message - The message to print.
        See Also:
        print(MsgCategory, String)
      • print

        public void print​(MsgCategory category,
                          String message)
        Triggers a print event of the given category. If an appropriate listener is installed, this should produce an output of message.
        Parameters:
        category - Category of the message.
        message - The message to print.
        See Also:
        ConsolePrinter
      • print

        public void print​(MsgCategory category,
                          String messageFormat,
                          Object... params)
        Triggers a print event of the given category. If an appropriate listener is installed, this should produce a message created by the given format string and parameters.
        Parameters:
        category - Category of the message.
        messageFormat - Format string for the message to produce.
        params - Parameters to use in the format string.
      • print

        public void print​(String messageFormat,
                          Object... params)
        Same as print(MsgCategory, String, Object...), just defaulting to the category INFO.
        Parameters:
        messageFormat - The format String to use.
        params - Parameters to use when formatting the message.
      • printResults

        public final void printResults()
        Prints the results of this experiment to System.out.
      • nestingLevel

        public void nestingLevel​(int nestingLevel)
        Sets the nesting level. This method is only for internal purposes.
        Parameters:
        nestingLevel - The nesting level for this experiment.
      • nestingLevel

        public int nestingLevel()
        The level in the call hierarchy this experiment is executed in. Experiments that spawn new sub-experiments (like MultipleReplicationExperiment) are required to increase their children's nestingLevel by 1. If executeSubExperiment(Experiment) is used, then this is set automatically to the correct value.
        Returns:
        This experiment's nesting level.
      • setName

        public void setName​(String name)
        Set some descriptive name for this experiment.
        Parameters:
        name - The name of the experiment.
      • getName

        public String getName()
      • getInitialSeed

        public long getInitialSeed()
      • setInitialSeed

        public void setInitialSeed​(long initialSeed)
        Sets the initial seed for this experiment. If an experiment makes use of random influences, they should all and solely depend on this value.
        Parameters:
        initialSeed - The initial seed to use.
        See Also:
        RandomFactory
      • setLogLevel

        public void setLogLevel​(MsgCategory logLevel)
        Set the maximum level of logging messages that are supposed to be printed (e.g. TRACE to produce a detailed log file). Default is INFO.
        Parameters:
        logLevel - The maximum log level to display/forward to listeners.
      • valueStoreImpl

        public ValueStore valueStoreImpl()
        Description copied from interface: ValueStore
        Returns the implementation to use for adding ValueStore functionality.
        Specified by:
        valueStoreImpl in interface ValueStore