File size: 4,806 Bytes
fa7b8b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d53f142
 
fa7b8b5
 
 
 
d53f142
fa7b8b5
 
 
 
 
d53f142
fa7b8b5
f78daca
 
 
fa7b8b5
 
d53f142
 
fa7b8b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd083b1
fa7b8b5
dd083b1
b6f5dd4
 
 
 
 
ed97acb
 
e46c84a
 
 
08aba45
 
714bb14
08aba45
714bb14
fa7b8b5
 
714bb14
 
08aba45
714bb14
 
36dbf87
fa7b8b5
 
08aba45
fa7b8b5
137e662
714bb14
 
fa7b8b5
 
 
 
b1ead6c
 
fa7b8b5
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import gradio as gr
import pandas as pd
import numpy as np
import json
from io import StringIO


def dynamic_huff_model(df_distances, df_attractiveness, alpha, beta, df_capacity, df_population=None, iterations=5, crowding_threshold=1.0):
    """
    Iteratively calculates the distribution of people/visitors to destinations considering capacity and crowding based on an extended Huff model with linear decay function.

    Parameters:
    - df_distances, df_attractiveness, alpha, beta, df_capacity, df_population are the same as before.
    - iterations (int): The number of iterations to distribute the population.
    - crowding_threshold (float): The ratio of current visitors to capacity at which the decay of attractiveness starts.

    Returns:
    - pd.DataFrame: A DataFrame with the final distribution of visitors to each destination.
    """
    if df_population is None:
        df_population = pd.Series(np.ones(df_distances.shape[0]), index=df_distances.index)

    # Initialize the visitors DataFrame
    df_visitors = pd.DataFrame(0, index=df_distances.index, columns=df_distances.columns)
    
    # Distribute the population over the iterations
    df_population_per_iteration = df_population / iterations

    # Run the iterative distribution process
    for i in range(int(iterations)):
        print("iteration " + str(i) + "/"+str(int(iterations)))
        attractiveness = df_attractiveness.copy()
        current_visitors = df_visitors.sum(axis=0)
        
        # Calculate the decay based on the relative share of free capacity
        print(" Calculate the decay based on the relative share of free capacity")
        relative_crowding = current_visitors / df_capacity
        decay_factor = np.where(relative_crowding < crowding_threshold, 1, 1 - (relative_crowding - crowding_threshold) / (1 - crowding_threshold))
        attractiveness *= decay_factor
        
        # Calculate Huff model probabilities
        print("Calculate Huff model probabilities")
        distance_term = df_distances ** -beta
        # If df_distances is a DataFrame and df_attractiveness is a Series, you might need an operation like:
        numerator = df_distances.multiply(df_attractiveness, axis=0)  # Adjust based on actual intent

        denominator = numerator.sum(axis='columns')
        probabilities = numerator.div(denominator, axis='index').fillna(0)

        print("Distribute visitors based on probabilities and population")
        # Distribute visitors based on probabilities and population
        visitors_this_iteration = probabilities.multiply(df_population_per_iteration, axis='index')
        
        # Adjust for excess visitors beyond capacity
        potential_new_visitors = df_visitors + visitors_this_iteration
        excess_visitors = potential_new_visitors.sum(axis=0) - df_capacity
        excess_visitors[excess_visitors < 0] = 0
        visitors_this_iteration -= visitors_this_iteration.multiply(excess_visitors, axis='columns') / visitors_this_iteration.sum(axis=0)
        
        df_visitors += visitors_this_iteration

    # Return the final distribution of visitors
    return df_visitors

def app_function(input_json):
    print("something happend")
    # Parse the input JSON string
    print(input_json)

    try:
        inputs = json.loads(input_json)
    except:
        inputs = json.loads(input_json.replace("'", '"'))
    print(inputs.keys())
    # navigate to payload
    inputs = inputs["input"]

    print(inputs.keys())
    # Convert 'df_distances' from a list of lists into a DataFrame directly
    df_distances = pd.DataFrame(inputs["df_distances"])
    
    # 'inputs["df_attractiveness"]' and others are directly usable as lists
    df_attractiveness = pd.Series(inputs["df_attractiveness"])
    alpha = inputs["alpha"]
    beta = inputs["beta"]
    df_capacity = pd.Series(inputs["df_capacity"])
    
    # Check if 'df_population' is provided and convert to Series
    df_population = pd.Series(inputs["df_population"]) if "df_population" in inputs else None
    
    iterations = int(inputs.get("iterations", 5))
    crowding_threshold = inputs.get("crowding_threshold", 1.0)
    
    # Assuming dynamic_huff_model function is correctly defined to accept these parameters
    result = dynamic_huff_model(df_distances, df_attractiveness, alpha, beta, df_capacity, df_population, iterations, crowding_threshold)
    print(result)
    # Convert the result DataFrame to a JSON string for output
    return result.to_json(orient='split')

# Define the Gradio interface with a single JSON input
iface = gr.Interface(
    fn=app_function,
    inputs=gr.Textbox(label="Input JSON", lines=20, placeholder="Enter JSON with all parameters here..."),
    outputs=gr.JSON(label="Output JSON"),
    title="Dynamic Huff Model"
)

iface.launch()