WISH : "Match by branch paths" option in relevant components

I know that tree matching is based on the simplistic idea of matching the first branch in one tree to the first branch in the second, etc… but why ?
Why make fancy branching structures if you can’t leverage it to make a smart matching ?
Let’s take the “Concatenate” component as an example :


Match Quizz.gh (9.6 KB)

In decreasing order of what would intuitively make sense/be useful as an output, I’d say, “A” first, then “B”, then “C”, but what actually comes out is both un-intuitive and pretty much useless.

It is also obvious with components like “Replace Items”…
By chance, the Treesloth tools (Add Unmatched, Filter Unmatched, …) allow to adapt trees in order to make proper matches, but why not use the obvious matching ?
Matching

5 Likes

Here’s a great example of how much you can get screwed by the current matching scheme :

Merfect Patch.gh (7.2 KB)

A simple “List item” will output a tree with branch numbers above the max branch number of both inputs !

1 Like

I might be missing something, but the way I see it things are very intuitive: The output will always depend on the structure of one of the inputs (generally on the first one). It would be counter intuitive if it didn’t.

You can see the list item is actually using the structure of the ‘i’ input up to the first 10 items (branch {23}), because you have 10 branches and then it continues +1 from there: {24}, {25}, etc. Makes sense. What output do you propose otherwise?

If you would like to use the structure of ‘L’ input instead you can use ‘Principal’ to force the component to use the structure of that input. Note how now the max branch is {23}.

Then, I am not sure if this is your problem, but you can rename the paths easily like so:

I totally did not get your first example with Concatenate. Not sure why you would expect A, B or C. None of them make sense nor have the correct number of branches. What is wrong with the Concatenate output?

1 Like

Well it is intuitive if you consider that paths should behave as lists.
My argument is that branch paths and lists are of a very different nature.
In a tree structure, the path indices have a meaning.
Take {A;B} ; “A” might be the name of the building, and “B” the level in that building.
Say the items (i) in the lists are relative to occupants.
Whatever operation I perform, I want to perform between items on the same branch because otherwise, it is meaningless.
If I start concatenating the first names of the fine folk in {1;4} with the surnames of the dummies in {5;7}, just because these branches are the first ones in each tree I concatenate, the yearbook it is going to end up messy.

The reasons why Grasshopper is so tough is precisely because you need to spend a lot of energy and ruse making sure that the data is computed with it’s proper sibbling.
Trees branches are perfect for this… except GH doesn’t care about matching them !

In my “Concatenate” example, I want to concatenate the strings which are from the same branches because the content of each branch is of a certain “family” which I have struggled to keep together.
The question becomes :“what to do with lists who don’t have a matching branch”.
Actually, any of the three proposed outcomes “A”, “B”, or “C” could be useful, depending on what you are doing, and therefore could be an option withing the processing component.

Oh I see now, you want to match by ‘name’ of path instead of by number of branch. Say instead of doing 1st branch with 1st branch, you want to do {0} with {0}, {89} with {89} no matter the order.

The concatenate probably does not represent your more complex problems, but for this example Merge behaves exactly like you want it to. It literally merges the branches with same path name. I added an extra ‘Axe’ on the 3rd branch, path {4} to make sure that Merge was doing the correct merge despite branch number.

In this case ‘Orange’ is branch nr 3, while ‘Baseball bat’ is branch nr 4 and they still get merged together because their path name is {5}.

The point of this thread is to imagine an alternate matching logic which -to me- makes more sense.
You are free to say it’s nonsense as long as you can bring something interesting to the discussion of course.
I acknowledge you attempt to be helpful, but I don’t need that you tutor me on how to manage trees (see what I did here ?).
It took me a while, but I can do my own path juggling now.

Again, despite GH’s annoying habit to raise the branching level even when not required, it is important to enforce a branching logic that keeps the lists organized in a meaningful way, and this is one of the toughest tasks in GH.
So wouldn’t it make sense if the list matching was branch-focused too, and not just on a first-arrived-first-served basis ?

I never said it was nonsense. If you find help offensive it is your problem. I am humble enough to accept help as what it is instead of thinking that someone is trying to offend me by making a fool out of me. Much less in the context of this forum where it is all about helping each other. Even more with this lovely software, with which one can be really good at it, but still be missing something so obvious and simple in front of one’s eyes and some less experience user can come along and said. “I solved it like this” and the rest would say “huh, I never thought of using x component like that”. I have seen it happen countless of times.

What I have also seen many times, is people asking for ‘x’ feature not realizing it is already possible with native GH. Most of the times a workaround is enough.

I am not sure why you would mention the Concatenate example if the entire problem can be bypassed by using the correct component Merge. There is a dedicated component that matches branches like you want them to, clearly, CLEARLY, making this a global option for every component is an overdo. I am surprised you don’t see that. I think that your lesser opinion of McNeel developers (given your frequent rantings) blinds you. They know what they are doing better than you, that I can assure.

For every component? No.

Btw: It is better if you state in the title that your post is a request/feedback with [WISH] or something of the sorts. But still, be ready for people trying to provide workarounds. As I said before, inexperience makes for dull requests that can easily be solved. Like both the examples you provided. Both Concatenate and List Item. If you knew you could use Merge or Principal option, you would have never used those examples. I mean you complained about the branch path number going up to {28} when with "Principal’ it goes up to {23}. When I see this, I take it as symptom of what I mentioned before, which happens often in this forum, people asking for requests when it can be solved with a simple workaround.

What is the point of this thread anyways? Not addressing the only person that actually needs to see this @DavidRutten. I honestly believe it won’t matter, what you ask for is clearly an overdo and I doubt it will even be present in GH 3 if ever. So this whole thread is a waste.

Edit: Honestly it is frustrating, your lack of humility and impressive stubbornness, or maybe it is lack of imagination? To not even consider the option that the problem you have might be solvable with workarounds. Have you considered the chance that you might have missed something? You make a big request/rant and so you have to stick to it, despite people providing possible solutions. This is exactly what happened on the other thread I tried to help you. You prematurely conclude the software is broken and unintelligently designed.

5 Likes

You are giving me intentions I do not have, and wasting a lot of my/your time indeed.

1 Like

Indeed, my intention was to tutor you all along. :man_shrugging: :man_facepalming:

1 Like

Sure there can be improvements and some more useful components, but let me go for a more conceptual side, since I don’t think there will be changes in GH1 when version 2 is being written from scratch.

GH does not have tree structures, although it makes you think so with its terminology. All data in GH, even a single element or a single list, is within the same type of structure, a list of lists ordered by paths, being these a multidimensional indexer. If you have a single element, you actually have a path-list pair where this list contains one element, so you always see at least one {0} when using the panel.

To really be considered a tree, any structure must be nested with other structures of the same type and have a root node and leaf nodes, i.e. a tree must contain a tree node and within this other tree nodes, it must by definition be able to be traversed recursively. This does not exist in GH, only a path-list collection is used. There is no nesting, there are pairs.

So you can’t think of this as a tree, or some kind of nesting, you must think of it as a list of lists. Once here, taking into account what kind of access each input has, if it expects to receive a single element, a list or a wrongly named tree, you can understand why each component behaves as it does. The Merge component for example, all its accesses are tree type, and it behaves as you expect, right? each branch match the other branches with the same multidimensional index. But if you do this with the other access types, as in Concat, but the user gives it the wrong so-called tree, the component must decide under the hood which path-list or list-element to associate with the others of the other inputs. There is no good way to solve this generically, because in each case you may need or agree on one way of matching or another. Then, which is the less bad? to associate by path index or by position in the list of lists? which is more common to happen, trees with missing branches or trees with ordered branches? which is easier to associate by hand to solve this limitation, two trees with different path indices or the result of matching by path returning empty branches or those that the operation could not be done?

I believe that as it is, to match by position, the first with the first, the second with the second, is the less bad option. With good practices of use and understanding this structure as it is, it is only necessary to fill with duplicated data or empty lists in rare cases to match as you wish, instead of having to correct the paths because the {0;0;1;3;0;2;0;0} did not associate with the {0;1;3;0;2;0} of other input. The less I have to work with these paths, the better.

In short, there is no nested data, there are lists of path-list pairs. And then working with it is easier than it seemed.

1 Like

Great explanation Dani. I think that @osuire does not mean to replace the current behavior but rather wishes to be able to select what matching to use in every component. Maybe with an ui similar to whatTree Branch and other components have.

But again, this is pretty much what I tried to tell him.

No need to rewrite every component just for this…

Hi Dani, thanks for your explanation.
I like the example you cite in the quote because it illustrates my other gripe with (some) components behavior, which is the un-necessary addition of a branching levels.
I know that some folks don’t care about having a garland of trailing zeros in their paths, and indeed, due to how GH matches paths, it doesn’t matter.
But given how hard it is to make sense of path indexes in complex definitions, I like to keep all my paths as short as they need to be to get a good grasp of what I’m doing.

