Skip to main content

Conditional constraints

Answered

Comments

6 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff
    This post is more than three 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.
  • Dan Steffy
    • Gurobi Staff

    Hello Abhishek,

    It looks like the python max function will help you represent this in a more direct way. I am assuming that \(\texttt{harvestleadtime}\) and \(\texttt{purchaseleadtime}\) represent problem data, not variables. Your logic assigns a to the maximum of 0 and \(\texttt{t-harvestleadtime[j]}\), so an alternative to building and using a would be to use the following, in place of a, when creating your constraints:

    max(0,t-harvestleadtime[j])

    Similarly, in place of constructing and using b in your constraints, you could use: 

    max(0,t-purchaseleadtime[j])

    The last part of your logic is replacing \(\texttt{InventoryQty[j,t-1]}\) with zero in your constraint when t is 1, perhaps because t-1 would be out of range in this case. One alternative would be to include 0 among your periods and set \(\texttt{InventoryQty[j,0]}\) equal to zero (or whatever starting inventory quantity would make sense) for all values j. Then when constructing these inventory balance constraints, you could build them for periods t = 1 and later.

    Finally, you may want to double-check the logic of your constraints. It appears as though the quantities represented by a and b are amounts of time, and your constraints directly equate them with decision variables representing inventory quantities, so the units do not seem to match up. I hope this helps.

    0
  • Abhishek Solomon
    • Gurobi-versary
    • Curious
    • Conversationalist

    Hello Dan,

    Firstly, thank you for the elaborate reply.

    I think i posted the definitions of a and b incorrectly, here's the correct snippet:

    for j in produce:
        for t in periods:
            if t-harvestleadtime[j]>0:
                a = ProductionQty[j,t-harvestleadtime[j]]
            else:
                a = 0
            if t-purchaseleadtime[j]>0:
                b = PurchaseQty[j,t-purchaseleadtime[j]]
            else:
                b = 0
            if t>1:
                c = InventoryQty[j,t-1]
            else:
                c = 0
            m.addConstr(a + b + (1-fractionlost[j])*c == ShippingQty[j,t] + InventoryQty[j,t], 'InvBalanceConstraint')

    So I believe the MAX function may not work here. t and harvestleadtime are both integers, so a comparison should work.

    For example, If t > harvestleadtime, I would like to use ProductionQty[j,t-harvestleadtime[j]]. Otherwise, I want to use 0, hence the variable a. This seems okay to a novice like me, but something tells me there is a more efficient way to do this.

    0
  • Dan Steffy
    • Gurobi Staff

    Hello Abhishek,

    OK, thanks for sending the update. One way to avoid defining a, b, and c would be to accumulate the left-hand sides term-by-term, as follows. 

    for j in produce:
        for t in periods:
            lhs = 0
            if t-harvestleadtime[j]>0:
                lhs += ProductionQty[j,t-harvestleadtime[j]]
            if t-purchaseleadtime[j]>0:
                lhs += PurchaseQty[j,t-purchaseleadtime[j]]
            if t>1:
                lhs += (1-fractionlost[j])*InventoryQty[j,t-1]
            m.addConstr(lhs == ShippingQty[j,t] + InventoryQty[j,t], 'InvBalanceConstraint')

    There are often many ways to build your model. If you are interested in seeing more examples of how models can be constructed I encourage you to browse through some of the Python examples.

    0
  • Abhishek Solomon
    • Gurobi-versary
    • Curious
    • Conversationalist

    Thanks a lot Dan. I notice that your suggestion also has 3 if statements. Just out of curiosity, will this be more efficient than how I've done it? Or is it just a way to avoid creating new variables?

    0
  • Dan Steffy
    • Gurobi Staff

    Hello Abhishek,

    What I have suggested is just a way to avoid creating three new variables each time. It simplifies/shortens the code a little bit, but I doubt it would be much faster. Based on your model, it seems that some conditional logic is needed here to determine which terms should be added, as the lead times are allowed to vary. 

    There are other ways in which you could shorten the code that I can describe bellow, but I do not think they would make any big difference in overall performance. The time to build a model is usually small compared to the time to solve it. 

    One thing you could do is to bring the conditional logic inside of the addConstr method, which would look like this:

    for j in produce:
        for t in periods:
            m.addConstr(
            (0 if t-harvestleadtime[j]<=0 else ProductionQty[j,t-harvestleadtime[j]]) +
            (0 if t-purchaseleadtime[j]<=0 else PurchaseQty[j,t-purchaseleadtime[j]]) +
            (0 if t<=1 else (1-fractionlost[j])*InventoryQty[j,t-1])
            == ShippingQty[j,t] + InventoryQty[j,t])

    Since the above has all of the logic within the call to addConstr, you could even call the addConstrs method, as follows:

    m.addConstrs( 
    (0 if t-harvestleadtime[j]<=0 else ProductionQty[j,t-harvestleadtime[j]]) + 
       (0 if t-purchaseleadtime[j]<=0 else PurchaseQty[j,t-purchaseleadtime[j]]) + 
       (0 if t<=1 else (1-fractionlost[j])*InventoryQty[j,t-1])
       == ShippingQty[j,t] + InventoryQty[j,t] for j in produce for t in period)

    But as mentioned above, I do not think any of these alternatives would make things much faster.

     

    0

Post is closed for comments.