TNFR Logo
TheoryLearnSoftwareResearch

On this page

TNFR

Resonant Fractal Nature Theory — a mathematical framework for coherent patterns on graph-coupled networks.

About
  • Project history
  • Editorial policy
  • Contact
Resources
  • GitHub
  • PyPI
  • DOI · Zenodo
Legal
  • MIT License
  • Citation
© 2026 TNFR project — MIT licensed.DOI 10.5281/zenodo.17602860
docs
grammar
PHYSICS_VERIFICATION.md
API_CONTRACTS.mdCANONICAL_OZ_SEQUENCES.mdEMPIRICAL_CONFRONTATION_EEG.mdREADME.mdSTRUCTURAL_FIELDS_TETRAD.mdSTRUCTURAL_INTERFACE_THEORY.md
theory
APPLIED_STRUCTURAL_ANALYSIS.mdCATALOG_TYPE_HYGIENE_PROGRAMME.mdDISSIPATIVE_AND_OPEN_SYSTEMS.mdEMERGENT_ONTOLOGY.mdEXTENDED_FIELDS_AND_DERIVED_QUANTITIES.mdFUNDAMENTAL_THEORY.mdGAUGE_SYMMETRY_AND_UNIFICATION.mdGLOSSARY.mdMATHEMATICAL_DYNAMICS_BASIS.mdMINIMAL_STRUCTURAL_DEGREES.mdNUCLEUS_A_PRIME_LADDER_ATLAS.mdNUCLEUS_B_EQUIVARIANCE_OBSTRUCTIONS.mdPHYSICAL_REGIME_CORRESPONDENCES.mdREADME.mdREMESH_INFINITY_DERIVATION.mdSTRUCTURAL_CONSERVATION_THEOREM.mdSTRUCTURAL_OPERATORS.mdSTRUCTURAL_STABILITY_AND_DYNAMICS.mdTNFR_BSD_RESEARCH_NOTES.mdTNFR_HODGE_RESEARCH_NOTES.mdTNFR_NAVIER_STOKES_RESEARCH_NOTES.mdTNFR_NUMBER_THEORY.mdTNFR_P_VS_NP_RESEARCH_NOTES.mdTNFR_RIEMANN_RESEARCH_NOTES.mdTNFR_VARIATIONAL_PRINCIPLE.mdTNFR_YANG_MILLS_RESEARCH_NOTES.mdTNFR.pdfUNIFIED_GRAMMAR_RULES.md
factorization-lab
analysis
analyze_patterns.pycertificate_manifest.py
benchmarks
benchmark_analysis.pybenchmark_expansion_suite.pyfull_spectrum_factorization.pypaley_gap_extended.pypaley_gap_smoke.pytest_benchmark_suite.py
demos
experiment_contexts
exp_0b1663cd19b7.jsonexp_0bf0054b7474.jsonexp_75a4c8ca616a.jsonexp_848ee0fd1857.jsonexp_f6fe00562193.jsonexp_fdf3da424e1e.json
failure_telemetry_batch.pyfeedback_integration_demo.pyintegration_demo_snapshots.dbseed_management_integration_demo.pysnapshot_integration_demo.pytrajectory_143.jsontrajectory_77.jsontrajectory_89.jsontrajectory_91.jsontrajectory_97.json
docs
FACTORING_PLAYBOOK.mdFALSE_POSITIVE_TEST_SUITE.mdOPERATOR_CERTIFICATES.mdROADMAP.mdSPECTRAL_ROUTE.md
experiment_contexts
exp_cebe1d9e7d8e.json
notebooks
spectral_history.ipynb
scripts
run_false_positive_tests.py
tests
run_false_positive_test_suite.pytest_cli.pytest_false_positive_methodology.pytest_false_positive_verifier.pytest_feedback_integration.pytest_partitioning.pytest_seed_management.pytest_self_opt_support.pytest_snapshot_system.pytest_spectral_paley.pytest_verification_robustness.py
tnfr_factorization
__init__.pyapi.pycli.pyfailure_telemetry.pyfeedback_adapter.pyfeedback_integration.pypartitioning.pyself_opt_support.pyspectral_paley.py
demo_snapshots.dbLICENSE_SNAPSHOT.mdPACKAGE_SUMMARY.mdREADME.mdseed_management.pysnapshot_system.pytest_certificate_hashing.pytest_installation.pyverification_trajectory_77.json
benchmarks
analyze_tetrad_universality.pyb0star_alpha_canonical_product_graphs.pybenchmark_optimization_tracks.pybenchmark_utils.pyboundary_vibration.pybridge_primes_riemann.pychiral_involution.pycli_utils.pycoherence_projector_sense_index.pycommutant_bridge.pycomposition_arithmetic.pyconfinement_zones_test.pyconservation_law_validation.pydirected_paley_bridge.pyemergent_arithmetic_pulse.pyemergent_atom_dynamics.pyemergent_atomic_shells.pyemergent_base_dimension.pyemergent_dimension_dynamics.pyemergent_fractal_pulse.pyemergent_fractal_simplex_dimension.pyemergent_integers_symmetry.pyemergent_musical_nfr.pyemergent_nfr_geometry.pyemergent_nfr_where.pyemergent_rationals.pyemergent_rhythm.pyemergent_screening.pyemergent_shell_cardinals.pyemergent_shell_ordering.pyemergent_simplex_dimension.pyemergent_substrate_symmetry.pyequivariance_wall.pyexternal_phase_gate_validation.pyfield_methods_battery.pygolden_residue_remesh_bridge.pyintegrated_force_regime_study.pyinverse_spectrum_to_symmetry.pyk_phi_safety_demo.pykuramoto_farey_bridge.pymissing_piece_bridge.pymultichannel_interface_benchmark.pynavier_stokes_recipe_bridge.pynodal_propagator_residue_bridge.pyns_moment_hierarchy_cascade.pyoperational_irreducibility.pypaley_bridge.pyphase_curvature_investigation.pyphase_wall.pyphi_s_confinement_investigation.pyprimes_as_consequence.pypulse_phase_coherence_budget.pyREADME.mdremesh_infinity_riemann_baseline.pyremesh_infinity_riemann_composed.pyremesh_infinity_riemann_modified_graph.pyremesh_infinity_riemann_operator.pyremesh_infinity_riemann_spectral_basis.pyremesh_infinity_riemann_spectral_robustness.pyremesh_infinity_riemann_spectral.pyresidue_phase_vs_riemann.pystructural_interface_benchmark.pytemporal_interface_benchmark.pytetrad_results_aggregate.pyu2_destabilization_irreversibility.pyuniversality_clusters.pyxi_c_fast_experiment.py
primality-test
benchmarks
comprehensive_benchmark.py
docs
ADVANCED_INTEGRATION.mdmathematical_foundation.mdperformance_analysis.md
examples
advanced_examples.pybasic_usage.py
tnfr_primality
__init__.py__main__.pyadvanced_cli.pyadvanced_core.pycli.pyconstants.pycore.pyoptimized.py
MANIFEST.inPACKAGE_SUMMARY.mdREADME.mdRELEASE_NOTES_v1.0.mdsetup.pytest_installation.py
tests
core_physics
__init__.pytest_conservation_laws.pytest_delta_nfr_computation_paths.pytest_delta_nfr.pytest_dispersion_coherence_sign_invariance.pytest_emergent_constants_guard.pytest_lyapunov_operators.pytest_nodal_equation.pytest_structural_triad.py
data
replay_manifests
sample_run
_manifest_summary.json_manifest.json_partition_files.txt.gz
self_opt_validation
seed_alpha
paley.json
seed_beta
integration.json
seed_gamma
unknown.json
self_optimization
test_run
partitioned
test_run
test_run_p0.jsontest_run_p1.json
_manifest_summary.json_manifest.json
engines
test_pattern_discovery_manifest.pytest_self_optimization_engine.py
mathematics
__init__.pytest_autodiff.pytest_backends.pytest_dissipative_dynamics.pytest_epi.pytest_factory_patterns.pytest_metrics.pytest_navier_stokes_refounded.pytest_number_theory_canonical.pytest_operators.pytest_residue_networks.pytest_riemann_nodal_pulse.pytest_riemann_pulse_coherence.pytest_spaces.pytest_transforms.pytest_validator.py
operators
test_canonical_operators_modern.pytest_grammar_canon.pytest_grammar_canonical_consistency.pytest_grammar_dynamics.pytest_operator_contracts.pytest_operator_strategies.py
parallel
test_fractal_partition_manifest.py
physics
test_conservation_gauge_unification.pytest_dissipative_conservation.pytest_emergent_chemistry.pytest_field_cache_invalidation.pytest_gauge.pytest_phase_transition.pytest_signatures.pytest_spectral_conservation.pytest_structural_diffusion.pytest_structural_integrity.pytest_symplectic_substrate.pytest_tetrad_bounds.pytest_variational.pytest_yang_mills_closure.pytest_yang_mills_derivability.pytest_yang_mills_scaling.pytest_yang_mills_structural_gap.pytest_yang_mills_u6_sweep.py
scripts
test_run_self_opt_validation.pytest_run_self_optimization.py
sdk
__init__.pytest_simple_advanced.py
__init__.pyconftest.pyREADME.mdtest_breast_cancer_phase_gate_demo.pytest_classical_mechanics.pytest_distributed_fft.pytest_external_phase_gate_validation.pytest_factorization_entrypoint.pytest_multichannel_interface.pytest_nodal_optimizer.pytest_phase_gate_api.pytest_replay_register_manifest.pytest_signal_confrontation.pytest_structural_interface_api.pytest_structural_interface_baselines.pytest_structural_interface_benchmark.pytest_temporal_interface.pytest_vectorized_coherence_length_regression.pytest_wine_quality_phase_gate_demo.pyutils.py
examples
01_foundations
01_hello_world.py02_musical_resonance.py03_network_formation.py04_operator_sequences.py05_coherence_evolution.py06_network_topologies.py07_phase_transitions.py08_emergent_phenomena.py09_visualization_suite.py10_simplified_sdk_showcase.py
02_physics_regimes
11_classical_limit_comparison.py115_operator_contract_audit.py12_classical_mechanics_demo.py13_quantum_mechanics_demo.py14_uncertainty_and_interference.py15_train_crossing_demo.py17_conservation_law_demo.py26_gauge_structure_demo.py27_variational_principle_demo.py28_dissipative_systems_demo.py29_lyapunov_stability_demo.py30_self_optimization_demo.py31_mathematical_constants_basis.py33_complex_field_unification.py34_conservation_protocol_suite.py35_tetrad_irreducibility.py36_grammar_violation_detector.py37_operator_tetrad_synergy.py38_grammar_energy_landscape.py39_nodal_equation_decomposition.py
03_riemann_zeta
157_nodal_pulse_phase_attack.py41_von_mangoldt_zeta_demo.py42_riemann_zeros_as_resonances.py43_prime_ladder_hamiltonian_demo.py44_weil_explicit_formula_demo.py45_li_keiper_demo.py46_weil_tnfr_positivity_demo.py47_alpha_sweep_demo.py48_admissible_family_sweep_demo.py49_nodeaware_gauge_sweep_demo.py50_uniform_coercivity_demo.py51_adaptive_coercivity_demo.py52_paley_gap_coercivity_demo.py53_lyapunov_spectral_positivity_demo.py54_hilbert_polya_demo.py55_structural_zero_density_demo.py56_spectral_emergence_demo.py57_admissible_rescaling_demo.py58_oscillatory_correction_demo.py
04_riemann_L_twisted
59_dirichlet_l_function_demo.py60_dirichlet_l_continuation_demo.py61_dirichlet_l_hamiltonian_demo.py62_dirichlet_weil_explicit_formula_demo.py63_dirichlet_li_keiper_demo.py64_twisted_weil_positivity_demo.py65_twisted_alpha_sweep_demo.py66_twisted_admissible_family_sweep_demo.py67_twisted_nodeaware_gauge_sweep_demo.py68_twisted_hermite_family_demo.py69_twisted_coercivity_uniform_demo.py70_twisted_paley_gap_coercivity_demo.py71_twisted_lyapunov_spectral_demo.py72_twisted_hilbert_polya_demo.py73_twisted_structural_zero_density_demo.py74_twisted_spectral_emergence_demo.py75_twisted_admissible_rescaling_demo.py76_twisted_oscillatory_correction_demo.py
05_type_hygiene
77_remesh_infinity_residue_split_demo.py78_nuf_type_signature_demo.py79_epi_type_signature_demo.py80_phi_type_signature_demo.py81_dnfr_type_signature_demo.py82_remesh_window_type_signature_demo.py83_delta_phi_max_type_signature_demo.py84_coupling_weights_type_signature_demo.py85_tetrad_closure_signature_demo.py86_currents_closure_signature_demo.py87_aggregates_closure_signature_demo.py88_urules_consistency_signature_demo.py89_operator_catalog_discipline_signature_demo.py
06_navier_stokes
158_navier_stokes_two_face_refounded.py
07_number_theory
100_prime_families_orbits.py101_numbers_as_coupled_network.py102_nodal_flow_primes_equilibria.py116_nuf_emergent_prime_visibility.py146_primality_grammatical_inertness.py147_numbers_as_free_monoid_words.py148_capacity_arm_carries_von_mangoldt.py149_p14_is_the_capacity_arm_operator.py153_structural_frequency_rank_cyclotomy.py40_arithmetic_number_theory.py94_generative_number_construction.py95_primes_from_spectral_waves.py96_spectral_vibration_of_coherence.py97_goldbach_additive_multiplicative.pyemergent_chemistry_particles_demo.py
08_emergent_geometry
103_emergent_substrate_meets_riemann.py106_per_node_polarization_geometry.py107_orthogonal_structure_emergent_geometry.py108_emergent_field_generating_structure.py112_structure_predicts_coherence_flow.py113_overdamped_projection_bridge.py114_substrate_conserved_quantities.py117_emergent_geometry_residue_graph.py118_emergent_vs_classical_operator.py119_phase_sector_directed_residue.py120_symmetry_wall_substrate_vs_spectrum.py121_canonical_symmetry_break_negative.py122_factorization_phase_sector.py123_symmetry_sector_decomposition.py124_emergent_metric_fractal_consistency.py125_node_is_the_emergent_substrate.py126_two_layers_base_fiber.py127_base_is_emergent_not_imposed.py128_base_substrate_coemergence.py129_spectral_gap_base_fiber_clock.py130_operators_break_substrate_charges.py131_coemergent_loop_convergence.py132_geometric_phase_holonomy.py133_psi_topological_defects.py134_spectral_dimension_heat_kernel.py135_arrow_of_time_h_theorem.py136_heat_kernel_coefficients.py137_synchronization_transition.py138_structure_frequency_synchronization.py139_grammar_formal_language.py140_grammar_automaton.py141_grammar_rule_decomposition.py142_grammar_operator_quotient.py143_glyphic_function_sublanguage.py144_branching_combinator.py145_syntactic_monoid_starfree.py150_emergent_grammatical_pattern_parry.py151_grammar_in_emergent_geometry.py152_operator_contract_tetrahedron.py154_conductor_annotated_qr_spectrum.py155_ontological_position_of_numbers.py156_emergence_directness_law.py98_emergent_symplectic_substrate.py99_structural_diffusion.pyunified_fields_showcase.py
09_millennium
109_p_vs_np_coherence_synthesis.py110_bsd_rank_structural_pressure.py111_hodge_discrete_and_honest_gap.py
10_applications
159_empirical_confrontation_pipeline.py90_phase_gate_monitor_demo.py91_breast_cancer_phase_gate_demo.py92_wine_quality_phase_gate_demo.py93_structural_interface_demo.pypytorch_cuda_demo.py
README.md
scripts
replay
__init__.pyregister_manifest.py
__init__.pyREADME.mdrebuild_failure_manifest.pyrun_reproducible_benchmarks.pyrun_self_opt_validation.pyrun_self_optimization.pytnfr_is_prime.pyvalidate_conservation_law.pyverify_internal_references.py
src
core
__init__.pyevaluation.py
tnfr
backends
__init__.pyjax_backend.pynumpy_backend.pyoptimized_numpy.pyREADME.mdtorch_backend.py
cli
__init__.py__init__.pyiarguments.pyarguments.pyiexecution.pyexecution.pyiinteractive_validator.pyREADME.mdutils.pyutils.pyi
compat
__init__.pydataclass.pyjsonschema_stub.pymatplotlib_stub.pynumpy_stub.pyREADME.md
config
__init__.py__init__.pyiconstants.pyconstants.pyidefaults_core.pydefaults_init.pydefaults_metric.pydefaults.pyfeature_flags.pyfeature_flags.pyiglyph_constants.pyoperator_names.pyoperator_names.pyiphysics_derivation.pyprecision_modes.pypresets.pypresets.pyiREADME.mdsecurity.pythresholds.pytnfr_config.py
constants
__init__.py__init__.pyialiases.pyaliases.pyicanonical.pymetric.pymetric.pyioperational.py
core
__init__.pycontainer.pydefault_implementations.pyexceptions.pyinterfaces.pyREADME.md
dynamics
__init__.py__init__.pyiadaptation.pyadaptation.pyiadaptive_sequences.pyadaptive_sequences.pyiadelic.pyadvanced_cache_optimizer.pyadvanced_fft_arithmetic.pyaliases.pyaliases.pyibifurcation.pycache_aware_fft_engine.pycanonical.pycanonical.pyicomputational_hub.pycoordination.pycoordination.pyidistributed_fft.pydnfr.pydnfr.pyidynamic_limits.pyemergent_centralization.pyemergent_integration_engine.pyfeedback.pyfeedback.pyifft_backend.pyfft_cache_coordinator.pyfft_dispatchers.pyfft_engine.pyfft_workers.pyfused_dnfr.pyhomeostasis.pyhomeostasis.pyiintegrators.pyintegrators.pyilearning.pylearning.pyimetabolism.pymulti_modal_cache.pynbody_tnfr.pynbody.pynodal_optimizer.pyoptimization_orchestrator.pypropagation.pyREADME.mdruntime.pyruntime.pyisampling.pysampling.pyiselectors.pyselectors.pyiself_optimizing_engine.pyspectral_structural_fusion.pystructural_cache.pystructural_clip.pysymplectic.pyunified_backend.pyunified_mathematical_cache_orchestrator.py
engines
computation
__init__.pyfft_engine.pyunified_fft_engine.pyunified_gpu_system.py
constants
__init__.pycanonical.pyoperational.py
integration
__init__.pyemergent_integration.py
pattern_discovery
__init__.pymathematical_patterns.pymulti_modal_cache.py
self_optimization
__init__.pyengine.py
__init__.pyREADME.md
errors
__init__.pycontextual.py
factorization
__init__.py
flatten
README.md
gamma
README.md
glyph_history
README.md
glyph_runtime
README.md
immutable
README.md
initialization
README.md
io
README.md
math
__init__.pyfields_symbolic.pygrammar_validators.pyoptimizer.pyREADME.mdsymbolic.py
mathematics
__init__.pybackend.pybackend.pyidynamics.pydynamics.pyiepi.pyepi.pyigenerators.pygenerators.pyiliouville.pymetrics.pymetrics.pyinumber_theory.pyoperators_factory.pyoperators_factory.pyioperators.pyoperators.pyioptimized_primality.pyprojection.pyprojection.pyiREADME.mdruntime.pyruntime.pyispaces.pyspaces.pyispectral.pytransforms.pytransforms.pyiunified_cache.pyunified_numerical.pyzeta.py
metrics
__init__.py__init__.pyibuffer_cache.pybuffer_cache.pyicache_utils.pycoherence.pycoherence.pyicommon.pycommon.pyicore.pycore.pyidiagnosis.pydiagnosis.pyiemergence.pyexport.pyexport.pyiglyph_timing.pyglyph_timing.pyilearning_metrics.pylearning_metrics.pyilocal_coherence.pyphase_coherence.pyphase_compatibility.pyREADME.mdreporting.pyreporting.pyisense_index.pysense_index.pyitelemetry.pytetrad.pytrig_cache.pytrig_cache.pyitrig.pytrig.pyi
multiscale
__init__.pyhierarchical.pyREADME.md
navier_stokes
__init__.pyconservative_face.pyoperator.py
node
README.md
observers
README.md
operators
network_analysis
__init__.pysource_detection.py
postconditions
__init__.pymutation.py
preconditions
__init__.pycoherence.pydissonance.pyemission.pymutation.pyreception.pyresonance.py
strategies
__init__.pydefaults.pygpu_strategies.pystrategy.py
__init__.py__init__.pyialgebra.pycanonical_patterns.pycascade.pycoherence.pycontraction.pycoupling.pycycle_detection.pydefinitions_base.pydefinitions.pydefinitions.pyidissonance.pyemission.pyexpansion.pygrammar_application.pygrammar_canon.pygrammar_context.pygrammar_core.pygrammar_dynamics.pygrammar_error_factory.pygrammar_memoization.pygrammar_patterns.pygrammar_telemetry.pygrammar_types.pygrammar_u6.pygrammar_validate.pygrammar.pygrammar.pyihamiltonian.pyhealth_analyzer.pyintrospection.pyjitter.pyjitter.pyilifecycle.pymetabolism.pymetrics_basic.pymetrics_core.pymetrics_network.pymetrics_structural.pymetrics_u6.pymetrics.pymutation.pynodal_equation.pyoperator_contracts.pypattern_detection.pypatterns.pyREADME.mdreception.pyrecursivity.pyregistry.pyregistry.pyiremesh.pyremesh.pyiresonance.pyself_organization.pysilence.pystructural_units.pytransition.py
parallel
__init__.pyauto_scaler.pydistributed.pyengine.pymonitoring.pypartitioner.pyREADME.md
performance
guardrails.py
physics
__init__.py_helpers.pycalibration.pycanonical.pycell.pyclassical_mechanics.pyconservation_gauge_unification.pyconservation.pydissipative_conservation.pyemergent_chemistry.pyemergent_particles.pyextended.pyfields.pygauge.pyintegrity.pyinteractions.pylife.pylyapunov.pypatterns.pyphase_transition.pyquantum_mechanics.pyREADME.mdsignatures.pyspectral_conservation.pyspectral_metrics.pystructural_diffusion.pysymplectic_substrate.pytelemetry.pyunified.pyvariational.pyvectorized_ops.py
primality
__init__.py
recipes
__init__.pycookbook.pyREADME.md
riemann
__init__.pyadmissible_family_sweep.pyadmissible_rescaling.pyaggregates_closure_signature.pyalpha_sweep.pyanalytic_continuation_dirichlet.pyanalytic_continuation.pycoercivity_uniform.pycoupling_weights_type_signature.pycurrents_closure_signature.pydelta_phi_max_type_signature.pydirichlet_l.pydnfr_type_signature.pyepi_type_signature.pyhilbert_polya.pyli_keiper.pylyapunov_spectral_positivity.pynodal_pulse.pynodeaware_gauge_sweep.pynuf_type_signature.pyoperator_catalog_discipline_signature.pyoperator.pyoscillatory_correction.pypaley_gap_coercivity.pyphi_type_signature.pyprime_ladder_hamiltonian.pypulse_coherence.pyremesh_infinity_residue_split.pyremesh_window_type_signature.pyspectral_emergence.pystructural_zero_density.pytelemetry.pytetrad_closure_signature.pytwisted_admissible_family_sweep.pytwisted_admissible_rescaling.pytwisted_alpha_sweep.pytwisted_coercivity_uniform.pytwisted_hermite_family.pytwisted_hilbert_polya.pytwisted_li_keiper.pytwisted_lyapunov_spectral_positivity.pytwisted_nodeaware_gauge_sweep.pytwisted_oscillatory_correction.pytwisted_paley_gap_coercivity.pytwisted_prime_ladder_hamiltonian.pytwisted_spectral_emergence.pytwisted_structural_zero_density.pytwisted_weil_explicit_formula.pytwisted_weil_positivity.pyurules_consistency_signature.pyvon_mangoldt.pyweil_explicit_formula.pyweil_positivity.py
schemas
__init__.pygrammar.jsonREADME.md
sdk
__init__.py__init__.pyiadaptive_system.pyadaptive_system.pyibuilders.pybuilders.pyifluent.pyfluent.pyiREADME.mdself_opt.pysimple.pytemplates.pytemplates.pyiutils.py
security
__init__.pycrypto.pydatabase.pyREADME.mdsubprocess.pyvalidation.py
sequencing
__init__.pypatterns.pyREADME.md
services
__init__.pyorchestrator.pyREADME.md
sparse
__init__.pyREADME.mdrepresentations.py
structural
README.md
telemetry
__init__.pycache_metrics.pycache_metrics.pyiconstants.pynu_f.pynu_f.pyiREADME.mdunified_telemetry_system.pyverbosity.pyverbosity.pyi
tools
__init__.pydomain_templates.pyREADME.mdsequence_generator.pytnfr_is_prime_cli_optimized.pytnfr_is_prime_cli.py
topology
__init__.pyasymmetry.pyREADME.md
utils
cache_layers.pycache.pycache.pyicallbacks.pycallbacks.pyichunks.pychunks.pyidata.pydata.pyifast_diameter.pygraph.pygraph.pyiinit.pyinit.pyiio.pyio.pyinumeric.pynumeric.pyiREADME.mdtopology.pyunified_cache.py
validation
__init__.py__init__.pyiaggregator.pybase.pycompatibility.pycompatibility.pyiconfig.pygraph.pygraph.pyihealth.pyinput_validation.pyinterface_baselines.pyinvariants.pymultichannel_interface.pyphase_gate.pyREADME.mdrules.pyrules.pyiruntime.pyruntime.pyisequence_validator.pysignal_confrontation.pysoft_filters.pysoft_filters.pyispectral.pyspectral.pyistructural_interface.pytemporal_interface.pyunified_validation_system.pyvalidator.pywindow.pywindow.pyi
visualization
__init__.pycascade_viz.pyhierarchy.pyREADME.mdsequence_plotter.py
yang_mills
__init__.pyclosure.pyderivability.pyscaling.pystructural_gap.pyu6_sweep.py
__init__.py__init__.pyi_compat.py_version.py_version.pyialias.pyalias.pyibackend_config.pycache.pycache.pyiexecution.pyexecution.pyiflatten.pyflatten.pyigamma.pygamma.pyiglyph_history.pyglyph_history.pyiglyph_runtime.pyglyph_runtime.pyiimmutable.pyimmutable.pyiinitialization.pyinitialization.pyiio.pyio.pyilocking.pylocking.pyinode.pynode.pyiobservers.pyobservers.pyiontosim.pyontosim.pyipy.typedrng.pyrng.pyisecure_config.pyselector.pyselector.pyisense.pysense.pyistructural.pystructural.pyitokens.pytokens.pyitrace.pytrace.pyitypes.pytypes.pyiunits.pyunits.pyi
tetrad_evaluator.py
.pre-commit-config.yaml.semgrep.yaml.zenodo.jsonARCHITECTURE.mdbandit.yamlCHANGELOG.mdCITATION.cffCONTRIBUTING.mdEMERGENT_CANON_AUDIT.mdEMERGENT_DERIVATION_PLAN.mdLICENSE.mdMakefileMANIFEST.inpyproject.tomlpyrightconfig.jsonPYTORCH_CUDA_INTEGRATION.mdREADME.mdSECURITY.mdTESTING.mdTNFR_Website_Content_Brief.md
FILE: src/tnfr/dynamics/nbody.py

