/*
* DynamicalSystem.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.evomodel.epidemiology;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
/**
* @author Trevor Bedford
*/
public class DynamicalSystem {
private List<DynamicalVariable> variables = new ArrayList<DynamicalVariable>();
private List<DynamicalForce> forces = new ArrayList<DynamicalForce>();
private HashMap<String,DynamicalVariable> varMap = new HashMap<String,DynamicalVariable>();
private HashMap<String,DynamicalForce> forceMap = new HashMap<String,DynamicalForce>();
private double currentTime = 0.0;
private double startTime = 0.0;
private double timeStep = 0.0;
private double storedCurrentTime = 0.0;
private double storedStartTime = 0.0;
public static void main(String[] args) {
DynamicalSystem syst = new DynamicalSystem(0, 0.001);
double transmissionRate = 0.027;
double recoveryRate = 0.00054;
syst.addVariable("susceptibles", 330);
syst.addVariable("infecteds", 23325);
syst.addVariable("recovereds", 4524);
syst.addVariable("total", 330 + 23325 + 4524);
syst.addForce("contact", transmissionRate, new String[]{"infecteds","susceptibles"}, new String[]{"total"}, "susceptibles", "infecteds");
syst.addForce("recovery", recoveryRate, new String[]{"infecteds"}, new String[]{}, "infecteds", "recovereds");
// while (syst.getTime() < 400) {
// syst.step();
// }
// syst.print(0,400,1);
double val = syst.getValue("susceptibles", 500);
System.out.println(val);
syst.print(0,500,10);
}
public DynamicalSystem(double t0, double dt) {
startTime = t0;
currentTime = startTime;
timeStep = dt;
}
public double getTime() {
return currentTime;
}
public int size() {
return variables.size();
}
public DynamicalVariable getVar(String n) {
return varMap.get(n);
}
public DynamicalForce getForce(String n) {
return forceMap.get(n);
}
public void resetVar(String n, double v0) {
DynamicalVariable var = getVar(n);
var.reset(startTime, v0);
}
public void resetForce(String n, double c) {
DynamicalForce frc = getForce(n);
frc.reset(c);
}
public void resetTime() {
currentTime = startTime;
}
// copy values to stored state
public void store() {
storedCurrentTime = currentTime;
storedStartTime = startTime;
for (DynamicalVariable var : variables) {
var.store();
}
for (DynamicalForce frc : forces) {
frc.store();
}
}
// copy values from stored state
public void restore() {
currentTime = storedCurrentTime;
startTime = storedStartTime;
for (DynamicalVariable var : variables) {
var.restore();
}
for (DynamicalForce frc : forces) {
frc.restore();
}
}
// get value of indexed variable at time t
// dynamically extend trace
public double getValue(int index, double t) {
while (currentTime < t) {
step();
}
DynamicalVariable var = variables.get(index);
return var.getValue(t);
}
// get value of named variable at time t
// dynamically extend trace
public double getValue(String n, double t) {
while (currentTime < t) {
step();
}
DynamicalVariable var = getVar(n);
return var.getValue(t);
}
// get integral of indexed variable between times start and finish
// dynamically extend trace
public double getIntegral(int index, double start, double finish) {
while (currentTime < finish) {
step();
}
DynamicalVariable var = variables.get(index);
return var.getIntegral(start, finish);
}
// get integral of named variable between times start and finish
// dynamically extend trace
public double getIntegral(String n, double start, double finish) {
while (currentTime < finish) {
step();
}
DynamicalVariable var = getVar(n);
return var.getIntegral(start, finish);
}
// get average of indexed variable between times start and finish
// dynamically extend trace
public double getAverage(int index, double start, double finish) {
while (currentTime < finish) {
step();
}
DynamicalVariable var = variables.get(index);
return var.getAverage(start, finish);
}
// get average of named variable between times start and finish
// dynamically extend trace
public double getAverage(String n, double start, double finish) {
while (currentTime < finish) {
step();
}
DynamicalVariable var = getVar(n);
return var.getAverage(start, finish);
}
public void addVariable(String n, double v0) {
DynamicalVariable var = new DynamicalVariable(n, startTime, v0);
varMap.put(n, var);
variables.add(var);
}
public void addForce(String n, double coeff, String[] mult, String[] div, String increasing, String decreasing) {
DynamicalForce frc = new DynamicalForce(n, coeff, getVar(increasing), getVar(decreasing));
for (String s : mult) {
frc.addMultiplier(getVar(s));
}
for (String s : div) {
frc.addDivisor(getVar(s));
}
forceMap.put(n, frc);
forces.add(frc);
}
public void step() {
for (DynamicalForce frc : forces) {
frc.modCurrentValue(currentTime, timeStep);
}
for (DynamicalVariable var : variables) {
var.modCurrentTime(timeStep);
var.pushCurrentState();
}
currentTime += timeStep;
}
public void print(double start, double finish, double step) {
System.out.print("time");
for (DynamicalVariable var : variables) {
System.out.print("\t" + var.getName());
}
System.out.println();
for (double t=start; t<=finish; t += step) {
System.out.printf("%.3f", t);
for (DynamicalVariable var : variables) {
System.out.printf("\t%.3f", var.getValue(t));
}
System.out.println();
}
}
public String printValues(String n, double start, double finish, double step) {
String out = "";
DynamicalVariable var = getVar(n);
for (double t=start; t<=finish; t += step) {
double v = var.getValue(t);
out += "\t";
out += Double.toString(v);
}
return out;
}
}