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

[Feature]: Count how many variables are in a ComposableExpression #406

Open
Moelf opened this issue Feb 6, 2025 · 8 comments
Open

[Feature]: Count how many variables are in a ComposableExpression #406

Moelf opened this issue Feb 6, 2025 · 8 comments

Comments

@Moelf
Copy link

Moelf commented Feb 6, 2025

Feature Request

Sometimes when looking at the result in HoF, I'm interested in selecting the first equation that used "variable" in both component:

Image

In this case, I'd like to select the equation with complexity = 10.

I thought I just need to check .constant, but then I found this counter-example:
Image

So I checked the code base:

function DE.count_scalar_constants(ex::AbstractComposableExpression)
return DE.count_scalar_constants(convert(Expression, ex))
end

but looks like there's no way to count the non-constant terms

@MilesCranmer
Copy link
Owner

MilesCranmer commented Feb 6, 2025

A lot of the Base operations on collections are overloaded to do tree traversal on the inner Node type (it's a binary tree). So you can solve this with:

ex::ComposableExpression
tree = ex.tree
target_feature = 1
has_variable = any(node -> node.degree == 0 && node.feature == target_feature, tree)

@MilesCranmer
Copy link
Owner

@MilesCranmer
Copy link
Owner

I'm assuming this is fixed; feel free to re-open if not!

@Moelf
Copy link
Author

Moelf commented Feb 10, 2025

Image

that doesn't quite work, clearly the base_func here is a constant

@Moelf
Copy link
Author

Moelf commented Feb 10, 2025

maybe it should have been:

node.degree != 0 && node.feature == 1

?

@Moelf
Copy link
Author

Moelf commented Feb 10, 2025

then it doesn't work on nested equations:

Image

@MilesCranmer
Copy link
Owner

MilesCranmer commented Feb 10, 2025

Ah, sorry, I need(ed) coffee!

It needs to first check !node.constant before checking node.feature. So the correct call would be:

has_variable = any(node -> node.degree == 0 && !node.constant && node.feature == target_feature, tree)

A specific method for checking feature equality would no doubt be a good idea.

I suppose you can also use node == Node{Float64}(feature=target_feature) and it will handle this automatically. (Though might want to create the checked node once, since it will allocate on the heap)

@MilesCranmer MilesCranmer reopened this Feb 10, 2025
@Moelf
Copy link
Author

Moelf commented Feb 11, 2025

ahh, I see how that works now, yeah that works.

If there's any place where something like this would be useful I'm happy to add a few utility functions, but I'm not sure what to call it. (something like is_a_function_of(tree, target_variable)?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants