scipy.minimize 如何将多个目标函数相加到一个目标函数?

问题描述

对于一个练习,我需要解决 4 种不同产品的不同基质中的多个混合问题。我的问题是我有一个目标函数可以分别针对每种类型进行优化。我的目标是将这 4 个目标函数添加一个目标函数

感谢您的帮助!

我的代码看起来像这样: 如何将 4 个目标函数一个目标函数相加?

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

class substrat_1:
    C = 0.93
    N = 0.005
    P = 0.031
    Si = 0.034
class substrat_2:
    C = 0.523
    N = 0.3
    P = 0.123
    Si = 0.054
class substrat_3:
    C = 0.257
    N = 0.176
    P = 0.461
    Si = 0.106
class substrat_4:
    C = 0.694
    N = 0.005
    P = 0.003
    Si = 0.298
class sort_1:
    C = 0.7
    N = 0.15
    P = 0.05
    Si = 0.1
class sort_2:
    C = 0.8
    N = 0.03
    P = 0.1
    Si = 0.07
class sort_3:
    C = 0.4
    N = 0.2
    P = 0.1
    Si = 0.3
class sort_4:
    C = 0.5
    N = 0.05
    P = 0.3
    Si = 0.15

#Pflanzensorte 1:

def targetFun1(y):
    amount_sort1_C = substrat_1.C*y[0] + substrat_2.C*y[1] + substrat_3.C*y[2] + substrat_4.C*y[3]
    amount_sort1_N = substrat_1.N*y[0] + substrat_2.N*y[1] + substrat_3.N*y[2] + substrat_4.N*y[3]
    amount_sort1_P = substrat_1.P*y[0] + substrat_2.P*y[1] + substrat_3.P*y[2] + substrat_4.P*y[3]
    amount_sort1_Si = substrat_1.Si*y[0] + substrat_2.Si*y[1] + substrat_3.Si*y[2] + substrat_4.Si*y[3]
    
    return (np.abs(amount_sort1_C-sort_1.C)+np.abs(amount_sort1_N-sort_1.N)+np.abs(amount_sort1_P-sort_1.P)+np.abs(amount_sort1_Si-sort_1.Si)) 

#Pflanzensorte 2:

def targetFun2(y):
    amount_sort2_C = substrat_1.C*y[4] + substrat_2.C*y[5] + substrat_3.C*y[6] + substrat_4.C*y[7]
    amount_sort2_N = substrat_1.N*y[4] + substrat_2.N*y[5] + substrat_3.N*y[6] + substrat_4.N*y[7]
    amount_sort2_P = substrat_1.P*y[4] + substrat_2.P*y[5] + substrat_3.P*y[6] + substrat_4.P*y[7]
    amount_sort2_Si = substrat_1.Si*y[4] + substrat_2.Si*y[5] + substrat_3.Si*y[6] + substrat_4.Si*y[7]
    
    return (np.abs(amount_sort2_C-sort_2.C)+np.abs(amount_sort2_N-sort_2.N)+np.abs(amount_sort2_P-sort_2.P)+np.abs(amount_sort2_Si-sort_2.Si))

#Pflanzensorte 3:

def targetFun3(y):
    amount_sort3_C = substrat_1.C*y[8] + substrat_2.C*y[9] + substrat_3.C*y[10] + substrat_4.C*y[11]
    amount_sort3_N = substrat_1.N*y[8] + substrat_2.N*y[9] + substrat_3.N*y[10] + substrat_4.N*y[11]
    amount_sort3_P = substrat_1.P*y[8] + substrat_2.P*y[9] + substrat_3.P*y[10] + substrat_4.P*y[11]
    amount_sort3_Si = substrat_1.Si*y[8] + substrat_2.Si*y[9] + substrat_3.Si*y[10] + substrat_4.Si*y[11]
    
    return (np.abs(amount_sort3_C-sort_3.C)+np.abs(amount_sort3_N-sort_3.N)+np.abs(amount_sort3_P-sort_3.P)+np.abs(amount_sort3_Si-sort_3.Si))
#Pflanzensorte 4:

def targetFun4(y):
    amount_sort4_C = substrat_1.C*y[12] + substrat_2.C*y[13] + substrat_3.C*y[14] + substrat_4.C*y[15]
    amount_sort4_N = substrat_1.N*y[12] + substrat_2.N*y[13] + substrat_3.N*y[14] + substrat_4.N*y[15]
    amount_sort4_P = substrat_1.P*y[12] + substrat_2.P*y[13] + substrat_3.P*y[14] + substrat_4.P*y[15]
    amount_sort4_Si = substrat_1.Si*y[12] + substrat_2.Si*y[13] + substrat_3.Si*y[14] + substrat_4.Si*y[15]
    
    return (np.abs(amount_sort4_C-sort_4.C)+np.abs(amount_sort4_N-sort_4.N)+np.abs(amount_sort4_P-sort_4.P)+np.abs(amount_sort4_Si-sort_4.Si))

bnds=((0,1),(0,1)) 
y0 = np.zeros((16,))

res = minimize(lambda y: targetFun1(y) + targetFun2(y)+ targetFun3(y) + targetFun4(y),x0 = y0,method='SLSQP',bounds=bnds)
y = res.x.reshape(4,4)
print(y)

解决方法

它的工作原理与 answer to your previous question 完全相似:通过使用 np.ndarray 代替类,即

substrat = np.array([
    [0.93,0.005,0.031,0.034],# substrat_1
    [0.523,0.3,0.123,0.054],# substrat_2
    [0.257,0.176,0.461,0.106],# substrat_3
    [0.694,0.003,0.298],# substrat_4
])

sort = np.array([
    [0.7,0.15,0.05,0.1],# sort_1
    [0.8,0.03,0.1,0.07],# sort_2
    [0.4,0.2,0.3],# sort_3
    [0.5,0.15],# sort_4
])

你可以把目标函数写成:

# create the block diagonal matrix:
# 
# ( substrat.T      0           0           0      )
# (    0        substrat.T      0           0      )
# (    0            0       substrat.T      0      )
# (    0            0.          0       substrat.T )
#
DiagSubstrat = np.kron(np.eye(4),substrat.T)

def targetFun(y): 
    return np.sum(np.abs(DiagSubstrat @ y - sort.flatten()))