0

(几天前我发布了一个类似的问题,但是鉴于上一篇文章中的答案,我已经改变了我的方法并且有不同的方法)

我正在尝试使用 scipy.optimize 来解决我的优化问题,但我一直得到一个不正确的答案,它只是返回我最初的猜测(x0)。在这里,我使用的是 dual_annealing 算法,但我也尝试了不同的全局优化算法(差分进化,shgo)以及局部最小化(使用方法 SLSQP 最小化,但这会导致问题,因为我的函数没有梯度)但没有利用。

就上下文而言,该计划正试图找到在多个商店中分配某些产品的最佳方式。每家商店都有他们预计在接下来几天内销售的商品的预测 (sales_data)。这个预测不一定是整数,或者大于 1(很少是这样),它是统计意义上的预期。因此,如果一家商店的 sales_data = [0.33, 0.33, 0.33] ,则预计 3 天后,他们将售出 1 件产品。

我想尽量减少出售我分配的单位所需的总时间(我想以最快的速度出售它们),我的限制是我必须分配我可用的单位,并且我不能分配负数的产品到一家商店。我现在可以进行非整数分配。对于我的初始分配,我在所有商店中平均分配我可用的单位。

因此,以更数学的方式陈述,我想最大化 time_objective 函数,受制于所有分配必须具有非负值(min(allocations)> = 0)并且我必须分配所有单元的约束可用(总和(分配)==单位可用)。由于 dual_annealing 不支持约束,我通过将 0 指定为每个分配的下限(并将 unitsAvailable 作为上限)来处理第一个约束。对于第二个约束,我将目标函数包装在 constrained_objective 函数中,如果违反了约束,它将返回 numpy.inf。这个 constrained_objective 函数还接受除最后一个之外的所有分配,并将最后一个分配设置为剩余单元(因为这相当于约束所有单元,

这是我的代码:

import numpy
import scipy.optimize as spo

unitsAvailable = 10
days = 50

class Store:

    def __init__(self, num):
        self.num = num

        self.sales_data = []

# Mock Data
stores = []
for i in range(10):
    # Identifier
    stores.append(Store(i))
    # Expected units to be sold that day (It's unlikey they will sell 1 every day)
    stores[i].sales_data = [(i % 10) / 10 for x in range(days)]

def days_to_turn(alloc, store):
    day = 0

    inventory = alloc
    while (inventory > 0 and day < days):
        inventory -= store.sales_data[day]
        day += 1
    return day

def time_objective(allocations):
    time = 0
    for i in range(len(stores)):
        time = max(time, days_to_turn(allocations[i], stores[i]))
    return time

def constrained_objective(partial_allocs):
    if numpy.sum(partial_allocs) > unitsAvailable:
        # can't sell more than is available, so make the objective infeasible
        return numpy.inf
    # Partial_alloc contains allocations to all but one store.
    # The final store gets allocated the remaining units.
    allocs = numpy.append(partial_allocs, unitsAvailable - numpy.sum(partial_allocs))
    return time_objective(allocs)

# Initial guess (x0)
guess_allocs = []
for i in range(len(stores)):
    guess_allocs.append(unitsAvailable / len(stores))
guess_allocs = numpy.array(guess_allocs)

print('Optimizing...')

bounds = [(0, unitsAvailable)] * (len(stores))
time_solution = spo.dual_annealing(constrained_objective, bounds[:-1], x0=guess_allocs[:-1])
allocs = numpy.append(time_solution.x, unitsAvailable - numpy.sum(time_solution.x))
print("Allocations: " + str(allocs))
print("Days to turn: " + str(time_solution.fun))
4

0 回答 0