Project: s41467-025-61454-1 | Function: kpl_rule (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Implements the Kolm-Pollak Linear (KPL) objective function that minimizes the population-weighted transformed distances to achieve equitable facility location optimization.

**KEY TERMS:** {
  "origins_dict[r]": "population weights p_r",
  "distances_transformed_dict[r,s]": "e^(-κ d_{r,s}) transformed distances",
  "model.y[r,s]": "assignment variables y_{r,s}"
}

**CONTEXT CODE:**         raise NotImplementedError('This function is masked for testing purposes.')
    '''
    Transform distances before optimization to lessen computational burden

    Parameters:
    distances_df (pandas.DataFrame): Contains distance information
    kappa (float): kappa value to be used in the optimization model

    Returns: distances_df with additional transformed distance column and distances_transformed_dict

    '''

    logger.info('transforming distances')

    #transforming distances
    distances_df['transformed'] = distances_df.network.apply(lambda d:np.exp(-kappa*d))
    #to get all the right pairs of origins and destinations in the dict
    distances_transformed_dict = dict(zip(zip(distances_df["id_orig"], distances_df["id_dest"]), distances_df["transformed"]))

    return distances_transformed_dict
    
    
def create_pyomo_model(kappa,origins_list,destinations_list,origins_dict,distances_dict,distances_transformed_dict,open_current_list,open_total,total_pop,measure,kp_threshold=None):
    '''
    Defines pyomo model, adds appropriate variables and constraints.
     
    Parameters: 
    kappa (float) : kappa value to be used in the optimization model
    origins_list (list) : list of origins (r)
    destinations_list (list) : list of destinations (s)
    origins_dict (dict) : dictionary of origins and populations for each origin
    distances_dict (dict) : contains information about the network distance traveled from all origins to all destinations
    distances_transformed_dict (dict) : transformed network distance traveled from all origins to all destinations
    open_current_list (list) : list of currently open facilities 
    open_total (int) : number of currently open facilities + number of desired facilities to add
    total_pop (int) : total population for all residential areas
    measure (str): Defines which measure to use in model, PCENT, PMED, KPL, or KPCON.
    kp_threshold (float,default=None) : Upper bound for Kolm-Pollak value to be used in KPCON model.

    
    Returns:
    model
    '''
    
    logger.info('building model in pyomo')
    
    
    #DEFINE DIFFERENT MODEL OBJECTIVE FUNCTIONS

    #KPL Objective: Minimize the population weighted kolm-pollak distance for residential areas (r) and services (s)
    def kpl_rule(model):
        import os
        if os.getenv('TEST_GOLDEN', 'true') == 'false':
            raise NotImplementedError('This function is masked for testing purposes.')
        return sum(origins_dict[r]*distances_transformed_dict[r,s]*model.y[r,s] for r, s in distances_transformed_dict)       
        
        
    #PMED Objective: Minimize the population weighted average distance for residential areas (r) and services (s)
    def pmed_rule(model):
        return sum(origins_dict*distances_dict*model.y[r,s] for r, s in distances_dict)
            

    #PCENT Objective: Minimize the maximum distance any resident area has to travel
    def pcent_rule(model):
        return model.u
            
    def minimax_rule(model,r,s):
        return model.y[r,s]*distances_dict <= model.u
        
    #KPCON Objective: Minimize total number of facilities to open
    def kpcon_obj_rule(model):
        return sum(model.x[s] for s in destinations_list)
          

    #DEFINE MODEL CONSTRAINTS

    #residential area r is only assigned to service s if service s is open.
    def open_rule(model,r,s):
        return model.y[r,s]-model.x[s]<=0


    #each origin is only assigned to a single destination
    def single_rule(model,r):
        return sum(model.y[r,s] for s in destinations_list if (r,s) in distances_transformed_dict) == 1


    #sum of open destinations  should equal the number we want to open
    def open_total_rule(model):
        return sum(model.x[s] for s in destinations_list)==open_total


    #forces open service locations that are already there
    def currently_open_rule(model,s):
        return model.x[s]==1
        
    #bounding the population weighted kolm-pollak distance for residential areas (r) and services (s) from above by the kp_threshold
    def kpcon_rule(model):
        return sum(origins_dict*distances_transformed_dict*model.y[r,s] for r, s in distances_transformed_dict)-kp_threshold <= 0 
    
    #define model
    model= pyo.ConcreteModel()
    
    #Binary variable that is 1 if service s is open
    model.x=pyo.Var(destinations_list, within=pyo.Binary)
    # y[r,s] - 1 if  r that is served by service s, 0 otherwise
    model.y=pyo.Var(origins_list,destinations_list, within=pyo.Binary)
    
    if measure=='PCENT':
        model.u = pyo.Var(domain=pyo.NonNegativeReals)
        model.minimax_constraint = pyo.Constraint(distances_dict.keys(), rule=minimax_rule)
        model.pcent = pyo.Objective(rule=pcent_rule, sense=pyo.minimize)
    
    if measure=='PMED':
        model.pmed = pyo.Objective(rule=pmed_rule, sense=pyo.minimize)
    
    if measure=='KPL':
        model.kpl = pyo.Objective(rule=kpl_rule, sense=pyo.minimize)
    
    if measure=='KPCON':
        model.kpcon_obj=pyo.Objective(rule=kpcon_obj_rule,sense=pyo.minimize)
        model.kp_con = pyo.Constraint(rule=kpcon_rule)
    else: 
        model.open_total_constraint=pyo.Constraint(rule=open_total_rule)  
        
    model.open_constraint = pyo.Constraint(origins_list,destinations_list,rule=open_rule)
    model.single_constraint = pyo.Constraint(origins_list, rule=single_rule)
    model.currently_open_constraint = pyo.Constraint(open_current_list,rule=currently_open_rule)
    
    
    return model
    

def solve_model(model,solver):
    '''
    Solve the pyomo model
    
    Parameters:
    model : pyomo model
    solver (string) : desired solver to be used in optimization
    
    Returns:
    results
    model
    wall_time
    time 
    '''
    
    logger.info('solving the model')
    
    


Complete the function implementation replacing "raise NotImplementedError".