[Python] What could I be doing wrong in this gurobi optimization problem, I have included the...

Discussão em 'Python' iniciado por Stack, Abril 21, 2025.

  1. Stack

    Stack Membro Participativo

    from gurobipy import Model, GRB, quicksum

    I = 8 # Generators
    J = 5 # Consumers
    Gamma_q = 0 # Demand uncertainty budget
    Delta_p = 0.5 # Capacity uncertainty budget
    F = [53] * 2 + [30] * 6 # Fixed costs
    C = [3] * 2 + [2] * 6 # Dispatch costs
    p_max = [16] * 2 + [7] * 6 # Generator capacities
    q = [8, 8, 3, 5, 16] # Consumer demands
    total_demand = sum(q) # Total demand
    # e_i = (0,…,0,1,0,…,0) ← 1 in the i‑th position only
    e = {i: [1.0 if k == i else 0.0 for k in range(I)] for i in range(I)}
    model = Model("ARO_Primal")

    x = model.addVars(I, vtype=GRB.BINARY, name="x") # Commitment
    u = model.addVars(I, vtype=GRB.CONTINUOUS, name="u") # Dispatch
    V = model.addVars(I, J, vtype=GRB.CONTINUOUS, name="V") # Uncertainty variable for each (i, j)
    eta = model.addVar(vtype=GRB.CONTINUOUS, name="eta") # Slack variable
    t = model.addVars(J, vtype=GRB.CONTINUOUS, name="t") # Bounds for infinity norm terms
    t_v = model.addVars(J,vtype=GRB.CONTINUOUS, name="t_v") # Infinity norm of 1-V
    v_inf = model.addVars(I,J, vtype=GRB.CONTINUOUS, name="v_inf") # Infinity norm of V for (i, j)
    t_inf = model.addVar(vtype=GRB.CONTINUOUS, name="t_inf") # Infinity norm of V
    tv_inf = model.addVar(vtype=GRB.CONTINUOUS, name="tv_inf") # Infinity norm of V
    v_new_inf = model.addVars(I,vtype=GRB.CONTINUOUS, name="v_new_inf") # Infinity norm of v_inf

    Z = model.addVars(I, I, vtype=GRB.CONTINUOUS, name="Z")
    Tz = model.addVars(I, vtype=GRB.CONTINUOUS, name="Tz") # ∑ C_i·Z[i,k]
    tz_norm = model.addVar( vtype=GRB.CONTINUOUS, name="tz_norm") # ∥Tz∥∞
    S = model.addVars(I, vtype=GRB.CONTINUOUS, name="S") # ∑ Z[i,k]
    s_norm = model.addVar( vtype=GRB.CONTINUOUS, name="s_norm") # ∥S∥∞
    z_inf = model.addVars(I, I, vtype=GRB.CONTINUOUS, name="z_inf") # ∥Z[i,k]∥∞ coords
    z_new_inf = model.addVars(I, vtype=GRB.CONTINUOUS, name="z_new_inf")# ∥z_inf[i,·]∥∞
    zdiff_inf = model.addVars(I, I, vtype=GRB.CONTINUOUS, name="zdiff_inf")# ∥Z[i,k]-x_i e_i[k]∥∞ coords
    zdiff_norm= model.addVars(I, vtype=GRB.CONTINUOUS, name="zdiff_norm")# ∥zdiff_inf[i,·]∥∞

    # Objective Function
    model.setObjective(
    quicksum(F * x for i in range(I)) + eta,
    GRB.MINIMIZE
    )

    # Infinity norms for robust uncertainty (across all consumers `j`)
    for j in range(J):
    model.addConstr(t[j] >= quicksum(C * V[i, j] for i in range(I)), name=f"InfinityNorm_Pos_{j}") # Positive part
    model.addConstr(t[j] >= -quicksum(C * V[i, j] for i in range(I)), name=f"InfinityNorm_Neg_{j}") # Negative part
    # Infinity norms for robust uncertainty (across all consumers `j`)
    for k in range(I):
    model.addConstr(Tz[k] >= quicksum(C * Z[i, k] for i in range(I)), name=f"InfinityNorm_Postz_{k}") # Positive part
    model.addConstr(Tz[k] >= -quicksum(C * Z[i, k] for i in range(I)), name=f"InfinityNorm_Negtz_{k}") # Negative part
    for j in range(J):
    model.addConstr(t_v[j] >= 1 - quicksum(V[i, j] for i in range(I)), name=f"InfinityNorm_Pos_t_v{j}")
    model.addConstr(t_v[j] >= -1 + quicksum(V[i, j] for i in range(I)), name=f"InfinityNorm_Neg_t_v{j}")
    for k in range(I):
    model.addConstr(S[k] >= quicksum(Z[i,k] for i in range(I)), name=f"InfinityNorm_Pos_sk_{k}")
    model.addConstr(S[k] >= -quicksum(Z[i,k] for i in range(I)), name=f"InfinityNorm_Neg_sk_{k}")
    for k in range(I):
    model.addConstr(tz_norm >= Tz[k], name=f"tzinf_pos_{k}")
    model.addConstr(tz_norm >= -Tz[k], name=f"tzinf_neg_{k}")
    for k in range(I):
    model.addConstr(s_norm >= S[k], name=f"sinf_pos_{k}")
    model.addConstr(s_norm >= -S[k], name=f"sinf_neg_{k}")

    for i in range(I):
    # z_inf coords
    for k in range(I):
    model.addConstr(z_inf[i,k] >= Z[i,k], name=f"zinf_pos_{i}_{k}")
    model.addConstr(z_inf[i,k] >= -Z[i,k], name=f"zinf_neg_{i}_{k}")
    for i in range(I):
    for k in range(I):
    expr = x*e[k] - Z[i,k]
    model.addConstr(zdiff_inf[i,k] >= expr,
    name=f"zdiff_pos_{i}_{k}")
    model.addConstr(zdiff_inf[i,k] >= -expr,
    name=f"zdiff_neg_{i}_{k}")

    # Total Cost with Robust Uncertainty
    for i in range(I):
    for j in range(J):
    model.addConstr(v_inf[i, j] >= V[i, j], name=f"InfinityNorm_Pos_v_{i}_{j}") # Positive part
    model.addConstr(v_inf[i, j] >= -V[i, j], name=f"InfinityNorm_Neg_v_{i}_{j}") # Negative part


    for j in range(J):
    model.addConstr(t_inf >= t[j], name=f"InfinityNorm_t_inf_Pos_{j}")
    model.addConstr(t_inf >= -t[j], name=f"InfinityNorm_t_inf_Neg_{j}") # Negative part

    for j in range(J):
    model.addConstr(tv_inf >= t_v[j], name=f"InfinityNorm_tv_inf_Pos_{j}")
    model.addConstr(tv_inf >= -t_v[j], name=f"InfinityNormtv_inf_Neg_{j}") # Negative part
    for i in range(I):
    for j in range(J):
    model.addConstr(v_new_inf >= v_inf[i, j], name=f"InfinityNorm_tv--_inf_Pos_{i}")
    model.addConstr(v_new_inf >= -v_inf[i, j], name=f"InfinityNormtv--_Neg_{i}") # Negative part
    for i in range(I):

    for k in range(I):
    model.addConstr(z_new_inf >= z_inf[i,k], name=f"znewinfpl_{i}_{k}")
    model.addConstr(z_new_inf >= -z_inf[i,k], name=f"znewinf_{i}_{k}")

    for i in range(I):

    for k in range(I):
    model.addConstr(zdiff_norm >= zdiff_inf[i,k], name=f"zdnormpl_{i}_{k}")
    model.addConstr(zdiff_norm >= -zdiff_inf[i,k], name=f"zdnorm_{i}_{k}")
    model.addConstr(
    quicksum(C * u for i in range(I)) + Gamma_q * t_inf+Delta_p*tz_norm
    <= eta,
    name="TotalCostWithNorms"
    )

    model.addConstr(
    quicksum(u for i in range(I)) == total_demand,
    name="DemandSatisfaction"
    )
    # model.addConstr(u[1] >= u[0]+6.5, name="Distinguish_u1_u2")

    # Capacity Constraints
    for i in range(I):
    model.addConstr(
    u + Gamma_q * v_new_inf+Delta_p*zdiff_norm<= p_max[i] * x[i],
    name=f"CapacityConstraint_{i}"
    )
    model.addConstr(
    -u[i] + Gamma_q * v_new_inf[i]+Delta_p*z_new_inf[i] <= 0,
    name=f"DispatchBound_{i}"
    )

    model.addConstr(
    Gamma_q * tv_inf+Delta_p*s_norm <= 0,
    name="UncertaintyBudget_V"
    )


    # Solve the model
    model.optimize()

    model.write("aro_debug.lp")

    if model.status == GRB.OPTIMAL:
    print("Optimal Cost:", model.objVal)
    print("\nCommitments and Dispatch:")
    for i in range(I):
    print(f"∥Z[{i}]∥∞ = {z_new_inf[i].X}, ∥x_i e_i - Z[{i}]∥∞ = {zdiff_norm[i].X}")

    for i in range(I):
    print(f"Generator {i + 1}: x = {x[i].X}, u = {u[i].X}")
    print("\nUncertainty Allocation (V):")
    for i in range(I):
    for j in range(J):
    print(f"V[{i + 1}, {j + 1}] = {V[i, j].X}")
    for i in range(I):
    for k in range(I):
    print(Z[i,k])
    print(zdiff_inf[i,k])
    print(zdiff_norm[i])
    print(f"Z[{i},{k}]={Z[i,k].X:.2f}")
    expected_Z = [
    [ 5.75, 4.75, 5.75, -5.75, -5.75, -5.75, 5.75, -5.75],
    [-5.75, -4.75, -5.75, 5.75, 5.75, 5.75, -5.75, 5.75],
    [ 0.0, -0.5, 0.5, -0.5, 0.0, 0.5, 0.0, 0.5],
    [ 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.5, -0.5],
    [-0.5, -0.5, -0.5, 0.0, 0.5, -0.5, -0.5, 0.5],
    [-0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5],
    [ 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.0],
    [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    ]
    for i in range(I):
    actual = [Z[i,k].X for k in range(I)]
    print(i, actual, "matches?", all(abs(actual[k] - expected_Z[i][k])<1e-6 for k in range(I)))

    expected_V = [
    [0.25625, 0.25625, 0.25625, 0.25625, 0.25625],
    [0.25625, 0.25625, 0.25625, 0.25625, 0.25625],
    [0.16250, 0.16250, 0.16250, 0.16250, 0.16250],
    [0.16250, 0.16250, 0.16250, 0.16250, 0.16250],
    [0.00000, 0.00000, 0.00000, 0.00000, 0.00000],
    [0.00000, 0.00000, 0.00000, 0.00000, 0.00000],
    [0.16250, 0.16250, 0.16250, 0.16250, 0.16250],
    [0.00000, 0.00000, 0.00000, 0.00000, 0.00000],
    ]

    print("\nChecking V against expected_V:")
    for i in range(I):
    actual_row = [V[i, j].X for j in range(J)]
    match = all(abs(actual_row[j] - expected_V[i][j]) < 1e-6
    for j in range(J))
    print(f"Row {i}: {actual_row} matches? {match}")

    [LIST=1]
    [*]could you see what is wrong with my code since I am trying to have the function below into my gurobi code what should I do what is wrong with my code I'm trying to verify the solution of a robust optimization model that involves matrix variables [B]Z[/B] and [B]V[/B], where [B]Z[/B] represents the perturbations to the identity matrix and [B]V[/B] is derived from it under specific norm constraints. Specifically, I'm modeling ∞-norm constraints on the rows of [B]Z[/B] and their deviation from a scaled identity matrix to ensure robustness in the objective. I'm using Gurobi in Python to formulate and solve the model, and I'm hardcoding expected values of [B]Z[/B] and [B]V[/B] to validate that the optimization behaves as intended. However, despite building the model correctly in parts, my constraints aren't fully enforced due to miswritten or missing loops, leading to incorrect or zero solutions for [B]Z[/B] and [B]V[/B]. I’ve also realized that some constraints like the infinity-norm budget or the deviation bounds weren’t actually connected to the model as I intended. I haven’t tried alternative formulations yet (like dualizing or simplifying the problem), but I’m currently focused on correctly enforcing the ∞-norm constraints element-wise to reproduce the desired matrix values. I'm looking for feedback on both my formulation strategy and implementation pitfalls—especially how to make sure these types of norm-bounded constraints are applied properly in a solver like Gurobi.
    [/LIST]


    /* Container around your displayed equation */
    .math-block {
    /* pick a nice serif “math” font if available */
    font-family: "Latin Modern Math", "STIX Math", serif;

    /* subtle background and left highlight bar */
    background: #fdfdfd;
    border-left: 4px solid #4a90e2;

    /* inner padding */
    padding: 1.2em 1.5em;

    /* spacing around the block */
    margin: 2em 0;

    /* slightly larger for readability */
    font-size: 1.1rem;
    line-height: 1.5;
    color: #333;
    }

    /* MathJax SVG output lives in .mjx-svg */
    .math-block .mjx-svg {
    display: block;
    margin: 0 auto;
    }

    /* Override MathJax’s default margin */
    .math-block .mjx-svg-href {
    fill: #222 !important;
    }

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8" />
    <title>Styled Optimization Model</title>

    <!-- MathJax v3 -->
    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>

    <!-- Your custom CSS -->
    <link rel="stylesheet" href="styles.css" />
    </head>
    <body>

    <div class="math-block">
    \[
    \begin{aligned}
    \min_{x,u,V,Z,\eta}\;& \sum_{i=1}^I F_i x_i + \eta \\[4pt]
    \mathrm{s.t.}\;&
    \sum_{i=1}^I C_i u_i
    + \Gamma_q \Big\|\sum_{i=1}^I C_i V_i\Big\|_{\ell_*}
    + \Delta_p \Big\|\sum_{i=1}^I C_i Z_i\Big\|_{\ell_*}
    \;\le\;\eta, \\[6pt]
    &\Gamma_q \Big\|1 - \sum_{i=1}^I V_i\Big\|_{\ell_*}
    + \Delta_p \Big\|-\sum_{i=1}^I Z_i\Big\|_{\ell_*}
    \;\le\;0, \\[6pt]
    &\sum_{i=1}^I u_i \;=\;\sum_{j=1}^J \bar q_j, \\[6pt]
    &u_i
    + \Gamma_q \|V_i\|_{\ell_*}
    + \Delta_p \|\,x_i e_i - Z_i\|_{\ell_*}
    \;\le\;p_i^{\max}x_i,
    \quad\forall i, \\[6pt]
    &-\,u_i
    + \Gamma_q \|V_i\|_{\ell_*}
    + \Delta_p \|Z_i\|_{\ell_*}
    \;\le\;0,
    \quad\forall i, \\[6pt]
    &x_i \in\{0,1\},
    \quad\forall i.
    \end{aligned}
    \]
    </div>

    </body>
    </html>

    [url="https://stackoverflow.com/questions/79584309/what-could-i-be-doing-wrong-in-this-gurobi-optimization-problem-i-have-included"]Continue reading...[/url][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]

Compartilhe esta Página