简体   繁体   中英

How to add and remove constraints in CPLEX-python?

I new using Cplex in python. I already know how to code a mathematical optimization problem correctly and create a function to show the solution friendly (F1). Currently, I want to modify some features of the model without creating a new model. My idea is solving a model P, then a model P1 (changing the decision variables domain), P2 (relaxing some set o constraints), and so on. I would like to have the solution of those models using my function F1.

My code is the following:

import time
import numpy as np
import cplex
from cplex import Cplex
from cplex.exceptions import CplexError
import sys
from openpyxl import Workbook
import xlrd

def GAP_RL(I,J,data):
    #TIEMPO INICIAL
    inicio=time.process_time() #------------------------------- INICIO DEL CONTEO DE TIEMPO
    #CONJUNTOS
    maquinas=range(I)  #CONJUNTO DE TRABAJOS
    trabajos=range(J)  #CONJUNTO DE MÁQUINAS
    #print("MÁQUINAS={} | TRABAJOS= {} |\n".format(list(maquinas),list(trabajos)))
    print("\n")
    #PARÁMETROS
    wb = Workbook()
    ws = wb.active
    book = xlrd.open_workbook(data+'.xlsx')           
    sheet = book.sheet_by_name("c")
    c_a=[[int(sheet.cell_value(r,c)) for c in range(sheet.ncols)] for r in range(sheet.nrows)]
    c_a=np.matrix(c_a)  
    print("COSTO DE ASIGNACIÓN")      
    print("")         
    print(c_a) # ------------------------------------------------ COSTO DE ASIGNACIÓN
    print("\n")
    sheet = book.sheet_by_name("a")
    a=[[int(sheet.cell_value(r,c)) for c in range(sheet.ncols)] for r in range(sheet.nrows)]
    a=np.matrix(a)  
    print("UTILIZACIÓN")      
    print("")         
    print(a) #---------------------------------------------------- REQUERIMIENTOS   
    print("\n")
    sheet = book.sheet_by_name("b")
    b=[[int(sheet.cell_value(r,c)) for c in range(sheet.ncols)] for r in range(sheet.nrows)]
    b=np.matrix(b)  
    print("DISPONIBILIDAD")      
    print("")         
    print(b) #---------------------------------------------------- CAPACIDAD MÁXIMA DE PROCESO
    print("\n")

    Model=cplex.Cplex()                                                  #CREACIÓN DEL MODELO.

    Model.parameters.mip.tolerances.integrality.set(0)                   #ESPECIFICA LA CANTIDAD POR LA CUAL UNA 
                                                                         #VARIABLE ENTERA PUEDE SER DIFERENTE DE UN 
                                                                         #ENTERO Y AÚN ASÍ CONSIDERASE FACTIBLE
    Model.objective.set_sense(Model.objective.sense.minimize)            #SENTIDO DE OPTIMIZACIÓN.

    #Model.parameters.timelimit.set(float(7200))                         #TIEMPO MÁXIMO DE EJECUCIÓN [SEGUNDOS].

    #Model.parameters.mip.tolerances.mipgap.set(float(0.1))              #GAP DE TÉRMINO.

    #VARIABLES DE DECISIÓN
    x_vars=np.array([["x("+str(i)+","+str(j)+")" for j in trabajos] for i in maquinas])
    x_varnames = x_vars.flatten()
    x_vartypes='B'*I*J
    x_varlb = [0.0]*len(x_varnames)
    x_varub = [1.0]*len(x_varnames)
    x_varobj = []
    for i in maquinas:
        for j in trabajos:
            x_varobj.append(float(c_a[i,j]))
    Model.variables.add(obj = x_varobj, lb = x_varlb, ub = x_varub, types = x_vartypes, names = x_varnames)
    #RESTRICCIONES

    #PRIMER CONJUNTO DE RESTRICCIONES: CADA TRABAJO ES ASIGNADO A UNA ÚNICA MÁQUINA.
    for j in trabajos:
        row1=[]
        val1=[]
        for i in maquinas:
            row1.append(x_vars[i,j])
            val1.append(float(1.0))
        Model.linear_constraints.add(lin_expr = [cplex.SparsePair(ind = row1, val= val1)], senses = 'E', rhs = [float(1.0)])

    #SEGUNDO CONJUNTO DE RESTRICCIONES: LAS ASIGNACIONES DE TRABAJOS CONSIDERAN LA CAPACIDAD MÁXIMA DE PROCESAMIENTO DE LAS MÁQUINAS
    for i in maquinas:
        row2=[]
        val2=[]
        for j in trabajos:
            row2.append(x_vars[i,j])
            val2.append(float(a[i,j]))
        Model.linear_constraints.add(lin_expr = [cplex.SparsePair(ind = row2, val= val2)], senses = 'L', rhs = [float(b[i])])
    #RESOLVER MODELO Y EXPANDIR
    solution=Model.solve() 
    Model.write('modelo_GAP.lp') 
    #MOSTRAR SOLUCION
    def show_solution():
        print("--------------------------------------------------------------------------------------------------------------")
        print("\nVALOR FUNCIÓN OBJETIVO - COSTO TOTAL DE ASIGNACIÓN = {}".format(Model.solution.get_objective_value()))
        print("--------------------------------------------------------------------------------------------------------------")

        for i in maquinas:
            for j in trabajos:
                if(Model.solution.get_values("x("+str(i)+","+str(j)+")")!=0.0):
                    print("x("+str(i+1)+","+str(j+1)+")"+" = "+str(Model.solution.get_values("x("+str(i)+","+str(j)+")")))
        fin=time.process_time()
        tiempo=float(fin)-float(inicio)
        print("")
        print("TIEMPO DE CÓMPUTO [s]= ", float(tiempo))
    show_solution()
