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

1# -*- coding: utf-8 -*- 

2 

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""" 

10 

11# ============================================================================== 

12# IMPORT PYTHON DEPENDENCIES 

13# ============================================================================== 

14 

15import pytest 

16 

17from cognitivefactory.interactive_clustering.constraints.binary import ( 

18 BinaryConstraintsManager, 

19 load_constraints_manager_from_json, 

20) 

21 

22 

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 """ 

30 

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

36 

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

42 

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

48 

49 

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 """ 

57 

58 # Initialize a classic binaray constraints manager. 

59 constraints_manager = BinaryConstraintsManager( 

60 list_of_data_IDs=["first", "second", "third"], 

61 ) 

62 

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 ) 

68 

69 # Run assertions. 

70 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "second", "third"] 

71 

72 

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 """ 

80 

81 # Initialize a classic binaray constraints manager. 

82 constraints_manager = BinaryConstraintsManager( 

83 list_of_data_IDs=["first", "second", "third"], 

84 ) 

85 

86 # Try to add `"fourth"` data ID. 

87 assert ( 

88 constraints_manager.add_data_ID( 

89 data_ID="fourth", 

90 ) 

91 is True 

92 ) 

93 

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 ) 

124 

125 

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 """ 

133 

134 # Initialize a classic binaray constraints manager. 

135 constraints_manager = BinaryConstraintsManager( 

136 list_of_data_IDs=["first", "second", "third"], 

137 ) 

138 

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 ) 

144 

145 # Run assertions. 

146 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "second", "third"] 

147 

148 

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 """ 

156 

157 # Initialize a classic binaray constraints manager. 

158 constraints_manager = BinaryConstraintsManager( 

159 list_of_data_IDs=["first", "second", "third"], 

160 ) 

161 

162 # Try to delete `"second"` data ID. 

163 assert ( 

164 constraints_manager.delete_data_ID( 

165 data_ID="second", 

166 ) 

167 is True 

168 ) 

169 

170 # Run assertions. 

171 assert constraints_manager.get_list_of_managed_data_IDs() == ["first", "third"] 

172 

173 

174# ============================================================================== 

175# test_BinaryConstraintsManager_get_list_of_managed_data_IDs 

176# ============================================================================== 

177 

178# Not implemented because `get_list_of_managed_data_IDs` is already tested in other unittests. 

179 

180 

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 """ 

188 

189 # Initialize a classic binaray constraints manager. 

190 constraints_manager = BinaryConstraintsManager( 

191 list_of_data_IDs=["first", "second", "third"], 

192 ) 

193 

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 ) 

201 

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 ) 

209 

210 

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 """ 

218 

219 # Initialize a classic binaray constraints manager. 

220 constraints_manager = BinaryConstraintsManager( 

221 list_of_data_IDs=["first", "second", "third"], 

222 ) 

223 

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 ) 

231 

232 

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 """ 

240 

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 ) 

255 

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 ) 

265 

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 ) 

273 

274 

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 """ 

282 

283 # Initialize a classic binaray constraints manager. 

284 constraints_manager = BinaryConstraintsManager( 

285 list_of_data_IDs=["first", "second", "third"], 

286 ) 

287 

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) 

301 

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) 

315 

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 ) 

323 

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) 

337 

338 

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 """ 

346 

347 # Initialize a classic binaray constraints manager. 

348 constraints_manager = BinaryConstraintsManager( 

349 list_of_data_IDs=["first", "second", "third"], 

350 ) 

351 

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 ) 

358 

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 ) 

365 

366 

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 """ 

374 

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 ) 

389 

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 ! 

412 

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 

435 

436 

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 """ 

444 

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 ) 

459 

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 ) 

466 

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 ) 

473 

474 

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 """ 

482 

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 ) 

497 

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) 

503 

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) 

509 

510 

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 """ 

518 

519 # Initialize a classic binaray constraints manager. 

520 constraints_manager = BinaryConstraintsManager( 

521 list_of_data_IDs=["first", "second", "third"], 

522 ) 

523 

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 ) 

530 

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 ) 

537 

538 

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 """ 

