Help Converting Math function into Code : Linear Kalman Particle Swarm Optimization - java

I'm trying to convert the math presented on this paper:
http://www.bouncingchairs.net/pskalman-lategecco.pdf
Around page 3 forward into working code. The algorithm itself is given
around page 6, but I don't speak greek or math; so for the time being I'm stuck.
If I understand the code, it should run down like this:
vt = particle velocity, 1d array
vbest = best particle velocity 1d array
v_prime = 1d storage array
v_hat = 1d storage array
alpha = 0.45
sigma = 0.60
denom = float
denom_best = float
Prep:
for(int i = 0; i < vt.length; i++)
{
denom += vt[i] ^ 2
denom_best += vbest[i] ^ 2
}
denom = denom ^ (1/2)
denom_best = denom_best ^ (1/2)
Equation 7:
for(int i = 0; i < vt.length; i++)
{
v_prime[i] = alpha * (vt[i]/denom) + (1 - alpha) * (vbest[i]/denom_best)
}
Equation 8:
for(int i = 0; i < vt.length; i++)
{
v_hat[i] = Rand_Gauss(v_prime[i], sigma) //gaussian random number with
//v_prime[i] average, and sigma StDev
}
Equation 9:
for(int i = 0; i < vt.length; i++)
{
vt[i] = (alpha * denom + (1 - alpha) * denom_best) * v_hat[i]
}
Is this even close to what the math is saying?
Thanks in advance,
-JW

I think you might be missing the calls to "norm(...)". Normalizing a vector is just dividing each component of the vector by the length. In Equation 9, they calculate the weighted sum of the lengths of vt and vbest and multiply that average length by norm(vbar). You're just multiplying it by vbar directly.
The intent behind that equation seems to be to create a new vector v_{t+1} whose length is the average length of vt and vbest. However, vhat could be any length at all, so the multiplication in Equation 9 most of the time won't give you the correct answer unless you force the length of the vhat vector to be exactly one. That's what the vector norm does.
The norm is just the components of the vector divided by the length. So replace your code for equation 9 with something like this:
vtlen=0
for(int i=0; i<vt.length; i++)
{
vtlen+=vt[i]*vt[i];
}
vtlen=sqrt(vtlen);
for(int i=0; i<vt.length; i++)
{
vt[i] = (alpha * denom + (1 - alpha) * denom_best) * (v_hat[i] / vtlen);
}
You've also ignored the norm operation in Equation 7. I haven't read the paper, but it may not be strictly necessary here as the weights sum to one and the vectors are already normalized. I'd have to spend a bit more time to convince myself one way or the other, but it certainly wouldn't hurt to go ahead and normalize that calculated v' vector too.

Related

Estimating pi by throwing darts

Essentially i want to find an estimate of pi by throwing a dart at the unit circle. So I want to throw a dart a the positive x and y quadrant of the unit circle , each dart thrown will give me a random position in the x and y direction that is less that 1. I then need to find the distance from the origin from that point. The approximation of pi will come from when the distance of the dart from the origin is less than 1 when calculated, this will count as a hit, anything else will count as a miss. Using this number pi is found by (#hits/#of tosses)*4 since i will only be looking at 1/4 of the circle .I then want to print a table with different results depending on how many darts are thrown. my code is below, I'm confused on a lot of things, mainly how do I collect all the data and print it all, I was thinking of using an ArrayList of arrays of ints since it will not be limited to the amount of trials I want to do but I am unsure on how to proceed. Any help is useful, thanks!
public static void main(String[]args){
int[] darts_Thrown = {10, 100, 1000, 10000, 100000,1000000};
// for( int i = 0; i < points.length; i++){
// System.out.print(points[i]);
// }
for (int i = 0; i < darts_Thrown.length;i++){
for (int j = 0; j < darts_Thrown[i]; j++){
int test = 0;
double [] points = getPoint();
// distanceToOrigin(points[0],points[1]);
// getHits();
test++;
System.out.printf("%d",test);
}
System.out.printf("%n%s", "hi ");
}
}
public static double[] getPoint()//code to generate x and y and return them in a double array
{
double[] point_X_Y = {Math.random(),Math.random()};
return point_X_Y;
}
public static double distanceToOrigin(double x,double y) //code to compute distance from point (x,y) to origin (0,0)
{
double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2))); // used to find distance from origin
return distance;
}
public static int getHits(int n)
{
int hits = 0;
int misses=0;
//double distance = distanceToOrigin(points[0], points[1]);
//if (distance < 0){
// hits++;
// return hits;
// }
// else{
// misses++;
//return misses;
// }
// return 0;
//code to get hits given n= number of darts
}
}
The formula #hits/#tosses is correct in thought, but it's gotta be too small, since it can't possibly be larger than 1. It turns out that that formula will approximate the value of PI/4, so the approximation of PI is #hits/#tosses*4.
For each trial, it isn't really practical to "collect all the data and print it all", if you want to get a reasonable approximation of PI by the end, because it's going to take a million or so trials to get at all close. I found that 1M trials gives a pretty good result, and 10M often gives you the right result to 4 decimal places. There's no use in printing even a few 100 individual trials, much less 1M of them. So I think all you can really print is the trial number, the number of throws, the number of hits, and the final approximation of PI. Here's code that does that:
public class Test {
public static void main(String[]args){
int[] darts_Thrown = {10, 100, 1000, 10000, 100000, 1000000, 10000000};
for (int i = 0; i < darts_Thrown.length;i++){
int hits = 0;
for (int j = 0; j < darts_Thrown[i]; j++){
double [] points = getPoint();
double distance = distanceToOrigin(points[0],points[1]);
if (distance <= 1.0)
hits++;
}
double pi_est = (double)hits / darts_Thrown[i] * 4.0;
System.out.printf("Trial: %d Throws: %d Hits: %d Approximation of PI (hits/throws*4): %.4f\n",
i, darts_Thrown[i], hits, pi_est);
}
}
public static double[] getPoint()//code to generate x and y and return them in a double array
{
final double[] doubles = {Math.random(), Math.random()};
return doubles;
}
public static double distanceToOrigin(double x,double y) //code to compute distance from point (x,y) to origin (0,0)
{
double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2))); // used to find distance from origin
return distance;
}
}
Result:
Trial: 1 Throws: 10 Hits: 8 Approximation of PI (hits/throws*4): 3.2000
Trial: 2 Throws: 100 Hits: 79 Approximation of PI (hits/throws*4): 3.1600
Trial: 3 Throws: 1000 Hits: 773 Approximation of PI (hits/throws*4): 3.0920
Trial: 4 Throws: 10000 Hits: 7800 Approximation of PI (hits/throws*4): 3.1200
Trial: 5 Throws: 100000 Hits: 78409 Approximation of PI (hits/throws*4): 3.1364
Trial: 6 Throws: 1000000 Hits: 785250 Approximation of PI (hits/throws*4): 3.1410
Trial: 7 Throws: 10000000 Hits: 7852455 Approximation of PI (hits/throws*4): 3.1410
The formula is pretty easy to derive. For a circle with radius 1 centered at the origin, 1/4 of it will be in the quadrant x=0-1, y=0-1. The points inside that circle are 1 unit from the origin or closer, so those are all 'hits'. A 1/4 of a circle of radius 1 has an area of PI * r^2 / 4 = PI * 1^2 / 4 = PI/4. The entire target area is x * y = 1 * 1 = 1. So hits/throws = (PI/4)/(1) = PI/4. Multiply both sides by 4 to get PI = hits/throws * 4.

java StdDraw formula for ratio [duplicate]

