Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 173 additions & 56 deletions uam_system_model/Pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,27 @@ def optimize(
uam_distance_matrix,
optimality_gap,
value_of_time,
utility_type,
beta_time=-0.0192,
beta_cost=-0.0353,
uam_transition_time=10,
time_limit=1800,
CASM=0.79,
verbose=True,
):
if isinstance(value_of_time, int) or isinstance(value_of_time, float):
value_of_time = [value_of_time for _ in range(len(self.network.vertiport_dict))]

value_of_time = [
value_of_time for _ in range(len(self.network.vertiport_dict))
]

pax_arr = self.network.pax_arrival_times.copy()
self.time_resolution = time_resolution
self.num_vehicles = num_vehicles
self.beta_time = [
beta_cost * value_of_time[i] / 60
for i in range(len(self.network.vertiport_dict))
]
self.beta_cost = [beta_cost for _ in range(len(self.network.vertiport_dict))]

pax_arr["passenger_arrival_time_slot"] = np.ceil(
pax_arr["passenger_arrival_time_s"] / self.time_resolution / 60
Expand Down Expand Up @@ -93,9 +103,10 @@ def optimize(
t_i_uam = []
first_last_mile_cost = []
flight_cost_uam = []
beta_time_i = []
beta_cost_i = []
p_i_bar = []


for idx, row in self.pax_arr_grouped.iterrows():
origin = row["origin_vertiport_id"]
destination = row["destination_vertiport_id"]
Expand Down Expand Up @@ -126,9 +137,12 @@ def optimize(
od_idx = max(origin, destination)
uber_fare_i.append(uber_fare[od_idx])
elif len(uber_fare.shape) == 3:
od_idx = max(origin, destination)
uber_fare_i.append(uber_fare[origin, destination, time])

p_i_bar.append(1 / value_of_time[od_idx])
beta_time_i.append(self.beta_time[od_idx])
beta_cost_i.append(self.beta_cost[od_idx])

distance = uam_distance_matrix[origin, destination]
flight_cost_uam.append(CASM * 4 * distance)
Expand All @@ -141,25 +155,30 @@ def optimize(
non_zero_indices = [i for i, value in enumerate(self.di_bar) if value != 0]

di_bar_selected_x = [self.di_bar[i] for i in non_zero_indices]

if isinstance(value_of_time, float):
p_i_bar = [
1 / value_of_time for _ in non_zero_indices
] # 32.63 is the VOT in dollars per minute

else:
p_i_bar = []
for idx, row in self.pax_arr_grouped.iterrows():
origin = row["origin_vertiport_id"]
destination = row["destination_vertiport_id"]
od_idx = max(origin, destination)
p_i_bar.append(1 / (value_of_time[od_idx] / 60))

v_i_bar_uber = -uber_travel_time_i - p_i_bar * uber_fare_i
if utility_type == "vot":
if isinstance(value_of_time, float):
p_i_bar = [
1 / value_of_time for _ in non_zero_indices
] # 32.63 is the VOT in dollars per minute

else:
p_i_bar = []
for idx, row in self.pax_arr_grouped.iterrows():
origin = row["origin_vertiport_id"]
destination = row["destination_vertiport_id"]
od_idx = max(origin, destination)
p_i_bar.append(1 / (value_of_time[od_idx] / 60))

v_i_bar_uber = -uber_travel_time_i - p_i_bar * uber_fare_i
elif utility_type == "betas":
beta_time_i = np.array(beta_time_i)
beta_cost_i = np.array(beta_cost_i)
v_i_bar_uber = beta_time_i * uber_travel_time_i + beta_cost_i * uber_fare_i

bins = 20
max_flights = num_vehicles
eps = 0.01
eps = 0.05

m = Model("Pricing Problem")
m.Params.NonConvex = 2
Expand Down Expand Up @@ -215,7 +234,7 @@ def optimize(
)

# Flow conservation constraints
for n in tqdm(self.nodes):
for n in self.nodes:
m.addConstr(
sum(m._x_vars[i, j] for i, j in self.edges if j == n)
- sum(m._x_vars[i, j] for i, j in self.edges if i == n)
Expand Down Expand Up @@ -243,36 +262,82 @@ def optimize(
m._x_vars[self.edges[i]] * flight_cost_uam[i_non_zero]
for i_non_zero, i in zip(range(len(di_bar_selected_x)), non_zero_indices)
)
cost_level_of_service = quicksum(
di_bar_selected_x[i_non_zero]
/ p_i_bar[i_non_zero]
* m._x_inverse_vars[self.edges[i]]
* self.time_resolution
/ 2
for i_non_zero, i in zip(range(len(di_bar_selected_x)), non_zero_indices)
)
if utility_type == "vot":
cost_level_of_service = quicksum(
di_bar_selected_x[i_non_zero]
/ p_i_bar[i_non_zero]
* m._x_inverse_vars[self.edges[i]]
* self.time_resolution
/ 2
for i_non_zero, i in zip(
range(len(di_bar_selected_x)), non_zero_indices
)
)
theta_terms = quicksum(
di_bar_selected_x[i_non_zero]
/ p_i_bar[i_non_zero]
* (
m._theta_ln_theta_uam[i_non_zero]
- m._theta_ln_1_minus_theta_uam[i_non_zero]
)
for i_non_zero in range(len(di_bar_selected_x))
)

theta_terms = quicksum(
di_bar_selected_x[i_non_zero]
/ p_i_bar[i_non_zero]
* (
m._theta_ln_theta_uam[i_non_zero]
- m._theta_ln_1_minus_theta_uam[i_non_zero]
other_terms = quicksum(
di_bar_selected_x[i_non_zero]
/ p_i_bar[i_non_zero]
* m._theta_uam[i_non_zero]
* (v_i_bar_uber[i_non_zero] + t_i_uam[i_non_zero])
for i_non_zero in range(len(di_bar_selected_x))
)
for i_non_zero in range(len(di_bar_selected_x))
)

other_terms = quicksum(
di_bar_selected_x[i_non_zero]
/ p_i_bar[i_non_zero]
* m._theta_uam[i_non_zero]
* (v_i_bar_uber[i_non_zero] + t_i_uam[i_non_zero])
for i_non_zero in range(len(di_bar_selected_x))
)
objective = (
theta_terms + other_terms + operating_cost + cost_level_of_service
)

elif utility_type == "betas":
theta_terms = quicksum(
-di_bar_selected_x[i_non_zero]
/ beta_cost_i[i_non_zero]
* (
m._theta_ln_theta_uam[i_non_zero]
- m._theta_ln_1_minus_theta_uam[i_non_zero]
)
for i_non_zero in range(len(di_bar_selected_x))
)

other_terms = quicksum(
-di_bar_selected_x[i_non_zero]
/ beta_cost_i[i_non_zero]
* m._theta_uam[i_non_zero]
* (
v_i_bar_uber[i_non_zero]
- beta_time_i[i_non_zero] * t_i_uam[i_non_zero]
)
for i_non_zero in range(len(di_bar_selected_x))
)

objective = theta_terms + other_terms + operating_cost + cost_level_of_service
# objective = theta_terms + other_terms + operating_cost + cost_level_of_service
objective = theta_terms + other_terms + operating_cost

m.setObjective(objective, GRB.MINIMIZE)

if utility_type == "betas":
max_v = max_flights
for i, idx in enumerate(non_zero_indices):
current_los_costs = []
factor = (
di_bar_selected_x[i] * beta_time_i[i] * self.time_resolution
) / (2 * beta_cost_i[i])
for k in range(max_v + 1):
if k == 0:
current_los_costs.append(1e6) # Penalty for no service
else:
current_los_costs.append(factor * (1.0 / k))

m.setPWLObj(
m._x_vars[self.edges[idx]], range(max_v + 1), current_los_costs
)
if not verbose:
m.setParam("OutputFlag", 0)
m.update()
Expand Down Expand Up @@ -308,17 +373,31 @@ def optimize(
self.t_i_uam = t_i_uam
self.value_of_time = value_of_time

output_merged["fare"] = output_merged.apply(
lambda row: self.calc_fare(
row,
1/p_i_bar[int(row["flight_index"])],
v_i_bar_uber,
t_i_uam,
first_last_mile_cost,
self.time_resolution,
),
axis=1,
)
if utility_type == "vot":
output_merged["fare"] = output_merged.apply(
lambda row: self.calc_fare_vot(
row,
1 / p_i_bar[int(row["flight_index"])],
v_i_bar_uber,
t_i_uam,
first_last_mile_cost,
self.time_resolution,
),
axis=1,
)
elif utility_type == "betas":
output_merged["fare"] = output_merged.apply(
lambda row: self.calc_fare_betas(
row,
beta_time_i,
beta_cost_i,
v_i_bar_uber,
t_i_uam,
first_last_mile_cost,
self.time_resolution,
),
axis=1,
)

pax_arr_grouped_to_join = self.pax_arr_grouped.copy()
pax_arr_grouped_to_join["flight_index"] = pax_arr_grouped_to_join.index
Expand Down Expand Up @@ -355,7 +434,7 @@ def optimize(
return df

@staticmethod
def calc_fare(
def calc_fare_vot(
row, value_of_time, v_i_bar_uber, t_i_uam, first_last_mile_cost, time_resolution
):
num_flights = row["num_flights"]
Expand All @@ -373,6 +452,41 @@ def calc_fare(

return fare - first_last_cost

@staticmethod
def calc_fare_betas(
row,
beta_time,
beta_cost,
v_i_bar_uber,
t_i_uam,
first_last_mile_cost,
time_resolution,
):
num_flights = row["num_flights"]
theta = row["percentage_uam"]
index = int(row["flight_index"])
first_last_cost = first_last_mile_cost[index]
beta_time = beta_time[index]
beta_cost = beta_cost[index]

if theta >= 1:
theta = 0.9999
if theta <= 0:
theta = 0.0001

fare = (
1
/ beta_cost
* (
math.log(theta)
- math.log(1 - theta)
+ v_i_bar_uber[index]
- beta_time * (t_i_uam[index] + time_resolution / 2 / num_flights)
)
)

return fare - first_last_cost


class FlightTask:
def __init__(
Expand Down Expand Up @@ -405,7 +519,10 @@ def next_task(self, next_task):
+ reposition_time
)

if ready_time <= next_task_start_time:
if (
next_task_start_time - ready_time >= 0
and next_task_start_time - ready_time <= 12
):
return True
else:
return False
Expand Down
Loading
Loading