This commit is contained in:
2025-11-04 15:02:02 +03:00
parent 83be98e923
commit 8e8e0abd0d
6 changed files with 657 additions and 1 deletions

2
lab4/tests/__init__.py Normal file
View File

@@ -0,0 +1,2 @@
# Tests for gp library

View File

@@ -0,0 +1,304 @@
import math
import sys
from pathlib import Path
import pytest
# Добавляем путь к родительской директории для корректных импортов
sys.path.insert(0, str(Path(__file__).parent.parent))
from gp.chromosome import Chromosome
from gp.operation import Operation
from gp.ops import ADD, COS, DIV, EXP, MUL, NEG, SIN, SUB
from gp.terminal import Terminal
class TestChromosomeEval:
"""Тесты для метода eval класса Chromosome."""
def test_eval_single_terminal(self):
"""Тест вычисления хромосомы с одним терминалом."""
x = Terminal("x")
def init_single_terminal(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(x, [])
chromosome = Chromosome([ADD], [x], init_single_terminal)
result = chromosome.eval([5.0])
assert result == 5.0
result = chromosome.eval([-3.5])
assert result == -3.5
def test_eval_addition(self):
"""Тест вычисления простого сложения: x + y."""
x = Terminal("x")
y = Terminal("y")
def init_addition(chr: Chromosome) -> Chromosome.Node:
# Создаём дерево: x + y
return Chromosome.Node(
ADD,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
chromosome = Chromosome([ADD], [x, y], init_addition)
result = chromosome.eval([3.0, 4.0])
assert result == 7.0
result = chromosome.eval([10.0, -5.0])
assert result == 5.0
def test_eval_subtraction(self):
"""Тест вычисления вычитания: x - y."""
x = Terminal("x")
y = Terminal("y")
def init_subtraction(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(
SUB,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
chromosome = Chromosome([SUB], [x, y], init_subtraction)
result = chromosome.eval([10.0, 3.0])
assert result == 7.0
result = chromosome.eval([5.0, 8.0])
assert result == -3.0
def test_eval_multiplication(self):
"""Тест вычисления умножения: x * y."""
x = Terminal("x")
y = Terminal("y")
def init_multiplication(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(
MUL,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
chromosome = Chromosome([MUL], [x, y], init_multiplication)
result = chromosome.eval([3.0, 4.0])
assert result == 12.0
result = chromosome.eval([-2.0, 5.0])
assert result == -10.0
def test_eval_division(self):
"""Тест вычисления деления: x / y."""
x = Terminal("x")
y = Terminal("y")
def init_division(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(
DIV,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
chromosome = Chromosome([DIV], [x, y], init_division)
result = chromosome.eval([10.0, 2.0])
assert result == 5.0
result = chromosome.eval([7.0, 2.0])
assert result == 3.5
def test_eval_division_by_zero(self):
"""Тест деления на ноль (должно вернуть inf)."""
x = Terminal("x")
y = Terminal("y")
def init_division(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(
DIV,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
chromosome = Chromosome([DIV], [x, y], init_division)
result = chromosome.eval([10.0, 0.0])
assert result == float("inf")
def test_eval_unary_negation(self):
"""Тест вычисления унарного минуса: -x."""
x = Terminal("x")
def init_negation(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(NEG, [Chromosome.Node(x, [])])
chromosome = Chromosome([NEG], [x], init_negation)
result = chromosome.eval([5.0])
assert result == -5.0
result = chromosome.eval([-3.0])
assert result == 3.0
def test_eval_sin(self):
"""Тест вычисления синуса: sin(x)."""
x = Terminal("x")
def init_sin(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(SIN, [Chromosome.Node(x, [])])
chromosome = Chromosome([SIN], [x], init_sin)
result = chromosome.eval([0.0])
assert result == pytest.approx(0.0)
result = chromosome.eval([math.pi / 2])
assert result == pytest.approx(1.0)
result = chromosome.eval([math.pi])
assert result == pytest.approx(0.0, abs=1e-10)
def test_eval_cos(self):
"""Тест вычисления косинуса: cos(x)."""
x = Terminal("x")
def init_cos(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(COS, [Chromosome.Node(x, [])])
chromosome = Chromosome([COS], [x], init_cos)
result = chromosome.eval([0.0])
assert result == pytest.approx(1.0)
result = chromosome.eval([math.pi / 2])
assert result == pytest.approx(0.0, abs=1e-10)
result = chromosome.eval([math.pi])
assert result == pytest.approx(-1.0)
def test_eval_complex_expression(self):
"""Тест вычисления сложного выражения: (x + y) * (x - y)."""
x = Terminal("x")
y = Terminal("y")
def init_complex(chr: Chromosome) -> Chromosome.Node:
# (x + y) * (x - y)
return Chromosome.Node(
MUL,
[
Chromosome.Node(
ADD,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
),
Chromosome.Node(
SUB,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
),
],
)
chromosome = Chromosome([ADD, SUB, MUL], [x, y], init_complex)
# (5 + 3) * (5 - 3) = 8 * 2 = 16
result = chromosome.eval([5.0, 3.0])
assert result == 16.0
# (10 + 2) * (10 - 2) = 12 * 8 = 96
result = chromosome.eval([10.0, 2.0])
assert result == 96.0
def test_eval_nested_expression(self):
"""Тест вычисления вложенного выражения: sin(x + y)."""
x = Terminal("x")
y = Terminal("y")
def init_nested(chr: Chromosome) -> Chromosome.Node:
# sin(x + y)
return Chromosome.Node(
SIN,
[
Chromosome.Node(
ADD,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
],
)
chromosome = Chromosome([ADD, SIN], [x, y], init_nested)
result = chromosome.eval([math.pi / 4, math.pi / 4])
# sin(π/4 + π/4) = sin(π/2) = 1
assert result == pytest.approx(1.0)
def test_eval_exp(self):
"""Тест вычисления экспоненты: exp(x)."""
x = Terminal("x")
def init_exp(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(EXP, [Chromosome.Node(x, [])])
chromosome = Chromosome([EXP], [x], init_exp)
result = chromosome.eval([0.0])
assert result == pytest.approx(1.0)
result = chromosome.eval([1.0])
assert result == pytest.approx(math.e)
result = chromosome.eval([2.0])
assert result == pytest.approx(math.e**2)
def test_eval_multiple_calls(self):
"""Тест многократного вызова eval с разными значениями."""
x = Terminal("x")
y = Terminal("y")
def init_mul(chr: Chromosome) -> Chromosome.Node:
return Chromosome.Node(
MUL,
[
Chromosome.Node(x, []),
Chromosome.Node(y, []),
],
)
chromosome = Chromosome([MUL], [x, y], init_mul)
# Проверяем, что терминалы правильно обновляются
assert chromosome.eval([2.0, 3.0]) == 6.0
assert chromosome.eval([4.0, 5.0]) == 20.0
assert chromosome.eval([10.0, 0.5]) == 5.0
def test_eval_without_root_raises_error(self):
"""Тест, что eval вызывает ошибку, если root = None."""
def init_none(chr: Chromosome) -> Chromosome.Node:
return None # type: ignore
chromosome = Chromosome([ADD], [Terminal("x")], init_none)
with pytest.raises(ValueError, match="Chromosome is not initialized"):
chromosome.eval([1.0])