Cgal quadratic programming objective function - c++

I am trying to minimize a function like the following:
25*x^2 + 45*x*y + y^2
and similar constraints like:
(25 + y) + 25*x <= 1
in CGAL::Quadratic_program.
To input "25x^2" and "y^2" in the objective function I can do the following:
qp.set_d(X, X, 50);
qp.set_d(Y, Y, 2);
but what about "45*x*y" ?
And how to add this constraint "(25 + y) + 25*x <= 1"
In my opinion like this, but i am not sure with 25:
qp.set_a(X, 0, 25);
qp.set_a(Y, 0, 1);
qp.set_b(0, 1);
One solution should be to update function to this form "y + 25*x <= -24"
qp.set_a(X, 0, 25);
qp.set_a(Y, 0, 1);
qp.set_b(0, -24);
(Please in constraint correct me if i am wrong)
I will be gratefull for any advices, expecially with "45*x*y" problem.

Your approach with replacing "(25 + y) + 25*x <= 1" by "y + 25*x <= -24" is obviously correct.
For objective function try:
qp.set_d(X, Y, 90);
but your matrix D:
25 22.5
22.5 1
is not positive semidefinite, so the solver may fail.

Related

Numerical instability creating wrong result on Mixed-Integer Linear Program, bug or error?

I created a bug ticket for Google or-tools Java library.
I was told it is a feature of Mixed-Integer solvers.
But those results for this simple program makes me think it is a bug, since I would have to round every coefficients in order to not get a wrong result.
Program:
Minimize epsPlus + epsMinus
x, y : integer
epsPlus, epsMinus : linear
19 <= x <= 23
21 <= y <= 47
x + y <= 60
x - 0.499999999y - epsPlus + epsMinus = 0
Results with different y coefficients on the last constraint:
0.499999990 working : objective=0.000000, x=20.000000, y=40.000000, epsPlus=0.000000, epsMinus=0.000000
0.499999999 failing : objective=1.500000, x=19.000000, y=41.000000, epsPlus=0.000000, epsMinus=1.500000
0.500000000 working : objective=0.000000, x=20.000000, y=40.000000, epsPlus=0.000000, epsMinus=0.000000
Can you confirm it is not a bug?
Minimal code:
Loader.loadNativeLibraries();
MPSolver solver = MPSolver.createSolver("SCIP");
// variables
MPVariable x = solver.makeIntVar(19, 23, "x");
MPVariable y = solver.makeIntVar(21, 47, "y");
MPVariable epsPlus = solver.makeNumVar(0, Double.POSITIVE_INFINITY, "epsPlus");
MPVariable epsMinus = solver.makeNumVar(0, Double.POSITIVE_INFINITY, "epsMinus");
// constraints
MPConstraint constraint1 = solver.makeConstraint(60, 60, "constraint1");
constraint1.setCoefficient(x, 1);
constraint1.setCoefficient(y, 1);
MPConstraint constraint2 = solver.makeConstraint(0, 0, "constraint2");
constraint2.setCoefficient(x, 1);
constraint2.setCoefficient(y, -0.499999999);
constraint2.setCoefficient(epsPlus, -1);
constraint2.setCoefficient(epsMinus, 1);
// objective
MPObjective objective = solver.objective();
objective.setCoefficient(epsPlus, 1);
objective.setCoefficient(epsMinus, 1);
objective.setMinimization();
// result
solver.solve();
System.out.println(String.format("objective=%f, x=%f, y=%f, epsPlus=%f, epsMinus=%f", objective.value(), x.solutionValue(), y.solutionValue(), epsPlus.solutionValue(), epsMinus.solutionValue()));
https://github.com/google/or-tools/issues/3098
Thanks :)

