Skip to main content

Python: Constraint coding problem.

Comments

6 comments

  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Hi,

    Yes, you should only create one set of \(X\) variables as they denote the decision. You could do it with two sets of variables but you would have to enforce equality on each of the variable pairs making the problem unnecessary complicated.

    Your code should then look something like this

    I=list('i'+str(i) for i in range(1,22))
    K=list('k'+str(i) for i in range(1,19))
    U=list('u'+str(i) for i in range(1,9))
    J=list('j'+str(i) for i in range(1,22))

    #decision variables
    X= m.addVars( I , J , U , vtype=GRB.BINARY,name="X")

    #parameters
    Sik = { i : { k : 0 for k in K } for i in I}
    Sik['i1']['k1'] = 1
    Sik['i2']['k1'] = 1
    Sik['i3']['k1'] = 1
    Sik['i4']['k2'] = 1
    Sik['i5']['k3'] = 1
    Sik['i6']['k3'] = 1
    Sik['i7']['k4'] = 1
    Sik['i7']['k5'] = 1
    Sik['i8']['k5'] = 1
    Sik['i9']['k6'] = 1
    Sik['i10']['k6'] = 1
    Sik['i10']['k7'] = 1
    Sik['i11']['k7'] = 1
    Sik['i11']['k8'] = 1
    Sik['i12']['k8'] = 1
    Sik['i13']['k9'] = 1
    Sik['i13']['k13'] = 1
    Sik['i14']['k10'] = 1
    Sik['i15']['k11'] = 1
    Sik['i16']['k12'] = 1
    Sik['i17']['k14'] = 1
    Sik['i18']['k15'] = 1
    Sik['i19']['k16'] = 1
    Sik['i20']['k17'] = 1
    Sik['i21']['k18'] = 1

    Pik = { i : { k : 0 for k in K } for i in I}
    Pik['i1']['k2'] = 1
    Pik['i1']['k3'] = 1
    Pik['i2']['k4'] = 1
    Pik['i3']['k5'] = 1
    Pik['i4']['k6'] = 1
    Pik['i4']['k7'] = 1
    Pik['i5']['k8'] = 1
    Pik['i6']['k9'] = 1
    Pik['i7']['k9'] = 1
    Pik['i7']['k10'] = 1
    Pik['i8']['k11'] = 1
    Pik['i8']['k12'] = 1
    Pik['i8']['k13'] = 1
    Pik['i9']['k15'] = 1
    Pik['i9']['k16'] = 1
    Pik['i10']['k6'] = 1
    Pik['i10']['k14'] = 1
    Pik['i10']['k18'] = 1
    Pik['i11']['k14'] = 1
    Pik['i11']['k16'] = 1
    Pik['i11']['k17'] = 1
    Pik['i12']['k17'] = 1
    Pik['i13']['k13'] = 1
    Pik['i13']['k17'] = 1
    Pik['i14']['k18'] = 1
    Pik['i15']['k16'] = 1
    Pik['i15']['k18'] = 1
    Pik['i16']['k17'] = 1

    #constraints
    for k in K:
    for v in J:
    m.addConstr(
    (quicksum(Pik[i][k]*X[i,j,u] for i in I for j in J for u in U))
    >=(quicksum(Sik[i][k]*X[i,v,u] for i in I for u in U)),'c'+str(k)+str(v))

    I tried to stick to your notation to avoid confusion. Note that I define the dictionaries \(P_{ik}\) and \(S_{ik}\) differently. I first set all entries to 0. Then, I set the desired entries to 1. Performance wise, this is in general slower than writing the whole dictionary by hand, but as you only have a few 1 entries, it is acceptable and makes the code shorter.

    Please let me know if the above was helpful and don't hesitate to ask further questions.

    Best regards,
    Jaromił

    0
  • Ching Chang
    Gurobi-versary
    First Comment
    First Question

    Dear Jaromił:

    Thank you for your idea.

    I have tried this but it is in feasible.The error report as the enclosed picture.

    On my opinion, I thought the reason was that you only create one variable X[i,j,u] but in the part of constraints, you wrote X[i,j,u] & X[i,v,u].

    I'm glad to discuss with you.

     

    B.R.,

    Jimmy

    0
  • Ching Chang
    Gurobi-versary
    First Comment
    First Question

    Dear Jaromił:

    I also found a mistake(as the red rectangle) from your code below. Index J should be revise as index V.

    I forget to explain what constraint (8) means: It ensures that the selected
    successor is not assigned to a lower -indexed station than the one to which the
    selected predecessor is assigned.

    The constraint:

    Your code:

    The key point is that index V hasn't been created,but both J and V are meaning work stations. And J is predecessor, V is  successor.

     

    B.R.,

    Jimmy

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Hi Jimmy,

    I am not sure if I understand your problem correctly. In your code you define \(J\) as a list of integers and \(V\) as a list of strings. I assume the \(J\) list is defined this way due to your other Community post. Are the sets \(J\) and \(V\) meant to be equal? If yes, then I think that you don't need both to construct your constraint (8).

    Could you provide an example of constraint (8) with small sets \(U\), \(I\), \(V\), and \(K\), e.g., the cardinality of all sets could be 2 and all \(p_{ik}\) and \(s_{ik}\) equal 1, and check if the above code produces the desired constraints? You can do it conveniently by calling \(\texttt{model.write("myLP.lp")}\).

    As far as I understand, with the above, constraint (8) would provide
    \(\begin{align}
     &p_{11} X_{111} + p_{11} X_{121} + p_{11} X_{112} + p_{11} X_{122}\\
    +&p_{21} X_{211} + p_{21} X_{221} + p_{21} X_{212} + p_{21} X_{222} \\
    \geq & s_{11} X_{111} + s_{11} X_{112} + s_{21} X_{211} + s_{21} X_{212}
    \end{align}\)
    If now all \(p\) and \(s\) equal 1 you can eliminate 4 variables. If not, then you can eliminate only parts of the variables. This is should be achieved by the provided code.

    Best regards,
    Jaromił

    0
  • Ching Chang
    Gurobi-versary
    First Comment
    First Question

     Hi Jaromił,

    You are right that you assume the J list is defined this way due to my other community post.
    Sets J & V both are the index of workstation,but when they come to constraint(8); J is predecessor and V is successor.

    B.R.,

    Jimmy

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Hi Jimmy,

    How do you express that \(J\) is a predecessor and  \(V\) is a successor? Is it modeled in a different constraint?


    In constraint (8), you use the set \(V\) only and since \(J\) has the same indices as \(V\), you can just use \(J\) in this case.
    Did you try writing down the constraints and printing the LP file to check whether the code produces the constraints you desire?

    Best regards,
    Jaromił

    0

Please sign in to leave a comment.