Здравствуйте ! Я написал простенькую программу численного решения уравнения Риккати. Так же ешо реализовал свой класс матриц. Хотелось бы обсудить решение и реализацию. Что не учол, какие подводные камни могут встретися и вобше хотелось бы послушать критические замечания. Особенно интересно на счот самого алгоритма численного решения. Сама формула | Код | A^T - транспортированная матрица А A^T - транспортированная матрица T invR - обрашонная матрица R S - искомая матрица Риккати (решение уравнения) A^T*S+S*A-(S*B+N)*invR*(B^T*S+N*T)+Q =0;
|
в реализации пока что матрица N не участвует заголовочный файл класса Матрицы | Код | #ifndef MATRIX_H #define MATRIX_H #include <iostream> #include <QVector> #include <QString>
using namespace std;
class MMatrix { unsigned int row; unsigned int column; QVector<double*> mArray; public: MMatrix(void); MMatrix( const MMatrix& h); MMatrix(int r, int c); unsigned int rowCount() const { return row; } unsigned int columnCount() const { return column; }
MMatrix& operator =( const MMatrix& h); MMatrix operator *( const MMatrix& h) const; MMatrix operator *( const double x) const; MMatrix operator +( const MMatrix& h) const; MMatrix operator -( const MMatrix& h)const ; double* operator []( int index); const double* operator []( int index) const;
MMatrix& swap_row( unsigned int r1,unsigned int r2); MMatrix& swap_column( unsigned int c1,unsigned int c2); MMatrix& resize( unsigned int r,unsigned int c); MMatrix transpon() const;
MMatrix elem( const MMatrix& h); // по элементное перемножение матриц
int rang() const;
int search( double what, bool match, int& I, int& J, unsigned int startI, unsigned int startJ) const;
MMatrix& add_matrix( const MMatrix& h);
double max(); // мамксимальный элемент double min(); // минимальный элемнт friend ostream& operator<<( ostream& out, const MMatrix& h); friend istream& operator>>( istream& in, const MMatrix& h); QString toString() const;
~MMatrix(); };
MMatrix Riccati(const MMatrix &a,const MMatrix &b,const MMatrix &q,const MMatrix &r, double dt); // решение уравнения Риккати #endif
|
в качестве численного метода использовал метод Ньютона последовательного приближения | Код | MMatrix Riccati(const MMatrix &a,const MMatrix &b,const MMatrix &q,const MMatrix &r, double dt) {
MMatrix Bt; // транспорированая матрица B Bt = b.transpon();
MMatrix At; // транспорированя матрица A At=a.transpon();
MMatrix invR(r); // обрашонная матрица R invR = Invert(invR);
MMatrix X(a.rowCount(),a.columnCount()); // решенее уравненя
int N = 10000/dt; // количество точек MMatrix prevX = X; // предыдушая итерация double epsilon = 0.0000001; // ошибка выичления for( int i =0; i<N; i++){ X =X + (At*X+X*a-(X*b)*invR*(Bt*X)+q)*dt; // проверка что предушая итерация не изменилась больше чем на ошибку вычисления MMatrix t = X - prevX; bool bBreak= true; for( int k =0; k < t.rowCount() ; k++) { for( int l = 0; l < t.columnCount(); l++) { if( t[k][l] > epsilon) { bBreak = false; break; } } } prevX = X; if( bBreak ) { qDebug()<<" Break "<<i; break; } } return X; }
|
Результат работы проверил с помощью Matlab функция lqr. Программа пример написана с использование Qt.
|