polysolve 0.6.0__tar.gz → 0.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polysolve-0.6.0/src/polysolve.egg-info → polysolve-0.6.2}/PKG-INFO +1 -1
- {polysolve-0.6.0 → polysolve-0.6.2}/pyproject.toml +1 -1
- {polysolve-0.6.0 → polysolve-0.6.2}/src/polysolve/__init__.py +56 -4
- {polysolve-0.6.0 → polysolve-0.6.2/src/polysolve.egg-info}/PKG-INFO +1 -1
- {polysolve-0.6.0 → polysolve-0.6.2}/tests/test_polysolve.py +32 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/LICENSE +0 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/README.md +0 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/setup.cfg +0 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/src/polysolve.egg-info/SOURCES.txt +0 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/src/polysolve.egg-info/dependency_links.txt +0 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/src/polysolve.egg-info/requires.txt +0 -0
- {polysolve-0.6.0 → polysolve-0.6.2}/src/polysolve.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polysolve
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: A Python library for representing, manipulating, and solving exponential functions using analytical methods and genetic algorithms, with optional CUDA acceleration.
|
|
5
5
|
Author-email: Jonathan Rampersad <jonathan@jono-rams.work>
|
|
6
6
|
License: MIT License
|
|
@@ -133,6 +133,15 @@ class GA_Options:
|
|
|
133
133
|
raise ValueError(
|
|
134
134
|
f"blend_alpha cannot be negative, but got {self.blend_alpha}"
|
|
135
135
|
)
|
|
136
|
+
if self.root_precision > 15:
|
|
137
|
+
warnings.warn(
|
|
138
|
+
f"root_precision={self.root_precision} is greater than 15. "
|
|
139
|
+
"This demands an accuracy that is likely impossible for standard "
|
|
140
|
+
"64-bit floats (float64), which are limited to 15-16 significant digits. "
|
|
141
|
+
"The solver may fail to find any roots.",
|
|
142
|
+
UserWarning,
|
|
143
|
+
stacklevel=2
|
|
144
|
+
)
|
|
136
145
|
|
|
137
146
|
def _get_cauchy_bound(coeffs: np.ndarray) -> float:
|
|
138
147
|
"""
|
|
@@ -256,7 +265,9 @@ class Function:
|
|
|
256
265
|
"""
|
|
257
266
|
self._check_initialized()
|
|
258
267
|
if self._largest_exponent == 0:
|
|
259
|
-
|
|
268
|
+
diff_func = Function(0)
|
|
269
|
+
diff_func.set_coeffs([0])
|
|
270
|
+
return diff_func
|
|
260
271
|
|
|
261
272
|
derivative_coefficients = np.polyder(self.coefficients)
|
|
262
273
|
|
|
@@ -672,7 +683,7 @@ class Function:
|
|
|
672
683
|
|
|
673
684
|
def _multiply_by_scalar(self, scalar: Union[int, float]) -> 'Function':
|
|
674
685
|
"""Helper method to multiply the function by a scalar constant."""
|
|
675
|
-
self._check_initialized()
|
|
686
|
+
self._check_initialized()
|
|
676
687
|
|
|
677
688
|
if scalar == 0:
|
|
678
689
|
result_func = Function(0)
|
|
@@ -735,6 +746,21 @@ class Function:
|
|
|
735
746
|
return NotImplemented
|
|
736
747
|
|
|
737
748
|
return self
|
|
749
|
+
|
|
750
|
+
def __eq__(self, other: object) -> bool:
|
|
751
|
+
"""
|
|
752
|
+
Checks if two Function objects are equal by comparing
|
|
753
|
+
their coefficients.
|
|
754
|
+
"""
|
|
755
|
+
# Check if the 'other' object is even a Function
|
|
756
|
+
if not isinstance(other, Function):
|
|
757
|
+
return NotImplemented
|
|
758
|
+
|
|
759
|
+
# Ensure both are initialized before trying to access .coefficients
|
|
760
|
+
if not self._initialized or not other._initialized:
|
|
761
|
+
return False
|
|
762
|
+
|
|
763
|
+
return np.array_equal(self.coefficients, other.coefficients)
|
|
738
764
|
|
|
739
765
|
|
|
740
766
|
def quadratic_solve(self) -> Optional[List[float]]:
|
|
@@ -759,9 +785,35 @@ class Function:
|
|
|
759
785
|
return None # No real roots
|
|
760
786
|
|
|
761
787
|
sqrt_discriminant = math.sqrt(discriminant)
|
|
762
|
-
|
|
763
|
-
|
|
788
|
+
|
|
789
|
+
# 1. Calculate the first root.
|
|
790
|
+
# We use math.copysign(val, sign) to get the sign of b.
|
|
791
|
+
# This ensures (-b - sign*sqrt) is always an *addition*
|
|
792
|
+
# (or subtraction of a smaller from a larger number),
|
|
793
|
+
# avoiding catastrophic cancellation.
|
|
794
|
+
root1 = (-b - math.copysign(sqrt_discriminant, b)) / (2 * a)
|
|
795
|
+
|
|
796
|
+
# 2. Calculate the second root using Vieta's formulas.
|
|
797
|
+
# We know that root1 * root2 = c / a.
|
|
798
|
+
# This is just a division, which is numerically stable.
|
|
799
|
+
|
|
800
|
+
# Handle the edge case where c=0.
|
|
801
|
+
# If c=0, then root1 is 0.0, and root2 is -b/a
|
|
802
|
+
# We can't divide by root1=0, so we check.
|
|
803
|
+
if root1 == 0.0:
|
|
804
|
+
# If c is also 0, the other root is -b/a
|
|
805
|
+
if c == 0.0:
|
|
806
|
+
root2 = -b / a
|
|
807
|
+
else:
|
|
808
|
+
# This case (root1=0 but c!=0) shouldn't happen
|
|
809
|
+
# with real numbers, but it's safe to just
|
|
810
|
+
# return the one root we found.
|
|
811
|
+
return [0.0]
|
|
812
|
+
else:
|
|
813
|
+
# Standard case: Use Vieta's formula
|
|
814
|
+
root2 = (c / a) / root1
|
|
764
815
|
|
|
816
|
+
# Return roots in a consistent order
|
|
765
817
|
return [root1, root2]
|
|
766
818
|
|
|
767
819
|
# Example Usage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polysolve
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: A Python library for representing, manipulating, and solving exponential functions using analytical methods and genetic algorithms, with optional CUDA acceleration.
|
|
5
5
|
Author-email: Jonathan Rampersad <jonathan@jono-rams.work>
|
|
6
6
|
License: MIT License
|
|
@@ -37,6 +37,12 @@ def m_func_2() -> Function:
|
|
|
37
37
|
f.set_coeffs([5, -4])
|
|
38
38
|
return f
|
|
39
39
|
|
|
40
|
+
@pytest.fixture
|
|
41
|
+
def base_func():
|
|
42
|
+
f = Function(2)
|
|
43
|
+
f.set_coeffs([1, 2, 3])
|
|
44
|
+
return f
|
|
45
|
+
|
|
40
46
|
# --- Core Functionality Tests ---
|
|
41
47
|
|
|
42
48
|
def test_solve_y(quadratic_func):
|
|
@@ -95,6 +101,32 @@ def test_function_multiplication(m_func_1, m_func_2):
|
|
|
95
101
|
assert result.largest_exponent == 3
|
|
96
102
|
assert np.array_equal(result.coefficients, [10, 7, -7, -4])
|
|
97
103
|
|
|
104
|
+
def test_equality(base_func):
|
|
105
|
+
"""Tests the __eq__ method for the Function class."""
|
|
106
|
+
|
|
107
|
+
# 1. Test for equality with a new, identical object
|
|
108
|
+
f_identical = Function(2)
|
|
109
|
+
f_identical.set_coeffs([1, 2, 3])
|
|
110
|
+
assert base_func == f_identical
|
|
111
|
+
|
|
112
|
+
# 2. Test for inequality (different coefficients)
|
|
113
|
+
f_different = Function(2)
|
|
114
|
+
f_different.set_coeffs([1, 9, 3])
|
|
115
|
+
assert base_func != f_different
|
|
116
|
+
|
|
117
|
+
# 3. Test for inequality (different degree)
|
|
118
|
+
f_diff_degree = Function(1)
|
|
119
|
+
f_diff_degree.set_coeffs([1, 2])
|
|
120
|
+
assert base_func != f_diff_degree
|
|
121
|
+
|
|
122
|
+
# 4. Test against a different type
|
|
123
|
+
assert base_func != "some_string"
|
|
124
|
+
assert base_func != 123
|
|
125
|
+
|
|
126
|
+
# 5. Test against an uninitialized Function
|
|
127
|
+
f_uninitialized = Function(2)
|
|
128
|
+
assert base_func != f_uninitialized
|
|
129
|
+
|
|
98
130
|
# --- Genetic Algorithm Root-Finding Tests ---
|
|
99
131
|
|
|
100
132
|
def test_get_real_roots_numpy(quadratic_func):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|