Skip to content

Commit

Permalink
Make intersection and isPairwiseDisjoint stricter, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Linus Wagner committed Mar 13, 2024
1 parent c60ae14 commit d29bdf4
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 14 deletions.
49 changes: 38 additions & 11 deletions src/org/rascalmpl/library/Set.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -516,23 +516,50 @@ real jaccard(set[value] x, set[value] y) = (1. * size(x & y)) / size(x + y);


@synopsis{Calculate the intersection of a set of sets.}
public set[&T] intersection({set[&T] firstSet, *set[&T] otherSets}) = (firstSet | it & elem | elem <- otherSets);
public set[&T] intersection({}) = {};
@description{
Can only be applied to sets that contain at least two sets,
because the intersection is generally a binary operator.
Empty sets or sets with one set throw an exception.
}
public set[&T] intersection(wholeSet:{set[&T] firstSet, *set[&T] otherSets}) {
if (otherSets == {}) {
throw IllegalArgument(wholeSet, "Intersection only possible with at least two sets.");
}
return (firstSet | it & elem | elem <- otherSets);
}
public set[&T] intersection(wholeSet:{}) {
throw IllegalArgument(wholeSet, "Intersection only possible with at least two sets.");
}


@synopsis{Checks if all sets in the set are pairwise disjoint.}
@synopsis{Checks if all sets in the list are pairwise disjoint.}
@description{
To allow two elements (i.e. two sets) to be identical, the argument is of type list and not type set.
We follow one definition of pairwise disjoint sets, which does not allow identical sets.
For example, `[{1}, {1}]` is not pairwise disjoint, because it contains two times the same sets.

Can only be applied to lists that contain at least two sets,
because no or only a single set can not be pairwise disjoint.
Empty lists or lists with one set throw an exception.
}
@examples{
```rascal-shell
import Set;
isDisjoint([{1,2}, {3,4}, {5,6}]);
isDisjoint([{1,2}, {1,4}, {5,6}]);
isDisjoint([{1,2}, {1,4}, {1,6}]);
isPairwiseDisjoint([{1,2}, {3,4}, {5,6}]);
isPairwiseDisjoint([{1,2}, {1,4}, {5,6}]);
isPairwiseDisjoint([{1,2}, {1,4}, {1,6}]);
```
}
public bool isDisjoint([set[&T] a, set[&T] b, *_]) = false when a & b != {}; // will backtrack to other pairs of a and b while the condition fails
public default bool isDisjoint([set[&T] a, set[&T] b, *_]) = true;
public bool isDisjoint([set[&T] a]) = true;
public bool isDisjoint([]) = true;
public bool isPairwiseDisjoint(wholeInput:list[set[&T]] sets) {
int sizeSets = size(sets);
if (sizeSets == 0 || sizeSets == 1) {
throw IllegalArgument(wholeInput, "Only two or more sets can be pairwise disjoint.");
}

for (i <- [0..sizeSets-1]) {
for (j <- [i+1..sizeSets]) {
if (sets[i] & sets[j] != {}) return false;
}
}

return true;
}
51 changes: 48 additions & 3 deletions src/org/rascalmpl/library/lang/rascal/tests/library/Set.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,51 @@ test bool testDynamicTypes2() {set[value] s = {"1",2,3}; return set[int] _ := s
test bool testDynamicTypes3() {set[value] s = {"1",2,3}; return set[int] _ := s & {2,3};}
test bool testDynamicTypes4() = {"1", *int _} := {"1",2,3};




// intersection
test bool testIntersectionEmptySet() {
try {
intersection({});
}
catch IllegalArgument(wholeSet, msg): {
return wholeSet == {} && msg == "Intersection only possible with at least two sets.";
}
return false;
}

test bool testIntersectionSingleElement() {
try {
intersection({{1}});
}
catch IllegalArgument(wholeSet, msg): {
return wholeSet == {{1}} && msg == "Intersection only possible with at least two sets.";
}
return false;
}

test bool testIntersectionNoOverlap() {return intersection({{1,2}, {3,4}}) == {};}
test bool testIntersectionOverlap() {return intersection({{1,2}, {2,3}, {2,5}}) == {2};}

// isDisjoint
test bool testIsPairwiseDisjointEmpty() {
try {
isPairwiseDisjoint([]);
}
catch IllegalArgument(wholeInput, msg): {
return wholeInput == [] && msg == "Only two or more sets can be pairwise disjoint.";
}
return false;
}

test bool testIsPairwiseDisjointSingleElement() {
try {
isPairwiseDisjoint([{1}]);
}
catch IllegalArgument(wholeInput, msg): {
return wholeInput == [{1}] && msg == "Only two or more sets can be pairwise disjoint.";
}
return false;
}

test bool testIsPairwiseDisjointIdenticalElements() {return isPairwiseDisjoint([{1}, {1}]) == false;}
test bool testIsPairwiseDisjointNoOverlap() {return isPairwiseDisjoint([{1,2},{3,4},{5,6}]) == true;}
test bool testIsPairwiseDisjointOverlap() {return isPairwiseDisjoint([{1,2}, {-4,5}, {1,6,7}]) == false;}

0 comments on commit d29bdf4

Please sign in to comment.