51 线性代数开发

2023-10-21  本文已影响0人  北极的大企鹅

前景提示

需求

6f7f22d48561ecc95e07f11c4741a9c.jpg 663ea051f8abc9c42702477261980b9.jpg 42a391db77d91ca414d6442d5fa7f77.jpg

分析

1、初始化不需要指定矩阵的尺寸,并且可以直接传入数据。

2、可以计算2x2矩阵的逆

3、可以做2x2的矩阵乘法

Java版本开发

一、 开发详情

1、开发一个子类,如图所示。

image.png

父类



package com.grandfather.www.marixs;

/**
 * @projectName: marixs
 * @package: com.grandfathers.www.marixs
 * @className: BaseMatrix
 * @author: your-father
 * @description: TODO
 * @date: 2023-09-30 20:58
 * @version: 1.0
 */
public class BaseMatrix {

    // 矩阵的行列数
    int m = 0, n = 0;

    // 矩阵的数据
    float data[];

    public BaseMatrix() {
    }

    // 构造函数
    public BaseMatrix(int m, int n) {
        this.m = m;
        this.n = n;
        this.data = new float[m * n];
    }

    // 设置矩阵
    public void setData(float[] data) {
        this.data = data;
    }

    public float[] getData() {
        return data;
    }

    // 显示矩阵的信息
    void showInfo() {

        System.out.println("-----------");

        System.out.println("矩阵尺寸为: " + m + "x" + n);

        System.out.println("矩阵的数据为 : ");

        for (int i = 0; i < this.data.length; i++) {

            System.out.println(this.data[i] + ",");

            if ((i + 1) % n == 0) {
                System.out.println("\n");
            }
        }

        System.out.println("------------");

    }


    // 矩阵加法
    BaseMatrix add(BaseMatrix m2) {

        if ((this.m == m2.m) && (this.n == m2.n)) {

            float[] d = new float[m * n];

            for (int i = 0; i < m * n; i++) {
                d[i] = this.data[i] + m2.data[i];
            }

            BaseMatrix baseMatrix = new BaseMatrix(m, n);

            // 结果放到新的矩阵中
            baseMatrix.setData(d);

            return baseMatrix;
        } else {

            System.out.println("两个矩阵尺寸不一致,无法做加法");

            return null;
        }

    }

}


子类

public class Marix_2X2 extends BaseMatrix {


    public static void main(String[] args) {

        // 查看矩阵
        Marix_2X2 marix2X2 = new Marix_2X2();
        marix2X2.setData(new float[]{1, 2, 2, 5});
        marix2X2.n=2;
        marix2X2.showInfo();

    }

}
image-20231010081649114.png

2、根据问题修改子类,父类,以便真实可用

解决1、初始化不需要指定矩阵的尺寸,并且可以直接传入数据。
image-20231010082003211.png
  
  public class Marix_2X2 extends BaseMatrix {


    public Marix_2X2() {
    }
    
    public Marix_2X2(float[] data) {
        super();
        this.data = data;
        createBase(data);
    }
    
    BaseMatrix createBase(float[] data) {
    
        int m = 0, n = 0;
    
        for (int i = 0; i < data.length; i++) {
    
            if (i % 2 == 0) {
                n = i;
            } else {
                m = i;
            }
    
        }
    
        this.m = m;
        this.n = n;
    
        BaseMatrix baseMatrix = new BaseMatrix(m, n);
    
        // 结果放到新的矩阵中
        baseMatrix.setData(data);
    
        return baseMatrix;
    }

}

// 显示矩阵的信息
    @Override
    void showInfo() {

        System.out.println("-----------");

        System.out.println("矩阵尺寸为: " + (m - 1) + "x" + n);

        System.out.println("矩阵的数据为 : ");

        for (int i = 0; i < this.data.length; i++) {

            System.out.print(this.data[i] + ",");

            if ((i + 1) % n == 0) {
                System.out.println();
            }
        }

        System.out.println("------------");
        System.out.println();

    }

image-20231010083741556.png
解决 2、可以计算2x2矩阵的逆

