Got rid of min/max_range to exclusively use Cauchy's Bound. Updated quadratic solve to handle complex roots.

This commit is contained in:
2025-11-18 09:06:38 -04:00
parent dca1d66346
commit 602269889b

View File

@@ -1,4 +1,5 @@
import math
import cmath
import numpy as np
import numba
from dataclasses import dataclass
@@ -104,8 +105,6 @@ class GA_Options:
(e.g., 7) is more precise but may return
multiple near-identical roots. Default: 5
"""
min_range: float = 0.0
max_range: float = 0.0
num_of_generations: int = 10
data_size: int = 100000
mutation_strength: float = 0.01
@@ -359,20 +358,9 @@ class Function:
mutation_size = int(data_size * mutation_ratio)
random_size = data_size - elite_size - crossover_size - mutation_size
# Check if the user is using the default, non-expert range
user_range_is_default = (options.min_range == 0.0 and options.max_range == 0.0)
if user_range_is_default:
# User hasn't specified a custom range.
# We are the expert; use the smart, guaranteed bound.
bound = _get_cauchy_bound(self.coefficients)
min_r = -bound
max_r = bound
else:
# User has provided a custom range.
# Trust the expert; use their range.
min_r = options.min_range
max_r = options.max_range
bound = _get_cauchy_bound(self.coefficients)
min_r = -bound
max_r = bound
# Create initial random solutions
solutions = np.random.uniform(min_r, max_r, data_size)
@@ -488,20 +476,9 @@ class Function:
fitness_gpu = cupy.RawKernel(_FITNESS_KERNEL_FLOAT, 'fitness_kernel')
d_coefficients = cupy.array(self.coefficients, dtype=cupy.float64)
# Check if the user is using the default, non-expert range
user_range_is_default = (options.min_range == 0.0 and options.max_range == 0.0)
if user_range_is_default:
# User hasn't specified a custom range.
# We are the expert; use the smart, guaranteed bound.
bound = _get_cauchy_bound(self.coefficients)
min_r = -bound
max_r = bound
else:
# User has provided a custom range.
# Trust the expert; use their range.
min_r = options.min_range
max_r = options.max_range
bound = _get_cauchy_bound(self.coefficients)
min_r = -bound
max_r = bound
# Create initial random solutions on the GPU
d_solutions = cupy.random.uniform(
@@ -781,10 +758,7 @@ class Function:
discriminant = (b**2) - (4*a*c)
if discriminant < 0:
return None # No real roots
sqrt_discriminant = math.sqrt(discriminant)
sqrt_discriminant = cmath.sqrt(discriminant)
# 1. Calculate the first root.
# We use math.copysign(val, sign) to get the sign of b.