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

Lazy Replace #171

Open
JDBetteridge opened this issue Jun 8, 2023 · 1 comment
Open

Lazy Replace #171

JDBetteridge opened this issue Jun 8, 2023 · 1 comment

Comments

@JDBetteridge
Copy link
Contributor

It would be very useful to have a lazy version of replace, which only gets applied when the expression tree is traversed.

Example:
Say I have an expression expr which contains a ufl.ConstantValue named c as a parameter. If I want to have the derivative of expr wrt. c I can do so by creating a ufl.Coefficient named f and doing:

ufl.replace(expr, {c: f})
ufl.derivative(expr, f)

However this traverses the expression tree twice.

(This issue would also be fixed by implementing derivative wrt. ufl.ConstantValue, but there are more examples where this is desirable). This came up as a discussion point when reviewing a recent Firedrake PR. Tagging @dham .

@wence-
Copy link
Collaborator

wence- commented Jun 8, 2023

I think that you would still (in the general case) have to traverse the expression tree twice if you want your transformers to not have to handle every UFL node. In the specific case of replace, this is because differentiation doesn't commute through replacement: derivative(replace(expr, {c: f}), c) != replace(derivative(expr, c), {c: f}. In general it's because if you think as the expression transformation rules as fixed point "local" replacements with the recursive knot tied by map_expr_dag, then it is only some transformation rules that have the functorial property in the sense of map f o g == map f o map g.

I think specifically for replace you could solve it by having a Replace node, and then all transformers would be augmented to have a dispatch on Replace that traverses and replaces in the subtree before applying themselves to the result.

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

No branches or pull requests

2 participants