我正在尝试对烹饪食谱进行简单的优化。特点是系统将不得不同时优化多个配方,因为共同创建的约束尚未实现(例如:所有配方共有的核心)。
以下是显示 scipy 的错误:
fun: 3.467601477010358
jac: array([1.79999998, 2.04999998, 1.79999998, 2.04999998])
message: 'Singular matrix C in LSQ subproblem'
nfev: 6
nit: 1
njev: 1
status: 6
success: False
x: array([0.99425684, 0.3895346 , 0.31931526, 0.14859794])
这里的代码:
import sys
import numpy as np
from scipy.optimize import minimize
ingredient = dict()
ingredient[0] = dict()
ingredient[0]['description'] = 'Corn'
ingredient[0]['price'] = 180
ingredient[1] = dict()
ingredient[1]['description'] = 'Rice'
ingredient[1]['price'] = 205
ingredient_count = len(ingredient)
product = dict()
product[0] = dict()
product[0]['description'] = "Bread 1"
product[0]['ingredient'] = dict()
product[0]['ingredient'][0] = dict()
product[0]["ingredient"][0]['min'] = 0
product[0]["ingredient"][0]['max'] = 36
product[0]["ingredient"][1] = dict()
product[0]["ingredient"][1]['min'] = 0
product[0]["ingredient"][1]['max'] = 100
product[1] = dict()
product[1]["description"] = "Bread 2"
product[1]['ingredient'] = dict()
product[1]['ingredient'][0] = dict()
product[1]["ingredient"][0]['min'] = 0
product[1]["ingredient"][0]['max'] = 36
product[1]["ingredient"][1] = dict()
product[1]["ingredient"][1]['min'] = 0
product[1]["ingredient"][1]['max'] = 100
product_count = len(product)
def function(x):
totals = list()
for product_index in product:
total = 0
for ingredient_index in product[product_index]['ingredient']:
x_index = (ingredient_count * product_index) + ingredient_index
total += (x[x_index] * ingredient[ingredient_index]['price'] / 100)
totals.append(total)
return totals
def function_sum(x):
# p1 + p2 + ... + pn
totals = function(x)
return sum(totals)
def function_diff_sum(x):
# p_min + (p1 - p_min) + (p2 - p_min) + ... + (pn - p_min)
totals = function(x)
min_total = min(totals)
grand_total = min_total
for total in totals:
grand_total += total - min_total
return grand_total
# Constraints
constraints = list()
def populate_constraints():
for product_index in product:
total_of_ingredients(product_index)
for ingredient_index in product[product_index]['ingredient']:
for constraint_type in product[product_index]['ingredient'][ingredient_index]:
if constraint_type == 'min':
min_for_ingredient(product_index, ingredient_index)
elif constraint_type == 'max':
max_for_ingredient(product_index, ingredient_index)
def min_for_ingredient(product_index, ingredient_index):
x_index = (ingredient_count*product_index)+ingredient_index
constraints.append({'type': 'ineq', 'fun': lambda x: x[x_index] - product[product_index]['ingredient'][ingredient_index]['min']})
def max_for_ingredient(product_index, ingredient_index):
x_index = (ingredient_count*product_index) + ingredient_index
constraints.append({'type': 'ineq', 'fun': lambda x: product[product_index]['ingredient'][ingredient_index]['max'] - x[x_index]})
def total_of_ingredients(product_index):
# The total of ingredient for a product have to be 100.
first_x_index = ingredient_count*product_index
constraints.append({'type': 'eq', 'fun': lambda x: (sum(x[i] for i in range(first_x_index, ingredient_count)))-100})
def main():
x0 = np.random.rand(1, product_count*ingredient_count)
# x0 = np.array([36, 64, 36, 64]) # The solution that the optimizer should give
populate_constraints()
# There are 2 type of sum
fun = function_sum
# fun = function_diff_sum
res = minimize(fun, x0, constraints=constraints)
print(res)
if __name__ == '__main__':
sys.exit(main())