0

I am trying to build an optimisation program based on Bass model (see below):

  • Decision variables: p, m, q
  • Problem: min RMSE
  • Constraints:
    • Ft = (p + q(C(t-1)/m)(m - C(t-1))
    • Et = Ft - St

with C(t) being the cumulative sum of sales, St being the actual amount of sales, Ft being the predicted sales for period t and Et being the error term.

I cannot seem to figure out how to write constraints that assign such values to new variables (and not necessarily use comparative operators)...

For the moment, I created a Bass_F function doing the equation Ft above, and an rmse function computing the rmse. I also wrote the following code (my actual sales value are variable y and I have 4 records in it):

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])

Obviously this gives me an error, which is:

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

Can anyone help? Thanks in advance!

1 Answers1

0

You cannot "define" variables like you would define macros or similar. What you can do is this:

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])

This for example forces F[0] to be the same as p * m. The solver engine will substitute F[0] by p * m whenever necessary.

You can also create this sort of definition outside the model. That is, you can do this:

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

After this, F[0] is an expression that you can use whenever you want to reference p * m. So your code could be written as (replace M with an appropriate limit)

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]

With that you can use F[i] and E[i] as "shortcuts" for the respective expressions.

As far as I can see, there is an issue with your model, though. You define

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

This requires division by decision variable m. Dividing by decision variables is not supported. You multiply both sides by m to get rid of that. The resulting constraint may be non-convex, though. That is not supported either. You may have to linearize this constraint.

Daniel Junglas
  • 5,830
  • 1
  • 5
  • 22