diff --git a/python/simod/demand_sample.py b/python/simod/demand_sample.py index a4c30b06..e34bdfd8 100644 --- a/python/simod/demand_sample.py +++ b/python/simod/demand_sample.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import math import pandas as pd import numpy as np diff --git a/python/simod/resources/config.cfg b/python/simod/resources/config.cfg index 98fa811e..6de3bca0 100644 --- a/python/simod/resources/config.cfg +++ b/python/simod/resources/config.cfg @@ -1,9 +1,9 @@ # common data for all experiments -data_dir: 'C:/AIC Experiment data/VGA/' +data_dir: '/Users/adela/Documents/bakalarka/randomdemand/' map_dir: $data_dir + 'maps/' -experiments_dir: 'HERE FILL THE PROJECT EXPERIMENT DIR PATH/' +experiments_dir: '/Users/adela/Documents/bakalarka/randomdemand/experiments/test/' rci_experiments_dir: 'HERE FILL THE PROJECT RCI EXPERIMENT DIR PATH/' # change this for each experiment! diff --git a/python/simod/station_positions_map.py b/python/simod/station_positions_map.py index 2f79556a..634b3216 100644 --- a/python/simod/station_positions_map.py +++ b/python/simod/station_positions_map.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import numpy as np import matplotlib @@ -26,7 +26,7 @@ import roadmaptools.utm import matplotlib import matplotlib.font_manager as fm -import amodsim.demand +import simod.demand from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar from matplotlib.colors import LogNorm @@ -69,7 +69,7 @@ # map = np.random.rand(len(lon_range), len(lat_range)) # - fill heatmap -demand_data = amodsim.demand.load(config.trips_path) +demand_data = simod.demand.load(config.trips_path) xlist, ylist = roadmaptools.plotting.export_nodes_for_matplotlib(demand_data[["from_lat", "from_lon"]].to_numpy()) for i, x in enumerate(xlist): y = ylist[i] diff --git a/python/simod/statistics/comparisons/comparison_table.py b/python/simod/statistics/comparisons/comparison_table.py index 4568693a..6a43c153 100644 --- a/python/simod/statistics/comparisons/comparison_table.py +++ b/python/simod/statistics/comparisons/comparison_table.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import numpy as np import roadmaptools.inout @@ -25,7 +25,7 @@ from typing import List # from scripts.printer import print_table # from statistics.model.traffic_load import VehiclePhase -from amodsim.statistics.traffic_density_histogram import TrafficDensityHistogram +from simod.statistics.traffic_density_histogram import TrafficDensityHistogram def compute_stats(result: List, histogram: TrafficDensityHistogram, load) -> List: diff --git a/python/simod/statistics/comparisons/density_histogram_scenario_comparion.py b/python/simod/statistics/comparisons/density_histogram_scenario_comparion.py index 811c7199..3e7d8668 100644 --- a/python/simod/statistics/comparisons/density_histogram_scenario_comparion.py +++ b/python/simod/statistics/comparisons/density_histogram_scenario_comparion.py @@ -17,14 +17,14 @@ # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import matplotlib.pyplot as plt import numpy as np import statistics.model.traffic_load as traffic_load from matplotlib.axes import Axes -from amodsim.statistics.traffic_density_histogram import TrafficDensityHistogram, HIGH_THRESHOLD, HISTOGRAM_SAMPLES +from simod.statistics.traffic_density_histogram import TrafficDensityHistogram, HIGH_THRESHOLD, HISTOGRAM_SAMPLES from statistics.model.traffic_load import VehiclePhase diff --git a/python/simod/statistics/comparisons/occupancy_histogram_comparison.py b/python/simod/statistics/comparisons/occupancy_histogram_comparison.py index 453a98d7..a219fbde 100644 --- a/python/simod/statistics/comparisons/occupancy_histogram_comparison.py +++ b/python/simod/statistics/comparisons/occupancy_histogram_comparison.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import numpy as np import pandas as pd @@ -24,8 +24,8 @@ import matplotlib.pyplot as plt import datetime import roadmaptools.inout -import amodsim.statistics.model.occupancy as occupancy -import amodsim.statistics.comparisons.common as common +import simod.statistics.model.occupancy as occupancy +import simod.statistics.comparisons.common as common from matplotlib.ticker import FuncFormatter diff --git a/python/simod/statistics/comparisons/performance_comparison.py b/python/simod/statistics/comparisons/performance_comparison.py index 9907a504..7e31a657 100644 --- a/python/simod/statistics/comparisons/performance_comparison.py +++ b/python/simod/statistics/comparisons/performance_comparison.py @@ -16,10 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from init import config +from simod.init import config import matplotlib.pyplot as plt -import amodsim.statistics.model.ridesharing as ridesharing +import simod.statistics.model.ridesharing as ridesharing ih_capacity1_stats = ridesharing.load(config.comparison.experiment_1_dir) diff --git a/python/simod/statistics/comparisons/sensitivity_analysis.py b/python/simod/statistics/comparisons/sensitivity_analysis.py index 1bca887f..d407957c 100644 --- a/python/simod/statistics/comparisons/sensitivity_analysis.py +++ b/python/simod/statistics/comparisons/sensitivity_analysis.py @@ -16,14 +16,14 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config from typing import List, Tuple import roadmaptools.inout -import amodsim.statistics.model.edges as edges -import amodsim.statistics.model.transit as transit -import amodsim.statistics.model.ridesharing as ridesharing -import amodsim.statistics.model.service as service +import simod.statistics.model.edges as edges +import simod.statistics.model.transit as transit +import simod.statistics.model.ridesharing as ridesharing +import simod.statistics.model.service as service import matplotlib.pyplot as plt delay_experiments = ["sw-vga-max_delay_3_min", "sw-vga", "sw-vga-max_delay_5_min", "sw-vga-max_delay_6_min"] diff --git a/python/simod/statistics/comparisons/transfer_ridesharing_comparison_table.py b/python/simod/statistics/comparisons/transfer_ridesharing_comparison_table.py new file mode 100644 index 00000000..69c6c71e --- /dev/null +++ b/python/simod/statistics/comparisons/transfer_ridesharing_comparison_table.py @@ -0,0 +1,100 @@ +from simod.init import config + +import numpy as np +import pandas.errors +import roadmaptools.inout +import simod.statistics.model.traffic_load as traffic_load +import simod.statistics.model.transit as transit +import simod.statistics.model.edges as edges +import simod.statistics.model.ridesharing as ridesharing +import simod.statistics.model.service as service +import simod.statistics.model.occupancy as occupancy + +from typing import List, Dict, Iterable +from pandas import DataFrame +from roadmaptools.printer import print_table, print_info +from simod.statistics.traffic_density_histogram import TrafficDensityHistogram +from simod.statistics.model.vehicle_state import VehicleState + + +def compute_stats(result: Dict, histogram: TrafficDensityHistogram, load, experiment_dir: str, + edge_data: DataFrame) -> List: + # km total + transit_data = transit.load(experiment_dir) + km_total_window = int(round(transit.get_total_distance(transit_data, edge_data, True) / 1000 / 100)) + km_per_served_demand = round(km_total_window / (result["demandsCount"] - result["numberOfDemandsDropped"]), 3) + + dropped_demand_count = result["numberOfDemandsDropped"] + demand_count_served = result["demandsCount"] - result["numberOfDemandsDropped"] + + occupancies = occupancy.load(experiment_dir) + occupancies_in_window = occupancy.filter_window(occupancies) + used_cars_count = len(occupancies_in_window.vehicle_id.unique()) + + # delay + service_stat = service.load_dataframe(experiment_dir) + delays_window = service.get_delays(service_stat, True, False) + mean_delay = int(round(delays_window.mean() / 1000)) + + transfers_count = result['transfersDone'] + + return [km_total_window, dropped_demand_count, used_cars_count, mean_delay, demand_count_served, + km_per_served_demand, transfers_count] + +exp_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/experiments/test/' +# exp_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/experiments/test/' +exp_dir_2 = '/Users/adela/Documents/bakalarka/randomdemand/experiments/test/' + +exp_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/experiments/test/' + +edges_path = '/Users/adela/Documents/bakalarka/randomdemand/maps/edges.geojson' +loaded_edges = roadmaptools.inout.load_geojson(edges_path) +edge_data = edges.make_data_frame(loaded_edges) +edge_object_data = edges.load_edges_mapped_by_id(loaded_edges) + +results_insertion_heuristic \ + = roadmaptools.inout.load_json(exp_dir_1 + config.statistics.result_file_name) +results_insertion_heuristic_transfer \ + = roadmaptools.inout.load_json(exp_dir_2 + config.statistics.result_file_name) +results_taset \ + = roadmaptools.inout.load_json(exp_dir_3 + config.statistics.result_file_name) + +loads_insertion_heuristic = traffic_load.load_all_edges_load_history( + exp_dir_1 + config.statistics.all_edges_load_history_file_name) +loads_insertion_heuristic_transfer = traffic_load.load_all_edges_load_history( + exp_dir_2 + config.statistics.all_edges_load_history_file_name) +loads_taset = traffic_load.load_all_edges_load_history( + exp_dir_3 + config.statistics.all_edges_load_history_file_name) + +histogram = TrafficDensityHistogram(edge_object_data) + +insertion_heuristic_data = compute_stats(results_insertion_heuristic, histogram, loads_insertion_heuristic["ALL"], + exp_dir_1, edge_data) +insertion_heuristic_transfer_data = compute_stats(results_insertion_heuristic_transfer, histogram, + loads_insertion_heuristic_transfer["ALL"], exp_dir_2, + edge_data) +taset_data = compute_stats(results_taset, histogram, loads_taset["ALL"], + exp_dir_3, edge_data) + +output_table = np.array([[" ", "INSERTION HEURISTIC", "INSERTION HEURISTIC TRANSFER", "GREEDY HEURISTIC TRANSFER"], + ["Dropped demands", insertion_heuristic_data[1], insertion_heuristic_transfer_data[1], + taset_data[1]], + ["Demands served", insertion_heuristic_data[4], insertion_heuristic_transfer_data[4], + taset_data[4]], + ["Total transfers", insertion_heuristic_data[6], insertion_heuristic_transfer_data[6], + taset_data[6]], + ["Total veh. dist. traveled (km)", insertion_heuristic_data[0], + insertion_heuristic_transfer_data[0], taset_data[0]], + ["Total veh. dist. traveled per demand served (km)", insertion_heuristic_data[5], + insertion_heuristic_transfer_data[5], taset_data[5]], + ["Used car count", insertion_heuristic_data[2], insertion_heuristic_transfer_data[2], + taset_data[2]], + ["Average delay (s)", insertion_heuristic_data[3], insertion_heuristic_transfer_data[3], + taset_data[3]], + + ]) + +# console results +print("COMPARISON:") +print() +print_table(output_table) \ No newline at end of file diff --git a/python/simod/statistics/delay_percentage.py b/python/simod/statistics/delay_percentage.py new file mode 100644 index 00000000..d6df6365 --- /dev/null +++ b/python/simod/statistics/delay_percentage.py @@ -0,0 +1,65 @@ +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +import pandas.errors +import roadmaptools.inout +import simod.statistics.model.traffic_load as traffic_load +import simod.statistics.model.transit as transit +import simod.statistics.model.edges as edges +import simod.statistics.model.ridesharing as ridesharing +import simod.statistics.model.service as service +import simod.statistics.model.occupancy as occupancy + + +exp_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/experiments/test/' +exp_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/experiments/test/' +exp_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/experiments/test/' + +save_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/img/' +save_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/img/' +save_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/img/' + + +# delays dataframe +# TODO change dir +service_stat = service.load_dataframe(exp_dir_3) +# TODO change dir +save_results_to = save_dir_3 + +delays = service.get_delays(service_stat, True, False).to_frame() +service_stat['percentage_delay'] = (service_stat['dropoff_time'] - service_stat['demand_time']) / service_stat['min_possible_delay'] - 1 +maximum = service_stat['percentage_delay'].max() +service_stat['percentage_delay_norm'] = service_stat['percentage_delay'] / maximum + +new_df = service_stat.where(service_stat['percentage_delay'] > 0.0) +new_df = new_df.dropna() + +bins = [0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8, 1 * maximum] + + +bins_df = pd.cut(new_df['percentage_delay'], bins) +print(bins_df.value_counts()) + +t = bins_df.value_counts(sort=False) +labels = ['< 10 %', '< 20 %', '< 30 %', '< 40 %', '< 60 %', '< 80 %', '81 % +'] + + +counts = t +plt.axis('equal') +explode = bins +colors = ['#191970','#0038E2','#0071C6','#329A82', '#46C3A6', '#93DCCB', '#E0F5F0'] +colors2 = ['#E6F7FF', '#BAE7FF', '#91D5FF', '#69C0FF', '#1890FF', '#096DD9', '#0050B3', '#002766'] +cc = list(reversed(colors)) +counts.plot(kind='pie', fontsize=15, colors=cc, labels=t, + wedgeprops={"edgecolor": "black", + 'linewidth': 0.2, + 'antialiased': True} + ) +plt.legend(labels=labels, loc="best") +plt.ylabel('') + + +plt.savefig(save_results_to + 'delay_percentages', bbox_inches='tight', transparent=True) + + +plt.show() \ No newline at end of file diff --git a/python/simod/statistics/demand_service.py b/python/simod/statistics/demand_service.py index 838ce18f..482496eb 100644 --- a/python/simod/statistics/demand_service.py +++ b/python/simod/statistics/demand_service.py @@ -17,7 +17,8 @@ # along with this program. If not, see . # -from simod.init import config, roadmaptools_config +from simod.init import config +from roadmaptools.config import roadmaptools_config from tqdm import tqdm import numpy as np diff --git a/python/simod/statistics/demand_trip_duration_histogram.py b/python/simod/statistics/demand_trip_duration_histogram.py index 32f42f2e..eac110c7 100644 --- a/python/simod/statistics/demand_trip_duration_histogram.py +++ b/python/simod/statistics/demand_trip_duration_histogram.py @@ -16,12 +16,12 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter -from amodsim.statistics.model import demand_trips +from simod.statistics.model import demand_trips trips_data = demand_trips.load() diff --git a/python/simod/statistics/fleet_utilization.py b/python/simod/statistics/fleet_utilization.py new file mode 100644 index 00000000..ddb1c4d5 --- /dev/null +++ b/python/simod/statistics/fleet_utilization.py @@ -0,0 +1,85 @@ + +from simod.init import config + +from tqdm import tqdm +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +import matplotlib +import roadmaptools.inout +import simod.utils + +from matplotlib.ticker import FuncFormatter +from pandas import DataFrame + + +def to_percent_x(x, position): + # Ignore the passed in position. This has the effect of scaling the default + # tick locations. + s = str(int(round(100 * x))) + + # The percent symbol needs escaping in latex + if matplotlib.rcParams['text.usetex'] is True: + return s + r'$\%$' + else: + return s + '%' + +def to_percent_y(y, position): + # Ignore the passed in position. This has the effect of scaling the default + # tick locations. + s = str(int(round(10 * y))) + + # The percent symbol needs escaping in latex + if matplotlib.rcParams['text.usetex'] is True: + return s + r'$\%$' + else: + return s + '%' + + +data_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/experiments/test/inactive_vehicles.csv' +data_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/experiments/test/inactive_vehicles.csv' +data_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/experiments/test/inactive_vehicles.csv' + +save_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/img/' +save_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/img/' +save_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/img/' + +# TODO change dir +df = pd.read_csv(data_dir_3) + +# vehicles = df['id'].values + +occur = df.groupby(['id']).size() + +occur_df = occur.to_frame() +occur_df = occur_df.reset_index() +occur_df.columns=['id','occurance_inactive'] +occur_df['time_inactive'] = occur_df['occurance_inactive'] * 30 + +simulation_duration = 5 * 60 * 60 + 600 # in seconds + +occur_df['percentage_active'] = (simulation_duration - occur_df['time_inactive']) / simulation_duration + +df_short = occur_df[['id', 'percentage_active']] + +fig, axis = plt.subplots(1, 1, subplot_kw={"adjustable": 'box'}, figsize=(4, 3)) + +plt.gca().xaxis.set_major_formatter(FuncFormatter(to_percent_x)) + +bins = np.arange(0, 1, 0.1) +axis.set_xticks(bins) +plt.xticks(fontsize=9, rotation=0) + +axis.hist(occur_df['percentage_active'], bins, density=False, stacked=False, edgecolor='black', linewidth=0.4) + +# plt.title("Vehicle utilization") + +# TODO change dir +save_results_to = save_dir_3 +plt.savefig(save_results_to + 'vehicle-utilization', bbox_inches='tight', transparent=True) + +plt.show() + + + +print('done') \ No newline at end of file diff --git a/python/simod/statistics/map_from_edges.py b/python/simod/statistics/map_from_edges.py new file mode 100644 index 00000000..c8a2ad23 --- /dev/null +++ b/python/simod/statistics/map_from_edges.py @@ -0,0 +1,90 @@ +import geopandas as gpd +import contextily as ctx +import matplotlib.pyplot as plt +import pandas as pd +import seaborn as sns +import shapely +from mpl_toolkits.basemap import Basemap +import rasterio.crs +from ctypes.util import find_library + + + +def add_basemap(ax, zoom, url='http://tile.stamen.com/terrain/tileZ/tileX/tileY.png'): + xmin, xmax, ymin, ymax = ax.axis() + basemap, extent = ctx.bounds2img(xmin, ymin, xmax, ymax, zoom=zoom, source=url) + ax.imshow(basemap, extent=extent, interpolation='bilinear') + # restore original x/y limits + ax.axis((xmin, xmax, ymin, ymax)) + + + +# find_library('geos_c') + +# data = gpd.read_file('/Users/adela/Documents/bakalarka/randomdemand/maps/edges.geojson') +save_dir = '/Users/adela/Documents/bakalarka/vysledky2/' + +data = pd.read_csv('/Users/adela/Documents/bakalarka/randomdemand/trips.txt', sep=" ", header=None) +data.columns = ["time", "y", "x", "y2", "x2"] +data_part1 = data[['y', 'x']] +data_part2 = data[['y2', 'x2']] +# +new_data = pd.concat([data_part1, data_part2.rename(columns={'y2': 'y', 'x2': 'x'})], ignore_index=True) +new_data = new_data.reset_index() +# +gdf = gpd.GeoDataFrame(new_data, geometry=gpd.points_from_xy(new_data.y, new_data.x), crs='EPSG:4326') + + +gdf.geometry.map(lambda polygon: shapely.ops.transform(lambda x, y: (y, x), polygon)) + +gdf = gdf.set_crs(epsg='4326', allow_override=True) +gdf = gdf['geometry'] + +df_wm = gdf.to_crs(epsg=3857) +# ax = gdf.plot(figsize=(10, 10), alpha=0.7, c='grey') + +ax = gdf.plot(figsize=(10, 10), alpha=0, c='grey') +# ctx.add_basemap(ax, crs='EPSG:3857', source=ctx.providers.Stamen.TonerLite) + +sns.kdeplot(data=new_data, + x='y', + y='x', + fill=True, + cmap='coolwarm', + alpha=0.6, + gridsize=300, + levels=10, + ax=ax, + legend=False) + +# ax = gdf.plot(figsize=(10, 10), alpha=0.1, c='grey') + +# ctx.add_basemap(ax, zoom=18) +# ctx.add_basemap(ax, crs=df_wm.crs.to_string(), zoom=10) +# m.shadedrelief() + +# minx, miny, maxx, maxy = data.total_bounds + +# print(minx, maxx, miny, maxy) + +# ax = gdf.plot(figsize=(10, 10), alpha=0.5, edgecolor='b') + +# add_basemap(ax, zoom=10) +# ctx.add_basemap(ax, crs=gdf.crs, zoom=10) + +# ctx.add_basemap(ax, zoom=12, source=ctx.providers.OpenStreetMap.Mapnik) +# ctx.add_basemap(ax, crs=gdf.crs, source=ctx.providers.OpenStreetMap.Mapnik) +# ctx.add_basemap(ax, source=ctx.providers.Stamen.TonerLite) +# ctx.add_basemap(ax, source=ctx.providers.Stamen.TonerLite, crs=gdf.crs.to_string()) + +# ax.get_xaxis().set_ticks([]) +# ax.get_yaxis().set_ticks([]) +ax.set_ylabel('') +ax.set_xlabel('') + +# plt.savefig(save_dir + 'road_graph', bbox_inches='tight', transparent=True) +# plt.savefig(save_dir + 'demand_locations', bbox_inches='tight', transparent=True) +plt.savefig(save_dir + 'demand_heatmap', bbox_inches='tight', transparent=True) + +plt.show() + diff --git a/python/simod/statistics/model/edges.py b/python/simod/statistics/model/edges.py index d51304e1..a276d2ba 100644 --- a/python/simod/statistics/model/edges.py +++ b/python/simod/statistics/model/edges.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import pandas import roadmaptools.inout diff --git a/python/simod/statistics/model/occupancy.py b/python/simod/statistics/model/occupancy.py index 46648a5d..9f585f78 100644 --- a/python/simod/statistics/model/occupancy.py +++ b/python/simod/statistics/model/occupancy.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import pandas diff --git a/python/simod/statistics/model/ridesharing.py b/python/simod/statistics/model/ridesharing.py index 26e9ad97..c0460b78 100644 --- a/python/simod/statistics/model/ridesharing.py +++ b/python/simod/statistics/model/ridesharing.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import pandas import roadmaptools.inout diff --git a/python/simod/statistics/model/service.py b/python/simod/statistics/model/service.py index aeb2e509..c45f62c3 100644 --- a/python/simod/statistics/model/service.py +++ b/python/simod/statistics/model/service.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import pandas diff --git a/python/simod/statistics/model/traffic_load.py b/python/simod/statistics/model/traffic_load.py index c5d4a2bf..3561e808 100644 --- a/python/simod/statistics/model/traffic_load.py +++ b/python/simod/statistics/model/traffic_load.py @@ -18,7 +18,7 @@ # from pandas.io.formats.format import return_docstring -from amodsim.init import config +from simod.init import config import json import matplotlib @@ -28,7 +28,7 @@ from matplotlib import cm from roadmaptools.printer import print_info -from amodsim.json_cache import load_json_file +from simod.json_cache import load_json_file CRITICAL_DENSITY = config.critical_density diff --git a/python/simod/statistics/model/transit.py b/python/simod/statistics/model/transit.py index c90f3e87..0adb661e 100644 --- a/python/simod/statistics/model/transit.py +++ b/python/simod/statistics/model/transit.py @@ -16,13 +16,13 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import pandas from typing import Union from pandas import DataFrame -from amodsim.statistics.model.vehicle_state import VehicleState +from simod.statistics.model.vehicle_state import VehicleState cols = ["time", "edge_id", "vehicle_state"] diff --git a/python/simod/statistics/model/trips.py b/python/simod/statistics/model/trips.py index 1d8d1d30..4c21aad1 100644 --- a/python/simod/statistics/model/trips.py +++ b/python/simod/statistics/model/trips.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import pandas import roadmaptools.inout diff --git a/python/simod/statistics/occupancy.py b/python/simod/statistics/occupancy.py index d0802939..a3248f47 100644 --- a/python/simod/statistics/occupancy.py +++ b/python/simod/statistics/occupancy.py @@ -17,14 +17,14 @@ # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config from tqdm import tqdm import numpy as np import matplotlib.pyplot as plt import matplotlib import roadmaptools.inout -import amodsim.utils +import simod.utils from matplotlib.ticker import FuncFormatter from pandas import DataFrame @@ -42,8 +42,25 @@ def to_percent(y, position): return s + '%' -results = roadmaptools.inout.load_json(config.statistics.result_file_path) -data = np.genfromtxt(config.statistics.occupancies_file_path, delimiter=',') +exp_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/experiments/test/result.json' +exp_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/experiments/test/result.json' +exp_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/experiments/test/result.json' + +# results = roadmaptools.inout.load_json(config.statistics.result_file_path) +# TODO change dir +results = roadmaptools.inout.load_json(exp_dir_3) + +occ_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/experiments/test/vehicle_occupancy.csv' +occ_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/experiments/test/vehicle_occupancy.csv' +occ_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/experiments/test/vehicle_occupancy.csv' +# TODO change dir +data = np.genfromtxt(occ_dir_3, delimiter=',') + +save_dir_1 = '/Users/adela/Documents/bakalarka/vysledky2/InsertionHeuristic/Archiv/img/' +save_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/img/' +save_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/img/' +# TODO change dir +save_results_to = save_dir_3 occupancy_col = data[:,2] @@ -60,9 +77,11 @@ def to_percent(y, position): bins = np.arange(-0.5, 6.5, 1) -axis.hist(occupancy_col, bins, normed=True) +# axis.hist(occupancy_col, bins, normed=True) +axis.hist(occupancy_col, bins, density=True, stacked=True) +# plt.title('Vehicle occupancy') -# plt.savefig(config.images.occupancy_histogram, bbox_inches='tight', transparent=True) +plt.savefig(save_results_to + 'occupancy', bbox_inches='tight', transparent=True) # in window @@ -82,9 +101,12 @@ def to_percent(y, position): # axis.set_xlabel("Vehicle occupancy [persons]") # axis.set_ylabel("Share of vehicles") -axis.hist(occupancy_in_window, bins, normed=True) +# axis.hist(occupancy_in_window, bins, normed=True) +axis.hist(occupancy_in_window, bins, density=True, stacked=True) + +# plt.savefig(config.images.occupancy_histogram_window, bbox_inches='tight', transparent=True) +plt.savefig(save_results_to + 'occupancy-window', bbox_inches='tight', transparent=True) -plt.savefig(config.images.occupancy_histogram_window, bbox_inches='tight', transparent=True) # occupancy in time df = DataFrame(data, columns=["period", "id", "occupancy"]) @@ -95,5 +117,7 @@ def to_percent(y, position): fig, axis = plt.subplots(1, 1, subplot_kw={"adjustable": 'box'}, figsize=(4, 3)) axis.plot(avg_occupancies_per_period) +# plt.title("Average vehicle occupancy over time") +plt.savefig(save_results_to + 'occupancy-in-time', bbox_inches='tight', transparent=True) plt.show() diff --git a/python/simod/statistics/traffic_density_histogram.py b/python/simod/statistics/traffic_density_histogram.py index 0296e02c..81a22c68 100644 --- a/python/simod/statistics/traffic_density_histogram.py +++ b/python/simod/statistics/traffic_density_histogram.py @@ -16,17 +16,17 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # -from amodsim.init import config +from simod.init import config import matplotlib.pyplot as plt import numpy as np from matplotlib import rcParams from roadmaptools.printer import print_info, print_table -from amodsim.statistics.model.traffic_load import WINDOW_START, WINDOW_END, WINDOW_LENGTH -from amodsim.statistics.model.vehicle_state import VehicleState -from amodsim.utils import to_percetnt, col_to_percent -import amodsim.statistics.model.traffic_load as traffic_load +from simod.statistics.model.traffic_load import WINDOW_START, WINDOW_END, WINDOW_LENGTH +from simod.statistics.model.vehicle_state import VehicleState +from simod.utils import to_percetnt, col_to_percent +import simod.statistics.model.traffic_load as traffic_load HISTOGRAM_SAMPLES = 16 diff --git a/python/simod/statistics/trip_statistics.py b/python/simod/statistics/trip_statistics.py index 2f578d01..1f0d73ca 100644 --- a/python/simod/statistics/trip_statistics.py +++ b/python/simod/statistics/trip_statistics.py @@ -23,11 +23,11 @@ from matplotlib.ticker import FuncFormatter from simod.statistics.model import trips -HOURS_IN_DAY = 24 +HOURS_IN_DAY = 5 MINUTES_IN_HOUR = 60 -HISTOGRAM_SAMPLES = 96 +HISTOGRAM_SAMPLES = 5 def format_timestamps(tick, tick_index): @@ -43,7 +43,8 @@ def format_timestamps(tick, tick_index): counts, bins, patches = axis.hist(trips_data["start_time"], HISTOGRAM_SAMPLES) -tick_interval = int(HISTOGRAM_SAMPLES / 16) +tick_interval = 5 +tick_interval = int(HISTOGRAM_SAMPLES / 20) axis.set_xticks(bins[0::tick_interval]) axis.xaxis.set_major_formatter(FuncFormatter(format_timestamps)) @@ -52,8 +53,8 @@ def format_timestamps(tick, tick_index): plt.subplots_adjust(bottom=0.2) axis.get_xaxis().set_tick_params(direction='out') - -# plt.savefig(config.images.trip_start_histogram, bbox_inches='tight', transparent=True, pad_inches=0) +save_dir_1 = '/Users/adela/Documents/bakalarka/vysledky/' +plt.savefig(save_dir_1 + 'demands_in_time', bbox_inches='tight', transparent=True, pad_inches=0) # fig, axis = plt.subplots(figsize=(6, 4)) # diff --git a/python/simod/statistics/waiting_time_histogram.py b/python/simod/statistics/waiting_time_histogram.py new file mode 100644 index 00000000..cba8bfd0 --- /dev/null +++ b/python/simod/statistics/waiting_time_histogram.py @@ -0,0 +1,66 @@ +import matplotlib.pyplot as plt +import pandas.errors +import pandas as pd +import numpy as np +import matplotlib +import roadmaptools.inout +from matplotlib.ticker import FuncFormatter + +import simod.statistics.model.traffic_load as traffic_load +import simod.statistics.model.transit as transit +import simod.statistics.model.edges as edges +import simod.statistics.model.ridesharing as ridesharing +import simod.statistics.model.service as service +import simod.statistics.model.occupancy as occupancy + +def to_percent_x(x, position): + # Ignore the passed in position. This has the effect of scaling the default + # tick locations. + s = str(int(round(100 * x))) + + # The percent symbol needs escaping in latex + if matplotlib.rcParams['text.usetex'] is True: + return s + r'$\%$' + else: + return s + '%' + +def to_percent_y(y, position): + # Ignore the passed in position. This has the effect of scaling the default + # tick locations. + s = str(int(round(10 * y))) + + # The percent symbol needs escaping in latex + if matplotlib.rcParams['text.usetex'] is True: + return s + r'$\%$' + else: + return s + '%' + + +exp_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/experiments/test/waiting_times.csv' +save_dir_2 = '/Users/adela/Documents/bakalarka/vysledky2/transferInsertionHeuristic/Archiv/img/' +exp_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/experiments/test/waiting_times.csv' +save_dir_3 = '/Users/adela/Documents/bakalarka/vysledky2/taset/Archiv/img/' + + +# delays dataframe +# TODO change dir +df = pd.read_csv(exp_dir_2) +# TODO change dir +save_results_to = save_dir_2 + +fig, axis = plt.subplots(1, 1, subplot_kw={"adjustable": 'box'}, figsize=(4, 3)) + +maximum = df['waiting_time'].max() + +bins = np.arange(0, maximum+20, 10) +labels = bins[0::2] +axis.set_xticks(labels) +plt.xticks(fontsize=8, rotation=0) + +axis.hist(df['waiting_time'], bins, density=False, stacked=False, edgecolor='black', linewidth=0.4) + +# plt.title("Waiting times") + +plt.savefig(save_results_to + 'waiting_times', bbox_inches='tight', transparent=True) + +plt.show() \ No newline at end of file diff --git a/src/main/java/cz/cvut/fel/aic/simod/DriveToTransferStation.java b/src/main/java/cz/cvut/fel/aic/simod/DriveToTransferStation.java new file mode 100644 index 00000000..7754ab7c --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/DriveToTransferStation.java @@ -0,0 +1,103 @@ +package cz.cvut.fel.aic.simod; + +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.Trip; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.Activity; +import cz.cvut.fel.aic.agentpolis.simmodel.ActivityInitializer; +import cz.cvut.fel.aic.agentpolis.simmodel.Agent; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.PhysicalVehicleDrive; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.VehicleMoveActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.agent.Driver; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.vehicle.Vehicle; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.EGraphType; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationEdge; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.networks.TransportNetworks; +import cz.cvut.fel.aic.agentpolis.simmodel.eventType.DriveEvent; +import cz.cvut.fel.aic.agentpolis.simmodel.eventType.Transit; +import cz.cvut.fel.aic.alite.common.event.EventProcessor; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; +import cz.cvut.fel.aic.geographtools.Graph; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; + + +/** + * @param + * @author fido + */ +public class DriveToTransferStation extends PhysicalVehicleDrive { + + private final Vehicle vehicle; + + public final Trip trip; + + private final VehicleMoveActivityFactory moveActivityFactory; + + private final Graph graph; + + private final EventProcessor eventProcessor; + + private final StandardTimeProvider timeProvider; + + + private SimulationNode from; + + public SimulationNode to; + + + + + public DriveToTransferStation(ActivityInitializer activityInitializer, TransportNetworks transportNetworks, + VehicleMoveActivityFactory moveActivityFactory, TypedSimulation eventProcessor, + StandardTimeProvider timeProvider, + A agent, Vehicle vehicle, Trip trip) { + super(activityInitializer, agent); + this.vehicle = vehicle; + this.trip = trip; + this.moveActivityFactory = moveActivityFactory; + this.eventProcessor = eventProcessor; + this.timeProvider = timeProvider; + graph = transportNetworks.getGraph(EGraphType.HIGHWAY); + } + + @Override + protected void performAction() { + agent.startDriving(vehicle); + from = trip.removeFirstLocation(); + move(); + } + + @Override + protected void onChildActivityFinish(Activity activity) { + if (trip.isEmpty() || stoped) { + agent.endDriving(); + if (agent instanceof RideSharingOnDemandVehicle) { + ((RideSharingOnDemandVehicle) agent).tripAlreadyPlanned = false; + } + vehicle.setLastFromPosition(from); + finish(); + } else { + from = to; + move(); + } + } + + + private void move() { + to = trip.removeFirstLocation(); + SimulationEdge edge = graph.getEdge(from, to); + + runChildActivity(moveActivityFactory.create(agent, edge, from, to)); + triggerVehicleEnteredEdgeEvent(); + } + + private void triggerVehicleEnteredEdgeEvent() { + SimulationEdge edge = graph.getEdge(from, to); + Transit transit = new Transit(timeProvider.getCurrentSimTime(), edge.getStaticId(),trip.getTripId(), agent); + eventProcessor.addEvent(DriveEvent.VEHICLE_ENTERED_EDGE, null, null, transit); + } + + public Trip getTrip() { + return trip; + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/DriveToTransferStationActivityFactory.java b/src/main/java/cz/cvut/fel/aic/simod/DriveToTransferStationActivityFactory.java new file mode 100644 index 00000000..0b4d7e26 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/DriveToTransferStationActivityFactory.java @@ -0,0 +1,66 @@ +package cz.cvut.fel.aic.simod; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.Trip; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.ActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.Agent; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.Drive; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.PhysicalVehicleDriveFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.VehicleMoveActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.agent.Driver; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.vehicle.PhysicalVehicle; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.networks.TransportNetworks; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; + +/** + * @author fido + */ +@Singleton +public class DriveToTransferStationActivityFactory extends ActivityFactory implements PhysicalVehicleDriveFactory { + + private final TransportNetworks transportNetworks; + + private final VehicleMoveActivityFactory moveActivityFactory; + + private final TypedSimulation eventProcessor; + + private final StandardTimeProvider timeProvider; + + private final TripsUtil tripsUtil; + + + @Inject + public DriveToTransferStationActivityFactory(TransportNetworks transportNetworks, VehicleMoveActivityFactory moveActivityFactory, + TypedSimulation eventProcessor, StandardTimeProvider timeProvider,TripsUtil tripsUtil) { + this.transportNetworks = transportNetworks; + this.moveActivityFactory = moveActivityFactory; + this.eventProcessor = eventProcessor; + this.timeProvider = timeProvider; + this.tripsUtil = tripsUtil; + } + + + @Override + public void runActivity(A agent, PhysicalVehicle vehicle, Trip trip) { + create(agent, vehicle, trip).run(); + } + + + public DriveToTransferStation create(A agent, PhysicalVehicle vehicle, Trip trip) { + return new DriveToTransferStation<>(activityInitializer, transportNetworks, moveActivityFactory, eventProcessor, + timeProvider, agent, vehicle, trip); + } + + @Override + public DriveToTransferStation create(A agent, PhysicalVehicle vehicle, SimulationNode target) { + Trip trip = tripsUtil.createTrip(agent.getPosition(), target); + + return new DriveToTransferStation<>(activityInitializer, transportNetworks, moveActivityFactory, eventProcessor, timeProvider, + agent, vehicle, trip); + } + +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/MainModule.java b/src/main/java/cz/cvut/fel/aic/simod/MainModule.java index 15d96090..3a9fc356 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/MainModule.java +++ b/src/main/java/cz/cvut/fel/aic/simod/MainModule.java @@ -18,6 +18,9 @@ */ package cz.cvut.fel.aic.simod; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.GreedyTASeTNoFreezeSolver; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.GreedyTASeTSolver; +import cz.cvut.fel.aic.simod.ridesharing.transferinsertion.TransferInsertionSolver; import cz.cvut.fel.aic.simod.traveltimecomputation.DistanceMatrixTravelTimeProvider; import cz.cvut.fel.aic.simod.traveltimecomputation.TNRTravelTimeProvider; import cz.cvut.fel.aic.simod.traveltimecomputation.TNRAFTravelTimeProvider; @@ -146,6 +149,16 @@ protected void configureNext() { bind(SingleVehicleDARPSolver.class).to(ArrayOptimalVehiclePlanFinder.class); // bind(OptimalVehiclePlanFinder.class).to(PlanBuilderOptimalVehiclePlanFinder.class); break; + case "greedy-taset": + bind(DARPSolver.class).to(GreedyTASeTSolver.class); + // nabindovat i nove tridy + break; + case "greedy-taset-no-freeze": + bind(DARPSolver.class).to(GreedyTASeTNoFreezeSolver.class); + break; + case "transfer-insertion": + bind(DARPSolver.class).to(TransferInsertionSolver.class); + break; } } else{ diff --git a/src/main/java/cz/cvut/fel/aic/simod/MapVisualizer.java b/src/main/java/cz/cvut/fel/aic/simod/MapVisualizer.java index ad7c7820..900a1c7a 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/MapVisualizer.java +++ b/src/main/java/cz/cvut/fel/aic/simod/MapVisualizer.java @@ -25,6 +25,7 @@ import cz.cvut.fel.aic.agentpolis.system.AgentPolisInitializer; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.init.StationsInitializer; +import cz.cvut.fel.aic.simod.init.TransferPointsInitializer; import cz.cvut.fel.aic.simod.mapVisualization.MapVisualiserModule; import cz.cvut.fel.aic.simod.mapVisualization.MapVisualizationCreator; import java.io.File; @@ -60,6 +61,9 @@ public void run(String[] args) { // load stations injector.getInstance(StationsInitializer.class).loadStations(); + // load transfer points + injector.getInstance(TransferPointsInitializer.class).loadTransferPoints(); + creator.startSimulation(); diff --git a/src/main/java/cz/cvut/fel/aic/simod/OnDemandVehiclesSimulation.java b/src/main/java/cz/cvut/fel/aic/simod/OnDemandVehiclesSimulation.java index 1454ace0..b32a90ef 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/OnDemandVehiclesSimulation.java +++ b/src/main/java/cz/cvut/fel/aic/simod/OnDemandVehiclesSimulation.java @@ -20,20 +20,34 @@ import com.google.inject.Injector; import cz.cvut.fel.aic.agentpolis.config.AgentpolisConfig; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.Trip; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.init.MapInitializer; import cz.cvut.fel.aic.agentpolis.simulator.creator.SimulationCreator; +import cz.cvut.fel.aic.agentpolis.simulator.visualization.visio.VisioPositionUtil; import cz.cvut.fel.aic.agentpolis.system.AgentPolisInitializer; import cz.cvut.fel.aic.simod.config.SimodConfig; +import cz.cvut.fel.aic.simod.config.TransferInsertion; import cz.cvut.fel.aic.simod.init.EventInitializer; import cz.cvut.fel.aic.simod.init.StationsInitializer; import cz.cvut.fel.aic.simod.init.StatisticInitializer; +import cz.cvut.fel.aic.simod.init.TransferPointsInitializer; +import cz.cvut.fel.aic.simod.io.TimeTrip; import cz.cvut.fel.aic.simod.io.TripTransform; import cz.cvut.fel.aic.simod.rebalancing.ReactiveRebalancing; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.GreedyTASeTSolver; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.GreedyTASeTNoFreezeSolver; +import cz.cvut.fel.aic.simod.ridesharing.transferinsertion.TransferInsertionSolver; import cz.cvut.fel.aic.simod.traveltimecomputation.TravelTimeProvider; import cz.cvut.fel.aic.simod.statistics.Statistics; import cz.cvut.fel.aic.simod.tripUtil.TripsUtilCached; import java.io.File; import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + import org.slf4j.LoggerFactory; /** @@ -51,6 +65,7 @@ public static void checkPaths(SimodConfig config, AgentpolisConfig agentpolisCon String[] pathsForRead = { config.tripsPath, config.stationPositionFilepath, + config.transferPointsFilepath, agentpolisConfig.mapNodesFilepath, agentpolisConfig.mapEdgesFilepath }; @@ -109,6 +124,14 @@ public void run(String[] args) { // load stations injector.getInstance(StationsInitializer.class).loadStations(); + // load transfer points +// injector.getInstance(TransferPointsInitializer.class).loadTransferPoints(); + injector.getInstance(GreedyTASeTSolver.class).setTransferPoints(injector.getInstance(TransferPointsInitializer.class).loadTransferPoints()); + + injector.getInstance(GreedyTASeTNoFreezeSolver.class).setTransferPoints(injector.getInstance(TransferPointsInitializer.class).loadTransferPoints()); + + injector.getInstance(TransferInsertionSolver.class).setTransferPoints(injector.getInstance(TransferPointsInitializer.class).loadTransferPoints()); + if(config.rebalancing.on){ // start rebalancing @@ -121,6 +144,29 @@ public void run(String[] args) { injector.getInstance(EventInitializer.class).initialize( tripTransform.loadTripsFromTxt(new File(config.tripsPath)), null); +// USED TO COMPUTE STATISTICS OF DEMAND +// List lengths = new ArrayList<>(); +// List> trips = tripTransform.loadTripsFromTxt(new File(config.tripsPath)); +// for (TimeTrip trip : trips) { +// SimulationNode origin = trip.getAllLocations()[0]; +// SimulationNode destination = trip.getAllLocations()[1]; +// Trip t = injector.getInstance(TripsUtil.class).createTrip(origin, destination); +// long l = injector.getInstance(VisioPositionUtil.class).getTripLengthInMeters(t); +// lengths.add(l); +// } +// +//// get max, min and avg +// lengths.stream() // +// .max(Comparator.comparing(i -> i)) // +// .ifPresent(max -> System.out.println("Maximum found is " + max)); +// lengths.stream() // +// .min(Comparator.comparing(i -> i)) // +// .ifPresent(min -> System.out.println("Minimum found is " + min)); +// lengths.stream() // +// .mapToLong(i -> i) // +// .average() // +// .ifPresent(avg -> System.out.println("Average found is " + avg)); + injector.getInstance(StatisticInitializer.class).initialize(); // start it up diff --git a/src/main/java/cz/cvut/fel/aic/simod/TransferPickUp.java b/src/main/java/cz/cvut/fel/aic/simod/TransferPickUp.java new file mode 100644 index 00000000..3241f980 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/TransferPickUp.java @@ -0,0 +1,41 @@ +package cz.cvut.fel.aic.simod; + +import cz.cvut.fel.aic.agentpolis.simmodel.agent.TransportEntity; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.TransportableEntity; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.vehicle.PhysicalTransportVehicle; + +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public final class TransferPickUp { + + public static void pickUp(T entity, + boolean isVehicleFull, E transportingEntity, List transportedEntities) { + if (isVehicleFull) { + try { + throw new Exception( + String.format("Cannot pick up entity, the vehicle is full! [%s]", entity)); + } catch (Exception ex) { + Logger.getLogger(PhysicalTransportVehicle.class.getName()).log(Level.SEVERE, null, ex); + } + } + if(entity.getTransportingEntity() != null) { + // auto se snazi zavolat pickup na demand, ktery jeste nedojel do cilove stanice + // ale nez by toto auto dojelo na stanici, demand uz by tam byl vylozeny + // proto podminka entity.getTransportingEntity() != null neni spravne + +// try { +// throw new Exception( +// String.format("Cannot pick up entity, it's already being transported! [%s]", entity)); +// } catch (Exception ex) { +// Logger.getLogger(PhysicalTransportVehicle.class.getName()).log(Level.SEVERE, null, ex); +// } + } + else{ + transportedEntities.add(entity); + entity.setTransportingEntity(transportingEntity); + } + } + +} \ No newline at end of file diff --git a/src/main/java/cz/cvut/fel/aic/simod/WaitTransfer.java b/src/main/java/cz/cvut/fel/aic/simod/WaitTransfer.java new file mode 100644 index 00000000..41993da5 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/WaitTransfer.java @@ -0,0 +1,94 @@ +package cz.cvut.fel.aic.simod; + +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.Trip; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.Activity; +import cz.cvut.fel.aic.agentpolis.simmodel.ActivityInitializer; +import cz.cvut.fel.aic.agentpolis.simmodel.Agent; +import cz.cvut.fel.aic.agentpolis.simmodel.TimeConsumingActivity; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.VehicleMoveActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.agent.Driver; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.vehicle.Vehicle; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.EGraphType; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationEdge; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.networks.TransportNetworks; +import cz.cvut.fel.aic.agentpolis.simmodel.eventType.DriveEvent; +import cz.cvut.fel.aic.agentpolis.simmodel.eventType.Transit; +import cz.cvut.fel.aic.alite.common.event.EventProcessor; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; +import cz.cvut.fel.aic.geographtools.Graph; + +public class WaitTransfer extends TimeConsumingActivity { + + private final long waitTime; + + private final WaitActivityFactory waitActivityFactory; + +// private final Trip trip; +// +// private final VehicleMoveActivityFactory moveActivityFactory; +// +// private final Vehicle vehicle; +// +// private final Graph graph; +// +// private final EventProcessor eventProcessor; +// +// private final StandardTimeProvider timeProvider; + + +// private SimulationNode from; +// +// private SimulationNode to; + + public WaitTransfer(ActivityInitializer activityInitializer, A agent, long waitTime, WaitActivityFactory waitActivityFactory +// , VehicleMoveActivityFactory moveActivityFactory, +// TypedSimulation eventProcessor, StandardTimeProvider timeProvider, Trip trip, Vehicle vehicle, TransportNetworks transportNetworks + ) { + super(activityInitializer, agent); + this.waitTime = waitTime; + this.waitActivityFactory = waitActivityFactory; +// this.moveActivityFactory = moveActivityFactory; +// this.timeProvider = timeProvider; +// this.eventProcessor = eventProcessor; +// this.trip = trip; +// this.vehicle = vehicle; +// graph = transportNetworks.getGraph(EGraphType.HIGHWAY); + + } + + @Override + protected long performPreDelayActions() { + return waitTime; + } + + @Override + protected void performAction() { + waitTransfer(); + +// finish(); + } + +// @Override +// protected void onChildActivityFinish(Activity activity) { +//// if (trip.isEmpty()) { +//// vehicle.setLastFromPosition(from); +//// finish(); +//// } else { +// from = to; +// move(); +//// } +// } + +// private void move() { +// +// } + + private void waitTransfer() { + runChildActivity(waitActivityFactory.create(agent, waitTime)); + } + + +} \ No newline at end of file diff --git a/src/main/java/cz/cvut/fel/aic/simod/WaitTransferActivityFactory.java b/src/main/java/cz/cvut/fel/aic/simod/WaitTransferActivityFactory.java new file mode 100644 index 00000000..464a6199 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/WaitTransferActivityFactory.java @@ -0,0 +1,20 @@ +package cz.cvut.fel.aic.simod; + +import com.google.inject.Singleton; +import cz.cvut.fel.aic.agentpolis.simmodel.Activity; +import cz.cvut.fel.aic.agentpolis.simmodel.ActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.Agent; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; + +@Singleton +public class WaitTransferActivityFactory extends ActivityFactory { + + + public void runActivity(A agent, long waitTime, WaitActivityFactory waitActivityFactory) { + create(agent, waitTime, waitActivityFactory).run(); + } + + public WaitTransfer create(A agent, long waitTime, WaitActivityFactory waitActivityFactory) { + return new WaitTransfer<>(activityInitializer, agent, waitTime, waitActivityFactory); + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/WaitWithStop.java b/src/main/java/cz/cvut/fel/aic/simod/WaitWithStop.java new file mode 100644 index 00000000..3c714afd --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/WaitWithStop.java @@ -0,0 +1,38 @@ +package cz.cvut.fel.aic.simod; + +import cz.cvut.fel.aic.agentpolis.simmodel.ActivityInitializer; +import cz.cvut.fel.aic.agentpolis.simmodel.Agent; +import cz.cvut.fel.aic.agentpolis.simmodel.TimeConsumingActivity; + +public class WaitWithStop extends TimeConsumingActivity{ + + private final long waitTime; + + protected boolean stoped; + + + public WaitWithStop(ActivityInitializer activityInitializer, A agent, long waitTime) { + super(activityInitializer, agent); + this.waitTime = waitTime; + this.stoped = false; + } + + public boolean isStoped() { + return stoped; + } + + public void end(){ + stoped = true; + } + + @Override + protected long performPreDelayActions() { + return waitTime; + } + + @Override + protected void performAction() { + finish(); + } + +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/WaitWithStopActivityFactory.java b/src/main/java/cz/cvut/fel/aic/simod/WaitWithStopActivityFactory.java new file mode 100644 index 00000000..ac33db49 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/WaitWithStopActivityFactory.java @@ -0,0 +1,19 @@ +package cz.cvut.fel.aic.simod; + +import com.google.inject.Singleton; +import cz.cvut.fel.aic.agentpolis.simmodel.ActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.Agent; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.Wait; + +@Singleton +public class WaitWithStopActivityFactory extends ActivityFactory { + + + public void runActivity(A agent, long waitTime) { + create(agent, waitTime).run(); + } + + public WaitWithStop create(A agent, long waitTime) { + return new WaitWithStop<>(activityInitializer, agent, waitTime); + } +} \ No newline at end of file diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/GreedyTASeT.java b/src/main/java/cz/cvut/fel/aic/simod/config/GreedyTASeT.java new file mode 100644 index 00000000..15cc7b14 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/config/GreedyTASeT.java @@ -0,0 +1,10 @@ +package cz.cvut.fel.aic.simod.config; + +import java.util.Map; + +public class GreedyTASeT { + + public GreedyTASeT(Map greedytaset) { + + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/GreedyTASeTNoFreeze.java b/src/main/java/cz/cvut/fel/aic/simod/config/GreedyTASeTNoFreeze.java new file mode 100644 index 00000000..e4d7058a --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/config/GreedyTASeTNoFreeze.java @@ -0,0 +1,10 @@ +package cz.cvut.fel.aic.simod.config; + +import java.util.Map; + +public class GreedyTASeTNoFreeze { + + public GreedyTASeTNoFreeze(Map greedytaset) { + + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/OnDemandVehicleStatistic.java b/src/main/java/cz/cvut/fel/aic/simod/config/OnDemandVehicleStatistic.java index 92759ce7..788b452f 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/config/OnDemandVehicleStatistic.java +++ b/src/main/java/cz/cvut/fel/aic/simod/config/OnDemandVehicleStatistic.java @@ -14,6 +14,8 @@ public class OnDemandVehicleStatistic { public String finishRebalancingFilePath; + public String waitFilePath; + public String dirPath; public String startRebalancingFilePath; @@ -26,5 +28,6 @@ public OnDemandVehicleStatistic(Map onDemandVehicleStatistic) { this.finishRebalancingFilePath = (String) onDemandVehicleStatistic.get("finish_rebalancing_file_path"); this.dirPath = (String) onDemandVehicleStatistic.get("dir_path"); this.startRebalancingFilePath = (String) onDemandVehicleStatistic.get("start_rebalancing_file_path"); + this.waitFilePath = (String) onDemandVehicleStatistic.get("wait_file_path"); } } diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/Ridesharing.java b/src/main/java/cz/cvut/fel/aic/simod/config/Ridesharing.java index a4408f2b..def4fd8c 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/config/Ridesharing.java +++ b/src/main/java/cz/cvut/fel/aic/simod/config/Ridesharing.java @@ -1,5 +1,6 @@ package cz.cvut.fel.aic.simod.config; + import java.lang.Boolean; import java.lang.Double; import java.lang.Integer; @@ -7,6 +8,12 @@ import java.util.Map; public class Ridesharing { + public TransferInsertion transferInsertion; + + public GreedyTASeTNoFreeze greedyTASeTNoFreeze; + + public GreedyTASeT greedytaset; + public Vga vga; public Integer batchPeriod; @@ -28,6 +35,9 @@ public class Ridesharing { public Boolean on; public Ridesharing(Map ridesharing) { + this.transferInsertion = new TransferInsertion((Map) ridesharing.get("transfer-insertion")); + this.greedyTASeTNoFreeze = new GreedyTASeTNoFreeze((Map) ridesharing.get("greedy_taset_no_freeze")); + this.greedytaset = new GreedyTASeT((Map) ridesharing.get("greedy_taset")); this.vga = new Vga((Map) ridesharing.get("vga")); this.batchPeriod = (Integer) ridesharing.get("batch_period"); this.method = (String) ridesharing.get("method"); diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/SimodConfig.java b/src/main/java/cz/cvut/fel/aic/simod/config/SimodConfig.java index ef16dedd..0521c112 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/config/SimodConfig.java +++ b/src/main/java/cz/cvut/fel/aic/simod/config/SimodConfig.java @@ -48,6 +48,8 @@ public class SimodConfig implements GeneratedConfig { public String stationPositionFilepath; + public String transferPointsFilepath; + public Rebalancing rebalancing; public Statistics statistics; @@ -76,6 +78,7 @@ public SimodConfig fill(Map simodConfig) { this.simplifyGraph = (Boolean) simodConfig.get("simplify_graph"); this.ridesharing = new Ridesharing((Map) simodConfig.get("ridesharing")); this.stationPositionFilepath = (String) simodConfig.get("station_position_filepath"); + this.transferPointsFilepath = (String) simodConfig.get("transfer_points_filepath"); this.rebalancing = new Rebalancing((Map) simodConfig.get("rebalancing")); this.statistics = new Statistics((Map) simodConfig.get("statistics")); return this; diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/Statistics.java b/src/main/java/cz/cvut/fel/aic/simod/config/Statistics.java index 7b6ecbc2..54a6b1f0 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/config/Statistics.java +++ b/src/main/java/cz/cvut/fel/aic/simod/config/Statistics.java @@ -9,6 +9,10 @@ public class Statistics { public String occupanciesFilePath; + public String inactiveVehiclesFilePath; + + public String inactiveVehiclesFileName; + public String ridesharingFileName; public Integer statisticIntervalMilis; @@ -41,6 +45,10 @@ public class Statistics { public String ridesharingFilePath; + public String waitingTimesFilePath; + + public String waitingTimesFileName; + public Statistics(Map statistics) { this.resultFilePath = (String) statistics.get("result_file_path"); this.occupanciesFilePath = (String) statistics.get("occupancies_file_path"); @@ -60,5 +68,9 @@ public Statistics(Map statistics) { this.serviceFileName = (String) statistics.get("service_file_name"); this.serviceFilePath = (String) statistics.get("service_file_path"); this.ridesharingFilePath = (String) statistics.get("ridesharing_file_path"); + this.inactiveVehiclesFileName = (String) statistics.get("inactive_vehicles_file_name"); + this.inactiveVehiclesFilePath = (String) statistics.get("inactive_vehicles_file_path"); + this.waitingTimesFileName = (String) statistics.get("waiting_times_file_name"); + this.waitingTimesFilePath = (String) statistics.get("waiting_times_file_path"); } } diff --git a/src/main/java/cz/cvut/fel/aic/simod/config/TransferInsertion.java b/src/main/java/cz/cvut/fel/aic/simod/config/TransferInsertion.java new file mode 100644 index 00000000..c64bf85a --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/config/TransferInsertion.java @@ -0,0 +1,10 @@ +package cz.cvut.fel.aic.simod.config; + +import java.util.Map; + +public class TransferInsertion { + + public TransferInsertion(Map transferinsertion) { + + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgent.java b/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgent.java index 3998c4bd..cb3f9592 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgent.java +++ b/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgent.java @@ -205,6 +205,38 @@ public void tripEnded() { die(); } + public void tripPaused() { + if (state == DemandAgentState.WAITING) { + try { + throw new Exception(String.format("Demand Agent %s already stopped", this)); + } catch (Exception ex) { + Logger.getLogger(DemandAgent.class.getName()).log(Level.SEVERE, null, ex); + } + } + else{ + state = DemandAgentState.TRANSFERING; +// this.onDemandVehicle = null; + eventProcessor.addEvent(StatisticEvent.DEMAND_DROPPED_AT_TRANSFER, null, null, + null); + + } + } + + public void tripRePaused(OnDemandVehicle vehicle) { +// if(state == DemandAgentState.DRIVING){ +// try { +// throw new Exception(String.format("Demand Agent %s already repaused in vehicle %s, it cannot be picked up by" +// + "another vehicle %s", this, onDemandVehicle, vehicle)); +// } catch (Exception ex) { +// Logger.getLogger(DemandAgent.class.getName()).log(Level.SEVERE, null, ex); +// } +// } +// else{ + state = DemandAgentState.DRIVING; + this.onDemandVehicle = vehicle; +// } + } + public void tripStarted(OnDemandVehicle vehicle) { if(state == DemandAgentState.DRIVING){ try { diff --git a/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgentState.java b/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgentState.java index ee8c2f7b..687ee9ab 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgentState.java +++ b/src/main/java/cz/cvut/fel/aic/simod/entity/DemandAgentState.java @@ -24,5 +24,6 @@ */ public enum DemandAgentState { WAITING, - DRIVING + DRIVING, + TRANSFERING } diff --git a/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleState.java b/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleState.java index 4e989e5d..1aaf3aa4 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleState.java +++ b/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleState.java @@ -24,8 +24,10 @@ */ public enum OnDemandVehicleState { WAITING, + WAITINGFORTRANSFER, DRIVING_TO_START_LOCATION, DRIVING_TO_TARGET_LOCATION, DRIVING_TO_STATION, + DRIVING_TO_TRANSFER_STATION_TO_WAIT, REBALANCING; } diff --git a/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleStation.java b/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleStation.java index e25fd5e3..0aea69b4 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleStation.java +++ b/src/main/java/cz/cvut/fel/aic/simod/entity/OnDemandVehicleStation.java @@ -204,9 +204,11 @@ public int getIndex(){ } private OnDemandVehicle getAndRemoveVehicle() { - OnDemandVehicle nearestVehicle; + OnDemandVehicle nearestVehicle = null; - nearestVehicle = parkedVehicles.remove(0); + if (parkedVehicles.size() > 0) { + nearestVehicle = parkedVehicles.remove(0); + } return nearestVehicle; } diff --git a/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicle.java b/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicle.java index 4b5d7c1b..037ecadd 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicle.java +++ b/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicle.java @@ -28,7 +28,9 @@ import cz.cvut.fel.aic.agentpolis.simmodel.Agent; import cz.cvut.fel.aic.agentpolis.simmodel.IdGenerator; import cz.cvut.fel.aic.agentpolis.simmodel.activity.PhysicalVehicleDrive; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.Wait; import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.PhysicalVehicleDriveFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; import cz.cvut.fel.aic.agentpolis.simmodel.agent.DelayData; import cz.cvut.fel.aic.agentpolis.simmodel.agent.Driver; import cz.cvut.fel.aic.agentpolis.simmodel.entity.EntityType; @@ -39,9 +41,7 @@ import cz.cvut.fel.aic.alite.common.event.Event; import cz.cvut.fel.aic.alite.common.event.EventHandler; import cz.cvut.fel.aic.alite.common.event.EventProcessor; -import cz.cvut.fel.aic.simod.DemandData; -import cz.cvut.fel.aic.simod.DemandSimulationEntityType; -import cz.cvut.fel.aic.simod.StationsDispatcher; +import cz.cvut.fel.aic.simod.*; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.entity.DemandAgent; import cz.cvut.fel.aic.simod.entity.OnDemandVehicleState; @@ -50,6 +50,8 @@ import cz.cvut.fel.aic.simod.event.OnDemandVehicleEvent; import cz.cvut.fel.aic.simod.event.OnDemandVehicleEventContent; import cz.cvut.fel.aic.simod.event.RebalancingEventContent; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionWait; import cz.cvut.fel.aic.simod.statistics.PickupEventContent; import cz.cvut.fel.aic.simod.storage.PhysicalTransportVehicleStorage; import cz.cvut.fel.aic.geographtools.Node; @@ -122,6 +124,10 @@ public class OnDemandVehicle extends Agent implements EventHandler, PlanningAgen protected OnDemandVehicleStation parkedIn; + public WaitWithStopActivityFactory waitWithStopActivityFactory; + + private WaitActivityFactory waitActivityFactory; + @@ -187,6 +193,8 @@ public OnDemandVehicle( SimodConfig config, IdGenerator idGenerator, AgentpolisConfig agentpolisConfig, + WaitWithStopActivityFactory waitWithStopActivityFactory, + WaitActivityFactory waitActivityFactory, @Assisted String vehicleId, @Assisted SimulationNode startPosition) { super(vehicleId, startPosition); this.tripsUtil = tripsUtil; @@ -197,6 +205,8 @@ public OnDemandVehicle( this.timeProvider = timeProvider; this.rebalancingIdGenerator = rebalancingIdGenerator; this.config = config; + this.waitWithStopActivityFactory = waitWithStopActivityFactory; + this.waitActivityFactory = waitActivityFactory; index = idGenerator.getId(); @@ -252,6 +262,9 @@ public void finishedDriving(boolean wasStopped) { case REBALANCING: finishRebalancing(); break; +// case WAITINGFORTRANSFER: +// waitForTransfer(); +// break; } } @@ -417,13 +430,48 @@ protected void dropOffDemand() { currentlyServedDemmand.demandAgent.getSimpleId(), getId())); } + public void startWaiting() { + // pokud je auto jinde nez ve stanici, tak chcu vytvorit trip ke stanici, spustit jizdu a az dojede, + // tak spustit cekani, ktere je kratsi o cas dojezdu na stanici +// waitActivityFactory.runActivity(this, ((PlanActionWait) currentTask).getWaitTime()); + state = OnDemandVehicleState.WAITINGFORTRANSFER; +// currentPlan.taskCompleted(); +// currentTask = currentPlan.getNextTask(); + } + @Override protected void onActivityFinish(Activity activity) { super.onActivityFinish(activity); - PhysicalVehicleDrive drive = (PhysicalVehicleDrive) activity; - finishedDriving(drive.isStoped()); + if (activity instanceof DriveToTransferStation && ((DriveToTransferStation) activity).trip.isEmpty()) { + PhysicalVehicleDrive drive = (PhysicalVehicleDrive) activity; + if (drive.isStoped()) { + finishedDriving(drive.isStoped()); + } + else { + startWaiting(); + } + return; + + // try to do nothing + } + if (activity instanceof PhysicalVehicleDrive) { + PhysicalVehicleDrive drive = (PhysicalVehicleDrive) activity; + finishedDriving(drive.isStoped()); + } + else if (activity instanceof WaitWithStop) { + WaitWithStop wait = (WaitWithStop) activity; + finishedWaiting(wait.isStoped()); + } + + else { + finishedDriving(true); + } } + public void finishedWaiting(boolean wasStopped) { + + }; + @Override public EntityType getType() { return DemandSimulationEntityType.ON_DEMAND_VEHICLE; diff --git a/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicleFactory.java b/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicleFactory.java index 03d31815..98b9fc59 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicleFactory.java +++ b/src/main/java/cz/cvut/fel/aic/simod/entity/vehicle/OnDemandVehicleFactory.java @@ -25,10 +25,14 @@ import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; import cz.cvut.fel.aic.agentpolis.simmodel.IdGenerator; import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.PhysicalVehicleDriveFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; import cz.cvut.fel.aic.agentpolis.simulator.visualization.visio.VisioPositionUtil; import cz.cvut.fel.aic.alite.common.event.EventProcessor; import cz.cvut.fel.aic.simod.StationsDispatcher; +import cz.cvut.fel.aic.simod.WaitTransferActivityFactory; +import cz.cvut.fel.aic.simod.WaitWithStop; +import cz.cvut.fel.aic.simod.WaitWithStopActivityFactory; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.storage.PhysicalTransportVehicleStorage; @@ -62,6 +66,9 @@ public class OnDemandVehicleFactory implements OnDemandVehicleFactorySpec{ protected final AgentpolisConfig agentpolisConfig; + protected final WaitWithStopActivityFactory waitWithStopActivityFactory; + + protected final WaitActivityFactory waitActivityFactory; @@ -75,6 +82,8 @@ public OnDemandVehicleFactory( StandardTimeProvider timeProvider, IdGenerator rebalancingIdGenerator, SimodConfig config, + WaitWithStopActivityFactory waitWithStopActivityFactory, + WaitActivityFactory waitActivityFactory, IdGenerator idGenerator, AgentpolisConfig agentpolisConfig) { this.tripsUtil = tripsUtil; @@ -87,6 +96,8 @@ public OnDemandVehicleFactory( this.config = config; this.idGenerator = idGenerator; this.agentpolisConfig = agentpolisConfig; + this.waitWithStopActivityFactory = waitWithStopActivityFactory; + this.waitActivityFactory = waitActivityFactory; } @@ -105,6 +116,8 @@ public OnDemandVehicle create(String vehicleId, SimulationNode startPosition){ config, idGenerator, agentpolisConfig, + waitWithStopActivityFactory, + waitActivityFactory, vehicleId, startPosition); } diff --git a/src/main/java/cz/cvut/fel/aic/simod/event/OnDemandVehicleEvent.java b/src/main/java/cz/cvut/fel/aic/simod/event/OnDemandVehicleEvent.java index d8ce076d..ddcf97ae 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/event/OnDemandVehicleEvent.java +++ b/src/main/java/cz/cvut/fel/aic/simod/event/OnDemandVehicleEvent.java @@ -28,5 +28,6 @@ public enum OnDemandVehicleEvent{ DROP_OFF, REACH_NEAREST_STATION, START_REBALANCING, - FINISH_REBALANCING + FINISH_REBALANCING, + WAIT } diff --git a/src/main/java/cz/cvut/fel/aic/simod/init/StationsInitializer.java b/src/main/java/cz/cvut/fel/aic/simod/init/StationsInitializer.java index 6f43e17d..62ea4225 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/init/StationsInitializer.java +++ b/src/main/java/cz/cvut/fel/aic/simod/init/StationsInitializer.java @@ -78,10 +78,11 @@ public void loadStations(){ discarded++; } else{ - int initCount = Integer.parseInt(row[1]) + 100; - if(initCount < 500){ - initCount += 100; - } + // tady vznika tech 200 aut v kazde stanici + int initCount = Integer.parseInt(row[1]); +// if(initCount < 500){ +// initCount += 100; +// } createStation(node, initCount, counter++); } } diff --git a/src/main/java/cz/cvut/fel/aic/simod/init/TransferPointsInitializer.java b/src/main/java/cz/cvut/fel/aic/simod/init/TransferPointsInitializer.java new file mode 100644 index 00000000..a109cde4 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/init/TransferPointsInitializer.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021 Czech Technical University in Prague. + * + * This file is part of the SiMoD project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package cz.cvut.fel.aic.simod.init; + +import com.google.inject.Inject; +import com.univocity.parsers.csv.CsvParser; +import com.univocity.parsers.csv.CsvParserSettings; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.networks.NodesMappedByIndex; +import cz.cvut.fel.aic.simod.config.SimodConfig; +import cz.cvut.fel.aic.simod.entity.OnDemandVehicleStation; +import cz.cvut.fel.aic.simod.entity.OnDemandVehicleStation.OnDemandVehicleStationFactory; +import cz.cvut.fel.aic.simod.traveltimecomputation.DistanceMatrixTravelTimeProvider; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author david + */ +public class TransferPointsInitializer { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DistanceMatrixTravelTimeProvider.class); + + private final OnDemandVehicleStation.OnDemandVehicleStationFactory onDemandVehicleStationFactory; + + private final NodesMappedByIndex nodesMappedByIndex; + + private final SimodConfig config; + + + + @Inject + public TransferPointsInitializer(OnDemandVehicleStationFactory onDemandVehicleStationFactory, NodesMappedByIndex + nodesMappedByIndex, SimodConfig config) { + this.onDemandVehicleStationFactory = onDemandVehicleStationFactory; + this.nodesMappedByIndex = nodesMappedByIndex; + this.config = config; + } + + + public List loadTransferPoints(){ + List transferPoints = new ArrayList<>(); + List stationRows = loadTransferPointsRows(config.transferPointsFilepath); + LOGGER.info("{} Stations indexes loaded from {}", stationRows.size(), config.transferPointsFilepath); + + int counter = 0; + int discarded = 0; + for(String[] row: stationRows){ + int index = Integer.parseInt(row[0]); + SimulationNode node = nodesMappedByIndex.getNodeByIndex(index); + if(node == null){ + LOGGER.info("Station at node with index {} discarded as it is not in the Agentpolis road graph", index); + discarded++; + } + else{ +// int initCount = Integer.parseInt(row[1]) + 100; +// if(initCount < 500){ +// initCount += 100; +// } + transferPoints.add(node); + //createStation(node, initCount, counter++); + } + } + + LOGGER.info("{} Stations Discarded", discarded); + + return transferPoints; + + } + + private List loadTransferPointsRows(String filepath){ + LOGGER.info("Loading station positions from: {}", filepath); + + try { + Reader reader + = new BufferedReader(new InputStreamReader(new FileInputStream(filepath), "utf-8")); + CsvParserSettings settings = new CsvParserSettings(); + + settings.getFormat().setLineSeparator("\r\n"); + + //turning off features enabled by default + settings.setIgnoreLeadingWhitespaces(false); + settings.setIgnoreTrailingWhitespaces(false); + settings.setSkipEmptyLines(false); + settings.setColumnReorderingEnabled(false); + + CsvParser parser = new CsvParser(settings); + + Iterator it = parser.iterate(reader).iterator(); + + String[] row; + + // first row processing + List stationRows = new ArrayList<>(); + while (it.hasNext()) { + row = it.next(); + stationRows.add(row); + } + parser.stopParsing(); + return stationRows; + } + catch (FileNotFoundException | UnsupportedEncodingException ex) { + Logger.getLogger(DistanceMatrixTravelTimeProvider.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } + + // TODO: nahradit + private void createStation(SimulationNode position, int vehicleCount, int id){ + onDemandVehicleStationFactory.create(Integer.toString(id), position, vehicleCount); + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/DroppedDemandsAnalyzer.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/DroppedDemandsAnalyzer.java index 5a341943..a554bc2f 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/DroppedDemandsAnalyzer.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/DroppedDemandsAnalyzer.java @@ -54,15 +54,15 @@ public class DroppedDemandsAnalyzer { private final OnDemandvehicleStationStorage onDemandvehicleStationStorage; - - - + + + @Inject public DroppedDemandsAnalyzer( - OnDemandVehicleStorage vehicleStorage, - PositionUtil positionUtil, - TravelTimeProvider travelTimeProvider, - SimodConfig config, + OnDemandVehicleStorage vehicleStorage, + PositionUtil positionUtil, + TravelTimeProvider travelTimeProvider, + SimodConfig config, OnDemandvehicleStationStorage onDemandvehicleStationStorage, AgentpolisConfig agentpolisConfig) { this.vehicleStorage = vehicleStorage; @@ -70,20 +70,17 @@ public DroppedDemandsAnalyzer( this.travelTimeProvider = travelTimeProvider; this.onDemandvehicleStationStorage = onDemandvehicleStationStorage; this.config = config; - + // max distance in meters between vehicle and request for the vehicle to be considered to serve the request - maxDistance = (double) config.ridesharing.maxProlongationInSeconds + maxDistance = (double) config.ridesharing.maxProlongationInSeconds * agentpolisConfig.maxVehicleSpeedInMeters; - + // the traveltime from vehicle to request cannot be greater than max prolongation in milliseconds for the // vehicle to be considered to serve the request maxDelayTime = config.ridesharing.maxProlongationInSeconds * 1000; } - - - public void debugFail(PlanComputationRequest request, int[] usedVehiclesPerStation) { boolean freeVehicle = false; double bestEuclideanDistance = Double.MAX_VALUE; diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RideSharingOnDemandVehicle.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RideSharingOnDemandVehicle.java index 3b385a7f..27238f62 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RideSharingOnDemandVehicle.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RideSharingOnDemandVehicle.java @@ -22,31 +22,42 @@ import com.google.inject.assistedinject.Assisted; import cz.cvut.fel.aic.agentpolis.config.AgentpolisConfig; import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.Trip; import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.VehicleTrip; import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.Activity; import cz.cvut.fel.aic.agentpolis.simmodel.IdGenerator; import cz.cvut.fel.aic.agentpolis.simmodel.activity.PhysicalVehicleDrive; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.Wait; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.CongestedDriveFactory; import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.PhysicalVehicleDriveFactory; + +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.vehicle.PickUp; import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.init.SimpleMapInitializer; +import cz.cvut.fel.aic.agentpolis.simulator.creator.SimulationCreator; import cz.cvut.fel.aic.agentpolis.simulator.visualization.visio.VisioPositionUtil; +import cz.cvut.fel.aic.agentpolis.system.AgentPolisInitializer; import cz.cvut.fel.aic.alite.common.event.Event; import cz.cvut.fel.aic.alite.common.event.EventProcessor; -import cz.cvut.fel.aic.simod.StationsDispatcher; +import cz.cvut.fel.aic.simod.*; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.entity.DemandAgent; import cz.cvut.fel.aic.simod.entity.OnDemandVehicleState; import cz.cvut.fel.aic.simod.entity.vehicle.OnDemandVehicle; import cz.cvut.fel.aic.simod.event.OnDemandVehicleEvent; import cz.cvut.fel.aic.simod.event.OnDemandVehicleEventContent; +import cz.cvut.fel.aic.simod.mapVisualization.MapVisualiserModule; import cz.cvut.fel.aic.simod.ridesharing.insertionheuristic.DriverPlan; -import cz.cvut.fel.aic.simod.ridesharing.model.PlanAction; -import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionCurrentPosition; -import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionDropoff; -import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionPickup; -import cz.cvut.fel.aic.simod.ridesharing.model.PlanRequestAction; +import cz.cvut.fel.aic.simod.ridesharing.model.*; import cz.cvut.fel.aic.simod.statistics.PickupEventContent; import cz.cvut.fel.aic.simod.storage.PhysicalTransportVehicleStorage; +import cz.cvut.fel.aic.simod.traveltimecomputation.TravelTimeProvider; import cz.cvut.fel.aic.simod.visio.PlanLayerTrip; +import org.opengis.filter.PropertyIsGreaterThanOrEqualTo; + +import java.io.File; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -67,10 +78,30 @@ public class RideSharingOnDemandVehicle extends OnDemandVehicle{ private IdGenerator tripIdGenerator; + private WaitActivityFactory waitActivityFactory; + + private TravelTimeProvider travelTimeProvider; + + private DriveToTransferStationActivityFactory driveToTransferStationActivityFactory; + + public boolean tripAlreadyPlanned = false; + public DriverPlan getCurrentPlan() { currentPlan.updateCurrentPosition(getPosition()); return currentPlan; } + + public DriverPlan getCurrentPlanNoUpdate() { + return currentPlan; + } + + public void setCurrentPlan(DriverPlan driverPlan) { + List newPlan = new ArrayList<>(); + newPlan.add(currentPlan.plan.get(0)); + currentPlan.plan = newPlan; + currentPlan.updateCurrentPosition(getPosition()); + currentPlan.plan.addAll(driverPlan.plan); + } @@ -89,6 +120,9 @@ public RideSharingOnDemandVehicle( SimodConfig config, IdGenerator idGenerator, AgentpolisConfig agentpolisConfig, + WaitWithStopActivityFactory waitWithStopActivityFactory, + WaitActivityFactory waitActivityFactory, + DriveToTransferStationActivityFactory driveToTransferStationActivityFactory, @Assisted String vehicleId, @Assisted SimulationNode startPosition) { super( vehicleStorage, @@ -102,10 +136,16 @@ public RideSharingOnDemandVehicle( config, idGenerator, agentpolisConfig, + waitWithStopActivityFactory, + waitActivityFactory, vehicleId, startPosition); this.positionUtil = positionUtil; this.tripIdGenerator = tripIdGenerator; + + this.waitWithStopActivityFactory = waitWithStopActivityFactory; + this.waitActivityFactory = waitActivityFactory; + this.driveToTransferStationActivityFactory = driveToTransferStationActivityFactory; // empty plan LinkedList plan = new LinkedList<>(); @@ -127,11 +167,35 @@ public int getFreeCapacity(){ } public void replan(DriverPlan plan){ - currentPlan = plan; + currentPlan = plan; // The vehicle now waits, we have to start moving. if(state == OnDemandVehicleState.WAITING && plan.getLength() > 1){ driveToNextTask(); } + if (state == OnDemandVehicleState.WAITINGFORTRANSFER) { + // if top akce neni stejna jako currentTask (currentTask je cekani) + if (currentPlan.getNextTask() != currentTask) { + ((PlanActionWait) currentTask).setWaitingPaused(true); + ((PlanActionWait) currentTask).setWaitingPausedAt(timeProvider.getCurrentSimTime()); + ((WaitWithStop) getCurrentTopLevelActivity()).end(); + // ted potrebuji aktivitu ukoncit, ona ale stale bezi + driveToNextTask(); + } + // jinak pokracovat v aktivite + // todo priradit stop time + // a ukoncit aktivitu + // todo tam kde se spousti cekani, tak reagovat na start a stop time + // auto je v prubehu vykonavani wait akce + } + if (state == OnDemandVehicleState.DRIVING_TO_TRANSFER_STATION_TO_WAIT) { + if (currentPlan.getNextTask() != currentTask) { + // pokud se zmenila current task, tak ukoncim cestu na stanici + ((PhysicalVehicleDrive) getCurrentTopLevelActivity()).end(); + } + // jinak necham aktivitu pokracovat + +// driveToNextTask(); + } // SPECIAL CASES - we don't have to do anything and let the current Drive action continue. else if( @@ -151,17 +215,26 @@ else if( @Override protected void driveToDemandStartLocation() { // safety check that prevents request from being picked up twice because of the delayed pickup event - if(((PlanActionPickup) currentTask).request.isOnboard()){ - currentPlan.taskCompleted(); - driveToNextTask(); + if (currentTask instanceof PlanActionPickup) { + if(((PlanActionPickup) currentTask).request.isOnboard()){ + currentPlan.taskCompleted(); + driveToNextTask(); + } } +// else { +// if(((PlanActionPickupTransfer) currentTask).request.isOnboard()){ +// currentPlan.taskCompleted(); +// driveToNextTask(); +// } +// } + state = OnDemandVehicleState.DRIVING_TO_START_LOCATION; if(getPosition().id == currentTask.getPosition().id){ pickupAndContinue(); } else{ currentTrip = tripsUtil.createTrip(getPosition(), currentTask.getPosition(), vehicle); - DemandAgent demandAgent = ((PlanActionPickup) currentTask).getRequest().getDemandAgent(); +// DemandAgent demandAgent = ((PlanActionPickup) currentTask).getRequest().getDemandAgent(); driveFactory.runActivity(this, vehicle, currentTrip); } } @@ -170,7 +243,12 @@ protected void driveToDemandStartLocation() { protected void driveToTargetLocation() { state = OnDemandVehicleState.DRIVING_TO_TARGET_LOCATION; if(getPosition().id == currentTask.getPosition().id){ - dropOffAndContinue(); + if (currentTask instanceof PlanActionDropoff) { + dropOffAndContinue(); + } else if (currentTask instanceof PlanActionDropoffTransfer) { +// dropoffTransferAndContinue(); + dropOffAndContinue(); + } } else{ currentTrip = tripsUtil.createTrip(getPosition(), currentTask.getPosition(), vehicle); @@ -192,25 +270,70 @@ protected void driveToNearestStation() { } } + @Override + public void finishedWaiting(boolean wasStopped) { + if (wasStopped) { +// driveToNextTask(); + } else { + currentPlan.taskCompleted(); + currentTask = currentPlan.getNextTask(); + if (currentTask instanceof PlanActionWait) { + startWaiting(); + } else if (currentTask instanceof PlanActionPickup || currentTask instanceof PlanActionPickupTransfer) { + pickupAndContinue(); + } else if (currentTask instanceof PlanActionDropoff || currentTask instanceof PlanActionDropoffTransfer) { + dropOffAndContinue(); + } + } + } + + @Override + public void startWaiting() { + // pokud je auto jinde nez ve stanici, tak chcu vytvorit trip ke stanici, spustit jizdu a az dojede, + // tak spustit cekani, ktere je kratsi o cas dojezdu na stanici + state = OnDemandVehicleState.WAITINGFORTRANSFER; + if (currentTask instanceof PlanActionWait) { + long substractTime = 0; + if (((PlanActionWait) currentTask).isWaitingPaused()) { + substractTime = ((PlanActionWait) currentTask).getWaitingPausedAt() - ((PlanActionWait) currentTask).getWaitingStartedAt(); + } + ((PlanActionWait) currentTask).setWaitingStarted(true); + ((PlanActionWait) currentTask).setWaitingStartedAt(timeProvider.getCurrentSimTime()); + ((PlanActionWait) currentTask).setWaitingPaused(false); + long waitTime = ((PlanActionWait) currentTask).getWaitTime(); + waitWithStopActivityFactory.runActivity(this, waitTime - substractTime); + } else { + driveToNextTask(); + } + + + } + @Override public void finishedDriving(boolean wasStopped) { - logTraveledDistance(wasStopped); - + if(wasStopped){ driveToNextTask(); } else{ switch(state){ + // start location agenta - pickup misto case DRIVING_TO_START_LOCATION: + logTraveledDistance(wasStopped); pickupAndContinue(); break; + // dropoff misto agenta case DRIVING_TO_TARGET_LOCATION: + logTraveledDistance(wasStopped); dropOffAndContinue(); break; + // stanice auta case DRIVING_TO_STATION: + logTraveledDistance(wasStopped); finishDrivingToStation(); break; case REBALANCING: + logTraveledDistance(wasStopped); finishRebalancing(); break; } @@ -238,26 +361,83 @@ private void driveToNextTask() { if(currentTask instanceof PlanActionPickup){ driveToDemandStartLocation(); } - else{ + else if(currentTask instanceof PlanActionWait) { + if (currentTask.getPosition() == this.getPosition()) { + startWaiting(); + } else { + // drive to station and begin waiting + if (this.tripAlreadyPlanned) { + return; + } + // else make new trip and start driving with edited wait time + VehicleTrip newTrip = tripsUtil.createTrip(this.getPosition(), currentTask.getPosition(), vehicle); + this.currentTrip = newTrip; + state = OnDemandVehicleState.DRIVING_TO_TRANSFER_STATION_TO_WAIT; +// driveFactory.create(this, vehicle, currentTrip).run(); + driveToTransferStationActivityFactory.create(this, vehicle, currentTrip).run(); + this.tripAlreadyPlanned = true; + + + + } + + } + else if(currentTask instanceof PlanActionPickupTransfer) { + driveToDemandStartLocation(); + } + else if(currentTask instanceof PlanActionDropoffTransfer) { + driveToTargetLocation(); + } + else // dropoff + { driveToTargetLocation(); } } } private void pickupAndContinue() { +// state = OnDemandVehicleState.DRIVING_TO_TARGET_LOCATION; try { - DemandAgent demandAgent = ((PlanActionPickup) currentTask).getRequest().getDemandAgent(); - if(demandAgent.isDropped()){ - long currentTime = timeProvider.getCurrentSimTime(); - long droppTime = demandAgent.getDemandTime() + config.ridesharing.maxProlongationInSeconds * 1000; - throw new Exception( - String.format("Demand agent %s cannot be picked up, he is already dropped! Current simulation " - + "time: %s, dropp time: %s", demandAgent, currentTime, droppTime)); + DemandAgent demandAgent; + if (currentTask instanceof PlanActionPickup) { + demandAgent = ((PlanActionPickup) currentTask).getRequest().getDemandAgent(); + if(demandAgent.isDropped()){ + long currentTime = timeProvider.getCurrentSimTime(); + long droppTime = demandAgent.getDemandTime() + config.ridesharing.maxProlongationInSeconds * 1000; + throw new Exception( + String.format("Demand agent %s cannot be picked up, he is already dropped! Current simulation " + + "time: %s, dropp time: %s", demandAgent, currentTime, droppTime)); + } + demandAgent.tripStarted(this); } - demandAgent.tripStarted(this); + else if (currentTask instanceof PlanActionPickupTransfer) { + demandAgent = ((PlanActionPickupTransfer) currentTask).getRequest().getDemandAgent(); + if(demandAgent.isDropped()){ + long currentTime = timeProvider.getCurrentSimTime(); + long droppTime = demandAgent.getDemandTime() + config.ridesharing.maxProlongationInSeconds * 1000; + throw new Exception( + String.format("Demand agent %s cannot be picked up, he is already dropped! Current simulation " + + "time: %s, dropp time: %s", demandAgent, currentTime, droppTime)); + } + demandAgent.tripRePaused(this); + } else { + // should not be + throw new Exception(String.format("Wrong action order in plan")); + + } + +// if(demandAgent.isDropped()){ +// long currentTime = timeProvider.getCurrentSimTime(); +// long droppTime = demandAgent.getDemandTime() + config.ridesharing.maxProlongationInSeconds * 1000; +// throw new Exception( +// String.format("Demand agent %s cannot be picked up, he is already dropped! Current simulation " +// + "time: %s, dropp time: %s", demandAgent, currentTime, droppTime)); +// } +// demandAgent.tripStarted(this); vehicle.pickUp(demandAgent); // statistics TODO demand tirp? + // demandTrip = tripsUtil.createTrip(currentTask.getDemandAgent().getPosition().id, // currentTask.getLocation().id, vehicle); // demand trip length 0 - need to find out where the statistic is used, does it make sense with rebalancing? @@ -274,8 +454,16 @@ private void pickupAndContinue() { } private void dropOffAndContinue() { - DemandAgent demandAgent = ((PlanActionDropoff) currentTask).getRequest().getDemandAgent(); - demandAgent.tripEnded(); + DemandAgent demandAgent = null; + if (currentTask instanceof PlanActionDropoff) { + demandAgent = ((PlanActionDropoff) currentTask).getRequest().getDemandAgent(); + demandAgent.tripEnded(); + } else + { + demandAgent = ((PlanActionDropoffTransfer) currentTask).getRequest().getDemandAgent(); + demandAgent.tripPaused(); + } + vehicle.dropOff(demandAgent); // statistics @@ -298,6 +486,10 @@ public VehicleTrip getCurrentTripPlan() { return currentTrip; } + public PlanAction getCurrentTask() { + return currentTask; + } + public boolean hasFreeCapacity() { return getFreeCapacity() > 0; } diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingDispatcher.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingDispatcher.java index edf88420..95562631 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingDispatcher.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingDispatcher.java @@ -253,13 +253,16 @@ public void handleEvent(Event event) { if(eventType == OnDemandVehicleEvent.PICKUP){ OnDemandVehicleEventContent eventContent = (OnDemandVehicleEventContent) event.getContent(); PlanComputationRequest request = requestsMapByDemandAgents.get(eventContent.getDemandId()); - if(!waitingRequests.remove(request)){ - try { - throw new SimodException("Request picked up but it is not present in the waiting request queue!"); - } catch (Exception ex) { - Logger.getLogger(VehicleGroupAssignmentSolver.class.getName()).log(Level.SEVERE, null, ex); + if (waitingRequests.contains(request)) { + if (!waitingRequests.remove(request)) { + try { + throw new SimodException("Request picked up but it is not present in the waiting request queue!"); + } catch (Exception ex) { + Logger.getLogger(VehicleGroupAssignmentSolver.class.getName()).log(Level.SEVERE, null, ex); + } } - }; + ; + } request.setOnboard(true); } } diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingOnDemandVehicleFactory.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingOnDemandVehicleFactory.java index a44247de..939dbe61 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingOnDemandVehicleFactory.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/RidesharingOnDemandVehicleFactory.java @@ -24,10 +24,11 @@ import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; import cz.cvut.fel.aic.agentpolis.simmodel.IdGenerator; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; import cz.cvut.fel.aic.agentpolis.simulator.visualization.visio.VisioPositionUtil; import cz.cvut.fel.aic.alite.common.event.EventProcessor; -import cz.cvut.fel.aic.simod.StationsDispatcher; +import cz.cvut.fel.aic.simod.*; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.entity.vehicle.OnDemandVehicle; import cz.cvut.fel.aic.simod.entity.vehicle.OnDemandVehicleFactory; @@ -39,19 +40,27 @@ */ @Singleton public class RidesharingOnDemandVehicleFactory extends OnDemandVehicleFactory{ + + WaitWithStopActivityFactory waitWithStopActivityFactory; + + DriveToTransferStationActivityFactory driveToTransferStationActivityFactory; @Inject public RidesharingOnDemandVehicleFactory( - PhysicalTransportVehicleStorage vehicleStorage, - TripsUtil tripsUtil, + PhysicalTransportVehicleStorage vehicleStorage, + TripsUtil tripsUtil, StationsDispatcher onDemandVehicleStationsCentral, - VisioPositionUtil positionUtil, - EventProcessor eventProcessor, - StandardTimeProvider timeProvider, - IdGenerator rebalancingIdGenerator, + VisioPositionUtil positionUtil, + EventProcessor eventProcessor, + StandardTimeProvider timeProvider, + IdGenerator rebalancingIdGenerator, SimodConfig config, IdGenerator idGenerator, - AgentpolisConfig agentpolisConfig) { + AgentpolisConfig agentpolisConfig, + WaitWithStopActivityFactory waitWithStopActivityFactory, + WaitActivityFactory waitActivityFactory, + DriveToTransferStationActivityFactory driveToTransferStationActivityFactory + ) { super( vehicleStorage, tripsUtil, @@ -60,9 +69,14 @@ public RidesharingOnDemandVehicleFactory( eventProcessor, timeProvider, rebalancingIdGenerator, - config, + config, + waitWithStopActivityFactory, + waitActivityFactory, idGenerator, agentpolisConfig); + this.waitWithStopActivityFactory = waitWithStopActivityFactory; + this.driveToTransferStationActivityFactory = driveToTransferStationActivityFactory; + } @Override @@ -80,8 +94,12 @@ public OnDemandVehicle create(String vehicleId, SimulationNode startPosition) { config, idGenerator, agentpolisConfig, + waitWithStopActivityFactory, + waitActivityFactory, + driveToTransferStationActivityFactory, vehicleId, - startPosition); + startPosition) + ; } diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/GreedyTASeTNoFreezeSolver.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/GreedyTASeTNoFreezeSolver.java new file mode 100644 index 00000000..bad8e87d --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/GreedyTASeTNoFreezeSolver.java @@ -0,0 +1,1503 @@ +package cz.cvut.fel.aic.simod.ridesharing.greedyTASeT; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import cz.cvut.fel.aic.agentpolis.config.AgentpolisConfig; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.VehicleTrip; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.TimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.AgentPolisEntity; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.utils.PositionUtil; +import cz.cvut.fel.aic.alite.common.event.Event; +import cz.cvut.fel.aic.alite.common.event.EventHandler; +import cz.cvut.fel.aic.alite.common.event.EventProcessor; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; +import cz.cvut.fel.aic.simod.config.SimodConfig; +import cz.cvut.fel.aic.simod.event.OnDemandVehicleEvent; +import cz.cvut.fel.aic.simod.ridesharing.DARPSolver; +import cz.cvut.fel.aic.simod.ridesharing.DroppedDemandsAnalyzer; +import cz.cvut.fel.aic.simod.ridesharing.PlanCostProvider; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.insertionheuristic.DriverPlan; +import cz.cvut.fel.aic.simod.ridesharing.model.*; +import cz.cvut.fel.aic.simod.storage.OnDemandVehicleStorage; +import cz.cvut.fel.aic.simod.storage.OnDemandvehicleStationStorage; +import cz.cvut.fel.aic.simod.traveltimecomputation.TravelTimeProvider; +import org.jgrapht.alg.util.Pair; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Singleton +public class GreedyTASeTNoFreezeSolver extends DARPSolver implements EventHandler { + + + private final TypedSimulation eventProcessor; + + private final SimodConfig config; + + private final TimeProvider timeProvider; + + private final PositionUtil positionUtil; + + private final DroppedDemandsAnalyzer droppedDemandsAnalyzer; + + private final OnDemandvehicleStationStorage onDemandvehicleStationStorage; + + private final double maxDistance = 100; + + private final double maxDistanceSquared = 10000; + + private final int maxDelayTime = 10; + + private List transferPoints; + + protected final DefaultPlanComputationRequest.DefaultPlanComputationRequestFactory requestFactory; + + private Map planMap; + + + + + @Inject + public GreedyTASeTNoFreezeSolver( + OnDemandVehicleStorage vehicleStorage, + TravelTimeProvider travelTimeProvider, + PlanCostProvider travelCostProvider, + DefaultPlanComputationRequest.DefaultPlanComputationRequestFactory requestFactory, + TypedSimulation eventProcessor, + SimodConfig config, + TimeProvider timeProvider, + PositionUtil positionUtil, + DroppedDemandsAnalyzer droppedDemandsAnalyzer, + OnDemandvehicleStationStorage onDemandvehicleStationStorage, + AgentpolisConfig agentpolisConfig) { + + super(vehicleStorage, travelTimeProvider, travelCostProvider, requestFactory); + this.eventProcessor = eventProcessor; + this.config = config; + this.timeProvider = timeProvider; + this.positionUtil = positionUtil; + this.droppedDemandsAnalyzer = droppedDemandsAnalyzer; + this.onDemandvehicleStationStorage = onDemandvehicleStationStorage; + this.requestFactory = requestFactory; + + setEventHandeling(); + } + + public void setTransferPoints(List transferPoints) { + this.transferPoints = transferPoints; + } + + @Override + public EventProcessor getEventProcessor() { + return eventProcessor; + } + + @Override + public void handleEvent(Event event) { + + } + + + private void setEventHandeling() { + List typesToHandle = new LinkedList<>(); + + typesToHandle.add(OnDemandVehicleEvent.PICKUP); + eventProcessor.addEventHandler(this, typesToHandle); + } + + /** + * Transfer-allowed scheduling solver + * @return Map + */ + @Override + public Map solve(List newRequests, List waitingRequests) { + Map planMap = new ConcurrentHashMap<>(); + Map planMapReturn = new ConcurrentHashMap<>(); + List taxis = new ArrayList<>(); + + for(AgentPolisEntity tVvehicle: vehicleStorage.getEntitiesForIteration()) { + RideSharingOnDemandVehicle vehicle = (RideSharingOnDemandVehicle) tVvehicle; + taxis.add(vehicle); + } + + planMap = dispatch(taxis, newRequests); + + + + return planMap; + } + + /** + * Transfer-allowed scheduling function + * @return + */ + private Map dispatch(List taxis, List requests) { + // because all passengers allow ridesharing, only greedy taset will be called + List carpoolAcceptingTaxis = taxis; + List carpoolAcceptingPassengers = requests; + Map map = heuristics(carpoolAcceptingTaxis, carpoolAcceptingPassengers); + return map; + } + + + private boolean isWithTransfer(DriverPlan plan) { + for(PlanAction action : plan.plan) { + if(action instanceof PlanRequestAction) { + if (action instanceof PlanActionDropoffTransfer || action instanceof PlanActionPickupTransfer || action instanceof PlanActionWait) { + return true; + } + } + } + return false; + } + + private int findLastPickupIndex(DriverPlan plan) { + int index = -1; + for (int i = 0; i < plan.getLength(); i++) { + if (plan.plan.get(i) instanceof PlanActionPickup) { + index = i; + } + } + return index; + } + + private int findLastPickupIndexList(List plan) { + int index = -1; + for (int i = 0; i < plan.size(); i++) { + if (plan.get(i) instanceof PlanActionPickup) { + index = i; + } + } + return index; + } + + private int findLastTransferActionIndex(DriverPlan plan) { + int index = -1; + for (int i = 0; i < plan.getLength(); i++) { + if (plan.plan.get(i) instanceof PlanActionDropoffTransfer || plan.plan.get(i) instanceof PlanActionPickupTransfer || plan.plan.get(i) instanceof PlanActionWait) { + index = i; + } + } + return index; + } + + private long countTimeToNewPickup(RideSharingOnDemandVehicle taxi, PlanComputationRequest request, List requestsOnBoard) { + DriverPlan taxiPlan; + if (planMap.containsKey(taxi)) { + taxiPlan = planMap.get(taxi); + } else { + taxiPlan = taxi.getCurrentPlanNoUpdate(); + } + if (isWithTransfer(taxiPlan)) { + // nekdo prestupuje + int indexLastTransferAction = findLastTransferActionIndex(taxiPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (taxiPlan.plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) taxiPlan.plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, taxiPlan.plan.get(q).getPosition()); + } + previousPos = taxiPlan.plan.get(q).getPosition(); + } + // ted potrebuju najit posledni pickup ve zbyvajicim driver planu po prestupu + List segmentAfterTransfer = taxiPlan.plan.subList(indexLastTransferAction+1, taxiPlan.plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = taxiPlan.plan.get(taxiPlan.plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + SimulationNode newPickupFrom = request.getFrom(); + long timeToNewPick = travelTimeProvider.getExpectedTravelTime(previousPos2, newPickupFrom); + long estimatedArrivalToPickup = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToNewPick; + long maxTime = request.getMaxDropoffTime() * 1000; + if (estimatedArrivalToPickup > maxTime) { + return Long.MAX_VALUE; + } + return estimatedArrivalToPickup; + } + else { + //neprestupuje nikdo + int indexLastPickup = findLastPickupIndex(taxiPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, taxiPlan.plan.get(q).getPosition()); + previousPos = taxiPlan.plan.get(q).getPosition(); + } + SimulationNode newPickupFrom = request.getFrom(); + long timeToNewPick = travelTimeProvider.getExpectedTravelTime(previousPos, newPickupFrom); + long estimatedArrivalToNewPickup = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToNewPick; + long maxTime = request.getMaxDropoffTime() * 1000; + if (estimatedArrivalToNewPickup > maxTime) { + return Long.MAX_VALUE; + } + return estimatedArrivalToNewPickup; + } + } + + /** + * Greedy TASeT heuristics function + * @return + */ + private Map heuristics(List taxis, List requests) { + //transfer points = charging stations + List transferPoints = this.transferPoints; + + //lookup table LT - LT [t][k] stores the earliest arrival time for taxi k to charging station t without violating the tolerable delay for k’s current passengers + int stationsCount = transferPoints.size(); + int taxisCount = taxis.size(); + long[][] LT = new long[stationsCount][taxisCount]; + //fill the LT table + for (int i = 0; i < taxisCount; i++) { + RideSharingOnDemandVehicle taxi = taxis.get(i); + SimulationNode taxiPosition = taxis.get(i).getPosition(); + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan = taxi.getCurrentPlanNoUpdate(); + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + // kolik lidi je prave ted v aute + boolean taxiFree = true; + int taxiCapacity = taxi.getCapacity(); + if (requestsOnBoardSet.size() >= taxiCapacity) { + taxiFree = false; + } + for(int j = 0; j < stationsCount; j++) { + //check if taxi has free seat + if (!taxiFree) { + LT[j][i] = Long.MAX_VALUE; + } + else { + if (isWithTransfer(taxi.getCurrentPlanNoUpdate())) { + // nekdo prestupuje + int indexLastTransferAction = findLastTransferActionIndex(taxi.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (taxi.getCurrentPlanNoUpdate().plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) taxi.getCurrentPlanNoUpdate().plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + } + previousPos = taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + // ted potrebuju najit posledni pickup ve zbyvajicim driver planu po prestupu + List segmentAfterTransfer = taxi.getCurrentPlanNoUpdate().plan.subList(indexLastTransferAction+1, taxi.getCurrentPlanNoUpdate().plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = taxi.getCurrentPlanNoUpdate().plan.get(taxi.getCurrentPlanNoUpdate().plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToStation; + LT[j][i] = estimatedArrivalToStation; + // zkontrolovat, zda arrival je v pohode z hlediska delay - kontroluju pro requesty po ukonceni prestupu + Set requestsInSegmentSet = new HashSet<>(); + for(PlanAction action : segmentAfterTransfer) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsInSegmentSet.add(requestAction.request); + } + } + List requestsInSegment = new ArrayList<>(requestsInSegmentSet); + for (PlanComputationRequest request : requestsInSegment) { + long maxTime = request.getMaxDropoffTime() * 1000; + if (LT[j][i] > maxTime) { + LT[j][i] = Long.MAX_VALUE; + break; + } + } + } + else { + //neprestupuje nikdo + int indexLastPickup = findLastPickupIndex(taxi.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + previousPos = taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToStation; + LT[j][i] = estimatedArrivalToStation; + // zkontrolovat, zda arrival je v pohode z hlediska delay + for (PlanComputationRequest request : requestsOnBoard) { + long maxTime = request.getMaxDropoffTime() * 1000; + if (LT[j][i] > maxTime) { + LT[j][i] = Long.MAX_VALUE; + break; + } + } + } + } + } + } + + //we rank the requests in descending order by the number of taxis that are possible to pick them up in time (without considering transfer or destination) + //get possible taxis for every request and number of possible taxis + int[] possiblePickupTaxisCounts = new int[requests.size()]; + int i = 0; + Map> possiblePickupTaxisMap = new HashMap<>(); + for(PlanComputationRequest request : requests) { + int counter = 0; + List possiblePickupTaxisOneRequest = new ArrayList<>(); + for(RideSharingOnDemandVehicle t : taxis) { + if (canServeRequestTASeT2(t, request)) { + counter++; + possiblePickupTaxisOneRequest.add(t); + } + } + possiblePickupTaxisCounts[i] = counter; + possiblePickupTaxisMap.put(request, possiblePickupTaxisOneRequest); + i++; + } + + + //sort R by the number of possible pickup taxis + List requestsCopy = new ArrayList<>(requests); + requests.sort(Comparator.comparing(x -> possiblePickupTaxisCounts[requestsCopy.indexOf(x)])); + //order to descending order + Collections.reverse(requests); + + planMap = new ConcurrentHashMap<>(); + + + for(PlanComputationRequest request : requests) { + List>, List>> templistP = new ArrayList<>(); + // list ve kterem je list dvojic - list dvojic, protoze dvojice muze byt jen jedna (neni prestup) nebo dve (je prestup) + List delays = new ArrayList<>(); + List transferTimes = new ArrayList<>(); + List canPickupRequestTaxis = possiblePickupTaxisMap.get(request); + for (RideSharingOnDemandVehicle taxi : canPickupRequestTaxis) { + List posbitnry = findPlanWithNoTransferNew(request, taxi); + // pokud neexistuje ani jeden validni itinerar, tak je posbitnry null + // tehdy ho nebudu pridavat do templistu + if (posbitnry != null) { + if (checkValidItinerary(posbitnry, taxi)) { + List> tmp = new ArrayList<>(); + List tmpVehs = new ArrayList<>(); + tmpVehs.add(taxi); + tmp.add(posbitnry); + Pair>, List> pair = new Pair<>(tmp, tmpVehs); + templistP.add(pair); + long minimalArrivalTime = timeProvider.getCurrentSimTime() + travelTimeProvider.getExpectedTravelTime(request.getFrom(), request.getTo()); + HashMap dropoffs = getEstimatedTimesOfDropoff(posbitnry, taxi); + long realArrivalTime = dropoffs.get(request); + long delay = realArrivalTime - minimalArrivalTime; + delays.add(delay); + transferTimes.add((long) 0); + } + } + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan; + if (planMap.containsKey(taxi)) { + actualPlan = planMap.get(taxi); + } else { + actualPlan = taxi.getCurrentPlanNoUpdate(); + } + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + + long timeToNewPickup = countTimeToNewPickup(taxi, request, requestsOnBoard); + int stationIndex = 0; + for (SimulationNode station : transferPoints) { + // je stanice potencialne vhodna pro prestup? + if (timeToNewPickup + travelTimeProvider.getExpectedTravelTime(request.getFrom(), station) > + request.getMaxDropoffTime() * 1000 - travelTimeProvider.getExpectedTravelTime(station, request.getTo())) { + continue; + } + + // find k' = taxis that taxi k can transfer to at station + for (int k = 0; k < taxisCount; k++) { + // minimalni cas na druhy usek + //not possible to transfer to + if (LT[stationIndex][k] == Long.MAX_VALUE) { + continue; + } else if(LT[stationIndex][k] > request.getMaxDropoffTime() * 1000 - travelTimeProvider.getExpectedTravelTime(station, request.getTo())) { + continue; + } else if(taxi.equals(taxis.get(k))) { + continue; + } else if (station == request.getTo()) { + continue; + } else if (station == request.getFrom()) { + continue; + } else { + // split request to two requests with transfer point + long travelTimeFromStationToDest = travelTimeProvider.getExpectedTravelTime(station, request.getTo()); + int maxDropOffTime = request.getMaxDropoffTime() - (int) Math.round(travelTimeFromStationToDest / 1000.0); + PlanActionDropoffTransfer dropoffActionTransfer = new PlanActionDropoffTransfer(request, station, maxDropOffTime); + PlanActionPickupTransfer pickupActionTransfer = new PlanActionPickupTransfer(request, station, maxDropOffTime); + + List itnryp1 = findPlanWithNoTransferActionsNew(request.getPickUpAction(), dropoffActionTransfer, taxi); // pro auto + List itnryp2 = findPlanWithNoTransferActionsNew(pickupActionTransfer, request.getDropOffAction(), taxis.get(k)); + if (itnryp1 == null || itnryp2 == null) { + // neexistuje plan + continue; + } + Pair>, Long> p = createChargePlanNoNewRequests(itnryp1, itnryp2, taxi, taxis.get(k), request); + if (p == null) { + // neni zadny validni plan a tedy neni mozne prestoupit, takze neudelam nic + continue; + } else { + List> itnrys = p.getFirst(); + itnryp1 = itnrys.get(0); + itnryp2 = itnrys.get(1); + List> tmp2 = new ArrayList<>(); + tmp2.add(itnryp1); + tmp2.add(itnryp2); + List tmpVehs2 = new ArrayList<>(); + tmpVehs2.add(taxi); + tmpVehs2.add(taxis.get(k)); + Pair>, List> pair2 = new Pair<>(tmp2, tmpVehs2); + templistP.add(pair2); + // travel time daneho requestu s prestupem spocitam jako: + // cas nez prvni auto dojede pro request a vyzvedne ho + // + cas jizdy v prvnim vozidle + // + pokud druhe auto prijede pozdeji nez to prvni tak k tomu prictu rozdil + // + doba jizdy v druhem aute + HashMap drops = getEstimatedTimesOfDropoff(itnryp2, taxis.get(k)); + if (drops == null) { + // not valid + delays.add(Long.MAX_VALUE); + transferTimes.add((long) -1); + continue; + } + long minimalArrivalTime = timeProvider.getCurrentSimTime() + travelTimeProvider.getExpectedTravelTime(request.getFrom(), request.getTo()); + long realArrivalTime = drops.get(request); + long delay = realArrivalTime - minimalArrivalTime; + delays.add(delay); + long transferTime = p.getSecond(); + transferTimes.add(transferTime); + } + } + } + stationIndex++; + } + } + List listTransferPlans = new ArrayList<>(); + for (int j = 0; j < templistP.size(); j++) { + TransferPlan t = new TransferPlan(transferTimes.get(j), delays.get(j), templistP.get(j)); + listTransferPlans.add(t); + } + listTransferPlans.sort(TransferPlan::compareByDelay); + + //vezmu hornich beta procent + double beta = 0.2; + int numOfTaken = (int) (delays.size() * beta); + if (numOfTaken == 0) { + numOfTaken = 1; + } + List sublistTransferPlans = new ArrayList<>(); + for (int q = 0; q < numOfTaken; q++) + { + if(!listTransferPlans.isEmpty()) { + sublistTransferPlans.add(listTransferPlans.get(q)); + } + } + sublistTransferPlans.sort(TransferPlan::compareByTransferTime); + Collections.reverse(sublistTransferPlans); + + // ted mam serazene transferTimes + if (sublistTransferPlans.isEmpty()) { + continue; + } + else + { + // ziskam entry ktery je nejlepsi podle heuristiky + if (sublistTransferPlans.get(0).delay == Long.MAX_VALUE || sublistTransferPlans.get(0).trasferTime < 0) { + continue; + } + Pair>, List> key = sublistTransferPlans.get(0).pair; + List> plansForVehicles = key.getFirst(); + List vehicles = key.getSecond(); + for (int q = 0; q < vehicles.size(); q++) { + List vehPlan = plansForVehicles.get(q); + List planWithPos = new ArrayList<>(); + planWithPos.add(vehicles.get(q).getCurrentPlanNoUpdate().plan.get(0)); + planWithPos.addAll(vehPlan); + DriverPlan dp = new DriverPlan(planWithPos, 0, 0); + planMap.put(vehicles.get(q), dp); + } + } + + // update k, k′ and LT + //update LT - not efficient + for (int z = 0; z < taxisCount; z++) { + RideSharingOnDemandVehicle taxi = taxis.get(z); + SimulationNode taxiPosition = taxis.get(z).getPosition(); + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan; + if (planMap.containsKey(taxis.get(z))) { + actualPlan = planMap.get(taxi); + } else { + actualPlan = taxi.getCurrentPlanNoUpdate(); + } + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + // kolik lidi je prave ted v aute + boolean taxiFree = true; + int taxiCapacity = taxi.getCapacity(); + if (requestsOnBoardSet.size() >= taxiCapacity) { + taxiFree = false; + } + for(int j = 0; j < stationsCount; j++) { + //check if taxi has free seat + if (!taxiFree) { + LT[j][z] = Long.MAX_VALUE; + } else { + if (isWithTransfer(actualPlan)) { + // nekdo prestupuje + int indexLastTransferAction = findLastTransferActionIndex(actualPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (actualPlan.plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) actualPlan.plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, actualPlan.plan.get(q).getPosition()); + } + previousPos = actualPlan.plan.get(q).getPosition(); + } + // ted potrebuju najit posledni pickup ve zbyvajicim driver planu po prestupu + List segmentAfterTransfer = actualPlan.plan.subList(indexLastTransferAction + 1, actualPlan.plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = actualPlan.plan.get(actualPlan.plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos2, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToStation; + LT[j][z] = estimatedArrivalToStation; + // zkontrolovat, zda arrival je v pohode z hlediska delay - kontroluju pro requesty po ukonceni prestupu + Set requestsInSegmentSet = new HashSet<>(); + for (PlanAction action : segmentAfterTransfer) { + if (action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsInSegmentSet.add(requestAction.request); + } + } + List requestsInSegment = new ArrayList<>(requestsInSegmentSet); + for (PlanComputationRequest r : requestsInSegment) { + long maxTime = r.getMaxDropoffTime() * 1000; + if (LT[j][z] > maxTime) { + LT[j][z] = Long.MAX_VALUE; + break; + } + } + } else { + //neprestupuje nikdo + int indexLastPickup = findLastPickupIndex(actualPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, actualPlan.plan.get(q).getPosition()); + previousPos = actualPlan.plan.get(q).getPosition(); + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToStation; + LT[j][z] = estimatedArrivalToStation; + // zkontrolovat, zda arrival je v pohode z hlediska delay + for (PlanComputationRequest r : requestsOnBoard) { + long maxTime = r.getMaxDropoffTime() * 1000; + if (LT[j][z] > maxTime) { + LT[j][z] = Long.MAX_VALUE; + break; + } + } + } + } + } + } + } + return planMap; + } + + private boolean checkValidItinerary(List itinerary, RideSharingOnDemandVehicle vehicle) { + SimulationNode previousDestination = vehicle.getPosition(); + boolean ret = true; + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + previousDestination = vehicle.getPosition(); + + // podivam se na trip plan + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + // protoze je size trip planu 0, tak to znamena, ze uz je auto rozjete do posledni destinace tripu + // je ale mozne, ze tam jeste nedojelo, tedy jeho pozice je jina nez pozice posledniho bodu v trip planu + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time += timeToFinishEdge; + + for (PlanAction action : itinerary) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxPickupTime()*1000)) { + //not valid itinerary + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxDropoffTime()*1000)) { + //not valid itinerary + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + } + } + } + return ret; + } + + private Pair>, Long> createChargePlanNoNewRequests(List itnryp1, List itnryp2, RideSharingOnDemandVehicle veh1, RideSharingOnDemandVehicle veh2, PlanComputationRequest request) { + long time1 = 0; + long timeToFinishEdge1 = 0; + SimulationNode previousDestination = veh1.getPosition(); + + // podivam se na trip plan + if (veh1.getCurrentTripPlan() != null) { + // pokud je get size u current trip planu vetsi nez nula, tak get first location vybere nejblizsi node kde se auto muze zastavit a je to spravne + // pokud je ale delka current trip nula, tak vyberu posledni akci z tripu - auto tam jeste nemuselo dojet a to zpusobuje chybku + // proto demand 298 neni vyzvednut vcas, protoze se tam neuvazuje cas ktere auto potrebuje na dokonceni trupu + if (veh1.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh1.getCurrentTripPlan().getLastLocation(); + // protoze je size trip planu 0, tak to znamena, ze uz je auto rozjete do posledni destinace tripu + // je ale mozne, ze tam jeste nedojelo, tedy jeho pozice je jina nez pozice posledniho bodu v trip planu + timeToFinishEdge1 += travelTimeProvider.getTravelTime(veh1, stopLoc); + previousDestination = stopLoc; + } + else if (veh1.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh1.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge1 += travelTimeProvider.getTravelTime(veh1, currLoc); + } + if (currLoc == veh1.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time1 = timeToFinishEdge1; + + // nemusim pricitat current sim time, protoze budu od sebe oba casy odecitat, jde mi jen o jejich rozdil + long transferTime = 0; + //expected arrival time of first car + for (PlanAction action : itnryp1) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (dropoffTransfer.request == request) { + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time1 = time1 + wait.getWaitTime(); + } + } + } + // expected arrival of second car + int indexPickupSecondCar = 0; + long time2 = 0; + long timeToFinishEdge2 = 0; + PlanActionPickupTransfer pickup = null; + previousDestination = veh2.getPosition(); + + // podivam se na trip plan + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + // protoze je size trip planu 0, tak to znamena, ze uz je auto rozjete do posledni destinace tripu + // je ale mozne, ze tam jeste nedojelo, tedy jeho pozice je jina nez pozice posledniho bodu v trip planu + timeToFinishEdge2 += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge2 += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time2 = timeToFinishEdge2; + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (pickupTransfer.request == request) { + pickup = pickupTransfer; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time2 = time2 + wait.getWaitTime(); + } + } + indexPickupSecondCar++; + } + long waitTime = time2 - time1; // k wait time prictu navic rezervu + + // pokud je zaporny, tak druhe auto bude muset cekat waitTime dlouho + // pokud je kladny, tak to znamena ze prvni auto prijede drive nez druhe - bude cekat cestujici + + boolean valid = true; + long maxTransferTime; + +// pridat wait i pro druhe auto tam, kde je rozdil mensi nez 5 s +// aby tam byla rezerva + if (waitTime > 0 && waitTime < 2000) { + maxTransferTime = time1; + // ceka aspon 2 s + long newWait = 2000 - waitTime; + setMaxTransferTimeForDropoffTransferAction(maxTransferTime, itnryp1, request); + PlanActionWait waitAction = new PlanActionWait(request, pickup.getPosition(), pickup.getMaxTime(), newWait); + transferTime = newWait; + itnryp2.add(indexPickupSecondCar, waitAction); + + //check tolerable delay for passengers in vehicle2 + long time = 0; + previousDestination = veh2.getPosition(); + // podivam se na trip plan + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + // protoze je size trip planu 0, tak to znamena, ze uz je auto rozjete do posledni destinace tripu + // je ale mozne, ze tam jeste nedojelo, tedy jeho pozice je jina nez pozice posledniho bodu v trip planu + time += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } + else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + time += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= pcq.getMaxPickupTime()*1000)) { + //not valid itinerary - check new driver plan + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= pcq.getMaxDropoffTime()*1000)) { + //not valid itinerary - check new driver plan + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + previousDestination = wait.getPosition(); + } else if (action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer p = (PlanActionPickupTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= p.getMaxTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer p = (PlanActionDropoffTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= p.getMaxTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } + } + } + } + // pridam wait time do planu pro druhe auto pokud je wait time zaporny + // pozor, pokud bych chtela smazat casovou rezervu 5 s, tak je tam nekde problem s wait akci s casem 0 + // - tak na to by bylo potreba udelat zvlast podminku a nejaky minimalni wait time tam nastavit, aby bylo zajistene poradi pri pruchodu algoritmem + else if (waitTime <= 0) { + maxTransferTime = time1; + // pridat 1000 je malo, ale 2000 dostacuje + waitTime = waitTime - 2000; + setMaxTransferTimeForDropoffTransferAction(maxTransferTime, itnryp1, request); + //transfer time je -waitTime + // pickup by nemel byt null protoze se nastavi v predeslem loopu + assert pickup != null; + PlanActionWait waitAction = new PlanActionWait(request, pickup.getPosition(), pickup.getMaxTime(), -waitTime); + transferTime = -waitTime; + itnryp2.add(indexPickupSecondCar, waitAction); + + //check tolerable delay for passengers in vehicle2 + long time = 0; + previousDestination = veh2.getPosition(); + // podivam se na trip plan + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + // protoze je size trip planu 0, tak to znamena, ze uz je auto rozjete do posledni destinace tripu + // je ale mozne, ze tam jeste nedojelo, tedy jeho pozice je jina nez pozice posledniho bodu v trip planu + time += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } + else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + time += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= pcq.getMaxPickupTime()*1000)) { + //not valid itinerary - check new driver plan + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= pcq.getMaxDropoffTime()*1000)) { + //not valid itinerary - check new driver plan + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + previousDestination = wait.getPosition(); + } else if (action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer p = (PlanActionPickupTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= p.getMaxTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer p = (PlanActionDropoffTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= p.getMaxTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } + } + } + } + else { + maxTransferTime = time2 - 2000; +// maxTransferTime = time1; + setMaxTransferTimeForDropoffTransferAction(maxTransferTime, itnryp1, request); + } + if(valid) { + List> itnrys = new ArrayList<>(); + itnrys.add(itnryp1); + itnrys.add(itnryp2); + Pair>, Long> ret = new Pair<>(itnrys, transferTime); + return ret; + } + else { + return null; + } + } + + public List getPickupActions(List plan) { + List pickups = new ArrayList<>(); + for(PlanAction action : plan) { + if(action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + pickups.add(action); + } + } + return pickups; + } + + public void setMaxTransferTimeForDropoffTransferAction(long maxTime, List itinerary, PlanComputationRequest request) { + maxTime = maxTime + timeProvider.getCurrentSimTime(); + int maxTimeInt = (int) Math.floor(maxTime / 1000.0); + for (PlanAction action : itinerary) { + if (action instanceof PlanActionDropoffTransfer) { + if(((PlanActionDropoffTransfer) action).getRequest() == request) { + PlanActionDropoffTransfer ac = (PlanActionDropoffTransfer) action; + ac.setMaxTime(maxTimeInt-1); + } + } + } + } + + + public List getDropoffActions(List plan) { + List dropoffs = new ArrayList<>(); + for(PlanAction action : plan) { + if(action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + dropoffs.add(action); + } + } + return dropoffs; + } + + private HashMap getEstimatedTimesOfDropoff(List itinerary, RideSharingOnDemandVehicle vehicle) { + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + SimulationNode previousDestination = vehicle.getPosition(); + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + // protoze je size trip planu 0, tak to znamena, ze uz je auto rozjete do posledni destinace tripu + // je ale mozne, ze tam jeste nedojelo, tedy jeho pozice je jina nez pozice posledniho bodu v trip planu + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + time = time + timeToFinishEdge; + + HashMap times = new HashMap<>(); + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + if (time > ((PlanRequestAction) action).request.getMaxPickupTime() * 1000) { + //not valid + return null; + } + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + if (time > ((PlanRequestAction) action).request.getMaxDropoffTime() * 1000) { + //not valid + return null; + } + times.put(((PlanRequestAction) action).getRequest(), time); + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionWait) { + time = time + ((PlanActionWait) action).getWaitTime(); + } + + } + return times; + } + + private List findItineraryWithMinimumDelayNew(List> lst, List originalPlan, RideSharingOnDemandVehicle vehicle) { + HashMap timesOfDropOriginal = getEstimatedTimesOfDropoff(originalPlan, vehicle); + if (timesOfDropOriginal == null) { + //plan neni validni + // to je chyba, puvodni plan by mel byt validni vzdy + return null; + //TODO throw exception + } + List delays = new ArrayList<>(); + for (List itnry : lst) { + HashMap timesOfDropNew = getEstimatedTimesOfDropoff(itnry, vehicle); + if (timesOfDropNew == null) { + //plan neni validni + delays.add(Long.MAX_VALUE); + } else { + // plan je validni, spocitam zpozdeni + long delay = countDelayDifference(timesOfDropOriginal, timesOfDropNew); + delays.add(delay); + } + } + //find max in delays + int maxAt = 0; + for (int i = 0; i < delays.size(); i++) { + maxAt = delays.get(i) > delays.get(maxAt) ? i : maxAt; + } + if (delays.get(maxAt) == Long.MAX_VALUE) { + return null; + } + List bestPlan = lst.get(maxAt); + return bestPlan; + } + + private long countDelayDifference(HashMap originalMap, HashMap newMap) { + long time = 0; + for (Map.Entry entry : originalMap.entrySet()) { + long difference = Math.abs(entry.getValue() - newMap.get(entry.getKey())); + time = time + difference; + } + // todo maybe add delay for a new passenger? + return time; + } + + private List removeCurrentPositionActions(List listOfActionsWithPositions) { + List copyOfList = new ArrayList<>(); + copyOfList.addAll(listOfActionsWithPositions); + for (PlanAction action : listOfActionsWithPositions) { + if (action instanceof PlanActionCurrentPosition) { + copyOfList.remove(action); + } + } + return copyOfList; + } + + + private List findPlanWithNoTransferNew(PlanComputationRequest newRequest, RideSharingOnDemandVehicle vehicle) { + DriverPlan vehiclePlan; + if (planMap.containsKey(vehicle)) { + vehiclePlan = planMap.get(vehicle); + } else { + vehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + if (isWithTransfer(vehiclePlan)) { + // v aute nekdo prestupuje + // musim oddelit segment s prestupem + // ze zbytku vezmu pickups, pridam novy a potom hledam permutace dropoff akci + int indexLastTransfer = findLastTransferActionIndex(vehiclePlan); + List segmentWithTransfer = vehiclePlan.plan.subList(0, indexLastTransfer+1); + List segmentWithTransferWithoutPositionAction = removeCurrentPositionActions(segmentWithTransfer); + + List segmentAfterTransfer = vehiclePlan.plan.subList(indexLastTransfer+1, vehiclePlan.plan.size()); + List> lstTemp = new ArrayList<>(); + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + for (PlanAction action : segmentAfterTransfer) { + newPlan.add(action); + } + //add pickup and dropoff for new request + newPlan.add(newRequest.getPickUpAction()); + newPlan.add(newRequest.getDropOffAction()); + //get pickup order based on heuristic from TASeT paper + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lstTemp.add(createItineraryList(pickups, dropoffPlan)); + } + // ted spojit puvodni segment a kadzy itinerare z lst + for (List itnry : lstTemp) { + List newList = new ArrayList<>(segmentWithTransferWithoutPositionAction); + newList.addAll(itnry); + lst.add(newList); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + + } else { + //neni prestup v aute + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + newPlan.addAll(vehiclePlan.plan); + //add pickup and dropoff for new request + newPlan.add(newRequest.getPickUpAction()); + newPlan.add(newRequest.getDropOffAction()); + //get pickup order based on heuristic from TASeT paper + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lst.add(createItineraryList(pickups, dropoffPlan)); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + } + } + + private List findPlanWithNoTransferActionsNew(PlanAction pickup, PlanAction dropoff, RideSharingOnDemandVehicle vehicle) { + DriverPlan vehiclePlan; + if (planMap.containsKey(vehicle)) { + vehiclePlan = planMap.get(vehicle); + } else { + vehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + if (isWithTransfer(vehiclePlan)) { + // v aute nekdo prestupuje + // musim oddelit segment s prestupem + // ze zbytku vezmu pickups, pridam novy a potom hledam permutace dropoff akci + int indexLastTransfer = findLastTransferActionIndex(vehiclePlan); + List segmentWithTransfer = vehiclePlan.plan.subList(0, indexLastTransfer+1); + List segmentWithTransferWithoutPositionAction = removeCurrentPositionActions(segmentWithTransfer); + + List segmentAfterTransfer = vehiclePlan.plan.subList(indexLastTransfer+1, vehiclePlan.plan.size()); + List> lstTemp = new ArrayList<>(); + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + newPlan.addAll(segmentAfterTransfer); + //add pickup and dropoff for new request + newPlan.add(pickup); + newPlan.add(dropoff); + //get pickup order based on heuristic from TASeT paper + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lstTemp.add(createItineraryList(pickups, dropoffPlan)); + } + // ted spojit puvodni segment a kadzy itinerare z lst + for (List itnry : lstTemp) { + List newList = new ArrayList<>(segmentWithTransferWithoutPositionAction); + newList.addAll(itnry); + lst.add(newList); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + + } else { + //neni prestup v aute + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + newPlan.addAll(vehiclePlan.plan); + //add pickup and dropoff for new request + newPlan.add(pickup); + newPlan.add(dropoff); + //get pickup order based on heuristic from TASeT paper + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lst.add(createItineraryList(pickups, dropoffPlan)); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + } + } + + private List createItineraryList(List pickupOrder, List dropoffOrder) { + List listOfActionsOrdered = new ArrayList<>(pickupOrder); + listOfActionsOrdered.addAll(dropoffOrder); + return listOfActionsOrdered; + } + + /** + * @return new list with all permutations of PlanActrions from lst List. + */ + public List> permute(List lst) { + List> list = new ArrayList<>(); + permuteHelper(list, new ArrayList<>(), lst); + return list; + } + + /** + * Helper function for permute() + */ + private void permuteHelper(List> list, List resultList, List lst){ + // Base case + if(resultList.size() == lst.size()){ + list.add(new ArrayList<>(resultList)); + } + else{ + for(int i = 0; i < lst.size(); i++){ + if(resultList.contains(lst.get(i))) + { + // If element already exists in the list then skip + continue; + } + // Choose element + resultList.add(lst.get(i)); + // Explore + permuteHelper(list, resultList, lst); + // Unchoose element + resultList.remove(resultList.size() - 1); + } + } + } + + private boolean canServeRequestTASeT2(RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan = vehicle.getCurrentPlanNoUpdate(); + for (PlanAction action : actualPlan) { + if (action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + // kolik lidi je prave ted v aute + boolean taxiFree = true; + int taxiCapacity = vehicle.getCapacity(); + if (requestsOnBoardSet.size() >= taxiCapacity) { + taxiFree = false; + } + if (!taxiFree) { + return false; + } else { + if (requestsOnBoard.size() == 0) { + long timeToNewRequest = travelTimeProvider.getTravelTime(vehicle, request.getFrom()); + if (timeToNewRequest <= request.getMaxPickupTime() * 1000) { + return true; + } + return false; + } + if (isWithTransfer(vehicle.getCurrentPlanNoUpdate())) { + // nekdo prestupuje + int indexLastTransferAction = findLastTransferActionIndex(vehicle.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = vehicle.getPosition(); + if (vehicle.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(vehicle, vehicle.getCurrentTask().getPosition()); + previousPos = vehicle.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (vehicle.getCurrentPlanNoUpdate().plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) vehicle.getCurrentPlanNoUpdate().plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + } + previousPos = vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + // ted potrebuju najit posledni pickup ve zbyvajicim driver planu po prestupu + List segmentAfterTransfer = vehicle.getCurrentPlanNoUpdate().plan.subList(indexLastTransferAction + 1, vehicle.getCurrentPlanNoUpdate().plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = vehicle.getCurrentPlanNoUpdate().plan.get(vehicle.getCurrentPlanNoUpdate().plan.size() - 1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + + //odtud jestli muze dojet k requestu - tj. cas od mista kde skoncil k vyzvednuti requestu + long timeToNewRequest = travelTimeProvider.getExpectedTravelTime(previousPos2, request.getFrom()); + long estimatedArrival = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToNewRequest; + if (estimatedArrival <= request.getMaxPickupTime() * 1000) { + return true; + } else { + return false; + } + } else { + //neprestupuje nikdo + int indexLastPickup = findLastPickupIndex(vehicle.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = vehicle.getPosition(); + if (vehicle.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(vehicle, vehicle.getCurrentTask().getPosition()); + previousPos = vehicle.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + previousPos = vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + long timeToNewRequest = travelTimeProvider.getExpectedTravelTime(previousPos, request.getFrom()); + long estimatedArrival = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToNewRequest; + if (estimatedArrival <= request.getMaxPickupTime() * 1000) { + return true; + } else { + return false; + } + } + + } + } +} + diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/GreedyTASeTSolver.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/GreedyTASeTSolver.java new file mode 100644 index 00000000..a26c41d1 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/GreedyTASeTSolver.java @@ -0,0 +1,1634 @@ +package cz.cvut.fel.aic.simod.ridesharing.greedyTASeT; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import cz.cvut.fel.aic.agentpolis.config.AgentpolisConfig; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.TimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.AgentPolisEntity; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.utils.PositionUtil; +import cz.cvut.fel.aic.alite.common.event.Event; +import cz.cvut.fel.aic.alite.common.event.EventHandler; +import cz.cvut.fel.aic.alite.common.event.EventProcessor; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; +import cz.cvut.fel.aic.simod.config.SimodConfig; +import cz.cvut.fel.aic.simod.event.OnDemandVehicleEvent; +import cz.cvut.fel.aic.simod.ridesharing.DARPSolver; +import cz.cvut.fel.aic.simod.ridesharing.DroppedDemandsAnalyzer; +import cz.cvut.fel.aic.simod.ridesharing.PlanCostProvider; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.insertionheuristic.DriverPlan; +import cz.cvut.fel.aic.simod.ridesharing.model.*; +import cz.cvut.fel.aic.simod.storage.OnDemandVehicleStorage; +import cz.cvut.fel.aic.simod.storage.OnDemandvehicleStationStorage; +import cz.cvut.fel.aic.simod.traveltimecomputation.TravelTimeProvider; +import org.jgrapht.alg.util.Pair; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Singleton +public class GreedyTASeTSolver extends DARPSolver implements EventHandler { + + + private final TypedSimulation eventProcessor; + + private final SimodConfig config; + + private final TimeProvider timeProvider; + + private final PositionUtil positionUtil; + + private final DroppedDemandsAnalyzer droppedDemandsAnalyzer; + + private final OnDemandvehicleStationStorage onDemandvehicleStationStorage; + + private List transferPoints; + + protected final DefaultPlanComputationRequest.DefaultPlanComputationRequestFactory requestFactory; + + private Map planMap; + + protected List> inactiveVehicles; + + protected List> waitingTimes; + + + @Inject + public GreedyTASeTSolver( + OnDemandVehicleStorage vehicleStorage, + TravelTimeProvider travelTimeProvider, + PlanCostProvider travelCostProvider, + DefaultPlanComputationRequest.DefaultPlanComputationRequestFactory requestFactory, + TypedSimulation eventProcessor, + SimodConfig config, + TimeProvider timeProvider, + PositionUtil positionUtil, + DroppedDemandsAnalyzer droppedDemandsAnalyzer, + OnDemandvehicleStationStorage onDemandvehicleStationStorage, + AgentpolisConfig agentpolisConfig) { + + super(vehicleStorage, travelTimeProvider, travelCostProvider, requestFactory); + this.eventProcessor = eventProcessor; + this.config = config; + this.timeProvider = timeProvider; + this.positionUtil = positionUtil; + this.droppedDemandsAnalyzer = droppedDemandsAnalyzer; + this.onDemandvehicleStationStorage = onDemandvehicleStationStorage; + this.requestFactory = requestFactory; + inactiveVehicles = new ArrayList<>(); + waitingTimes = new ArrayList<>(); + + setEventHandeling(); + } + + public void setTransferPoints(List transferPoints) { + this.transferPoints = transferPoints; + } + + @Override + public EventProcessor getEventProcessor() { + return eventProcessor; + } + + @Override + public void handleEvent(Event event) { + + } + + + private void setEventHandeling() { + List typesToHandle = new LinkedList<>(); + + typesToHandle.add(OnDemandVehicleEvent.PICKUP); + eventProcessor.addEventHandler(this, typesToHandle); + } + + /** + * Transfer-allowed scheduling solver + * @return Map + */ + @Override + public Map solve(List newRequests, List waitingRequests) { + Map planMap = new ConcurrentHashMap<>(); + Map planMapReturn = new ConcurrentHashMap<>(); + List taxis = new ArrayList<>(); + + for(AgentPolisEntity tVvehicle: vehicleStorage.getEntitiesForIteration()) { + RideSharingOnDemandVehicle vehicle = (RideSharingOnDemandVehicle) tVvehicle; + taxis.add(vehicle); + } + + planMap = dispatch(taxis, newRequests); + + + + return planMap; + } + + /** + * Transfer-allowed scheduling function + * @return + */ + private Map dispatch(List taxis, List requests) { + // because all passengers allow ridesharing, only greedy taset will be called + List carpoolAcceptingTaxis = taxis; + List carpoolAcceptingPassengers = requests; + Map map = heuristics(carpoolAcceptingTaxis, carpoolAcceptingPassengers); + return map; + } + + + private boolean isWithTransfer(DriverPlan plan) { + for(PlanAction action : plan.plan) { + if(action instanceof PlanRequestAction) { + if (action instanceof PlanActionDropoffTransfer || action instanceof PlanActionPickupTransfer || action instanceof PlanActionWait) { + return true; + } + } + } + return false; + } + + + private void logInactiveVehicles(List vehicles) { + for (RideSharingOnDemandVehicle vehicle : vehicles) { + if (vehicle.getCurrentPlanNoUpdate().plan.size() == 1) { + if (!planMap.containsKey(vehicle)) { + // toto vozidlo ma prazdny plan + inactiveVehicles.add(new Pair(vehicle.getId(), (int) Math.round(timeProvider.getCurrentSimTime() / 1000.0))); + } + } + } + } + + private void logWaitingTime(RideSharingOnDemandVehicle vehicle, Integer waitTimeInSeconds) { + waitingTimes.add(new Pair(vehicle.getId(), waitTimeInSeconds)); + } + + private int findLastPickupIndex(DriverPlan plan) { + int index = -1; + for (int i = 0; i < plan.getLength(); i++) { + if (plan.plan.get(i) instanceof PlanActionPickup) { + index = i; + } + } + return index; + } + + private int findLastPickupIndexList(List plan) { + int index = -1; + for (int i = 0; i < plan.size(); i++) { + if (plan.get(i) instanceof PlanActionPickup) { + index = i; + } + } + return index; + } + + private int findLastTransferActionIndex(DriverPlan plan) { + int index = -1; + for (int i = 0; i < plan.getLength(); i++) { + if (plan.plan.get(i) instanceof PlanActionDropoffTransfer || plan.plan.get(i) instanceof PlanActionPickupTransfer || plan.plan.get(i) instanceof PlanActionWait) { + index = i; + } + } + return index; + } + + private long countTimeToNewPickup(RideSharingOnDemandVehicle taxi, PlanComputationRequest request, List requestsOnBoard) { + DriverPlan taxiPlan; + if (planMap.containsKey(taxi)) { + taxiPlan = planMap.get(taxi); + } else { + taxiPlan = taxi.getCurrentPlanNoUpdate(); + } + if (isWithTransfer(taxiPlan)) { + int indexLastTransferAction = findLastTransferActionIndex(taxiPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (taxiPlan.plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) taxiPlan.plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, taxiPlan.plan.get(q).getPosition()); + } + previousPos = taxiPlan.plan.get(q).getPosition(); + } + List segmentAfterTransfer = taxiPlan.plan.subList(indexLastTransferAction+1, taxiPlan.plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = taxiPlan.plan.get(taxiPlan.plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + SimulationNode newPickupFrom = request.getFrom(); + long timeToNewPick = travelTimeProvider.getExpectedTravelTime(previousPos2, newPickupFrom); + long estimatedArrivalToPickup = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToNewPick; + long maxTime = request.getMaxDropoffTime() * 1000; + if (estimatedArrivalToPickup > maxTime) { + return Long.MAX_VALUE; + } + return estimatedArrivalToPickup; + } + else { + int indexLastPickup = findLastPickupIndex(taxiPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, taxiPlan.plan.get(q).getPosition()); + previousPos = taxiPlan.plan.get(q).getPosition(); + } + SimulationNode newPickupFrom = request.getFrom(); + long timeToNewPick = travelTimeProvider.getExpectedTravelTime(previousPos, newPickupFrom); + long estimatedArrivalToNewPickup = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToNewPick; + long maxTime = request.getMaxDropoffTime() * 1000; + if (estimatedArrivalToNewPickup > maxTime) { + return Long.MAX_VALUE; + } + return estimatedArrivalToNewPickup; + } + } + + /** + * Greedy TASeT heuristics function + * @return + */ + private Map heuristics(List taxis, List requests) { + //transfer points = charging stations + List transferPoints = this.transferPoints; + + //lookup table LT - LT [t][k] stores the earliest arrival time for taxi k to charging station t without violating the tolerable delay for k’s current passengers + int stationsCount = transferPoints.size(); + int taxisCount = taxis.size(); + long[][] LT = new long[stationsCount][taxisCount]; + //fill the LT table + for (int i = 0; i < taxisCount; i++) { + RideSharingOnDemandVehicle taxi = taxis.get(i); + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan = taxi.getCurrentPlanNoUpdate(); + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + // kolik lidi je prave ted v aute + boolean taxiFree = true; + int taxiCapacity = taxi.getCapacity(); + if (requestsOnBoardSet.size() >= taxiCapacity) { + taxiFree = false; + } + for(int j = 0; j < stationsCount; j++) { + //check if taxi has free seat + if (!taxiFree) { + LT[j][i] = Long.MAX_VALUE; + } + else { + if (isWithTransfer(taxi.getCurrentPlanNoUpdate())) { + // nekdo prestupuje + int indexLastTransferAction = findLastTransferActionIndex(taxi.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (taxi.getCurrentPlanNoUpdate().plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) taxi.getCurrentPlanNoUpdate().plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + } + previousPos = taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + // ted potrebuju najit posledni pickup ve zbyvajicim driver planu po prestupu + List segmentAfterTransfer = taxi.getCurrentPlanNoUpdate().plan.subList(indexLastTransferAction+1, taxi.getCurrentPlanNoUpdate().plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = taxi.getCurrentPlanNoUpdate().plan.get(taxi.getCurrentPlanNoUpdate().plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToStation; + LT[j][i] = estimatedArrivalToStation; + Set requestsInSegmentSet = new HashSet<>(); + for(PlanAction action : segmentAfterTransfer) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsInSegmentSet.add(requestAction.request); + } + } + List requestsInSegment = new ArrayList<>(requestsInSegmentSet); + for (PlanComputationRequest request : requestsInSegment) { + long maxTime = request.getMaxDropoffTime() * 1000; + if (LT[j][i] > maxTime) { + LT[j][i] = Long.MAX_VALUE; + break; + } + } + } + else { + int indexLastPickup = findLastPickupIndex(taxi.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + previousPos = taxi.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToStation; + LT[j][i] = estimatedArrivalToStation; + for (PlanComputationRequest request : requestsOnBoard) { + long maxTime = request.getMaxDropoffTime() * 1000; + if (LT[j][i] > maxTime) { + LT[j][i] = Long.MAX_VALUE; + break; + } + } + } + } + } + } + + //we rank the requests in descending order by the number of taxis that are possible to pick them up in time (without considering transfer or destination) + //get possible taxis for every request and number of possible taxis + int[] possiblePickupTaxisCounts = new int[requests.size()]; + int i = 0; + Map> possiblePickupTaxisMap = new HashMap<>(); + for(PlanComputationRequest request : requests) { + int counter = 0; + List possiblePickupTaxisOneRequest = new ArrayList<>(); + for(RideSharingOnDemandVehicle t : taxis) { + if (canServeRequestTASeT2(t, request)) { + counter++; + possiblePickupTaxisOneRequest.add(t); + } + } + possiblePickupTaxisCounts[i] = counter; + possiblePickupTaxisMap.put(request, possiblePickupTaxisOneRequest); + i++; + } + + + //sort R by the number of possible pickup taxis + List requestsCopy = new ArrayList<>(requests); + requests.sort(Comparator.comparing(x -> possiblePickupTaxisCounts[requestsCopy.indexOf(x)])); + //order to descending order - ve skutecnosti to ma byt ascending, i kdyz pisou descending :]]] +// Collections.reverse(requests); + + planMap = new ConcurrentHashMap<>(); + + + for(PlanComputationRequest request : requests) { + List>, List>> templistP = new ArrayList<>(); + List delays = new ArrayList<>(); + List transferTimes = new ArrayList<>(); + List canPickupRequestTaxis = possiblePickupTaxisMap.get(request); + for (RideSharingOnDemandVehicle taxi : canPickupRequestTaxis) { + List posbitnry = findPlanWithNoTransferNew(request, taxi); + if (posbitnry != null) { + if (checkValidItinerary(posbitnry, taxi)) { + List> tmp = new ArrayList<>(); + List tmpVehs = new ArrayList<>(); + tmpVehs.add(taxi); + tmp.add(posbitnry); + Pair>, List> pair = new Pair<>(tmp, tmpVehs); + templistP.add(pair); + long minimalArrivalTime = timeProvider.getCurrentSimTime() + travelTimeProvider.getExpectedTravelTime(request.getFrom(), request.getTo()); + HashMap dropoffs = getEstimatedTimesOfDropoff(posbitnry, taxi); + long realArrivalTime = dropoffs.get(request); + long delay = realArrivalTime - minimalArrivalTime; + delays.add(delay); + transferTimes.add((long) 0); + } + } + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan; + if (planMap.containsKey(taxi)) { + actualPlan = planMap.get(taxi); + } else { + actualPlan = taxi.getCurrentPlanNoUpdate(); + } + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + + long timeToNewPickup = countTimeToNewPickup(taxi, request, requestsOnBoard); + int stationIndex = 0; + for (SimulationNode station : transferPoints) { + if (timeToNewPickup + travelTimeProvider.getExpectedTravelTime(request.getFrom(), station) > + request.getMaxDropoffTime() * 1000 - travelTimeProvider.getExpectedTravelTime(station, request.getTo())) { + continue; + } + + // find k' = taxis that taxi k can transfer to at station + for (int k = 0; k < taxisCount; k++) { + //not possible to transfer to + if (LT[stationIndex][k] == Long.MAX_VALUE) { + continue; + } else if(LT[stationIndex][k] > request.getMaxDropoffTime() * 1000 - travelTimeProvider.getExpectedTravelTime(station, request.getTo())) { + continue; + } else if(taxi.equals(taxis.get(k))) { + continue; + } else if (station == request.getTo()) { + continue; + } else if (station == request.getFrom()) { + continue; + } else { + // split request to two requests with transfer point + long travelTimeFromStationToDest = travelTimeProvider.getExpectedTravelTime(station, request.getTo()); + int maxDropOffTime = request.getMaxDropoffTime() - (int) Math.round(travelTimeFromStationToDest / 1000.0); + PlanActionDropoffTransfer dropoffActionTransfer = new PlanActionDropoffTransfer(request, station, maxDropOffTime); + PlanActionPickupTransfer pickupActionTransfer = new PlanActionPickupTransfer(request, station, maxDropOffTime); + + List itnryp1 = findPlanWithNoTransferActionsNew(request.getPickUpAction(), dropoffActionTransfer, taxi); // pro auto + List itnryp2 = findPlanWithNoTransferActionsNew(pickupActionTransfer, request.getDropOffAction(), taxis.get(k)); + if (itnryp1 == null || itnryp2 == null) { + continue; + } + Pair>, Long> p = createChargePlanNoNewRequestsWithRounding(itnryp1, itnryp2, taxi, taxis.get(k), request); + if (p == null) { + continue; + } else { + List> itnrys = p.getFirst(); + itnryp1 = itnrys.get(0); + itnryp2 = itnrys.get(1); + List> tmp2 = new ArrayList<>(); + tmp2.add(itnryp1); + tmp2.add(itnryp2); + List tmpVehs2 = new ArrayList<>(); + tmpVehs2.add(taxi); + tmpVehs2.add(taxis.get(k)); + Pair>, List> pair2 = new Pair<>(tmp2, tmpVehs2); + templistP.add(pair2); + HashMap drops = getEstimatedTimesOfDropoff(itnryp2, taxis.get(k)); + if (drops == null) { + delays.add(Long.MAX_VALUE); + transferTimes.add((long) -1); + continue; + } + long minimalArrivalTime = timeProvider.getCurrentSimTime() + travelTimeProvider.getExpectedTravelTime(request.getFrom(), request.getTo()); + long realArrivalTime = drops.get(request); + long delay = realArrivalTime - minimalArrivalTime; + delays.add(delay); + long transferTime = p.getSecond(); + transferTimes.add(transferTime); + } + } + } + stationIndex++; + } + } + List listTransferPlans = new ArrayList<>(); + for (int j = 0; j < templistP.size(); j++) { + TransferPlan t = new TransferPlan(transferTimes.get(j), delays.get(j), templistP.get(j)); + listTransferPlans.add(t); + } + listTransferPlans.sort(TransferPlan::compareByDelay); + + double beta = 0.2; + int numOfTaken = (int) (delays.size() * beta); + if (numOfTaken == 0) { + numOfTaken = 1; + } + List sublistTransferPlans = new ArrayList<>(); + for (int q = 0; q < numOfTaken; q++) + { + if(!listTransferPlans.isEmpty()) { + sublistTransferPlans.add(listTransferPlans.get(q)); + } + } + sublistTransferPlans.sort(TransferPlan::compareByTransferTime); + Collections.reverse(sublistTransferPlans); + + if (sublistTransferPlans.isEmpty()) { + continue; + } + else + { + if (sublistTransferPlans.get(0).delay == Long.MAX_VALUE || sublistTransferPlans.get(0).trasferTime < 0) { + continue; + } + Pair>, List> key = sublistTransferPlans.get(0).pair; + List> plansForVehicles = key.getFirst(); + List vehicles = key.getSecond(); + for (int q = 0; q < vehicles.size(); q++) { + List vehPlan = plansForVehicles.get(q); + List planWithPos = new ArrayList<>(); + planWithPos.add(vehicles.get(q).getCurrentPlanNoUpdate().plan.get(0)); + planWithPos.addAll(vehPlan); + int waitTime = findWaitingAction(vehPlan, vehicles.get(q), request); + if (waitTime > 0) { + logWaitingTime(vehicles.get(q), waitTime); + } + DriverPlan dp = new DriverPlan(planWithPos, 0, 0); + planMap.put(vehicles.get(q), dp); + } + } + + // update k, k′ and LT + for (int z = 0; z < taxisCount; z++) { + RideSharingOnDemandVehicle taxi = taxis.get(z); + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan; + if (planMap.containsKey(taxis.get(z))) { + actualPlan = planMap.get(taxi); + } else { + actualPlan = taxi.getCurrentPlanNoUpdate(); + } + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + boolean taxiFree = true; + int taxiCapacity = taxi.getCapacity(); + if (requestsOnBoardSet.size() >= taxiCapacity) { + taxiFree = false; + } + for(int j = 0; j < stationsCount; j++) { + if (!taxiFree) { + LT[j][z] = Long.MAX_VALUE; + } else { + if (isWithTransfer(actualPlan)) { + int indexLastTransferAction = findLastTransferActionIndex(actualPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (actualPlan.plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) actualPlan.plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, actualPlan.plan.get(q).getPosition()); + } + previousPos = actualPlan.plan.get(q).getPosition(); + } + List segmentAfterTransfer = actualPlan.plan.subList(indexLastTransferAction + 1, actualPlan.plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = actualPlan.plan.get(actualPlan.plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos2, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToStation; + LT[j][z] = estimatedArrivalToStation; + Set requestsInSegmentSet = new HashSet<>(); + for (PlanAction action : segmentAfterTransfer) { + if (action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsInSegmentSet.add(requestAction.request); + } + } + List requestsInSegment = new ArrayList<>(requestsInSegmentSet); + for (PlanComputationRequest r : requestsInSegment) { + long maxTime = r.getMaxDropoffTime() * 1000; + if (LT[j][z] > maxTime) { + LT[j][z] = Long.MAX_VALUE; + break; + } + } + } else { + int indexLastPickup = findLastPickupIndex(actualPlan); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = taxi.getPosition(); + if (taxi.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(taxi, taxi.getCurrentTask().getPosition()); + previousPos = taxi.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, actualPlan.plan.get(q).getPosition()); + previousPos = actualPlan.plan.get(q).getPosition(); + } + SimulationNode station = transferPoints.get(j); + long timeToStation = travelTimeProvider.getExpectedTravelTime(previousPos, station); + long estimatedArrivalToStation = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToStation; + LT[j][z] = estimatedArrivalToStation; + for (PlanComputationRequest r : requestsOnBoard) { + long maxTime = r.getMaxDropoffTime() * 1000; + if (LT[j][z] > maxTime) { + LT[j][z] = Long.MAX_VALUE; + break; + } + } + } + } + } + } + } + + logInactiveVehicles(taxis); + + return planMap; + } + + public Integer findWaitingAction(List plan, RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + for (PlanAction action : plan) { + if (action instanceof PlanActionWait) { + if (((PlanActionWait) action).getRequest() == request) { + PlanActionWait wait = (PlanActionWait) action; + return (int) Math.round(wait.getWaitTime() / 1000.0); + } + } + } + return 0; + } + + public List> getInactiveVehicles() { + return inactiveVehicles; + } + + public List> getWaitingTimes() { + return waitingTimes; + } + + private boolean checkValidItinerary(List itinerary, RideSharingOnDemandVehicle vehicle) { + SimulationNode previousDestination = vehicle.getPosition(); + boolean ret = true; + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + previousDestination = vehicle.getPosition(); + + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time += timeToFinishEdge; + + for (PlanAction action : itinerary) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxPickupTime()*1000)) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxDropoffTime()*1000)) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + } + } + } + return ret; + } + + private Pair>, Long> createChargePlanNoNewRequests(List itnryp1, List itnryp2, RideSharingOnDemandVehicle veh1, RideSharingOnDemandVehicle veh2, PlanComputationRequest request) { + long time1 = 0; + long timeToFinishEdge1 = 0; + SimulationNode previousDestination = veh1.getPosition(); + + if (veh1.getCurrentTripPlan() != null) { + if (veh1.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh1.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge1 += travelTimeProvider.getTravelTime(veh1, stopLoc); + previousDestination = stopLoc; + } + else if (veh1.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh1.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge1 += travelTimeProvider.getTravelTime(veh1, currLoc); + } + if (currLoc == veh1.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time1 = timeToFinishEdge1; + + long transferTime = 0; + //expected arrival time of first car + for (PlanAction action : itnryp1) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (dropoffTransfer.request == request) { + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time1 = time1 + wait.getWaitTime(); + } + } + } + // expected arrival of second car + int indexPickupSecondCar = 0; + long time2 = 0; + long timeToFinishEdge2 = 0; + PlanActionPickupTransfer pickup = null; + previousDestination = veh2.getPosition(); + + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge2 += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge2 += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time2 = timeToFinishEdge2; + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (pickupTransfer.request == request) { + pickup = pickupTransfer; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time2 = time2 + wait.getWaitTime(); + } + } + indexPickupSecondCar++; + } + long waitTime = time2 - time1; + + boolean valid = true; + + if (waitTime > 0 && waitTime < 2000) { + long newWait = 2000 - waitTime; + PlanActionWait waitAction = new PlanActionWait(request, pickup.getPosition(), pickup.getMaxTime(), newWait); + transferTime = newWait; + itnryp2.add(indexPickupSecondCar, waitAction); + + //check tolerable delay for passengers in vehicle2 + long time = 0; + previousDestination = veh2.getPosition(); + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + time += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } + else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + time += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxPickupTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxDropoffTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + previousDestination = wait.getPosition(); + } else if (action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer p = (PlanActionPickupTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer p = (PlanActionDropoffTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } + } + } + } + if (waitTime <= 0) { + waitTime = waitTime - 2000; + assert pickup != null; + PlanActionWait waitAction = new PlanActionWait(request, pickup.getPosition(), pickup.getMaxTime(), -waitTime); + transferTime = -waitTime; + itnryp2.add(indexPickupSecondCar, waitAction); + + long time = 0; + previousDestination = veh2.getPosition(); + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + time += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } + else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + time += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxPickupTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxDropoffTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + previousDestination = wait.getPosition(); + } else if (action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer p = (PlanActionPickupTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer p = (PlanActionDropoffTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } + } + } + } + if(valid) { + List> itnrys = new ArrayList<>(); + itnrys.add(itnryp1); + itnrys.add(itnryp2); + Pair>, Long> ret = new Pair<>(itnrys, transferTime); + return ret; + } + else { + return null; + } + } + + private Pair>, Long> createChargePlanNoNewRequestsWithRounding(List itnryp1, List itnryp2, RideSharingOnDemandVehicle veh1, RideSharingOnDemandVehicle veh2, PlanComputationRequest request) { + long time1 = 0; + int time1Int = (int) Math.ceil(timeProvider.getCurrentSimTime() / 1000.0); + long timeToFinishEdge1 = 0; + SimulationNode previousDestination = veh1.getPosition(); + + if (veh1.getCurrentTripPlan() != null) { + if (veh1.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh1.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge1 += travelTimeProvider.getTravelTime(veh1, stopLoc); + previousDestination = stopLoc; + } + else if (veh1.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh1.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge1 += travelTimeProvider.getTravelTime(veh1, currLoc); + } + if (currLoc == veh1.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh1.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time1 = timeToFinishEdge1; + time1Int += (int) Math.ceil(timeToFinishEdge1 / 1000.0); + + long transferTime = 0; + + //expected arrival time of first car + for (PlanAction action : itnryp1) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time1Int += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest)/1000.0); + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time1Int += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest)/1000.0); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time1Int += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest)/1000.0); + if (dropoffTransfer.request == request) { + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time1 = time1 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time1Int += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest)/1000.0); + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time1 = time1 + wait.getWaitTime(); + time1Int += (int) Math.ceil(wait.getWaitTime())/1000.0; + } + } + } + time1Int += 1; + // expected arrival of second car + int indexPickupSecondCar = 0; + long time2 = 0; + int time2Int = (int) Math.floor(timeProvider.getCurrentSimTime() / 1000.0); + long timeToFinishEdge2 = 0; + PlanActionPickupTransfer pickup = null; + previousDestination = veh2.getPosition(); + + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge2 += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge2 += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time2 = timeToFinishEdge2; + time2Int += (int) Math.floor(timeToFinishEdge2/1000.0); + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time2Int += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time2Int += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (pickupTransfer.request == request) { + pickup = pickupTransfer; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time2Int += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time2 = time2 + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + time2Int += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time2 = time2 + wait.getWaitTime(); + time2Int += (int) Math.floor(wait.getWaitTime() / 1000.0); + } + } + indexPickupSecondCar++; + } + time2Int -= 1; + int waitTimeInt = time1Int - time2Int; + + boolean valid = true; + + if (waitTimeInt > 0) { + PlanActionWait waitAction = new PlanActionWait(request, pickup.getPosition(), pickup.getMaxTime(), waitTimeInt * 1000); + transferTime = waitTimeInt * 1000; + itnryp2.add(indexPickupSecondCar, waitAction); + + long time = timeProvider.getCurrentSimTime(); +// int timeInt = (int) Math.round(timeProvider.getCurrentSimTime() / 1000.0); + previousDestination = veh2.getPosition(); + if (veh2.getCurrentTripPlan() != null) { + if (veh2.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getLastLocation(); + time += travelTimeProvider.getTravelTime(veh2, stopLoc); + previousDestination = stopLoc; + } + else if (veh2.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) veh2.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + time += travelTimeProvider.getTravelTime(veh2, currLoc); + } + if (currLoc == veh2.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) veh2.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + for (PlanAction action : itnryp2) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxPickupTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxDropoffTime()*1000)) { + valid = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + time = time + wait.getWaitTime(); + previousDestination = wait.getPosition(); + } else if (action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer p = (PlanActionPickupTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer p = (PlanActionDropoffTransfer) action; + SimulationNode dest = p.getPosition(); + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = dest; + } + } + } + } + if(valid) { + List> itnrys = new ArrayList<>(); + itnrys.add(itnryp1); + itnrys.add(itnryp2); + Pair>, Long> ret = new Pair<>(itnrys, transferTime); + return ret; + } + else { + return null; + } + } + + public List getPickupActions(List plan) { + List pickups = new ArrayList<>(); + for(PlanAction action : plan) { + if(action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + pickups.add(action); + } + } + return pickups; + } + + public List getDropoffActions(List plan) { + List dropoffs = new ArrayList<>(); + for(PlanAction action : plan) { + if(action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + dropoffs.add(action); + } + } + return dropoffs; + } + + private HashMap getEstimatedTimesOfDropoff(List itinerary, RideSharingOnDemandVehicle vehicle) { + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + SimulationNode previousDestination = vehicle.getPosition(); + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + + time = time + timeToFinishEdge; + + HashMap times = new HashMap<>(); + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + if (time > ((PlanRequestAction) action).request.getMaxPickupTime() * 1000) { + return null; + } + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + if (time > ((PlanRequestAction) action).request.getMaxDropoffTime() * 1000) { + return null; + } + times.put(((PlanRequestAction) action).getRequest(), time); + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionWait) { + time = time + ((PlanActionWait) action).getWaitTime(); + } + } + return times; + } + + private List findItineraryWithMinimumDelayNew(List> lst, List originalPlan, RideSharingOnDemandVehicle vehicle) { + HashMap timesOfDropOriginal = getEstimatedTimesOfDropoff(originalPlan, vehicle); + if (timesOfDropOriginal == null) { + return null; + //TODO throw exception + } + List delays = new ArrayList<>(); + for (List itnry : lst) { + HashMap timesOfDropNew = getEstimatedTimesOfDropoff(itnry, vehicle); + if (timesOfDropNew == null) { + delays.add(Long.MAX_VALUE); + } else { + long delay = countDelayDifference(timesOfDropOriginal, timesOfDropNew); + delays.add(delay); + } + } + int maxAt = 0; + for (int i = 0; i < delays.size(); i++) { + maxAt = delays.get(i) > delays.get(maxAt) ? i : maxAt; + } + if (delays.get(maxAt) == Long.MAX_VALUE) { + return null; + } + List bestPlan = lst.get(maxAt); + return bestPlan; + } + + private long countDelayDifference(HashMap originalMap, HashMap newMap) { + long time = 0; + for (Map.Entry entry : originalMap.entrySet()) { + long difference = Math.abs(entry.getValue() - newMap.get(entry.getKey())); + time = time + difference; + } + // todo maybe add delay for a new passenger? + return time; + } + + private List removeCurrentPositionActions(List listOfActionsWithPositions) { + List copyOfList = new ArrayList<>(); + copyOfList.addAll(listOfActionsWithPositions); + for (PlanAction action : listOfActionsWithPositions) { + if (action instanceof PlanActionCurrentPosition) { + copyOfList.remove(action); + } + } + return copyOfList; + } + + + private List findPlanWithNoTransferNew(PlanComputationRequest newRequest, RideSharingOnDemandVehicle vehicle) { + DriverPlan vehiclePlan; + if (planMap.containsKey(vehicle)) { + vehiclePlan = planMap.get(vehicle); + } else { + vehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + if (isWithTransfer(vehiclePlan)) { + int indexLastTransfer = findLastTransferActionIndex(vehiclePlan); + List segmentWithTransfer = vehiclePlan.plan.subList(0, indexLastTransfer+1); + List segmentWithTransferWithoutPositionAction = removeCurrentPositionActions(segmentWithTransfer); + + List segmentAfterTransfer = vehiclePlan.plan.subList(indexLastTransfer+1, vehiclePlan.plan.size()); + List> lstTemp = new ArrayList<>(); + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + for (PlanAction action : segmentAfterTransfer) { + newPlan.add(action); + } + newPlan.add(newRequest.getPickUpAction()); + newPlan.add(newRequest.getDropOffAction()); + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lstTemp.add(createItineraryList(pickups, dropoffPlan)); + } + for (List itnry : lstTemp) { + List newList = new ArrayList<>(segmentWithTransferWithoutPositionAction); + newList.addAll(itnry); + lst.add(newList); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + + } else { + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + newPlan.addAll(vehiclePlan.plan); + newPlan.add(newRequest.getPickUpAction()); + newPlan.add(newRequest.getDropOffAction()); + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lst.add(createItineraryList(pickups, dropoffPlan)); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + } + } + + private List findPlanWithNoTransferActionsNew(PlanAction pickup, PlanAction dropoff, RideSharingOnDemandVehicle vehicle) { + DriverPlan vehiclePlan; + if (planMap.containsKey(vehicle)) { + vehiclePlan = planMap.get(vehicle); + } else { + vehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + if (isWithTransfer(vehiclePlan)) { + int indexLastTransfer = findLastTransferActionIndex(vehiclePlan); + List segmentWithTransfer = vehiclePlan.plan.subList(0, indexLastTransfer+1); + List segmentWithTransferWithoutPositionAction = removeCurrentPositionActions(segmentWithTransfer); + + List segmentAfterTransfer = vehiclePlan.plan.subList(indexLastTransfer+1, vehiclePlan.plan.size()); + List> lstTemp = new ArrayList<>(); + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + newPlan.addAll(segmentAfterTransfer); + //add pickup and dropoff for new request + newPlan.add(pickup); + newPlan.add(dropoff); + //get pickup order based on heuristic from TASeT paper + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lstTemp.add(createItineraryList(pickups, dropoffPlan)); + } + for (List itnry : lstTemp) { + List newList = new ArrayList<>(segmentWithTransferWithoutPositionAction); + newList.addAll(itnry); + lst.add(newList); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + + } else { + List> lst = new ArrayList<>(); + List newPlan = new ArrayList<>(); + newPlan.addAll(vehiclePlan.plan); + //add pickup and dropoff for new request + newPlan.add(pickup); + newPlan.add(dropoff); + //get pickup order based on heuristic from TASeT paper + List pickups = getPickupActions(newPlan); + List dropoffs = getDropoffActions(newPlan); + //permute dropoff orders + List> dropoffOrders = permute(dropoffs); + for (List dropoffPlan : dropoffOrders) { + lst.add(createItineraryList(pickups, dropoffPlan)); + } + return findItineraryWithMinimumDelayNew(lst, vehiclePlan.plan, vehicle); + } + } + + private List createItineraryList(List pickupOrder, List dropoffOrder) { + List listOfActionsOrdered = new ArrayList<>(pickupOrder); + listOfActionsOrdered.addAll(dropoffOrder); + return listOfActionsOrdered; + } + + /** + * @return new list with all permutations of PlanActrions from lst List. + */ + public List> permute(List lst) { + List> list = new ArrayList<>(); + permuteHelper(list, new ArrayList<>(), lst); + return list; + } + + /** + * Helper function for permute() + */ + private void permuteHelper(List> list, List resultList, List lst){ + // Base case + if(resultList.size() == lst.size()){ + list.add(new ArrayList<>(resultList)); + } + else{ + for(int i = 0; i < lst.size(); i++){ + if(resultList.contains(lst.get(i))) + { + // If element already exists in the list then skip + continue; + } + // Choose element + resultList.add(lst.get(i)); + // Explore + permuteHelper(list, resultList, lst); + // Unchoose element + resultList.remove(resultList.size() - 1); + } + } + } + + private boolean canServeRequestTASeT2(RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + Set requestsOnBoardSet = new HashSet<>(); + DriverPlan actualPlan = vehicle.getCurrentPlanNoUpdate(); + for(PlanAction action : actualPlan) { + if(action instanceof PlanRequestAction) { + PlanRequestAction requestAction = (PlanRequestAction) action; + requestsOnBoardSet.add(requestAction.request); + } + } + List requestsOnBoard = new ArrayList<>(requestsOnBoardSet); + boolean taxiFree = true; + int taxiCapacity = vehicle.getCapacity(); + if (requestsOnBoardSet.size() >= taxiCapacity) { + taxiFree = false; + } + if (!taxiFree) { + return false; + } + else { + if (requestsOnBoard.size() == 0) { + long timeToNewRequest = travelTimeProvider.getTravelTime(vehicle, request.getFrom()); + if (timeToNewRequest <= request.getMaxPickupTime() * 1000) { + return true; + } + return false; + } + if (isWithTransfer(vehicle.getCurrentPlanNoUpdate())) { + int indexLastTransferAction = findLastTransferActionIndex(vehicle.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = vehicle.getPosition(); + if (vehicle.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(vehicle, vehicle.getCurrentTask().getPosition()); + previousPos = vehicle.getCurrentTask().getPosition(); + } + long timeToLastTransferAction = 0; + for (int q = 0; q < indexLastTransferAction + 1; q++) { + if (vehicle.getCurrentPlanNoUpdate().plan.get(q) instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) vehicle.getCurrentPlanNoUpdate().plan.get(q); + timeToLastTransferAction = timeToLastTransferAction + wait.getWaitTime(); + } else { + timeToLastTransferAction = timeToLastTransferAction + travelTimeProvider.getExpectedTravelTime(previousPos, vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + } + previousPos = vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + List segmentAfterTransfer = vehicle.getCurrentPlanNoUpdate().plan.subList(indexLastTransferAction+1, vehicle.getCurrentPlanNoUpdate().plan.size()); + int indexLastPickupSegment = findLastPickupIndexList(segmentAfterTransfer); + long timeToLastPickup = 0; + SimulationNode previousPos2 = vehicle.getCurrentPlanNoUpdate().plan.get(vehicle.getCurrentPlanNoUpdate().plan.size()-1).getPosition(); + if (segmentAfterTransfer.size() > 0) { + previousPos2 = segmentAfterTransfer.get(0).getPosition(); + for (int q = 0; q < indexLastPickupSegment + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos2, segmentAfterTransfer.get(q).getPosition()); + previousPos2 = segmentAfterTransfer.get(q).getPosition(); + } + } + long timeToNewRequest = travelTimeProvider.getExpectedTravelTime(previousPos2, request.getFrom()); + long estimatedArrival = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastTransferAction + timeToLastPickup + timeToNewRequest; + if (estimatedArrival <= request.getMaxPickupTime() * 1000) { + return true; + } else { + return false; + } + } + else { + int indexLastPickup = findLastPickupIndex(vehicle.getCurrentPlanNoUpdate()); + long timeToFinishCurrentEdge = 0; + SimulationNode previousPos = vehicle.getPosition(); + if (vehicle.getCurrentTask() != null) { + timeToFinishCurrentEdge = travelTimeProvider.getTravelTime(vehicle, vehicle.getCurrentTask().getPosition()); + previousPos = vehicle.getCurrentTask().getPosition(); + } + long timeToLastPickup = 0; + for (int q = 0; q < indexLastPickup + 1; q++) { + timeToLastPickup = timeToLastPickup + travelTimeProvider.getExpectedTravelTime(previousPos, vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition()); + previousPos = vehicle.getCurrentPlanNoUpdate().plan.get(q).getPosition(); + } + long timeToNewRequest = travelTimeProvider.getExpectedTravelTime(previousPos, request.getFrom()); + long estimatedArrival = timeProvider.getCurrentSimTime() + timeToFinishCurrentEdge + timeToLastPickup + timeToNewRequest; + if (estimatedArrival <= request.getMaxPickupTime() * 1000) { + return true; + } else { + return false; + } + } + } + } +} + diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/RequestPlan.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/RequestPlan.java new file mode 100644 index 00000000..e19f8488 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/RequestPlan.java @@ -0,0 +1,38 @@ +package cz.cvut.fel.aic.simod.ridesharing.greedyTASeT; + +import cz.cvut.fel.aic.simod.ridesharing.model.PlanAction; +import cz.cvut.fel.aic.simod.ridesharing.model.PlanComputationRequest; + +import java.util.Iterator; +import java.util.List; + +public class RequestPlan implements Iterable{ + public final List plan; + + public final long totalTime; + + public final double cost; + + public PlanComputationRequest getRequest() { + return request; + } + + public void setRequest(PlanComputationRequest request) { + this.request = request; + } + + public PlanComputationRequest request; + + public RequestPlan(List plan, long totalTime, double cost ) { + this.plan = plan; + this.totalTime = totalTime; + this.cost = cost; + } + + @Override + public Iterator iterator() { + return plan.iterator(); + } + + // plan for each request, contains onboarding / offboarding actions +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/TransferPlan.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/TransferPlan.java new file mode 100644 index 00000000..62974c40 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/greedyTASeT/TransferPlan.java @@ -0,0 +1,30 @@ +package cz.cvut.fel.aic.simod.ridesharing.greedyTASeT; + +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.model.PlanAction; +import org.jgrapht.alg.util.Pair; + +import java.util.List; + +public class TransferPlan { + + public final long trasferTime; + public final long delay; + public final Pair>, List> pair; + + public TransferPlan(long trasferTime, long delay, Pair>, List> pair) { + this.trasferTime = trasferTime; + this.delay = delay; + this.pair = pair; + } + + public int compareByDelay(TransferPlan o2) { + return Long.compare(this.delay, o2.delay); + } + + public int compareByTransferTime(TransferPlan o2) { + return Long.compare(this.trasferTime, o2.trasferTime); + } +} + + diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/DriverPlan.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/DriverPlan.java index 14850036..df9ac88a 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/DriverPlan.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/DriverPlan.java @@ -19,8 +19,13 @@ package cz.cvut.fel.aic.simod.ridesharing.insertionheuristic; import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; import cz.cvut.fel.aic.simod.ridesharing.model.PlanAction; import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionCurrentPosition; +import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionDropoff; +import cz.cvut.fel.aic.simod.ridesharing.model.PlanActionPickup; + +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -29,12 +34,16 @@ * @author F.I.D.O. */ public class DriverPlan implements Iterable{ - public final List plan; + public List plan; public final long totalTime; public final double cost; + public int vehicleIndex = -1; + + public RideSharingOnDemandVehicle vehicle; + @@ -65,6 +74,24 @@ public void taskCompleted(){ plan.remove(1); } + public void setVehicleIndex(int vehicleIndex) { + this.vehicleIndex = vehicleIndex; + } + + public void setVehicle(RideSharingOnDemandVehicle vehicle) { + this.vehicle = vehicle; + } + + public RideSharingOnDemandVehicle getVehicle() { + return this.vehicle; + } + + public int getVehicleIndex() { + return this.vehicleIndex; + } + + + @Override public String toString() { StringBuilder sb = new StringBuilder("["); @@ -76,6 +103,7 @@ public String toString() { sb.append("]"); return sb.toString(); } + } diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/InsertionHeuristicSolver.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/InsertionHeuristicSolver.java index c7561a6d..65623806 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/InsertionHeuristicSolver.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/insertionheuristic/InsertionHeuristicSolver.java @@ -56,6 +56,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import me.tongfei.progressbar.ProgressBar; +import org.jgrapht.alg.util.Pair; import org.slf4j.LoggerFactory; /** @@ -116,6 +117,8 @@ public class InsertionHeuristicSolver extends DARPSolver implements EventHandler private int[] usedVehiclesPerStation; private List vehiclesForPlanning; + + protected List> inactiveVehicles; @@ -140,6 +143,7 @@ public InsertionHeuristicSolver( this.eventProcessor = eventProcessor; this.droppedDemandsAnalyzer = droppedDemandsAnalyzer; this.onDemandvehicleStationStorage = onDemandvehicleStationStorage; + inactiveVehicles = new ArrayList<>(); // max distance in meters between vehicle and request for the vehicle to be considered to serve the request @@ -159,6 +163,12 @@ public Map solve(List waitingRequests) { callCount++; long startTime = System.nanoTime(); + + List taxis = new ArrayList<>(); + for(AgentPolisEntity tVvehicle: vehicleStorage.getEntitiesForIteration()) { + RideSharingOnDemandVehicle vehicle = (RideSharingOnDemandVehicle) tVvehicle; + taxis.add(vehicle); + } planMap = new ConcurrentHashMap<>(); @@ -219,6 +229,7 @@ public Map solve(List requests) { requests.size())); } + private void logInactiveVehicles(List vehicles) { + for (RideSharingOnDemandVehicle vehicle : vehicles) { + if (vehicle.getCurrentPlanNoUpdate().plan.size() == 1) { + if (!planMap.containsKey(vehicle)) { + // toto vozidlo ma prazdny plan + inactiveVehicles.add(new Pair(vehicle.getId(), (int) Math.round(timeProvider.getCurrentSimTime() / 1000.0))); + } + } + } + } + private void computeBestPlanForRequest(PlanComputationRequest request) { resetBestPlan(); @@ -545,6 +567,10 @@ private void processRequest(PlanComputationRequest request) { // } // return listForPlanning; // } + + public List> getInactiveVehicles() { + return inactiveVehicles; + } private List getVehiclesForPlanning() { vehiclesForPlanning = new ArrayList<>(); diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/DefaultPlanComputationRequest.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/DefaultPlanComputationRequest.java index 677cf48f..94336bf6 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/DefaultPlanComputationRequest.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/DefaultPlanComputationRequest.java @@ -86,7 +86,7 @@ public DemandAgent getDemandAgent() { @Inject - private DefaultPlanComputationRequest(TravelTimeProvider travelTimeProvider, @Assisted int id, + public DefaultPlanComputationRequest(TravelTimeProvider travelTimeProvider, @Assisted int id, SimodConfig SimodConfig, @Assisted("origin") SimulationNode origin, @Assisted("destination") SimulationNode destination, @Assisted DemandAgent demandAgent){ this.id = id; diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionDropoffTransfer.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionDropoffTransfer.java new file mode 100644 index 00000000..d8886027 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionDropoffTransfer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Czech Technical University in Prague. + * + * This file is part of the SiMoD project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package cz.cvut.fel.aic.simod.ridesharing.model; + +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; + +public class PlanActionDropoffTransfer extends PlanRequestAction { + + /** + * DropoffTransfer action. + * @param request Request + * @param node Position where action takes place. + * @param maxTime Time constraint in seconds. + */ + public PlanActionDropoffTransfer(PlanComputationRequest request, SimulationNode node, int maxTime) { + super(request, node, maxTime); + } + + + + @Override + public String toString() { + return String.format("Drop off demand %s at node %s", request.getDemandAgent().getId(), location.id); + } + + + +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionOffboard.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionOffboard.java new file mode 100644 index 00000000..b92be184 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionOffboard.java @@ -0,0 +1,22 @@ +package cz.cvut.fel.aic.simod.ridesharing.model; + +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; + +public class PlanActionOffboard extends PlanRequestAction{ + + private RideSharingOnDemandVehicle fromVehicle; + + public PlanActionOffboard(PlanComputationRequest request, SimulationNode location, int maxTime, RideSharingOnDemandVehicle fromVehicle) { + super(request, location, maxTime); + this.fromVehicle = fromVehicle; + } + + public RideSharingOnDemandVehicle getFromVehicle() { + return fromVehicle; + } + + public void setFromVehicle(RideSharingOnDemandVehicle fromVehicle) { + this.fromVehicle = fromVehicle; + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionOnboard.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionOnboard.java new file mode 100644 index 00000000..881bd78a --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionOnboard.java @@ -0,0 +1,22 @@ +package cz.cvut.fel.aic.simod.ridesharing.model; + +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; + +public class PlanActionOnboard extends PlanRequestAction { + + private RideSharingOnDemandVehicle toVehicle; + + public PlanActionOnboard(PlanComputationRequest request, SimulationNode location, int maxTime, RideSharingOnDemandVehicle toVehicle) { + super(request, location, maxTime); + this.toVehicle = toVehicle; + } + + public RideSharingOnDemandVehicle getToVehicle() { + return toVehicle; + } + + public void setToVehicle(RideSharingOnDemandVehicle toVehicle) { + this.toVehicle = toVehicle; + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionPickupTransfer.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionPickupTransfer.java new file mode 100644 index 00000000..49150438 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionPickupTransfer.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Czech Technical University in Prague. + * + * This file is part of the SiMoD project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package cz.cvut.fel.aic.simod.ridesharing.model; + +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; + +public class PlanActionPickupTransfer extends PlanRequestAction { + + /** + * PickupTransfer action. + * @param request Request + * @param node Position where action takes place. + * @param maxTime Time constraint in seconds. + */ + public PlanActionPickupTransfer(PlanComputationRequest request, SimulationNode node, int maxTime) { + super(request, node, maxTime); + } + + + + @Override + public String toString() { + return String.format("Pick up demand %s at node %s", request.getDemandAgent().getId(), location.id); + } + + +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionWait.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionWait.java new file mode 100644 index 00000000..5eab7c49 --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanActionWait.java @@ -0,0 +1,70 @@ +package cz.cvut.fel.aic.simod.ridesharing.model; + +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; + +public class PlanActionWait extends PlanRequestAction { + + protected long waitTime; + + protected boolean waitingStarted = false; + + protected long waitingStartedAt; + + protected boolean waitingPaused = false; + + protected long waitingPausedAt; + + public long getWaitingStartedAt() { + return waitingStartedAt; + } + + public void setWaitingStartedAt(long waitingStartedAt) { + this.waitingStartedAt = waitingStartedAt; + } + + public long getWaitTime(){ + return waitTime; + } + + public boolean isWaitingStarted() { + return waitingStarted; + } + + public boolean isWaitingPaused() { + return waitingPaused; + } + + public void setWaitingPaused(boolean waitingPaused) { + this.waitingPaused = waitingPaused; + } + + public long getWaitingPausedAt() { + return waitingPausedAt; + } + + public void setWaitingPausedAt(long waitingPausedAt) { + this.waitingPausedAt = waitingPausedAt; + } + + public void setWaitingStarted(boolean waitingStarted) { + this.waitingStarted = waitingStarted; + } + + public void setWaitTime(long waitTime) { + this.waitTime = waitTime; + } + + + + public PlanActionWait(PlanComputationRequest request, SimulationNode node, int maxTime, long waitTime) { + super(request, node, maxTime); + this.waitTime = waitTime; + this.waitingStarted = false; + + } + + @Override + public String toString() { + return String.format("Wait for demand %s at node %s", request.getDemandAgent().getId(), location.id); + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanRequestAction.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanRequestAction.java index e86f588e..4b6c202d 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanRequestAction.java +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/model/PlanRequestAction.java @@ -29,7 +29,7 @@ public abstract class PlanRequestAction extends PlanAction{ /** * Time constraint in seconds */ - private final int maxTime; + private int maxTime; public PlanComputationRequest getRequest() { return request; @@ -42,6 +42,10 @@ public PlanComputationRequest getRequest() { public int getMaxTime() { return maxTime; } + + public void setMaxTime(int maxTime) { + this.maxTime = maxTime; + } diff --git a/src/main/java/cz/cvut/fel/aic/simod/ridesharing/transferinsertion/TransferInsertionSolver.java b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/transferinsertion/TransferInsertionSolver.java new file mode 100644 index 00000000..8226bf7d --- /dev/null +++ b/src/main/java/cz/cvut/fel/aic/simod/ridesharing/transferinsertion/TransferInsertionSolver.java @@ -0,0 +1,1181 @@ +package cz.cvut.fel.aic.simod.ridesharing.transferinsertion; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import cz.cvut.fel.aic.agentpolis.config.AgentpolisConfig; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.trip.Trip; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.TimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.entity.AgentPolisEntity; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.EGraphType; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationEdge; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.utils.PositionUtil; +import cz.cvut.fel.aic.alite.common.event.Event; +import cz.cvut.fel.aic.alite.common.event.EventHandler; +import cz.cvut.fel.aic.alite.common.event.EventProcessor; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; +import cz.cvut.fel.aic.geographtools.Node; +import cz.cvut.fel.aic.simod.config.SimodConfig; +import cz.cvut.fel.aic.simod.event.OnDemandVehicleEvent; +import cz.cvut.fel.aic.simod.ridesharing.DARPSolver; +import cz.cvut.fel.aic.simod.ridesharing.DroppedDemandsAnalyzer; +import cz.cvut.fel.aic.simod.ridesharing.PlanCostProvider; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.TransferPlan; +import cz.cvut.fel.aic.simod.ridesharing.insertionheuristic.DriverPlan; +import cz.cvut.fel.aic.simod.ridesharing.model.*; +import cz.cvut.fel.aic.simod.storage.OnDemandVehicleStorage; +import cz.cvut.fel.aic.simod.storage.OnDemandvehicleStationStorage; +import cz.cvut.fel.aic.simod.traveltimecomputation.TravelTimeProvider; +import org.jgrapht.alg.util.Pair; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Singleton +public class TransferInsertionSolver extends DARPSolver implements EventHandler { + + private final TypedSimulation eventProcessor; + + private final SimodConfig config; + + private final TimeProvider timeProvider; + + private final PositionUtil positionUtil; + + private final DroppedDemandsAnalyzer droppedDemandsAnalyzer; + + private final OnDemandvehicleStationStorage onDemandvehicleStationStorage; + + + private List transferPoints; + + protected final DefaultPlanComputationRequest.DefaultPlanComputationRequestFactory requestFactory; + + private Map planMap; + + protected List> inactiveVehicles; + + protected List> waitingTimes; + + protected List> demandTripMinimalLength; + + + @Inject + public TransferInsertionSolver( + OnDemandVehicleStorage vehicleStorage, + TravelTimeProvider travelTimeProvider, + PlanCostProvider travelCostProvider, + DefaultPlanComputationRequest.DefaultPlanComputationRequestFactory requestFactory, + TypedSimulation eventProcessor, + SimodConfig config, + TimeProvider timeProvider, + PositionUtil positionUtil, + DroppedDemandsAnalyzer droppedDemandsAnalyzer, + OnDemandvehicleStationStorage onDemandvehicleStationStorage, + AgentpolisConfig agentpolisConfig) { + + super(vehicleStorage, travelTimeProvider, travelCostProvider, requestFactory); + this.eventProcessor = eventProcessor; + this.config = config; + this.timeProvider = timeProvider; + this.positionUtil = positionUtil; + this.droppedDemandsAnalyzer = droppedDemandsAnalyzer; + this.onDemandvehicleStationStorage = onDemandvehicleStationStorage; + this.requestFactory = requestFactory; + inactiveVehicles = new ArrayList<>(); + waitingTimes = new ArrayList<>(); + demandTripMinimalLength = new ArrayList<>(); + + setEventHandeling(); + } + + public void setTransferPoints(List transferPoints) { + this.transferPoints = transferPoints; + } + + @Override + public EventProcessor getEventProcessor() { + return eventProcessor; + } + + @Override + public void handleEvent(Event event) { + + } + + private void setEventHandeling() { + List typesToHandle = new LinkedList<>(); + + typesToHandle.add(OnDemandVehicleEvent.PICKUP); + eventProcessor.addEventHandler(this, typesToHandle); + } + + private void logWaitingTime(RideSharingOnDemandVehicle vehicle, Integer waitTimeInSeconds) { + waitingTimes.add(new Pair(vehicle.getId(), waitTimeInSeconds)); + } + + private void logInactiveVehicles(List vehicles) { + for (RideSharingOnDemandVehicle vehicle : vehicles) { + if (vehicle.getCurrentPlanNoUpdate().plan.size() == 1) { + if (!planMap.containsKey(vehicle)) { + // toto vozidlo ma prazdny plan + inactiveVehicles.add(new Pair(vehicle.getId(), (int) Math.round(timeProvider.getCurrentSimTime() / 1000.0))); + } + } + } + } + + @Override + public Map solve(List newRequests, List waitingRequests) { + + // nacist taxiky + List taxis = new ArrayList<>(); + for(AgentPolisEntity tVvehicle: vehicleStorage.getEntitiesForIteration()) { + RideSharingOnDemandVehicle vehicle = (RideSharingOnDemandVehicle) tVvehicle; + taxis.add(vehicle); + } + // nacist requesty + List requests = new ArrayList<>(newRequests); + + // ke kazdemu requestu priradit auta, ktera k nemu mohou dojet vcas + int[] possiblePickupTaxisCounts = new int[requests.size()]; + int i = 0; + Map> possiblePickupTaxisMap = new HashMap<>(); + for(PlanComputationRequest request : requests) { + int counter = 0; + List possiblePickupTaxisOneRequest = new ArrayList<>(); + for(RideSharingOnDemandVehicle t : taxis) { + if (canPickupRequestInTime(t, request)) { + counter++; + possiblePickupTaxisOneRequest.add(t); + } + } + possiblePickupTaxisCounts[i] = counter; + possiblePickupTaxisMap.put(request, possiblePickupTaxisOneRequest); + i++; + } + + //sort R by the number of possible pickup taxis + List requestsCopy = new ArrayList<>(requests); + requests.sort(Comparator.comparing(x -> possiblePickupTaxisCounts[requestsCopy.indexOf(x)])); + + + planMap = new ConcurrentHashMap<>(); + + for (PlanComputationRequest request : requests) { + List>, List>> itinerariesPairs = new ArrayList<>(); + List canPickupRequestTaxis = possiblePickupTaxisMap.get(request); + List delays = new ArrayList<>(); + List waitTimes = new ArrayList<>(); + + long minimalTravelTime = travelTimeProvider.getExpectedTravelTime(request.getFrom(), request.getTo()); + for (RideSharingOnDemandVehicle taxi : canPickupRequestTaxis) { + List positnry = findItineraryBestInsertion(request.getPickUpAction(), request.getDropOffAction(), taxi); + if (positnry != null) { + Long dropoffTime = getDropoffTimeForRequest(positnry, taxi, request); + if (dropoffTime == null) { + // chyba + continue; + } + delays.add(dropoffTime - timeProvider.getCurrentSimTime() - minimalTravelTime); + waitTimes.add((long)0); + List> listItinerary = new ArrayList<>(); + listItinerary.add(positnry); + List vehicles = new ArrayList<>(); + vehicles.add(taxi); + itinerariesPairs.add(new Pair<>(listItinerary, vehicles)); + } + + for (SimulationNode station : transferPoints) { + if (timeProvider.getCurrentSimTime() + travelTimeProvider.getTravelTime(taxi, request.getFrom()) + travelTimeProvider.getExpectedTravelTime(request.getFrom(), station) > + request.getMaxDropoffTime() * 1000 - travelTimeProvider.getExpectedTravelTime(station, request.getTo())) { + continue; + } + // najit auta, do kterych je mozne prestoupit + for (int k = 0; k < taxis.size(); k++) { + if (taxi.equals(taxis.get(k))) { + continue; + } else if (station == request.getTo()) { + continue; + } else if (station == request.getFrom()) { + continue; + } else if (timeProvider.getCurrentSimTime() + travelTimeProvider.getTravelTime(taxis.get(k), station) > + request.getMaxDropoffTime() * 1000 - travelTimeProvider.getExpectedTravelTime(station, request.getTo())) { + continue; + } else { + int maxDropOffTime = request.getMaxDropoffTime() - (int) Math.round(travelTimeProvider.getExpectedTravelTime(station, request.getTo()) / 1000.0); + + PlanActionDropoffTransfer dropoffActionTransfer = new PlanActionDropoffTransfer(request, station, maxDropOffTime); + PlanActionPickupTransfer pickupActionTransfer = new PlanActionPickupTransfer(request, station, maxDropOffTime); + + // prvni usek = ceil + List itnryp1 = findItineraryBestInsertionFirstSegment(request.getPickUpAction(), dropoffActionTransfer, taxi); + if (itnryp1 == null) { + continue; + } + Integer dropTime = getDropoffTimeForRequestFirstSegment(itnryp1, taxi, request); + + // druhy usek = floor + List itnryp2 = findTransferItineraryBestInsertionSecondSegment(pickupActionTransfer, request.getDropOffAction(), taxis.get(k), dropTime); + if (itnryp2 == null) { + continue; + } + int maxTransferTime = countMaxTimeTransferRound(itnryp1, taxi, itnryp2, taxis.get(k), request); + for (PlanAction action : itnryp1) { + if (action.equals(dropoffActionTransfer)) { + ((PlanActionDropoffTransfer)action).setMaxTime(maxTransferTime); + } + } + Integer dropoffTime = getDropoffTimeForRequestFirstSegment(itnryp2, taxis.get(k), request); + if (dropoffTime == null) { + // chyba + continue; + } + delays.add(dropoffTime * 1000 - timeProvider.getCurrentSimTime() - minimalTravelTime); + + long waitTime = getWaitTimeForRequest(itnryp2, request); + waitTimes.add(waitTime); + + List> listItinerary = new ArrayList<>(); + listItinerary.add(itnryp1); + listItinerary.add(itnryp2); + List vehicles = new ArrayList<>(); + vehicles.add(taxi); + vehicles.add(taxis.get(k)); + itinerariesPairs.add(new Pair<>(listItinerary, vehicles)); + + } + } + } + } + + List transferPlans = new ArrayList<>(); + for (int j = 0; j < itinerariesPairs.size(); j++) { + TransferPlan t = new TransferPlan(waitTimes.get(j), delays.get(j), itinerariesPairs.get(j)); + transferPlans.add(t); + } + transferPlans.sort(TransferPlan::compareByTransferTime); + double beta = 0.2; + int numOfTaken = (int) (transferPlans.size() * beta); + if (numOfTaken == 0) { + numOfTaken = 1; + } + List sublistTransferPlans = new ArrayList<>(); + for (int q = 0; q < numOfTaken; q++) + { + if(!transferPlans.isEmpty()) { + sublistTransferPlans.add(transferPlans.get(q)); + } + } + sublistTransferPlans.sort(TransferPlan::compareByDelay); + + if (!sublistTransferPlans.isEmpty()) { + Pair>, List> key = sublistTransferPlans.get(0).pair; + List> plansForVehicles = key.getFirst(); + List vehicles = key.getSecond(); + for (int q = 0; q < vehicles.size(); q++) { + List vehPlan = plansForVehicles.get(q); + int waitTime = findWaitingAction(vehPlan, vehicles.get(q), request); + if (waitTime > 0) { + logWaitingTime(vehicles.get(q), waitTime); + } + DriverPlan dp = new DriverPlan(vehPlan, 0, 0); + planMap.put(vehicles.get(q), dp); + } + + } + } + + logInactiveVehicles(taxis); + + return planMap; + } + + public Integer findWaitingAction(List plan, RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + for (PlanAction action : plan) { + if (action instanceof PlanActionWait) { + if (((PlanActionWait) action).getRequest() == request) { + PlanActionWait wait = (PlanActionWait) action; + return (int) Math.round(wait.getWaitTime() / 1000.0); + } + } + } + return 0; + } + + public List> getInactiveVehicles() { + return inactiveVehicles; + } + + public List> getWaitingTimes() { + return waitingTimes; + } + + public List findItineraryBestInsertionFirstSegment(PlanAction pickup, PlanAction dropoff, RideSharingOnDemandVehicle vehicle) { + DriverPlan currentVehiclePlan; + if (planMap.containsKey(vehicle)) { + currentVehiclePlan = planMap.get(vehicle); + } else { + currentVehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + List> allPosibleActionsOrder = new ArrayList<>(); + List planDurations = new ArrayList<>(); + Pair originalPlanPair = checkValidItineraryAndCountPlanDurationFirstPart(currentVehiclePlan.plan, vehicle); + Integer durationOriginalPlan = originalPlanPair.getSecond(); + + for (int i = 1; i < currentVehiclePlan.plan.size()+1; i++) { + for (int j = i+1; j < currentVehiclePlan.plan.size()+2; j++) { + List tempPlan = new ArrayList<>(currentVehiclePlan.plan); + tempPlan.add(i, pickup); + tempPlan.add(j, dropoff); + Pair p = checkValidItineraryAndCountPlanDurationFirstPart(tempPlan, vehicle); + if (p.getFirst()) { + if (checkCapacityNotExceeded(tempPlan, vehicle)) { + allPosibleActionsOrder.add(tempPlan); + planDurations.add(p.getSecond() - durationOriginalPlan); + } + } + } + } + + if (allPosibleActionsOrder.isEmpty()) { + return null; + } + + int minIndex = planDurations.indexOf(Collections.min(planDurations)); + List selectedPlan = allPosibleActionsOrder.get(minIndex); + + return selectedPlan; + } + + public List findTransferItineraryBestInsertionSecondSegment(PlanAction pickup, PlanAction dropoff, RideSharingOnDemandVehicle vehicle, int arrivalToStationForVeh1) { + DriverPlan currentVehiclePlan; + if (planMap.containsKey(vehicle)) { + currentVehiclePlan = planMap.get(vehicle); + } else { + currentVehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + List> allPosibleActionsOrder = new ArrayList<>(); + List planDurations = new ArrayList<>(); + Pair originalPlanPair = checkValidItineraryAndCountPlanDurationSecondPart(currentVehiclePlan.plan, vehicle); + Integer durationOriginalPlan = originalPlanPair.getSecond(); + + + for (int i = 1; i < currentVehiclePlan.plan.size()+1; i++) { + for (int j = i+1; j < currentVehiclePlan.plan.size()+2; j++) { + List tempPlan = new ArrayList<>(currentVehiclePlan.plan); + tempPlan.add(i, pickup); + tempPlan.add(j, dropoff); + Integer arrivalTime = getArrivalTimeToStationIntFloor(tempPlan, vehicle, ((PlanRequestAction)pickup).request); + assert arrivalTime != null; + int waitTime = arrivalToStationForVeh1 - arrivalTime; + if (waitTime > 0) { + PlanActionWait waitAction = new PlanActionWait(((PlanRequestAction)pickup).request, pickup.getPosition(), ((PlanRequestAction) pickup).getMaxTime(), waitTime * 1000); + tempPlan.add(i, waitAction); + } + Pair p = checkValidItineraryAndCountPlanDurationSecondPart(tempPlan, vehicle); + if (p.getFirst()) { + if (checkCapacityNotExceeded(tempPlan, vehicle)) { + allPosibleActionsOrder.add(tempPlan); + planDurations.add(p.getSecond() - durationOriginalPlan); + } + } + } + } + + if (allPosibleActionsOrder.isEmpty()) { + return null; + } + + int minIndex = planDurations.indexOf(Collections.min(planDurations)); + List selectedPlan = allPosibleActionsOrder.get(minIndex); + + return selectedPlan; + } + + public List findItineraryBestInsertion(PlanAction pickup, PlanAction dropoff, RideSharingOnDemandVehicle vehicle) { + DriverPlan currentVehiclePlan; + if (planMap.containsKey(vehicle)) { + currentVehiclePlan = planMap.get(vehicle); + } else { + currentVehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + List> allPosibleActionsOrder = new ArrayList<>(); + List planDurations = new ArrayList<>(); + Pair originalPlanPair = checkValidItineraryAndCountPlanDuration(currentVehiclePlan.plan, vehicle); + Long durationOriginalPlan = originalPlanPair.getSecond(); + + + for (int i = 1; i < currentVehiclePlan.plan.size()+1; i++) { + for (int j = i+1; j < currentVehiclePlan.plan.size()+2; j++) { + List tempPlan = new ArrayList<>(currentVehiclePlan.plan); + tempPlan.add(i, pickup); + tempPlan.add(j, dropoff); + Pair p = checkValidItineraryAndCountPlanDuration(tempPlan, vehicle); + if (p.getFirst()) { + if (checkCapacityNotExceeded(tempPlan, vehicle)) { + allPosibleActionsOrder.add(tempPlan); + planDurations.add(p.getSecond() - durationOriginalPlan); + } + } + } + } + + if (allPosibleActionsOrder.isEmpty()) { + return null; + } + + int minIndex = planDurations.indexOf(Collections.min(planDurations)); + List selectedPlan = allPosibleActionsOrder.get(minIndex); + + return selectedPlan; + } + + public List findTransferItineraryBestInsertion(PlanAction pickup, PlanAction dropoff, RideSharingOnDemandVehicle vehicle, Long arrivalToStationForVeh1) { + DriverPlan currentVehiclePlan; + if (planMap.containsKey(vehicle)) { + currentVehiclePlan = planMap.get(vehicle); + } else { + currentVehiclePlan = vehicle.getCurrentPlanNoUpdate(); + } + List> allPosibleActionsOrder = new ArrayList<>(); + List planDurations = new ArrayList<>(); + + for (int i = 1; i < currentVehiclePlan.plan.size()+1; i++) { + for (int j = i+1; j < currentVehiclePlan.plan.size()+2; j++) { + List tempPlan = new ArrayList<>(currentVehiclePlan.plan); + tempPlan.add(i, pickup); + tempPlan.add(j, dropoff); + Long arrivalTime = getArrivalTimeToStation(tempPlan, vehicle, ((PlanRequestAction)pickup).request); + assert arrivalTime != null; + long waitTime = arrivalToStationForVeh1 - arrivalTime; + if (waitTime >= 0) { + waitTime += 3000; + PlanActionWait waitAction = new PlanActionWait(((PlanRequestAction)pickup).request, pickup.getPosition(), ((PlanRequestAction) pickup).getMaxTime(), waitTime); + tempPlan.add(i, waitAction); + } + else if (waitTime < 0 && waitTime > -3000) { + waitTime -= 3000; + PlanActionWait waitAction = new PlanActionWait(((PlanRequestAction)pickup).request, pickup.getPosition(), ((PlanRequestAction) pickup).getMaxTime(), -waitTime); + tempPlan.add(i, waitAction); + } + Pair p = checkValidItineraryAndCountPlanDuration(tempPlan, vehicle); + if (p.getFirst()) { + if (checkCapacityNotExceeded(tempPlan, vehicle)) { + allPosibleActionsOrder.add(tempPlan); + planDurations.add(p.getSecond()); + } + } + } + } + + if (allPosibleActionsOrder.isEmpty()) { + return null; + } + + int minIndex = planDurations.indexOf(Collections.min(planDurations)); + List selectedPlan = allPosibleActionsOrder.get(minIndex); + + return selectedPlan; + } + + public long getWaitTimeForRequest(List itinerary, PlanComputationRequest request) { + for (PlanAction action : itinerary) { + if (action instanceof PlanActionWait) { + if (((PlanActionWait) action).request == request) { + return ((PlanActionWait) action).getWaitTime(); + } + } + } + return -1; + } + + public int countMaxTimeTransfer(List itnryp1, RideSharingOnDemandVehicle veh1, List itnryp2, RideSharingOnDemandVehicle veh2, PlanComputationRequest request) { + boolean isWaitInItnryp2 = false; + for (PlanAction action : itnryp2) { + if (action instanceof PlanActionWait) { + if (((PlanActionWait) action).request == request) { + isWaitInItnryp2 = true; + } + } + } + if (isWaitInItnryp2) { + Long dropTime = getDropoffTimeForRequest(itnryp1, veh1, request); + int time = (int) Math.round(dropTime / 1000.0); + return time; + } else { + Long dropTime = getArrivalTimeToStation(itnryp2, veh2, request); + int time = (int) Math.round(dropTime / 1000.0); + return time - 2; + } + } + + public int countMaxTimeTransferRound(List itnryp1, RideSharingOnDemandVehicle veh1, List itnryp2, RideSharingOnDemandVehicle veh2, PlanComputationRequest request) { + boolean isWaitInItnryp2 = false; + for (PlanAction action : itnryp2) { + if (action instanceof PlanActionWait) { + if (((PlanActionWait) action).request == request) { + isWaitInItnryp2 = true; + } + } + } + if (isWaitInItnryp2) { + Integer dropTime = getDropoffTimeForRequestFirstSegment(itnryp1, veh1, request); + return dropTime; + } else { + Integer dropTime = getArrivalTimeToStationIntFloor(itnryp2, veh2, request); + return dropTime; + } + } + + public boolean canPickupRequestInTime(RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + SimulationNode previousDestination = vehicle.getPosition(); + + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time += timeToFinishEdge; + + long timeToNewPickup = travelTimeProvider.getExpectedTravelTime(previousDestination, request.getFrom()); + time += timeToNewPickup; + + if (!(time > request.getMaxPickupTime() * 1000)) { + return true; + } + return false; + + } + + private boolean checkCapacityNotExceeded(List itinerary, RideSharingOnDemandVehicle vehicle) { + int freeCapacity = vehicle.getFreeCapacity(); + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + freeCapacity -= 1; + if (freeCapacity < 0) { + return false; + } + } + else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + freeCapacity += 1; + } + } + return true; + } + + private Pair checkValidItineraryAndCountPlanDuration(List itinerary, RideSharingOnDemandVehicle vehicle) { + SimulationNode previousDestination; + boolean ret = true; + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + previousDestination = vehicle.getPosition(); + + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time += timeToFinishEdge; + + for (PlanAction action : itinerary) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxPickupTime() * 1000)) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= pickupTransfer.getMaxTime() * 1000)) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time <= dropoffTransfer.getMaxTime() * 1000)) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + if (!(time < pcq.getMaxDropoffTime() * 1000)) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + SimulationNode dest = action.getPosition(); + PlanActionWait wait = (PlanActionWait) action; + if (!(wait.isWaitingStarted())) { + time += wait.getWaitTime(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + } + time = time + waitTime; + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = action.getPosition(); + } + } + } + } + Pair p = new Pair<>(ret, time); + return p; + } + + private Pair checkValidItineraryAndCountPlanDurationFirstPart(List itinerary, RideSharingOnDemandVehicle vehicle) { + SimulationNode previousDestination; + boolean ret = true; + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + previousDestination = vehicle.getPosition(); + int timeRounded = (int) Math.ceil(timeProvider.getCurrentSimTime() / 1000.0); + + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time += timeToFinishEdge; + timeRounded += (int) Math.ceil(timeToFinishEdge / 1000.0); + + for (PlanAction action : itinerary) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded < pcq.getMaxPickupTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded <= pickupTransfer.getMaxTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded <= dropoffTransfer.getMaxTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded < pcq.getMaxDropoffTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + SimulationNode dest = action.getPosition(); + PlanActionWait wait = (PlanActionWait) action; + if (!(wait.isWaitingStarted())) { + time += wait.getWaitTime(); + timeRounded += (int) Math.ceil(wait.getWaitTime() / 1000.0); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + } + time = time + waitTime; + timeRounded += (int) Math.ceil(wait.getWaitTime() / 1000.0); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = action.getPosition(); + } + } + } + } + Pair p = new Pair<>(ret, timeRounded); + return p; + } + + private Pair checkValidItineraryAndCountPlanDurationSecondPart(List itinerary, RideSharingOnDemandVehicle vehicle) { + SimulationNode previousDestination; + boolean ret = true; + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + previousDestination = vehicle.getPosition(); + int timeRounded = (int) Math.floor(timeProvider.getCurrentSimTime() / 1000.0); + + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time += timeToFinishEdge; + timeRounded += (int) Math.floor(timeToFinishEdge / 1000.0); + + for (PlanAction action : itinerary) { + if (action instanceof PlanRequestAction) { + PlanComputationRequest pcq = ((PlanRequestAction) action).getRequest(); + if (action instanceof PlanActionPickup) { + SimulationNode dest = pcq.getFrom(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded < pcq.getMaxPickupTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionPickupTransfer) { + PlanActionPickupTransfer pickupTransfer = (PlanActionPickupTransfer) action; + SimulationNode dest = pickupTransfer.getPosition(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded <= pickupTransfer.getMaxTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if(action instanceof PlanActionDropoffTransfer) { + PlanActionDropoffTransfer dropoffTransfer = (PlanActionDropoffTransfer) action; + SimulationNode dest = dropoffTransfer.getPosition(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded <= dropoffTransfer.getMaxTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionDropoff) { + SimulationNode dest = pcq.getTo(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + if (!(timeRounded < pcq.getMaxDropoffTime())) { + ret = false; + break; + } + previousDestination = dest; + } else if (action instanceof PlanActionWait) { + SimulationNode dest = action.getPosition(); + PlanActionWait wait = (PlanActionWait) action; + if (!(wait.isWaitingStarted())) { + time += wait.getWaitTime(); + timeRounded += (int) Math.floor(wait.getWaitTime() / 1000.0); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + } + time = time + waitTime; + timeRounded += (int) Math.floor(wait.getWaitTime() / 1000.0); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeRounded += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, dest) / 1000.0); + previousDestination = action.getPosition(); + } + } + } + } + Pair p = new Pair<>(ret, timeRounded); + return p; + } + + private Integer getDropoffTimeForRequestFirstSegment(List itinerary, RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + int timeInt = (int) Math.ceil(timeProvider.getCurrentSimTime() / 1000.0); + SimulationNode previousDestination = vehicle.getPosition(); + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time = time + timeToFinishEdge; + timeInt += (int) Math.ceil(timeToFinishEdge / 1000.0); + + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + timeInt += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()) / 1000.0); + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + timeInt += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()) / 1000.0); + if (((PlanRequestAction) action).getRequest() == request) { + return timeInt; + } + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionWait) { + SimulationNode dest = action.getPosition(); + PlanActionWait wait = (PlanActionWait) action; + if (!(wait.isWaitingStarted())) { + time = time + wait.getWaitTime(); + timeInt += (int) Math.ceil(wait.getWaitTime()); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeInt += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()) / 1000.0); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + } + time = time + waitTime; + timeInt += (int) Math.ceil(wait.getWaitTime()); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeInt += (int) Math.ceil(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()) / 1000.0); + previousDestination = action.getPosition(); + } + } + } + return null; + } + + + private Long getDropoffTimeForRequest(List itinerary, RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + SimulationNode previousDestination = vehicle.getPosition(); + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time = time + timeToFinishEdge; + + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + if (((PlanRequestAction) action).getRequest() == request) { + return time; + } + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionWait) { + SimulationNode dest = action.getPosition(); + PlanActionWait wait = (PlanActionWait) action; + if (!(wait.isWaitingStarted())) { + time = time + wait.getWaitTime(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + } + time = time + waitTime; + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = action.getPosition(); + } + } + } + return null; + } + + private Long getArrivalTimeToStation(List itinerary, RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + long time = timeProvider.getCurrentSimTime(); + long timeToFinishEdge = 0; + SimulationNode previousDestination = vehicle.getPosition(); + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time = time + timeToFinishEdge; + + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + if (((PlanRequestAction) action).getRequest() == request) { + return time; + } + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + SimulationNode dest = action.getPosition(); + if (!(wait.isWaitingStarted())) { + time = time + wait.getWaitTime(); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + + } + time = time + waitTime; + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + previousDestination = action.getPosition(); + } + } + + } + return null; + } + + private Integer getArrivalTimeToStationIntFloor(List itinerary, RideSharingOnDemandVehicle vehicle, PlanComputationRequest request) { + long time = timeProvider.getCurrentSimTime(); + int timeInt = (int) Math.floor(timeProvider.getCurrentSimTime() / 1000.0); + long timeToFinishEdge = 0; + SimulationNode previousDestination = vehicle.getPosition(); + if (vehicle.getCurrentTripPlan() != null) { + if (vehicle.getCurrentTripPlan().getSize() == 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getLastLocation(); + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, stopLoc); + previousDestination = stopLoc; + } + else if (vehicle.getCurrentTripPlan().getSize() > 0) { + SimulationNode stopLoc = (SimulationNode) vehicle.getCurrentTripPlan().getFirstLocation(); + SimulationNode currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[0]; + boolean currLocIsVehiclePosition = false; + int curridx = 0; + while (currLoc != stopLoc) { + if (currLocIsVehiclePosition) { + timeToFinishEdge += travelTimeProvider.getTravelTime(vehicle, currLoc); + } + if (currLoc == vehicle.getPosition()) { + currLocIsVehiclePosition = true; + } + previousDestination = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + curridx++; + currLoc = (SimulationNode) vehicle.getCurrentTripPlan().getAllLocations()[curridx]; + } + } + } + time = time + timeToFinishEdge; + timeInt += (int) Math.floor(timeToFinishEdge / 1000.0); + + for (PlanAction action : itinerary) { + if (action instanceof PlanActionPickup || action instanceof PlanActionPickupTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + timeInt += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition())/1000.0); + if (((PlanRequestAction) action).getRequest() == request) { + return timeInt; + } + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionDropoff || action instanceof PlanActionDropoffTransfer) { + time = time + travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition()); + timeInt += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition())/1000.0); + previousDestination = action.getPosition(); + } else if (action instanceof PlanActionWait) { + PlanActionWait wait = (PlanActionWait) action; + SimulationNode dest = action.getPosition(); + if (!(wait.isWaitingStarted())) { + time = time + wait.getWaitTime(); + timeInt += (int) Math.floor(wait.getWaitTime() / 1000.0); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeInt += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition())/1000.0); + previousDestination = action.getPosition(); + } else { + long substract; + long waitTime; + if (wait.isWaitingPaused()) { + substract = wait.getWaitingPausedAt() - wait.getWaitingStartedAt(); + waitTime = wait.getWaitTime() - substract; + } else { + waitTime = wait.getWaitTime() - (timeProvider.getCurrentSimTime() - wait.getWaitingStartedAt()); + + } + time = time + waitTime; + timeInt += (int) Math.floor(waitTime / 1000.0); + time += travelTimeProvider.getExpectedTravelTime(previousDestination, dest); + timeInt += (int) Math.floor(travelTimeProvider.getExpectedTravelTime(previousDestination, action.getPosition())/1000.0); + previousDestination = action.getPosition(); + } + } + + } + return null; + } +} diff --git a/src/main/java/cz/cvut/fel/aic/simod/statistics/Result.java b/src/main/java/cz/cvut/fel/aic/simod/statistics/Result.java index 37765757..7ce4e571 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/statistics/Result.java +++ b/src/main/java/cz/cvut/fel/aic/simod/statistics/Result.java @@ -55,6 +55,8 @@ public class Result { private final long totalDistanceRebalancing; + private final int transfersDone; + @@ -122,6 +124,8 @@ public long getTotalDistanceToStation() { public long getTotalDistanceRebalancing() { return totalDistanceRebalancing; } + + public int getTransfersDone() { return transfersDone; } @@ -134,7 +138,7 @@ public Result(long tickCount, double averageLoadTotal, int maxLoad, double avera double averageKmToStartLocation, double averageKmToStation, double averageKmRebalancing, int numberOfDemandsNotServedFromNearestStation, int numberOfDemandsDropped, int demandsCount, int numberOfVehicles, int numberOfRebalancingDropped, long totalDistanceWithPassenger, - long totalDistanceToStartLocation, long totalDistanceToStation, long totalDistanceRebalancing) { + long totalDistanceToStartLocation, long totalDistanceToStation, long totalDistanceRebalancing, int transfersDone) { this.tickCount = tickCount; this.averageLoadTotal = averageLoadTotal; this.maxLoad = maxLoad; @@ -151,6 +155,7 @@ public Result(long tickCount, double averageLoadTotal, int maxLoad, double avera this.totalDistanceToStartLocation = totalDistanceToStartLocation; this.totalDistanceToStation = totalDistanceToStation; this.totalDistanceRebalancing = totalDistanceRebalancing; + this.transfersDone = transfersDone; } diff --git a/src/main/java/cz/cvut/fel/aic/simod/statistics/StatisticEvent.java b/src/main/java/cz/cvut/fel/aic/simod/statistics/StatisticEvent.java index b6c98667..c3a32370 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/statistics/StatisticEvent.java +++ b/src/main/java/cz/cvut/fel/aic/simod/statistics/StatisticEvent.java @@ -25,5 +25,6 @@ public enum StatisticEvent { TICK, VEHICLE_LEFT_STATION_TO_SERVE_DEMAND, - DEMAND_DROPPED_OFF + DEMAND_DROPPED_OFF, + DEMAND_DROPPED_AT_TRANSFER } diff --git a/src/main/java/cz/cvut/fel/aic/simod/statistics/Statistics.java b/src/main/java/cz/cvut/fel/aic/simod/statistics/Statistics.java index 1a562e7a..0d343cb0 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/statistics/Statistics.java +++ b/src/main/java/cz/cvut/fel/aic/simod/statistics/Statistics.java @@ -31,6 +31,7 @@ import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; import cz.cvut.fel.aic.simod.CsvWriter; import cz.cvut.fel.aic.simod.StationsDispatcher; +import cz.cvut.fel.aic.simod.config.InsertionHeuristic; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.entity.OnDemandVehicleState; import cz.cvut.fel.aic.simod.entity.vehicle.OnDemandVehicle; @@ -38,7 +39,12 @@ import cz.cvut.fel.aic.simod.event.OnDemandVehicleEventContent; import cz.cvut.fel.aic.simod.io.Common; import cz.cvut.fel.aic.simod.ridesharing.DARPSolver; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.insertionheuristic.InsertionHeuristicSolver; +import org.jgrapht.alg.util.Pair; import cz.cvut.fel.aic.simod.ridesharing.RidesharingDispatcher; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.GreedyTASeTSolver; +import cz.cvut.fel.aic.simod.ridesharing.transferinsertion.TransferInsertionSolver; import cz.cvut.fel.aic.simod.statistics.content.RidesharingBatchStats; import cz.cvut.fel.aic.simod.statistics.content.RidesharingBatchStatsIH; import cz.cvut.fel.aic.simod.statistics.content.RidesharingBatchStatsVGA; @@ -123,6 +129,8 @@ public class Statistics extends AliteEntity implements EventHandler{ private long totalDistanceToStation; private long totalDistanceRebalancing; + + private int transfersDone; @@ -158,6 +166,7 @@ public Statistics(TypedSimulation eventProcessor, Provider all tickCount = 0; averageEdgeLoad = new LinkedList<>(); maxLoad = 0; + transfersDone = 0; eventProcessor.addEventHandler(this); init(eventProcessor); @@ -179,6 +188,9 @@ public void handleEvent(Event event) { case DEMAND_DROPPED_OFF: handleDemandDropoff((DemandServiceStatistic) event.getContent()); break; + case DEMAND_DROPPED_AT_TRANSFER: + handleTransfer(); + break; } } else if(event.getType() instanceof OnDemandVehicleEvent){ @@ -215,6 +227,10 @@ private void measure() { countEdgeLoadForInterval(); countVehicleOccupancyForInterval(); } + + private void handleTransfer() { + transfersDone++; + } private void saveResult(){ @@ -226,7 +242,7 @@ private void saveResult(){ onDemandVehicleStationsCentral.getNumberOfDemandsDropped(), onDemandVehicleStationsCentral.getDemandsCount(), numberOfVehicles, onDemandVehicleStationsCentral.getNumberOfRebalancingDropped(), totalDistanceWithPassenger, - totalDistanceToStartLocation, totalDistanceToStation, totalDistanceRebalancing); + totalDistanceToStartLocation, totalDistanceToStation, totalDistanceRebalancing, transfersDone); ObjectMapper mapper = new ObjectMapper(); @@ -246,6 +262,8 @@ public void simulationFinished() { saveOnDemandVehicleEvents(); saveDistances(); saveOccupancies(); + saveInactiveVehicles(); + saveWaitingTimes(); saveServiceStatistics(); if(onDemandVehicleStationsCentral instanceof RidesharingDispatcher){ saveDarpSolverComputationalTimes(); @@ -271,6 +289,7 @@ protected List getEventTypesToHandle() { typesToHandle.add(OnDemandVehicleEvent.REACH_NEAREST_STATION); typesToHandle.add(DriveEvent.VEHICLE_ENTERED_EDGE); typesToHandle.add(StatisticEvent.DEMAND_DROPPED_OFF); + typesToHandle.add(StatisticEvent.DEMAND_DROPPED_AT_TRANSFER); return typesToHandle; } @@ -426,6 +445,91 @@ private void saveServiceStatistics() { LOGGER.error(null, ex); } } + + private void saveWaitingTimes() { + if (dARPSolver instanceof TransferInsertionSolver) { + TransferInsertionSolver transferInsertionSolver = (TransferInsertionSolver) dARPSolver; + if (transferInsertionSolver.getWaitingTimes().size() < 1) { + return; + } + try { + CsvWriter writer = new CsvWriter(Common.getFileWriter(config.statistics.waitingTimesFilePath)); + writer.writeLine("id", "waiting_time"); + for (Pair waitingTimesPair : transferInsertionSolver.getWaitingTimes()) { + writer.writeLine(waitingTimesPair.getFirst(), Integer.toString(waitingTimesPair.getSecond())); + } + writer.close(); + } catch (IOException ex) { + LOGGER.error(null, ex); + } + } else if (dARPSolver instanceof GreedyTASeTSolver) { + GreedyTASeTSolver greedyTASeTSolver = (GreedyTASeTSolver) dARPSolver; + if (greedyTASeTSolver.getInactiveVehicles().size() < 1) { + return; + } + try { + CsvWriter writer = new CsvWriter(Common.getFileWriter(config.statistics.waitingTimesFilePath)); + writer.writeLine("id", "waiting_time"); + for (Pair waitingTimesPair : greedyTASeTSolver.getWaitingTimes()) { + writer.writeLine(waitingTimesPair.getFirst(), Integer.toString(waitingTimesPair.getSecond())); + } + writer.close(); + } catch (IOException ex) { + LOGGER.error(null, ex); + } + } + } + private void saveInactiveVehicles() { + if (dARPSolver instanceof TransferInsertionSolver) { + TransferInsertionSolver transferInsertionSolver = (TransferInsertionSolver) dARPSolver; + if (transferInsertionSolver.getInactiveVehicles().size() < 1) { + return; + } + try { + CsvWriter writer = new CsvWriter(Common.getFileWriter(config.statistics.inactiveVehiclesFilePath)); + writer.writeLine("id", "time"); + for (Pair inactiveVehiclePair: transferInsertionSolver.getInactiveVehicles()) { + writer.writeLine(inactiveVehiclePair.getFirst(), Integer.toString(inactiveVehiclePair.getSecond())); + } + writer.close(); + } catch (IOException ex) { + LOGGER.error(null, ex); + } + + } else if (dARPSolver instanceof GreedyTASeTSolver) { + GreedyTASeTSolver greedyTASeTSolver = (GreedyTASeTSolver) dARPSolver; + if (greedyTASeTSolver.getInactiveVehicles().size() < 1) { + return; + } + try { + CsvWriter writer = new CsvWriter(Common.getFileWriter(config.statistics.inactiveVehiclesFilePath)); + writer.writeLine("id", "time"); + for (Pair inactiveVehiclePair: greedyTASeTSolver.getInactiveVehicles()) { + writer.writeLine(inactiveVehiclePair.getFirst(), Integer.toString(inactiveVehiclePair.getSecond())); + } + writer.close(); + } catch (IOException ex) { + LOGGER.error(null, ex); + } + } else if (dARPSolver instanceof InsertionHeuristicSolver) { + InsertionHeuristicSolver insertionHeuristicSolver = (InsertionHeuristicSolver) dARPSolver; + if (insertionHeuristicSolver.getInactiveVehicles().size() < 1) { + return; + } + try { + CsvWriter writer = new CsvWriter(Common.getFileWriter(config.statistics.inactiveVehiclesFilePath)); + writer.writeLine("id", "time"); + for (Pair inactiveVehiclePair: insertionHeuristicSolver.getInactiveVehicles()) { + writer.writeLine(inactiveVehiclePair.getFirst(), Integer.toString(inactiveVehiclePair.getSecond())); + } + writer.close(); + } catch (IOException ex) { + LOGGER.error(null, ex); + } + + } + + } private void saveRidesharingStatistics() { int highestGroup = 0; @@ -548,6 +652,8 @@ private void saveOnDemandVehicleEvents() { case FINISH_REBALANCING: filepath = config.statistics.onDemandVehicleStatistic.finishRebalancingFilePath; break; + case WAIT: + filepath = config.statistics.onDemandVehicleStatistic.waitFilePath; } try { diff --git a/src/main/java/cz/cvut/fel/aic/simod/traveltimecomputation/AstarTravelTimeProvider.java b/src/main/java/cz/cvut/fel/aic/simod/traveltimecomputation/AstarTravelTimeProvider.java index 80e738a5..0d29a727 100644 --- a/src/main/java/cz/cvut/fel/aic/simod/traveltimecomputation/AstarTravelTimeProvider.java +++ b/src/main/java/cz/cvut/fel/aic/simod/traveltimecomputation/AstarTravelTimeProvider.java @@ -51,8 +51,8 @@ public class AstarTravelTimeProvider extends TravelTimeProvider{ @Inject public AstarTravelTimeProvider( - TimeProvider timeProvider, - TripsUtil tripsUtil, + TimeProvider timeProvider, + TripsUtil tripsUtil, TransportNetworks transportNetworks, MoveUtil moveUtil) { super(timeProvider); diff --git a/src/main/resources/cz/cvut/fel/aic/simod/config/config.cfg b/src/main/resources/cz/cvut/fel/aic/simod/config/config.cfg index 43dd59f6..1b62cadd 100644 --- a/src/main/resources/cz/cvut/fel/aic/simod/config/config.cfg +++ b/src/main/resources/cz/cvut/fel/aic/simod/config/config.cfg @@ -14,7 +14,7 @@ map_dir: $simod_data_dir + 'maps/' trips_filename: 'trips' trips_path: $simod_data_dir + $trips_filename + '.txt' -trips_multiplier: 3.433 +trips_multiplier: 1.0 #~ trips_multiplier: 1.0 @@ -159,6 +159,7 @@ statistics: reach_nearest_station_file_path: $statistics.on_demand_vehicle_statistic.dir_path + 'reach_nearest_station.csv' start_rebalancing_file_path: $statistics.on_demand_vehicle_statistic.dir_path + 'start_rebalancing.csv' finish_rebalancing_file_path: $statistics.on_demand_vehicle_statistic.dir_path + 'finish_rebalancing.csv' + wait_file_path: $statistics.on_demand_vehicle_statistic.dir_path + 'wait.csv' } trip_distances_file_path: $simod_experiment_dir + 'demand_trip_lengths.csv' occupancies_file_name: 'vehicle_occupancy.csv' @@ -170,6 +171,12 @@ statistics: group_data_filename: 'group_data.csv' group_data_file_path: $simod_experiment_dir + $statistics.group_data_filename + + inactive_vehicles_file_name: 'inactive_vehicles.csv' + inactive_vehicles_file_path: $simod_experiment_dir + $statistics.inactive_vehicles_file_name + + waiting_times_file_name: 'waiting_times.csv' + waiting_times_file_path: $simod_experiment_dir + $statistics.waiting_times_file_name } !parent diff --git a/src/test/java/cz/cvut/fel/aic/simod/system/TestOnDemandVehicle.java b/src/test/java/cz/cvut/fel/aic/simod/system/TestOnDemandVehicle.java index e8494980..7789879c 100644 --- a/src/test/java/cz/cvut/fel/aic/simod/system/TestOnDemandVehicle.java +++ b/src/test/java/cz/cvut/fel/aic/simod/system/TestOnDemandVehicle.java @@ -24,11 +24,15 @@ import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; import cz.cvut.fel.aic.agentpolis.simmodel.IdGenerator; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.Wait; import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.StandardDriveFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; import cz.cvut.fel.aic.agentpolis.simulator.visualization.visio.VisioPositionUtil; import cz.cvut.fel.aic.alite.common.event.EventProcessor; import cz.cvut.fel.aic.simod.StationsDispatcher; +import cz.cvut.fel.aic.simod.WaitTransferActivityFactory; +import cz.cvut.fel.aic.simod.WaitWithStopActivityFactory; import cz.cvut.fel.aic.simod.config.SimodConfig; import cz.cvut.fel.aic.simod.entity.vehicle.OnDemandVehicle; import cz.cvut.fel.aic.simod.storage.PhysicalTransportVehicleStorage; @@ -53,6 +57,8 @@ public TestOnDemandVehicle( SimodConfig config, IdGenerator idGenerator, AgentpolisConfig agentpolisConfig, + WaitWithStopActivityFactory waitWithStopActivityFactory, + WaitActivityFactory waitActivityFactory, @Assisted String vehicleId, @Assisted SimulationNode startPosition) { super(vehicleStorage, @@ -66,6 +72,8 @@ public TestOnDemandVehicle( config, idGenerator, agentpolisConfig, + waitWithStopActivityFactory, + waitActivityFactory, vehicleId, startPosition); diff --git a/src/test/java/cz/cvut/fel/aic/simod/visual/ridesharing/greedyTASeT/GreedyTASeTSolverTest.java b/src/test/java/cz/cvut/fel/aic/simod/visual/ridesharing/greedyTASeT/GreedyTASeTSolverTest.java new file mode 100644 index 00000000..4119e4f1 --- /dev/null +++ b/src/test/java/cz/cvut/fel/aic/simod/visual/ridesharing/greedyTASeT/GreedyTASeTSolverTest.java @@ -0,0 +1,332 @@ +package cz.cvut.fel.aic.simod.visual.ridesharing.greedyTASeT; + +import cz.cvut.fel.aic.agentpolis.config.AgentpolisConfig; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.AStarShortestPathPlanner; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.EuclideanTraveltimeHeuristic; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.ShortestPathPlanner; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.planner.TripsUtil; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.StandardTimeProvider; +import cz.cvut.fel.aic.agentpolis.siminfrastructure.time.TimeProvider; +import cz.cvut.fel.aic.agentpolis.simmodel.IdGenerator; +import cz.cvut.fel.aic.agentpolis.simmodel.MoveUtil; +import cz.cvut.fel.aic.agentpolis.simmodel.activity.activityFactory.WaitActivityFactory; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.EGraphType; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.GraphType; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.NearestElementUtils; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.Utils; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationEdge; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.elements.SimulationNode; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.networks.HighwayNetwork; +import cz.cvut.fel.aic.agentpolis.simmodel.environment.transportnetwork.networks.TransportNetworks; +import cz.cvut.fel.aic.agentpolis.utils.PositionUtil; +import cz.cvut.fel.aic.alite.common.event.typed.TypedSimulation; +import cz.cvut.fel.aic.geographtools.Graph; +import cz.cvut.fel.aic.geographtools.util.Transformer; +import cz.cvut.fel.aic.simod.DriveToTransferStationActivityFactory; +import cz.cvut.fel.aic.simod.WaitTransferActivityFactory; +import cz.cvut.fel.aic.simod.WaitWithStop; +import cz.cvut.fel.aic.simod.WaitWithStopActivityFactory; +import cz.cvut.fel.aic.simod.config.SimodConfig; +import cz.cvut.fel.aic.simod.entity.DemandAgent; +import cz.cvut.fel.aic.simod.entity.vehicle.OnDemandVehicle; +import cz.cvut.fel.aic.simod.io.TimeTrip; +import cz.cvut.fel.aic.simod.ridesharing.DroppedDemandsAnalyzer; +import cz.cvut.fel.aic.simod.ridesharing.PlanCostProvider; +import cz.cvut.fel.aic.simod.ridesharing.RideSharingOnDemandVehicle; +import cz.cvut.fel.aic.simod.ridesharing.StandardPlanCostProvider; +import cz.cvut.fel.aic.simod.ridesharing.insertionheuristic.DriverPlan; +import cz.cvut.fel.aic.simod.ridesharing.model.*; +import cz.cvut.fel.aic.simod.storage.OnDemandVehicleStorage; +import cz.cvut.fel.aic.simod.storage.OnDemandvehicleStationStorage; +import cz.cvut.fel.aic.simod.storage.PhysicalTransportVehicleStorage; +import cz.cvut.fel.aic.simod.traveltimecomputation.AstarTravelTimeProvider; +import cz.cvut.fel.aic.simod.traveltimecomputation.TravelTimeProvider; +import cz.cvut.fel.aic.simod.ridesharing.greedyTASeT.GreedyTASeTSolver; +import cz.cvut.fel.aic.simod.visual.ridesharing.vga.mock.TestPlanRequest; +import ninja.fido.config.Configuration; +import org.junit.Test; + +import java.util.*; + +public class GreedyTASeTSolverTest { + + @Test + public void run() { + + TypedSimulation eventProcessor = new TypedSimulation(120); + SimodConfig simodConfig = new SimodConfig(); + IdGenerator tripIdGenerator = new IdGenerator(); + IdGenerator idGenerator2 = new IdGenerator(); + IdGenerator idGenerator3 = new IdGenerator(); + + TimeProvider timeProvider1 = new TimeProvider() { + @Override + public long getCurrentSimTime() { + return 0; + } + }; + PositionUtil positionUtil = new PositionUtil(); + + // creating MAP of city: 4columns x 3rows grid + int citySRID = 32618; + Transformer transformer = new Transformer(citySRID); + Graph graph = Utils.getGridGraph(4, transformer, 3); + Map> gridMap = new HashMap<>(); + gridMap.put(EGraphType.HIGHWAY, graph); + + // setting up Agentpolis config + AgentpolisConfig agentpolisConfig = new AgentpolisConfig(); + Configuration.load(agentpolisConfig, simodConfig, null, "agentpolis"); + + // TripsUtil initialization + MoveUtil moveUtil = new MoveUtil(agentpolisConfig); + TransportNetworks transportNetworks = new TransportNetworks(gridMap); + AStarShortestPathPlanner aStarPlanner = new AStarShortestPathPlanner( + transportNetworks, + new EuclideanTraveltimeHeuristic(positionUtil), + agentpolisConfig, + moveUtil + ); + NearestElementUtils nearestElementUtils = new NearestElementUtils(transportNetworks, transformer); + TripsUtil tripsUtil = new TripsUtil( + aStarPlanner, + nearestElementUtils, + new HighwayNetwork(graph), + tripIdGenerator + ); + + // Time providers + AstarTravelTimeProvider astarTravelTimeProvider = new AstarTravelTimeProvider(timeProvider1, tripsUtil, null, moveUtil); + StandardTimeProvider standardTimeProvider = new StandardTimeProvider(eventProcessor); + + StandardPlanCostProvider travelCostProvider = new StandardPlanCostProvider(simodConfig); + + // Storages + OnDemandVehicleStorage onDemandVehicleStorage = new OnDemandVehicleStorage(); + PhysicalTransportVehicleStorage physicalVehicleStorage = new PhysicalTransportVehicleStorage(); + OnDemandvehicleStationStorage onDemandvehicleStationStorage = new OnDemandvehicleStationStorage(transformer); + + DroppedDemandsAnalyzer droppedDemandsAnalyzer = null; // new DroppedDemandsAnalyzer( vehicleStorage, positionUtil, astarTravelTimeProvider, config, onDemandvehicleStationStorage, agentpolisConfig); + + // start position of 1st vehicle + SimulationNode startPos = graph.getNode(6); // top left corner + + WaitWithStopActivityFactory waitWithStopActivityFactory = new WaitWithStopActivityFactory(); + WaitActivityFactory waitActivityFactory = new WaitActivityFactory(); + DriveToTransferStationActivityFactory driveToTransferStationActivityFactory = null; + + RideSharingOnDemandVehicle vehicle_1 = new RideSharingOnDemandVehicle( + physicalVehicleStorage, + tripsUtil, + null, + null, + null, + tripIdGenerator, + eventProcessor, + standardTimeProvider, + idGenerator2, + simodConfig, + idGenerator3, + agentpolisConfig, + waitWithStopActivityFactory, + waitActivityFactory, + null, + "1", + startPos + ); + RideSharingOnDemandVehicle vehicle_2 = new RideSharingOnDemandVehicle( + physicalVehicleStorage, + tripsUtil, + null, + null, + null, + tripIdGenerator, + eventProcessor, + standardTimeProvider, + idGenerator2, + simodConfig, + idGenerator3, + agentpolisConfig, + waitWithStopActivityFactory, + waitActivityFactory, + null, + "2", + startPos + ); + + onDemandVehicleStorage.addEntity(vehicle_1); + onDemandVehicleStorage.addEntity(vehicle_2); + + SimulationNode transferPoint = graph.getNode(6); + List transferPoints = new ArrayList<>(); + transferPoints.add(transferPoint); + + GreedyTASeTSolver solver = new GreedyTASeTSolver( onDemandVehicleStorage, + astarTravelTimeProvider, + travelCostProvider, + null, + eventProcessor, + simodConfig, + timeProvider1, + positionUtil, + droppedDemandsAnalyzer, + onDemandvehicleStationStorage, + agentpolisConfig + ); + + solver.setTransferPoints(transferPoints); + + // create requests + SimulationNode origin_1 = graph.getNode(2); + SimulationNode destination_1 = graph.getNode(8); + long startTime = 0; + long endTime = 100; + SimulationNode[] locations = {origin_1, destination_1}; + DemandAgent demandAgent_0 = new DemandAgent( + null, + eventProcessor, + null, + standardTimeProvider, + tripsUtil, + "agent_00", + 0, + new TimeTrip( + 0, + startTime, + endTime, + locations + ) + ); + + SimulationNode origin_2 = graph.getNode(5); + SimulationNode destination_2 = graph.getNode(10); + long startTime2 = 0; + long endTime2 = 100; + SimulationNode[] locations2 = {origin_2, destination_2}; + DemandAgent demandAgent_1 = new DemandAgent( + null, + eventProcessor, + null, + standardTimeProvider, + tripsUtil, + "agent_01", + 1, + new TimeTrip( + 0, + startTime2, + endTime2, + locations2 + ) + ); + + SimulationNode origin_3 = graph.getNode(2); + SimulationNode destination_3 = graph.getNode(10); + long startTime3 = 0; + long endTime3 = 100; + SimulationNode[] locations3 = {origin_3, destination_3}; + DemandAgent demandAgent_2 = new DemandAgent( + null, + eventProcessor, + null, + standardTimeProvider, + tripsUtil, + "agent_02", + 1, + new TimeTrip( + 0, + startTime3, + endTime3, + locations3 + ) + ); + + SimulationNode origin_4 = graph.getNode(5); + SimulationNode destination_4 = graph.getNode(8); + long startTime4 = 0; + long endTime4 = 100; + SimulationNode[] locations4 = {origin_4, destination_4}; + DemandAgent demandAgent_3 = new DemandAgent( + null, + eventProcessor, + null, + standardTimeProvider, + tripsUtil, + "agent_03", + 1, + new TimeTrip( + 0, + startTime4, + endTime4, + locations4 + ) + ); + + + + + DefaultPlanComputationRequest request_1 = new DefaultPlanComputationRequest(astarTravelTimeProvider, 0, simodConfig, origin_1, destination_1, demandAgent_0); + DefaultPlanComputationRequest request_2 = new DefaultPlanComputationRequest(astarTravelTimeProvider, 1, simodConfig, origin_2, destination_2, demandAgent_1); + DefaultPlanComputationRequest request_3 = new DefaultPlanComputationRequest(astarTravelTimeProvider, 1, simodConfig, origin_3, destination_3, demandAgent_2); + DefaultPlanComputationRequest request_4 = new DefaultPlanComputationRequest(astarTravelTimeProvider, 1, simodConfig, origin_4, destination_4, demandAgent_3); + List requestsPeople = new ArrayList<>(); + requestsPeople.add(request_2); + requestsPeople.add(request_1); + requestsPeople.add(request_3); + requestsPeople.add(request_4); + + // call solve method + Map solution = solver.solve(requestsPeople, null); + System.out.println("Solution:"); + System.out.println(solution.values().toString()); + + + + } + + @Test + public void testSort() { + int [] array = {10, 2, 5, 9, 3}; + List list = new ArrayList<>(); + Double one = 1d; + Double two = 2d; + Double three = 3d; + Double four = 4d; + Double five = 5d; + list.add(one); + list.add(two); + list.add(three); + list.add(four); + list.add(five); + + System.out.println("sort"); + List listCopy = new ArrayList<>(list); + list.sort(Comparator.comparing(x -> array[listCopy.indexOf(x)])); + Collections.reverse(list); + System.out.println(Arrays.toString(array)); + System.out.println(list); + + } + + @Test + public void removeCurrentPositionActions() { + + List listOfActionsWithPositions = new ArrayList<>(); + + PlanActionCurrentPosition a1 = new PlanActionCurrentPosition(null); + PlanActionPickup a2 = new PlanActionPickup(null, null, 0); + PlanActionDropoffTransfer a3 = new PlanActionDropoffTransfer(null, null, 0); + + listOfActionsWithPositions.add(a1); + listOfActionsWithPositions.add(a2); + listOfActionsWithPositions.add(a3); + + List copyOfList = new ArrayList<>(); + copyOfList.addAll(listOfActionsWithPositions); + for (PlanAction action : listOfActionsWithPositions) { + if (action instanceof PlanActionCurrentPosition) { + copyOfList.remove(action); + } + } + System.out.println(copyOfList.size()); + } +} diff --git a/src/test/resources/cz/cvut/fel/aic/simod/config/config.cfg b/src/test/resources/cz/cvut/fel/aic/simod/config/config.cfg index 1bd52bc5..0983f307 100644 --- a/src/test/resources/cz/cvut/fel/aic/simod/config/config.cfg +++ b/src/test/resources/cz/cvut/fel/aic/simod/config/config.cfg @@ -4,10 +4,10 @@ experiment_name: 'test' # common data for all experiments -amodsim_data_dir: 'FILL THIS WITH PATH TO DATA DIR' +amodsim_data_dir: '/Users/adela/Documents/bakalarka/test_simod/data/' # experiment specific data (cache, results,...) -amodsim_experiment_dir: "FILL THIS WITH PATH TO EXPERIMENT DIR" +amodsim_experiment_dir: "/Users/adela/Documents/bakalarka/test_simod/" map_dir: $amodsim_data_dir + 'maps/'