Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.

 View Only
Expand all | Collapse all

Boolean var to tell whether a float var is null or not

  • 1.  Boolean var to tell whether a float var is null or not

    Posted Mon April 23, 2012 07:28 AM

    Originally posted by: SystemAdmin


    My code is very simple (see below)
    It is a debts program. D[i] represent what the person i should pay (or be paid if negative)
    I want to minimize the number or transactions.
    So my y[s] variable is true if x[s] (which represents the amount of money from s.i to s.j) is not null.

    But cplex returns to me a solution with y=0 and x!=0, I cannot understand.
    Constraints (1) and (2) should be violated !!!

    Thanks for your concern !
    Adrien

    tuple pair {int i; int j;}

    int n = ...;
    range N = 1..n;
    {pair} S = {<i,j> | i,j in N : i<j};
    {pair} Ik in N = { s | s in S : s.i==k};
    {pair} Jk in N = { s | s in S : s.j==k};

    float D[N] = ...;

    int M = 1000000;

    dvar float x[S];
    dvar boolean y[S];

    minimize sum(s in S) y[s];

    subject to{
    forall( i in N)
    sum(s in J[i]) x[s] - sum(s in J[i]) x[s] == D[i];
    forall (s in S)
    {
    x[s] <= M * y[s]; (1)
    x[s] >= - M * y[s]; (2)
    }
    }
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 2.  Re: Boolean var to tell whether a float var is null or not

    Posted Mon April 23, 2012 11:29 AM

    Originally posted by: SystemAdmin


    What are the values you observe for y=0 and "x != 0" mean? Is it possible that x is "almost" zero, like 1e-10? And what is y? Is it really 0 or is it only very close to 0?
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 3.  Re: Boolean var to tell whether a float var is null or not

    Posted Mon April 23, 2012 12:12 PM

    Originally posted by: SystemAdmin


    Hi, thanks for awsering !

    To begin with, here's the data I used for the test :
    n = 6;
    D = http://0 12 3 -5 -12.4 2.4;

    y is a boolean that should assure that x is non null and is, in the result, all false (so x is null everywhere...)
    But there are 4 non null values for x, which are : 1.3, 0.2, 6, 1.2

    (
    In fact for this data, cplex returns me a no solution warning, so I used a different model for x and y wich is x[N][
    N] and y[N][N], but I don't like it cause it is redundant...
    Same constraints plus x[i][j]=-x[j][i] and x[i][i]=0
    There is a solution there (WHY????) but it violates (1) and (2) constraints
    )

    Thanks,
    Hope you'll understand
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 4.  Re: Boolean var to tell whether a float var is null or not

    Posted Mon April 23, 2012 01:14 PM

    Originally posted by: SystemAdmin


    Sorry, I did not understand completely how your second model looks like. Could you post it here?
    But I know why your first model is infeasible. The problem is this constraint:
    forall( i in N)
      sum(s in J[i]) x[s] - sum(s in J[i]) x[s] == D[i];
    

    The two terms on the left-hand side are the same so the left-hand side is always 0. As soon as there is an index 'i' for which 'D[i]' is not 0 this constraint cannot be satisfied.
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 5.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 04:00 AM

    Originally posted by: SystemAdmin


    You're right about the J[i], it was a I[i]....
    But still, now that I corrected it, there still are some strange behaviour...
    Here is the code (quite the same as my frst post) :

    tuple pair {int i; int j;}
    int n = ...;
    range N = 1..n;
    {pair} S = {<i,j> | i,j in N : i<j};
    {pair} Ik in N = { s | s in S : s.i==k};
    {pair} Jk in N = { s | s in S : s.j==k};
    float D[N] = ...;
    int M = 1000000;
    dvar float x[S];
    dvar boolean y[S];
    minimize sum(s in S) y[s];
    subject to{
    forall( i in N)
    sum(s in I[i]) x[s] - sum(s in J[i]) x[s] == D[i];
    forall (s in S)
    {
    x[s] <= M * y[s];
    x[s] >= - M * y[s];
    }
    }

    I give you the whole thing so that everuthing is clear...

    And with these values of D :
    i D[i]
    1 0
    2 12
    3 3
    4 -5
    5 -12.4
    6 2.4
    I get these ( y x) values :

    : y / x
    <1 2> : 0 / -9.79999999998836
    <1 3> : 0 / -0.200000000011642
    <1 4> : 0 / 0
    <1 5> : 1 / 10
    <1 6> : 0 / 0
    <2 3> : 0 / 0
    <2 4> : 0 / 2.20000000001164
    <2 5> : 0 / 0
    <2 6> : 0 / 0
    <3 4> : 1 / 2.79999999998836
    <3 5> : 0 / 0
    <3 6> : 0 / 0
    <4 5> : 0 / 0
    <4 6> : 0 / 0
    <5 6> : 0 / -2.4

    There are a few null y with non null x...
    Hope it's clear enough

    Thanks for reading
    Adrien

    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 6.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 04:53 AM

    Originally posted by: SystemAdmin


    You are facing numerical problems. Internally CPLEX uses double precision floating point numbers to represent all values, even integral values. When you export your model to an LP file and solve it explicitly with the interactive optimizer you get something like this:
    
    Variable Name           Solution Value y(
    {1,2
    })                      0.000010 y(
    {1,3
    })                      0.000000 y(
    {1,5
    })                      0.999998 y(
    {2,4
    }) 0.000002 y(
    {3,4
    })                      1.000000 y(
    {5,6
    })                      0.000002 x(
    {1,2
    })                     -9.800000 x(
    {1,3
    })                     -0.200000 x(
    {1,5
    })                     10.000000 x(
    {2,4
    })                      2.200000 x(
    {3,4
    })                      2.800000 x(
    {5,6
    })                     -2.400000
    

    As you can see, the boolean variable 'y({1,2})' has value 1e-5 which is close to zero. By default, CPLEX considers values for integer variables as integer if their absolute value does not exceed 1e-5. So what you have here is y({1,2}) = 1e-5, so CPLEX considers this as integral 0. On the other hand you have x({1,2}) = -9.8 and -9.8 >= 1e-5 * M, so the constraint is satisfied. As you can see, the problem is numerical roundoff, i.e., the fact that y({1,2}) is considered as 0 but is not quite 0. There are two ways to work around this problem:
    1. Change CPLEX's integrality tolerance from 1e-5 to something smaller. This can be changed in a settings file by changing "Mathematical Programming"->"Mixed Integer Programming"->"Tolerances"->"Integrality Tolerance". Setting this to 1e-9 gave consistent results for me.
    2. Use indicator constraints. Instead of defining your own 'M' you can rewrite the constraint
    
    sum(s in I[i]) x[s] - sum(s in J[i]) x[s] == D[i]; forall (s in S) 
    { x[s] <= M * y[s]; x[s] >= - M * y[s]; 
    }
    

    to read
    
    sum(s in I[i]) x[s] - sum(s in J[i]) x[s] == D[i]; forall (s in S) 
    { y[s] == 0 => x[s] == 0; 
    }
    

    This uses the "implication" logical constraint (see here) and says "if y is 0 then x must also be 0". This does not use an explicit big M in the formulation and is less likely to suffer from numerical issues.
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 7.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 05:15 AM

    Originally posted by: SystemAdmin


    That, my dear Daniel, is what I call an answer !

    Thanks a lot a lot for both solving my problem and teaching me some interesting facts about cplex...

    But still, I don't see why does cplex use a float (32/64 bits) to represent a boolean when only 1 bit is enough...

    Anyway, you did a great job here (not sure you need me to tell you but anyway)

    Thanks again
    Adrien
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 8.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 05:15 AM

    Originally posted by: SystemAdmin


    That, my dear Daniel, is what I call an answer !

    Thanks a lot a lot for both solving my problem and teaching me some interesting facts about cplex...

    But still, I don't see why does cplex use a float (32/64 bits) to represent a boolean when only 1 bit is enough...

    Anyway, you did a great job here (not sure you need me to tell you but anyway)

    Thanks again
    Adrien
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 9.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 05:15 AM

    Originally posted by: SystemAdmin


    That, my dear Daniel, is what I call an answer !

    Thanks a lot a lot for both solving my problem and teaching me some interesting facts about cplex...

    But still, I don't see why does cplex use a float (32/64 bits) to represent a boolean when only 1 bit is enough...

    Anyway, you did a great job here (not sure you need me to tell you but anyway)

    Thanks again
    Adrien
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 10.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 05:15 AM

    Originally posted by: SystemAdmin


    That, my dear Daniel, is what I call an answer !

    Thanks a lot a lot for both solving my problem and teaching me some interesting facts about cplex...

    But still, I don't see why does cplex use a float (32/64 bits) to represent a boolean when only 1 bit is enough...

    Anyway, you did a great job here (not sure you need me to tell you but anyway)

    Thanks again
    Adrien
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 11.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue April 24, 2012 06:32 AM

    Originally posted by: SystemAdmin


    > But still, I don't see why does cplex use a float (32/64 bits) to represent a boolean when only 1 bit is enough...
    >
    That is a technical detail. The branch-and-bound algorithm implemented in CPLEX makes use of linear relaxations. A linear relaxation of your problem is the original problem with all integrality constraints removed. In this relaxation a boolean 0-1 variable is now a continuous variable that can attain all values between 0 and 1. That is why CPLEX eventually needs to represent a boolean variable as a floating point number. You could look up descriptions of the "branch and bound" algorithm to learn more about that (the one here may be a good starter).

    > Anyway, you did a great job here (not sure you need me to tell you but anyway)
    >
    Thanks!
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 12.  how to solve a MICQP containing the product of two boolean variables in C++

    Posted Wed April 25, 2012 06:02 AM

    Originally posted by: Ximenes


    How to solve a MICQP containing the product of two boolean variables in C++ ? When I debug the code, it reported an error that it cann't extract the extractables.
    Then, I tried to use another variable to represent the product, but it reported that the Q is not positive semi-definite. The specific source file are written in C++ as the attarchment.

    Thanks very much.
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 13.  Re: how to solve a MICQP containing the product of two boolean variables in C++

    Posted Wed April 25, 2012 07:07 AM

    Originally posted by: SystemAdmin


    If you have a product of 2 booleans x*y, then z=x*y, with the following constraints :
    z <= x
    z <= y
    z >= x + y - 1
    z >= 0

    If z is in the objective fonction, you need only 2 of the 4 constraints, depending on whether it is a maximization or minimization...
    And z does not need to be of boolean type, if x and y are, you can set z to be float.

    Moreover, if you have constraints like :
    forall j, sum(i) a(i,j) * x(i) <= b(j)
    you can transform them into :
    forall j, sum(i) a(i,j) * z(i,j) <= b(j) * y(j)
    to have a better bound...

    Hope I helped and not said anything wrong....
    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 14.  Re: Boolean var to tell whether a float var is null or not

    Posted Tue August 07, 2012 07:09 PM

    Originally posted by: osarood


    Hello

    I am having the exact same problem. But I am writing my model using Pyomo (which is a python API). It does not have the => (imply) operator. Can you tell me what are you using to write your model. I tried using .mod file with ampl but it doesnt take the => operator.
    Sorry for the basic question as I am a newbie

    Thanks
    #DecisionOptimization
    #OPLusingCPLEXOptimizer