import com.dashoptimization.DefaultMessageListener; import com.dashoptimization.IntHolder; import com.dashoptimization.XPRSconstants; import com.dashoptimization.XPRSenumerations.ObjSense; import com.dashoptimization.XPRSprob; import com.dashoptimization.XPRSprob.VecMapDeltaFunction; import com.dashoptimization.XPRSprob.VecMapDeltaFunctor; import java.util.ArrayList; /** Code example that uses a user function of type "vecmapdelta".
Xpress Optimizer Examples ========================= Maximize the area of polygon of N vertices and diameter of 1 The position of vertices is indicated as (rho,theta) coordinates where rho denotes the distance to the base point (vertex with number N) and theta the angle from the x-axis. (c) 2021-2025 Fair Isaac CorporationPolygon example: maximise the area of an N sided polygon *** Demonstrating using a simple map (R^2->R) userfunction ***
Variables:
rho : 0..N-1 ! Distance of vertex from the base point
theta : 0..N-1 ! Angle from x-axis
Objective:
(sum (i in 1..N-2) (rho(i)*rho(i-1)*sin(theta(i)-theta(i-1)))) * 0,5
Constraints:
Vertices in increasing degree order:
theta(i) >= theta(i-1) +.0001 : i = 1..N-2
Boundary conditions:
theta(N-1) <= Pi
0,1 <= rho(i) <= 1 : i = 0..N-2
Third side of all triangles <= 1
rho(i)^2 + rho(j)^2 - rho(i)*rho(j)*2*cos(theta(j)-theta(i)) <= 1 : i in 0..N-3, j in i..N-2
*
* In this example we create two user functions that take two arguments each.
* One computes the sine of the difference of its arguments, the other computes
* the cosine of the difference of its arguments.
*/
public final class PolygonVecMapDelta {
/** User function that maps two doubles to a double.
* Computes sin(x[0] - x[1]).
* In addition to the function evaluated at the given point we must
* also provide the value of the partial derivatives evaluated at the
* given value.
*/
private static final VecMapDeltaFunctor mySinDiff = new VecMapDeltaFunctor() {
@Override
public double map(double[] value, double[] delta, double[] partial) {
if (delta != null) {
if (delta[0] != 0.0)
partial[0] = Math.cos(value[0] - value[1]);
if (delta[1] != 0.0)
partial[1] = -Math.cos(value[0] - value[1]);
}
return Math.sin(value[0] - value[1]);
}
};
/** Function that maps two doubles to a double.
* Computes cos(x[0] - x[1]).
* As opposed to {@link #mySinDiff} this is implemented as plain (static)
* function and added using PolygonVecMapDelta::myCosDiff later.
* The same could be done with instance methods as well.
*/
private static double myCosDiff(double[] value, double[] delta, double[] partial) {
if (delta != null) {
if (delta[0] != 0.0)
partial[0] = -Math.sin(value[0] - value[1]);
if (delta[1] != 0.0)
partial[1] = Math.sin(value[0] - value[1]);
}
return Math.cos(value[0] - value[1]);
}
public static void main(String[] args) {
try (XPRSprob prob = new XPRSprob(null)) {
prob.addMessageListener(new DefaultMessageListener());
// Number of sides of the Polygon
int nSide = 5;
// Theta
int[] theta = prob.varArray('C', nSide - 1, 0.0, Math.PI,
i -> String.format("THETA%d", i + 1));
// Rho
int[] rho = prob.varArray('C', nSide - 1, 0.01, 1.0,
i -> String.format("RHO%d", i + 1));
// Add the user functions.
// Both user functions take 2 input arguments. This must be
// specified here.
VecMapDeltaFunction sinDiff = prob.nlpAddUserFunction("mySinDiff", 2, 0, mySinDiff);
VecMapDeltaFunction cosDiff = prob.nlpAddUserFunction("myCosDiff", 2, 0, PolygonVecMapDelta::myCosDiff);
// Objective function. We build the objective function as
// a formula in infix notation. See below for submitting a
// formula as string.
// Tokens are always integers, while values may be integers
// (for example operator or delimiter constants) or double
// values (actual numbers). That is why the `val` list has
// elements of type Number.
ArrayList