Within a java project I've developed I need to calculate the inverse of a matrix. In order to align with other projects and other developers I'm using the Efficient Java Matrix Library (orj.ejml).
For inverting the Matrix I'm using invert from org.ejml.ops.CommonOps, and I has worked fine until now that I'm getting a unexpected result
I've isolated the case that doesn't work to be:
DenseMatrix64F X = new DenseMatrix64F(3, 3);
X.setData(new double[]{77.44000335693366,-24.64000011444091,-8.800000190734865, -24.640000114440916,7.839999732971196,2.799999952316285, -8.800000190734865,2.799999952316285,1.0000000000000004});
DenseMatrix64F invX = new DenseMatrix64F(3, 3);
boolean completed = CommonOps.invert(X, invX);
System.out.println(X);
System.out.println(invX);
System.out.println(completed);
The output I get from this test is:
Type = dense , numRows = 3 , numCols = 3
77.440 -24.640 -8.800
-24.640 7.840 2.800
-8.800 2.800 1.000
Type = dense , numRows = 3 , numCols = 3
NaN -Infinity Infinity
NaN Infinity -Infinity
NaN -Infinity Infinity
true
My first thought was that it could be a singular matrix and therefore not invertible, but after testing the same matrix with a different calculation tool I've found that it is not singular.
So I went back to the EJML documentation and found out the following information for this particular function.
If the algorithm could not invert the matrix then false is returned. If it returns true that just means the algorithm finished. The results could still be bad because the matrix is singular or nearly singular.
And, in this particular case the matrix is not singular but we could say it is near singular.
The only solution I could think off was to search the inverted matrix for NaN or Infinites after calculating it, and if I find something funny in there I just replace the inverted matrix with the original matrix, although it doesn't seem a very clean practice it yields reasonable results.
My question is:
Could you think of any solution for this situation? Something smarter and wiser than just using the original matrix as its own inverse matrix.
In case there is no way around it, do you know of any other Java Matrix library that has some solution to this situation, I'm not looking forward to introduce a new library but it may be the only solution if this becomes a real problem.
Regards and thanks for your inputs!
You should try using SVD if you have to have an inverse. Also consider a pseudo inverse instead. Basically any library using LU decomposition will have serious issues. Here's the output from Octave. Note how two of the singular values are almost zero. Octave will give you an inverse with real numbers, but it's a poor one...
octave:7> cond(B)
ans = 8.5768e+17
octave:8> svd(B)
ans =
8.6280e+01
3.7146e-15
1.0060e-16
inv(B)*B
warning: inverse: matrix singular to machine precision, rcond = 4.97813e-19
ans =
0.62500 0.06250 0.03125
0.00000 0.00000 0.00000
0.00000 0.00000 4.00000
Related
For an project I have to demonstrate JPEG compression and therefore the conversion with DCTII and IDCT. I have no idea how to implement this formula. But I found an website that provides the Java code and online IDE for testing.
https://ide.geeksforgeeks.org/FnC3bRJEAr here you can see the code.
(formulas from Wikipedia/JPEG)
So, what changes have to be made to the code?
I tried switching the for-loops and the variables in the formula but the values I got were definitely wrong, other tries lead to error messages.
The only difference between the DCT and IDCT is where coefficient are taken into account.
You should replace line 46 in your code by
sum = sum + ck*cl*dct1;
where ck and cl are computed as in lines 24-34, but for k and l
And suppress ci*cj in line 49
BTW, this java code is exceptionally inefficient. Precompute Math.sqrt(2), Math.sqrt(n) and put your cosine in a table and it will be at least 3 times faster.
Your summations are doing a matrix multiplication. Your a multiplying an 8x8 data matrix by an 8x8 DCT matrix.
The DCT matrix is orthonormal so its inverse is its transpose.
You should therefore be able to invert by exchanging u and v.
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 using the non linear least squares Levenburg Marquardt algorithm in java to fit a number of exponential curves (A+Bexp(Cx)). Although the data is quite clean and has a good approximation to the model the algorithm is not able to model the majority of them even with a excessive number of iterations(5000-6000). For the curves it can model, it does so in about 150 iterations.
LeastSquaresProblem problem = new LeastSquaresBuilder()
.start(start).model(jac).target(dTarget)
.lazyEvaluation(false).maxEvaluations(5000)
.maxIterations(6000).build();
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
LeastSquaresOptimizer.Optimum optimum = optimizer.optimize(problem);}
My question is how would I define a convergence criteria in apache commons in order to stop it hitting a max number of iterations?
I don't believe Java is your problem. Let's address the mathematics.
This problem is easier to solve if you change your function.
Your assumed equation is:
y = A + B*exp(C*x)
It'd be easier if you could do this:
y-A = B*exp(C*x)
Now A is just a constant that can be zero or whatever value you need to shift the curve up or down. Let's call that variable z:
z = B*exp(C*x)
Taking the natural log of both sides:
ln(z) = ln(B*exp(C*x))
We can simplify that right hand side to get the final result:
ln(z) = ln(B) + C*x
Transform your (x, y) data to (x, z) and you can use least squares fitting of a straight line where C is the slope in (x, z) space and ln(B) is the intercept. Lots of software available to do that.
I am using Java + Jblas (first time user) and am trying to multiply two matrices. One is a 163x4 and the other is 4x1 matrix. I would expect the result of such a multiplication to be a 163x1 matrix. However using:
FloatMatrix a = b.mmuli(c);
I am getting the error:
Matrices must have same length (is: 652 and 4)
Now while I assume, that makes perfect sense for the program I am confused. The same multiplication worked fine in Octave (which of course applies some magic). But now for getting this to work I would need to know what kind of sorcery this is?
EDIT
So here is what the Octave Documentation says about broadcasting (the sorcery):
In case all dimensions are equal, no broadcasting occurs and ordinary
element-by-element arithmetic takes place. For arrays of higher
dimensions, if the number of dimensions isn’t the same, then missing
trailing dimensions are treated as 1. When one of the dimensions is 1,
the array with that singleton dimension gets copied along that
dimension until it matches the dimension of the other array.
So this means I just copy the 4x1 matrix 163 times. Then I can execute the multiplication, but instead of the 163x1 matrix I wanted, I now have a 163x4 matrix. Which for me is strange. What is my solution now?
So I finally figured it out. And it's one of those mistakes... It has to be
FloatMatrix a = b.mmul(c);
The element wise multiplication was the error here.
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