Decision Optimization

Decision Optimization

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

 View Only
  • 1.  Python API change the variable type

    Posted Tue October 03, 2017 10:58 AM

    Originally posted by: felycite28


    Hello everyone ;

    I have MIP model on cplex , set the problem type as LP on Python and got the LP version of it and now I am studying on a sort of improvement heuristic which is based on initial relaxed solution .I have to change some specific des. variables to binary again and solve the model  again . I had applied this heuristic on opl by adding new constraint and playing with it according to iteration;here is the constraint we added:

    dvar float x[1..5] in 0..1;

    dvar boolean intx[1..5];           

    maximize sum(i in 1..5) x[i];
    subject to
    {            
      forall(i in 1..5)ctx:intx[i]-x[i]==0;

    }

    main

    {

    activate/desactivate the constraint and solve it

    }

    Question 1)Now ; on python ; Is there any other way to change the type of the variable instead of adding new constraint ?

    If there isn't; I tried to add it ( c is the model )

    c.add.variables(obj="what should I write here? ",lb=[0],ub=[1],type='C']  Naturally, I got an error

    and for constraint part , how will I link added fake float x and original boolean x of math model on cplex 

    Basically how will I turn above opl code to python ?

    2) If there is another easier way to change the variable type , I would be very happy if you can teach me ?

    Regards


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Python API change the variable type

    Posted Tue October 03, 2017 03:59 PM

    Hello,

    let me give you a smal example:

    Take this lp with 2 integer decision variables

    \ENCODING=ISO-8859-1
    \Problem name: Basic Configuration

    Maximize
     obj: 40 Gas + 50 Chloride
    Subject To
     ctMaxTotal:    Gas + Chloride <= 50
     ctMaxTotal2:   3 Gas + 4 Chloride <= 180
     ctMaxChloride: Chloride <= 40
    Bounds
          Gas >= 0
          Chloride >= 0
    Generals
     Gas  Chloride
    End

    and suppose you want to turn Gas into a continuous decision variable.

    import cplex
    import sys
    def sample1(filename):
        c=cplex.Cplex(filename)
        
        try:
            c.solve()
        except CplexSolverError:
            print ("Exception raised during solve")
            return
        
        status=c.solution.get_status()
        print ("Solution Status=", status),
        print (c.solution.status[status]);
        print ("Objective value=",c.solution.get_objective_value())
        print (c.variables.get_names())
        print(c.variables.get_lower_bounds("Gas"))
        print(c.get_problem_type())
        print(c.problem_type[c.get_problem_type()])
        print("Types:",c.variables.get_types())
        c.variables.set_types("Gas","C")
        print("Types:",c.variables.get_types())
        try:
            c.solve()
        except CplexSolverError:
            print ("Exception raised during solve")
            return
        
        status=c.solution.get_status()
        print ("Solution Status=", status),
        print (c.solution.status[status]);
        print ("Objective value=",c.solution.get_objective_value())

    sample1("volsay.lp")

    which would give a log where you first see

     

    MIP Presolve eliminated 1 rows and 0 columns.
    Reduced MIP has 2 rows, 2 columns, and 4 nonzeros.
    Reduced MIP has 0 binaries, 2 generals, 0 SOSs, and 0 indicators.

    and then later

     

    MILP
    Types: ['I', 'I']
    Types: ['C', 'I']
    2 of 2 MIP starts provided solutions.
    MIP start 'm1' defined initial solution with objective 2300.0000.
    Tried aggregator 1 time.
    MIP Presolve eliminated 1 rows and 0 columns.
    Reduced MIP has 2 rows, 2 columns, and 4 nonzeros.
    Reduced MIP has 0 binaries, 1 generals, 0 SOSs, and 0 indicators.

    regards

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Python API change the variable type

    Posted Tue October 03, 2017 05:24 PM

    Using c.variables.set_types, as Alex mentioned above, is indeed the way to change the variable type. One thing to keep in mind is the following (see CPXchgctype):

    If a variable is to be changed to binary, a call to CPXXchgbds/CPXchgbds should also be made to change the bounds to 0 (zero) and 1 (one).

    In the Python API, the bounds can be changed with c.variables.set_lower_bounds and c.variables.set_upper_bounds.

    Also, this may not apply in your case (taken from the same place in the documentation):

    If calls to CPXXchgctype/CPXchgctype change all the discrete variables in a MIP to continuous, the problem type still remains MIP. Use CPXXchgprobtype/CPXchgprobtype to change the problem type.

    In the Python API, you can change the problem type with c.set_problem_type.

    Finally, here is another subtlety to keep in mind when specifying the variable type while adding variables with c.variables.add (see CPXnewcols):

    xctype: An array of length ccnt containing the type of each of the new variables. Possible values appear in the table. This array may be NULL, in which case the new variables are created as continuous type. If this array is not NULL, then CPLEX interprets the problem as a MIP; in that case, the routine CPXXlpopt/CPXlpopt will return the error CPXERR_NOT_FOR_MIP.

    So, if you are trying to create an LP, do not specify the variable types when using c.variables.add.


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Python API change the variable type

    Posted Thu October 05, 2017 09:24 AM

    Originally posted by: felycite28


    Thank you Ryan ,

    I have a small question . I had already checked documents , I have a question about changing the type of a group of variable ; As I explained to Alex , I have variables in the "x(1)(1),x(1)(2),x(1)(3) ...." I want to make all of the x values binary . With the help of Alex , I could change the type of one variable.To change all of them I created list of them like this :

    for ma in range(5):
            for a in range(2):
                varname = "x(" + str(ma+1) + ")(" +str(a+1)+ ")"
                allxvars.append(varname)
        print allxvars

    and to change it i did,

     # c.variables.set_types(allxvars,"I") so I am getting error

    TypeError: in method 'intArray___setitem__', argument 3 of type 'int' First qustion how can I deal with this error ?

    Second, Is there any other easier or faster way to do it ?

    Because I checked your previous discussions , you were saying using indices instead of names might be faster . May be you can give me brillant ideas

    Thanks in advance

    Regards


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: Python API change the variable type

    Posted Thu October 05, 2017 07:25 PM

    For the first part, you need to provide a sequence of pairs to c.variables.set_types. For example:

    c.variables.set_types([("name1", "I"), ("name2", "I"), ("name3", "I")])
    

    With your example above, it may be easier to do something like the following (i.e., use a list comprehension):

    c.variables.set_types([(name, "I") for name in allvars])
    

    For the second part of your question, see this page in the user manual. In your case, you could do something like the following to build a dictionary:

    names2indices = {name:index for name, index                                     
                     in zip(c.variables.get_names(),                                
                            range(c.variables.get_num()))}
                           
    

    Then, convert all of the names into indices before passing them into CPLEX:

     

    c.variables.set_types([(names2indices[n], "I") for n in allxvars])
    

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: Python API change the variable type

    Posted Fri October 06, 2017 11:26 AM

    Originally posted by: felycite28


    Million thanks Ryan , I learned  a lot , it works !!


     


    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: Python API change the variable type

    Posted Wed October 04, 2017 01:04 PM

    Originally posted by: felycite28


    Thank you Alex , you can not imagine how much you taught me from the beginning of the process.

    I had did the same thing for getting the names of variables, to change the type I had applied the

    c.variables.set_types() , too . I stucked  on a stupid place. For you , it is "Gas " which is obviuos .

    For my variables names  ; I am getting like in this structure (because the variable itself is x[m][t])

    'x(1)(1)', 'I(1)(1)', 'y(1)(1)'

    I could not know , how can I express x variable   in

    c.variables.set_types("Gas","C") 

    I tried:c.variables.set_types("x()()","C")  but the model could not find the variable

    They are details which are special for my model and hard to find an example to see how to express this specific one  , it is very easy and small detail but when you do not know it, the code does not work , you know, and it is easy to  get crazy , thats why I make you busy , sorry , but I am a good learner..

    Thanks in advance

    Regards

     

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: Python API change the variable type

    Posted Wed October 04, 2017 03:12 PM

    Hi,

    same idea with multi dimensions:

    dvar int+ Gas[1..2][1..2];
    dvar int+ Chloride[1..2][1..2];


    maximize
      sum(i,j in 1..2 )(40 * Gas[i,j] + 50 * Chloride[i,j]);
    subject to {
      forall(i,j in 1..2) ctMaxTotal:     
        Gas[i,j] + Chloride[i,j] <= 50;
      forall(i,j in 1..2 )ctMaxTotal2:    
        3 * Gas[i,j] + 4 * Chloride[i,j] <= 180;
      forall(i,j in 1..2 ) ctMaxChloride:  
        Chloride[i,j] <= 40;
    }

    execute
    {
    writeln("Chloride=",Chloride);
    writeln("Gas=",Gas);
    }

     

    will give

    Maximize
     obj: 40 Gas(1)(1) + 50 Chloride(1)(1) + 40 Gas(1)(2) + 50 Chloride(1)(2)
          + 40 Gas(2)(1) + 50 Chloride(2)(1) + 40 Gas(2)(2) + 50 Chloride(2)(2)
    Subject To
     ctMaxTotal(1)(1):    Gas(1)(1) + Chloride(1)(1) <= 50
     ctMaxTotal(1)(2):    Gas(1)(2) + Chloride(1)(2) <= 50
     ctMaxTotal(2)(1):    Gas(2)(1) + Chloride(2)(1) <= 50
     ctMaxTotal(2)(2):    Gas(2)(2) + Chloride(2)(2) <= 50
     ctMaxTotal2(1)(1):   3 Gas(1)(1) + 4 Chloride(1)(1) <= 180
     ctMaxTotal2(1)(2):   3 Gas(1)(2) + 4 Chloride(1)(2) <= 180
     ctMaxTotal2(2)(1):   3 Gas(2)(1) + 4 Chloride(2)(1) <= 180
     ctMaxTotal2(2)(2):   3 Gas(2)(2) + 4 Chloride(2)(2) <= 180
     ctMaxChloride(1)(1): Chloride(1)(1) <= 40
     ctMaxChloride(1)(2): Chloride(1)(2) <= 40
     ctMaxChloride(2)(1): Chloride(2)(1) <= 40
     ctMaxChloride(2)(2): Chloride(2)(2) <= 40
    Bounds
          Gas(1)(1) >= 0
          Chloride(1)(1) >= 0
          Gas(1)(2) >= 0
          Chloride(1)(2) >= 0
          Gas(2)(1) >= 0
          Chloride(2)(1) >= 0
          Gas(2)(2) >= 0
          Chloride(2)(2) >= 0
    Generals
     Gas(1)(1)  Chloride(1)(1)  Gas(1)(2)  Chloride(1)(2)  Gas(2)(1)
     Chloride(2)(1)  Gas(2)(2)  Chloride(2)(2)
    End

    and then

    import cplex
    import sys
    def sample1(filename):
        c=cplex.Cplex(filename)
        
        try:
            c.solve()
        except CplexSolverError:
            print ("Exception raised during solve")
            return
        
        status=c.solution.get_status()
        print ("Solution Status=", status),
        print (c.solution.status[status]);
        print ("Objective value=",c.solution.get_objective_value())
        print (c.variables.get_names())
        print(c.variables.get_lower_bounds("Gas(1)(1)"))
        print(c.get_problem_type())
        print(c.problem_type[c.get_problem_type()])
        print("Types:",c.variables.get_types())
        c.variables.set_types("Gas(1)(1)","C")
        print("Types:",c.variables.get_types())
        try:
            c.solve()
        except CplexSolverError:
            print ("Exception raised during solve")
            return
        
        status=c.solution.get_status()
        print ("Solution Status=", status),
        print (c.solution.status[status]);
        print ("Objective value=",c.solution.get_objective_value())

    sample1("volsay.lp")   

    will give

    Types: ['I', 'I', 'I', 'I', 'I', 'I', 'I', 'I']
    Types: ['C', 'I', 'I', 'I', 'I', 'I', 'I', 'I']

    regards


    #CPLEXOptimizers
    #DecisionOptimization


  • 9.  Re: Python API change the variable type

    Posted Thu October 05, 2017 09:27 AM

    Originally posted by: felycite28


    Thanks Alex , it worked !!! I am so happy; I asked another question to Ryan's answer ,  if you have good ideas, too,  I would like to learn them , too.

    Thanks in advance

    Regards
     


    #CPLEXOptimizers
    #DecisionOptimization