net.sourceforge.jabm.SimulationExperiment.java Source code

Java tutorial

Introduction

Here is the source code for net.sourceforge.jabm.SimulationExperiment.java

Source

/*
 * JABM - Java Agent-Based Modeling Toolkit
 * Copyright (C) 2013 Steve Phelps
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 */
package net.sourceforge.jabm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import net.sourceforge.jabm.spring.BeanFactorySingleton;
import net.sourceforge.jabm.spring.PropertyOverrideWithReferencesConfigurer;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyOverrideConfigurer;

import cern.jet.random.engine.RandomSeedGenerator;

/**
 * A simulation experiment represents a simulation and a corresponding treatment:
 * that is, a set of parameter bindings represented as Java Properties.
 * 
 * @author Steve Phelps
 *
 */
public class SimulationExperiment implements Runnable {

    /**
     * The SimulationController for conducting this experiment.
     */
    protected SimulationController model;

    /**
     * The properties specified here represent parameter bindings
     * which override those specified in the original model configuration.
     */
    protected Properties properties;

    /**
     * The path name of the directory where report data will be written to.
     */
    protected String directoryName;

    /**
     * The Spring BeanFactory instance which is used to construct the
     * model.
     */
    protected BeanFactory beanFactory;

    protected static RandomSeedGenerator prngSeedGenerator = new RandomSeedGenerator();

    static Logger logger = Logger.getLogger(SimulationExperiment.class);

    public SimulationExperiment(BeanFactory beanFactory, String baseDirName, int experimentNumber,
            Map<String, String> variableBindings, boolean generateSeeds, int seedMask) {
        super();
        logger.info("Initialising experiment " + (experimentNumber + 1) + " ..");
        this.beanFactory = beanFactory;
        properties = new Properties();
        for (String variable : variableBindings.keySet()) {
            properties.put(variable, variableBindings.get(variable));
        }
        logger.info("Using properties: " + properties);

        directoryName = baseDirName + "/experiment" + (experimentNumber + 1) + "/";
        properties.put("fileNamePrefix.value", directoryName);

        if (generateSeeds) {
            int seed = prngSeedGenerator.nextSeed();
            if (seedMask > 0) {
                seed = seed | ((seedMask & 0x0ffff) << 48);
            }
            properties.put("prng.seed", seed + "");
        }

        initialise();
        logger.info("initialisation done.");
    }

    public SimulationExperiment(Properties properties) {
        this.properties = properties;
        this.directoryName = properties.getProperty("fileNamePrefix.value");
        this.beanFactory = BeanFactorySingleton.getBeanFactory();
        initialise();
    }

    /**
     * Initialise the model by constructing it from the bean factory
     * and then applying the parameter bindings specified by the properties
     * attribute using Spring's properties post-processing feature.
     */
    public void initialise() {
        PropertyOverrideConfigurer configurer = new PropertyOverrideWithReferencesConfigurer();
        configurer.setProperties(properties);
        configurer.postProcessBeanFactory((ConfigurableListableBeanFactory) beanFactory);
        this.model = (SimulationController) beanFactory.getBean("simulationController");
    }

    /**
     * Run this experiment.
     */
    public void run() {
        logProperties();
        model.run();
    }

    /**
     * Print a summary of the parameter bindings for this experiment
     * to a log.
     */
    public void logProperties() {
        if (properties != null && properties.size() > 0) {
            logger.info("Using properties " + properties);
        }
    }

    /**
     * Save the parameter bindings of this experiment to a property file.
     * The property file is called 'experiment.properties' and is saved in 
     * the same directory as the report data.
     */
    public void createPropertyFile() {
        File propertyFile = null;
        try {
            File directory = new File(directoryName);
            directory.mkdir();
            propertyFile = new File(directoryName + "experiment.properties");
            if (!propertyFile.exists()) {
                logger.debug("Creating property file " + propertyFile);
                propertyFile.createNewFile();
            }
            FileOutputStream propertyFileOutputStream = new FileOutputStream(propertyFile, false);
            logger.info("Saving properties in " + propertyFile);
            properties.store(propertyFileOutputStream, this.getClass().toString());
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            logger.error(propertyFile.toString() + ": " + e);
            throw new RuntimeException(e);
        }
    }

}