gridstate 2.4.0__tar.gz → 2.4.1__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 (228) hide show
  1. {gridstate-2.4.0 → gridstate-2.4.1}/CHANGELOG.md +22 -0
  2. {gridstate-2.4.0 → gridstate-2.4.1}/PKG-INFO +1 -1
  3. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/_version.py +3 -3
  4. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/ipm_pd.py +48 -8
  5. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/PKG-INFO +1 -1
  6. gridstate-2.4.1/gridstate.egg-info/scm_version.json +8 -0
  7. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ipm_pd.py +66 -1
  8. gridstate-2.4.0/gridstate.egg-info/scm_version.json +0 -8
  9. {gridstate-2.4.0 → gridstate-2.4.1}/.github/workflows/ci.yml +0 -0
  10. {gridstate-2.4.0 → gridstate-2.4.1}/.github/workflows/release.yml +0 -0
  11. {gridstate-2.4.0 → gridstate-2.4.1}/.gitignore +0 -0
  12. {gridstate-2.4.0 → gridstate-2.4.1}/.pre-commit-config.yaml +0 -0
  13. {gridstate-2.4.0 → gridstate-2.4.1}/LICENSE +0 -0
  14. {gridstate-2.4.0 → gridstate-2.4.1}/Makefile +0 -0
  15. {gridstate-2.4.0 → gridstate-2.4.1}/README.md +0 -0
  16. {gridstate-2.4.0 → gridstate-2.4.1}/build_cython.py +0 -0
  17. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/__init__.py +0 -0
  18. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/__pyinstaller/__init__.py +0 -0
  19. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/__pyinstaller/hook-gridstate.py +0 -0
  20. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/_arrays.py +0 -0
  21. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/adapters/__init__.py +0 -0
  22. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/adapters/from_pandapower.py +0 -0
  23. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algebra/__init__.py +0 -0
  24. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algebra/_selinv_kernels.py +0 -0
  25. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algebra/base.py +0 -0
  26. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algebra/estimators.py +0 -0
  27. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algebra/jacobian_pattern.py +0 -0
  28. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algebra/normalized_residuals.py +0 -0
  29. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/__init__.py +0 -0
  30. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/_gram_numba.py +0 -0
  31. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/ipm.py +0 -0
  32. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/kkt_solver.py +0 -0
  33. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/status.py +0 -0
  34. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/algorithms/wls.py +0 -0
  35. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/api.py +0 -0
  36. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/bad_data_repass.py +0 -0
  37. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/bounds.py +0 -0
  38. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/constants.py +0 -0
  39. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/__init__.py +0 -0
  40. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/_legacy.py +0 -0
  41. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/containers.py +0 -0
  42. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/derived.py +0 -0
  43. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/derived_tables.py +0 -0
  44. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/serialize.py +0 -0
  45. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/tables.py +0 -0
  46. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/validate.py +0 -0
  47. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/contract/version.py +0 -0
  48. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/ipm_hints.py +0 -0
  49. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/load_characteristics.py +0 -0
  50. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/losses.py +0 -0
  51. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/measurement_ids.py +0 -0
  52. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/__init__.py +0 -0
  53. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/config.py +0 -0
  54. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/context.py +0 -0
  55. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/manifest.py +0 -0
  56. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/orchestration.py +0 -0
  57. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/passes.py +0 -0
  58. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/preparation.py +0 -0
  59. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/runner.py +0 -0
  60. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/pipeline/steps.py +0 -0
  61. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/post_processing.py +0 -0
  62. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/__init__.py +0 -0
  63. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/_scan.py +0 -0
  64. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/ipm_setup.py +0 -0
  65. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/meas_rows.py +0 -0
  66. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/mirror_voltage.py +0 -0
  67. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/node_props.py +0 -0
  68. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/preprocessing/pseudo_measurements.py +0 -0
  69. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/py.typed +0 -0
  70. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/quality_summary.py +0 -0
  71. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/resolve_pass.py +0 -0
  72. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/result.py +0 -0
  73. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/runtime.py +0 -0
  74. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/shunt_sanity.py +0 -0
  75. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/solution_hints.py +0 -0
  76. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/state.py +0 -0
  77. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/__init__.py +0 -0
  78. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/_filters.py +0 -0
  79. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/apply_resolved.py +0 -0
  80. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/generators.py +0 -0
  81. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/kinds.py +0 -0
  82. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/load_only_injection.py +0 -0
  83. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/loss_filter.py +0 -0
  84. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/measurements.py +0 -0
  85. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/noise.py +0 -0
  86. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/on_line.py +0 -0
  87. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/quality.py +0 -0
  88. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/rpn.py +0 -0
  89. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/shunts.py +0 -0
  90. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/sigma_floor.py +0 -0
  91. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/units.py +0 -0
  92. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/voltage_filter.py +0 -0
  93. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/telemetry/voltage_nominal.py +0 -0
  94. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/topology.py +0 -0
  95. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/units.py +0 -0
  96. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/utils.py +0 -0
  97. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/v_mirror.py +0 -0
  98. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/v_refine.py +0 -0
  99. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/validation/__init__.py +0 -0
  100. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/validation/_diagnostics.py +0 -0
  101. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/validation/bad_data.py +0 -0
  102. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/validation/chi2_test.py +0 -0
  103. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/validation/observability.py +0 -0
  104. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/working.py +0 -0
  105. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/ybus.py +0 -0
  106. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate/z_vector.py +0 -0
  107. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/SOURCES.txt +0 -0
  108. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/dependency_links.txt +0 -0
  109. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/entry_points.txt +0 -0
  110. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/requires.txt +0 -0
  111. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/scm_file_list.json +0 -0
  112. {gridstate-2.4.0 → gridstate-2.4.1}/gridstate.egg-info/top_level.txt +0 -0
  113. {gridstate-2.4.0 → gridstate-2.4.1}/pyproject.toml +0 -0
  114. {gridstate-2.4.0 → gridstate-2.4.1}/setup.cfg +0 -0
  115. {gridstate-2.4.0 → gridstate-2.4.1}/tests/__init__.py +0 -0
  116. {gridstate-2.4.0 → gridstate-2.4.1}/tests/_golden.py +0 -0
  117. {gridstate-2.4.0 → gridstate-2.4.1}/tests/conftest.py +0 -0
  118. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_adapters_lazy_import.py +0 -0
  119. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_aggregate_generators.py +0 -0
  120. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_algebra_base.py +0 -0
  121. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_anti_overshoot.py +0 -0
  122. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_arrays_helpers.py +0 -0
  123. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_bad_data.py +0 -0
  124. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_bad_data_repass.py +0 -0
  125. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_bounds.py +0 -0
  126. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_boxed_balance.py +0 -0
  127. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_breaker_reactance.py +0 -0
  128. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_chain_mirror.py +0 -0
  129. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_contract.py +0 -0
  130. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_contract_edge_cases.py +0 -0
  131. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_contract_runtime.py +0 -0
  132. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case118.json +0 -0
  133. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case118.npz +0 -0
  134. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case118_degraded.json +0 -0
  135. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case118_degraded.npz +0 -0
  136. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case14.json +0 -0
  137. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case14.npz +0 -0
  138. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case14_degraded.json +0 -0
  139. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case14_degraded.npz +0 -0
  140. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case30.json +0 -0
  141. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case30.npz +0 -0
  142. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case30_degraded.json +0 -0
  143. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/case30_degraded.npz +0 -0
  144. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/golden/manifest.json +0 -0
  145. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/ieee/case118.npz +0 -0
  146. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/ieee/case118_truth.npz +0 -0
  147. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/ieee/case14.npz +0 -0
  148. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/ieee/case14_truth.npz +0 -0
  149. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/ieee/case30.npz +0 -0
  150. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_data/ieee/case30_truth.npz +0 -0
  151. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_derived_tables.py +0 -0
  152. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_enum_codes.py +0 -0
  153. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_flow_sigma_floor.py +0 -0
  154. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_from_pandapower.py +0 -0
  155. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_generator_shunt_kernels.py +0 -0
  156. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_golden.py +0 -0
  157. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_gram_numba.py +0 -0
  158. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ieee_cases.py +0 -0
  159. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ipm.py +0 -0
  160. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ipm_balance_modes.py +0 -0
  161. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ipm_hints.py +0 -0
  162. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ipm_injection_roles.py +0 -0
  163. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ipm_integration.py +0 -0
  164. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_jacobian_pattern.py +0 -0
  165. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_kkt_solver.py +0 -0
  166. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_load_characteristic_segments.py +0 -0
  167. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_load_only_injection.py +0 -0
  168. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_losses_breakdown.py +0 -0
  169. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_losses_q_convention.py +0 -0
  170. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_losses_trafo_classification.py +0 -0
  171. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_materialize_kernel.py +0 -0
  172. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_measurement_filter_kernels.py +0 -0
  173. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_measurement_ids.py +0 -0
  174. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_mirror_voltage_kernel.py +0 -0
  175. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_near_critical_ranking.py +0 -0
  176. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_neutral_wording.py +0 -0
  177. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_noise_model.py +0 -0
  178. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_normalized_residuals.py +0 -0
  179. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_numpy_only_runtime.py +0 -0
  180. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_observability.py +0 -0
  181. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_on_line_kernel.py +0 -0
  182. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_perf_synthetic_network.py +0 -0
  183. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline.py +0 -0
  184. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline_config_validation.py +0 -0
  185. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline_idempotent.py +0 -0
  186. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline_invariant_errors.py +0 -0
  187. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline_step_order.py +0 -0
  188. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline_warm_start.py +0 -0
  189. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pipeline_working_layer.py +0 -0
  190. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_post_processing.py +0 -0
  191. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_preparation_steps.py +0 -0
  192. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_prepare_network.py +0 -0
  193. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pseudo_unknown_load.py +0 -0
  194. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_pseudo_v_unobservable.py +0 -0
  195. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_quality_summary_paths.py +0 -0
  196. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_reconcile_balance.py +0 -0
  197. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_refine_merge.py +0 -0
  198. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_resolve_pass.py +0 -0
  199. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_result_quality_summary.py +0 -0
  200. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_rn_selected_inversion.py +0 -0
  201. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_serialize_npz.py +0 -0
  202. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_shunt_sanity.py +0 -0
  203. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_solution_hints.py +0 -0
  204. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_solve_status.py +0 -0
  205. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_state.py +0 -0
  206. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_state_range.py +0 -0
  207. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_telemetry_apply_kernel.py +0 -0
  208. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_telemetry_bounds.py +0 -0
  209. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_telemetry_physics_kernels.py +0 -0
  210. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_tm_code_quality.py +0 -0
  211. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_topology_kernels.py +0 -0
  212. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_topology_port.py +0 -0
  213. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_transformer_from_shunt.py +0 -0
  214. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_units.py +0 -0
  215. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_units_array_kernels.py +0 -0
  216. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_v_mirror.py +0 -0
  217. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_v_refine.py +0 -0
  218. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_variance_charging.py +0 -0
  219. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_version.py +0 -0
  220. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_voltage_calibration_gen_nodes.py +0 -0
  221. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_voltage_range_filter_fallback.py +0 -0
  222. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_wls.py +0 -0
  223. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_wls_robustness.py +0 -0
  224. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_working_container.py +0 -0
  225. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_ybus.py +0 -0
  226. {gridstate-2.4.0 → gridstate-2.4.1}/tests/test_z_vector.py +0 -0
  227. {gridstate-2.4.0 → gridstate-2.4.1}/tools/gen_ieee_fixtures.py +0 -0
  228. {gridstate-2.4.0 → gridstate-2.4.1}/tools/golden.py +0 -0
