I try to mimic this algorithm, developed in Python, that calculates geolocation based on seen Wifi stations positions, itself based on this idea.
This algorithm uses at first a Numpy function in order to calculate a basic weighted average of observed latitudes and longitudes. To minimize the impact of possible Wifi positions errors, it’s also use the “scipy.optimize.leastsq” method in order to calculate in an statistical way and if possible, a more precise position.
I want to implement the same behavior on the Java Android platform.
For all other calculations I successfully rely on org.apache.commons.math3.
So for the least-squares problem I logically try to rely on https://commons.apache.org/proper/commons-math/userguide/leastsquares.html.
My problem, if I well understood, is that Scipy manage for me the complexity of Jacobian function definition and my poor mathematics skills doesn't allow me to define correctly the model of a LeastSquaresProblem. I tried some experimentations based on this example, that seems closed to what I need, but the results aren't good as I don't know how to deal with the "jacobian" parts.
As someone do for this post, could someone do the same thing for me and try to explain it in a simple way?
More details on how Python part is working :
The “scipy.optimize.leastsq” statement used is:
(lat, lon), cov_x, info, mesg, ier =
scipy.optimize.leastsq(func, initial, args=data, full_output=True)
Where data are: latitude/longitude/age in milliseconds/signal strength, for example: data = numpy.array([(43.48932915, 1.66561772, 1000, -20), (43.48849093, 1.6648176, 2000, -10), (43.48818612, 1.66615113, 3000, -50)])
Initial is calculated weighted average latitude/longitude, in this example: initial = 43.48864654, 1.66550075
Function is
def func(initial, data):
return numpy.array([
geographic distance((float(point[latitude]), float(point[longitude])), (initial[latitude], initial[longitude])).meters * min(math.sqrt(2000.0 / float(point[age])), 1.0) / math.pow(float(point[signal strength]), 2)
The result is: 43.4885401095, 1.6648660983
My experiments in Java, I've replaced data values and have changed the way "modelI" is calculated. I simplified signal strength and age values. But it's a fact, and results show, that it isn't sufficient.
double modelI = calculateVincentyDistance(o.getY(), o.getX(), center.getY(), center.getX())* Math.min(Math.sqrt(2000.0/1000.0), 1.0) / Math.pow(-10, 2);
I also going to try https://github.com/odinsbane/least-squares-in-java, but I'm not sure to use it correctly as I don't master the way it's work.
FYI, I use Vincenty distance calculation that for example can be replaced by Haversine or Euclidean.
Thank you for any help !
The code is not easy to port because SciPy provides a more generic Least-squares minimization interface while Apache Commons Math provides curve fitting. Still many optimization problems can be restated as curve fitting. In the Python code you minimize
F(current_point) = Sum{ (distance(known_point[i], current_point) * weight[i])^2 } -> min
Java curve fitting problem is a bit different:
F(current_point) = Sum{ (target_value[i] - model[i](current_point))^2 } -> min
So equivalent fitting problem can be created by assigning all target_values to 0 and making model[i] calculate weighted distance from current_point to known_point[i].
In a general case such problems have no exact solution using formula and some numerical optimization method is used. And here lies another difference: Java implementation explicitly requires you to provide means for the optimizer to calculate derivatives of the function being optimized. Python code seems to use some kind of differences differentiator if Dfun is not provided. You can do something like this in Java by hand or using FiniteDifferencesDifferentiator but for simple formulas it might be easier to code them explicitly using DerivativeStructure
static class PositionInfo {
public final double latitude;
public final double longitude;
public final int ageMs;
public final int strength;
public PositionInfo(double latitude, double longitude, int ageMs, int strength) {
this.latitude = latitude;
this.longitude = longitude;
this.ageMs = ageMs;
this.strength = strength;
}
public double getWeight() {
return Math.min(1.0, Math.sqrt(2000.0 / ageMs)) / (strength * strength);
}
}
static DerivativeStructure getWeightedEuclideanDistance(double tgtLat, double tgtLong, PositionInfo knownPos) {
DerivativeStructure varLat = new DerivativeStructure(2, 1, 0, tgtLat); // latitude is 0-th variable of 2 for derivatives up to 1
DerivativeStructure varLong = new DerivativeStructure(2, 1, 1, tgtLong); // longitude is 1-st variable of 2 for derivatives up to 1
DerivativeStructure latDif = varLat.subtract(knownPos.latitude);
DerivativeStructure longDif = varLong.subtract(knownPos.longitude);
DerivativeStructure latDif2 = latDif.pow(2);
DerivativeStructure longDif2 = longDif.pow(2);
DerivativeStructure dist2 = latDif2.add(longDif2);
DerivativeStructure dist = dist2.sqrt();
return dist.multiply(knownPos.getWeight());
}
// as in https://en.wikipedia.org/wiki/Haversine_formula
static DerivativeStructure getWeightedHaversineDistance(double tgtLat, double tgtLong, PositionInfo knownPos) {
DerivativeStructure varLat = new DerivativeStructure(2, 1, 0, tgtLat);
DerivativeStructure varLong = new DerivativeStructure(2, 1, 1, tgtLong);
DerivativeStructure varLatRad = varLat.toRadians();
DerivativeStructure varLongRad = varLong.toRadians();
DerivativeStructure latDifRad2 = varLat.subtract(knownPos.latitude).toRadians().divide(2);
DerivativeStructure longDifRad2 = varLong.subtract(knownPos.longitude).toRadians().divide(2);
DerivativeStructure sinLat2 = latDifRad2.sin().pow(2);
DerivativeStructure sinLong2 = longDifRad2.sin().pow(2);
DerivativeStructure summand2 = varLatRad.cos().multiply(varLongRad.cos()).multiply(sinLong2);
DerivativeStructure sum = sinLat2.add(summand2);
DerivativeStructure dist = sum.sqrt().asin();
return dist.multiply(knownPos.getWeight());
}
Using such preparation you may do something like this:
public static void main(String[] args) {
// latitude/longitude/age in milliseconds/signal strength
final PositionInfo[] data = new PositionInfo[]{
new PositionInfo(43.48932915, 1.66561772, 1000, -20),
new PositionInfo(43.48849093, 1.6648176, 2000, -10),
new PositionInfo(43.48818612, 1.66615113, 3000, -50)
};
double[] target = new double[data.length];
Arrays.fill(target, 0.0);
double[] start = new double[2];
for (PositionInfo row : data) {
start[0] += row.latitude;
start[1] += row.longitude;
}
start[0] /= data.length;
start[1] /= data.length;
MultivariateJacobianFunction distancesModel = new MultivariateJacobianFunction() {
#Override
public Pair<RealVector, RealMatrix> value(final RealVector point) {
double tgtLat = point.getEntry(0);
double tgtLong = point.getEntry(1);
RealVector value = new ArrayRealVector(data.length);
RealMatrix jacobian = new Array2DRowRealMatrix(data.length, 2);
for (int i = 0; i < data.length; i++) {
DerivativeStructure distance = getWeightedEuclideanDistance(tgtLat, tgtLong, data[i]);
//DerivativeStructure distance = getWeightedHaversineDistance(tgtLat, tgtLong, data[i]);
value.setEntry(i, distance.getValue());
jacobian.setEntry(i, 0, distance.getPartialDerivative(1, 0));
jacobian.setEntry(i, 1, distance.getPartialDerivative(0, 1));
}
return new Pair<RealVector, RealMatrix>(value, jacobian);
}
};
LeastSquaresProblem problem = new LeastSquaresBuilder()
.start(start)
.model(distancesModel)
.target(target)
.lazyEvaluation(false)
.maxEvaluations(1000)
.maxIterations(1000)
.build();
LeastSquaresOptimizer optimizer = new LevenbergMarquardtOptimizer().
withCostRelativeTolerance(1.0e-12).
withParameterRelativeTolerance(1.0e-12);
LeastSquaresOptimizer.Optimum optimum = optimizer.optimize(problem);
RealVector point = optimum.getPoint();
System.out.println("Start = " + Arrays.toString(start));
System.out.println("Solve = " + point);
}
P.S. the logic of the weight seems suspicious to me. In the question you reference the OP has some estimates for radius and then it is an obvious weight. Using reverse square of the signal strength which is measured in logarithmic dBm seems strange to me.
I've looked everywhere for code I can understand which could help me on my way. I've found one but I'm struggling, so I hope someone could help me.
This is what I want to achieve:
Solve a cubic function (ax^3+bx^2+cx+d) where a,b,c and d are filled
in by the command line when you run it.
I need the roots and complex roots to be found using the Newton's Method. The code I'm struggling with is this, but I don't know if this works and I don't know how I can calculate all 3 roots (even knowing if it has multiplicity 1, 2 or 3).
Any help is appreciated.
import java.util.function.Function;
public class Newton {
static double a = Polynom.geta(); // these are to get the input from the class you run from calling this class to solve the roots
static double b = Polynom.getb();
static double c = Polynom.getc();
static double d = Polynom.getd();
public static void main(String args[]) {
}
private Complex[] sqrt(double x, double y) {
Complex com = new Complex(x,y); // Complex is my class that deals with Complexnumbers, com is supposed to get the value of the root in the end
double tolerance = 1e-11; // tolerance for the error
int iterations = 1, max = 512;
Complex aa = com.pow(3).multiply(a); // These put in the values from input to complex values and fill in the cubic function of ax^3+bx^2+cx+d
Complex bb = com.pow(2).multiply(b);
Complex cc = com.multiply(c);
Complex dd = com.pow(2).multiply(a).multiply(3.0);
Complex ee = com.multiply(2.0).add(com);
Complex function = aa.add(bb).add(cc).add(d,0);
Complex derivative = dd.add(ee);
for(int k = 0; k<3; k++) {
while(iterations<max) {
Complex difference = function.divide(derivative); //difference=fx/dx
com = com.subtract(difference);
if (Math.abs(difference.getReal()) < tolerance && Math.abs(difference.getImaginary()) < tolerance)
return com; // this is where i get an error atm "Cannot convert from Complex to Complex
iterations++;
}
}
}
I have an android application which is getting gesture coordinates (3 axis - x,y,z). I need to compare them with coordinates which I have in my DB and determine whether they are the same or not.
I also need to add some tolerance, since accelerometer (device which captures gestures) is very sensitive. It would be easy, but I also want to consider e.g. "big circle" drawn in the air, same as "small circle" drawn in the air. meaning that there would be different values, but structure of the graph would be the same, right?
I have heard about translating graph values into bits and then compare. Is that the right approach? Is there any library for such comparison?
So far I just hard coded it, covering all my requirements except the last one (big circle vs small circle).
My code now:
private int checkWhetherGestureMatches(byte[] values, String[] refValues) throws IOException {
int valuesSize = 32;
int ignorePositions = 4;
byte[] valuesX = new byte[valuesSize];
byte[] valuesY = new byte[valuesSize];
byte[] valuesZ = new byte[valuesSize];
for (int i = 0; i < valuesSize; i++) {
int position = i * 3 + ignorePositions;
valuesX[i] = values[position];
valuesY[i] = values[position + 1];
valuesZ[i] = values[position + 2];
}
Double[] valuesXprevious = new Double[valuesSize];
Double[] valuesYprevious = new Double[valuesSize];
Double[] valuesZprevious = new Double[valuesSize];
for (int i = 0; i < valuesSize; i++) {
int position = i * 3 + ignorePositions;
valuesXprevious[i] = Double.parseDouble(refValues[position]);
valuesYprevious[i] = Double.parseDouble(refValues[position + 1]);
valuesZprevious[i] = Double.parseDouble(refValues[position + 2]);
}
int incorrectPoints = 0;
for (int j = 0; j < valuesSize; j++) {
if (valuesX[j] < valuesXprevious[j] + 20 && valuesX[j] > valuesXprevious[j] - 20
&& valuesY[j] < valuesYprevious[j] + 20 && valuesY[j] > valuesYprevious[j] - 20
&& valuesZ[j] < valuesZprevious[j] + 20 && valuesZ[j] > valuesZprevious[j] - 20) {
} else {
incorrectPoints++;
}
}
return incorrectPoints;
}
EDIT:
I found JGraphT, it might work. If you know anything about that already, let me know.
EDIT2:
See these images, they are the same gesture but one is done in a slower motion than another.
Faster one:
Slower one:
I haven't captured images of the same gesture where one would be smaller than another, might add that later.
If your list of gestures is complex, I would suggest training a neural network which can classify the gestures based on the graph value bits you mentioned. The task is very similar to classification of handwritten numerical digits, for which lots of resources are there on the net.
The other approach would be to mathematically guess the shape of the gesture, but I doubt it will be useful considering the tolerance of the accelerometer and the fact that users won't draw accurate shapes.
(a) convert your 3D coordinates into 2D plain figure. Use matrix transformations.
(b) normalize your gesture scale - again with matrix transformations
(c) normalize the number of points or use interpolation on the next step.
(d) calculate the difference between your stored (s) gesture and current (c) gesture as
Sum((Xs[i] - Xc[i])^2 + (Ys[i] - Yc[i])^2) where i = 0 .. num of points
If the difference is below your predefined precision - gestures are equal.
I have used a Java implementation of Dynamic Time Wrapping algorithm. The library is called fastDTW.
Unfortunately from what I undersood they don't support it anymore, though I found a use for it.
https://code.google.com/p/fastdtw/
I can't recall now, but I think I used this one and compiled it myself:
https://github.com/cscotta/fastdtw/tree/master/src/main/java/com/fastdtw/dtw
I would like to fit a quadratic function y = a + bx + cx^2 to some data, in such a way that c is always greater than or equal to 0 in the final result. That is, I would like to restrict my search domain over c to a particular range ([0, Double.MAX_VALUE]). Currently, I have the following code snippet:
final CurveFitter<Parametric> fitter = new CurveFitter<Parametric>(new LevenbergMarquardtOptimizer());
fitter.addObservedPoint(0, 0);
fitter.addObservedPoint(1, -1);
fitter.addObservedPoint(-1, -1);
fitter.addObservedPoint(2, -4);
fitter.addObservedPoint(-2, -4);
final double[] init = { 1, 2, 3 };
final double[] best = fitter.fit(new PositivePolynomialFunctionParametric(), init);
final PolynomialFunction fitted = new PolynomialFunction(best);
System.out.println(Arrays.toString(fitted.getCoefficients()));
where:
private static class PositivePolynomialFunctionParametric extends PolynomialFunction.Parametric {
#Override
public double value(double x, double... parameters) {
parameters[parameters.length - 1] = Math.abs(parameters[parameters.length - 1]);
return super.value(x, parameters);
}
#Override
public double[] gradient(double x, double... parameters) {
parameters[parameters.length - 1] = Math.abs(parameters[parameters.length - 1]);
return super.gradient(x, parameters);
}
}
The output makes sense:
[-1.4286835350284688, -8.489786562989103E-17, 1.0300498244514197E-11]
This seems to work in this particular application, but it is not a very elegant solution for the general case of restricting the search domain. Is there a better way to do this?
You should use one of the optimizers that implements/extends the *BoundsOptimizer types, or that supports a SimpleBounds in its OptimizationData. Section 12.4 of the user guide on optimization also mentions a way to adjust the function being optimized, but recommends using one of the bounds-supporting algorithms instead.
I am currently coding up a fuzzy logic library in java. I have found the equations for all the standard functions - Grade, inverseGrade, Triangle, Trapezoid, Gaussian. However, I can't find the inverse of the sigmoid/ logistic function.
The way I have written the logistic function is java is :
//f(x) = 1/(1+e(-x))
public double logistic(double x){
return (1/(1+(Math.exp(-x)));
}
But I can't work out or find the inverse anywhere.
My algebraic/calculus abilities are fairly limited, hence why I haven't been able to work out the inverse of the function.
Any hints or pointers would be a big help.
Thanks
If
y = 1/(1+exp(-x))
then
x = ln(y/(1-y))
Just to go through the steps:
y = 1/(1 + exp(-x))
1 + exp(-x) = 1/y
exp(-x) = 1/y - 1
exp(-x) = 1/y - y/y
exp(-x) = (1 - y)/y
ln(exp(-x)) = ln((1 - y)/y)
-x = ln((1 - y)/y)
x = -ln((1 - y)/y)
x = ln(y/(1 - y))