带约束的scipy最小化

jyztefdp  于 2023-03-12  发布在  其他
关注(0)|答案(2)|浏览(163)

假设我有一个矩阵

arr = array([[0.8, 0.2],[-0.1, 0.14]])

具有目标函数

def matr_t(t):
    return array([[t[0], 0],[t[2]+complex(0,1)*t[3], t[1]]]

def target(t):
    arr2 = matr_t(t)
    ret = 0
    for i, v1 in enumerate(arr):
          for j, v2 in enumerate(v1):
               ret += abs(arr[i][j]-arr2[i][j])**2
    return ret

现在我想在t[i]是真实的的假设下,最小化这个目标函数,类似于t[0]+t[1]=1 .

bcs8qyzn

bcs8qyzn1#

这种限制

t[0] + t[1] = 1

将是一个等式(type='eq')约束,其中您创建了一个必须等于零的函数:

def con(t):
    return t[0] + t[1] - 1

然后,你为你的约束创建一个dict(如果有多个dicts,就列出一个dicts):

cons = {'type':'eq', 'fun': con}

我从未尝试过,但我相信要保持t真实的,您可以用途:

con_real(t):
    return np.sum(np.iscomplex(t))

并使您的cons包含两个约束:

cons = [{'type':'eq', 'fun': con},
        {'type':'eq', 'fun': con_real}]

然后将cons输入minimize,如下所示:

scipy.optimize.minimize(func, x0, constraints=cons)
juud5qan

juud5qan2#

你可以构造一个scipy.optimize.LinearConstraint对象并将其作为约束传递,而不是编写一个自定义约束函数。而且,自变量的向量必须具有与传递到目标函数的变量长度相同的长度,因此诸如t[0] + t[1] = 1的约束应当被重新表达为如下(因为t的长度为4,这可以从其在matr_t()中的操作看出):

而且minimize在真实的空间上进行优化,因此t[i]为实数的限制已经嵌入到算法中。

import numpy as np
from scipy.optimize import minimize, LinearConstraint

def matr_t(t):
    return np.array([[t[0], 0],[t[2]+complex(0,1)*t[3], t[1]]]

def target(t):
    arr2 = matr_t(t)
    ret = 0
    for i, v1 in enumerate(arr):
          for j, v2 in enumerate(v1):
               ret += abs(arr[i][j]-arr2[i][j])**2
    return ret

arr = np.array([[0.8, 0.2],[-0.1, 0.14]])
linear_constraint = LinearConstraint([[1, 1, 0, 0]], [1], [1])
result = minimize(target, x0=[0.5, 0.5, 0, 0], constraints=[linear_constraint])

x_opt = result.x            # array([ 0.83,  0.17, -0.1 , 0.])
minimum = result.fun        # 0.0418

相关问题