Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New functions for checking multiple sets #1925

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/org/rascalmpl/library/Set.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -513,3 +513,53 @@ public set[&T] union(set[set[&T]] sets) = {*s | s <- sets};

@synopsis{Compute the Jaccard similarity between two sets.}
real jaccard(set[value] x, set[value] y) = (1. * size(x & y)) / size(x + y);


@synopsis{Calculate the intersection of a set of sets.}
@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 list are pairwise disjoint.}
@description{
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;
isPairwiseDisjoint([{1,2}, {3,4}, {5,6}]);
isPairwiseDisjoint([{1,2}, {1,4}, {5,6}]);
isPairwiseDisjoint([{1,2}, {1,4}, {1,6}]);
```
}
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.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sets == wholeInput, no need to give it two names right?

}

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;}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible, think of an way to write an random tests. something like:

test bool testRandomPairwiseDisjoint(set[value] a, set[value] b) = (a & b == {}) == isPairwiseDisjoint([a,b]);

or even better if you could do it without using the intersection operator.