123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731 |
- <?php
- namespace MathPHP\Tests\SetTheory;
- use MathPHP\SetTheory\Set;
- /**
- * Tests of Set axioms
- * These tests don't test specific functions,
- * but rather set axioms which in term make use of multiple functions.
- * If all the set logic is implemented properly, these tests should
- * all work out according to the axioms.
- *
- * Axioms tested:
- * - Subsets
- * - Ø ⊆ A
- * - A ⊆ A
- * - A = B iff A ⊆ B and B ⊆ A
- * - Union
- * - A ∪ B = B ∪ A
- * - A ∪ (B ∪ C) = (A ∪ B) ∪ C
- * - A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C)
- * - A ∪ (A ∩ B) = A
- * - A ⊆ (A ∪ B)
- * - A ∪ A = A
- * - A ∪ Ø = A
- * - |A ∪ B| = |A| + |B| - |A ∩ B|
- * - Intersection
- * - A ∩ B = B ∩ A
- * - A ∩ (B ∩ C) = (A ∩ B) ∩ C
- * - A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C)
- * - A ∩ (A ∪ B) = A
- * - (A ∩ B) ⊆ A
- * - A ∩ A = A
- * - A ∩ Ø = Ø
- * - Complement (difference)
- * - A ∖ B ≠ B ∖ A for A ≠ B
- * - A ∖ A = Ø
- * - Symmetric difference
- * - A Δ B = (A ∖ B) ∪ (B ∖ A)
- * - Cartesian product
- * - A × Ø = Ø
- * - A × (B ∪ C) = (A × B) ∪ (A × C)
- * - (A ∪ B) × C = (A × C) ∪ (B × C)
- * - |A × B| = |A| * |B|
- * - Power set
- * - |S| = n, then |P(S)| = 2ⁿ
- */
- class SetAxiomsTest extends \PHPUnit\Framework\TestCase
- {
- /**
- * @test Axiom: Ø ⊆ A
- * The empty set is a subset of every set
- * @dataProvider dataProviderForSingleSet
- */
- public function testEmptySetSubsetOfEverySet(Set $A)
- {
- // Given
- $Ø = new Set();
- // When
- $isSubset = $Ø->isSubset($A);
- // Then
- $this->assertTrue($isSubset);
- }
- /**
- * @test Axiom: A ⊆ A
- * Every set is a subset of itself
- * @dataProvider dataProviderForSingleSet
- */
- public function testSetIsSubsetOfItself(Set $A)
- {
- // When
- $isSubset = $A->isSubset($A);
- // Then
- $this->assertTrue($isSubset);
- }
- /**
- * @test Axiom: A = B iff A ⊆ B and B ⊆ A
- * Sets are equal if and only if they are both subsets of each other.
- * @dataProvider dataProviderForSingleSet
- */
- public function testEqualSetsAreSubsetsInBothDirections(Set $A)
- {
- // Given
- $B = $A;
- $this->assertEquals($A, $A);
- // Then
- $this->assertTrue($A->isSubset($B));
- $this->assertTrue($B->isSubset($A));
- }
- public function dataProviderForSingleSet(): array
- {
- return [
- [new Set([])],
- [new Set([0])],
- [new Set([1])],
- [new Set([5])],
- [new Set([-5])],
- [new Set([1, 2])],
- [new Set([1, 2, 3])],
- [new Set([1, -2, 3])],
- [new Set([1, 2, 3, 4, 5, 6])],
- [new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])],
- [new Set([1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2, 2.01, 2.001, 2.15])],
- [new Set(['a'])],
- [new Set(['a', 'b'])],
- [new Set(['a', 'b', 'c', 'd', 'e'])],
- [new Set([1, 2, 'a', 'b', 3.14, 'hello', 'goodbye'])],
- [new Set([1, 2, 3, new Set([1, 2]), 'a', 'b'])],
- [new Set(['a', 1, 'b', new Set([1, 'b']), new Set([3, 4, 5]), '4', 5])],
- [new Set(['a', 1, 'b', new Set([1, 'b']), new Set([3, 4, 5]), '4', 5, new Set([3, 4, 5, new Set([1, 2])])])],
- ];
- }
- /**
- * @test Axiom: A ∪ B = B ∪ A
- * Union is commutative
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testUnionCommutative(Set $A, Set $B)
- {
- // Given
- $A∪B = $A->union($B);
- $B∪A = $B->union($A);
- // Then
- $this->assertEquals($A∪B, $B∪A);
- $this->assertEquals($A∪B->asArray(), $B∪A->asArray());
- }
- public function dataProviderForTwoSets(): array
- {
- return [
- [
- new Set([]),
- new Set([]),
- ],
- [
- new Set([1]),
- new Set([]),
- ],
- [
- new Set([]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([2]),
- ],
- [
- new Set([2]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([2]),
- ],
- [
- new Set([2]),
- new Set([1]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b']),
- new Set([1, 'a', 'k']),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set([1, 2])]),
- new Set([1, 'a', 'k']),
- ],
- [
- new Set([1, 2, 3, 'a', 'b']),
- new Set([1, 'a', 'k', new Set([1, 2])]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set()]),
- new Set([1, 'a', 'k', new Set([1, 2])]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set([1, 2])]),
- new Set([1, 'a', 'k', -2, '2.4', 3.5, new Set([1, 2])]),
- ],
- ];
- }
- /**
- * @test Axiom: A ∪ (B ∪ C) = (A ∪ B) ∪ C
- * Unsion is associative
- *
- * @dataProvider dataProviderForThreeSets
- * @param Set $A
- * @param Set $B
- * @param Set $C
- */
- public function testUnsionAssociative(Set $A, Set $B, Set $C)
- {
- // Given
- $A∪⟮B∪C⟯ = $A->union($B->union($C));
- $⟮A∪B⟯∪C = $A->union($B)->union($C);
- // Then
- $this->assertEquals($A∪⟮B∪C⟯, $⟮A∪B⟯∪C);
- $this->assertEquals($A∪⟮B∪C⟯->asArray(), $⟮A∪B⟯∪C->asArray());
- }
- /**
- * @test Axiom: A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C)
- * Union is distributive
- *
- * @dataProvider dataProviderForThreeSets
- * @param Set $A
- * @param Set $B
- * @param Set $C
- */
- public function testUnionDistributive(Set $A, Set $B, Set $C)
- {
- // Given
- $A∪⟮B∩C⟯ = $A->union($B->intersect($C));
- $⟮A∪B⟯∩⟮A∪C⟯ = $A->union($B)->intersect($A->union($C));
- // Then
- $this->assertEquals($A∪⟮B∩C⟯, $⟮A∪B⟯∩⟮A∪C⟯);
- $this->assertEquals($A∪⟮B∩C⟯->asArray(), $⟮A∪B⟯∩⟮A∪C⟯->asArray());
- }
- /**
- * @test Axiom: A ∪ (A ∩ B) = A
- * Union absorbtion law
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testUnionAbsorbtion(Set $A, Set $B)
- {
- // Given
- $A∪⟮B∩C⟯ = $A->union($A->intersect($B));
- // Then
- $this->assertEquals($A, $A∪⟮B∩C⟯);
- $this->assertEquals($A->asArray(), $A∪⟮B∩C⟯->asArray());
- }
- /**
- * @test Axiom: A ⊆ (A ∪ B)
- * A is a subset of A union B
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testAIsSubsetOfAUnionB(Set $A, Set $B)
- {
- // Given
- $A∪B = $A->union($B);
- // Then
- $this->assertTrue($A->isSubset($A∪B));
- $this->assertTrue($B->isSubset($A∪B));
- }
- /**
- * @test Axiom: A ∪ A = A
- * A union A equals A
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testAUnionAEqualsA(Set $A)
- {
- // Given
- $A∪A = $A->union($A);
- // Then
- $this->assertEquals($A, $A∪A);
- $this->assertEquals($A->asArray(), $A∪A->asArray());
- }
- /**
- * @test Axiom: A ∪ Ø = A
- * A union empty set is A
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testAUnionEmptySetEqualsA(Set $A)
- {
- // Given
- $Ø = new Set();
- $A∪Ø = $A->union($Ø);
- // Then
- $this->assertEquals($A, $A∪Ø);
- $this->assertEquals($A->asArray(), $A∪Ø->asArray());
- }
- /**
- * @test Axiom: |A ∪ B| = |A| + |B| - |A ∩ B|
- * The cardinality (count) of unsion of A and B is equal to the cardinality of A + B minus the cardinality of A intersection B
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testCardinalityOfUnion(Set $A, Set $B)
- {
- // Given
- $A∪B = $A->union($B);
- $A∩B = $A->intersect($B);
- // Then
- $this->assertEquals(count($A) + count($B) - count($A∩B), count($A∪B));
- $this->assertEquals(count($A->asArray()) + count($B->asArray()) - count($A∩B->asArray()), count($A∪B->asArray()));
- }
- public function dataProviderForThreeSets(): array
- {
- return [
- [
- new Set([]),
- new Set([]),
- new Set([]),
- ],
- [
- new Set([1]),
- new Set([]),
- new Set([]),
- ],
- [
- new Set([]),
- new Set([]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([1]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([2]),
- new Set([2]),
- ],
- [
- new Set([2]),
- new Set([1]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([2]),
- new Set([3]),
- ],
- [
- new Set([2]),
- new Set([1]),
- new Set([1, 4]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b']),
- new Set([1, 'a', 'k']),
- new Set([1, 9]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set([1, 2])]),
- new Set([1, 'a', 'k']),
- new Set([34, 40]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b']),
- new Set([1, 'a', 'k', new Set([1, 2])]),
- new Set([1, 9, 33]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set()]),
- new Set([1, 'a', 'k', new Set([1, 2])]),
- new Set([1, new Set([1, 2])]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set([1, 2])]),
- new Set([1, 'a', 'k', -2, '2.4', 3.5, new Set([1, 2])]),
- new Set([1, new Set([1, 2])], 99),
- ],
- ];
- }
- /**
- * @test Axiom: A ∩ B = B ∩ A
- * Intersection is commutative
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testIntersectionCommutative(Set $A, Set $B)
- {
- // Given
- $A∩B = $A->intersect($B);
- $B∩A = $B->intersect($A);
- // Then
- $this->assertEquals($A∩B, $B∩A);
- $this->assertEquals($A∩B->asArray(), $B∩A->asArray());
- }
- /**
- * @test Axiom: A ∩ (B ∩ C) = (A ∩ B) ∩ C
- * Intersection is associative
- *
- * @dataProvider dataProviderForThreeSets
- * @param Set $A
- * @param Set $B
- * @param Set $C
- */
- public function testIntersectionAssociative(Set $A, Set $B, Set $C)
- {
- // Given
- $A∩⟮B∩C⟯ = $A->intersect($B->intersect($C));
- $⟮A∩B⟯∩C = $A->intersect($B)->intersect($C);
- // Then
- $this->assertEquals($A∩⟮B∩C⟯, $⟮A∩B⟯∩C);
- $this->assertEquals($A∩⟮B∩C⟯->asArray(), $⟮A∩B⟯∩C->asArray());
- }
- /**
- * @test Axiom: A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C)
- * Intersection is distributive
- *
- * @dataProvider dataProviderForThreeSets
- * @param Set $A
- * @param Set $B
- * @param Set $C
- */
- public function testIntersectionDistributive(Set $A, Set $B, Set $C)
- {
- // Given
- $A∩⟮B∪C⟯ = $A->intersect($B->union($C));
- $⟮A∩B⟯∪⟮A∩C⟯ = $A->intersect($B)->union($A->intersect($C));
- // Then
- $this->assertEquals($A∩⟮B∪C⟯, $⟮A∩B⟯∪⟮A∩C⟯);
- $this->assertEquals($A∩⟮B∪C⟯->asArray(), $⟮A∩B⟯∪⟮A∩C⟯->asArray());
- }
- /**
- * @test Axiom: A ∩ (A ∪ B) = A
- * Intersection absorbtion law
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testIntersectionAbsorbtion(Set $A, Set $B)
- {
- // Given
- $A∩⟮B∪C⟯ = $A->intersect($A->union($B));
- // Then
- $this->assertEquals($A, $A∩⟮B∪C⟯);
- $this->assertEquals($A->asArray(), $A∩⟮B∪C⟯->asArray());
- }
- /**
- * @test Axiom: (A ∩ B) ⊆ A
- * A intersect B is a subset of A
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testAIntersectionBIsSubsetOfA(Set $A, Set $B)
- {
- // Given
- $A∩B = $A->intersect($B);
- // Then
- $this->assertTrue($A∩B->isSubset($A));
- $this->assertTrue($A∩B->isSubset($B));
- }
- /**
- * @test Axiom: A ∩ A = A
- * A intersection A equals A
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testAIntersectionAEqualsA(Set $A)
- {
- // Given
- $A∩A = $A->intersect($A);
- // Then
- $this->assertEquals($A, $A∩A);
- $this->assertEquals($A->asArray(), $A∩A->asArray());
- }
- /**
- * @test Axiom: A ∩ Ø = Ø
- * A union empty set is A
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testAIntersectionEmptySetIsEmptySet(Set $A)
- {
- // Given
- $Ø = new Set();
- $A∩Ø = $A->intersect($Ø);
- // Then
- $this->assertEquals($Ø, $A∩Ø);
- $this->assertEquals($Ø->asArray(), $A∩Ø->asArray());
- }
- /**
- * @test Axiom: A ∖ B ≠ B ∖ A for A ≠ B
- * A diff B does not equal B diff A if A and B are different sets
- *
- * @dataProvider dataProviderForTwoSetsDifferent
- * @param Set $A
- * @param Set $B
- */
- public function testADiffBDifferentFromBDiffAWhenNotEqual(Set $A, Set $B)
- {
- // Given
- $A∖B = $A->difference($B);
- $B∖A = $B->difference($A);
- // Then
- $this->assertNotEquals($A∖B, $B∖A);
- $this->assertNotEquals($A∖B->asArray(), $B∖A->asArray());
- }
- public function dataProviderForTwoSetsDifferent(): array
- {
- return [
- [
- new Set([1]),
- new Set([]),
- ],
- [
- new Set([]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([2]),
- ],
- [
- new Set([2]),
- new Set([1]),
- ],
- [
- new Set([1]),
- new Set([2]),
- ],
- [
- new Set([2]),
- new Set([1]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b']),
- new Set([1, 'a', 'k']),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set([1, 2])]),
- new Set([1, 'a', 'k']),
- ],
- [
- new Set([1, 2, 3, 'a', 'b']),
- new Set([1, 'a', 'k', new Set([1, 2])]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set()]),
- new Set([1, 'a', 'k', new Set([1, 2])]),
- ],
- [
- new Set([1, 2, 3, 'a', 'b', new Set([1, 2])]),
- new Set([1, 'a', 'k', -2, '2.4', 3.5, new Set([1, 2])]),
- ],
- ];
- }
- /**
- * @test Axiom: A ∖ A = Ø
- * A diff itself is the empty set
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testADiffItselfIsEmptySet(Set $A)
- {
- // Given
- $Ø = new Set();
- $A∖A = $A->difference($A);
- // Then
- $this->assertEquals($Ø, $A∖A);
- $this->assertEquals($Ø->asArray(), $A∖A->asArray());
- }
- /**
- * @test Axiom: A Δ B = (A ∖ B) ∪ (B ∖ A)
- * A symmetric different B equals union of A diff B and B diff A
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testASymmetricDifferentBEqualsUnionADiffBAndBDiffA(Set $A, Set $B)
- {
- // Given
- $AΔB = $A->symmetricDifference($B);
- $A∖B = $A->difference($B);
- $B∖A = $B->difference($A);
- $⟮A∖B⟯∪⟮B∖A⟯ = $A∖B->union($B∖A);
- // Then
- $this->assertEquals($AΔB, $⟮A∖B⟯∪⟮B∖A⟯);
- $this->assertEquals($AΔB->asArray(), $⟮A∖B⟯∪⟮B∖A⟯->asArray());
- }
- /**
- * @test Axiom: A × Ø = Ø
- * A cartesian product with empty set is the empty set
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testACartesianProductWithEmptySetIsEmptySet(Set $A)
- {
- // Given
- $Ø = new Set();
- $Aר = $A->cartesianProduct($Ø);
- // Then
- $this->assertEquals($Ø, $Aר);
- }
- /**
- * @test Axiom: A × (B ∪ C) = (A × B) ∪ (A × C)
- * A cross union of B and C is the union of A cross B and A cross C
- *
- * @dataProvider dataProviderForThreeSets
- * @param Set $A
- * @param Set $B
- * @param Set $C
- */
- public function testACrossUnionBCEqualsACrossBUnionACrossC(Set $A, Set $B, Set $C)
- {
- // Given
- $A×⟮B∪C⟯ = $A->cartesianProduct($B->union($C));
- $⟮A×B⟯∪⟮A×C⟯ = $A->cartesianProduct($B)->union($A->cartesianProduct($C));
- // Then
- $this->assertEquals($A×⟮B∪C⟯, $⟮A×B⟯∪⟮A×C⟯);
- $this->assertEquals($A×⟮B∪C⟯->asArray(), $⟮A×B⟯∪⟮A×C⟯->asArray());
- }
- /**
- * @test Axiom: (A ∪ B) × C = (A × C) ∪ (B × C)
- * A union B cross C is the union of A cross C and B cross C
- *
- * @dataProvider dataProviderForThreeSets
- * @param Set $A
- * @param Set $B
- * @param Set $C
- */
- public function testAUnionBCrossCEqualsUnsionOfACRossCAndBCrossC(Set $A, Set $B, Set $C)
- {
- // Given
- $⟮A∪B⟯×C = $A->union($B)->cartesianProduct($C);
- $⟮A×C⟯∪⟮B×C⟯ = $A->cartesianProduct($C)->union($B->cartesianProduct($C));
- // Then
- $this->assertEquals($⟮A∪B⟯×C, $⟮A×C⟯∪⟮B×C⟯);
- $this->assertEquals($⟮A∪B⟯×C->asArray(), $⟮A×C⟯∪⟮B×C⟯->asArray());
- }
- /**
- * @test Axiom: |A × B| - |A| * |B|
- * The cardinality (count) of the cartesian product is the product of the cardinality of A and B
- *
- * @dataProvider dataProviderForTwoSets
- * @param Set $A
- * @param Set $B
- */
- public function testCardinalityOfCartesianProduct(Set $A, Set $B)
- {
- // Given
- $A×B = $A->cartesianProduct($B);
- // Then
- $this->assertEquals(count($A) * count($B), count($A×B));
- $this->assertEquals(count($A->asArray()) * count($B->asArray()), count($A×B->asArray()));
- }
- /**
- * @test Axiom: |S| = n, then |P(S)| = 2ⁿ
- * The cardinality (count) of a power set of S is 2ⁿ if the cardinality of S is n.
- *
- * @dataProvider dataProviderForSingleSet
- * @param Set $A
- */
- public function testCardinalityOfPowerSet(Set $A)
- {
- // Given
- $P⟮S⟯ = $A->powerSet();
- $n = count($A);
- // Then
- $this->assertEquals(\pow(2, $n), count($P⟮S⟯));
- $this->assertEquals(\pow(2, $n), count($P⟮S⟯->asArray()));
- }
- }
|