diff --git a/fasttrips/Assignment.py b/fasttrips/Assignment.py index a544d6e9..f222af21 100644 --- a/fasttrips/Assignment.py +++ b/fasttrips/Assignment.py @@ -180,7 +180,7 @@ def read_configuration(input_network_dir, input_demand_dir): 'stochastic_pathset_size' :1000, 'capacity_constraint' :False, 'trace_person_ids' :'None', - 'prepend_route_id_to_trip_id' :False, + 'prepend_route_id_to_trip_id' :'False', 'number_of_processes' :0, 'bump_buffer' :5, 'bump_one_at_a_time' :True, diff --git a/fasttrips/FastTrips.py b/fasttrips/FastTrips.py index 8887d775..0e9bb74d 100644 --- a/fasttrips/FastTrips.py +++ b/fasttrips/FastTrips.py @@ -14,6 +14,7 @@ """ import os from operator import attrgetter +import pandas import transitfeed from .Assignment import Assignment @@ -36,6 +37,9 @@ class FastTrips: #: Debug log filename. Detailed output goes here, including trace information. DEBUG_LOG = "ft_debug%s.log" + #: Pathset debug filename. Writes pathset here. + PATHSET_LOG = "ft_pathset%s.txt" + def __init__(self, input_network_dir, input_demand_dir, output_dir, is_child_process=False, logname_append="", appendLog=False): """ @@ -93,6 +97,15 @@ def __init__(self, input_network_dir, input_demand_dir, output_dir, os.path.join(self.output_dir, FastTrips.DEBUG_LOG % logname_append), logToConsole=False if is_child_process else True, append=appendLog) + # clear pathset files if we're starting out -- reset them to just a header + # there will be one for the parent process, and one each for workers + pathset_filename = os.path.join(self.output_dir, FastTrips.PATHSET_LOG % logname_append) + if not appendLog: + FastTripsLogger.info("Writing %s" % pathset_filename) + pathset_file = open(pathset_filename, 'w') + pathset_file.write("iteration passenger_id_num trip_list_id_num path_cost path_probability path_board_stops path_trips path_alight_stops\n") + pathset_file.close() + # Read the configuration Assignment.read_configuration(self.input_network_dir, self.input_demand_dir) @@ -143,6 +156,50 @@ def read_input_files(self): else: self.passengers = None + def combine_pathset_files(self): + """ + Since the pathset files are output by worker, let's combine them into a single file. + """ + procnum = 1 + pathset_init = False + pathsets_df = None + # if we don't have one, no worries + + while True: + logname_append = "_worker%02d" % procnum + pathset_filename = os.path.join(self.output_dir, FastTrips.PATHSET_LOG % logname_append) + + if not os.path.exists(pathset_filename): + break + + # read the pathset + pathset_df = pandas.read_table(pathset_filename, sep="[ ]+") + FastTripsLogger.info("Read %d lines from %s" % (len(pathset_df), pathset_filename)) + # remove it + os.remove(pathset_filename) + + # append to ours + if not pathset_init: + pathsets_df = pathset_df + pathset_init = True + else: + pathsets_df = pandas.concat([pathsets_df, pathset_df], axis=0) + + # see if we have more + procnum += 1 + + if pathset_init: + # sort it by iteration, trip_id_num + pathsets_df.sort(columns=['iteration','trip_list_id_num'], inplace=True) + # write it + pathset_filename = os.path.join(self.output_dir, FastTrips.PATHSET_LOG % "") + pathsets_df.to_csv(pathset_filename, sep=" ", index=False) + FastTripsLogger.info("Wrote %d lines to %s" % (len(pathsets_df), pathset_filename)) + + def run_assignment(self, output_dir): # Do it! - Assignment.assign_paths(output_dir, self); \ No newline at end of file + Assignment.assign_paths(output_dir, self) + + self.combine_pathset_files() + diff --git a/src/fasttrips.cpp b/src/fasttrips.cpp index 2cba2117..e2a29c1d 100644 --- a/src/fasttrips.cpp +++ b/src/fasttrips.cpp @@ -120,29 +120,28 @@ _fasttrips_find_path(PyObject *self, PyObject *args) // package for returning. We'll separate ints and doubles. npy_intp dims_int[2]; - dims_int[0] = path.stops_.size(); + dims_int[0] = path.size(); dims_int[1] = 6; // stop_id, deparr_mode_, trip_id_, stop_succpred_, seq_, seq_succpred_ PyArrayObject *ret_int = (PyArrayObject *)PyArray_SimpleNew(2, dims_int, NPY_INT32); npy_intp dims_double[2]; - dims_double[0] = path.stops_.size(); + dims_double[0] = path.size(); dims_double[1] = 5; // label_, deparr_time_, link_time_, cost_, arrdep_time_ PyArrayObject *ret_double = (PyArrayObject *)PyArray_SimpleNew(2, dims_double, NPY_DOUBLE); for (int ind = 0; ind < dims_int[0]; ++ind) { - int stop_id = path.stops_[ind]; - *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 0) = stop_id; - *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 1) = path.states_[stop_id].deparr_mode_; - *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 2) = path.states_[stop_id].trip_id_; - *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 3) = path.states_[stop_id].stop_succpred_; - *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 4) = path.states_[stop_id].seq_; - *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 5) = path.states_[stop_id].seq_succpred_; - - *(npy_double*)PyArray_GETPTR2(ret_double, ind, 0) = path.states_[stop_id].label_; - *(npy_double*)PyArray_GETPTR2(ret_double, ind, 1) = path.states_[stop_id].deparr_time_; - *(npy_double*)PyArray_GETPTR2(ret_double, ind, 2) = path.states_[stop_id].link_time_; - *(npy_double*)PyArray_GETPTR2(ret_double, ind, 3) = path.states_[stop_id].cost_; - *(npy_double*)PyArray_GETPTR2(ret_double, ind, 4) = path.states_[stop_id].arrdep_time_; + *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 0) = path[ind].first; + *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 1) = path[ind].second.deparr_mode_; + *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 2) = path[ind].second.trip_id_; + *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 3) = path[ind].second.stop_succpred_; + *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 4) = path[ind].second.seq_; + *(npy_int32*)PyArray_GETPTR2(ret_int, ind, 5) = path[ind].second.seq_succpred_; + + *(npy_double*)PyArray_GETPTR2(ret_double, ind, 0) = path[ind].second.label_; + *(npy_double*)PyArray_GETPTR2(ret_double, ind, 1) = path[ind].second.deparr_time_; + *(npy_double*)PyArray_GETPTR2(ret_double, ind, 2) = path[ind].second.link_time_; + *(npy_double*)PyArray_GETPTR2(ret_double, ind, 3) = path[ind].second.cost_; + *(npy_double*)PyArray_GETPTR2(ret_double, ind, 4) = path[ind].second.arrdep_time_; } PyObject *returnobj = Py_BuildValue("(OOd)",ret_int,ret_double,path_info.cost_); diff --git a/src/pathfinder.cpp b/src/pathfinder.cpp index 04027a30..6dae31a8 100644 --- a/src/pathfinder.cpp +++ b/src/pathfinder.cpp @@ -1328,8 +1328,7 @@ namespace fasttrips { size_t chosen_index = chooseState(path_spec, trace_file, access_cum_prob); StopState ss = taz_state[chosen_index]; - path.stops_.push_back(start_state_id); - path.states_[start_state_id] = ss; + path.push_back( std::make_pair(start_state_id, ss) ); if (path_spec.trace_) { @@ -1344,8 +1343,6 @@ namespace fasttrips { double arrdep_time = ss.deparr_time_ + (ss.link_time_*dir_factor); int prev_mode = ss.deparr_mode_; int prev_trip_id = ss.trip_id_; - int prev_stop_id = start_state_id; - int prev_prev_stop_id = -1; while (true) { // setup probabilities @@ -1445,8 +1442,8 @@ namespace fasttrips { double dep_time = getScheduledDeparture(next_ss.trip_id_, current_stop_id, next_ss.seq_); // set departure time for the access link to perfectly catch the vehicle // todo: what if there is a wait queue? - path.states_[prev_stop_id].arrdep_time_ = dep_time; - path.states_[prev_stop_id].deparr_time_ = dep_time - path.states_[start_state_id].link_time_; + path.back().second.arrdep_time_ = dep_time; + path.back().second.deparr_time_ = dep_time - path.front().second.link_time_; // no wait time for the trip next_ss.link_time_ = next_ss.arrdep_time_ - next_ss.deparr_time_; } @@ -1457,12 +1454,12 @@ namespace fasttrips { } // *Fix transfer times* else if (next_ss.deparr_mode_ == MODE_TRANSFER) { - next_ss.deparr_time_ = path.states_[prev_stop_id].arrdep_time_; // start transferring immediately + next_ss.deparr_time_ = path.back().second.arrdep_time_; // start transferring immediately next_ss.arrdep_time_ = next_ss.deparr_time_ + next_ss.link_time_; } // Egress: don't wait, just walk. Get to destination as early as possible else if (next_ss.deparr_mode_ == MODE_EGRESS) { - next_ss.deparr_time_ = path.states_[prev_stop_id].arrdep_time_; + next_ss.deparr_time_ = path.back().second.arrdep_time_; next_ss.arrdep_time_ = next_ss.deparr_time_ + next_ss.link_time_; } } @@ -1471,13 +1468,13 @@ namespace fasttrips { { // Leave origin as late as possible if (next_ss.deparr_mode_ == MODE_ACCESS) { - double dep_time = getScheduledDeparture(path.states_[prev_stop_id].trip_id_, current_stop_id, path.states_[prev_stop_id].seq_succpred_); + double dep_time = getScheduledDeparture(path.back().second.trip_id_, current_stop_id, path.back().second.seq_succpred_); // set arrival time for the access link to perfectly catch the vehicle // todo: what if there is a wait queue? next_ss.deparr_time_ = dep_time; next_ss.arrdep_time_ = next_ss.deparr_time_ - next_ss.link_time_; // no wait time for the trip - path.states_[prev_stop_id].link_time_ = path.states_[prev_stop_id].deparr_time_ - path.states_[prev_stop_id].arrdep_time_; + path.back().second.link_time_ = path.back().second.deparr_time_ - path.back().second.arrdep_time_; } // *Fix trip time*: we are choosing in reverse so pretend the wait time is zero for now to // accurately evaluate possible transfers in next choice. @@ -1487,36 +1484,33 @@ namespace fasttrips { // and we can update the transfer and the trip with the real wait if (prev_mode == MODE_TRANSFER) { // move transfer time so we do it right after arriving - path.states_[prev_stop_id].arrdep_time_ = next_ss.deparr_time_; // depart right away - path.states_[prev_stop_id].deparr_time_ = next_ss.deparr_time_ + path.states_[prev_stop_id].link_time_; // arrive after walk + path.back().second.arrdep_time_ = next_ss.deparr_time_; // depart right away + path.back().second.deparr_time_ = next_ss.deparr_time_ + path.back().second.link_time_; // arrive after walk // give the wait time to the previous trip - path.states_[prev_prev_stop_id].link_time_ = path.states_[prev_prev_stop_id].deparr_time_ - path.states_[prev_stop_id].deparr_time_; + path[path.size()-2].second.link_time_ = path[path.size()-2].second.deparr_time_ - path.back().second.deparr_time_; } // If the previous (next in time) is another trip (so zero-walk transfer) give it wait time else if (isTrip(prev_mode)) { - path.states_[prev_stop_id].link_time_ = path.states_[prev_stop_id].deparr_time_ - next_ss.deparr_time_; + path.back().second.link_time_ = path.back().second.deparr_time_ - next_ss.deparr_time_; } } // *Fix transfer depart/arrive times*: transfer as late as possible to preserve options for earlier trip else if (next_ss.deparr_mode_ == MODE_TRANSFER) { - next_ss.deparr_time_ = path.states_[prev_stop_id].arrdep_time_; + next_ss.deparr_time_ = path.back().second.arrdep_time_; next_ss.arrdep_time_ = next_ss.deparr_time_ - next_ss.link_time_; } // Egress: don't wait, just walk. Get to destination as early as possible if (prev_mode == MODE_EGRESS) { - path.states_[prev_stop_id].arrdep_time_ = next_ss.deparr_time_; - path.states_[prev_stop_id].deparr_time_ = path.states_[prev_stop_id].arrdep_time_ + path.states_[prev_stop_id].link_time_; + path.back().second.arrdep_time_ = next_ss.deparr_time_; + path.back().second.deparr_time_ = path.back().second.arrdep_time_ + path.back().second.link_time_; } } // record the choice - path.stops_.push_back(current_stop_id); - path.states_[current_stop_id] = next_ss; + path.push_back( std::make_pair(current_stop_id, next_ss) ); // move on to the next - prev_prev_stop_id = prev_stop_id; - prev_stop_id = current_stop_id; current_stop_id = next_ss.stop_succpred_; prev_mode = next_ss.deparr_mode_; prev_trip_id = next_ss.trip_id_; @@ -1526,7 +1520,7 @@ namespace fasttrips { if (path_spec.trace_) { trace_file << " -> Updated link "; - printStopState(trace_file, prev_stop_id, path.states_[prev_stop_id], path_spec); + printStopState(trace_file, path.back().first, path.back().second, path_spec); trace_file << std::endl; } @@ -1593,7 +1587,7 @@ namespace fasttrips { PathInfo& path_info) const { // no stops - nothing to do - if (path.stops_.size()==0) { return; } + if (path.size()==0) { return; } if (path_spec.trace_) { trace_file << "calculatePathCost:" << std::endl; @@ -1605,15 +1599,15 @@ namespace fasttrips { double dir_factor = path_spec.outbound_ ? 1.0 : -1.0; // iterate through the states in chronological order - int start_ind = path_spec.outbound_ ? 0 : path.stops_.size()-1; - int end_ind = path_spec.outbound_ ? path.stops_.size() : -1; - int inc = path_spec.outbound_ ? 1 : -1; + int start_ind = path_spec.outbound_ ? 0 : path.size()-1; + int end_ind = path_spec.outbound_ ? path.size() : -1; + int inc = path_spec.outbound_ ? 1 : -1; - path_info.cost_ = 0; + path_info.cost_ = 0; for (int index = start_ind; index != end_ind; index += inc) { - int stop_id = path.stops_[index]; - StopState& stop_state = path.states_[stop_id]; + int stop_id = path[index].first; + StopState& stop_state = path[index].second; // ============= access ============= if (stop_state.deparr_mode_ == MODE_ACCESS) @@ -1756,6 +1750,18 @@ namespace fasttrips { } if (logsum == 0) { return false; } // fail + // debug -- print pet set to file + std::ofstream pathset_file; + std::ostringstream ss; + ss << output_dir_ << kPathSeparator; + ss << "ft_pathset"; + if (process_num_ > 0) { + ss << "_worker" << std::setfill('0') << std::setw(2) << process_num_; + } + ss << ".txt"; + // append + pathset_file.open(ss.str().c_str(), (std::ios_base::out | std::ios_base::app)); + // for integerized probability*1000000 int cum_prob = 0; int cost_cutoff = 1; @@ -1781,7 +1787,18 @@ namespace fasttrips { printPathCompat(trace_file, path_spec, paths_iter->first); trace_file << std::endl; } + // print path to pathset file + pathset_file << path_spec.iteration_ << " "; // Iteration + pathset_file << path_spec.passenger_id_ << " "; // The passenger ID + pathset_file << path_spec.path_id_ << " "; // The path ID - uniquely identifies a passenger+path + pathset_file << std::setw(8) << std::fixed << std::setprecision(2) << paths_iter->second.cost_ << " "; + pathset_file << std::setw(8) << std::fixed << std::setprecision(6) << paths_iter->second.probability_ << " "; + printPathCompat(pathset_file, path_spec, paths_iter->first); + pathset_file << std::endl; } + + pathset_file.close(); + if (cum_prob == 0) { return false; } // fail // choose path @@ -1795,81 +1812,75 @@ namespace fasttrips { int final_state_type = path_spec.outbound_ ? MODE_EGRESS : MODE_ACCESS; StopState ss = taz_state.front(); // there's only one - path.states_[end_taz_id] = ss; - path.stops_.push_back(end_taz_id); - - int prev_prev_stop_id = -1; - int prev_stop_id = end_taz_id; - int prev_mode = ss.deparr_mode_; + path.push_back( std::make_pair(end_taz_id, ss) ); while (ss.deparr_mode_ != final_state_type) { int stop_id = ss.stop_succpred_; StopStates::const_iterator ssi = stop_states.find(stop_id); ss = ssi->second.front(); - path.states_[stop_id] = ss; - path.stops_.push_back(stop_id); + path.push_back( std::make_pair(stop_id, ss)); + + int curr_index = path.size() - 1; + int prev_index = curr_index - 1; if (path_spec.outbound_) { // Leave origin as late as possible - if (prev_mode == MODE_ACCESS) { - path.states_[prev_stop_id].arrdep_time_ = ss.deparr_time_; - path.states_[prev_stop_id].deparr_time_ = path.states_[prev_stop_id].arrdep_time_ - path.states_[prev_stop_id].link_time_; + if (path[prev_index].second.deparr_mode_ == MODE_ACCESS) { + path[prev_index].second.arrdep_time_ = ss.deparr_time_; + path[prev_index].second.deparr_time_ = path[prev_index].second.arrdep_time_ - path[prev_index].second.link_time_; // no wait time for the trip - path.states_[stop_id].link_time_ = path.states_[stop_id].arrdep_time_ - path.states_[stop_id].deparr_time_; + path[curr_index].second.link_time_ = path[curr_index].second.arrdep_time_ - path[curr_index].second.deparr_time_; } // *Fix trip time* - else if (isTrip(path.states_[stop_id].deparr_mode_)) { + else if (isTrip(path[curr_index].second.deparr_mode_)) { // link time is arrival time - previous arrival time - path.states_[stop_id].link_time_ = path.states_[stop_id].arrdep_time_ - path.states_[prev_stop_id].arrdep_time_; + path[curr_index].second.link_time_ = path[curr_index].second.arrdep_time_ - path[prev_index].second.arrdep_time_; } // *Fix transfer times* - else if (path.states_[stop_id].deparr_mode_ == MODE_TRANSFER) { - path.states_[stop_id].deparr_time_ = path.states_[prev_stop_id].arrdep_time_; // start transferring immediately - path.states_[stop_id].arrdep_time_ = path.states_[stop_id].deparr_time_ + path.states_[stop_id].link_time_; + else if (path[curr_index].second.deparr_mode_ == MODE_TRANSFER) { + path[curr_index].second.deparr_time_ = path[prev_index].second.arrdep_time_; // start transferring immediately + path[curr_index].second.arrdep_time_ = path[curr_index].second.deparr_time_ + path[curr_index].second.link_time_; } // Egress: don't wait, just walk. Get to destination as early as possible else if (ss.deparr_mode_ == MODE_EGRESS) { - path.states_[stop_id].deparr_time_ = path.states_[prev_stop_id].arrdep_time_; - path.states_[stop_id].arrdep_time_ = path.states_[stop_id].deparr_time_ + path.states_[stop_id].link_time_; + path[curr_index].second.deparr_time_ = path[prev_index].second.arrdep_time_; + path[curr_index].second.arrdep_time_ = path[curr_index].second.deparr_time_ + path[curr_index].second.link_time_; } } // INBOUND: We are choosing links in REVERSE chronological order else { // Leave origin as late as possible - if (path.states_[stop_id].deparr_mode_ == MODE_ACCESS) { - path.states_[stop_id].deparr_time_ = path.states_[prev_stop_id].arrdep_time_; - path.states_[stop_id].arrdep_time_ = path.states_[stop_id].deparr_time_ - path.states_[stop_id].link_time_; + if (path[curr_index].second.deparr_mode_ == MODE_ACCESS) { + path[curr_index].second.deparr_time_ = path[prev_index].second.arrdep_time_; + path[curr_index].second.arrdep_time_ = path[curr_index].second.deparr_time_ - path[curr_index].second.link_time_; // no wait time for the trip - path.states_[prev_stop_id].link_time_ = path.states_[prev_stop_id].deparr_time_ - path.states_[prev_stop_id].arrdep_time_; + path[prev_index].second.link_time_ = path[prev_index].second.deparr_time_ - path[prev_index].second.arrdep_time_; } // *Trip* - fix transfer and next trip if applicable - else if (isTrip(path.states_[stop_id].deparr_mode_)) { + else if (isTrip(path[curr_index].second.deparr_mode_)) { // If we just picked this trip and the previous (next in time) is transfer then we know the wait now // and we can update the transfer and the trip with the real wait - if (prev_mode == MODE_TRANSFER) { + if (path[prev_index].second.deparr_mode_ == MODE_TRANSFER) { // move transfer time so we do it right after arriving - path.states_[prev_stop_id].arrdep_time_ = path.states_[stop_id].deparr_time_; // depart right away - path.states_[prev_stop_id].deparr_time_ = path.states_[stop_id].deparr_time_ + path.states_[prev_stop_id].link_time_; // arrive after walk + path[prev_index].second.arrdep_time_ = path[curr_index].second.deparr_time_; // depart right away + path[prev_index].second.deparr_time_ = path[curr_index].second.deparr_time_ + path[prev_index].second.link_time_; // arrive after walk // give the wait time to the previous trip - path.states_[prev_prev_stop_id].link_time_ = path.states_[prev_prev_stop_id].deparr_time_ - path.states_[prev_stop_id].deparr_time_; + path[prev_index-1].second.link_time_ = path[prev_index-1].second.deparr_time_ - path[prev_index].second.deparr_time_; } // If the previous (next in time) is another trip (so zero-walk transfer) give it wait time - else if (isTrip(prev_mode)) { - path.states_[prev_stop_id].link_time_ = path.states_[prev_stop_id].deparr_time_ - path.states_[stop_id].deparr_time_; + else if (isTrip(path[prev_index].second.deparr_mode_)) { + path[prev_index].second.link_time_ = path[prev_index].second.deparr_time_ - path[curr_index].second.deparr_time_; } } // Egress: don't wait, just walk. Get to destination as early as possible - if (prev_mode == MODE_EGRESS) { - path.states_[prev_stop_id].arrdep_time_ = ss.deparr_time_; - path.states_[prev_stop_id].deparr_time_ = path.states_[prev_stop_id].arrdep_time_ + path.states_[prev_stop_id].link_time_; + if (path[prev_index].second.deparr_mode_ == MODE_EGRESS) { + path[prev_index].second.arrdep_time_ = ss.deparr_time_; + path[prev_index].second.deparr_time_ = path[prev_index].second.arrdep_time_ + path[prev_index].second.link_time_; } } - prev_prev_stop_id = prev_stop_id; - prev_stop_id = stop_id; - prev_mode = ss.deparr_mode_; } calculatePathCost(path_spec, trace_file, path, path_info); } @@ -1945,41 +1956,38 @@ namespace fasttrips { { printStopStateHeader(ostr, path_spec); ostr << std::endl; - for (std::vector::const_iterator stop_id_iter = path.stops_.begin(); - stop_id_iter != path.stops_.end(); ++stop_id_iter) + for (int index = 0; index < path.size(); ++index) { - std::map::const_iterator psi = path.states_.find(*stop_id_iter); - printStopState(ostr, *stop_id_iter, psi->second, path_spec); + printStopState(ostr, path[index].first, path[index].second, path_spec); ostr << std::endl; } } void PathFinder::printPathCompat(std::ostream& ostr, const PathSpecification& path_spec, const Path& path) const { - if (path.stops_.size() == 0) + if (path.size() == 0) { ostr << "no_path"; return; } // board stops, trips, alight stops std::string board_stops, trips, alight_stops; - int start_ind = path_spec.outbound_ ? 0 : path.stops_.size()-1; - int end_ind = path_spec.outbound_ ? path.stops_.size() : -1; + int start_ind = path_spec.outbound_ ? 0 : path.size()-1; + int end_ind = path_spec.outbound_ ? path.size() : -1; int inc = path_spec.outbound_ ? 1 : -1; for (int index = start_ind; index != end_ind; index += inc) { - int stop_id = path.stops_[index]; - std::map::const_iterator psi = path.states_.find(stop_id); + int stop_id = path[index].first; // only want trips - if (psi->second.deparr_mode_ == MODE_ACCESS ) { continue; } - if (psi->second.deparr_mode_ == MODE_EGRESS ) { continue; } - if (psi->second.deparr_mode_ == MODE_TRANSFER) { continue; } + if (path[index].second.deparr_mode_ == MODE_ACCESS ) { continue; } + if (path[index].second.deparr_mode_ == MODE_EGRESS ) { continue; } + if (path[index].second.deparr_mode_ == MODE_TRANSFER) { continue; } if ( board_stops.length() > 0) { board_stops += ","; } if ( trips.length() > 0) { trips += ","; } if (alight_stops.length() > 0) { alight_stops += ","; } - board_stops += (path_spec.outbound_ ? stop_num_to_str_.find(stop_id)->second : stop_num_to_str_.find(psi->second.stop_succpred_)->second); - trips += trip_num_to_str_.find(psi->second.trip_id_)->second; - alight_stops += (path_spec.outbound_ ? stop_num_to_str_.find(psi->second.stop_succpred_)->second : stop_num_to_str_.find(stop_id)->second); + board_stops += (path_spec.outbound_ ? stop_num_to_str_.find(stop_id)->second : stop_num_to_str_.find(path[index].second.stop_succpred_)->second); + trips += trip_num_to_str_.find(path[index].second.trip_id_)->second; + alight_stops += (path_spec.outbound_ ? stop_num_to_str_.find(path[index].second.stop_succpred_)->second : stop_num_to_str_.find(stop_id)->second); } ostr << " " << board_stops << " " << trips << " " << alight_stops; } diff --git a/src/pathfinder.h b/src/pathfinder.h index c278e5b0..c49addc6 100644 --- a/src/pathfinder.h +++ b/src/pathfinder.h @@ -197,15 +197,10 @@ namespace fasttrips { */ typedef std::priority_queue, struct LabelStopCompare> LabelStopQueue; - /** A single path consists of a map of stop id to StopState, plus the order of the stops are given - * a list of stop ids. - */ - typedef struct { - std::map states_; ///< Stop states will be in here, indexed by stop ID. - std::vector stops_; ///< stop IDs. They are in origin to destination order - ///< for outbound trips, and destination to origin - ///< order for inbound trips. - } Path; + /** A single path consists of a vector of stop ID & stop states. They are in origin to destination order for + * outbound trips, and destination to origin order for inbound trips. + **/ + typedef std::vector< std::pair > Path; /** In stochastic path finding, this is the information we'll collect about the path. */ typedef struct { @@ -221,19 +216,16 @@ namespace fasttrips { struct PathCompare { // less than bool operator()(const Path &path1, const Path &path2) const { - if (path1.stops_.size() < path2.stops_.size()) { return true; } - if (path1.stops_.size() > path2.stops_.size()) { return false; } + if (path1.size() < path2.size()) { return true; } + if (path1.size() > path2.size()) { return false; } // if number of stops matches, check the stop ids and deparr_mode_ - for (int ind=0; ind path2.stops_[ind]) { return false; } - int stop_id = path1.stops_[ind]; - std::map::const_iterator ssi1 = path1.states_.find(stop_id); - std::map::const_iterator ssi2 = path2.states_.find(stop_id); - if (ssi1->second.deparr_mode_ < ssi2->second.deparr_mode_) { return true; } - if (ssi1->second.deparr_mode_ > ssi2->second.deparr_mode_) { return false; } - if (ssi1->second.trip_id_ < ssi2->second.trip_id_ ) { return true; } - if (ssi1->second.trip_id_ > ssi2->second.trip_id_ ) { return false; } + for (int ind=0; ind path2[ind].first) { return false; } + if (path1[ind].second.deparr_mode_ < path2[ind].second.deparr_mode_) { return true; } + if (path1[ind].second.deparr_mode_ > path2[ind].second.deparr_mode_) { return false; } + if (path1[ind].second.trip_id_ < path2[ind].second.trip_id_ ) { return true; } + if (path1[ind].second.trip_id_ > path2[ind].second.trip_id_ ) { return false; } } return false; }