Как реализовать это ограничение в Python с помощью Gurobi?

У меня есть выражение, приведенное ниже, и мне было интересно, можете ли вы помочь мне формализовать ограничение ILP для решения с помощью оптимизатора Gurobi (Python):

forall (y in Y), forall (j in M), forall (x in X): ЕСЛИ r [x] [y] = 1 и c [y, j] = 1, ТО p [x, a] = 1, forall (a in {U [j], ..., W [j] - 1}) Где: r [x] [y], c [y, j] и p [x, a] - 3 двоичные переменные; U [j] и W [j] - две положительные целые переменные, где U [j] + beta = W [j] (бета - положительная константа)

Я знаю, что это ограничение может быть записано как логическое следствие в конъюнктивной нормальной форме: x ∧ y → z Я уже пробовал это решение: z≥x + y − 1 вместе с несколькими другими возможностями :( Но у меня была ошибка с Решатель гуроби

Мой код Python для этого ограничения выглядит следующим образом:

для y в Y:

для j в M:

для x в X:

для in range (int (U [j]), int (W [j])):

M1.addConstr (r [x] [y] + c [y, j] - 1 ‹= p [x, a], 'TileRequirement_% s_% s_% s_% s'% (y, j, x, a) )

Я всегда получаю ошибку в этой строке: for a in range (int (U [j]), int (W [j]) :, потому что и U [j], и W [j] определены как положительные целочисленные переменные Итак , Кто-нибудь может мне помочь ? Спасибо :)

С уважением, Хадиджа


person k. HADJ SALEM    schedule 06.06.2017    source источник


Ответы (2)


Вы не можете создавать ограничения на основе переменных еще не оптимизированных, например:

for a in range(int(U[j]),int(W[j]))  # optimized value unknown @ build-constr-time

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

Ваш вопрос трудно читать, и нет информации о мотивации этих ограничений, но общая идея может быть такой:

  • избавиться от диапазона, определенного U[j] и W[j]
  • formulate your constraint for the full-range
    • with one modification:
      • introduce one more activating-variable a:
      • (x^y)->z становится: (a^x^y)->z == !a v !x v !y v z
      • как линейное выражение: (1-a) + (1-x) + (1-y) + z >= 1
  • теперь используйте концепцию индикаторных переменных, чтобы сформулировать свои активирующие переменные

Да, это беспорядочно, и из-за этого (и из-за скудности информации) я не буду публиковать полное решение.

person sascha    schedule 06.06.2017
comment
Спасибо за ваш ответ. Я уже пробовал несколько альтернатив с использованием Big-M, но каждый раз получаю одну и ту же ошибку :( - person k. HADJ SALEM; 06.06.2017
comment
Я сказал вам, в чем именно источник проблемы (первое предложение). Чтобы это сформулировать, нужно внести много изменений (а новичку это не понравится). - person sascha; 06.06.2017

# -*- coding: utf-8 -*-
#programmer: Khadija HS
#date: June 2017
#name: B-C-MCT PLNE Model (Khadija.HS,2017) <---> BCMCT1.py


"""
Solve the B-C-MCTP (fixed Z & min Delta) sub-pb of 3-PSDPP (K-HS et al.,2016), where:
    X: list of input tiles (tile x)
    Y: list of output tiles (tile y)
    Ry: requirement relation between  X & Y
        <---> is a List of Y list, each sub List define the input tiles required by each y
        <---> rxy: incidence matrix (0-1): Input Tiles/Output Tiles (Configuration of each output tile % input tile)
        <---> Ry is a list of list where Row <--- x & Column <--- y
    alpha: prefetches times (uniform)
    beta: computations times (uniform)
    Delta: the Total completion time (to be determined)
"""

from gurobipy import *
""" Find Yx: set of output tiles y that required the input tile x """
def OuputTileTe(Ry,X):
    Yx=[]
    for x in X:
        Yx.append(OuputTileTex(Ry,x))
    return Yx
""" Find B: List Ts for x """
def OuputTileTex(Ry,x):
    B=[]
    for y in range(len(Ry)):
        if x in Ry[y]:
            B.append(y)
    return B

""" Find N: Max Value of N ( <---> sum(len(Ry),y in Y)) """
def NbPrefetchTile(S):
    N=0        
    for k in range(0,len(S)):
        N += len(S[k])       
    return  N



""" BCMCT1 - Model"""
def BCMCT1(X,Y,Z,Ry,alpha,beta):
    # DET VBLES: M,N,Z1,T,K,L
    M=list(range(len(Y)))                   # List of Computation steps
    nb=NbPrefetchTile(Ry)                   # Number of prefetches (Big Value of N)
    N=range(nb)                             # List of Prefetches steps 
    ListZ=range(Z)                          # List of Buffers
    T=range(alpha*len(X) + beta*len(Y))     # List of Start Date times (Computation+Prefetches)
    K=range(alpha)                          # Interval Time of a prefetch step
    L=range(beta)                           # Interval Time of a compute step
    
    # DET VBLES: A,T1,B,Yx
    A=alpha*nb + beta*len(Y)                # Big Value of Total Completion Time  
    T1=range(A)                             # List of Start Date times (Computation+Prefetches)
    minLen=min([len(elt) for elt in Ry])    #1,alpha+1
    B=alpha*minLen + beta*len(Y)            # Value of LB2
    Yx=OuputTileTe(Ry,X)                    # List of output tile y, for x, x in X
    
    


    # MODEL
    M1=Model("BCMCT1")    


    # CONSTANT VARIABLES
    r=[[0]*len(Y) for i in range(len(X))]
    for x in X:
        for y in Y:
            if x in Ry[Y.index(y)]:
                r[x][y]=1
    

    # DECISION VARIABLES
    c,p,q,U,W,a={},{},{},{},{},{}

    for y in Y:
        for j in M:
            c[y,j]=M1.addVar(vtype=GRB.BINARY,name="c[%s,%s]"%(y,j)) #obj=beta,

    for x in X:
        for t in T:
            p[x,t]=M1.addVar(vtype=GRB.BINARY,name="p[%s,%s]"%(x,t)) #obj=1,

    for x in X:
        for t in T:
            q[x,t]=M1.addVar(vtype=GRB.BINARY,name="q[%s,%s]"%(x,t)) #obj=1,
    
    for j in M:
        U[j]=M1.addVar(vtype='I',name="U_%s"%j)
        W[j]=M1.addVar(obj=1,vtype='I',name="W_%s"%j)

    for j in M:
        a[j]=M1.addVar(vtype=GRB.BINARY,name="a[%s]"%j) 
    

    # MODEL UPDATE
    M1.update()


    # OBJECTIVE
    Obj=W[len(M)-1]   
    M1.setObjective(Obj, GRB.MINIMIZE)


    # CONSTRAINTS     
    """ (1): Computation's Assignement Constraints """
    """ (a) """
    for j in M:
        M1.addConstr(quicksum(c[y,j] for y in Y)==1,'ComputeAssign1_%s'%j)
    """ (b) """
    for y in Y:
        M1.addConstr(quicksum(c[y,j] for j in M)==1,'ComputeAssign2_%s'%y)    

       
    """ (2): Buffer's Constraints """
    for t in T:
        M1.addConstr(quicksum(p[x,t] for x in X) <= Z,'BufferNb_%s'%t)

        
    """ 3): Computation/Prefetch's Constraints """    
    """ (a) """
    for t in T:
        M1.addConstr(quicksum(q[x,t] for x in X) <= 1,'PrefetchTileA_%s'%t)

    """ (b) """
    for x in X:
        for t in T[1:]:
            for k in K:
                M1.addConstr(p[x,t] - p[x,t-1] <= q[x,t-k],'PrefetchTileB_%s_%s_%s'%(x,t,k))

    """ (c) """ 
    for y in Y:
        for j in M:
            for x in X:
                for t in T: 
                    M1.addConstr(3 - r[x][y] - c[y,j] - a[j] + p[x,t] >= 1, 'TileRequirement_%s_%s_%s_%s'%(y,j,x,t)) 
                 
    """ (5): Computation Time's Constraint """
    """ (a) """
    for j in M:
        M1.addConstr(W[j] == U[j] + beta,'ComputeTime1_%s'%j)

    """ (b) """
    for j in M[1:]:
        M1.addConstr(W[j-1] <= U[j],'ComputeTime2_%s'%j)
    

    # SOLUTION
    M1.__data=c,p,q,U,W,a
    return M1

Пожалуйста, найдите в приложении мою подробную ILP. Может быть, мне будет легче понять мой вопрос об ограничении № 17, где,

L = range(beta)

K=range(alpha)

\Lambda (Big M)=alpha*Z*Y+beta*Y

r[x][y]= 1 if x in Ry and 0 otherwise (forall x in X & forall y in Y) : incidence matrix given as input data

Я дам вам пример, который очень просто, чтобы лучше понять мою проблему, а именно: let: X=[X1,X2,X3,X4] Y=[Y1,Y2,Y3] Ry=[(X1,X2,X3), (X2,X4),(X1,X3,X4)] Z=3 alpha=2, beta=4

Цель состоит в том, чтобы найти последовательность вычислений для вычисления Y1,Y2 & Y3, чтобы минимизировать дельту (общее время завершения)

Оптимальное решение: Y2, Y3, Y1 (or Y2,Y1,Y3) с \Delta=17

Составление ПДОДИ

person k. HADJ SALEM    schedule 06.06.2017