病态方程组求解方法的C++实现(支持复系数方程组)

头文件:

/*
 * 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
 */


/*****************************************************************************
 *                                linequs3.h
 *
 * Function template for solving Rank Defect linear equations.
 *
 * For a m-by-n coefficient matrix A and m-by-1 constant vector b, if A is a
 * Rank Deficient Matrix, then the conventional methods will fail to solve
 * Ax = b. Three methods for solving such problem are provided in this file,
 * they are: Truncated SVD, Dampted SVD and Tikhonov Regularization.
 *
 * These methods adapt to both REAL or COMPLEX linear equations.
 *
 * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University.
 *****************************************************************************/


#ifndef RANKDEFLINEQUS_H
#define RANKDEFLINEQUS_H


#include <svd.h>
#include <csvd.h>


namespace splab
{

	template<typename Real>
	Vector<Real> tsvd( const Matrix<Real>&, const Vector<Real>&,
                       Real tol=Real(-1.0) );
	template<typename Type>
	Vector<complex<Type> > tsvd( const Matrix<complex<Type> >&,
                                 const Vector<complex<Type> >&, Type tol=Type(-1.0) );

	template<typename Real>
	Vector<Real> dsvd( const Matrix<Real>&, const Vector<Real>&, Real& );
	template<typename Type>
	Vector<complex<Type> > dsvd( const Matrix<complex<Type> >&,
                                 const Vector<complex<Type> >&, Type& );

	template<typename Real>
	Vector<Real> tikhonov( const Matrix<Real>&, const Vector<Real>&, Real& );
	template<typename Type>
	Vector<complex<Type> > tikhonov( const Matrix<complex<Type> >&,
                                     const Vector<complex<Type> >&, Type& );


	#include <linequs3-impl.h>

}
// namespace splab


#endif
// RANKDEFLINEQUS_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
 */


/*****************************************************************************
 *                            linequs3-impl.h
 *
 * Implementation for Rank Defect linear equations.
 *
 * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University.
 *****************************************************************************/


/**
 * Rank defect linear equationequations solution by Truncated SVD.
 * A  --->  The m-by-n coefficient matrix(Rank Defect);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 solution vector.
 */
template <typename Real>
Vector<Real> tsvd( const Matrix<Real> &A, const Vector<Real> &b, Real tol )
{
    int m = A.rows(),
        n = A.cols();

    assert( m == b.size() );

    SVD<Real> svd;
    svd.dec( A );
    Matrix<Real> U = svd.getU();
    Matrix<Real> V = svd.getV();
    Vector<Real> s = svd.getSV();
    Vector<Real> x(n);

    int r = 0;
    if( tol <= 0 )
        tol = max( m, n ) * s[0] * EPS;
    for( int i=0; i<s.size(); ++i )
        if( s[i] >= tol )
            r++;

    // y = U^T * b
    Vector<Real> y(r);
    for( int i=0; i<r; ++i )
        for( int j=0; j<m; ++j )
            y[i] += U[j][i]*b[j];

    // y = y / s
    for( int i=0; i<r; ++i )
        y[i] /= s[i];

    // x = V * y
    for( int i=0; i<n; ++i )
        for( int j=0; j<r; ++j )
            x[i] += V[i][j]*y[j];

//    for( int i=0; i<n; ++i )
//        for( int j=0; j<r; ++j )
//        {
//            Real sum = 0;
//            for( int k=0; k<m; ++k )
//                sum += U[k][j]*b[k];
//            x[i] += sum * V[i][j] / s[j];
//        }

    return x;
}


/**
 * Rank defect complex linear equationequations solution by Truncated SVD.
 * A  --->  The m-by-n coefficient matrix(Rank Defect);
 * b  --->  The n-by-1 right-hand side vector;
 * x  --->  The n-by-1 solution vector.
 */
template <typename Type>
Vector<complex<Type> > tsvd( const Matrix<complex<Type> > &A,
                             const Vector<complex<Type> > &b,
                             Type tol )
{
    int m = A.rows(),
        n = A.cols();

    assert( m == b.size() );

    CSVD<Type> svd;
    svd.dec( A );
    Matrix<complex<Type> > U = svd.getU();
    Matrix<complex<Type> > V = svd.getV();
    Vector<Type> s = svd.getSV();
    Vector<complex<Type> > x(n);

    int r = 0;
    if( tol <= 0 )
        tol = max( m, n ) * s[0] * EPS;
    for( int i=0; i<s.size(); ++i )
        if( s[i] >= tol )
            r++;

    // y = U^H * b
    Vector<complex<Type> > y(r);
    for( int i=0; i<r; ++i )
        for( int j=0; j<m; ++j )
            y[i] += conj(U[j][i])*b[j];

    // y = y / s
    for( int i=0; i<r; ++i )
        y[i] /= s[i];

    // x = V * y
    for( int i=0; i<n; ++i )
        for( int j=0; j<r; ++j )
            x[i] += V[i][j]*y[j];

//    for( int i=0; i<n; ++i )
//        for( int j=0; j<r; ++j )
//        {
//            complex<Type> sum = 0;
//            for( int k=0; k<m; ++k )
//                sum += conj(U[k][j])*b[k];
//            x[i] += sum * V[i][j] / s[j];
//        }

    return x;
}