How do I map numbers, linearly, between a and b to go between c and d.
That is, I want numbers between 2 and 6 to map to numbers between 10 and 20... but I need the generalized case.
My brain is fried.
If your number X falls between A and B, and you would like Y to fall between C and D, you can apply the following linear transform:
Y = (X-A)/(B-A) * (D-C) + C
That should give you what you want, although your question is a little ambiguous, since you could also map the interval in the reverse direction. Just watch out for division by zero and you should be OK.
Divide to get the ratio between the sizes of the two ranges, then subtract the starting value of your inital range, multiply by the ratio and add the starting value of your second range. In other words,
R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10
This evenly spreads the numbers from the first range in the second range.
It would be nice to have this functionality in the java.lang.Math class, as this is such a widely required function and is available in other languages.
Here is a simple implementation:
final static double EPSILON = 1e-12;
public static double map(double valueCoord1,
double startCoord1, double endCoord1,
double startCoord2, double endCoord2) {
if (Math.abs(endCoord1 - startCoord1) < EPSILON) {
throw new ArithmeticException("/ 0");
}
double offset = startCoord2;
double ratio = (endCoord2 - startCoord2) / (endCoord1 - startCoord1);
return ratio * (valueCoord1 - startCoord1) + offset;
}
I am putting this code here as a reference for future myself and may be it will help someone.
As an aside, this is the same problem as the classic convert celcius to farenheit where you want to map a number range that equates 0 - 100 (C) to 32 - 212 (F).
https://rosettacode.org/wiki/Map_range
[a1, a2] => [b1, b2]
if s in range of [a1, a2]
then t which will be in range of [b1, b2]
t= b1 + ((s- a1) * (b2-b1))/ (a2-a1)
In addition to #PeterAllenWebb answer, if you would like to reverse back the result use the following:
reverseX = (B-A)*(Y-C)/(D-C) + A
Each unit interval on the first range takes up (d-c)/(b-a) "space" on the second range.
Pseudo:
var interval = (d-c)/(b-a)
for n = 0 to (b - a)
print c + n*interval
How you handle the rounding is up to you.
if your range from [a to b] and you want to map it in [c to d] where x is the value you want to map
use this formula (linear mapping)
double R = (d-c)/(b-a)
double y = c+(x*R)+R
return(y)
Where X is the number to map from A-B to C-D, and Y is the result:
Take the linear interpolation formula, lerp(a,b,m)=a+(m*(b-a)), and put C and D in place of a and b to get Y=C+(m*(D-C)). Then, in place of m, put (X-A)/(B-A) to get Y=C+(((X-A)/(B-A))*(D-C)). This is an okay map function, but it can be simplified. Take the (D-C) piece, and put it inside the dividend to get Y=C+(((X-A)*(D-C))/(B-A)). This gives us another piece we can simplify, (X-A)*(D-C), which equates to (X*D)-(X*C)-(A*D)+(A*C). Pop that in, and you get Y=C+(((X*D)-(X*C)-(A*D)+(A*C))/(B-A)). The next thing you need to do is add in the +C bit. To do that, you multiply C by (B-A) to get ((B*C)-(A*C)), and move it into the dividend to get Y=(((X*D)-(X*C)-(A*D)+(A*C)+(B*C)-(A*C))/(B-A)). This is redundant, containing both a +(A*C) and a -(A*C), which cancel each other out. Remove them, and you get a final result of: Y=((X*D)-(X*C)-(A*D)+(B*C))/(B-A)
TL;DR: The standard map function, Y=C+(((X-A)/(B-A))*(D-C)), can be simplified down to Y=((X*D)-(X*C)-(A*D)+(B*C))/(B-A)
int srcMin = 2, srcMax = 6;
int tgtMin = 10, tgtMax = 20;
int nb = srcMax - srcMin;
int range = tgtMax - tgtMin;
float rate = (float) range / (float) nb;
println(srcMin + " > " + tgtMin);
float stepF = tgtMin;
for (int i = 1; i < nb; i++)
{
stepF += rate;
println((srcMin + i) + " > " + (int) (stepF + 0.5) + " (" + stepF + ")");
}
println(srcMax + " > " + tgtMax);
With checks on divide by zero, of course.

