spopt.locate.FRLM¶
- class spopt.locate.FRLM(vehicle_range: float | int = 200000, p_facilities: int = 5, capacity: float | None = None, threshold: float = 0.0, weight: float = 0.99, objective: str = 'flow', include_destination: bool = False)[source]¶
Flow Refueling Location Model (FRLM)
- Parameters:
- vehicle_range
float|int, default=200000.0 Defines the maximum travel distance or range for vehicles.
If value is between 0 and 1: Treated as a percentage of the longest path. e.g. 0.5: 50% of the longest path in the network
If value > 1: Treated as an absolute distance in distance units (e.g., meters)
- p_facilities
int, default=5 Number of facility modules to be located in the network.
- capacity
float|None, default=None Facility module capacity constraint.
If None: Uses an uncapacitated model
If provided: Sets a maximum capacity for each facility module
- threshold
float, default=0.0 Minimum flow coverage percentage for a node to be considered covered, 0 disables threshold extension.
- weight
float, default=0.99 Controls the trade-off between node coverage and flow coverage for threshold extension objective. Range: [0.0, 1.0]
1.0: Prioritises node coverage
0.0: Prioritises flow coverage
Only used when threshold > 0.
- objective
str, default=”flow” Optimisation objective.
“flow”: Maximize total flow coverage
“vmt”: Maximize vehicle miles traveled (VMT) coverage
- include_destinationbool, default=False
Determines how node weights are calculated in threshold extension.
False: Only origin nodes contribute to weight calculation
True: Both origin and destination nodes contribute to weight calculation
- vehicle_range
- __init__(vehicle_range: float | int = 200000, p_facilities: int = 5, capacity: float | None = None, threshold: float = 0.0, weight: float = 0.99, objective: str = 'flow', include_destination: bool = False)[source]¶
Methods
__init__([vehicle_range, p_facilities, ...])add_flow(origin, destination, volume[, path])Add flow with path calculation using scipy network.
add_flows(flows)Add multiple flows to the FRLM instance.
add_network(network)Add network to the FRLM instance.
calculate_covered_nodes()calculate_node_weights([include_destination])Calculate node weights based on flow volumes.
check_path_refueling_feasibility(path, ...)Check if a path can be traversed with given facilities using scipy network.
compute_refueling_frequency(origin, destination)extract_solver_statistics()from_flow_dataframe(network, flows, **kwargs)Create FRLM instance from network and flows.
Generate dictionary mapping OD pairs to valid facility combinations.
get_constraint_dual(constraint_name)get_detailed_results()get_flow_coverage()Improved and fixed calculation of flow coverage.
get_node_coverage_percentage()Get percentage of nodes covered.
get_shadow_price(constraint_name)get_slack(constraint_name)Retrieve detailed solver information.
get_variable_value(var_name)get_vmt_coverage()is_constraint_active(constraint_name)solve([solver, seed, initialization_method, ...])Solve the FRLM problem.
summary()Generate a summary of the solution.
to_dataframes([include_iterations])Export solution to pandas DataFrames.
Attributes
Return the PuLP problem instance.
Read facility selection from PuLP variables.
- add_flow(origin: Any, destination: Any, volume: float, path: list | None = None) None[source]¶
Add flow with path calculation using scipy network.
- add_flows(flows: DataFrame | dict[tuple[Any, Any], float])[source]¶
Add multiple flows to the FRLM instance.
- add_network(network: csr_matrix)[source]¶
Add network to the FRLM instance.
- Parameters:
- network
scipy.sparse.csr_matrix The network as a scipy sparse matrix where element [i,j] represents the distance/cost between nodes i and j.
- network
- Returns:
- self
FRLM Returns the instance for method chaining
- self
- calculate_node_weights(include_destination: bool = False) ndarray[source]¶
Calculate node weights based on flow volumes.
- Parameters:
- include_destinationbool, default=False
If True, include destination nodes in weight calculation. If False, only use origin nodes for weight calculation, as specified in the paper (Hong and Kuby, 2016).
- Returns:
np.ndarrayArray of node weights
- check_path_refueling_feasibility(path: list, facilities: list) bool[source]¶
Check if a path can be traversed with given facilities using scipy network.
- classmethod from_flow_dataframe(network: csr_matrix, flows: DataFrame | dict, **kwargs)[source]¶
Create FRLM instance from network and flows.
- Parameters:
- network
sp.csr_matrix Network as a scipy sparse matrix
- flows
pd.DataFrame|dict Flow data
- network
- generate_path_refueling_combinations(facility_combinations: list[list] | None = None, start: int | None = None, stop: int | None = None, method: str = 'auto') dict[source]¶
Generate dictionary mapping OD pairs to valid facility combinations.
- Parameters:
- facility_combinations
list[list]], optional Pre-computed facility combinations (only used for combination method)
- start
int, optional Minimum size of combinations (for combination method)
- stop
int, optional Maximum size of combinations (for combination method)
- method
str, optional Method to use: “auto”, “combination”, or “ac_pc”
“auto”: Automatically choose based on model type
“combination”: Generate all possible facility combinations
“ac_pc”: Generate K and a sets for Arc Cover Path Cover
- facility_combinations
- Returns:
dictDictionary of OD pairs to valid facility combinations (combination method) or sets K and a sets (ac_pc method).
- property problem¶
Return the PuLP problem instance.
- property selected_facilities¶
Read facility selection from PuLP variables.
- solve(solver: Literal['greedy'] | LpSolver = None, seed: int | None = None, initialization_method: str = 'empty', max_iterations: int = 100, **kwargs) dict[source]¶
Solve the FRLM problem.
- Parameters:
- solver
Literal[“greedy”] |pulp.LpSolver] Solver to use. If None, PuLP will use its default solver. If “greedy”, uses greedy heuristic. If a
pulp.Solverinstance, uses that solver.- seed
int|None, default=None Random seed for reproducibility
- initialization_method
str, default=”empty” Method for initializing greedy solution
- max_iterations
int, default=100 Maximum iterations for greedy solver
- **kwargs
Additional solver-specific parameters
- solver
- to_dataframes(include_iterations: bool = True) dict[str, DataFrame][source]¶
Export solution to pandas DataFrames.
- Parameters:
- include_iterationsbool, default=True
Whether to include iteration details (for greedy solver)
- Returns:
dictDictionary of DataFrames with keys:
‘facilities’: Selected facilities and modules
‘coverage’: Flow coverage details
‘summary’: Summary statistics
‘iterations’: Greedy solver iterations (if applicable)
‘shadow_prices’: Shadow prices/Lagrange multipliers (if applicable)