FEAT: Added support for float coefficients
All checks were successful
Run Python Tests / test (3.12) (pull_request) Successful in 10s
Run Python Tests / test (3.10) (pull_request) Successful in 14s
Run Python Tests / test (3.8) (pull_request) Successful in 9s

This commit is contained in:
2025-06-18 09:10:37 -04:00
parent c94d08498d
commit 89a9700222
3 changed files with 18 additions and 12 deletions

View File

@ -9,7 +9,7 @@ A Python library for representing, manipulating, and solving polynomial equation
## Key Features ## Key Features
* **Create and Manipulate Polynomials**: Easily define polynomials of any degree and perform arithmetic operations like addition, subtraction, multiplication, and scaling. * **Create and Manipulate Polynomials**: Easily define polynomials of any degree using integer or float coefficients, and perform arithmetic operations like addition, subtraction, multiplication, and scaling.
* **Genetic Algorithm Solver**: Find approximate real roots for complex polynomials where analytical solutions are difficult or impossible. * **Genetic Algorithm Solver**: Find approximate real roots for complex polynomials where analytical solutions are difficult or impossible.
* **CUDA Accelerated**: Leverage NVIDIA GPUs for a massive performance boost when finding roots in large solution spaces. * **CUDA Accelerated**: Leverage NVIDIA GPUs for a massive performance boost when finding roots in large solution spaces.
* **Analytical Solvers**: Includes standard, exact solvers for simple cases (e.g., `quadratic_solve`). * **Analytical Solvers**: Includes standard, exact solvers for simple cases (e.g., `quadratic_solve`).
@ -44,6 +44,7 @@ Here is a simple example of how to define a quadratic function, find its propert
from polysolve import Function, GA_Options, quadratic_solve from polysolve import Function, GA_Options, quadratic_solve
# 1. Define the function f(x) = 2x^2 - 3x - 5 # 1. Define the function f(x) = 2x^2 - 3x - 5
# Coefficients can be integers or floats.
f1 = Function(largest_exponent=2) f1 = Function(largest_exponent=2)
f1.set_constants([2, -3, -5]) f1.set_constants([2, -3, -5])

View File

@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
# --- Core Metadata --- # --- Core Metadata ---
name = "polysolve" name = "polysolve"
version = "0.2.2" version = "0.3.0"
authors = [ authors = [
{ name="Jonathan Rampersad", email="jonathan@jono-rams.work" }, { name="Jonathan Rampersad", email="jonathan@jono-rams.work" },
] ]

View File

@ -15,7 +15,7 @@ except ImportError:
# The CUDA kernel for the fitness function # The CUDA kernel for the fitness function
_FITNESS_KERNEL = """ _FITNESS_KERNEL = """
extern "C" __global__ void fitness_kernel( extern "C" __global__ void fitness_kernel(
const long long* coefficients, const double* coefficients,
int num_coefficients, int num_coefficients,
const double* x_vals, const double* x_vals,
double* ranks, double* ranks,
@ -76,13 +76,14 @@ class Function:
self.coefficients: Optional[np.ndarray] = None self.coefficients: Optional[np.ndarray] = None
self._initialized = False self._initialized = False
def set_coeffs(self, coefficients: List[int]): def set_coeffs(self, coefficients: List[Union[int, float]]):
""" """
Sets the coefficients of the polynomial. Sets the coefficients of the polynomial.
Args: Args:
coefficients (List[int]): A list of integer coefficients. The list size coefficients (List[Union[int, float]]): A list of integer or float
must be largest_exponent + 1. coefficients. The list size
must be largest_exponent + 1.
Raises: Raises:
ValueError: If the input is invalid. ValueError: If the input is invalid.
@ -96,7 +97,7 @@ class Function:
if coefficients[0] == 0 and self._largest_exponent > 0: if coefficients[0] == 0 and self._largest_exponent > 0:
raise ValueError("The first constant (for the largest exponent) cannot be 0.") raise ValueError("The first constant (for the largest exponent) cannot be 0.")
self.coefficients = np.array(coefficients, dtype=np.int64) self.coefficients = np.array(coefficients, dtype=np.float64)
self._initialized = True self._initialized = True
def _check_initialized(self): def _check_initialized(self):
@ -279,7 +280,7 @@ class Function:
fitness_gpu = cupy.RawKernel(_FITNESS_KERNEL, 'fitness_kernel') fitness_gpu = cupy.RawKernel(_FITNESS_KERNEL, 'fitness_kernel')
# Move coefficients to GPU # Move coefficients to GPU
d_coefficients = cupy.array(self.coefficients, dtype=cupy.int64) d_coefficients = cupy.array(self.coefficients, dtype=cupy.float64)
# Create initial random solutions on the GPU # Create initial random solutions on the GPU
d_solutions = cupy.random.uniform( d_solutions = cupy.random.uniform(
@ -337,12 +338,16 @@ class Function:
power = self._largest_exponent - i power = self._largest_exponent - i
# Coefficient part # Coefficient part
if c == 1 and power != 0: coeff_val = c
if c == int(c):
coeff_val = int(c)
if coeff_val == 1 and power != 0:
coeff = "" coeff = ""
elif c == -1 and power != 0: elif coeff_val == -1 and power != 0:
coeff = "-" coeff = "-"
else: else:
coeff = str(c) coeff = str(coeff_val)
# Variable part # Variable part
if power == 0: if power == 0:
@ -356,7 +361,7 @@ class Function:
sign = "" sign = ""
if i > 0: if i > 0:
sign = " + " if c > 0 else " - " sign = " + " if c > 0 else " - "
coeff = str(abs(c)) coeff = str(abs(coeff_val))
if abs(c) == 1 and power != 0: if abs(c) == 1 and power != 0:
coeff = "" # Don't show 1 for non-constant terms coeff = "" # Don't show 1 for non-constant terms