diff --git a/gap/union-find.gd b/gap/union-find.gd
index acecc3f..dfda1a2 100644
--- a/gap/union-find.gd
+++ b/gap/union-find.gd
@@ -28,7 +28,7 @@ DeclareCategory("IsPartitionDS", IsObject);
#! @Description
#! Family containing all partition data structures
-BindGlobal("PartitionDSFamily", NewFamily(IsPartitionDS));
+BindGlobal("PartitionDSFamily", NewFamily("PartitionDSFamily", IsPartitionDS));
#
# Constructors. Given an integer return the trivial partition (n parts of size 1)
@@ -38,11 +38,37 @@ BindGlobal("PartitionDSFamily", NewFamily(IsPartitionDS));
#! @Description
#! Returns the trivial partition of the set [1..n].
#! @Arguments filter, n
-DeclareConstructor("PartitionDS",[IsPartitionDS, IsPosInt]);
+DeclareConstructor("PartitionDSCons",[IsPartitionDS, IsPosInt]);
+
#! @Description
#! Returns the union find structure of partition.
#! @Arguments filter, partition
-DeclareConstructor("PartitionDS",[IsPartitionDS, IsCyclotomicCollColl]);
+DeclareConstructor("PartitionDSCons",[IsPartitionDS, IsCyclotomicCollColl]);
+
+#
+# Operations. Given an integer return the trivial partition (n parts of size 1)
+# Given a list of disjoint sets, return that partition. Any points up to the maximum
+# of any of the sets not included in a set are in singleton parts.
+#
+#! @Description
+#! Returns the trivial partition of the set [1..n].
+#! @Arguments filter, n
+DeclareOperation("PartitionDS",[IsFunction, IsPosInt]);
+
+#! @Description
+#! Returns the trivial partition of the set [1..n].
+#! @Arguments n
+DeclareOperation("PartitionDS",[IsPosInt]);
+
+#! @Description
+#! Returns the union find structure of partition.
+#! @Arguments filter, partition
+DeclareOperation("PartitionDS",[IsFunction, IsCyclotomicCollColl]);
+
+#! @Description
+#! Returns the union find structure of partition.
+#! @Arguments partition
+DeclareOperation("PartitionDS",[IsCyclotomicCollColl]);
#
# Key operations
@@ -69,6 +95,13 @@ DeclareOperation("Unite",[IsPartitionDS and IsMutable, IsPosInt, IsPosInt]);
#! @Returns an iterator
DeclareOperation("RootsIteratorOfPartitionDS", [IsPartitionDS]);
+#! @Description
+#! Returns a list of the canonical representatives of the parts
+#! of the partition unionfind.
+#! @Arguments unionfind
+#! @Returns A list.
+DeclareOperation("RootsOfPartitionDS", [IsPartitionDS]);
+
#! @Description
#! Returns the number of parts of the partition unionfind.
#! @Arguments unionfind
diff --git a/gap/union-find.gi b/gap/union-find.gi
index 5161b83..7007e25 100644
--- a/gap/union-find.gi
+++ b/gap/union-find.gi
@@ -25,7 +25,7 @@ UF.setRank := UF.Bitfields.setters[1];
UF.setParent := UF.Bitfields.setters[2];
-InstallMethod(PartitionDS, [IsPartitionDSRep and IsPartitionDS and IsMutable, IsPosInt],
+InstallMethod(PartitionDSCons, [IsPartitionDSRep and IsPartitionDS and IsMutable, IsPosInt],
function(filt, n)
local r;
r := rec();
@@ -37,7 +37,7 @@ InstallMethod(PartitionDS, [IsPartitionDSRep and IsPartitionDS and IsMutable, Is
end);
-InstallMethod(PartitionDS, [IsPartitionDSRep and IsPartitionDS and IsMutable, IsCyclotomicCollColl],
+InstallMethod(PartitionDSCons, [IsPartitionDSRep and IsPartitionDS and IsMutable, IsCyclotomicCollColl],
function(filt, parts)
local r, n, seen, sp, sr, p, x;
if not (ForAll(parts, IsSet) and
@@ -66,76 +66,31 @@ InstallMethod(PartitionDS, [IsPartitionDSRep and IsPartitionDS and IsMutable, Is
return r;
end);
+InstallMethod(PartitionDS, [IsPosInt],
+n -> PartitionDSCons(IsPartitionDSRep, n));
+InstallMethod(PartitionDS, [IsCyclotomicCollColl],
+parts -> PartitionDSCons(IsPartitionDSRep, parts));
-UF.RepresentativeTarjan :=
- function(uf, x)
- local gp, sp, p, y, z;
- gp := UF.getParent;
- sp := UF.setParent;
- p := uf!.data;
- while true do
- y := gp(p[x]);
- if y = x then
- return x;
- fi;
- z := gp(p[y]);
- if y = z then
- return y;
- fi;
- p[x] := sp(p[x],z);
- x := z;
- od;
-end;
+InstallMethod(PartitionDS, [IsFunction, IsPosInt],
+{filt, n} -> PartitionDSCons(filt, n));
-if IsBound(DS_UF_FIND) then
- UF.RepresentativeKernel := function(uf, x)
- return DS_UF_FIND(x, uf!.data);
- end;
- InstallMethod(Representative, [IsPartitionDSRep and IsPartitionDS, IsPosInt],
- UF.RepresentativeKernel);
-else
- InstallMethod(Representative, [IsPartitionDSRep and IsPartitionDS, IsPosInt],
- UF.RepresentativeTarjan);
-fi;
+InstallMethod(PartitionDS, [IsFunction, IsCyclotomicCollColl],
+{filt, parts} -> PartitionDSCons(filt, parts));
-UF.UniteGAP := function(uf, x, y)
- local r, rx, ry;
- x := Representative(uf, x);
- y := Representative(uf, y);
- if x = y then
- return;
- fi;
- r := uf!.data;
- rx := UF.getRank(r[x]);
- ry := UF.getRank(r[y]);
- if rx > ry then
- r[y] := UF.setParent(r[y],x);
- elif ry > rx then
- r[x] := UF.setParent(r[x],y);
- else
- r[x] := UF.setParent(r[x],y);
- r[y] := UF.setRank(r[y],ry+1);
- fi;
- uf!.nparts := uf!.nparts -1;
- return;
+UF.RepresentativeKernel := function(uf, x)
+ return DS_UF_FIND(x, uf!.data);
end;
-
-
-if IsBound(DS_UF_UNITE) then
- InstallMethod(Unite, [IsPartitionDSRep and IsMutable and IsPartitionDS,
- IsPosInt, IsPosInt],
- function(uf, x, y)
- if DS_UF_UNITE(x, y, uf!.data) then
- uf!.nparts := uf!.nparts -1;
- fi;
- end);
-else
- InstallMethod(Unite, [IsPartitionDSRep and IsMutable and IsPartitionDS,
- IsPosInt, IsPosInt],
- UF.UniteGAP);
-fi;
-
+InstallMethod(Representative, [IsPartitionDSRep and IsPartitionDS, IsPosInt],
+ UF.RepresentativeKernel);
+
+InstallMethod(Unite, [IsPartitionDSRep and IsMutable and IsPartitionDS,
+ IsPosInt, IsPosInt],
+ function(uf, x, y)
+ if DS_UF_UNITE(x, y, uf!.data) then
+ uf!.nparts := uf!.nparts -1;
+ fi;
+end);
InstallMethod(\=, [IsPartitionDSRep and IsPartitionDS, IsPartitionDSRep and IsPartitionDS], IsIdenticalObj);
@@ -193,6 +148,26 @@ InstallMethod(RootsIteratorOfPartitionDS, [IsPartitionDSRep and IsPartitionDS],
end));
end);
+InstallMethod(RootsOfPartitionDS, [IsPartitionDSRep and IsPartitionDS],
+function(uf)
+ local pt, gp, data, n, result;
+ pt := 0;
+ gp := UF.getParent;
+ data := uf!.data;
+ n := SizeUnderlyingSetDS(uf);
+ result := [];
+ while pt <= n do
+ pt := pt + 1;
+ while pt <= n and gp(data[pt]) <> pt do
+ pt := pt + 1;
+ od;
+ if pt <= n then
+ Add(result, pt);
+ fi;
+ od;
+ return result;
+end);
+
InstallMethod(PartsOfPartitionDS, [IsPartitionDS],
function(u)
local p, i, r, x;
diff --git a/tst/uf.tst b/tst/uf.tst
index 41c9e85..29a4a88 100644
--- a/tst/uf.tst
+++ b/tst/uf.tst
@@ -5,7 +5,7 @@ gap> START_TEST("uf.tst");
# Test the union-find data structure
#
#
-gap> u := PartitionDS(IsPartitionDS,10);
+gap> u := PartitionDS(10);
gap> NumberParts(u);
10
@@ -36,7 +36,7 @@ gap> Unite(u,1,3);
gap> u;
gap> Print(u,"\n");
-PartitionDS( IsPartitionDS, [ [ 1, 2, 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], \
+PartitionDS(IsPartitionDS, [ [ 1, 2, 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], \
[ 9 ], [ 10 ] ])
gap> PartitionDS( IsPartitionDS, [ [ 1, 2, 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ],
> [ 9 ], [ 10 ] ]);
@@ -57,6 +57,8 @@ gap> for x in i do Print(x,"\n"); od;
8
9
10
+gap> RootsOfPartitionDS(u);
+[ 2, 4, 5, 6, 7, 8, 9, 10 ]
gap> for x in i2 do Print(x,"\n"); od;
4
5
@@ -65,21 +67,21 @@ gap> for x in i2 do Print(x,"\n"); od;
8
9
10
-gap> UF.RepresentativeTarjan(u,3);
+gap> Representative(u,3);
2
-gap> UF.UniteGAP(u,4,5);
+gap> Unite(u,4,5);
gap> u;
-gap> PartitionDS(IsPartitionDS,[[2,1]]);
+gap> PartitionDS([[2,1]]);
Error, PartitionDS: supplied partition must be a list of disjoint sets of posi\
tive integers
-gap> PartitionDS(IsPartitionDS,[[-2,1]]);
+gap> PartitionDS([[-2,1]]);
Error, PartitionDS: supplied partition must be a list of disjoint sets of posi\
tive integers
-gap> PartitionDS(IsPartitionDS,[[1,2,3],[3,4,5]]);
+gap> PartitionDS([[1,2,3],[3,4,5]]);
Error, PartitionDS: supplied partition must be a list of disjoint sets of posi\
tive integers
-gap> u := PartitionDS(IsPartitionDS, 16);
+gap> u := PartitionDS(16);
gap> for i in [1,3..15] do Unite(u,i, i+1); od;
gap> for i in [1,5..13] do Unite(u,i, i+2); od;
@@ -89,28 +91,30 @@ gap> Representative(u,1);
16
gap> Representative(u,15);
16
-gap> u := PartitionDS(IsPartitionDS, 16);
+gap> u := PartitionDS(16);
-gap> for i in [1,3..15] do UF.UniteGAP(u,i, i+1); od;
-gap> for i in [1,5..13] do UF.UniteGAP(u,i, i+2); od;
-gap> for i in [1,9] do UF.UniteGAP(u,i, i+4); od;
-gap> UF.UniteGAP(u,1,9);
-gap> UF.RepresentativeTarjan(u,1);
+gap> for i in [1,3..15] do Unite(u,i, i+1); od;
+gap> for i in [1,5..13] do Unite(u,i, i+2); od;
+gap> for i in [1,9] do Unite(u,i, i+4); od;
+gap> Unite(u,1,9);
+gap> Representative(u,1);
16
-gap> UF.RepresentativeTarjan(u,15);
+gap> Representative(u,15);
16
-gap> u := PartitionDS(IsPartitionDS, 16);;
+gap> u := PartitionDS(16);;
gap> Unite(u,1,2);
gap> Unite(u,2,3);
gap> Unite(u,4,2);
gap> Unite(u,5,5);
-gap> UF.UniteGAP(u,9,10);
-gap> UF.UniteGAP(u,10,11);
-gap> UF.UniteGAP(u,12,10);
-gap> UF.UniteGAP(u,9,12);
+gap> Unite(u,9,10);
+gap> Unite(u,10,11);
+gap> Unite(u,12,10);
+gap> Unite(u,9,12);
gap> PartsOfPartitionDS(u);
[ [ 1, 2, 3, 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], [ 9, 10, 11, 12 ], [ 13 ],
[ 14 ], [ 15 ], [ 16 ] ]
+gap> RootsOfPartitionDS(u);
+[ 2, 5, 6, 7, 8, 10, 13, 14, 15, 16 ]
#
gap> STOP_TEST( "uf.tst", 1);