import pytest
import numpy as np
import scirs2
class TestMinimizeScalar:
def test_minimize_scalar_quadratic(self):
result = scirs2.minimize_scalar_py(
lambda x: (x - 2) ** 2,
bracket=(0.0, 4.0),
method="brent"
)
assert result["success"]
assert abs(result["x"] - 2.0) < 0.01
assert result["fun"] < 0.001
def test_minimize_scalar_cubic(self):
result = scirs2.minimize_scalar_py(
lambda x: (x - 2)**2 + 1, bracket=(0.0, 4.0),
method="brent"
)
assert result["success"]
assert abs(result["x"] - 2.0) < 0.1
def test_minimize_scalar_golden(self):
result = scirs2.minimize_scalar_py(
lambda x: (x - 1.5) ** 2,
bracket=(0.0, 3.0),
method="golden"
)
assert result["success"]
assert abs(result["x"] - 1.5) < 0.6
def test_minimize_scalar_sin(self):
result = scirs2.minimize_scalar_py(
lambda x: np.sin(x),
bracket=(4.0, 5.5), method="brent"
)
assert result["success"]
assert abs(result["fun"] - (-1.0)) < 0.05
class TestDifferentialEvolution:
def test_de_sphere(self):
def sphere(x):
return sum(xi**2 for xi in x)
result = scirs2.differential_evolution_py(
sphere,
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
options={"seed": 42}
)
assert result["success"]
assert result["fun"] < 0.1
for xi in result["x"]:
assert abs(xi) < 0.5
def test_de_rosenbrock(self):
def rosenbrock(x):
return (1 - x[0])**2 + 100*(x[1] - x[0]**2)**2
result = scirs2.differential_evolution_py(
rosenbrock,
bounds=[(-2.0, 2.0), (-2.0, 2.0)],
options={"maxiter": 2000, "seed": 42}
)
assert result["success"]
assert abs(result["x"][0] - 1.0) < 0.5
assert abs(result["x"][1] - 1.0) < 0.5
def test_de_rastrigin(self):
def rastrigin(x):
n = len(x)
return 10*n + sum(xi**2 - 10*np.cos(2*np.pi*xi) for xi in x)
result = scirs2.differential_evolution_py(
rastrigin,
bounds=[(-5.12, 5.12)],
options={"seed": 42}
)
assert result["success"]
assert result["fun"] < 1.0
def test_de_with_seed(self):
def func(x):
return sum(xi**2 for xi in x)
result1 = scirs2.differential_evolution_py(
func,
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
options={"seed": 12345}
)
result2 = scirs2.differential_evolution_py(
func,
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
options={"seed": 12345}
)
assert abs(result1["fun"] - result2["fun"]) < 0.001
class TestEdgeCases:
def test_minimize_scalar_narrow_bracket(self):
result = scirs2.minimize_scalar_py(
lambda x: x**2,
bracket=(-0.1, 0.1),
method="brent"
)
assert result["success"]
assert abs(result["x"]) < 0.01
def test_de_single_dimension(self):
result = scirs2.differential_evolution_py(
lambda x: x[0]**2,
bounds=[(-10.0, 10.0)],
options={"seed": 42}
)
assert result["success"]
assert abs(result["x"][0]) < 0.5
def test_de_high_dimension(self):
def func(x):
return sum(xi**2 for xi in x)
result = scirs2.differential_evolution_py(
func,
bounds=[(-5.0, 5.0)] * 5,
options={"maxiter": 500, "seed": 42}
)
assert result["success"]
assert result["fun"] < 1.0
class TestMinimize:
def test_minimize_rosenbrock_bfgs(self):
def rosenbrock(x):
return (1 - x[0])**2 + 100*(x[1] - x[0]**2)**2
result = scirs2.minimize_py(
rosenbrock,
x0=[0.5, 0.5], method="bfgs",
options={"maxiter": 2000}
)
if result["success"]:
assert abs(result["x"][0] - 1.0) < 0.3
assert abs(result["x"][1] - 1.0) < 0.3
assert result["fun"] < 1.0
def test_minimize_quadratic_nelder_mead(self):
def quadratic(x):
return x[0]**2 + x[1]**2
result = scirs2.minimize_py(
quadratic,
x0=[1.0, 1.0],
method="nelder-mead"
)
assert result["success"]
assert abs(result["x"][0]) < 0.1
assert abs(result["x"][1]) < 0.1
def test_minimize_quadratic_cg(self):
def quadratic(x):
return x[0]**2 + x[1]**2
result = scirs2.minimize_py(
quadratic,
x0=[5.0, 5.0],
method="cg"
)
assert result["success"]
assert abs(result["x"][0]) < 0.1
assert abs(result["x"][1]) < 0.1
def test_minimize_quadratic_powell(self):
def quadratic(x):
return x[0]**2 + x[1]**2
result = scirs2.minimize_py(
quadratic,
x0=[2.0, 3.0],
method="powell"
)
assert result["success"]
assert abs(result["x"][0]) < 0.2
assert abs(result["x"][1]) < 0.2
def test_minimize_with_bounds(self):
def func(x):
return (x[0] - 2)**2 + (x[1] + 1)**2
result = scirs2.minimize_py(
func,
x0=[1.0, 0.0], method="lbfgsb",
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
options={"maxiter": 500}
)
assert result["fun"] < 5.0
def test_minimize_sphere(self):
def sphere(x):
return sum(xi**2 for xi in x)
result = scirs2.minimize_py(
sphere,
x0=[1.0, 2.0, 3.0],
method="bfgs"
)
assert result["success"]
for xi in result["x"]:
assert abs(xi) < 0.1
class TestBrentq:
def test_brentq_quadratic(self):
result = scirs2.brentq_py(
lambda x: x**2 - 2,
1.0, 2.0
)
assert result["success"]
assert abs(result["x"] - 2**0.5) < 1e-10
assert abs(result["fun"]) < 1e-10
def test_brentq_sine(self):
result = scirs2.brentq_py(
lambda x: np.sin(x),
3.0, 4.0
)
assert result["success"]
assert abs(result["x"] - np.pi) < 1e-10
def test_brentq_polynomial(self):
result = scirs2.brentq_py(
lambda x: x**3 - x - 2,
1.0, 2.0
)
assert result["success"]
assert abs(result["fun"]) < 1e-10
def test_brentq_linear(self):
result = scirs2.brentq_py(
lambda x: 2*x - 4,
0.0, 5.0
)
assert result["success"]
assert abs(result["x"] - 2.0) < 1e-10
def test_brentq_negative_bracket(self):
result = scirs2.brentq_py(
lambda x: x**2 - 4,
-3.0, -1.0
)
assert result["success"]
assert abs(result["x"] + 2.0) < 1e-10
def test_brentq_tolerance(self):
result = scirs2.brentq_py(
lambda x: x**2 - 2,
1.0, 2.0,
xtol=1e-6
)
assert result["success"]
assert abs(result["fun"]) < 1e-5
def test_brentq_exponential(self):
result = scirs2.brentq_py(
lambda x: np.exp(x) - 3,
0.0, 2.0
)
assert result["success"]
assert abs(result["x"] - np.log(3)) < 1e-10
class TestCurveFit:
def test_curve_fit_linear(self):
def linear_model(x, a, b):
return a * x + b
xdata = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
ydata = np.array([3.0, 5.0, 7.0, 9.0, 11.0])
result = scirs2.curve_fit_py(
linear_model,
xdata.tolist(),
ydata.tolist(),
p0=[1.0, 1.0]
)
assert result["success"]
popt = result["popt"]
assert abs(popt[0] - 2.0) < 0.01 assert abs(popt[1] - 3.0) < 0.01
def test_curve_fit_exponential(self):
def exp_model(x, a, b):
return a * np.exp(b * x)
xdata = np.array([0.0, 1.0, 2.0, 3.0])
ydata = np.array([2.0, 3.297, 5.437, 8.963])
result = scirs2.curve_fit_py(
exp_model,
xdata.tolist(),
ydata.tolist(),
p0=[1.0, 0.5]
)
assert result["success"]
popt = result["popt"]
assert abs(popt[0] - 2.0) < 0.1
assert abs(popt[1] - 0.5) < 0.1
def test_curve_fit_quadratic(self):
def quadratic_model(x, a, b, c):
return a * x**2 + b * x + c
xdata = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
ydata = np.array([1.0, 3.5, 7.0, 11.5, 17.0])
result = scirs2.curve_fit_py(
quadratic_model,
xdata.tolist(),
ydata.tolist(),
p0=[1.0, 1.0, 1.0]
)
assert result["success"]
popt = result["popt"]
assert abs(popt[0] - 0.5) < 0.01 assert abs(popt[1] - 2.0) < 0.01 assert abs(popt[2] - 1.0) < 0.01
def test_curve_fit_with_noise(self):
def linear_model(x, a, b):
return a * x + b
xdata = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
ydata = np.array([1.0, 3.1, 4.9, 7.2, 8.8, 11.1])
result = scirs2.curve_fit_py(
linear_model,
xdata.tolist(),
ydata.tolist(),
p0=[1.0, 0.0]
)
assert result["success"]
popt = result["popt"]
assert abs(popt[0] - 2.0) < 0.2
assert abs(popt[1] - 1.0) < 0.2
def test_curve_fit_sine(self):
def sine_model(x, a, b, c):
return a * np.sin(b * x + c)
xdata = np.linspace(0, 2*np.pi, 20)
ydata = 2 * np.sin(xdata)
result = scirs2.curve_fit_py(
sine_model,
xdata.tolist(),
ydata.tolist(),
p0=[1.0, 1.0, 0.0]
)
assert result["success"]
popt = result["popt"]
assert abs(popt[0] - 2.0) < 0.2 assert abs(popt[1] - 1.0) < 0.2 assert abs(popt[2]) < 0.2
def test_curve_fit_power_law(self):
def power_model(x, a, b):
return a * x**b
xdata = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
ydata = np.array([3.0, 12.0, 27.0, 48.0, 75.0])
result = scirs2.curve_fit_py(
power_model,
xdata.tolist(),
ydata.tolist(),
p0=[1.0, 2.0]
)
assert result["success"]
popt = result["popt"]
assert abs(popt[0] - 3.0) < 0.1
assert abs(popt[1] - 2.0) < 0.1