Are there any methods which do that? I have an application where I need the area under the curve, and I am given the formula, so if I can do the integration on hand, I should be able to do it programatically? I can't find the name of the method I'm referring to, but this image demonstrates it: http://www.mathwords.com/a/a_assets/area%20under%20curve%20ex1work.gif
Edit: to everyone replying, I have already implemented rectangular, trapezoidal and Simpson's rule. However, they take like 10k+ stripes to be accurate, and should I not be able to find programatically the integrated version of a function? If not, there must be a bloody good reason for that.
Numerical integration
There are multiple methods, which can be used. For description, have a look in Numerical Recipes: The Art of Scientific Computing.
For Java there is Apace Commons library, which can be used. Integration routines are in Numerical Analysis section.
Symbolic integration
Check out jScience. Functions module "provides support for fairly simple symbolic math analysis (to solve algebraic equations, integrate, differentiate, calculate expressions, and so on)".
If type of function is given, it can be possible to integrate faster in that specific case than when using some standard library.
To compute it exactly, you would need a computer algebra system library of some sort to perform symbolic manipulations. Such systems are rather complicated to implement, and I am not familiar with any high quality, open source libraries for Java. An alternative, though, assuming it meets your requirements, would be to estimate the area under the curve using the trapezoidal rule. Depending on how accurate you require your result to be, you can vary the size of the subdivisions accordingly.
I would recommend using Simpsons rule or the trapezium rule, because it could be excessively complicated to integrate every single type of graph.
See Numerical analysis specifically numerical integration. How about using the Riemann sum method?
You can use numerical integration, using some rule, like already mentioned Simpsons, Trapezoidal, or Monte-Carlo simulation. It uses pseudo random generator.
You can try some libraries for symbolic integration, but I'm not sure that you can get symbolic representation of every integral.
Here's a simple but efficient approach:
public static double area(DoubleFunction<Double> f, double start, double end, int intervals) {
double deltaX = (end - start)/intervals;
double area = 0.0;
double effectiveStart = start + (deltaX / 2);
for (int i=0; i<intervals; ++i) {
area += f.apply(effectiveStart + (i * deltaX));
}
return deltaX * area;
}
This is a Riemann sum using the midpoint rule, which is a variation of the trapezoidal rule, except instead of calculating the area of a trapezoid, I use a rectangle from f(x) at the middle of the interval. This is faster and gives a better result. This is why my effective starting value of x is at the middle of the first interval. And by looping over an integer, I avoid any round-off problems.
I also improve performance by waiting till the end of the loop before multiplying by deltaX. I could have written the loop like this:
for (int i=0; i<intervals; ++i) {
area += deltaX * f.apply(effectiveStart + (i * deltaX)); // this is x * y for each rectangle
}
But deltaX is constant, so it's faster to wait till the loop is finished.
One of the most popular forms of numeric integration is the Runge-Kutta order 4 (RK4) technique. It's implementations is as follows:
double dx, //step size
y ; //initial value
for(i=0;i<number_of_iterations;i++){
double k1=f(y);
double k2=f(y+dx/2*k1);
double k3=f(y+dx/2*k2);
double k4=f(y+dx*k3);
y+= dx/6*(k1+2*k2+2*k3+k4);
}
and will converge much faster than rectangle, trapezoids, and Simpson's rule. It is one of the more commonly used techniques for integration in physics simulations.
Related
I am working on a function plotter project for Android in which the user inputs the equation as a string.
this string is solved using the EvalEx library and I get a bunch of data points which I plot using graph-view library.
now the problem is when I give it an equation with negative square root. for example SQRT(1-x) this is causing errors.
for( i = 0; i < x.length ; i++) {
//the equation solver only takes BigDecimal as input.
x1 = new BigDecimal(x[i]);
try {
// eq is the sting that i got from the EditText.
y1 = new Expression(eq).with("x", x1).eval();
y[i] = y1.floatValue();
} catch(ArithmeticException excp) {
//these are the data points that go into the plot function
x[i] = 0;
y[i] = 0;
}
}
I'm still a little unclear what you are trying to do, but I think I understand enough to give you a definitive answer.
Here's the thing:
The eval(...) function returns a single value.
That's what the API says. That's all it can do. You cannot avoid that fact. (There is no magic .....)
So if you want to get both (real) square roots, you need take the positive result returned by SQRT and negate it yourself to get the second solution. In your code. Something like this:
y1 = new Expression("SQRT(3 - x^2)").with("x", x1).eval();
y2 = BigDecimal.ZERO - y1;
Of course, this is special-case code1. And there is no general-case code that is going to give you multiple solutions to equations when the SQRT functions could be anywhere in your expression.
And expressions with complex solutions will be even more intractable with the EvalEx API. You cannot represent a complex solution using the (single) BigDecimal that is returned by the eval method. (If you look at the code, taking a square root of a negative number throws the API's ExpressionException.)
The bottom line is that EvalEx is a simple, light-weight expression evaluator. It is not designed for your use-case which involves finding all solutions, and / or dealing with complex numbers. And making the existing API work for these use-cases would be ... impossible.
But the good news is that the source code for EvalEx is available on GitHub.
https://github.com/uklimaschewski/EvalEx (I assume this is corresponds to the version you are using.)
You could download it and use it as the starting point for writing a more sophisticated expression evaluator.
Or ... you could look for an alternative library that does what you need.
1 - That is, it is implemented with the pre-knowledge of what the expression we are evaluating is! Moreover, it still fails for values of x where 3 - x^2 is negative.
I'm coding an application in Java that requires quite a lot of geometry. I made heavy use of existing classes and my calculations so far have been in double precision (so I'm using for instance, Point2D.Double, Line2D.Double and coded a convex polygon class using the latter...).
I ran into several issues relating to double precision calculations that make my application at times unstable and I considered switching to BigDecimal but that would imply creating creating my own Point2D, Line2D classes with BigDecimals etc, and rewriting several functions. Another solution would be to accept the imprecisions and deal with them; i.e. A point is actually a small square, a line is a an infinite band, a point lies on a line if the square and the band intersect and so on. Although this solution can be implemented quickly my code would be disfigured by statements like (Math.abs(x) < precision) (to signify that x == 0) scattered here and there.
Is someone aware of nice clean way to do accurate geometry in Java?
I tried to squeeze (parts of) this into a comment, but it didn't fit. You should not consider this as "THE" answer, but there are some points that I would like to list here.
The recommendation to use BigDecimal is annoyingly common whenever someone mentions precision problems with float or double - and yet is equally inappropriate in such cases as this one. In all but the fewest cases, the limited precision of double is simply not relevant.
Unless, maybe, you are writing software that should compute the trajectory of a manned spacecraft that is about to be sent to Mars, or doing other highly scientific computations.
Additionally, replacing double with BigDecimal tends to only replace one small problem with several larger ones. For example, you'll have to think about the RoundingMode and "scale", which can be tricky. And eventually, you will notice that a simple value like 1.0/3.0 can't be represented with BigDecimal either.
For your particular application case, there are more caveats:
Even with a BigDecimal-based implementation of Point2D, the data would still be exposed as double, via the getX()/getY() methods. For example, a method like Line2D#ptLineDistSq will still use the double values. This could only be avoided if you wrote everything that is related to your computations, from scratch, using BigDecimal really everywhere.
But even if you did this: You cannot compute the slope of a line from the point (-1,0) to the point (2,1), and you cannot say where this line intersects the y-axis. You might try some rational number representation here, but there's still this issue with the length of the diagonal of a unit square - which is an irrational number.
The imprecisions of double are annoying. You can compute whether a point is left of a line or right of a line. And due to the precision issues, it may well be that it is both. Doing computations with points that should "mathematically" be equal, but differ by some small floating-point error can lead to bogus results (I also stumbled over this in one of my libraries).
As you already mentioned in the question: Some concepts that work in pure mathematics have to be rethought when they should be implemented with limited precision. Any == comparison is a no-go, and other comparisons should be carefully validated, taking the possible rounding errors into account.
But using some "epsilon"-based comparisons is the usual way to deal with this. Of course, they make the code a bit more clumsy. But compare this to some "arbitrary precision" code with BigDecimal:
BigDecimal computeArea(BigDecimal radius) {
// Let's be very precise here....
BigDecimal pi = new BigDecimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319");
BigDecimal radiusSquared = radius.multiply(radius);
BigDecimal area = radiusSquared.multiply(pi);
return area;
}
Vs.
double computeArea(double radius) {
return Math.PI * radius * radius;
}
Also, the epsilon-based comparisons are still error-prone and raise some questions. Most prominently: How large should this "epsilon" be? Where should the epsilon-based comparison take place? However, existing implementations, like the geometric algorithms in http://www.geometrictools.com/ might give some ideas of how this can be done (even though they are implemented in C++, and became a bit less readable in the latest versions). They are time-tested and already show how to cope with many of the precision-related problems.
I am creating a graphing calculator and I need an algorithm to interpret equations that users input. For example, if the user types in "x^3+5x^2-4x-9", the algorithm should take the string input and return (0, -9), (1, -7) and so on. How should I go about doing this? Are there any open source libraries I can use? Thanks in advance.
You could implement a Shunting-Yard Algorithm, but there are plenty of mathematical parsers already out there. There is a very famous saying in software development:
"Don't reinvent the wheel."
I encountered this problem when developing my own app. If there's already open source libraries out there, you should definitely use them to your advantage. That being said, I would recommend the MathEval library if you want double precision. Double is usually enough in terms of precision, because precision after double such as BigDecimal, which is an exact way of representing numbers is extremely expensive in terms of speed and memory, two things you want to reduce in computation.
The easiest, O(n) method in which you would generate solutions is set a range in a for loop, and use MathEval's setVariable method for x based on the iterations in the loop and retrieve the result through MathEval's evaluate method. There could be some boundaries in the equation, so make sure you compute the necessary restrictions and condition them inside your loop.
Check out this link Terrance which mentions the MathEval library:
Built-in method for evaluating math expressions in Java
Let me know if you need any help because I have implemented both the algorithm from scratch and through an external library.
I'm doing some video processing, for each frame I need to get a gradient of a bi-variate function.
The function is represented as a two dimensional array of doubles. Where the domain is the rows and columns indices and the range is the double value of the corresponding indices values. Or more simply put, the function f is defined for double[][] matrix as such:
f(x,y)=matrix[x][y]
I'm trying to use the Apache Commons Math library for it:
SmoothingPolynomialBicubicSplineInterpolator iterpolator = new SmoothingPolynomialBicubicSplineInterpolator();
BicubicSplineInterpolatingFunction f = iterpolator.interpolate(xs, ys, matrix.getData());
for (int i = 0; i < ans.length; i++) {
for (int j = 0; j < ans[0].length; j++) {
ans[i][j] = f.partialDerivativeY(i, j);
}
}
with xs, as a sorted array of the x indices (0,1,...,matrix.getRowDimension() - 1)
ys the same on the columns dimension (0,1,...,matrix.getColumnDimension() - 1)
The problem is that for a typical matrix in the size of 150X80 it takes as much as 1.4 seconds to run, which renders it completely irrelevant for my needs. So, as a novice user of this library, and programmatic numeric analysis in general, I want to know:
Am I doing something wrong?
Is there another, faster, way I can accomplish this task with?
Is there another open source library (preferably maven-friendly) that offers a solution?
Numerical differentiation is an entire topic unto itself, a simple google should bring up enough material for you to work with (just the wiki might be sufficient). There are parameters of your problem that I cannot know, so I can only speak broadly here, but there are direct methods of determining the gradient at a given point, i.e. ones that don't require an interpolation. See the wikipedia for the formulae (ranging from the simple f(x+1)-f(x), which is where h=1, to the higher order ones). Calculating the partial derivatives is then a simple O(NM) loop with an uber easy formula inside (no interpolation required).
The specifics can get gritty:
The higher order formulae need to be reduced for the edges, or
discarded altogether.
Your precise speed requirements might render more complex formulae useless (depending on the platform sometimes the lookup times for higher order formulae make them too slow; again, it depends on the cache etc.). This is easy to test, the formulae are simple; code them and benchmark.
The specific implementation is also dependent on your error requirements. The theory provides error bounds, so that will play a role in what formula you need; but again, there's a trade-off with speed requirements. The in turn can be practically lowered if you know specifics about the types of matrices you'll be processing, if such a thing is known.
The implementation can be made even easier (and maybe faster) if you have existing convolution tools, since this method is really just a convolution of the matrix (note; technically it's called a cross-correlation).
Does anyone know of a scientific/mathematical library in Java that has a straightforward implementation of weighted linear regression? Something along the lines of a function that takes 3 arguments and returns the corresponding coefficients:
linearRegression(x,y,weights)
This seems fairly straightforward, so I imagine it exists somewhere.
PS) I've tried Flannigan's library: http://www.ee.ucl.ac.uk/~mflanaga/java/Regression.html, it has the right idea but seems to crash sporadically and complain out my degrees of freedom?
Not a library, but the code is posted: http://www.codeproject.com/KB/recipes/LinReg.aspx
(and includes the mathematical explanation for the code, which is a huge plus).
Also, it seems that there is another implementation of the same algorithm here: http://sin-memories.blogspot.com/2009/04/weighted-linear-regression-in-java-and.html
Finally, there is a lib from a University in New Zealand that seems to have it implemented: http://www.cs.waikato.ac.nz/~ml/weka/ (pretty decent javadocs). The specific method is described here:
http://weka.sourceforge.net/doc/weka/classifiers/functions/LinearRegression.html
I was also searching for this, but I couldn't find anything. The reason might be that you can simplify the problem to the standard regression as follows:
The weighted linear regression without residual can be represented as
diag(sqrt(weights))y = diag(sqrt(weights))Xb where diag(sqrt(weights))T basically means multiplying each row of the T matrix by a different square rooted weight. Therefore, the translation between weighted and unweighted regressions without residual is trivial.
To translate a regression with residual y=Xb+u into a regression without residual y=Xb, you add an additional column to X - a new column with only ones.
Now that you know how to simplify the problem, you can use any library to solve the standard linear regression.
Here's an example, using Apache Commons Math:
void linearRegression(double[] xUnweighted, double[] yUnweighted, double[] weights) {
double[] y = new double[yUnweighted.length];
double[][] x = new double[xUnweighted.length][2];
for (int i = 0; i < y.length; i++) {
y[i] = Math.sqrt(weights[i]) * yUnweighted[i];
x[i][0] = Math.sqrt(weights[i]) * xUnweighted[i];
x[i][1] = Math.sqrt(weights[i]);
}
OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
regression.setNoIntercept(true);
regression.newSampleData(y, x);
double[] regressionParameters = regression.estimateRegressionParameters();
double slope = regressionParameters[0];
double intercept = regressionParameters[1];
System.out.println("y = " + slope + "*x + " + intercept);
}
This can be explained intuitively by the fact that in linear regression with u=0, if you take any point (x,y) and convert it to (xC,yC), the error for the new point will also get multiplied by C. In other words, linear regression already applies higher weight to points with higher x. We are minimizing the squared error, that's why we extract the roots of the weights.
I personally used org.apache.commons.math.stat.regression.SimpleRegression Class of the Apache Math library.
I also found a more lightweight class from Princeton university but didn't test it:
http://introcs.cs.princeton.edu/java/97data/LinearRegression.java.html
Here's a direct Java port of the C# code for weighted linear regression from the first link in Aleadam's answer:
https://github.com/lukehutch/WeightedLinearRegression.java