Commit cc942f0f authored by Aurore Sallard's avatar Aurore Sallard
Browse files

Fixing act. dur. + implementing sec.loc. assignment

parent 85ef56cd
Pipeline #107494 failed with stage
......@@ -134,11 +134,15 @@ def execute(context):
df_mz_trips.loc[:, "previous_trip_id"] = df_mz_trips["trip_id"] -1
df_durations = pd.merge(
df_mz_trips[["person_id", "trip_id", "departure_time"]],
df_mz_trips[["person_id", "previous_trip_id", "arrival_time"]],
#df_mz_trips[["person_id", "trip_id", "departure_time"]],
df_mz_trips[["person_id", "trip_id", "arrival_time"]],
#df_mz_trips[["person_id", "previous_trip_id", "arrival_time"]],
df_mz_trips[["person_id", "previous_trip_id", "departure_time"]],
left_on = ["person_id", "trip_id"], right_on = ["person_id", "previous_trip_id"])
df_durations.loc[:, "activity_duration"] = df_durations["arrival_time"] - df_durations["departure_time"]
#df_durations.loc[:, "activity_duration"] = df_durations["arrival_time"] - df_durations["departure_time"]
df_durations.loc[:, "activity_duration"] = df_durations["departure_time"] - df_durations["arrival_time"]
df_mz_trips = pd.merge(
df_mz_trips, df_durations[["person_id", "trip_id", "activity_duration"]],
......
......@@ -2,6 +2,202 @@ import synthesis.population.spatial.secondary.rda as rda
import sklearn.neighbors
import numpy as np
def compute_weight(purpose, duration, capacity):
if purpose == "culture":
if duration / 60 < 39.40000000000003:
x = 0
elif duration / 60 >= 39.40000000000003 and duration / 60 < 85.0:
x = 0.00548245614035088 * duration / 60 + -0.21600877192982482
elif duration / 60 >= 85.0 and duration / 60 < 140.0:
x = 0.004545454545454545 * duration / 60 + -0.13636363636363635
elif duration / 60 >= 140.0 and duration / 60 < 210.0:
x = 0.0035714285714285713 * duration / 60 + 0.0
elif duration / 60 >= 210.0 and duration / 60 < 319.59999999999985:
x = 0.0022810218978102223 * duration / 60 + 0.2709854014598533
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 1.0:
y = inf * capacity + -inf
elif capacity > 1.0 and capacity <= 4.0:
y = 0.08333333333333333 * capacity + 0.16666666666666669
elif capacity > 4.0 and capacity <= 10.0:
y = 0.041666666666666664 * capacity + 0.33333333333333337
elif capacity > 10.0 and capacity <= 19.0:
y = 0.027777777777777776 * capacity + 0.4722222222222222
else:
y = 1
if purpose == "religion":
if duration / 60 < 15.0:
x = 0
elif duration / 60 >= 15.0 and duration / 60 < 42.5:
x = 0.00909090909090909 * duration / 60 + -0.13636363636363635
elif duration / 60 >= 42.5 and duration / 60 < 75.0:
x = 0.007692307692307693 * duration / 60 + -0.07692307692307698
elif duration / 60 >= 75.0 and duration / 60 < 123.5:
x = 0.005154639175257732 * duration / 60 + 0.11340206185567014
elif duration / 60 >= 123.5 and duration / 60 < 180.0:
x = 0.004424778761061947 * duration / 60 + 0.20353982300884954
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 7.0:
y = 0.041666666666666664 * capacity + -0.04166666666666663
elif capacity > 7.0 and capacity <= 17.0:
y = 0.025 * capacity + 0.07499999999999996
elif capacity > 17.0 and capacity <= 28.0:
y = 0.022727272727272728 * capacity + 0.11363636363636365
elif capacity > 28.0 and capacity <= 39.0:
y = 0.022727272727272728 * capacity + 0.11363636363636365
else:
y = 1
if purpose == "grocery":
if duration / 60 < 5.0:
x = 0
elif duration / 60 >= 5.0 and duration / 60 < 10.0:
x = 0.05 * duration / 60 + -0.25
elif duration / 60 >= 10.0 and duration / 60 < 20.0:
x = 0.025 * duration / 60 + 0.0
elif duration / 60 >= 20.0 and duration / 60 < 41.0:
x = 0.011904761904761904 * duration / 60 + 0.2619047619047619
elif duration / 60 >= 41.0 and duration / 60 < 70.0:
x = 0.008620689655172414 * duration / 60 + 0.39655172413793105
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 9.0:
y = 0.03125 * capacity + -0.03125
elif capacity > 9.0 and capacity <= 17.0:
y = 0.03125 * capacity + -0.03125
elif capacity > 17.0 and capacity <= 32.0:
y = 0.016666666666666666 * capacity + 0.21666666666666667
elif capacity > 32.0 and capacity <= 48.0:
y = 0.015625 * capacity + 0.25
else:
y = 1
if purpose == "other(S)":
if duration / 60 < 5.0:
x = 0
elif duration / 60 >= 5.0 and duration / 60 < 10.0:
x = 0.05 * duration / 60 + -0.25
elif duration / 60 >= 10.0 and duration / 60 < 30.0:
x = 0.0125 * duration / 60 + 0.125
elif duration / 60 >= 30.0 and duration / 60 < 65.0:
x = 0.007142857142857143 * duration / 60 + 0.28571428571428575
elif duration / 60 >= 65.0 and duration / 60 < 120.0:
x = 0.004545454545454545 * duration / 60 + 0.4545454545454546
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 5.0:
y = 0.0625 * capacity + -0.0625
elif capacity > 5.0 and capacity <= 10.0:
y = 0.05 * capacity + 0.0
elif capacity > 10.0 and capacity <= 15.0:
y = 0.05 * capacity + 0.0
elif capacity > 15.0 and capacity <= 20.0:
y = 0.05 * capacity + 0.0
else:
y = 1
if purpose == "gastronomy":
if duration / 60 < 25.0:
x = 0
elif duration / 60 >= 25.0 and duration / 60 < 40.0:
x = 0.016666666666666666 * duration / 60 + -0.41666666666666663
elif duration / 60 >= 40.0 and duration / 60 < 65.0:
x = 0.01 * duration / 60 + -0.15000000000000002
elif duration / 60 >= 65.0 and duration / 60 < 120.0:
x = 0.004545454545454545 * duration / 60 + 0.20454545454545459
elif duration / 60 >= 120.0 and duration / 60 < 194.0:
x = 0.0033783783783783786 * duration / 60 + 0.3445945945945945
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 8.0:
y = 0.03571428571428571 * capacity + -0.0357142857142857
elif capacity > 8.0 and capacity <= 16.0:
y = 0.03125 * capacity + 0.0
elif capacity > 16.0 and capacity <= 25.0:
y = 0.027777777777777776 * capacity + 0.05555555555555558
elif capacity > 25.0 and capacity <= 33.57999999999811:
y = 0.02913752913753556 * capacity + 0.021561771561610987
else:
y = 1
if purpose == "other(L)":
if duration / 60 < 1.0:
x = 0
elif duration / 60 >= 1.0 and duration / 60 < 10.0:
x = 0.027777777777777776 * duration / 60 + -0.02777777777777779
elif duration / 60 >= 10.0 and duration / 60 < 55.0:
x = 0.005555555555555556 * duration / 60 + 0.19444444444444442
elif duration / 60 >= 55.0 and duration / 60 < 132.0:
x = 0.003246753246753247 * duration / 60 + 0.3214285714285714
elif duration / 60 >= 132.0 and duration / 60 < 225.0:
x = 0.002688172043010753 * duration / 60 + 0.3951612903225806
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 1.0:
y = inf * capacity + -inf
elif capacity > 1.0 and capacity <= 2.0:
y = 0.25 * capacity + 0.0
elif capacity > 2.0 and capacity <= 6.0:
y = 0.0625 * capacity + 0.375
elif capacity > 6.0 and capacity <= 10.0:
y = 0.0625 * capacity + 0.375
else:
y = 1
if purpose == "services":
if duration / 60 < 2.0:
x = 0
elif duration / 60 >= 2.0 and duration / 60 < 5.0:
x = 0.08333333333333333 * duration / 60 + -0.16666666666666663
elif duration / 60 >= 5.0 and duration / 60 < 15.0:
x = 0.025 * duration / 60 + 0.125
elif duration / 60 >= 15.0 and duration / 60 < 50.0:
x = 0.007142857142857143 * duration / 60 + 0.39285714285714285
elif duration / 60 >= 50.0 and duration / 60 < 85.0:
x = 0.007142857142857143 * duration / 60 + 0.3928571428571429
else:
x = 1
if capacity <= 1.0:
y = 0
elif capacity > 1.0 and capacity <= 1.0:
y = inf * capacity + -inf
elif capacity > 1.0 and capacity <= 3.0:
y = 0.125 * capacity + 0.125
elif capacity > 3.0 and capacity <= 6.0:
y = 0.08333333333333333 * capacity + 0.25
elif capacity > 6.0 and capacity <= 10.0:
y = 0.0625 * capacity + 0.375
else:
y = 1
return max(2**5*0.98*(x-0.5)**3*(y-0.5)**3+0.5,0)
def compute_all_weights(purpose, duration, capacities):
return [compute_weight(purpose, duration, c) for c in capacities]
class CustomDistanceSampler(rda.FeasibleDistanceSampler):
def __init__(self, random, distributions, maximum_iterations = 1000):
rda.FeasibleDistanceSampler.__init__(self, random = random, maximum_iterations = maximum_iterations)
......@@ -28,7 +224,7 @@ class CustomDiscretizationSolver(rda.DiscretizationSolver):
def __init__(self, data):
self.data = data
self.indices = {}
self.query_size = 10
self.query_size = 5
for purpose, data in self.data.items():
print("Constructing spatial index for %s ..." % purpose)
......@@ -38,14 +234,20 @@ class CustomDiscretizationSolver(rda.DiscretizationSolver):
discretized_locations = []
discretized_identifiers = []
for location, purpose in zip(locations, problem["purposes"]):
#index = self.indices[purpose].query(location.reshape(1, -1), return_distance = False)[0][0]
distances, indices = self.indices[purpose].query(location.reshape(1, -1), self.query_size, return_distance=True)
candidates_nboemployees = self.data[purpose]["number_employees"][indices][0]
weights = candidates_nboemployees / np.sum(candidates_nboemployees)
for location, purpose, act_dur, start_time in zip(locations, problem["purposes"], problem["activity_duration"], problem["activity_start_time"]):
if purpose in ["grocery", "other(S)", "culture", "gastronomy", "religion", "other(L)", "services"]:
self.query_size = 5
distances, indices = self.indices[purpose].query(location.reshape(1, -1), self.query_size, return_distance=True)
candidates_nboemployees = self.data[purpose]["number_employees"][indices][0]
weights = compute_all_weights(purpose, act_dur, candidates_nboemployees)
weights = weights / np.sum(weights)
selector = np.random.choice(self.query_size, p=weights)
index = np.choose(selector, indices.T)
selector = np.random.choice(self.query_size, p=weights)
index = np.choose(selector, indices.T)
else:
index = self.indices[purpose].query(location.reshape(1, -1), return_distance = False)[0][0]
discretized_identifiers.append(self.data[purpose]["identifiers"][index])
discretized_locations.append(self.data[purpose]["locations"][index])
......
......@@ -22,6 +22,7 @@ def configure(context):
context.config("random_seed")
context.config("threads")
context.config("use_detailed_activities")
context.config("output_path")
def prepare_locations(context):
......@@ -78,6 +79,8 @@ def prepare_destinations(context):
df_destinations["offers_services"] = df_destinations['offers_services'].fillna(False)
df_destinations["number_employees"] = df_destinations['number_employees'].fillna(1)
output_path = context.config("output_path")
#df_destinations.to_csv("%s/destinations_sec_activities.csv" % output_path, index = None)
for purpose in ("grocery", "other(S)", "culture", "gastronomy", "religion", "sport", "other(L)", "other", "visits", "volunteer", "outdoor", "services"):
f = df_destinations["offers_%s" % purpose].values
......@@ -89,6 +92,9 @@ def prepare_destinations(context):
)
print(purpose, len(identifiers[f]))
else:
identifiers = df_destinations["destination_id"].values
locations = np.vstack(df_destinations["geometry"].apply(lambda x: np.array([x.x, x.y])).values)
......
import numpy as np
FIELDS = ["person_id", "trip_index", "preceding_purpose", "following_purpose", "mode", "travel_time"]
FIELDS = ["person_id", "trip_index", "preceding_purpose", "following_purpose", "mode", "travel_time", "activity_duration", "arrival_time"]
FIXED_PURPOSES = ["home", "work", "education"]
......@@ -8,7 +8,7 @@ def find_bare_assignment_problems(df):
problem = None
for row in df[FIELDS].itertuples(index=False):
person_id, trip_index, preceding_purpose, following_purpose, mode, travel_time = row
person_id, trip_index, preceding_purpose, following_purpose, mode, travel_time, act_dur, arr_time = row
if not problem is None and person_id != problem["person_id"]:
# We switch person, but we're still tracking a problem. This is a tail!
......@@ -19,12 +19,14 @@ def find_bare_assignment_problems(df):
# Start a new problem
problem = dict(
person_id=person_id, trip_index=trip_index, purposes=[preceding_purpose],
modes=[], travel_times=[]
modes=[], travel_times=[], activity_duration = [], activity_start_time = []
)
problem["purposes"].append(following_purpose)
problem["modes"].append(mode)
problem["travel_times"].append(travel_time)
problem["activity_duration"].append(act_dur)
problem["activity_start_time"].append(arr_time)
if problem["purposes"][-1] in FIXED_PURPOSES:
# The current chain (or initial tail) ends with a fixed activity.
......
......@@ -19,9 +19,9 @@ def execute(context):
]]
df_trips = pd.DataFrame(context.stage("data.microcensus.trips"), copy=True)[[
"person_id", "trip_id", "departure_time", "arrival_time", "mode", "purpose"
"person_id", "trip_id", "departure_time", "arrival_time", "mode", "purpose", "activity_duration"
]]
df_trips.columns = ["mz_person_id", "trip_id", "departure_time", "arrival_time", "mode", "following_purpose"]
df_trips.columns = ["mz_person_id", "trip_id", "departure_time", "arrival_time", "mode", "following_purpose", "activity_duration"]
# Assume the preceeding purpose for all trips is home
df_trips["preceding_purpose"] = df_trips["following_purpose"].shift(1)
......@@ -42,7 +42,7 @@ def execute(context):
df_trips = df_trips[["person_id", "trip_id",
"departure_time", "arrival_time",
"travel_time", "mode",
"preceding_purpose", "following_purpose"]].sort_values(by=["person_id", "trip_id"])
"preceding_purpose", "following_purpose", "activity_duration"]].sort_values(by=["person_id", "trip_id"])
# Diversify departure times
counts = df_trips[["person_id", "trip_id"]].groupby("person_id").size().reset_index(name="count")["count"].values
......@@ -77,6 +77,7 @@ def execute(context):
"following_purpose",
# "is_first_trip", "is_last_trip",
"trip_duration",
# "activity_duration",
"activity_duration",
"mode"
]]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment