我的高斯 - 约旦消灭有什么问题?

时间:2018-04-28 20:52:54

标签: algorithm scala matrix matrix-inverse

重要编辑

问题解决了。请在本StackOverflow问题中查看我自己的答案,了解具体方法。

但是,这是新的(并且正常工作)代码:

显示仪

显示器与下面相同。

我的正确和有效的实施

/**
  * Returns the identity matrix of the specified dimension
  * @param size the number of columns (i.e. the number of rows) of the desired identity matrix
  * @return the identity matrix of the specified dimension
  */
def getIdentityMatrix(size : Int): scala.collection.mutable.Seq[scala.collection.mutable.Seq[Double]] = {
  scala.collection.mutable.Seq.tabulate(size)(r => scala.collection.mutable.Seq.tabulate(size)(c => if(r == c) 1.0 else 0.0))
}

  /**
    * This algorithm processes column by column.
    * STEP 1. It finds the greatest coefficient for the current column (called 'a') and, if it equals 0, returns NULL (since the matrix
    * can't be inverted) ; otherwise (STEP 2.), it swaps the pivot's line with this new line and the pivot becomes the adequate coefficient
    * of this new line
    * STEP 3. It divides the pivot's line by the pivot
    * STEP 4. It sets each of the current column's coefficient to 0 by subtracting the corresponding lines by the pivot's line
    * @return
    */
  def getGaussJordanInvertedMatrix: (Matrix, Matrix) = {

    // We get first the matrix to be inverted, second the identity one
    val mutable_being_inversed_matrix : collection.mutable.Seq[collection.mutable.Seq[Double]] = scala.collection.mutable.Seq(content.map(ms => scala.collection.mutable.Seq(ms:_*)):_*)
    val identity_matrix : collection.mutable.Seq[collection.mutable.Seq[Double]] = getIdentityMatrix(content.length)  // We get the identity matrix. It will be modified
                                                                      // as the original matrix will.

    var id_last_pivot : Int = 0  // ID of the last pivot, i.e. ID of the current column
    content.indices.foreach(general_id_column => {
      println("Current column : " + general_id_column)

      //  STEP 1.
      val id_line_with_max_coefficient_in_this_column = (id_last_pivot until content.length).maxBy(id_line_in_this_column => Math.abs(mutable_being_inversed_matrix(id_line_in_this_column)(general_id_column)))

      if(mutable_being_inversed_matrix(id_line_with_max_coefficient_in_this_column)(general_id_column) == 0) {
        println("The Gauss-Jordan elimination's algorithm returns an error : indeed, the matrix can't be inverted")

      } else {

        //  STEP 2.
        val tmp_line : scala.collection.mutable.Seq[Double] = mutable_being_inversed_matrix(id_last_pivot)
        mutable_being_inversed_matrix(id_last_pivot) = mutable_being_inversed_matrix(id_line_with_max_coefficient_in_this_column)
        mutable_being_inversed_matrix(id_line_with_max_coefficient_in_this_column) = tmp_line

        val identity_tmp_line : scala.collection.mutable.Seq[Double] = identity_matrix(id_last_pivot)
        identity_matrix(id_last_pivot) = identity_matrix(id_line_with_max_coefficient_in_this_column)
        identity_matrix(id_line_with_max_coefficient_in_this_column) = identity_tmp_line
        println("\nSWAP DONE")
        println(Console.BLUE + "Original matrix :\n" + Console.RESET + mutable_being_inversed_matrix.mkString("\n"))
        println(Console.RED + "Identity matrix :\n" + Console.RESET + identity_matrix.mkString("\n"))

        //  STEP 3.
        val tmp = mutable_being_inversed_matrix(id_last_pivot)(general_id_column)
        mutable_being_inversed_matrix(id_last_pivot) = mutable_being_inversed_matrix(id_last_pivot).map(coefficient => coefficient / tmp)
        identity_matrix(id_last_pivot) = identity_matrix(id_last_pivot).map(coefficient => coefficient / tmp)

        println("\nDIVISION DONE")
        println(Console.BLUE + "Original matrix :\n" + Console.RESET + mutable_being_inversed_matrix.mkString("\n"))
        println(Console.RED + "Identity matrix :\n" + Console.RESET + identity_matrix.mkString("\n"))

        //  STEP 4.
        content.indices.foreach(id_line => {
          val tmp = mutable_being_inversed_matrix(id_line)(general_id_column)

          if(id_line != id_last_pivot) {
            content.indices.foreach(id_column => {
              mutable_being_inversed_matrix(id_line)(id_column) -= mutable_being_inversed_matrix(id_last_pivot)(id_column) * tmp
              identity_matrix(id_line)(id_column) -= identity_matrix(id_last_pivot)(id_column) * tmp
            })
          }

        })

        println("\nSUBTRACTION & MULTIPLICATION DONE")
        println(Console.BLUE + "Original matrix :\n" + Console.RESET + mutable_being_inversed_matrix.mkString("\n"))
        println(Console.RED + "Identity matrix :\n" + Console.RESET + identity_matrix.mkString("\n"))
        println()

        id_last_pivot += 1

      }

    })

    (new Matrix(identity_matrix), new Matrix(mutable_being_inversed_matrix))
  }

