1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! # Traffic Assignment Module (Step 4)
//!
//! Assigns OD demand to the network to find User Equilibrium
//! (Wardrop's first principle: no traveller can reduce their travel
//! time by unilaterally changing routes).
//!
//! ## Methods
//!
//! | Method | Step size | Path storage | Convergence |
//! |---|---|---|---|
//! | [`FrankWolfe`] | Bisection line search | None (link-based) | Typically good |
//! | [`Msa`] | Fixed 1/n | None (link-based) | Slower, simpler |
//! | [`GradientProjection`] | Gradient-scaled | Explicit path sets | Path-level detail |
//!
//! All three implement [`AssignmentMethod`], so they are interchangeable.
//!
//! ## Volume-delay function
//!
//! The BPR function models congestion:
//!
//! ```text
//! t(x) = t0 * (1 + alpha * (x / c) ^ beta)
//! ```
//!
//! Default parameters: `alpha = 0.15`, `beta = 4.0`.
//!
//! ## Components
//!
//! - [`AssignmentMethod`] - Trait for assignment algorithms
//! - [`VolumeDelayFunction`] - Trait for volume-delay functions
//! - [`BprFunction`] - BPR implementation
//! - [`AssignmentConfig`] - Iteration/convergence settings
//! - [`AssignmentResult`] - Output volumes, costs, convergence info
//! - [`shortest_path`] - Dijkstra, all-or-nothing, skim computation
//! - [`error`] - Assignment error types
//!
//! ## Examples
//!
//! ### BPR volume-delay function
//!
//! ```
//! use macro_traffic_sim_core::assignment::{BprFunction, VolumeDelayFunction};
//!
//! let bpr = BprFunction::default();
//!
//! // Free-flow: 10 min, no volume
//! assert_eq!(bpr.travel_time(10.0, 0.0, 1000.0), 10.0);
//!
//! // At capacity: t = 10 * (1 + 0.15 * 1^4) = 11.5
//! assert!((bpr.travel_time(10.0, 1000.0, 1000.0) - 11.5).abs() < 1e-10);
//!
//! // Over capacity: congestion grows rapidly
//! assert!(bpr.travel_time(10.0, 2000.0, 1000.0) > 11.5);
//! ```
//!
//! ### Computing the relative gap
//!
//! ```
//! use std::collections::HashMap;
//! use macro_traffic_sim_core::assignment::compute_relative_gap;
//!
//! let volumes = HashMap::from([(1, 100.0), (2, 200.0)]);
//! let costs = HashMap::from([(1, 5.0), (2, 10.0)]);
//!
//! // If auxiliary volumes equal current volumes, gap = 0
//! let gap = compute_relative_gap(&volumes, &costs, &volumes);
//! assert_eq!(gap, 0.0);
//! ```
pub use *;
pub use IndexedGraph;
pub use ;