@@ -9,6 +9,28 @@ types of the merged pull requests; breaking and behavior-changing items are
9
9
  listed separately under "Breaking changes" and "Behavior changes". A release is
10
10
  cut by tagging the merged main commit; the version is derived from that tag.
11
11
 
12
+ ## v2.4.1 (2026-10-18)
13
+
14
+ ### Behavior changes
15
+
16
+ - `ipm_pd`: the proximal term on the box-variable diagonal adapts to the step
17
+ length: ×10 after a step αp < 0.1, up to `box_prox_max` (new, default 1e-2 of
18
+ the median weight), ÷10 after αp ≥ 0.5, down to `box_prox`. It damps the step
19
+ only; the fixed point is unchanged. Estimates on the test models move by
20
+ ≤ 1.6e-8 p.u. V with unchanged iteration counts.
21
+ - `ipm_pd`: a second stopping test, `fit_tol` (new, default 1e-2): the step moves
22
+ no data row by more than that fraction of its sigma (the μ, feasibility and
23
+ equality tests still apply).
24
+
25
+ ### Fix
26
+
27
+ - `ipm_pd` no longer runs into its iteration limit and the primal fallback when
28
+ box variables are seen only through near-zero-weight rows (loads with
29
+ effectively free injections): such directions have barrier curvature only,
30
+ their steps dwarf the box and the boundary rule cut every step to a tiny αp.
31
+ A state the data do not determine no longer keeps the V/δ step test from
32
+ passing (it could move, or cycle, without changing any estimate).
33
+
12
34
  ## v2.4.0 (2026-10-17)
