Skip to content

added xperm function: reorder state variables in a ss model. #1039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions control/statesp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2142,6 +2142,113 @@ def _parse_list(signals, signame='input', prefix='u'):
return StateSpace(
ss_sys, inputs=input_names, outputs=output_names, name=name)

# Reorder states in state-space object
def xperm(sys, P):
r"""Reorder states in a state-space representation.

``xperm(sys,P)``
Reorder a space system. Always creates a new system.

Parameters
----------
sys : StateSpace or TransferFunction
A linear system.
A, B, C, D : array_like or string
System, control, output, and feed forward matrices.
P : permutation vector P.
It is a 0:N-1 where N-1 is the number of states in sys.

Returns
-------
out: :class:`StateSpace`
Linear input/output system.

Raises
------
ValueError
ValueError: If matrix sizes are not self-consistent or if the order
is invalid.

Example
-------

Reorder a ss model:
>>> G = ct.ss([[-1, -2], [3, -4]], [[5], [7]], [[6, 8]], [[9]])
>>> ct.xperm(G,[1, 0, 2])

"""
# TODO: transfer the original sys parameters to the new output sys to preserve labels.
# TODO: create docstrings for this function - WIP
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not be merged without a substantial docstring.


# Convert `order` to numpy array if it's a list
P = np.array(P)

# Get order of A
n = sys.A.shape[0]
_sorted_P = np.sort(P)
_sorted_sys_labels = np.sort(sys.state_labels)

# Check if inputs are state labels from sys
if np.array_equal(_sorted_sys_labels, _sorted_P):
order_contains_labels = True
elif np.array_equal(np.arange(n), _sorted_P):
order_contains_labels = False
else:
raise ValueError('Invalid P array. P must be a list of unique integers from 0 to N-1, or a list of state labels of sys.')

# Check dimensions of matrices
if sys.A.shape[0] != sys.A.shape[1]:
raise ValueError("Matrix A must be square.")
if sys.B.shape[0] != n:
raise ValueError("Matrix B must have the same number of rows as A.")
if sys.C.shape[1] != n:
raise ValueError("Matrix C must have the same number of columns as A.")
if sys.D.shape[0] != sys.C.shape[0] or sys.D.shape[1] != sys.B.shape[1]:
raise ValueError("Matrix D dimensions must be consistent with matrices C and B.")

# if P contains labels, find their order
if order_contains_labels:
# list1 is the reference, we want indices of list2 elements in list1
P = np.searchsorted(sys.state_labels, P)

# Construct the permutation matrix T
T = np.zeros((n, n))
for i, j in enumerate(P):
T[i, j] = 1

P_inv = np.linalg.inv(T)

# Apply the transformation
A_perm = T @ sys.A @ P_inv
B_perm = T @ sys.B
C_perm = sys.C @ P_inv
D_perm = sys.D # D remains unchanged

return ss(A_perm, B_perm, C_perm, D_perm)
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string block should be moved to somewhere accessible to users: the docstring, or a file in examples/.

Example usage
>>> A = np.array([[-10., -24., 0.],
[ 1., 0., 0.],
[ 0., 1., 0.]])

>>> B = np.array([[1],[0],[0]])
>>> C = np.array([[0, 1, 0]])
>>> D = np.array([[0]])
>>> sys = ct.ss(A,B,C,D)

# Desired order of state variables (e.g., swap x1 and x3):
>>> P = [2, 1, 0] # permutations: x3->x1, x2->x2, x1->x3.

try:
sys_reordered = xperm(sys, P)
print("A' =\n", sys_reordered.A)
print("B' =\n", sys_reordered.B)
print("C' =\n", sys_reordered.C)
print("D' =\n", sys_reordered.D)
except ValueError as e:
print("Error:", e)
"""

#
# Utility functions
#
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy