Kunal Mathur
Kunal Mathur

Reputation: 273

Unable to minimze in scipy when constraint equals zero

I have two arrays, one with amounts and the other with risk. I want to basically minimize the sum of the amounts and at the same time keep the sum of the risks the same. To do this, I want to multiply the Amount and Risk with a array of weights (which needs to be solved for).

from scipy.optimize import minimize
import numpy as np

#Array of Amounts
Amount = np.array([10000000,-2000000,400000000,60000000])

#Array of Risk
Risk = np.array([-10000,5000,-20000,500])

#Minimize the sum of Amounts
def Objective(weights):
    x = weights * Amount
    return np.sum(x)

#While keeping the sum of Risks constant i.e Sum of New Weighted Risk - Sum of Old weighted risk = 0
def Cons1(weights):
    x = weights*Risk
    return np.sum(x)-np.sum(Risk)
    
#Create Constraint
cons = ({'type': 'eq', 'fun':Cons1})

#Give Initial Guess 
guess = np.array([0.25,0.25,0.25,0.25])
     
#Minimize 
minimize(Objective,guess,constraints=cons)

The result I get is:

     fun: -2.1834331315418437e+18
     jac: array([0., 0., 0., 0.])
 message: 'Singular matrix C in LSQ subproblem'
    nfev: 18
     nit: 3
    njev: 3
  status: 6
 success: False
       x: array([ 9.32859191e+09, -4.14243499e+09, -4.78072085e+09, -6.21192636e+09])

When I use the solver on Excel (Simplex LP), I get a viable result: Using guess weights : enter image description here

After Solving: enter image description here

Can anyone tell me what I'm doing wrong here?

Upvotes: 0

Views: 677

Answers (1)

Kunal Mathur
Kunal Mathur

Reputation: 46

As Erwin Kalvelagen correctly stated, it is a linear problem. In order to document the solution, I used linprog

import numpy as np
from scipy.optimize import linprog

#Inputs into the Equation
#We want to minimize Amount and keep Risk constant

#Input Amount    
Amount=np.array([10000000,-2000000,400000000,60000000])

#Input Risk
Risk = np.array([[-10000,5000,-20000,500]])

c= Amount
A_eq = Risk
b_eq = np.sum(A_eq)
linprog(c,A_eq=A_eq,b_eq=b_eq)

I get the correct result:

     fun: 24500000.0
 message: 'Optimization terminated successfully.'
     nit: 2
   slack: array([], dtype=float64)
  status: 0
 success: True
       x: array([ 2.45,  0.  ,  0.  ,  0.  ])

Upvotes: 3

Related Questions