Skip to content

Inconsistent coordinate override in arithmetic expressions #257

@apfelix

Description

@apfelix

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:

import xarray as xr

import linopy

m = linopy.Model()

# 2 days, hourly (48 hours)
t = [0, 1, 2, 3]
n = ["a", "b"]

level = m.add_variables(coords=[t, n], name="level", dims=["time", "node"])

alpha = xr.DataArray([[1, 2], [3, 4], [5, 6], [7, 8]], coords=level.coords)

other_times = [2, 0, 3, 1]
other_time_level = level.loc[dict(time=other_times)]

Some arithmetic expressions
level + other_time_level works as expected, coordinates are overridden based on level

LinearExpression (time: 4, node: 2):
------------------------------------
[0, a]: +1 level[0, a] + 1 level[2, a]
[0, b]: +1 level[0, b] + 1 level[2, b]
[1, a]: +1 level[1, a] + 1 level[0, a]
[1, b]: +1 level[1, b] + 1 level[0, b]
[2, a]: +1 level[2, a] + 1 level[3, a]
[2, b]: +1 level[2, b] + 1 level[3, b]
[3, a]: +1 level[3, a] + 1 level[1, a]
[3, b]: +1 level[3, b] + 1 level[1, b]

When using level + alpha * other_time_level, I would have expected to get

LinearExpression (time: 4, node: 2):
------------------------------------
[0, a]: +1 level[0, a] + 1 level[2, a]
[0, b]: +1 level[0, b] + 2 level[2, b]
[1, a]: +1 level[1, a] + 3 level[0, a]
[1, b]: +1 level[1, b] + 4 level[0, b]
[2, a]: +1 level[2, a] + 5 level[3, a]
[2, b]: +1 level[2, b] + 6 level[3, b]
[3, a]: +1 level[3, a] + 7 level[1, a]
[3, b]: +1 level[3, b] + 8 level[1, b]

since I though that alpha would be term to define the coordinates in alpha * 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)

LinearExpression (time: 4, node: 2):
------------------------------------
[0, a]: +1 level[0, a] + 1 level[0, a]
[0, b]: +1 level[0, b] + 2 level[0, b]
[1, a]: +1 level[1, a] + 3 level[1, a]
[1, b]: +1 level[1, b] + 4 level[1, b]
[2, a]: +1 level[2, a] + 5 level[2, a]
[2, b]: +1 level[2, b] + 6 level[2, b]
[3, a]: +1 level[3, a] + 7 level[3, a]
[3, b]: +1 level[3, b] + 8 level[3, b]

Interestingly, the result changes when transforming other_time_level into a LinearExpression first, i.e., call level + alpha * other_time_level.to_linexpr()

LinearExpression (time: 4, node: 2):
------------------------------------
[0, a]: +1 level[0, a] + 5 level[2, a]
[0, b]: +1 level[0, b] + 6 level[2, b]
[1, a]: +1 level[1, a] + 1 level[0, a]
[1, b]: +1 level[1, b] + 2 level[0, b]
[2, a]: +1 level[2, a] + 7 level[3, a]
[2, b]: +1 level[2, b] + 8 level[3, b]
[3, a]: +1 level[3, a] + 3 level[1, a]
[3, b]: +1 level[3, b] + 4 level[1, b]

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:

LinearExpression (time: 4, node: 2):
------------------------------------
[0, a]: +1 level[0, a] + 1 level[2, a] + 1
[0, b]: +1 level[0, b] + 1 level[2, b] + 2
[1, a]: +1 level[1, a] + 1 level[0, a] + 3
[1, b]: +1 level[1, b] + 1 level[0, b] + 4
[2, a]: +1 level[2, a] + 1 level[3, a] + 5
[2, b]: +1 level[2, b] + 1 level[3, b] + 6
[3, a]: +1 level[3, a] + 1 level[1, a] + 7
[3, b]: +1 level[3, b] + 1 level[1, b] + 8

So my question would be: How to achieve the intended result and is all of the behaviour as it should be?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions