Skip to main content

Add a new constraint to the model

Open

Comments

8 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff
    This post is more than two years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum, or try Gurobot, our chatbot interface offering instant, expert-level support.
  • 子龙 王
    • Gurobi-versary
    • Conversationalist
    • First Question

    The last line of code is wrong. My new code should read:

    D[previous_machine][operations_machines],
    Instead of

    D(previous_machine,operations_machines),
    But it also fails in the following parts:

    for k in operations_machines[i, j-1]:
    if x[i, j-1, k] >0.5:
    previous_machine = k
    break
    for k in operations_machines[i, j]:
    if x[i, j, k] > 0.5:
    current_machine = k
    break

    0
  • 子龙 王
    • Gurobi-versary
    • Conversationalist
    • First Question

    I don't know if adding the corresponding code in constraint 4 is the right thing to do, and I appreciate someone giving me some guidance

    0
  • 子龙 王
    • Gurobi-versary
    • Conversationalist
    • First Question

    I also tried the following:
    # constraint(4)
    # for i in J:
    #     for j in OJ[i]:
    #         if j ! = OJ[i][0]:

    #             p = None
    #             current_machine = None
    #             model.update()
    #             model. addConstr(s[i, j] >= s[i, j - 1] + quicksum(
    #                 operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
    #                quicksum(D[p*x[i, j - 1, p]][q*x[i, j, q]] for p in operations_machines[i,  j - 1] for q in operations_machines[i, j])
    #                ,"stime(%s,%s)"  % (i, j))


    There will be:
    TypeError: list indices must be integers or slices, not gurobipy. LinExpr

    Someone told me I should use the indicator, but I still don't know how to do it

    0
  • Ahmed Azab
    • Gurobi Staff

    Hi 子龙 王,

    Please provide values for the model input Data. A small instance with some comments is better.

    Thanks

    - Ahmed

    1
  • 子龙 王
    • Gurobi-versary
    • Conversationalist
    • First Question

    The complete executable code is as follows:

    from gurobipy import Model, GRB, quicksum
    import sys
    import numpy as np
    import time
    import os

    from DataRead import getdata

    from itertools import chain

    def MPModel(Data):
        n = Data['n']
        m = Data['m']
        J = Data['J']
        OJ = Data['OJ']
        oj=OJ
        operations_machines = Data['operations_machines']
        operations_times = Data['operations_times']
        largeM = Data['largeM']
        # starttime=[0,1,2,3,4,5,6,7,8]
        D = [[60, 60, 65, 60, 65, 90, 60, 65],
                    [65, 65, 85, 75, 60, 75, 85, 80],
                    [60, 70, 75, 80, 75, 80, 80, 75],
                    [65, 65, 80, 75, 80, 75, 75, 80],
                    [60, 65, 65, 60, 75, 80, 80, 75],
                    [60, 65, 65, 80, 75, 75, 80, 75],
                    [60, 60, 75, 80, 75, 70, 60, 75]]

        # preprocessing
        # obtain the earliest starting time for each operation
        stimeOp = {}
        stimeOpMax = 0
        for i in J:
            for j in OJ[i]:
                if j == 1:
                    # stimeOp[i, j] =     starttime[i]
                    stimeOp[i, j] = 0
                else:
                    opt_time_min = sys.maxsize
                    for k in operations_machines[i, j - 1]:
                        if operations_times[i, j - 1, k] < opt_time_min:
                            opt_time_min = operations_times[i, j - 1, k]
                    stimeOp[i, j] = stimeOp[i, j - 1] + opt_time_min
                if stimeOpMax < stimeOp[i, j]:
                    stimeOpMax = stimeOp[i, j]
        print(stimeOp)
        # the latest completion time for each operation
        ltimeOp = {}
        for i in J:
            for jj in range(len(OJ[i]) - 1, -1, -1):
                j = OJ[i][jj]
                opt_time_min = sys.maxsize
                for k in operations_machines[i, j]:
                    if operations_times[i, j, k] < opt_time_min:
                        opt_time_min = operations_times[i, j, k]

                if jj == len(OJ[i]) - 1:
                    ltimeOp[i, j] = largeM - opt_time_min
                else:
                    ltimeOp[i, j] = ltimeOp[i, j + 1] - opt_time_min
        print(ltimeOp)

        model = Model("model")

        x, y, s = {}, {}, {}
        cmax = model.addVar(lb=stimeOpMax, ub=largeM, vtype="I", name="cmax")

        # define x
        for j in J:  # job
            for i in OJ[j]:  # operation
                # s[j,i]=model.addVar(lb=0,ub=largeM,vtype="I",name="s(%s,%s)"%(j,i))
                s[j, i] = model.addVar(lb=stimeOp[j, i], ub=largeM, vtype="I", name="s(%s,%s)" % (j, i))  # ltimeOp[j,i]
                for k in operations_machines[j, i]:
                    x[j, i, k] = model.addVar(lb=0, ub=1, vtype="I", name="x(%s,%s,%s)" % (j, i, k))
        # define y
        for i in J:
            for ip in J:
                for j in OJ[i]:
                    for jp in OJ[ip]:
                        y[i, j, ip, jp] = model.addVar(lb=0, ub=1, vtype="I", name="y(%s,%s,%s,%s)" % (i, j, ip, jp))

        # define objective function
        model.setObjective(cmax, GRB.MINIMIZE)
        
        # constraint(3)
        for i in J:
            for j in OJ[i]:
                model.addConstr(sum(x[i, j, k] for k in operations_machines[i, j]) == 1, "assignment(%s,%s)" % (i, j))
        # constraint(4)
        for i in J:
            for j in OJ[i]:
                if j != OJ[i][0]:

                    p = None
                    current_machine = None
                    model.update()
                    model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
                        operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])
                         ,"stime(%s,%s)" % (i, j))
        # constraint(4)  idea1
        # for i in J:
        #     for j in OJ[i]:
        #         if j != OJ[i][0]:

        #             p = None
        #             current_machine = None
        #             model.update()
        #             model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
        #                 operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
        #                 quicksum(D[p*x[i, j - 1, p]][q*x[i, j, q]] for p in operations_machines[i, j - 1] for q in operations_machines[i, j])
        #                 ,"stime(%s,%s)" % (i, j))
        # # constraint(4)  idea2
        # for i in J:
        #     for j in OJ[i]:
        #         if j != OJ[i][0]:

        #             previous_machine = None
        #             current_machine = None
        #             model.update()
        #             for k in operations_machines[i, j-1]:
        #                 if  x[i, j-1, k] > 0.5: # 根据机器分配情况确定前一个操作所在的机器
        #                     previous_machine = k
        #                 break
        #             for k in operations_machines[i, j]:
        #                 if x[i, j, k] > 0.5:  # 根据机器分配情况确定当前操作所在的机器
        #                     current_machine = k
        #                 break
        #             model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
        #                 operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
        #                D[[previous_machine][current_machine]]
        #                ,"stime(%s,%s)" % (i, j))
           # constraint(5) 
        for k in operations_machines[1, 1]    :
            for i in J:
                model.addConstr(sum(x[i, j, k]    for j in OJ[i] ) == 1, "cons_x(%s,%s)" % (i, j))   
        # constraint(6)
        for i in J:
            for ip in J:
                if i < ip:
                    for j in OJ[i]:
                        for jp in OJ[ip]:
                            kkp = [k for k in operations_machines[i, j] if k in operations_machines[ip, jp]]
                            if len(kkp):
                                for iipk in kkp:
                                    model.addConstr(s[ip, jp] >= s[i, j] + operations_times[i, j, iipk] - largeM * (
                                                3 - y[i, j, ip, jp] - x[i, j, iipk] - x[ip, jp, iipk]),
                                                    "cons_6_(%s,%s,%s,%s)" % (i, j, ip, jp))
                                    model.addConstr(
                                        s[i, j] >= s[ip, jp] +
                                        operations_times[ip, jp, iipk] - largeM *
                                        (2 + y[i, j, ip, jp] - x[i, j, iipk] - x[ip, jp, iipk]),
                                        "cons_5_(%s,%s,%s,%s)" % (i, j, ip, jp))
        # cmax constraint
        for i in J:
            model.addConstr(cmax >= s[i, OJ[i][len(OJ[i]) - 1]] + quicksum(
                operations_times[i, OJ[i][len(OJ[i]) - 1], k] * x[i, OJ[i][len(OJ[i]) - 1], k] for k in
                operations_machines[i, OJ[i][len(OJ[i]) - 1]]), "cmax_cons_(%s)" % (i))

     

        model.params.TimeLimit=90
        model.update()
        model.optimize()
        # print(y)

        for j in J:  # job
            for i in OJ[j]:  # operation
                # s[j,i]=model.addVar(lb=0,ub=largeM,vtype="I",name="s(%s,%s)"%(j,i))
               
                for k in operations_machines[j, i]:
                    string= ''
                    if abs(  x[j, i, k].x-1) <= 0.01:
                        string =j+i+k+s[j,i].x
                        print(j,i,k,s[j,i].x)
                        # print(s[j,i].x)
        # print(s)
        return model
    filename='datasss.txt'
    Data=getdata(filename)

    n=Data['n']
    m=Data['m']
    J=Data['J']
    OJ=Data['OJ']
    print(OJ)
    operations_machines=Data['operations_machines']
    operations_times=Data['operations_times']
    largeM=Data['largeM']

    mipmodel=MPModel(Data) 

     

    txt document content is:
    4 4 1
    4 4 3 54 1 34 4 61 2 2 4 3 54 1 34 4 61 2 2 4 3 54 1 34 4 61 2 2 4 3 54 1 34 4 61 2 2
    4 4 4 9 1 15 2 89 3 70 4 4 9 1 15 2 89 3 70 4 4 9 1 15 2 89 3 70 4 4 9 1 15 2 89 3 70
    4 4 1 38 2 19 3 28 4 87 4 1 38 2 19 3 28 4 87 4 1 38 2 19 3 28 4 87 4 1 38 2 19 3 28 4 87
    4 4 1 95 3 34 2 7 4 29 4 1 95 3 34 2 7 4 29 4 1 95 3 34 2 7 4 29 4 1 95 3 34 2 7 4 29

     

    txt explanation:

    -in the first line there are (at least) 2 numbers: the first is the number of jobs and the second the number of machines (the 3rd is not necessary, it is the average number of machines per operation)

    -Every row represents one job: the first number is the number of operations of that job, the second number (let's say k>=1) is the number of machines that can process the first operation; then according to k, there are k pairs of numbers (machine,processing time) that specify which are the machines and the processing times; then the data for the second operation and so on...


    Example: Fisher and Thompson 6x6 instance, alternate name (mt06)

    6   6   1   
    6   1   3   1   1   1   3   1   2   6   1   4   7   1   6   3   1   5   6   
    6   1   2   8   1   3   5   1   5   10  1   6   10  1   1   10  1   4   4   
    6   1   3   5   1   4   4   1   6   8   1   1   9   1   2   1   1   5   7   
    6   1   2   5   1   1   5   1   3   5   1   4   3   1   5   8   1   6   9   
    6   1   3   9   1   2   3   1   5   5   1   6   4   1   1   3   1   4   1   
    6   1   2   3   1   4   3   1   6   9   1   1   10  1   5   4   1   3   1   

    first row = 6 jobs and 6 machines 1 machine per operation
    second row: job 1 has 6 operations, the first operation can be processed by 1 machine that is machine 3 with processing time 1.

    0
  • Ahmed Azab
    • Gurobi Staff

    The reasons for the errors you have in constraint 4 are as follows:

    # constraint(4)  idea1

     quicksum(D[p*x[i, j - 1, p]][q*x[i, j, q]]

    TypeError: list indices must be integers or slices, not gurobipy.LinExpr

    This error occurred because you used linear expressions  p*x[i, j - 1, p] and q*x[i, j, q] as the index for D where D is a Python list.

     # constraint(4)  idea2

    if  x[i, j-1, k] > 0.5:

    TypeError: '>' not supported between instances of 'Var' and 'float'

    Here, you attempted to add an if condition for x[i, j-1, k], which does not yet have a value, since it is a decision variable.

    Please refer to this article for more details about How do I model conditional statements in Gurobi?

    - Ahmed

    0
  • 子龙 王
    • Gurobi-versary
    • Conversationalist
    • First Question

    I have looked at the relevant website and understood the application of the if constraint in gurobi, but I still don't know how to write my own questions I wonder if it is convenient to provide specific code details

    0

Post is closed for comments.