最小二乘解与极小范数解算法的C++实现(支持复系数方程组)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

头文件:

/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected]
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                                linequs2.h
 *
 * Function template for solving linear equations.
 *
 * For a m-by-n (m!=n) coefficient matrix A and m-by-1 constant vector b, if
 * m>n, the exact solution of Ax=b is not existent, but we can find the least
 * square solution that minimize norm of Ax-b; if m
#include 
#include 
#include 
#include 


namespace splab
{

	template
	Vector lsSolver( const Matrix&, const Vector& );
	template
	Vector qrLsSolver( const Matrix&, const Vector& );
	template
	Vector svdLsSolver( const Matrix&, const Vector& );
	template
	Vector > qrLsSolver( const Matrix >&,
                                       const Vector >& );
	template
	Vector > svdLsSolver( const Matrix >&,
                                        const Vector >& );

	template
	Vector lnSolver( const Matrix&, const Vector& );
	template
	Vector qrLnSolver( const Matrix&, const Vector& );
	template
	Vector svdLnSolver( const Matrix&, const Vector& );
	template
	Vector > qrLnSolver( const Matrix >&,
                                       const Vector >& );
	template
	Vector > svdLnSolver( const Matrix >&,
                                        const Vector >& );


	#include 

}
// namespace splab


#endif
// UNDETLINEQUS_H

实现文件:

/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected]
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                               linequs2-impl.h
 *
 * Implementation for solving overdetermined and underdetermined linear
 * equations.
 *
 * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University.
 *****************************************************************************/


/**
 * Overdetermined linear equationequations solution by Least Squares
 * Generalized Inverse.
 * A  --->  The m-by-n(m>n) coefficient matrix(Full Column Rank);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 least squares solution vector.
 */
template 
Vector lsSolver( const Matrix &A, const Vector &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() > A.cols() );

    Cholesky cho;
    cho.dec( trMult(A,A) );
    if( cho.isSpd() )
        return cho.solve( trMult(A,b) );
    else
        return luSolver( trMult(A,A), trMult(A,b) );
}


/**
 * Overdetermined linear equationequations solution by QR Decomposition.
 * A  --->  The m-by-n(m>n) coefficient matrix(Full Column Rank);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 least squares solution vector.
 */
template 
Vector qrLsSolver( const Matrix &A, const Vector &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() > A.cols() );

    QRD qr;
    qr.dec( A );
    if( !qr.isFullRank() )
    {
        cerr << "The matrix A is not Full Rank!" << endl;
        return Vector();
    }
    else
        return qr.solve( b );
}


/**
 * Overdetermined linear equationequations solution by SVD Decomposition.
 * A  --->  The m-by-n(m>n) coefficient matrix(Full Column Rank);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 least squares solution vector.
 */
template
Vector svdLsSolver( const Matrix &A, const Vector &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() > A.cols() );

    SVD svd;
    svd.dec( A );
    Matrix U = svd.getU();
    Matrix V = svd.getV();
    Vector s = svd.getSV();

//    for( int i=0; i  The m-by-n(m>n) coefficient matrix(Full Column Rank);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 least squares solution vector.
 */
template
Vector > qrLsSolver( const Matrix > &A,
                                   const Vector > &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() > A.cols() );

    CQRD qr;
    qr.dec( A );
    if( !qr.isFullRank() )
    {
        cerr << "The matrix A is not Full Rank!" << endl;
        return Vector >();
    }
    else
        return qr.solve( b );
}


/**
 * Overdetermined linear equationequations solution by SVD Decomposition.
 * A  --->  The m-by-n(m>n) coefficient matrix(Full Column Rank);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 least squares solution vector.
 */
template
Vector > svdLsSolver( const Matrix > &A,
                                    const Vector > &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() > A.cols() );

    CSVD svd;
    svd.dec( A );
    Matrix > U = svd.getU();
    Matrix > V = svd.getV();
    Vector s = svd.getSV();

//    for( int i=0; i  The m-by-n(m  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 minimum norm solution vector.
 */
template 
Vector lnSolver( const Matrix &A, const Vector &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() < A.cols() );

    Cholesky cho;
    cho.dec( multTr(A,A) );
    if( cho.isSpd() )
        return trMult( A, cho.solve(b) );
    else
        return trMult( A, luSolver(multTr(A,A),b) );
}


/**
 * Undetermined linear equationequations solution by QR Decomposition.
 * A  --->  The m-by-n(m  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 minimum norm solution vector.
 */
template 
Vector qrLnSolver( const Matrix &A, const Vector &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() < A.cols() );

    Matrix At( trT( A ) );
    QRD qr;
    qr.dec( At );
    if( !qr.isFullRank() )
    {
        cerr << "The matrix A is not Full Rank!" << endl;
        return Vector();
    }
    else
    {
        Matrix Q, R;
        Q = qr.getQ();
        R = qr.getR();
        Vector y( ltSolver( trT( R ), b ) );
        return Q * y;
    }
}


/**
 * Undetermined complex linear equationequations solution by SVD
 * Decomposition.
 * A  --->  The m-by-n(m  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 minimum norm solution vector.
 */
template
Vector svdLnSolver( const Matrix &A, const Vector &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() < A.cols() );

    SVD svd;
    svd.dec( A );
    Matrix U = svd.getU();
    Matrix V = svd.getV();
    Vector s = svd.getSV();

//    for( int i=0; i  The m-by-n(m  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 minimum norm solution vector.
 */
template
Vector > qrLnSolver( const Matrix > &A,
                                   const Vector > &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() < A.cols() );

    Matrix > At( trH( A ) );
    CQRD qr;
    qr.dec( At );
    if( !qr.isFullRank() )
    {
        cerr << "The matrix A is not Full Rank!" << endl;
        return Vector >();
    }
    else
    {
        Matrix > Q, R;
        Q = qr.getQ();
        R = qr.getR();
        Vector > y( ltSolver( trH( R ), b ) );
        return Q * y;
    }
}


/**
 * Undetermined complex linear equationequations solution by SVD
 * Decomposition.
 * A  --->  The m-by-n(m  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 minimum norm solution vector.
 */
