File size: 3,053 Bytes
157b149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""Tests for core/model.py — POMDP state space definitions."""

import numpy as np
import pytest

from mindsphere.core.model import SphereModel, SKILL_FACTORS, SKILL_LEVEL_VALUES


@pytest.fixture
def model():
    return SphereModel()


class TestSphereModel:
    def test_all_factors_have_matrices(self, model):
        """Every factor should have A, B, C, D matrices."""
        for factor in model.get_all_factor_names():
            assert factor in model.A, f"Missing A matrix for {factor}"
            assert factor in model.B, f"Missing B matrix for {factor}"
            assert factor in model.C, f"Missing C matrix for {factor}"
            assert factor in model.D, f"Missing D matrix for {factor}"

    def test_a_matrices_are_valid(self, model):
        """A matrix columns should sum to 1 (valid likelihood)."""
        for factor, A in model.A.items():
            col_sums = A.sum(axis=0)
            np.testing.assert_allclose(
                col_sums, 1.0, atol=0.01,
                err_msg=f"A[{factor}] columns don't sum to 1: {col_sums}"
            )

    def test_b_matrices_are_valid(self, model):
        """B matrix columns should sum to 1 (valid transition)."""
        for factor, B in model.B.items():
            for a in range(B.shape[0]):
                col_sums = B[a].sum(axis=0)
                np.testing.assert_allclose(
                    col_sums, 1.0, atol=0.01,
                    err_msg=f"B[{factor}][action={a}] columns don't sum to 1"
                )

    def test_d_matrices_are_valid(self, model):
        """D vectors should sum to 1 (valid prior)."""
        for factor, D in model.D.items():
            np.testing.assert_allclose(
                D.sum(), 1.0, atol=0.01,
                err_msg=f"D[{factor}] doesn't sum to 1"
            )

    def test_initial_beliefs_match_d(self, model):
        """get_initial_beliefs should return copies of D vectors."""
        beliefs = model.get_initial_beliefs()
        for factor in model.get_all_factor_names():
            np.testing.assert_array_equal(beliefs[factor], model.D[factor])

    def test_skill_score_range(self, model):
        """Skill scores should be in [0, 100]."""
        # All probability on lowest level
        low_belief = np.array([1.0, 0.0, 0.0, 0.0, 0.0])
        assert model.get_skill_score(low_belief) == pytest.approx(10.0)

        # All probability on highest level
        high_belief = np.array([0.0, 0.0, 0.0, 0.0, 1.0])
        assert model.get_skill_score(high_belief) == pytest.approx(90.0)

    def test_eight_skill_factors(self, model):
        """Should have exactly 8 skill factors."""
        assert len(model.spec.skill_factors) == 8

    def test_get_all_skill_scores(self, model):
        """get_all_skill_scores should return dict with 8 entries."""
        beliefs = model.get_initial_beliefs()
        scores = model.get_all_skill_scores(beliefs)
        assert len(scores) == 8
        for skill in SKILL_FACTORS:
            assert skill in scores
            assert 0 <= scores[skill] <= 100