diff --git a/src/org/rascalmpl/library/Set.rsc b/src/org/rascalmpl/library/Set.rsc index 10e0f819cdd..a2a1105e320 100644 --- a/src/org/rascalmpl/library/Set.rsc +++ b/src/org/rascalmpl/library/Set.rsc @@ -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."); + } + + for (i <- [0..sizeSets-1]) { + for (j <- [i+1..sizeSets]) { + if (sets[i] & sets[j] != {}) return false; + } + } + + return true; +} diff --git a/src/org/rascalmpl/library/lang/rascal/tests/library/Set.rsc b/src/org/rascalmpl/library/lang/rascal/tests/library/Set.rsc index b3374c5e52b..a963c6f2c4c 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/library/Set.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/library/Set.rsc @@ -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;} \ No newline at end of file