nbody.py

Classical N-body problem implementation in TNFR structural framework.

⚠️ IMPORTANT LIMITATION: This module ASSUMES Newtonian gravitational potential: U(q) = -Σ_{i<j} G * m_i * m_j / |r_i - r_j|

This is an external assumption, NOT derived from TNFR first principles!

For a PURE TNFR implementation (no gravitational assumption), see: tnfr.dynamics.nbody_tnfr

That module derives dynamics from coherence potential and Hamiltonian commutator, with NO classical force law assumptions.

Purpose of This Module

This module demonstrates how TNFR can reproduce classical mechanics when we explicitly map classical potentials into the TNFR framework. It shows the correspondence:

Classical Mechanics ←→ TNFR Framework


Position q ←→ EPI spatial component Velocity v ←→ EPI velocity component Mass m ←→ 1/νf (structural inertia) Force F = -∇U ←→ ΔNFR (ASSUMED from classical U) Newton's 2nd law ←→ Nodal equation ∂EPI/∂t = νf·ΔNFR

Comparison:

This module (nbody.py):

python
# Assumes gravitational potential
U = -Σ G*m_i*m_j/r_ij
F = -∇U  # Classical force
ΔNFR = F/m  # External assumption

Pure TNFR (nbody_tnfr.py):

python
# NO assumed potential
H_int = H_coh + H_freq + H_coupling
ΔNFR = i[H_int, ·]/ℏ_str  # From Hamiltonian
# Forces emerge from coherence/phase sync

