creating two kinds of dependent variable using cplex and java - java

I am new to work by CPLEX. My simplified optimization problem is:
objective function:
Maximize z1 + z2 + z3
Subject to:
c1: x1 - 3 x2 + x3 <= 30
c2: x1 + x2 + x3 >= z1
...
Bounds
x1=[0,1]
x2=[0,1]
...
To model this problem, my code is:
public static void main(String[] args) {
try {
IloCplex cplex = new IloCplex();
IloNumVar[] z = cplex.numVarArray(3, 0.0, 1.0);
IloLinearNumExpr objectiveExpr = cplex.linearNumExpr();
IloLinearNumExpr constraintExpr1 = cplex.linearNumExpr();
IloLinearNumExpr constraintExpr3 = cplex.linearNumExpr();
IloNumVar[] x = cplex.numVarArray(3, 0.0, 1.0);
for (int i = 1; i < 3; i++){
objectiveExpr.addTerm(1, z[i]);
}
IloObjective obj = cplex.maximize(objectiveExpr);
cplex.add(obj);
constraintExpr1.addTerm(1, x[1]);
constraintExpr1.addTerm(-3, x[2]);
constraintExpr1.addTerm(1, x[3]);
cplex.addLe(constraintExpr1, 30);
constraintExpr2.addTerm(-1, x[1]);
constraintExpr2.addTerm(1, x[2]);
constraintExpr2.addTerm(1, x[3]);
cplex.addGe(constraintExpr2, z[1]);
.
.
.
}
catch (IloException e){
System.err.println("Concert exception '" + e + "' caught");
}
}
The generated model of this code is:
objective function:
Maximize x1 + 2 x2 + 3 x3
Subject To:
c1: x7 - 3 x8 + x9 <= 30
c2: - x1 - x7 + x8 + x9 <= 0
Bounds
0 <= x1 <= 1
...
If it starts to model the constraints from x4 instead of x7, I could distinguish x and z easily.

Unlike David, I do know CPLEX for about 17 years, but I also don't understand what your problem is. Can you explain in what way the generated model is different from what you expected - we can probably work this out ourselves, but it seems daft for potentially many of us to have to spend extra time understanding your problem when you could explain better.
Can I suggest that you name your variables and constraints using setName(...) so that you can see better what is happening in the generated model.

Related

How do I easily implement the Matlab percentile in Java?

