Skip to main content

Adding constraints only if a certain condition is verified

Answered

Comments

4 comments

  • Simranjit Kaur
    Gurobi Staff Gurobi Staff

    Hi Maria,

    It seems you are trying to find the minimum of the dist_ij when the fixed number (loaded from outside) assigned to both i and j is 1. In this case, the min_dist calculation can simply be done in Python (no need to define any variables or constraints):

    min_dist = min( dist_ij for i in I for j in I if num_i = 1 and num_j = 1)

    where num_i is the fixed number assigned to i. Please note here I am assuming that dist_ij is a known fixed value for every pair of i and j.

    Best regards,
    Simran

    0
  • Maria Laura Santoni
    First Comment
    First Question

    Hi Simran,

    This is my current code:

    from gurobipy import Model, GRB, quicksum
    import numpy as np


    # Carica i pesi da un file txt (10000 pesi)
    weights = np.loadtxt('15_0_2_10000_5_-5_5_1000_sample_values.txt', usecols=[0], skiprows=1)

    # Carica le distanze da un file txt (10000 righe e 10000 colonne)
    distances = np.loadtxt('distances.txt')

    # Creazione del modello
    model = Model()

    # Crea le variabili binarie
    num_var = len(weights)
    var = model.addVars(num_var, vtype=GRB.BINARY, name="variable")
    #distanza_vars = model.addVars([(i, j) for i in range(num_var) for j in range(i + 1, num_var)], vtype=GRB.INTEGER, name="distanza_var")

    # Constants
    # M is chosen to be as small as possible given the bounds on x and y
    # eps = 0.0001
    # M = 2 + eps
    # Crea il vincolo per la distanza tra i punti
    min_dist = 3  # Specifica il valore minimo di distanza
    dist_var = model.addVars(num_var, num_var, vtype=GRB.INTEGER, name='dist_var')
    for i in range(num_var):
        for j in range(i + 1, num_var):
            model.addConstr(dist_var[i,j] == var[i] + var[j])
            model.addConstr((dist_var[i,j] == 2) >> (distances[i,j]>=min_dist))
    # Crea il vincolo per la somma delle variabili
    model.addConstr(var.sum() == 5, "sum_constraint")
    # Crea la funzione obiettivo utilizzando le distanze
    # Definisci la funzione obiettivo
    objective = quicksum(var[i] * weights[i] for i in range(num_var))
    model.setObjective(objective, GRB.MINIMIZE)

    # Ottimizza il modello
    model.optimize()

    # Stampa i risultati
    if model.status == GRB.OPTIMAL:
        results= f"Optimal value: {model.objVal}\nOptimal solution: {[var[i].x for i in range(num_var)]}"
        # Salva i risultati in un file
        with open('results_d3_f15.txt', 'w') as file:
            file.write(results)
    else:
        print("The problem does not have a solution.")
     
     
     
     
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     
    I am trying to put some constraints: if var_i and var_j are both equal to 1 then d_ij has to be bigger or equal to min_dist. I already know d_ij and min_dist to (It is a threshold that I fix before).
     
    with this code, I got the error:
    raceback (most recent call last): File "/dss/dsshome1/lxc0D/ge89yen2/Gurobi/main3.py", line 29, in <module> model.addConstr((dist_var[i,j] == 2) >> (distances[i,j]>=min_dist)) File "src/gurobipy/model.pxi", line 3591, in gurobipy.Model.addConstr File "src/gurobipy/model.pxi", line 4670, in gurobipy.Model.addGenConstrIndicator TypeError: unsupported operand type(s) for -=: 'NoneType' and 'flo
    0
  • Michel Soares
    Thought Leader

    Hi Maria,

    I believe var_i =1 and var_j =1 then dist_ij>= min_dist could be modelled as:

    dist_ij >= (var_i * var_j  * min_dist)

    That would make your model quadratic, but it should yield the desired result. I believe this would be the constraint, and I encourage you to read the documentation for quadratic constraint:

    model.addQConstr(dist_var[i,j] >= var[j] * var[j] * min_dist)
    0
  • Simranjit Kaur
    Gurobi Staff Gurobi Staff

    Hi Maria,

    Thanks for sharing your code. Since var_i and var_j are decision variables in the model that are not known a priori, the suggestion in my previous comment will not work.

    The condition
                 "If var_i =1 and var_j =1, then dist_ij>= min_dist"
    is equivalent to saying
           " If dist_ij < min_dist, then at least one of var_i or var_j must be zero".

    Since distances[i,j] and min_dist are inputs to your model, the above condition can be modelled using linear constraints as follows:

    if distances[i,j] < min_dist:
        model.addConstr(var[i] +var[j] <= 1)

    Best regards,
    Simran

    0

Please sign in to leave a comment.