4

I would like linearizate the product of two float variables. Suppose that a model has the product x * y, where x and y are float, with 0 <= x <= 1 and 0 <= y <= 1. How linearizate this product?

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Ernando Gomes
  • 41
  • 1
  • 2
  • What do you mean by linearize? Or was it linearizate? – Mad Physicist Feb 28 '18 at 03:17
  • Also, what language? Cplex offers a number of alternatives to my understanding, and float can mean different things. – Mad Physicist Feb 28 '18 at 03:20
  • 1
    I am building a mathematical model on cplex, using c++, and I would like linearizate a constraint that has the product of two continuous variables. I have a constraint x * y (product of two variables), where domain this variable are 0 <= x <= 1 and 0 <= y <= 1. Linearizate is to transform this expression (x * y) into something that does not exist the multiplication of two variables – Ernando Gomes Feb 28 '18 at 03:40
  • 1
    Thanks for the clarification. Have you actually tried anything or done any research of your own? – Mad Physicist Feb 28 '18 at 04:22
  • 1
    I don't think you can exactly linearise that. You can approximate it with e.g. piecewise linear expressions. – TimChippingtonDerrick Feb 28 '18 at 07:14
  • Quadratic solvers are developed for a reason. – Erwin Kalvelagen Feb 28 '18 at 12:01

1 Answers1

4

I gave an example in OPL/CPLEX here What you can do is remember that

4*x*y=(x+y)*(x+y)-(x-y)(x-y)

So if you do a variable change X=x+y and Y=x-y

x*y

becomes

1/4*(X*X-Y*Y)

which is separable.

And then you are able to interpolate the function x*x by piecewise linear function:

// y=x*x interpolation



int sampleSize=10000;
float s=0;
float e=100;

float x[i in 0..sampleSize]=s+(e-s)*i/sampleSize;

int nbSegments=20;

float x2[i in 0..nbSegments]=(s)+(e-s)*i/nbSegments;
float y2[i in 0..nbSegments]=x2[i]*x2[i];

float firstSlope=0;
 float lastSlope=0;
 
 tuple breakpoint // y=f(x)
 {
  key float x;
  float y;
 }
 
 sorted { breakpoint } breakpoints={<x2[i],y2[i]> | i in 0..nbSegments};
 
 float slopesBeforeBreakpoint[b in breakpoints]=
 (b.x==first(breakpoints).x)
 ?firstSlope
 :(b.y-prev(breakpoints,b).y)/(b.x-prev(breakpoints,b).x);
 
 pwlFunction f=piecewise(b in breakpoints)
 { slopesBeforeBreakpoint[b]->b.x; lastSlope } (first(breakpoints).x, first(breakpoints).y);
 
 assert forall(b in breakpoints) f(b.x)==b.y;
 
 float maxError=max (i in 0..sampleSize) abs(x[i]*x[i]-f(x[i]));
 float averageError=1/(sampleSize+1)*sum (i in 0..sampleSize) abs(x[i]*x[i]-f(x[i]));
 
 execute
{
writeln("maxError = ",maxError);
writeln("averageError = ",averageError);
}

dvar float a in 0..10;
dvar float b in 0..10;
dvar float squareaplusb;
dvar float squareaminusb;

maximize a+b;
dvar float ab;
subject to
{
    ab<=10;
    ab==1/4*(squareaplusb-squareaminusb);
    
    squareaplusb==f(a+b);
    squareaminusb==f(a-b);
}
Alex Fleischer
  • 9,276
  • 2
  • 12
  • 15