问题描述
我目前正在处理一个复杂的调度问题,其中涉及大量参数和决策变量。简而言之,我正在尝试根据容量,复杂性,可用时间和潜在的完成时间来安排任务的资源。
我有一个矩阵Av,j,t,它确定在时间t向项目v上的作业j分配了多少资源,以及变量Sv,j和Ev,j,它们确定每个项目的开始和结束时间按项目工作。从数学上讲,约束都是有道理的,但是我在建模时遇到了很多麻烦。
为了确保仅在工作的开始和结束时间之间分配工作,我强制执行了约束:
pulp.lpSum([A[t][v][j] for t in [t0 for t0 in T if t0 >= S[v][j]]]) == P[v][j]
pulp.lpSum([A[t][v][j] for t in [t0 for t0 in T if t0 <= S[v][j] - 1]]) == 0
pulp.lpSum([A[t][v][j] for t in [t0 for t0 in T if t0 >= E[v][j] + 1]]) == 0
其中Pv,j是任务使用单个资源花费的总时间。我遇到的这类约束的主要问题是开始时间和结束时间是模型变量,而T(时间集)不是。试图在模型中强制执行此约束被证明是有问题的,因为在设置约束时Sv,j并未真正“初始化”,因此该约束实际上没有像集合那样做任何事情
[t0 for t0 in T if t0 >= S[v][j]]
不随模型改变。我还设置了一个指标来跟踪作业完成情况Xv,j,t,对于t> Ev,j,它为1,否则为0。我已经尝试了多种方法来强制执行此操作,但是所有方法都依赖于T中t的集合的总和,而模型调整时并不会调整。
有人对我如何强制这些集合随模型本身进行调整有任何想法吗?
解决方法
所有约束都必须是线性的。您尝试指定的是非线性的,因此是不允许的。
相反,您需要建模:
t 1 2 3 4 5 6 7 8 9 10 11
job is executing x(t) 0 0 0 0 1 1 1 1 0 0 0
job is starting s(t) 0 0 0 0 1 0 0 0 0 0 0
这可以建模为:
s(t) >= x(t)-x(t-1)
sum(t,s(t)) <= 1 (one start allowed)
sum(t,x(t)) = joblen
要获取开始时间和结束时间:
S = sum(t,t*s(t));
E = S + joblen - 1
这是一个相当标准的方法。您的教科书中可能会提到它。