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

Implement algorithm for enumerating ideals of a poset in O(log n) amortized time #37805

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5881,6 +5881,10 @@ REFERENCES:
Journal of Algorithms, Volume 26, Issue 2, Pages 275 - 290, 1998.
(https://doi.org/10.1006/jagm.1997.0891)

.. [Sq2002] Matthew B. Squire.
*Enumerating the Ideals of a Poset*.
(https://citeseer.ist.psu.edu/465417.html)

.. [SS1983] Shorey and Stewart. "On the Diophantine equation a
x^{2t} + b x^t y + c y^2 = d and pure powers in recurrence
sequences." Mathematica Scandinavica, 1983.
Expand Down
50 changes: 50 additions & 0 deletions src/sage/categories/posets.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,56 @@ def order_filter(self, elements):
[3, 7, 8, 9, 10, 11, 12, 13, 14, 15]
"""

def generate_upsets(U, Y, Poset):
r"""
Enumerates the ideals (upsets) of a given poset.

ALGORITHM:

The algorithm is based on [Sq2002]_.
Current algorithms for genertating ideals require an amortized
time of `O(n)` per ideal in the worst case, where `n` is the number
of elements in the poset. This algorithm generates ideals in an
amortized time of `O(log n)` per ideal.

The function recursively generates all possible upsets (subsets) of
a given set `Y` based on a partially ordered set (Poset), ensuring that
if `Xi < Xm < Xj`, then Xi must also be less than `Xj`. It iterates through
`Y`, partitioning it into two subsets based on the relationship between
elements and yields the resulting upsets.

INPUT:

- ``U`` -- a list of the current upset being constructed.
- ``Y`` -- a list of remaining elements to be considered for inclusion.
- ``Poset`` -- a dictionary representing the partial order.

OUTPUT:

- A subset of Y that satisfies the upset condition.
saatvikraoIITGN marked this conversation as resolved.
Show resolved Hide resolved

EXAMPLES::

"""
if not Y:
yield U
else:
Xm = Y[len(Y) // 2]
Y1 = []
Y2 = []
for Xi in Y:
if Poset[(Xi, Xm)] == 1:
U[Y.index(Xi)] = 0
saatvikraoIITGN marked this conversation as resolved.
Show resolved Hide resolved
else:
Y1.append(Xi)
yield from Posets.generate_upsets(U.copy(), Y1, Poset)
for Xj in Y:
if Poset[(Xm, Xj)] == 1:
U[Y.index(Xj)] = 1
saatvikraoIITGN marked this conversation as resolved.
Show resolved Hide resolved
else:
Y2.append(Xj)
yield from Posets.generate_upsets(U.copy(), Y2, Poset)

def directed_subset(self, elements, direction):
r"""
Return the order filter or the order ideal generated by a
Expand Down
Loading