-
Notifications
You must be signed in to change notification settings - Fork 108
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
Tree #1169
Tree #1169
Conversation
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.
I quickly glanced over it, I think it's a great idea to add trees in general! Here's a first pass of comments!
Other random comments would include considering whether adding a more sophisticated type of tree would make sense (red-black, for example?)
yield descendant | ||
|
||
def traverse(self): | ||
"""Traverse the tree from this node.""" |
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.
Traverse can be done many ways, is it ok to have a single top level traverse method and no alternative for choice which traversal strategy?
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.
Added pre-order and post-order, things like in-order are for binary tree so not included here
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.
please add parameter to the docs and document, return, raise, ...
Thx for the feedbacks! For more specific type of trees like binary tree, red black tree etc we can add them in the same folder inheriting from this class. For instance for binary tree we'd add left/right property, in-order traverse, for red black tree we add color property and corresponding algorithms, but it is very important that the base tree class does not create any limitation on later more specific implementations, as well as not creating any significant computational overhead due to the way we structure it. The primary use cases we have in mind for now are things like scene objects graph (like spatial hierarchy in ifc files), classes inheritance tree etc, rather high-level stuff. btw I'm curious to know your opinion on the serialization strategy, is it good the way it is now as nested dicts or should we do flat node list + uuid identifiers? |
yield descendant | ||
|
||
def traverse(self): | ||
"""Traverse the tree from this node.""" |
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.
please add parameter to the docs and document, return, raise, ...
|
||
|
||
class Tree(Datastructure): | ||
"""A tree data structure. |
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.
perhaps a short overview of the most important characteristics of the data structure would be useful.
Greenwashing compas with trees ;) |
@tomvanmele How does it look now?
|
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.
maybe you should also add a few tests :)
if strategy == "preorder": | ||
yield self | ||
for child in self.children: | ||
for node in child.traverse(strategy): | ||
yield node | ||
elif strategy == "postorder": | ||
for child in self.children: | ||
for node in child.traverse(strategy): | ||
yield node | ||
yield self | ||
else: | ||
raise ValueError("Unknown traversal strategy: {}".format(strategy)) |
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.
preorder and postorder is the same as depth-first, breadth-first?
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.
I thought they are, but just realized I got it confused too... Turned out pre and post order are both subcategory of depth-first, the difference is whether you visit current node first or not. None of them are breath-first. Will make some adjustments here
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.
@tomvanmele ok now there are two arguments strategy
and order
, strategy refers to depth first of breath first, and order is pre or post order (only for depth first). This should better aligns the terminologies.
raise TypeError("The node is not a TreeNode object.") | ||
|
||
if node.parent: | ||
raise ValueError("The node is already part of another tree, remove it from that tree first.") |
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.
can also be THIS tree, no?
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.
Sorry for the confusion, I adjusted a bit the sentence here, the idea is that if a node is already added somewhere (a parent link already exists, no matter it is this tree or another), we can ask user to explicitly remove that link first. Another option would be to not care about it and directly overwrite this link, which one you think is better?
The traversal strategy. Options are ``"preorder"`` and ``"postorder"``. | ||
strategy : {"depthfirst", "breadthfirst"}, optional | ||
The traversal strategy. | ||
Default is ``"depthfirst"``. |
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.
in my opinion you don't have to mention the default. this is already clear from line 163
---------- | ||
strategy : {"depthfirst", "breadthfirst"}, optional | ||
The traversal strategy. | ||
Default is ``"depthfirst"``. |
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.
same here. no mention of default needed in my opinion
hey @gonzalocasas could you take another look at the current state of this PR, it needs your approval |
@@ -379,11 +377,9 @@ def traverse(self, strategy="depthfirst", order="preorder"): | |||
---------- | |||
strategy : {"depthfirst", "breadthfirst"}, optional | |||
The traversal strategy. | |||
Default is ``"depthfirst"``. | |||
|
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.
there can't be a blank line in parameter lists
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.
oops.... fixed
@@ -168,11 +168,9 @@ def traverse(self, strategy="depthfirst", order="preorder"): | |||
---------- | |||
strategy : {"depthfirst", "breadthfirst"}, optional | |||
The traversal strategy. | |||
Default is ``"depthfirst"``. | |||
|
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.
same here
@gonzalocasas Pin.... : ) Could you approve this so it can be merged? |
Adding the tree class. @tomvanmele for serialization strategy, I ended up opting for directed nested dictionaries. This way it uses least amount of memory and not needing any types of uuid referencing. I'm aware the docstrings is not formatted entirely correctly, but besides that let me know how does the class structure itself look like. thx!
What type of change is this?
Checklist
Put an
x
in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.CHANGELOG.md
file in theUnreleased
section under the most fitting heading (e.g.Added
,Changed
,Removed
).invoke test
).invoke lint
).compas.datastructures.Mesh
.