For my study I have to make some exercises and I am getting stuck on a specific question. Here is the introduction to the exercise:
Introduction The flower-cutting company “Blossom Logistics” specializes in the transportation of fresh flow- ers. Blossom Logistics operates a network comprising fields, warehouses, and retailers. Within their network, they handle three distinct categories of flowers: romantic roses (R), vibrant tulips (T), and delicate lilies (L). They transfer the flower in boxes. The company faces in- creasing competition during the flowering season, so optimizing its network has become crucial. As an intern in Blossom Logistics’ operations department, you have received two data files: “nodes.txt” and “fixedCost.txt”. The “nodes.txt” file contains essential information about each node’s location, supply, and demand for each flower category. Meanwhile, the “fixedCost.txt” file includes the fixed charges associated with utilizing different transportation routes between the nodes. The network is represented by a directed graph, denoted as G = (V, A), and can be visualized in Figure 1. Here, V represents the set of all nodes, and A represents the set of all possible arcs. In the “nodes.txt” file, the column “StringID” denotes the unique identifier for each node. The nodes are categorized as follows: “f” for fields, “w” for warehouses, and “r” for retailers. The columns “x” and “y” represent the coordinates of each node. Additionally, the columns “capR”, “capT”, and “capL” denote the capacity of each node for romantic roses, vibrant tulips, and delicate lilies, respectively. The columns “demR”, “demT”, and “demL” represent the demand of each node for romantic roses, vibrant tulips, and delicate lilies, respectively.
Here is the nodes.txt:
StringID x y capR capT capL demR demT demL
f1 6 8 55 100 55 0 0 0
f2 7 27 55 115 150 0 0 0
w3 -8 13 0 0 0 0 0 0
w4 12 -23 0 0 0 0 0 0
w5 27 8 0 0 0 0 0 0
w6 -6 28 0 0 0 0 0 0
w7 3 -15 0 0 0 0 0 0
r8 -29 -27 0 0 0 40 70 70
r9 20 7 0 0 0 25 95 75
r10 -12 25 0 0 0 45 50 60
Transportation cost per kilometer for a box of R flower: 2
Transportation cost per kilometer for a box of T flower: 3
Transportation cost per kilometer for a box of L flower: 4
Below I provided pictures of the particular part I have troubles with: Part 1 Part 2
So I have to code the model in python using Gurobi. The problem is is that I keep getting and infeasible solution. The code I have for now:
Aria Dahimi
import gurobipy as gp
import numpy as np
1) Read the data and define the problem
instname = 'nodes'
mainFolderInput = 'C:\\Users\\karsp\\Documents\\Python Scripts\\'
mainFolderResults = 'C:\\Users\\karsp\\Documents\\Python Scripts\\'
fileAddress = mainFolderInput + instname + '.txt'
f = open(fileAddress)
nodeCount = 0
requestCount = 1
costFactor = 0
fDict = {}
rDict = {}
wDict = {}
for line in f.readlines()[1:-4]:
asList = []
n = 13
for index in range(0, len(line)-1, n):
if index == 0:
asList.append(line[index : index + n].strip())
else:
asList.append(int(line[index : index + n].strip()))
lID = asList[0]
if lID.startswith("f"):
fDict[lID] = asList
if lID.startswith("r"):
rDict[lID] = asList
if lID.startswith("w"):
wDict[lID] = asList
vDict = {}
vDict.update(fDict)
vDict.update(rDict)
vDict.update(wDict)
print(fDict)
print()
print(rDict)
print()
print(wDict)
print()
print(vDict)
f = open(fileAddress)
capLine = f.readlines()[-1]
costFactor = int(capLine[-5:].strip())
print(costFactor)
{'f1': ['f1', 6, 8, 55, 100, 55, 0, 0, 0], 'f2': ['f2', 7, 27, 55, 115, 150, 0, 0, 0]}
{'r8': ['r8', -29, -27, 0, 0, 0, 40, 70, 70], 'r9': ['r9', 20, 7, 0, 0, 0, 25, 95, 75], 'r10': ['r10', -12, 25, 0, 0, 0, 45, 50, 60]}
{'w3': ['w3', -8, 13, 0, 0, 0, 0, 0, 0], 'w4': ['w4', 12, -23, 0, 0, 0, 0, 0, 0], 'w5': ['w5', 27, 8, 0, 0, 0, 0, 0, 0], 'w6': ['w6', -6, 28, 0, 0, 0, 0, 0, 0], 'w7': ['w7', 3, -15, 0, 0, 0, 0, 0, 0]}
{'f1': ['f1', 6, 8, 55, 100, 55, 0, 0, 0], 'f2': ['f2', 7, 27, 55, 115, 150, 0, 0, 0], 'r8': ['r8', -29, -27, 0, 0, 0, 40, 70, 70], 'r9': ['r9', 20, 7, 0, 0, 0, 25, 95, 75], 'r10': ['r10', -12, 25, 0, 0, 0, 45, 50, 60], 'w3': ['w3', -8, 13, 0, 0, 0, 0, 0, 0], 'w4': ['w4', 12, -23, 0, 0, 0, 0, 0, 0], 'w5': ['w5', 27, 8, 0, 0, 0, 0, 0, 0], 'w6': ['w6', -6, 28, 0, 0, 0, 0, 0, 0], 'w7': ['w7', 3, -15, 0, 0, 0, 0, 0, 0]}
4
transportCosts = {(i, j): costFactor * np.math.trunc(np.hypot(fDict[i][1]-wDict[j][1], fDict[i][2]-wDict[j][2])) for i in list(fDict.keys()) for j in list(wDict.keys())}
transportCosts2 = {(i, j): costFactor * np.math.trunc(np.hypot(wDict[i][1]-rDict[j][1], wDict[i][2]-rDict[j][2])) for i in list(wDict.keys()) for j in list(rDict.keys())}
transportCosts3 = {(i, j): costFactor * np.math.trunc(np.hypot(wDict[i][1]-wDict[j][1], wDict[i][2]-wDict[j][2])) for i in list(wDict.keys()) for j in list(wDict.keys())}
transportCosts.update(transportCosts2)
transportCosts.update(transportCosts3)
transportCosts
{('f1', 'w3'): 56,
('f1', 'w4'): 124,
('f1', 'w5'): 84,
('f1', 'w6'): 92,
('f1', 'w7'): 92,
('f2', 'w3'): 80,
('f2', 'w4'): 200,
('f2', 'w5'): 108,
('f2', 'w6'): 52,
('f2', 'w7'): 168,
('w3', 'r8'): 180,
('w3', 'r9'): 112,
('w3', 'r10'): 48,
('w4', 'r8'): 164,
('w4', 'r9'): 124,
('w4', 'r10'): 212,
('w5', 'r8'): 264,
('w5', 'r9'): 28,
('w5', 'r10'): 168,
('w6', 'r8'): 236,
('w6', 'r9'): 132,
('w6', 'r10'): 24,
('w7', 'r8'): 136,
('w7', 'r9'): 108,
('w7', 'r10'): 168,
('w3', 'w3'): 0,
('w3', 'w4'): 164,
('w3', 'w5'): 140,
('w3', 'w6'): 60,
('w3', 'w7'): 120,
('w4', 'w3'): 164,
('w4', 'w4'): 0,
('w4', 'w5'): 136,
('w4', 'w6'): 216,
('w4', 'w7'): 48,
('w5', 'w3'): 140,
('w5', 'w4'): 136,
('w5', 'w5'): 0,
('w5', 'w6'): 152,
('w5', 'w7'): 132,
('w6', 'w3'): 60,
('w6', 'w4'): 216,
('w6', 'w5'): 152,
('w6', 'w6'): 0,
('w6', 'w7'): 172,
('w7', 'w3'): 120,
('w7', 'w4'): 48,
('w7', 'w5'): 132,
('w7', 'w6'): 172,
('w7', 'w7'): 0}
2) initialize the model
TPModel = gp.Model('1CK100-TP')
Set parameter Username
Academic license - for non-commercial use only - expires 2024-06-01
TPModel.modelSense = gp.GRB.MINIMIZE
3) Variables
arcs = [('f1','w3'),('f1','w4'),('f2', 'w4'),('f2','w5'),('w3','w6'),('w4','w6'),('w4','r9'),('w4','w7'),('w5','w7'),('w5','r9'),('w6','r8'),('w6','r9'),('w6','r10'),('w7','r8'),('w7','r9'),('w7','r10')]
x = TPModel.addVars(arcs, vtype=gp.GRB.INTEGER, name='x')
x
{('f1', 'w3'): <gurobi.Var *Awaiting Model Update*>,
('f1', 'w4'): <gurobi.Var *Awaiting Model Update*>,
('f2', 'w4'): <gurobi.Var *Awaiting Model Update*>,
('f2', 'w5'): <gurobi.Var *Awaiting Model Update*>,
('w3', 'w6'): <gurobi.Var *Awaiting Model Update*>,
('w4', 'w6'): <gurobi.Var *Awaiting Model Update*>,
('w4', 'r9'): <gurobi.Var *Awaiting Model Update*>,
('w4', 'w7'): <gurobi.Var *Awaiting Model Update*>,
('w5', 'w7'): <gurobi.Var *Awaiting Model Update*>,
('w5', 'r9'): <gurobi.Var *Awaiting Model Update*>,
('w6', 'r8'): <gurobi.Var *Awaiting Model Update*>,
('w6', 'r9'): <gurobi.Var *Awaiting Model Update*>,
('w6', 'r10'): <gurobi.Var *Awaiting Model Update*>,
('w7', 'r8'): <gurobi.Var *Awaiting Model Update*>,
('w7', 'r9'): <gurobi.Var *Awaiting Model Update*>,
('w7', 'r10'): <gurobi.Var *Awaiting Model Update*>}
3) Objective function
TPModel.setObjective(
gp.quicksum(transportCosts[i, j] * x[i, j] for i, j in arcs)
)
4) Constraints
Capacity of warehouses
v = vDict.keys()
FirstConstraint = TPModel.addConstrs((gp.quicksum(x[i, j] for j in v if (i, j) in arcs) - gp.quicksum(x[j, i] for j in v if (j, i) in arcs) == fDict[i][5] for i in fDict.keys()), name='balance_f')
v = vDict.keys()
SecondConstraint = TPModel.addConstrs((gp.quicksum(x[i, j] for j in v if (i, j) in arcs) - gp.quicksum(x[j, i] for j in v if (j, i) in arcs) == (-1 * rDict[i][8]) for i in rDict.keys()), name='balance_r')
v = vDict.keys()
ThirdConstraint = TPModel.addConstrs((gp.quicksum(x[i, j] for j in v if (i, j) in arcs) - gp.quicksum(x[j, i] for j in v if (j, i) in arcs) == 0 for i in wDict.keys()), name='balance_w')
FourthConstraint = TPModel.addConstrs((x[i, j] >= 0 for i, j in arcs), name='nonnegativity')
Does anyone know why my model is infeasible and if so how do I correct it?