/**
 * Rank defect linear equationequations solution by Dampted SVD.
 * A  --->  The m-by-n(m>n) coefficient matrix(Rank Defect);
 * b  --->  The n-by-1 right-hand side vector;
 * sigma :  dampted factor;
 * x  --->  The n-by-1 solution vector.
 */
template <typename Real>
Vector<Real> dsvd( const Matrix<Real> &A, const Vector<Real> &b,
                   Real &sigma )
{
    int m = A.rows(),
        n = A.cols();

    assert( m == b.size() );

    SVD<Real> svd;
    svd.dec( A );
    Matrix<Real> U = svd.getU();
    Matrix<Real> V = svd.getV();
    Vector<Real> s = svd.getSV();
    Vector<Real> x(n);

    int p = s.size();
    s += sigma;

    // y = U^T * b
    Vector<Real> y(p);
    for( int i=0; i<p; ++i )
        for( int j=0; j<m; ++j )
            y[i] += U[j][i]*b[j];

    // y = y / s
    for( int i=0; i<p; ++i )
        y[i] /= s[i];

    // x = V * y
    for( int i=0; i<n; ++i )
        for( int j=0; j<p; ++j )
            x[i] += V[i][j]*y[j];

//    for( int i=0; i<n; ++i )
//        for( int j=0; j<p; ++j )
//        {
//            Real sum = 0;
//            for( int k=0; k<m; ++k )
//                sum += U[k][j]*b[k];
//            x[i] += sum * V[i][j] / s[j];
//        }

    return x;
}


/**
 * Rank defect complex linear equationequations solution by Dampted SVD.
 * A  --->  The m-by-n(m>n) coefficient matrix(Rank Defect);
 * b  --->  The n-by-1 right-hand side vector;
 * sigma :  dampted factor;
 * x  --->  The n-by-1 solution vector.
 */
template <typename Type>
Vector<complex<Type> > dsvd( const Matrix<complex<Type> > &A,
                             const Vector<complex<Type> > &b,
                             Type &sigma )
{
    int m = A.rows(),
        n = A.cols();

    assert( m == b.size() );

    CSVD<Type> svd;
    svd.dec( A );
    Matrix<complex<Type> > U = svd.getU();
    Matrix<complex<Type> > V = svd.getV();
    Vector<Type> s = svd.getSV();
    Vector<complex<Type> > x(n);

    int p = s.size();
    s += sigma;

    // y = U^H * b
    Vector<complex<Type> > y(p);
    for( int i=0; i<p; ++i )
        for( int j=0; j<m; ++j )
            y[i] += conj(U[j][i])*b[j];

    // y = y / s
    for( int i=0; i<p; ++i )
        y[i] /= s[i];

    // x = V * y
    for( int i=0; i<n; ++i )
        for( int j=0; j<p; ++j )
            x[i] += V[i][j]*y[j];

//    for( int i=0; i<n; ++i )
//        for( int j=0; j<p; ++j )
//        {
//            complex<Type> sum = 0;
//            for( int k=0; k<m; ++k )
//                sum += conj(U[k][j])*b[k];
//            x[i] += sum * V[i][j] / s[j];
//        }

    return x;
}


/**
 * Rank defect linear equationequations solution by Tikhonov Regularization.
 * A  --->  The m-by-n(m>n) coefficient matrix(Rank Defect);
 * b  --->  The n-by-1 right-hand side vector;
 * alpha :  regularization factor;
 * x  --->  The n-by-1 solution vector.
 */