13
35
 
14
36
  ### Behavior changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gridstate
3
- Version: 2.4.0
3
+ Version: 2.4.1
4
4
  Summary: Power system State Estimation: pure-Python WLS/IPM on numpy/scipy, input via a versioned file contract (npz).
5
5
  Author-email: Evgeny Istomin <gena@alpisto.eu>
6
6
  License: MIT
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.4.0'
22
- __version_tuple__ = version_tuple = (2, 4, 0)
21
+ __version__ = version = '2.4.1'
22
+ __version_tuple__ = version_tuple = (2, 4, 1)
23
23
 
24
- __commit_id__ = commit_id = 'g81767e831'
24
+ __commit_id__ = commit_id = 'g640125491'
@@ -50,6 +50,19 @@ corrector's second-order term may spoil descent, and then the centering
50
50
  direction is taken instead (one more solve on the same factor). The dual step
51
51
  keeps its own fraction-to-boundary length.
52
52
 
53
+ Adaptive box regularisation. A box variable seen only through rows of
54
+ negligible weight (a load whose injection row is a near-zero-weight pseudo
55
+ measurement) or through a combination the data do not resolve (a reactive flow
56
+ circulating between two such loads) has no curvature but the barrier's, and
57
+ the Newton step along it is orders of magnitude longer than the box. The
58
+ fraction-to-boundary rule then cuts every step to ``αp ≪ 1``, the
59
+ complementarity stops decreasing and the iteration crawls to its limit. The
60
+ proximal term on the box diagonal is therefore raised tenfold after every
61
+ step shorter than 0.1 (up to ``box_prox_max``) and lowered tenfold after
62
+ every step of 0.5 or longer (down to ``box_prox``). The term damps the step
63
+ only, so the fixed point is unchanged; a well-scaled problem takes long steps
64
+ and keeps the base term.
65
+
53
66
  Start on the central path: ``s`` = half-range of a two-sided constraint (the
54
67
  distance for a one-sided one), ``y = μ0/s``; the initial point need not satisfy
