简体   繁体   中英

Strange optimizer behavior when using variables with integer = True in GEKKO

I'm trying to use GEKKO to solve some kind of the shop stock balance problem - the main goal is to determine which arrival (x) of goods per day will provide sufficient stock (Inv) in the store, taking into account sales (s) and demand (d).

So, my objective function is:

客观的

With restrictions:

约束

See them in code below:

from gekko import GEKKO

m = GEKKO(remote=False)

n = 70  # Number of days, iterations
a = m.Param(144.846147/n)  # coefficient for balance valuation
b = m.Param(417.33)  # coefficient for deficit valuation
zero = m.Param(0.001)

receptions = [24, 31, 38, 45, 52, 59, 66]   # Days when arrival expected
sales_coef = m.Param([0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,
                      0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
                      0, 1, 0, 0], integer=True)  # Sales
demand_coef = m.Param([0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218,
                       0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.218, 0.206, 0.206, 0.206, 0.206, 0.206, 0.206, 0.206,
                       0.206, 0.206, 0.206, 0.206, 0.206, 0.206, 0.206, 0.206, 0.251, 0.251, 0.251, 0.251, 0.251, 0.251,
                       0.251, 0.251, 0.251, 0.251, 0.251, 0.251, 0.251, 0.251, 0.251, 0.251, 0.21, 0.21, 0.21, 0.21,
                       0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21], integer=False)  # Demand

x = m.Array(m.MV, n, lb=0, integer=True)  # Arrival
y = m.Array(m.MV, n, lb=0, integer=True)  # Balance

# Restrictions
for i in range(n):
    if i + 1 in receptions:  # if arrival expected
        m.Equation(x[i] >= 0)
        x[i].STATUS = 1
    else:
        x[i].VALUE = 0  # In other days arrival fixed to 0
        x[i].STATUS = 0

    if i > 0:  # Restrictions for balance, except first day with initial value
        y[i] = m.Intermediate(m.max2(y[i - 1] - sales_coef[i - 1], zero) + x[i])
    else:
        y[i].VALUE = 5  # Initial balance
        y[i].STATUS = 0

m.Obj(a * m.sum(y) + b * m.sum([m.max2(demand_coef[i] - y[i], zero) for i in range(n)]))

m.options.SOLVER = 1
m.options.IMODE = 5
m.options.MAX_ITER = 1000

m.solve(disp=True)

print([(i + 1, yi) for i, yi in enumerate(y)])

I'm using APOPT (v1.0) and, as you can see, variables with integer=True are used for balancies and arrivals. But when I look at the values of balancies y[i] in output, I can see, that for some days (when the deficit is expected), optimizer somehow selected float values for integer variable, for example:

(24, [1.0]), (25, [0.2059999]), (26, [0.2059999])

I expected, that type of variable will be taken into account when manipulating with variable. So, how is it possible? Have I miss some variables parameters, model options?

There is an option in APOPT that gives a tolerance for what is considered an integer value. It is the amount that a candidate solution variable can deviate from an integer solution and still be considered an integer and has a default value of 1.0e-2 .

minlp_integer_tol 1.0e-2

This means that it can deviate up to 0.01 away from an integer value and still be considered an integer. You can adjust this and other solver options in Gekko as shown in the documentation .

m.solver_options = ['minlp_integer_tol 1.0e-2',\
                    'minlp_gap_tol 1.0e-2',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 500']

If you set minlp_integer_tol 0 it may increase the solution time but will give you exact integer solutions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM