Skip to content

Commit 4bdf19e

Browse files
Add UniformPartialPerm
1 parent 1200df2 commit 4bdf19e

File tree

4 files changed

+81
-7
lines changed

4 files changed

+81
-7
lines changed

PackageInfo.g

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ PackageDoc := rec(
384384

385385
Dependencies := rec(
386386
GAP := ">=4.12.1",
387-
NeededOtherPackages := [["datastructures", ">=0.2.5"],
387+
NeededOtherPackages := [["datastructures", ">=0.3.0"],
388388
["digraphs", ">=1.6.2"],
389389
["genss", ">=1.6.5"],
390390
["images", ">=1.3.1"],

gap/elements/pperm.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
##
1010

1111
DeclareAttribute("CyclesOfPartialPerm", IsPartialPerm);
12+
DeclareOperation("UniformRandomPartialPerm", [IsPosInt]);

gap/elements/pperm.gi

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,70 @@ InstallMethod(IndexPeriodOfSemigroupElement, "for a partial perm",
1212

1313
InstallMethod(CyclesOfPartialPerm, "for a partial perm", [IsPartialPerm],
1414
f -> DigraphAllSimpleCircuits(AsDigraph(f)));
15+
16+
DeclareGlobalVariable("_RANDOM_PPERM_CACHED_VALUES");
17+
MakeReadWriteGlobal("_RANDOM_PPERM_CACHED_VALUES");
18+
_RANDOM_PPERM_CACHED_VALUES := WeakPointerObj([]);
19+
20+
InstallMethod(UniformRandomPartialPerm, "for a positive integer", [IsPosInt],
21+
function(n)
22+
local cache, num_bijections, r, im, unused_vals, num_undefined,
23+
num_each_defined, pos, i, j;
24+
25+
cache := Immutable(_RANDOM_PPERM_CACHED_VALUES);
26+
27+
if not IsBound(cache[n + 1]) then
28+
# TODO check that all the values in cache are bound
29+
cache := [];
30+
cache[1] := [1];
31+
for i in [2 .. n + 1] do
32+
cache[i] := [1];
33+
for j in [2 .. i] do
34+
cache[i][j] := cache[i][j - 1] + (i - 1) * cache[i - 1][j - 1];
35+
od;
36+
od;
37+
fi;
38+
39+
# The number of partial perms from a set of size i to a set of size j.
40+
# num_bijections := function(i, j)
41+
# local tmp;
42+
# if j < i then
43+
# tmp := i;
44+
# i := j;
45+
# j := tmp;
46+
# fi;
47+
# return Sum([0 .. i], r -> Binomial(i, r) * Binomial(j, r) * Factorial(r));
48+
# end;
49+
50+
num_bijections := function(i, j)
51+
local tmp;
52+
if j > i then
53+
tmp := i;
54+
i := j;
55+
j := tmp;
56+
fi;
57+
return cache[i + 1][j + 1];
58+
end;
59+
60+
# Rank so far
61+
r := 0;
62+
im := [];
63+
64+
unused_vals := HashSet([1 .. n]);
65+
66+
for i in [1 .. n] do
67+
num_undefined := num_bijections(n - i, n - r);
68+
num_each_defined := num_bijections(n - i, n - r - 1);
69+
pos := Random(1, num_undefined + (n - r) * num_each_defined);
70+
if pos <= num_undefined then
71+
im[i] := 0; # undefined
72+
else
73+
pos := pos - num_undefined;
74+
im[i] := Set(unused_vals)[QuoInt(pos - 1, num_each_defined) + 1];
75+
RemoveSet(unused_vals, im[i]);
76+
r := r + 1;
77+
fi;
78+
od;
79+
_RANDOM_PPERM_CACHED_VALUES := WeakPointerObj(cache);
80+
return PartialPermNC(im);
81+
end);

gap/semigroups/semipperm.gi

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,33 @@ InstallMethod(SEMIGROUPS_ProcessRandomArgsCons,
2424
{filt, params} -> SEMIGROUPS_ProcessRandomArgsCons(IsSemigroup, params));
2525

2626
InstallMethod(RandomSemigroupCons, "for IsPartialPermSemigroup and a list",
27-
[IsPartialPermSemigroup, IsList], {filt, params} ->
28-
Semigroup(List([1 .. params[1]], i -> RandomPartialPerm(params[2]))));
27+
[IsPartialPermSemigroup, IsList],
28+
function(_, params)
29+
return Semigroup(List([1 .. params[1]],
30+
i -> UniformRandomPartialPerm(params[2])));
31+
end);
2932

3033
InstallMethod(RandomMonoidCons, "for IsPartialPermMonoid and a list",
31-
[IsPartialPermMonoid, IsList], {filt, params} ->
32-
Monoid(List([1 .. params[1]], i -> RandomPartialPerm(params[2]))));
34+
[IsPartialPermMonoid, IsList],
35+
function(_, params)
36+
return Monoid(List([1 .. params[1]],
37+
i -> UniformRandomPartialPerm(params[2])));
38+
end);
3339

3440
InstallMethod(RandomInverseSemigroupCons,
3541
"for IsPartialPermSemigroup and a list",
3642
[IsPartialPermSemigroup, IsList],
3743
function(_, params)
3844
return InverseSemigroup(List([1 .. params[1]],
39-
i -> RandomPartialPerm(params[2])));
45+
i -> UniformRandomPartialPerm(params[2])));
4046
end);
4147

4248
InstallMethod(RandomInverseMonoidCons,
4349
"for IsPartialPermMonoid and a list",
4450
[IsPartialPermMonoid, IsList],
4551
function(_, params)
4652
return InverseMonoid(List([1 .. params[1]],
47-
i -> RandomPartialPerm(params[2])));
53+
i -> UniformRandomPartialPerm(params[2])));
4854
end);
4955

5056
#############################################################################

0 commit comments

Comments
 (0)