Coverage for tests\constraints\test_binary.py: 100.00%
238 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-17 13:31 +0100
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-17 13:31 +0100
1# -*- coding: utf-8 -*-
3"""
4* Name: interactive-clustering/tests/constraints/test_binary.py
5* Description: Unittests for the `constraints.binary` module.
6* Author: Erwan SCHILD
7* Created: 17/03/2021
8* Licence: CeCILL (https://cecill.info/licences.fr.html)
9"""
11# ==============================================================================
12# IMPORT PYTHON DEPENDENCIES
13# ==============================================================================
15import pytest
17from cognitivefactory.interactive_clustering.constraints.binary import (
18 BinaryConstraintsManager,
19 load_constraints_manager_from_json,
20)
23# ==============================================================================
24# test_BinaryConstraintsManager_init
25# ==============================================================================
26def test_BinaryConstraintsManager_init():
27 """
28 Test that the `__init__` method of the `constraints.binary.BinaryConstraintsManager` class works.
29 """
31 # Initialize an empty binaray constraints manager.
32 constraints_manager_1 = BinaryConstraintsManager(
33 list_of_data_IDs=[],
34 )
35 assert not constraints_manager_1.get_list_of_managed_data_IDs()
37 # Initialize a classic binaray constraints manager.
38 constraints_manager_2 = BinaryConstraintsManager(
39 list_of_data_IDs=["first", "second", "third"],
40 )
41 assert constraints_manager_2.get_list_of_managed_data_IDs() == ["first", "second", "third"]
43 # Initialize a binaray constraints manager with duplicates in `list_of_data_IDs`.
44 constraints_manager_3 = BinaryConstraintsManager(
45 list_of_data_IDs=["first", "second", "same", "same"],
46 )
47 assert constraints_manager_3.get_list_of_managed_data_IDs() == ["first", "second", "same"]
50# ==============================================================================
51# test_BinaryConstraintsManager_add_data_ID_with_incorrect_data_ID
52# ==============================================================================
53def test_BinaryConstraintsManager_add_data_ID_with_incorrect_data_ID():
54 """
55 Test that the `add_data_ID` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for an incorrect data ID.
56 """
58 # Initialize a classic binaray constraints manager.
59 constraints_manager = BinaryConstraintsManager(
60 list_of_data_IDs=["first", "second", "third"],
61 )
63 # Try to add `"second"` data ID.
64 with pytest.raises(ValueError, match="`data_ID`"):
65 constraints_manager.add_data_ID(
66 data_ID="second",
67 )
69 # Run assertions.
70 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "second", "third"]
73# ==============================================================================
74# test_BinaryConstraintsManager_add_data_ID_with_correct_parameters
75# ==============================================================================
76def test_BinaryConstraintsManager_add_data_ID_with_correct_parameters():
77 """
78 Test that the `add_data_ID` method of the `constraints.binary.BinaryConstraintsManager` class returns `True` for a correct parameters.
79 """
81 # Initialize a classic binaray constraints manager.
82 constraints_manager = BinaryConstraintsManager(
83 list_of_data_IDs=["first", "second", "third"],
84 )
86 # Try to add `"fourth"` data ID.
87 assert (
88 constraints_manager.add_data_ID(
89 data_ID="fourth",
90 )
91 is True
92 )
94 # Run assertions.
95 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "second", "third", "fourth"]
96 assert (
97 constraints_manager.get_inferred_constraint(
98 data_ID1="first",
99 data_ID2="fourth",
100 )
101 is None
102 )
103 assert (
104 constraints_manager.get_inferred_constraint(
105 data_ID1="second",
106 data_ID2="fourth",
107 )
108 is None
109 )
110 assert (
111 constraints_manager.get_inferred_constraint(
112 data_ID1="third",
113 data_ID2="fourth",
114 )
115 is None
116 )
117 assert (
118 constraints_manager.get_inferred_constraint(
119 data_ID1="fourth",
120 data_ID2="fourth",
121 )
122 == "MUST_LINK"
123 )
126# ==============================================================================
127# test_BinaryConstraintsManager_delete_data_ID_with_incorrect_data_ID
128# ==============================================================================
129def test_BinaryConstraintsManager_delete_data_ID_with_incorrect_data_ID():
130 """
131 Test that the `delete_data_ID` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for an incorrect data ID.
132 """
134 # Initialize a classic binaray constraints manager.
135 constraints_manager = BinaryConstraintsManager(
136 list_of_data_IDs=["first", "second", "third"],
137 )
139 # Try to delete `"unknown"` data ID.
140 with pytest.raises(ValueError, match="`data_ID`"):
141 constraints_manager.delete_data_ID(
142 data_ID="unknown",
143 )
145 # Run assertions.
146 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "second", "third"]
149# ==============================================================================
150# test_BinaryConstraintsManager_delete_data_ID_with_correct_parameters
151# ==============================================================================
152def test_BinaryConstraintsManager_delete_data_ID_with_correct_parameters():
153 """
154 Test that the `delete_data_ID` method of the `constraints.binary.BinaryConstraintsManager` class returns `True` for a correct parameters.
155 """
157 # Initialize a classic binaray constraints manager.
158 constraints_manager = BinaryConstraintsManager(
159 list_of_data_IDs=["first", "second", "third"],
160 )
162 # Try to delete `"second"` data ID.
163 assert (
164 constraints_manager.delete_data_ID(
165 data_ID="second",
166 )
167 is True
168 )
170 # Run assertions.
171 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "third"]
174# ==============================================================================
175# test_BinaryConstraintsManager_get_list_of_managed_data_IDs
176# ==============================================================================
178# Not implemented because `get_list_of_managed_data_IDs` is already tested in other unittests.
181# ==============================================================================
182# test_BinaryConstraintsManager_add_constraint_with_incorrect_data_ID
183# ==============================================================================
184def test_BinaryConstraintsManager_add_constraint_with_incorrect_data_ID():
185 """
186 Test that the `add_constraint` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for incorrect data IDs.
187 """
189 # Initialize a classic binaray constraints manager.
190 constraints_manager = BinaryConstraintsManager(
191 list_of_data_IDs=["first", "second", "third"],
192 )
194 # Try to add the constraint with `"unknown"` data ID in `"data_ID1"`.
195 with pytest.raises(ValueError, match="`data_ID1`"):
196 constraints_manager.add_constraint(
197 data_ID1="unknown",
198 data_ID2="second",
199 constraint_type="MUST_LINK",
200 )
202 # Try to add the constraint with `"unknown"` data ID in `"data_ID2"`.
203 with pytest.raises(ValueError, match="`data_ID2`"):
204 constraints_manager.add_constraint(
205 data_ID1="first",
206 data_ID2="unknown",
207 constraint_type="CANNOT_LINK",
208 )
211# ==============================================================================
212# test_BinaryConstraintsManager_add_constraint_with_incorrect_constraint_type
213# ==============================================================================
214def test_BinaryConstraintsManager_add_constraint_with_incorrect_constraint_type():
215 """
216 Test that the `add_constraint` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for an incorrect constraint type.
217 """
219 # Initialize a classic binaray constraints manager.
220 constraints_manager = BinaryConstraintsManager(
221 list_of_data_IDs=["first", "second", "third"],
222 )
224 # Try to add the constraint with `"UNKNOWN_LINK"` constraint type in `"constraint_type"`.
225 with pytest.raises(ValueError, match="`constraint_type`"):
226 constraints_manager.add_constraint(
227 data_ID1="first",
228 data_ID2="second",
229 constraint_type="UNKNOWN_LINK",
230 )
233# ==============================================================================
234# test_BinaryConstraintsManager_add_constraint_with_already_linked_data_IDs
235# ==============================================================================
236def test_BinaryConstraintsManager_add_constraint_with_already_linked_data_IDs():
237 """
238 Test that the `add_constraint` method of the `constraints.binary.BinaryConstraintsManager` class works for already linked data IDs.
239 """
241 # Initialize a classic binaray constraints manager.
242 constraints_manager = BinaryConstraintsManager(
243 list_of_data_IDs=["first", "second", "third"],
244 )
245 constraints_manager.add_constraint(
246 data_ID1="first",
247 data_ID2="second",
248 constraint_type="MUST_LINK",
249 )
250 constraints_manager.add_constraint(
251 data_ID1="first",
252 data_ID2="third",
253 constraint_type="CANNOT_LINK",
254 )
256 # Try to add `"MUST_LINK"` data ID between `"first"` and `"second"` data IDs.
257 assert (
258 constraints_manager.add_constraint(
259 data_ID1="first",
260 data_ID2="second",
261 constraint_type="MUST_LINK",
262 )
263 is True
264 )
266 # Try to add `"CANNOT_LINK"` data ID between `"first"` and `"second"` data IDs.
267 with pytest.raises(ValueError, match="`constraint_type`"):
268 constraints_manager.add_constraint(
269 data_ID1="first",
270 data_ID2="second",
271 constraint_type="CANNOT_LINK",
272 )
275# ==============================================================================
276# test_BinaryConstraintsManager_add_constraint_with_not_already_linked_data_IDs
277# ==============================================================================
278def test_BinaryConstraintsManager_add_constraint_with_not_already_linked_data_IDs():
279 """
280 Test that the `add_constraint` method of the `constraints.binary.BinaryConstraintsManager` class works for not already linked data IDs.
281 """
283 # Initialize a classic binaray constraints manager.
284 constraints_manager = BinaryConstraintsManager(
285 list_of_data_IDs=["first", "second", "third"],
286 )
288 # Try to add `"MUST_LINK"` data ID between `"first"` and `"second"` data IDs.
289 assert (
290 constraints_manager.add_constraint(
291 data_ID1="first",
292 data_ID2="second",
293 constraint_type="MUST_LINK",
294 )
295 is True
296 )
297 assert constraints_manager.get_added_constraint(
298 data_ID1="first",
299 data_ID2="second",
300 ) == ("MUST_LINK", 1.0)
302 # Try to add `"CANNOT_LINK"` data ID between `"first"` and `"third"` data IDs.
303 assert (
304 constraints_manager.add_constraint(
305 data_ID1="first",
306 data_ID2="third",
307 constraint_type="CANNOT_LINK",
308 )
309 is True
310 )
311 assert constraints_manager.get_added_constraint(
312 data_ID1="first",
313 data_ID2="third",
314 ) == ("CANNOT_LINK", 1.0)
316 # Try to add `"MUST_LINK"` data ID between `"second"` and `"third"` data IDs.
317 with pytest.raises(ValueError, match="`constraint_type`"):
318 constraints_manager.add_constraint(
319 data_ID1="second",
320 data_ID2="third",
321 constraint_type="MUST_LINK",
322 )
324 # Try to add `"CANNOT_LINK"` data ID between `"second"` and `"third"` data IDs.
325 assert (
326 constraints_manager.add_constraint(
327 data_ID1="second",
328 data_ID2="third",
329 constraint_type="CANNOT_LINK",
330 )
331 is True
332 )
333 assert constraints_manager.get_added_constraint(
334 data_ID1="second",
335 data_ID2="third",
336 ) == ("CANNOT_LINK", 1.0)
339# ==============================================================================
340# test_BinaryConstraintsManager_delete_constraint_with_incorrect_data_IDs
341# ==============================================================================
342def test_BinaryConstraintsManager_delete_constraint_with_incorrect_data_IDs():
343 """
344 Test that the `delete_constraint` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for incorrect data IDs.
345 """
347 # Initialize a classic binaray constraints manager.
348 constraints_manager = BinaryConstraintsManager(
349 list_of_data_IDs=["first", "second", "third"],
350 )
352 # Try to delete constraint with `"unknown"` data ID in `"data_ID1"`.
353 with pytest.raises(ValueError, match="`data_ID1`"):
354 constraints_manager.delete_constraint(
355 data_ID1="unknown",
356 data_ID2="second",
357 )
359 # Try to delete constraint with `"unknown"` data ID in `"data_ID2"`.
360 with pytest.raises(ValueError, match="`data_ID2`"):
361 constraints_manager.delete_constraint(
362 data_ID1="first",
363 data_ID2="unknown",
364 )
367# ==============================================================================
368# test_BinaryConstraintsManager_delete_constraint_with_correct_parameters
369# ==============================================================================
370def test_BinaryConstraintsManager_delete_constraint_with_correct_parameters():
371 """
372 Test that the `delete_constraint` method of the `constraints.binary.BinaryConstraintsManager` returns `True` for correct parameters.
373 """
375 # Initialize a classic binaray constraints manager.
376 constraints_manager = BinaryConstraintsManager(
377 list_of_data_IDs=["first", "second", "third"],
378 )
379 constraints_manager.add_constraint(
380 data_ID1="first",
381 data_ID2="second",
382 constraint_type="MUST_LINK",
383 )
384 constraints_manager.add_constraint(
385 data_ID1="first",
386 data_ID2="third",
387 constraint_type="CANNOT_LINK",
388 )
390 # Try to delete constraint betwenn `"second"` and `"third"` data IDs.
391 assert (
392 constraints_manager.delete_constraint(
393 data_ID1="second",
394 data_ID2="third",
395 )
396 is True
397 )
398 assert (
399 constraints_manager.get_added_constraint(
400 data_ID1="second",
401 data_ID2="third",
402 )
403 is None
404 )
405 assert (
406 constraints_manager.get_inferred_constraint(
407 data_ID1="second",
408 data_ID2="third",
409 )
410 == "CANNOT_LINK"
411 ) # transitivity activated !
413 # Try to delete constraint betwenn `"first"` and `"third"` data IDs.
414 assert (
415 constraints_manager.delete_constraint(
416 data_ID1="first",
417 data_ID2="third",
418 )
419 is True
420 )
421 assert (
422 constraints_manager.get_added_constraint(
423 data_ID1="first",
424 data_ID2="third",
425 )
426 is None
427 )
428 assert (
429 constraints_manager.get_added_constraint(
430 data_ID1="second",
431 data_ID2="third",
432 )
433 is None
434 ) # No more transitivity
437# ==============================================================================
438# test_BinaryConstraintsManager_get_added_constraint_with_incorrect_data_ID
439# ==============================================================================
440def test_BinaryConstraintsManager_get_added_constraint_with_incorrect_data_ID():
441 """
442 Test that the `get_added_constraint` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for an incorrect data ID.
443 """
445 # Initialize a classic binaray constraints manager.
446 constraints_manager = BinaryConstraintsManager(
447 list_of_data_IDs=["first", "second", "third"],
448 )
449 constraints_manager.add_constraint(
450 data_ID1="first",
451 data_ID2="second",
452 constraint_type="MUST_LINK",
453 )
454 constraints_manager.add_constraint(
455 data_ID1="first",
456 data_ID2="third",
457 constraint_type="CANNOT_LINK",
458 )
460 # Try to get the constraint with `"unknown"` data ID in `"data_ID1"`.
461 with pytest.raises(ValueError, match="`data_ID1`"):
462 constraints_manager.get_added_constraint(
463 data_ID1="unknown",
464 data_ID2="second",
465 )
467 # Try to get the constraint with `"unknown"` data ID in `"data_ID2"`.
468 with pytest.raises(ValueError, match="`data_ID2`"):
469 constraints_manager.get_added_constraint(
470 data_ID1="first",
471 data_ID2="unknown",
472 )
475# ==============================================================================
476# test_BinaryConstraintsManager_get_added_constraint_with_correct_parameters
477# ==============================================================================
478def test_BinaryConstraintsManager_get_added_constraint_with_correct_parameters():
479 """
480 Test that the `get_added_constraint` method of the `constraints.binary.BinaryConstraintsManager` class returns `True` for correct parameters.
481 """
483 # Initialize a classic binaray constraints manager.
484 constraints_manager = BinaryConstraintsManager(
485 list_of_data_IDs=["first", "second", "third"],
486 )
487 constraints_manager.add_constraint(
488 data_ID1="first",
489 data_ID2="second",
490 constraint_type="MUST_LINK",
491 )
492 constraints_manager.add_constraint(
493 data_ID1="first",
494 data_ID2="third",
495 constraint_type="CANNOT_LINK",
496 )
498 # Try to get the constraint betwwen `"first"` and `"second"`.
499 assert constraints_manager.get_added_constraint(
500 data_ID1="first",
501 data_ID2="second",
502 ) == ("MUST_LINK", 1.0)
504 # Try to get the constraint betwwen `"first"` and `"third"`.
505 assert constraints_manager.get_added_constraint(
506 data_ID1="first",
507 data_ID2="third",
508 ) == ("CANNOT_LINK", 1.0)
511# ==============================================================================
512# test_BinaryConstraintsManager_get_inferred_constraint_with_incorrect_data_ID
513# ==============================================================================
514def test_BinaryConstraintsManager_get_inferred_constraint_with_incorrect_data_ID():
515 """
516 Test that the `get_inferred_constraint` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for an incorrect data ID.
517 """
519 # Initialize a classic binaray constraints manager.
520 constraints_manager = BinaryConstraintsManager(
521 list_of_data_IDs=["first", "second", "third"],
522 )
524 # Try `get_inferred_constraint` method with `"unknown"` data ID in `data_ID1`.
525 with pytest.raises(ValueError, match="`data_ID1`"):
526 constraints_manager.get_inferred_constraint(
527 data_ID1="unknown",
528 data_ID2="second",
529 )
531 # Try `get_inferred_constraint` method with `"unknown"` data ID in `data_ID2`.
532 with pytest.raises(ValueError, match="`data_ID2`"):
533 constraints_manager.get_inferred_constraint(
534 data_ID1="first",
535 data_ID2="unknown",
536 )
539# ==============================================================================
540# test_BinaryConstraintsManager_get_inferred_constraint_with_correct_parameter
541# ==============================================================================
542def test_BinaryConstraintsManager_get_inferred_constraint_with_correct_parameter():
543 """
544 Test that the `get_inferred_constraint` method of the `constraints.binary.BinaryConstraintsManager` class works for a correct data ID.
545 """
547 # Initialize a classic binaray constraints manager.
548 constraints_manager = BinaryConstraintsManager(
549 list_of_data_IDs=["first", "second", "third"],
550 )
552 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
553 constraints_manager.add_constraint(
554 data_ID1="first",
555 data_ID2="second",
556 constraint_type="MUST_LINK",
557 )
559 # Try to check the link bewteen `"first"` and `"second"`data IDs.
560 assert (
561 constraints_manager.get_inferred_constraint(
562 data_ID1="first",
563 data_ID2="second",
564 )
565 == "MUST_LINK"
566 )
568 # Try to check the link bewteen `"first"` and `"third"`data IDs.
569 assert (
570 constraints_manager.get_inferred_constraint(
571 data_ID1="first",
572 data_ID2="third",
573 )
574 is None
575 )
578# ==============================================================================
579# test_BinaryConstraintsManager_get_connected_components
580# ==============================================================================
581def test_BinaryConstraintsManager_get_connected_components():
582 """
583 Test that the `get_connected_components` method of the `constraints.binary.BinaryConstraintsManager` class works.
584 """
586 # Initialize a classic binaray constraints manager.
587 constraints_manager = BinaryConstraintsManager(
588 list_of_data_IDs=["first", "second", "third", "fourth"],
589 )
591 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
592 constraints_manager.add_constraint(
593 data_ID1="first",
594 data_ID2="second",
595 constraint_type="MUST_LINK",
596 )
597 # Add `"MUST_LINK"` constraint between `"second"` and `"third"`.
598 constraints_manager.add_constraint(
599 data_ID1="second",
600 data_ID2="third",
601 constraint_type="MUST_LINK",
602 )
603 # Add `"CANNOT_LINK"` constraint between `"second"` and `"fourth"`.
604 constraints_manager.add_constraint(
605 data_ID1="second",
606 data_ID2="fourth",
607 constraint_type="CANNOT_LINK",
608 )
610 # Try to get the list of connected components.
611 connected_component = constraints_manager.get_connected_components()
612 assert connected_component == [["first", "second", "third"], ["fourth"]]
615# ==============================================================================
616# test_BinaryConstraintsManager_check_completude_of_constraints
617# ==============================================================================
618def test_BinaryConstraintsManager_check_completude_of_constraints():
619 """
620 Test that the `check_completude_of_constraints` method of the `constraints.binary.BinaryConstraintsManager` class works.
621 """
623 # Initialize a classic binaray constraints manager.
624 constraints_manager = BinaryConstraintsManager(
625 list_of_data_IDs=["first", "second", "third", "fourth"],
626 )
627 assert constraints_manager.check_completude_of_constraints() is False
629 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
630 constraints_manager.add_constraint(
631 data_ID1="first",
632 data_ID2="second",
633 constraint_type="MUST_LINK",
634 )
635 assert constraints_manager.check_completude_of_constraints() is False
637 # Add `"MUST_LINK"` constraint between `"second"` and `"third"`.
638 constraints_manager.add_constraint(
639 data_ID1="second",
640 data_ID2="third",
641 constraint_type="MUST_LINK",
642 )
643 assert constraints_manager.check_completude_of_constraints() is False
645 # Add `"CANNOT_LINK"` constraint between `"second"` and `"fourth"`.
646 constraints_manager.add_constraint(
647 data_ID1="second",
648 data_ID2="fourth",
649 constraint_type="CANNOT_LINK",
650 )
651 assert constraints_manager.check_completude_of_constraints() is True
654# ==============================================================================
655# test_BinaryConstraintsManager_get_min_and_max_number_of_clusters
656# ==============================================================================
657def test_BinaryConstraintsManager_get_min_and_max_number_of_clusters():
658 """
659 Test that the `get_min_and_max_number_of_clusters` method of the `constraints.binary.BinaryConstraintsManager` class works.
660 """
662 # Initialize a classic binaray constraints manager.
663 constraints_manager = BinaryConstraintsManager(
664 list_of_data_IDs=["first", "second", "third", "fourth", "fifth", "sixth"],
665 )
666 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
667 assert mini == 2
668 assert maxi == 6
670 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
671 constraints_manager.add_constraint(
672 data_ID1="first",
673 data_ID2="second",
674 constraint_type="MUST_LINK",
675 )
676 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
677 assert mini == 2
678 assert maxi == 5
680 # Add `"CANNOT_LINK"` constraint between `"second"` and `"third"`.
681 constraints_manager.add_constraint(
682 data_ID1="second",
683 data_ID2="third",
684 constraint_type="CANNOT_LINK",
685 )
686 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
687 assert mini == 2
688 assert maxi == 5
690 # Add `"CANNOT_LINK"` constraint between `"second"` and `"fourth"`.
691 constraints_manager.add_constraint(
692 data_ID1="second",
693 data_ID2="fourth",
694 constraint_type="CANNOT_LINK",
695 )
696 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
697 assert mini == 2
698 assert maxi == 5
700 # Add `"CANNOT_LINK"` constraint between `"third"` and `"fourth"`.
701 constraints_manager.add_constraint(
702 data_ID1="third",
703 data_ID2="fourth",
704 constraint_type="CANNOT_LINK",
705 )
706 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
707 assert mini == 3 # 2.99999...
708 assert maxi == 5
710 # Add `"MUST_LINK"` constraint between `"fourth"` and `"fifth"`.
711 constraints_manager.add_constraint(
712 data_ID1="fourth",
713 data_ID2="fifth",
714 constraint_type="MUST_LINK",
715 )
716 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
717 assert mini == 3 # 2.99999...
718 assert maxi == 4
720 # Add `"MUST_LINK"` constraint between `"fourth"` and `"sixth"`.
721 constraints_manager.add_constraint(
722 data_ID1="fourth",
723 data_ID2="sixth",
724 constraint_type="MUST_LINK",
725 )
726 mini, maxi = constraints_manager.get_min_and_max_number_of_clusters()
727 assert mini == 3 # 2.99999...
728 assert maxi == 3
729 assert constraints_manager.check_completude_of_constraints() is True
732# ==============================================================================
733# test_BinaryConstraintsManager_check_symetry_after_constraint_addition
734# ==============================================================================
735def test_BinaryConstraintsManager_check_symetry_after_constraint_addition():
736 """
737 Test that the `add_constraint` method of the `constraints.binary.BinaryConstraintsManager` class is symetric.
738 """
740 # Initialize a classic binaray constraints manager.
741 constraints_manager = BinaryConstraintsManager(
742 list_of_data_IDs=["first", "second", "third"],
743 )
745 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
746 constraints_manager.add_constraint(
747 data_ID1="first",
748 data_ID2="second",
749 constraint_type="MUST_LINK",
750 )
751 # Add `"CANNOT_LINK"` constraint between `"first"` and `"third"`.
752 constraints_manager.add_constraint(
753 data_ID1="first",
754 data_ID2="third",
755 constraint_type="CANNOT_LINK",
756 )
758 # Run assertion on : ML(1,2) => ML(2,1).
759 assert constraints_manager.get_added_constraint(
760 data_ID1="first",
761 data_ID2="second",
762 ) == ("MUST_LINK", 1.0)
763 assert constraints_manager.get_added_constraint(
764 data_ID1="second",
765 data_ID2="first",
766 ) == ("MUST_LINK", 1.0)
767 assert (
768 constraints_manager.get_inferred_constraint(
769 data_ID1="first",
770 data_ID2="second",
771 )
772 == "MUST_LINK"
773 )
774 assert (
775 constraints_manager.get_inferred_constraint(
776 data_ID1="second",
777 data_ID2="first",
778 )
779 == "MUST_LINK"
780 )
782 # Run assertion on : CL(1,3) => CL(3,1).
783 assert constraints_manager.get_added_constraint(
784 data_ID1="first",
785 data_ID2="third",
786 ) == ("CANNOT_LINK", 1.0)
787 assert constraints_manager.get_added_constraint(
788 data_ID1="third",
789 data_ID2="first",
790 ) == ("CANNOT_LINK", 1.0)
791 assert (
792 constraints_manager.get_inferred_constraint(
793 data_ID1="first",
794 data_ID2="third",
795 )
796 == "CANNOT_LINK"
797 )
798 assert (
799 constraints_manager.get_inferred_constraint(
800 data_ID1="third",
801 data_ID2="first",
802 )
803 == "CANNOT_LINK"
804 )
807# ==============================================================================
808# test_BinaryConstraintsManager_check_transitivity_after_constraint_addition
809# ==============================================================================
810def test_BinaryConstraintsManager_check_transitivity_after_constraint_addition():
811 """
812 Test that the `add_constraint` method of the `constraints.binary.BinaryConstraintsManager` class is transitive.
813 """
815 # Initialize a classic binaray constraints manager.
816 constraints_manager = BinaryConstraintsManager(
817 list_of_data_IDs=["first", "second", "third", "fourth"],
818 )
820 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
821 constraints_manager.add_constraint(
822 data_ID1="first",
823 data_ID2="second",
824 constraint_type="MUST_LINK",
825 )
826 # Add `"MUST_LINK"` constraint between `"second"` and `"third"`.
827 constraints_manager.add_constraint(
828 data_ID1="second",
829 data_ID2="third",
830 constraint_type="MUST_LINK",
831 )
832 # Add `"CANNOT_LINK"` constraint between `"second"` and `"fourth"`.
833 constraints_manager.add_constraint(
834 data_ID1="second",
835 data_ID2="fourth",
836 constraint_type="CANNOT_LINK",
837 )
839 # Run assertion on : ML(1,2)+ML(2,3) => ML(1,3) AND ML(3,1).
840 assert (
841 constraints_manager.get_added_constraint(
842 data_ID1="first",
843 data_ID2="third",
844 )
845 is None
846 )
847 assert (
848 constraints_manager.get_added_constraint(
849 data_ID1="third",
850 data_ID2="first",
851 )
852 is None
853 )
854 assert (
855 constraints_manager.get_inferred_constraint(
856 data_ID1="first",
857 data_ID2="third",
858 )
859 == "MUST_LINK"
860 )
861 assert (
862 constraints_manager.get_inferred_constraint(
863 data_ID1="third",
864 data_ID2="first",
865 )
866 == "MUST_LINK"
867 )
869 # Run assertion on : ML(1,2)+CL(2,4) => CL(1,4) AND CL(4,1).
870 assert (
871 constraints_manager.get_added_constraint(
872 data_ID1="first",
873 data_ID2="fourth",
874 )
875 is None
876 )
877 assert (
878 constraints_manager.get_added_constraint(
879 data_ID1="fourth",
880 data_ID2="first",
881 )
882 is None
883 )
884 assert (
885 constraints_manager.get_inferred_constraint(
886 data_ID1="first",
887 data_ID2="fourth",
888 )
889 == "CANNOT_LINK"
890 )
891 assert (
892 constraints_manager.get_inferred_constraint(
893 data_ID1="fourth",
894 data_ID2="first",
895 )
896 == "CANNOT_LINK"
897 )
900# ==============================================================================
901# test_BinaryConstraintsManager_check_symetry_after_constraint_deletion
902# ==============================================================================
903def test_BinaryConstraintsManager_check_symetry_after_constraint_deletion():
904 """
905 Test that the `delete_constraint` method of the `constraints.binary.BinaryConstraintsManager` class is symetric.
906 """
908 # Initialize a classic binaray constraints manager.
909 constraints_manager = BinaryConstraintsManager(
910 list_of_data_IDs=["first", "second", "third"],
911 )
913 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
914 constraints_manager.add_constraint(
915 data_ID1="first",
916 data_ID2="second",
917 constraint_type="MUST_LINK",
918 )
919 # Delete constraint between `"second"` and `"first"`.
920 constraints_manager.delete_constraint(
921 data_ID1="second",
922 data_ID2="first",
923 )
925 # Run assertion (no more symetry).
926 assert (
927 constraints_manager.get_added_constraint(
928 data_ID1="first",
929 data_ID2="second",
930 )
931 is None
932 )
933 assert (
934 constraints_manager.get_added_constraint(
935 data_ID1="second",
936 data_ID2="first",
937 )
938 is None
939 )
940 assert (
941 constraints_manager.get_inferred_constraint(
942 data_ID1="first",
943 data_ID2="second",
944 )
945 is None
946 )
947 assert (
948 constraints_manager.get_inferred_constraint(
949 data_ID1="second",
950 data_ID2="first",
951 )
952 is None
953 )
956# ==============================================================================
957# test_BinaryConstraintsManager_check_transitivity_after_constraint_deletion
958# ==============================================================================
959def test_BinaryConstraintsManager_check_transitivity_after_constraint_deletion():
960 """
961 Test that the `delete_constraint` method of the `constraints.binary.BinaryConstraintsManager` class is transitive.
962 """
964 # Initialize a classic binaray constraints manager.
965 constraints_manager = BinaryConstraintsManager(
966 list_of_data_IDs=["first", "second", "third", "fourth"],
967 )
969 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
970 constraints_manager.add_constraint(
971 data_ID1="first",
972 data_ID2="second",
973 constraint_type="MUST_LINK",
974 )
976 # Add `"MUST_LINK"` constraint between `"second"` and `"third"`.
977 constraints_manager.add_constraint(
978 data_ID1="second",
979 data_ID2="third",
980 constraint_type="MUST_LINK",
981 )
982 assert (
983 constraints_manager.get_inferred_constraint(
984 data_ID1="first",
985 data_ID2="third",
986 )
987 == "MUST_LINK"
988 )
989 assert (
990 constraints_manager.get_inferred_constraint(
991 data_ID1="third",
992 data_ID2="first",
993 )
994 == "MUST_LINK"
995 )
997 # Add `"CANNOT_LINK"` constraint between `"second"` and `"fourth"`.
998 constraints_manager.add_constraint(
999 data_ID1="second",
1000 data_ID2="fourth",
1001 constraint_type="CANNOT_LINK",
1002 )
1003 assert (
1004 constraints_manager.get_inferred_constraint(
1005 data_ID1="first",
1006 data_ID2="fourth",
1007 )
1008 == "CANNOT_LINK"
1009 )
1010 assert (
1011 constraints_manager.get_inferred_constraint(
1012 data_ID1="fourth",
1013 data_ID2="first",
1014 )
1015 == "CANNOT_LINK"
1016 )
1018 # Delete constraint between `"second"` and `"first"`.
1019 constraints_manager.delete_constraint(
1020 data_ID1="second",
1021 data_ID2="first",
1022 )
1024 # Run assertion (no more transitivity).
1025 assert (
1026 constraints_manager.get_inferred_constraint(
1027 data_ID1="first",
1028 data_ID2="third",
1029 )
1030 is None
1031 )
1032 assert (
1033 constraints_manager.get_inferred_constraint(
1034 data_ID1="third",
1035 data_ID2="first",
1036 )
1037 is None
1038 )
1039 assert (
1040 constraints_manager.get_inferred_constraint(
1041 data_ID1="first",
1042 data_ID2="fourth",
1043 )
1044 is None
1045 )
1046 assert (
1047 constraints_manager.get_inferred_constraint(
1048 data_ID1="fourth",
1049 data_ID2="first",
1050 )
1051 is None
1052 )
1055# ==============================================================================
1056# test_BinaryConstraintsManager_check_transitivity_after_data_ID_deletion
1057# ==============================================================================
1058def test_BinaryConstraintsManager_check_transitivity_after_data_ID_deletion():
1059 """
1060 Test that the `delete_data_ID` method of the `constraints.binary.BinaryConstraintsManager` class is transitive.
1061 """
1063 # Initialize a classic binaray constraints manager.
1064 constraints_manager = BinaryConstraintsManager(
1065 list_of_data_IDs=["first", "second", "third", "fourth"],
1066 )
1068 # Add `"MUST_LINK"` constraint between `"first"` and `"second"`.
1069 constraints_manager.add_constraint(
1070 data_ID1="first",
1071 data_ID2="second",
1072 constraint_type="MUST_LINK",
1073 )
1074 # Add `"MUST_LINK"` constraint between `"second"` and `"third"`.
1075 constraints_manager.add_constraint(
1076 data_ID1="second",
1077 data_ID2="third",
1078 constraint_type="MUST_LINK",
1079 )
1080 assert (
1081 constraints_manager.get_inferred_constraint(
1082 data_ID1="first",
1083 data_ID2="third",
1084 )
1085 == "MUST_LINK"
1086 )
1087 assert (
1088 constraints_manager.get_inferred_constraint(
1089 data_ID1="third",
1090 data_ID2="first",
1091 )
1092 == "MUST_LINK"
1093 )
1095 # Add `"CANNOT_LINK"` constraint between `"second"` and `"fourth"`.
1096 constraints_manager.add_constraint(
1097 data_ID1="second",
1098 data_ID2="fourth",
1099 constraint_type="CANNOT_LINK",
1100 )
1101 assert (
1102 constraints_manager.get_inferred_constraint(
1103 data_ID1="first",
1104 data_ID2="fourth",
1105 )
1106 == "CANNOT_LINK"
1107 )
1108 assert (
1109 constraints_manager.get_inferred_constraint(
1110 data_ID1="fourth",
1111 data_ID2="first",
1112 )
1113 == "CANNOT_LINK"
1114 )
1116 # Delete data ID `"second"`.
1117 constraints_manager.delete_data_ID(
1118 data_ID="second",
1119 )
1121 # Run assertion (no more transitivity).
1122 assert (
1123 constraints_manager.get_inferred_constraint(
1124 data_ID1="first",
1125 data_ID2="third",
1126 )
1127 is None
1128 )
1129 assert (
1130 constraints_manager.get_inferred_constraint(
1131 data_ID1="third",
1132 data_ID2="first",
1133 )
1134 is None
1135 )
1136 assert (
1137 constraints_manager.get_inferred_constraint(
1138 data_ID1="first",
1139 data_ID2="fourth",
1140 )
1141 is None
1142 )
1143 assert (
1144 constraints_manager.get_inferred_constraint(
1145 data_ID1="fourth",
1146 data_ID2="first",
1147 )
1148 is None
1149 )
1152# ==============================================================================
1153# test_BinaryConstraintsManager_get_list_of_involved_data_IDs_in_a_constraint_conflict_with_incorrect_data_ID
1154# ==============================================================================
1155def test_BinaryConstraintsManager_get_list_of_involved_data_IDs_in_a_constraint_conflict_with_incorrect_data_ID():
1156 """
1157 Test that the `get_list_of_involved_data_IDs_in_a_constraint_conflict` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for incorrect data IDs.
1158 """
1160 # Initialize a classic binary constraints manager.
1161 constraints_manager = BinaryConstraintsManager(
1162 list_of_data_IDs=["first", "second", "third"],
1163 )
1165 # Try with `"unknown"` data ID in `"data_ID1"`.
1166 with pytest.raises(ValueError, match="`data_ID1`"):
1167 constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1168 data_ID1="unknown",
1169 data_ID2="second",
1170 constraint_type="MUST_LINK",
1171 )
1173 # Try with `"unknown"` data ID in `"data_ID2"`.
1174 with pytest.raises(ValueError, match="`data_ID2`"):
1175 constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1176 data_ID1="first",
1177 data_ID2="unknown",
1178 constraint_type="CANNOT_LINK",
1179 )
1182# ==============================================================================
1183# test_BinaryConstraintsManager_get_list_of_involved_data_IDs_in_a_constraint_conflict_with_incorrect_constraint_type
1184# ==============================================================================
1185def test_BinaryConstraintsManager_get_list_of_involved_data_IDs_in_a_constraint_conflict_with_incorrect_constraint_type():
1186 """
1187 Test that the `get_list_of_involved_data_IDs_in_a_constraint_conflict` method of the `constraints.binary.BinaryConstraintsManager` class raises `ValueError` for an incorrect constraint type.
1188 """
1190 # Initialize a classic binary constraints manager.
1191 constraints_manager = BinaryConstraintsManager(
1192 list_of_data_IDs=["first", "second", "third"],
1193 )
1195 # Try with `"UNKNOWN_LINK"` constraint type in `"constraint_type"`.
1196 with pytest.raises(ValueError, match="`constraint_type`"):
1197 constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1198 data_ID1="first",
1199 data_ID2="second",
1200 constraint_type="UNKNOWN_LINK",
1201 )
1204# ==============================================================================
1205# test_BinaryConstraintsManager_get_list_of_involved_data_IDs_in_a_constraint_conflict
1206# ==============================================================================
1207def test_BinaryConstraintsManager_get_list_of_involved_data_IDs_in_a_constraint_conflict():
1208 """
1209 Test that the `get_list_of_involved_data_IDs_in_a_constraint_conflict` method of the `constraints.binary.BinaryConstraintsManager` class works.
1210 """
1212 # Initialize a classic binary constraints manager.
1213 constraints_manager = BinaryConstraintsManager(
1214 list_of_data_IDs=["first", "second", "third", "fourth", "fifth"],
1215 )
1216 constraints_manager.add_constraint(
1217 data_ID1="first",
1218 data_ID2="second",
1219 constraint_type="MUST_LINK",
1220 )
1221 constraints_manager.add_constraint(
1222 data_ID1="second",
1223 data_ID2="third",
1224 constraint_type="MUST_LINK",
1225 )
1226 constraints_manager.add_constraint(
1227 data_ID1="third",
1228 data_ID2="fourth",
1229 constraint_type="CANNOT_LINK",
1230 )
1231 constraints_manager.add_constraint(
1232 data_ID1="fourth",
1233 data_ID2="fifth",
1234 constraint_type="CANNOT_LINK",
1235 )
1237 # Conflict of adding `"MUST_LINK"` between "first" and "fourth".
1238 assert constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1239 data_ID1="first",
1240 data_ID2="fourth",
1241 constraint_type="MUST_LINK",
1242 ) == ["first", "second", "third", "fourth"]
1244 # Conflict of adding `"CANNOT_LINK"` between "first" and "fourth".
1245 assert constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1246 data_ID1="first",
1247 data_ID2="third",
1248 constraint_type="CANNOT_LINK",
1249 ) == ["first", "second", "third"]
1251 # No conflict.
1252 assert (
1253 constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1254 data_ID1="first",
1255 data_ID2="third",
1256 constraint_type="MUST_LINK",
1257 )
1258 is None
1259 )
1261 # No conflict.
1262 assert (
1263 constraints_manager.get_list_of_involved_data_IDs_in_a_constraint_conflict(
1264 data_ID1="fourth",
1265 data_ID2="fifth",
1266 constraint_type="CANNOT_LINK",
1267 )
1268 is None
1269 )
1272# ==============================================================================
1273# test_BinaryConstraintsManager_serialization
1274# ==============================================================================
1275def test_BinaryConstraintsManager_serialization():
1276 """
1277 Test that `to_json` and `load_constraints_manager_from_json` methods of the `constraints.binary.BinaryConstraintsManager` class work.
1278 """
1280 # Initialize a classic binary constraints manager.
1281 constraints_manager_1 = BinaryConstraintsManager(
1282 list_of_data_IDs=["first", "second", "third"],
1283 )
1284 constraints_manager_1.add_constraint(
1285 data_ID1="first",
1286 data_ID2="second",
1287 constraint_type="MUST_LINK",
1288 )
1289 constraints_manager_1.add_constraint(
1290 data_ID1="second",
1291 data_ID2="third",
1292 constraint_type="CANNOT_LINK",
1293 )
1295 # Serialize to JSON.
1296 constraints_manager_1.to_json(
1297 filepath="./tests/temp/test_BinaryConstraintsManager_to_json__constraints_manager_1.json",
1298 )
1300 # Deserialize from JSON
1301 constraints_manager_2 = load_constraints_manager_from_json(
1302 filepath="./tests/temp/test_BinaryConstraintsManager_to_json__constraints_manager_1.json",
1303 )
1305 # Assert type.
1306 assert isinstance(constraints_manager_2, BinaryConstraintsManager)
1308 # Assert data IDs storage is the same.
1309 assert constraints_manager_1.get_list_of_managed_data_IDs() == constraints_manager_2.get_list_of_managed_data_IDs()
1311 # Assert constraints storage.
1312 assert constraints_manager_1.get_added_constraint(
1313 data_ID1="first", data_ID2="second"
1314 ) == constraints_manager_2.get_added_constraint(data_ID1="first", data_ID2="second")
1315 assert constraints_manager_1.get_added_constraint(
1316 data_ID1="second", data_ID2="third"
1317 ) == constraints_manager_2.get_added_constraint(data_ID1="second", data_ID2="third")
1319 # Assert constraints transitivity.
1321 assert constraints_manager_1.get_inferred_constraint(
1322 data_ID1="first", data_ID2="third"
1323 ) == constraints_manager_2.get_inferred_constraint(data_ID1="first", data_ID2="third")