C++ 从欠定系统中去除不可解方程

C++ 从欠定系统中去除不可解方程,c++,linear-algebra,eigen,C++,Linear Algebra,Eigen,我的程序试图解线性方程组。为此,它将矩阵系数矩阵和向量值向量组合起来,并使用特征值来求解它们,如下所示: Eigen::VectorXd sol_vector = coeff_matrix .colPivHouseholderQr().solve(value_vector); 问题是,这个系统既可能被过度确定,也可能被低估。在前一种情况下,Eigen给出了正确或不正确的解,我使用coeff\u matrix*sol\u vector-value\u vector检查该解 请考虑

我的程序试图解线性方程组。为此,它将矩阵
系数矩阵
和向量
值向量
组合起来,并使用特征值来求解它们,如下所示:

Eigen::VectorXd sol_vector = coeff_matrix
        .colPivHouseholderQr().solve(value_vector);
问题是,这个系统既可能被过度确定,也可能被低估。在前一种情况下,Eigen给出了正确或不正确的解,我使用
coeff\u matrix*sol\u vector-value\u vector
检查该解

请考虑以下方程组:

a + b - c     =  0
        c - d =  0
        c     = 11
      - c + d =  0
在这种特殊情况下,Eigen正确地求解了后三个方程,但也给出了
a
b
的解

我想实现的是,只有只有只有一个解的方程会被解,剩下的方程(这里的第一个方程)会保留在系统中

换句话说,我在寻找一种方法,找出在给定的方程组中,哪些方程可以求解,哪些不能,因为会有多个解

你能提出实现这一目标的好方法吗


编辑:请注意,在大多数情况下,矩阵不是正方形的。我在这里又增加了一行,只是为了说明过度决定也可能发生。

您需要的是计算系统的行列式。如果行列式为0,则有无穷多个解。如果行列式很小,那么解是存在的,但我不相信计算机找到的解(它会导致数值不稳定)

以下是关于什么是决定因素以及如何计算它的链接:

请注意,高斯消去法也应起作用: 使用此方法,如果有无限多个解,则最终将得到0行

编辑

如果矩阵不是正方形,首先需要提取一个正方形矩阵。有两种情况:

  • 你有比方程更多的变量:那么你要么没有解,要么有无限多的解
  • 方程比变量多:在这种情况下,找到一个非空行列式的方子矩阵。求解此矩阵并检查解决方案。如果解决方案不合适,就意味着你没有解决方案。如果解合适,这意味着额外的方程与提取的方程线性相关
  • 在这两种情况下,在检查矩阵的维度之前,请删除只有0的行和列


    至于高斯消去法,它应该直接用于非平方矩阵。但是,这一次,您应该检查非空行(即具有一些非0值的行)的数量是否等于变量的数量。如果它少,你就有无穷多的解,如果它多,你就没有任何解。

    我想你想要的是,它会给你你想要的。奇异值分解后,“只有一个解的方程组将被求解”,并且解是伪逆的。它还将为您提供零空间(无限解来自何处)和左零空间(不一致性来自何处,即无解)。

    根据SVD注释,我可以这样做:

    Eigen::FullPivLU<Eigen::MatrixXd> lu = coeff_matrix.fullPivLu();
    
    Eigen::VectorXd sol_vector = lu.solve(value_vector);
    Eigen::VectorXd null_vector = lu.kernel().rowwise().sum();
    
    Eigen::FullPivLU lu=coeff_matrix.FullPivLU();
    特征::VectorXd sol_vector=lu.solve(值_vector);
    特征::VectorXd null_vector=lu.kernel().rowwise().sum();
    
    AFAICS中,对应于单个解的
    null\u向量
    行为
    0
    s,而对应于非确定解的行为
    1
    s。我可以用默认的treshold特征值在我所有的例子中重现这一点


    但是,我不确定我是否做了正确的事情,或者只是注意到了一个随机模式。

    行列式仅在平方矩阵中有效。@MichałGórny我编辑了非平方情况下的解。但只有平方矩阵才有唯一的解。另外,你的例子是一个平方矩阵,我的例子也是一个超定矩阵,其中两个变量有唯一的解。没有什么是那么简单的。。。顺便说一句,我也在想类似的事情,但我担心所有的计算都会使求解效率非常低。你能给我指一些能帮助我理解如何使用它的页面或文档吗?维基百科讲了很多数学…实际上学习SVD需要相当多的数学,SVD是线性代数的高潮。我只是在谷歌上搜索了一些介绍,看,还有。谢谢。我在空空间中移动了一点,组装了一些东西,并将其粘贴为解决方案(因为注释对实际代码不好)。不确定我是真的发明了什么,还是仅仅是一个随机模式。如果我正确地记住了我的线性代数,它似乎是正确的。我曾在应用线性代数考试中使用过类似的技巧,我们被允许使用matlab,但必须一步一步地解决问题。