Используйте концентрацию смешивания как ограничение для линейной оптимизации - PullRequest
0 голосов
/ 31 января 2019

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

enter image description here

И используя or-tools для решения этой проблемы, пока у меня есть:

Форматированные данные

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

Ограничения для нутриентов:

питательные вещества = [["белок", 15,5], ["углеводы", 12,3]]

Целевая функция, где верхняя граница "data i"- запас этого конкретного элемента.

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, data[i][1], data[i][0])
    objective.SetCoefficient(food[i], 4)
objective.SetMinimization()

У меня также есть как ограничить требуемое значение каждого питательного вещества:

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

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

Моим первым предположением было добавить множитель к требованию к питательным веществам

factor = 10
nutrients = [
    ["protein",15.5*factor],
    ["carbohydrates",12.3*factor]]

Таким образом, у меня будет в 10 раз больше еды, но потом я понял, что это неправильно, так какпотребность в концентрации EG

Мне нужно 10 кг с 15,5 белка / кг и 12,3 углеводов / кг. Необходимое ограничение выглядит примерно так:

(f1*W + f2*X + f3*Y + f4*Z)/(W+X+Y+Z) = 10kg with  15.5 protein/kg and 12.3 carbohydrates/kg 

Where W, X, Y and Z are the kg of each food

Как добавить это ограничение в решатель?

1 Ответ

0 голосов
/ 31 января 2019
(f1*W + f2*X + f3*Y + f4*Z)/(W+X+Y+Z) = 10

совпадает с

f1*W + f2*X + f3*Y + f4*Z = 10*(W+X+Y+Z)

Теперь это линейно.

И, если мы пропустили некоторые математические классы, мы можем записать это как стандартное ограничение LP:

(f1-10)*W + (f2-10)*X + (f3-10)*Y + (f4-10)*Z = 0
...