template <typename Real>
Vector<Real> tikhonov( const Matrix<Real> &A, const Vector<Real> &b,
                       Real &alpha )
{
    int m = A.rows(),
        n = A.cols();

    assert( m == b.size() );

    SVD<Real> svd;
    svd.dec( A );
    Matrix<Real> U = svd.getU();
    Matrix<Real> V = svd.getV();
    Vector<Real> s = svd.getSV();
    Vector<Real> x(n);

    int p = s.size();
    Real alpha2 = alpha*alpha;
    for( int i=0; i<p; ++i )
        s[i] += alpha2/s[i];

    // y = U^T * b
    Vector<Real> y(p);
    for( int i=0; i<p; ++i )
        for( int j=0; j<m; ++j )
            y[i] += U[j][i]*b[j];

    // y = y / s
    for( int i=0; i<p; ++i )
        y[i] /= s[i];

    // x = V * y
    for( int i=0; i<n; ++i )
        for( int j=0; j<p; ++j )
            x[i] += V[i][j]*y[j];

//    for( int i=0; i<n; ++i )
//        for( int j=0; j<p; ++j )
//        {
//            Real sum = 0;
//            for( int k=0; k<m; ++k )
//                sum += U[k][j]*b[k];
//            x[i] += sum * V[i][j] / s[j];
//        }

    return x;
}


/**
 * Rank defect complex linear equationequations solution by
 * Tikhonov Regularization.
 * A  --->  The m-by-n(m>n) coefficient matrix(Rank Defect);
 * b  --->  The n-by-1 right-hand side vector;
 * alpha :  regularization factor;
 * x  --->  The n-by-1 solution vector.
 */
template <typename Type>
Vector<complex<Type> > tikhonov( const Matrix<complex<Type> > &A,
                                 const Vector<complex<Type> > &b,
                                 Type &alpha )
{
    int m = A.rows(),
        n = A.cols();

    assert( m == b.size() );

    CSVD<Type> svd;
    svd.dec( A );
    Matrix<complex<Type> > U = svd.getU();
    Matrix<complex<Type> > V = svd.getV();
    Vector<Type> s = svd.getSV();
    Vector<complex<Type> > x(n);

    int p = s.size();
    Type alpha2 = alpha*alpha;
    for( int i=0; i<p; ++i )
        s[i] += alpha2/s[i];

    // y = U^H * b
    Vector<complex<Type> > y(p);
    for( int i=0; i<p; ++i )
        for( int j=0; j<m; ++j )
            y[i] += conj(U[j][i])*b[j];

    // y = y / s
    for( int i=0; i<p; ++i )
        y[i] /= s[i];

    // x = V * y
    for( int i=0; i<n; ++i )
        for( int j=0; j<p; ++j )
            x[i] += V[i][j]*y[j];

//    for( int i=0; i<n; ++i )
//        for( int j=0; j<p; ++j )
//        {
//            complex<Type> sum = 0;
//            for( int k=0; k<m; ++k )
//                sum += conj(U[k][j])*b[k];
//            x[i] += sum * V[i][j] / s[j];
//        }

    return x;
}

运行结果:

The original matrix A : size: 8 by 6
64.0000 2.0000  3.0000  61.0000 60.0000 6.0000
9.0000  55.0000 54.0000 12.0000 13.0000 51.0000
17.0000 47.0000 46.0000 20.0000 21.0000 43.0000
40.0000 26.0000 27.0000 37.0000 36.0000 30.0000
32.0000 34.0000 35.0000 29.0000 28.0000 38.0000
41.0000 23.0000 22.0000 44.0000 45.0000 19.0000
49.0000 15.0000 14.0000 52.0000 53.0000 11.0000
8.0000  58.0000 59.0000 5.0000  4.0000  62.0000

The constant vector b : size: 8 by 1
260.0000
260.0000
260.0000
260.0000
260.0000
260.0000
260.0000
260.0000

The solution of Truncated SVD (is consistent with Matlab) :
size: 6 by 1
1.1538
1.4615
1.3846
1.3846
1.4615
1.1538

The solution of Damped SVD with alpha = 0.0000 :
size: 6 by 1
1.1539
1.4615
1.3847
1.3847
1.4615
1.1538

The solution of Tikhonov Regularization with alpha = 0.0000 :
size: 6 by 1
1.1538
1.4615
1.3846
1.3846
1.4615
1.1538

The original complex matrix cA is: A - jA

The constant complex vector cb is: b

The solution of Truncated SVD (is consistent with Matlab) :
size: 6 by 1
(0.5769,0.5769)
(0.7308,0.7308)
(0.6923,0.6923)
(0.6923,0.6923)
(0.7308,0.7308)
(0.5769,0.5769)

The solution of Damped SVD with alpha = 0.0000 :
size: 6 by 1
(0.5769,0.5769)
(0.7308,0.7308)
(0.6923,0.6923)
(0.6923,0.6923)
(0.7308,0.7308)
(0.5769,0.5769)

The solution of Tikhonov Regularization with alpha = 0.0000 :
size: 6 by 1
(0.5769,0.5769)
(0.7308,0.7308)
(0.6923,0.6923)
(0.6923,0.6923)
(0.7308,0.7308)
(0.5769,0.5769)


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

你可能感兴趣的:(病态方程组求解方法的C++实现(支持复系数方程组))