Home > Net >  docplex does not support square root np.sqrt(x), please suggest an alternative solution
docplex does not support square root np.sqrt(x), please suggest an alternative solution

Time:12-23

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")
  • Related