I've built a model of the solar system in Java. In order to determine the position of a planet it does do a whole lot of computations which give a very exact value. However I am often satisfied with the approximate position, if that could make it go faster. Because I'm using it in a simulation speed is important, as the position of the planet will be requested millions of times.
Currently I try to cache the position of a planet throughout its orbit and then use those coordinates over and over. If a position in between two values is requested I perform a linear interpolation. This is how I store values:
for(int t=0; t<tp; t++) {
listCoordinates[t]=super.coordinates(ti+t);
}
interpolator = new PlanetOrbit(listCoordinates,tp);
PlanetOrbit has the interpolation code:
package cometsim;
import org.apache.commons.math3.util.FastMath;
public class PlanetOrbit {
final double[][] coordinates;
double tp;
public PlanetOrbit(double[][] coordinates, double tp) {
this.coordinates = coordinates;
this.tp = tp;
}
public double[] coordinates(double julian) {
double T = julian % FastMath.floor(tp);
if(coordinates.length == 1 || coordinates.length == 0) return coordinates[0];
if(FastMath.round(T) == T) return coordinates[(int) T];
int floor = (int) FastMath.floor(T);
if(floor>=coordinates.length) floor=coordinates.length-5;
double[] f = coordinates[floor];
double[] c = coordinates[floor+1];
double[] retval = f;
retval[0] += (T-FastMath.floor(T))*(c[0]-f[0]);
retval[1] += (T-FastMath.floor(T))*(c[1]-f[1]);
retval[2] += (T-FastMath.floor(T))*(c[2]-f[2]);
return retval;
}
}
You can think of FastMath as Math but faster. However, this code is not much of a speed improvement over calculating the exact value every time. Do you have any ideas for how to make it faster?
There are a few issues I can see, the main ones I can see are as follows
PlanetOrbit#coordinates seems to actually change the values in the variable coordinates. As this method is supposed to only interpolate I expect that your orbit will actually corrupt slightly everytime you run though it (because it is a linear interpolation the orbit will actually degrade towards its centre).
You do the same thing several times, most clearly T-FastMath.floor(T) occures 3 seperate times in the code.
Not a question of efficiency or accuracy but the variable and method names are very opaque, use real words for variable names.
My proposed method would be as follows
public double[] getInterpolatedCoordinates(double julian){ //julian calendar? This variable name needs to be something else, like day, or time, or whatever it actually means
int startIndex=(int)julian;
int endIndex=(startIndex+1>=coordinates.length?1:startIndex+1); //wrap around
double nonIntegerPortion=julian-startIndex;
double[] start = coordinates[startIndex];
double[] end = coordinates[endIndex];
double[] returnPosition= new double[3];
for(int i=0;i< start.length;i++){
returnPosition[i]=start[i]*(1-nonIntegerPortion)+end[i]*nonIntegerPortion;
}
return returnPosition;
}
This avoids corrupting the coordinates array and avoids repeating the same floor several times (1-nonIntegerPortion is still done several times and could be removed if needs be but I expect profiling will show it isn't significant). However, it does create a new double[] each time which may be inefficient if you only need the array temporarily. This can be corrected using a store object (an object you used previously but no longer need, usually from the previous loop)
public double[] getInterpolatedCoordinates(double julian, double[] store){
int startIndex=(int)julian;
int endIndex=(startIndex+1>=coordinates.length?1:startIndex+1); //wrap around
double nonIntegerPortion=julian-startIndex;
double[] start = coordinates[startIndex];
double[] end = coordinates[endIndex];
double[] returnPosition= store;
for(int i=0;i< start.length;i++){
returnPosition[i]=start[i]*(1-nonIntegerPortion)+end[i]*nonIntegerPortion;
}
return returnPosition; //store is returned
}
Related
I have an amount of ranges, each with a weight. Every point on the total range is scored by the sum of the weights of all the ranges the point falls into. I'd like to be able to cheaply find the total value of points, and would like to be able to find a maximum. Ideally, it would also be able to find the maximum for a set of (equidistantly) spaced points.
Unfortunately, I'm heavily limited by performance, and am struggling to find a good algorithm for this.
The only two decent solutions I could find are:
- Bruteforce it by sampling a bunch of points. For each: check every range whether it fits, find the total value, then check if it's better than the best so far. Decent point samples can be found by taking the boundaries of the ranges.
- Create a set of buckets. Iterate through all the ranges, adding a value to all the buckets that fit within the range. Then iterate through all the buckets to find the best one
Neither are fast enough for my liking (they have been tested), and the latter isn't continuous so has accuracy problems.
I'd be okay with getting a slightly inaccurate response as long as the performance is way better.
What adds a bit of extra complexity to my particular case is that I'm actually dealing with angles, so the environment is modular. The ranges can't be ordered, and I need to ensure that a range going from 340 degrees to 20 degrees contains both a point at 350 and at 10 degrees.
The angle-ranges I'm dealing with can't exceed 180 beyond degrees and only very rarely are above 90.
The amount of ranges generally isn't very high (1-30), but I need to do this calculation a lot.
The language is Java if it matters.
Make a list (array) of angle intervals. If interval finish value less than start value (20<340), add 360 to the finish (340, 380)
Make a list of pair (angle, +weight for start point or -weight for finish point).
Concatenate list with its copy to provide circular intersection. (It is possible to copy only part of list)
Sort them by angle (use +/- as secondary key in case of tie: - before +)
Make CurrWeight=0
Walk through the list, adding +/weight field to CurrWeight. Check for max value.
(Such approach works for linear lists, I tried to modify it for circular ones, perhaps I might miss some caveats)
here, instead of the term 'edges', i should have better used the term 'boundaries', because it referes to interval boundaries
import java.util.ArrayList;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
public class Main {
ArrayList<Interval> intervals;
public static void main(String args[]) {
Main main = new Main();
main.intervals = new ArrayList<Interval>();
Interval i1 = new Interval(10, 30, 1);
Interval i2= new Interval(20, 40, 1);
Interval i3= new Interval(50, 60, 1);
Interval i4= new Interval(0, 70, 1);
main.intervals.add(i1);
main.intervals.add(i2);
main.intervals.add(i3);
main.intervals.add(i4);
Interval winningInterval = main.processIntervals(main.intervals);
System.out.println("winning interval="+winningInterval);
}
public Interval processIntervals(ArrayList<Interval> intervals)
{
SortedSet<Integer> intervalEdges = new TreeSet<Integer>();
for(int i = 0;i<intervals.size();i++)
{
Interval currentInterval = intervals.get(i);
intervalEdges.add(currentInterval.a);
intervalEdges.add(currentInterval.b);
}
System.out.println(intervalEdges);
//edges stores the same data as intervalEdges, but for convenience, it is a list
ArrayList<Integer> edges = new ArrayList<Integer>(intervalEdges);
ArrayList<Interval> intersectionIntervals = new ArrayList<Interval>();
for(int i=0; i<edges.size()-1;i++)
{
Interval newInterval = new Interval(edges.get(i), edges.get(i+1), 0);
int score = 0; //the sum of the values of the overlapping intervals
for(int j=0; j<intervals.size();j++)
{
if(newInterval.isIncludedInInterval(intervals.get(j)))
score = score+ intervals.get(j).val;
}
newInterval.val = score;
intersectionIntervals.add(newInterval);
}
System.out.println(intersectionIntervals);
int maxValue=0; //the maximum value of an interval
Interval x = new Interval(-1,-1,0);//that interval with the maximum value
for(int i=0; i<intersectionIntervals.size();i++)
{
if(intersectionIntervals.get(i).val > maxValue)
{
maxValue=intersectionIntervals.get(i).val;
x=intersectionIntervals.get(i);
}
}
return x;
}
}
class Interval
{
public int a, b, val;
public Interval(int a, int b, int val) {
super();
this.a = a;
this.b = b;
this.val = val;
}
#Override
public String toString() {
return "Interval [a=" + a + ", b=" + b + ", val=" + val + "]";
}
boolean isIncludedInInterval(Interval y)
{
//returns true if current interval is included in interval y
return this.a>=y.a && this.b<= y.b;
}
}
gives the output
[0, 10, 20, 30, 40, 50, 60, 70]
[Interval [a=0, b=10, val=1], Interval [a=10, b=20, val=2], Interval [a=20, b=30, val=3], Interval [a=30, b=40, val=2], Interval [a=40, b=50, val=1], Interval [a=50, b=60, val=2], Interval [a=60, b=70, val=1]]
winning interval=Interval [a=20, b=30, val=3]
This solves the case when the intervals are straight line intervals, and not angular intervals. I will come back with modifications to take into account the fact that x=x+360.
I've created a class that attempts to create an average image from any number of images (passed one by one).
This process will run in it's own thread, while other threads read in images, do processing, and pass the output to this average object.
Unfortunately, the averaged image gets brighter, and brighter, with each additional image.
I suspect that there is an error in my averaging function, but I have been unable to find it.
Edit: I was missing the "curImg/curCount" part of the equation. With this correction, the images now get dark. I am not left with a good average.
Edit 2: I see that I was down voted. Is there something I could do to improve this question?
class AverageImage {
private Vector<Mat> average = new Vector<>();
private int count = 0;
public void add(Mat img) {
count++;
Vector<Mat> splitImg = new Vector<>();
Mat convertedImg = img.clone();
convertedImg.convertTo(convertedImg, CvType.CV_32FC1);
Core.split(img.clone(), splitImg);
if (average.isEmpty()) {
average = splitImg;
} else {
// prevAverage * (prevCount/curCount) + curImg/curCount
for (int i = 0; i < average.size(); i++) {
Core.multiply(average.get(i), new Scalar((count - 1) / ((double) count)), average.get(i));
Mat temp = new Mat();
Core.divide(count, splitImg.get(i), temp);
Core.add(average.get(i), temp, average.get(i));
}
}
}
public Mat getAverage() {
Mat convertedAverage = new Mat();
Core.merge(average, convertedAverage);
convertedAverage.convertTo(convertedAverage.clone(), CvType.CV_8UC3);
return convertedAverage;
}
}
Minor comment: convertedImg is not being used at all in your code. You can remove it.
Your determination of what is known as the cumulative mean is correct. However, the part that is really messing with you is the divide statement:
Core.divide(count, splitImg.get(i), temp);
By consulting the OpenCV documentation, when you call the variant which the first element is a scalar, the operation that is being done is:
dst(I) = saturate(scale / src(I))
scale is used to divide into the output. Therefore, what you are doing is count / splitImg.get(i) when you should actually be doing splitImg.get(i) / count. With this in mind, divide does not support taking an image and dividing by a coefficient. However, a workaround is to use Core.multiply with the inverse of count:
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);
All you need to do is change the Core.divide statement to the one above and it should work out.
// prevAverage * (prevCount/curCount) + curImg/curCount
for (int i = 0; i < average.size(); i++) {
Core.multiply(average.get(i), new Scalar((count - 1) / ((double) count)), average.get(i));
Mat temp = new Mat();
// Core.divide(count, splitImg.get(i), temp);
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);
Core.add(average.get(i), temp, average.get(i));
}
To verify that this is correct, here's the math I wrote out for this in LaTeX. Given a signal of N values which we call x, we can calculate the mean with the first line of the equation. x_i denotes the ith value of the signal x. The second line and onwards is what would happen if we added an additional term to the mean. If you work out the math, we verify that your equation in your code is correct... but you simply need to correct the Core.divide statement:
The left most term in the second equation is what you have in your first line of code in the loop which is correct:
Core.multiply(average.get(i), new Scalar((count - 1) / ((double) count)), average.get(i));
Finally to compute the second term of this equation, we do:
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);
For numerical stability it's probably best to just store the accumulated sum image and divide that by the current N when you need the avg.
Just take care that you don't overflow.
I have a basic framework for a neural network to recognize numeric digits, but I'm having some problems with training it. My back-propogation works for small data sets, but when I have more than 50 data points, the return value starts converging to 0. And when I have data sets in the thousands, I get NaN's for costs and returns.
Basic structure: 3 layers: 784 : 15 : 1
784 is the number of pixels per data set, 15 neurons in my hidden layer, and one output neuron which returns a value from 0 to 1 (when you multiply by 10 you get a digit).
public class NetworkManager {
int inputSize;
int hiddenSize;
int outputSize;
public Matrix W1;
public Matrix W2;
public NetworkManager(int input, int hidden, int output) {
inputSize = input;
hiddenSize = hidden;
outputSize = output;
W1 = new Matrix(inputSize, hiddenSize);
W2 = new Matrix(hiddenSize, output);
}
Matrix z2, z3;
Matrix a2;
public Matrix forward(Matrix X) {
z2 = X.dot(W1);
a2 = sigmoid(z2);
z3 = a2.dot(W2);
Matrix yHat = sigmoid(z3);
return yHat;
}
public double costFunction(Matrix X, Matrix y) {
Matrix yHat = forward(X);
Matrix cost = yHat.sub(y);
cost = cost.mult(cost);
double returnValue = 0;
int i = 0;
while (i < cost.m.length) {
returnValue += cost.m[i][0];
i++;
}
return returnValue;
}
Matrix yHat;
public Matrix[] costFunctionPrime(Matrix X, Matrix y) {
yHat = forward(X);
Matrix delta3 = (yHat.sub(y)).mult(sigmoidPrime(z3));
Matrix dJdW2 = a2.t().dot(delta3);
Matrix delta2 = (delta3.dot(W2.t())).mult(sigmoidPrime(z2));
Matrix dJdW1 = X.t().dot(delta2);
return new Matrix[]{dJdW1, dJdW2};
}
}
There's the code for network framework. I pass double arrays of length 784 into the forward method.
int t = 0;
while (t < 10000) {
dJdW = Nn.costFunctionPrime(X, y);
Nn.W1 = Nn.W1.sub(dJdW[0].scalar(3));
Nn.W2 = Nn.W2.sub(dJdW[1].scalar(3));
t++;
}
I call this to adjust the weights. With small sets, the cost converges to 0 pretty well, but larger sets don't (the cost associated with 100 characters converges to 13, always). And if the set is too large, the first adjustment works (and costs go down) but after the second all I can get is NaN.
Why does this implementation fail with larger data sets (specifically training) and how can I fix this? I tried a similar structure with 10 outputs instead of 1 where each would return a value near 0 or 1 acting like boolean values, but the same thing was happening.
I'm also doing this in java by the way, and I'm wondering if that has something to do with the problem. I was wondering if it was a problem with running out of space but I haven't been getting any heap space messages. Is there a problem with how I'm back-propogating or is something else happening?
EDIT: I think I know what's happening. I think my backpropogation function is getting caught in local minimums. Sometimes the training succeeds and sometimes it fails for large data sets. Because I'm starting with random weights, I get random initial costs. What I've noticed is that when the cost initially exceeds a certain amount (it depends on the number of datasets involved), the costs converge to a clean number (sometimes 27, others 17.4) and the outputs converge to 0 (which makes sense).
I was warned about relative minimums in the cost function when I began, and I'm beginning to realize why. So now the question becomes, how do I go about my gradient descent so that I'll actually find the global minimum? I'm working in Java by the way.
This seems like a problem with weight initialization.
As far as i can see you never initialize the weights to any specific value. Therefore the network diverges. You should at least use random initialization.
If your backprop works on small dataset is there really good assumtion that there isn't problem. When you're suspicious about it you can try your BP on XOR problem.
Are units biased?
I once discuss with guy who doing exactly same thing. Hand digit recognition and 15 units in hidden layer. I saw a network who doing this task well. Her topology was:
Input: 784
First hidden: 500
Second hidden: 500
Third hidden: 2000
Output: 10
You have a sets of images and you nonlinear transform 784 pixels of image into the 15 numbers from <0, 1> interval and you doing this for all images of your set. You hope that you can right separate digit based on these 15 numbers. From my point of view is 15 hidden unit too little for such a task when I assumed you have dataset with thousands of example. Please try for example 500 hidden units.
And learning rate has influence on backprop and can caused problem with convergence.
I'm getting strange results from the TA-LIB Mama indicator.
Calls to other indicators using the same price array give correct results.
But calls to core.mama() give Mama values a pip or two out, and Fama values up to 30 pips out. I'm comparing to the values in JForex, which I've validated against other platforms.
I'm setting the length of the price array with a call to TA-LIB, but a longer lookback doesn't improve results:
int priceLength = core.mamaLookback(fastLimit, slowLimit) + 1;
My settings for the fastLimit and slowLimit are within sensible limits.
Changing the startIdx param to 0 and returning more values doesn't help either.
The code is so simple that it's hard to see what I could be doing wrong. Am I having some kind of brain fart, or is the library bugged?
public static double[] runMama(double[] prices, double fastLimit, double slowLimit) {
try {
MInteger outBegIdx = new MInteger();
MInteger outNbElement = new MInteger();
int count = prices.length;
Core core = new Core();
// We only need the most recent value.
double[] outputFama = new double[1];
double[] outputMama = new double[1];
RetCode retCode = core.mama(count-1, count-1, prices, fastLimit, slowLimit, outBegIdx, outNbElement, outputMama, outputFama);
if (retCode != RetCode.Success) {
throw new RuntimeException("TA-LIB Mama has barfed!");
}
return new double[]{outputMama[0], outputFama[0]};
} catch (Exception e) {
Printer.printErr("Problem with MESA", e);
return null;
}
}
OK - my bad
I hadn't realised that Java TA-Lib returns data in a somewhat eccentric fashion.
In contrast to pretty much every other trading library the most recent values have the higher keys, with the highest keys being padded with a number of zero values related to the length of the lookback.
Also, when indicators have memories (like the Mama which is based on an exponential MA), you need a much longer lookback than the value returned by core.mamaLookback(fastLimit, slowLimit) to get a meaningful result. So you need to pass in a long enough price array.
I'm now getting reliable results.
I have developed a program that solves kinematic equations in elementary physics. To solve, one needs 3 out of a possible 5 variables. There are 10 different combinations of what 3 variables are known. I coded 10 scenarios similar to the two blocks of code below
// If we have acceleration, final velocity, and initial velocity
if (varEntered[0] == true && varEntered[1] == true && varEntered[2] == true)
{
double acceleration = knownVariables[0]; //Setting acceleration
double finalVelocity = knownVariables[1]; //Setting finalVelocity
double initVelocity = knownVariables[2]; //Setting initVelocity
double time = ((finalVelocity - initVelocity)/acceleration); //Finding time using an equation
double distance = ((finalVelocity + initVelocity)*((0.5)*time)); //Finding distance using an equation
System.out.println("The time is " + time + " seconds"); //Printing time
System.out.println("The distance is " + distance + " meters"); //Printing distance
}
//If we have distance, final velocity, initial velocity
if (varEntered[3] == true && varEntered[1] == true && varEntered[2] == true)
{
//Known variables
double distance = knownVariables[3]; //Acceleration
double finalVelocity = knownVariables[1]; //Final Velocity
double initVelocity = knownVariables[2]; //Initial Velocity
// Unknown variables
double time = (distance/((0.5)*(finalVelocity + initVelocity))); //Time
double acceleration = ((finalVelocity - initVelocity)/time); //Acceleration
System.out.println("The time is " + time + " meters/second"); //Printing time
System.out.println("The acceleration is " + acceleration + " meters/second^2"); //Printing distance
}
These seem very similar, but are different scenarios. As a programming beginner, I am wondering if the algorithm I use can be modified to shorten the code. If any more info is needed I will be more than happy to provide.
You should define a function that accepts three numbers and performs the general calculation.
For a starter, try this tutorial. Then you can call your function twice, each time with different sets of variables.
I would use a Map and do something like this (warning: pseudocode):
import java.util.HashMap;
import java.util.Map;
Map<String,double> map=new HashMap<String, double>();
Initialize the map with all the values that are known, e.g.:
map.put("initVelocity", 0.35);
Then you can define the following function:
void calculateValues(Map<double,String> map){
if( map.containsKey("initVelocity") && map.containsKey("finalVelocity") && map.containsKey("acceleration")){
map.put("time",((map.get("finalVelocity") - map.get("initVelocity")/map.get("acceleration"));
}
add all the other algorithms here in the same way!!!
}
This function takes the values that are already defined in the HashMap and tries to calculate the missing parameters. It will often be necessary to call it multiple times on a map until all parameters are set. You could do something like:
while( the map has not all values set){
calculateValues(map);
}
Also, you could make sure (by adding this condition to the if-statements) that any of the algorithms is called only if the resulting values are not set yet. But don't worry too much about that.
From what I noticed, it seems each variable is associated with a number. You can eliminate all the possible scenarios completely and have if conditions on each of the five variables; through this identify the 3 variables first and initialize the local variables. They are independent of each other when assigned, so there's no reason to make that many combinations. This will shorten the code by a lot.
The next step is to shorten the number of combinations you have. The best thing I can think of is finding out the two values you need to compute and using the formulas, in other words another block of if else statements. Here's what the code would look like:
//initialize all to 0
double acceleration = 0;
double distance = 0;
double finalVelocity = 0;
double initVelocity = 0;
double time = 0;
//place the proper values for each
if (varEntered[0] == true){
acceleration = knownVariables[0];
}
if (varEntered[1] == true){
finalVelocity = knownVariables[1];
}
if (varEntered[2] == true){
initVelocity = knownVariables[2];
}
if (varEntered[3] == true){
distance = knownVariables[3];
}
if (varEntered[4] == true){
time = knownVariables[4];
}
// now you have 10 cases
if(varEntered[0] == false && varEntered[1] == false){
//use the formulas here
} else if (varEntered[0] == false && varEntered[2] == false){
//use other formula here
}// repeat for the next 8, with each time you change the condition and formulas
//like you have it. Also, I noticed that you missed the else in your conditionals;
//it is more efficient if you use if-else clauses when only one should execute every time you run the code.
Hope this helps.
Feel free to copy this out, fill the rest and try it out.
If you're careful with your dependencies, you can get away with 5 cases with 1 calculation each instead of 10 cases with 2 calculations each. To do this, you have to make sure that no two variables directly depend on each other. If that were to happen, then you would be out of luck when both of the variables are unknown.
One way to do this is to take your list of variables and calculate each variable in terms of the following three (wrapping around when you reach the end of the list), as in the following example. In this example, solveAll takes an array of doubles with the unknowns set to Double.MAX_VALUE, and it sets the unknowns to the correct values. (If there are more than two unknowns, you'll get an infinite recursion.)
// Really should use enum instead of constant ints, and an EnumMap instead of an array.
public final static int ACCELERATION = 0;
public final static int FINALVELOCITY = 1;
public final static int INITVELOCITY = 2;
public final static int DISTANCE = 3;
public final static int TIME = 4;
private double[] vars;
public void solveAll(double[] vars) {
this.vars = vars;
for (int i=ACCELERATION; i<=TIME; i++) {
get(i);
}
}
private double get(int v) {
if (vars[v] != Double.MAX_VALUE) {
return vars[v];
}
switch (v) {
case ACCELERATION:
return (vars[ACCELERATION] = (get(FINALVELOCITY)*get(FINALVELOCITY) - get(INITVELOCITY)*get(INITVELOCITY)) / (2*get(DISTANCE)));
case FINALVELOCITY:
return (vars[FINALVELOCITY] = 2*get(DISTANCE)/get(TIME) - get(INITVELOCITY));
case INITVELOCITY:
return (vars[INITVELOCITY] = get(DISTANCE)/get(TIME) - get(ACCELERATION)*get(TIME)/2);
case DISTANCE:
return (vars[DISTANCE] = (get(FINALVELOCITY) - get(ACCELERATION)*get(TIME)/2) * get(TIME));
case TIME:
return (vars[TIME] = (get(FINALVELOCITY) - get(INITVELOCITY)) / get(ACCELERATION));
}
return Double.MAX_VALUE; // Bad variable index
}