2

I am having a small script in numpy (Ubuntu 18.04, Python 3.6.9, numpy 1.18.3). I want to squeeze an array, but I somehow do not manage to do it.

Looking at numpy documentation, np.squeeze should be able to do that. So I did the following:

        print(self.U.shape)
        print(self.renorm_action)
        to_plot = np.squeeze(self.U) / self.renorm_action
        print(to_plot.shape)

It prints:

(1, 1002)
1.0
(1, 1002)

I am very surprised, as I would expect:

(1, 1002)
1.0
(1002,)

instead. Any idea what I am doing wrong?

Explanation

Thanks for the great help in comments, and looking forward to the 'answer', but shortly, looks like lqr returns a matrix, which is always 2D. This may be inconsistent with the doc of the control package.

Edits

Edit 1

I really do not understand why this does not work. In python3 terminal I am well able to do:

$ python3
Python 3.6.9 (default, Apr 18 2020, 01:56:04) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> arr = np.zeros((1, 1002))
>>> arr.shape
(1, 1002)
>>> arr2 = np.squeeze(arr)
>>> arr2.shape
(1002,)

Edit 2

Of course I can find a workaround, i.e. this works, but this is ugly...

        print(self.U.shape)
        print(self.renorm_action)
        to_plot = np.zeros((self.total_nbr_timesteps,))
        to_plot[:] = np.squeeze(self.U)[0, :] / self.renorm_action
        print(to_plot.shape)

prints:

(1, 1002)
1.0
(1002,)

There is really something I do not understand / miss here... :(

Edit 3

So this is (of course...) part of a quite large program. But here is a short snippet I can write to reproduce the problem. If this is min_ex.py:

import numpy as np
import control

total_nbr_timesteps = 5
A = np.array([[0, 0, 1, 0],
              [0, 0, 0, 1],
              [-418, 0, -0.184, 0],
              [0, -16343, 0, -0.767]])


B = np.array([[0],
              [0],
              [0.0002],
              [-0.0034]])

nbr_modes = A.shape[1]

X = np.zeros((nbr_modes, total_nbr_timesteps))

Q = np.eye(nbr_modes)
R = np.array([1.0])
N = np.array([[0.0],
               [0.0],
               [0.0],
               [0.0]])

K_lqr, _, _ = control.lqr(A, B, Q, R, N)

# K_lqr = np.ones((1, 4)) # using this matrix instead, it works

print(K_lqr.shape)
print(X.shape)
U = -K_lqr @ X

print(U.shape)
to_plot = np.squeeze(U)
print(to_plot.shape)

# this prints:
# $ python3 min_ex.py
# (1, 4)
# (4, 5)
# (1, 5)
# (1, 5)
Zorglub29
  • 6,979
  • 6
  • 20
  • 37
  • 1
    Can you provide a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)? Use `repr(self.renorm_action)` and `repr(self.U)` (and truncate `U` to something reasonable to include in the question) – Han-Kwang Nienhuys Jun 12 '20 at 11:39
  • It was a bit hard to reduce the length of the example, but in Edit 3 I put the best I manage to do. Seems like the problem is due to a matrix multiplication, where the matrix is obtained from the lqr function of the control package. – Zorglub29 Jun 12 '20 at 12:26
  • 1
    np.matrix is fixed at 2d. Use only np.array instead. I listed some issues at https://stackoverflow.com/questions/53254738/deprecation-status-of-the-numpy-matrix-class/53254739 – Andras Deak -- Слава Україні Jun 12 '20 at 12:26
  • @AndrasDeak you should post it as an answer – tstanisl Jun 12 '20 at 12:31
  • I will update the edit, same problem using ```array``` instead of ```matrix```. – Zorglub29 Jun 12 '20 at 12:32
  • 2
    `control.lqr(A, B, Q, R, N)` returns a matrix, not an array, there's no other way. Check `type(U)`. You can explicitly convert to an array with `K_lqr = np.asarray(K_lqr)`. – Andras Deak -- Слава Україні Jun 12 '20 at 12:35
  • 1
    Ok, thanks. Then I guess there is nothing I could do to prevent this and be bitten the first time ^^ :) . Thanks for your help :) . – Zorglub29 Jun 12 '20 at 12:36
  • That's annoying, because the doc here: https://python-control.readthedocs.io/en/0.8.1/generated/control.lqr.html Mentions explicitly "K (2-d array) – State feedback gains". Is that a doc problem then? :) Anyways even if they had written 'Matrix' I would still have been bitten ^^ . A bit annoying, I spent quite some time on it... But but, learnt something. – Zorglub29 Jun 12 '20 at 12:38
  • If you can confirm it returns a matrix then yes, that's a glaring docbug. Or, arguably, a design mistake ;) – Andras Deak -- Слава Україні Jun 12 '20 at 12:41
  • I can confirm: >>> K_lqr matrix([[ 2.39126707e-07, -1.04263507e-07, 5.44778287e-04, -2.21655236e-03]]) Thanks again for the help! How would you suggest to report that? :) – Zorglub29 Jun 12 '20 at 12:41
  • 1
    It's probably a custom subclass https://github.com/python-control/python-control/blob/4785145110352d58dd61ea6a6de31d2ab79095fd/control/statefbk.py#L446 – Andras Deak -- Слава Україні Jun 12 '20 at 12:45
  • 1
    You would use their issue tracker at https://github.com/python-control/python-control/issues if it isn't there yet. – Andras Deak -- Слава Україні Jun 12 '20 at 12:46
  • 1
    Seems you can opt out of matrices with a config... https://github.com/python-control/python-control/blob/4785145110352d58dd61ea6a6de31d2ab79095fd/control/statesp.py#L95 We can continue in the python chatroom if needed https://chat.stackoverflow.com/rooms/6/python – Andras Deak -- Слава Україні Jun 12 '20 at 12:47
  • Looks like `type(K_lqr)` would have helped. Also a `print(repr(K_lqr))`. Any thing to show that this isn't an ordinary `ndarray`. And following on the duplicate does `K_lqr.A1` work? – hpaulj Jun 12 '20 at 13:46
  • Yes agree. ```.A1``` works. – Zorglub29 Jun 12 '20 at 14:20

0 Answers0