样例一

 
 // 判断数组的元素是否全为0
 boolean flag = true;
 
 private Marix_2X2 get_inverse() {

        Marix_2X2 m1 = new Marix_2X2(this.data);

        if (null != this.data) {

            float[] newdata = this.data;

            int temp = 0;

            for (int i = 0; i < newdata.length; i++) {
                if (newdata[i] == 0) {
                    temp++;
                }
            }

            if (temp == newdata.length) {
                m1.flag = false;
            } else {


                float[][] newdata2 = new float[this.m - 1][this.n];
                newdata2 = one2Two(newdata, newdata2);

                float[][] floats = gaussianElimination(newdata2);

                float[] result = two2One(floats, newdata);

                m1.setData(result);

                return m1;
            }

            return m1;
        } else {

            System.out.println("为传入合法的数据....");

            return null;
        }
    }

    float[][] gaussianElimination(float[][] arr) {
        int i, j, k;

        float tem_1, tem_2, tem_3;
        int N = arr.length;
        float[][] W = new float[N][2 * N];
        float[][] result = new float[N][N];

        // 对矩阵右半部分进行扩增
        for (i = 0; i < arr.length; i++) {
            for (j = 0; j < 2 * arr.length; j++) {
                if (j < arr.length) {
                    W[i][j] = arr[i][j];
                } else {
                    W[i][j] = (float) (j - N == i ? 1 : 0);
                }
            }
        }

        for (i = 0; i < N; i++) {
            // 判断矩阵第一行第一列的元素是否为0,若为0,继续判断第二行第一列元素,直到不为0,将其加到第一行
            if (((int) W[i][i]) == 0) {
                for (j = i + 1; j < N; j++) {
                    if (((int) W[j][i]) != 0) {
                        break;
                    }
                }
                if (j == N) {
                    System.out.print("这个矩阵不能求逆");
                    break;
                }
                //将前面为0的行加上后面某一行
                for (k = 0; k < 2 * N; k++) {
                    W[i][k] += W[j][k];
                }
            }

            //将前面行首位元素置1
            tem_1 = W[i][i];
            for (j = 0; j < 2 * N; j++) {
                W[i][j] = W[i][j] / tem_1;
            }

            //将后面所有行首位元素置为0
            for (j = i + 1; j < N; j++) {
                tem_2 = W[j][i];
                for (k = i; k < 2 * N; k++) {
                    W[j][k] = W[j][k] - tem_2 * W[i][k];
                }
            }
        }

        // 将矩阵前半部分标准化
        for (i = N - 1; i >= 0; i--) {
            for (j = i - 1; j >= 0; j--) {
                tem_3 = W[j][i];
                for (k = i; k < 2 * N; k++) {
                    W[j][k] = W[j][k] - tem_3 * W[i][k];
                }
            }
        }

        //得出逆矩阵
        for (i = 0; i < N; i++) {
            for (j = N; j < 2 * N; j++) {
                result[i][j - N] = W[i][j];
            }
        }

        return result;

    }

    /*!!!注意:
     * 1.传入的数组里两个数组的大小(一维数组length为10,则二维数组的行数乘列数也为10
     * 2.数组类型必须一样
     * */
    public static float[][] one2Two(float[] data, float[][] da) {
        int k = 0;
        int hang = da.length;
        int lie = 0;

        if (!isAllZero(da)) {
            lie = da[0].length;
        } else {
            lie = 1;
        }

        for (int i = 0; i < hang; i++) {
            for (int j = 0; j < lie; j++) {
                da[i][j] = data[k];
                k++;
            }
        }

        return da;
    }


    /*!!!注意:
     * 1.传入的数组里两个数组的大小(一维数组length为10,则二维数组的行数乘列数也为10
     * 2.数组类型必须一样
     * */
    public static float[] two2One(float[][] da, float[] data) {
        int k = 0;
        int hang = da.length;
        int lie = 0;
        if (!isAllZero(da)) {
            lie = da[0].length;
        } else {
            lie = 1;
        }

        for (int i = 0; i < hang; i++) {
            for (int j = 0; j < lie; j++) {
                data[k] = da[i][j];
                k++;
            }
        }

        return data;
    }

    private static boolean isAllZero(float[][] onwResult) {
        int temp = 0;

        for (float[] floats : onwResult) {
            for (float aFloat : floats) {
                if (aFloat == 0) {
                    temp++;
                }
            }
        }

        if (temp == onwResult.length) {
            return true;
        } else {
            return false;
        }
    }
    
    // 添加了全为0 的判断
    // 显示矩阵的信息
    @Override
    void showInfo() {

        if (flag) {
            System.out.println("-----------");

            System.out.println("矩阵尺寸为: " + (m - 1) + "x" + n);

            System.out.println("矩阵的数据为 : ");

            for (int i = 0; i < this.data.length; i++) {

                System.out.print(this.data[i] + ",");

                if ((i + 1) % n == 0) {
                    System.out.println();
                }
            }

            System.out.println("------------");
            System.out.println();
        } else {
            System.out.println("行列式为0,不能求逆矩阵");
            System.out.println();
        }

    }