Stuck with calculating exponents in Java (Taylor Series) [duplicate]

This question already has answers here:
pow (x,y) in Java
(4 answers)
Closed 6 years ago.
I'm a bit stumped. I'm working on a homework question that requires you to find e^x through a series of 30 iterations: 1 + x + x^2/2! ... x^n/n!. In this case n = 30 and the range for x is -3 through 3. Seems straightforward enough. However when trying to execute it in Java I'm finding that I'm baffled.
The thought was to run two for loops. The outer loop for the iterations of x and the inner loop for the iterations for n. Here is the code so far:
double series = 1.0;
for (int x=-3; x<=3; x++)
{
for (int n=1; n<=x+30; n++)
{
series = series + (x^n)/n;
n*=n;
}
System.out.println(""+ x +"\t "+ (series+1));
}
Any advice would be greatly appreciated.
You might have to pay more attention to every single variable and the value changes inside the loops to better verify your code.
You have done a few mistakes:
multiplied n to itself and then divided by n as well. According to your formula you need to power the number by n, not nFactorial. Moreover nFactorial is a large number to be stored (and get accurate results), better use the advantage of dividing by n and multiplying by x at every step (see below code).
You have also used the XOR operator. Instead use the Math.pow() method.
You need to initialize the series value in each inner loop start.
If you started with initial value of 1, do not need to print (series+1) at end. Better initialize it to 0, or remove +1 in the print.
The following code would solve your purpose better.
double series = 1.0;
double term = 1.0;
for (int x = -3; x <= 3; x++) {
series = 1.0;
term = 1.0;
for (int n = 1; n <= 30; n++) {
term = (term * x / n);
series += term;
}
System.out.println("" + x + "\t " + (series));
}
you can write your formula with MATH.POW like this:
for (int x=-3; x<=3; x++)
{
for (int n=1; n<=x+30; n++)
{
series = series + (Math.pow(x,n)/n);
n*=n;
}
System.out.println(""+ x +"\t "+ (series+1));
}

Most efficient way to compute a polynomial

Polynomial: a0x^0 + a1x^1 +a2x^2 + a3x^3 + ... + anx^n
Array: array_a[] = {a0, a1, a2, a3 ... an};
I wrote a function to calculate this polynomial in Java:
public double cal(double x) {
double y = 0.0;
for (int index = array_a.length - 1; index >= 0; index--) {
y = array_a[index] + y * x;
}
return y;
}
This seems 5 times faster than the loop y += array_a[index] * Math.Pow(x, index);
But I wondering if there is a better way to compute this polynomial?
** For anyone thinks it's a different calculation: I did test the function above. It does the same thing with y += array_a[index] * Math.Pow(x, index); and they compute the same result.
Thanks.
This is Horner's method. If you only want to calculate it once per polynomial, this is the most efficient algorithm:
… Horner's method requires only n additions and n multiplications, and its storage requirements are only n times the number of bits of x. …
Horner's method is optimal, in the sense that any algorithm to evaluate an arbitrary polynomial must use at least as many operations. Alexander Ostrowski proved in 1954 that the number of additions required is minimal. Victor Pan proved in 1966 that the number of multiplications is minimal.
If you need to evaluate the polynomial extremely many times and the degree is very high, then there are methods to transform the representation of the polynomial (preconditioning) so that the number of multiplication is reduced to ⌊n/2⌋ + 2. This seems not very practical though, at least I've never seen this in the wild. I've found an online paper that describes some of the algorithms if you are interested.
Also mentioned in the paper, due to the CPU architecture it might be more efficient if you evaluating even and odd terms separately so they can be placed in parallel pipelines:
public double cal(double x) {
double x2 = x * x;
double y_odd = 0.0, y_even = 0.0;
int index = array_a.length - 1;
if (index % 2 == 0) {
y_even = array_a[index];
index -= 1;
}
for (; index >= 0; index -= 2) {
y_odd = array_a[index] + y_odd * x2;
y_even = array_a[index-1] + y_even * x2;
}
return y_even + y_odd * x;
}
The JIT/compiler might be able to do this conversion for you or even use SIMD to make it very fast automagically. Anyway, for this kind of micro-optimization, always profile before committing to a final solution.