我试图实现高斯 - 乔丹消除的Scala版本来反转矩阵(NB:可变集合和命令范式用于简化实现 - 我尝试编写算法,但它&#&# 39;几乎不可能,因此算法包含嵌套步骤。

我的问题

单位矩阵没有很好地转化为反演的结果。换句话说:将单位矩阵转换为倒置矩阵(这是Gauss-Jordan消除的结果)是不正确的。

实施例

考虑这个矩阵(A):

  

(2.0,-1.0,0.0)

     

( - 1.0,2.0,-1.0)

     

(0.0,-1.0,2.0)

这一个(B):

  

(1.0,0.0,0.0)

     

(0.0,1.0,0.0)

     

(0.0,0.0,1.0)

如果我们应用Gauss-Jordan消除,A变为:

  

(1.0,0.0,0.0)

     

(0.0,1.0,0.0)

     

(0.0,0.0,1.0)

如果我们应用Gauss-Jordan消除,B变为:

  

(0.75 0.5 0.25)

     

(0.5 1 0.5)

     

(0.25 0.5 0.75)

如果我们应用我的实现,A就没有问题,因为我得到了以下矩阵:

  

(1.0,0.0,0.0)

     

(0.0,1.0,0.0)

     

(0.0,0.0,1.0)

但是,如果我们应用我的实现,B没有很好地转换,因为我获得了以下矩阵:

  

(1.0,0.5,0.0)

     

(1.0,0.5,0.66666666666666666)

     

(0.0,1.0,0.33333333333333337)

Gauss-Jordan的消除:关于该算法的解释

逐行进行3个步骤。这些步骤是:

  1. 我们在当前列^ 2中找到max ^ 1系数。如果它等于0,则意味着矩阵不能被反转并且算法返回该错误。否则,我们将包含max系数的行与包含pivot的行交换:换句话说,我们使用列的max系数更改pivot(NB:交换整行)。 ^ 1:max是仅用于除法精度原因的已使用函数(在步骤2中完成的除法)。另一个功能是随机功能。
  2. ^ 2:当前列中的最大系数是从第(z + 1)行找到的,其中z是我们使用的最后一个数据透视表的ID(即:最后一个工作列的ID)

    1. 我们将包含我们在步骤1得到的枢轴的整行划分为枢轴,将枢轴设置为1(在后面的句子中,表达式"枢轴"系统地指的是此枢轴我们得到了STEP 1)。顺便说一下,注意不太重要的事实,即同一条线的其他系数也是分开的(参见"我们将整行划分为#34;)。

    2. 我们将当前列的每一行整数减去绕轴的行,将所有当前列的系数设置为0.顺便说一下,注意不太重要的事实这些相同行的其他系数也被减去(参见"我们减去每一行")。

    3. 步骤3和步骤2在步骤1中实现(即:那些是嵌套的步骤)。必须在步骤2之后实现STEP 3(在STEP 3中实现的{减法和乘法}中使用数值= 1的旋转值。

      高斯 - 乔丹的消除:我的不工作实施

      输入

      val m : Matrix = new Matrix(Seq(Seq(2, -1, 0), Seq(-1, 2, -1), Seq(0, -1, 2)))
      

      此算法的未实现实现

      显示仪

      val m : Matrix = new Matrix(Seq(Seq(2, -1, 0), Seq(-1, 2, -1), Seq(0, -1, 2)))
      println("ORIGINAL MATRIX =\n" + m)
      println
      val result : (Matrix, Matrix) = m.getGaussJordanInvertedMatrix
      println()
      println("RESULT =\n" + Console.BLUE + "Original matrix :\n" + Console.RESET + result._2 + Console.RED + "\nIdentity matrix :\n" + Console.RESET + result._1)
      

      我的工作实施

      /**
        * Returns the identity matrix of the specified dimension
        * @param size the number of columns (i.e. the number of rows) of the desired identity matrix
        * @return the identity matrix of the specified dimension
        */
      def getIdentityMatrix(size : Int): scala.collection.mutable.Seq[scala.collection.mutable.Seq[Double]] = {
        scala.collection.mutable.Seq.tabulate(size)(r => scala.collection.mutable.Seq.tabulate(size)(c => if(r == c) 1.0 else 0.0))
      }
      
        /**
          * This algorithm processes column by column.
          * STEP 1. It finds the greatest coefficient for the current column (called 'a') and, if it equals 0, returns NULL (since the matrix
          * can't be inverted) ; otherwise (STEP 2.), it swaps the pivot's line with this new line and the pivot becomes the adequate coefficient
          * of this new line
          * STEP 3. It divides the pivot's line by the pivot
          * STEP 4. It sets each of the current column's coefficient to 0 by subtracting the corresponding lines by the pivot's line
          * @return
          */
        def getGaussJordanInvertedMatrix: (Matrix, Matrix) = {
      
          // We get first the matrix to be inverted, second the identity one
          val mutable_being_inversed_matrix : collection.mutable.Seq[collection.mutable.Seq[Double]] = scala.collection.mutable.Seq(content.map(ms => scala.collection.mutable.Seq(ms:_*)):_*)
          val identity_matrix : collection.mutable.Seq[collection.mutable.Seq[Double]] = getIdentityMatrix(content.length)  // We get the identity matrix. It will be modified
                                                                            // as the original matrix will.
      
          var id_last_pivot : Int = 0  // ID of the last pivot, i.e. ID of the current column
          content.indices.foreach(general_id_column => {
            println("Current column : " + general_id_column)
      
            //  STEP 1.
            val id_line_with_max_coefficient_in_this_column = (id_last_pivot until content.length).maxBy(id_line_in_this_column => Math.abs(mutable_being_inversed_matrix(id_line_in_this_column)(general_id_column)))
      
            if(mutable_being_inversed_matrix(id_line_with_max_coefficient_in_this_column)(general_id_column) == 0) {
              println("The Gauss-Jordan elimination's algorithm returns an error : indeed, the matrix can't be inverted")
      
            } else {
      
              //  STEP 2.
              val tmp_line : scala.collection.mutable.Seq[Double] = mutable_being_inversed_matrix(id_last_pivot)
              mutable_being_inversed_matrix(id_last_pivot) = mutable_being_inversed_matrix(id_line_with_max_coefficient_in_this_column)
              mutable_being_inversed_matrix(id_line_with_max_coefficient_in_this_column) = tmp_line
      
              val identity_tmp_line : scala.collection.mutable.Seq[Double] = identity_matrix(id_last_pivot)
              identity_matrix(id_last_pivot) = identity_matrix(id_line_with_max_coefficient_in_this_column)
              identity_matrix(id_line_with_max_coefficient_in_this_column) = identity_tmp_line
              println("\nSWAP DONE")
              println(Console.BLUE + "Original matrix :\n" + Console.RESET + mutable_being_inversed_matrix.mkString("\n"))
              println(Console.RED + "Identity matrix :\n" + Console.RESET + identity_matrix.mkString("\n"))
      
              //  STEP 3.
              mutable_being_inversed_matrix(id_last_pivot) = mutable_being_inversed_matrix(id_last_pivot).map(coefficient => coefficient / mutable_being_inversed_matrix(id_last_pivot)(general_id_column))
              identity_matrix(id_last_pivot) = identity_matrix(id_last_pivot).map(coefficient => coefficient / mutable_being_inversed_matrix(id_last_pivot)(general_id_column))
      
              println("\nDIVISION DONE")
              println(Console.BLUE + "Original matrix :\n" + Console.RESET + mutable_being_inversed_matrix.mkString("\n"))
              println(Console.RED + "Identity matrix :\n" + Console.RESET + identity_matrix.mkString("\n"))
      
              //  STEP 4.
              content.indices.foreach(id_line => {
                val tmp = mutable_being_inversed_matrix(id_line)(general_id_column)
      
                if(id_line != id_last_pivot) {
                  content.indices.foreach(id_column => {
                    mutable_being_inversed_matrix(id_line)(id_column) -= mutable_being_inversed_matrix(id_last_pivot)(id_column) * tmp
                    identity_matrix(id_line)(id_column) -= mutable_being_inversed_matrix(id_last_pivot)(id_column) * tmp
                  })
                }
      
              })
      
              println("\nSUBTRACTION & MULTIPLICATION DONE")
              println(Console.BLUE + "Original matrix :\n" + Console.RESET + mutable_being_inversed_matrix.mkString("\n"))
              println(Console.RED + "Identity matrix :\n" + Console.RESET + identity_matrix.mkString("\n"))
              println()
      
              id_last_pivot += 1
      
            }
      
          })
      
          (new Matrix(identity_matrix), new Matrix(mutable_being_inversed_matrix))
        }
      

      执行和输出

      您可以在此处使用此输入找到我的实施的执行:https://jsfiddle.net/wwhdu32x/

      故障排除

      您可以在此处找到疑难解答:https://jsfiddle.net/wwhdu32x/1/(以&#34开头的评论; ERROR"写入 - 注意:此故障排除仅涉及第一次迭代,即第一列)。

      我的问题

      为什么我的身份矩阵没有得到很好的转变?我怎么能处理它?<​​/ p>

1 个答案:

答案 0 :(得分:0)

问题解决了。问题已经更新,其中包括新代码(旧代码仍然可用,以便进行比较)。有两个错误(下面的“STEP XYZ”引用了相应的源代码的STEP,而不是这个StackOverflow问题中提到的步骤,它们有点不同):

  1. 关于单位矩阵的减法不使用单位矩阵的系数(步骤4)。错误修复:identity_matrix(id_line)(id_column) -= identity_matrix(id_last_pivot)(id_column) * tmp

  2. 其次,在STEP 3中,我忘了将枢轴存储在临时变量中,以便将两个矩阵(原始矩阵和标识矩阵)与它分开。在不存储它的情况下,在原始矩阵上划分后,枢轴的值发生了变化。错误修复:

        val tmp = mutable_being_inversed_matrix(id_last_pivot)(general_id_column)
        mutable_being_inversed_matrix(id_last_pivot) = mutable_being_inversed_matrix(id_last_pivot).map(coefficient => coefficient / tmp)
        identity_matrix(id_last_pivot) = identity_matrix(id_last_pivot).map(coefficient => coefficient / tmp)