/* * 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); } } }