How to solve "X^2 - Y is perfect square, X, Y ≤ N" in O(sqrt(N)) time complexity? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 1 year ago.
Improve this question
Given N. Find number of all the integer pairs x, y such that
1<=x, y<=N
and x^2 - y is a perfect square
the N is large but O(sqrt(N)) will be fine to solve this problem.
I tried to solve this problem like, letting z^2 be the square number
x^2 - z^2 = y = (x+z)(x-z)
then let x + z = p and x - z = q;
then x = (p+q)/2 and z = (p-q)/2;
and (p+q)/2<=N;
and p and q should have same parity (both even or odd as (p+q)/2 is integer)
also pq<=N
Now I don't know how to proceed from here
or tell me some other method to solve this problem efficiently.
This solution solves the problem in O(sqrt N).
Rephrasing the problem
Let z^2 = x^2 - y, z ≥ 0, or equivalently 0 < y = x^2 - z^2 ≤ N
We need pairs of perfect squares under N^2 whose differences are less than or equal to N. By arithmetic series,
1 + 3 + 5 + 7 + ... + (2k - 1) = k^2
That means x^2 - z^2 is a sum of some n consecutive odd integers.
Counting odd integers
z^2 + (2z + 1) + (2z + 3) + ... + (2x - 1) = x^2. Apply arithmetic series formula
z^2 + n/2 * (4z + 2 + 2(n - 1)) = x^2
z^2 + n * (2z + n) = x^2
n(2z + n) ≤ N
z ≤ floor((N/n - n)/2)
We are thus able to find the last values of z for which at least n+1 odd consecutive integers are needed for their sum to exceed N.
For each z, the x can be z+1, z+2 ... z+n, for a total of n pairs.
#include <cmath>
#include <iostream>
int N = 99;
int main(void){
int z = -1;
// z = 0 is valid for x^2 < N, so -1 is largest invalid z.
int count = 0;
for (int n = std::sqrt(N); n > 0; n--){
int zNew = (N/n - n)/2;
// zNew is max z that has n perfect squares from z + 1 to z + n
count += (zNew - z) * n;
z = zNew;
}
std::cout << count << '\n';
}
A version in Java passed these unit tests.
(N, count) = (1, 1), (3, 2), (5, 4), (8, 6), (60, 68), (99, 124), (500, 808)

Graphtheory. How to approach these kinds of problems? I want to know the logic and the way one needs to think while trying to solve this.

Find the number of paths on the Cartesian plane from (0, 0) to (n, n), which never raises above the y = x line. It is possible to make three types of moves along the path:
move up, i.e. from (i, j) to (i, j + 1);
move to the right, i.e. from (i, j) to (i + 1, j);
the right-up move, i.e. from (i, j) to (i + 1, j + 1)
Path count 101
First, we solve a simpler problem:
Find the number of paths on the Cartesian plane from (0, 0) to (n, n) with:
move up, i.e. from (i, j) to (i, j + 1);
move to the right, i.e. from (i, j) to (i + 1, j);
and we can go to grid which x < y.
How to solve it? Too Hard? Okay, we try to find the number of paths from (0, 0) to (2, 2) first. We could draw all paths in a grid:
We define
f(x,y) => the number of paths from (0, 0) to (x, y)
You can see the path to (2, 2) from either (1, 2) or (1, 2), so we can get:
f(2, 2) = f(2, 1) + f(1, 2)
And then you will notice for point(x, y), its path from either (x, y - 1) or (x - 1, y). That's very natural, since we have only two possible moves:
move up, i.e. from (i, j) to (i, j + 1);
move to the right, i.e. from (i, j) to (i + 1, j);
I draw a larger illustration for you, and you can check our conclusion:
So we can get that:
f(x, y) = f(x, y - 1) + f(x - 1, y)
Wait... What if x = 0 or y = 0? That's quite direct:
if x = 0 => f(x, y) = f(x, y - 1)
if y = 0 => f(x, y) = f(x - 1, y)
The last... How about f(0, 0)? We define:
f(0, 0) = 1
since there just 1 path from (0,0) to (1,0) and (0, 1).
OK, summarise:
f(x, y) = f(x, y - 1) + f(x - 1, y)
if x = 0 => f(x, y) = f(x, y - 1)
if y = 0 => f(x, y) = f(x - 1, y)
f(0, 0) = 1
And by recursion, we can solve that problem.
Your problem
Now let's discuss your original problem, just modify our equations a little bit:
f(x, y) = f(x, y - 1) + f(x - 1, y) + f(x - 1, y - 1)
if x = 0 => f(x, y) = f(x, y - 1)
if y = 0 => f(x, y) = f(x - 1, y)
if x < y => f(x, y) = 0
f(0, 0) = 1
and it will result my code.
The last thing I add to my code is Memoization. In short, Memoization can eliminate the repeat calculation -- if we have calculated f(x,y) already, just store it in a dictionary and never calculate it again. You can read the wiki page for a further learning.
So, that's all of my code. If you still get some questions, you can leave a comment here, and I will reply it as soon as possible.
Code:
d = {} # Memoization
def find(x, y):
if x == 0 and y == 0:
return 1
if x < y:
return 0
if d.get((x, y)) is not None:
return d.get((x, y))
ret = 0
if x > 0:
ret += find(x - 1, y)
if y > 0:
ret += find(x, y - 1)
if x > 0 and y > 0:
ret += find(x - 1, y - 1)
d[(x, y)] = ret
return ret
print find(2, 1) # 4
For additional ideas for solving problems such as this one, there is a mathematical curiosity that is in 1-1 correspondence with not only the sequences produced by lattice walks where one's steps must remain below the line x = y, but a veritable plethora, of fantastical mathematical beasts that cut a wide swath of applicability to problem solving and research.
What are these curiosities?
Catalan Numbers:
C_n = 1/(n+1)*(2n)Choose(n), n >= 0, where if n = 0, C_0 = 1.
They also count:
The number of expressions containing $n$ pairs of parentheses
eg. n = 3: ((())), (()()), (())(), ()(()), ()()()
Number of plane trees with n + 1 vertices
Number of Triangulations of a convex (n + 2)-gon
Monomials from the product: p(x1, ..., xn) = x1(x1 + x2)(x1 + x2 + x3) ... (x1 + ... + xn)
bipartite vertices of rooted planar trees
And soooo many more things
These object appear in a lot of active research in mathematical physics, for instance, which is an active area of algorithms research due to the enormous data sets.
So you never know what seemingly far flung concepts are intimately linked in some deep dark mathematical recess.

