Как построить правильное ограничение связывания в Pyomo - Смешанная целочисленная линейная программа? - PullRequest
0 голосов
/ 24 октября 2019

Контекст: я работаю над заданием, для которого я использую Pyomo, чтобы изучить эту структуру. Вот назначение:

header

Fixed cost contraint

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

Вот моя реализация:

from pyomo.environ import *

VERY_LARGE_NUMBER = 1e8


def part_4_april(data, limit_ballons, limit_labor):

    model = ConcreteModel()

    PACKAGES = data.keys()

    model.x = Var(PACKAGES, within=NonNegativeReals)
    model.y = Var(PACKAGES, within=Binary)

    model.profit = Objective(
        expr=sum(
            (
                (data[p]["price"] - data[p]["cost"]) * model.x[p]
                - data[p]["fixed_cost"] * model.y[p]
            )
            for p in PACKAGES
        ),
        sense=maximize,
    )

    model.ballon_cst = Constraint(
        expr=sum(data[p]["ballons"] * model.x[p] for p in PACKAGES) <= limit_ballons
    )

    model.labor_cst = Constraint(
        expr=sum(data[p]["labor"] * model.x[p] for p in PACKAGES) <= limit_labor
    )

    model.fixed_cost_cst = Constraint(
        expr=sum(model.x[p] - VERY_LARGE_NUMBER * model.y[p] for p in PACKAGES) <= 0
    )

    opt = SolverFactory("cbc")
    results = opt.solve(model, tee=True)
    model.pprint()
    return model


if __name__ == "__main__":
    # part 4
    data = {
        "Standard": {"labor": 3, "ballons": 2, "cost": 2, "price": 3, "fixed_cost": 10},
        "Joyful": {"labor": 5, "ballons": 5, "cost": 3, "price": 5, "fixed_cost": 5},
        "Fabulous": {"labor": 8, "ballons": 8, "cost": 4, "price": 7, "fixed_cost": 1},
    }
    model = part_4_april(data, limit_ballons=360, limit_labor=500)
    print("----- PART 4: April -----")
    print("Profit:", model.profit())
    for c in data.keys():
        print("  ", c, ":", model.x[c]())

Код не дает ожидаемый результат, вместо этого он должен произвести следующеевывод:

    # must produce :
    # Profit: 188.0
    #     Standard : 140.0
    #     Joyful : 0.0
    #     Fabulous : 10.0

Есть ли проблема с моим кодом или с тем, как я использую двоичные переменные?

1 Ответ

0 голосов
/ 29 октября 2019

Я наконец нашел решение с комментарием от Бетани Николсон и Эрвина Кальвелангена - с моим кодом было две проблемы. Во-первых, фиксированная стоимость не должна содержать sum и должна применяться ко всем пакетам индивидуально

# NOT...
# model.fixed_cost_cst = Constraint(
#     expr=sum(model.x[p] - VERY_LARGE_NUMBER * model.y[p] for p in PACKAGES) <= 0
# )

# must be applied to all packages individually 
def fixed_cost_rule(model, p):
    return model.x[p] - VERY_LARGE_NUMBER * model.y[p] <= 0

model.fixed_cost_cst = Constraint(PACKAGES, rule=fixed_cost_rule)

Во-вторых, результат должен быть 159, а не 188.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...