Решить оптимизацию, связанную с составной суммой - PullRequest
0 голосов
/ 30 января 2019

Я работаю над проблемой оптимизации, похожей на Диета Стиглера Вместо большого списка свойств в примере, я имею только свойства: углеводы и белок.

Еда доступна в N банках, каждая с разными свойствами и ценой.Цель состоит в том, чтобы получить более дешевую комбинацию для получения C кг пищи со значением белка> = a и углеводов> = b.Для этого мне разрешено брать несколько частей содержимого или всей банки.

food = ["f1","f2","f3","f4"]
kg_available = [10,2,5,8]
protein =       [17,12,16,8]
carbohydrates = [10,14,13,16]
price_per_kg =  [15,11,17,12]



df = pd.DataFrame({"food":food,"kg_available":kg_available,"protein":protein,"carbohydrates":carbohydrates,"price_per_kg":price_per_kg})

enter image description here

Это образец требований:

##            protein,carbohydrates,kg
requirement = [15.5,12.3,11]

Например, я хочу 2 кг пищи, в которой содержится 15,5 белка и 12,3 углеводов.

Следуя примеру на сайте Google, у меня есть этот код:

data = [
['f1', 10, 15, 17, 10],
['f2', 2, 11, 12, 14],
['f3', 5, 17, 16, 13],
['f4', 8, 12, 8, 16]
]

nutrients = [
    ["protein",15.5],
    ["carbohydrates",12.3]]


food = [[]] * len(data)

# Objective: minimize the sum of (price-normalized) foods.
objective = solver.Objective()
for i in range(0, len(data)):
    food[i] = solver.NumVar(0.0, solver.infinity(), data[i][0])
    objective.SetCoefficient(food[i], 4)
objective.SetMinimization()

# Create the constraints, one per nutrient.

constraints = [0] * len(nutrients)
for i in range(0, len(nutrients)):
    constraints[i] = solver.Constraint(nutrients[i][1], solver.infinity())
    for j in range(0, len(data)):
        constraints[i].SetCoefficient(food[j], data[j][i+3])


status = solver.Solve()

if status == solver.OPTIMAL:
    # Display the amounts (in dollars) to purchase of each food.
    price = 0
    num_nutrients = len(data[i]) - 3
    nutrients = [0] * (len(data[i]) - 3)
    for i in range(0, len(data)):
        price += food[i].solution_value()

        for nutrient in range(0, num_nutrients):
            nutrients[nutrient] += data[i][nutrient+3] * food[i].solution_value()

        if food[i].solution_value() > 0:
            print ("%s = %f" % (data[i][0], food[i].solution_value()))

    print ('Optimal  price: $%.2f' % (price))
else:  # No optimal solution was found.
    if status == solver.FEASIBLE:
        print ('A potentially suboptimal solution was found.')
    else:
        print ('The solver could not solve the problem.')

, который почти работает, он возвращает следующий результат:

f1 = 0.077049
f3 = 0.886885
Optimal  price: $0.96

Это было быПравильно, за исключением части, которая не учитывает, что мне нужно 2 кг, и что у меня ограниченный запас для каждой банки.

Как я могу добавить это ограничение к проблеме?

...