linopy icon indicating copy to clipboard operation
linopy copied to clipboard

Inconsistent creation of dimensions in add_variables

Open jkiviluo opened this issue 8 months ago • 1 comments

Version Checks (indicate both or one)

  • [x] I have confirmed this bug exists on the lastest release of Linopy.

  • [ ] I have confirmed this bug exists on the current master branch of Linopy.

Issue Description

I am trying to add variables with lower and upper bounds. When both, lower and upper, have less dimensions than in the 'coords', those extra dimensions are not created in the variable. However, if lower (or upper) bound is set to 0 (or other constant), the full dimensionality of the 'coords' will be replicated in the new variable (even though the upper or the lower bound parameter doesn't have all the dimensions).

Reproducible Example

import xarray as xr
import numpy as np
import linopy

m = linopy.Model()
test = xr.DataArray(np.random.rand(3, 2), [("x", ["a", "b", "c"]), ("y", ["X", "Y"])])

# Works correctly, uses y dim from test.coords
foo = m.add_variables(lower=0, upper=test.sum("y"), coords=test.coords, name="foo")
print(foo)

# Does not take y dim from test.coords
bar = m.add_variables(lower=-test.sum("y"), upper=test.sum("y"), coords=test.coords, name="bar")
print(bar)

Expected Behavior

Both examples should create variables with the full dimensionality of the test.coords.

Installed Versions

Replace this line.

jkiviluo avatar Apr 26 '25 19:04 jkiviluo

I have a similar bug. This could work as a minimal example:

Creating a Variable with scalar xarray.DataArray as bounds leads to scalar Variable, regardless of passed coords

import numpy as np
import pandas as pd
import xarray as xr
import linopy

m = linopy.Model()
my_dim = pd.RangeIndex(2, name='my-dim')
var = m.add_variables(
    lower=xr.DataArray(0),
    upper=xr.DataArray(10),
    coords=[my_dim]
)

print(var)
Variable
--------
var0 ∈ [0, 10]

Using floats or integers works as expected.

import numpy as np
import pandas as pd
import xarray as xr
import linopy

m = linopy.Model()
my_dim = pd.RangeIndex(2, name='my-dim')
var = m.add_variables(
    lower=0,
    upper=10,
    coords=[my_dim]
)

print(var)
Variable (my-dim: 2)
--------------------
[0]: var0[0] ∈ [0, 10]
[1]: var0[1] ∈ [0, 10]

FBumann avatar May 05 '25 11:05 FBumann