feat(mean_field): Implement Mean Field Games module with PDE solvers
- Add complete mean_field module with 6 submodules - Implement HJB and Fokker-Planck PDE solvers with rayon parallelization - Add forward-backward fixed-point iteration algorithm - Include Nash equilibrium and optimal transport utilities - Add comprehensive Jupyter notebook tutorial with: * Mathematical formulation (HJB and FP equations) * Finite difference methods explanation * Complete congestion game example * 3D visualizations and convergence plots * Citations to Jiang, Chewi, Pooladian (2023) paper - All tests passing (5 tests in mean_field module) - Based on 'Numerical Methods for Mean Field Games' PDF algorithms
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
//! Mean Field Games Module
|
||||
//!
|
||||
//! This module implements numerical methods for Mean Field Games (MFG) and Mean Field Type Control.
|
||||
//! Based on: "Numerical Methods for Mean Field Games and Mean Field Type Control"
|
||||
//!
|
||||
//! # Overview
|
||||
//!
|
||||
//! Mean Field Games (MFG) study strategic decision-making in large populations where each agent
|
||||
//! optimizes their cost functional while being influenced by the aggregate behavior (mean field)
|
||||
//! of all agents.
|
||||
//!
|
||||
//! ## Mathematical Framework
|
||||
//!
|
||||
//! A Mean Field Game consists of two coupled PDEs:
|
||||
//!
|
||||
//! 1. **Hamilton-Jacobi-Bellman (HJB) Equation** (backward in time):
|
||||
//! ```text
|
||||
//! -∂ₜu - νΔu + H(x, ∇u) = f(x, m) in Ω × (0,T)
|
||||
//! u(x,T) = g(x, m(T)) in Ω
|
||||
//! ```
|
||||
//!
|
||||
//! 2. **Fokker-Planck (FP) Equation** (forward in time):
|
||||
//! ```text
|
||||
//! ∂ₜm - νΔm - div(m · Hₚ(x, ∇u)) = 0 in Ω × (0,T)
|
||||
//! m(x,0) = m₀(x) in Ω
|
||||
//! ```
|
||||
//!
|
||||
//! where:
|
||||
//! - u(x,t): value function
|
||||
//! - m(x,t): distribution of agents
|
||||
//! - H: Hamiltonian (typically H(x,p) = ½|p|²)
|
||||
//! - ν: viscosity coefficient
|
||||
//!
|
||||
//! ## Numerical Methods
|
||||
//!
|
||||
//! This module implements:
|
||||
//! - Finite difference schemes for HJB and FP equations
|
||||
//! - Fixed-point iteration for MFG system
|
||||
//! - Primal-dual methods
|
||||
//! - Newton-type methods
|
||||
//! - Monotone schemes
|
||||
//!
|
||||
//! # References
|
||||
//!
|
||||
//! - Achdou, Y., & Capuzzo-Dolcetta, I. (2010). "Mean field games: numerical methods."
|
||||
//! - Carmona, R., & Delarue, F. (2018). "Probabilistic Theory of Mean Field Games."
|
||||
//! - Cardaliaguet, P. (2013). "Notes on Mean Field Games."
|
||||
|
||||
pub mod types;
|
||||
pub mod pde_solvers;
|
||||
pub mod forward_backward;
|
||||
pub mod nash_equilibrium;
|
||||
pub mod optimal_transport;
|
||||
|
||||
pub use types::*;
|
||||
pub use pde_solvers::*;
|
||||
pub use forward_backward::*;
|
||||
pub use nash_equilibrium::*;
|
||||
pub use optimal_transport::*;
|
||||
|
||||
use ndarray::{Array1, Array2};
|
||||
use crate::core::{OptimizrError, Result};
|
||||
|
||||
/// Configuration for Mean Field Games solver
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MFGConfig {
|
||||
/// Spatial dimension
|
||||
pub dim: usize,
|
||||
/// Number of spatial grid points per dimension
|
||||
pub nx: usize,
|
||||
/// Number of time steps
|
||||
pub nt: usize,
|
||||
/// Spatial domain bounds [xmin, xmax]
|
||||
pub domain: (f64, f64),
|
||||
/// Time horizon
|
||||
pub time_horizon: f64,
|
||||
/// Viscosity coefficient
|
||||
pub viscosity: f64,
|
||||
/// Convergence tolerance for fixed-point iteration
|
||||
pub tolerance: f64,
|
||||
/// Maximum number of iterations
|
||||
pub max_iterations: usize,
|
||||
/// Relaxation parameter for updates
|
||||
pub relaxation: f64,
|
||||
}
|
||||
|
||||
impl Default for MFGConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
dim: 1,
|
||||
nx: 100,
|
||||
nt: 100,
|
||||
domain: (0.0, 1.0),
|
||||
time_horizon: 1.0,
|
||||
viscosity: 0.01,
|
||||
tolerance: 1e-6,
|
||||
max_iterations: 1000,
|
||||
relaxation: 0.5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Main Mean Field Games solver
|
||||
pub struct MFGSolver {
|
||||
config: MFGConfig,
|
||||
}
|
||||
|
||||
impl MFGSolver {
|
||||
/// Create a new MFG solver with given configuration
|
||||
pub fn new(config: MFGConfig) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
/// Solve the MFG system using fixed-point iteration
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `hamiltonian`: Hamiltonian function H(x, p, m)
|
||||
/// - `running_cost`: Running cost f(x, m)
|
||||
/// - `terminal_cost`: Terminal cost g(x, m(T))
|
||||
/// - `initial_dist`: Initial distribution m₀(x)
|
||||
///
|
||||
/// # Returns
|
||||
/// Tuple of (value_function, distribution, number_of_iterations)
|
||||
pub fn solve<H, F, G>(
|
||||
&self,
|
||||
hamiltonian: H,
|
||||
running_cost: F,
|
||||
terminal_cost: G,
|
||||
initial_dist: &Array1<f64>,
|
||||
) -> Result<(Array2<f64>, Array2<f64>, usize)>
|
||||
where
|
||||
H: Fn(f64, f64, f64) -> f64 + Send + Sync,
|
||||
F: Fn(f64, f64) -> f64 + Send + Sync,
|
||||
G: Fn(f64, f64) -> f64 + Send + Sync,
|
||||
{
|
||||
// Implemented in forward_backward.rs
|
||||
forward_backward_fixed_point(
|
||||
&self.config,
|
||||
hamiltonian,
|
||||
running_cost,
|
||||
terminal_cost,
|
||||
initial_dist,
|
||||
)
|
||||
}
|
||||
|
||||
/// Solve using primal-dual method (faster convergence)
|
||||
pub fn solve_primal_dual<H, F, G>(
|
||||
&self,
|
||||
hamiltonian: H,
|
||||
running_cost: F,
|
||||
terminal_cost: G,
|
||||
initial_dist: &Array1<f64>,
|
||||
) -> Result<(Array2<f64>, Array2<f64>, usize)>
|
||||
where
|
||||
H: Fn(f64, f64, f64) -> f64 + Send + Sync,
|
||||
F: Fn(f64, f64) -> f64 + Send + Sync,
|
||||
G: Fn(f64, f64) -> f64 + Send + Sync,
|
||||
{
|
||||
nash_equilibrium::primal_dual_mfg(
|
||||
&self.config,
|
||||
hamiltonian,
|
||||
running_cost,
|
||||
terminal_cost,
|
||||
initial_dist,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_mfg_config_default() {
|
||||
let config = MFGConfig::default();
|
||||
assert_eq!(config.dim, 1);
|
||||
assert_eq!(config.nx, 100);
|
||||
assert_eq!(config.nt, 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mfg_solver_creation() {
|
||||
let config = MFGConfig::default();
|
||||
let _solver = MFGSolver::new(config);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user