Skip to content

Commit 12c9b19

Browse files
committed
Fix core consistency test
1 parent 7513a27 commit 12c9b19

File tree

1 file changed

+53
-5
lines changed

1 file changed

+53
-5
lines changed

tests/test_visualisation.py

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,64 @@ def test_core_element_plot_works_labelled_and_unlabelled(seed, labelled):
5353
assert isinstance(ax, matplotlib.axes.Axes)
5454

5555

56+
@pytest.mark.parametrize("weight_scale", [1, 100, 0.01])
5657
@pytest.mark.parametrize("normalised", [True, False])
57-
def test_core_element_plot_normalised_flag(seed, normalised):
58+
def test_core_element_has_correct_title(seed, normalised, weight_scale):
59+
"""This test checks that the title of the core element plot is correct.
60+
61+
There are six scenarios to test (CC=Core consistency):
62+
63+
1. CC = 100, normalised=True
64+
2. CC = 100, normalised=False
65+
3. 0 <= CC < 100, normalised=True
66+
4. 0 <= CC < 100, normalised=False
67+
5. CC < 0, normalised=True
68+
6. CC < 0, normalised=False
69+
70+
To test both scenarios when CC = 100, we have a noise-free dataset and the correct
71+
decomposition.
72+
73+
To test scenario 3, we need that :math:`0 < \|G - T\| \leq \|G\|`. To accomplish this, can
74+
have large entries in :math:`G` that point in the "same direction" as :math:`T`. Similarly, to
75+
test scenario 4, we need that :math:`0 < \|G - T\| \geq R`, which we can accomplish by having
76+
small entries in :math:`G` that point in the "same direction" as :math:`T`.
77+
78+
To test scenario 5, we need that :math:`\|G - T\| > \|G\|`, which we can accomplish by having
79+
small entries in :math:`G`. To test scenario 6, we need that :math:`\|G - T\| > R`, which we
80+
can accomplish by having large entries in :math:`G`.
81+
82+
We can, in other words, create decompositions that cover all 6 above scenarios so long as we
83+
can create decompositions whose optimal core tensor "points in the same direction" as the
84+
superdiagonal tensor consisting only ones and whose optimal core tensor's magnitude we can
85+
control. Luckily, we can control this by only scaling the weights by positive number. Then,
86+
the optimal core tensor will be a superdiagonal tensor whose elements are the reciprocal of
87+
the scaling coefficient.
88+
"""
5889
rank = 3
59-
cp_tensor, X = simulated_random_cp_tensor((10, 20, 30), rank, noise_level=0.2, seed=seed)
60-
# If not normalised
90+
cp_tensor, X = simulated_random_cp_tensor((10, 20, 30), rank, noise_level=0.0, seed=seed)
91+
cp_tensor[0][:] *= weight_scale
92+
6193
ax = visualisation.core_element_plot(cp_tensor, X, normalised=normalised)
6294
title = ax.get_title()
63-
title_core_consistency = float(title.split(": ")[1])
6495
core_consistency = model_evaluation.core_consistency(cp_tensor, X, normalised=normalised)
65-
assert title_core_consistency == pytest.approx(core_consistency, abs=0.1)
96+
97+
# Case 5 and 6, respectively:
98+
if (weight_scale > 1 and normalised) or (weight_scale < 1 and not normalised):
99+
assert title.split(": ")[1] == "<0"
100+
else:
101+
title_core_consistency = float(title.split(": ")[1])
102+
assert title_core_consistency == pytest.approx(core_consistency, abs=0.1)
103+
104+
105+
@pytest.mark.parametrize("weight_scale", [1, 100, 0.01])
106+
@pytest.mark.parametrize("normalised", [True, False])
107+
def test_core_element_has_core_element_scatter_points(seed, normalised, weight_scale):
108+
rank = 3
109+
cp_tensor, X = simulated_random_cp_tensor((10, 20, 30), rank, noise_level=0.1, seed=seed)
110+
cp_tensor[0][:] *= weight_scale
111+
112+
ax = visualisation.core_element_plot(cp_tensor, X, normalised=normalised)
113+
core_consistency = model_evaluation.core_consistency(cp_tensor, X, normalised=normalised)
66114

67115
superdiag_x, superdiag_y = ax.lines[-2].get_data()
68116
offdiag_x, offdiag_y = ax.lines[-1].get_data()

0 commit comments

Comments
 (0)