-
-
Notifications
You must be signed in to change notification settings - Fork 481
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
Add make_set function for DisjointSets #38692
Changes from all commits
21417a4
d173d35
5080482
76e2b1c
c0b9fd9
baf6539
2c26072
b9cd6d2
1d0df0e
5ff7cac
598ccfd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ from libc.string cimport memcpy | |
from libc.stdlib cimport rand | ||
from sage.libs.gmp.mpz cimport * | ||
|
||
from cysignals.memory cimport sig_free | ||
|
||
|
||
cdef enum: | ||
# The following is for the automorphism group computation, says what the | ||
|
@@ -136,6 +138,39 @@ cdef inline void OP_join(OrbitPartition *OP, int m, int n) noexcept: | |
if m_root != n_root: | ||
OP.num_cells -= 1 | ||
|
||
|
||
cdef inline void OP_make_set(OrbitPartition *OP) noexcept: | ||
cdef int i, n = OP.degree | ||
cdef int *new_parent, *new_rank, *new_mcr, *new_size | ||
|
||
cdef int *int_array = <int *> sig_malloc(4*(n+1) * sizeof(int)) | ||
if int_array is NULL: | ||
raise MemoryError("MemoryError allocating int_array in make_set method") | ||
|
||
OP.degree = n + 1 | ||
OP.num_cells = OP.num_cells + 1 | ||
new_parent = int_array | ||
new_rank = int_array + (n + 1) | ||
new_mcr = int_array + (2*n + 2) | ||
new_size = int_array + (3 * n + 3) | ||
|
||
memcpy(new_parent, OP.parent, n * sizeof(int)) | ||
memcpy(new_rank, OP.rank, n * sizeof(int)) | ||
memcpy(new_mcr, OP.mcr, n * sizeof(int)) | ||
memcpy(new_size, OP.size, n * sizeof(int)) | ||
|
||
new_parent[n] = n | ||
new_rank[n] = 0 | ||
new_mcr[n] = n | ||
new_size[n] = 1 | ||
|
||
sig_free(OP.parent) | ||
|
||
OP.parent = new_parent | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. before this statement, you must release the memory used by the previous arrays, so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. I'm not so good with memory allocation stuff, but I think we only need |
||
OP.rank = new_rank | ||
OP.mcr = new_mcr | ||
OP.size = new_size | ||
|
||
cdef inline int OP_merge_list_perm(OrbitPartition *OP, int *gamma) noexcept: | ||
""" | ||
Joins the cells of OP which intersect the same orbit of gamma. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -537,6 +537,26 @@ cdef class DisjointSet_of_integers(DisjointSet_class): | |
raise ValueError('j must be between 0 and %s (%s given)' % (card - 1, j)) | ||
OP_join(self._nodes, i, j) | ||
|
||
def make_set(self): | ||
r""" | ||
Add a new element into a new set containing only the new element. | ||
|
||
According to :wikipedia:`Disjoint-set_data_structure#Making_new_sets` the | ||
`make_set` operation adds a new element into a new set containing only | ||
the new element. The new set is added at the end of `self`. | ||
|
||
EXAMPLES:: | ||
sage: d = DisjointSet(5) | ||
sage: d.union(1, 2) | ||
sage: d.union(0, 1) | ||
sage: d.make_set() | ||
sage: d | ||
{{0, 1, 2}, {3}, {4}, {5}} | ||
sage: d.find(1) | ||
1 | ||
""" | ||
OP_make_set(self._nodes) | ||
|
||
cpdef root_to_elements_dict(self): | ||
r""" | ||
Return the dictionary where the keys are the roots of ``self`` and the | ||
|
@@ -834,6 +854,43 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): | |
cdef int j = <int> self._el_to_int[f] | ||
OP_join(self._nodes, i, j) | ||
|
||
def make_set(self, new_elt=None): | ||
r""" | ||
Add a new element into a new set containing only the new element. | ||
|
||
According to :wikipedia:`Disjoint-set_data_structure#Making_new_sets` | ||
the `make_set` operation adds a new element into a new set containing | ||
only the new element. The new set is added at the end of `self`. | ||
|
||
INPUT: | ||
|
||
- ``new_elt`` -- (optional) element to add. If `None`, then an integer | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for the second line, you must add 2 extra spaces, like:
this currently breaks building the pdf documentation (reported by CI). |
||
is added. | ||
|
||
EXAMPLES:: | ||
|
||
sage: e = DisjointSet('abcde') | ||
sage: e.union('d', 'c') | ||
sage: e.union('c', 'e') | ||
sage: e.make_set('f') | ||
sage: e | ||
{{'a'}, {'b'}, {'c', 'd', 'e'}, {'f'}} | ||
sage: e.union('f', 'b') | ||
sage: e | ||
{{'a'}, {'b', 'f'}, {'c', 'd', 'e'}} | ||
sage: e.make_set('e'); e | ||
{{'a'}, {'b', 'f'}, {'c', 'd', 'e'}} | ||
sage: e.make_set(); e | ||
{{'a'}, {'b', 'f'}, {'c', 'd', 'e'}, {6}} | ||
""" | ||
if new_elt is None: | ||
new_elt = self._nodes.degree | ||
if new_elt not in self._int_to_el: | ||
d = self._nodes.degree | ||
self._int_to_el.append(new_elt) | ||
self._el_to_int[new_elt] = d | ||
OP_make_set(self._nodes) | ||
|
||
cpdef root_to_elements_dict(self): | ||
r""" | ||
Return the dictionary where the keys are the roots of ``self`` and the | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really want to call free on NULL ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry, I'll fix that.