Apache Commons Math: restricting optimization domain - java

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.

Related

Python scipy.optimize.leastsq to Java org.apache.commons.math3.fitting.leastsquares

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.

Convert a long to an int cutting off the overflow

I want to cast a long value to an int value and if the long value is too big to fit into an int it should just be the the biggest possible int value. My solution looks like that:
long longVar = ...;
int intVar = (int) Math.min(longVar, Integer.MAX_VALUE)
In a more general way (to include the negative maximum) it would be:
long longVar = ...;
int intVar = (int) (longVar < 0 ? Math.max(longVar, Integer.MIN_VALUE) : Math.min(longVar, Integer.MAX_VALUE));
Is there an easier way to do this, like a method in the JRE or something?
An improvement would be
int intVar = (int) Math.min(Math.max(longVar, Integer.MIN_VALUE),
Integer.MAX_VALUE));
Math.max would make [Long.Min,Long.Max] => [Int.Min, Long.Max] and whatever outcome of that, if it is greater than Int.Max will be trimmed down by the outer Math.min to [Int.Min, Int.Max].
I don't know of a ready-to-go method doing this included in java.
The java 8 method Math.toIntExact will throw an exception on overflow. And using that to do this - well, I'd consider it a misuse of exceptions. And probably less efficient than above construct.
If you can use Guava, there is a method that does exactly what you want: static int Ints.saturatedCast(long):
long longVar = ...;
int intVar = Ints.saturatedCast(longVar);
For general interest, there's the Wikipedia article on saturation arithmetic. The Intel MMX instruction set uses saturation arithmetic and I think Intel offer an SDK to allow Java developers to use MMX. I'm not sure if Guava implements its methods using this SDK (probably not).
You can also write some reusable code.
package it.stackoverflow;
public class UtilInt {
public static int getIntMaxMinLong(long longNumber){
int intNumber = 0;
if (longNumber < Integer.MIN_VALUE )
intNumber = Integer.MIN_VALUE;
else if (longNumber > Integer.MAX_VALUE)
intNumber = Integer.MAX_VALUE;
else
intNumber = (int) longNumber;
return intNumber;
}
}
You can call the method in the static way.
package it.stackoverflow;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int intNewValue = UtilInt.getIntMaxMinLong(224748223647L);
}
}

How do I create symbolic variables/functions involving vectors using JScience?

How do I create symbolic variables/functions involving vectors using JScience? Creating float variables is easy:
Variable<Float64> varX = Variable.local<Float64>("x");
How can I do the same for a vector? Once I have a vector variable, how do I create
a Polynomial involving that vector (say, by using Euclidean distance)?
Given a Vector<Float64> of coefficients, you can construct a Polynomial<Float64> as shown below. As shown here, the highest order coefficient is first for convenience in applying Horner's scheme.
public static Polynomial<Float64> create(Vector<Float64> v) {
Variable<Float64> x = new Variable.Local<Float64>("x");
Polynomial<Float64> px = Polynomial.valueOf(Float64.ZERO, x);
for (int i = 0, e = v.getDimension() - 1; i < v.getDimension(); i++, e--) {
px = px.plus(Polynomial.valueOf(v.get(i), Term.valueOf(x, e)));
}
return px;
}
Typical usage:
Polynomial<Float64> px = create(Float64Vector.valueOf(3, 2, 1));
System.out.println(px);
System.out.println(px.evaluate(Float64.ONE));
Console:
[3.0]x² + [2.0]x + [1.0]
6.0

How can I find the bucketid when using GeospatialCoordinateEncoder in htm.java

