Indicator variable that depends on two other indicator variables
回答済みHi,
I want to create an indicator that is defined by two other indicators. More specifically, I have the indicators “start” and “finish”, indicating the whether a machine started working at a position i or whether it finished the work (commodity at 0).
I encounter a difficulty to define a new variable restricted[i,t], that indicates when fields are started but not finished.
restricted = 1 only if start[i,t] + finish [i,t] is bigger 0 and smaller 2, otherwise 0. In my binary case I can define restricted = 1 if start + finish = 1
However, when defining such case I get an infeasible model.
How can I define a case like this?
Below you can find code that creates a test case and the output of my IIS file.
Python Code:
from gurobipy import Model, GRB, quicksum
# Define the sets I, Ih, T, H
H = [1]
I = [1]
Ih = [0] + I # I plus the depot 0
T = [0, 1, 2, 3, 4,5]
# Create a new Gurobi model
model = Model("test_model")
# Define variables
commodity = model.addVars(I, range(1), range(1), T, vtype=GRB.CONTINUOUS, name="b", lb=0)
machine_flow = model.addVars(H, Ih, Ih, T, vtype=GRB.CONTINUOUS, name="machine_flow", lb=0)
finish = model.addVars(I, T, vtype=GRB.BINARY, name="finish")
start = model.addVars(I, T, vtype=GRB.BINARY, name="start")
restricted = model.addVars(I, T, vtype=GRB.BINARY, name="restricted")
# Define Values:
# Set artificial commodity values
model.addConstr(commodity[1, 0, 0, 0] == 100)
model.addConstr(commodity[1, 0, 0, 1] == 100)
model.addConstr(commodity[1, 0, 0, 2] == 50)
model.addConstr(commodity[1, 0, 0, 3] == 0)
model.addConstr(commodity[1, 0, 0, 4] == 0)
model.addConstr(commodity[1, 0, 0, 5] == 0)
# Set artificial machine_flow values
model.addConstr(machine_flow[1, 0, 0, 0] == 1)
model.addConstr(machine_flow[1, 0, 1, 1] == 1)
model.addConstr(machine_flow[1, 1, 1, 2] == 1)
model.addConstr(machine_flow[1, 1, 1, 3] == 1)
model.addConstr(machine_flow[1, 1, 0, 4] == 1)
model.addConstr(machine_flow[1, 0, 0, 5] == 1)
# set 0 for all other machine values
for h in H:
for i in Ih:
for j in Ih:
for t in T:
if (h, i, j, t) not in [(1, 0, 0, 0), (1, 0, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3),
(1, 1, 0, 4), (1, 0, 0, 5)]:
model.addConstr(machine_flow[h, i, j, t] == 0)
# Define start variable as an indicator for when a machine has visited a field
for i in I:
for t in T:
model.addGenConstrIndicator(
start[i, t],
1,
quicksum(machine_flow[h, i, i, t_bar] for h in H for t_bar in range(t + 1)) >= 1)
model.addGenConstrIndicator(
start[i, t],
0,
quicksum(machine_flow[h, i, i, t_bar] for h in H for t_bar in range(t + 1)) <= 1e-7)
# Ensure the 'finish' variable is 1 when beets are 0 using indicator constraints
for i in I:
for t in T:
model.addGenConstrIndicator(
finish[i, t],
0,
commodity[i, 0, 0, t] >= 1e-7)
model.addGenConstrIndicator(
finish[i, t],
1,
commodity[i, 0, 0, t] <= 1e-7)
# restricted is 0 when start and finish is 0 (we cant say 0 in gurobi, hence the 1e-7)
for i in I:
for t in T:
model.addGenConstrIndicator(
restricted[i, t],
1,
start[i,t] + finish[i,t] == 1)
# restricted is also 0 when start and finish is bigger 2 or smaller 0.5
for i in I:
for t in T:
model.addGenConstrIndicator(
restricted[i, t],
0,
start[i,t] + finish[i,t] >= 2)
for i in I:
for t in T:
model.addGenConstrIndicator(
restricted[i, t],
0,
start[i,t] + finish[i,t] <= 0.5)
# Optimize the model
model.optimize()
# Check if the model is infeasible
if model.status == GRB.INFEASIBLE:
print("Model is infeasible. Computing IIS to find the issue...")
# Compute the Irreducible Inconsistent Subsystem (IIS)
model.computeIIS()
# Write the IIS to a file
model.write("model_iis.ilp")
print("IIS written to file 'model_iis.ilp'")
print("Review the IIS file to identify conflicting constraints.")
# Check and print the results
if model.status == GRB.OPTIMAL:
for i in I:
for t in T:
print(f"start[{i}, {t}] = {start[i, t].x}")
print(f"finish[{i}, {t}] = {finish[i, t].x}")
print(f"restricted[{i}, {t}] = {restricted[i, t].x}")
print(f"commodity[{i}, 0, 0, {t}] = {commodity[i, 0, 0, t].x}")
print(f"machine_flow[1, {i}, {i}, {t}] = {machine_flow[1, i, i, t].x}")
Output:
\ Model test_model_copy
\ LP format - for model browsing. Use MPS format to capture full model detail.
Minimize
0 finish[1,0] + 0 start[1,0] + 0 restricted[1,0]
Subject To
R0: b[1,0,0,0] = 100
R26: machine_flow[1,1,1,0] = 0
GC0: start[1,0] = 1 -> machine_flow[1,1,1,0] >= 1
GC13: finish[1,0] = 1 -> b[1,0,0,0] <= 1e-07
GC24: restricted[1,0] = 1 -> finish[1,0] + start[1,0] = 1
GC30: restricted[1,0] = 0 -> finish[1,0] + start[1,0] >= 2
Bounds
b[1,0,0,0] free
machine_flow[1,1,1,0] free
Binaries
finish[1,0] start[1,0] restricted[1,0]
End
-
正式なコメント
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. -
Hi Ludwig,
Thanks for posting here! I have not fully analyzed your model (we typically try to provide hints that help you take a next step by yourself), but noticed a few things.
- Just to be sure about the meaning of indicator constraints: When calling addGenConstrIndicator(binary, value, expr) then the meaning is "if binary=value then force expr" where some of your comments suggest the reverse "if expr then force binary=value". The latter is not necessarily true.
- For restricted[i, t]=0 you define two consequences. Note that those consequences cannot be true at the same time (lines 84-96). From that, it can be concluded restricted[i, t] cannot be 0 ever, so it is forced to be 1. Could this lead to infeasibility?
- The exact meaning of the start/finish/restricted variables is not entirely clear to me. Usually we have variables that mean the following:
- Started[t]=1 when an operation has started at or before time t; this series starts at 0 and at some point switches to 1
- Finished[t]=1 when the operation has finished at or before time t (with discrete time buckets, it would mean finished before bucket t); it has a similar pattern to started
- Busy[t]=1 when the operation is busy (started but not finished); this series starts with 0s, then has 1s when started and becomes 0s when finished
Do you have the same in mind?
Hope this helps; otherwise let us know.
Kind regards,
Ronald0
投稿コメントは受け付けていません。
コメント
2件のコメント