Lab Assignment 5 Solution



Getting motivated

ACME Shipping needs your help! They have obtained the rights to ship goods between a number of cities across the world. Use your newly acquired knowledge about graphs to write a program called “citysim” that can tell ACME Shipping what the shortest valid route is between any two cities. Being customer friendly, ACME Shipping wants to explore two options: (i) a cheap rate based on distance traveled and (ii) a more expensive rate based on time in transit. See details below. Lots of them.

Lab submission and due date

Submit your work via Canvas no later than 11:59pm Wednesday October 23, 2019. You submit only one file called Citysim.cpp. The incremental development outlined below is merely intended to walk you through the process of completing the assignment. CS307 students will write additional code as outlined below. CS302 are free to write this code as well but there is no extra credit to be earned this time.

While it may seem like you have a long time to do this assignment, keep in mind that Fall Break is coming up. Thus, you really only a week to get the job done. Make sure you have code that compiles and does at least part of the assignment, if not all of it by the due date.

Getting started and what you need to do

To help you get started, run the Hydra script /home/cs302/labs/lab5/copy to obtain the following files: scitysim (Hydra solution executable), city_list.txt (input data), Citysim.cpp (skeleton code), and a makefile. Your job is to write the citysim program and make it behave as described next.

While you have some design freedom, you must base your code on the classes and functions discussed next. How you tie them all together is up to you. Also, floating-point computations should be done using floats, not doubles. Most math functions take and produce doubles. That’s fine. Feed them floats and assign the output to floats.

Please raise concerns about assignment inconsistencies or unspoken design criteria on sooner rather than later, so that clarifications can be shared with the class as early as possible.

You might find it helpful to take a glance at the city_list.txt snippet included below before you continue reading.

  • Version 1 should implement a city class that stores the name (string), type (string), zone (int), latitude (float), longitude (float) and population (int). Make these variables private data members. Add get_variable() functions for each variable. Overload the input and output operators to facilitate “fin >> city” and “fout << city” type code. The city type is either REGIONAL or GATEWAY. We discuss these in more detail below.

Next, implement function read_cityinfo() which reads the “city_list.txt” file in the current directory into a vector<city> array using the overloaded city input operator. Empty lines or lines that begin with a hash symbol (#) should be ignored. You may find it convenient to also implement function write_cityinfo() which writes the contents of the vector<city> array to stdout or an appropriately named file, so you know you read things correctly. See below for example output from the solution code which produces a file called “city_info.txt”. The name field is 18 characters wide. The type and population fields are 12 and 10 characters wide, respectively. The zone is 2 characters wide. The latitude and longitude fields are 8 characters wide and the output is restricted to two decimal places.

Note: The latitude and longitude values are in degrees in city_list.txt and city_info.txt. However, your program will need them to be in radians for internal use. Perform the necessary conversion when you read and write these variables. Recall that radians=degrees*(pi/180) and degrees=radians*(180/pi).

  • Version 2 should implement a travelcost class which computes and contains a table of distances between all cities and a table of the time it takes to get from one city to another. Since the distance from A to B is the same as from B to A, store each of these tables in a 1D array that holds the diagonal and lower triangle of the full matrix; we don’t need the diagonal, but including it simplifies implementation. Say the equivalent 2D table[i][j] is NxN. Then the 1D table is of size N*(N+1)/2 and you access the elements using using table[i*(i+1)/2+j] where j <i. You are free to create two independent tables, but you may find it more convenient to use an array of vectors instead. That is,

vector<float> distance_table;
vector<float> time_table;


vector<float> table[2];

Either way, create an overloaded function operator that returns the same value for travelcost(mode,i,j) as for travelcost(mode,j,i) by looking the appropriate value in the 1D array. Here mode refers to distance (0) or time (1). Hint: Have the overloaded function operator swap arguments i and j if i <j before doing a lookup. Hint: The mode controls whether you look up a distance or a time.

Use the great-circle distance when computing the distance between two cities. This is the shortest distance between them on a sphere representing the Earth which we will assume has a radius of 3,982 miles. Don’t try to be clever and use a more accurate radius as it will throw your output off relative to the solution code which filed called “city_info.txt”. Also, use the Haversine Formula for your computation.

See for mathematical details.

Round the distances to the closest 25.0 mile distance. This will make it easier to compare your distances with those produced by the solution code. Hint: Set distance = 25.0*round(distance/25.0).

ACME Shipping has access to large fleet of trucks. They travel at an average speed of 65 mph. They also have access to planes. They travel at an average speed of 520 mph. The rules for when to use a truck versus a plane are as follows.

— Goods shipped between REGIONAL cities in the same zone go by truck.

— Goods shipped between REGIONAL cities and a GATEWAY city in the same zone go by plane.

— Goods shipped between GATEWAY cities go by plane no matter what the zone they are in.

You may find it convenient to also implement functions write_traveldistance() write_traveltime() which write the contents of the travelcost tables stdout or appropriately named files, so you know you compute these correctly. See below for example output from the solution code which produces files called “city_distancetable.txt”. and “city_timetable.txt”.

  • Version 3 should implement function create_citygraph() which determines which cities are adjacent to one another (connected) thereby implicitly creating a graph. The rules for adjacency are as follows.

— A REGIONAL city is adjacent to all other REGIONAL cities in the same zone. A REGIONAL city is also adjacent to the closest GATEWAY city in the same zone.

— A GATEWAY city is adjacent to all other GATEWAY cities in the same zone. A GATEWAY city is also adjacent to the closest GATEWAY in each of the other zones if the distance is 6,000 miles or less.

— In order to make the graph undirected, adjacency is bidirectional. Thus, if A is adjacent to B, then B is also adjacent to A. This can result in a GATEWAY city becoming connected with multiple GATEWAY cities in another zone (see for example Cairo_EG below).

Hint: First extract an index list for each type of city. Then iterate thru these lists following the above rules. Use the indices to look up the pertinent information in the vector<city> array discussed above. In fact, think of these indices as pointers.

You may find it convenient to also implement a function called write_citygraph() and have it write the graph to stdout or an appropriately named fil. so you know you connected the cities correctly. See below for example output from the solution code which produces a file called “city_graph.txt”.

  • Version 4 should add the ability to determine the shortest path between any two cities using Dijkstra’s algorithm. The output consists of the sequence of cities from source to sink (destination) along with the incremental and cumulative distances and travel times. This is likely the easiest step of them all. Embed the code from the Dijkstra code handout. Add logic to select between use of the distance and time edge weights you computed earlier. The algoithm works the same either way but wil produce different answers if the optimal paths are different. See an example below.

Update the main program to take one of two command-line options:

unix> Citysim -distance|time

Then have the user input an endless sequence of city pair names for which the shorted path is reported. Hint: In order to translate the names into the indices used internally, have the read_cityinfo() function create a map that links the two: “index = map[name]”. This will allow fast lookup of an index given a name.

  • The following is optional for CS302 students (no extra credit this time) but required in order for CS307 students to get full credit. That is, CS307 students will have up to 10 points deducted if the functionality described next is not included or doesn’t work right.

Add the ability to input just a partial name, e.g., “Knoxville” or even just “Knox” for “Knoxville_TN”. In case of ambiguity, choose the city name that follows the partial name in a lexicographical order, e.g., “K” may produce “Kansas_City_KS” instead of “Knoxville_TN”. To be acceptable, this city must match the search prefix. Thus, “Knox” should produce a city that begins with that, e.g., “Knoxvegas_TN”. Run the solution code to determine the desired behavior. Your code should function similarly. Hint: The STL algorithm map::upper_bound() can do the lookup for you.

  • See for a Google map with the city graph displayed. You can pan and zoom using the mouse directly or the little control pad in the upper left hand corner. The trajectories stand out more clearly on the map than the satellite data. The white text is courtesy of Google who now charges for use of their maps.

Input file: citylist.txt (abbreviated)

unix> cat citylist.txt
# AFRICA Zone 1
1 Cairo_EG GATEWAY  30.058 31.229 17800000
1 Johannesburg_SA GATEWAY -26.204444 28.045556 7151500

# ASIA Zone 2
2 Beijing_CN REGIONAL 39.916667 116.383333 21700000
2 Hong_Kong_CN REGIONAL 22.3 114.2 7400000
2 Taipei_TW REGIONAL 25.066667 121.516667 8500000
2 Tokyo_JP GATEWAY 35.683333 139.766667 35000000
2 Seoul_KR REGIONAL 37.55 126.983333 24472000


Output file: city_info.txt (abbreviated)

unix> ./citysim -graphinfo
unix> cat ./city_info.txt


  0 Cairo_EG          GATEWAY     1   17800000   30.06   31.23
  1 Johannesburg_SA   GATEWAY     1    7151500  -26.20   28.05
  2 Beijing_CN        REGIONAL    2   21700000   39.92  116.38
  3 Hong_Kong_CN      REGIONAL    2    7400000   22.30  114.20
  4 Taipei_TW         REGIONAL    2    8500000   25.07  121.52
  5 Tokyo_JP          GATEWAY     2   35000000   35.68  139.77
  6 Seoul_KR          REGIONAL    2   24472000   37.55  126.98
  7 Bangalore_IN      GATEWAY     2   12350000   12.97   77.57


Output file: city_distancetable.txt (abbreviated)

unix> ./citysim -graphinfo
unix> cat ./city_distancetable.txt


  1 Johannesburg_SA to Cairo_EG .......... 3925.0 miles

  2 Beijing_CN to Cairo_EG ............... 4725.0 miles
  2 Beijing_CN to Johannesburg_SA ........ 7325.0 miles

  3 Hong_Kong_CN to Cairo_EG ............. 5100.0 miles
  3 Hong_Kong_CN to Johannesburg_SA ...... 6700.0 miles
  3 Hong_Kong_CN to Beijing_CN ........... 1225.0 miles

  4 Taipei_TW to Cairo_EG ................ 5425.0 miles
  4 Taipei_TW to Johannesburg_SA ......... 7200.0 miles
  4 Taipei_TW to Beijing_CN .............. 1075.0 miles
  4 Taipei_TW to Hong_Kong_CN ............  500.0 miles

  5 Tokyo_JP to Cairo_EG ................. 5975.0 miles
  5 Tokyo_JP to Johannesburg_SA .......... 8475.0 miles
  5 Tokyo_JP to Beijing_CN ............... 1325.0 miles
  5 Tokyo_JP to Hong_Kong_CN ............. 1800.0 miles


Output file: city_timetable.txt (abbreviated)

unix> ./citysim -graphinfo
unix> cat ./city_timetable.txt


  1 Johannesburg_SA to Cairo_EG ..........  7.5 hours

  2 Beijing_CN to Cairo_EG ...............  9.1 hours
  2 Beijing_CN to Johannesburg_SA ........ 14.1 hours

  3 Hong_Kong_CN to Cairo_EG .............  9.8 hours
  3 Hong_Kong_CN to Johannesburg_SA ...... 12.9 hours
  3 Hong_Kong_CN to Beijing_CN ........... 18.8 hours

  4 Taipei_TW to Cairo_EG ................ 10.4 hours
  4 Taipei_TW to Johannesburg_SA ......... 13.8 hours
  4 Taipei_TW to Beijing_CN .............. 16.5 hours
  4 Taipei_TW to Hong_Kong_CN ............  7.7 hours

  5 Tokyo_JP to Cairo_EG ................. 11.5 hours
  5 Tokyo_JP to Johannesburg_SA .......... 16.3 hours
  5 Tokyo_JP to Beijing_CN ...............  2.5 hours
  5 Tokyo_JP to Hong_Kong_CN .............  3.5 hours

Output file: city_graph.txt (abbreviated)

unix> ./citysim -graphinfo
unix> cat ./city_graph.txt


  0 Cairo_EG
     1 Johannesburg_SA     3925.0 miles   7.5 hours
     5 Tokyo_JP            5975.0 miles  11.5 hours
     7 Bangalore_IN        3200.0 miles   6.2 hours
     9 Singapore_SG        5150.0 miles   9.9 hours
    13 London_UK           2200.0 miles   4.2 hours
    16 Frankfurt_DE        1825.0 miles   3.5 hours
    25 New_York_NY         5650.0 miles  10.9 hours

  1 Johannesburg_SA
     0 Cairo_EG            3925.0 miles   7.5 hours
     7 Bangalore_IN        4325.0 miles   8.3 hours
    16 Frankfurt_DE        5425.0 miles  10.4 hours
    28 Santiago_CL         5725.0 miles  11.0 hours
    29 Rio_de_Janeiro_BR   4450.0 miles   8.6 hours

  2 Beijing_CN
     3 Hong_Kong_CN        1225.0 miles  18.8 hours
     4 Taipei_TW           1075.0 miles  16.5 hours
     5 Tokyo_JP            1325.0 miles   2.5 hours
     6 Seoul_KR             600.0 miles   9.2 hours
     8 New_Delhi_IN        2350.0 miles  36.2 hours

  3 Hong_Kong_CN
     2 Beijing_CN          1225.0 miles  18.8 hours
     4 Taipei_TW            500.0 miles   7.7 hours
     6 Seoul_KR            1300.0 miles  20.0 hours
     8 New_Delhi_IN        2350.0 miles  36.2 hours


Functionality: Shortest path

unix> ./citysim -distance

Enter> Knoxville_TN Seattle_WA
    0.0 miles   0.0 hours : 21 Knoxville_TN      
 2125.0 miles  32.7 hours : 27 Seattle_WA         2125.0 miles  32.7 hours

Enter> London_UK Seoul_KR
    0.0 miles   0.0 hours : 13 London_UK         
  400.0 miles   0.8 hours : 16 Frankfurt_DE        400.0 miles   0.8 hours
 6225.0 miles  12.0 hours :  5 Tokyo_JP           5825.0 miles  11.2 hours
 6950.0 miles  13.4 hours :  6 Seoul_KR            725.0 miles   1.4 hours

unix> ./citysim -time

Enter> Knoxville_TN Seattle_WA
    0.0 miles   0.0 hours : 21 Knoxville_TN
  625.0 miles   1.2 hours : 25 New_York_NY         625.0 miles   1.2 hours
 3075.0 miles   5.9 hours : 22 Los_Angeles_CA     2450.0 miles   4.7 hours
 4050.0 miles   7.8 hours : 27 Seattle_WA          975.0 miles   1.9 hours

Enter> London_UK Seoul_KR
    0.0 miles   0.0 hours : 13 London_UK
  400.0 miles   0.8 hours : 16 Frankfurt_DE        400.0 miles   0.8 hours
 6225.0 miles  12.0 hours :  5 Tokyo_JP           5825.0 miles  11.2 hours
 6950.0 miles  13.4 hours :  6 Seoul_KR            725.0 miles   1.4 hours
unix> ./citysim -distance

Enter> Knox Seattle
    0.0 miles   0.0 hours : 21 Knoxville_TN
 2125.0 miles  32.7 hours : 27 Seattle_WA         2125.0 miles  32.7 hours

Enter> Knox S
    0.0 miles   0.0 hours : 21 Knoxville_TN
 2125.0 miles  32.7 hours : 26 San_Fransisco_CA   2125.0 miles  32.7 hours

Enter> * *
    0.0 miles   0.0 hours : 23 Mexico_City_MX
 1900.0 miles  29.2 hours : 26 San_Fransisco_CA   1900.0 miles  29.2 hours
 2250.0 miles  29.9 hours : 22 Los_Angeles_CA      350.0 miles   0.7 hours
 7750.0 miles  40.5 hours :  5 Tokyo_JP           5500.0 miles  10.6 hours
 9075.0 miles  43.0 hours :  4 Taipei_TW          1325.0 miles   2.5 hours
 9575.0 miles  50.7 hours :  3 Hong_Kong_CN        500.0 miles   7.7 hours

As shown above, the solution code accepts abbreviations. When multiple cities share the same prefix, alphabetical order applies. The solution code even accepts wildcards in which case it randomly choses a city. You can use this feature for source, destination, or both.

Grading rubric

Your code most compile and run free of segmentation faults in order to be fully graded.

15: Reading city_list.txt into city objects using overloaded input operator
30: Creating travelcost object that holds city travel distances and times
30: Creating graph by determing city adjacencies (graph edges) 
30: Finding shortest path between two cities and printing result to stdout
20: Writing main program that ties data structures and function calls together 
    to achieve overall functionality (CS307 extra assignment is part of this)

error: Content is protected !!