The function for finding bucketid encoder.getBucketIndices() require a double or string of input value.
However, the input value of the GeospatialCoordinateEncoder is bucket[] which contain longitude and lantitude, and another double speed.
How can I solve these problem?
Here is the code:
public int[] getBucketIndices(double input) {}
public int[] getBucketIndices(String input) {}
the problem is the input value for the GeospatialCoordinateEncoder is :
int[] encoding1 = encode(ge, new double[] { -122.229194, 37.486782 }, speed);// ge is GeospatialCoordinateEncoder
public int[] encode(CoordinateEncoder encoder, double[] coordinate, double radius) {
int[] output = new int[encoder.getWidth()];// return n/** number of bits in the representation (must be >= w) */
encoder.encodeIntoArray(new Tuple(coordinate[0], coordinate[1], radius), output);
return output;//
}
the get bucketid function
int bucketIdx = encoder.getBucketIndices(value)[0];
we haven't forgotten about you. The answer is that so far this functionality was never developed for the GeospatialCoordinateEncoder in either its Java or Python version. We're discussing the implementation of this now - when we decide something, I'll post the github issue link here (if StackOverflow allows questions to be resolved in this manner).

Can The 5-Op Log2(Int 32) Bit Hack be Done in Java?

Just to clarify this is NOT a homework question as I've seen similar accusations leveled against other bit-hackish questions:
That said, I have this bit hack in C:
#include <stdio.h>
const int __FLOAT_WORD_ORDER = 0;
const int __LITTLE_END = 0;
// Finds log-base 2 of 32-bit integer
int log2hack(int v)
{
union { unsigned int u[2]; double d; } t; // temp
t.u[0]=0;
t.u[1]=0;
t.d=0.0;
t.u[__FLOAT_WORD_ORDER==__LITTLE_END] = 0x43300000;
t.u[__FLOAT_WORD_ORDER!=__LITTLE_END] = v;
t.d -= 4503599627370496.0;
return (t.u[__FLOAT_WORD_ORDER==__LITTLE_END] >> 20) - 0x3FF;
}
int main ()
{
int i = 25; //Log2n(25) = 4
int j = 33; //Log2n(33) = 5
printf("Log2n(25)=%i!\n",
log2hack(25));
printf("Log2n(33)=%i!\n",
log2hack(33));
return 0;
}
I want to convert this to Java. So far what I have is:
public int log2Hack(int n)
{
int r; // result of log_2(v) goes here
int[] u = new int [2];
double d = 0.0;
if (BitonicSorterForArbitraryN.__FLOAT_WORD_ORDER==
BitonicSorterForArbitraryN.LITTLE_ENDIAN)
{
u[1] = 0x43300000;
u[0] = n;
}
else
{
u[0] = 0x43300000;
u[1] = n;
}
d -= 4503599627370496.0;
if (BitonicSorterForArbitraryN.__FLOAT_WORD_ORDER==
BitonicSorterForArbitraryN.LITTLE_ENDIAN)
r = (u[1] >> 20) - 0x3FF;
else
r = (u[0] >> 20) - 0x3FF;
return r;
}
(Note it's inside a bitonic sorting class of mine...)
Anyhow, when I run this for the same values 33 and 25, I get 52 in each cases.
I know Java's integers are signed, so I'm pretty sure that has something to do with why this is failing. Does anyone have any ideas how I can get this 5-op, 32-bit integer log 2 to work in Java?
P.S. For the record, the technique is not mine, I borrowed it from here:
http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogIEEE64Float
If you're in Java, can't you simply do 31 - Integer(v).numberOfLeadingZeros()? If they implement this using __builtin_clz it should be fast.
I think you did not get the meaning of that code. The C code uses a union - a struct that maps the same memory to two or more different fields. That makes it possible to access the storage allocated for the double as integers. In your Java code, you don't use an union but two different variables that are mapped to different parts of memory. This makes the hack fail.
As Java has no unions, you had to use serialization to get the results you want. Since that is quite slow, why not use another method to calculate the logarithm?
You are using the union to convert your pair of ints into a double with the same bit pattern. In Java, you can do that with Double.longBitsToDouble, and then convert back with Double.doubleToLongBits. Java is always (or at least gives the impression of always being) big-endian, so you don't need the endianness check.
That said, my attempt to adapt your code into Java didn't work. The signedness of Java integers might be a problem.

Categories

Resources