Gurobi add an if condition
進行中The following is my code, what I wanted to add is that: indices named 'idx' such that column4 == 1, add constraint such that the sum([df.loc[i, "Column3"] * Y_actual[i] for i in idx]) == 6. The following code gave me a result but it is not correct. Shown as in picture. I need to optimize both Y and column4. Can anyone help me plz?
import gurobipy as gp
from gurobipy import GRB
import pandas as pd
# Define explicit feasible data
data = {
"Column3": [3, -1, 2, -2, 4], # Carefully chosen values
}
df = pd.DataFrame(data)
# Define Gurobi model
model = gp.Model()
# Add binary Y variables
Y_vars = model.addVars(len(df), vtype=GRB.BINARY, name="Y")
# Convert binary Y to {-1,1}
Y_actual = {i: 2 * Y_vars[i] - 1 for i in range(len(df))}
# Add integer Column4 variables (1 to 4)
Column4_vars = model.addVars(len(df), vtype=GRB.INTEGER, name="Column4")
# Constrain Column4 values to be between 1 and 4
for i in range(len(df)):
model.addConstr(Column4_vars[i] >= 1)
model.addConstr(Column4_vars[i] <= 4)
# Add binary indicator variables for Column4 == 1
Indicator_vars = model.addVars(len(df), vtype=GRB.BINARY, name="Indicator")
# Link Indicator_vars to Column4_vars using addGenConstrIndicator
for i in range(len(df)):
model.addGenConstrIndicator(Indicator_vars[i], True, Column4_vars[i] == 1)
# Add constraint that sum([df.loc[i, "Column3"] * Y_actual[i] for i in idx]) == 6
# where idx are indices such that Column4 == 1
model.addConstr(
gp.quicksum(df.loc[i, "Column3"] * Y_actual[i] * Indicator_vars[i] for i in range(len(df))) == 6
)
# Optimize without an objective function
model.optimize()
# Extract results
if model.status == GRB.OPTIMAL or model.status == GRB.FEASIBLE:
df["Y"] = [2 * int(Y_vars[i].X) - 1 for i in range(len(df))] # Convert binary to {-1, 1}
df["Column4"] = [int(Column4_vars[i].X) for i in range(len(df))]
idx = [i for i in range(len(df)) if Column4_vars[i].X == 1]
print("Indices where Column4 == 1:", idx)
print(df)
else:
print("No feasible solution found.")
-
0
-
Hi,
If I understand the puzzle correctly:
- You need to choose a value -1 or +1 for each row
- Then you need to select a subset of rows
- For those rows, the sum of each -1/+1 multiplied by a given constant Column3 must add up to 6
It sounds like you could simplify this by saying we should select an integer value between -1 and 1 (including 0), where the sum of -1/0/+1 multiplied by the constants adds up to 6.
import gurobipy as gp
from gurobipy import GRB
data = [3, -1, 2, -2, 4]
with gp.Model() as model:
N=len(data)
X=model.addVars(N, lb=-1, ub=1, vtype=GRB.INTEGER)
model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 6)
model.optimize()
for i in range(N):
print(f'X[{i}] = {X[i].X}')Kind regards,
Ronald0 -
Hi Ronald,
Thanks a lot for your reply. My problem becomes more complicated than this. Since, Column4_Vars can take values in 1,2,3,4, in the end I have four subsets based on this problem. for example
if Column4_Vars == 1,
model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 6)
if Column4_Vars == 2,
model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 10)
if Column4_Vars == 3,
model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 20)
if Column4_Vars == 4,
model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == -5)0 -
so in the end I need to find X and Column4_Vars at the same time
0 -
The full puzzle is still not entirely clear now. Is the challenge now to partition the rows into four groups, where each row gets a +/- sign, and the product/sum within each group must match a certain value? E.g. "Divide the numbers [3, -1, 2, -2, 4] into four partitions; multiply some of them by -1, then take the sum within each group and make sure the sums equal 6, 10, 20, -5? For this particular sample data I think there is no solution. Also, the code you shared in your previous comment sums all items and not just the one in a partition/subset.
0 -
Hi, Yes your understanding is correct, but I didn't design the numerical example such that it adds up. but it is what you described
1 -
import pandas as pd data = { "Column3": [2, 56, 3, 3, 2, 6, 8, 8, 43, 32, 2, 3, 6, 34, 2, 6], "Y1": [1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1], "Column4_Vars": [1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4], "Column3_times_Y1": [2, -56, 3, 3, 2, -6, 8, -8, 43, 32, -2, -3, 6, 34, 2, -6], "sum": [-48, -48, -48, -48, 39, 39, 39, 39, 39, 27, 27, 27, 36, 36, 36, 36] } df = pd.DataFrame(data)
The above example is a valid example.if Column4_Vars == 1, model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == -48) if Column4_Vars == 2, model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 39) if Column4_Vars == 3, model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 27) if Column4_Vars == 4, model.addConstr(gp.quicksum(data[i] * X[i] for i in range(N)) == 36)
I need to learn Y1 and Column4_Vars at the same time. 'Column3' and 'sum' are training data.0
サインインしてコメントを残してください。
コメント
7件のコメント