测试

       // 全为0的矩阵
        Marix_2X2 m1 = new Marix_2X2(new float[]{0, 0, 0, 0});
        Marix_2X2 tmp = m1.get_inverse();
        assert tmp != null;
        tmp.showInfo();
       
(1) 第二题第一问,全为零打印
image-20231010091943351.png
(2)第二题第二问,逆矩阵输出
image-20231010091955504.png
解决 3、可以做2x2的矩阵乘法

矩阵的乘法

private Marix_2X2 mul(Marix_2X2 m3) {


        float[][] a = new float[this.m - 1][this.n];
        one2Two(this.getData(), a);

        float[][] b = new float[this.m - 1][this.n];
        one2Two(m3.getData(), b);

        float[][] c = new float[this.m - 1][this.n];
        float[] newdata = this.data;

        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a.length; j++) {
                for (int k = 0; k < a.length; k++) {
                    c[i][j] += a[i][k] * b[k][j];
                }
            }
        }


        float[] result = two2One(c, newdata);

        m3.setData(result);

        return m3;
    }

替换逆矩阵算法

    //求解逆矩阵
    public Marix_2X2 get_inverse_2() {

        Marix_2X2 m1 = new Marix_2X2(this.data);

        if (null != this.data) {

            int temp = 0;

            float[] onwResult = this.data;

            temp = isAllZero(temp, onwResult);

            if (temp == onwResult.length) {
                m1.flag = false;
            } else {

                float[][] floats = new float[this.m - 1][this.n];

                float[][] floats2 = one2Two(m1.getData(), floats);

                int row = floats2.length;
                float[][] floats1 = CopyArry(floats2);
                float[][] floats6 = new float[row][row];
                float[][] floats7 = AdjointMatrix(floats1);
                for (int i = 0; i < row; i++) {
                    for (int i1 = 0; i1 < row; i1++) {
                        floats6[i][i1] = floats7[i][i1] / ArrayCount(floats1, row);
                    }
                }


                float[] result = two2One(floats6, onwResult);

                m1.setData(result);


            }
            return m1;
        } else {

            System.out.println("为传入合法的数据....");

            return null;
        }
    }

    //矩阵的复制
    public static float[][] CopyArry(float[][] floats) {
        int row = floats.length;
        float[][] floats1 = new float[row][row];
        for (int i = 0; i < row; i++) {
            for (int i1 = 0; i1 < row; i1++) {
                floats1[i][i1] = floats[i][i1];
            }
        }
        return floats1;
    }


    //矩阵求伴随矩阵
    public static float[][] AdjointMatrix(float[][] floats) {

        int row = floats.length;
        float[][] floats1 = CopyArry(floats);


        float[][] floats4 = new float[row][row];
        for (int i = 0; i < row; i++) {
            for (int i1 = 0; i1 < row; i1++) {

                floats4[i1][i] = (-1) * (((i + i1) % 2) == 1 ? 1 : -1) * ArrayCount(RemoveRC(floats1, row, i, i1), row - 1);
            }
        }
        return floats4;
    }


    // 计算数组行列式方法
    public static float ArrayCount(float a[][], int n) {

        float p = 0;

        for (int k = 0; k <= n - 2; k++) {
            for (int r = k + 1; r <= n - 1; r++) {
                if (a[k][k] == 0) {
                    try {
                        ArrayChange(a, k, n);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                        return 0;
                    }
                }
                p = -(a[r][k] / a[k][k]);
                for (int i = k; i <= n - 1; i++) {
                    a[r][i] = a[k][i] * p + a[r][i];
                }
            }


        }
        float result = 1;
        for (int i = 0; i <= n - 1; i++) {
            result *= a[i][i];

        }


        return result;
    }


    /**
     * @param a 传入的数组
     * @param k 出现问题的元素的行和列的坐标数值
     * @param n 数组的长度 ,虽然是从0 标开始,但是这里仍然使用n来计数
     */
    public static void ArrayChange(float a[][], int k, int n) {
        float b[] = new float[n - k];
        int c = k;
        for (int i = k + 1; i <= n - 1; i++) {
            if (a[i][k] != 0) {
                c = i;
            }
        }
        if (c == k) {
            throw new RuntimeException("高斯求解失败");
        }
        int w = 0;
        for (int i = k; i <= n - 1; i++) {
            b[w] = a[k][i];
            a[k][i] = a[c][i];
            a[c][i] = b[w];
            w++;
        }


    }

    //去掉固定的行和列的行列式
    public static float[][] RemoveRC(float[][] floats, int n, int p, int q) {
        float[][] floats1 = new float[n][n];
        float[][] floats2 = new float[n - 1][n - 1];
        ArrayList<Float> arrayList = new ArrayList<>((n - 1) * (n - 1));
        for (int i = 0; i <= n - 1; i++) {
            for (int i1 = 0; i1 <= n - 1; i1++) {
                floats1[i][i1] = floats[i][i1];
            }

        }
        for (int i = 0; i <= n - 1; i++) {
            for (int i1 = 0; i1 <= n - 1; i1++) {
                if (i == p || i1 == q) {

                } else {
                    arrayList.add(floats[i][i1]);

                }
            }

        }
        Object[] objects = arrayList.toArray();
        int index = 0;
        for (int i = 0; i < n - 1; i++) {
            for (int i1 = 0; i1 < n - 1; i1++) {
                floats2[i][i1] = (float) objects[index];
                index++;

            }

        }


        return floats2;
    }
