@@ -290,23 +290,29 @@ def _push_eigenvalues(self, eigenvalues):
290290 if "conjugate_pairs" in self ._eig_constraints :
291291 num_eigs = len (eigenvalues )
292292 new_eigs = np .empty (num_eigs , dtype = "complex" )
293+ unassigned_inds = set (np .arange (num_eigs ))
293294 # If given an odd number of eigenvalues, find the eigenvalue with
294295 # the smallest imaginary part and take it to be a real eigenvalue.
295296 if num_eigs % 2 == 1 :
296- ind_single = np .argmin (np .abs (eigenvalues .imag ))
297- new_eigs [ind_single ] = eigenvalues [ind_single ].real
298- eig_pair_inds = np .delete (np .arange (num_eigs ), ind_single )[::2 ]
299- else :
300- eig_pair_inds = np .arange (0 , num_eigs , 2 )
301- # Note: a consequence of the OptDMD variable projection process is
302- # that complex conjugate pairs naturally appear together in the
303- # computed eigenvalue vectors. We thus take advantage of this...
304- for i in eig_pair_inds :
305- eig_pair = eigenvalues [i : i + 2 ]
306- real_comp = np .mean (eig_pair .real )
307- imag_comp = np .mean (np .abs (eig_pair .imag ))
308- new_eigs [i ] = real_comp + 1j * imag_comp
309- new_eigs [i + 1 ] = real_comp - 1j * imag_comp
297+ ind_0 = np .argmin (np .abs (eigenvalues .imag ))
298+ new_eigs [ind_0 ] = eigenvalues [ind_0 ].real
299+ unassigned_inds .remove (ind_0 )
300+ # Assign complex conjugate pairs until all eigenvalues are paired.
301+ while len (unassigned_inds ) != 0 :
302+ # Randomly grab the next unassigned eigenvalue.
303+ ind_1 = unassigned_inds .pop ()
304+ eig_1 = eigenvalues [ind_1 ]
305+ # Get the index of the eigenvalue that's closest to being the
306+ # complex conjugate of the randomly selected eigenvalue.
307+ ind_2 = np .argmin (np .abs (eigenvalues - np .conj (eig_1 )))
308+ eig_2 = eigenvalues [ind_2 ]
309+ unassigned_inds .remove (ind_2 )
310+ # Average their real and imaginary components together.
311+ a = 0.5 * (eig_1 .real + eig_2 .real )
312+ b = 0.5 * (abs (eig_1 .imag ) + abs (eig_2 .imag ))
313+ new_eigs [ind_1 ] = a + 1j * (b * np .sign (eig_1 .imag ))
314+ new_eigs [ind_2 ] = a + 1j * (b * np .sign (eig_2 .imag ))
315+ # ind_1 and ind_2 have now been paired.
310316
311317 eigenvalues = np .copy (new_eigs )
312318
0 commit comments