1

I'm trying to solve a constraint maximization problem with bounds in scipy minimize SLSQP. But why am I getting this message: 'Singular matrix C in LSQ subproblem'? How to resolve this? When I'm removing the constraint and trying to minimize the objective function it's working fine but when I'm trying to maximize it, it shows 'Positive directional derivative for linesearch'. Code follows below:

#Import libs
import numpy as np 
import matplotlib.pyplot as plt 
from scipy.optimize import minimize, Bounds

#Initial activity level
x0 = np.array([60, 40])

#Revenue function
def revenue(X):
    dollarperTRx = 300
    coeff_x1 = 0.234
    coeff_x2 = 0.127
    predwo= 1.245
    nhcp = 400
    r = dollarperTRx * nhcp * predwo * (pow(1 + (1+ X[0]),coeff_x1)) * (pow((1 + X[1]),coeff_x2))
    return r 

#Objective function
def objective(X, sign = -1.0):
    return sign * revenue(X)

#Spend
cost_per_promo = np.array([400, 600])
def spend(X):
    return np.dot(cost_per_promo, x0.transpose()) 

#Initial Spend
s0 = spend(x0)

#Spend constraint
def spend_constraint(X):
    return spend(X) - s0

#Getting the constraints into a dictionary
cons = ({'type':'eq', 'fun': spend_constraint})    

#Bounds
bounds1 = (30, 90)
bounds2 = (20, 60)

#Optimize
minimize(objective, x0, method='SLSQP', constraints = cons, bounds = (bounds1, bounds2))
Soutir
  • 11
  • 4
  • 2
    Possible duplicate of [scipy minimize SLSQP - 'Singular matrix C in LSQ subproblem'](https://stackoverflow.com/questions/56222292/scipy-minimize-slsqp-singular-matrix-c-in-lsq-subproblem) – aliaksei Nov 24 '19 at 16:53

1 Answers1

0

Your spend function does not depend on your design vector, therefore your constraint also does not depend on it. This makes the problem singular. I changed X0 to the current design vector in your example, that way it converges. You have to verify, if that is what you meant to do with the constraint. But with X0 it always gives 0.

#Import libs
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize, Bounds

#Initial activity level
x0 = np.array([60, 40])


#Revenue function
def revenue(X):
    dollarperTRx = 300
    coeff_x1 = 0.234
    coeff_x2 = 0.127
    predwo= 1.245
    nhcp = 400
    r = dollarperTRx * nhcp * predwo * (pow(1 + (1+ X[0]),coeff_x1)) * (pow((1 + X[1]),coeff_x2))
    return r

revenue0 = revenue(x0)

#Objective function
def objective(X):
    return -revenue(X) / revenue0

#Spend
cost_per_promo = np.array([400., 600.])
def spend(X):
    return np.dot(cost_per_promo, X.transpose())

#Initial Spend
s0 = spend(x0)

#Spend constraint
def spend_constraint(X):
    return spend(X) - s0

#Getting the constraints into a dictionary
cons = ({'type':'eq', 'fun': spend_constraint})

#Bounds
bounds1 = (30., 90.)
bounds2 = (20., 60.)

#Optimize
res = minimize(objective, x0, method='SLSQP',
               constraints = cons,
               bounds = (bounds1, bounds2))
print(res)

Results in:

     fun: -1.0157910949030706
     jac: array([-0.00297113, -0.00444862])
 message: 'Optimization terminated successfully.'
    nfev: 36
     nit: 9
    njev: 9
  status: 0
 success: True
       x: array([78.0015639, 27.9989574])
onodip
  • 635
  • 7
  • 12