Open apfelix opened 3 months ago
very good that you look into this @apfelix, there is some inconsistency indeed. However, I would not fully have the same expectation on the operations.
In my point of view overriding should only happen when adding and subtracting terms. works as intended. See level + other_time_level
multiplication should be aligned by coordinates, no overriding. Thus, when multiplying a variable with a coefficient, the first object in the multiplication should determine the coordinate alignment of the result . Meaning:
alpha * other_time_level
-> result has the same coordinates as alpha
, other_time_level
is sorted accordingly. works as intended
other_time_level * alpha
-> result has the same coordinates as other_time_level
, alpha
is sorted accordingly. :negative_squared_cross_mark: does not work.
If one wants to ignore the coefficient coords in the multiplication, i.e. not aligning the coefficient with the variable, then one should use
other_time_level * alpha.values
what do you think?
I though a little about this, and I think your expectation does make sense. However, I'm curious on what should happen if the multiplication does involve two variables. Currently level * other_time_level
also works as coefficient multiplication, i.e., aligning the values by coordinate again
QuadraticExpression (time: 4, node: 2):
---------------------------------------
[0, a]: +1 level[0, a] level[0, a]
[0, b]: +1 level[0, b] level[0, b]
[1, a]: +1 level[1, a] level[1, a]
[1, b]: +1 level[1, b] level[1, b]
[2, a]: +1 level[2, a] level[2, a]
[2, b]: +1 level[2, b] level[2, b]
[3, a]: +1 level[3, a] level[3, a]
[3, b]: +1 level[3, b] level[3, b]
But then how would you achieve
QuadraticExpression (time: 4, node: 2):
---------------------------------------
[0, a]: +1 level[0, a] level[2, a]
[0, b]: +1 level[0, b] level[2, b]
[1, a]: +1 level[1, a] level[0, a]
[1, b]: +1 level[1, b] level[0, b]
[2, a]: +1 level[2, a] level[3, a]
[2, b]: +1 level[2, b] level[3, b]
[3, a]: +1 level[3, a] level[1, a]
[3, b]: +1 level[3, b] level[1, b]
?
If the multiplication of linopy objects should also ignore alignment, my suggestion for a consistent set of alignment rules would be the following (not sure how hard it would be to implement this):
.values
, which cannot be aligned due to lacking coordinates. (no change)Order of the resulting coordinates should always be defined by the first term that actually has coordinates, so numpy arrays would be ignored even if they are first.
Interesting, let me think about it. I would like to have the API change as small as possible, as changes can lead to very much unexpected behaviour.
Based on the discussion in #256, I started using
<variable>.loc[indices]
in arithmetic expressions and observed some inconsistencies (or I still do not understand the behaviour to 100% ^^)Following setup:
Some arithmetic expressions
level + other_time_level
works as expected, coordinates are overridden based onlevel
When using
level + alpha * other_time_level
, I would have expected to getsince I though that
alpha
would be term to define the coordinates inalpha * other_time_level
However, what I actually get is the following (coordinates of
other_time_level
are sorted according to the original time index again)Interestingly, the result changes when transforming
other_time_level
into aLinearExpression
first, i.e., calllevel + alpha * other_time_level.to_linexpr()
Finally, I tried to simply add
alpha
instead of multiplying it, i.e.,level + alpha + other_time_level
and this gives the expected result in terms of sorting the single terms into the expected rows:So my question would be: How to achieve the intended result and is all of the behaviour as it should be?