I want to use Scipy minimize function to find the optimal values that achieve the minimum error function. I used scipy.optimize.minimize
, which requires me to specify the rubber and lower bound and any constraint to be passed to the minimization function. I wanted to add an inequality constraint such that A*x < b
, so here is my code:
from scipy.optimize import minimize, LinearConstraint
import numpy as np
def error_func(theta):
return theta[0] - theta[1]
theta0 = [100, 0]
A = np.array([[1, 0], [0, 1]])
b = np.array([[100], [0]])
bnds = ((0, 100), (0, 0))
constraint = LinearConstraint(A, lb=-np.inf, ub=b)
theta = minimize(error_func, theta0, method='trust-constr',constraints=constraint, bounds=bnds, options={'maxiter': 500})
But, when I run the code, I receive the following error on the optimization function line:
/usr/local/lib/python3.7/dist-packages/scipy/optimize/_constraints.py in __init__(self, constraint, x0, sparse_jacobian, finite_diff_bounds)
259 mask = keep_feasible & (lb != ub)
260 f0 = fun.f
--> 261 if np.any(f0[mask] < lb[mask]) or np.any(f0[mask] > ub[mask]):
262 raise ValueError("`x0` is infeasible with respect to some "
263 "inequality constraint with `keep_feasible` "
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed
So can anyone please explain why I receive such an error? what I'm doing wrong here?
I just figured out the solution. The constraint I added will find a solution such that A*x <= b
. Therefore, there will be a comparison between A*x and b. The output of the comparison is of shape (2,2) (I don't understand why although the shape of the matrix multiplication is (2,1) and so is b). Long story short, the minimization function expects the return of the constraint comparison to being a list containing two values as same as I defined initial theta. Therefore, I needed to change my constraint function such that it returns the same shape as the initial theta. Here is the correct code:
from scipy.optimize import minimize, NonlinearConstraint
import numpy as np
def error_func(theta):
return theta[0] - theta[1]
theta0 = [100, 0]
A = np.array([[1, 0], [0, 1]])
b = [100, 0]
bnds = ((0, 100), (0, 0))
func = lambda x: A.dot(x).tolist()
constraint = NonlinearConstraint(func, -np.inf, b)
theta = minimize(error_func, theta0, method='trust-constr',constraints=constraint, bounds=bnds, options={'maxiter': 500})