Как упоминалось @ sascha , scipy.minimize()
разрешается только для 1-го массива.Следовательно, вам нужно выровнять свою матрицу (преобразовать ее в вектор), и после того, как минимизация будет выполнена, вы восстановите свою матрицу.Это можно сделать разными способами.В следующем коде я использовал numpy.vstack()
и numpy.concatenate()
для выполнения преобразований.Я также реализовал и присоединился к вашим ограничениям.См. Следующий код:
# import packages
import numpy as np
from scipy.optimize import minimize
# create objective function
def objective(p, y, s):
x = p[0:sep] + 2*p[sep:2*sep] + 3*p[2*sep:3*sep]
return np.sum(np.abs(y-x))
def vec2mat(vec):
sep = int(vec.size / 3)
return np.vstack((np.vstack((vec[0:sep], vec[sep:2*sep])), vec[2*sep:3*sep]))
def mat2vec(mat):
return np.concatenate((np.concatenate((mat[:,0], mat[:,1]), axis=0), mat[:,2]), axis=0)
def columns_sum(mat):
return np.array([sum(x) for x in zip(*mat)])
def rows_sum(mat):
return np.array([sum(x) for x in mat])
def constraint_func(x):
c1 = np.all(0 <= x) & np.all(x <= 1) # 0 <= x_i <= 1
c2 = np.all(rows_sum(vec2mat(x)) <= 1) # row sum <= 1
c3 = np.all(1 == columns_sum(vec2mat(x))) # columns sum == 1
if (c1 and c2 and c3) == True: return 1
else : return 0
# define constraints
cons = [{'type':'eq', 'fun': lambda x: constraint_func(x) - 1 }]
# generate target data (y)
y = np.array([2.48, 1.75, 1.13, 0.20, 0.20, 0.20, 0.0, 0.0, 0.0, 0.0])
# initialise starting param values
p0 = np.zeros((10,3))
p0[:,0] = 0.001
p0[:,1] = 0.002
p0[:,2] = 0.003
# flatten p
p0_flat = mat2vec(p0)
sep = int(p0_flat.size / 3)
# solve
sol = minimize(objective, p0_flat, args=(y,sep), method='SLSQP', constraints=cons)
print(sol)
# reconstruct p
p_sol = vec2mat(sol.x)
К сожалению, хотя код компилируется и работает правильно, но возвращает следующий вывод:
fun: 5.932
jac: array([-1., -1., -1., -1., -1., -1., 1., 1., 1., 1., -2., -2., -2.,
-2., -2., -2., 2., 2., 2., 2., -3., -3., -3., -3., -3., -3.,
3., 3., 3., 3.])
message: 'Singular matrix C in LSQ subproblem'
nfev: 32
nit: 1
njev: 1
status: 6
success: False
x: array([0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,
0.001, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002,
0.002, 0.002, 0.003, 0.003, 0.003, 0.003, 0.003, 0.003, 0.003,
0.003, 0.003, 0.003])
Поэтому может потребоваться дальнейшая отладка кода(Я подозреваю, что раздел ограничений), или попробуйте другие методы, предлагаемые в scipy.minimize_docs .