Theoretical Foundation

The classical N-body problem emerges from TNFR as the low-dissonance coherence regime where:

  1. Mass as inverse frequency: m_i = 1/νf_i High mass → low structural reorganization rate (inertia) Low mass → high structural reorganization rate (responsiveness)

  2. Gravitational potential as coherence potential (ASSUMED): U(q) = -Σ_{i<j} G * m_i * m_j / |r_i - r_j|

    This potential encodes structural stability landscape. Nodes naturally evolve toward configurations of higher coherence (lower potential energy).

  3. Nodal equation integration: ∂EPI/∂t = νf · ΔNFR(t)

    Where EPI encodes position and velocity, and ΔNFR is computed from the gravitational coherence gradient (ASSUMED).

Mathematical Correspondence

Classical mechanics: TNFR structural dynamics:

  • Position q_i → EPI spatial component
  • Velocity v_i → EPI velocity component
  • Mass m_i → 1/νf_i (structural inertia)
  • Force F_i = -∇U → ΔNFR (coherence gradient, ASSUMED)
  • Newton's 2nd law → Nodal equation ∂EPI/∂t = νf·ΔNFR

Conservation Laws

The implementation preserves:

  • Total energy (H_int = T + U)
  • Linear momentum (Σ m_i * v_i)
  • Angular momentum (Σ r_i × m_i * v_i)

