吸收马尔可夫链在矩阵求逆过程中产生错误输出

问题描述

我有一个程序可以在 NxN 分数矩阵上运行逆矩阵计算。我选择这样做的算法是高斯消除算法。但是在对矩阵求逆后,结果值与预期值不同。

用于输入的矩阵:

[1/1,-43/252,-61/504,-3/8]
[0/1,1/1,-2/3,0/1]
[-5/81,-187/243,0/1]
[-1/1,0/1,1/1]

预期的矩阵输出

[42/25,91/100,81/100,63/100]
[252/1775,7563/3550,5103/3550,189/3550]
[378/1775,12039/7100,15309/7100,567/7100]
[42/25,163/100]

实际矩阵输出

[42/25,-160423/8076,-186456755/182802,-186639557/121868,163/100]

如您所见,只有 3 个矩阵单元格的值不正确。我针对其他几个矩阵对其进行了测试,我可以获得一些正确的输出,但并非总是如此。我真的不知道是什么原因造成的。

这里是程序的实际源代码

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Matrix m = new Matrix(new Rational[][]{
                {new Rational(1),new Rational(-43,252),new Rational(-61,504),new Rational(-3,8)},{new Rational(0),new Rational(1),new Rational(-2,3),new Rational(0)},{new Rational(-5,81),new Rational(-187,243),{new Rational(-1),new Rational(0),new Rational(1)},});
        System.out.println(m.invert());;
    }
}

class Rational {
    int numerator;
    int denominator;

    Rational(int num) {
        this.numerator = num;
        this.denominator = 1;
    }

    Rational(int numerator,int denominator) {
        if (numerator < 0 && denominator < 0)
            this.numerator = Math.abs(numerator);
        else
            this.numerator = denominator < 0 ? -numerator : numerator;

        this.denominator = Math.abs(denominator);
    }

    public Rational abs() { return new Rational(Math.abs(this.numerator),Math.abs(this.denominator)); }

    public boolean greaterThan(Rational rhs) {
        if (this.numerator * rhs.denominator > rhs.numerator * this.denominator) return true;
        return false;
    }

    public Rational subtract(Rational rhs) {
        return simplify(this.numerator * rhs.denominator - rhs.numerator * this.denominator,this.denominator * rhs.denominator);
    }

    public Rational multiply(Rational rhs) {
        return simplify(this.numerator * rhs.numerator,this.denominator * rhs.denominator);
    }

    public Rational divide(Rational rhs) {
        return simplify(this.numerator * rhs.denominator,this.denominator * rhs.numerator);
    }

    private Rational simplify(int num,int denom) {
        int gcd = gcd(Math.abs(num),Math.abs(denom));
        return gcd <= 0 ? new Rational(0) : new Rational(num / gcd,num == 0 ? 1 : denom / gcd);
    }

    public static int gcd(int i,int j) {
        return j == 0 ? i : gcd(j,i % j);
    }

    @Override
    public String toString() {
        return numerator + "/" + denominator;
    }
}

class Matrix {
    Rational[][] rows;

    Matrix(Rational[][] matrix) {
        this.rows = matrix;
    }

    public Matrix(int dimensions) {
        this.rows = new Rational[dimensions][dimensions];
        Arrays.stream(rows).forEach(rationals -> Arrays.fill(rationals,new Rational(0)));
    }

    public Matrix invert() {
        int n = rows.length;
        Matrix x = new Matrix(n);
        Matrix b = new Matrix(n).identity();
        int index[] = new int[n];

        // Transform the matrix into an upper triangle
        System.out.println(this);
        gaussian(index);
        System.out.println(this);

        // Update the matrix b[i][j] with the ratios stored
        for (int i = 0; i < n - 1; ++i)
            for (int j = i + 1; j < n; ++j)
                for (int k = 0; k < n; ++k)
                    b.rows[index[j]][k] = b.rows[index[j]][k].subtract(rows[index[j]][i].multiply(b.rows[index[i]][k]));

        // Perform backward substitutions
        for (int i = 0; i < n; ++i) {
            x.rows[n - 1][i] = b.rows[index[n - 1]][i].divide(rows[index[n - 1]][n - 1]);
            for (int j = n - 2; j >= 0; --j) {
                x.rows[j][i] = b.rows[index[j]][i];
                for (int k = j + 1; k < n; ++k)
                    x.rows[j][i] = x.rows[j][i].subtract(rows[index[j]][k].multiply(x.rows[k][i]));
                x.rows[j][i] = x.rows[j][i].divide(rows[index[j]][j]);
            }
        }
        return x;
    }

    // Method to carry out the partial-pivoting Gaussian
    // elimination.  Here index[] stores pivoting order.
    public void gaussian(int index[]) {
        int n = index.length;
        Rational c[] = new Rational[n];

        // Initialize the index
        for (int i = 0; i < n; ++i) index[i] = i;

        // Find the rescaling factors,one from each row
        for (int i = 0; i < n; ++i) {
            Rational c1 = new Rational(0);
            for (int j = 0; j < n; ++j) {
                Rational c0 = rows[i][j].abs();
                if (c0.greaterThan(c1)) c1 = c0;
            }
            c[i] = c1;
        }

        // Search the pivoting element from each column
        int k = 0;
        for (int j = 0; j < n - 1; ++j) {
            Rational pi1 = new Rational(0);
            for (int i = j; i < n; ++i) {
                Rational pi0 = rows[index[i]][j].abs();
                pi0 = pi0.divide(c[index[i]]);
                if (pi0.greaterThan(pi1)) {
                    pi1 = pi0;
                    k = i;
                }
            }

            // Interchange rows according to the pivoting order
            int itmp = index[j];
            index[j] = index[k];
            index[k] = itmp;
            for (int i = j + 1; i < n; ++i) {
                Rational pj = rows[index[i]][j].divide(rows[index[j]][j]);

                // Record pivoting ratios below the diagonal
                rows[index[i]][j] = pj;

                // Modify other elements accordingly
                for (int l = j + 1; l<n; ++l)
                    rows[index[i]][l] = rows[index[i]][l].subtract(pj.multiply(rows[index[j]][l]));
            }
        }
    }

    public Matrix identity() {
        for (int i = 0; i < rows.length; ++i)
            for (int j = 0; j < rows[0].length; ++j)rows[i][j] = new Rational(j == i ? 1 : 0);
        return new Matrix(rows);
    }

    @Override
    public String toString() {
        String s = "";
        for (Rational[] row: rows) s += "\t" + Arrays.toString(row) + "\n";
        return String.format("[\n%s]",s);
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)