/******************************************************************************* * Copyright (c) 2015 QUANTICOL EU Project. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Michele Loreti (University of Firenze) - initial API and implementation *******************************************************************************/ package org.cmg.ml.sam.sim; import java.util.ArrayList; import java.util.LinkedList; import org.apache.commons.math3.random.RandomGenerator; import org.cmg.ml.sam.sim.sampling.SamplingFunction; import org.cmg.ml.sam.sim.sampling.SimulationTimeSeries; import org.cmg.ml.sam.sim.util.WeightedElement; import org.cmg.ml.sam.sim.util.WeightedStructure; /** * @author loreti * */ public class SimulationEnvironment<S extends ModelI> { protected RandomGenerator random; private SimulationFactory<S> factory; private S model; private SamplingFunction<S> sampling_function; private int iterations = 0; public SimulationEnvironment(SimulationFactory<S> factory) { // if (factory == null) { // throw new NullPointerException(); // } this.factory = factory; this.random = new DefaultRandomGenerator(); } public SimulationEnvironment() { this(null); } public void setFactory(SimulationFactory<S> factory) { this.factory = factory; } public void seed(long seed) { random.setSeed(seed); } public void setSampling(SamplingFunction<S> sampling_function) { this.sampling_function = sampling_function; } public synchronized void simulate(SimulationMonitor monitor , int iterations, double deadline) { RandomGeneratorRegistry rgi = RandomGeneratorRegistry.getInstance(); rgi.register(random); for (int i = 0; (((monitor == null)||(!monitor.isCancelled()))&&(i < iterations)) ; i++) { if (monitor != null) { monitor.startIteration( i ); } System.out.print('<'); if ((i + 1) % 50 == 0) { System.out.print(i + 1); } System.out.flush(); doSimulate(factory.getModel(),monitor,deadline); if (monitor != null) { monitor.endSimulation( i ); } System.out.print('>'); if ((i + 1) % 50 == 0) { System.out.print("\n"); } System.out.flush(); this.iterations++; } rgi.unregister(); } public synchronized void simulate(int iterations, double deadline) { simulate( null , iterations , deadline ); } public void simulate( S model , SamplingFunction<S> measure , double deadline) { this.sampling_function = measure; doSimulate(model,null,deadline); } public synchronized double simulate(double deadline) { RandomGeneratorRegistry rgi = RandomGeneratorRegistry.getInstance(); rgi.register(random); double result = doSimulate(deadline); rgi.unregister(); return result; } private double doSimulate(S model, SimulationMonitor monitor , double deadline) { this.model = model; double time = 0.0; if (sampling_function != null) { sampling_function.start(); sampling_function.sample(time, model); } while (((monitor == null)||(!monitor.isCancelled()))&&(time < deadline)) { double dt = doAStep(); if (dt <= 0) { if (sampling_function != null) { sampling_function.end(time); } return time; } time += dt; this.model.timeStep(dt); if (monitor != null && !monitor.isCancelled()) { monitor.update(time); } if (sampling_function != null) { sampling_function.sample(time, model); } } if (sampling_function != null) { sampling_function.end(time); } return time; } private double doSimulate(double deadline) { return doSimulate(factory.getModel(),null,deadline); } private double doAStep() { WeightedStructure<Activity> agents = this.model.getActivities( random ); double totalRate = agents.getTotalWeight(); if (totalRate == 0.0) { return 0.0; } double dt = (1.0 / totalRate) * Math.log(1 / (random.nextDouble())); double select = random.nextDouble() * totalRate; WeightedElement<Activity> wa = agents.select(select); if (wa == null) { return 0.0; } wa.getElement().execute(random); return dt; } public double nextDouble() { return random.nextDouble(); } public int nextInt(int zones) { return random.nextInt(zones); } public LinkedList<SimulationTimeSeries> getTimeSeries( ) { if (sampling_function == null) { return null; } return sampling_function.getSimulationTimeSeries( iterations ); } }