Skip to content

2 LP infeasible

View or edit on GitHub

This page is synchronized from trase/models/lp/2_LP_infeasible.ipynb. Last modified on 2026-03-20 23:00 CET by Trase Admin. Please view or edit the original file there; changes should be reflected here after a midnight build (CET time), or manually triggering it with a GitHub action (link).

LP between farms and silos - Infeasible

import pandas as pd

from functools import partial
from pulp import (
    getSolver,
    LpProblem,
    LpMinimize,
    LpVariable,
    lpSum,
)

from trase.models.lp.plot import plot_dataframe
from trase.tools.sps import SupplyChain

sc = SupplyChain("lp", year=2023)
# sc.preparation()
sc.load()

df_supply = sc.get("production")
supply_sum = df_supply["production_vol"].sum()

df_demand = sc.get("silos")
df_demand = df_demand[df_demand.pop("facility_type") == "hub"]
capacity_sum = df_demand["storage_capacity"].sum()

We now assume that all the soy produced must go to hubs.

df_demand["silo_demand_vol"] = (
    df_demand.pop("storage_capacity") * supply_sum / capacity_sum
)

df_costs = sc.get("cost")

problem = LpProblem("MunicipalityToSilo", LpMinimize)

df = pd.merge(df_supply, df_demand, how="cross")
df = pd.merge(
    df,
    df_costs,
    left_on=["production_trase_id", "silo_trase_id"],
    right_on=["origin_trase_id", "destination_trase_id"],
).drop(columns=["origin_trase_id", "destination_trase_id"])

df["variable_name"] = "v" + df.index.to_series().astype(str)
df["variable"] = df["variable_name"].apply(partial(LpVariable, lowBound=0))

for (production_trase_id, production_vol), variables in df.groupby(
    ["production_trase_id", "production_vol"]
)["variable"]:
    problem += (lpSum(variables) <= production_vol, f"supply at {production_trase_id}")

for (silo_trase_id, silo_demand_vol), variables in df.groupby(
    ["silo_trase_id", "silo_demand_vol"]
)["variable"]:
    problem += (lpSum(variables) == silo_demand_vol, f"demand at {silo_trase_id}")

problem += (lpSum(df["variable"] * df["cost"]), "total cost")

Solve LP

problem.solve(getSolver("GLPK_CMD"))
GLPSOL--GLPK LP/MIP Solver 5.0
Parameter(s) specified in the command line:
 --cpxlp /tmp/28e56e5a0940422ca84f2f3d128e0ce4-pulp.lp -o /tmp/28e56e5a0940422ca84f2f3d128e0ce4-pulp.sol
Reading problem data from '/tmp/28e56e5a0940422ca84f2f3d128e0ce4-pulp.lp'...
2740 rows, 356611 columns, 713222 non-zeros
195006 lines were read
GLPK Simplex Optimizer 5.0
2740 rows, 356611 columns, 713222 non-zeros
Preprocessing...
2740 rows, 356611 columns, 713222 non-zeros
Scaling...
 A: min|aij| =  1.000e+00  max|aij| =  1.000e+00  ratio =  1.000e+00
Problem data seem to be well scaled
Constructing initial basis...
Size of triangular part is 2740
      0: obj =   4.691082694e+07 inf =   1.137e+08 (121)
   1912: obj =   6.403750909e+10 inf =   3.150e+07 (21) 1
   2615: obj =   1.046920160e+11 inf =   4.230e-05 (1)
LP HAS NO PRIMAL FEASIBLE SOLUTION
glp_simplex: unable to recover undefined or non-optimal solution
If you need actual output for non-optimal solution, use --nopresol
Time used:   7.0 secs
Memory used: 243.3 Mb (255078556 bytes)
Writing basic solution to '/tmp/28e56e5a0940422ca84f2f3d128e0ce4-pulp.sol'...





-3

The solver is unable to find a solution.

This means that some volumes demanded by the hubs cannot be supplied by municipalities of production.

Unfortunately the solver cannot give more details.

The issue is usually related to missing paths in the cost matrix: some demand centers are not connected to enough supply centers to meet their demand.