template
Vector > svdLnSolver( const Matrix > &A,
                                    const Vector > &b )
{
    assert( A.rows() == b.size() );
    assert( A.rows() < A.cols() );

    CSVD svd;
    svd.dec( A );
    Matrix > U = svd.getU();
    Matrix > V = svd.getV();
    Vector s = svd.getSV();

//    for( int i=0; i

测试代码:

/*****************************************************************************
 *                              linequs2_test.cpp
 *
 * Undetermined Linear Equations testing.
 *
 * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University.
 *****************************************************************************/


#define BOUNDS_CHECK

#include 
#include 
#include 


using namespace std;
using namespace splab;


typedef double  Type;
const   int     M = 3;
const   int     N = 3;


int main()
{
	Matrix A(M,N), B(M,N);
	Vector b(N);

    // overdetermined linear equations
    A.resize( 4, 3 );
	A[0][0] = 1;	A[0][1] = -1;	A[0][2] = 1;
	A[1][0] = 1;	A[1][1] = 2;	A[1][2] = 4;
	A[2][0] = 1;	A[2][1] = 3;	A[2][2] = 9;
	A[3][0] = 1;	A[3][1] = -4;	A[3][2] = 16;
	b.resize( 4 );
	b[0]= 1;    b[1] = 2;   b[2] = 3;   b[3] = 4;

	cout << setiosflags(ios::fixed) << setprecision(3);
    cout << "The original matrix A : " << A << endl;
    cout << "The constant vector b : " << b << endl;
	cout << "The least square solution is (using generalized inverse) : "
         << lsSolver( A, b ) << endl;
    cout << "The least square solution is (using QR decomposition) : "
         << qrLsSolver( A, b ) << endl;
    cout << "The least square solution is (using SVD decomposition) : "
         << svdLsSolver( A, b ) << endl;

    Matrix > cA = complexMatrix( A, A );
    Vector > cb = complexVector( b );
    cout << "The original complex matrix cA : " << cA << endl;
    cout << "The constant complex vector cb : " << cb << endl;
	cout << "The least square solution is (using generalized inverse) : "
         << lsSolver( cA, cb ) << endl;
    cout << "The least square solution is (using QR decomposition) : "
         << qrLsSolver( cA, cb ) << endl;
    cout << "The least square solution is (using SVD decomposition) : "
         << svdLsSolver( cA, cb ) << endl;

    // undetermined linear equations
    Matrix At( trT( A ) );
	b.resize( 3 );
	b[0]= 1;	b[1] = 2;   b[2]= 3;
	cout << "The original matrix A : " << At << endl;
    cout << "The constant vector b : " << b << endl;
	cout << "The least norm solution is (using generalized inverse) : "
         << lnSolver( At, b ) << endl;
	cout << "The least norm solution is (using QR decomposition) : "
         << qrLnSolver( At, b ) << endl;
    cout << "The least norm solution is (using SVD decomposition) : "
         << svdLnSolver( At, b ) << endl;

    cA = complexMatrix( At, -At );
    cb = complexVector( b );
    cout << "The original complex matrix cA : " << cA << endl;
    cout << "The constant complex vector cb : " << cb << endl;
	cout << "The least square solution is (using generalized inverse) : "
         << lnSolver( cA, cb ) << endl;
    cout << "The least square solution is (using QR decomposition) : "
         << qrLnSolver( cA, cb ) << endl;
    cout << "The least square solution is (using SVD decomposition) : "
         << svdLnSolver( cA, cb ) << endl;

	return 0;
}

运行结果:

The original matrix A : size: 4 by 3
1.000   -1.000  1.000
1.000   2.000   4.000
1.000   3.000   9.000
1.000   -4.000  16.000

The constant vector b : size: 4 by 1
1.000
2.000
3.000
4.000

The least square solution is (using generalized inverse) : size: 3 by 1
0.909
0.079
0.212

The least square solution is (using QR decomposition) : size: 3 by 1
0.909
0.079
0.212

The least square solution is (using SVD decomposition) : size: 3 by 1
0.909
0.079
0.212

The original complex matrix cA : size: 4 by 3
(1.000,1.000)   (-1.000,-1.000) (1.000,1.000)
(1.000,1.000)   (2.000,2.000)   (4.000,4.000)
(1.000,1.000)   (3.000,3.000)   (9.000,9.000)
(1.000,1.000)   (-4.000,-4.000) (16.000,16.000)

The constant complex vector cb : size: 4 by 1
(1.000,0.000)
(2.000,0.000)
(3.000,0.000)
(4.000,0.000)

The least square solution is (using generalized inverse) : size: 3 by 1
(0.455,-0.455)
(0.039,-0.039)
(0.106,-0.106)

The least square solution is (using QR decomposition) : size: 3 by 1
(0.455,-0.455)
(0.039,-0.039)
(0.106,-0.106)

The least square solution is (using SVD decomposition) : size: 3 by 1
(0.455,-0.455)
(0.039,-0.039)
(0.106,-0.106)

The original matrix A : size: 3 by 4
1.000   1.000   1.000   1.000
-1.000  2.000   3.000   -4.000
1.000   4.000   9.000   16.000

The constant vector b : size: 3 by 1
1.000
2.000
3.000

The least norm solution is (using generalized inverse) : size: 4 by 1
0.373
0.421
0.336
-0.130

The least norm solution is (using QR decomposition) : size: 4 by 1
0.373
0.421
0.336
-0.130

The least norm solution is (using SVD decomposition) : size: 4 by 1
0.373
0.421
0.336
-0.130

The original complex matrix cA : size: 3 by 4
(1.000,-1.000)  (1.000,-1.000)  (1.000,-1.000)  (1.000,-1.000)
(-1.000,1.000)  (2.000,-2.000)  (3.000,-3.000)  (-4.000,4.000)
(1.000,-1.000)  (4.000,-4.000)  (9.000,-9.000)  (16.000,-16.000)

The constant complex vector cb : size: 3 by 1
(1.000,0.000)
(2.000,0.000)
(3.000,0.000)

The least square solution is (using generalized inverse) : size: 4 by 1
(0.186,0.186)
(0.211,0.211)
(0.168,0.168)
(-0.065,-0.065)

The least square solution is (using QR decomposition) : size: 4 by 1
(0.186,0.186)
(0.211,0.211)
(0.168,0.168)
(-0.065,-0.065)

The least square solution is (using SVD decomposition) : size: 4 by 1
(0.186,0.186)
(0.211,0.211)
(0.168,0.168)
(-0.065,-0.065)


Process returned 0 (0x0)   execution time : 0.140 s
Press any key to continue.

转载于:https://my.oschina.net/zmjerry/blog/6185

你可能感兴趣的:(c/c++,操作系统,python)