Source code for libadalina_analytics.relocation.algorithms.adalina_relocation_algorithm

from libadalina_core.sedona_utils import DataFrame, EPSGFormats
from libadalina_analytics.utils import GeometryFormats
from .adalina_algorithms import run_hierarchy_with_distance_threshold
from ..models import AdalinaData, AdalinaSolution, AdalinaAlgorithmOptions
from ..models.adalina_solution import get_solution_csv_AMELIA
import pandas as pd

from ..models.relocation_resource import RelocationResource


[docs] def relocation_algorithm(data: DataFrame, epsg: EPSGFormats, id_column: str = 'id', geometry_column: str = 'geometry', demand_column: str = 'demand', geometry_format: GeometryFormats = GeometryFormats.WKT, max_distance_assignment: float | None = None, max_distance_relocation: float | None = None, server_column: str | None = None, resources: list[RelocationResource] | None = None, timelimit: int = 60) -> pd.DataFrame | None: """ Optimally assign demand to servers minimizing relocation costs. Parameters ---------- data : pandas.DataFrame The input data containing the geometries and properties. epsg : EPSGFormats The EPSG format of the input geometries. id_column : str The name of the column containing the unique identifiers for each location. Default is 'id'. geometry_column : str The name of the column containing the geometries. Default is 'geometry'. demand_column : str The name of the column containing the demand values. Default is 'demand'. geometry_format : GeometryFormats The format of the geometries in the geometry column. Default is GeometryFormats.WKT. max_distance_assignment : float | None The maximum distance allowed for assigning demand to servers. If None, no limit is applied. Default is None. max_distance_relocation : float | None The maximum distance allowed for relocating demands. If None, no limit is applied. Default is None. server_column : str | None The name of the column indicating whether a location is a server (True) or not (False). If None, all locations are considered as potential servers. Default is None. resources : list[RelocationResource] | None A list of RelocationResource objects representing the resources available at each server. Each RelocationResource contains: - column_name: The name of the column in the input data representing the resource - amount: The total amount of the resource needed to serve one unit of demand. timelimit : int The maximum time (in seconds) to run the algorithm. Default is 60 seconds. Returns ------- pandas.DataFrame | None A DataFrame containing the optimal assignment of demand to servers, or None if no solution is found. """ user_input: dict = { "epsg": epsg, "geometry_type": geometry_format, "geometry": geometry_column, "timelimit": timelimit } if id_column is not None: user_input["IDs"] = id_column if max_distance_assignment is not None: user_input["max_distance_assignment"] = max_distance_assignment if max_distance_relocation is not None: user_input["max_distance_relocation"] = max_distance_relocation if demand_column is not None: user_input["demand"] = demand_column if resources is not None: user_input["resources"] = [{ 'name': resource.column_name, 'amount': resource.amount } for resource in resources] if server_column is not None: user_input["is_server"] = server_column data = AdalinaData.from_Amelia(amelia_file=data, user_input=user_input ) # 4 - RUN ADALINA HIERARCHICAL ALGORITHM options = AdalinaAlgorithmOptions() # I keep the default options _, all_solutions = run_hierarchy_with_distance_threshold(data, options) if len(all_solutions) == 0: return None return get_solution_csv_AMELIA(all_solutions[-1], data, epsg, geometry_format)