I'm attempting to make a simulation of the SEIR epidemic model.
It contains four parts:
Susceptibles (non-infected)
Exposed (infected but not infectious yet)
Infectious (infected and infectious)
Removed (recovered/dead)
where gamma γ is the infection rate and beta β is the reovery/death rate.
I've previously used the SIR model, a more basic model where E and I are combined, which uses these equations:
From another thread I've used a solution to simulate SIR using this code:
double dS = (beta * S.get(day) * I.get(day) / N);
double newS = (S.get(day) - dS);
double newI = (I.get(day) + dS - gamma * I.get(day));
double newR = (R.get(day) + gamma * I.get(day));
This works fine using the Euler's method. However, I've tried to manipulate this to try and fit the SEIR model (which has these equations:)
where u is the death rate, delta is the birth rate and a is the incubation period. I've made an attempt to try and use a similar method to work for SEIR but I'm unsuccessful to simulate it well at all. This isn't really a problem with the variables but as a whole differentiating these complex equations. Wondering if anyone could help, thanks.
Really should've realised this earlier but from messing around with random sign changes, worked out that everything apart from 'newS' requires getting the previous day's number and plussing the new dS, rather than minusing it. My SIR code already did this. Don't really know how I missed this..
New working code:
int totalDays = 160; // How many days/times to loop
int N = 1000; // Population
int I0 = 1; // Starting infected/exposed
double beta = 0.2; // Infection rate
double gamma = 1.0/10.0; // recovery time (days to the -1)
double a = 1.0/2.0; // incubation period (days to the -1)
List<Double> S = new ArrayList<>();
List<Double> E = new ArrayList<>();
List<Double> I = new ArrayList<>();
List<Double> R = new ArrayList<>();
private void createData() {
final int R0 = 0;
final int S0 = N - E0 - R0;
S.add((double) S0);
E.add((double) I0);
I.add(0.0);
R.add(0.0);
for (int day = 1; day < totalDays + 1; day++) {
double[] derivative = deriv(day);
S.add(derivative[0]);
E.add(derivative[1]);
I.add(derivative[2]);
R.add(derivative[3]);
}
}
private double[] deriv(int day) {
day = day - 1;
double dS = (beta * S.get(day) * I.get(day)) / N;
double newS = S.get(day) - (dS);
double newE = E.get(day) + (dS - (a * E.get(day)));
double newI = I.get(day) + ((a * E.get(day)) - (gamma * I.get(day)));
double newR = R.get(day) + (gamma * I.get(day));
return new double[] {newS, newE, newI, newR};
}
Related
I am busy making a basic neural network in java with three inputs, one hidden layer with two hidden neurons and one output neuron.I have previously made a smaller one with three inputs and one output but no hidden layers, where I used some basic calculus for the back propagation and the cost was calculated using the formula (prediction-target)^2. Both of these NNs do not use an activation function like sigmoid as they predict a value, not a binary output.
My problem comes in when I try to train my bigger NN with a hidden layer. The basic calculus method I used for my first one does not work.
Could anyone help me by telling me how to train the NN with the hidden layer? (the Mathematical formula)
This video on YouTube should be a good resource to start with! If you're just interested in the mathematical formula, you can skip to the end of the second part. I recommend watching both videos if you want to know how the weights are updated. Using this video, I developed following algorithm:
public void applyBackpropagation(double expectedOutput[]){
for (int i = 0; i < expectedOutput.length; i++) {
double d = expectedOutput[i];
if (d < 0 || d > 1) {
if (d < 0)
expectedOutput[i] = 0 + epsilon;
else
expectedOutput[i] = 1 - epsilon;
}
}
int i = 0;
for(Neuron n : outputLayer){
ArrayList<Connection> connections = n.getAllInConnections();
double Ok = n.getOutput();
double tk = expectedOutput[i];
double dk = Ok*(1-Ok)*(Ok - tk);
for(Connection c : connections){
double dw = -learningRate * dk * c.leftNeuron.getOutput();
c.setWeight(c.getWeight() + dw);
}
i++;
}
for(Neuron n : hiddenLayer){
ArrayList<Connection> connections = n.getAllInConnections();
double Oj = n.getOutput();
double sum = 0;
i = 0;
for(Neuron out_n : outputLayer){
double out_ok = out_n.getOutput();
double out_tk = expectedOutput[i];
double out_dk = out_ok*(1-out_ok)*(out_ok - out_tk);
double wjk = getWeightByNeurons(n, out_n);
sum += out_dk * wjk;
i++;
}
double dj = Oj*(1-Oj)*sum;
for(Connection c : connections){
double dw = -learningRate * dj * c.getFromNeuron().getOutput();
c.setWeight(c.getWeight() + dw);
}
}
}
The activation function used was sigmoid.
I am currently building an Android app that has a calculator that not only shows the result, but also shows how it reached that result?
Is there any library or any way that I could show a step by step computation for the result of the code below?
int a = 5;
int b = 6
int c = 7;
int d = 8;
int result = a + (b * c) / d;
edit: By the way, it's a calculator for physics so I have lots of formulas. I'm using exp4j to parse a string formula as an expression. Here's a sample
//For formula velocity = (finalVelocity - initialVelocity) / time
String formula1 = "(finalVelocity - initialVelocity) / time";
Double result1 = new ExpressionBuilder(formula)
.variables("finalVelocity", "initialVelocity", "time")
.build()
.setVariable("finalVelocity", 4);
.setVariable("initialVelocity", 2);
.setVariable("time", 2)
.evaluate();
//Sample Output
//velocity = (4 - 2) / 2
//velocity = 2 /2
//velocity = 1
//For formula finalVelocity = (velocity * time) + initialVelocity
String formula2 = "(velocity * time) + initialVelocity";
Double result12 = new ExpressionBuilder(formula)
.variables("velocity", "time" "initialVelocity")
.build()
.setVariable("velocity", 4);
.setVariable("time", 2)
.setVariable("initialVelocity", 0)
.evaluate();
//Sample Output
//finalVelocity = (4 * 2) + 0
//finalVelocity = 8 + 0
//finalVelocity = 8
With many formulas, I'm trying to eliminate printing each step per formula. I'm trying to find a way to have a function that would print the steps for any formula.
Considering you will be using BODMAS to solve that problem, you could consider simply printing each step:
int a = 5;
int b = 6;
int c = 7;
int d = 8;
int ans = (b * c);
System.out.println(ans)
ans /= d;
System.out.println(ans)
ans += a;
System.out.println(ans)
To do this, you can build a function which searches for brackets first and solves the equations in the according to BODMAS(Brackets first, then Division, then Multiplication, then Addition, and finally Subtraction).
Considering you take the equation as a string, you first search for (), then solve / and print answers followed by *, + and -.
I am trying to write a simple band pass filter following the instructions in this book. My code creates a blackman window, and combines two low pass filter kernels to create a band pass filter kernel using spectral inversion, as described in the second example here (table 16-2).
I am testing my code by comparing it with the results I get in matlab. When I test the methods that create a blackman window and a low pass filter kernel separately, I get results that are close to what I see in matlab (up to some digits after the decimal point - I attribute the error to java double variables rounding issues), but my band pass filter kernel is incorrect.
Tests I ran:
Created a blackman window and compared it with what I get in matlab - all good.
Created a low pass filter using this window using my code and fir1(N, Fc1/(Fs/2), win, flag); in matlab (see full code below). I think the results are correct, although I get bigger error the bigger Fc1 is (why?)
Created a pand pass filter using my code and fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag); in matlab - results are completely off.
Filtered my data using my code and the kernel generated by matlab - all good.
So - why is my band pass filter kernel off? What did I do wrong?
I think I either have a bug or fir1 uses a different algorithm, but I can't check because the article referenced in its documentation is not publicly available.
This is my matlab code:
Fs = 200; % Sampling Frequency
N = 10; % Order
Fc1 = 1.5; % First Cutoff Frequency
Fc2 = 7.5; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
% Create the window vector for the design algorithm.
win = blackman(N+1);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
res = filter(Hd, data);
This is my java code (I believe the bug is in bandPassKernel):
/**
* See - http://www.mathworks.com/help/signal/ref/blackman.html
* #param length
* #return
*/
private static double[] blackmanWindow(int length) {
double[] window = new double[length];
double factor = Math.PI / (length - 1);
for (int i = 0; i < window.length; ++i) {
window[i] = 0.42d - (0.5d * Math.cos(2 * factor * i)) + (0.08d * Math.cos(4 * factor * i));
}
return window;
}
private static double[] lowPassKernel(int length, double cutoffFreq, double[] window) {
double[] ker = new double[length + 1];
double factor = Math.PI * cutoffFreq * 2;
double sum = 0;
for (int i = 0; i < ker.length; i++) {
double d = i - length/2;
if (d == 0) ker[i] = factor;
else ker[i] = Math.sin(factor * d) / d;
ker[i] *= window[i];
sum += ker[i];
}
// Normalize the kernel
for (int i = 0; i < ker.length; ++i) {
ker[i] /= sum;
}
return ker;
}
private static double[] bandPassKernel(int length, double lowFreq, double highFreq) {
double[] ker = new double[length + 1];
double[] window = blackmanWindow(length + 1);
// Create a band reject filter kernel using a high pass and a low pass filter kernel
double[] lowPass = lowPassKernel(length, lowFreq, window);
// Create a high pass kernel for the high frequency
// by inverting a low pass kernel
double[] highPass = lowPassKernel(length, highFreq, window);
for (int i = 0; i < highPass.length; ++i) highPass[i] = -highPass[i];
highPass[length / 2] += 1;
// Combine the filters and invert to create a bandpass filter kernel
for (int i = 0; i < ker.length; ++i) ker[i] = -(lowPass[i] + highPass[i]);
ker[length / 2] += 1;
return ker;
}
private static double[] filter(double[] signal, double[] kernel) {
double[] res = new double[signal.length];
for (int r = 0; r < res.length; ++r) {
int M = Math.min(kernel.length, r + 1);
for (int k = 0; k < M; ++k) {
res[r] += kernel[k] * signal[r - k];
}
}
return res;
}
And this is how I use my code:
double[] kernel = bandPassKernel(10, 1.5d / (200/2), 7.5d / (200/2));
double[] res = filter(data, kernel);
I ended up implementing Matlab's fir1 function in Java. My results are quite accurate.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
I am working with android project.I need FFT algorithm to process the android accelerometer data.Is there FFT library available in android sdk?
You can use this class, which is fast enough for real time audio analysis
public class FFT {
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
public FFT(int n) {
this.n = n;
this.m = (int) (Math.log(n) / Math.log(2));
// Make sure n is a power of 2
if (n != (1 << m))
throw new RuntimeException("FFT length must be power of 2");
// precompute tables
cos = new double[n / 2];
sin = new double[n / 2];
for (int i = 0; i < n / 2; i++) {
cos[i] = Math.cos(-2 * Math.PI * i / n);
sin[i] = Math.sin(-2 * Math.PI * i / n);
}
}
public void fft(double[] x, double[] y) {
int i, j, k, n1, n2, a;
double c, s, t1, t2;
// Bit-reverse
j = 0;
n2 = n / 2;
for (i = 1; i < n - 1; i++) {
n1 = n2;
while (j >= n1) {
j = j - n1;
n1 = n1 / 2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i = 0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j = 0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m - i - 1);
for (k = j; k < n; k = k + n2) {
t1 = c * x[k + n1] - s * y[k + n1];
t2 = s * x[k + n1] + c * y[k + n1];
x[k + n1] = x[k] - t1;
y[k + n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
}
}
Warning: this code appears to be derived from here, and has a GPLv2 license.
Using the class at: https://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8java-source.html
Short explanation: call fft() providing x as you amplitude data, y as all-zeros array, after the function returns your first answer will be a[0]=x[0]^2+y[0]^2.
Complete explanation: FFT is complex transform, it takes N complex numbers and produces N complex numbers. So x[0] is the real part of the first number, y[0] is the complex part. This function computes in-place, so when the function returns x and y will have the real and complex parts of the transform.
One typical usage is to calculate the power spectrum of audio. Your audio samples only have real part, you your complex part is 0. To calculate the power spectrum you add the square of the real and complex parts P[0]=x[0]^2+y[0]^2.
Also it's important to notice that the Fourier transform, when applied over real numbers, result in symmetrical result (x[0]==x[x.lenth-1]). The data at x[x.length/2] have the data from frequency f=0Hz. x[0]==x[x.length-1] has the data for a frequency equals to have the sampling rate (eg if you sampling was 44000Hz than it means f[0] refeers to 22kHz).
Full procedure:
create array p[n] with 512 samples with zeros
Collect 1024 audio samples, write them on x
Set y[n]=0 for all n
calculate fft(x,y)
calculate p[n]+=x[n+512]^2+y[n+512]^2 for all n=0 to 512
to go 2 to take another batch (after 50 batches go to next step)
plot p
go to 1
Than adjust the fixed number for your taste.
The number 512 defines the sampling window, I won't explain it. Just avoid reducing it too much.
The number 1024 must be always the double of the last number.
The number 50 defines you update rate. If your sampling rate is 44000 samples per second you update rate will be: R=44000/1024/50 = 0.85 seconds.
kissfft is a decent enough library that compiles on android. It has a more versatile license than FFTW (even though FFTW is admittedly better).
You can find an android binding for kissfft in libgdx https://github.com/libgdx/libgdx/blob/0.9.9/extensions/gdx-audio/src/com/badlogic/gdx/audio/analysis/KissFFT.java
Or if you would like a pure Java based solution try jTransforms
https://sites.google.com/site/piotrwendykier/software/jtransforms
Use this class (the one that EricLarch's answer is derived from).
Usage Notes
This function replaces your inputs arrays with the FFT output.
Input
N = the number of data points (the size of your input array, must be a power of 2)
X = the real part of your data to be transformed
Y = the imaginary part of the data to be transformed
i.e. if your input is
(1+8i, 2+3j, 7-i, -10-3i)
N = 4
X = (1, 2, 7, -10)
Y = (8, 3, -1, -3)
Output
X = the real part of the FFT output
Y = the imaginary part of the FFT output
To get your classic FFT graph, you will want to calculate the magnitude of the real and imaginary parts.
Something like:
public double[] fftCalculator(double[] re, double[] im) {
if (re.length != im.length) return null;
FFT fft = new FFT(re.length);
fft.fft(re, im);
double[] fftMag = new double[re.length];
for (int i = 0; i < re.length; i++) {
fftMag[i] = Math.pow(re[i], 2) + Math.pow(im[i], 2);
}
return fftMag;
}
Also see this StackOverflow answer for how to get frequencies if your original input was magnitude vs. time.
Yes, there is the JTransforms that is maintained on github here and avaiable as a Maven plugin here.
Use with:
compile group: 'com.github.wendykierp', name: 'JTransforms', version: '3.1'
But with more recent, Gradle versions you need to use something like:
dependencies {
...
implementation 'com.github.wendykierp:JTransforms:3.1'
}
#J Wang
Your output magnitude seems better than the answer given on the thread you have linked however that is still magnitude squared ... the magnitude of a complex number
z = a + ib
is calculated as
|z|=sqrt(a^2+b^2)
the answer in the linked thread suggests that for pure real inputs the outputs
should be using a2 or a for the output because the values for
a_(i+N/2) = -a_(i),
with b_(i) = a_(i+N/2) meaning the complex part in their table is in the second
half of the output table.
i.e the second half of the output table for an input table of reals is the conjugate of the real ...
so z = a-ia giving a magnitude
|z|=sqrt(2a^2) = sqrt(2)a
so it is worth noting the scaling factors ...
I would recommend looking all this up in a book or on wiki to be sure.
Unfortunately the top answer only works for Array that its size is a power of 2, which is very limiting.
I used the Jtransforms library and it works perfectly, you can compare it to the function used by Matlab.
here is my code with comments referencing how matlab transforms any signal and gets the frequency amplitudes (https://la.mathworks.com/help/matlab/ref/fft.html)
first, add the following in the build.gradle (app)
implementation 'com.github.wendykierp:JTransforms:3.1'
and here it is the code for for transforming a simple sine wave, works like a charm
double Fs = 8000;
double T = 1/Fs;
int L = 1600;
double freq = 338;
double sinValue_re_im[] = new double[L*2]; // because FFT takes an array where its positions alternate between real and imaginary
for( int i = 0; i < L; i++)
{
sinValue_re_im[2*i] = Math.sin( 2*Math.PI*freq*(i * T) ); // real part
sinValue_re_im[2*i+1] = 0; //imaginary part
}
// matlab
// tf = fft(y1);
DoubleFFT_1D fft = new DoubleFFT_1D(L);
fft.complexForward(sinValue_re_im);
double[] tf = sinValue_re_im.clone();
// matlab
// P2 = abs(tf/L);
double[] P2 = new double[L];
for(int i=0; i<L; i++){
double re = tf[2*i]/L;
double im = tf[2*i+1]/L;
P2[i] = sqrt(re*re+im*im);
}
// P1 = P2(1:L/2+1);
double[] P1 = new double[L/2]; // single-sided: the second half of P2 has the same values as the first half
System.arraycopy(P2, 0, P1, 0, L/2);
// P1(2:end-1) = 2*P1(2:end-1);
System.arraycopy(P1, 1, P1, 1, L/2-2);
for(int i=1; i<P1.length-1; i++){
P1[i] = 2*P1[i];
}
// f = Fs*(0:(L/2))/L;
double[] f = new double[L/2 + 1];
for(int i=0; i<L/2+1;i++){
f[i] = Fs*((double) i)/L;
}
I am trying to create a simple simulation program of SIR-epidemics model in java.
Basically, SIR is defined by a system of three differential equations:
S'(t) = - l(t) * S(t)
I'(t) = l(t) * S(t) - g(t) * I(t)
R'(t) = g(t) * I(t)
S - susceptible people, I - infected people, R - recovered people.
l(t) = [c * x * I(t)] / N(T)
c - number of contacts, x - infectiveness (probability to get sick after contact with sick person), N(t) - total population (which is constant).
How can I solve such differential equations in Java? I don't think I know any useful way to do that, so my implementation produces rubbish.
public class Main {
public static void main(String[] args) {
int tppl = 100;
double sppl = 1;
double hppl = 99;
double rppl = 0;
int numContacts = 50;
double infectiveness = 0.5;
double lamda = 0;
double duration = 0.5;
double gamma = 1 / duration;
for (int i = 0; i < 40; i++) {
lamda = (numContacts * infectiveness * sppl) / tppl;
hppl = hppl - lamda * hppl;
sppl = sppl + lamda * hppl - gamma * sppl;
rppl = rppl + gamma * sppl;
System.out.println (i + " " + tppl + " " + hppl + " " + sppl + " " + rppl);
}
}
}
I would greatly appreciate any help, many thanks in advance!
Time-series differential equations can be simulated numerically by taking dt = a small number, and using one of several numerical integration techniques e.g. Euler's method, or Runge-Kutta. Euler's method may be primitive but it works OK for some equations and it's simple enough that you might give it a try. e.g.:
S'(t) = - l(t) * S(t)
I'(t) = l(t) * S(t) - g(t) * I(t)
R'(t) = g(t) * I(t)
int N = 100;
double[] S = new double[N+1];
double[] I = new double[N+1];
double[] R = new double[N+1];
S[0] = /* initial value */
I[0] = /* initial value */
R[0] = /* initial value */
double dt = total_time / N;
for (int i = 0; i < 100; ++i)
{
double t = i*dt;
double l = /* compute l here */
double g = /* compute g here */
/* calculate derivatives */
double dSdt = - I[i] * S[i];
double dIdt = I[i] * S[i] - g * I[i];
double dRdt = g * I[i];
/* now integrate using Euler */
S[i+1] = S[i] + dSdt * dt;
I[i+1] = I[i] + dIdt * dt;
R[i+1] = R[i] + dRdt * dt;
}
The tough part is figuring out how many steps to use. You should read one of the articles I have linked to. More sophisticated differential equation solvers use variable step sizes that adapt to accuracy/stability for each step.
I would actually recommend using numerical software like R or Mathematica or MATLAB or Octave, as they include ODE solvers and you wouldn't need to go to all the trouble yourself. But if you need to do this as part of a larger Java application, at least try it out first with math software, then get a sense of what the step sizes are and what solvers work.
Good luck!