From 6d118173a9b4b1fbe3285d7e1edd3f218ffafedb Mon Sep 17 00:00:00 2001 From: Saatvik Rao Date: Mon, 15 Apr 2024 14:41:04 +0530 Subject: [PATCH 1/2] implemented function to generate upsets --- src/doc/en/reference/references/index.rst | 4 ++ src/sage/categories/posets.py | 50 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 4c2d05b1ec7..a59d85a8ecb 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -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. diff --git a/src/sage/categories/posets.py b/src/sage/categories/posets.py index 0d846648e6f..41cc858897f 100644 --- a/src/sage/categories/posets.py +++ b/src/sage/categories/posets.py @@ -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. + + 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 + 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 + 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 From 9746caf3996b753a4f24a6458ec076a7f3c486bd Mon Sep 17 00:00:00 2001 From: Saatvik Rao Date: Mon, 15 Apr 2024 18:31:39 +0530 Subject: [PATCH 2/2] using .enumerate instead of .index --- src/sage/categories/posets.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/posets.py b/src/sage/categories/posets.py index 41cc858897f..b11d5e6ad77 100644 --- a/src/sage/categories/posets.py +++ b/src/sage/categories/posets.py @@ -331,7 +331,7 @@ def generate_upsets(U, Y, Poset): OUTPUT: - - A subset of Y that satisfies the upset condition. + - A subset of `Y` that satisfies the upset condition. EXAMPLES:: @@ -342,15 +342,15 @@ def generate_upsets(U, Y, Poset): Xm = Y[len(Y) // 2] Y1 = [] Y2 = [] - for Xi in Y: + for i, Xi in enumerate(Y): if Poset[(Xi, Xm)] == 1: - U[Y.index(Xi)] = 0 + U[i] = 0 else: Y1.append(Xi) yield from Posets.generate_upsets(U.copy(), Y1, Poset) - for Xj in Y: + for j, Xj in enumerate(Y): if Poset[(Xm, Xj)] == 1: - U[Y.index(Xj)] = 1 + U[j] = 1 else: Y2.append(Xj) yield from Posets.generate_upsets(U.copy(), Y2, Poset)