(1) 第三题第一问,逆矩阵乘法
image-20231010093652885.png
(2)第三题第二问,复合乘法
image-20231010093943893.png

二、最终完整版

package com.grandfathers.www.exersice;/**
 * @author: MrLiu
 * @createTime: 2023/09/30 20:58
 * @description: xxx
 */

/**
 * @projectName: anlysistSentence
 * @package: com.grandfathers.www.exersice
 * @className: BaseMatrix
 * @author: your-father
 * @description: TODO
 * @date: 2023-09-30 20:58
 * @version: 1.0
 */
public class BaseMatrix {

    // 矩阵的行列数
    int m = 0, n = 0;

    // 矩阵的数据
    float data[];

    public BaseMatrix() {
    }

    // 构造函数
    public BaseMatrix(int m, int n) {
        this.m = m;
        this.n = n;
        this.data = new float[m * n];
    }

//    public BaseMatrix(float[] data) {
//        this.data = data;
//        createBase(data);
//    }




    // 设置矩阵睡觉
    public void setData(float[] data) {
        this.data = data;
    }

    public float[] getData() {
        return data;
    }

    // 显示矩阵的信息
    void showInfo() {

        System.out.println("-----------");

        System.out.println("矩阵尺寸为: " + m + "x" + n);

        System.out.println("矩阵的数据为 : ");

        for (int i = 0; i < this.data.length; i++) {

            System.out.println(this.data[i] + ",");

            if ((i + 1) % n == 0) {
                System.out.println("\n");
            }
        }

        System.out.println("------------");

    }


    // 矩阵加法
    BaseMatrix add(BaseMatrix m2) {

        if ((this.m == m2.m) && (this.n == m2.n)) {

            float[] d = new float[m * n];

            for (int i = 0; i < m * n; i++) {
                d[i] = this.data[i] + m2.data[i];
            }

            BaseMatrix baseMatrix = new BaseMatrix(m, n);

            // 结果放到新的矩阵中
            baseMatrix.setData(d);

            return baseMatrix;
        } else {

            System.out.println("两个矩阵尺寸不一致,无法做加法");

            return null;
        }

    }

}

三、其他相关方法的测试

