PyAntiGen 2.1.5__tar.gz → 2.1.6__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 (112) hide show
  1. {pyantigen-2.1.5 → pyantigen-2.1.6}/PKG-INFO +1 -1
  2. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/PKG-INFO +1 -1
  3. pyantigen-2.1.6/PyAntiGen.egg-info/scm_version.json +8 -0
  4. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/_version.py +3 -3
  5. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Optimize.py +5 -0
  6. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Simulate.py +51 -5
  7. pyantigen-2.1.5/PyAntiGen.egg-info/scm_version.json +0 -8
  8. {pyantigen-2.1.5 → pyantigen-2.1.6}/.github/workflows/publish.yml +0 -0
  9. {pyantigen-2.1.5 → pyantigen-2.1.6}/.github/workflows/tests.yml +0 -0
  10. {pyantigen-2.1.5 → pyantigen-2.1.6}/.gitignore +0 -0
  11. {pyantigen-2.1.5 → pyantigen-2.1.6}/.vscode/launch.json +0 -0
  12. {pyantigen-2.1.5 → pyantigen-2.1.6}/LICENSE +0 -0
  13. {pyantigen-2.1.5 → pyantigen-2.1.6}/MANIFEST.in +0 -0
  14. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/SOURCES.txt +0 -0
  15. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/dependency_links.txt +0 -0
  16. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/entry_points.txt +0 -0
  17. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/requires.txt +0 -0
  18. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/scm_file_list.json +0 -0
  19. {pyantigen-2.1.5 → pyantigen-2.1.6}/PyAntiGen.egg-info/top_level.txt +0 -0
  20. {pyantigen-2.1.5 → pyantigen-2.1.6}/README.md +0 -0
  21. {pyantigen-2.1.5 → pyantigen-2.1.6}/docs/ANALYTIC_GRADIENT.md +0 -0
  22. {pyantigen-2.1.5 → pyantigen-2.1.6}/docs/MULTISTART.md +0 -0
  23. {pyantigen-2.1.5 → pyantigen-2.1.6}/docs/PROTOCOL_LAYER.md +0 -0
  24. {pyantigen-2.1.5 → pyantigen-2.1.6}/docs/V2_DESIGN.md +0 -0
  25. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/.agents/skills/module_generation/SKILL.md +0 -0
  26. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/.agents/skills/ode_conversion_antimony/SKILL.md +0 -0
  27. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/.agents/skills/ode_extraction_pipeline/SKILL.md +0 -0
  28. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/.gitignore +0 -0
  29. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/__init__.py +0 -0
  30. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/cli.py +0 -0
  31. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Analytic_gradient.py +0 -0
  32. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Anchor_cache.py +0 -0
  33. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Deadline.py +0 -0
  34. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Differential_evolution.py +0 -0
  35. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Evaluator.py +0 -0
  36. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Event_times.py +0 -0
  37. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Fast_profile.py +0 -0
  38. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Fit_cache.py +0 -0
  39. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Identifiability.py +0 -0
  40. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Model_cache.py +0 -0
  41. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Model_optimize.py +0 -0
  42. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Model_simulate.py +0 -0
  43. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Multistart.py +0 -0
  44. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Nelder_mead.py +0 -0
  45. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Noise_floor.py +0 -0
  46. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Petab_export.py +0 -0
  47. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Preequil_cache.py +0 -0
  48. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Profile_checkpoint.py +0 -0
  49. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Profile_plan.py +0 -0
  50. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/README.md +0 -0
  51. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Results.py +0 -0
  52. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Scaled_amici.py +0 -0
  53. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Segmented.py +0 -0
  54. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Sensitivity_analysis.py +0 -0
  55. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/Stop_rules.py +0 -0
  56. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/engine/__init__.py +0 -0
  57. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/AntimonyGen.py +0 -0
  58. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/RxnDict_to_antimony.py +0 -0
  59. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/TelluriumGen.py +0 -0
  60. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/__init__.py +0 -0
  61. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/antimony_utils.py +0 -0
  62. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/data_interpolation.py +0 -0
  63. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/input_schedule.py +0 -0
  64. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/isotopomer_tools.py +0 -0
  65. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/model_generation.py +0 -0
  66. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/models.py +0 -0
  67. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/module_base.py +0 -0
  68. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/pyantigen.py +0 -0
  69. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/rate_laws.py +0 -0
  70. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/reaction_creation.py +0 -0
  71. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/generate/scaled_time.py +0 -0
  72. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/__init__.py +0 -0
  73. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/assay.py +0 -0
  74. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/describe.py +0 -0
  75. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/design.py +0 -0
  76. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/lower_v1.py +0 -0
  77. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/optimization.py +0 -0
  78. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/params.py +0 -0
  79. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/quantity.py +0 -0
  80. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/reagent.py +0 -0
  81. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/refs.py +0 -0
  82. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/remarks.py +0 -0
  83. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/serialize.py +0 -0
  84. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/study/validate.py +0 -0
  85. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/AntiGen_paths.py +0 -0
  86. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Flipflop_reference.py +0 -0
  87. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Model_generate.py +0 -0
  88. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Model_run.py +0 -0
  89. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Data.py +0 -0
  90. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Events.py +0 -0
  91. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Experiment.py +0 -0
  92. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Loss_config.py +0 -0
  93. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Observed_species.py +0 -0
  94. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Optimizer_settings.py +0 -0
  95. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Plots.py +0 -0
  96. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Solver_settings.py +0 -0
  97. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Update_opt_parameters.py +0 -0
  98. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/Modules/Update_parameters.py +0 -0
  99. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/optimizations/Example1_ADneg.json +0 -0
  100. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/optimizations/Example1_ADpos.json +0 -0
  101. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/optimizations/Example3_joint.json +0 -0
  102. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/optimizations/Example4_flipflop.json +0 -0
  103. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/optimizations/example.py +0 -0
  104. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/studies/example.json +0 -0
  105. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/studies/example.py +0 -0
  106. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/Example/studies/flipflop.json +0 -0
  107. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/data/ADneg.csv +0 -0
  108. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/data/ADpos.csv +0 -0
  109. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/data/Flipflop.csv +0 -0
  110. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyantigen/template/data/make_flipflop_data.py +0 -0
  111. {pyantigen-2.1.5 → pyantigen-2.1.6}/pyproject.toml +0 -0
  112. {pyantigen-2.1.5 → pyantigen-2.1.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAntiGen
3
- Version: 2.1.5
3
+ Version: 2.1.6
4
4
  Summary: Declarative generation, simulation and identifiability analysis of compartmental Antimony/SBML models
5
5
  Author-email: Don Elbert <elbert5770@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAntiGen
3
- Version: 2.1.5
3
+ Version: 2.1.6
4
4
  Summary: Declarative generation, simulation and identifiability analysis of compartmental Antimony/SBML models
5
5
  Author-email: Don Elbert <elbert5770@gmail.com>
6
6
  License-Expression: MIT
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.1.6",
3
+ "distance": 0,
4
+ "node": "g9171689079d2fc724733c9b7be5620f998df09cf",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-19"
8
+ }
@@ -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.1.5'
22
- __version_tuple__ = version_tuple = (2, 1, 5)
21
+ __version__ = version = '2.1.6'
22
+ __version_tuple__ = version_tuple = (2, 1, 6)
23
23
 
