sunnbear 0.2.2__tar.gz → 0.2.3__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.
- {sunnbear-0.2.2 → sunnbear-0.2.3}/.gitignore +0 -3
- {sunnbear-0.2.2 → sunnbear-0.2.3}/PKG-INFO +22 -12
- {sunnbear-0.2.2 → sunnbear-0.2.3}/pyproject.toml +33 -26
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/protocol/correctness.py +7 -4
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/state.py +3 -5
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/brent/solver.py +6 -10
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/illinois/state.py +3 -2
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/itp/solver.py +7 -5
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/modab/solver.py +10 -10
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/pegasus/state.py +3 -5
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/toms748/solver.py +5 -9
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/interval.py +3 -3
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/solver.py +5 -5
- sunnbear-0.2.3/src/sunnbear/_core/utils/floats.py +7 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/LICENSE +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/archiver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/builtin/mc_tuples/manifest.json +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/builtin/mc_tuples/mc_tuples.csv +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/data_release_client.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/declaration.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/exceptions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/listing.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/manifest.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/registry.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/source.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/store.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/aggregation/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/aggregation/derived_results.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/aggregation/summary.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/artifact.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_allocation.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_correction.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_population.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_result.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_solve.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/exceptions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/sizes.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/tuples.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/protocol/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/protocol/seeds.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/protocol/tolerances.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/exceptions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/results_schema.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/run_dir.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/run_info.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/run_settings.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/runner.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/task.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/runner/worker_pool.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/exceptions/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/exceptions/base.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c01_existing_benchmark_suites/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c02_standard_function_families/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c02_standard_function_families/c01_polynomials/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c02_standard_function_families/c01_polynomials/f01_cubic.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c02_standard_function_families/c01_polynomials/f02_odd_power.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c03_purpose_built_functions/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/catalog/c99_user_defined_functions/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/category.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/exceptions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/formula.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/identity.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/param_values.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/recipes.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/registry.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/taxonomy.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/test_cases.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/test_function.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/functions/core/types.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/bisection/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/bisection/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/bisection/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/brent/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/brent/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/carf/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/carf/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/carf/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/chandrupatla/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/chandrupatla/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/chandrupatla/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/illinois/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/illinois/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/illinois/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/itp/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/itp/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/itp/state.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/itp/variant.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/modab/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/modab/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/pegasus/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/pegasus/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/pegasus/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/regula_falsi/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/regula_falsi/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/regula_falsi/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/ridders/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/ridders/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/ridders/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/ridders/variant.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/steffen_brent/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/steffen_brent/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/steffen_brent/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/toms748/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/toms748/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/config.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/exceptions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/registry.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/result.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/role.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/state.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/core/wrapped_function.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/open/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/open/secant/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/open/secant/configs.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/open/secant/solver.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/stats/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/stats/pairwise_l1.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/stats/pseudo_quantiles/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/stats/pseudo_quantiles/geometric_pseudo_quantile.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/stats/pseudo_quantiles/ordered_weighted_geomean.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/utils/__init__.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/utils/class_origin.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/utils/grouping.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/utils/mapping_comparison.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/utils/slugify.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/benchmark.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/data.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/exceptions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/functions.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/py.typed +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/solvers.py +0 -0
- {sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/stats.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sunnbear
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Under construction.
|
|
5
5
|
Project-URL: Source, https://github.com/bertpl/sunnbear
|
|
6
6
|
Project-URL: ChangeLog, https://github.com/bertpl/sunnbear/blob/main/CHANGELOG.md
|
|
@@ -16,34 +16,44 @@ Classifier: Operating System :: OS Independent
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
20
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
20
21
|
Classifier: Typing :: Typed
|
|
21
22
|
Requires-Python: >=3.12
|
|
22
23
|
Requires-Dist: backports-zstd>=1.0.0; python_version < '3.14'
|
|
23
|
-
Requires-Dist: counted-float>=1.2.1
|
|
24
|
+
Requires-Dist: counted-float>=1.2.1; python_version < '3.15'
|
|
25
|
+
Requires-Dist: counted-float>=2.6.0; python_version >= '3.15'
|
|
24
26
|
Requires-Dist: matplotlib>=3.10.7; python_version == '3.12'
|
|
25
27
|
Requires-Dist: matplotlib>=3.10.7; python_version == '3.13'
|
|
26
|
-
Requires-Dist: matplotlib>=3.10.7; python_version
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: matplotlib>=3.10.7; python_version == '3.14'
|
|
29
|
+
Requires-Dist: matplotlib>=3.11.2; python_version >= '3.15'
|
|
30
|
+
Requires-Dist: max-div>=0.21.1; python_version < '3.15'
|
|
31
|
+
Requires-Dist: max-div>=0.21.3; python_version >= '3.15'
|
|
32
|
+
Requires-Dist: mpl-composite>=0.1.2; python_version < '3.15'
|
|
33
|
+
Requires-Dist: mpl-composite>=0.1.4; python_version >= '3.15'
|
|
29
34
|
Requires-Dist: numba>=0.60.0; python_version == '3.12'
|
|
30
35
|
Requires-Dist: numba>=0.66.0; python_version == '3.13'
|
|
31
|
-
Requires-Dist: numba>=0.66.0; python_version
|
|
36
|
+
Requires-Dist: numba>=0.66.0; python_version == '3.14'
|
|
37
|
+
Requires-Dist: numba>=0.68.0; python_version >= '3.15'
|
|
32
38
|
Requires-Dist: numpy>=2.0.0; python_version == '3.12'
|
|
33
39
|
Requires-Dist: numpy>=2.1.0; python_version == '3.13'
|
|
34
|
-
Requires-Dist: numpy>=2.3.2; python_version
|
|
40
|
+
Requires-Dist: numpy>=2.3.2; python_version == '3.14'
|
|
41
|
+
Requires-Dist: numpy>=2.5.2; python_version >= '3.15'
|
|
35
42
|
Requires-Dist: platformdirs>=4.0
|
|
36
|
-
Requires-Dist: polars>=1.0.0
|
|
37
|
-
Requires-Dist:
|
|
43
|
+
Requires-Dist: polars>=1.0.0; python_version < '3.15'
|
|
44
|
+
Requires-Dist: polars>=2.0.0; python_version >= '3.15'
|
|
45
|
+
Requires-Dist: pydantic>=2.12; python_version == '3.14'
|
|
46
|
+
Requires-Dist: pydantic>=2.14; python_version >= '3.15'
|
|
38
47
|
Requires-Dist: pydantic>=2.7; python_version == '3.12'
|
|
39
48
|
Requires-Dist: pydantic>=2.9; python_version == '3.13'
|
|
40
|
-
Requires-Dist: snuffled>=0.1.6
|
|
49
|
+
Requires-Dist: snuffled>=0.1.6; python_version < '3.15'
|
|
50
|
+
Requires-Dist: snuffled>=0.1.9; python_version >= '3.15'
|
|
41
51
|
Requires-Dist: typing-extensions>=4.4
|
|
42
52
|
Description-Content-Type: text/markdown
|
|
43
53
|
|
|
44
54
|
[](https://github.com/bertpl/sunnbear/actions/workflows/push_to_main.yml)
|
|
45
55
|
[](https://github.com/bertpl/sunnbear/actions/workflows/push_to_main.yml)
|
|
46
|
-
[](https://github.com/bertpl/sunnbear/actions/workflows/push_to_main.yml)
|
|
47
57
|
[](https://pypi.org/project/sunnbear/)
|
|
48
58
|
[](https://pypi.org/project/sunnbear/)
|
|
49
59
|
[](https://github.com/bertpl/sunnbear/blob/main/LICENSE)
|
|
@@ -54,4 +64,4 @@ Description-Content-Type: text/markdown
|
|
|
54
64
|
|
|
55
65
|
Under construction.
|
|
56
66
|
|
|
57
|
-

|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sunnbear"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.3"
|
|
4
4
|
description = "Under construction."
|
|
5
5
|
# readme is dynamic: hatch-fancy-pypi-readme builds the PyPI long-description from README.md,
|
|
6
6
|
# rewriting the relative splash link to a tag-pinned absolute URL (config below).
|
|
@@ -15,31 +15,45 @@ dependencies = [
|
|
|
15
15
|
# Per-Python minimal versions: each is the earliest version shipping a wheel for that
|
|
16
16
|
# CPython (and, for numpy, admitted by the numba minimal version on the same interpreter),
|
|
17
17
|
# so `lowest-direct` installs (not source-builds) across the whole matrix.
|
|
18
|
+
#
|
|
19
|
+
# A pure-Python package ships 1 wheel that installs on every Python version, so the rule above does
|
|
20
|
+
# not apply to it: where its minimal version does not declare 3.15 support, a separate dependency line
|
|
21
|
+
# for 3.15 raises its minimal version to the earliest release that does.
|
|
18
22
|
"numpy>=2.0.0; python_version == '3.12'",
|
|
19
23
|
"numpy>=2.1.0; python_version == '3.13'",
|
|
20
|
-
"numpy>=2.3.2; python_version
|
|
24
|
+
"numpy>=2.3.2; python_version == '3.14'",
|
|
25
|
+
"numpy>=2.5.2; python_version >= '3.15'",
|
|
21
26
|
"numba>=0.60.0; python_version == '3.12'",
|
|
22
27
|
"numba>=0.66.0; python_version == '3.13'",
|
|
23
|
-
"numba>=0.66.0; python_version
|
|
28
|
+
"numba>=0.66.0; python_version == '3.14'",
|
|
29
|
+
"numba>=0.68.0; python_version >= '3.15'",
|
|
24
30
|
"matplotlib>=3.10.7; python_version == '3.12'",
|
|
25
31
|
"matplotlib>=3.10.7; python_version == '3.13'",
|
|
26
|
-
"matplotlib>=3.10.7; python_version
|
|
27
|
-
"
|
|
32
|
+
"matplotlib>=3.10.7; python_version == '3.14'",
|
|
33
|
+
"matplotlib>=3.11.2; python_version >= '3.15'",
|
|
34
|
+
"counted-float>=1.2.1; python_version < '3.15'",
|
|
35
|
+
"counted-float>=2.6.0; python_version >= '3.15'",
|
|
28
36
|
# These pydantic minimal versions equal counted-float's own pydantic minimal versions; counted-float
|
|
29
37
|
# depends on pydantic, so every install already satisfies them.
|
|
30
38
|
"pydantic>=2.7; python_version == '3.12'",
|
|
31
39
|
"pydantic>=2.9; python_version == '3.13'",
|
|
32
|
-
"pydantic>=2.12; python_version
|
|
40
|
+
"pydantic>=2.12; python_version == '3.14'",
|
|
41
|
+
"pydantic>=2.14; python_version >= '3.15'",
|
|
33
42
|
"typing-extensions>=4.4", # TypeVar defaults (PEP 696) on Python < 3.13
|
|
34
43
|
"platformdirs>=4.0", # platformdirs finds the user's cache directory for downloaded data artifacts
|
|
35
44
|
# backports.zstd provides zstd for the archives of downloaded data artifacts; the standard library has it from 3.14.
|
|
36
45
|
"backports.zstd>=1.0.0; python_version < '3.14'",
|
|
37
|
-
"snuffled>=0.1.6",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
"
|
|
46
|
+
"snuffled>=0.1.6; python_version < '3.15'",
|
|
47
|
+
"snuffled>=0.1.9; python_version >= '3.15'",
|
|
48
|
+
# max-div 0.21.1 adds DiversityMetric.gpq_separation(q), the diversity metric that sunnbear maximizes when it builds the Monte Carlo (MC) tuple set.
|
|
49
|
+
"max-div>=0.21.1; python_version < '3.15'",
|
|
50
|
+
"max-div>=0.21.3; python_version >= '3.15'",
|
|
51
|
+
"mpl-composite>=0.1.2; python_version < '3.15'",
|
|
52
|
+
"mpl-composite>=0.1.4; python_version >= '3.15'",
|
|
53
|
+
# polars holds the benchmark results. Its wheels use the stable CPython ABI, so they install on every Python
|
|
54
|
+
# version, but on 3.15 the benchmark runner fails with polars 1.x.
|
|
55
|
+
"polars>=1.0.0; python_version < '3.15'",
|
|
56
|
+
"polars>=2.0.0; python_version >= '3.15'",
|
|
43
57
|
]
|
|
44
58
|
classifiers = [
|
|
45
59
|
"Development Status :: 2 - Pre-Alpha",
|
|
@@ -50,6 +64,7 @@ classifiers = [
|
|
|
50
64
|
"Programming Language :: Python :: 3.12",
|
|
51
65
|
"Programming Language :: Python :: 3.13",
|
|
52
66
|
"Programming Language :: Python :: 3.14",
|
|
67
|
+
"Programming Language :: Python :: 3.15",
|
|
53
68
|
"Topic :: Scientific/Engineering :: Mathematics",
|
|
54
69
|
"Typing :: Typed",
|
|
55
70
|
]
|
|
@@ -65,24 +80,18 @@ dev = [
|
|
|
65
80
|
# exact tool versions are pinned by the tracked uv.lock (used by pre-commit,
|
|
66
81
|
# `make lint`, and CI); these ranges just set the floor.
|
|
67
82
|
"ruff>=0.15.11",
|
|
68
|
-
|
|
83
|
+
# The solver tests compare against scipy's root finders; scipy is never a runtime dependency. On 3.15,
|
|
84
|
+
# its minimal version is its first release with a 3.15 wheel.
|
|
85
|
+
"scipy>=1.16.2; python_version < '3.15'",
|
|
86
|
+
"scipy>=1.18.1; python_version >= '3.15'",
|
|
69
87
|
"ty==0.0.56", # pre-1.0 type checker — pin exactly; its ruleset is still evolving
|
|
70
88
|
]
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
notebooks = [
|
|
74
|
-
"jupyterlab>=4.4.6",
|
|
75
|
-
"notebook>=7.4.5",
|
|
76
|
-
]
|
|
77
|
-
# packaging-integrity tooling for the _package_check.yml CI gate; opt-in via
|
|
78
|
-
# `--group package`, kept out of the default dev/notebooks sync.
|
|
89
|
+
# This group holds the packaging-integrity tooling for the _package_check.yml CI gate, which installs it with
|
|
90
|
+
# `--group package`.
|
|
79
91
|
package = [
|
|
80
92
|
"check-wheel-contents>=0.6.2",
|
|
81
93
|
]
|
|
82
94
|
|
|
83
|
-
[tool.uv]
|
|
84
|
-
default-groups = ["dev", "notebooks"]
|
|
85
|
-
|
|
86
95
|
[project.urls]
|
|
87
96
|
Source = "https://github.com/bertpl/sunnbear"
|
|
88
97
|
ChangeLog = "https://github.com/bertpl/sunnbear/blob/main/CHANGELOG.md"
|
|
@@ -189,8 +198,6 @@ invalid-method-override = "ignore"
|
|
|
189
198
|
[tool.codespell]
|
|
190
199
|
# "intoto": the in-toto attestation format (provenance.intoto.jsonl).
|
|
191
200
|
ignore-words-list = "intoto"
|
|
192
|
-
# Notebooks embed base64 image outputs that codespell misreads as typos.
|
|
193
|
-
skip = "*.ipynb"
|
|
194
201
|
|
|
195
202
|
[tool.pytest.ini_options]
|
|
196
203
|
addopts = "--strict-markers"
|
|
@@ -11,6 +11,8 @@ from collections.abc import Callable, Iterator, Sequence
|
|
|
11
11
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
|
|
14
|
+
from sunnbear._core.utils.floats import FLOAT64_EPS
|
|
15
|
+
|
|
14
16
|
# The largest number of function evaluations that 1 check spends before it judges the answer incorrect.
|
|
15
17
|
CORRECTNESS_CHECK_MAX_FEVALS = 1000
|
|
16
18
|
|
|
@@ -85,11 +87,12 @@ def _random_x_probes(x_found: float, xtol: float, seed: int) -> Iterator[float]:
|
|
|
85
87
|
likely, and uniform.
|
|
86
88
|
"""
|
|
87
89
|
rng = np.random.default_rng(seed)
|
|
88
|
-
# Adding a distance below 1 ulp (unit in the last place) of `x_found` returns `x_found` unchanged.
|
|
89
|
-
#
|
|
90
|
+
# Adding a distance below 1 ulp (unit in the last place) of `x_found` returns `x_found` unchanged.
|
|
91
|
+
#
|
|
92
|
+
# When `x_found` is 0, 1 ulp is about 5e-324, so log-uniform distances would spread over hundreds of orders of
|
|
90
93
|
# magnitude and almost all be negligible; the smallest log-uniform distance is therefore also held at or
|
|
91
|
-
# above `xtol ·
|
|
92
|
-
log_distance_min = math.log(min(xtol, max(math.ulp(x_found),
|
|
94
|
+
# above `xtol · FLOAT64_EPS`.
|
|
95
|
+
log_distance_min = math.log(min(xtol, max(math.ulp(x_found), xtol * FLOAT64_EPS)))
|
|
93
96
|
log_distance_max = math.log(xtol)
|
|
94
97
|
while True:
|
|
95
98
|
for is_log_uniform in (True, False):
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/state.py
RENAMED
|
@@ -20,14 +20,12 @@ class AndersonBjorckState(SolveState):
|
|
|
20
20
|
scaling factor of every iteration that kept the bound again.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
newest_bound: IntervalBound =
|
|
23
|
+
newest_bound: IntervalBound = field(init=False)
|
|
24
24
|
newest_f: float = field(init=False)
|
|
25
25
|
scaled_retained_f: float = field(init=False)
|
|
26
26
|
|
|
27
27
|
def __post_init__(self) -> None:
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
These values hold only for the default `newest_bound`.
|
|
31
|
-
"""
|
|
28
|
+
"""Start with the upper bound as the newest bound: `newest_f` is ``fb`` and `scaled_retained_f` is ``fa``."""
|
|
29
|
+
self.newest_bound = IntervalBound.UPPER
|
|
32
30
|
self.newest_f = self.interval.fb
|
|
33
31
|
self.scaled_retained_f = self.interval.fa
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"""`Brent` implements Brent's method: interpolation steps, with bisection when they converge too slowly."""
|
|
2
2
|
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
3
|
from sunnbear._core.solvers.core import Solver, SolveState
|
|
6
|
-
|
|
7
|
-
# ``_MACHEPS`` is Brent's ``macheps``, the relative machine precision: 2^-52 for float64.
|
|
8
|
-
_MACHEPS = sys.float_info.epsilon
|
|
4
|
+
from sunnbear._core.utils.floats import FLOAT64_EPS
|
|
9
5
|
|
|
10
6
|
|
|
11
7
|
class Brent(Solver):
|
|
@@ -30,9 +26,9 @@ class Brent(Solver):
|
|
|
30
26
|
|
|
31
27
|
- ``b`` and ``c`` are the interval bounds, ``b`` the one with the smaller ``|f|``, which is the best estimate;
|
|
32
28
|
- ``m`` is half the signed width of the interval, from ``b`` toward ``c``;
|
|
33
|
-
- ``tol = 2 * macheps * |b| + t`` is the tolerance, with ``macheps`` the relative machine precision
|
|
34
|
-
absolute tolerance derived from ``xtol`` (below); the solve ends once
|
|
35
|
-
returns ``b``.
|
|
29
|
+
- ``tol = 2 * macheps * |b| + t`` is the tolerance, with ``macheps`` the relative machine precision
|
|
30
|
+
(`FLOAT64_EPS`) and ``t`` an absolute tolerance derived from ``xtol`` (below); the solve ends once
|
|
31
|
+
``|m| <= tol`` or ``f(b) = 0``, and returns ``b``.
|
|
36
32
|
|
|
37
33
|
Brent's procedure returns a ``b`` within ``6 * macheps * |x| + 2 * t`` of a root ``x``. The solver sets
|
|
38
34
|
``t = (xtol - 6 * macheps * max(|a0|, |b0|)) / 2``, with ``a0`` and ``b0`` the bounds of the initial interval,
|
|
@@ -77,7 +73,7 @@ class Brent(Solver):
|
|
|
77
73
|
"""
|
|
78
74
|
interval = state.interval
|
|
79
75
|
a, fa, b, fb = interval.a, interval.fa, interval.b, interval.fb
|
|
80
|
-
t = 0.5 * (state.xtol - 6.0 *
|
|
76
|
+
t = 0.5 * (state.xtol - 6.0 * FLOAT64_EPS * max(abs(a), abs(b)))
|
|
81
77
|
# The Algol label "int": c becomes a, the bound on the other side of the root from b.
|
|
82
78
|
c, fc = a, fa
|
|
83
79
|
d = e = b - a
|
|
@@ -86,7 +82,7 @@ class Brent(Solver):
|
|
|
86
82
|
if abs(fc) < abs(fb):
|
|
87
83
|
a, b, c = b, c, b
|
|
88
84
|
fa, fb, fc = fb, fc, fb
|
|
89
|
-
tol = 2.0 *
|
|
85
|
+
tol = 2.0 * FLOAT64_EPS * abs(b) + t
|
|
90
86
|
m = 0.5 * (c - b)
|
|
91
87
|
if abs(m) <= tol or fb == 0.0:
|
|
92
88
|
return b
|
|
@@ -17,9 +17,10 @@ class IllinoisState(SolveState):
|
|
|
17
17
|
iteration that kept the bound again.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
newest_bound: IntervalBound =
|
|
20
|
+
newest_bound: IntervalBound = field(init=False)
|
|
21
21
|
scaled_retained_f: float = field(init=False)
|
|
22
22
|
|
|
23
23
|
def __post_init__(self) -> None:
|
|
24
|
-
"""Start with the
|
|
24
|
+
"""Start with the upper bound as the newest bound: `scaled_retained_f` is ``fa``."""
|
|
25
|
+
self.newest_bound = IntervalBound.UPPER
|
|
25
26
|
self.scaled_retained_f = self.interval.fa
|
|
@@ -7,6 +7,11 @@ from sunnbear._core.solvers.core import BracketingSolver, Interval
|
|
|
7
7
|
from .state import ITPState
|
|
8
8
|
from .variant import ITPVariant
|
|
9
9
|
|
|
10
|
+
# ``kappa_1`` and ``kappa_2`` are the truncation constants that the `ITP` docstring gives. ``kappa_1`` depends on
|
|
11
|
+
# the initial interval, so `ITP._solve` sets it per solve from `_KAPPA_1_TIMES_INITIAL_WIDTH`.
|
|
12
|
+
_KAPPA_1_TIMES_INITIAL_WIDTH = 0.2
|
|
13
|
+
_KAPPA_2 = 2
|
|
14
|
+
|
|
10
15
|
|
|
11
16
|
class ITP(BracketingSolver[ITPState]):
|
|
12
17
|
"""`ITP` implements the ITP method, in the variant of its paper's pseudocode or in that of its paper's experiments.
|
|
@@ -70,9 +75,6 @@ class ITP(BracketingSolver[ITPState]):
|
|
|
70
75
|
version = 1
|
|
71
76
|
state_cls = ITPState
|
|
72
77
|
|
|
73
|
-
# `_KAPPA_2` is the paper's kappa_2; kappa_1 depends on the initial interval, so `_solve` sets it per solve.
|
|
74
|
-
_KAPPA_2 = 2
|
|
75
|
-
|
|
76
78
|
def __init__(self, *, n_slack: int, variant: ITPVariant) -> None:
|
|
77
79
|
"""Configure the method.
|
|
78
80
|
|
|
@@ -99,7 +101,7 @@ class ITP(BracketingSolver[ITPState]):
|
|
|
99
101
|
"""
|
|
100
102
|
width = state.interval.width
|
|
101
103
|
n_bisection = math.ceil(math.log2(width / (2.0 * state.xtol)))
|
|
102
|
-
state.kappa_1 =
|
|
104
|
+
state.kappa_1 = _KAPPA_1_TIMES_INITIAL_WIDTH / width
|
|
103
105
|
state.max_next_width = state.xtol * 2.0 ** (n_bisection + self.n_slack)
|
|
104
106
|
return super()._solve(state)
|
|
105
107
|
|
|
@@ -121,7 +123,7 @@ class ITP(BracketingSolver[ITPState]):
|
|
|
121
123
|
sigma = -1.0
|
|
122
124
|
else:
|
|
123
125
|
sigma = 0.0
|
|
124
|
-
delta = state.kappa_1 * interval.width**
|
|
126
|
+
delta = state.kappa_1 * interval.width**_KAPPA_2
|
|
125
127
|
if delta <= abs(x_half_minus_x_f):
|
|
126
128
|
x_t = x_f + sigma * delta
|
|
127
129
|
else:
|
|
@@ -22,7 +22,7 @@ class ModAB(Solver):
|
|
|
22
22
|
|
|
23
23
|
``x3`` replaces the bound whose function value has the sign of ``y3``.
|
|
24
24
|
|
|
25
|
-
In Anderson-Björck mode, when the same bound
|
|
25
|
+
In Anderson-Björck mode, when the same bound is retained in 2 iterations in a row, its stored function value is
|
|
26
26
|
multiplied by the factor of `AndersonBjorck`, ``m = 1 - y3 / y_moved``, where ``y_moved`` is the function value at
|
|
27
27
|
the replaced bound; where ``m`` is not positive, the factor is 0.5.
|
|
28
28
|
|
|
@@ -42,7 +42,7 @@ class ModAB(Solver):
|
|
|
42
42
|
- **Clamping:** Algorithm 1 evaluates the chord's zero and then clamps it into the interval. The C# code clamps
|
|
43
43
|
first: a chord's zero that rounding puts on or outside a bound is replaced by that bound and its stored function
|
|
44
44
|
value, so nothing is evaluated. In Anderson-Björck mode, such an iteration only halves the stored function value
|
|
45
|
-
at the other bound, or marks the other bound as
|
|
45
|
+
at the other bound, or marks the other bound as retained.
|
|
46
46
|
- **The first threshold:** only the C# code shows the threshold's starting value at the switch.
|
|
47
47
|
- **Scaled function values:** Anderson-Björck mode's scaled function values stay stored after a fallback to
|
|
48
48
|
bisection, and the next bisection steps read them when they test whether the function looks close to a straight
|
|
@@ -81,7 +81,7 @@ class ModAB(Solver):
|
|
|
81
81
|
|
|
82
82
|
- ``x_new`` and ``y_new`` are the point that replaces a bound: ``x3`` and ``y3``, or, when ``x3`` is clamped
|
|
83
83
|
onto a bound, that bound with its stored function value;
|
|
84
|
-
- ``
|
|
84
|
+
- ``retained_bound`` is the bound that was retained in the last Anderson-Björck step, ``None`` before the first;
|
|
85
85
|
the C# code stores it as the integer ``side``, although the comment on ``side`` calls it the side that moved
|
|
86
86
|
last;
|
|
87
87
|
- ``is_bisecting`` is the mode, ``bisection`` in the C# code.
|
|
@@ -91,13 +91,13 @@ class ModAB(Solver):
|
|
|
91
91
|
- computes ``x3``, and ends the solve if the interval is narrow enough;
|
|
92
92
|
- evaluates ``x3``, unless it is clamped, and in bisection mode tests whether to switch;
|
|
93
93
|
- ends the solve if ``y_new = 0``;
|
|
94
|
-
- replaces a bound by ``(x_new, y_new)``, scaling the
|
|
94
|
+
- replaces a bound by ``(x_new, y_new)``, scaling the retained bound's function value in Anderson-Björck mode;
|
|
95
95
|
- falls back to bisection if the interval is wider than the threshold.
|
|
96
96
|
"""
|
|
97
97
|
interval = state.interval
|
|
98
98
|
x1, y1, x2, y2 = interval.a, interval.fa, interval.b, interval.fb
|
|
99
99
|
is_bisecting = True
|
|
100
|
-
|
|
100
|
+
retained_bound: IntervalBound | None = None
|
|
101
101
|
threshold = x2 - x1
|
|
102
102
|
while True:
|
|
103
103
|
# --- the new x-value x3 -------------
|
|
@@ -137,23 +137,23 @@ class ModAB(Solver):
|
|
|
137
137
|
# The C# code compares Math.Sign(y_new) with Math.Sign(y1); the test below gives the same result because
|
|
138
138
|
# y_new is not 0 here.
|
|
139
139
|
if (y_new > 0.0 and y1 > 0.0) or (y_new < 0.0 and y1 < 0.0):
|
|
140
|
-
if
|
|
140
|
+
if retained_bound is IntervalBound.UPPER:
|
|
141
141
|
m = 1.0 - y_new / y1
|
|
142
142
|
y2 = y2 * (0.5 if m <= 0.0 else m)
|
|
143
143
|
elif not is_bisecting:
|
|
144
|
-
|
|
144
|
+
retained_bound = IntervalBound.UPPER
|
|
145
145
|
x1, y1 = x_new, y_new
|
|
146
146
|
else:
|
|
147
|
-
if
|
|
147
|
+
if retained_bound is IntervalBound.LOWER:
|
|
148
148
|
m = 1.0 - y_new / y2
|
|
149
149
|
y1 = y1 * (0.5 if m <= 0.0 else m)
|
|
150
150
|
elif not is_bisecting:
|
|
151
|
-
|
|
151
|
+
retained_bound = IntervalBound.LOWER
|
|
152
152
|
x2, y2 = x_new, y_new
|
|
153
153
|
if x2 - x1 > threshold:
|
|
154
154
|
# The Anderson-Björck steps shrink the interval too slowly: fall back to bisection.
|
|
155
155
|
is_bisecting = True
|
|
156
|
-
|
|
156
|
+
retained_bound = None
|
|
157
157
|
|
|
158
158
|
# --------------------------------------------------------------------------
|
|
159
159
|
# Helpers
|
|
@@ -19,14 +19,12 @@ class PegasusState(SolveState):
|
|
|
19
19
|
scaling factor of every iteration that kept the bound again.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
newest_bound: IntervalBound =
|
|
22
|
+
newest_bound: IntervalBound = field(init=False)
|
|
23
23
|
newest_f: float = field(init=False)
|
|
24
24
|
scaled_retained_f: float = field(init=False)
|
|
25
25
|
|
|
26
26
|
def __post_init__(self) -> None:
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
These values hold only for the default `newest_bound`.
|
|
30
|
-
"""
|
|
27
|
+
"""Start with the upper bound as the newest bound: `newest_f` is ``fb`` and `scaled_retained_f` is ``fa``."""
|
|
28
|
+
self.newest_bound = IntervalBound.UPPER
|
|
31
29
|
self.newest_f = self.interval.fb
|
|
32
30
|
self.scaled_retained_f = self.interval.fa
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"""`TOMS748` implements Algorithm 748: interpolation steps, a double-size secant step, and bisection if needed."""
|
|
2
2
|
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
3
|
from sunnbear._core.solvers.core import Interval, IntervalBound, Solver, SolveState
|
|
6
|
-
|
|
7
|
-
# ``_MACHEPS`` is the paper's ``macheps``, the relative machine precision: 2^-52 for float64.
|
|
8
|
-
_MACHEPS = sys.float_info.epsilon
|
|
4
|
+
from sunnbear._core.utils.floats import FLOAT64_EPS
|
|
9
5
|
|
|
10
6
|
# ``_MU`` is the paper's ``mu``: an iteration that leaves the interval wider than ``_MU`` times its width at the start
|
|
11
7
|
# of the iteration ends with a bisection.
|
|
@@ -40,8 +36,8 @@ class TOMS748(Solver):
|
|
|
40
36
|
The paper states the 2 algorithms without a stopping criterion; its experiments, and the authors' code, add the
|
|
41
37
|
stopping criterion of Brent's method:
|
|
42
38
|
|
|
43
|
-
- ``stop_width = 2 * (2 * macheps * |u| + tol)``, with ``macheps`` the relative machine precision
|
|
44
|
-
absolute tolerance that the solver derives from ``xtol``;
|
|
39
|
+
- ``stop_width = 2 * (2 * macheps * |u| + tol)``, with ``macheps`` the relative machine precision
|
|
40
|
+
(`FLOAT64_EPS`) and ``tol`` an absolute tolerance that the solver derives from ``xtol``;
|
|
45
41
|
- the solve ends once the interval is at most ``stop_width`` wide, or once an evaluation returns exactly 0, and
|
|
46
42
|
returns the lower bound ``a``, or the point that returned 0.
|
|
47
43
|
|
|
@@ -162,7 +158,7 @@ class TOMS748(Solver):
|
|
|
162
158
|
@staticmethod
|
|
163
159
|
def _get_tol(xtol: float, a0: float, b0: float) -> float:
|
|
164
160
|
"""Return the ``tol`` that keeps ``stop_width`` at most ``xtol``, or 0 where that ``tol`` would be negative."""
|
|
165
|
-
return max(0.5 * xtol - 2.0 *
|
|
161
|
+
return max(0.5 * xtol - 2.0 * FLOAT64_EPS * max(abs(a0), abs(b0)), 0.0)
|
|
166
162
|
|
|
167
163
|
@staticmethod
|
|
168
164
|
def _get_u(interval: Interval) -> tuple[float, float]:
|
|
@@ -176,7 +172,7 @@ class TOMS748(Solver):
|
|
|
176
172
|
def _get_stop_width(interval: Interval, tol: float) -> float:
|
|
177
173
|
"""Return ``stop_width = 2 * (2 * macheps * |u| + tol)`` for ``interval``, the authors' subroutine ``TOLE``."""
|
|
178
174
|
u, _ = TOMS748._get_u(interval)
|
|
179
|
-
return 2.0 * (tol + 2.0 * abs(u) *
|
|
175
|
+
return 2.0 * (tol + 2.0 * abs(u) * FLOAT64_EPS)
|
|
180
176
|
|
|
181
177
|
def _evaluate_and_split_at(
|
|
182
178
|
self, state: SolveState, interval: Interval, c: float, stop_width: float, tol: float
|
|
@@ -115,13 +115,13 @@ class Interval(ABC):
|
|
|
115
115
|
else:
|
|
116
116
|
return type(self)(self.a, x, self.fa, fx, IntervalBound.UPPER)
|
|
117
117
|
|
|
118
|
-
def is_converged(self,
|
|
119
|
-
"""Return whether
|
|
118
|
+
def is_converged(self, xtol_doubled: float) -> bool:
|
|
119
|
+
"""Return whether the width is at most ``xtol_doubled`` or the function value at a bound is zero.
|
|
120
120
|
|
|
121
121
|
The parameter is the doubled tolerance, so the caller computes it once
|
|
122
122
|
per solve, not once per iteration.
|
|
123
123
|
"""
|
|
124
|
-
return self.width <=
|
|
124
|
+
return self.width <= xtol_doubled or self.is_fa_zero or self.is_fb_zero
|
|
125
125
|
|
|
126
126
|
def root(self) -> float:
|
|
127
127
|
"""Return the best root estimate without another step: a bound with a zero value if any, else the midpoint."""
|
|
@@ -95,15 +95,15 @@ class Solver(ABC, Generic[StateT]):
|
|
|
95
95
|
ValueError: If ``a >= b``, or ``f(a)`` and ``f(b)`` have the same sign and neither is
|
|
96
96
|
zero — a caller error, not a solve outcome.
|
|
97
97
|
"""
|
|
98
|
-
# --- uncounted validation
|
|
98
|
+
# --- uncounted validation ---------------
|
|
99
99
|
if not a < b:
|
|
100
100
|
raise ValueError(f"Interval must satisfy a < b (got a={a}, b={b}).")
|
|
101
101
|
wrapped_f = WrappedFunction(f, max_fevals=max_fevals, history_enabled=history_enabled)
|
|
102
102
|
|
|
103
|
-
# --- counted: main algorithm
|
|
103
|
+
# --- counted: main algorithm ------------
|
|
104
104
|
x_failed: float | None = None # Where f failed, if it did; decides FUNCTION_ERROR versus DIVERGED below.
|
|
105
105
|
with FlopCountingContext() as flop_ctx:
|
|
106
|
-
# --- prep and early exits
|
|
106
|
+
# --- prep and early exits -----------
|
|
107
107
|
a_counted, b_counted, xtol_counted = CountedFloat(a), CountedFloat(b), CountedFloat(xtol)
|
|
108
108
|
try:
|
|
109
109
|
fa, fb = wrapped_f(a_counted), wrapped_f(b_counted)
|
|
@@ -115,7 +115,7 @@ class Solver(ABC, Generic[StateT]):
|
|
|
115
115
|
elif fb == 0.0: # Early exit when b is a root.
|
|
116
116
|
x, status = b_counted, SolveStatus.CONVERGED
|
|
117
117
|
else:
|
|
118
|
-
# --- actual solve
|
|
118
|
+
# --- actual solve -----------
|
|
119
119
|
interval = Interval.from_interval_bounds(a_counted, b_counted, fa, fb)
|
|
120
120
|
state = self.state_cls(f=wrapped_f, interval=interval, xtol=xtol_counted, x_best=interval.midpoint)
|
|
121
121
|
try:
|
|
@@ -124,7 +124,7 @@ class Solver(ABC, Generic[StateT]):
|
|
|
124
124
|
except Exception as exc: # noqa: BLE001 — every ending becomes a recorded status, by design
|
|
125
125
|
x, status, x_failed = _ending_of(exc, x_best=state.x_best)
|
|
126
126
|
|
|
127
|
-
# --- return results
|
|
127
|
+
# --- return results ---------------------
|
|
128
128
|
# Divergence is the framework's judgment, not solver work, so these checks are uncounted.
|
|
129
129
|
x_plain = float(x)
|
|
130
130
|
if x_failed is not None and not a <= x_failed <= b:
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""This module holds the float64 constants that several packages share."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
# `FLOAT64_EPS` is 2^-52, the distance from 1.0 to the next larger float64 value; papers on root finding call it
|
|
6
|
+
# ``macheps``, the relative machine precision.
|
|
7
|
+
FLOAT64_EPS = sys.float_info.epsilon
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/builtin/mc_tuples/manifest.json
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/artifacts/builtin/mc_tuples/mc_tuples.csv
RENAMED
|
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
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/aggregation/derived_results.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_allocation.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_correction.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_population.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_result.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/benchmark/mc_tuples/construction_solve.py
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/__init__.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/configs.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/anderson_bjorck/solver.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/bisection/__init__.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/bisection/configs.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/chandrupatla/__init__.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/chandrupatla/configs.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/chandrupatla/solver.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/illinois/__init__.py
RENAMED
|
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
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/regula_falsi/__init__.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/regula_falsi/configs.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/regula_falsi/solver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/steffen_brent/__init__.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/steffen_brent/configs.py
RENAMED
|
File without changes
|
{sunnbear-0.2.2 → sunnbear-0.2.3}/src/sunnbear/_core/solvers/bracketing/steffen_brent/solver.py
RENAMED
|
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
|
|
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
|