casadi / casadi

CasADi is a symbolic framework for numeric optimization implementing automatic differentiation in forward and reverse modes on sparse matrix-valued computational graphs. It supports self-contained C-code generation and interfaces state-of-the-art codes such as SUNDIALS, IPOPT etc. It can be used from C++, Python or Matlab/Octave.
http://casadi.org
GNU Lesser General Public License v3.0
1.73k stars 384 forks source link

Broken logical indexing in casadi.DM #2221

Open mkatliar opened 6 years ago

mkatliar commented 6 years ago

Example:

v = cs.DM([1, 2, 3])
print(v[[False, True, False]])

Output:

DM([1, 2, 1])

Expected output:

DM(2)

This functionality was working previously as expected.

jaeandersson commented 6 years ago

Hmm, this sounds like a tricky thing to support. Do we want v[[False, True, False]] to behave differently from v[[0, 1, 0]]? I'm not sure.

mkatliar commented 6 years ago

@jaeandersson this is how it used to work in a previous version, so the tricky thing was already there somehow. One more good reason is that numpy.ndarray does support logical indexing, and it is reasonable to make casadi.DM indexing work in the same way, s.t. both types can be used similarly.

jaeandersson commented 6 years ago

casadi.DM is using MATLAB-syntax, not numpy.ndarray syntax (which isn't even everything-is-a-matrix), so that's not a good argument. Anyway, logical indexing is working in MATLAB:

v = [1;2;3];
v([false;true;false]) % 2

so it would be desirable if DM worked the same way.

billtubbs commented 2 months ago

I just got caught out by this so I guess it's not fixed/implemented.

My use-case is to add path constraints to selected states/outputs for an arbitrary model that may change dimensions. Took me a while to figure out why the solver could not find a feasible solution...

selected_outputs = ["position" in name for name in output_names]
Y[:, selected_outputs].shape  # expected (100, 1) got (100, 5)

Two workarounds I'm considering are not very pretty

Y[:, np.nonzero(selected_outputs)[0]]
selected_outputs = [i for i, name in enumerate(output_names) if "position" in name]
Y[:, selected_outputs]

It would also be useful for things like this:

opti.minimize(cas.sumsqr(Y_m[t >= 2.0, :] - Y[t >= 2.0, :])