From 394fa27eff4fcbef1e4c2e8448fc9ee43f99ac82 Mon Sep 17 00:00:00 2001 From: "Andrew D. McGuire" Date: Wed, 12 Dec 2018 15:29:45 -0500 Subject: [PATCH 1/3] Performance improvements to _remove_useless_states routine in statesp.py --- control/statesp.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/control/statesp.py b/control/statesp.py index b55a8c681..63d3e7056 100644 --- a/control/statesp.py +++ b/control/statesp.py @@ -193,20 +193,14 @@ def _remove_useless_states(self): """ - # Indices of useless states. - useless = [] - # Search for useless states. - for i in range(self.states): - if (all(self.A[i, :] == zeros((1, self.states))) and - all(self.B[i, :] == zeros((1, self.inputs)))): - useless.append(i) - # To avoid duplucate indices in useless, jump to the next - # iteration. - continue - if (all(self.A[:, i] == zeros((self.states, 1))) and - all(self.C[:, i] == zeros((self.outputs, 1)))): - useless.append(i) + ax1_A = np.where(~self.A.any(axis=1))[0] + ax1_B = np.where(~self.B.any(axis=1))[0] + ax0_A = np.where(~self.A.any(axis=0))[1] + ax0_C = np.where(~self.C.any(axis=0))[1] + useless_1 = np.intersect1d(ax1_A, ax1_B, assume_unique=True) + useless_2 = np.intersect1d(ax0_A, ax0_C, assume_unique=True) + useless = np.concatenate((useless_1, useless_2)) # Remove the useless states. self.A = delete(self.A, useless, 0) From c65d0858e960d290c68dd6b2425f29e7fdbeaa90 Mon Sep 17 00:00:00 2001 From: "Andrew D. McGuire" Date: Mon, 24 Dec 2018 08:13:33 -0500 Subject: [PATCH 2/3] Minor update to comment string in _remove_useless_states. --- control/statesp.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/control/statesp.py b/control/statesp.py index 63d3e7056..42342c184 100644 --- a/control/statesp.py +++ b/control/statesp.py @@ -193,14 +193,15 @@ def _remove_useless_states(self): """ - # Search for useless states. + # Search for useless states and get the indices of these states + # as an array. ax1_A = np.where(~self.A.any(axis=1))[0] ax1_B = np.where(~self.B.any(axis=1))[0] ax0_A = np.where(~self.A.any(axis=0))[1] ax0_C = np.where(~self.C.any(axis=0))[1] useless_1 = np.intersect1d(ax1_A, ax1_B, assume_unique=True) useless_2 = np.intersect1d(ax0_A, ax0_C, assume_unique=True) - useless = np.concatenate((useless_1, useless_2)) + useless = np.concatenate((useless_1, useless_2)) # Remove the useless states. self.A = delete(self.A, useless, 0) From be53eb734dab667020944c668d402140ed779e76 Mon Sep 17 00:00:00 2001 From: "Andrew D. McGuire" Date: Mon, 25 Mar 2019 17:46:15 -0400 Subject: [PATCH 3/3] Replace np.concatenate with np.union1d in statesp._remove_useless_states method This ensures that all elements in the array of state indices to be removed are unique. --- control/statesp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control/statesp.py b/control/statesp.py index d3f9ab709..4c8321342 100644 --- a/control/statesp.py +++ b/control/statesp.py @@ -202,7 +202,7 @@ def _remove_useless_states(self): ax0_C = np.where(~self.C.any(axis=0))[1] useless_1 = np.intersect1d(ax1_A, ax1_B, assume_unique=True) useless_2 = np.intersect1d(ax0_A, ax0_C, assume_unique=True) - useless = np.concatenate((useless_1, useless_2)) + useless = np.union1d(useless_1, useless_2) # Remove the useless states. self.A = delete(self.A, useless, 0)