зеркало из
https://github.com/docxology/cognitive.git
synced 2025-10-30 12:46:04 +02:00
146 строки
5.6 KiB
Python
146 строки
5.6 KiB
Python
"""
|
|
Tests for matrix operations.
|
|
"""
|
|
|
|
import pytest
|
|
import numpy as np
|
|
from src.models.matrices.matrix_ops import MatrixOps, MatrixLoader, MatrixInitializer
|
|
|
|
class TestMatrixOps:
|
|
"""Test matrix operation utilities."""
|
|
|
|
def test_normalize_columns(self, sample_matrix_2d):
|
|
"""Test column normalization."""
|
|
normalized = MatrixOps.normalize_columns(sample_matrix_2d)
|
|
# Check each column sums to 1
|
|
assert np.allclose(normalized.sum(axis=0), 1.0)
|
|
# Check non-negativity preserved
|
|
assert np.all(normalized >= 0)
|
|
|
|
def test_normalize_rows(self, sample_matrix_2d):
|
|
"""Test row normalization."""
|
|
normalized = MatrixOps.normalize_rows(sample_matrix_2d)
|
|
# Check each row sums to 1
|
|
assert np.allclose(normalized.sum(axis=1), 1.0)
|
|
# Check non-negativity preserved
|
|
assert np.all(normalized >= 0)
|
|
|
|
def test_ensure_probability_distribution(self):
|
|
"""Test probability distribution enforcement."""
|
|
# Test with negative values
|
|
matrix = np.array([[-1, 0.5], [2, 0.5]])
|
|
prob_dist = MatrixOps.ensure_probability_distribution(matrix)
|
|
assert np.all(prob_dist >= 0)
|
|
assert np.allclose(prob_dist.sum(axis=0), 1.0)
|
|
|
|
def test_compute_entropy(self, sample_belief_vector):
|
|
"""Test entropy computation."""
|
|
entropy = MatrixOps.compute_entropy(sample_belief_vector)
|
|
# Entropy should be non-negative
|
|
assert entropy >= 0
|
|
# Test with deterministic distribution
|
|
deterministic = np.array([1.0, 0.0, 0.0])
|
|
assert MatrixOps.compute_entropy(deterministic) == 0
|
|
|
|
def test_compute_kl_divergence(self):
|
|
"""Test KL divergence computation."""
|
|
P = np.array([0.5, 0.5])
|
|
Q = np.array([0.9, 0.1])
|
|
kl = MatrixOps.compute_kl_divergence(P, Q)
|
|
# KL divergence should be non-negative
|
|
assert kl >= 0
|
|
# KL divergence should be zero for identical distributions
|
|
assert MatrixOps.compute_kl_divergence(P, P) == 0
|
|
|
|
def test_softmax(self):
|
|
"""Test softmax computation."""
|
|
x = np.array([1.0, 2.0, 3.0])
|
|
probs = MatrixOps.softmax(x)
|
|
# Check output is probability distribution
|
|
assert np.allclose(probs.sum(), 1.0)
|
|
assert np.all(probs >= 0)
|
|
# Check ordering preserved
|
|
assert np.all(np.diff(probs) > 0)
|
|
|
|
class TestMatrixLoader:
|
|
"""Test matrix loading utilities."""
|
|
|
|
def test_load_spec(self, sample_markdown_spec):
|
|
"""Test loading matrix specification from markdown."""
|
|
spec = MatrixLoader.load_spec(sample_markdown_spec)
|
|
assert spec['type'] == 'matrix_spec'
|
|
assert spec['dimensions']['rows'] == 3
|
|
assert 'sum(cols) == 1.0' in spec['shape_constraints']
|
|
|
|
def test_load_matrix(self, sample_matrix_data):
|
|
"""Test loading matrix data from file."""
|
|
matrix = MatrixLoader.load_matrix(sample_matrix_data)
|
|
assert matrix.shape == (3, 3)
|
|
assert np.allclose(matrix.sum(axis=0), 1.0)
|
|
|
|
def test_validate_matrix(self, sample_matrix_2d, sample_matrix_spec):
|
|
"""Test matrix validation against specification."""
|
|
assert MatrixLoader.validate_matrix(sample_matrix_2d, sample_matrix_spec)
|
|
|
|
# Test invalid matrix
|
|
invalid_matrix = np.array([[1.1, -0.1], [0.2, 1.2]])
|
|
assert not MatrixLoader.validate_matrix(invalid_matrix, sample_matrix_spec)
|
|
|
|
class TestMatrixInitializer:
|
|
"""Test matrix initialization utilities."""
|
|
|
|
def test_random_stochastic(self):
|
|
"""Test random stochastic matrix initialization."""
|
|
shape = (3, 3)
|
|
matrix = MatrixInitializer.random_stochastic(shape)
|
|
# Check dimensions
|
|
assert matrix.shape == shape
|
|
# Check stochastic properties
|
|
assert np.allclose(matrix.sum(axis=0), 1.0)
|
|
assert np.all(matrix >= 0)
|
|
|
|
def test_identity_based(self):
|
|
"""Test identity-based matrix initialization."""
|
|
shape = (3, 3)
|
|
strength = 0.9
|
|
matrix = MatrixInitializer.identity_based(shape, strength)
|
|
# Check dimensions
|
|
assert matrix.shape == shape
|
|
# Check diagonal dominance
|
|
assert np.all(np.diag(matrix) > 0.5)
|
|
# Check stochastic properties
|
|
assert np.allclose(matrix.sum(axis=0), 1.0)
|
|
assert np.all(matrix >= 0)
|
|
|
|
def test_uniform(self):
|
|
"""Test uniform matrix initialization."""
|
|
shape = (3, 3)
|
|
matrix = MatrixInitializer.uniform(shape)
|
|
# Check dimensions
|
|
assert matrix.shape == shape
|
|
# Check uniformity
|
|
assert np.allclose(matrix, 1.0/9.0)
|
|
# Check stochastic properties
|
|
assert np.allclose(matrix.sum(), 1.0)
|
|
assert np.all(matrix >= 0)
|
|
|
|
@pytest.mark.parametrize("shape,strength", [
|
|
((2, 2), 0.9),
|
|
((3, 3), 0.8),
|
|
((4, 4), 0.7)
|
|
])
|
|
def test_identity_based_parametrized(shape, strength):
|
|
"""Parametrized tests for identity-based initialization."""
|
|
matrix = MatrixInitializer.identity_based(shape, strength)
|
|
assert matrix.shape == shape
|
|
assert np.all(np.diag(matrix) >= strength * 0.9) # Allow for normalization effects
|
|
assert np.allclose(matrix.sum(axis=0), 1.0)
|
|
|
|
@pytest.mark.parametrize("distribution,expected_entropy", [
|
|
(np.array([1.0, 0.0]), 0.0), # Deterministic
|
|
(np.array([0.5, 0.5]), np.log(2)), # Maximum entropy for 2 states
|
|
])
|
|
def test_entropy_special_cases(distribution, expected_entropy):
|
|
"""Test entropy computation for special cases."""
|
|
computed_entropy = MatrixOps.compute_entropy(distribution)
|
|
assert np.allclose(computed_entropy, expected_entropy) |