55
68
  ``g − l = s``.
@@ -96,6 +109,14 @@ def _blocking_constraint(
96
109
  return ku, False
97
110
 
98
111
 
112
+ # Adaptive box regularisation (see the module docstring): a primal step shorter
113
+ # than _PROX_SHORT raises the term by _PROX_GROW, one of _PROX_LONG or longer
114
+ # lowers it by the same factor.
115
+ _PROX_SHORT = 0.1
116
+ _PROX_LONG = 0.5
117
+ _PROX_GROW = 10.0
118
+
119
+
99
120
  Direction = tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]
100
121
 
101
122
 
@@ -212,6 +233,7 @@ def solve_ipm_pd(
212
233
  armijo_max: int = 10,
213
234
  max_search_failures: int = 20,
214
235
  step_tol: float = 1e-4,
236
+ fit_tol: float = 1e-2,
215
237
  feas_tol: float = 1e-6,
216
238
  max_iter: int = 100,
217
239
  box_eps: float = 1e-3,
@@ -225,6 +247,7 @@ def solve_ipm_pd(
225
247
  kkt_solver: KKTSolver | None = None,
226
248
  eq_prox: float = 1e-9,
227
249
  box_prox: float = 1e-6,
250
+ box_prox_max: float = 1e-2,
228
251
  ) -> IPMResult:
229
252
  """Mehrotra predictor-corrector IPM (see the module docstring).
230
253
 
@@ -251,6 +274,11 @@ def solve_ipm_pd(
251
274
  outside ``box_idx`` (V/δ) is below it. Box variables may still move
252
275
  along directions the data do not see (the common level of a node's
253
276
  generation and load), which change neither the state nor the residuals.
277
+ fit_tol: alternatively, stop once that step moves no data row by more
278
+ than ``fit_tol`` of its sigma (``max √w·|H·αp·Δx|``). A state the data
279
+ do not determine (a node behind loads whose injection rows carry
280
+ near-zero weight) can keep moving, or cycle, without changing any
281
+ estimated measurement; the fit has converged all the same.
254
282
  feas_tol: admissible primal infeasibility of the inequalities (p.u.).
255
283
  max_iter: iteration limit (one factorization each).
256
284
  box_eps: margin from the bounds when projecting ``x_init``.
@@ -271,6 +299,9 @@ def solve_ipm_pd(
271
299
  has no curvature along that common level but the barrier's, so a
272
300
  cold start produces huge box steps cut to tiny ``αp`` by the boundary
273
301
  rule; the term bounds those steps without moving the fixed point.
302
+ box_prox_max: ceiling of the adaptive box term (same units as
303
+ ``box_prox``, see the module docstring); a value not above
304
+ ``box_prox`` keeps the term fixed.
274
305
 
275
306
  Returns:
276
307
  :class:`~gridstate.algorithms.ipm.IPMResult`; ``status`` is ``"kkt"`` when
@@ -325,10 +356,9 @@ def solve_ipm_pd(
325
356
  is_eq = np.zeros(m, dtype=bool)
326
357
  is_eq[eq_rows] = True
327
358
  rho = w_base[eq_rows]
328
- prox = max(
329
- eq_prox * float(np.max(rho)) if rho.size else 0.0,
330
- box_prox * float(np.median(w_base[~is_eq])) if (~is_eq).any() else 0.0,
331
- )
359
+ eq_prox_abs = eq_prox * float(np.max(rho)) if rho.size else 0.0
360
+ w_median = float(np.median(w_base[~is_eq])) if (~is_eq).any() else 0.0
361
+ box_scale = box_prox
332
362
 
333
363
  huber_mask_arr = (
334
364
  np.asarray(huber_mask, dtype=bool) if huber_mask is not None else np.zeros(m, dtype=bool)
@@ -378,6 +408,7 @@ def solve_ipm_pd(
378
408
  w = w_base
379
409
  mu = mu0 if n_pairs else 0.0
380
410
  step_inf = float("inf")
411
+ fit_inf = float("inf")
381
412
  eq_inf = 0.0
382
413
  grad_inf = float("inf")
383
414
  status = "stalled"
@@ -399,7 +430,7 @@ def solve_ipm_pd(
399
430
  and mu <= mu_min
400
431
  and feas_inf <= feas_tol
401
432
  and bool(np.all(np.abs(c) <= eq_tol_arr))
402
- and step_inf <= step_tol
433
+ and (step_inf <= step_tol or fit_inf <= fit_tol)
403
434
  ):
404
435
  status = "kkt"
405
436
  break
@@ -413,7 +444,7 @@ def solve_ipm_pd(
413
444
  w_mat[eq_rows] = rho
414
445
  w_mat[mb_rows] += d_k[nb:]
415
446
  diag = np.zeros(n)
416
- diag[box_idx] = d_k[:nb] + prox
447
+ diag[box_idx] = d_k[:nb] + max(eq_prox_abs, box_scale * w_median)
417
448
  # Stationarity residual of the current point (for reporting).
418
449
  y_dual = np.zeros(nb + mb_rows.size)
419
450
  y_dual[il] += y_l
@@ -490,7 +521,8 @@ def solve_ipm_pd(
490
521
  il=il,
491
522
  iu=iu,
492
523
  )
493
- slope = merit.slope(lin, H @ dx, ds_l, ds_u)
524
+ hdx = H @ dx
525
+ slope = merit.slope(lin, hdx, ds_l, ds_u)
494
526
  if slope >= 0.0 and n_pairs:
495
527
  # The corrector's second-order term can spoil descent; the pure
496
528
  # centering direction is a Newton step on the merit and descends
@@ -498,9 +530,11 @@ def solve_ipm_pd(
498
530
  dx_c, ds_l_c, ds_u_c, dy_l_c, dy_u_c, dlam_c = lin.direction(
499
531
  target - s_l * y_l, target - s_u * y_u
500
532
  )
501
- slope_c = merit.slope(lin, H @ dx_c, ds_l_c, ds_u_c)
533
+ hdx_c = H @ dx_c
534
+ slope_c = merit.slope(lin, hdx_c, ds_l_c, ds_u_c)
502
535
  if slope_c < 0.0 and np.all(np.isfinite(dx_c)):
503
536
  dx, ds_l, ds_u, dy_l, dy_u, dlam = dx_c, ds_l_c, ds_u_c, dy_l_c, dy_u_c, dlam_c
537
+ hdx = hdx_c
504
538
  slope = slope_c
505
539
  n_centering += 1
506
540
 
@@ -521,6 +555,7 @@ def solve_ipm_pd(
521
555
  a_p = tr_radius / free_inf
522
556
  # The stopping test measures the Newton step, not how far the search cut it.
523
557
  step_inf = a_p * free_inf
558
+ fit_inf = a_p * float(np.max(np.sqrt(w_data) * np.abs(hdx))) if m else 0.0
524
559
  a_full = a_p
525
560
  r_new = None
526
561
  # A direction that does not descend (inconsistent slacks of a nonlinear
@@ -563,6 +598,11 @@ def solve_ipm_pd(
563
598
  eq_inf,
564
599
  feas_inf,
565
600
  )
601
+ if box_prox_max > box_prox:
602
+ if a_p < _PROX_SHORT:
603
+ box_scale = min(box_scale * _PROX_GROW, box_prox_max)
604
+ elif a_p >= _PROX_LONG:
605
+ box_scale = max(box_scale / _PROX_GROW, box_prox)
566
606
  x = x + a_p * dx
567
607
  s_l = s_l + a_p * ds_l
568
608
  s_u = s_u + a_p * ds_u
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gridstate
3
- Version: 2.4.0
3
+ Version: 2.4.1
4
4
  Summary: Power system State Estimation: pure-Python WLS/IPM on numpy/scipy, input via a versioned file contract (npz).
5
5
  Author-email: Evgeny Istomin <gena@alpisto.eu>
6
6
  License: MIT
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.4.1",
3
+ "distance": 0,
4
+ "node": "g640125491ba6b35d3beb20b4fd33688f9cceb117",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-18"
8
+ }
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from types import SimpleNamespace
6
+ from typing import Any
6
7
 
7
8
  import numpy as np
8
9
  import pytest
@@ -148,6 +149,68 @@ def test_equality_rows_with_a_box_free_common_level() -> None:
148
149
  assert out.x[1] - out.x[2] == pytest.approx(0.7, abs=1e-5)
149
150
 
150
151
 
152
+ def test_pd_adaptive_box_prox_keeps_the_fixed_point(monkeypatch: pytest.MonkeyPatch) -> None:
153
+ # Every step counts as short, so the box term climbs to its ceiling and stays
154
+ # there: the iteration is damped, the solution is not. Rows 1-2 see the box
155
+ # variables (g, l) only through near-zero weights, as a free load does.
156
+ import gridstate.algorithms.ipm_pd as pd_mod
157
+
158
+ A = np.array([[1.0, 0.0, 0.0], [1.0, -1.0, 1.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0]])
159
+ z = np.array([0.7, 0.0, 3.0, 0.75])
160
+ w = np.array([1.0, 1e-8, 1e-8, 1.0])
161
+ res, jac = _linear(A, z)
162
+ kw: dict[str, Any] = {
163
+ "box_idx": np.array([1, 2]),
164
+ "box_lo": np.array([-50.0, -50.0]),
165
+ "box_hi": np.array([50.0, 50.0]),
166
+ "step_tol": 1e-9,
167
+ "max_iter": 300,
168
+ }
169
+ fixed = solve_ipm_pd(np.zeros(3), res, jac, w, box_prox_max=0.0, **kw)
170
+ monkeypatch.setattr(pd_mod, "_PROX_SHORT", 2.0)
171
+ damped = solve_ipm_pd(np.zeros(3), res, jac, w, box_prox_max=1.0, **kw)
172
+ assert fixed.success and damped.success
173
+ assert damped.x[0] == pytest.approx(0.725, abs=1e-6)
174
+ np.testing.assert_allclose(damped.x[0], fixed.x[0], atol=1e-6)
175
+
176
+
177
+ def test_pd_adaptive_box_prox_is_inactive_on_long_steps() -> None:
178
+ # A well-scaled problem takes long steps: the ceiling never comes into play.
179
+ rng = np.random.default_rng(4)
180
+ A = rng.normal(size=(8, 3))
181
+ z = rng.normal(size=8)
182
+ res, jac = _linear(A, z)
183
+ kw: dict[str, Any] = {
184
+ "box_idx": np.array([2]),
185
+ "box_lo": np.array([-5.0]),
186
+ "box_hi": np.array([5.0]),
187
+ }
188
+ base = solve_ipm_pd(np.zeros(3), res, jac, np.ones(8), box_prox_max=0.0, **kw)
189
+ adaptive = solve_ipm_pd(np.zeros(3), res, jac, np.ones(8), **kw)
190
+ assert base.iterations_outer == adaptive.iterations_outer
191
+ np.testing.assert_array_equal(base.x, adaptive.x)
192
+
193
+
194
+ def test_pd_fit_tol_stops_once_the_estimates_settle() -> None:
195
+ # x1 enters only a row of negligible weight: once the measured x0 has
196
+ # settled, the remaining steps move x1 alone and no estimate noticeably.
197
+ z = np.array([1.0, 1.2, 3.0])
198
+ w = np.array([1.0, 1.0, 1e-12])
199
+
200
+ def residual_fn(x: np.ndarray) -> np.ndarray:
201
+ return z - np.array([x[0], x[0], np.sinh(x[1])])
202
+
203
+ def jacobian_fn(x: np.ndarray) -> csr_matrix:
204
+ return csr_matrix(np.array([[1.0, 0.0], [1.0, 0.0], [0.0, np.cosh(x[1])]]))
205
+
206
+ kw: dict[str, Any] = {"step_tol": 1e-12, "max_iter": 60}
207
+ by_fit = solve_ipm_pd(np.zeros(2), residual_fn, jacobian_fn, w, **kw)
208
+ by_step = solve_ipm_pd(np.zeros(2), residual_fn, jacobian_fn, w, fit_tol=0.0, **kw)
209
+ assert by_fit.success and by_step.success
210
+ assert by_fit.iterations_outer < by_step.iterations_outer
211
+ assert by_fit.x[0] == pytest.approx(1.1, abs=1e-9)
212
+
213
+
151
214
  def test_pd_merit_search_stops_gauss_newton_overshoot() -> None:
152
215
  # h = atan(x), z = 0 from x0 = 1.5: the Gauss-Newton step −(1 + x²)·atan(x)
153
216
  # overshoots and the full-step iteration diverges; the merit search does not.
@@ -157,7 +220,9 @@ def test_pd_merit_search_stops_gauss_newton_overshoot() -> None:
157
220
  def jacobian_fn(x: np.ndarray) -> csr_matrix:
158
221
  return csr_matrix(np.array([[1.0 / (1.0 + x[0] ** 2)]]))
159
222
 
160
- kw = {"tr_radius": 1e6, "step_tol": 1e-10, "max_iter": 50}
223
+ # fit_tol off: far out on the plateau of atan a diverging step barely moves
224
+ # the estimate, and this test is about the search, not the stopping rule.
225
+ kw = {"tr_radius": 1e6, "step_tol": 1e-10, "fit_tol": 0.0, "max_iter": 50}
161
226
  no_search = solve_ipm_pd(
162
227
  np.array([1.5]), residual_fn, jacobian_fn, np.ones(1), armijo_max=0, **kw
163
228
  )
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "2.4.0",
3
- "distance": 0,
4
- "node": "g81767e831d3e3cddd3b312090767b2568d2c26bd",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-10-17"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes