| """ |
| Example 4: Advanced Mathematical Features |
| |
| This example demonstrates the research-grade advanced features: |
| - Sequential Monte Carlo (particle filtering) |
| - Variational Inference |
| - Stochastic Differential Equations (SDEs) |
| - Gradient-based Optimal Transport |
| - Kantorovich Duality |
| - Event Extraction and Database |
| - Continuous-time dynamics |
| |
| These features enable measure-theoretic, rigorous forecasting. |
| """ |
|
|
| import numpy as np |
| import sys |
| sys.path.append('..') |
|
|
| from datetime import datetime, timedelta |
| from scipy import stats |
|
|
| |
| from geobot.inference.particle_filter import SequentialMonteCarlo |
| from geobot.inference.variational_inference import VariationalInference |
|
|
| |
| from geobot.simulation.sde_solver import ( |
| EulerMaruyama, |
| Milstein, |
| JumpDiffusionProcess, |
| GeopoliticalSDE |
| ) |
|
|
| |
| from geobot.core.advanced_optimal_transport import ( |
| KantorovichDuality, |
| EntropicOT, |
| GradientBasedOT |
| ) |
|
|
| |
| from geobot.data_ingestion.event_extraction import EventExtractor, EventType |
| from geobot.data_ingestion.event_database import EventDatabase |
|
|
|
|
| def demo_particle_filter(): |
| """Demonstrate Sequential Monte Carlo / Particle Filter.""" |
| print("\n" + "="*80) |
| print("1. Sequential Monte Carlo (Particle Filter)") |
| print("="*80) |
|
|
| |
| def dynamics_fn(x, noise): |
| |
| |
| tension = x[0] |
| stability = x[1] |
|
|
| new_tension = tension + 0.1 * (1 - stability) + noise[0] |
| new_stability = stability - 0.05 * tension + noise[1] |
|
|
| return np.array([ |
| np.clip(new_tension, 0, 1), |
| np.clip(new_stability, 0, 1) |
| ]) |
|
|
| def observation_fn(y, x): |
| |
| |
| predicted = x[0] |
| return stats.norm.logpdf(y[0], loc=predicted, scale=0.1) |
|
|
| |
| pf = SequentialMonteCarlo( |
| n_particles=500, |
| state_dim=2, |
| dynamics_fn=dynamics_fn, |
| observation_fn=observation_fn |
| ) |
|
|
| |
| pf.initialize_from_prior(lambda: np.array([0.3, 0.7])) |
|
|
| |
| observations = np.array([ |
| [0.35], [0.40], [0.45], [0.50], [0.55], |
| [0.60], [0.65], [0.70], [0.75], [0.80] |
| ]) |
|
|
| print(f"\nRunning particle filter with {pf.n_particles} particles...") |
| print("Tracking hidden geopolitical state from noisy observations\n") |
|
|
| |
| states = pf.filter(observations) |
|
|
| |
| for i, state in enumerate(states[-5:]): |
| mean, cov = pf.get_state_estimate() |
| print(f"Step {i+6}: Tension={mean[0]:.3f}±{np.sqrt(cov[0,0]):.3f}, " |
| f"Stability={mean[1]:.3f}±{np.sqrt(cov[1,1]):.3f}, " |
| f"ESS={state.ess:.1f}") |
|
|
| print("\n✓ Particle filter successfully tracked nonlinear hidden states!") |
|
|
|
|
| def demo_sde_solver(): |
| """Demonstrate Stochastic Differential Equations.""" |
| print("\n" + "="*80) |
| print("2. Stochastic Differential Equations (Continuous-Time Dynamics)") |
| print("="*80) |
|
|
| |
| def drift(x, t): |
| |
| return 0.2 * (0.5 - x) |
|
|
| def diffusion(x, t): |
| |
| return 0.1 * (1 + x) |
|
|
| |
| solver = EulerMaruyama( |
| drift=drift, |
| diffusion=diffusion, |
| x0=np.array([0.7]), |
| t0=0.0 |
| ) |
|
|
| print("\nSimulating continuous-time geopolitical tension dynamics...") |
| print("SDE: dx = 0.2(0.5 - x)dt + 0.1(1 + x)dW\n") |
|
|
| |
| solution = solver.integrate(T=10.0, dt=0.01, n_paths=5) |
|
|
| |
| final_values = solution.x[:, -1, 0] |
| print(f"After T=10.0 time units:") |
| print(f" Mean tension: {np.mean(final_values):.3f}") |
| print(f" Std deviation: {np.std(final_values):.3f}") |
| print(f" Min/Max: [{np.min(final_values):.3f}, {np.max(final_values):.3f}]") |
|
|
| print("\n✓ SDE solver successfully simulated continuous-time dynamics!") |
|
|
|
|
| def demo_jump_diffusion(): |
| """Demonstrate Jump-Diffusion Process.""" |
| print("\n" + "="*80) |
| print("3. Jump-Diffusion Process (Modeling Black Swan Events)") |
| print("="*80) |
|
|
| |
| jdp = JumpDiffusionProcess( |
| drift=0.05, |
| diffusion=0.1, |
| jump_intensity=0.5, |
| jump_mean=-0.2, |
| jump_std=0.1, |
| x0=np.array([0.5]) |
| ) |
|
|
| print("\nSimulating conflict escalation with discrete shock events...") |
| print("Model: Continuous diffusion + Poisson jumps (λ=0.5, μ=-0.2)\n") |
|
|
| |
| solution = jdp.simulate(T=20.0, dt=0.1, n_paths=3) |
|
|
| |
| for path in range(3): |
| |
| diffs = np.diff(solution.x[path, :, 0]) |
| n_jumps = np.sum(np.abs(diffs) > 0.15) |
| final_value = solution.x[path, -1, 0] |
| print(f"Path {path+1}: {n_jumps} jumps detected, Final value: {final_value:.3f}") |
|
|
| print("\n✓ Jump-diffusion successfully modeled rare shock events!") |
|
|
|
|
| def demo_kantorovich_duality(): |
| """Demonstrate Kantorovich Duality.""" |
| print("\n" + "="*80) |
| print("4. Kantorovich Duality (Optimal Transport Theory)") |
| print("="*80) |
|
|
| |
| n, m = 10, 10 |
| mu = np.ones(n) / n |
| nu = np.ones(m) / m |
|
|
| |
| X_source = np.random.rand(n, 2) |
| X_target = np.random.rand(m, 2) + np.array([0.5, 0.5]) |
| from scipy.spatial.distance import cdist |
| C = cdist(X_source, X_target, metric='sqeuclidean') |
|
|
| |
| kantorovich = KantorovichDuality() |
|
|
| print("\nComputing optimal transport between two geopolitical scenarios...") |
| print(f"Source: {n} points, Target: {m} points\n") |
|
|
| |
| coupling, primal_cost = kantorovich.solve_primal(mu, nu, C, method='emd') |
| print(f"Primal optimal cost: {primal_cost:.6f}") |
|
|
| |
| f, g, dual_value = kantorovich.solve_dual(mu, nu, C, max_iter=100) |
| print(f"Dual optimal value: {dual_value:.6f}") |
|
|
| |
| gap = kantorovich.verify_duality_gap(mu, nu, C) |
| print(f"Duality gap: {gap:.8f} (should be ≈ 0)") |
|
|
| if abs(gap) < 1e-4: |
| print("\n✓ Strong duality verified! Primal = Dual") |
| else: |
| print("\n⚠ Duality gap present (numerical approximation)") |
|
|
|
|
| def demo_entropic_ot(): |
| """Demonstrate Entropic Optimal Transport (Sinkhorn).""" |
| print("\n" + "="*80) |
| print("5. Entropic Optimal Transport (Sinkhorn Algorithm)") |
| print("="*80) |
|
|
| |
| n, m = 20, 20 |
| mu = np.random.dirichlet(np.ones(n)) |
| nu = np.random.dirichlet(np.ones(m)) |
|
|
| |
| X = np.random.rand(n, 2) |
| Y = np.random.rand(m, 2) |
| from scipy.spatial.distance import cdist |
| C = cdist(X, Y, metric='euclidean') |
|
|
| |
| epsilons = [0.01, 0.05, 0.1] |
|
|
| print("\nComparing regularization levels for Sinkhorn algorithm...\n") |
|
|
| for eps in epsilons: |
| eot = EntropicOT(epsilon=eps) |
| coupling, cost = eot.sinkhorn(mu, nu, C, max_iter=500) |
|
|
| print(f"ε = {eps:0.2f}: Cost = {cost:.6f}, " |
| f"Entropy = {-np.sum(coupling * np.log(coupling + 1e-10)):.4f}") |
|
|
| print("\n✓ Entropic OT computed with fast Sinkhorn iterations!") |
|
|
|
|
| def demo_event_extraction(): |
| """Demonstrate Event Extraction Pipeline.""" |
| print("\n" + "="*80) |
| print("6. Structured Event Extraction from Intelligence") |
| print("="*80) |
|
|
| |
| intelligence_text = """ |
| On March 15, 2024, tensions escalated between the United States and China |
| following a major military mobilization in the Taiwan Strait. NATO issued |
| a statement expressing concern. Russia announced sanctions on European Union |
| member states. India maintained diplomatic neutrality while calling for |
| de-escalation talks. |
| |
| The United Nations Security Council convened an emergency session on March 16, |
| 2024. Economic sanctions were proposed against China by the United States, |
| but Russia exercised its veto power. |
| """ |
|
|
| |
| extractor = EventExtractor() |
|
|
| print("\nExtracting structured events from intelligence report...\n") |
| print("Input text:") |
| print("-" * 60) |
| print(intelligence_text[:200] + "...") |
| print("-" * 60) |
|
|
| events = extractor.extract_events( |
| intelligence_text, |
| source="intel_report_001", |
| default_timestamp=datetime(2024, 3, 15) |
| ) |
|
|
| print(f"\n✓ Extracted {len(events)} geopolitical events:") |
| print() |
|
|
| for i, event in enumerate(events): |
| print(f"Event {i+1}:") |
| print(f" Type: {event.event_type.value}") |
| print(f" Actors: {', '.join(event.actors)}") |
| print(f" Magnitude: {event.magnitude:.2f}") |
| print(f" Timestamp: {event.timestamp.date()}") |
| print() |
|
|
| |
| print("Storing events in database...") |
| with EventDatabase("demo_events.db") as db: |
| db.insert_events(events) |
|
|
| |
| conflict_events = db.query_events( |
| event_types=[EventType.CONFLICT, EventType.MILITARY_MOBILIZATION] |
| ) |
|
|
| print(f"✓ Database contains {len(conflict_events)} conflict-related events") |
|
|
| print("\n✓ Event extraction and storage pipeline operational!") |
|
|
|
|
| def main(): |
| """Run all advanced feature demonstrations.""" |
| print("=" * 80) |
| print("GeoBotv1 - Advanced Mathematical Features Demonstration") |
| print("=" * 80) |
| print("\nThis example showcases research-grade capabilities:") |
| print("• Sequential Monte Carlo (particle filtering)") |
| print("• Stochastic Differential Equations") |
| print("• Jump-Diffusion Processes") |
| print("• Kantorovich Duality in Optimal Transport") |
| print("• Entropic OT with Sinkhorn") |
| print("• Structured Event Extraction") |
|
|
| |
| demo_particle_filter() |
| demo_sde_solver() |
| demo_jump_diffusion() |
| demo_kantorovich_duality() |
| demo_entropic_ot() |
| demo_event_extraction() |
|
|
| print("\n" + "=" * 80) |
| print("All Advanced Features Demonstrated Successfully!") |
| print("=" * 80) |
| print("\nKey Insights:") |
| print("1. Particle filters handle nonlinear/non-Gaussian state estimation") |
| print("2. SDEs model continuous-time geopolitical dynamics rigorously") |
| print("3. Jump-diffusion captures both gradual change and sudden shocks") |
| print("4. Kantorovich duality provides theoretical foundation for OT") |
| print("5. Entropic OT enables fast computation via Sinkhorn") |
| print("6. Event extraction creates structured data for causal modeling") |
|
|
| print("\n" + "="*80) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|