nrl-tracker 1.5.0__tar.gz → 1.7.0__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.
Files changed (226) hide show
  1. {nrl_tracker-1.5.0/nrl_tracker.egg-info → nrl_tracker-1.7.0}/PKG-INFO +13 -9
  2. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/README.md +12 -8
  3. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0/nrl_tracker.egg-info}/PKG-INFO +13 -9
  4. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/nrl_tracker.egg-info/SOURCES.txt +20 -0
  5. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pyproject.toml +1 -1
  6. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/__init__.py +1 -1
  7. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/__init__.py +28 -0
  8. nrl_tracker-1.7.0/pytcl/assignment_algorithms/nd_assignment.py +378 -0
  9. nrl_tracker-1.7.0/pytcl/assignment_algorithms/network_flow.py +361 -0
  10. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/__init__.py +101 -0
  11. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/reference_frames.py +734 -1
  12. nrl_tracker-1.7.0/pytcl/astronomical/sgp4.py +710 -0
  13. nrl_tracker-1.7.0/pytcl/astronomical/special_orbits.py +536 -0
  14. nrl_tracker-1.7.0/pytcl/astronomical/tle.py +558 -0
  15. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/atmosphere/__init__.py +11 -0
  16. nrl_tracker-1.7.0/pytcl/atmosphere/nrlmsise00.py +808 -0
  17. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/conversions/geodetic.py +248 -5
  18. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/__init__.py +26 -0
  19. nrl_tracker-1.7.0/pytcl/dynamic_estimation/gaussian_sum_filter.py +452 -0
  20. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/__init__.py +30 -0
  21. nrl_tracker-1.7.0/pytcl/dynamic_estimation/kalman/constrained.py +370 -0
  22. nrl_tracker-1.7.0/pytcl/dynamic_estimation/kalman/h_infinity.py +613 -0
  23. nrl_tracker-1.7.0/pytcl/dynamic_estimation/rbpf.py +593 -0
  24. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_astronomical.py +25 -0
  25. nrl_tracker-1.7.0/tests/test_constrained_ekf.py +745 -0
  26. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_coordinate_systems.py +118 -0
  27. nrl_tracker-1.7.0/tests/test_gaussian_sum_filter.py +508 -0
  28. nrl_tracker-1.7.0/tests/test_h_infinity.py +391 -0
  29. nrl_tracker-1.7.0/tests/test_nd_assignment.py +341 -0
  30. nrl_tracker-1.7.0/tests/test_network_flow.py +230 -0
  31. nrl_tracker-1.7.0/tests/test_nrlmsise00.py +549 -0
  32. nrl_tracker-1.7.0/tests/test_rbpf.py +599 -0
  33. nrl_tracker-1.7.0/tests/test_sgp4.py +388 -0
  34. nrl_tracker-1.7.0/tests/test_special_orbits.py +357 -0
  35. nrl_tracker-1.7.0/tests/test_tod_mod.py +308 -0
  36. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/CONTRIBUTING.md +0 -0
  37. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/LICENSE +0 -0
  38. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/MANIFEST.in +0 -0
  39. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/nrl_tracker.egg-info/dependency_links.txt +0 -0
  40. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/nrl_tracker.egg-info/requires.txt +0 -0
  41. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/nrl_tracker.egg-info/top_level.txt +0 -0
  42. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/data_association.py +0 -0
  43. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/gating.py +0 -0
  44. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/jpda.py +0 -0
  45. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/three_dimensional/__init__.py +0 -0
  46. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/three_dimensional/assignment.py +0 -0
  47. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/two_dimensional/__init__.py +0 -0
  48. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/two_dimensional/assignment.py +0 -0
  49. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/assignment_algorithms/two_dimensional/kbest.py +0 -0
  50. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/ephemerides.py +0 -0
  51. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/lambert.py +0 -0
  52. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/orbital_mechanics.py +0 -0
  53. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/relativity.py +0 -0
  54. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/astronomical/time_systems.py +0 -0
  55. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/atmosphere/ionosphere.py +0 -0
  56. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/atmosphere/models.py +0 -0
  57. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/clustering/__init__.py +0 -0
  58. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/clustering/dbscan.py +0 -0
  59. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/clustering/gaussian_mixture.py +0 -0
  60. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/clustering/hierarchical.py +0 -0
  61. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/clustering/kmeans.py +0 -0
  62. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/__init__.py +0 -0
  63. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/base.py +0 -0
  64. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/cluster_set.py +0 -0
  65. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/covertree.py +0 -0
  66. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/kd_tree.py +0 -0
  67. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/measurement_set.py +0 -0
  68. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/rtree.py +0 -0
  69. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/track_list.py +0 -0
  70. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/containers/vptree.py +0 -0
  71. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/__init__.py +0 -0
  72. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/conversions/__init__.py +0 -0
  73. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/conversions/spherical.py +0 -0
  74. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/jacobians/__init__.py +0 -0
  75. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/jacobians/jacobians.py +0 -0
  76. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/projections/__init__.py +0 -0
  77. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/projections/projections.py +0 -0
  78. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/rotations/__init__.py +0 -0
  79. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/coordinate_systems/rotations/rotations.py +0 -0
  80. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/core/__init__.py +0 -0
  81. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/core/array_utils.py +0 -0
  82. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/core/constants.py +0 -0
  83. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/core/validation.py +0 -0
  84. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/batch_estimation/__init__.py +0 -0
  85. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/imm.py +0 -0
  86. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/information_filter.py +0 -0
  87. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/extended.py +0 -0
  88. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/linear.py +0 -0
  89. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/square_root.py +0 -0
  90. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/sr_ukf.py +0 -0
  91. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/ud_filter.py +0 -0
  92. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/kalman/unscented.py +0 -0
  93. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/measurement_update/__init__.py +0 -0
  94. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/particle_filters/__init__.py +0 -0
  95. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/particle_filters/bootstrap.py +0 -0
  96. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_estimation/smoothers.py +0 -0
  97. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/__init__.py +0 -0
  98. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/continuous_time/__init__.py +0 -0
  99. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/continuous_time/dynamics.py +0 -0
  100. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/discrete_time/__init__.py +0 -0
  101. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/discrete_time/coordinated_turn.py +0 -0
  102. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/discrete_time/polynomial.py +0 -0
  103. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/discrete_time/singer.py +0 -0
  104. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/process_noise/__init__.py +0 -0
  105. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/process_noise/coordinated_turn.py +0 -0
  106. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/process_noise/polynomial.py +0 -0
  107. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/dynamic_models/process_noise/singer.py +0 -0
  108. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/gravity/__init__.py +0 -0
  109. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/gravity/clenshaw.py +0 -0
  110. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/gravity/egm.py +0 -0
  111. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/gravity/models.py +0 -0
  112. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/gravity/spherical_harmonics.py +0 -0
  113. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/gravity/tides.py +0 -0
  114. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/logging_config.py +0 -0
  115. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/magnetism/__init__.py +0 -0
  116. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/magnetism/emm.py +0 -0
  117. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/magnetism/igrf.py +0 -0
  118. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/magnetism/wmm.py +0 -0
  119. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/__init__.py +0 -0
  120. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/basic_matrix/__init__.py +0 -0
  121. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/basic_matrix/decompositions.py +0 -0
  122. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/basic_matrix/special_matrices.py +0 -0
  123. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/combinatorics/__init__.py +0 -0
  124. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/combinatorics/combinatorics.py +0 -0
  125. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/continuous_optimization/__init__.py +0 -0
  126. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/geometry/__init__.py +0 -0
  127. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/geometry/geometry.py +0 -0
  128. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/interpolation/__init__.py +0 -0
  129. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/interpolation/interpolation.py +0 -0
  130. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/numerical_integration/__init__.py +0 -0
  131. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/numerical_integration/quadrature.py +0 -0
  132. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/polynomials/__init__.py +0 -0
  133. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/signal_processing/__init__.py +0 -0
  134. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/signal_processing/detection.py +0 -0
  135. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/signal_processing/filters.py +0 -0
  136. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/signal_processing/matched_filter.py +0 -0
  137. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/__init__.py +0 -0
  138. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/bessel.py +0 -0
  139. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/debye.py +0 -0
  140. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/elliptic.py +0 -0
  141. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/error_functions.py +0 -0
  142. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/gamma_functions.py +0 -0
  143. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/hypergeometric.py +0 -0
  144. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/lambert_w.py +0 -0
  145. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/special_functions/marcum_q.py +0 -0
  146. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/statistics/__init__.py +0 -0
  147. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/statistics/distributions.py +0 -0
  148. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/statistics/estimators.py +0 -0
  149. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/transforms/__init__.py +0 -0
  150. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/transforms/fourier.py +0 -0
  151. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/transforms/stft.py +0 -0
  152. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/mathematical_functions/transforms/wavelets.py +0 -0
  153. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/misc/__init__.py +0 -0
  154. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/navigation/__init__.py +0 -0
  155. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/navigation/geodesy.py +0 -0
  156. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/navigation/great_circle.py +0 -0
  157. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/navigation/ins.py +0 -0
  158. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/navigation/ins_gnss.py +0 -0
  159. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/navigation/rhumb.py +0 -0
  160. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/performance_evaluation/__init__.py +0 -0
  161. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/performance_evaluation/estimation_metrics.py +0 -0
  162. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/performance_evaluation/track_metrics.py +0 -0
  163. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/physical_values/__init__.py +0 -0
  164. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/plotting/__init__.py +0 -0
  165. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/plotting/coordinates.py +0 -0
  166. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/plotting/ellipses.py +0 -0
  167. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/plotting/metrics.py +0 -0
  168. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/plotting/tracks.py +0 -0
  169. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/scheduling/__init__.py +0 -0
  170. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/static_estimation/__init__.py +0 -0
  171. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/static_estimation/least_squares.py +0 -0
  172. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/static_estimation/maximum_likelihood.py +0 -0
  173. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/static_estimation/robust.py +0 -0
  174. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/terrain/__init__.py +0 -0
  175. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/terrain/dem.py +0 -0
  176. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/terrain/loaders.py +0 -0
  177. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/terrain/visibility.py +0 -0
  178. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/trackers/__init__.py +0 -0
  179. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/trackers/hypothesis.py +0 -0
  180. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/trackers/mht.py +0 -0
  181. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/trackers/multi_target.py +0 -0
  182. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/trackers/single_target.py +0 -0
  183. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/pytcl/transponders/__init__.py +0 -0
  184. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/setup.cfg +0 -0
  185. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/__init__.py +0 -0
  186. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/conftest.py +0 -0
  187. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_additional_trees.py +0 -0
  188. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_assignment_algorithms.py +0 -0
  189. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_clustering.py +0 -0
  190. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_coverage_boost.py +0 -0
  191. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_coverage_boost_2.py +0 -0
  192. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_dynamic_models.py +0 -0
  193. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_egm.py +0 -0
  194. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_emm.py +0 -0
  195. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_ephemerides.py +0 -0
  196. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_gaussian_mixtures.py +0 -0
  197. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_geophysical.py +0 -0
  198. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_great_circle.py +0 -0
  199. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_ins.py +0 -0
  200. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_ins_gnss.py +0 -0
  201. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_kalman_filters.py +0 -0
  202. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_mathematical_functions.py +0 -0
  203. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_maximum_likelihood.py +0 -0
  204. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_mht.py +0 -0
  205. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_performance_evaluation.py +0 -0
  206. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_phase6_specialized.py +0 -0
  207. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_plotting.py +0 -0
  208. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_projections.py +0 -0
  209. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_relativity.py +0 -0
  210. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_rhumb.py +0 -0
  211. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_signal_processing.py +0 -0
  212. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_smoothers.py +0 -0
  213. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_spatial_containers_parametrized.py +0 -0
  214. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_spatial_structures.py +0 -0
  215. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_special_functions_phase12.py +0 -0
  216. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_static_estimation.py +0 -0
  217. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_terrain.py +0 -0
  218. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_terrain_loaders.py +0 -0
  219. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_tides.py +0 -0
  220. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_trackers.py +0 -0
  221. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_tracking_containers.py +0 -0
  222. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_transforms.py +0 -0
  223. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_v030_comprehensive.py +0 -0
  224. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_v030_features.py +0 -0
  225. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/test_validation.py +0 -0
  226. {nrl_tracker-1.5.0 → nrl_tracker-1.7.0}/tests/unit/test_core.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nrl-tracker