GAP_RL(I=2,J=7,data='data')

The data file is the following:

The matrix c_a is the following: 在此处输入图像描述

The matrix a is the following: 在此处输入图像描述

The matrix b is the following: 在此处输入图像描述

So I would like to know how to make those changes in my model which is written in that way. Thanks in advance.

Here are a few tips to get you headed in the right direction:

  1. The add methods (eg, Cplex.variables.add , Cplex.linear_constraints.add ) return an iterator containing the indices that were added to the model. You can use this to remember the indices for classes of variables or constraints that you want to modify. For example:

     varind = list(Model.variables.add(obj = x_varobj, lb = x_varlb, ub = x_varub, types = x_vartypes, names = x_varnames))
  2. Alternately, if you give names to the variables/constraints, you can query or modify them by name. This can result in a performance hit, though, so read this section in the User's Manual.

  3. You can change the lower and upper bounds of variables using Cplex.variables.set_lower_bounds and Cplex.variables.set_upper_bounds .

  4. You can remove linear constraints with Cplex.linear_constraints.delete .

  5. Finally, you can create a copy (aka clone) of your model by passing an existing model to the Cplex constructor. For example:

     Model1 = cplex.Cplex(Model)

you can do that very easily with the docplex python API.

from docplex.mp.model import Model

# original model

mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
mdl.minimize(nbbus40*500 + nbbus30*400)

mdl.solve()



for v in mdl.iter_integer_vars():
    print(v," = ",v.solution_value)

#now remove the constraint

print()
print("now 0 kids instead of 300")    

mdl.get_constraint_by_name("kids").rhs=0;
mdl.solve()

for v in mdl.iter_integer_vars():
    print(v," = ",v.solution_value)

# and now let 's adapt to Covid19 1 seat out of 2

print("now 40 seats buses take 20 children and same ratio for 30 seats buses") 

mdl.add_constraint(nbbus40*20 + nbbus30*15 >= 300, 'kidsCov19')

mdl.solve()

for v in mdl.iter_integer_vars():
    print(v," = ",v.solution_value)

which gives

nbBus40  =  6.0
nbBus30  =  2.0

now 0 kids instead of 300
nbBus40  =  0
nbBus30  =  0
now 40 seats buses take 20 children and same ratio for 30 seats buses
nbBus40  =  15.0
nbBus30  =  0

I have used the zoo and bus example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM