Skip to content

Commit 22e7d7e

Browse files
committed
update documentation on link-based ue
- add use cases on link-based ue in usecases.md and tutorial.ipynb; - conduct minor cosmetic changes to find_ue() and find_ue_fw(); - update README.md on release date.
1 parent 958e914 commit 22e7d7e

File tree

5 files changed

+99
-18
lines changed

5 files changed

+99
-18
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ The Python modules are written in **Python 3.x**, which is the minimum requireme
6060

6161
## How to Cite
6262

63-
Li, P. and Zhou, X. (2025, March 16). *Path4GMNS*. Retrieved from https://github.com/jdlph/Path4GMNS
63+
Li, P. and Zhou, X. (2025, December 12). *Path4GMNS*. Retrieved from https://github.com/jdlph/Path4GMNS
6464

6565
## Please Contribute
6666

docs/source/usecases.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ print(f'shortest path (link id) from node 1 to node 2: {sp_tree_link[2]}')
156156
print(f'shortest path (link id) from node 1 to node 3: {sp_tree_link[3]}')
157157
```
158158

159-
## Find Path-Based UE
160-
The Python column-generation module only implements path-based UE. If you need other assignment modes, e.g., link-based UE or DTA, please use DTALiteClassic(). Note that **column_gen_num** below specifies the maximum number of paths / columns for each OD pair.
159+
## Find UE
160+
161+
### Path-Based UE
162+
The column-generation module implements the path-based UE, where **column_gen_num** below specifies the maximum number of paths / columns for each OD pair.
161163

162164
```python
163165
import path4gmns as pg
@@ -219,6 +221,36 @@ pg.output_columns(network)
219221
pg.output_link_performance(network)
220222
```
221223

224+
### Link-Based UE
225+
226+
v0.10.0 introduces the link-based UE that adopts the Frank-Wolfe algorithm with line search. Compared to the path-based UE, it does not preserve any paths / columns but only (unique) link flows. Therefore, each iteration runs faster than the path-based procedure with less memory footprint.
227+
228+
```python
229+
import path4gmns as pg
230+
231+
network = pg.read_network()
232+
pg.read_demand(network)
233+
234+
pg.find_ue_fw(network)
235+
pg.output_link_performance(network)
236+
237+
# NOTE that pg.output_columns(network) is NOT available under the link-based UE!
238+
```
239+
find_ue_fw() will terminate when it reaches the maximum number of iterations (**max_iter_num**) or the target relative gap (**rel_gap_tolerance**), whichever comes first. The default values are **40** and **1e-04**, respectively. You can specify
240+
their values toward your own need like below.
241+
242+
```python
243+
import path4gmns as pg
244+
245+
network = pg.read_network()
246+
pg.read_demand(network)
247+
248+
pg.find_ue_fw(network, max_iter_num=100, rel_gap_tolerance=1e-6)
249+
pg.output_link_performance(network)
250+
251+
# NOTE that pg.output_columns(network) is NOT available under the link-based UE!
252+
```
253+
222254
### In Case of Special Events
223255

224256
A special event often comes with capacity reduction over affected links, which is supported in v0.8.4 or higher. You can introduce one special event for each demand period in settings.yml as below.

path4gmns/colgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ def update_links_using_columns(network):
294294
_update_link_travel_time(links)
295295

296296

297-
def find_ue(ui, column_gen_num, column_upd_num, rel_gap_tolerance=0.0001):
297+
def find_ue(ui, column_gen_num, column_upd_num, rel_gap_tolerance=1e-04):
298298
""" find user equilibrium (UE)
299299
300300
WARNING

path4gmns/fw.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def _init_sys_tt(demand_period_count):
171171
_total_min_sys_travel_time[tau] = 0
172172

173173

174-
def find_ue_fw(ui, max_iter = 40, rel_gap_tolerance=1e-04):
174+
def find_ue_fw(ui, max_iter=40, rel_gap_tolerance=1e-04):
175175
""" find user equilibrium (UE) with the Frank-Wolfe Algorithm
176176
177177
WARNING

tutorial/tutorial.ipynb

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -282,15 +282,21 @@
282282
"id": "mysterious-diamond",
283283
"metadata": {},
284284
"source": [
285-
"### 3.3 Perform Path-Based UE Traffic Assignment\n",
285+
"### 3.3 Perform UE Traffic Assignment\n",
286+
"\n",
287+
"#### 3.3.1 Prerequisite on Demand\n",
286288
"\n",
287289
"OD demand matrix and zone information is crucial in conducting traffic assignment are essential to perform this functionality. The demand file 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).\n",
288290
"\n",
289291
"The demand will be loaded by default via pg.read_demand(). If demand.csv is missing, pg.read_demand() will automatically conduct the following attempts.\n",
290292
"1. try to load the synthetic demand (as syn_demand.csv and zones as syn_zone.csv).\n",
291293
"2. synthesize demand (and zones) if the previous attempt fails.\n",
292294
"\n",
293-
"Then you can conduct traffic assignment via the following lines."
295+
"The demand file is specified in settings.yml as demand.csv (see 4.1 Sample setting.yml for details). 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",
296+
"\n",
297+
"#### 3.3.2 Path-Based UE\n",
298+
"\n",
299+
"With the required demand file, then you can conduct path-based UE traffic assignment via the following lines."
294300
]
295301
},
296302
{
@@ -323,8 +329,6 @@
323329
"id": "c2c1211e",
324330
"metadata": {},
325331
"source": [
326-
"The demand file is specified in settings.yml as demand.csv (see 4.1 Sample setting.yml for details). 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",
327-
"\n",
328332
"The code snippet below demonstrates how to adaptively the UE convergency directly through rel_gap_tolerance. find_ue() will terminate when either column_upd_num or rel_gap_tolerance is reached."
329333
]
330334
},
@@ -342,8 +346,8 @@
342346
"column_gen_num = 20\n",
343347
"column_upd_num = 20\n",
344348
"\n",
345-
"# the default value of rel_gap_tolerance is 0.0001 if not specified\n",
346-
"rel_gap = pg.find_ue(network, column_gen_num, column_upd_num, rel_gap_tolerance = 0.001)\n",
349+
"# the default value of rel_gap_tolerance is 1e-04 if not specified\n",
350+
"rel_gap = pg.find_ue(network, column_gen_num, column_upd_num, rel_gap_tolerance=1e-04)\n",
347351
"print(f'the final relative UE gap is {rel_gap:.4%}')\n",
348352
"\n",
349353
"# if you want to include path geometry info in the output file,\n",
@@ -352,14 +356,65 @@
352356
"pg.output_link_performance(network)"
353357
]
354358
},
359+
{
360+
"cell_type": "markdown",
361+
"id": "14ea3a1a",
362+
"metadata": {},
363+
"source": [
364+
"#### 3.3.3 Link-Based UE\n",
365+
"\n",
366+
"The link-based UE does not preserve any paths / columns but only (unique) link flows. Thus, pg.output_columns(network) is NOT available."
367+
]
368+
},
369+
{
370+
"cell_type": "code",
371+
"execution_count": null,
372+
"id": "4fafb09b",
373+
"metadata": {},
374+
"outputs": [],
375+
"source": [
376+
"network = pg.read_network()\n",
377+
"pg.read_demand(network)\n",
378+
"\n",
379+
"pg.find_ue_fw(network)\n",
380+
"pg.output_link_performance(network)\n",
381+
"\n",
382+
"# NOTE that pg.output_columns(network) is NOT available under the link-based UE!"
383+
]
384+
},
385+
{
386+
"cell_type": "markdown",
387+
"id": "bf333d6c",
388+
"metadata": {},
389+
"source": [
390+
"find_ue_fw() will terminate when it reaches the maximum number of iterations (**max_iter_num**) or the target relative gap (**rel_gap_tolerance**), whichever comes first. The default values are **40** and **1e-04**, respectively. You can adjust\n",
391+
"their values toward your own need like below."
392+
]
393+
},
394+
{
395+
"cell_type": "code",
396+
"execution_count": null,
397+
"id": "8cfb704d",
398+
"metadata": {},
399+
"outputs": [],
400+
"source": [
401+
"network = pg.read_network()\n",
402+
"pg.read_demand(network)\n",
403+
"\n",
404+
"pg.find_ue_fw(network, max_iter_num=100, rel_gap_tolerance=1e-6)\n",
405+
"pg.output_link_performance(network)\n",
406+
"\n",
407+
"# NOTE that pg.output_columns(network) is NOT available under the link-based UE!"
408+
]
409+
},
355410
{
356411
"cell_type": "markdown",
357412
"id": "ad91ad31",
358413
"metadata": {},
359414
"source": [
360415
"### 3.4 Conduct Dynamic Traffic Simulation\n",
361416
"\n",
362-
"Traffic simulation requires routing decision for each agent, which comes from the UE traffic assignment."
417+
"Traffic simulation requires routing decision for each agent, which comes from the **path-based UE** traffic assignment."
363418
]
364419
},
365420
{
@@ -610,12 +665,6 @@
610665
"pg.download_sample_setting_file()"
611666
]
612667
},
613-
{
614-
"cell_type": "markdown",
615-
"id": "e631fbf5",
616-
"metadata": {},
617-
"source": []
618-
},
619668
{
620669
"cell_type": "markdown",
621670
"id": "great-catholic",

0 commit comments

Comments
 (0)