24
- __commit_id__ = commit_id = 'g244c235d3'
24
+ __commit_id__ = commit_id = 'g917168907'
@@ -8279,6 +8279,11 @@ def predict_concentrations(params, observable_data, model, param_names, observab
8279
8279
  model.setIntegrator('cvode')
8280
8280
  model.integrator.absolute_tolerance = 1e-8
8281
8281
  _model_cache.put(model, "_scalar_abs_tol", 1e-8)
8282
+ # This helper takes no solver settings, so it cannot ask for pinning.
8283
+ # Drop any policy an earlier configure_integrator left on the model, or
8284
+ # its reference scale -- taken for a different parameter vector -- would
8285
+ # keep pinning here.
8286
+ _model_cache.put(model, "_tolerance_policy", None)
8282
8287
  model.integrator.relative_tolerance = 1e-8
8283
8288
  model.integrator.setValue('stiff', True)
8284
8289
  model.integrator.variable_step_size = True
@@ -288,10 +288,19 @@ TOLERANCE_CAP_RATIO = None
288
288
 
289
289
 
290
290
  def tolerance_policy(solver_settings):
291
- """``{"pin": bool, "cap_ratio": float | None}`` from *solver_settings*."""
292
- pin = bool(solver_settings.get("tolerance_pinning", TOLERANCE_PINNING))
291
+ """``{"pin": bool, "cap_ratio": float | None}`` from *solver_settings*.
292
+
293
+ ``tolerance_pinning`` must be a real bool: ``bool("false")`` is True, so a
294
+ string from a config file would switch pinning on while reading as off.
295
+ """
296
+ pin = solver_settings.get("tolerance_pinning", TOLERANCE_PINNING)
297
+ if not isinstance(pin, (bool, np.bool_)):
298
+ raise TypeError(f"tolerance_pinning must be True or False, got {pin!r}")
299
+ pin = bool(pin)
293
300
  cap = solver_settings.get("tolerance_cap_ratio", TOLERANCE_CAP_RATIO)
294
301
  if cap is not None:
302
+ if isinstance(cap, (bool, np.bool_, str)):
303
+ raise TypeError(f"tolerance_cap_ratio must be a number, got {cap!r}")
295
304
  cap = float(cap)
296
305
  if not cap > 0:
297
306
  raise ValueError(f"tolerance_cap_ratio must be positive, got {cap}")
@@ -313,20 +322,30 @@ def _remember_tolerance_policy(r, solver_settings, scalar):
313
322
  if not policy["pin"]:
314
323
  _model_cache.put(r, "_tolerance_policy", None)
315
324
  return
325
+ # The model clock is the test for "still at the initial state": reset() and
326
+ # resetAll() return it to exactly 0.0 whatever was simulated before (a model
327
+ # has no other start time), and save/restore_model_state carry 'time' with
328
+ # the amounts, so a restored state brings its clock back with it. A clock
329
+ # that is not 0 means the model has been integrated, whatever its start.
316
330
  try:
317
331
  at_start = float(r.getCurrentTime()) == 0.0
318
332
  except Exception:
319
333
  at_start = False
320
334
  if at_start:
335
+ # At the initial time the reference is re-derived every time, and a
336
+ # failure to do so drops the old one: it belongs to an earlier parameter
337
+ # vector, and pinning to it would silently use the wrong scales. (Away
338
+ # from t=0 the stored reference is kept on purpose -- see above.)
339
+ reference = None
321
340
  try:
322
341
  vec = np.asarray(r.integrator.getAbsoluteToleranceVector(), float)
323
342
  ids = state_vector_ids(r)
324
343
  n = min(len(ids), len(vec))
325
344
  if float(scalar) > 0 and n:
326
- _model_cache.put(r, "_atol_reference",
327
- (list(ids[:n]), vec[:n] / float(scalar)))
345
+ reference = (list(ids[:n]), vec[:n] / float(scalar))
328
346
  except Exception:
329
347
  pass
348
+ _model_cache.put(r, "_atol_reference", reference)
330
349
  if _model_cache.get(r, "_atol_reference") is None:
331
350
  # Never saw the initial state, so there is no initial scale to pin to.
332
351
  import warnings
@@ -359,6 +378,8 @@ def apply_tolerance_vector(r, scalar=None, floor=_MIN_ABSOLUTE_TOLERANCE):
359
378
  try:
360
379
  current = np.asarray(r.integrator.getAbsoluteToleranceVector(), float)
361
380
  except Exception:
381
+ # A vector that cannot be read cannot be floored either (the floor reads
382
+ # it first), so there is nothing to fall back to.
362
383
  return 0
363
384
  if len(current) < len(ids):
364
385
  return floor_tolerance_vector(r, floor)
@@ -368,12 +389,22 @@ def apply_tolerance_vector(r, scalar=None, floor=_MIN_ABSOLUTE_TOLERANCE):
368
389
  want = np.minimum(want, policy["cap_ratio"] * scalar)
369
390
  want = np.maximum(want, floor)
370
391
  n = 0
392
+ failed = []
371
393
  for i in np.flatnonzero(~np.isclose(current[:len(ids)], want, rtol=1e-9, atol=0.0)):
372
394
  try:
373
395
  r.integrator.setIndividualTolerance(ids[i], float(want[i]))
374
396
  n += 1
375
397
  except Exception:
376
- pass
398
+ failed.append(ids[i])
399
+ if failed and not _model_cache.get(r, "_tolerance_set_warned"):
400
+ # Once per model: a state left at its drifted tolerance is what pinning
401
+ # exists to prevent, so it must not be silent, but this runs before
402
+ # every block and would otherwise repeat for the whole fit.
403
+ import warnings
404
+ _model_cache.put(r, "_tolerance_set_warned", True)
405
+ warnings.warn(f"tolerance_pinning could not set the absolute tolerance of "
406
+ f"{len(failed)} state(s) (first: {failed[0]!r}); they keep "
407
+ f"RoadRunner's derived value", RuntimeWarning, stacklevel=2)
377
408
  return n
378
409
 
379
410
 
@@ -728,6 +759,15 @@ def safe_simulate(r, solver_settings, observed_species, depth=0, label=None):
728
759
  # corrupted/advanced state that cannot be reverted without this snapshot.
729
760
  saved_state = save_model_state(r)
730
761
 
762
+ # A sub-call of a subdivision begins wherever the previous one left the
763
+ # vector: re-derived from the decayed state after a restore, or loosened by
764
+ # a ladder. The top-level call is pinned by its caller (_run_blocks,
765
+ # SegmentRunner); the halves are not, so pin them here, from the configured
766
+ # scalar. Each half then tries the configured accuracy and runs its own
767
+ # ladder if that fails.
768
+ if depth > 0:
769
+ apply_tolerance_vector(r)
770
+
731
771
  # Fast path: try once with whatever settings the model already has.
732
772
  try:
733
773
  res = _run(r, start, end, points, times, observed_species)
@@ -814,6 +854,7 @@ def safe_simulate(r, solver_settings, observed_species, depth=0, label=None):
814
854
 
815
855
  # Restore original integrator settings on success
816
856
  r.integrator.absolute_tolerance = orig_abs_tol
857
+ apply_tolerance_vector(r, scalar=orig_abs_tol)
817
858
  r.integrator.relative_tolerance = orig_rel_tol
818
859
  r.integrator.maximum_num_steps = orig_max_steps
819
860
  try:
@@ -892,6 +933,7 @@ def safe_simulate(r, solver_settings, observed_species, depth=0, label=None):
892
933
 
893
934
  # Restore original integrator settings before returning
894
935
  r.integrator.absolute_tolerance = orig_abs_tol
936
+ apply_tolerance_vector(r, scalar=orig_abs_tol)
895
937
  r.integrator.relative_tolerance = orig_rel_tol
896
938
  r.integrator.maximum_num_steps = orig_max_steps
897
939
  try:
@@ -910,6 +952,7 @@ def safe_simulate(r, solver_settings, observed_species, depth=0, label=None):
910
952
 
911
953
  # If all else fails, restore original settings and raise exception
912
954
  r.integrator.absolute_tolerance = orig_abs_tol
955
+ apply_tolerance_vector(r, scalar=orig_abs_tol)
913
956
  r.integrator.relative_tolerance = orig_rel_tol
914
957
  r.integrator.maximum_num_steps = orig_max_steps
915
958
  try:
@@ -941,6 +984,9 @@ def configure_integrator(r, solver_settings):
941
984
  Mutates *solver_settings* with the defaults, as the original inline version
942
985
  did, so callers that read the values back afterwards still see them.
943
986
  """
987
+ # Before anything is touched: a bad pinning setting is a configuration
988
+ # error, and should not leave the integrator half set up.
989
+ tolerance_policy(solver_settings)
944
990
  solver_settings["integrator"] = solver_settings.get("integrator", "cvode")
945
991
  solver_settings["absolute_tolerance"] = solver_settings.get("absolute_tolerance", 1e-8)
946
992
  solver_settings["relative_tolerance"] = solver_settings.get("relative_tolerance", 1e-8)
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "2.1.5",
3
- "distance": 0,
4
- "node": "g244c235d347fa7cf25440401efc2e02f1a6955e2",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-10-15"
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