Files
genetic-algorithms/lab4/tests/test_chromosome.py
2025-11-04 15:02:02 +03:00

305 lines
9.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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])