3
- Version: 1.5.0
3
+ Version: 1.7.0
4
4
  Summary: Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms
5
5
  Author: Original: David F. Crouse, Naval Research Laboratory
6
6
  Maintainer: Python Port Contributors
@@ -63,15 +63,16 @@ Requires-Dist: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualizati
63
63
 
64
64
  # Tracker Component Library (Python)
65
65
 
66
- [![PyPI version](https://img.shields.io/badge/pypi-v1.5.0-blue.svg)](https://pypi.org/project/nrl-tracker/)
66
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.7.0-blue.svg)](https://pypi.org/project/nrl-tracker/)
67
67
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
68
68
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
69
69
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
70
- [![Tests](https://img.shields.io/badge/tests-1850%20passing-success.svg)](https://github.com/nedonatelli/TCL)
70
+ [![Tests](https://img.shields.io/badge/tests-1988%20passing-success.svg)](https://github.com/nedonatelli/TCL)
71
+ [![MATLAB Parity](https://img.shields.io/badge/MATLAB%20Parity-100%25-brightgreen.svg)](docs/gap_analysis.rst)
71
72
 
72
73
  A Python port of the [U.S. Naval Research Laboratory's Tracker Component Library](https://github.com/USNavalResearchLaboratory/TrackerComponentLibrary), a comprehensive collection of algorithms for target tracking, estimation, coordinate systems, and related mathematical functions.
73
74
 
74
- **840+ functions** | **148 modules** | **1,850 tests** | **15+ algorithm categories**
75
+ **1,070+ functions** | **153 modules** | **1,988 tests** | **100% MATLAB parity**
75
76
 
76
77
  ## Overview
77
78
 
@@ -79,12 +80,15 @@ The Tracker Component Library provides building blocks for developing target tra
79
80
 
80
81
  - **Coordinate Systems**: Conversions between Cartesian, spherical, geodetic, and other coordinate systems
81
82
  - **Dynamic Models**: State transition matrices for constant velocity, coordinated turn, and other motion models
82
- - **Estimation Algorithms**: Kalman filters (EKF, UKF, etc.), particle filters, and batch estimation
83
- - **Assignment Algorithms**: Hungarian algorithm, auction algorithms, and multi-dimensional assignment
83
+ - **Estimation Algorithms**: Kalman filters (EKF, UKF, CKF, H-infinity), particle filters, smoothers, and batch estimation
84
+ - **Assignment Algorithms**: Hungarian algorithm, auction algorithms, 3D/ND assignment, k-best assignments
85
+ - **Data Association**: Global Nearest Neighbor, JPDA, MHT for multi-target tracking
84
86
  - **Mathematical Functions**: Special functions, statistics, numerical integration, and more
85
- - **Astronomical Code**: Ephemeris calculations, time systems, celestial mechanics
86
- - **Navigation**: Geodetic calculations, INS algorithms, GNSS utilities
87
- - **Geophysical Models**: Gravity, magnetism, atmosphere, and terrain models
87
+ - **Astronomical Code**: SGP4/SDP4 propagation, TLE parsing, special orbits (parabolic/hyperbolic), ephemerides, relativistic corrections
88
+ - **Reference Frames**: GCRF, ITRF, TEME, TOD, MOD with full transformation chains
89
+ - **Navigation**: Geodetic calculations, INS mechanization, GNSS utilities, INS/GNSS integration
90
+ - **Geophysical Models**: Gravity (WGS84, EGM96/2008), magnetism (WMM, IGRF), atmosphere, tides, terrain
91
+ - **Signal Processing**: Digital filters, matched filtering, CFAR detection, transforms (FFT, STFT, wavelets)
88
92
 
89
93
  ## Installation
90
94
 
@@ -1,14 +1,15 @@
1
1
  # Tracker Component Library (Python)
2
2
 
3
- [![PyPI version](https://img.shields.io/badge/pypi-v1.5.0-blue.svg)](https://pypi.org/project/nrl-tracker/)
3
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.7.0-blue.svg)](https://pypi.org/project/nrl-tracker/)
4
4
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
5
5
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
6
6
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
7
- [![Tests](https://img.shields.io/badge/tests-1850%20passing-success.svg)](https://github.com/nedonatelli/TCL)
7
+ [![Tests](https://img.shields.io/badge/tests-1988%20passing-success.svg)](https://github.com/nedonatelli/TCL)
8
+ [![MATLAB Parity](https://img.shields.io/badge/MATLAB%20Parity-100%25-brightgreen.svg)](docs/gap_analysis.rst)
8
9
 
9
10
  A Python port of the [U.S. Naval Research Laboratory's Tracker Component Library](https://github.com/USNavalResearchLaboratory/TrackerComponentLibrary), a comprehensive collection of algorithms for target tracking, estimation, coordinate systems, and related mathematical functions.
10
11
 
11
- **840+ functions** | **148 modules** | **1,850 tests** | **15+ algorithm categories**
12
+ **1,070+ functions** | **153 modules** | **1,988 tests** | **100% MATLAB parity**
12
13
 
13
14
  ## Overview
14
15
 
@@ -16,12 +17,15 @@ The Tracker Component Library provides building blocks for developing target tra
16
17
 
17
18
  - **Coordinate Systems**: Conversions between Cartesian, spherical, geodetic, and other coordinate systems
18
19
  - **Dynamic Models**: State transition matrices for constant velocity, coordinated turn, and other motion models
19
- - **Estimation Algorithms**: Kalman filters (EKF, UKF, etc.), particle filters, and batch estimation
20
- - **Assignment Algorithms**: Hungarian algorithm, auction algorithms, and multi-dimensional assignment
20
+ - **Estimation Algorithms**: Kalman filters (EKF, UKF, CKF, H-infinity), particle filters, smoothers, and batch estimation
21
+ - **Assignment Algorithms**: Hungarian algorithm, auction algorithms, 3D/ND assignment, k-best assignments
22
+ - **Data Association**: Global Nearest Neighbor, JPDA, MHT for multi-target tracking
21
23
  - **Mathematical Functions**: Special functions, statistics, numerical integration, and more
22
- - **Astronomical Code**: Ephemeris calculations, time systems, celestial mechanics
23
- - **Navigation**: Geodetic calculations, INS algorithms, GNSS utilities
24
- - **Geophysical Models**: Gravity, magnetism, atmosphere, and terrain models
24
+ - **Astronomical Code**: SGP4/SDP4 propagation, TLE parsing, special orbits (parabolic/hyperbolic), ephemerides, relativistic corrections
25
+ - **Reference Frames**: GCRF, ITRF, TEME, TOD, MOD with full transformation chains
26
+ - **Navigation**: Geodetic calculations, INS mechanization, GNSS utilities, INS/GNSS integration
27
+ - **Geophysical Models**: Gravity (WGS84, EGM96/2008), magnetism (WMM, IGRF), atmosphere, tides, terrain
28
+ - **Signal Processing**: Digital filters, matched filtering, CFAR detection, transforms (FFT, STFT, wavelets)
25
29
 
26
30
  ## Installation
27
31
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nrl-tracker
3
- Version: 1.5.0
3
+ Version: 1.7.0
4
4
  Summary: Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms
5
5
  Author: Original: David F. Crouse, Naval Research Laboratory
6
6
  Maintainer: Python Port Contributors
@@ -63,15 +63,16 @@ Requires-Dist: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualizati
63
63
 
64
64
  # Tracker Component Library (Python)
65
65
 
66
- [![PyPI version](https://img.shields.io/badge/pypi-v1.5.0-blue.svg)](https://pypi.org/project/nrl-tracker/)
66
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.7.0-blue.svg)](https://pypi.org/project/nrl-tracker/)
67
67
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
68
68
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
69
69
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
70
- [![Tests](https://img.shields.io/badge/tests-1850%20passing-success.svg)](https://github.com/nedonatelli/TCL)
70
+ [![Tests](https://img.shields.io/badge/tests-1988%20passing-success.svg)](https://github.com/nedonatelli/TCL)
71
+ [![MATLAB Parity](https://img.shields.io/badge/MATLAB%20Parity-100%25-brightgreen.svg)](docs/gap_analysis.rst)
71
72
 
72
73
  A Python port of the [U.S. Naval Research Laboratory's Tracker Component Library](https://github.com/USNavalResearchLaboratory/TrackerComponentLibrary), a comprehensive collection of algorithms for target tracking, estimation, coordinate systems, and related mathematical functions.
73
74
 
74
- **840+ functions** | **148 modules** | **1,850 tests** | **15+ algorithm categories**
75
+ **1,070+ functions** | **153 modules** | **1,988 tests** | **100% MATLAB parity**
75
76
 
76
77
  ## Overview
77
78
 
@@ -79,12 +80,15 @@ The Tracker Component Library provides building blocks for developing target tra
79
80
 
80
81
  - **Coordinate Systems**: Conversions between Cartesian, spherical, geodetic, and other coordinate systems
81
82
  - **Dynamic Models**: State transition matrices for constant velocity, coordinated turn, and other motion models
82
- - **Estimation Algorithms**: Kalman filters (EKF, UKF, etc.), particle filters, and batch estimation
83
- - **Assignment Algorithms**: Hungarian algorithm, auction algorithms, and multi-dimensional assignment
83
+ - **Estimation Algorithms**: Kalman filters (EKF, UKF, CKF, H-infinity), particle filters, smoothers, and batch estimation
84
+ - **Assignment Algorithms**: Hungarian algorithm, auction algorithms, 3D/ND assignment, k-best assignments
85
+ - **Data Association**: Global Nearest Neighbor, JPDA, MHT for multi-target tracking
84
86
  - **Mathematical Functions**: Special functions, statistics, numerical integration, and more
85
- - **Astronomical Code**: Ephemeris calculations, time systems, celestial mechanics
86
- - **Navigation**: Geodetic calculations, INS algorithms, GNSS utilities
87
- - **Geophysical Models**: Gravity, magnetism, atmosphere, and terrain models
87
+ - **Astronomical Code**: SGP4/SDP4 propagation, TLE parsing, special orbits (parabolic/hyperbolic), ephemerides, relativistic corrections
88
+ - **Reference Frames**: GCRF, ITRF, TEME, TOD, MOD with full transformation chains
89
+ - **Navigation**: Geodetic calculations, INS mechanization, GNSS utilities, INS/GNSS integration
90
+ - **Geophysical Models**: Gravity (WGS84, EGM96/2008), magnetism (WMM, IGRF), atmosphere, tides, terrain
91
+ - **Signal Processing**: Digital filters, matched filtering, CFAR detection, transforms (FFT, STFT, wavelets)
88
92
 
89
93
  ## Installation
90
94
 
@@ -14,6 +14,8 @@ pytcl/assignment_algorithms/__init__.py
14
14
  pytcl/assignment_algorithms/data_association.py
15
15
  pytcl/assignment_algorithms/gating.py
16
16
  pytcl/assignment_algorithms/jpda.py
17
+ pytcl/assignment_algorithms/nd_assignment.py
18
+ pytcl/assignment_algorithms/network_flow.py
17
19
  pytcl/assignment_algorithms/three_dimensional/__init__.py
18
20
  pytcl/assignment_algorithms/three_dimensional/assignment.py
19
21
  pytcl/assignment_algorithms/two_dimensional/__init__.py
@@ -25,10 +27,14 @@ pytcl/astronomical/lambert.py
25
27
  pytcl/astronomical/orbital_mechanics.py
26
28
  pytcl/astronomical/reference_frames.py
27
29
  pytcl/astronomical/relativity.py
30
+ pytcl/astronomical/sgp4.py
31
+ pytcl/astronomical/special_orbits.py
28
32
  pytcl/astronomical/time_systems.py
33
+ pytcl/astronomical/tle.py
29
34
  pytcl/atmosphere/__init__.py
30
35
  pytcl/atmosphere/ionosphere.py
31
36
  pytcl/atmosphere/models.py
37
+ pytcl/atmosphere/nrlmsise00.py
32
38
  pytcl/clustering/__init__.py
33
39
  pytcl/clustering/dbscan.py
34
40
  pytcl/clustering/gaussian_mixture.py
@@ -58,12 +64,16 @@ pytcl/core/array_utils.py
58
64
  pytcl/core/constants.py
59
65
  pytcl/core/validation.py
60
66
  pytcl/dynamic_estimation/__init__.py
67
+ pytcl/dynamic_estimation/gaussian_sum_filter.py
61
68
  pytcl/dynamic_estimation/imm.py
62
69
  pytcl/dynamic_estimation/information_filter.py
70
+ pytcl/dynamic_estimation/rbpf.py
63
71
  pytcl/dynamic_estimation/smoothers.py
64
72
  pytcl/dynamic_estimation/batch_estimation/__init__.py
65
73
  pytcl/dynamic_estimation/kalman/__init__.py
74
+ pytcl/dynamic_estimation/kalman/constrained.py
66
75
  pytcl/dynamic_estimation/kalman/extended.py
76
+ pytcl/dynamic_estimation/kalman/h_infinity.py
67
77
  pytcl/dynamic_estimation/kalman/linear.py
68
78
  pytcl/dynamic_estimation/kalman/square_root.py
69
79
  pytcl/dynamic_estimation/kalman/sr_ukf.py
@@ -164,6 +174,7 @@ tests/test_additional_trees.py
164
174
  tests/test_assignment_algorithms.py
165
175
  tests/test_astronomical.py
166
176
  tests/test_clustering.py
177
+ tests/test_constrained_ekf.py
167
178
  tests/test_coordinate_systems.py
168
179
  tests/test_coverage_boost.py
169
180
  tests/test_coverage_boost_2.py
@@ -172,29 +183,38 @@ tests/test_egm.py
172
183
  tests/test_emm.py
173
184
  tests/test_ephemerides.py
174
185
  tests/test_gaussian_mixtures.py
186
+ tests/test_gaussian_sum_filter.py
175
187
  tests/test_geophysical.py
176
188
  tests/test_great_circle.py
189
+ tests/test_h_infinity.py
177
190
  tests/test_ins.py
178
191
  tests/test_ins_gnss.py
179
192
  tests/test_kalman_filters.py
180
193
  tests/test_mathematical_functions.py
181
194
  tests/test_maximum_likelihood.py
182
195
  tests/test_mht.py
196
+ tests/test_nd_assignment.py
197
+ tests/test_network_flow.py
198
+ tests/test_nrlmsise00.py
183
199
  tests/test_performance_evaluation.py
184
200
  tests/test_phase6_specialized.py
185
201
  tests/test_plotting.py
186
202
  tests/test_projections.py
203
+ tests/test_rbpf.py
187
204
  tests/test_relativity.py
188
205
  tests/test_rhumb.py
206
+ tests/test_sgp4.py
189
207
  tests/test_signal_processing.py
190
208
  tests/test_smoothers.py
191
209
  tests/test_spatial_containers_parametrized.py
192
210
  tests/test_spatial_structures.py
193
211
  tests/test_special_functions_phase12.py
212
+ tests/test_special_orbits.py
194
213
  tests/test_static_estimation.py
195
214
  tests/test_terrain.py
196
215
  tests/test_terrain_loaders.py
197
216
  tests/test_tides.py
217
+ tests/test_tod_mod.py
198
218
  tests/test_trackers.py
199
219
  tests/test_tracking_containers.py
200
220
  tests/test_transforms.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nrl-tracker"
7
- version = "1.5.0"
7
+ version = "1.7.0"
8
8
  description = "Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -20,7 +20,7 @@ References
20
20
  no. 5, pp. 18-27, May 2017.
21
21
  """
22
22
 
23
- __version__ = "1.5.0"
23
+ __version__ = "1.6.0"
24
24
  __author__ = "Python Port Contributors"
25
25
  __original_author__ = "David F. Crouse, Naval Research Laboratory"
26
26
 
@@ -51,6 +51,21 @@ from pytcl.assignment_algorithms.two_dimensional import (
51
51
  murty,
52
52
  ranked_assignments,
53
53
  )
54
+ from pytcl.assignment_algorithms.nd_assignment import (
55
+ AssignmentNDResult,
56
+ auction_assignment_nd,
57
+ detect_dimension_conflicts,
58
+ greedy_assignment_nd,
59
+ relaxation_assignment_nd,
60
+ validate_cost_tensor,
61
+ )
62
+ from pytcl.assignment_algorithms.network_flow import (
63
+ FlowStatus,
64
+ MinCostFlowResult,
65
+ assignment_to_flow_network,
66
+ min_cost_assignment_via_flow,
67
+ min_cost_flow_successive_shortest_paths,
68
+ )
54
69
 
55
70
  __all__ = [
56
71
  # 2D Assignment
@@ -91,4 +106,17 @@ __all__ = [
91
106
  "jpda_update",
92
107
  "jpda_probabilities",
93
108
  "compute_likelihood_matrix",
109
+ # N-Dimensional Assignment (4D+)
110
+ "AssignmentNDResult",
111
+ "validate_cost_tensor",
112
+ "greedy_assignment_nd",
113
+ "relaxation_assignment_nd",
114
+ "auction_assignment_nd",
115
+ "detect_dimension_conflicts",
116
+ # Network Flow-Based Assignment
117
+ "FlowStatus",
118
+ "MinCostFlowResult",
119
+ "assignment_to_flow_network",
120
+ "min_cost_flow_successive_shortest_paths",
121
+ "min_cost_assignment_via_flow",
94
122
  ]
@@ -0,0 +1,378 @@
1
+ """
2
+ N-dimensional assignment algorithms (4D and higher).
3
+
4
+ This module extends the 3D assignment solver to arbitrary dimensions,
5
+ enabling more complex assignment scenarios such as:
6
+ - 4D: Measurements × Tracks × Hypotheses × Sensors
7
+ - 5D+: Additional dimensions for time frames, maneuver classes, etc.
8
+
9
+ The module provides a unified interface for solving high-dimensional
10
+ assignment problems using generalized relaxation methods.
11
+
12
+ References
13
+ ----------
14
+ .. [1] Poore, A. B., "Multidimensional Assignment Problem and Data
15
+ Association," IEEE Transactions on Aerospace and Electronic Systems,
16
+ 2013.
17
+ .. [2] Cramer, R. D., et al., "The Emerging Role of Chemical Similarity in
18
+ Drug Discovery," Perspectives in Drug Discovery and Design, 2003.
19
+ """
20
+
21
+ from typing import NamedTuple, Optional, Tuple
22
+
23
+ import numpy as np
24
+ from numpy.typing import NDArray
25
+
26
+
27
+ class AssignmentNDResult(NamedTuple):
28
+ """Result of an N-dimensional assignment problem.
29
+
30
+ Attributes
31
+ ----------
32
+ assignments : ndarray
33
+ Array of shape (n_assignments, n_dimensions) containing assigned
34
+ index tuples. Each row is an n-tuple of indices.
35
+ cost : float
36
+ Total assignment cost.
37
+ converged : bool
38
+ Whether the algorithm converged (for iterative methods).
39
+ n_iterations : int
40
+ Number of iterations used (for iterative methods).
41
+ gap : float
42
+ Optimality gap (upper_bound - lower_bound) for relaxation methods.
43
+ """
44
+
45
+ assignments: NDArray[np.intp]
46
+ cost: float
47
+ converged: bool
48
+ n_iterations: int
49
+ gap: float
50
+
51
+
52
+ def validate_cost_tensor(cost_tensor: NDArray[np.float64]) -> Tuple[int, ...]:
53
+ """
54
+ Validate cost tensor and return dimensions.
55
+
56
+ Parameters
57
+ ----------
58
+ cost_tensor : ndarray
59
+ Cost tensor of arbitrary dimension.
60
+
61
+ Returns
62
+ -------
63
+ dims : tuple
64
+ Dimensions of the cost tensor.
65
+
66
+ Raises
67
+ ------
68
+ ValueError
69
+ If tensor has fewer than 2 dimensions.
70
+ """
71
+ if cost_tensor.ndim < 2:
72
+ raise ValueError(
73
+ f"Cost tensor must have at least 2 dimensions, got {cost_tensor.ndim}"
74
+ )
75
+
76
+ return cost_tensor.shape
77
+
78
+
79
+ def greedy_assignment_nd(
80
+ cost_tensor: NDArray[np.float64],
81
+ max_assignments: Optional[int] = None,
82
+ ) -> AssignmentNDResult:
83
+ """
84
+ Greedy solver for N-dimensional assignment.
85
+
86
+ Selects minimum-cost tuples in order until no more valid assignments
87
+ exist (no dimension index is repeated).
88
+
89
+ Parameters
90
+ ----------
91
+ cost_tensor : ndarray
92
+ Cost tensor of shape (n1, n2, ..., nk).
93
+ max_assignments : int, optional
94
+ Maximum number of assignments to find (default: min(dimensions)).
95
+
96
+ Returns
97
+ -------
98
+ AssignmentNDResult
99
+ Assignments, total cost, and algorithm info.
100
+
101
+ Notes
102
+ -----
103
+ Greedy assignment is fast O(n log n) but not optimal. Used as
104
+ heuristic or starting solution for optimization methods.
105
+ """
106
+ dims = cost_tensor.shape
107
+ n_dims = len(dims)
108
+
109
+ if max_assignments is None:
110
+ max_assignments = min(dims)
111
+
112
+ # Flatten tensor with index mapping
113
+ flat_costs = cost_tensor.ravel()
114
+ sorted_indices = np.argsort(flat_costs)
115
+
116
+ assignments: list[tuple[int, ...]] = []
117
+ used_indices: list[set[int]] = [set() for _ in range(n_dims)]
118
+
119
+ for flat_idx in sorted_indices:
120
+ if len(assignments) >= max_assignments:
121
+ break
122
+
123
+ # Convert flat index to multi-dimensional index
124
+ multi_idx = np.unravel_index(flat_idx, dims)
125
+
126
+ # Check if any dimension index is already used
127
+ conflict = False
128
+ for d, idx in enumerate(multi_idx):
129
+ if idx in used_indices[d]:
130
+ conflict = True
131
+ break
132
+
133
+ if not conflict:
134
+ assignments.append(multi_idx)
135
+ for d, idx in enumerate(multi_idx):
136
+ used_indices[d].add(idx)
137
+
138
+ assignments_array = np.array(assignments, dtype=np.intp)
139
+ if assignments_array.size > 0:
140
+ total_cost = float(np.sum(cost_tensor[tuple(assignments_array.T)]))
141
+ else:
142
+ total_cost = 0.0
143
+
144
+ return AssignmentNDResult(
145
+ assignments=assignments_array,
146
+ cost=total_cost,
147
+ converged=True,
148
+ n_iterations=1,
149
+ gap=0.0, # Greedy doesn't compute lower bound
150
+ )
151
+
152
+
153
+ def relaxation_assignment_nd(
154
+ cost_tensor: NDArray[np.float64],
155
+ max_iterations: int = 100,
156
+ tolerance: float = 1e-6,
157
+ verbose: bool = False,
158
+ ) -> AssignmentNDResult:
159
+ """
160
+ Lagrangian relaxation solver for N-dimensional assignment.
161
+
162
+ Uses iterative subgradient optimization on Lagrange multipliers
163
+ to tighten the lower bound and find good solutions.
164
+
165
+ Parameters
166
+ ----------
167
+ cost_tensor : ndarray
168
+ Cost tensor of shape (n1, n2, ..., nk).
169
+ max_iterations : int, optional
170
+ Maximum iterations (default 100).
171
+ tolerance : float, optional
172
+ Convergence tolerance for gap (default 1e-6).
173
+ verbose : bool, optional
174
+ Print iteration info (default False).
175
+
176
+ Returns
177
+ -------
178
+ AssignmentNDResult
179
+ Assignments, total cost, convergence info, and optimality gap.
180
+
181
+ Notes
182
+ -----
183
+ The relaxation approach:
184
+ 1. Maintain Lagrange multipliers for each dimension
185
+ 2. Solve relaxed problem (select best entries per tuple)
186
+ 3. Update multipliers based on constraint violations
187
+ 4. Iterate until convergence or gap tolerance met
188
+
189
+ This guarantees a lower bound on optimal cost and often finds
190
+ near-optimal or optimal solutions.
191
+ """
192
+ dims = cost_tensor.shape
193
+ n_dims = len(dims)
194
+
195
+ # Initialize Lagrange multipliers (one per dimension per index)
196
+ lambdas = [np.zeros(dim) for dim in dims]
197
+
198
+ best_cost = np.inf
199
+ best_assignments = None
200
+ lower_bound = -np.inf
201
+
202
+ for iteration in range(max_iterations):
203
+ # Compute relaxed costs: original - Lagrange penalty
204
+ relaxed_cost = cost_tensor.copy()
205
+ for d in range(n_dims):
206
+ # Reshape lambda[d] to broadcast correctly
207
+ shape = [1] * n_dims
208
+ shape[d] = dims[d]
209
+ relaxed_cost = relaxed_cost - lambdas[d].reshape(shape)
210
+
211
+ # Solve relaxed problem: greedy on relaxed costs
212
+ result_relaxed = greedy_assignment_nd(relaxed_cost)
213
+
214
+ # Compute lower bound from relaxed solution
215
+ lower_bound = (
216
+ result_relaxed.cost
217
+ + sum(np.sum(lambdas[d]) for d in range(n_dims))
218
+ )
219
+
220
+ # Extract solution from relaxed problem
221
+ if len(result_relaxed.assignments) > 0:
222
+ actual_cost = float(np.sum(cost_tensor[tuple(result_relaxed.assignments.T)]))
223
+
224
+ if actual_cost < best_cost:
225
+ best_cost = actual_cost
226
+ best_assignments = result_relaxed.assignments
227
+
228
+ # Compute constraint violations and update multipliers
229
+ violations = [np.zeros(dim) for dim in dims]
230
+
231
+ for assignment in result_relaxed.assignments:
232
+ for d, idx in enumerate(assignment):
233
+ violations[d][idx] += 1
234
+
235
+ # Subgradient descent on multipliers
236
+ step_size = 1.0 / (iteration + 1)
237
+ for d in range(n_dims):
238
+ lambdas[d] -= step_size * (violations[d] - 1.0)
239
+
240
+ # Compute gap
241
+ gap = best_cost - lower_bound if best_cost != np.inf else np.inf
242
+
243
+ if verbose:
244
+ print(
245
+ f"Iter {iteration+1}: LB={lower_bound:.4f}, UB={best_cost:.4f}, "
246
+ f"Gap={gap:.6f}"
247
+ )
248
+
249
+ if gap < tolerance:
250
+ if verbose:
251
+ print(f"Converged at iteration {iteration+1}")
252
+ break
253
+
254
+ if best_assignments is None:
255
+ best_assignments = np.empty((0, n_dims), dtype=np.intp)
256
+ best_cost = 0.0
257
+
258
+ gap = best_cost - lower_bound if best_cost != np.inf else np.inf
259
+
260
+ return AssignmentNDResult(
261
+ assignments=best_assignments,
262
+ cost=best_cost,
263
+ converged=gap < tolerance,
264
+ n_iterations=iteration + 1,
265
+ gap=gap,
266
+ )
267
+
268
+
269
+ def auction_assignment_nd(
270
+ cost_tensor: NDArray[np.float64],
271
+ max_iterations: int = 100,
272
+ epsilon: float = 0.01,
273
+ verbose: bool = False,
274
+ ) -> AssignmentNDResult:
275
+ """
276
+ Auction algorithm for N-dimensional assignment.
277
+
278
+ Inspired by the classical auction algorithm for 2D assignment,
279
+ adapted to higher dimensions. Objects bid for assignments based
280
+ on relative costs.
281
+
282
+ Parameters
283
+ ----------
284
+ cost_tensor : ndarray
285
+ Cost tensor of shape (n1, n2, ..., nk).
286
+ max_iterations : int, optional
287
+ Maximum iterations (default 100).
288
+ epsilon : float, optional
289
+ Bid increment (default 0.01). Larger epsilon → fewer iterations,
290
+ worse solution; smaller epsilon → more iterations, better solution.
291
+ verbose : bool, optional
292
+ Print iteration info (default False).
293
+
294
+ Returns
295
+ -------
296
+ AssignmentNDResult
297
+ Assignments, total cost, convergence info, gap estimate.
298
+
299
+ Notes
300
+ -----
301
+ The algorithm maintains a "price" for each index and allows bidding
302
+ (price adjustment) to maximize value. Converges to epsilon-optimal
303
+ solution in finite iterations.
304
+ """
305
+ dims = cost_tensor.shape
306
+ n_dims = len(dims)
307
+
308
+ # Initialize prices (one per dimension per index)
309
+ prices = [np.zeros(dim) for dim in dims]
310
+
311
+ for iteration in range(max_iterations):
312
+ # Compute profit: cost - price penalty
313
+ profit = cost_tensor.copy()
314
+ for d in range(n_dims):
315
+ shape = [1] * n_dims
316
+ shape[d] = dims[d]
317
+ profit = profit - prices[d].reshape(shape)
318
+
319
+ # Find best assignment at current prices (greedy)
320
+ result = greedy_assignment_nd(profit)
321
+
322
+ if len(result.assignments) == 0:
323
+ break
324
+
325
+ # Update prices: increase price for "in-demand" indices
326
+ demands = [np.zeros(dim) for dim in dims]
327
+ for assignment in result.assignments:
328
+ for d, idx in enumerate(assignment):
329
+ demands[d][idx] += 1
330
+
331
+ for d in range(n_dims):
332
+ prices[d] += epsilon * (demands[d] - 1.0)
333
+
334
+ if verbose and (iteration + 1) % 10 == 0:
335
+ actual_cost = float(np.sum(cost_tensor[tuple(result.assignments.T)]))
336
+ print(f"Iter {iteration+1}: Cost={actual_cost:.4f}")
337
+
338
+ # Final solution
339
+ result = greedy_assignment_nd(cost_tensor)
340
+
341
+ return AssignmentNDResult(
342
+ assignments=result.assignments,
343
+ cost=result.cost,
344
+ converged=True,
345
+ n_iterations=iteration + 1,
346
+ gap=0.0, # Auction algorithm doesn't track gap formally
347
+ )
348
+
349
+
350
+ def detect_dimension_conflicts(
351
+ assignments: NDArray[np.intp],
352
+ dims: Tuple[int, ...],
353
+ ) -> bool:
354
+ """
355
+ Check if assignments violate dimension uniqueness.
356
+
357
+ For valid assignment, each index should appear at most once per dimension.
358
+
359
+ Parameters
360
+ ----------
361
+ assignments : ndarray
362
+ Array of shape (n_assignments, n_dimensions) with assignments.
363
+ dims : tuple
364
+ Dimensions of the cost tensor.
365
+
366
+ Returns
367
+ -------
368
+ has_conflicts : bool
369
+ True if any index appears more than once in any dimension.
370
+ """
371
+ n_dims = len(dims)
372
+
373
+ for d in range(n_dims):
374
+ indices_in_dim = assignments[:, d]
375
+ if len(indices_in_dim) != len(np.unique(indices_in_dim)):
376
+ return True
377
+
378
+ return False