Добавьте размер шага к линейной оптимизации - PullRequest
0 голосов
/ 04 февраля 2019

Я работаю над проблемой смешивания, похожей на пример целлюлозы

У меня есть это ограничение, чтобы убедиться, что полученное количество является желаемым

prob += lpSum([KG[i] * deposit_vars[i] for i in deposit]) == 64, "KGRequirement"

Но мне также нужно добавить другое ограничение для минимального значения, отличного от нуля, это потому, что мне неудобно брать, например, 0,002 кг одного ингредиента, я должен брать либо 0, либо хотя бы 2 кг, следовательно, допустимые случаинапример, 0, 2, 2,3, 6, 3,23.

Я пытался сделать это так:

for i in deposit:
    prob += (KG[i] * deposit_vars[i] == 0) or (TM[i] * deposit_vars[i] >= 30)

Но это не работает, и это просто делает проблему неосуществимой

РЕДАКТИРОВАТЬ

Это мой текущий код:

import pulp
from pulp import *
import pandas as pd

food = ["f1","f2","f3","f4"]
KG = [10,20,50,80]
Protein =       [18,12,16,18]
Grass = [13,14,13,16]
price_per_kg =  [15,11,10,22]

##            protein,carbohydrates,kg

df = pd.DataFrame({"tkid":food,"KG":KG,"Protein":Protein,"Grass":Grass,"value":price_per_kg})


deposit =  df["tkid"].values.tolist()

factor_volumen = 1



costs =  dict((k,v) for k,v in zip(df["tkid"],df["value"]))
Protein =  dict((k,v) for k,v in zip(df["tkid"],df["Protein"]))
Grass =  dict((k,v) for k,v in zip(df["tkid"],df["Grass"]))
KG =  dict((k,v) for k,v in zip(df["tkid"],df["KG"]))

prob = LpProblem("The Whiskas Problem", LpMinimize)
deposit_vars = LpVariable.dicts("Ingr",deposit,0)
prob += lpSum([costs[i]*deposit_vars[i] for i in deposit]), "Total Cost of Ingredients per can"

#prob += lpSum([deposit_vars[i] for i in deposit]) == 1.0, "PercentagesSum"
prob += lpSum([Protein[i] *KG[i] * deposit_vars[i] for i in deposit]) >= 17.2*14, "ProteinRequirement"
prob += lpSum([Grass[i] *KG[i] * deposit_vars[i] for i in deposit]) >= 12.8*14, "FatRequirement"
prob += lpSum([KG[i] * deposit_vars[i] for i in deposit]) == 14, "KGRequirement"
prob += lpSum([KG[i] * deposit_vars[i] for i in deposit]) <= 80, "KGRequirement1"

prob.writeLP("WhiskasModel.lp")
prob.solve()
# The status of the solution is printed to the screen
print ("Status:", LpStatus[prob.status])

# Each of the variables is printed with it's resolved optimum value
for v in prob.variables():
    print (v.name, "=", v.varValue)

# The optimised objective function value is printed to the screen
print ("Total Cost of Ingredients per can = ", value(prob.objective))

Новое отличие, которое я хочу добавить, находится в этой части:

prob += lpSum([KG[i] * deposit_vars[i] for i in deposit]) <= 80, "KGRequirement1"

Где я хочу получить продукт KG [i] * deposit_vars[i] может быть либо 0, либо быть между a и b

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

В традиционной формулировке линейного программирования все переменные, целевые функции и ограничения должны быть непрерывными.Вы спрашиваете, как сделать эту переменную дискретной переменной, т.е. она может принимать только значения a, b, ... и ничего между ними.Когда у вас есть комбинация непрерывных и дискретных переменных, это называется смешанной целочисленной задачей (MIP). См. Документацию PuLP, отражающую это объяснение. Я предлагаю вам внимательно прочитать упоминания о проблемах смешивания в "целых числах";они разбросаны по странице.Согласно документации PuLP, он может решать проблемы с MIP, вызывая внешний MIP-решатель, некоторые из которых уже включены.

Без минимального рабочего примера немного сложно объяснить, как это реализовать.Один из способов сделать это - указать переменную (и) как целое число со значениями, которые он может принимать как dict.Если оставить решение по умолчанию, CIN-OR CBC solver , то решение MIP.Между тем, вот несколько ресурсов для продвижения вперед:

0 голосов
/ 04 февраля 2019

' или ' нельзя использовать непосредственно в модели LP / MIP.Помните, LP / MIP состоит из линейной цели и линейных ограничений.

Для моделирования x=0 or x≥L вы можете использовать так называемые полунепрерывные переменные .Самые продвинутые решатели поддерживают их.Однако я не верю, что Pulp это поддерживаетВ качестве обходного пути вы также можете использовать двоичную переменную δ:

δ*L ≤ x ≤ δ*U

, где U - верхняя граница x.Это легко увидеть:

δ = 0   ⇒   x = 0
δ = 1   ⇒   L ≤ x ≤ U 

Полунепрерывные переменные не требуют этих ограничений.Просто скажите, что переменная решателя x полунепрерывна с границами [L, U] (или просто L, если нет верхней границы).

Ограничение

a*x=0   or   L ≤ a*x ≤ U

может быть переписанокак

δ*L ≤ x*a ≤ δ*U
δ binary variable

Это довольно стандартная формулировка.Полунепрерывные переменные часто используются в финансах (модели портфеля) для предотвращения небольших ассигнований.

Все это делает модель идеально линейной (не квадратичной), поэтому можно использовать стандартный MIPрешатель и стандартный инструмент моделирования LP / MIP, такой как Pulp.

...