9 Combine LP and stitching
View or edit on GitHub
This page is synchronized from trase/models/lp/9_Combine_LP_and_stitching.ipynb. Last modified on 2026-05-06 16:54 CEST 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).
Combine LP and stitching
import pandas as pd
from pulp import getSolver
from trase.tools.sps import solve_transportation_problem, stitch_dataframes
df_exports = pd.DataFrame(
data=[
("PORT-1", "EXPORTER-1", 100),
("PORT-1", "EXPORTER-2", 200),
("PORT-1", "EXPORTER-3", 50),
("PORT-2", "EXPORTER-1", 50),
("PORT-3", "EXPORTER-2", 100),
],
columns=["port", "exporter", "vol"],
)
df_supply = pd.DataFrame(
data=[
("SILO-1", 100),
("SILO-2", 100),
("SILO-3", 100),
("SILO-4", 100),
("SILO-5", 100),
],
columns=["silo", "vol"],
)
df_costs = pd.DataFrame(
data=[
("SILO-1", "PORT-1", 40),
("SILO-1", "PORT-2", 60),
("SILO-1", "PORT-3", 80),
("SILO-2", "PORT-1", 30),
("SILO-2", "PORT-2", 50),
("SILO-2", "PORT-3", 70),
("SILO-3", "PORT-1", 20),
("SILO-3", "PORT-2", 10),
("SILO-3", "PORT-3", 20),
("SILO-4", "PORT-1", 35),
("SILO-4", "PORT-2", 35),
("SILO-4", "PORT-3", 55),
("SILO-5", "PORT-1", 80),
("SILO-5", "PORT-2", 60),
("SILO-5", "PORT-3", 40),
],
columns=["origin", "destination", "cost"],
)
supply = df_supply.set_index("silo")["vol"]
demand = df_exports.groupby("port")["vol"].sum()
costs = df_costs.set_index(["origin", "destination"])["cost"]
solution, leftover_supply = solve_transportation_problem(
supply=supply,
demand=demand,
costs=costs,
solver=getSolver("GLPK_CMD"),
)
GLPSOL--GLPK LP/MIP Solver 5.0
Parameter(s) specified in the command line:
--cpxlp /tmp/4671b6287ff445e79e43cee2e98507c4-pulp.lp -o /tmp/4671b6287ff445e79e43cee2e98507c4-pulp.sol
Reading problem data from '/tmp/4671b6287ff445e79e43cee2e98507c4-pulp.lp'...
8 rows, 15 columns, 30 non-zeros
14 lines were read
GLPK Simplex Optimizer 5.0
8 rows, 15 columns, 30 non-zeros
Preprocessing...
8 rows, 15 columns, 30 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 8
0: obj = 3.500000000e+04 inf = 4.000e+02 (1)
5: obj = 1.950000000e+04 inf = 0.000e+00 (0)
* 8: obj = 1.600000000e+04 inf = 0.000e+00 (0)
OPTIMAL LP SOLUTION FOUND
Time used: 0.0 secs
Memory used: 0.0 Mb (39693 bytes)
Writing basic solution to '/tmp/4671b6287ff445e79e43cee2e98507c4-pulp.sol'...
/mnt/custom-file-systems/efs/fs-049d752ef37739434/shared/shared_repos/TRASE/trase/tools/sei_pcs/pandas_lp.py:275: FutureWarning: The provided callable <built-in function sum> is currently using np.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string np.sum instead.
.apply(sum)
/mnt/custom-file-systems/efs/fs-049d752ef37739434/shared/shared_repos/TRASE/trase/tools/sei_pcs/pandas_lp.py:346: FutureWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.
infeasible = df.groupby("sink_group").apply(
/mnt/custom-file-systems/efs/fs-049d752ef37739434/shared/shared_repos/TRASE/trase/tools/sei_pcs/pandas_lp.py:532: FutureWarning: The provided callable <built-in function sum> is currently using np.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string np.sum instead.
df_allocation.groupby(["source"])["quantity"].apply(sum).to_frame()
df_solution = solution.reset_index()
df_solution
| silo | port | vol | |
|---|---|---|---|
| 0 | SILO-1 | PORT-1 | 100.0 |
| 1 | SILO-2 | PORT-1 | 100.0 |
| 2 | SILO-3 | PORT-1 | 50.0 |
| 3 | SILO-3 | PORT-2 | 50.0 |
| 4 | SILO-4 | PORT-1 | 100.0 |
| 5 | SILO-5 | PORT-3 | 100.0 |
df = stitch_dataframes(df_solution, df_exports, volume_column="vol")
df[["silo", "port", "exporter", "vol"]]
| silo | port | exporter | vol | |
|---|---|---|---|---|
| 0 | SILO-1 | PORT-1 | EXPORTER-1 | 28.571429 |
| 1 | SILO-2 | PORT-1 | EXPORTER-1 | 28.571429 |
| 2 | SILO-3 | PORT-1 | EXPORTER-1 | 14.285714 |
| 3 | SILO-4 | PORT-1 | EXPORTER-1 | 28.571429 |
| 4 | SILO-1 | PORT-1 | EXPORTER-2 | 57.142857 |
| 5 | SILO-2 | PORT-1 | EXPORTER-2 | 57.142857 |
| 6 | SILO-3 | PORT-1 | EXPORTER-2 | 28.571429 |
| 7 | SILO-4 | PORT-1 | EXPORTER-2 | 57.142857 |
| 8 | SILO-1 | PORT-1 | EXPORTER-3 | 14.285714 |
| 9 | SILO-2 | PORT-1 | EXPORTER-3 | 14.285714 |
| 10 | SILO-3 | PORT-1 | EXPORTER-3 | 7.142857 |
| 11 | SILO-4 | PORT-1 | EXPORTER-3 | 14.285714 |
| 12 | SILO-3 | PORT-2 | EXPORTER-1 | 50.000000 |
| 13 | SILO-5 | PORT-3 | EXPORTER-2 | 100.000000 |