serJD commited on
Commit
94ba0ac
·
verified ·
1 Parent(s): 673904b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -76
app.py CHANGED
@@ -5,107 +5,106 @@ 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
 
21
- print("====== PRAMETER =====")
22
- print("alpha",alpha)
23
- print("beta",beta)
24
- print("iterations",iterations)
25
- print("crowding_threshold",crowding_threshold)
26
- print("=====================")
27
-
28
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  if df_population is None:
30
  df_population = pd.Series(np.ones(df_distances.shape[0]), index=df_distances.index)
31
 
32
- # Initialize the visitors DataFrame
33
- df_visitors = pd.DataFrame(0, index=df_distances.index, columns=df_distances.columns)
34
-
35
- # Distribute the population over the iterations
36
- df_population_per_iteration = df_population / iterations
37
-
38
- # Run the iterative distribution process
39
- for i in range(int(iterations)):
40
- print("iteration " + str(i) + "/"+str(int(iterations)))
41
- attractiveness = df_attractiveness.copy()
42
- current_visitors = df_visitors.sum(axis=0)
43
-
44
- # Calculate the decay based on the relative share of free capacity
45
- print(" Calculate the decay based on the relative share of free capacity")
46
- relative_crowding = current_visitors / df_capacity
47
- decay_factor = np.where(relative_crowding < crowding_threshold, 1, 1 - (relative_crowding - crowding_threshold) / (1 - crowding_threshold))
48
- attractiveness *= decay_factor
49
-
50
- # Calculate Huff model probabilities
51
- print("Calculate Huff model probabilities")
52
- distance_term = df_distances ** -beta
53
- # If df_distances is a DataFrame and df_attractiveness is a Series, you might need an operation like:
54
- numerator = df_distances.multiply(df_attractiveness, axis=0) # Adjust based on actual intent
55
-
56
- denominator = numerator.sum(axis='columns')
57
- probabilities = numerator.div(denominator, axis='index').fillna(0)
58
-
59
- print("Distribute visitors based on probabilities and population")
60
- # Distribute visitors based on probabilities and population
61
- visitors_this_iteration = probabilities.multiply(df_population_per_iteration, axis='index')
62
-
63
- # Adjust for excess visitors beyond capacity
64
- potential_new_visitors = df_visitors + visitors_this_iteration
65
- excess_visitors = potential_new_visitors.sum(axis=0) - df_capacity
66
- excess_visitors[excess_visitors < 0] = 0
67
- visitors_this_iteration -= visitors_this_iteration.multiply(excess_visitors, axis='columns') / visitors_this_iteration.sum(axis=0)
68
-
69
- df_visitors += visitors_this_iteration
70
-
71
- # Return the final distribution of visitors
72
- return df_visitors
73
 
74
  def app_function(input_json):
75
- print("something happend")
76
  # Parse the input JSON string
77
- print(input_json)
78
-
79
  try:
80
  inputs = json.loads(input_json)
81
- except:
82
  inputs = json.loads(input_json.replace("'", '"'))
83
- print(inputs.keys())
84
- # navigate to payload
 
85
  inputs = inputs["input"]
86
 
87
- print(inputs.keys())
88
- # Convert 'df_distances' from a list of lists into a DataFrame directly
89
  df_distances = pd.DataFrame(inputs["df_distances"])
90
- print("df_distances shape", df_distances.shape)
91
- # 'inputs["df_attractiveness"]' and others are directly usable as lists
 
92
  df_attractiveness = pd.Series(inputs["df_attractiveness"])
93
- print("df_attractiveness shape", df_attractiveness.shape)
 
 
94
  alpha = inputs["alpha"]
95
  beta = inputs["beta"]
96
- df_capacity = pd.Series(inputs["df_capacity"])
97
 
98
- # Check if 'df_population' is provided and convert to Series
99
  df_population = pd.Series(inputs["df_population"]) if "df_population" in inputs else None
 
 
 
 
100
 
101
- iterations = int(inputs.get("iterations", 5))
102
- crowding_threshold = inputs.get("crowding_threshold", 1.0)
103
-
104
- # Assuming dynamic_huff_model function is correctly defined to accept these parameters
105
- result = dynamic_huff_model(df_distances, df_attractiveness, alpha, beta, df_capacity, df_population, iterations, crowding_threshold)
106
- print(result)
107
- # Convert the result DataFrame to a JSON string for output
108
- return result.to_json(orient='split')
 
 
 
 
109
 
110
  # Define the Gradio interface with a single JSON input
111
  iface = gr.Interface(
 
5
  from io import StringIO
6
 
7
 
8
+ def adjust_population_by_distance(df_distances, df_population, distance_threshold, decay_factor):
9
  """
10
+ Adjusts the population of each origin based on the distance to any destination, applying a decay effect for distances beyond the threshold.
11
 
12
  Parameters:
13
+ - df_distances (pd.DataFrame): DataFrame with distances from origins to destinations.
14
+ - df_population (pd.Series): Series with population for each origin.
15
+ - distance_threshold (float): Distance beyond which the decay effect is applied.
16
+ - decay_factor (float): Factor controlling the rate of decay in willingness to travel beyond the threshold.
17
 
18
  Returns:
19
+ - pd.Series: Adjusted population for each origin.
20
  """
21
+ # Calculate the minimum distance from each origin to any destination
22
+ min_distance = df_distances.min(axis=1)
23
 
24
+ # Adjust the population based on the minimum distance and the decay factor
25
+ def adjustment_factor(distance):
26
+ if distance > distance_threshold:
27
+ return np.exp(-(distance - distance_threshold) * decay_factor)
28
+ else:
29
+ return 1
30
+
31
+ adjustment_factors = min_distance.apply(adjustment_factor)
32
+ return df_population * adjustment_factors
33
+
34
+ def huff_model_probability(df_distances, df_attractiveness, alpha, beta, df_population=None, distance_threshold=None, decay_factor=0.1):
35
+ """
36
+ Calculates the probability of choosing among destinations based on an enhanced Huff model that considers a willingness to travel threshold and applies a decay effect for distances beyond this threshold.
37
+
38
+ Parameters:
39
+ - df_distances (pd.DataFrame): DataFrame where rows are origins, columns are destinations, and values are distances.
40
+ - df_attractiveness (pd.Series): Series with attractiveness weights for each destination.
41
+ - alpha (float): Attractiveness parameter of the Huff model.
42
+ - beta (float): Distance decay parameter of the Huff model.
43
+ - df_population (pd.Series, optional): Series with population for each origin. Defaults to 1 if not provided.
44
+ - distance_threshold (float, optional): Distance beyond which the decay effect on willingness to travel is applied.
45
+ - decay_factor (float, optional): Factor controlling the rate of decay in willingness to travel beyond the threshold.
46
+
47
+ Returns:
48
+ - pd.DataFrame: DataFrame with probabilities of choosing each destination from each origin.
49
+ """
50
  if df_population is None:
51
  df_population = pd.Series(np.ones(df_distances.shape[0]), index=df_distances.index)
52
 
53
+ if distance_threshold is not None:
54
+ df_population = adjust_population_by_distance(df_distances, df_population, distance_threshold, decay_factor)
55
+
56
+ attractiveness_term = df_attractiveness ** alpha
57
+ distance_term = df_distances ** -beta
58
+
59
+ numerator = (attractiveness_term * distance_term).multiply(df_population, axis=0)
60
+ denominator = numerator.sum(axis=1)
61
+ probabilities = numerator.div(denominator, axis=0)
62
+
63
+ return probabilities
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  def app_function(input_json):
66
+ print("Received input")
67
  # Parse the input JSON string
 
 
68
  try:
69
  inputs = json.loads(input_json)
70
+ except json.JSONDecodeError:
71
  inputs = json.loads(input_json.replace("'", '"'))
72
+ print("Parsed input keys:", inputs.keys())
73
+
74
+ # Assuming the input structure is correctly formatted to include the necessary parameters
75
  inputs = inputs["input"]
76
 
77
+ # Convert 'df_distances' from a list of lists into a DataFrame
 
78
  df_distances = pd.DataFrame(inputs["df_distances"])
79
+ print("df_distances shape:", df_distances.shape)
80
+
81
+ # Convert 'df_attractiveness' into a Series
82
  df_attractiveness = pd.Series(inputs["df_attractiveness"])
83
+ print("df_attractiveness shape:", df_attractiveness.shape)
84
+
85
+ # Extract alpha and beta parameters
86
  alpha = inputs["alpha"]
87
  beta = inputs["beta"]
 
88
 
89
+ # Check if 'df_population' is provided and convert to Series, else default to None
90
  df_population = pd.Series(inputs["df_population"]) if "df_population" in inputs else None
91
+
92
+ # Additional parameters for the updated Huff model
93
+ distance_threshold = inputs.get("distance_threshold", None)
94
+ decay_factor = inputs.get("decay_factor", 0.1) # Default decay factor if not provided
95
 
96
+ # Call the updated Huff model function
97
+ probabilities = huff_model_probability(
98
+ df_distances=df_distances,
99
+ df_attractiveness=df_attractiveness,
100
+ alpha=alpha,
101
+ beta=beta,
102
+ df_population=df_population,
103
+ distance_threshold=distance_threshold,
104
+ decay_factor=decay_factor
105
+ )
106
+
107
+ return probabilities.to_json(orient='split')
108
 
109
  # Define the Gradio interface with a single JSON input
110
  iface = gr.Interface(