У меня сложный вектор (VSII_Complex
содержащий собственные значения) и комплексную матрицу (CUII_Complex
содержащие собственные векторы). Каждый элемент VSII_Complex
соответствует столбцу CUII_Complex
, Моя проблема в том, что я хочу отсортировать собственные значения внутри VSII_Complex
основанный на их реальной части (не мнимой части), и мне придется сортировать столбцы CUII_Complex
по отсортированному VSII_Complex
, Следующий код разработан моим другом, но я чувствую, что что-то не так с этим кодом, но я не могу понять это. Интересно, кто-нибудь может сказать, что не так, если таковые имеются.
EIG eigA=EIG(m_IIStiffnessAct,m_IIMassAct,true);
ComplexColumnVector VSII_Complex=eigA.eigenvalues();
ComplexMatrix CUII_Complex=eigA.eigenvectors();
///// make eigenvalues in decreasing order, so do eigenvectors
for (long ii = 0; ii < VSII_Complex.rows(); ii++)
{
for (long jj = ii+1; jj < VSII_Complex.rows(); jj++)
{
if (VSII_Complex(ii).real() < VSII_Complex(jj).real())
{
Complex temp = VSII_Complex(ii);
VSII_Complex(ii) = VSII_Complex(jj);
VSII_Complex(jj) = temp;
for (long kk = 0; kk < CUII_Complex.rows(); kk++)
{
Complex tempVec = CUII_Complex(kk,ii);
CUII_Complex(kk,ii) = CUII_Complex(kk,jj);
CUII_Complex(kk,jj) = tempVec;
}
}
}
}
Просто используйте встроенную сортировку, которая возвращает позицию, в которой элемент находился ранее.
//couldn't find this in the docs, I'm overlooking something probably:
void swapColumns (ComplexMatrix &mat, octave_idx_type colA, octave_idx_type colB)
{
if(colA == colB) return;
ComplexColumnVector temp = mat.column(colA);
mat.insert(mat.column(colB),0,colA);
mat.insert(temp,0,colB);
}bool isRealGreater(const Complex& a, const Complex& b)
{
return a.real() > b.real();
}
//presumably in another function
//int func() {
EIG eigA=EIG(m_IIStiffnessAct,m_IIMassAct,true);
ComplexColumnVector VSII_Complex=eigA.eigenvalues();
ComplexMatrix CUII_Complex=eigA.eigenvectors();
///// make eigenvalues in decreasing order, so do eigenvectors
//create indices from 1-len(VSII_Complex)
Array<octave_idx_type> sort_order(VSII_Complex.length(),0);
for(int i =0 ; i< sort_order.length(); i++)
{sort_order.elem(i)= i;}
//create sorting object and sort VSII_Complex in descending order of the real component
octave_sort<Complex> sort_obj(&isRealGreater);
sort_obj.sort(VSII_Complex.jit_slice_data(), sort_order.jit_slice_data(), VSII_Complex.length());
//swap the columns of CUII_Complex in the same way VSII_Complex got sorted
for(octave_idx_type i=0; i<sort_order.length(); i++)
{
if(sort_order.elem(i) > i)
{
swapColumns(CUII_Complex,i,sort_order.elem(i));
}
}
//}
На самом деле не проверял это, потому что мне было лень устанавливать октаву, я просто читал документы.
Я решил проблему с помощью следующего кода, я разработал этот код на основе алгоритма на следующей веб-странице. Но ответ PeterT выглядит лучше для меня.
http://www.learncpp.com/cpp-tutorial/64-sorting-an-array-using-selection-sort/
///// make eigenvalues in decreasing order, so do eigenvectors
ComplexColumnVector ComplexColumnVector_toBesSorted=VSII_Complex;
ComplexMatrix ComplexMatrix_toBeSorted=CUII_Complex;
for (long idx_start = 0; idx_start < ComplexColumnVector_toBesSorted.rows(); idx_start++)
{
long idx_smallest=idx_start;
for (long idx_current = idx_start+1; idx_current < ComplexColumnVector_toBesSorted.rows(); idx_current++)
{
if (ComplexColumnVector_toBesSorted(idx_current).real() < ComplexColumnVector_toBesSorted(idx_smallest).real())
idx_smallest=idx_current;
}
Complex Complex_temp=ComplexColumnVector_toBesSorted(idx_start);
ComplexColumnVector_toBesSorted(idx_start)=ComplexColumnVector_toBesSorted(idx_smallest);
ComplexColumnVector_toBesSorted(idx_smallest)=Complex_temp;
for (long kk = 0; kk < ComplexMatrix_toBeSorted.rows(); kk++)
{
Complex Complex_temp_2 = ComplexMatrix_toBeSorted(kk,idx_start);
ComplexMatrix_toBeSorted(kk,idx_start) = ComplexMatrix_toBeSorted(kk,idx_smallest);
ComplexMatrix_toBeSorted(kk,idx_smallest) = Complex_temp_2;
}
}