CGAL Quadratic Programming Solver, how to enter "x^4" in objective function? and in the constraints?

I am trying to minimize a function like the following:
a*x^4+b*y
and constraints like:
x^2 <= a
in CGAL::Quadratic_program.
To input "x^2" in the objective function I can do the following:
qp.set_d(X, X, 2);
but what about "x^4" ?
To add a constraint like "x<=a":
hp.set_a(X, 0, 1);
hp.set_b(0, a);
but what about "x^2 <= a" ?
The solution to solve this
kind of problems is to modify the objective function and constraints, in this case by setting z^2 = z.
//>=
Program hp(CGAL::LARGER, false, 0, false, 0);
//x+y >= -4
hp.set_a(X, 0, 1); hp.set_a(Y, 0, 1);
hp.set_b(0, -4);
//4x+2y+z^2 >= -a*b
//z^2 = z
hp.set_a(X, 1, 4); hp.set_a(Y, 1, 2); hp.set_a(Z, 1, 1);
hp.set_b(1, -a * b);
//-x + y >= −1
hp.set_a(X, 2, -1); hp.set_a(Y, 2, 1);
hp.set_b(2, -1);
//x <= 0
hp.set_a(X,3,1);
hp.set_b(3,0);
hp.set_r(3,CGAL::SMALLER);
//y <= 0
hp.set_a(Y,4,1);
hp.set_b(4,0);
hp.set_r(4,CGAL::SMALLER);
//objective function
//min a*x^2 + b*y + z^4
//z^2 = z
//min a*x^2 + b*y + z^2
hp.set_d(X, X, 2 * a); //2D
hp.set_c(Y, b);
hp.set_d(Z, Z, 2); //2D
// solve the program
Solution s = CGAL::solve_quadratic_program(hp, ET());
assert(s.solves_quadratic_program(hp));
From the given link:
This package lets you solve convex quadratic programs of the general
form ...
Why did you decide you can use quadratic solver to solve your power-of-four polynomial? Quadratic doesn't stand for "quadra" as a "four", it stands for a square as a "quadragon" and means power-of-two.
In short: you cannot use this tool to solve your problem.

Translating a float to a negative or positive

I have a float from 0 to 100 and I want to translate that into a number from -20 to 20 an example:
float is 100 then translated it would be -20
float is 50 then translated it would be 0
float is 0 then translated it would be 20
What is the best method of doing this?
[I'm going to give you the approach to figuring this out, rather than just the answer, because it'll be more useful in the long-run.]
You need a linear transform, of the form y = mx + c, where x is your input number, y is your output number, and m and c are constants that you need to determine ahead of time.
To do so, you need to solve the following simultaneous equations:
-20 = m * 100 + c
+20 = m * 0 + c
Note that I've picked two of your required transformation examples, and plugged them into the equation. I could have picked any two.
How about this: (50. - x) * 0.4
Something like this should do:
20 - val * 0.4
float procent = (myval - 50)/2.5f;
use (int) floor(procent) if you need integers...
float translate(float f)
{
return 20.0f - ((20.0f * f) / 50.0f);
}
What you want to achieve is called "Linear interpolation" and can be done in a general function like this:
float linear_interpolate(float x, float x0, float x1, float y0, float y1)
{
return y0 + (x - x0)*((y1-y0)/(x1-x0));
}
In your case you would call it like (replace x with your in value):
float value = linear_interpolate(x, 0.0f, 100.0f, -20.0f, 20.0f);
See http://en.wikipedia.org/wiki/Linear_interpolation for a reference article.
((x / 2.5)- 20) * -1
this should do it
You need to calculate the slope. Since you have already 3 points (0, -20) (50, 0) (100, 20), you can do dx = 40/100 = 2/5 (change in y / change in x) and b = -20. Then you define a function (f(x) = mx + b) f(x) = (2/5)*x - 20, 0 <= x <= 100.