From ac8e816f7b54d7c6466ae4528ef651d1ab0b781b Mon Sep 17 00:00:00 2001 From: eric bryant Date: Sat, 7 Dec 2019 12:55:52 -0500 Subject: [PATCH 1/4] C++ "i17b" straightfwd intersection enhancements --- .../classes/GraphGeneration/HighwayGraph.cpp | 19 ++++++------ .../cplusplus/classes/Waypoint/Waypoint.cpp | 26 ++++++++++++++++ .../cplusplus/classes/Waypoint/Waypoint.h | 4 ++- .../canonical_waypoint_name.cpp | 9 +----- .../straightforward_intersection.cpp | 30 ++++++++++++------- .../WaypointQuadtree/WaypointQuadtree.cpp | 25 ++++++++++++++++ .../WaypointQuadtree/WaypointQuadtree.h | 1 + 7 files changed, 85 insertions(+), 29 deletions(-) diff --git a/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp b/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp index 5a25f03b..28ee0209 100644 --- a/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp +++ b/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp @@ -31,18 +31,16 @@ class HighwayGraph // of its colocation list unsigned int counter = 0; std::cout << et.et() + "Creating unique names and vertices" << std::flush; - for (Waypoint *w : all_waypoints.point_list()) + std::list graph_points = all_waypoints.graph_points(); + graph_points.sort(waypoint_simplification_sort); + for (Waypoint *w : graph_points) { if (counter % 10000 == 0) std::cout << '.' << std::flush; counter++; - // skip if this point is occupied by only waypoints in devel systems - if (!w->is_or_colocated_with_active_or_preview()) continue; - // skip if colocated and not at front of list - if (w->colocated && w != w->colocated->front()) continue; // come up with a unique name that brings in its meaning // start with the canonical name - std::string point_name = w->canonical_waypoint_name(waypoint_naming_log); + std::string point_name = w->canonical_waypoint_name(waypoint_naming_log, vertex_names, datacheckerrors); bool good_to_go = 1; // if that's taken, append the region code @@ -70,10 +68,11 @@ class HighwayGraph } // we're good; now construct a vertex - if (!w->colocated) - vertices[w] = new HGVertex(w, &*(vertex_names.insert(point_name).first), datacheckerrors, numthreads); - else vertices[w] = new HGVertex(w->colocated->front(), &*(vertex_names.insert(point_name).first), datacheckerrors, numthreads); - // deleted by HighwayGraph::clear + vertices[w] = new HGVertex(w, &*(vertex_names.insert(point_name).first), datacheckerrors, numthreads); + // deleted by HighwayGraph::clear + + // active/preview colocation lists are no longer needed; clear them + w->ap_coloc.clear(); } std::cout << '!' << std::endl; //#include "../../debug/unique_names.cpp" diff --git a/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp b/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp index 33f627f1..0a60bc4f 100644 --- a/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp @@ -2,6 +2,14 @@ bool sort_root_at_label(Waypoint *w1, Waypoint *w2) { return w1->root_at_label() < w2->root_at_label(); } +bool waypoint_simplification_sort(Waypoint *w1, Waypoint *w2) +{ if ( w2->ap_coloc.size() != 2 + || w2->ap_coloc.front()->route->abbrev.size() + || w2->ap_coloc.back()->route->abbrev.size() + ) return 1; + else return 0; +} + const double Waypoint::pi = 3.141592653589793238; Waypoint::Waypoint(char *line, Route *rte, std::mutex *strtok_mtx, DatacheckEntryList *datacheckerrors) @@ -308,6 +316,24 @@ inline Waypoint* Waypoint::hashpoint() return colocated->front(); } +bool Waypoint::label_references_route(Route *r, DatacheckEntryList *datacheckerrors) +{ std::string no_abbrev = r->name_no_abbrev(); + if (label.substr(0, no_abbrev.size()) != no_abbrev) + return 0; + if (label[no_abbrev.size()] == 0 || label[no_abbrev.size()] == '_') + return 1; + if (label.substr(no_abbrev.size(), r->abbrev.size()) != r->abbrev) + { /*if (label[no_abbrev.size()] == '/') + datacheckerrors->add(route, label, "", "", "UNEXPECTED_DESIGNATION", label.substr(no_abbrev.size()+1));//*/ + return 0; + } + if (label[no_abbrev.size() + r->abbrev.size()] == 0 || label[no_abbrev.size() + r->abbrev.size()] == '_') + return 1; + /*if (label[no_abbrev.size() + r->abbrev.size()] == '/') + datacheckerrors->add(route, label, "", "", "UNEXPECTED_DESIGNATION", label.substr(no_abbrev.size()+r->abbrev.size()+1));//*/ + return 0; +} + /* Datacheck */ inline void Waypoint::duplicate_label(DatacheckEntryList *datacheckerrors, std::unordered_set &all_route_labels) diff --git a/siteupdate/cplusplus/classes/Waypoint/Waypoint.h b/siteupdate/cplusplus/classes/Waypoint/Waypoint.h index 1040e9a3..72097c1c 100644 --- a/siteupdate/cplusplus/classes/Waypoint/Waypoint.h +++ b/siteupdate/cplusplus/classes/Waypoint/Waypoint.h @@ -17,6 +17,7 @@ class Waypoint std::string label; std::deque alt_labels; std::list *colocated; + std::vector ap_coloc; std::forward_list near_miss_points; bool is_hidden; static const double pi; @@ -30,12 +31,13 @@ class Waypoint unsigned int num_colocated(); double distance_to(Waypoint *); double angle(Waypoint *, Waypoint *); - std::string canonical_waypoint_name(std::list &); + std::string canonical_waypoint_name(std::list &, std::unordered_set &, DatacheckEntryList *); std::string simple_waypoint_name(); bool is_or_colocated_with_active_or_preview(); std::string root_at_label(); void nmplogs(std::list &, std::ofstream &, std::list &); inline Waypoint* hashpoint(); + bool label_references_route(Route *, DatacheckEntryList *); // Datacheck inline void duplicate_label(DatacheckEntryList *, std::unordered_set &); diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp index ca452600..be3cfa6b 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp @@ -1,4 +1,4 @@ -std::string Waypoint::canonical_waypoint_name(std::list &log) +std::string Waypoint::canonical_waypoint_name(std::list &log, std::unordered_set &vertex_names, DatacheckEntryList *datacheckerrors) { /* Best name we can come up with for this point bringing in information from itself and colocated points (if active/preview) */ @@ -10,11 +10,6 @@ std::string Waypoint::canonical_waypoint_name(std::list &log) // the route@label form and deal with conflicts elsewhere if (!colocated) return name; - // get a colocated list with any devel system entries removed - std::vector ap_coloc; - for (Waypoint *w : *colocated) - if (w->route->system->active_or_preview()) - ap_coloc.push_back(w); // just return the simple name if only one active/preview waypoint if (ap_coloc.size() == 1) return name; @@ -34,8 +29,6 @@ std::string Waypoint::canonical_waypoint_name(std::list &log) // How about? // I-581@4&US220@I-581(4)&US460@I-581&US11AltRoa@I-581&US220AltRoa@US220_S&VA116@I-581(4) - // INVESTIGATE: VA262@US11&US11@VA262&VA262@US11_S - // should be 2 colocated, shows up as 3? // TODO: I-610@TX288&I-610@38&TX288@I-610 // this is the overlap point of a loop diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp index b10a9436..47287232 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp @@ -6,14 +6,24 @@ // US24@CO21_N&CO21@US24_E would become US24_E/CO21_N if (ap_coloc.size() == 2) -{ std::string w0_list_entry = ap_coloc[0]->route->list_entry_name(); - std::string w1_list_entry = ap_coloc[1]->route->list_entry_name(); - std::string w0_label = ap_coloc[0]->label; - std::string w1_label = ap_coloc[1]->label; - if ( (w0_list_entry == w1_label or w1_label.find(w0_list_entry + '_') == 0) - && (w1_list_entry == w0_label or w0_label.find(w1_list_entry + '_') == 0) - ) - { log.push_back("Straightforward intersection: " + name + " -> " + w1_label + "/" + w0_label); - return w1_label + "/" + w0_label; - } +{ // check both refs independently, because datachecks are involved + bool one_ref_zero = ap_coloc[1]->label_references_route(ap_coloc[0]->route, datacheckerrors); + bool zero_ref_one = ap_coloc[0]->label_references_route(ap_coloc[1]->route, datacheckerrors); + if (one_ref_zero && zero_ref_one) + { std::string newname = ap_coloc[1]->label+"/"+ap_coloc[0]->label; + // if this is taken or if name_no_abbrev()s match, attempt to add in abbrevs if there's point in doing so + bool taken = vertex_names.find(newname) != vertex_names.end(); + if ( (ap_coloc[0]->route->abbrev.size() || ap_coloc[1]->route->abbrev.size()) + && (taken || ap_coloc[0]->route->name_no_abbrev() == ap_coloc[1]->route->name_no_abbrev()) + ) { const char *u0 = strchr(ap_coloc[0]->label.data(), '_'); + const char *u1 = strchr(ap_coloc[1]->label.data(), '_'); + std::string newname = (ap_coloc[0]->route->list_entry_name() + (u1 ? u1 : "")) + "/" + (ap_coloc[1]->route->list_entry_name() + (u0 ? u0 : "")); + std::string message = "Straightforward intersection: " + name + " -> " + newname; + if (taken) message += " (" + ap_coloc[1]->label+"/"+ap_coloc[0]->label + " already taken)"; + log.push_back(message); + return newname; + } + log.push_back("Straightforward intersection: " + name + " -> " + newname); + return newname; + } } diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp index 8a622162..477ede0b 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp @@ -142,6 +142,31 @@ std::forward_list WaypointQuadtree::point_list() else return points; } +std::list WaypointQuadtree::graph_points() +{ // return a list of points to be used as indices to HighwayGraph vertices + std::list hg_points; + if (refined()) + { std::list add_points; + add_points = sw_child->graph_points(); hg_points.splice(hg_points.end(), add_points); + add_points = se_child->graph_points(); hg_points.splice(hg_points.end(), add_points); + add_points = nw_child->graph_points(); hg_points.splice(hg_points.end(), add_points); + add_points = ne_child->graph_points(); hg_points.splice(hg_points.end(), add_points); + } + else for (Waypoint *w : points) + { // skip if this point is occupied by only waypoints in devel systems + if (!w->is_or_colocated_with_active_or_preview()) continue; + // skip if colocated and not at front of list + if (w->colocated && w != w->colocated->front()) continue; + // store a colocated list with any devel system entries removed + if (!w->colocated) w->ap_coloc.push_back(w); + else for (Waypoint *p : *(w->colocated)) + if (p->route->system->active_or_preview()) + w->ap_coloc.push_back(p); + hg_points.push_front(w); + } + return hg_points; +} + bool WaypointQuadtree::is_valid(ErrorList &el) { // make sure the quadtree is valid if (refined()) diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h index 68dce3b5..1ed0571b 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h @@ -18,6 +18,7 @@ class WaypointQuadtree std::string str(); unsigned int size(); std::forward_list point_list(); + std::list graph_points(); bool is_valid(ErrorList &); unsigned int max_colocated(); unsigned int total_nodes(); From ddd602e6969734bd3d6c22908a58149dc40d422f Mon Sep 17 00:00:00 2001 From: eric bryant Date: Sat, 7 Dec 2019 13:17:41 -0500 Subject: [PATCH 2/4] Python: straightfwd int before straightfwd conc also: snip vestigial per-Waypoint unique_name Identical waypoint simplification output to C++ version --- siteupdate/python-teresco/siteupdate.py | 45 +++++++++++-------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/siteupdate/python-teresco/siteupdate.py b/siteupdate/python-teresco/siteupdate.py index 1d1c5241..56c778ae 100755 --- a/siteupdate/python-teresco/siteupdate.py +++ b/siteupdate/python-teresco/siteupdate.py @@ -453,6 +453,25 @@ def canonical_waypoint_name(self,log): if (len(colocated) == 1): return name + # straightforward 2-route intersection with matching labels + # NY30@US20&US20@NY30 would become NY30/US20 + # or + # 2-route intersection with one or both labels having directional + # suffixes but otherwise matching route + # US24@CO21_N&CO21@US24_E would become US24_E/CO21_N + + if len(colocated) == 2: + w0_list_entry = colocated[0].route.list_entry_name() + w1_list_entry = colocated[1].route.list_entry_name() + w0_label = colocated[0].label + w1_label = colocated[1].label + if (w0_list_entry == w1_label or \ + w1_label.startswith(w0_list_entry + '_')) and \ + (w1_list_entry == w0_label or \ + w0_label.startswith(w1_list_entry + '_')): + log.append("Straightforward intersection: " + name + " -> " + w1_label + '/' + w0_label) + return w1_label + '/' + w0_label + # straightforward concurrency example with matching waypoint # labels, use route/route/route@label, except also matches # any hidden label @@ -477,25 +496,6 @@ def canonical_waypoint_name(self,log): log.append("Straightforward concurrency: " + name + " -> " + newname[1:]) return newname[1:] - # straightforward 2-route intersection with matching labels - # NY30@US20&US20@NY30 would become NY30/US20 - # or - # 2-route intersection with one or both labels having directional - # suffixes but otherwise matching route - # US24@CO21_N&CO21@US24_E would become US24_E/CO21_N - - if len(colocated) == 2: - w0_list_entry = colocated[0].route.list_entry_name() - w1_list_entry = colocated[1].route.list_entry_name() - w0_label = colocated[0].label - w1_label = colocated[1].label - if (w0_list_entry == w1_label or \ - w1_label.startswith(w0_list_entry + '_')) and \ - (w1_list_entry == w0_label or \ - w0_label.startswith(w1_list_entry + '_')): - log.append("Straightforward intersection: " + name + " -> " + w1_label + '/' + w0_label) - return w1_label + '/' + w0_label - # check for cases like # I-10@753B&US90@I-10(753B) # which becomes @@ -1661,13 +1661,6 @@ def __init__(self, all_waypoints, highway_systems, datacheckerrors, et): self.rg_vset_hash = {} all_waypoint_list = all_waypoints.point_list() - # add a unique name field to each waypoint, initialized to - # None, which should get filled in later for any waypoint that - # is or shares a location with any waypoint in an active or - # preview system - for w in all_waypoint_list: - w.unique_name = None - # to track the waypoint name compressions, add log entries # to this list self.waypoint_naming_log = [] From eae1ccbeadf29d91285f9a208d42b2697d122f62 Mon Sep 17 00:00:00 2001 From: eric bryant Date: Mon, 9 Dec 2019 18:47:02 -0500 Subject: [PATCH 3/4] Python straightfwd intersection enhancements with C++ changes for DIFFability: * waypoint_simplification_sort comparison also pays attention to w1 * WaypointQuadtree::graph_points() results in opposite order --- .../classes/GraphGeneration/HighwayGraph.cpp | 3 +- .../cplusplus/classes/Waypoint/Waypoint.cpp | 9 +- .../WaypointQuadtree/WaypointQuadtree.cpp | 10 +- siteupdate/python-teresco/siteupdate.py | 217 +++++++++++------- 4 files changed, 145 insertions(+), 94 deletions(-) diff --git a/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp b/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp index 28ee0209..5c46885f 100644 --- a/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp +++ b/siteupdate/cplusplus/classes/GraphGeneration/HighwayGraph.cpp @@ -30,9 +30,10 @@ class HighwayGraph // or preview system, or is colocated and not at the front // of its colocation list unsigned int counter = 0; - std::cout << et.et() + "Creating unique names and vertices" << std::flush; std::list graph_points = all_waypoints.graph_points(); + std::cout << et.et() + "Sorting graph index waypoints by name priority." << std::endl; graph_points.sort(waypoint_simplification_sort); + std::cout << et.et() + "Creating unique names and vertices" << std::flush; for (Waypoint *w : graph_points) { if (counter % 10000 == 0) std::cout << '.' << std::flush; counter++; diff --git a/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp b/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp index 0a60bc4f..92b40fab 100644 --- a/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp @@ -3,9 +3,12 @@ bool sort_root_at_label(Waypoint *w1, Waypoint *w2) } bool waypoint_simplification_sort(Waypoint *w1, Waypoint *w2) -{ if ( w2->ap_coloc.size() != 2 - || w2->ap_coloc.front()->route->abbrev.size() - || w2->ap_coloc.back()->route->abbrev.size() +{ if ( ( w2->ap_coloc.size() != 2 + || w2->ap_coloc.front()->route->abbrev.size() + || w2->ap_coloc.back()->route->abbrev.size() + ) && w1->ap_coloc.size() == 2 + && w1->ap_coloc.front()->route->abbrev.empty() + && w1->ap_coloc.back()->route->abbrev.empty() ) return 1; else return 0; } diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp index 477ede0b..b2d22a7c 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp @@ -147,10 +147,10 @@ std::list WaypointQuadtree::graph_points() std::list hg_points; if (refined()) { std::list add_points; - add_points = sw_child->graph_points(); hg_points.splice(hg_points.end(), add_points); - add_points = se_child->graph_points(); hg_points.splice(hg_points.end(), add_points); - add_points = nw_child->graph_points(); hg_points.splice(hg_points.end(), add_points); - add_points = ne_child->graph_points(); hg_points.splice(hg_points.end(), add_points); + add_points = sw_child->graph_points(); hg_points.splice(hg_points.begin(), add_points); + add_points = se_child->graph_points(); hg_points.splice(hg_points.begin(), add_points); + add_points = nw_child->graph_points(); hg_points.splice(hg_points.begin(), add_points); + add_points = ne_child->graph_points(); hg_points.splice(hg_points.begin(), add_points); } else for (Waypoint *w : points) { // skip if this point is occupied by only waypoints in devel systems @@ -162,7 +162,7 @@ std::list WaypointQuadtree::graph_points() else for (Waypoint *p : *(w->colocated)) if (p->route->system->active_or_preview()) w->ap_coloc.push_back(p); - hg_points.push_front(w); + hg_points.push_back(w); } return hg_points; } diff --git a/siteupdate/python-teresco/siteupdate.py b/siteupdate/python-teresco/siteupdate.py index 56c778ae..129ef77b 100755 --- a/siteupdate/python-teresco/siteupdate.py +++ b/siteupdate/python-teresco/siteupdate.py @@ -179,6 +179,33 @@ def point_list(self): else: return self.points + def graph_points(self): + # return a list of points to be used as indices to HighwayGraph vertices + hg_points = [] + if self.points is None: + hg_points.extend(self.ne_child.graph_points()) + hg_points.extend(self.nw_child.graph_points()) + hg_points.extend(self.se_child.graph_points()) + hg_points.extend(self.sw_child.graph_points()) + else: + for w in self.points: + # skip if this point is occupied by only waypoints in devel systems + if not w.is_or_colocated_with_active_or_preview(): + continue + # skip if colocated and not at front of list + if w.colocated is not None and w != w.colocated[0]: + continue + # store a colocated list with any devel system entries removed + if w.colocated is None: + w.ap_coloc = [w] + else: + w.ap_coloc = [] + for p in w.colocated: + if p.route.system.active_or_preview(): + w.ap_coloc.append(p) + hg_points.append(w) + return hg_points + def is_valid(self): """make sure the quadtree is valid""" if self.points is None: @@ -431,7 +458,7 @@ def angle(self,pred,succ): return math.degrees(math.acos(((x2 - x1)*(x1 - x0) + (y2 - y1)*(y1 - y0) + (z2 - z1)*(z1 - z0)) / math.sqrt(((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) + (z2 - z1)*(z2 - z1)) * ((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0) + (z1 - z0)*(z1 - z0))))) - def canonical_waypoint_name(self,log): + def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): """Best name we can come up with for this point bringing in information from itself and colocated points (if active/preview) """ @@ -444,13 +471,8 @@ def canonical_waypoint_name(self,log): if self.colocated is None: return name - # get a colocated list that any devel system entries removed - colocated = [] - for w in self.colocated: - if w.route.system.active_or_preview(): - colocated.append(w) # just return the simple name if only one active/preview waypoint - if (len(colocated) == 1): + if (len(self.ap_coloc) == 1): return name # straightforward 2-route intersection with matching labels @@ -460,17 +482,28 @@ def canonical_waypoint_name(self,log): # suffixes but otherwise matching route # US24@CO21_N&CO21@US24_E would become US24_E/CO21_N - if len(colocated) == 2: - w0_list_entry = colocated[0].route.list_entry_name() - w1_list_entry = colocated[1].route.list_entry_name() - w0_label = colocated[0].label - w1_label = colocated[1].label - if (w0_list_entry == w1_label or \ - w1_label.startswith(w0_list_entry + '_')) and \ - (w1_list_entry == w0_label or \ - w0_label.startswith(w1_list_entry + '_')): - log.append("Straightforward intersection: " + name + " -> " + w1_label + '/' + w0_label) - return w1_label + '/' + w0_label + if len(self.ap_coloc) == 2: + # check both refs independently, because datachecks are involved + one_ref_zero = self.ap_coloc[1].label_references_route(self.ap_coloc[0].route, datacheckerrors) + zero_ref_one = self.ap_coloc[0].label_references_route(self.ap_coloc[1].route, datacheckerrors) + if one_ref_zero and zero_ref_one: + newname = self.ap_coloc[1].label+"/"+self.ap_coloc[0].label + # if this is taken or if name_no_abbrev()s match, attempt to add in abbrevs if there's point in doing so + taken = newname in vertex_names + if (len(self.ap_coloc[0].route.abbrev) > 0 or len(self.ap_coloc[1].route.abbrev) > 0) \ + and (taken or self.ap_coloc[0].route.name_no_abbrev() == self.ap_coloc[1].route.name_no_abbrev()): + newname = self.ap_coloc[0].route.list_entry_name() \ + + (self.ap_coloc[1].label[self.ap_coloc[1].label.index('_'):] if '_' in self.ap_coloc[1].label else "") \ + + "/" \ + + self.ap_coloc[1].route.list_entry_name() \ + + (self.ap_coloc[0].label[self.ap_coloc[0].label.index('_'):] if '_' in self.ap_coloc[0].label else "") + message = "Straightforward intersection: " + name + " -> " + newname + if taken: + message += " (" + self.ap_coloc[1].label+"/"+self.ap_coloc[0].label + " already taken)" + log.append(message) + return newname + log.append("Straightforward intersection: " + name + " -> " + newname) + return newname # straightforward concurrency example with matching waypoint # labels, use route/route/route@label, except also matches @@ -480,19 +513,19 @@ def canonical_waypoint_name(self,log): # or possibly just compress ignoring the _ suffixes here routes = [] matches = 0 - for w in colocated: - if colocated[0].label == w.label or w.label[0] == '+': + for w in self.ap_coloc: + if self.ap_coloc[0].label == w.label or w.label[0] == '+': # avoid double route names at border crossings if w.route.list_entry_name() not in routes: routes.append(w.route.list_entry_name()) matches += 1 else: break - if matches == len(colocated): + if matches == len(self.ap_coloc): newname = "" for r in routes: newname += '/' + r - newname += '@' + colocated[0].label + newname += '@' + self.ap_coloc[0].label log.append("Straightforward concurrency: " + name + " -> " + newname[1:]) return newname[1:] @@ -510,26 +543,26 @@ def canonical_waypoint_name(self,log): # becomes # US20/NY30A/NY162 - for match_index in range(0,len(colocated)): - lookfor1 = colocated[match_index].route.list_entry_name() - lookfor2 = colocated[match_index].route.list_entry_name() + \ - '(' + colocated[match_index].label + ')' + for match_index in range(0,len(self.ap_coloc)): + lookfor1 = self.ap_coloc[match_index].route.list_entry_name() + lookfor2 = self.ap_coloc[match_index].route.list_entry_name() + \ + '(' + self.ap_coloc[match_index].label + ')' all_match = True - for check_index in range(0,len(colocated)): + for check_index in range(0,len(self.ap_coloc)): if match_index == check_index: continue - if (colocated[check_index].label != lookfor1) and \ - (colocated[check_index].label != lookfor2): + if (self.ap_coloc[check_index].label != lookfor1) and \ + (self.ap_coloc[check_index].label != lookfor2): all_match = False if all_match: - if (colocated[match_index].label[0:1].isnumeric()): + if (self.ap_coloc[match_index].label[0:1].isnumeric()): label = lookfor2 else: label = lookfor1 - for add_index in range(0,len(colocated)): + for add_index in range(0,len(self.ap_coloc)): if match_index == add_index: continue - label += '/' + colocated[add_index].route.list_entry_name() + label += '/' + self.ap_coloc[add_index].route.list_entry_name() log.append("Exit/Intersection: " + name + " -> " + label) return label @@ -549,35 +582,35 @@ def canonical_waypoint_name(self,log): # suffixes to put in and reduce the chance of conflicting names # and a second check to find matches when labels do not include # the abbrev field (which they often do not) - if len(colocated) > 2: + if len(self.ap_coloc) > 2: all_match = True - suffixes = [""] * len(colocated) - for check_index in range(len(colocated)): + suffixes = [""] * len(self.ap_coloc) + for check_index in range(len(self.ap_coloc)): this_match = False - for other_index in range(len(colocated)): + for other_index in range(len(self.ap_coloc)): if other_index == check_index: continue - if colocated[check_index].label.startswith(colocated[other_index].route.list_entry_name()): + if self.ap_coloc[check_index].label.startswith(self.ap_coloc[other_index].route.list_entry_name()): # should check here for false matches, like # NY50/67 would match startswith NY5 this_match = True - if '_' in colocated[check_index].label: - suffix = colocated[check_index].label[colocated[check_index].label.find('_'):] - if colocated[other_index].route.list_entry_name() + suffix == colocated[check_index].label: + if '_' in self.ap_coloc[check_index].label: + suffix = self.ap_coloc[check_index].label[self.ap_coloc[check_index].label.find('_'):] + if self.ap_coloc[other_index].route.list_entry_name() + suffix == self.ap_coloc[check_index].label: suffixes[other_index] = suffix - elif colocated[check_index].label.startswith(colocated[other_index].route.name_no_abbrev()): + elif self.ap_coloc[check_index].label.startswith(self.ap_coloc[other_index].route.name_no_abbrev()): this_match = True - if '_' in colocated[check_index].label: - suffix = colocated[check_index].label[colocated[check_index].label.find('_'):] - if colocated[other_index].route.name_no_abbrev() + suffix == colocated[check_index].label: + if '_' in self.ap_coloc[check_index].label: + suffix = self.ap_coloc[check_index].label[self.ap_coloc[check_index].label.find('_'):] + if self.ap_coloc[other_index].route.name_no_abbrev() + suffix == self.ap_coloc[check_index].label: suffixes[other_index] = suffix if not this_match: all_match = False break if all_match: - label = colocated[0].route.list_entry_name() + suffixes[0] - for index in range(1,len(colocated)): - label += "/" + colocated[index].route.list_entry_name() + suffixes[index] + label = self.ap_coloc[0].route.list_entry_name() + suffixes[0] + for index in range(1,len(self.ap_coloc)): + label += "/" + self.ap_coloc[index].route.list_entry_name() + suffixes[index] log.append("3+ intersection: " + name + " -> " + label) return label @@ -586,20 +619,20 @@ def canonical_waypoint_name(self,log): # Still TODO: I-39@171C(90)&I-90@171C&US14@I-39/90 # try each as a possible route@exit type situation and look # for matches - for try_as_exit in range(len(colocated)): + for try_as_exit in range(len(self.ap_coloc)): # see if all colocated points are potential matches # when considering the one at try_as_exit as a primary # exit number - if not colocated[try_as_exit].label[0].isdigit(): + if not self.ap_coloc[try_as_exit].label[0].isdigit(): continue all_match = True # get the route number only version for one of the checks below - route_number_only = colocated[try_as_exit].route.name_no_abbrev() + route_number_only = self.ap_coloc[try_as_exit].route.name_no_abbrev() for pos in range(len(route_number_only)): if route_number_only[pos].isdigit(): route_number_only = route_number_only[pos:] break - for try_as_match in range(len(colocated)): + for try_as_match in range(len(self.ap_coloc)): if try_as_exit == try_as_match: continue this_match = False @@ -608,26 +641,26 @@ def canonical_waypoint_name(self,log): # number in parens, match concurrency exit number format # nn(rr), match with _ suffix (like _N), match with a slash # match with exit number only - if (colocated[try_as_match].label == colocated[try_as_exit].route.list_entry_name() - or colocated[try_as_match].label == colocated[try_as_exit].route.name_no_abbrev() - or colocated[try_as_match].label == colocated[try_as_exit].route.list_entry_name() + "(" + colocated[try_as_exit].label + ")" - or colocated[try_as_match].label == colocated[try_as_exit].label + "(" + route_number_only + ")" - or colocated[try_as_match].label == colocated[try_as_exit].label + "(" + colocated[try_as_exit].route.name_no_abbrev() + ")" - or colocated[try_as_match].label.startswith(colocated[try_as_exit].route.name_no_abbrev() + "_") - or colocated[try_as_match].label.startswith(colocated[try_as_exit].route.name_no_abbrev() + "/") - or colocated[try_as_match].label == colocated[try_as_exit].label): + if (self.ap_coloc[try_as_match].label == self.ap_coloc[try_as_exit].route.list_entry_name() + or self.ap_coloc[try_as_match].label == self.ap_coloc[try_as_exit].route.name_no_abbrev() + or self.ap_coloc[try_as_match].label == self.ap_coloc[try_as_exit].route.list_entry_name() + "(" + self.ap_coloc[try_as_exit].label + ")" + or self.ap_coloc[try_as_match].label == self.ap_coloc[try_as_exit].label + "(" + route_number_only + ")" + or self.ap_coloc[try_as_match].label == self.ap_coloc[try_as_exit].label + "(" + self.ap_coloc[try_as_exit].route.name_no_abbrev() + ")" + or self.ap_coloc[try_as_match].label.startswith(self.ap_coloc[try_as_exit].route.name_no_abbrev() + "_") + or self.ap_coloc[try_as_match].label.startswith(self.ap_coloc[try_as_exit].route.name_no_abbrev() + "/") + or self.ap_coloc[try_as_match].label == self.ap_coloc[try_as_exit].label): this_match = True if not this_match: all_match = False if all_match: label = "" - for pos in range(len(colocated)): + for pos in range(len(self.ap_coloc)): if pos == try_as_exit: - label += colocated[pos].route.list_entry_name() + "(" + colocated[pos].label + ")" + label += self.ap_coloc[pos].route.list_entry_name() + "(" + self.ap_coloc[pos].label + ")" else: - label += colocated[pos].route.list_entry_name() - if pos < len(colocated) - 1: + label += self.ap_coloc[pos].route.list_entry_name() + if pos < len(self.ap_coloc) - 1: label += "/" log.append("Exit number: " + name + " -> " + label) return label @@ -640,15 +673,15 @@ def canonical_waypoint_name(self,log): slash = self.label.index('/') reverse = self.label[slash+1:]+'/'+self.label[:slash] matches = 1 - # colocated[0].label *IS* label, so no need to check that - for i in range(1, len(colocated)): - if colocated[i].label == self.label or colocated[i].label == reverse: + # self.ap_coloc[0].label *IS* label, so no need to check that + for i in range(1, len(self.ap_coloc)): + if self.ap_coloc[i].label == self.label or self.ap_coloc[i].label == reverse: matches += 1 else: break - if matches == len(colocated): + if matches == len(self.ap_coloc): routes = [] - for w in colocated: + for w in self.ap_coloc: if w.route.list_entry_name() not in routes: routes.append(w.route.list_entry_name()) @@ -668,8 +701,6 @@ def canonical_waypoint_name(self,log): # How about? # I-581@4&US220@I-581(4)&US460@I-581&US11AltRoa@I-581&US220AltRoa@US220_S&VA116@I-581(4) - # INVESTIGATE: VA262@US11&US11@VA262&VA262@US11_S - # should be 2 colocated, shows up as 3? # TODO: I-610@TX288&I-610@38&TX288@I-610 # this is the overlap point of a loop @@ -708,6 +739,32 @@ def hashpoint(self): return self return self.colocated[0] + def waypoint_simplification_priority(self): + if len(self.ap_coloc) != 2 \ + or len(self.ap_coloc[0].route.abbrev) > 0 \ + or len(self.ap_coloc[1].route.abbrev) > 0: + return 1 + else: + return 0 + + def label_references_route(self, r, datacheckerrors): + no_abbrev = r.name_no_abbrev() + if self.label[:len(no_abbrev)] != no_abbrev: + return False + if len(self.label) == len(no_abbrev) \ + or self.label[len(no_abbrev)] == '_': + return True + if self.label[len(no_abbrev):len(no_abbrev)+len(r.abbrev)] != r.abbrev: + #if self.label[len(no_abbrev)] == '/': + #datacheckerrors.append(route, [self.label], "UNEXPECTED_DESIGNATION", self.label[len(no_abbrev)+1:]) + return False + if len(self.label) == len(no_abbrev) + len(r.abbrev) \ + or self.label[len(no_abbrev) + len(r.abbrev)] == '_': + return True + #if self.label[len(no_abbrev) + len(r.abbrev)] == '/': + #datacheckerrors.append(route, [self.label], "UNEXPECTED_DESIGNATION", self.label[len(no_abbrev)+len(r.abbrev)+1:]) + return False + class HighwaySegment: """This class represents one highway segment: the connection between two Waypoints connected by one or more routes""" @@ -1659,7 +1716,8 @@ def __init__(self, all_waypoints, highway_systems, datacheckerrors, et): self.vertices = {} # hash table containing a set of vertices for each region self.rg_vset_hash = {} - all_waypoint_list = all_waypoints.point_list() + print(et.et() + "Sorting graph index waypoints by name priority.", flush=True) + graph_points = sorted(all_waypoints.graph_points(), key=lambda Waypoint: Waypoint.waypoint_simplification_priority()) # to track the waypoint name compressions, add log entries # to this list @@ -1671,23 +1729,15 @@ def __init__(self, all_waypoints, highway_systems, datacheckerrors, et): # of its colocation list counter = 0 print(et.et() + "Creating unique names and vertices", end="", flush=True) - for w in all_waypoint_list: + for w in graph_points: if counter % 10000 == 0: print('.', end="", flush=True) counter += 1 - # skip if this point is occupied by only waypoints in - # devel systems - if not w.is_or_colocated_with_active_or_preview(): - continue - - # skip if colocated and not at front of list - if w.colocated is not None and w != w.colocated[0]: - continue # come up with a unique name that brings in its meaning # start with the canonical name - point_name = w.canonical_waypoint_name(self.waypoint_naming_log) + point_name = w.canonical_waypoint_name(self.waypoint_naming_log, vertex_names, datacheckerrors) # if that's taken, append the region code if point_name in vertex_names: @@ -1709,10 +1759,7 @@ def __init__(self, all_waypoints, highway_systems, datacheckerrors, et): # we're good; now add point_name to the set and construct a vertex vertex_names.add(point_name) - if w.colocated is None: - self.vertices[w] = HGVertex(w, point_name, datacheckerrors, self.rg_vset_hash) - else: - self.vertices[w] = HGVertex(w.colocated[0], point_name, datacheckerrors, self.rg_vset_hash) + self.vertices[w] = HGVertex(w, point_name, datacheckerrors, self.rg_vset_hash) # now that vertices are in place with names, set of unique names is no longer needed vertex_names = None From 28d0e8aa9744cd178c3af1cd13b9eacf783517f8 Mon Sep 17 00:00:00 2001 From: eric bryant Date: Mon, 9 Dec 2019 19:28:13 -0500 Subject: [PATCH 4/4] space -> underscore in waypointsimplification.log --- .../canonical_waypoint_name/3plus_intersection.cpp | 2 +- .../canonical_waypoint_name.cpp | 2 +- .../canonical_waypoint_name/exit_number.cpp | 2 +- .../reversed_border_labels.cpp | 2 +- .../straightforward_concurrency.cpp | 2 +- .../straightforward_intersection.cpp | 4 ++-- siteupdate/python-teresco/siteupdate.py | 14 +++++++------- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/3plus_intersection.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/3plus_intersection.cpp index ca7b1445..dd646eaf 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/3plus_intersection.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/3plus_intersection.cpp @@ -49,7 +49,7 @@ if (ap_coloc.size() > 2) { std::string newname = ap_coloc[0]->route->list_entry_name() + suffixes[0]; for (unsigned int index = 1; index < ap_coloc.size(); index++) newname += "/" + ap_coloc[index]->route->list_entry_name() + suffixes[index]; - log.push_back("3+ intersection: " + name + " -> " + newname); + log.push_back("3+_intersection: " + name + " -> " + newname); return newname; } } diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp index be3cfa6b..12f34539 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/canonical_waypoint_name.cpp @@ -33,6 +33,6 @@ std::string Waypoint::canonical_waypoint_name(std::list &log, std:: // TODO: I-610@TX288&I-610@38&TX288@I-610 // this is the overlap point of a loop - log.push_back("Keep failsafe: " + name); + log.push_back("Keep_failsafe: " + name); return name; } diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/exit_number.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/exit_number.cpp index 9f7bfa7e..4bd5cedc 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/exit_number.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/exit_number.cpp @@ -44,7 +44,7 @@ for (unsigned int try_as_exit = 0; try_as_exit < ap_coloc.size(); try_as_exit++) if (pos < ap_coloc.size()-1) newname += "/"; } - log.push_back("Exit number: " + name + " -> " + newname); + log.push_back("Exit_number: " + name + " -> " + newname); return newname; } } diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/reversed_border_labels.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/reversed_border_labels.cpp index 80923a2a..cf491959 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/reversed_border_labels.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/reversed_border_labels.cpp @@ -22,7 +22,7 @@ if (slash) for (unsigned int i = 1; i < routes.size(); i++) newname += '/' + routes[i]; newname += '@' + label; - log.push_back("Reversed border labels: " + name + " -> " + newname); + log.push_back("Reversed_border_labels: " + name + " -> " + newname); return newname; } } diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_concurrency.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_concurrency.cpp index d07ef674..422a79f7 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_concurrency.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_concurrency.cpp @@ -19,6 +19,6 @@ if (matches == ap_coloc.size()) for (std::string &r : routes) newname += '/' + r; newname += '@' + ap_coloc.front()->label; - log.push_back("Straightforward concurrency: " + name + " -> " + newname.substr(1)); + log.push_back("Straightforward_concurrency: " + name + " -> " + newname.substr(1)); return newname.substr(1); } diff --git a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp index 47287232..c80f54b1 100644 --- a/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/canonical_waypoint_name/straightforward_intersection.cpp @@ -18,12 +18,12 @@ if (ap_coloc.size() == 2) ) { const char *u0 = strchr(ap_coloc[0]->label.data(), '_'); const char *u1 = strchr(ap_coloc[1]->label.data(), '_'); std::string newname = (ap_coloc[0]->route->list_entry_name() + (u1 ? u1 : "")) + "/" + (ap_coloc[1]->route->list_entry_name() + (u0 ? u0 : "")); - std::string message = "Straightforward intersection: " + name + " -> " + newname; + std::string message = "Straightforward_intersection: " + name + " -> " + newname; if (taken) message += " (" + ap_coloc[1]->label+"/"+ap_coloc[0]->label + " already taken)"; log.push_back(message); return newname; } - log.push_back("Straightforward intersection: " + name + " -> " + newname); + log.push_back("Straightforward_intersection: " + name + " -> " + newname); return newname; } } diff --git a/siteupdate/python-teresco/siteupdate.py b/siteupdate/python-teresco/siteupdate.py index 129ef77b..7f1c1343 100755 --- a/siteupdate/python-teresco/siteupdate.py +++ b/siteupdate/python-teresco/siteupdate.py @@ -497,12 +497,12 @@ def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): + "/" \ + self.ap_coloc[1].route.list_entry_name() \ + (self.ap_coloc[0].label[self.ap_coloc[0].label.index('_'):] if '_' in self.ap_coloc[0].label else "") - message = "Straightforward intersection: " + name + " -> " + newname + message = "Straightforward_intersection: " + name + " -> " + newname if taken: message += " (" + self.ap_coloc[1].label+"/"+self.ap_coloc[0].label + " already taken)" log.append(message) return newname - log.append("Straightforward intersection: " + name + " -> " + newname) + log.append("Straightforward_intersection: " + name + " -> " + newname) return newname # straightforward concurrency example with matching waypoint @@ -526,7 +526,7 @@ def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): for r in routes: newname += '/' + r newname += '@' + self.ap_coloc[0].label - log.append("Straightforward concurrency: " + name + " -> " + newname[1:]) + log.append("Straightforward_concurrency: " + name + " -> " + newname[1:]) return newname[1:] # check for cases like @@ -611,7 +611,7 @@ def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): label = self.ap_coloc[0].route.list_entry_name() + suffixes[0] for index in range(1,len(self.ap_coloc)): label += "/" + self.ap_coloc[index].route.list_entry_name() + suffixes[index] - log.append("3+ intersection: " + name + " -> " + label) + log.append("3+_intersection: " + name + " -> " + label) return label # Exit number simplification: I-90@47B(94)&I-94@47B @@ -662,7 +662,7 @@ def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): label += self.ap_coloc[pos].route.list_entry_name() if pos < len(self.ap_coloc) - 1: label += "/" - log.append("Exit number: " + name + " -> " + label) + log.append("Exit_number: " + name + " -> " + label) return label # Check for reversed border labels @@ -689,7 +689,7 @@ def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): for i in range(1, len(routes)): newname += '/' + routes[i] newname += '@' + self.label - log.append("Reversed border labels: " + name + " -> " + newname) + log.append("Reversed_border_labels: " + name + " -> " + newname) return newname # TODO: I-20@76&I-77@16 @@ -705,7 +705,7 @@ def canonical_waypoint_name(self,log, vertex_names, datacheckerrors): # TODO: I-610@TX288&I-610@38&TX288@I-610 # this is the overlap point of a loop - log.append("Keep failsafe: " + name) + log.append("Keep_failsafe: " + name) return name def simple_waypoint_name(self):