I have implemented docplex model with python, everything goes well: problem formulation, variables, constraints and objective function. The problem raised when I tried to compute Euclidian distance Between two centers of circles, simply numpy can do it np.sqrt((x2-x1)**2 (y2-y1)**2). please suggest me how to resolve this issue, I could not find quadratic equation for Euclidian distance without using square roots.
Working code attached, were you can see the issue at constraint 1.
from docplex.mp.model import Model
import numpy as np
def packing_cplex(CDA, R, H, items):
# continuous variables x,y range from -R to R
x = [ CDA.continuous_var(name="x{}:".format(i), lb=-R, ub=R)
for i in range(len(items))]
y = [ CDA.continuous_var(name="y{}:".format(i), lb=-R, ub=R)
for i in range(len(items))]
# integer variable z range from 0 to H
z = [ CDA.integer_var(name="z{}:".format(i), lb=0, ub=H)
for i in range(len(items))]
# indicator denotes whether an item is packed into the container
# i=1, .., n, values 1/0
d = [ CDA.binary_var(name="d{}:".format(i))
for i in range(len(items))]
# sqrt root issue--> np.sqrt((x[i]**2 y[i]**2))
# 1.constraint packed items and container radius
CDA.add_quadratic_constraints(R >= (items[i][0] (x[i]**2 y[i]**2)**1 )
for i in range(len(items)))
# 2.constraint packed items and container height
for i in range(len(items)):
CDA.add( CDA.if_then( d[i]==1, H >= ( items[i][1] z[i] ) ) )
# objective maximise max∑_(i=0 .. n-1 (π * ri^2 * hi * di)
CDA.set_objective("max", np.sum([d[i] * np.pi * items[i][0]**2 * items[i][1]
for i in range(len(items))]))
# radius and height of cylinder container
R, H = 3, 2
volume = np.pi * R**2 * H
# pack, [(ri,hi), ... ([rn,hn]) where ri/hi is radius/height of item
items = [(1,2),(1,2),(1,2),(1,2),(1,2),(1,2),(1,2)]
CDA = Model(name='CDA')
packing_cplex(CDA, R, H, items)
CDA.print_information()
solution = CDA.solve()
utilization = solution._objective / volume
print('Utilization (%) ', utilization)
I expect alternative solution for square roots
CodePudding user response:
If you have non linear functions you can use CPOptimizer within cplex.
For instance, https://github.com/AlexFleischerParis/zoodocplex/blob/master/zoononlinear.py
Or with square root:
from docplex.cp.model import CpoModel
mdl = CpoModel(name='buses')
nbbus40 = mdl.integer_var(0,1000,name='nbBus40')
nbbus30 = mdl.integer_var(0,1000,name='nbBus30')
mdl.add(nbbus40*40 nbbus30*30 >= 300)
#non linear objective
mdl.minimize(mdl.power(nbbus40,0.5)*500 mdl.power(nbbus30,0.5)*400)
msol=mdl.solve()
print(msol[nbbus40]," buses 40 seats")
print(msol[nbbus30]," buses 30 seats")
And to handle your decimal variables see
https://github.com/AlexFleischerParis/zoodocplex/blob/master/zoodecimalcpo.py
from docplex.cp.model import CpoModel
mdl = CpoModel(name='buses')
#now suppose we can book a % of buses not only complete buses
scale=100
scalenbbus40 = mdl.integer_var(0,1000,name='scalenbBus40')
scalenbbus30 = mdl.integer_var(0,1000,name='scalenbBus30')
nbbus40= scalenbbus40 / scale
nbbus30= scalenbbus30 / scale
mdl.add(nbbus40*40 nbbus30*30 >= 310)
mdl.minimize(nbbus40*500 nbbus30*400)
msol=mdl.solve()
print(msol[scalenbbus40]/scale," buses 40 seats")
print(msol[scalenbbus30]/scale," buses 30 seats")