save
This commit is contained in:
2
lab4/tests/__init__.py
Normal file
2
lab4/tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# Tests for gp library
|
||||
|
||||
304
lab4/tests/test_chromosome.py
Normal file
304
lab4/tests/test_chromosome.py
Normal 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])
|
||||
Reference in New Issue
Block a user