serJD commited on
Commit
fa7b8b5
·
verified ·
1 Parent(s): 8e513bf

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -0
app.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import json
5
+ from io import StringIO
6
+
7
+
8
+ def dynamic_huff_model(df_distances, df_attractiveness, alpha, beta, df_capacity, df_population=None, iterations=5, crowding_threshold=1.0):
9
+ """
10
+ Iteratively calculates the distribution of people/visitors to destinations considering capacity and crowding based on an extended Huff model with linear decay function.
11
+
12
+ Parameters:
13
+ - df_distances, df_attractiveness, alpha, beta, df_capacity, df_population are the same as before.
14
+ - iterations (int): The number of iterations to distribute the population.
15
+ - crowding_threshold (float): The ratio of current visitors to capacity at which the decay of attractiveness starts.
16
+
17
+ Returns:
18
+ - pd.DataFrame: A DataFrame with the final distribution of visitors to each destination.
19
+ """
20
+ if df_population is None:
21
+ df_population = pd.Series(np.ones(df_distances.shape[0]), index=df_distances.index)
22
+
23
+ # Initialize the visitors DataFrame
24
+ df_visitors = pd.DataFrame(0, index=df_distances.index, columns=df_distances.columns)
25
+
26
+ # Distribute the population over the iterations
27
+ df_population_per_iteration = df_population / iterations
28
+
29
+ # Run the iterative distribution process
30
+ for _ in range(iterations):
31
+ attractiveness = df_attractiveness.copy()
32
+ current_visitors = df_visitors.sum(axis=0)
33
+
34
+ # Calculate the decay based on the relative share of free capacity
35
+ relative_crowding = current_visitors / df_capacity
36
+ decay_factor = np.where(relative_crowding < crowding_threshold, 1, 1 - (relative_crowding - crowding_threshold) / (1 - crowding_threshold))
37
+ attractiveness *= decay_factor
38
+
39
+ # Calculate Huff model probabilities
40
+ distance_term = df_distances ** -beta
41
+ numerator = (attractiveness ** alpha).multiply(distance_term, axis='columns')
42
+ denominator = numerator.sum(axis='columns')
43
+ probabilities = numerator.div(denominator, axis='index').fillna(0)
44
+
45
+ # Distribute visitors based on probabilities and population
46
+ visitors_this_iteration = probabilities.multiply(df_population_per_iteration, axis='index')
47
+
48
+ # Adjust for excess visitors beyond capacity
49
+ potential_new_visitors = df_visitors + visitors_this_iteration
50
+ excess_visitors = potential_new_visitors.sum(axis=0) - df_capacity
51
+ excess_visitors[excess_visitors < 0] = 0
52
+ visitors_this_iteration -= visitors_this_iteration.multiply(excess_visitors, axis='columns') / visitors_this_iteration.sum(axis=0)
53
+
54
+ df_visitors += visitors_this_iteration
55
+
56
+ # Return the final distribution of visitors
57
+ return df_visitors
58
+
59
+ def app_function(input_json):
60
+ # Parse the input JSON string
61
+ inputs = json.loads(input_json)
62
+
63
+ # Convert stringified CSVs in JSON to DataFrames
64
+ df_distances = pd.read_csv(StringIO(inputs["df_distances"]))
65
+ df_attractiveness = pd.Series(json.loads(inputs["df_attractiveness"]))
66
+ alpha = inputs["alpha"]
67
+ beta = inputs["beta"]
68
+ df_capacity = pd.Series(json.loads(inputs["df_capacity"]))
69
+ df_population = pd.Series(json.loads(inputs["df_population"])) if "df_population" in inputs else None
70
+ iterations = inputs.get("iterations", 5)
71
+ crowding_threshold = inputs.get("crowding_threshold", 1.0)
72
+
73
+ # Call the dynamic Huff model function with these parameters
74
+ result = dynamic_huff_model(df_distances, df_attractiveness, alpha, beta, df_capacity, df_population, iterations, crowding_threshold)
75
+
76
+ # Convert the result DataFrame to a CSV string for Gradio output
77
+ return result.to_csv(index=False)
78
+
79
+ # Define the Gradio interface with a single JSON input
80
+ iface = gr.Interface(
81
+ fn=app_function,
82
+ inputs=gr.inputs.Textbox(label="Input JSON", lines=20, placeholder="Enter JSON with all parameters here..."),
83
+ outputs="file",
84
+ title="Dynamic Huff Model"
85
+ )
86
+
87
+ iface.launch()