It is obvious that tree matching is only relevant to a subset of components, and therefore should be an option. I updated the title of the thread to reflect this.
My suggestion is that association by path index is quite legitimate because it acknowledges the effort of data organization by branch paths, and it would reward the good practice of keeping path depths minimal.
@DavidRutten thankfully added the Suirify component for that purpose, by the way.
I’d rather that there was no extra branching when not required by the structure of upstream trees, but that’s another topic.

While I agree with that statement, I am convinced that the current matching behavior is not what most new users think (thus my qualification of "non-intuitive), and is the cause of many discouraged GH newbies, unable to make sense of what’s going on.

I am grateful to David Stasiuk, author of Treesloth, and Andrew Hewman, author of Human for their amazing tree management components, and to the later for his amazing tutorials on tree management.
It took a while for me to understand what each of these components do, but they sure save a lot of tedious branch hustling.

In programming, almost nothing is done unnecessarily. It is necessary to include zeros when the output access is a higher order than its inputs. For example, if you divide a curve, it receives an element and returns a list, if zero were not added to the first result (and 1 to the next, 2 to the next…) then by giving it a list of curves, the divisions would all enter the same list/branch, but thanks to that each one goes to its own branch, keeping the indexes of the input branches. In order not to complicate things further, it is better to leave only one behaviour than to condition it to only one element. Besides, it gives you easily fixable information that you could not have if a zero was not included when only an element is received.

Yes, as an option it would be fine. However, no idea if GH2 will still use data trees as we understand them today.

I work and develop with GH every day, I make complex definitions, sometimes I use input data as tables or more complex information… and never, but never, have I used surify. It surprises me.

I totally agree with that. It’s happened to me too, probably to everyone. And I think it stop being a problem when you understand them for what they are instead of what they are called. It was a good solution for its time, but it has a bad name.

I don’t have any plugin to manipulate trees. I’ve tried them but I didn’t need them. You can really restrict yourself to native components and do everything without problem if instead of forcing a solution to a problem you remodel the problem to handle it as native GH forces you. So I don’t know to what extent it is convenient for the user to use more intuitive external tools but that lead you to think about a way of working that seems to give a lot of headaches.

I beg to differ on this statement.
It is generally the case that I know in each specific input if I will have a single or multiple elements, because of the very nature of what I’m doing there.
Therefore, I perceive it like a chore to get rid of those zeros, and “Suirify” helps in that respect.

Maybe you don’t because you don’t mind ending up with paths like {1;5;0;0;0;0;0;0}
In my case, making sure I have the expected number of branch indices is one of the tricks I found to keep my sanity while debugging definitions. :slight_smile:

I’d be curious to see how you do the equivalent of Treesloth’s “Filter Unmatched” for example.
Yet, I would argue that GH is not necessarily targeted at people with your level in “traditional” programming, and there’s a kind of paradox here : all those yummy colored components trick you in the beginning that you can do awesome stuff without too much headache, and then you get caught in the branches.

I don’t take native GH as gospel, and feel free to criticize things that I consider have hindered my ability to be productive with it, as a non-programming genius.

1 Like

Just Simplify (parameter menu option) is enough for me. I use it quite often.

Not sure what it does. But unless someone in the data creation chain has done something wrong, you can always remodel the problem a priori instead of looking for a solution a posteriori. That’s what I do so I don’t need external components to manage data.

I just had some experience with 3d max modeling, then I learned GH, and two years later I start learning programming. That is, I had the same or less background as the new users of GH. It’s true that learning to program you understand everything else more clearly, but I’ve gone through the same as everyone else to understand how to work with branches. But this is almost 10 years ago, and was strongly passionate about GH.

I agree that it’s confusing at first, but it works quite well if you conform yourself within its limits. Try to adjust your input so that it doesn’t clash with those problems you describe.

Again, un-needed branching is very troubling to me.
Suirify adresses the issue here, while “Simplify” doesn’t :

Here’s what it does.
It does more or less what I would like the components to do according to the title of this thread.

Limits are made to be pushed back, aren’t they ?

That’s what I do, and I find treesloth tools very useful to that end, but I could probably achieve the same with a bunch of GH components connected in a well-crafted manner. It would just take more space on my canvas.

Same could be said about any plugin, like, say, a jewelry plug-in : handy components, but nothing you couldn’t achieve with honest-to-goodness plain GH components :wink:

True. I rarely use Suirify but sometimes it’s the only way to move forward, or at least the most expedient. I don’t know why ‘Simplify’ doesn’t work like ‘Suirify’? In fact, I think I’d be just fine if ‘Suirify’ were applied to all component outputs, eh?

“The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
– George Bernard Shaw, “Man and Superman”, 1903

1 Like

Never ever here too. I prefer to use 2 components or make my own cluster, but I never needed to anyways. I do have clusters for other stuff, like Flip Last