I need to replicate the Matlab Percentile ( https://www.mathworks.com/help/stats/prctile.html ) for a simple case
percentile(double[] arr, int percentile) in java. I am unable to find any implementations which give me the same result since it seems to have a percentile along with linear interpolation.
Any help or guidance is appreciated!
By directly applying the definition (you can found in the page you've linked)
// `xs` must be sorted
double percentile(double [] xs, int p) {
// The sorted elements in X are taken as the 100(0.5/n)th, 100(1.5/n)th, ..., 100([n – 0.5]/n)th percentiles.
int i = (int) (p * xs.length / 100.0 - 0.5);
// Linear interpolation uses linear polynomials to find yi = f(xi), the values of the underlying function
// Y = f(X) at the points in the vector or array x. Given the data points (x1, y1) and (x2, y2), where
// y1 = f(x1) and y2 = f(x2), linear interpolation finds y = f(x) for a given x between x1 and x2 as follows:
return xs[i] + (xs[i + 1] - xs[i]) * (p / 100.0 - (i + 0.5) / xs.length) / ((i + 1.5) / xs.length - (i + 0.5) / xs.length);
}
using the example on that page
double [] xs1 = new double[] {6.0753, 8.6678, 0.4823, 6.7243, 5.6375, 2.3846, 4.1328, 5.6852, 12.1568, 10.5389};
Arrays.sort(xs1);
double r = percentile(xs1, 42);
System.out.println("Result: " + r);
System.out.println("Error: " + Math.abs(r - 5.6709));
you get
Result: 5.67089
Error: 9.999999999621423E-6
The #josejuan's answer is very good: but is it not necessary to handle the case in which i is equal to xs.length - 1? I would modify the return formula of percentile function as follows:
return i != (xs.length - 1) ? xs[i] + (xs[i + 1] - xs[i]) * (p / 100.0 - (i + 0.5) / xs.length) / ((i + 1.5) / xs.length - (i + 0.5) / xs.length) : xs[i];

How to calculate points on a line at intervals

I am coding a game and want a projectile to go from one location to the next moving at intervals every frame.
I've been playing around with the slope-intercept method of determining things and I'm getting close, but I am stuck.
Here is my code so far:
animationFrame = refresh;
double x, y, xPerF; //Values for drawing
double m, b; //Value for slope and y-intercept
double x1, x2, y1, y2; //Values for the targets
x1 = getCenterX();
x2 = Canvas.target[shotTarget].getCenterX();
y1 = getCenterY();
y2 = Canvas.target[shotTarget].getCenterY();
xPerF = Point2D.distance(x1, y1, x2, y2)/animationSpeed;
//Calculate slope
if(x2>x1) m = (y2-y1)/(x2-x1);
else if(x2<x1) m = (y1-y2)/(x1-x2);
else m = 0;
//Calculate the y-intercept
b = m * x1 - y1;
if(b<0) b = -b + Canvas.myHeight;
else {
b -= Canvas.myHeight;
if(b<0) b = -b;
}
//Calculate the x value
if(x1>x2) x = x1 - (xPerF * animationFrame);
else if(x1<x2) x = x1 + (xPerF * animationFrame);
else x = x1;
//Calculate the y value
if(m!=0) y = (m * x + b) - Canvas.myHeight;
else {
if(y1>y2) y = y1 - (xPerF * animationFrame);
else y = y1 + (xPerF * animationFrame);
}
g.fillOval((int) x - 15, (int) y - 15, 30, 30);
//Debugging
System.out.println("Frame " + animationFrame + " of " + animationSpeed + " | " + y + " = " + m + " * " + x + " + " + b + " | at speed of " + xPerF);
Updated
I expect the animation to end at the target location, but it always either overshoots or is right on target. It mainly overshoots when the target is pretty kind of straight above the tower, give or take a few x co-ordinates. I have worked this out to be a quadrant 1 x-y plane and I believe the problem I have now lies with how I am calculating my slope. Thanks!
Outdated
Here is a mini applet to demonstrate: https://drive.google.com/file/d/1fCTFJzulY1fcBUmdV6AXOd7Ol1g9B3lo/view?usp=sharing
Click on each target to target it
I believe your approach is fundamentally flawed. It is prone to rounding errors which might be a source for overshoots. It is also hard to make work well under real world where your application is not the only one so CPU might be in high demand and some frames might be skipped, and so on. The better approach is to use time rather than frames as the main driver of the events. Your main method drawScene accepts current time as one of its arguments. When any animation starts, you save the time when it started. Then, the job becomes much easier. For example for linear animation it would be something like this:
double animationPart = (currentTime - animationStartTime) / totalAnimationDuration;
// fix rounding error
if (animationPart > 1.0)
animationPart = 1.0;
double xCur = xStart * (1.0 - animationPart) + xEnd * animationPart;
double yCur = yStart * (1.0 - animationPart) + yEnd * animationPart;
P.S. the "time" doesn't have to be real time, it might be some other "game time" if it somehow makes more sense but still this approach is IMHO much easier to implement correctly.
Update
I'd say that the overall code quality is rather bad. Concerns are badly separated, there are a lot of magic numbers, and global static things. For example, having to two bullets in flight will be not easy to implement in this code.
There are also some real bugs in animation code. Some obvious bugs are:
xPerF is calculated wrongly. You divide the Euclidean distance instead of just difference in the X-coordinate.
Logic for the y is flawed. At least you should add m * (x - x1) instead of m * x. But it still won't cover the case of a vertical shoot (i.e. the case when the X-coordinate is not changed at all). If you want to go this way, you should use xPerF and yPerF and get rid of the m and the related if's.
This might or might not fix the animation issues (at list you still will have a potential for rounding errors). I'd still say that changing your shoot to something like
public void shootTarget(int target) {
shotTarget = target;
shotTime = animationFrame;
}
and then using
double animationPart = ((double) (animationFrame - shotTime)) / animationSpeed;
as suggested above is a better way. Note: this is only a stub because in your real code you for some reason regularly assign 0 to refresh and thus to animationFrame so it won't work that easy.
Answer
I figured it out. Instead of calculating the coordinates with slope-intercept method, I simply calculated the intervals I would have to increment y and x per frame and incremented them based on the frame of the animation.
double x, y, xPerF, yPerF; //Values for drawing
double x1, x2, y1, y2; //Values for the targets
x1 = getCenterX();
x2 = Canvas.target[shotTarget].getCenterX();
y1 = getCenterY();
y2 = Canvas.target[shotTarget].getCenterY();
xPerF = (Math.max(x1, x2) - Math.min(x1, x2))/animationSpeed;
yPerF = (Math.max(y1, y2) - Math.min(y1, y2))/animationSpeed;
if(x1>x2) x = x1 - xPerF * animationFrame;
else if(x1<x2) x = x1 + xPerF * animationFrame;
else x = x1;
if(y1>y2) y = y1 - yPerF * animationFrame;
else if(y1<y2) y = y1 + yPerF * animationFrame;
else y = y1;
g.fillOval((int) x - 15, (int) y - 15, 30, 30);

How to solve a given optimization task with JOptimizer or any other Java library?

I have got such an optimization problem:
min a * x1^2 + b * x2^2 + c*x3^2 + d * x1*x2 + e * x1*x3 + f * x2*x3
s.t.
x1 + x2 + x3 + x4 = 1
x1, x2, x3, x4 >= 0
where a,b,c,d,e,f are given double type numbers
Could you help me to solve it using a Java library (for example JOptimizer)? I have been trying to find something proper recently, but I didn't manage..
Take a look at the first example shown at http://www.joptimizer.com/quadraticProgramming.html.
Your P matrix is:
P={{a, d/2, e/2, 0},{d/2, b, f/2, 0},{e/2, f/2, c, 0},{0, 0, 0, 1}}
And the following is almost the same as in the example.
PS: in order to have a convex problem the P matrix must be positive, that is:
(c d^2)/4 - (b e^2)/4 + (d e f)/4 - (a f^2)/4 > 0

distance between two points in processing app?

I try to get the distance between two points in http://processing.org/ is like java but dont works:
d = sqrt ((x2 - x1)**2 + (y2 - y1)**2);
the distance formula is:
http://www.purplemath.com/modules/xyplane/dist07b.gif
Java doesn't have an exponentiation operator. Instead, try Math.pow(x, 2) or x*x.
Processing already comes with a function to calculate the distance between two points in 2d and 3d. Just implement dist() as mentioned in the reference by handing over your x and y parameters of both points:
dist (x1, y1, x2, y2);
You've got a couple of things a bit wrong. It should be:
d = sqrt ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
other options:
d = dist(x1,y1,x2,y2);
or
d = PVector.dist(new PVector(x1,y1),new PVector(x2,y2));
Imagine you're distance as the hypothenuse of a right angled triangle.
One side is defined by the X axis (it's length is x2-x1) and the other by
the Y axis (it's length is y2-y1). Since the distance is the hypothenuse,
and you know the sides, you simply apply Pythagoras theorem:
BC squared = AB squared + AC squared
BC = square root (AB squared + AC squared)
AC = (x2-x1) = dx
AB = (y2-y1) = dy
or
d = sqrt(dx*dx + dy*dy);
According to http://processing.org/reference/ this should work:
d = sqrt ( pow ( x2 - x1, 2 ) + pow ( y2 - y1, 2 ) );
Although I'm not totally clear if you need this in Processing or in Java.
Just use the built-in Processing classes and methods:
PVector x = new PVector(random(width), random(height));
PVector y = new PVector(random(width), random(height));
System.out.println(getEuclidianDistance(x, y))
Use the build in dist function from processing: http://processing.org/reference/dist_.html.
Btw, this is the way it works internally: http://www.google.com/codesearch#Ej56LtI_pY0/trunk/processing/core/src/processing/core/PApplet.java&q=dist%20package:http://processing%5C.googlecode%5C.com&ct=rc&cd=8&sq=&l=3314

get values for a polynomical function from excel in java

I have a chart in excel that represents some value over a one day period. So I add the reference function and I get something like this:
y = 1E-13x6 - 2E-10x5 + 8E-08x4 - 1E-05x3 + 0,0004x2 + 0,0275x + 8,414
A mesure in my data set is:
09:36:21 => 5,27
The firts thing I need to know is how to transform the timestamp into a value to give to the function. After some cell value transforming I've found out that excel gives timestamps a representation between 0.00000 and 0.99999, so for example 09:36:21 is 0.400243055555556. Then I've coded a little java test script:
double x = 0.400243055555556;
double x6 = (1*Math.pow(10, -13))*Math.pow(x, 6);
double x5 = (2*Math.pow(10, -10))*Math.pow(x, 5);
double x4 = (8*Math.pow(10, -8))*Math.pow(x, 4);
double x3 = (1*Math.pow(10, -5))*Math.pow(x, 3);
double x2 = (4*Math.pow(10, -4))*Math.pow(x, 2);
double y = x6 - x5 + x4 - x3 + x2 + 0.0275*x + 8.414;
But after executing this script I get y = 8.425070122712738. So this is obviously not working. I must say that all the values in the chart range from 5 to 12.
I'm obviously doing something wrong, but I don't know what. Maybe I've coded the function badly, or maybe the x I'm choosing is not a right value, but something is wrong. Can anyone help?
Update: My code wasn't that good, what duffymo suggested worked better. But the problem was that Excel was giving my the wrong tendendy line. I've managed to get the good one using a scatter graph.
I would not recommend coding it this way - roundoff could be an issue.
I would recommend Horner scheme:
I coded it this way and got the same answer that you did:
public class Horner
{
public static final NumberFormat DEFAULT_FORMAT = new DecimalFormat("0.000");
public static void main(String[] args)
{
double [] a = { 8.414, 0.0275, 0.0004, -1.0e-5, 8.0e-8, -2.0e-10, 1.0e-13 };
for (double x = 0.0; x < 1.0; x += 0.05)
{
double y = a[0] + x*(a[1] + x*(a[2] + x*(a[3] + x*(a[4] + x*(a[5])))));
System.out.println("x = " + DEFAULT_FORMAT.format(x) + " y = " + DEFAULT_FORMAT.format(y));
}
}
}
Here's the result I get. The higher order terms aren't doing much good; the coefficients are small, and when you raise a fraction to a power it diminishes the effect even more.
x = 0.000 y = 8.414
x = 0.050 y = 8.415
x = 0.100 y = 8.417
x = 0.150 y = 8.418
x = 0.200 y = 8.420
x = 0.250 y = 8.421
x = 0.300 y = 8.422
x = 0.350 y = 8.424
x = 0.400 y = 8.425
x = 0.450 y = 8.426
x = 0.500 y = 8.428
x = 0.550 y = 8.429
x = 0.600 y = 8.431
x = 0.650 y = 8.432
x = 0.700 y = 8.433
x = 0.750 y = 8.435
x = 0.800 y = 8.436
x = 0.850 y = 8.438
x = 0.900 y = 8.439
x = 0.950 y = 8.440
Still not what you want, but I think the coding is far simpler.

Categories