0

I am trying to add quadratic constraints to a docplex model however it is interpreting them as linear and giving me error messages.

below is a excerpt from the script

here is the quadratic constraint:

mdl.add_constraints((mdl.sum(Allocation[o,p] * Folds[o,p] for o in rangeOils) == proddf['Demand'][p] for p in rangeProd))

here is where it sits

rangeOils = range(nb_Oils)
rangeProd = range(nb_Products)

#this is our decision variable it containts a matrix of the oils and the products
Allocation = mdl.continuous_var_matrix(keys1=nb_Oils, keys2=nb_Products, lb=0)


#this is another decision variable  it contains a matrix of the folding an oil needs in a product 
Folds = mdl.continuous_var_matrix(keys1=nb_Oils, keys2=nb_Products, lb=1)


#adding demand constraint - demand must be met even after a product is folded
mdl.add_constraints((mdl.sum(Allocation[o,p] * Folds[o,p] for o in rangeOils) == proddf['Demand'][p] for p in rangeProd))

any help would be massively appreciated

here is the error

DOcplexException: Expecting linear constraint, got: x1*x155+x3*x157+x5*x159+x7*x161+x9*x163+x11*x165+x13*x167+x15*x169+x17*x171+x19*x173+x21*x175+x23*x177+x25*x179+x27*x181+x29*x183+x31*x185+x33*x187+x35*x189+x37*x191+x39*x193+x41*x195+x43*x197+x45*x199+x47*x201+x49*x203+x51*x205+x53*x207+x55*x209+x57*x211+x59*x213+x61*x215+x63*x217+x65*x219+x67*x221+x69*x223+x71*x225+x73*x227+x75*x229+x77*x231+x79*x233+x81*x235+x83*x237+x85*x239+x87*x241+x89*x243+x91*x245+x93*x247+x95*x249+x97*x251+x99*x253+x101*x255+x103*x257+x105*x259+x107*x261+x109*x263+x111*x265+x113*x267+x115*x269+x117*x271+x119*x273+x121*x275+x123*x277+x125*x279+x127*x281+x129*x283+x131*x285+x133*x287+x135*x289+x137*x291+x139*x293+x141*x295+x143*x297+x145*x299+x147*x301+x149*x303+x151*x305+x153*x307 == 500000 with type: <class 'docplex.mp.constr.QuadraticConstraint'>
Copaq
  • 27
  • 4

1 Answers1

1

Not very nice syntax but the following should work:

for p in rangeProd:
  mdl.add_constraint(mdl.sum(Allocation[o,p] * Folds[o,p] for o in rangeOils) == proddf['Demand'][p])

Performance-wise this should be fine since at the engine level constraints are added one-by-one anyway.

Apparently there is a problem with add_constraints() because in the code below some statements fail unexpectedly:

with Model() as m:
    x = m.continuous_var()
    y = m.continuous_var()
    # This works
    m.add_constraint(m.sum([x * y]) <= 1)
    # This works
    for i in range(3):
        m.add_constraint(m.sum([x * y]) <= i)
    # This fails
    m.add_constraints((m.sum([x * y]) <= i for i in range(3)))
    # This fails
    m.add_constraints([m.sum([x * y]) <= i for i in range(3)])
Daniel Junglas
  • 5,830
  • 1
  • 5
  • 22
  • Hi Daniel, Thanks. That now compiles but the model strangely wont solve. If i replace Folds[o,p] with just the value 1 the model will solve and that implies there is a solution for folds matix i.e. all values in it would be 1. Do you have any idea why the model wont solve with this line in it? – Copaq Aug 05 '20 at 13:58
  • What exactly do you mean by "won't solve"? Do you get an error or does the solver go off into an infinite loop? Or does it make progress but just not enough? One thing to observe is that you have quadratic equality constraints. These are not convex and if CPLEX does not manage to get rid of them in presolve then it will fail to solve the model and you should get an error. – Daniel Junglas Aug 05 '20 at 14:22
  • 'Solve Failed'. I assume that I assume this is due to your latter point. Do you have any idea to get around this or would you have any material you could point to regarding this. – Copaq Aug 05 '20 at 14:27
  • Confirmed - yes its because model is not convex – Copaq Aug 05 '20 at 14:34
  • Two things come to mind: (1) You could change your constraints to inequality. For example, assuming that `Allocation` and `Folds` both incur some sort of penalty (for example cost) in case they are non-zero, you could replace `==` by `>=`. Since the variables incur cost, the solver will attempt to satisfy the constraint at equality. However, `>=` is maybe not what you need to make the constraint convex, you may need `<=`. (2) If one of the involved variables is binary then you could reformulate your problem using auxiliary variables and just get rid of the product of variables. – Daniel Junglas Aug 05 '20 at 14:54
  • The CPLEX documentation explains the concepts of convex quadratic constraints. You can search here https://www.ibm.com/support/knowledgecenter/SSSA5P_12.10.0/ilog.odms.studio.help/Optimization_Studio/topics/COS_home.html (currently the server seems down, so I cannot give the exact link). – Daniel Junglas Aug 05 '20 at 14:56