Skip to content

Commit bf464fa

Browse files
committed
enhance tutorial over the legacy way
- output origin node and destination node of each agent in agent_paths.csv, and change header 'volume' to 'OD volume' to avoid confusion; - enhance exception message when an invalid agent_no as a result of an invalid agent_id is encountered in _get_agent(); - udpate README on Major Updates introduced in v0.8.7a1.
1 parent de41050 commit bf464fa

File tree

4 files changed

+117
-18
lines changed

4 files changed

+117
-18
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ The Python modules are written in **Python 3.x**, which is the minimum requireme
3333

3434
## Quick Start
3535

36-
v0.8.7a1 includes several important changes in user interface. We highly recommend that you go through the [tutorial](https://github.com/jdlph/Path4GMNS/tree/dev/tests/tutorial.ipynb) written in Jupyter notebook with step-by-step demonstration using the latest release, no matter you are one of the existing users or new to Path4GMNS.
36+
v0.8.7a1 as a hot fix over v0.8.6 includes several important changes in user interface. We highly recommend that you go through the [tutorial](https://github.com/jdlph/Path4GMNS/tree/dev/tests/tutorial.ipynb) written in Jupyter notebook with step-by-step demonstration using the latest release, no matter you are one of the existing users or new to Path4GMNS.
3737

3838
## User Manual
3939

@@ -559,6 +559,10 @@ DTALite uses arrays rather than STL containers to store columns. These arrays ar
559559
22. More robust parsing functions (v0.8.6)
560560
23. Fix crucial bug in column generation module which will lead to wrong results if a zone has multiple nodes (v0.8.6)
561561
24. Fix crucial bug in setting up the capacity of each VDFPeriod instance if the input is missing from link.csv (v0.8.6)
562+
25. Add backwards compatibility on deprecated default agent type of p or passenger (v0.8.7a1)
563+
26. Fix potential issue that bin_index might not start from zero when all zones have the same number of nodes in _synthesize_bin_index() (v0.8.7a1)
564+
27. Fix potential zero division issue in _synthesize_bin_index() when min_ and max_ are the same (v0.8.7a1)
565+
28. Elaborate the legacy way of loading demand and zone information in tutorial (v0.8.7a1)
562566

563567
Detailed update information can be found in [Releases](https://github.com/jdlph/Path4GMNS/releases).
564568

@@ -572,7 +576,7 @@ You are encouraged to join our [Gmail group](https://groups.google.com/g/path4gm
572576

573577
## How to Cite
574578

575-
Li, P. and Zhou, X. (2022, September 27). *Path4GMNS*. Retrieved from https://github.com/jdlph/Path4GMNS
579+
Li, P. and Zhou, X. (2022, October 2). *Path4GMNS*. Retrieved from https://github.com/jdlph/Path4GMNS
576580

577581
## References
578582
Lu, C. C., Mahmassani, H. S., Zhou, X. (2009). Equivalent gap function-based reformulation and solution algorithm for the dynamic user equilibrium problem. Transportation Research Part B: Methodological, 43, 345-364.

path4gmns/classes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,8 @@ def _get_agent(self, agent_no):
531531
try:
532532
return self.agents[agent_no]
533533
except IndexError:
534-
print('Please provide a valid agent id, which shall be a\
535-
positive integer!')
534+
agent_id = agent_no + 1
535+
print('Please provide a valid agent id. agent_id: {agent_id} does NOT EXIST!')
536536

537537
def get_agent_node_path(self, agent_id, path_only):
538538
""" return the sequence of node IDs along the agent path

path4gmns/utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,10 +1178,12 @@ def output_agent_paths(ui, output_geometry=True, output_dir='.'):
11781178
line = ['agent_id',
11791179
'o_zone_id',
11801180
'd_zone_id',
1181+
'origin node',
1182+
'destination node',
11811183
'path_id',
11821184
'agent_type',
11831185
'demand_period',
1184-
'volume',
1186+
'OD volume',
11851187
'distance',
11861188
'node_sequence',
11871189
'link_sequence',
@@ -1232,6 +1234,8 @@ def output_agent_paths(ui, output_geometry=True, output_dir='.'):
12321234
line = [agent_id,
12331235
oz,
12341236
dz,
1237+
a.get_orig_node_id(),
1238+
a.get_dest_node_id(),
12351239
0,
12361240
at_str,
12371241
dp_str,

tests/tutorial.ipynb

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
"id": "annoying-berry",
8080
"metadata": {},
8181
"source": [
82-
"Navigate to the target data set directory. In this tutorial, we will use the data set where this Jupyter notebook is located for simplicity. You can check your present working directory (PWD) by the following commnad."
82+
"Navigate to the target data set directory. In this tutorial, we will use the [data set](https://github.com/jdlph/Path4GMNS/tree/dev/tests) where this Jupyter notebook is located for simplicity. You can check your present working directory (PWD) by the following commnad."
8383
]
8484
},
8585
{
@@ -293,7 +293,9 @@
293293
"\n",
294294
"Accessiblity defines where you can go given a time budget and a transportation mode (e.g., auto). You can find the number of accessible zones from each zone (zone_accessibility.csv) along with the free flow travel time for each OD pair (od_accessibility.csv).\n",
295295
"\n",
296-
"The default mode is 'auto' and the default time budget is 240 minutes. We will come back to multimodal evaluation in a later section."
296+
"The default mode is 'auto' and the default time budget is 240 minutes. We will come back to multimodal evaluation in a later section.\n",
297+
"\n",
298+
"Zone information is necessary for accessibility evaluation."
297299
]
298300
},
299301
{
@@ -305,6 +307,7 @@
305307
"source": [
306308
"# no need to load demand file for accessibility evaluation\n",
307309
"network = pg.read_network()\n",
310+
"pg.read_zones(network)\n",
308311
"\n",
309312
"pg.evaluate_accessibility(network, single_mode=True)"
310313
]
@@ -323,7 +326,7 @@
323326
"3. max accessibility. This metric refers to the zone with the maximum number of accessible zones. \n",
324327
"4. mean accessibility. The average number of accessible zones over a bin of zones (corresponding to a specific demographic) given a time budget and a transportation mode.\n",
325328
"\n",
326-
"Similar to accessiblity evaluation, the default mode is 'auto' but the default time budget is 60 minutes."
329+
"Similar to accessiblity evaluation, the default mode is 'auto' but the default time budget is 60 minutes. Zone information is still required here."
327330
]
328331
},
329332
{
@@ -334,6 +337,7 @@
334337
"outputs": [],
335338
"source": [
336339
"network = pg.read_network()\n",
340+
"pg.read_zones(network)\n",
337341
"\n",
338342
"pg.evaluate_equity(network, single_mode=True)"
339343
]
@@ -345,7 +349,7 @@
345349
"source": [
346350
"## 4. Move Foward to Multimodal Evaluation\n",
347351
"\n",
348-
"In order to perform multimodal evaluation, the corresponding modes (i.e., agent types) must be presented in settings.yml. It will be parsed by pyyaml (5.1 or higher) to the Python engine at run-time. A sample file looks like blow. You can start from here and modify it towards your own needs.\n",
352+
"In order to perform multimodal evaluation, the corresponding modes (i.e., agent types) must be presented in settings.yml. It will be parsed by pyyaml (5.1 or higher) to the Python engine at run-time. A sample file looks like blow. You can start from here and modify it towards your own needs. **Note that** the default agent type which is **'a' as type and 'auto' as name must be present in this file**. Otherwise, you will encounter an exception with message \"No AGENT type: a\". We will relax this requirement in a later release.\n",
349353
"\n",
350354
"```yaml\n",
351355
"agents:\n",
@@ -464,8 +468,8 @@
464468
"metadata": {},
465469
"outputs": [],
466470
"source": [
467-
"# no need to load demand file for accessibility evaluation\n",
468471
"network = pg.read_network()\n",
472+
"pg.read_zones(network)\n",
469473
"\n",
470474
"pg.evaluate_accessibility(network)"
471475
]
@@ -488,6 +492,7 @@
488492
"outputs": [],
489493
"source": [
490494
"network = pg.read_network()\n",
495+
"pg.read_zones(network)\n",
491496
"\n",
492497
"pg.evaluate_equity(network)"
493498
]
@@ -590,13 +595,51 @@
590595
"source": [
591596
"## 7. Legacy Way to Load Demand and Zone Info\n",
592597
"\n",
593-
"The legacy way to load demand is via read_network() by speicifying \"load_demand=True\". We have **deprecated** it and switch to the new way demonstrated in **Section 3.2**. If you came to Path4GMNS before v0.8.6, you probably notice that \"load_demand=True\" was not required as demand will be loaded by default. This is one of the changes introduced in v0.8.6. The legacy way are still used in [demo.py](https://github.com/jdlph/Path4GMNS/blob/dev/tests/demo.py) and the code examples in [User Manual](https://github.com/jdlph/Path4GMNS/tree/dev#user-manual), which will be updated gradually over time.\n",
598+
"### A Little Bit of History\n",
599+
"\n",
600+
"During the early development of Path4GMNS, demand.csv is presumed to be given and zone information is provided along node.csv. The latter is the current design of GMNS and is endorsed in [OSM2GMNS](https://github.com/jiawlu/OSM2GMNS). This assumption leads to the following legacy way (as the original design of Path4GMNS) to load demand and zone information while the new way demonstrated was in **Section 3.2**. \n",
601+
"\n",
602+
"```python\n",
603+
"network = pg.read_network(load_demand=True)\n",
604+
"```\n",
605+
"\n",
606+
"The demand file is specified in settings.yml as demand.csv. You can change it to any demand file in your PWD. This design actually allows us to load multiple demand files simultaneously corresponding to different period and agent_type. We will elaborate it in a future release.\n",
607+
"\n",
608+
"```yaml\n",
609+
"---\n",
610+
"# settings for Path4GMNS\n",
611+
"agents:\n",
612+
" - type: a\n",
613+
" name: auto\n",
614+
" vot: 10\n",
615+
" flow_type: 0\n",
616+
" pce: 1\n",
617+
" free_speed: 60\n",
618+
" use_link_ffs: true\n",
619+
" - type: w\n",
620+
" name: walk\n",
621+
" vot: 10\n",
622+
" flow_type: 0\n",
623+
" pce: 1\n",
624+
" free_speed: 10\n",
625+
" use_link_ffs: false\n",
626+
"\n",
627+
"demand_periods:\n",
628+
" - period: AM\n",
629+
" time_period: 0700_0800\n",
630+
"\n",
631+
"demand_files:\n",
632+
" - file_name: demand.csv\n",
633+
" format_type: column\n",
634+
" period: AM\n",
635+
" agent_type: a\n",
594636
"\n",
595-
"read_network(load_demand=True) will automatically check OD connectivity which **requires zone info to be specified in node.csv**. Otherwise, you will get an exception stating \"NO VALID OD VOLUME!! DOUBLE CHECK YOUR demand.csv\". \n",
637+
"```\n",
638+
"If you came to Path4GMNS before v0.8.6, you probably notice that \"load_demand=True\" was not required as demand will be loaded by default. This is one of the changes introduced in v0.8.6 to better promote the new way of loading demand. The legacy way are still used in [demo.py](https://github.com/jdlph/Path4GMNS/blob/dev/tests/demo.py) and the code examples in [User Manual](https://github.com/jdlph/Path4GMNS/tree/dev#user-manual), which will be updated gradually over time. You can still use this legacy way with the [existing sample data sets](https://github.com/jdlph/Path4GMNS/tree/dev/data), which do not have zone.csv but have zone information in node.csv. \n",
596639
"\n",
597-
"Here, we still present how to use this legacy way to find paths for agents and conduct traffic assigment. You can use it with the existing [sample data sets](https://github.com/jdlph/Path4GMNS/tree/dev/data), which do not have zone.csv. \n",
640+
"**Note that** read_network(load_demand=True) will **automatically check OD connectivity** which **requires zone info to be specified in node.csv**. Otherwise, you will get an exception stating \"NO VALID OD VOLUME!! DOUBLE CHECK YOUR demand.csv\". \n",
598641
"\n",
599-
"### Find Shortest Paths for All Individual Agents"
642+
"### 7.1 Find Shortest Paths for All Individual Agents"
600643
]
601644
},
602645
{
@@ -606,10 +649,12 @@
606649
"metadata": {},
607650
"outputs": [],
608651
"source": [
652+
"# zone info must be present in node.csv\n",
653+
"# demand.csv must be given\n",
609654
"network = pg.read_network(load_demand=True)\n",
610655
"network.find_path_for_agents()\n",
611656
"\n",
612-
"agent_id = 300\n",
657+
"agent_id = 1\n",
613658
"print('\\norigin node id of agent is '\n",
614659
" f'{network.get_agent_orig_node_id(agent_id)}')\n",
615660
"print('destination node id of agent is '\n",
@@ -619,7 +664,7 @@
619664
"print('shortest path (link id) of agent, '\n",
620665
" f'{network.get_agent_link_path(agent_id)}')\n",
621666
"\n",
622-
"agent_id = 1000\n",
667+
"agent_id = 100\n",
623668
"print('\\norigin node id of agent is '\n",
624669
" f'{network.get_agent_orig_node_id(agent_id)}')\n",
625670
"print('destination node id of agent is '\n",
@@ -640,7 +685,7 @@
640685
"id": "insured-electronics",
641686
"metadata": {},
642687
"source": [
643-
"### Perform Path-Based UE Traffic Assignment"
688+
"### 7.2 Perform Path-Based UE Traffic Assignment"
644689
]
645690
},
646691
{
@@ -650,9 +695,11 @@
650695
"metadata": {},
651696
"outputs": [],
652697
"source": [
698+
"# zone info must be present in node.csv\n",
699+
"# demand.csv must be given\n",
653700
"network = pg.read_network(load_demand=True)\n",
654701
"\n",
655-
"column_gen_num = 20\n",
702+
"column_gen_num = 10\n",
656703
"column_update_num = 10\n",
657704
"\n",
658705
"# path-based UE only\n",
@@ -663,6 +710,50 @@
663710
"pg.output_columns(network)\n",
664711
"pg.output_link_performance(network)"
665712
]
713+
},
714+
{
715+
"cell_type": "markdown",
716+
"id": "5d68b5d7",
717+
"metadata": {},
718+
"source": [
719+
"### 7.3 Evaluate Multimodal Accessibility"
720+
]
721+
},
722+
{
723+
"cell_type": "code",
724+
"execution_count": null,
725+
"id": "4b3decc8",
726+
"metadata": {},
727+
"outputs": [],
728+
"source": [
729+
"# zone info must be present in node.csv\n",
730+
"# no need to load demand file for accessibility evaluation\n",
731+
"network = pg.read_network()\n",
732+
"\n",
733+
"pg.evaluate_accessibility(network)"
734+
]
735+
},
736+
{
737+
"cell_type": "markdown",
738+
"id": "6226ee32",
739+
"metadata": {},
740+
"source": [
741+
"### 7.4 Evaluate Multimodal Equity"
742+
]
743+
},
744+
{
745+
"cell_type": "code",
746+
"execution_count": null,
747+
"id": "87a65ad8",
748+
"metadata": {},
749+
"outputs": [],
750+
"source": [
751+
"# zone info must be present in node.csv\n",
752+
"# no need to load demand file for accessibility evaluation\n",
753+
"network = pg.read_network()\n",
754+
"\n",
755+
"pg.evaluate_equity(network)"
756+
]
666757
}
667758
],
668759
"metadata": {

0 commit comments

Comments
 (0)