メインコンテンツへスキップ

Quadratic constraint

回答済み

コメント

17件のコメント

  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Please have a look at the Knowledge Base article How do I divide by a variable in Gurobi?

    If this is not what you are asking for, please clarify.

    Edit: It looks like you are asking about performance degradation. Is this correct? In this case: Did you set tight variable bounds for variables `D_edge`and `mass_edge`? Could you please share a log snippet and possibly a model file. Note that uploading files in the Community Forum is not possible but we discuss an alternative in Posting to the Community Forum.

    Best regards, 
    Jaromił

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

    Thanks for your response. 

    This is constraint in my code:

    for edge in df_edges.index:

           model.addConstr((D_edge[edge] * D_edge[edge]) >= (4 * 10e6 * mass_edge[edge] * Bp[edge]) /        (3600 * 3.14 * ro * V_max))

    in this constraint the D_edge and mass_edge are continuous variables and Bp is binary variable.

    When I run my model with this constraint and with a different objective function that doesn't involve the variable D_edge, the model performs well. However, when I include D_edge in my objective function, it significantly increases the time required for solving, often prompting me to interrupt the process.

    I tried your suggestion, but I think it does not work. Can you tell me what is the problem when I put D_edge variable in objective function? Or could you please guide me how I can manage this constraint? Thanks a lot

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

    this constraint is related to the determination of pipe sizes in district heating network. D_edge is diameter of each pipe, mass_edge is mass rate in each pipe and Bp is binary variable for selection the pipe. these are more line of my codes including objective function. 

    Cost_cap_pi = 0.0
    #M=1000000
    Cost_pi = {}

    for edge in df_edges.index:
        # Create a Gurobi variable for each edge
        Cost_pi[edge] = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"Cost_pi_{edge}")

        # Piping cost calculation
        Cost_pi_unit = 5.36 * D_edge[edge] + 139.15 * (Bp[edge]) # CHF/m
        model.addConstr(Cost_pi[edge] == Cost_pi_unit * df_edges.at[edge, 'length'])

        Cost_cap_pi += Cost_pi[edge]

    Cost_pi_tot = 2 * Cost_cap_pi


    model.setObjective(Cost_pi_tot , GRB.MINIMIZE)
    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    I tried your suggestion, but I think it does not work. Can you tell me what is the problem when I put D_edge variable in objective function? Or could you please guide me how I can manage this constraint?

    In general, there is nothing wrong in using D_edge in your objective. However, with the new constraint your model is now nonconvex which makes the model by itself a lot harder. Additionally, from what you are saying it looks like that if you add D_edge to the objective that this steers the optimal solution point into an area of nonconvexity. There are no good general workarounds for this.

    Could you please share a log output of your model? If possible, you could also share your model. You can generate an MPS or an LP file via the write() method. Note that uploading files in the Community Forum is not possible but we discuss an alternative in Posting to the Community Forum.

    Best regards, 
    Jaromił

     

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

    Thank you. 

    Here is file link of my code.

    https://www.filemail.com/d/xldiqdqckummbbe 

    for example if i set the objective function without the D_edge variable it works well( such as this file), but if i add the main objective function such as : 

    # ----------------- Set Objective Function -------------------- #

    ### Capital Cost of piping 

    Cost_cap_pi = 0.0
    Cost_pi = {}

    for edge in df_edges.index:
        Cost_pi[edge] = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"Cost_pi_{edge}")

        # Piping cost calculation
        Cost_cap_pi += Cost_pi[edge]

    Cost_pi_tot = 2 * Cost_cap_pimodel.setObjective(Cost_pi_tot , GRB.MINIMIZE)

    it takes a lot of time and didn't give me a solution. 
    thank you. 

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Thank you. Could you please also share the model where Gurobi does not converge well?

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Note that it would be best to again share just the MPS or LP file and not the Python code. If you share the Python code, then you also have to share all files it depends on which might be a lot (and possibly confidential).

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    The main difference between the two models is that some continuous variables have now more freedom. In the following I am referring to constraints which you get when you generate the human-readable LP file out of the MPS file. You can do that via, e.g.,

    ./gurobi_cl resultfile=my_model.lp timelimit=1 my_model.mps

    For example

    R844: - 56.57181062942548 B2351(5) + C2652(1) = 0

    vs

    R844: - 303.2249049737206 C2342(2) - 7871.967449084555 B2351(5) + C2652(1) = 0

    In the first constraint C2652(1) can attain only 2 values 0 or 56.57181062942548. In the second case C2652(1) can attain many (continuous) values making the proof of global optimality way harder.

    In general, the second model will always be way harder to solve than the first one due to the above.

    Anyway, you could try the following reformulation:

    Use the constraints

    R688: - 85.6668337605393 C2(2) - 2223.981327943851 B11(6) + C2496(1) = 0
    qc250: C12(2) + [ - 0.151888879626705 C1(5) * B11(6) ] = 0
    qc251: - C12(2) + [ C2(2) ^2 ] >= 0

    to first get

    R688: - 85.6668337605393 C2(2) - 2223.981327943851 B11(6) + C2496(1) = 0
    qc251: [ - 0.151888879626705 C1(5) * B11(6) + C2(2) ^2 ] >= 0

    and then solve for C2(2) to get

    R688:  - 2223.981327943851/85.6668337605393 B11(6) + 1/85.6668337605393 C2496(1) = C2(2)
    qc251: [ - 0.151888879626705 C1(5) * B11(6) + C2(2) ^2 ] >= 0

    Then substitute C2(2) into the square term

    qc251: [ - 0.151888879626705 C1(5) * B11(6) + (- 2223.981327943851/85.6668337605393 B11(6) + 1/85.6668337605393 C2496(1)) ^2 ] >= 0

    which gives

    qc251:  (2223.981327943851/85.6668337605393)^2 B11(6) +  [ - 0.151888879626705 C1(5) * B11(6) - 2 * 2223.981327943851/85.6668337605393 * 1/85.6668337605393 C2496(1) * B11(6) +  (1/85.6668337605393 C2496(1)) ^2 ] >= 0

    I used that B11(6)^2 = B11(6) because B11(6) is a binary variable.
    You could do this reformulation at the model construction level. There is no guarantee that this helps performance but I think it might be worth a try.

    Best regards, 
    Jaromił

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

     I think it is better I use the root 2 in objective function for that. Can i implement it by 

    Model.addGenConstrPow()? 

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    You could but this would then be a piecewise-linear approximation, see General Functions Constraints docs. Thus, I would stick to the quadratic formulation.

    It would also be best if you bound every continuous variable. From looking at your model, I think you could bound every variable between [0,1e+06].

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

    I tried it but it doesn't work (it's same as before). i have a constraint such as: 

    model.addConstr(aux1[edge] == fix * mass_edge[edge] * Bp[edge])

    model.addConstr(D_edge[edge] * D_edge[edge] >= (aux1[edge]))

    when i delete one of the D_edge[edge] in second line, it works well. i can put the one variable instead D_edge[edge] * D_edge[edge] . but I have a D_edge in objective function, so i need put square root for that. What do you think? 

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    You could try the square root approach. It might work, but please keep in mind that Gurobi currently works with a piecewise-linear approximation of the \(\sqrt{}\) function and not with the true \(\sqrt{}\) function. This might lead to numerical inaccuracies in the final solution.

    You also have to make sure that the argument variables are \(\geq 0\) when working with the \(\sqrt{}\) function.

    Regarding variable bounds: You might want to try and use some problem knowledge you have to bound at least some of the variables without turning the model infeasible.

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

    Yes, but it is very weird because when i want to limit some variables it takes more time. in this special problem when i set this heuristics solver parameter model.setParam(GRB.Param.Heuristics, 0.1) it works. But i have not understood yet what was the problem with my code. I'm scared that it will not be general. 

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    If finding a good feasible solution point is the bottleneck for your model then setting the Heuristics parameter definitely makes sense.

    But i have not understood yet what was the problem with my code. I'm scared that it will not be general. 

    This is something you could find out through try-and-error and by utilizing as much problem knowledge as possible.

    0
  • atefeh Behzadi
    Gurobi-versary
    Conversationalist
    First Question

    Yes, i guess it too. Thanks a lot. 

    0

サインインしてコメントを残してください。