Spinning out the Lazy part of the now closed issue on an expressions container (#881). Copying some text from that issue verbatim
Would be interesting to add some lazy equivalent (LazyExpressions?) of expressions which doesn't evaluate the expression but rather takes a callable and only promotes them to an Expression member on request. This would work well with the text math (#561) as you could define any number of expressions and have only those which will be used by downstream constraints or objectives actually evaluated; the rest only need evaluating on-the-fly when requesting their solutions (they could be statistics of your model runs that you just want to calculate in postprocessing).
I had a few thoughts on the LazyExpressions that I haven't fully resolved in my head:
- Should they always be promoted on first evaluation or not? I'm leaning towards having a separate promote method which explicitly promotes them, otherwise they can spit out the evaluated expression on calling evaluate but the linopy model still stores them as a LazyExpression.
- Should it be possible for them to store an explicit AST or is a callable OK? From the perspective of having a consistent Python API that allows these to be created interactively in Python or (in future) via the text math, I was thinking of keeping it as a callable. But if we limited it to just working with the text math, it could also hold the AST, knowing that it is a pyparsing object and having explicit functionality to deal with that.
- How to handle arithmetic operations? I guess easiest is to always evaluate them if any kind of arithmetic is applied, but then you can't have lazy + lazy -> lazy. One could also defer the operations by storing the callables and their connecting arithmetic, then you could get a LazyExpression out of combining two lazy expressions (you probably wouldn't want to support lazy + variable -> lazy).
- should providing a mask be possible, and how to handle cases where this should also be a callable / AST? The use-case is where you mask based on a value in the solution (e.g. mask to only evaluate when p_nom > 0), so it is only viable to evaluate the mask also when calling LazyExpression.solution.
Spinning out the Lazy part of the now closed issue on an expressions container (#881). Copying some text from that issue verbatim
Would be interesting to add some lazy equivalent (LazyExpressions?) of expressions which doesn't evaluate the expression but rather takes a callable and only promotes them to an Expression member on request. This would work well with the text math (#561) as you could define any number of expressions and have only those which will be used by downstream constraints or objectives actually evaluated; the rest only need evaluating on-the-fly when requesting their solutions (they could be statistics of your model runs that you just want to calculate in postprocessing).
I had a few thoughts on the LazyExpressions that I haven't fully resolved in my head: