I have an issue as the problem is not optimaze and I am trying to use a binary variable x to identify if the edge is used or not as the number of edges used should be minimized. The issue is that I cannot assign the correct value to x=1 when the Q of the edge is greater then zero. There is surely an issue or in the objective function or in the contraint 7. This is the code I am running:
import matplotlib.pyplot as plt
import networkx as nx
import pyomo.environ as pe
import pyomo.opt as po
import pandas as pd
import numpy as np
d = pd.read_excel("Grafo9Nodi_Bil.xlsx",header=0, index_col=0) #importo le posizioni dal file Excel
#impongo una lunghezza massima del singolo arco
LunMax=8
nodes = range(0,len((d["X"])))
distance = {}
pos={}
edges={}
for i in sorted(nodes):
pos[i]=(d["X"][i],d["Y"][i])
for j in sorted(nodes):
if i!=j and np.round(pe.sqrt((d["X"][i]-d["X"][j])**2+(d["Y"][i]-d["Y"][j])**2),2)<=LunMax:
distance [i,j]=np.round(pe.sqrt((d["X"][i]-d["X"][j])**2+(d["Y"][i]-d["Y"][j])**2),2)
edges={(i,j) for i in sorted(nodes) for j in sorted(nodes) if i!=j and np.round(pe.sqrt((d["X"][i]-d["X"][j])**2+(d["Y"][i]-d["Y"][j])**2),2)<=LunMax}
model = pe.ConcreteModel()
path_edges = []
model.nodes = pe.Set(initialize=nodes)
model.edges = pe.Set(within=model.nodes*model.nodes, initialize=edges)
model.IN = pe.Var(model.nodes, domain=pe.NonNegativeReals,initialize=0)
IN=model.IN
model.x = pe.Var(model.nodes*model.nodes, domain=pe.Binary,initialize=0)
x=model.x
model.Q = pe.Var(model.nodes*model.nodes, domain=pe.NonNegativeReals)
Q=model.Q
model.OUT = pe.Var(model.nodes, domain=pe.NonNegativeReals,initialize=0)
OUT=model.OUT
#funzione obiettivo
def obj_rule(model):
TCC=sum(d["OpexC"][i]*IN[i] for i in model.nodes)
TTC=sum(Q[i,j]*1*distance[i,j] if Q[i,j] is not None and Q[i,j].value != 0 else 0 for [i,j] in model.edges)+sum(distance [i,j]*4*x[i,j] for [i,j] in model.edges if x[i,j].value != None and x[i,j].value != 0)
TSC=sum(d["OpexS"][i]*OUT[i] for i in model.nodes)
return TCC+TTC+TSC
model.Objf= pe.Objective (rule=obj_rule, sense = pe.minimize)
#vincoli
def constraint1(model,nodes):
return IN[nodes] <= d["IN"][nodes]
model.Const1=pe.Constraint(model.nodes, rule=constraint1)
def constraint2(model,nodes):
return sum(IN[nodes] for nodes in model.nodes) >= 1*sum(d["IN"][nodes] for nodes in model.nodes)
model.Const2=pe.Constraint(model.nodes, rule=constraint2)
def constraint4(model,nodes):
return IN[nodes]+sum(Q[i,nodes] for i in model.nodes if [i,nodes] in model.edges) == sum(Q[nodes,i] for i in model.nodes if [i,nodes] in model.edges) +OUT[nodes]
model.Const4=pe.Constraint(model.nodes, rule=constraint4)
def constraint5(model,nodes):
return OUT[nodes] <= d["OUT"][nodes]
model.Const5=pe.Constraint(model.nodes, rule=constraint5)
def constraint6(model,nodes):
return sum(IN[nodes] for nodes in model.nodes) == sum(OUT[nodes] for nodes in model.nodes)
model.Const6=pe.Constraint(model.nodes, rule=constraint6)
def constraint7(model, i, j):
if Q[i,j].value != 0:
return x[i,j] == 1
else:
return x[i,j] == 0
model.Const7 = pe.Constraint(model.edges, rule=constraint7)
Solver = po.SolverFactory ('gurobi', tee=True)
results = Solver.solve(model)
The result is not optimazed as x[i,j] are all equal to 1 while Q[i,j] have different values. Thanks in advance for the help