These emerge naturally from the Hamiltonian structure and translational/rotational symmetry of the coherence potential.

References

  • tnfr.dynamics.nbody_tnfr: Pure TNFR n-body (no assumptions)
  • docs/source/theory/07_emergence_classical_mechanics.md
  • docs/source/theory/08_classical_mechanics_euler_lagrange.md
  • TNFR.pdf: Canonical nodal equation (§2.3)
  • AGENTS.md: Canonical invariants (§3)

Examples

Two-body orbit (Earth-Moon system) with ASSUMED gravity:

from tnfr.dynamics.nbody import NBodySystem import numpy as np

Create 2-body system (dimensionless units)

system = NBodySystem( ... n_bodies=2, ... masses=[1.0, 0.012], # Mass ratio ~ Earth/Moon ... G=1.0 # Gravitational constant (ASSUMED) ... )

Initialize circular orbit

positions = np.array([ ... [0.0, 0.0, 0.0], # Earth at origin ... [1.0, 0.0, 0.0] # Moon at distance 1 ... ]) velocities = np.array([ ... [0.0, 0.0, 0.0], # Earth at rest (CM frame) ... [0.0, 1.0, 0.0] # Moon with tangential velocity ... ])

system.set_state(positions, velocities)

Evolve system (structural time)

history = system.evolve(t_final=10.0, dt=0.01)

Check energy conservation

E0 = history['energy'][0] E_final = history['energy'][-1] print(f"Energy drift: {abs(E_final - E0) / abs(E0):.2e}")

Three-body system (Figure-8 orbit):

system = NBodySystem(n_bodies=3, masses=[1.0, 1.0, 1.0], G=1.0)

Use known figure-8 initial conditions

(See Chenciner & Montgomery, 2000)

history = system.evolve(t_final=6.3, dt=0.001) system.plot_trajectories(history)

Source Code

python
"""Classical N-body problem implementation in TNFR structural framework.

⚠️ **IMPORTANT LIMITATION**: This module ASSUMES Newtonian gravitational potential:
   U(q) = -Σ_{i<j} G * m_i * m_j / |r_i - r_j|

This is an **external assumption**, NOT derived from TNFR first principles!

For a PURE TNFR implementation (no gravitational assumption), see:
   tnfr.dynamics.nbody_tnfr

That module derives dynamics from coherence potential and Hamiltonian
commutator, with NO classical force law assumptions.

Purpose of This Module
-----------------------

This module demonstrates how TNFR can **reproduce** classical mechanics
when we explicitly map classical potentials into the TNFR framework.
It shows the correspondence:

Classical Mechanics   ←→   TNFR Framework
-------------------        ---------------
Position q            ←→   EPI spatial component
Velocity v            ←→   EPI velocity component
Mass m                ←→   1/νf (structural inertia)
Force F = -∇U         ←→   ΔNFR (ASSUMED from classical U)
Newton's 2nd law      ←→   Nodal equation ∂EPI/∂t = νf·ΔNFR

Comparison:
-----------

**This module** (nbody.py):
```python
# Assumes gravitational potential
U = -Σ G*m_i*m_j/r_ij
F = -∇U  # Classical force
ΔNFR = F/m  # External assumption
```

**Pure TNFR** (nbody_tnfr.py):
```python
# NO assumed potential
H_int = H_coh + H_freq + H_coupling
ΔNFR = i[H_int, ·]/ℏ_str  # From Hamiltonian
# Forces emerge from coherence/phase sync
```

Theoretical Foundation
----------------------

The classical N-body problem emerges from TNFR as the **low-dissonance
coherence regime** where:

1. **Mass as inverse frequency**: m_i = 1/νf_i
   High mass → low structural reorganization rate (inertia)
   Low mass → high structural reorganization rate (responsiveness)

2. **Gravitational potential as coherence potential** (ASSUMED):
   U(q) = -Σ_{i<j} G * m_i * m_j / |r_i - r_j|

   This potential encodes structural stability landscape. Nodes
   naturally evolve toward configurations of higher coherence
   (lower potential energy).

3. **Nodal equation integration**:
   ∂EPI/∂t = νf · ΔNFR(t)

   Where EPI encodes position and velocity, and ΔNFR is computed
   from the gravitational coherence gradient (ASSUMED).

Mathematical Correspondence
---------------------------

Classical mechanics:     TNFR structural dynamics:
- Position q_i          → EPI spatial component
- Velocity v_i          → EPI velocity component
- Mass m_i              → 1/νf_i (structural inertia)
- Force F_i = -∇U       → ΔNFR (coherence gradient, ASSUMED)
- Newton's 2nd law      → Nodal equation ∂EPI/∂t = νf·ΔNFR

Conservation Laws
-----------------

The implementation preserves:
- Total energy (H_int = T + U)
- Linear momentum (Σ m_i * v_i)
- Angular momentum (Σ r_i × m_i * v_i)

These emerge naturally from the Hamiltonian structure and
translational/rotational symmetry of the coherence potential.

References
----------
- tnfr.dynamics.nbody_tnfr: Pure TNFR n-body (no assumptions)
- docs/source/theory/07_emergence_classical_mechanics.md
- docs/source/theory/08_classical_mechanics_euler_lagrange.md
- TNFR.pdf: Canonical nodal equation (§2.3)
- AGENTS.md: Canonical invariants (§3)

Examples
--------
Two-body orbit (Earth-Moon system) with ASSUMED gravity:

>>> from tnfr.dynamics.nbody import NBodySystem
>>> import numpy as np
>>>
>>> # Create 2-body system (dimensionless units)
>>> system = NBodySystem(
...     n_bodies=2,
...     masses=[1.0, 0.012],  # Mass ratio ~ Earth/Moon
...     G=1.0  # Gravitational constant (ASSUMED)
... )
>>>
>>> # Initialize circular orbit
>>> positions = np.array([
...     [0.0, 0.0, 0.0],      # Earth at origin
...     [1.0, 0.0, 0.0]       # Moon at distance 1
... ])
>>> velocities = np.array([
...     [0.0, 0.0, 0.0],      # Earth at rest (CM frame)
...     [0.0, 1.0, 0.0]       # Moon with tangential velocity
... ])
>>>
>>> system.set_state(positions, velocities)
>>>
>>> # Evolve system (structural time)
>>> history = system.evolve(t_final=10.0, dt=0.01)
>>>
>>> # Check energy conservation
>>> E0 = history['energy'][0]
>>> E_final = history['energy'][-1]
>>> print(f"Energy drift: {abs(E_final - E0) / abs(E0):.2e}")

Three-body system (Figure-8 orbit):

>>> system = NBodySystem(n_bodies=3, masses=[1.0, 1.0, 1.0], G=1.0)
>>> # Use known figure-8 initial conditions
>>> # (See Chenciner & Montgomery, 2000)
>>> history = system.evolve(t_final=6.3, dt=0.001)
>>> system.plot_trajectories(history)
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from numpy.typing import NDArray

from ..constants.canonical import EPI_MAX_CANONICAL
from ..mathematics.unified_numerical import np
from ..structural import create_nfr
from ..types import TNFRGraph

if TYPE_CHECKING:
    from matplotlib.figure import Figure

__all__ = (
    "NBodySystem",
    "gravitational_potential",
    "gravitational_force",
    "compute_gravitational_dnfr",
)


def gravitational_potential(
    positions: NDArray[np.floating],
    masses: NDArray[np.floating],
    G: float = 1.0,
    softening: float = 0.0,
) -> float:
    """Compute total Newtonian gravitational potential energy.

    U(q) = -Σ_{i<j} G * m_i * m_j / |r_i - r_j|

    This is the coherence potential in TNFR language: lower U means
    higher structural stability (attractive gravitational well).

    Parameters
    ----------
    positions : ndarray, shape (N, 3)
        Positions of N bodies in 3D space
    masses : ndarray, shape (N,)
        Masses of N bodies
    G : float, default=1.0
        Gravitational constant (in appropriate units)
    softening : float, default=0.0
        Softening length to avoid singularities at r=0.
        Effective distance: r_eff = sqrt(r² + ε²)

    Returns
    -------
    U : float
        Total gravitational potential energy (negative)

    Notes
    -----
    The negative sign ensures bound states have U < 0, matching
    the TNFR convention that coherent states minimize the potential.
    """
    N = len(positions)
    U = 0.0

    for i in range(N):
        for j in range(i + 1, N):
            r_ij = positions[j] - positions[i]
            dist = np.sqrt(np.sum(r_ij**2) + softening**2)
            U -= G * masses[i] * masses[j] / dist

    return U


def gravitational_force(
    positions: NDArray[np.floating],
    masses: NDArray[np.floating],
    G: float = 1.0,
    softening: float = 0.0,
) -> NDArray[np.floating]:
    """Compute gravitational forces on all bodies.

    F_i = -∇_i U = Σ_{j≠i} G * m_i * m_j * (r_j - r_i) / |r_j - r_i|³

    In TNFR language: force is the coherence gradient pointing toward
    higher stability (lower potential).

    Parameters
    ----------
    positions : ndarray, shape (N, 3)
        Positions of N bodies
    masses : ndarray, shape (N,)
        Masses of N bodies
    G : float, default=1.0
        Gravitational constant
    softening : float, default=0.0
        Softening length for numerical stability

    Returns
    -------
    forces : ndarray, shape (N, 3)
        Gravitational forces on each body

    Notes
    -----
    Force points from lower to higher coherence (lower potential).
    Newton's 3rd law (F_ij = -F_ji) emerges from symmetry of U(q).
    """
    N = len(positions)
    forces = np.zeros_like(positions)

    for i in range(N):
        for j in range(N):
            if i == j:
                continue

            r_ij = positions[j] - positions[i]
            dist_sq = np.sum(r_ij**2) + softening**2
            dist = np.sqrt(dist_sq)
            dist_cubed = dist_sq * dist

            # F_i = G * m_i * m_j * (r_j - r_i) / |r_j - r_i|³
            forces[i] += G * masses[i] * masses[j] * r_ij / dist_cubed

    return forces


def compute_gravitational_dnfr(
    positions: NDArray[np.floating],
    masses: NDArray[np.floating],
    G: float = 1.0,
    softening: float = 0.0,
) -> NDArray[np.floating]:
    """Compute ΔNFR from gravitational coherence gradient.

    ΔNFR_i = F_i / m_i = a_i (acceleration)

    This is the structural reorganization operator that drives evolution
    via the nodal equation: ∂EPI/∂t = νf · ΔNFR

    Parameters
    ----------
    positions : ndarray, shape (N, 3)
        Positions of N bodies
    masses : ndarray, shape (N,)
        Masses (or inverse frequencies: m = 1/νf)
    G : float, default=1.0
        Gravitational constant
    softening : float, default=0.0
        Softening length

    Returns
    -------
    dnfr : ndarray, shape (N, 3)
        ΔNFR values (accelerations) for each body

    Notes
    -----
    ΔNFR = a = F/m is independent of mass by equivalence principle.
    This is the reorganization "pressure" that drives structural change.
    """
    forces = gravitational_force(positions, masses, G, softening)

    # ΔNFR = F/m (acceleration)
    # Broadcast division: (N, 3) / (N, 1) -> (N, 3)
    dnfr = forces / masses[:, np.newaxis]

    return dnfr


class NBodySystem:
    """Classical N-body gravitational system in TNFR framework.

    Implements N particles (resonant nodes) coupled through Newtonian
    gravitational potential. Positions and velocities are encoded as
    EPI components, masses as inverse frequencies (m = 1/νf), and
    evolution follows the canonical nodal equation.

    Attributes
    ----------
    n_bodies : int
        Number of bodies in the system
    masses : ndarray, shape (N,)
        Masses of bodies (m_i = 1/νf_i)
    G : float
        Gravitational constant
    softening : float
        Softening length for numerical stability
    positions : ndarray, shape (N, 3)
        Current positions
    velocities : ndarray, shape (N, 3)
        Current velocities
    time : float
        Current structural time
    graph : TNFRGraph
        NetworkX graph storing nodes as NFRs

    Notes
    -----
    The system maintains TNFR canonical invariants:
    - EPI encodes (position, velocity) pairs
    - νf = 1/m (structural frequency from mass)
    - ΔNFR computed from gravitational gradient
    - Evolution via ∂EPI/∂t = νf · ΔNFR

    Conservation laws emerge naturally from Hamiltonian structure.
    """

    def __init__(
        self,
        n_bodies: int,
        masses: list[float] | NDArray[np.floating],
        G: float = 1.0,
        softening: float = 0.0,
    ):
        """Initialize N-body system.

        Parameters
        ----------
        n_bodies : int
            Number of bodies
        masses : array_like, shape (N,)
            Masses of bodies (must be positive)
        G : float, default=1.0
            Gravitational constant
        softening : float, default=0.0
            Softening length (ε) for numerical stability.
            Prevents singularities at r=0.

        Raises
        ------
        ValueError
            If masses are non-positive or dimensions mismatch
        """
        if n_bodies < 1:
            raise ValueError(f"n_bodies must be >= 1, got {n_bodies}")

        self.n_bodies = n_bodies
        self.masses = np.array(masses, dtype=float)

        if len(self.masses) != n_bodies:
            raise ValueError(f"masses length {len(self.masses)} != n_bodies {n_bodies}")

        if np.any(self.masses <= 0):
            raise ValueError("All masses must be positive")

        self.G = float(G)
        self.softening = float(softening)

        # State vectors
        self.positions: NDArray[np.floating] = np.zeros((n_bodies, 3), dtype=float)
        self.velocities: NDArray[np.floating] = np.zeros((n_bodies, 3), dtype=float)
        self.time = 0.0

        # Create TNFR graph representation
        self._build_graph()

    def _build_graph(self) -> None:
        """Build TNFR graph representation of the N-body system.

        Each body becomes a resonant node with:
        - νf = 1/m (structural frequency)
        - EPI encoding (position, velocity)
        - Phase initialized to 0 (can be set for rotation)
        - Fully connected topology (all-to-all gravitational coupling)
        """
        # Create empty graph (will add nodes manually)
        import networkx as nx

        self.graph: TNFRGraph = nx.Graph()
        self.graph.graph["name"] = "nbody_system"

        # Canonical EPI seed stays below the EPI_MAX = 1.0 validation bound.
        epi_seed = min(0.5, EPI_MAX_CANONICAL * 0.95)

        # Add nodes with TNFR attributes
        for i in range(self.n_bodies):
            node_id = f"body_{i}"

            # Structural frequency: νf = 1/m
            nu_f = 1.0 / self.masses[i]

            # Create NFR node
            _, _ = create_nfr(
                node_id,
                epi=epi_seed,  # Will be overwritten by set_state
                vf=nu_f,
                theta=0.0,  # Phase (for rotating systems)
                graph=self.graph,
            )

        # Add edges (all-to-all coupling for gravitational interaction)
        # Edge weight represents gravitational coupling strength
        for i in range(self.n_bodies):
            for j in range(i + 1, self.n_bodies):
                node_i = f"body_{i}"
                node_j = f"body_{j}"
                # Coupling weight: G * m_i * m_j
                weight = self.G * self.masses[i] * self.masses[j]
                self.graph.add_edge(node_i, node_j, weight=weight)

    def set_state(
        self,
        positions: NDArray[np.floating],
        velocities: NDArray[np.floating],
    ) -> None:
        """set system state (positions and velocities).

        Parameters
        ----------
        positions : ndarray, shape (N, 3)
            Positions of N bodies
        velocities : ndarray, shape (N, 3)
            Velocities of N bodies

        Raises
        ------
        ValueError
            If shapes don't match (N, 3)
        """
        positions = np.asarray(positions, dtype=float)
        velocities = np.asarray(velocities, dtype=float)

        expected_shape = (self.n_bodies, 3)
        if positions.shape != expected_shape:
            raise ValueError(f"positions shape {positions.shape} != {expected_shape}")
        if velocities.shape != expected_shape:
            raise ValueError(f"velocities shape {velocities.shape} != {expected_shape}")

        self.positions = positions.copy()
        self.velocities = velocities.copy()

        # Update EPI in graph nodes
        # EPI encodes state as dictionary with position/velocity
        for i in range(self.n_bodies):
            node_id = f"body_{i}"
            # Store as structured EPI
            epi_state = {
                "position": self.positions[i].copy(),
                "velocity": self.velocities[i].copy(),
            }
            self.graph.nodes[node_id]["epi"] = epi_state

    def get_state(self) -> tuple[NDArray[np.floating], NDArray[np.floating]]:
        """Get current state (positions and velocities).

        Returns
        -------
        positions : ndarray, shape (N, 3)
            Current positions
        velocities : ndarray, shape (N, 3)
            Current velocities
        """
        return self.positions.copy(), self.velocities.copy()

    def compute_energy(self) -> tuple[float, float, float]:
        """Compute system energy (kinetic + potential).

        Returns
        -------
        kinetic : float
            Total kinetic energy T = Σ (1/2) m_i v_i²
        potential : float
            Total potential energy U (negative for bound systems)
        total : float
            Total energy H = T + U

        Notes
        -----
        Energy conservation is a fundamental check of integrator accuracy.
        For Hamiltonian systems, H should be constant over time.
        """
        # Kinetic energy: T = Σ (1/2) m_i v_i²
        v_squared = np.sum(self.velocities**2, axis=1)
        kinetic = 0.5 * np.sum(self.masses * v_squared)

        # Potential energy: U = -Σ_{i<j} G m_i m_j / r_ij
        potential = gravitational_potential(
            self.positions, self.masses, self.G, self.softening
        )

        total = kinetic + potential

        return kinetic, potential, total

    def compute_momentum(self) -> NDArray[np.floating]:
        """Compute total linear momentum.

        Returns
        -------
        momentum : ndarray, shape (3,)
            Total momentum P = Σ m_i v_i

        Notes
        -----
        For isolated systems, momentum should be conserved (constant).
        """
        momentum = np.sum(self.masses[:, np.newaxis] * self.velocities, axis=0)
        return momentum

    def compute_angular_momentum(self) -> NDArray[np.floating]:
        """Compute total angular momentum about origin.

        Returns
        -------
        angular_momentum : ndarray, shape (3,)
            Total angular momentum L = Σ r_i × m_i v_i

        Notes
        -----
        For central force systems, angular momentum is conserved.
        """
        L = np.zeros(3)
        for i in range(self.n_bodies):
            L += self.masses[i] * np.cross(self.positions[i], self.velocities[i])
        return L

    def step(self, dt: float) -> None:
        """Advance system by one time step using velocity Verlet.

        The velocity Verlet integrator is symplectic (preserves phase space
        volume) and provides excellent long-term energy conservation.

        Algorithm:
        1. r(t+dt) = r(t) + v(t)*dt + (1/2)*a(t)*dt²
        2. a(t+dt) = compute acceleration at new positions
        3. v(t+dt) = v(t) + (1/2)*(a(t) + a(t+dt))*dt

        Parameters
        ----------
        dt : float
            Time step (in structural time units)

        Notes
        -----
        This integrator is equivalent to applying the nodal equation:
        ∂EPI/∂t = νf · ΔNFR with νf = 1/m and ΔNFR = acceleration.
        """
        # Compute acceleration at current time: a(t) = ΔNFR
        accel_t = compute_gravitational_dnfr(
            self.positions, self.masses, self.G, self.softening
        )

        # Update positions: r(t+dt) = r(t) + v(t)*dt + (1/2)*a(t)*dt²
        self.positions += self.velocities * dt + 0.5 * accel_t * dt**2

        # Compute acceleration at new time: a(t+dt)
        accel_t_plus_dt = compute_gravitational_dnfr(
            self.positions, self.masses, self.G, self.softening
        )

        # Update velocities: v(t+dt) = v(t) + (1/2)*(a(t) + a(t+dt))*dt
        self.velocities += 0.5 * (accel_t + accel_t_plus_dt) * dt

        # Update structural time
        self.time += dt

        # Update graph representation
        for i in range(self.n_bodies):
            node_id = f"body_{i}"
            epi_state = {
                "position": self.positions[i].copy(),
                "velocity": self.velocities[i].copy(),
            }
            self.graph.nodes[node_id]["epi"] = epi_state

    def evolve(
        self,
        t_final: float,
        dt: float,
        store_interval: int = 1,
    ) -> dict[str, Any]:
        """Evolve system from current time to t_final.

        Parameters
        ----------
        t_final : float
            Final structural time
        dt : float
            Time step for integration
        store_interval : int, default=1
            Store state every N steps (for memory efficiency)

        Returns
        -------
        history : dict
            Dictionary containing:
            - 'time': array of time points
            - 'positions': array of positions (n_steps, N, 3)
            - 'velocities': array of velocities (n_steps, N, 3)
            - 'energy': array of total energies
            - 'kinetic': array of kinetic energies
            - 'potential': array of potential energies
            - 'momentum': array of momentum vectors (n_steps, 3)
            - 'angular_momentum': array of L vectors (n_steps, 3)

        Notes
        -----
        The evolution implements the nodal equation iteratively.
        Conservation laws are tracked for validation.
        """
        n_steps = int((t_final - self.time) / dt)

        if n_steps < 1:
            raise ValueError(f"t_final {t_final} <= current time {self.time}")

        # Pre-allocate storage
        n_stored = (n_steps // store_interval) + 1
        times = np.zeros(n_stored)
        positions_hist = np.zeros((n_stored, self.n_bodies, 3))
        velocities_hist = np.zeros((n_stored, self.n_bodies, 3))
        energies = np.zeros(n_stored)
        kinetic_energies = np.zeros(n_stored)
        potential_energies = np.zeros(n_stored)
        momenta = np.zeros((n_stored, 3))
        angular_momenta = np.zeros((n_stored, 3))

        # Store initial state
        store_idx = 0
        times[store_idx] = self.time
        positions_hist[store_idx] = self.positions.copy()
        velocities_hist[store_idx] = self.velocities.copy()
        K, U, E = self.compute_energy()
        kinetic_energies[store_idx] = K
        potential_energies[store_idx] = U
        energies[store_idx] = E
        momenta[store_idx] = self.compute_momentum()
        angular_momenta[store_idx] = self.compute_angular_momentum()
        store_idx += 1

        # Evolution loop
        for step in range(n_steps):
            self.step(dt)

            # Store state if needed
            if (step + 1) % store_interval == 0 and store_idx < n_stored:
                times[store_idx] = self.time
                positions_hist[store_idx] = self.positions.copy()
                velocities_hist[store_idx] = self.velocities.copy()
                K, U, E = self.compute_energy()
                kinetic_energies[store_idx] = K
                potential_energies[store_idx] = U
                energies[store_idx] = E
                momenta[store_idx] = self.compute_momentum()
                angular_momenta[store_idx] = self.compute_angular_momentum()
                store_idx += 1

        return {
            "time": times[:store_idx],
            "positions": positions_hist[:store_idx],
            "velocities": velocities_hist[:store_idx],
            "energy": energies[:store_idx],
            "kinetic": kinetic_energies[:store_idx],
            "potential": potential_energies[:store_idx],
            "momentum": momenta[:store_idx],
            "angular_momentum": angular_momenta[:store_idx],
        }

    def plot_trajectories(
        self,
        history: dict[str, Any],
        ax: Any | None = None,
        show_energy: bool = True,
    ) -> Figure:
        """Plot trajectories and energy evolution.

        Parameters
        ----------
        history : dict
            Result from evolve() method
        ax : matplotlib axis, optional
            Axis to plot on. If None, creates new figure.
        show_energy : bool, default=True
            If True, also plot energy conservation

        Returns
        -------
        fig : matplotlib Figure
            Figure object containing plots

        Raises
        ------
        ImportError
            If matplotlib is not available
        """
        try:
            import matplotlib.pyplot as plt
        except ImportError as exc:
            raise ImportError(
                "matplotlib is required for plotting. "
                "Install with: pip install 'tnfr[viz-basic]'"
            ) from exc

        if show_energy:
            fig = plt.figure(figsize=(14, 6))
            ax_3d = fig.add_subplot(121, projection="3d")
            ax_energy = fig.add_subplot(122)
        else:
            fig = plt.figure(figsize=(10, 8))
            ax_3d = fig.add_subplot(111, projection="3d")

        # Plot 3D trajectories
        positions = history["positions"]
        colors = plt.cm.rainbow(np.linspace(0, 1, self.n_bodies))

        for i in range(self.n_bodies):
            traj = positions[:, i, :]
            ax_3d.plot(
                traj[:, 0],
                traj[:, 1],
                traj[:, 2],
                color=colors[i],
                label=f"Body {i + 1} (m={self.masses[i]:.2f})",
                alpha=0.7,
            )
            # Mark initial position
            ax_3d.scatter(
                traj[0, 0],
                traj[0, 1],
                traj[0, 2],
                color=colors[i],
                s=100,
                marker="o",
            )
            # Mark final position
            ax_3d.scatter(
                traj[-1, 0],
                traj[-1, 1],
                traj[-1, 2],
                color=colors[i],
                s=50,
                marker="x",
            )

        ax_3d.set_xlabel("X")
        ax_3d.set_ylabel("Y")
        ax_3d.set_zlabel("Z")
        ax_3d.set_title("N-Body Trajectories (TNFR Framework)")
        ax_3d.legend()

        if show_energy:
            # Plot energy conservation
            time = history["time"]
            E = history["energy"]
            E0 = E[0]

            ax_energy.plot(
                time,
                (E - E0) / abs(E0) * 100,
                label="Relative energy error (%)",
                color="red",
            )
            ax_energy.axhline(0, color="black", linestyle="--", alpha=0.3)
            ax_energy.set_xlabel("Structural Time")
            ax_energy.set_ylabel("ΔE/E₀ (%)")
            ax_energy.set_title("Energy Conservation Check")
            ax_energy.legend()
            ax_energy.grid(True, alpha=0.3)

        plt.tight_layout()
        return fig