Басовая модель в DoCplex: как назначать переменные в ограничениях - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь построить программу оптимизации на основе модели Басса (см. Ниже):

  • Переменные решения: p, m, q
  • Проблема: мин RMSE
  • Ограничения:
    • Ft = (p + q (C (t-1) / m) (m - C (t-1))
    • Et = Ft - St

с C (t) - совокупная сумма продаж, St - фактическая сумма продаж, Ft - прогнозируемые продажи за период t и Et - термин ошибки.

Кажется, я не могу понять, как записать ограничения, которые присваивают такие значения новым переменным (и не обязательно используют сравнительные операторы) ...

На данный момент я создал функция Bass_F, выполняющая приведенное выше уравнение Ft, и функция rmse, вычисляющая rmse. Я также написал следующий код (мои фактические значения продаж - переменная y, и у меня есть 4 записи в нем):

import docplex.mp.model as cpx
opt_model = cpx.Model(name="Bass")

opt_model.continuous_var(name = "p")
opt_model.continuous_var(name = "q")
opt_model.continuous_var(name = "m")

F = [None]*4
E = [None]*4
opt_model.add_constraint_(F[0] = p*m)
opt_model.add_constraint_(E[0] = F[0] - y[0])
for i in range(1,len(F)):
    opt_model.add_constraints_(F[i] = Bass_F(F[i-1], p, q, m))
    opt_model.add_constraints_(E[i] = F[i] - y[i])

Очевидно, это дает мне ошибку, которая:

opt_model.add_constraint_(F[0] = p*m)                             ^
SyntaxError: keyword can't be an expression

Может кто-нибудь помочь? Заранее спасибо!

1 Ответ

0 голосов
/ 23 марта 2020

Вы не можете «определять» переменные, как если бы вы определяли макросы или аналогичные. Что вы можете сделать, это:

opt_model.add_constraint_(F[0] == p*m)
opt_model.add_constraint_(E[0] == F[0] - y[0])
for i in range(1,len(F)):
    opt_model.add_constraints_(F[i] == Bass_F(F[i-1], p, q, m))
    opt_model.add_constraints_(E[i] == F[i] - y[i])

Это, например, заставляет F[0] быть таким же, как p * m. Механизм решателя при необходимости заменит F[0] на p * m.

Вы также можете создать такое определение вне модели. То есть вы можете сделать это:

F = []
F.append(p * m)

После этого F[0] - это выражение, которое вы можете использовать всякий раз, когда хотите сослаться на p * m. Таким образом, ваш код может быть записан как (замените M с соответствующим пределом)

F = [None] * M
E = [None] * M
F[0] = p * m
E[0] = F[0] - y[0]
for i in range(1, M):
    F[i] = Bass_F(F[i - 1], p, q, m)
    E[i] = F[i] - y[i]

С этим вы можете использовать F[i] и E[i] в качестве «ярлыков» для соответствующих выражений.

Насколько я вижу, у вашей модели есть проблема. Вы определяете

Ft = (p + q(C(t-1)/m)(m - C(t-1))

Это требует деления на переменную решения m. Разделение на переменные решения не поддерживается. Вы умножаете обе стороны на m, чтобы избавиться от этого. Однако полученное ограничение может быть невыпуклым. Это тоже не поддерживается. Возможно, вам придется линеаризовать это ограничение.

...