546 

547 # Initialize a classic binaray constraints manager. 

548 constraints_manager = BinaryConstraintsManager( 

549 list_of_data_IDs=["first", "second", "third"], 

550 ) 

551 

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 ) 

558 

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 ) 

567 

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 ) 

576 

577 

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 """ 

585 

586 # Initialize a classic binaray constraints manager. 

587 constraints_manager = BinaryConstraintsManager( 

588 list_of_data_IDs=["first", "second", "third", "fourth"], 

589 ) 

590 

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 ) 

609 

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

613 

614 

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 """ 

622 

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 

628 

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 

636 

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 

644 

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 

652 

653 

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 """ 

661 

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 

669 

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 

679 

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 

689 

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 

699 

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 

709 

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 

719 

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 

730 

731 

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 """ 

739 

740 # Initialize a classic binaray constraints manager. 

741 constraints_manager = BinaryConstraintsManager( 

742 list_of_data_IDs=["first", "second", "third"], 

743 ) 

744 

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 ) 

757 

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 ) 

781 

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 ) 

805 

806 

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 """ 

814 

815 # Initialize a classic binaray constraints manager. 

816 constraints_manager = BinaryConstraintsManager( 

817 list_of_data_IDs=["first", "second", "third", "fourth"], 

818 ) 

819 

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 ) 

838 

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 ) 

868 

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 ) 

898 

899 

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 """ 

907 

908 # Initialize a classic binaray constraints manager. 

909 constraints_manager = BinaryConstraintsManager( 

910 list_of_data_IDs=["first", "second", "third"], 

911 ) 

912 

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 ) 

924 

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 ) 

954 

955 

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 """ 

963 

964 # Initialize a classic binaray constraints manager. 

965 constraints_manager = BinaryConstraintsManager( 

966 list_of_data_IDs=["first", "second", "third", "fourth"], 

967 ) 

968 

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 ) 

975 

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 ) 

996 

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 ) 

1017 

1018 # Delete constraint between `"second"` and `"first"`. 

1019 constraints_manager.delete_constraint( 

1020 data_ID1="second", 

1021 data_ID2="first", 

1022 ) 

1023 

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 ) 

1053 

1054 

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 """ 

1062 

1063 # Initialize a classic binaray constraints manager. 

1064 constraints_manager = BinaryConstraintsManager( 

1065 list_of_data_IDs=["first", "second", "third", "fourth"], 

1066 ) 

1067 

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 ) 

1094 

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 ) 

1115 

1116 # Delete data ID `"second"`. 

1117 constraints_manager.delete_data_ID( 

1118 data_ID="second", 

1119 ) 

1120 

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 ) 

1150 

1151 

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 """ 

1159 

1160 # Initialize a classic binary constraints manager. 

1161 constraints_manager = BinaryConstraintsManager( 

1162 list_of_data_IDs=["first", "second", "third"], 

1163 ) 

1164 

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 ) 

1172 

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 ) 

1180 

1181 

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 """ 

1189 

1190 # Initialize a classic binary constraints manager. 

1191 constraints_manager = BinaryConstraintsManager( 

1192 list_of_data_IDs=["first", "second", "third"], 

1193 ) 

1194 

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 ) 

1202 

1203 

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 """ 

1211 

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 ) 

1236 

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

1243 

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

1250 

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 ) 

1260 

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 ) 

1270 

1271 

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 """ 

1279 

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 ) 

1294 

1295 # Serialize to JSON. 

1296 constraints_manager_1.to_json( 

1297 filepath="./tests/temp/test_BinaryConstraintsManager_to_json__constraints_manager_1.json", 

1298 ) 

1299 

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 ) 

1304 

1305 # Assert type. 

1306 assert isinstance(constraints_manager_2, BinaryConstraintsManager) 

1307 

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

1310 

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

1318 

1319 # Assert constraints transitivity. 

1320 

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