graphs, continued ece 297. review: map as a graph intersections nodes –unique id and unique name...
TRANSCRIPT
Graphs, Continued
ECE 297
Review: Map as a Graph
• Intersections Nodes– unique id and unique name
• Street Segments Edges– unique id only
0
1
2
3
4
Bloor & Yonge
Bay & College
Bloor & Bay
College & Spadina
DVP & unknown(20)
01
2 3
4
5
ids for intersections & street segments
overlap remember which is which in your
code
Graph Type?
• Undirected or directed?
• One way streets directed• A two way street makes 2 edges
Graph Representation?• Adjacency List or Adjacency Matrix?
0
1
2
3
4
Adjacency ListNode 0: out_edge {3}Node 1: out_edge {0, 3, 2}Node 2: out_edge {3, 4}…
Might also have “in_edge” list if you want/need it
Adjacency Matrix
0 1 2 3 4
To NodeF
rom N
ode
0 0 0 0 1 0
1 1 0 1 1 0
2 0 0 0 1 1
3 0 1 0 0 0
4 0 0 1 0 0
Memory Complexity• N intersections (N ~ 166,000 for Toronto)
0
1
2
3
4
Adjacency ListNode 0: out_edge {3}Node 1: out_edge {0, 3, 2}Node 2: out_edge {3, 4}…
Adjacency Matrix
0 1 2 3 4
To NodeF
rom N
ode
0 0 0 0 1 0
1 1 0 1 1 0
2 0 0 0 1 1
3 0 1 0 0 0
4 0 0 1 0 0
• Adjacency matrix:– N rows x N columns– Memory required: O(N2)– 26 GB (for 1 byte / entry)!
• Adjacency list:– N lists– Average: 4 ints / list– O(N)– 2.6 MB!
libstreetsdatabase: More Than Connectivity
• Intersections (Nodes)– id– name– lattitude, longitude
• StreetSegments (Edges)– id– Street id What street are you part of?
• This has a name
– Speed limit– One way (from node to node)– Curvepoints shape of street segment
StreetSegment: Curve Points
• Not all StreetSegments (city blocks) are straight
• If not straight, have CurvePoints list of (lat,lon) points followed between intersections
libstreetdatabase: Streets & POI
• Streets– list of StreetSegments– unique id– unique name (e.g. “Yonge”)
• Points of Interest– id– location– non-unique name (e.g. “Tim Horton’s)
• Natural Features– ponds, parks, etc.– Not used in milestone1
Graph Reference
• Chapter 22 of Introduction to Algorithms by Cormen et al
Milestone 1
• List of functions to implement in m1.h– Comments say what each should do– Good practice: documentation is in your code!– Header file: comments say how to use
• Not how it is built
• Detailed unit tests in ece297exercise– These give the detailed specification– “Test-driven development”– Most test functionality– Some also test speed too slow fail– One runs valgrind to check memory OK
Milestone 1 Unit Tests
// Load anything you want hereload_map (“toronto.bin”);
int id = find_intersection_id_from_name (“Yonge & Bloor”);if (id != 22333) { <your code failed the test, record it>}// lots more tests
// clean up here; all memory should be de-allocatedclose_map ();
main.cpp(made by unit tests)
load_map
// Load anything you want hereload_map (string map_name);
What should I do in load_map ()?3 basic approaches
1. load_map does nothing • Implement all your higher-level api calls by calling lower level api
(libstreetdatabaseapi) directly• Stateless• Often easier to code & debug• But may be slow for some calls
2. load_map builds everything you could ever want• Never have to call lower-level api again• You have full control make beautiful, fast data structures
load_map
// Load anything you want hereload_map (string map_name);
3. Blended approach• load_map creates some new data structures• Use them for api calls that need them for speed• Call lower level api when it is fast enough
• All 3 approaches are reasonable• Your choice which to use• If you fail speed tests, change your approach
• load_map not automatically speed tested• Spec: keep speed interactive• Your TA will notice in the demo if it is very slow (> 1 s or so)• Otherwise OK
Clean Up
// Load anything you want hereload_map (“toronto.bin”);
int id = find_intersection_id_from_name (“Yonge & Bloor”);if (id != 22333) { <your code failed the test, record it>}// lots more tests
// clean up here; all memory should be de-allocatedclose_map ();
main.cpp(made by unit tests)
ece297exercise runs valgrind on a load_map(), use, close_map() testMust free all memory or will lose marks
Automatic Memory Checking• Memory checking:
valgrind slowdown ~10x
• Testing: want fast & thorough
• Small test case: almost as thorough as big
• St. Helena
load_map How Do I Get Its Data?
// Load anything you want hereload_map (“toronto.bin”);
int id = find_intersection_id_from_name (“Yonge & Bloor”);if (id != 22333) { <your code failed the test, record it>}// lots more tests
// clean up here; all memory should be de-allocatedclose_map ();
main.cpp(made by unit tests)
?
Easy way global variable
But Aren’t Global Variables Bad?
• Yes, if you overuse them– E.g. could pass argument but use global
variable to avoid typing!
• But almost all programs have some– Or something very similar– Limit their number
• Group related data into classes (e.g. StreetGraph?) organizes data and avoids lots of namespace pollution
StreetGraph
load_map()close_map()
find_intersection_id_from_name (“B & Y“);
Global Variable Pitfalls
• Anyone can use / call functions of / delete our global object– Would be nice if we could check it was set up first
StreetGraph *streetGraph; // Pointer to your data!
int find_intersection_id_from_name (string intersection_name){ streetGraph->answerMe (intersection_name); // What if streetGraph isn’t loaded yet? // Crash!
delete streetGraph; // Thought I should clean up, but my teammates will be // surprised when they try to use streetGraph next!}
Object-Oriented Alternative
• Design pattern: singleton– Have one loaded copy of a certain object– Many parts of the program need it
StreetGraph
load_map()close_map()
find_intersection_id_from_name (“B & Y“);
• When function asks for access– Return a pointer to the singleton object
• But can check that it is loaded first
StreetGraph as a Singletonclass StreetGraph {private: static StreetGraph *theObjectPtr; // One copy per class
public: StreetGraph (string mapName) { if (theObjectPtr != NULL) { cerr << “StreetGraph already loaded!” << endl; . . . // take some action; else { ... // Load up stuff theObjectPtr = this; } }
static StreetGraph *getObjectPtr ( ) { if (theObjectPtr == NULL) { cerr << “StreetGraph not loaded yet!” << endl; . . . // could end the program, or could load stuff up } return (theObjectPtr); }}
Can call without an object
Replaces our global variable: like a controlled
access global variable
Singletonclass StreetGraph {...public: ~StreetGraph () { ... // Clean everything up theObjectPtr = NULL; // Says we’re not loaded }}
StreetGraph.h
#include “StreetGraph.h”
void myFunc ( ) { StreetGraph *streetGraph = StreetGraph::getObjectPtr (); streetGraph->someQuery ( ... ); ...}
somefile.cpp
Calling without an object use full name
Further Reading
• Common problems, and how to map them to software designs
• E.g. singleton pattern
• Inspired by patterns in architecture
Team Formation
Dr. Tallman
ECE297 Tutorials, Jan 21 & Jan 23
• Your team will meet your Communication Instructor (CI) and schedule a weekly 30-minute meeting beginning the following week.
• Wed, Jan 21, 1-3pm, students go to GB404• Fri, Jan 23, 9-11am, students go to GB412• Fri, Jan 23, 3-5pm, students go to GB412 • If you do not have a full team formed by these
dates, come to your scheduled tutorial, and Dr. Tallman will assist you.