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

Provide an iterative version on some functions on trees #39519

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

Oscfon
Copy link

@Oscfon Oscfon commented Feb 13, 2025

This pull request provide iterative methods on AbstractTrees which work both on OrderedTree and BinaryTree.
The problem was that some functions like node_number reach the recursion limit on huge instances.

sage: T = OrderedTree([])
sage: for _ in range(10000):
....:     T = OrderedTree([])
sage: T.node_number()
RecursionError

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

@Oscfon Oscfon added sd125 sage days 125 sd128 tickets of Sage Days 128 Le Teich and removed sd125 sage days 125 labels Feb 13, 2025
if not subtree.is_empty():
stack.append(subtree)
else:
stack.pop()
node = stack.pop()
action(node)

def contour_traversal(self,first_action=None, middle_action=None, final_action=None, leaf_action=[]):
Copy link
Contributor

@mantepse mantepse Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def contour_traversal(self,first_action=None, middle_action=None, final_action=None, leaf_action=[]):
def contour_traversal(self, first_action=None, middle_action=None, final_action=None, leaf_action=None):

I don't see why leaf_action should not be None by default.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want that if you change only first_action and final_action, leaf_action will be the action of both of them but it's perhaps a bad idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, can you give an example?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the depth code : i only change the final_action and it change accordingly the leaf_action.
I would like it to work like that.

Comment on lines +654 to +661
The algorithm is::

manipulate the root with function `first_action`;
iteratively manipulate the root with function `middle_action`
and explore each subtree (by the algorithm) from the
leftmost one to the rightmost one;
then manipulate the root with function `final_action`;
if the root is a leaf it only manipulate with function `leaf_action`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The algorithm is::
manipulate the root with function `first_action`;
iteratively manipulate the root with function `middle_action`
and explore each subtree (by the algorithm) from the
leftmost one to the rightmost one;
then manipulate the root with function `final_action`;
if the root is a leaf it only manipulate with function `leaf_action`.
ALGORITHM:
- apply `first_action` to the root
- iteratively apply `middle_action` to the root and traverse each subtree from the
leftmost one to the rightmost one
- apply `final_action` to the root if it is not a leaf, and apply `leaf_action` to the root otherwise

(I'm not sure whether my modification introduce mistakes, please double check!)

Copy link
Author

@Oscfon Oscfon Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The algorithm is::
manipulate the root with function `first_action`;
iteratively manipulate the root with function `middle_action`
and explore each subtree (by the algorithm) from the
leftmost one to the rightmost one;
then manipulate the root with function `final_action`;
if the root is a leaf it only manipulate with function `leaf_action`.
ALGORITHM:
- if the root is a leaf, apply `leaf_action`
- else
- apply `first_action` to the root
- iteratively apply `middle_action` to the root and traverse each subtree
from the leftmost one to the rightmost one
- apply `final_action` to the root

Copy link
Author

@Oscfon Oscfon Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does but i fixed it here.

sage: t.contour_traversal(first_action = lambda node: l.append(0),leaf_action = None)
sage: len(l)
7

Copy link
Contributor

@mantepse mantepse Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

"""
if first_action is None:
def first_action(x):
return None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return None
return

return None
if middle_action is None:
def middle_action(x):
return None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return None
return

return None
if final_action is None:
def final_action(x):
return None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return None
return

return None
if leaf_action is None:
def leaf_action(x):
None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
None
return

final_action(x)
stack = []
stack.append(self)
corners = [0,0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
corners = [0,0]
corners = [0, 0]

corners = [0,0]
while stack:
node = stack.pop()
if not(bool(node)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if not(bool(node)):
if not node:

leaf_action(node)
corners.pop()
corners[-1] += 1
elif corners[-1] == 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
elif corners[-1] == 0:
elif not corners[-1]:

Comment on lines +948 to +950
def fr_action(node, depths, m, depth):
if depths[-1] == depth:
m[0] += 1
Copy link
Contributor

@mantepse mantepse Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def fr_action(node, depths, m, depth):
if depths[-1] == depth:
m[0] += 1
m = 0
def fr_action(node):
nonlocal m, depths, depth
if depths[-1] == depth:
m += 1

Comment on lines +951 to +954
def m_action(node,depths):
depths.append(depths[-1]+1)
def fn_action(node,depths):
depths.pop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def m_action(node,depths):
depths.append(depths[-1]+1)
def fn_action(node,depths):
depths.pop()
def m_action(node):
nonlocal depths
depths.append(depths[-1] + 1)
def fn_action(node):
nonlocal depths
depths.pop()

Comment on lines +956 to +958
m = [0]
self.contour_traversal(lambda node: fr_action(node, depths,m, depth),lambda node: m_action(node, depths),lambda node: fn_action(node, depths))
return m[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m = [0]
self.contour_traversal(lambda node: fr_action(node, depths,m, depth),lambda node: m_action(node, depths),lambda node: fn_action(node, depths))
return m[0]
self.contour_traversal(fr_action, m_action, fn_action)
return m

return Integer(0 if self.is_empty() else 1)
if self.is_empty():
return 0
def action(node,m):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def action(node,m):
m = []
def action(node):
nonlocal m

m.append(0)
else:
mx = max(m.pop() for _ in node)
m.append(mx+1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m.append(mx+1)
m.append(mx + 1)

Comment on lines +1242 to +1244
m = []
self.contour_traversal(final_action = lambda node: action(node,m))
return m[0]+1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m = []
self.contour_traversal(final_action = lambda node: action(node,m))
return m[0]+1
self.contour_traversal(final_action=action)
return m[0] + 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
s: needs review sd128 tickets of Sage Days 128 Le Teich
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants