pyrecest 2.2.1__tar.gz → 2.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyrecest-2.2.1 → pyrecest-2.2.2}/PKG-INFO +1 -1
- {pyrecest-2.2.1 → pyrecest-2.2.2}/pyproject.toml +1 -1
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/autodiff.py +24 -12
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/random.py +22 -6
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/_so3_helpers.py +30 -4
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_dirac_distribution.py +27 -6
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_grid_distribution.py +4 -4
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_manifold_specific_distribution.py +51 -10
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_mixture.py +3 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_orthogonal_basis_distribution.py +23 -4
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_hypercylindrical_distribution.py +18 -11
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_lin_bounded_cart_prod_distribution.py +1 -1
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/mardia_sutton_distribution.py +25 -3
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_fourier_distribution.py +19 -4
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_grid_distribution.py +3 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/sine_skewed_distributions.py +12 -3
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/von_mises_distribution.py +65 -8
- pyrecest-2.2.2/src/pyrecest/distributions/circle/wrapped_cauchy_distribution.py +55 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/wrapped_normal_distribution.py +89 -30
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/ellipsoidal_ball_uniform_distribution.py +11 -1
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hyperhemispherical_distribution.py +15 -17
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py +88 -43
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_grid_distribution.py +23 -8
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hyperspherical_distribution.py +18 -9
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_sphere_subset_distribution.py +19 -7
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/bingham_distribution.py +38 -5
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperhemispherical_grid_distribution.py +16 -12
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperhemispherical_watson_distribution.py +11 -9
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperspherical_dirac_distribution.py +8 -7
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperspherical_grid_distribution.py +30 -12
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperspherical_uniform_distribution.py +2 -1
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/spherical_grid_distribution.py +21 -5
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/spherical_harmonics_distribution_complex.py +5 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/von_mises_fisher_distribution.py +104 -27
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/watson_distribution.py +9 -8
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/abstract_hypertoroidal_distribution.py +22 -6
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/hypertoroidal_fourier_distribution.py +54 -23
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/hypertoroidal_wrapped_normal_distribution.py +26 -12
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/toroidal_fourier_distribution.py +3 -4
- pyrecest-2.2.2/src/pyrecest/distributions/hypertorus/toroidal_von_mises_cosine_distribution.py +120 -0
- pyrecest-2.2.2/src/pyrecest/distributions/hypertorus/toroidal_von_mises_sine_distribution.py +76 -0
- pyrecest-2.2.2/src/pyrecest/distributions/hypertorus/toroidal_wrapped_normal_distribution.py +114 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/abstract_linear_distribution.py +25 -8
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/custom_linear_distribution.py +3 -3
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/gaussian_distribution.py +12 -10
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_helpers.py +2 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_product_tangent_gaussian_distribution.py +18 -9
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_tangent_gaussian_distribution.py +19 -13
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/perform_predict_update_cycles.py +2 -2
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/__init__.py +6 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/_ukf.py +40 -11
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_particle_filter.py +30 -2
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/circular_ukf.py +157 -72
- pyrecest-2.2.2/src/pyrecest/filters/factorized_giw_random_matrix_tracker.py +256 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hyperhemisphere_cart_prod_particle_filter.py +9 -4
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hyperhemispherical_grid_filter.py +6 -6
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hyperspherical_particle_filter.py +3 -1
- pyrecest-2.2.2/src/pyrecest/filters/information_form_distributed_kalman_filter.py +597 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/lomem_tracker.py +246 -68
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mem_rbpf_tracker.py +9 -4
- pyrecest-2.2.2/src/pyrecest/filters/multi_bernoulli_mixture_tracker.py +467 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/se2_ukf.py +36 -19
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/unscented_kalman_filter.py +45 -3
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/von_mises_filter.py +3 -1
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/wrapped_normal_filter.py +5 -4
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/additive_noise.py +18 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/protocols/filters.py +4 -6
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/hyperspherical_sampler.py +0 -3
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/leopardi_sampler.py +5 -6
- pyrecest-2.2.2/src/pyrecest/smoothers/__init__.py +87 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/smoothers/abstract_smoother.py +22 -14
- pyrecest-2.2.2/src/pyrecest/smoothers/fixed_lag_mem_qkf_smoother.py +1204 -0
- pyrecest-2.2.2/src/pyrecest/smoothers/fixed_lag_random_matrix_smoother.py +918 -0
- pyrecest-2.2.2/src/pyrecest/smoothers/mem_rbpf_ffbsi_smoother.py +504 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/plotting.py +1 -1
- pyrecest-2.2.1/src/pyrecest/distributions/circle/wrapped_cauchy_distribution.py +0 -36
- pyrecest-2.2.1/src/pyrecest/distributions/hypertorus/toroidal_von_mises_cosine_distribution.py +0 -86
- pyrecest-2.2.1/src/pyrecest/distributions/hypertorus/toroidal_von_mises_sine_distribution.py +0 -40
- pyrecest-2.2.1/src/pyrecest/distributions/hypertorus/toroidal_wrapped_normal_distribution.py +0 -133
- pyrecest-2.2.1/src/pyrecest/smoothers/__init__.py +0 -41
- pyrecest-2.2.1/src/pyrecest/smoothers/fixed_lag_random_matrix_smoother.py +0 -349
- {pyrecest-2.2.1 → pyrecest-2.2.2}/LICENSE +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/README.md +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/.pylintrc +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/LICENSE_geomstats +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/README.md +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_backend_config.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_dtype_utils.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_shared_numpy/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_shared_numpy/_common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_shared_numpy/_dispatch.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_shared_numpy/linalg.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/_shared_numpy/random.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/autograd/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/autograd/_common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/autograd/_dtype.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/autograd/autodiff.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/autograd/linalg.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/autograd/random.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/_dtype.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/fft.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/linalg.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/signal.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/jax/spatial.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/_common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/_dtype.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/autodiff.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/fft.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/linalg.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/random.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/signal.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/numpy/spatial.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/_common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/_dtype.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/autodiff.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/fft.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/linalg.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/random.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/signal.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/_backend/pytorch/spatial.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_bounded_domain_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_bounded_nonperiodic_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_custom_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_custom_nonperiodic_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_disk_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_distribution_type.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_ellipsoidal_ball_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_nonperiodic_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_periodic_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_periodic_grid_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_se2_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_se3_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/abstract_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_custom_lin_bounded_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_lin_hemisphere_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_lin_hyperhemisphere_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_lin_hypersphere_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_lin_hypersphere_subset_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/abstract_lin_periodic_cart_prod_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/cart_prod_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/cart_prod_stacked_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/custom_hypercylindrical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/gauss_von_mises_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/hypercylindrical_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/hypercylindrical_state_space_subdivision_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/hypercylindrical_state_space_subdivision_gaussian_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/hyperhemisphere_cart_prod_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/lin_bounded_cart_prod_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/lin_hypersphere_cart_prod_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/lin_hypersphere_subset_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/lin_periodic_cart_prod_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/partially_wrapped_normal_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/se2_bingham_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/se2_pwn_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/se2_state_space_subdivision_gaussian_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/se3_lin_vel_cart_prod_stacked_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/state_space_subdivision_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/state_space_subdivision_gaussian_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/abstract_circular_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_mixture.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/custom_circular_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/generalized_von_mises_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/piecewise_constant_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/wrapped_exponential_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/wrapped_laplace_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conditional/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conditional/abstract_conditional_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conditional/s2_cond_s2_grid_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conditional/sd_cond_sd_grid_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conditional/sd_half_cond_sd_half_grid_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conditional/td_cond_td_grid_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/conversion.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/custom_hyperrectangular_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/disk_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_complex_hyperspherical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hemispherical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_spherical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/abstract_spherical_harmonics_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/bayesian_complex_watson_mixture_model.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/complex_angular_central_gaussian_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/complex_bingham_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/complex_watson_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/custom_hemispherical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/custom_hyperhemispherical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/custom_hyperspherical_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hemispherical_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperhemispherical_bingham_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperhemispherical_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperhemispherical_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/hyperspherical_mixture.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypersphere_subset/spherical_harmonics_distribution_real.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/abstract_toroidal_bivar_vm_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/abstract_toroidal_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/custom_hypertoroidal_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/custom_toroidal_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/hypertoroidal_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/hypertoroidal_grid_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/hypertoroidal_mixture.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/hypertoroidal_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/toroidal_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/toroidal_mixture.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/toroidal_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/toroidal_vm_matrix_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/hypertorus/toroidal_vm_rivest_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/abstract_hyperrectangular_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/gaussian_mixture.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/hyperrectangular_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/linear_box_particle_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/linear_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/nonperiodic/linear_mixture.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/se2_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/se3_cart_prod_stacked_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/se3_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_bingham_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_conversion.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_product_dirac_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/so3_uniform_distribution.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/check_and_fix_config.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/configure_for_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/determine_all_deviations.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/eot_shape_database.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/evaluate_for_file.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/evaluate_for_simulation_config.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/evaluate_for_variables.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/generate_groundtruth.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/generate_measurements.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/generate_simulated_scenarios.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/get_axis_label.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/get_distance_function.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/get_extract_mean.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/group_results_by_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/iterate_configs_and_runs.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/plot_results.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/simulation_database.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/evaluation/summarize_filter_results.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/_linear_gaussian.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_axial_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_circular_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_dummy_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_extended_object_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_grid_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_multiple_extended_object_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_multitarget_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_nearest_neighbor_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/abstract_tracker_with_logging.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/association_hypotheses.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/axial_kalman_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/bingham_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/block_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/circular_fourier_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/circular_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/ekf_spline_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/euclidean_box_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/euclidean_boxed_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/euclidean_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/fourier_rhm_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/gaussian_mixture_phd_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/ggiw_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/global_nearest_neighbor.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/goal_conditioned_replay_imm_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/goal_conditioned_replay_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/goal_conditioned_replay_particle_imm_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/gprhm_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hypercylindrical_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hyperhemispherical_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hyperspherical_dummy_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hyperspherical_ukf.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hypertoroidal_dummy_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hypertoroidal_fourier_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/hypertoroidal_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/interacting_multiple_model_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/iterated_batch_mem_qkf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/joint_probabilistic_data_association_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/kalman_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/kernel_sme_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/lin_bounded_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/lin_periodic_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/manifold_exponential_moving_average.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/manifold_mixins.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mem_ekf_star_oa_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mem_ekf_star_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mem_ekf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mem_qkf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mem_soekf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/mode_rbpf_manifold_ukf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/multi_bernoulli_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/multi_hypothesis_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/orientation_vector_eot_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/out_of_sequence.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/partitioned_so3_product_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/piecewise_constant_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/random_matrix_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/relaxed_s3f_circular.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/relaxed_s3f_so3.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/so3_grid_transition.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/so3_product_block_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/so3_product_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/spherical_harmonics_eot_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/spherical_harmonics_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/state_space_subdivision_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/toroidal_particle_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/toroidal_wrapped_normal_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/track_manager.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/ukf_on_manifolds.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/vbrm_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/velocity_aided_mem_qkf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/velocity_locked_mem_qkf_tracker.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/filters/von_mises_fisher_filter.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/adapters.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/grid.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/likelihood.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/linear_gaussian.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/motion_models.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/particle.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/sensor_models.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/models/validation.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/protocols/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/protocols/common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/protocols/models.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/protocols/testing.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/py.typed +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/abstract_sampler.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/euclidean_sampler.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/hypertoroidal_sampler.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/sampling/sigma_points.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/smoothers/fixed_lag_velocity_locked_mem_qkf_smoother.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/smoothers/rauch_tung_striebel_smoother.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/smoothers/sliding_window_manifold_mean_smoother.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/smoothers/so3_chordal_mean_smoother.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/smoothers/unscented_rauch_tung_striebel_smoother.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/__init__.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/_point_set_registration_common.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/assignment.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/association_features.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/association_models.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/history_recorder.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/metrics.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/multisession_assignment.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/multisession_assignment_observation_costs.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/multisession_assignment_score.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/nonrigid_point_set_registration.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/pairwise_covariance_features.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/point_set_registration.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/roi_assignment.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/track_evaluation.py +0 -0
- {pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/utils/track_metrics.py +0 -0
|
@@ -3,7 +3,7 @@ name = "pyrecest"
|
|
|
3
3
|
description = "Framework for recursive Bayesian estimation in Python."
|
|
4
4
|
readme = "README.md"
|
|
5
5
|
authors = ["Florian Pfaff <pfaff@ias.uni-stuttgart.de>"]
|
|
6
|
-
version = "2.2.
|
|
6
|
+
version = "2.2.2"
|
|
7
7
|
|
|
8
8
|
[build-system]
|
|
9
9
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
@@ -6,10 +6,9 @@ https://github.com/oxcsml/geomstats/blob/master/geomstats/_backend/jax/autodiff.
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
import jax.numpy as anp
|
|
9
|
-
from jax import vmap, grad
|
|
10
|
-
from jax import jacfwd
|
|
11
|
-
from jax import value_and_grad as _value_and_grad
|
|
12
9
|
from autograd.extend import defvjp, primitive # TODO: replace
|
|
10
|
+
from jax import grad, jacfwd
|
|
11
|
+
from jax import value_and_grad as _value_and_grad
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def detach(x):
|
|
@@ -33,7 +32,14 @@ def elementwise_grad(func):
|
|
|
33
32
|
func : callable
|
|
34
33
|
Function for which the element-wise grad is computed.
|
|
35
34
|
"""
|
|
36
|
-
|
|
35
|
+
|
|
36
|
+
def _elementwise_grad(*args, **kwargs):
|
|
37
|
+
def _summed_func(*inner_args):
|
|
38
|
+
return anp.sum(func(*inner_args, **kwargs))
|
|
39
|
+
|
|
40
|
+
return grad(_summed_func)(*args)
|
|
41
|
+
|
|
42
|
+
return _elementwise_grad
|
|
37
43
|
|
|
38
44
|
|
|
39
45
|
def custom_gradient(*grad_funcs):
|
|
@@ -116,14 +122,20 @@ def value_and_grad(func, to_numpy=False):
|
|
|
116
122
|
|
|
117
123
|
return aux_value_and_grad
|
|
118
124
|
|
|
125
|
+
|
|
119
126
|
unsupported_functions = [
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
"hessian",
|
|
128
|
+
"hessian_vec",
|
|
129
|
+
"jacobian_vec",
|
|
130
|
+
"jacobian_and_hessian",
|
|
131
|
+
"value_jacobian_and_hessian",
|
|
132
|
+
"value_and_jacobian",
|
|
126
133
|
]
|
|
127
|
-
for func_name in unsupported_functions:
|
|
128
|
-
exec(f"{func_name} = lambda *args, **kwargs: NotImplementedError('This function is not supported in this JAX backend.')")
|
|
129
134
|
|
|
135
|
+
|
|
136
|
+
def _raise_unsupported(*args, **kwargs):
|
|
137
|
+
raise NotImplementedError("This function is not supported in this JAX backend.")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
for func_name in unsupported_functions:
|
|
141
|
+
globals()[func_name] = _raise_unsupported
|
|
@@ -120,15 +120,31 @@ def choice(a, n, *args, **kwargs):
|
|
|
120
120
|
return set_state_return(has_state, state, res)
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
def
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
def _shape_from_size(size):
|
|
124
|
+
"""Convert a NumPy-style ``size`` argument to JAX's ``shape`` argument."""
|
|
125
|
+
if size is None:
|
|
126
|
+
return None
|
|
127
|
+
if hasattr(size, "__iter__"):
|
|
128
|
+
return tuple(int(dim) for dim in size)
|
|
129
|
+
return (int(size),)
|
|
126
130
|
|
|
127
131
|
|
|
128
|
-
def
|
|
129
|
-
|
|
132
|
+
def _multivariate_normal(state, mean, cov, size=None, *args, **kwargs):
|
|
133
|
+
state, key = jax.random.split(state)
|
|
134
|
+
if "shape" in kwargs:
|
|
135
|
+
if size is not None:
|
|
136
|
+
raise TypeError("Specify only one of 'size' or 'shape'.")
|
|
137
|
+
size = kwargs.pop("shape")
|
|
138
|
+
shape = _shape_from_size(size)
|
|
139
|
+
return state, jax.random.multivariate_normal(
|
|
140
|
+
key, mean, cov, shape, *args, **kwargs
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def multivariate_normal(mean, cov, size=None, *args, **kwargs):
|
|
145
|
+
"""Draw samples with NumPy-compatible ``multivariate_normal`` arguments."""
|
|
130
146
|
state, has_state, kwargs = _get_state(**kwargs)
|
|
131
|
-
state, res = _multivariate_normal(state, size, *args, **kwargs)
|
|
147
|
+
state, res = _multivariate_normal(state, mean, cov, size, *args, **kwargs)
|
|
132
148
|
return set_state_return(has_state, state, res)
|
|
133
149
|
|
|
134
150
|
|
|
@@ -11,6 +11,7 @@ from pyrecest.backend import (
|
|
|
11
11
|
concatenate,
|
|
12
12
|
cos,
|
|
13
13
|
linalg,
|
|
14
|
+
log,
|
|
14
15
|
ndim,
|
|
15
16
|
reshape,
|
|
16
17
|
sin,
|
|
@@ -72,6 +73,28 @@ def quaternion_multiply(left, right):
|
|
|
72
73
|
return normalize_quaternions(product)
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
def so3_exp_map_volume_log_jacobian(tangent_vectors):
|
|
77
|
+
"""Return the SO(3) exponential-map volume log-Jacobian.
|
|
78
|
+
|
|
79
|
+
For scalar-last unit quaternions with the canonical ``w >= 0`` sign, the
|
|
80
|
+
principal rotation-vector chart maps the ball ``||v|| <= pi`` to the upper
|
|
81
|
+
unit-quaternion half sphere. With ``theta = ||v||``, its volume element is
|
|
82
|
+
|
|
83
|
+
dV = sin(theta / 2)^2 / (2 * theta^2) dv,
|
|
84
|
+
|
|
85
|
+
with limiting value ``1 / 8`` at the identity. The returned value is
|
|
86
|
+
``log(dV / dv)`` and preserves all leading dimensions of ``tangent_vectors``.
|
|
87
|
+
"""
|
|
88
|
+
tangent_vectors = array(tangent_vectors, dtype=float)
|
|
89
|
+
assert tangent_vectors.shape[-1] == 3, "SO(3) tangent vectors must have length 3."
|
|
90
|
+
|
|
91
|
+
angles = linalg.norm(tangent_vectors, axis=-1)
|
|
92
|
+
safe_angles = where(angles > 1e-8, angles, 1.0)
|
|
93
|
+
direct = 2.0 * (log(sin(0.5 * safe_angles)) - log(safe_angles)) - log(2.0)
|
|
94
|
+
small_angle_series = -log(8.0) - angles**2 / 12.0 - angles**4 / 1440.0
|
|
95
|
+
return where(angles > 1e-8, direct, small_angle_series)
|
|
96
|
+
|
|
97
|
+
|
|
75
98
|
def exp_map_identity(tangent_vectors):
|
|
76
99
|
"""Map SO(3) tangent vectors at identity to scalar-last quaternions."""
|
|
77
100
|
tangent_vectors = array(tangent_vectors, dtype=float)
|
|
@@ -107,10 +130,13 @@ def log_map_identity(rotations):
|
|
|
107
130
|
angles = 2.0 * arctan2(vector_norm, scalar_part)
|
|
108
131
|
vector_norm_col = reshape(vector_norm, tuple(vector_norm.shape) + (1,))
|
|
109
132
|
safe_norm = where(vector_norm_col > 1e-12, vector_norm_col, 1.0)
|
|
110
|
-
scale =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
133
|
+
scale = (
|
|
134
|
+
where(
|
|
135
|
+
vector_norm_col > 1e-12,
|
|
136
|
+
reshape(angles, tuple(angles.shape) + (1,)),
|
|
137
|
+
2.0 * safe_norm,
|
|
138
|
+
)
|
|
139
|
+
/ safe_norm
|
|
114
140
|
)
|
|
115
141
|
return vector_part * scale
|
|
116
142
|
|
|
@@ -9,10 +9,12 @@ from beartype import beartype
|
|
|
9
9
|
from pyrecest.backend import (
|
|
10
10
|
all,
|
|
11
11
|
apply_along_axis,
|
|
12
|
+
arange,
|
|
12
13
|
argmax,
|
|
13
14
|
int32,
|
|
14
15
|
int64,
|
|
15
16
|
isclose,
|
|
17
|
+
isfinite,
|
|
16
18
|
log,
|
|
17
19
|
ones,
|
|
18
20
|
random,
|
|
@@ -42,13 +44,31 @@ class AbstractDiracDistribution(AbstractDistributionType):
|
|
|
42
44
|
self.w = copy.copy(w)
|
|
43
45
|
self.normalize_in_place()
|
|
44
46
|
|
|
47
|
+
@staticmethod
|
|
48
|
+
def _validate_weights(w):
|
|
49
|
+
"""
|
|
50
|
+
Validate Dirac weights and return their total mass.
|
|
51
|
+
"""
|
|
52
|
+
if not bool(all(isfinite(w))):
|
|
53
|
+
raise ValueError("Dirac weights must be finite.")
|
|
54
|
+
|
|
55
|
+
if not bool(all(w >= 0)):
|
|
56
|
+
raise ValueError("Dirac weights must be nonnegative.")
|
|
57
|
+
|
|
58
|
+
total_weight = sum(w)
|
|
59
|
+
if not bool(isfinite(total_weight)) or not bool(total_weight > 0):
|
|
60
|
+
raise ValueError("Dirac weights must have positive finite total mass.")
|
|
61
|
+
|
|
62
|
+
return total_weight
|
|
63
|
+
|
|
45
64
|
def normalize_in_place(self):
|
|
46
65
|
"""
|
|
47
66
|
Normalize the weights in-place to ensure they sum to 1.
|
|
48
67
|
"""
|
|
49
|
-
|
|
68
|
+
total_weight = self._validate_weights(self.w)
|
|
69
|
+
if not isclose(total_weight, 1.0, atol=1e-10):
|
|
50
70
|
warnings.warn("Weights are not normalized.", RuntimeWarning)
|
|
51
|
-
self.w = self.w /
|
|
71
|
+
self.w = self.w / total_weight
|
|
52
72
|
|
|
53
73
|
def normalize(self) -> "AbstractDiracDistribution":
|
|
54
74
|
dist = copy.deepcopy(self)
|
|
@@ -75,16 +95,17 @@ class AbstractDiracDistribution(AbstractDistributionType):
|
|
|
75
95
|
w_new = f(dist.d)
|
|
76
96
|
|
|
77
97
|
assert w_new.shape == dist.w.shape, "Function returned wrong output dimensions."
|
|
78
|
-
|
|
79
|
-
assert sum(w_new) > 0, "The sum of all weights should be greater than 0."
|
|
98
|
+
self._validate_weights(w_new)
|
|
80
99
|
|
|
81
100
|
dist.w = w_new * dist.w
|
|
82
|
-
|
|
101
|
+
total_weight = self._validate_weights(dist.w)
|
|
102
|
+
dist.w = dist.w / total_weight
|
|
83
103
|
|
|
84
104
|
return dist
|
|
85
105
|
|
|
86
106
|
def sample(self, n: Union[int, int32, int64]):
|
|
87
|
-
|
|
107
|
+
indices = random.choice(arange(self.d.shape[0]), n, p=self.w)
|
|
108
|
+
samples = self.d[indices]
|
|
88
109
|
return samples
|
|
89
110
|
|
|
90
111
|
def entropy(self) -> float:
|
|
@@ -74,14 +74,14 @@ class AbstractGridDistribution(AbstractDistributionType):
|
|
|
74
74
|
|
|
75
75
|
def normalize_in_place(self, tol=1e-4, warn_unnorm=True):
|
|
76
76
|
int_val = self.integrate()
|
|
77
|
+
if float(abs(int_val)) < 1e-200:
|
|
78
|
+
raise ValueError(
|
|
79
|
+
"Sum of grid values is too close to zero, this usually points to a user error."
|
|
80
|
+
)
|
|
77
81
|
if any(self.grid_values < 0):
|
|
78
82
|
warnings.warn(
|
|
79
83
|
"Warning: There are negative values. This usually points to a user error."
|
|
80
84
|
)
|
|
81
|
-
elif abs(int_val) < 1e-200:
|
|
82
|
-
raise ValueError(
|
|
83
|
-
"Sum of grid values is too close to zero, this usually points to a user error."
|
|
84
|
-
)
|
|
85
85
|
elif abs(int_val - 1) > tol:
|
|
86
86
|
if warn_unnorm:
|
|
87
87
|
warnings.warn(
|
|
@@ -9,6 +9,16 @@ import pyrecest.backend
|
|
|
9
9
|
from pyrecest.backend import empty, int32, int64, log, random, squeeze
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def _to_scalar(value):
|
|
13
|
+
"""Convert a backend scalar or length-one array to a Python float."""
|
|
14
|
+
try:
|
|
15
|
+
return float(value.item())
|
|
16
|
+
except AttributeError:
|
|
17
|
+
return float(value)
|
|
18
|
+
except (TypeError, ValueError, RuntimeError):
|
|
19
|
+
return float(value.reshape(-1)[0])
|
|
20
|
+
|
|
21
|
+
|
|
12
22
|
class AbstractManifoldSpecificDistribution(ABC):
|
|
13
23
|
"""
|
|
14
24
|
Abstract base class for distributions catering to specific manifolds.
|
|
@@ -98,7 +108,7 @@ class AbstractManifoldSpecificDistribution(ABC):
|
|
|
98
108
|
return self.sample_metropolis_hastings(n)
|
|
99
109
|
|
|
100
110
|
# jscpd:ignore-start
|
|
101
|
-
# pylint: disable=too-many-positional-arguments,too-many-locals
|
|
111
|
+
# pylint: disable=too-many-positional-arguments,too-many-locals,too-many-arguments
|
|
102
112
|
def sample_metropolis_hastings(
|
|
103
113
|
self,
|
|
104
114
|
n: Union[int, int32, int64],
|
|
@@ -106,9 +116,19 @@ class AbstractManifoldSpecificDistribution(ABC):
|
|
|
106
116
|
skipping: Union[int, int32, int64] = 5,
|
|
107
117
|
proposal: Callable | None = None,
|
|
108
118
|
start_point=None,
|
|
119
|
+
proposal_log_pdf: Callable | None = None,
|
|
109
120
|
):
|
|
110
121
|
# jscpd:ignore-end
|
|
111
|
-
"""Metropolis
|
|
122
|
+
"""Metropolis-Hastings sampling algorithm.
|
|
123
|
+
|
|
124
|
+
``proposal`` generates a candidate state from the current state. For
|
|
125
|
+
non-JAX backends it must be callable as ``proposal(x)``; for JAX it
|
|
126
|
+
must be callable as ``proposal(key, x)``.
|
|
127
|
+
|
|
128
|
+
``proposal_log_pdf`` is optional and must evaluate
|
|
129
|
+
``log q(candidate | current)``. If it is omitted, the proposal is
|
|
130
|
+
assumed symmetric, recovering the ordinary Metropolis ratio.
|
|
131
|
+
"""
|
|
112
132
|
if pyrecest.backend.__backend_name__ == "jax":
|
|
113
133
|
# Get a key from your global JAX random state *outside* of lax.scan
|
|
114
134
|
import jax as _jax # pylint: disable=import-error
|
|
@@ -132,6 +152,7 @@ class AbstractManifoldSpecificDistribution(ABC):
|
|
|
132
152
|
n=int(n),
|
|
133
153
|
burn_in=int(burn_in),
|
|
134
154
|
skipping=int(skipping),
|
|
155
|
+
proposal_log_pdf=proposal_log_pdf,
|
|
135
156
|
)
|
|
136
157
|
# You could optionally stash `key_out` somewhere if you want chain continuation.
|
|
137
158
|
return squeeze(samples)
|
|
@@ -146,20 +167,30 @@ class AbstractManifoldSpecificDistribution(ABC):
|
|
|
146
167
|
s = empty((total_samples, self.input_dim))
|
|
147
168
|
x = start_point
|
|
148
169
|
i = 0
|
|
149
|
-
|
|
170
|
+
log_pdfx = _to_scalar(self.ln_pdf(x))
|
|
150
171
|
|
|
151
172
|
while i < total_samples:
|
|
152
173
|
x_new = proposal(x)
|
|
153
174
|
assert (
|
|
154
175
|
x_new.shape == x.shape
|
|
155
176
|
), "Proposal must return a vector of same shape as input"
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
177
|
+
log_pdfx_new = _to_scalar(self.ln_pdf(x_new))
|
|
178
|
+
log_acceptance_ratio = log_pdfx_new - log_pdfx
|
|
179
|
+
|
|
180
|
+
if proposal_log_pdf is not None:
|
|
181
|
+
log_acceptance_ratio += _to_scalar(
|
|
182
|
+
proposal_log_pdf(x, x_new)
|
|
183
|
+
) - _to_scalar(proposal_log_pdf(x_new, x))
|
|
184
|
+
|
|
185
|
+
if (
|
|
186
|
+
log_acceptance_ratio >= 0.0
|
|
187
|
+
or _to_scalar(log(random.rand(1))) < log_acceptance_ratio
|
|
188
|
+
):
|
|
160
189
|
x = x_new
|
|
161
|
-
|
|
162
|
-
|
|
190
|
+
log_pdfx = log_pdfx_new
|
|
191
|
+
# Record every chain step; rejected proposals keep the current state.
|
|
192
|
+
s[i, :] = x.squeeze()
|
|
193
|
+
i += 1
|
|
163
194
|
|
|
164
195
|
relevant_samples = s[burn_in::skipping, :]
|
|
165
196
|
return squeeze(relevant_samples)
|
|
@@ -174,6 +205,8 @@ def sample_metropolis_hastings_jax(
|
|
|
174
205
|
n: int,
|
|
175
206
|
burn_in: int = 10,
|
|
176
207
|
skipping: int = 5,
|
|
208
|
+
# function: (candidate, current) -> log q(candidate | current)
|
|
209
|
+
proposal_log_pdf=None,
|
|
177
210
|
):
|
|
178
211
|
"""
|
|
179
212
|
Metropolis-Hastings sampler in JAX using a plain Python loop.
|
|
@@ -186,6 +219,8 @@ def sample_metropolis_hastings_jax(
|
|
|
186
219
|
proposal: callable (key, x) -> x_proposed
|
|
187
220
|
start_point: initial state (array)
|
|
188
221
|
n: number of samples to return (after burn-in and thinning)
|
|
222
|
+
proposal_log_pdf: optional callable evaluating log q(candidate | current).
|
|
223
|
+
If omitted, the proposal is assumed symmetric.
|
|
189
224
|
"""
|
|
190
225
|
import jax.numpy as _jnp # pylint: disable=import-error
|
|
191
226
|
from jax import random as _random # pylint: disable=import-error
|
|
@@ -209,8 +244,14 @@ def sample_metropolis_hastings_jax(
|
|
|
209
244
|
x_prop = proposal(key_prop, x)
|
|
210
245
|
log_px_prop = _to_scalar(log_pdf(x_prop))
|
|
211
246
|
|
|
212
|
-
# Metropolis acceptance
|
|
247
|
+
# Metropolis-Hastings acceptance. The proposal correction vanishes for
|
|
248
|
+
# symmetric proposals.
|
|
213
249
|
log_alpha = log_px_prop - log_px
|
|
250
|
+
if proposal_log_pdf is not None:
|
|
251
|
+
log_alpha += _to_scalar(proposal_log_pdf(x, x_prop)) - _to_scalar(
|
|
252
|
+
proposal_log_pdf(x_prop, x)
|
|
253
|
+
)
|
|
254
|
+
|
|
214
255
|
log_u = _to_scalar(_jnp.log(_random.uniform(key_u, shape=())))
|
|
215
256
|
|
|
216
257
|
if log_u < min(0.0, log_alpha):
|
|
@@ -47,6 +47,9 @@ class AbstractMixture(AbstractDistributionType):
|
|
|
47
47
|
if num_distributions != len(weights):
|
|
48
48
|
raise ValueError("Sizes of distributions and weights must be equal")
|
|
49
49
|
|
|
50
|
+
if any(bool(weight < 0) for weight in weights):
|
|
51
|
+
raise ValueError("Mixture weights must be nonnegative")
|
|
52
|
+
|
|
50
53
|
if not all(dists[0].dim == dist.dim for dist in dists):
|
|
51
54
|
raise ValueError("All distributions must have the same dimension")
|
|
52
55
|
|
|
@@ -4,10 +4,13 @@ from abc import abstractmethod
|
|
|
4
4
|
|
|
5
5
|
# pylint: disable=redefined-builtin,no-name-in-module,no-member
|
|
6
6
|
# pylint: disable=no-name-in-module,no-member
|
|
7
|
+
from pyrecest.backend import abs as backend_abs
|
|
7
8
|
from pyrecest.backend import all, exp, imag, real
|
|
8
9
|
|
|
9
10
|
from .abstract_distribution_type import AbstractDistributionType
|
|
10
11
|
|
|
12
|
+
_REAL_DENSITY_IMAG_TOL = 1e-10
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
class AbstractOrthogonalBasisDistribution(AbstractDistributionType):
|
|
13
16
|
"""
|
|
@@ -48,6 +51,23 @@ class AbstractOrthogonalBasisDistribution(AbstractDistributionType):
|
|
|
48
51
|
result = copy.deepcopy(self)
|
|
49
52
|
return result.normalize_in_place()
|
|
50
53
|
|
|
54
|
+
@staticmethod
|
|
55
|
+
def _discard_negligible_imaginary_part(val):
|
|
56
|
+
"""
|
|
57
|
+
Return the real part of a numerically real value.
|
|
58
|
+
|
|
59
|
+
Non-square-root density representations should evaluate to real-valued
|
|
60
|
+
densities. Small imaginary parts arise from floating-point roundoff in
|
|
61
|
+
complex basis evaluations and can be discarded; larger imaginary parts
|
|
62
|
+
indicate inconsistent coefficients and must not be silently ignored.
|
|
63
|
+
"""
|
|
64
|
+
if not all(backend_abs(imag(val)) <= _REAL_DENSITY_IMAG_TOL):
|
|
65
|
+
raise ValueError(
|
|
66
|
+
"Density evaluation has a non-negligible imaginary part. "
|
|
67
|
+
"Check that the coefficients define a real-valued density."
|
|
68
|
+
)
|
|
69
|
+
return real(val)
|
|
70
|
+
|
|
51
71
|
def pdf(self, xs):
|
|
52
72
|
"""
|
|
53
73
|
Calculates probability density function for the given input.
|
|
@@ -57,14 +77,13 @@ class AbstractOrthogonalBasisDistribution(AbstractDistributionType):
|
|
|
57
77
|
"""
|
|
58
78
|
val = self.value(xs)
|
|
59
79
|
if self.transformation == "sqrt":
|
|
60
|
-
|
|
61
|
-
return real(val) ** 2
|
|
80
|
+
return backend_abs(val) ** 2
|
|
62
81
|
|
|
63
82
|
if self.transformation == "identity":
|
|
64
|
-
return val
|
|
83
|
+
return self._discard_negligible_imaginary_part(val)
|
|
65
84
|
|
|
66
85
|
if self.transformation == "log":
|
|
67
86
|
warnings.warn("Density may not be normalized")
|
|
68
|
-
return exp(val)
|
|
87
|
+
return exp(self._discard_negligible_imaginary_part(val))
|
|
69
88
|
|
|
70
89
|
raise ValueError("Transformation not recognized or unsupported")
|
|
@@ -71,23 +71,30 @@ class AbstractHypercylindricalDistribution(AbstractLinPeriodicCartProdDistributi
|
|
|
71
71
|
|
|
72
72
|
def get_reasonable_integration_boundaries(self, scalingFactor=10):
|
|
73
73
|
"""
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
Return reasonable integration boundaries for numerical integration.
|
|
75
|
+
|
|
76
|
+
The input dimensions are ordered as bounded dimensions first and linear
|
|
77
|
+
dimensions second. SciPy's nquad expects one [lower, upper] interval per
|
|
78
|
+
input dimension, so the periodic dimensions are integrated over a full
|
|
79
|
+
period and the linear dimensions are truncated around the mode according
|
|
80
|
+
to their marginal standard deviations.
|
|
76
81
|
"""
|
|
77
|
-
left = empty((self.bound_dim + self.lin_dim, 1))
|
|
78
|
-
right = empty((self.bound_dim + self.lin_dim, 1))
|
|
79
82
|
P = self.linear_covariance()
|
|
80
83
|
m = self.mode()
|
|
81
84
|
|
|
82
|
-
for
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
integration_boundaries = [[0.0, float(2.0 * pi)] for _ in range(self.bound_dim)]
|
|
86
|
+
|
|
87
|
+
for linear_idx in range(self.lin_dim):
|
|
88
|
+
input_idx = self.bound_dim + linear_idx
|
|
89
|
+
linear_std = sqrt(P[linear_idx, linear_idx])
|
|
90
|
+
integration_boundaries.append(
|
|
91
|
+
[
|
|
92
|
+
float(m[input_idx] - scalingFactor * linear_std),
|
|
93
|
+
float(m[input_idx] + scalingFactor * linear_std),
|
|
94
|
+
]
|
|
88
95
|
)
|
|
89
96
|
|
|
90
|
-
return
|
|
97
|
+
return integration_boundaries
|
|
91
98
|
|
|
92
99
|
def mode(self):
|
|
93
100
|
"""Find the mode of the distribution by calling mode_numerical."""
|
|
@@ -27,7 +27,7 @@ class AbstractLinBoundedCartProdDistribution(AbstractCartProdDistribution):
|
|
|
27
27
|
"""
|
|
28
28
|
if not bound_dim >= 1:
|
|
29
29
|
raise ValueError("bound_dim must be a positive integer")
|
|
30
|
-
if not
|
|
30
|
+
if not lin_dim >= 1:
|
|
31
31
|
raise ValueError("lin_dim must be a positive integer")
|
|
32
32
|
|
|
33
33
|
AbstractCartProdDistribution.__init__(self, bound_dim + lin_dim)
|
{pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/cart_prod/mardia_sutton_distribution.py
RENAMED
|
@@ -120,13 +120,35 @@ class MardiaSuttonDistribution(AbstractHypercylindricalDistribution):
|
|
|
120
120
|
return column_stack([s_vm, s_gauss])
|
|
121
121
|
|
|
122
122
|
def linear_covariance(self, approximate_mean=None):
|
|
123
|
-
"""Return the
|
|
123
|
+
"""Return the marginal linear variance as a (1, 1) matrix.
|
|
124
124
|
|
|
125
125
|
Returns:
|
|
126
|
-
C (1, 1):
|
|
126
|
+
C (1, 1): marginal variance of the linear variable
|
|
127
127
|
"""
|
|
128
128
|
_ = approximate_mean
|
|
129
|
-
|
|
129
|
+
|
|
130
|
+
kappa = float(self.kappa)
|
|
131
|
+
bessel_0 = iv(0, kappa)
|
|
132
|
+
bessel_ratio_1 = iv(1, kappa) / bessel_0
|
|
133
|
+
bessel_ratio_2 = iv(2, kappa) / bessel_0
|
|
134
|
+
|
|
135
|
+
rho_squared = self.rho1**2 + self.rho2**2
|
|
136
|
+
conditional_variance = self.sigma**2 * (1.0 - rho_squared)
|
|
137
|
+
|
|
138
|
+
# The conditional linear mean depends on the von-Mises-distributed angle.
|
|
139
|
+
# Hence the marginal linear variance is E[Var[X | theta]] plus
|
|
140
|
+
# Var(E[X | theta]); returning sigma**2 alone ignores the second term.
|
|
141
|
+
aligned_rho_cos = self.rho1 * cos(self.mu0) + self.rho2 * sin(self.mu0)
|
|
142
|
+
aligned_rho_sin = -self.rho1 * sin(self.mu0) + self.rho2 * cos(self.mu0)
|
|
143
|
+
cos_variance = 0.5 * (1.0 + bessel_ratio_2) - bessel_ratio_1**2
|
|
144
|
+
sin_variance = 0.5 * (1.0 - bessel_ratio_2)
|
|
145
|
+
conditional_mean_variance = (
|
|
146
|
+
self.sigma**2
|
|
147
|
+
* self.kappa
|
|
148
|
+
* (aligned_rho_cos**2 * cos_variance + aligned_rho_sin**2 * sin_variance)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return array([[conditional_variance + conditional_mean_variance]])
|
|
130
152
|
|
|
131
153
|
def marginalize_linear(self):
|
|
132
154
|
"""Return the marginal circular distribution.
|
{pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_fourier_distribution.py
RENAMED
|
@@ -29,6 +29,16 @@ from .abstract_circular_distribution import AbstractCircularDistribution
|
|
|
29
29
|
from .circular_dirac_distribution import CircularDiracDistribution
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def _ensure_odd_n(n) -> None:
|
|
33
|
+
if n is not None and int(n) % 2 == 0:
|
|
34
|
+
raise ValueError(
|
|
35
|
+
"CircularFourierDistribution requires an odd number of "
|
|
36
|
+
"coefficients/grid values. Even lengths contain a Nyquist "
|
|
37
|
+
"coefficient that is not represented by the current real "
|
|
38
|
+
"coefficient convention."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
32
42
|
class CircularFourierDistribution(AbstractCircularDistribution):
|
|
33
43
|
"""Circular distribution represented by a Fourier series.
|
|
34
44
|
|
|
@@ -67,7 +77,8 @@ class CircularFourierDistribution(AbstractCircularDistribution):
|
|
|
67
77
|
)
|
|
68
78
|
self.n = 2 * c.shape[0] - 1
|
|
69
79
|
else:
|
|
70
|
-
self.n = n
|
|
80
|
+
self.n = int(n)
|
|
81
|
+
_ensure_odd_n(self.n)
|
|
71
82
|
elif a is not None and b is not None:
|
|
72
83
|
assert a.ndim == 1
|
|
73
84
|
assert b.ndim == 1
|
|
@@ -76,6 +87,7 @@ class CircularFourierDistribution(AbstractCircularDistribution):
|
|
|
76
87
|
self.c = None
|
|
77
88
|
self.n = a.shape[0] + b.shape[0]
|
|
78
89
|
assert self.n == n or n is None
|
|
90
|
+
_ensure_odd_n(self.n)
|
|
79
91
|
else:
|
|
80
92
|
raise ValueError("Need to provide either c or a and b.")
|
|
81
93
|
|
|
@@ -270,7 +282,7 @@ class CircularFourierDistribution(AbstractCircularDistribution):
|
|
|
270
282
|
|
|
271
283
|
def get_c(self):
|
|
272
284
|
if self.a is not None:
|
|
273
|
-
c = (self.a[0]
|
|
285
|
+
c = hstack((self.a[0:1], self.a[1:] - 1j * self.b)) * 0.5
|
|
274
286
|
elif self.c is not None:
|
|
275
287
|
c = self.c
|
|
276
288
|
else:
|
|
@@ -308,6 +320,7 @@ class CircularFourierDistribution(AbstractCircularDistribution):
|
|
|
308
320
|
transformation: str = "sqrt",
|
|
309
321
|
store_values_multiplied_by_n: bool = True,
|
|
310
322
|
) -> "CircularFourierDistribution":
|
|
323
|
+
_ensure_odd_n(n)
|
|
311
324
|
if isinstance(distribution, CircularDiracDistribution):
|
|
312
325
|
if transformation != "identity":
|
|
313
326
|
warnings.warn(
|
|
@@ -355,14 +368,16 @@ class CircularFourierDistribution(AbstractCircularDistribution):
|
|
|
355
368
|
transformation: str = "sqrt",
|
|
356
369
|
store_values_multiplied_by_n: bool = True,
|
|
357
370
|
) -> "CircularFourierDistribution":
|
|
371
|
+
n_values = fvals.shape[0]
|
|
372
|
+
_ensure_odd_n(n_values)
|
|
358
373
|
c = fft.rfft(fvals)
|
|
359
374
|
if not store_values_multiplied_by_n:
|
|
360
|
-
c = c * (1.0 /
|
|
375
|
+
c = c * (1.0 / n_values)
|
|
361
376
|
|
|
362
377
|
fd = CircularFourierDistribution(
|
|
363
378
|
c=c,
|
|
364
379
|
transformation=transformation,
|
|
365
|
-
n=
|
|
380
|
+
n=n_values,
|
|
366
381
|
multiplied_by_n=store_values_multiplied_by_n,
|
|
367
382
|
)
|
|
368
383
|
|
{pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/circular_grid_distribution.py
RENAMED
|
@@ -81,6 +81,9 @@ class CircularGridDistribution(AbstractCircularDistribution, AbstractGridDistrib
|
|
|
81
81
|
def get_manifold_size(self):
|
|
82
82
|
return 2 * pi
|
|
83
83
|
|
|
84
|
+
def get_grid_point(self, indices):
|
|
85
|
+
return self.grid[indices]
|
|
86
|
+
|
|
84
87
|
def trigonometric_moment(self, n):
|
|
85
88
|
weights = self.grid_values / sum(self.grid_values)
|
|
86
89
|
grid = self.get_grid()
|
{pyrecest-2.2.1 → pyrecest-2.2.2}/src/pyrecest/distributions/circle/sine_skewed_distributions.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
|
|
3
3
|
# pylint: disable=no-name-in-module,no-member
|
|
4
|
-
from pyrecest.backend import cos, cosh, exp, mod, ndim, pi, sin, sinh
|
|
4
|
+
from pyrecest.backend import array, cos, cosh, exp, mod, ndim, pi, sin, sinh
|
|
5
5
|
from scipy.special import ive # pylint: disable=no-name-in-module
|
|
6
6
|
|
|
7
7
|
from .abstract_circular_distribution import AbstractCircularDistribution
|
|
@@ -57,7 +57,7 @@ class GeneralizedKSineSkewedVonMisesDistribution(AbstractCircularDistribution):
|
|
|
57
57
|
1
|
|
58
58
|
+ self.lambda_**4
|
|
59
59
|
/ 8
|
|
60
|
-
* (3 -
|
|
60
|
+
* (3 - 4 * bessel_ratio(2, self.kappa) + bessel_ratio(4, self.kappa))
|
|
61
61
|
+ 3 * self.lambda_**2 * (1 - bessel_ratio(2, self.kappa))
|
|
62
62
|
)
|
|
63
63
|
else:
|
|
@@ -134,7 +134,16 @@ class AbstractSineSkewedDistribution(AbstractCircularDistribution):
|
|
|
134
134
|
"""
|
|
135
135
|
AbstractCircularDistribution.__init__(self)
|
|
136
136
|
self.mu = mu
|
|
137
|
-
self.lambda_ = lambda_
|
|
137
|
+
self.lambda_ = array(lambda_)
|
|
138
|
+
self.validate_parameters()
|
|
139
|
+
|
|
140
|
+
def validate_parameters(self):
|
|
141
|
+
"""Validate parameters common to first-order sine-skewed distributions."""
|
|
142
|
+
if ndim(self.lambda_) != 0:
|
|
143
|
+
raise ValueError("lambda_ must be a scalar")
|
|
144
|
+
|
|
145
|
+
if not (-1.0 <= self.lambda_ <= 1.0):
|
|
146
|
+
raise ValueError("lambda_ must be between -1 and 1 inclusive")
|
|
138
147
|
|
|
139
148
|
@abstractmethod
|
|
140
149
|
def base_pdf(self, xs):
|