LpPiecewise2

class passengersim.rm.linear_program.LpPiecewise2(carrier: str, epsilon: float = 0.01, _debug: bool = False)[source]

Bases: LpBase

Piecewise Linear Program from Talluri & Van Ryzin (3.8). Formulation and code by Rithvik

For each product j and each unit of capacity d = 1, …, M_j, define variable z_{j,d} in [0, 1] representing the d-th unit of capacity allocated to product j. The objective coefficient is p_j * P(D_j >= d), the marginal expected revenue of that unit. Because P(D_j >= d) is non-increasing in d, the LP automatically fills lower-indexed (higher probability) units first.

For continuous normal demand:

P(D_j >= d) = 1 - Phi((d - mu_j) / sigma_j)

The resulting LP is:

max sum_j p_j * sum_{d=1}^{M_j} P(D_j >= d) * z_{j,d} s.t. sum_{j uses leg l} sum_d z_{j,d} <= cap_l - sold_l

0 <= z_{j,d} <= 1

M_j is the minimum remaining capacity across all legs used by product j, which is the tightest feasible upper bound on allocations to that product.

The dual of each leg capacity constraint is the displacement cost (bid price), written back to leg.displacement.

Parameters:
sim : SimulationEngine

carrier : str

epsilon : float

Treat demand mean/sigma below this as effectively zero.

_debug : bool

Methods

__init__(carrier[, epsilon, _debug])

initialize(eng)

Construct the LP from current path-class forecasts and remaining leg capacities.

solve(eng[, debug])

Solve the LP and write dual values (displacement costs / bid prices) back to each leg.

test_status(status)

update(eng)

Attributes

carrier

solver

objective

lp_vars

constraints

epsilon

set_bp

debug

carrier
epsilon
set_bp
debug
initialize(eng: SimulationEngine)[source]

Construct the LP from current path-class forecasts and remaining leg capacities. Called once per DCP.

Implements (3.8):
  • Variable z_{j,d} in [0,1] for each product j, unit d = 1..M_j

  • Objective coefficient: p_j * P(D_j >= d)

  • Capacity constraint per leg: sum of all z_{j,d} for products on that leg <= remaining capacity

Requires sim.build_connections() to have been called so that path.num_legs() and path.get_leg_fltno() are populated.

update(eng: SimulationEngine)[source]
solve(eng: SimulationEngine, debug: bool = False)[source]

Solve the LP and write dual values (displacement costs / bid prices) back to each leg.

solver
objective
lp_vars
constraints
test_status(status)