// 转置
        Marix_2X2 m7 = new Marix_2X2(new float[]{2, 5, -1, 1});
        Marix_2X2 transpose = m7.Transpose();
        transpose.showInfo();


        // 伴随矩阵
        Marix_2X2 m8 = new Marix_2X2(new float[]{2, 5, -1, 1});
        float[][] floats = m8.AdjointMatrix(getData(m8));
        m8.setData(two2One(floats, m8.getData()));
        m8.showInfo();


        // 余子式
        m8.setData(two2One(m8.confactor(getData(m8), 2, 2), m8.getData()));
        m8.Transpose();
        m8.showInfo();
image-20231010095100384.png

Python版本开发

一、python代码

1、导入 包

# 这个一定要导入,不然的话,是用不了的
import numpy as np

2、创建数组


A = np.array([[1,2],[2,5]])


3、打印数组

# 矩阵信息打印
def showInfo(x):
    print("------------")
    print("矩阵的尺寸为:",np.shape(x)[0],"x",np.shape(x)[1])
    print(x)
    print("------------")

4、求矩阵的逆

# 求逆矩阵
def getInverse(x):

    if(np.all(x==0)):
      print("行列为0,不能求逆矩阵")
    else:
      B = np.linalg.inv(x)
      print("逆矩阵")
      return B

5、矩阵的乘法

# 矩阵乘法
def mul(x,y):
    c = np.matmul(x,y)
    return c

6、完整版

import numpy as np
from numpy import *


# 矩阵信息打印
def showInfo(x):
    print("------------")
    print("矩阵的尺寸为:",np.shape(x)[0],"x",np.shape(x)[1])
    print(x)
    print("------------")

# 求逆矩阵
def getInverse(x):

    if(np.all(x==0)):
      print("行列为0,不能求逆矩阵")
    else:
      B = np.linalg.inv(x)
      print("逆矩阵")
      return B

# 矩阵乘法
def mul(x,y):
    c = np.matmul(x,y)
    return c


def main():
    pass

if __name__ == '__main__':
    main()

    A = np.array([[1,2],[2,5]])
    showInfo(A)


    B = np.array([[0,0],[0,0]])
    getInverse(B)
    H = getInverse(A)
    showInfo(H)

    print("-----矩阵乘法-------")

    C = np.array([[2,5],[1,3]])
    D = np.array([[4,-6],[2,1]])

    m2 = getInverse(C)
    result1 = mul(m2,D)
    showInfo(result1)


    print("-----混合乘法-------")
    E = np.array([[1,4],[-1,2]])
    F = np.array([[3,1],[0,-1]])
    G = np.array([[2,0],[-1,1]])

    m3 = getInverse(E)
    result2 = mul(m3,F)
    m4 = getInverse(G)
    result3 = mul(result2,m4)
    showInfo(result3)

7、测试结果

image-20231021100912265.png image-20231021100928938.png

8、拓展其他功能

# 求单位矩阵
def singleArray(x):
    F = np.eye(x)
    return F


# 矩阵转置
def transArray(x):
    H = x.T
    return H



# 计算行列式的值
def getValue(x):
    H = np.linalg.det(x)
    return H

# A的伴随矩阵
def adjointMatrix(A):
    n,_=A.shape                             #获取阶数n
    Am=np.zeros((n,n))                      #Am初始化为零阵
    for i in range(n):                      #每一行
        for j in range(n):                  #每一列
            Am[i,j]=Aij(A,i,j)              #伴随阵元素
    return Am.T

#代数余子式
def Aij(A,i,j):
    up=np.hstack((A[:i,:j],A[:i,j+1:]))     #横向连接上方片段
    lo=np.hstack((A[i+1:,:j],A[i+1:,j+1:])) #横向连接下方片段
    M=np.vstack((up,lo))                    #纵向连接
    return ((-1)**(i+j))*np.linalg.det(M)   #代数余子式


# 求代数余子式
def cofactor(matrix, i, j):
    m = np.delete(matrix, i, axis=0)
    m = np.delete(m, j, axis=1)
    return np.linalg.det(m)

def cofactor_matrix(matrix):
    n = matrix.shape[0]
    cofactors = np.zeros((n, n))

    for i in range(n):
        for j in range(n):
            cofactors[i, j] = (-1) ** (i + j) * cofactor(matrix, i, j)

    return cofactors

image-20231021101311105.png

总结

上一篇下一篇

猜你喜欢

热点阅读