Formula for data that looks like a hockey stick

The following are X and Y values:
X Y
20 10
100 25
140 50
It would be nice if I could approximately represent this data as a formula and plug in any arbitrary value of X from 20 to 140. The data seems to be kind of like a hockey stick curve. Or is it more exponential? I could code this to just create linear segments between those three points but it would be way better if a formula could give me more of a smooth result. The numbers above aren't fixed in stone. They can vary a little. As long as the formula gets me in the ballpark.
You can use the equation of a polynomial or an exponential to approximate that kind of shape, which one you pick sort of depends on what exactly you are trying to do.
If you just need a smooth curve that is close to some shape, then pick a formula and tweak the coefficients until it looks how you want.
A polynomial fit of your data from Excel gives:
Y = 0.0036*(X^2) - 0.25*X + 13.542
Three points uniquely define a second-order polynomial curve, of the form
y = Ax2 + Bx + C
There are widely known formulas to deduce A, B, C from the point coordinates.
One way to do this is by implementing some GROWTH function similar to the one offered by Excel. It will interpolate a new_y value from a new_x value you give it, assuming some exponential growth. Here is a piece of code for it in JavaScript. Translating it to Java should be pretty straightforward.
Note that I borrowed most of it from someone else (credits in the code).
function GROWTH(known_y, known_x, new_x, use_const) {
// Credits: Ilmari Karonen
// Default values for optional parameters:
if (typeof(known_x) == 'undefined') {
known_x = [];
for (var i = 1; i <= known_y.length; i++) known_x.push(i);
}
if (typeof(new_x) == 'undefined') {
new_x = [];
for (var i = 1; i <= known_y.length; i++) new_x.push(i);
}
if (typeof(use_const) == 'undefined') use_const = true;
// Calculate sums over the data:
var n = known_y.length;
var avg_x = 0;
var avg_y = 0;
var avg_xy = 0;
var avg_xx = 0;
for (var i = 0; i < n; i++) {
var x = known_x[i];
var y = Math.log(known_y[i]);
avg_x += x;
avg_y += y;
avg_xy += x*y;
avg_xx += x*x;
}
avg_x /= n;
avg_y /= n;
avg_xy /= n;
avg_xx /= n;
// Compute linear regression coefficients:
if (use_const) {
var beta = (avg_xy - avg_x*avg_y) / (avg_xx - avg_x*avg_x);
var alpha = avg_y - beta*avg_x;
} else {
var beta = avg_xy / avg_xx;
var alpha = 0;
}
// Compute and return result array:
var new_y = [];
for (var i = 0; i < new_x.length; i++) {
new_y.push(Math.exp(alpha + beta * new_x[i]));
}
return new_y;
}
You can statistically fit a curve to a set of points using some form of regression analyzis. However, the validity of your curve depends on the number of points that you have; three points do not give a lot of confidence that your formula is correct.
You can start by assuming a relationship like this:
y = A*exp(B*x)
Taking the natural log of both sides:
ln(y) = ln(A) + B*x
Substitute as many points as you like and solve for the two coefficients. It's a simple linear regression problem.
Here's what I get for your data:
y = exp(2.006369+0.013132*x)
Here's a table of generated values:
X Y
0 7.436267437
20 9.669855877
40 12.5743343
60 16.35121402
80 21.26253316
100 27.6490367
120 35.95381719
140 46.75305634
160 60.7960002
180 79.0569415
200 102.8028156
220 133.6811
240 173.8341152
260 226.0476583
This will work even if you have lots of data.
If you do a Taylor series expansion of the exponential function, you'll see that it's an infinite series of polynomial terms. The quadratic and cubic proposals are truncated approximations to the exponential.

Categories

Resources