单从一个矩阵来看,我们可以发现该矩阵的列秩和行秩是相等的,都为2,那么这是一个特例还是矩阵的特性呢?其实这是矩阵的特性,矩阵的行秩=矩阵的列秩。
我们来看一个任意m行n列的矩阵
其实不论矩阵是什么样子,都可以将矩阵转换成如下的形式
这个样子中,在中间的横线下面都是行最简形式的零行;横线上面都是行最简形式的非零行;横线上方的左边是一个单位矩阵,其实也是主元列;横线上方的右边是一个任意矩阵,其实也是自由列。
那为什么我们之前的例子并不是这个样子呢?
首先,这确实是化成了行最简形式,但对于这个行最简形式要变成我们需要的样子还需要进行一个列变换,将2、3列交换位置,这样就变成了我们需要的样子。
这里的关键是左上角是一个单位矩阵,我们假定它有r行、r列(r表示行秩或列秩)。通过这个单位矩阵,我们可以看出该矩阵的非零行数一定等于它的主元列数,都排在了这个单位矩阵中。最终任意矩阵都可以化成这个样式
其中I是单位矩阵,F是自由列矩阵,O是零矩阵。由于矩阵的行秩一定等于矩阵的列秩,它们都是一个数,我们称这个数为矩阵的秩(Rank)。对于任意一个矩阵,它的行空间和列空间的维度相等。
现在有3个向量,u=(1,1,2),v=(2,2,3),w=(3,3,4)的生成空间的维度是多少?
初看,我们无法一下判断,但如果将这3个向量无论是排成行矩阵还是列矩阵,这都无所谓。现在我们将其排成一个行矩阵
从这个样子,我们就能一眼判断出第一列和第二列的列向量一定是线性相关的,从而判断这3个向量的生成空间的维度最大只能为2.
对于一个m行n列的矩阵,行空间是n维空间的子空间,列空间是m维空间的子空间。
对于一个n阶方阵(n行n列),行空间是n维空间的子空间,列空间是n维空间的子空间。那么何时行空间和列空间都是n维空间?也就是矩阵的秩r=n,此时我们称该方阵为满秩(Full Rank)。也就是说,它的行最简形式的非零行个数为n,行最简形式的主元列个数为n,那么可以断定这个行最简形式就是一个单位矩阵I
至此,我们可以给方阵A的等价命题再添加几个新的命题
现在我们用代码来实现求取矩阵的秩、行空间的基、列空间的基,先给Ranks接口添加一个求取矩阵的秩方法rank,一个行空间的基的方法rowBase,一个列空间的基的方法colBase,由于行秩和列秩是相等的,这里我们就实现求行秩的方法就好了
public interface Ranks<T extends Number> {
/**
* 矩阵的行列数
* @return
*/
int[] shape();
/**
* 矩阵的行数
* @return
*/
int rowNum();
/**
* 矩阵的列数
* @return
*/
int colNum();
/**
* 矩阵的元素个数
* @return
*/
int size();
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int pos);
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int[] pos);
/**
* 设置矩阵中某个位置的元素
* @param pos
* @param value
*/
void set(int[] pos,T value);
/**
* 获取一个行向量
* @param index
* @return
*/
Attribute<T> rowVector(int index);
/**
* 获取一个列向量
* @param index
* @return
*/
Attribute<T> colVector(int index);
/**
* 矩阵相加
* @param another
* @return
*/
Ranks<T> add(Ranks<T> another,Addr<T> addr);
/**
* 矩阵相减
* @param another
* @param addr
* @return
*/
Ranks<T> sub(Ranks<T> another,Addr<T> addr);
/**
* 矩阵乘以一个数
* @param k
* @param addr
* @return
*/
Ranks<T> mul(T k,Addr<T> addr);
/**
* 矩阵除以一个数
* @param k
* @param addr
* @return
*/
Ranks<Double> div(double k,Addr<T> addr);
/**
* 矩阵取正的结果
* @return
*/
Ranks<T> pos(Addr<T> addr,T one);
/**
* 矩阵取负的结果
* @return
*/
Ranks<T> neg(Addr<T> addr,T negOne);
/**
* 矩阵与向量的点乘
* @param another
* @param addr
* @return
*/
Attribute<T> dot(Attribute<T> another,Addr<T> addr);
/**
* 矩阵与矩阵的点乘
* @param another
* @param addr
* @return
*/
Ranks<T> dot(Ranks<T> another,Addr<T> addr);
/**
* 转置矩阵
* @return
*/
Ranks<T> trans();
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invFunc(Addr<T> addr);
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invMatrix(Addr<T> addr);
/**
* 矩阵的LU分解
* @param addr
* @return
*/
Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr);
/**
* 矩阵的秩
* @param addr
* @return
*/
int rank(Addr<T> addr);
/**
* 行空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> rowBase(Addr<T> addr);
/**
* 列空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> colBase(Addr<T> addr);
}
Attribute接口添加判断两个向量是否相等的方法equals
public interface Attribute<T extends Number> {
/**
* 向量的长度
* @return
*/
int len();
/**
* 获取向量的元素
* @param index 索引
* @return
*/
T get(int index);
/**
* 判断两个向量是否相等
* @param another
* @param addr
* @return
*/
boolean equals(Attribute<T> another,Addr<T> addr);
/**
* 向量相加
* @param another
* @return
*/
Attribute<T> add(Attribute<T> another,Addr<T> addr);
/**
* 向量相减
* @param another
* @param addr
* @return
*/
Attribute<T> sub(Attribute<T> another,Addr<T> addr);
/**
* 向量乘以一个数
* @param k
* @param addr
* @return
*/
Attribute<T> mul(T k,Addr<T> addr);
/**
* 向量除以一个数
* @param k
* @param addr
* @return
*/
Attribute<T> div(T k,Addr<T> addr);
/**
* 向量的模
* @return
*/
double norm(Addr<T> addr);
/**
* 单位向量
* @return
*/
Attribute<Double> normalize(Addr<T> addr);
/**
* 向量的点乘
* @param another
* @param addr
* @return
*/
T dot(Attribute<T> another,Addr<T> addr);
/**
* 向量的夹角
* @param another
* @param addr
* @return
*/
double degree(Attribute<T> another,Addr<T> addr);
/**
* 其他向量在当前向量的投影
* @param another
* @param addr
* @return
*/
Attribute<Double> project(Attribute<T> another,Addr<T> addr);
}
向量实现类
@Getter
@AllArgsConstructor
public class Vector<T extends Number> implements Attribute<T> {
private T[] values;
@SuppressWarnings("unchecked")
public static <T extends Number> Attribute<T> zero(int dim,Addr<T> addr) {
T[] values = (T[])new Number[dim];
Arrays.fill(values,addr.zero());
return new Vector<>(values);
}
@Override
public String toString() {
return "Vector{" +
"values=" + Arrays.toString(values) +
'}';
}
@Override
@SuppressWarnings("unchecked")
public boolean equals(Attribute<T> another,Addr<T> addr) {
if (this.len() != another.len()) {
return false;
}
for (int i = 0; i < len(); i++) {
if (!addr.equals(this.get(i),another.get(i))) {
return false;
}
}
return true;
}
@Override
public int len() {
return values.length;
}
@Override
public T get(int index) {
if (index >= len() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return values[index];
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> add(Attribute<T> another,Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("加法错误,两个向量的维度必须相等");
}
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.add(this.get(i),another.get(i));
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> sub(Attribute<T> another, Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("减法错误,两个向量的维度必须相等");
}
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.sub(this.get(i),another.get(i));
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> div(T k, Addr<T> addr) {
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.div(this.get(i),k);
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> mul(T k, Addr<T> addr) {
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.mul(k,this.get(i));
}
this.values = newValues;
return this;
}
@Override
public double norm(Addr<T> addr) {
T total = addr.zero();
for (int i = 0; i < this.len(); i++) {
total = addr.add(total,addr.square(this.get(i)));
}
return addr.prescription(total);
}
@Override
public Attribute<Double> normalize(Addr<T> addr) {
Double[] newValues = new Double[this.len()];
double norm = this.norm(addr);
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.div(this.get(i),norm);
}
return new Vector<>(newValues);
}
@Override
public T dot(Attribute<T> another, Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("点乘错误,两个向量的维度必须相等");
}
T total = addr.zero();
for (int i = 0; i < this.len(); i++) {
total = addr.add(total,addr.mul(this.get(i),another.get(i)));
}
return total;
}
@Override
public double degree(Attribute<T> another, Addr<T> addr) {
T dot = this.dot(another,addr);
double selfNorm = this.norm(addr);
double anotherNorm = another.norm(addr);
double productNorm = selfNorm * anotherNorm;
return addr.toDegree(addr.acos(addr.div(dot,productNorm)));
}
@Override
public Attribute<Double> project(Attribute<T> another, Addr<T> addr) {
T dot = this.dot(another,addr);
double selfNorm = this.norm(addr);
Attribute<Double> unitVector = this.normalize(addr);
double d = addr.div(dot, selfNorm);
return mul(d,unitVector);
}
private Attribute<Double> mul(double d,Attribute<Double> v) {
Double[] values = new Double[v.len()];
for (int i = 0; i < v.len(); i++) {
values[i] = d * v.get(i);
}
return new Vector<>(values);
}
private T sumValue(List<T> list, Addr<T> addr) {
T total = addr.zero();
for (T n : list) {
total = addr.add(total,n);
}
return total;
}
}
矩阵实现类
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
Python代码
重写向量类的等__eq__与不等__neq__
import math
from ._global import is_equal
class Vector:
def __init__(self, lst):
self._values = lst
@classmethod
def zero(cls,dim):
# 返回一个dim维的零向量
return cls([0] * dim)
def project(self, another):
# 其他向量在当前向量的投影
return self.normalize() * (self.dot(another) / self.norm())
def degree(self, another):
# 返回向量的夹角
return math.degrees(math.acos(self.dot(another) / (self.norm() * another.norm())))
def norm(self):
# 返回向量的模
return math.sqrt(sum(e**2 for e in self))
def normalize(self):
# 返回向量的单位向量
return Vector([e / self.norm() for e in self])
def underlying_list(self):
# 返回向量的底层列表
return self._values[:]
def __add__(self, another):
# 向量加法,返回结果向量
assert len(self) == len(another),\
"加法错误,两个向量的维度必须相等"
return Vector([a + b for a, b in zip(self, another)])
def __sub__(self, another):
# 向量减法,返回结果向量
assert len(self) == len(another), \
"减法错误,两个向量的维度必须相等"
return Vector([a - b for a, b in zip(self, another)])
def __pos__(self):
# 返回向量取正的结果向量
return 1 * self
def __neg__(self):
# 返回向量取负的结果向量
return -1 * self
def __eq__(self, another):
# 返回向量是否相等
another_list = another.underlying_list()
if(len(another_list) != len(self._values)):
return False
return all(is_equal(x, y) for x, y in zip(self._values, another_list))
def __neq__(self, another):
# 返回向量是否不等
return not(self == another)
def dot(self, another):
# 向量点乘,返回结果标量
assert len(self) == len(another), \
"点乘错误,两个向量的维度必须相等"
return sum(a * b for a, b in zip(self, another))
def __mul__(self, k):
# 返回数量乘法的结果向量:self * k
return Vector([k * e for e in self])
def __rmul__(self, k):
# 返回数量乘法的结果向量:k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果向量:self / k
return (1 / k) * self
def __iter__(self):
# 返回向量的迭代器
return self._values.__iter__()
def __getitem__(self, index):
# 取向量的第index个元素
return self._values[index]
def __len__(self):
# 返回向量的长度
return len(self._values)
def __repr__(self):
return "Vector({})".format(self._values)
def __str__(self):
return "({})".format(", ".join(str(e) for e in self._values))
矩阵类添加一个求秩的方法rank,求行空间的一组基的方法row_base,求列空间的一组基的方法col_base
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
self._values = [row[:] for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
零空间
一个齐次线性方程组的所有解,形成一个向量空间
对于齐次线性方程组来说,它一定有解,最少它有一个零解,这是一个向量空间。或者它有无数解,如果系数矩阵为m*n的矩阵,解为n维向量。如果解形成向量空间,则该向量空间是n维空间的子空间。之前我们说过,假设V是一个向量空间,如果S是V的子集,且S对加法和数量乘法封闭,则称S是V的一个子空间。
假设系数矩阵为A,假设u和v都是解,则有
以及
,则有
,经过乘法分配律,则有
,由该式子我们可以看出u+v也是该齐次线性方程组的一个解(也在解的向量空间中),所以该空间对向量加法封闭。
假设系数矩阵为A,假设u是解,则有
,等式左右两边乘以一个实数k,则有
,这里零向量乘以任何实数等于其本身,通过乘法结合律,则有
,由该式子我们可以看出ku也是该齐次线性方程组的一个解(也在解的向量空间中),所以该空间对向量数量乘法封闭。
由以上两点,得出一个齐次线性方程组的所有解,形成一个向量空间,称这个空间,为零空间(Null Space)
A的零空间,就是Ax=0中,所有x组成的空间。
我们之前说,可以把矩阵看作是向量的函数(转换函数),零空间是一个集合,在集合中的所有向量,在A的变换下,都将映射到零点!
我们又可以把矩阵看作是空间,零空间是一个集合,这个集合中的所有向量,和A的行向量点乘结果为0!
这个集合中的所有的向量,和A的行空间中所有向量点乘结果为0!这里行空间指的是由矩阵A的行向量生成的空间,在该空间中的任意一个向量,它的范围比A的行向量要大的多,可以有无数个,是由A的行向量任意线性组合的。任意两个向量点乘结果为0,意味着这两个向量彼此垂直,则这个集合中的所有的向量,和A的行空间中所有向量垂直(正交)!这个集合和A的行空间正交,换句话说,A的零空间和A的行空间正交
A的零空间中所有的向量,和A的行空间中所有向量垂直
曾经我们觉得两个平面垂直是这个样子的
但其实这两个平面不正交,它并不是分属两个平面中任意两个向量彼此垂直,真正两个空间正交,比如下面两个例子
那么两个二维空间是不是不能正交呢?其实两个二维空间是可以正交的,只不过它们不可能在三维空间中正交,实际上两个二维平面在四维空间中可以正交,只不过四维空间过于抽象,所以无法直观的理解两个二维平面正交。
零空间的基和秩-零化度定理
零空间的维度是多少?能否给出一组基?
要获取这个问题的答案,依然从解齐次线性方程组开始
这里左边是齐次线性方程组的系数矩阵,右边是该系数矩阵的行最简形式。这样的一个行最简形式,意味着这样的一个方程组
变换后得
这里x1、x2是主元列上的未知数,而x3是自由列上的未知数,x3可以任意取值来获取相应的x1和x2。之前说到这一步,就相当于解出来了这个方程组,但是现在我们面对零空间的维度和零空间的一组基,我们还需要进一步讨论这个问题。由于零空间是方程组解所生成的空间,所以我们来看一下这三个未知数转化成向量的样子
根据这个式子,我们可以看出,(-7,-5,1)是三维空间的一个向量,而这个向量点乘任意一个实数,它只可能在一条直线上变化,所以该系数矩阵零空间的维度为1,而(-7,-5,1)就是该零空间的一组基。
我们再来看一下一个比较复杂的齐次线性方程组的系数矩阵,而右边同样是该系数矩阵的行最简形式
同样,它可以表示成一个这样的方程组
其中x1、x2是主元列的未知数,x3、x4、x5、x6是自由列的未知数,它们可以随便取值。我们将所有的未知数形成一个向量,则有
我们将各个自由列的未知数分别拆开,得
该式子又可以转化为
由该式子可以看出,最终该齐次线性方程组的系数矩阵的零空间,就是由这4个向量(1,-2,1,0,0,0)、(2,-3,0,1,0,0)、(3,-4,0,0,1,0)、(4,-5,0,0,0,1)生成的,所以该零空间的维度为4,而这4个向量也就是零空间的一组基。
我们来重新用列视角来审视一下该系数矩阵的行最简形式,竖线左边是主元列,右边是自由列。对于一个m*n的矩阵,将其化为行最简形式,主元列数为列空间的维度,自由列数为零空间的维度。所以则有列空间的维度 + 零空间的维度 = n。由于列空间的维度就是矩阵的秩,零空间的维度又被称为零化度(Nulity),所以又有——秩(rank) + 零化度(Nulity) = n,这就是秩-零化度定理
对于一个m行n列的矩阵
列空间 | 零空间 |
---|---|
Ax=v(x任取) | Av=0 |
列空间是m维空间的子空间 | 零空间是n维空间的子空间 |
列空间的维度,为行最简形式中主元列数 | 零空间的维度,为行最简形式中自由列数 |
主元列的对应原矩阵的列,是列空间的一组基 | 求零空间的基需要求解Av=0 |
何时零空间的维度为0?也就是列空间的维度为n。对方阵来说,即为满秩的时候。现在我们又可以增加一条方阵的等价命题
对于方阵A
Attribute接口增加一个修改向量元素的方法set
public interface Attribute<T extends Number> {
/**
* 向量的长度
* @return
*/
int len();
/**
* 获取向量的元素
* @param index 索引
* @return
*/
T get(int index);
/**
* 修改向量的元素
* @param index
*/
void set(int index,T value);
/**
* 判断两个向量是否相等
* @param another
* @param addr
* @return
*/
boolean equals(Attribute<T> another,Addr<T> addr);
/**
* 向量相加
* @param another
* @return
*/
Attribute<T> add(Attribute<T> another,Addr<T> addr);
/**
* 向量相减
* @param another
* @param addr
* @return
*/
Attribute<T> sub(Attribute<T> another,Addr<T> addr);
/**
* 向量乘以一个数
* @param k
* @param addr
* @return
*/
Attribute<T> mul(T k,Addr<T> addr);
/**
* 向量除以一个数
* @param k
* @param addr
* @return
*/
Attribute<T> div(T k,Addr<T> addr);
/**
* 向量的模
* @return
*/
double norm(Addr<T> addr);
/**
* 单位向量
* @return
*/
Attribute<Double> normalize(Addr<T> addr);
/**
* 向量的点乘
* @param another
* @param addr
* @return
*/
T dot(Attribute<T> another,Addr<T> addr);
/**
* 向量的夹角
* @param another
* @param addr
* @return
*/
double degree(Attribute<T> another,Addr<T> addr);
/**
* 其他向量在当前向量的投影
* @param another
* @param addr
* @return
*/
Attribute<Double> project(Attribute<T> another,Addr<T> addr);
}
向量实现类
@Getter
@AllArgsConstructor
public class Vector<T extends Number> implements Attribute<T> {
private T[] values;
@SuppressWarnings("unchecked")
public static <T extends Number> Attribute<T> zero(int dim,Addr<T> addr) {
T[] values = (T[])new Number[dim];
Arrays.fill(values,addr.zero());
return new Vector<>(values);
}
@Override
public String toString() {
return "Vector{" +
"values=" + Arrays.toString(values) +
'}';
}
@Override
@SuppressWarnings("unchecked")
public boolean equals(Attribute<T> another,Addr<T> addr) {
if (this.len() != another.len()) {
return false;
}
for (int i = 0; i < len(); i++) {
if (!addr.equals(this.get(i),another.get(i))) {
return false;
}
}
return true;
}
@Override
public int len() {
return values.length;
}
@Override
public T get(int index) {
if (index >= len() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return values[index];
}
@Override
public void set(int index, T value) {
if (index >= len() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
this.values[index] = value;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> add(Attribute<T> another,Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("加法错误,两个向量的维度必须相等");
}
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.add(this.get(i),another.get(i));
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> sub(Attribute<T> another, Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("减法错误,两个向量的维度必须相等");
}
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.sub(this.get(i),another.get(i));
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> div(T k, Addr<T> addr) {
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.div(this.get(i),k);
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> mul(T k, Addr<T> addr) {
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.mul(k,this.get(i));
}
this.values = newValues;
return this;
}
@Override
public double norm(Addr<T> addr) {
T total = addr.zero();
for (int i = 0; i < this.len(); i++) {
total = addr.add(total,addr.square(this.get(i)));
}
return addr.prescription(total);
}
@Override
public Attribute<Double> normalize(Addr<T> addr) {
Double[] newValues = new Double[this.len()];
double norm = this.norm(addr);
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.div(this.get(i),norm);
}
return new Vector<>(newValues);
}
@Override
public T dot(Attribute<T> another, Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("点乘错误,两个向量的维度必须相等");
}
T total = addr.zero();
for (int i = 0; i < this.len(); i++) {
total = addr.add(total,addr.mul(this.get(i),another.get(i)));
}
return total;
}
@Override
public double degree(Attribute<T> another, Addr<T> addr) {
T dot = this.dot(another,addr);
double selfNorm = this.norm(addr);
double anotherNorm = another.norm(addr);
double productNorm = selfNorm * anotherNorm;
return addr.toDegree(addr.acos(addr.div(dot,productNorm)));
}
@Override
public Attribute<Double> project(Attribute<T> another, Addr<T> addr) {
T dot = this.dot(another,addr);
double selfNorm = this.norm(addr);
Attribute<Double> unitVector = this.normalize(addr);
double d = addr.div(dot, selfNorm);
return mul(d,unitVector);
}
private Attribute<Double> mul(double d,Attribute<Double> v) {
Double[] values = new Double[v.len()];
for (int i = 0; i < v.len(); i++) {
values[i] = d * v.get(i);
}
return new Vector<>(values);
}
private T sumValue(List<T> list, Addr<T> addr) {
T total = addr.zero();
for (T n : list) {
total = addr.add(total,n);
}
return total;
}
}
Ranks接口增加两个方法,零空间的维度dimensionNullSpace,零空间的一组基nullBase
public interface Ranks<T extends Number> {
/**
* 矩阵的行列数
* @return
*/
int[] shape();
/**
* 矩阵的行数
* @return
*/
int rowNum();
/**
* 矩阵的列数
* @return
*/
int colNum();
/**
* 矩阵的元素个数
* @return
*/
int size();
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int pos);
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int[] pos);
/**
* 设置矩阵中某个位置的元素
* @param pos
* @param value
*/
void set(int[] pos,T value);
/**
* 获取一个行向量
* @param index
* @return
*/
Attribute<T> rowVector(int index);
/**
* 获取一个列向量
* @param index
* @return
*/
Attribute<T> colVector(int index);
/**
* 矩阵相加
* @param another
* @return
*/
Ranks<T> add(Ranks<T> another,Addr<T> addr);
/**
* 矩阵相减
* @param another
* @param addr
* @return
*/
Ranks<T> sub(Ranks<T> another,Addr<T> addr);
/**
* 矩阵乘以一个数
* @param k
* @param addr
* @return
*/
Ranks<T> mul(T k,Addr<T> addr);
/**
* 矩阵除以一个数
* @param k
* @param addr
* @return
*/
Ranks<Double> div(double k,Addr<T> addr);
/**
* 矩阵取正的结果
* @return
*/
Ranks<T> pos(Addr<T> addr,T one);
/**
* 矩阵取负的结果
* @return
*/
Ranks<T> neg(Addr<T> addr,T negOne);
/**
* 矩阵与向量的点乘
* @param another
* @param addr
* @return
*/
Attribute<T> dot(Attribute<T> another,Addr<T> addr);
/**
* 矩阵与矩阵的点乘
* @param another
* @param addr
* @return
*/
Ranks<T> dot(Ranks<T> another,Addr<T> addr);
/**
* 转置矩阵
* @return
*/
Ranks<T> trans();
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invFunc(Addr<T> addr);
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invMatrix(Addr<T> addr);
/**
* 矩阵的LU分解
* @param addr
* @return
*/
Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr);
/**
* 矩阵的秩
* @param addr
* @return
*/
int rank(Addr<T> addr);
/**
* 行空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> rowBase(Addr<T> addr);
/**
* 列空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> colBase(Addr<T> addr);
/**
* 零空间的维度
* @param addr
* @return
*/
int dimensionNullSpace(Addr<T> addr);
/**
* 零空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> nullBase(Addr<T> addr);
}
矩阵实现类
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
self._values = [row[:] for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
1
[Vector([0, 1, 0])]
2
[Vector([1.0, 0.0, 7.0]), Vector([-0.0, 1.0, 5.0])]
[Vector([-1, 1, -3]), Vector([2, -4, 5])]
1
[Vector([-7.0, -5.0, 1])]
2
[Vector([1.0, 0.0, -1.0000000000000007, -2.0000000000000018, -3.0000000000000013, -4.000000000000002]), Vector([0.0, 1.0, 2.0000000000000004, 3.000000000000001, 4.000000000000001, 5.000000000000002])]
[Vector([1, 27, 15, 31, 45]), Vector([2, 28, 16, 32, 46])]
4
[Vector([1.0000000000000007, -2.0000000000000004, 1, 0, 0, 0]), Vector([2.0000000000000018, -3.000000000000001, 0, 1, 0, 0]), Vector([3.0000000000000013, -4.000000000000001, 0, 0, 1, 0]), Vector([4.000000000000002, -5.000000000000002, 0, 0, 0, 1])]
左零空间和四大子空间
对于m*n的矩阵A
我们可以找到它的列空间,这里用Col(A)来表示,维度为矩阵的秩r;也可以找到它的零空间,这里用Null(A)来表示,维度为n-r
也可以找到它的行空间,这里用
来表示,这里
为矩阵的转置,维度为r。零空间与行空间是正交关系。
那么
的列空间为A的行空间,那么
的零空间是什么呢?其实它叫做左零空间,用
来表示,维度为m-r,左零空间与列空间是正交关系。
这样,列空间,零空间,行空间,左零空间称为四大子空间。
对于m*n的矩阵A,左零空间
,用式子表示就是
,将向量x看成是一个m*1的矩阵,对式子的两边同时进行转置,则有
,根据矩阵转置的性质——两个矩阵相乘后的转置等于第二个矩阵的转置乘以第一个矩阵的转置
,则有
。由于零空间是Ax=0,这是一个右乘,而
是一个左乘,我们都知道矩阵乘法是不遵循乘法交换律的,所以这里叫做左零空间。
Ranks接口新增左零空间维度方法dimensionLeftNullSpace和左零空间的一组基方法leftNullBase
public interface Ranks<T extends Number> {
/**
* 矩阵的行列数
* @return
*/
int[] shape();
/**
* 矩阵的行数
* @return
*/
int rowNum();
/**
* 矩阵的列数
* @return
*/
int colNum();
/**
* 矩阵的元素个数
* @return
*/
int size();
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int pos);
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int[] pos);
/**
* 设置矩阵中某个位置的元素
* @param pos
* @param value
*/
void set(int[] pos,T value);
/**
* 获取一个行向量
* @param index
* @return
*/
Attribute<T> rowVector(int index);
/**
* 获取一个列向量
* @param index
* @return
*/
Attribute<T> colVector(int index);
/**
* 矩阵相加
* @param another
* @return
*/
Ranks<T> add(Ranks<T> another,Addr<T> addr);
/**
* 矩阵相减
* @param another
* @param addr
* @return
*/
Ranks<T> sub(Ranks<T> another,Addr<T> addr);
/**
* 矩阵乘以一个数
* @param k
* @param addr
* @return
*/
Ranks<T> mul(T k,Addr<T> addr);
/**
* 矩阵除以一个数
* @param k
* @param addr
* @return
*/
Ranks<Double> div(double k,Addr<T> addr);
/**
* 矩阵取正的结果
* @return
*/
Ranks<T> pos(Addr<T> addr,T one);
/**
* 矩阵取负的结果
* @return
*/
Ranks<T> neg(Addr<T> addr,T negOne);
/**
* 矩阵与向量的点乘
* @param another
* @param addr
* @return
*/
Attribute<T> dot(Attribute<T> another,Addr<T> addr);
/**
* 矩阵与矩阵的点乘
* @param another
* @param addr
* @return
*/
Ranks<T> dot(Ranks<T> another,Addr<T> addr);
/**
* 转置矩阵
* @return
*/
Ranks<T> trans();
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invFunc(Addr<T> addr);
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invMatrix(Addr<T> addr);
/**
* 矩阵的LU分解
* @param addr
* @return
*/
Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr);
/**
* 矩阵的秩
* @param addr
* @return
*/
int rank(Addr<T> addr);
/**
* 行空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> rowBase(Addr<T> addr);
/**
* 列空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> colBase(Addr<T> addr);
/**
* 零空间的维度
* @param addr
* @return
*/
int dimensionNullSpace(Addr<T> addr);
/**
* 零空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> nullBase(Addr<T> addr);
/**
* 左零空间的维度
* @param addr
* @return
*/
int dimensionLeftNullSpace(Addr<T> addr);
/**
* 左零空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> leftNullBase(Addr<T> addr);
}
矩阵实现类
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
public int dimensionLeftNullSpace(Addr<T> addr) {
return this.rowNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> leftNullBase(Addr<T> addr) {
return this.trans().nullBase(addr);
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
System.out.println(F.dimensionLeftNullSpace(addr1));
System.out.println(F.leftNullBase(addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
self._values = [row[:] for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def dimension_left_null_space(self):
# 左零空间的维度
return self.row_num() - self.rank()
def left_null_base(self):
# 左零空间的一组基
return self.trans().null_base()
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
print(F.dimension_left_null_space())
print(F.left_null_base())
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
正交基与标准正交基
n维空间中,任意n个线性无关的向量,一定是这个n维空间的一组基。如二维平面中
但我们更喜欢的其实是这样的一组基
这组基其中的向量是两两相垂直的,我们称这样的基为正交基
在我们之前讲向量的点乘的时候有过这样一个式子
这两个向量之间的夹角为
,两个向量点乘的结果为一个标量,当
为90度的时候,
,无论这两个向量的模是多少,这两个向量点乘的结果为0,
若两个向量点乘的结果为0,则这两个向量互相垂直,称两个向量正交
正交向量组——一组向量,如果两两正交,则称为正交向量组。正交非零向量组一定线性无关。这里需要注意的是如果这组向量存在零向量的话,则它们就线性相关了。
证明: 假设
是一组正交向量组,根据线性无关的定义,需证明
,只有当k全部为0,即只有零解时,这组向量才线性无关。
我们在式子的左右两边同时乘以一个
,这个
是这组向量中的任意一个向量,则有
转化后
,由于这是一个正交向量组,任意两个向量点乘后的结果为0,则该式化为
,又可以表示为
,由于
是非零向量,则它的模肯定是大于0的,所以
,得证。
n个非零正交向量一定是n维空间的基,因为我们已经证明n个非零正交向量它们线性无关了。
如果一个空间的一组基两两正交,则称这组基为一组正交基
如果一个空间的一组正交基,模为1,则称这组基是一组标准正交基。只要满足这个定义,它们都是一组标准正交基
这两组基,它们都是标准正交基,所以一个空间的标准正交基也有无数组。
一维投影
如果给定一个空间的一组基(如我们都可以获取一个矩阵的四大子空间的一组基),但是我们并不能保证这组基是一组正交基。我们希望进一步找到这个空间的一组正交基。一旦我们找到了这个空间的正交基,则进一步就可以找到这组空间的标准正交基。
在二维平面上的任意一组基u和v
向量p是v在u上的投影,而v-p就是与u垂直的一个向量,则最终v-p和u就形成了这个二维空间的一个组正交基。
我们之前在讲向量点乘的时候知道
,将式子变形
,该等式表示v在u上的投影向量p的模
现在只是知道了p的模,p和u是同方向的,我们之前说单位向量表示方向,则u的单位向量为
,最终p等于p的模点乘这个单位向量
知道了p就很容易求u垂直向量v-p了
Attribute接口新增一个求正交向量的方法rectangular
public interface Attribute<T extends Number> {
/**
* 向量的长度
* @return
*/
int len();
/**
* 获取向量的元素
* @param index 索引
* @return
*/
T get(int index);
/**
* 修改向量的元素
* @param index
*/
void set(int index,T value);
/**
* 判断两个向量是否相等
* @param another
* @param addr
* @return
*/
boolean equals(Attribute<T> another,Addr<T> addr);
/**
* 向量相加
* @param another
* @return
*/
Attribute<T> add(Attribute<T> another,Addr<T> addr);
/**
* 向量相减
* @param another
* @param addr
* @return
*/
Attribute<T> sub(Attribute<T> another,Addr<T> addr);
/**
* 向量乘以一个数
* @param k
* @param addr
* @return
*/
Attribute<T> mul(T k,Addr<T> addr);
/**
* 向量除以一个数
* @param k
* @param addr
* @return
*/
Attribute<T> div(T k,Addr<T> addr);
/**
* 向量的模
* @return
*/
double norm(Addr<T> addr);
/**
* 单位向量
* @return
*/
Attribute<Double> normalize(Addr<T> addr);
/**
* 向量的点乘
* @param another
* @param addr
* @return
*/
T dot(Attribute<T> another,Addr<T> addr);
/**
* 向量的夹角
* @param another
* @param addr
* @return
*/
double degree(Attribute<T> another,Addr<T> addr);
/**
* 其他向量在当前向量的投影
* @param another
* @param addr
* @return
*/
Attribute<Double> project(Attribute<T> another,Addr<T> addr);
/**
* 当前向量的正交向量
* @param another
* @param addr
* @return
*/
Attribute<Double> rectangular(Attribute<T> another,Addr<T> addr);
}
向量实现类
@Getter
@AllArgsConstructor
public class Vector<T extends Number> implements Attribute<T> {
private T[] values;
@SuppressWarnings("unchecked")
public static <T extends Number> Attribute<T> zero(int dim,Addr<T> addr) {
T[] values = (T[])new Number[dim];
Arrays.fill(values,addr.zero());
return new Vector<>(values);
}
@Override
public String toString() {
return "Vector{" +
"values=" + Arrays.toString(values) +
'}';
}
@Override
@SuppressWarnings("unchecked")
public boolean equals(Attribute<T> another,Addr<T> addr) {
if (this.len() != another.len()) {
return false;
}
for (int i = 0; i < len(); i++) {
if (!addr.equals(this.get(i),another.get(i))) {
return false;
}
}
return true;
}
@Override
public int len() {
return values.length;
}
@Override
public T get(int index) {
if (index >= len() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return values[index];
}
@Override
public void set(int index, T value) {
if (index >= len() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
this.values[index] = value;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> add(Attribute<T> another,Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("加法错误,两个向量的维度必须相等");
}
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.add(this.get(i),another.get(i));
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> sub(Attribute<T> another, Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("减法错误,两个向量的维度必须相等");
}
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.sub(this.get(i),another.get(i));
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> div(T k, Addr<T> addr) {
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.div(this.get(i),k);
}
this.values = newValues;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> mul(T k, Addr<T> addr) {
T[] newValues = (T[])new Number[this.len()];
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.mul(k,this.get(i));
}
this.values = newValues;
return this;
}
@Override
public double norm(Addr<T> addr) {
T total = addr.zero();
for (int i = 0; i < this.len(); i++) {
total = addr.add(total,addr.square(this.get(i)));
}
return addr.prescription(total);
}
@Override
public Attribute<Double> normalize(Addr<T> addr) {
Double[] newValues = new Double[this.len()];
double norm = this.norm(addr);
for (int i = 0; i < this.len(); i++) {
newValues[i] = addr.div(this.get(i),norm);
}
return new Vector<>(newValues);
}
@Override
public T dot(Attribute<T> another, Addr<T> addr) {
if (this.len() != another.len()) {
throw new IllegalArgumentException("点乘错误,两个向量的维度必须相等");
}
T total = addr.zero();
for (int i = 0; i < this.len(); i++) {
total = addr.add(total,addr.mul(this.get(i),another.get(i)));
}
return total;
}
@Override
public double degree(Attribute<T> another, Addr<T> addr) {
T dot = this.dot(another,addr);
double selfNorm = this.norm(addr);
double anotherNorm = another.norm(addr);
double productNorm = selfNorm * anotherNorm;
return addr.toDegree(addr.acos(addr.div(dot,productNorm)));
}
@Override
public Attribute<Double> project(Attribute<T> another, Addr<T> addr) {
T dot = this.dot(another,addr);
double selfNorm = this.norm(addr);
Attribute<Double> unitVector = this.normalize(addr);
double d = addr.div(dot, selfNorm);
return mul(d,unitVector);
}
private Attribute<Double> mul(double d,Attribute<Double> v) {
Double[] values = new Double[v.len()];
for (int i = 0; i < v.len(); i++) {
values[i] = d * v.get(i);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<Double> rectangular(Attribute<T> another, Addr<T> addr) {
Attribute<Double> att = (Attribute<Double>) another;
Addr<Double> add = (Addr<Double>) addr;
return att.sub(this.project(another,addr),add);
}
public static void main(String[] args) {
Attribute<Integer> vector = new Vector<>(new Integer[]{5,2});
System.out.println(vector.toString());
System.out.println(vector.len());
System.out.println(vector.get(0));
Attribute<Integer> vector1 = new Vector<>(new Integer[]{6,3});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-6;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
//(5,2)*(6,3)
System.out.println(vector.dot(vector1,addr));
//(5,2),(6,3)的夹角
System.out.println(vector.degree(vector1,addr));
//(6,3)在(5,2)上的映射
System.out.println(vector.project(vector1,addr));
//(5,2)+(6,3)
vector.add(vector1, addr);
System.out.println(vector);
vector.mul(3,addr);
System.out.println(vector);
System.out.println(Vector.zero(4,addr));
System.out.println(vector.norm(addr));
Attribute<Double> unitVector = vector.normalize(addr);
System.out.println(unitVector);
System.out.println(unitVector.norm(addr1));
Attribute<Double> v1 = new Vector<>(new Double[]{5.0,2.0});
Attribute<Double> v2 = new Vector<>(new Double[]{6.0,3.0});
Attribute<Double> v3 = v1.rectangular(v2,addr1);
//(5,2)的垂直向量
System.out.println(v3);
//垂直的两个向量点乘为0
System.out.println(v1.dot(v3,addr1));
System.out.println(addr1.equals(addr1.zero(),v1.dot(v3,addr1)));
}
}
运行结果
Vector{values=[5, 2]}
2
5
36
4.763641690726143
Vector{values=[6.20689655172414, 2.4827586206896552]}
Vector{values=[11, 5]}
Vector{values=[33, 15]}
Vector{values=[0, 0, 0, 0]}
36.24913792078372
Vector{values=[0.9103664774626047, 0.413802944301184]}
0.9999999999999999
Vector{values=[-0.20689655172413968, 0.5172413793103448]}
-8.881784197001252E-15
true
Python代码
import math
from ._global import is_equal
class Vector:
def __init__(self, lst):
self._values = lst
@classmethod
def zero(cls,dim):
# 返回一个dim维的零向量
return cls([0] * dim)
def project(self, another):
# 其他向量在当前向量的投影
return self.normalize() * (self.dot(another) / self.norm())
def rectangular(self, another):
# 当前向量的正交向量
return another - self.project(another)
def degree(self, another):
# 返回向量的夹角
return math.degrees(math.acos(self.dot(another) / (self.norm() * another.norm())))
def norm(self):
# 返回向量的模
return math.sqrt(sum(e**2 for e in self))
def normalize(self):
# 返回向量的单位向量
return Vector([e / self.norm() for e in self])
def underlying_list(self):
# 返回向量的底层列表
return self._values[:]
def __add__(self, another):
# 向量加法,返回结果向量
assert len(self) == len(another),\
"加法错误,两个向量的维度必须相等"
return Vector([a + b for a, b in zip(self, another)])
def __sub__(self, another):
# 向量减法,返回结果向量
assert len(self) == len(another), \
"减法错误,两个向量的维度必须相等"
return Vector([a - b for a, b in zip(self, another)])
def __pos__(self):
# 返回向量取正的结果向量
return 1 * self
def __neg__(self):
# 返回向量取负的结果向量
return -1 * self
def __eq__(self, another):
# 返回向量是否相等
another_list = another.underlying_list()
if(len(another_list) != len(self._values)):
return False
return all(is_equal(x, y) for x, y in zip(self._values, another_list))
def __neq__(self, another):
# 返回向量是否不等
return not(self == another)
def dot(self, another):
# 向量点乘,返回结果标量
assert len(self) == len(another), \
"点乘错误,两个向量的维度必须相等"
return sum(a * b for a, b in zip(self, another))
def __mul__(self, k):
# 返回数量乘法的结果向量:self * k
return Vector([k * e for e in self])
def __rmul__(self, k):
# 返回数量乘法的结果向量:k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果向量:self / k
return (1 / k) * self
def __iter__(self):
# 返回向量的迭代器
return self._values.__iter__()
def __getitem__(self, index):
# 取向量的第index个元素
return self._values[index]
def __len__(self):
# 返回向量的长度
return len(self._values)
def __repr__(self):
return "Vector({})".format(self._values)
def __str__(self):
return "({})".format(", ".join(str(e) for e in self._values))
from playLA.Vector import Vector
from playLA._global import is_zero
if __name__ == "__main__":
vec = Vector([5, 2])
print(vec)
print(len(vec))
print("vec[0] = {}, vec[1] = {}".format(vec[0], vec[1]))
vec2 = Vector([6, 3])
print("{} + {} = {}".format(vec, vec2, vec + vec2))
print("{} * {} = {}".format(vec, 3, vec * 3))
zero2 = Vector.zero(4)
print(zero2)
print("norm({}) = {}".format(vec, vec.norm()))
print("normalize {} is {}".format(vec, vec.normalize()))
print(vec.normalize().norm())
print(vec.dot(vec2))
print(vec.degree(vec2))
print(vec.project(vec2))
vec3 = vec.rectangular(vec2)
print(vec3)
print(vec.dot(vec3))
print(is_zero(vec.dot(vec3)))
运行结果
(5, 2)
2
vec[0] = 5, vec[1] = 2
(5, 2) + (6, 3) = (11, 5)
(5, 2) * 3 = (15, 6)
(0, 0, 0, 0)
norm((5, 2)) = 5.385164807134504
normalize (5, 2) is (0.9284766908852594, 0.3713906763541037)
1.0
36
4.763641690726144
(6.20689655172414, 2.4827586206896552)
(-0.20689655172413968, 0.5172413793103448)
-8.881784197001252e-15
True
高维投影和格拉姆-施密特过程
假设有三维空间中的一组基:u、v、w,当然它们并不是一组正交基
此时,我们先将u、v所生成的二维平面,根据之前的方法,获取该平面的正交基p1、p2
此时,我们将w向p1、p2生成的平面做映射,w的映射向量为p,而w-p就是与p1、p2生成的二维平面的正交向量
此时p可以写成p1、p2的线性组合
,这里a为p在p1上的投影,也是w在p1上的投影;b为p在p2上的投影,也是w在p2上的投影。
很明显a、b都可以求出为
则p可得
则w-p可得
整个过程为,先求出u与v所生成的二维空间u的正交向量p2,这里
为v在u上的映射,
为w在u、v生成的二维平面上的映射,p3为u、v生成的二维平面的正交向量。
我们假设还有一个四维空间的向量x,x向u、v、w生成的三维空间做投影,则与这个三维空间正交的四维空间向量p4为
如果已知一组基:
,求一组正交基,则只需要按照下面的一组公式层层递进下去就可以了
一直处理到Vn
这一个过程又叫格拉姆-施密特(Gram-Schmidt)过程。注意:算法的输入必须是一组基,即线性无关的。
进一步的标准正交基,只需要将正交基中的各个向量各自除以它们的模即可。
我们给矩阵类添加两个静态方法gramSchmidtProcess(通过一组基获取一组正交基),orthonormalBasis(通过一组基获取一组标准正交基)
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
public int dimensionLeftNullSpace(Addr<T> addr) {
return this.rowNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> leftNullBase(Addr<T> addr) {
return this.trans().nullBase(addr);
}
/**
* 根据空间的一组基生成空间的一组正交基
* @param basis 空间的一组基
* @param addr
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> gramSchmidtProcess(List<Attribute<T>> basis, Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.size()][basis.get(0).len()];
for (int i = 0; i < basis.size(); i++) {
for (int j = 0; j < basis.get(0).len(); j++) {
values[i][j] = basis.get(i).get(j);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
List<Attribute<Double>> res = new ArrayList<>();
res.add((Attribute<Double>) basis.get(0));
Addr<Double> add = (Addr<Double>) addr;
//获取每i个正交基的生成空间的正交向量
//第一次获取任意基的第一个向量和第二个向量所生成的二维平面的第一个向量的正交向量
//第二次获取任意基的第一个向量和获取的正交向量生成的二维空间的三维正交向量
//第三次获取三个正交向量生成的三维空间的四维正交向量,以此类推
//所有的正交向量最终构成正交基
for (int i = 1; i < basis.size(); i++) {
Attribute<Double> p = (Attribute<Double>) basis.get(i);
for (Attribute<Double> r : res) {
p = r.rectangular(p,add);
}
res.add(p);
}
return res;
}
/**
* 根据空间的一组基生成空间的一组标准正交基
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> orthonormalBasis(List<Attribute<T>> basis, Addr<T> addr) {
List<Attribute<Double>> bas = gramSchmidtProcess(basis,addr);
Addr<Double> add = (Addr<Double>) addr;
List<Attribute<Double>> res = bas.stream().map(vec -> vec.normalize(add))
.collect(Collectors.toList());
return res;
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
System.out.println(F.dimensionLeftNullSpace(addr1));
System.out.println(F.leftNullBase(addr1));
List<Attribute<Double>> basis = Arrays.asList(new Vector<>(new Double[]{2.0,1.0}),
new Vector<>(new Double[]{1.0,1.0}));
System.out.println(Matrix.gramSchmidtProcess(basis,addr1));
System.out.println(Matrix.orthonormalBasis(basis,addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
[Vector{values=[2.0, 1.0]}, Vector{values=[-0.19999999999999996, 0.4]}]
[Vector{values=[0.8944271909999159, 0.4472135954999579]}, Vector{values=[-0.4472135954999579, 0.8944271909999159]}]
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
if isinstance(list2d[0], list):
self._values = [row[:] for row in list2d]
elif isinstance(list2d[0], Vector):
self._values = [row.underlying_list() for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def dimension_left_null_space(self):
# 左零空间的维度
return self.row_num() - self.rank()
def left_null_base(self):
# 左零空间的一组基
return self.trans().null_base()
@classmethod
def gram_schmidt_process(cls, basis):
# 根据空间的一组基生成空间的一组正交基
matrix = Matrix(basis)
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
res = [basis[0]]
for i in range(1, len(basis)):
p = basis[i]
for r in res:
p = r.rectangular(p)
res.append(p)
return res
@classmethod
def orthonormal_basis(cls, basis):
# 根据空间的一组基生成空间的一组标准正交基
bas = cls.gram_schmidt_process(basis)
return [row.normalize() for row in bas]
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
print(F.dimension_left_null_space())
print(F.left_null_base())
basis = [Vector([2, 1]), Vector([1, 1])]
res = Matrix.gram_schmidt_process(basis)
print(res)
res = Matrix.orthonormal_basis(basis)
print(res)
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
1
[Vector([0, 1, 0])]
2
[Vector([1.0, 0.0, 7.0]), Vector([-0.0, 1.0, 5.0])]
[Vector([-1, 1, -3]), Vector([2, -4, 5])]
1
[Vector([-7.0, -5.0, 1])]
2
[Vector([1.0, 0.0, -1.0000000000000007, -2.0000000000000018, -3.0000000000000013, -4.000000000000002]), Vector([0.0, 1.0, 2.0000000000000004, 3.000000000000001, 4.000000000000001, 5.000000000000002])]
[Vector([1, 27, 15, 31, 45]), Vector([2, 28, 16, 32, 46])]
4
[Vector([1.0000000000000007, -2.0000000000000004, 1, 0, 0, 0]), Vector([2.0000000000000018, -3.000000000000001, 0, 1, 0, 0]), Vector([3.0000000000000013, -4.000000000000001, 0, 0, 1, 0]), Vector([4.000000000000002, -5.000000000000002, 0, 0, 0, 1])]
3
[Vector([-0.4615384615384617, -0.5384615384615384, 1, 0, 0]), Vector([0.1538461538461533, -1.1538461538461537, 0, 1, 0]), Vector([0.6923076923076934, -1.6923076923076923, 0, 0, 1])]
[Vector([2, 1]), Vector([-0.19999999999999996, 0.4])]
[Vector([0.8944271909999159, 0.4472135954999579]), Vector([-0.44721359549995787, 0.894427190999916])]
标准正交矩阵
之前我们在讲矩阵的时候,有说过可以把矩阵看成是一个空间
(2,2)这个点就是(4,1),(2,3)生成空间的坐标系中的坐标
标准正交基按照列的方式排成矩阵,这个矩阵就是标准正交矩阵
一组n维标准正交基
,按照列的方式排成一个n阶方阵Q,称Q为标准正交矩阵
标准正交矩阵的重要性质:
证明:
,这里需要注意的是这里的每一个向量v都是一个列向量,就好比这个样子的
则
由于这是一组标准正交基,任意两个不同的向量相乘为0,相同的向量相乘为1,所以它的结果为单位矩阵I,得证
Q的各列线性无关,根据方阵A的等价命题
根据6和8条都可知,Q可逆,根据
是Q的左逆,则
也是Q的右逆,则
是Q的逆
标准正交矩阵的重要性质
,这样的性质在机器学习算法中有一个非常重要的非监督学习算法叫做PCA算法,它的作用是降维。在这个降维的过程中,我们把一个高维空间降成了低维空间,反过来我们想把这个低维空间再转成高维空间,其实就要利用这一条性质,这是因为我们描述那个低维空间的方式就是一个标准正交矩阵,那么反过去的过程,我们就看这个标准正交矩阵的逆就好了。这个逆我们直接转置一下就得到了相应的结果。
矩阵类中增加一个由一组标准正交基生成一个标准正交矩阵的静态方法orthonormalMatrix
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
public int dimensionLeftNullSpace(Addr<T> addr) {
return this.rowNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> leftNullBase(Addr<T> addr) {
return this.trans().nullBase(addr);
}
/**
* 根据空间的一组基生成空间的一组正交基
* @param basis 空间的一组基
* @param addr
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> gramSchmidtProcess(List<Attribute<T>> basis, Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.size()][basis.get(0).len()];
for (int i = 0; i < basis.size(); i++) {
for (int j = 0; j < basis.get(0).len(); j++) {
values[i][j] = basis.get(i).get(j);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
List<Attribute<Double>> res = new ArrayList<>();
res.add((Attribute<Double>) basis.get(0));
Addr<Double> add = (Addr<Double>) addr;
//获取每i个正交基的生成空间的正交向量
//第一次获取任意基的第一个向量和第二个向量所生成的二维平面的第一个向量的正交向量
//第二次获取任意基的第一个向量和获取的正交向量生成的二维空间的三维正交向量
//第三次获取三个正交向量生成的三维空间的四维正交向量,以此类推
//所有的正交向量最终构成正交基
for (int i = 1; i < basis.size(); i++) {
Attribute<Double> p = (Attribute<Double>) basis.get(i);
for (Attribute<Double> r : res) {
p = r.rectangular(p,add);
}
res.add(p);
}
return res;
}
/**
* 根据空间的一组基生成空间的一组标准正交基
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> orthonormalBasis(List<Attribute<T>> basis, Addr<T> addr) {
List<Attribute<Double>> bas = gramSchmidtProcess(basis,addr);
Addr<Double> add = (Addr<Double>) addr;
List<Attribute<Double>> res = bas.stream().map(vec -> vec.normalize(add))
.collect(Collectors.toList());
return res;
}
/**
* 由一组标准正交基生成一个标准正交矩阵
* @param basis 标准正交基
* @return
*/
public static Ranks<Double> orthonormalMatrix(List<Attribute<Double>> basis) {
Double[][] values = new Double[basis.get(0).len()][basis.size()];
for (int i = 0; i < basis.get(0).len(); i++) {
for (int j = 0; j < basis.size(); j++) {
values[i][j] = basis.get(j).get(i);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
System.out.println(F.dimensionLeftNullSpace(addr1));
System.out.println(F.leftNullBase(addr1));
List<Attribute<Double>> basis = Arrays.asList(new Vector<>(new Double[]{2.0,1.0}),
new Vector<>(new Double[]{1.0,1.0}));
System.out.println(Matrix.gramSchmidtProcess(basis,addr1));
System.out.println(Matrix.orthonormalBasis(basis,addr1));
Ranks<Double> orthonormalMatrix = Matrix.orthonormalMatrix(Matrix.orthonormalBasis(basis,addr1));
System.out.println(orthonormalMatrix);
System.out.println(orthonormalMatrix.dot(orthonormalMatrix.trans(),addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
[Vector{values=[2.0, 1.0]}, Vector{values=[-0.19999999999999996, 0.4]}]
[Vector{values=[0.8944271909999159, 0.4472135954999579]}, Vector{values=[-0.4472135954999579, 0.8944271909999159]}]
Matrix{values=[[0.8944271909999159, -0.4472135954999579],[0.4472135954999579, 0.8944271909999159]]}
Matrix{values=[[0.9999999999999999, 0.0],[0.0, 0.9999999999999999]]}
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
if isinstance(list2d[0], list):
self._values = [row[:] for row in list2d]
elif isinstance(list2d[0], Vector):
self._values = [row.underlying_list() for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def dimension_left_null_space(self):
# 左零空间的维度
return self.row_num() - self.rank()
def left_null_base(self):
# 左零空间的一组基
return self.trans().null_base()
@classmethod
def gram_schmidt_process(cls, basis):
# 根据空间的一组基生成空间的一组正交基
matrix = Matrix(basis)
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
res = [basis[0]]
for i in range(1, len(basis)):
p = basis[i]
for r in res:
p = r.rectangular(p)
res.append(p)
return res
@classmethod
def orthonormal_basis(cls, basis):
# 根据空间的一组基生成空间的一组标准正交基
bas = cls.gram_schmidt_process(basis)
return [row.normalize() for row in bas]
@classmethod
def orthonormal_matrix(cls, basis):
# 由一组标准正交基生成一个标准正交矩阵
return Matrix([[basis[i][j] for i in range(len(basis[0]))] for j in range(len(basis))])
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
print(F.dimension_left_null_space())
print(F.left_null_base())
basis = [Vector([2, 1]), Vector([1, 1])]
res = Matrix.gram_schmidt_process(basis)
print(res)
res = Matrix.orthonormal_basis(basis)
print(res)
orthonormal_matrix = Matrix.orthonormal_matrix(res)
print(orthonormal_matrix)
print(orthonormal_matrix.dot(orthonormal_matrix.trans()))
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
1
[Vector([0, 1, 0])]
2
[Vector([1.0, 0.0, 7.0]), Vector([-0.0, 1.0, 5.0])]
[Vector([-1, 1, -3]), Vector([2, -4, 5])]
1
[Vector([-7.0, -5.0, 1])]
2
[Vector([1.0, 0.0, -1.0000000000000007, -2.0000000000000018, -3.0000000000000013, -4.000000000000002]), Vector([0.0, 1.0, 2.0000000000000004, 3.000000000000001, 4.000000000000001, 5.000000000000002])]
[Vector([1, 27, 15, 31, 45]), Vector([2, 28, 16, 32, 46])]
4
[Vector([1.0000000000000007, -2.0000000000000004, 1, 0, 0, 0]), Vector([2.0000000000000018, -3.000000000000001, 0, 1, 0, 0]), Vector([3.0000000000000013, -4.000000000000001, 0, 0, 1, 0]), Vector([4.000000000000002, -5.000000000000002, 0, 0, 0, 1])]
3
[Vector([-0.4615384615384617, -0.5384615384615384, 1, 0, 0]), Vector([0.1538461538461533, -1.1538461538461537, 0, 1, 0]), Vector([0.6923076923076934, -1.6923076923076923, 0, 0, 1])]
[Vector([2, 1]), Vector([-0.19999999999999996, 0.4])]
[Vector([0.8944271909999159, 0.4472135954999579]), Vector([-0.44721359549995787, 0.894427190999916])]
Matrix([[0.8944271909999159, -0.44721359549995787], [0.4472135954999579, 0.894427190999916]])
Matrix([[0.9999999999999999, 0.0], [0.0, 1.0000000000000002]])
矩阵的QR分解
将一个矩阵A分解成一个Q(标准正交矩阵)和一个R(上三角矩阵)的过程为矩阵的QR分解
对于线性系统Ax=b来说,我们将A分解成QR,则该线性系统就转变为(QR)x=b,我们将式子的两边同时乘以Q的逆,则有
,由于Q的逆乘以Q就是一个单位矩阵I,则有(Q是标准正交矩阵,这里Q的逆就是Q的转置)
R是一个上三角矩阵
,这就意味着我们已经做完了高斯消元法的过程,最后一个未知数是已知的了,只要依次代入上面的行,就能很快求出所有的未知数x
但是矩阵A能进行QR分解,有一个条件:A的各个列向量线性无关
假设
,这里的每一个a都是一个列向量,对A的各个列向量执行格拉姆-施密特过程,得到一组正交基
,再进行规范化,得到一组标准正交基
在之前的高维投影中,我们知道(很明显p就等于p的模乘以q,以下式子中都会出现)
根据这所有的推导,最终一定有下面的结论
则矩阵A可以依次化为
最后化为n个矩阵相加,而每一个矩阵都只包含标准正交基中的一个向量
之前我们在讲两个矩阵相乘,有这样一个结果
则A的n个矩阵相加的结果可以化为两个矩阵相乘
由于q是一组标准正交基,则它组成的列矩阵就是标准正交矩阵Q,而
这个矩阵,我们定义为R
当然我们并不需要这么繁琐的去求这个R,因为A=QR
则
,也就为
Ranks接口新增一个矩阵QR分解的方法qr,我们限定原矩阵是一个方阵
public interface Ranks<T extends Number> {
/**
* 矩阵的行列数
* @return
*/
int[] shape();
/**
* 矩阵的行数
* @return
*/
int rowNum();
/**
* 矩阵的列数
* @return
*/
int colNum();
/**
* 矩阵的元素个数
* @return
*/
int size();
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int pos);
/**
* 获取矩阵中的一个元素
* @param pos
* @return
*/
T get(int[] pos);
/**
* 设置矩阵中某个位置的元素
* @param pos
* @param value
*/
void set(int[] pos,T value);
/**
* 获取一个行向量
* @param index
* @return
*/
Attribute<T> rowVector(int index);
/**
* 获取一个列向量
* @param index
* @return
*/
Attribute<T> colVector(int index);
/**
* 矩阵相加
* @param another
* @return
*/
Ranks<T> add(Ranks<T> another,Addr<T> addr);
/**
* 矩阵相减
* @param another
* @param addr
* @return
*/
Ranks<T> sub(Ranks<T> another,Addr<T> addr);
/**
* 矩阵乘以一个数
* @param k
* @param addr
* @return
*/
Ranks<T> mul(T k,Addr<T> addr);
/**
* 矩阵除以一个数
* @param k
* @param addr
* @return
*/
Ranks<Double> div(double k,Addr<T> addr);
/**
* 矩阵取正的结果
* @return
*/
Ranks<T> pos(Addr<T> addr,T one);
/**
* 矩阵取负的结果
* @return
*/
Ranks<T> neg(Addr<T> addr,T negOne);
/**
* 矩阵与向量的点乘
* @param another
* @param addr
* @return
*/
Attribute<T> dot(Attribute<T> another,Addr<T> addr);
/**
* 矩阵与矩阵的点乘
* @param another
* @param addr
* @return
*/
Ranks<T> dot(Ranks<T> another,Addr<T> addr);
/**
* 转置矩阵
* @return
*/
Ranks<T> trans();
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invFunc(Addr<T> addr);
/**
* 矩阵的逆
* @param addr
* @return
*/
Ranks<T> invMatrix(Addr<T> addr);
/**
* 矩阵的LU分解
* @param addr
* @return
*/
Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr);
/**
* 矩阵的秩
* @param addr
* @return
*/
int rank(Addr<T> addr);
/**
* 行空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> rowBase(Addr<T> addr);
/**
* 列空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> colBase(Addr<T> addr);
/**
* 零空间的维度
* @param addr
* @return
*/
int dimensionNullSpace(Addr<T> addr);
/**
* 零空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> nullBase(Addr<T> addr);
/**
* 左零空间的维度
* @param addr
* @return
*/
int dimensionLeftNullSpace(Addr<T> addr);
/**
* 左零空间的一组基
* @param addr
* @return
*/
List<Attribute<T>> leftNullBase(Addr<T> addr);
/**
* 矩阵的QR分解
* @param addr
* @return
*/
Tuple<Ranks<Double>,Ranks<Double>> qr(Addr<T> addr);
}
矩阵实现类
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
public int dimensionLeftNullSpace(Addr<T> addr) {
return this.rowNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> leftNullBase(Addr<T> addr) {
return this.trans().nullBase(addr);
}
/**
* 根据空间的一组基生成空间的一组正交基
* @param basis 空间的一组基
* @param addr
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> gramSchmidtProcess(List<Attribute<T>> basis, Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.size()][basis.get(0).len()];
for (int i = 0; i < basis.size(); i++) {
for (int j = 0; j < basis.get(0).len(); j++) {
values[i][j] = basis.get(i).get(j);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
List<Attribute<Double>> res = new ArrayList<>();
res.add((Attribute<Double>) basis.get(0));
Addr<Double> add = (Addr<Double>) addr;
//获取每i个正交基的生成空间的正交向量
//第一次获取任意基的第一个向量和第二个向量所生成的二维平面的第一个向量的正交向量
//第二次获取任意基的第一个向量和获取的正交向量生成的二维空间的三维正交向量
//第三次获取三个正交向量生成的三维空间的四维正交向量,以此类推
//所有的正交向量最终构成正交基
for (int i = 1; i < basis.size(); i++) {
Attribute<Double> p = (Attribute<Double>) basis.get(i);
for (Attribute<Double> r : res) {
p = r.rectangular(p,add);
}
res.add(p);
}
return res;
}
/**
* 根据空间的一组基生成空间的一组标准正交基
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> orthonormalBasis(List<Attribute<T>> basis, Addr<T> addr) {
List<Attribute<Double>> bas = gramSchmidtProcess(basis,addr);
Addr<Double> add = (Addr<Double>) addr;
List<Attribute<Double>> res = bas.stream().map(vec -> vec.normalize(add))
.collect(Collectors.toList());
return res;
}
/**
* 由一组标准正交基生成一个标准正交矩阵
* @param basis 标准正交基
* @return
*/
public static Ranks<Double> orthonormalMatrix(List<Attribute<Double>> basis) {
Double[][] values = new Double[basis.get(0).len()][basis.size()];
for (int i = 0; i < basis.get(0).len(); i++) {
for (int j = 0; j < basis.size(); j++) {
values[i][j] = basis.get(j).get(i);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<Double>,Ranks<Double>> qr(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
throw new RuntimeException("矩阵必须为一个方阵");
}
if (this.rank(addr) != this.colNum()) {
throw new RuntimeException("矩阵的列向量必须线性无关");
}
List<Attribute<T>> basis = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
basis.add(this.colVector(i));
}
List<Attribute<Double>> sp = Matrix.orthonormalBasis(basis,addr);
Ranks<Double> Q = Matrix.orthonormalMatrix(sp);
Ranks<Double> source = (Ranks<Double>) this;
Addr<Double> add = (Addr<Double>) addr;
Ranks<Double> R = Q.trans().dot(source,add);
return new Tuple<>(Q,R);
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
System.out.println(F.dimensionLeftNullSpace(addr1));
System.out.println(F.leftNullBase(addr1));
List<Attribute<Double>> basis = Arrays.asList(new Vector<>(new Double[]{2.0,1.0}),
new Vector<>(new Double[]{1.0,1.0}));
System.out.println(Matrix.gramSchmidtProcess(basis,addr1));
System.out.println(Matrix.orthonormalBasis(basis,addr1));
Ranks<Double> orthonormalMatrix = Matrix.orthonormalMatrix(Matrix.orthonormalBasis(basis,addr1));
System.out.println(orthonormalMatrix);
System.out.println(orthonormalMatrix.dot(orthonormalMatrix.trans(),addr1));
Ranks<Double> A1 = new Matrix<>(new Double[][]{{1.0,1.0,2.0},{1.0,1.0,0.0},
{1.0,0.0,0.0}});
Tuple<Ranks<Double>,Ranks<Double>> qr = A1.qr(addr1);
Ranks<Double> Q = qr.getField(0);
Ranks<Double> R = qr.getField(1);
System.out.println(Q);
System.out.println(R);
System.out.println(Q.dot(R,addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
[Vector{values=[2.0, 1.0]}, Vector{values=[-0.19999999999999996, 0.4]}]
[Vector{values=[0.8944271909999159, 0.4472135954999579]}, Vector{values=[-0.4472135954999579, 0.8944271909999159]}]
Matrix{values=[[0.8944271909999159, -0.4472135954999579],[0.4472135954999579, 0.8944271909999159]]}
Matrix{values=[[0.9999999999999999, 0.0],[0.0, 0.9999999999999999]]}
Matrix{values=[[0.5773502691896258, 0.4082482904638628, 0.7071067811865475],[0.5773502691896258, 0.4082482904638628, -0.7071067811865476],[0.5773502691896258, -0.8164965809277263, 0.0]]}
Matrix{values=[[1.7320508075688776, 1.1547005383792517, 1.1547005383792517],[-6.661338147750939E-16, 0.8164965809277256, 0.8164965809277256],[-1.1102230246251565E-16, -1.1102230246251565E-16, 1.414213562373095]]}
Matrix{values=[[0.9999999999999999, 0.9999999999999997, 1.9999999999999996],[1.0, 0.9999999999999999, -2.220446049250313E-16],[1.0000000000000007, 3.3306690738754696E-16, 3.3306690738754696E-16]]}
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
if isinstance(list2d[0], list):
self._values = [row[:] for row in list2d]
elif isinstance(list2d[0], Vector):
self._values = [row.underlying_list() for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def dimension_left_null_space(self):
# 左零空间的维度
return self.row_num() - self.rank()
def left_null_base(self):
# 左零空间的一组基
return self.trans().null_base()
@classmethod
def gram_schmidt_process(cls, basis):
# 根据空间的一组基生成空间的一组正交基
matrix = Matrix(basis)
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
res = [basis[0]]
for i in range(1, len(basis)):
p = basis[i]
for r in res:
p = r.rectangular(p)
res.append(p)
return res
@classmethod
def orthonormal_basis(cls, basis):
# 根据空间的一组基生成空间的一组标准正交基
bas = cls.gram_schmidt_process(basis)
return [row.normalize() for row in bas]
@classmethod
def orthonormal_matrix(cls, basis):
# 由一组标准正交基生成一个标准正交矩阵
return Matrix([[basis[i][j] for i in range(len(basis[0]))] for j in range(len(basis))])
def qr(self):
# 矩阵的QR分解
assert self.row_num() == self.col_num(), \
"矩阵必须为一个方阵"
assert self.rank() == self.col_num(), \
"矩阵的列向量必须线性无关"
basis = [self.col_vector(i) for i in range(self.col_num())]
sp = Matrix.orthonormal_basis(basis)
Q = Matrix.orthonormal_matrix(sp)
R = Q.trans().dot(self)
return Q, R
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
print(F.dimension_left_null_space())
print(F.left_null_base())
basis = [Vector([2, 1]), Vector([1, 1])]
res = Matrix.gram_schmidt_process(basis)
print(res)
res = Matrix.orthonormal_basis(basis)
print(res)
orthonormal_matrix = Matrix.orthonormal_matrix(res)
print(orthonormal_matrix)
print(orthonormal_matrix.dot(orthonormal_matrix.trans()))
A1 = Matrix([[1, 1, 2], [1, 1, 0], [1, 0, 0]])
Q, R = A1.qr()
print(Q)
print(R)
print(Q.dot(R))
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
1
[Vector([0, 1, 0])]
2
[Vector([1.0, 0.0, 7.0]), Vector([-0.0, 1.0, 5.0])]
[Vector([-1, 1, -3]), Vector([2, -4, 5])]
1
[Vector([-7.0, -5.0, 1])]
2
[Vector([1.0, 0.0, -1.0000000000000007, -2.0000000000000018, -3.0000000000000013, -4.000000000000002]), Vector([0.0, 1.0, 2.0000000000000004, 3.000000000000001, 4.000000000000001, 5.000000000000002])]
[Vector([1, 27, 15, 31, 45]), Vector([2, 28, 16, 32, 46])]
4
[Vector([1.0000000000000007, -2.0000000000000004, 1, 0, 0, 0]), Vector([2.0000000000000018, -3.000000000000001, 0, 1, 0, 0]), Vector([3.0000000000000013, -4.000000000000001, 0, 0, 1, 0]), Vector([4.000000000000002, -5.000000000000002, 0, 0, 0, 1])]
3
[Vector([-0.4615384615384617, -0.5384615384615384, 1, 0, 0]), Vector([0.1538461538461533, -1.1538461538461537, 0, 1, 0]), Vector([0.6923076923076934, -1.6923076923076923, 0, 0, 1])]
[Vector([2, 1]), Vector([-0.19999999999999996, 0.4])]
[Vector([0.8944271909999159, 0.4472135954999579]), Vector([-0.44721359549995787, 0.894427190999916])]
Matrix([[0.8944271909999159, -0.44721359549995787], [0.4472135954999579, 0.894427190999916]])
Matrix([[0.9999999999999999, 0.0], [0.0, 1.0000000000000002]])
Matrix([[0.5773502691896258, 0.4082482904638628, 0.7071067811865475], [0.5773502691896258, 0.4082482904638628, -0.7071067811865476], [0.5773502691896258, -0.8164965809277263, 0.0]])
Matrix([[1.7320508075688776, 1.1547005383792517, 1.1547005383792517], [-6.661338147750939e-16, 0.8164965809277256, 0.8164965809277256], [-1.1102230246251565e-16, -1.1102230246251565e-16, 1.414213562373095]])
Matrix([[0.9999999999999999, 0.9999999999999997, 1.9999999999999996], [1.0, 0.9999999999999999, -2.220446049250313e-16], [1.0000000000000007, 3.3306690738754696e-16, 3.3306690738754696e-16]])
空间的基和坐标系
理解空间的基的一个视角:坐标系
这是我们之前一直在说的把矩阵看成一个空间的例子。之前也说过:在n维空间,如果给定一组基,任何一个向量(或者是点)都可以表示成这组基的线性组合!且表示方法唯一。
一般我们说一个向量,比如
,如果没有特殊说明,指的是以
这样的一组标准单位向量为空间的一组基来说的,即
但是对
这样的一组基来说,
却是这样的情况
对于同一个向量(或者点)在不同的基所对应的坐标系中,它所对应的坐标就是不同的
如果在给定向量空间V中的一组基
以及V中的一个向量x,则x一定可以被这组基线性表示。假设:
,则称x在这组基B下的坐标,为
,记为:
如果标准单位向量所组成的基用£来表示的话
,u、v这组基用B来表示的话
,则
而
被称为标准基(Standard Basis),也被称为标准坐标系。(这里需要注意的是标准基是标准正交基(Orthonormal Basis)的一个特例,标准基只有一个,而标准正交基有无数个)
n维标准基(n维标准坐标系)
其他坐标系与标准坐标系的转换
理解空间的基的一个视角:坐标系,我们还是以这个图为例
之前我们在讲将矩阵看成一个空间的时候就知道,它们之间的转换关系是这个样子的
假设n维空间有一组基
设立矩阵
,在这组基下的一个向量
,有
。这里的
就是坐标转换矩阵
为什么它是成立的,我们还是以
来说明一下
因为
则
既然我们可以将B这组基下的坐标转换成标准基下的坐标,自然也就可以将标准基下的坐标转换成B这组基下的坐标。
等式的两边同时乘以
的逆,就有
,则
,这里
是一个方阵,因为
是n维空间的一组基,所以
一定可逆。
最后则有
,这里可以简单的记忆就是
所乘以的那个坐标一定是B那组基下所对应的坐标。如果不是,则用
的逆。
矩阵类中增加两个静态方法otherToStandard(其他坐标系坐标转换标准坐标系坐标),以及standardToOther(标准坐标系坐标转换其他坐标系坐标)
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
public int dimensionLeftNullSpace(Addr<T> addr) {
return this.rowNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> leftNullBase(Addr<T> addr) {
return this.trans().nullBase(addr);
}
/**
* 根据空间的一组基生成空间的一组正交基
* @param basis 空间的一组基
* @param addr
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> gramSchmidtProcess(List<Attribute<T>> basis, Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.size()][basis.get(0).len()];
for (int i = 0; i < basis.size(); i++) {
for (int j = 0; j < basis.get(0).len(); j++) {
values[i][j] = basis.get(i).get(j);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
List<Attribute<Double>> res = new ArrayList<>();
res.add((Attribute<Double>) basis.get(0));
Addr<Double> add = (Addr<Double>) addr;
//获取每i个正交基的生成空间的正交向量
//第一次获取任意基的第一个向量和第二个向量所生成的二维平面的第一个向量的正交向量
//第二次获取任意基的第一个向量和获取的正交向量生成的二维空间的三维正交向量
//第三次获取三个正交向量生成的三维空间的四维正交向量,以此类推
//所有的正交向量最终构成正交基
for (int i = 1; i < basis.size(); i++) {
Attribute<Double> p = (Attribute<Double>) basis.get(i);
for (Attribute<Double> r : res) {
p = r.rectangular(p,add);
}
res.add(p);
}
return res;
}
/**
* 根据空间的一组基生成空间的一组标准正交基
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> orthonormalBasis(List<Attribute<T>> basis, Addr<T> addr) {
List<Attribute<Double>> bas = gramSchmidtProcess(basis,addr);
Addr<Double> add = (Addr<Double>) addr;
List<Attribute<Double>> res = bas.stream().map(vec -> vec.normalize(add))
.collect(Collectors.toList());
return res;
}
/**
* 由一组标准正交基生成一个标准正交矩阵
* @param basis 标准正交基
* @return
*/
public static Ranks<Double> orthonormalMatrix(List<Attribute<Double>> basis) {
Double[][] values = new Double[basis.get(0).len()][basis.size()];
for (int i = 0; i < basis.get(0).len(); i++) {
for (int j = 0; j < basis.size(); j++) {
values[i][j] = basis.get(j).get(i);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<Double>,Ranks<Double>> qr(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
throw new RuntimeException("矩阵必须为一个方阵");
}
if (this.rank(addr) != this.colNum()) {
throw new RuntimeException("矩阵的列向量必须线性无关");
}
List<Attribute<T>> basis = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
basis.add(this.colVector(i));
}
List<Attribute<Double>> sp = Matrix.orthonormalBasis(basis,addr);
Ranks<Double> Q = Matrix.orthonormalMatrix(sp);
Ranks<Double> source = (Ranks<Double>) this;
Addr<Double> add = (Addr<Double>) addr;
Ranks<Double> R = Q.trans().dot(source,add);
return new Tuple<>(Q,R);
}
/**
* 其他坐标系坐标转换标准坐标系坐标
* @param otherBasis 其他坐标系的一组基
* @param otherVector 其他坐标系的一个向量坐标
* @param <T>
* @return
*/
public static <T extends Number> Attribute<T> otherToStandard(List<Attribute<T>> otherBasis,
Attribute<T> otherVector,
Addr<T> addr) {
Ranks<T> matrix = buildColMatrix(otherBasis,addr);
return matrix.dot(otherVector,addr);
}
/**
* 标准坐标系坐标转换其他坐标系坐标
* @param otherBasis 其他坐标系的一组基
* @param vector 标准坐标系的一个向量坐标
* @param addr
* @param <T>
* @return
*/
public static <T extends Number> Attribute<T> standardToOther(List<Attribute<T>> otherBasis,
Attribute<T> vector,
Addr<T> addr) {
Ranks<T> matrix = buildColMatrix(otherBasis,addr);
return matrix.invFunc(addr).dot(vector,addr);
}
/**
* 根据空间的一组基建立一个列向量矩阵
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
private static <T extends Number> Ranks<T> buildColMatrix(List<Attribute<T>> basis,Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.get(0).len()][basis.size()];
for (int i = 0; i < basis.get(0).len(); i++) {
for (int j = 0; j < basis.size(); j++) {
values[i][j] = basis.get(j).get(i);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rowNum() != matrix.colNum()) {
throw new IllegalArgumentException("矩阵必须为一个方阵");
}
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
return matrix;
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
System.out.println(F.dimensionLeftNullSpace(addr1));
System.out.println(F.leftNullBase(addr1));
List<Attribute<Double>> basis = Arrays.asList(new Vector<>(new Double[]{2.0,1.0}),
new Vector<>(new Double[]{1.0,1.0}));
System.out.println(Matrix.gramSchmidtProcess(basis,addr1));
System.out.println(Matrix.orthonormalBasis(basis,addr1));
Ranks<Double> orthonormalMatrix = Matrix.orthonormalMatrix(Matrix.orthonormalBasis(basis,addr1));
System.out.println(orthonormalMatrix);
System.out.println(orthonormalMatrix.dot(orthonormalMatrix.trans(),addr1));
Ranks<Double> A1 = new Matrix<>(new Double[][]{{1.0,1.0,2.0},{1.0,1.0,0.0},
{1.0,0.0,0.0}});
Tuple<Ranks<Double>,Ranks<Double>> qr = A1.qr(addr1);
Ranks<Double> Q = qr.getField(0);
Ranks<Double> R = qr.getField(1);
System.out.println(Q);
System.out.println(R);
System.out.println(Q.dot(R,addr1));
List<Attribute<Double>> otherBasis = Arrays.asList(new Vector<>(new Double[]{4.0,1.0}),
new Vector<>(new Double[]{2.0,3.0}));
Attribute<Double> otherVector = new Vector<>(new Double[]{2.0,2.0});
Attribute<Double> vectorStard = Matrix.otherToStandard(otherBasis,otherVector,addr1);
System.out.println(vectorStard);
System.out.println(Matrix.standardToOther(otherBasis,vectorStard,addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
[Vector{values=[2.0, 1.0]}, Vector{values=[-0.19999999999999996, 0.4]}]
[Vector{values=[0.8944271909999159, 0.4472135954999579]}, Vector{values=[-0.4472135954999579, 0.8944271909999159]}]
Matrix{values=[[0.8944271909999159, -0.4472135954999579],[0.4472135954999579, 0.8944271909999159]]}
Matrix{values=[[0.9999999999999999, 0.0],[0.0, 0.9999999999999999]]}
Matrix{values=[[0.5773502691896258, 0.4082482904638628, 0.7071067811865475],[0.5773502691896258, 0.4082482904638628, -0.7071067811865476],[0.5773502691896258, -0.8164965809277263, 0.0]]}
Matrix{values=[[1.7320508075688776, 1.1547005383792517, 1.1547005383792517],[-6.661338147750939E-16, 0.8164965809277256, 0.8164965809277256],[-1.1102230246251565E-16, -1.1102230246251565E-16, 1.414213562373095]]}
Matrix{values=[[0.9999999999999999, 0.9999999999999997, 1.9999999999999996],[1.0, 0.9999999999999999, -2.220446049250313E-16],[1.0000000000000007, 3.3306690738754696E-16, 3.3306690738754696E-16]]}
Vector{values=[12.0, 8.0]}
Vector{values=[1.9999999999999996, 2.0]}
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
if isinstance(list2d[0], list):
self._values = [row[:] for row in list2d]
elif isinstance(list2d[0], Vector):
self._values = [row.underlying_list() for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def dimension_left_null_space(self):
# 左零空间的维度
return self.row_num() - self.rank()
def left_null_base(self):
# 左零空间的一组基
return self.trans().null_base()
@classmethod
def gram_schmidt_process(cls, basis):
# 根据空间的一组基生成空间的一组正交基
matrix = Matrix(basis)
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
res = [basis[0]]
for i in range(1, len(basis)):
p = basis[i]
for r in res:
p = r.rectangular(p)
res.append(p)
return res
@classmethod
def orthonormal_basis(cls, basis):
# 根据空间的一组基生成空间的一组标准正交基
bas = cls.gram_schmidt_process(basis)
return [row.normalize() for row in bas]
@classmethod
def orthonormal_matrix(cls, basis):
# 由一组标准正交基生成一个标准正交矩阵
return Matrix([[basis[i][j] for i in range(len(basis[0]))] for j in range(len(basis))])
def qr(self):
# 矩阵的QR分解
assert self.row_num() == self.col_num(), \
"矩阵必须为一个方阵"
assert self.rank() == self.col_num(), \
"矩阵的列向量必须线性无关"
basis = [self.col_vector(i) for i in range(self.col_num())]
sp = Matrix.orthonormal_basis(basis)
Q = Matrix.orthonormal_matrix(sp)
R = Q.trans().dot(self)
return Q, R
@classmethod
def _build_col_matrix(cls, basis):
# 根据空间的一组基建立一个列向量矩阵
matrix = Matrix([[basis[i][j] for i in range(len(basis[0]))] for j in range(len(basis))])
assert matrix.row_num() == matrix.col_num(), \
"矩阵必须为一个方阵"
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
return matrix
@classmethod
def other_to_standard(cls, other_basis, other_vector):
# 其他坐标系坐标转换标准坐标系坐标
matrix = cls._build_col_matrix(other_basis)
return matrix.dot(other_vector)
@classmethod
def standard_to_other(cls, other_basis, vector):
# 标准坐标系坐标转换其他坐标系坐标
matrix = cls._build_col_matrix(other_basis)
return matrix.inv_func().dot(vector)
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
print(F.dimension_left_null_space())
print(F.left_null_base())
basis = [Vector([2, 1]), Vector([1, 1])]
res = Matrix.gram_schmidt_process(basis)
print(res)
res = Matrix.orthonormal_basis(basis)
print(res)
orthonormal_matrix = Matrix.orthonormal_matrix(res)
print(orthonormal_matrix)
print(orthonormal_matrix.dot(orthonormal_matrix.trans()))
A1 = Matrix([[1, 1, 2], [1, 1, 0], [1, 0, 0]])
Q, R = A1.qr()
print(Q)
print(R)
print(Q.dot(R))
other_basis = [Vector([4, 1]), Vector([2, 3])]
other_vector = Vector([2, 2])
vector_stard = Matrix.other_to_standard(other_basis, other_vector)
print(vector_stard)
print(Matrix.standard_to_other(other_basis, vector_stard))
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
1
[Vector([0, 1, 0])]
2
[Vector([1.0, 0.0, 7.0]), Vector([-0.0, 1.0, 5.0])]
[Vector([-1, 1, -3]), Vector([2, -4, 5])]
1
[Vector([-7.0, -5.0, 1])]
2
[Vector([1.0, 0.0, -1.0000000000000007, -2.0000000000000018, -3.0000000000000013, -4.000000000000002]), Vector([0.0, 1.0, 2.0000000000000004, 3.000000000000001, 4.000000000000001, 5.000000000000002])]
[Vector([1, 27, 15, 31, 45]), Vector([2, 28, 16, 32, 46])]
4
[Vector([1.0000000000000007, -2.0000000000000004, 1, 0, 0, 0]), Vector([2.0000000000000018, -3.000000000000001, 0, 1, 0, 0]), Vector([3.0000000000000013, -4.000000000000001, 0, 0, 1, 0]), Vector([4.000000000000002, -5.000000000000002, 0, 0, 0, 1])]
3
[Vector([-0.4615384615384617, -0.5384615384615384, 1, 0, 0]), Vector([0.1538461538461533, -1.1538461538461537, 0, 1, 0]), Vector([0.6923076923076934, -1.6923076923076923, 0, 0, 1])]
[Vector([2, 1]), Vector([-0.19999999999999996, 0.4])]
[Vector([0.8944271909999159, 0.4472135954999579]), Vector([-0.44721359549995787, 0.894427190999916])]
Matrix([[0.8944271909999159, -0.44721359549995787], [0.4472135954999579, 0.894427190999916]])
Matrix([[0.9999999999999999, 0.0], [0.0, 1.0000000000000002]])
Matrix([[0.5773502691896258, 0.4082482904638628, 0.7071067811865475], [0.5773502691896258, 0.4082482904638628, -0.7071067811865476], [0.5773502691896258, -0.8164965809277263, 0.0]])
Matrix([[1.7320508075688776, 1.1547005383792517, 1.1547005383792517], [-6.661338147750939e-16, 0.8164965809277256, 0.8164965809277256], [-1.1102230246251565e-16, -1.1102230246251565e-16, 1.414213562373095]])
Matrix([[0.9999999999999999, 0.9999999999999997, 1.9999999999999996], [1.0, 0.9999999999999999, -2.220446049250313e-16], [1.0000000000000007, 3.3306690738754696e-16, 3.3306690738754696e-16]])
(12, 8)
(1.9999999999999996, 2.0)
任意坐标系转换
假设有一组基:
,另一组基
,在B这组基下的一个向量
,求
以标准坐标系为桥梁
最终得到
由于
也是一个矩阵,我们记作从B的坐标系到C的坐标系的转换矩阵
,则
反过来,从C的坐标系到B的坐标系下的转换就是
由于
,则我们知道了,这两组基互相转换的矩阵互为逆矩阵
由于标准基也是一组基,它同样满足这样的性质
我们把标准基定义为C,则
这些都和我们之前的结论是吻合的
我们之前所说的所有的基,其实也都是标准坐标系下的基
,
,其实矩阵的真实样子应该是这样的
假设有一组基:
,另一组基
,如果我们知道
,在这组基下的一个向量
,求
很明显,这里的有直接的转换矩阵
,无需再通过标准坐标系为桥梁。
则有
矩阵类新增一个静态方法oneToAnother(一个坐标系坐标转换另一个坐标系坐标)
@AllArgsConstructor
public class Matrix<T extends Number> implements Ranks<T>,Cloneable {
private T[][] values;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length - 1; i++) {
builder.append(Arrays.toString(values[i]) + ",");
}
builder.append(Arrays.toString(values[values.length - 1]));
return "Matrix{" +
"values=" + "[" + builder.toString() + "]" +
'}';
}
/**
* 创建一个零矩阵
* @param row
* @param col
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> zero(int row,int col,Addr<T> addr) {
T[][] values = (T[][])new Number[row][col];
for (int i = 0; i < row; i++) {
Arrays.fill(values[i],addr.zero());
}
return new Matrix<>(values);
}
/**
* 创建一个单位矩阵
* @param n
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> Ranks<T> identity(int n,Addr<T> addr) {
T[][] values = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(values[i],addr.zero());
}
for (int i = 0; i < n; i++) {
values[i][i] = addr.one();
}
return new Matrix<>(values);
}
@Override
public int[] shape() {
int[] res = new int[2];
res[0] = values.length;
res[1] = values[0].length;
return res;
}
@Override
public int rowNum() {
return shape()[0];
}
@Override
public int colNum() {
return shape()[1];
}
@Override
public int size() {
int row = rowNum();
int col = colNum();
return row * col;
}
@Override
public T get(int pos) {
if (pos >= size() || pos < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
int row = pos / colNum();
int col = pos % colNum();
return values[row][col];
}
@Override
public T get(int[] pos) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
return values[pos[0]][pos[1]];
}
@Override
public void set(int[] pos, T value) {
if (pos.length != 2) {
throw new IllegalArgumentException("位置长度超出范围");
}
if (pos[0] >= rowNum() || pos[0] < 0 || pos[1] >= colNum() || pos[1] < 0) {
throw new IllegalArgumentException("位置超出索引范围");
}
values[pos[0]][pos[1]] = value;
}
@Override
public Attribute<T> rowVector(int index) {
if (index >= rowNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
return new Vector<>(values[index]);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> colVector(int index) {
if (index >= colNum() || index < 0) {
throw new IllegalArgumentException("索引超出范围");
}
T[] values = (T[])new Number[rowNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = this.values[i][index];
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> add(Ranks<T> another,Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("加法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.add(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> sub(Ranks<T> another, Addr<T> addr) {
if (!Arrays.equals(this.shape(),another.shape())) {
throw new IllegalArgumentException("减法错误,两个矩阵的形状必须相同");
}
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.sub(this.get(new int[]{i,j}),another.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> mul(T k, Addr<T> addr) {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.mul(k,this.get(new int[]{i,j}));
}
}
this.values = values;
return this;
}
@Override
public Ranks<Double> div(double k, Addr<T> addr) {
Double[][] values = new Double[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
for (int j = 0; j < colNum(); j++) {
values[i][j] = addr.div(this.get(new int[]{i,j}),k);
}
}
return new Matrix<>(values);
}
@Override
public Ranks<T> pos(Addr<T> addr,T one) {
return mul(one,addr);
}
@Override
public Ranks<T> neg(Addr<T> addr,T negOne) {
return mul(negOne,addr);
}
@Override
@SuppressWarnings("unchecked")
public Attribute<T> dot(Attribute<T> another, Addr<T> addr) {
if (this.colNum() != another.len()) {
throw new IllegalArgumentException("矩阵列数需要与向量的长度相等");
}
T[] values = (T[])new Number[this.rowNum()];
for (int i = 0; i < this.rowNum(); i++) {
values[i] = this.rowVector(i).dot(another,addr);
}
return new Vector<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> dot(Ranks<T> another, Addr<T> addr) {
if (this.colNum() != another.rowNum()) {
throw new IllegalArgumentException("当前矩阵列数必须等于点乘矩阵行数");
}
T[][] values = (T[][]) new Number[this.rowNum()][another.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < another.colNum(); j++) {
values[i][j] = this.rowVector(i).dot(another.colVector(j),addr);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> trans() {
T[][] values = (T[][])new Number[this.colNum()][this.rowNum()];
for (int i = 0; i < this.colNum(); i++) {
for (int j = 0; j < this.rowNum(); j++) {
values[i][j] = this.values[j][i];
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invFunc(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemFunc<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemFunc)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemFunc)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemFunc)ls).getAb().get(new int[]{i,((LinearSystemFunc)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Ranks<T> invMatrix(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
return null;
}
int n = this.rowNum();
FuncGroup<T> ls = new LinearSystemMatrix<>(this,Matrix.identity(n,addr));
if (!ls.gaussJordanElimination(addr)) {
return null;
}
T[][] values = (T[][])new Number[this.rowNum()][((LinearSystemMatrix)ls).getAb().colNum() - this.colNum()];
for (int i = 0; i < this.rowNum(); i++) {
for (int j = 0; j < ((LinearSystemMatrix)ls).getAb().colNum() - this.colNum(); j++) {
values[i][j] = (T)((LinearSystemMatrix)ls).getAb().get(new int[]{i,((LinearSystemMatrix)ls).getAb().colNum() - this.colNum() + j});
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<T>,Ranks<T>> lu(Addr<T> addr) {
// if (this.rowNum() != this.colNum()) {
// throw new IllegalArgumentException("矩阵必须为方阵");
// }
int n = this.rowNum();
int l = this.colNum();
if (l > n) {
T[][] A = (T[][])new Number[n][l];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
}
T[][] A = (T[][])new Number[n][n];
//此处不能直接把this.values赋给A,否则会改变原矩阵的values
for (int i = 0; i < n; i++) {
A[i] = Arrays.copyOf(this.values[i],n);
}
//构建一个下三角矩阵的二维数组,先将其初始为一个单位矩阵
T[][] L = (T[][])new Number[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
L[i][j] = addr.one();
}else {
L[i][j] = addr.zero();
}
}
}
for (int i = 0; i < n; i++) {
//主元不能为0
if (addr.equals(A[i][i],addr.zero())) {
return null;
}else {
//将主元下面的元素变为0
for (int j = i + 1; j < n; j++) {
//获取初等矩阵逆矩阵的系数
T p = addr.div(A[j][i],A[i][i]);
for (int k = 0; k < n; k++) {
T u = A[i][k];
A[j][k] = addr.sub(A[j][k],addr.mul(p,u));
}
//将初等矩阵逆矩阵的系数填充下三角矩阵
L[j][i] = p;
}
}
}
return new Tuple<>(new Matrix(L),new Matrix(A));
}
@Override
@SuppressWarnings("unchecked")
public int rank(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
int sum = 0;
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出不为零向量的行数,即矩阵的秩,空间维度
if (!zero.equals(row,addr)) {
sum++;
}
}
return sum;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> rowBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
zero = Vector.zero(this.colNum() + 1,addr);
List<Attribute<T>> rowBaseList = new ArrayList<>();
for (int i = 0; i < ((LinearSystem) ls).getAb().rowNum(); i++) {
Attribute<T> row = ((LinearSystem) ls).getAb().rowVector(i);
//找出行最简形式不为零向量的向量
if (!zero.equals(row,addr)) {
T[] values = Arrays.copyOf((T[]) ((Vector) row).getValues(),this.colNum());
Attribute<T> newRow = new Vector<>(values);
rowBaseList.add(newRow);
}
}
return rowBaseList;
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> colBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> colBaseList = new ArrayList<>();
pivots.forEach(i -> colBaseList.add(this.colVector(i)));
return colBaseList;
}
@Override
public int dimensionNullSpace(Addr<T> addr) {
return this.colNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> nullBase(Addr<T> addr) {
Attribute<T> zero = Vector.zero(this.rowNum(),addr);
FuncGroup<T> ls = new LinearSystemFunc<>(this,zero);
ls.gaussJordanElimination(addr);
List<Integer> pivots = ((LinearSystem) ls).getPivots();
List<Attribute<T>> zeroBaseList = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
//如果是自由列
if (!pivots.contains(i)) {
Attribute<T> temp = Vector.zero(this.colNum(),addr);
Attribute<T> col = ((LinearSystem) ls).getAb().colVector(i);
for (int j = 0; j < temp.len(); j++) {
if (j < col.len() && !addr.equals(col.get(j),addr.zero())) {
temp.set(j, addr.neg(col.get(j)));
}
if (i == j) {
temp.set(j,addr.one());
}
}
zeroBaseList.add(temp);
}
}
return zeroBaseList;
}
@Override
public int dimensionLeftNullSpace(Addr<T> addr) {
return this.rowNum() - rank(addr);
}
@Override
@SuppressWarnings("unchecked")
public List<Attribute<T>> leftNullBase(Addr<T> addr) {
return this.trans().nullBase(addr);
}
/**
* 根据空间的一组基生成空间的一组正交基
* @param basis 空间的一组基
* @param addr
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> gramSchmidtProcess(List<Attribute<T>> basis, Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.size()][basis.get(0).len()];
for (int i = 0; i < basis.size(); i++) {
for (int j = 0; j < basis.get(0).len(); j++) {
values[i][j] = basis.get(i).get(j);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
List<Attribute<Double>> res = new ArrayList<>();
res.add((Attribute<Double>) basis.get(0));
Addr<Double> add = (Addr<Double>) addr;
//获取每i个正交基的生成空间的正交向量
//第一次获取任意基的第一个向量和第二个向量所生成的二维平面的第一个向量的正交向量
//第二次获取任意基的第一个向量和获取的正交向量生成的二维空间的三维正交向量
//第三次获取三个正交向量生成的三维空间的四维正交向量,以此类推
//所有的正交向量最终构成正交基
for (int i = 1; i < basis.size(); i++) {
Attribute<Double> p = (Attribute<Double>) basis.get(i);
for (Attribute<Double> r : res) {
p = r.rectangular(p,add);
}
res.add(p);
}
return res;
}
/**
* 根据空间的一组基生成空间的一组标准正交基
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Number> List<Attribute<Double>> orthonormalBasis(List<Attribute<T>> basis, Addr<T> addr) {
List<Attribute<Double>> bas = gramSchmidtProcess(basis,addr);
Addr<Double> add = (Addr<Double>) addr;
List<Attribute<Double>> res = bas.stream().map(vec -> vec.normalize(add))
.collect(Collectors.toList());
return res;
}
/**
* 由一组标准正交基生成一个标准正交矩阵
* @param basis 标准正交基
* @return
*/
public static Ranks<Double> orthonormalMatrix(List<Attribute<Double>> basis) {
Double[][] values = new Double[basis.get(0).len()][basis.size()];
for (int i = 0; i < basis.get(0).len(); i++) {
for (int j = 0; j < basis.size(); j++) {
values[i][j] = basis.get(j).get(i);
}
}
return new Matrix<>(values);
}
@Override
@SuppressWarnings("unchecked")
public Tuple<Ranks<Double>,Ranks<Double>> qr(Addr<T> addr) {
if (this.rowNum() != this.colNum()) {
throw new RuntimeException("矩阵必须为一个方阵");
}
if (this.rank(addr) != this.colNum()) {
throw new RuntimeException("矩阵的列向量必须线性无关");
}
List<Attribute<T>> basis = new ArrayList<>();
for (int i = 0; i < this.colNum(); i++) {
basis.add(this.colVector(i));
}
List<Attribute<Double>> sp = Matrix.orthonormalBasis(basis,addr);
Ranks<Double> Q = Matrix.orthonormalMatrix(sp);
Ranks<Double> source = (Ranks<Double>) this;
Addr<Double> add = (Addr<Double>) addr;
Ranks<Double> R = Q.trans().dot(source,add);
return new Tuple<>(Q,R);
}
/**
* 其他坐标系坐标转换标准坐标系坐标
* @param otherBasis 其他坐标系的一组基
* @param otherVector 其他坐标系的一个向量坐标
* @param <T>
* @return
*/
public static <T extends Number> Attribute<T> otherToStandard(List<Attribute<T>> otherBasis,
Attribute<T> otherVector,
Addr<T> addr) {
Ranks<T> matrix = buildColMatrix(otherBasis,addr);
return matrix.dot(otherVector,addr);
}
/**
* 标准坐标系坐标转换其他坐标系坐标
* @param otherBasis 其他坐标系的一组基
* @param vector 标准坐标系的一个向量坐标
* @param addr
* @param <T>
* @return
*/
public static <T extends Number> Attribute<T> standardToOther(List<Attribute<T>> otherBasis,
Attribute<T> vector,
Addr<T> addr) {
Ranks<T> matrix = buildColMatrix(otherBasis,addr);
return matrix.invFunc(addr).dot(vector,addr);
}
/**
* 一个坐标系坐标转换另一个坐标系坐标
* @param basis 第一个坐标系的一组基
* @param anotherBasis 另一个坐标系的一组基
* @param vector 第一个坐标系的一个向量坐标
* @param addr
* @param <T>
* @return
*/
public static <T extends Number> Attribute<T> oneToAnother(List<Attribute<T>> basis,
List<Attribute<T>> anotherBasis,
Attribute<T> vector,
Addr<T> addr) {
Attribute<T> standardVector = otherToStandard(basis,vector,addr);
return standardToOther(anotherBasis,standardVector,addr);
}
/**
* 根据空间的一组基建立一个列向量矩阵
* @param basis 空间的一组基
* @param addr
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
private static <T extends Number> Ranks<T> buildColMatrix(List<Attribute<T>> basis,Addr<T> addr) {
T[][] values = (T[][]) new Number[basis.get(0).len()][basis.size()];
for (int i = 0; i < basis.get(0).len(); i++) {
for (int j = 0; j < basis.size(); j++) {
values[i][j] = basis.get(j).get(i);
}
}
Ranks<T> matrix = new Matrix<>(values);
if (matrix.rowNum() != matrix.colNum()) {
throw new IllegalArgumentException("矩阵必须为一个方阵");
}
if (matrix.rank(addr) != basis.size()) {
throw new IllegalArgumentException("列表中的向量并非空间的一组基");
}
return matrix;
}
@Override
@SuppressWarnings("unchecked")
public Matrix clone() throws CloneNotSupportedException {
T[][] values = (T[][])new Number[this.rowNum()][this.colNum()];
for (int i = 0; i < rowNum(); i++) {
values[i] = Arrays.copyOf(this.values[i],this.colNum());
}
return new Matrix(values);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws CloneNotSupportedException {
Ranks<Integer> matrix = new Matrix<>(new Integer[][]{{1,2,3},{3,4,5}});
System.out.println(matrix);
System.out.println(Arrays.toString(matrix.shape()));
System.out.println(matrix.rowNum());
System.out.println(matrix.colNum());
System.out.println(matrix.size());
System.out.println(matrix.get(4));
System.out.println(matrix.get(new int[]{0,0}));
System.out.println(matrix.rowVector(1));
System.out.println(matrix.colVector(2));
Ranks<Integer> matrix1 = new Matrix<>(new Integer[][]{{7,8,9},{10,20,30}});
Addr<Integer> addr = new Addr<Integer>() {
@Override
public Integer zero() {
return 0;
}
@Override
public Integer one() {
return 1;
}
@Override
public Integer add(Integer lhs, Integer rhs) {
return lhs + rhs;
}
@Override
public Integer sub(Integer lhs, Integer rhs) {
return lhs - rhs;
}
@Override
public Integer mul(Integer k, Integer hs) {
return k * hs;
}
@Override
public Integer square(Integer hs) {
return hs * hs;
}
@Override
public double prescription(Integer hs) {
return Math.sqrt(hs);
}
@Override
public double div(Integer hs, double nhs) {
return hs / nhs;
}
@Override
public Integer div(Integer hs, Integer nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Integer lhs, Integer rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Integer lhs, Integer rhs) {
return lhs == rhs;
}
@Override
public Integer neg(Integer hs) {
return -hs;
}
};
System.out.println(matrix.trans());
Ranks<Integer> copy = ((Matrix)matrix).clone();
Attribute<Integer> vector = new Vector<>(new Integer[]{9,33,97});
Ranks<Integer> matrix2 = new Matrix<>(new Integer[][]{{7,9},{11,33},{42,97}});
//[(1,2,3),(3,4,5)]*(23,65,79)
System.out.println(matrix.dot(vector,addr));
// [(1,2,3),(3,4,5)]*[(7,9),(11,33),(42,97)]
System.out.println(matrix.dot(matrix2,addr));
Ranks<Integer> copy1 = ((Matrix)matrix).clone();
System.out.println(matrix.add(matrix1,addr));
System.out.println(matrix1.sub(copy,addr));
System.out.println(copy.div(2,addr));
System.out.println(copy.pos(addr,1));
System.out.println(copy.neg(addr,-1));
System.out.println(copy1.mul(3,addr));
System.out.println(Matrix.zero(2,3,addr));
Ranks<Integer> I = Matrix.identity(4, addr);
System.out.println(I);
Matrix<Integer> idenTest = new Matrix<>(new Integer[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
System.out.println(idenTest.dot(I,addr));
System.out.println(I.dot(idenTest,addr));
Addr<Double> addr1 = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> A = new Matrix<>(new Double[][]{{1.0,2.0},{3.0,4.0}});
System.out.println(A.invFunc(addr1));
System.out.println(A.invMatrix(addr1));
Ranks<Integer> B = new Matrix<>(new Integer[][]{{1,2,3},{4,5,6},{3,-3,5}});
Tuple<Ranks<Integer>,Ranks<Integer>> lu = B.lu(addr);
Ranks<Integer> L = lu.getField(0);
System.out.println(L);
Ranks<Integer> U = lu.getField(1);
System.out.println(U);
System.out.println(L.dot(U,addr));
Ranks<Integer> N = new Matrix<>(new Integer[][]{{2,0,0},{-1,0,0},{0,0,1}});
System.out.println(N.rank(addr));
System.out.println(N.rowBase(addr));
System.out.println(N.colBase(addr));
System.out.println(N.dimensionNullSpace(addr));
System.out.println(N.nullBase(addr));
Ranks<Integer> M = new Matrix<>(new Integer[][]{{-1,2,3},{1,-4,-13},{-3,5,4}});
System.out.println(M.rank(addr));
System.out.println(M.rowBase(addr));
System.out.println(M.colBase(addr));
System.out.println(M.dimensionNullSpace(addr));
System.out.println(M.nullBase(addr));
Ranks<Double> F = new Matrix<>(new Double[][]{{1.0,2.0,3.0,4.0,5.0,6.0},
{27.0,28.0,29.0,30.0,31.0,32.0},{15.0,16.0,17.0,18.0,19.0,20.0},
{31.0,32.0,33.0,34.0,35.0,36.0}, {45.0,46.0,47.0,48.0,49.0,50.0}});
System.out.println(F.rank(addr1));
System.out.println(F.trans());
System.out.println(F.trans().rank(addr1));
System.out.println(F.rowBase(addr1));
System.out.println(F.colBase(addr1));
System.out.println(F.dimensionNullSpace(addr1));
System.out.println(F.nullBase(addr1));
System.out.println(F.dimensionLeftNullSpace(addr1));
System.out.println(F.leftNullBase(addr1));
List<Attribute<Double>> basis = Arrays.asList(new Vector<>(new Double[]{2.0,1.0}),
new Vector<>(new Double[]{1.0,1.0}));
System.out.println(Matrix.gramSchmidtProcess(basis,addr1));
System.out.println(Matrix.orthonormalBasis(basis,addr1));
Ranks<Double> orthonormalMatrix = Matrix.orthonormalMatrix(Matrix.orthonormalBasis(basis,addr1));
System.out.println(orthonormalMatrix);
System.out.println(orthonormalMatrix.dot(orthonormalMatrix.trans(),addr1));
Ranks<Double> A1 = new Matrix<>(new Double[][]{{1.0,1.0,2.0},{1.0,1.0,0.0},
{1.0,0.0,0.0}});
Tuple<Ranks<Double>,Ranks<Double>> qr = A1.qr(addr1);
Ranks<Double> Q = qr.getField(0);
Ranks<Double> R = qr.getField(1);
System.out.println(Q);
System.out.println(R);
System.out.println(Q.dot(R,addr1));
List<Attribute<Double>> otherBasis = Arrays.asList(new Vector<>(new Double[]{4.0,1.0}),
new Vector<>(new Double[]{2.0,3.0}));
Attribute<Double> otherVector = new Vector<>(new Double[]{2.0,2.0});
Attribute<Double> vectorStard = Matrix.otherToStandard(otherBasis,otherVector,addr1);
System.out.println(vectorStard);
System.out.println(Matrix.standardToOther(otherBasis,vectorStard,addr1));
List<Attribute<Double>> anotherBasis = Arrays.asList(new Vector<>(new Double[]{1.0,3.0}),
new Vector<>(new Double[]{2.0,4.0}));
Attribute<Double> vectorAnother = Matrix.oneToAnother(otherBasis,anotherBasis,otherVector,addr1);
System.out.println(vectorAnother);
System.out.println(Matrix.otherToStandard(anotherBasis,vectorAnother,addr1));
}
}
运行结果
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
[2, 3]
2
3
6
4
1
Vector{values=[3, 4, 5]}
Vector{values=[3, 5]}
Matrix{values=[[1, 3],[2, 4],[3, 5]]}
Vector{values=[366, 644]}
Matrix{values=[[155, 366],[275, 644]]}
Matrix{values=[[8, 10, 12],[13, 24, 35]]}
Matrix{values=[[6, 6, 6],[7, 16, 25]]}
Matrix{values=[[0.5, 1.0, 1.5],[1.5, 2.0, 2.5]]}
Matrix{values=[[1, 2, 3],[3, 4, 5]]}
Matrix{values=[[-1, -2, -3],[-3, -4, -5]]}
Matrix{values=[[3, 6, 9],[9, 12, 15]]}
Matrix{values=[[0, 0, 0],[0, 0, 0]]}
Matrix{values=[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.49999999999999994]]}
Matrix{values=[[-1.9999999999999996, 0.9999999999999998],[1.4999999999999998, -0.4999999999999999]]}
Matrix{values=[[1, 0, 0],[4, 1, 0],[3, 3, 1]]}
Matrix{values=[[1, 2, 3],[0, -3, -6],[0, 0, 14]]}
Matrix{values=[[1, 2, 3],[4, 5, 6],[3, -3, 5]]}
2
[Vector{values=[1, 0, 0]}, Vector{values=[0, 0, 1]}]
[Vector{values=[2, -1, 0]}, Vector{values=[0, 0, 1]}]
1
[Vector{values=[0, 1, 0]}]
2
[Vector{values=[1, 0, 7]}, Vector{values=[0, 1, 5]}]
[Vector{values=[-1, 1, -3]}, Vector{values=[2, -4, 5]}]
1
[Vector{values=[-7, -5, 1]}]
2
Matrix{values=[[1.0, 27.0, 15.0, 31.0, 45.0],[2.0, 28.0, 16.0, 32.0, 46.0],[3.0, 29.0, 17.0, 33.0, 47.0],[4.0, 30.0, 18.0, 34.0, 48.0],[5.0, 31.0, 19.0, 35.0, 49.0],[6.0, 32.0, 20.0, 36.0, 50.0]]}
2
[Vector{values=[1.0, 0.0, -0.9999999999999993, -1.9999999999999998, -3.0, -3.9999999999999996]}, Vector{values=[0.0, 1.0, 1.9999999999999998, 3.0, 4.0, 5.0]}]
[Vector{values=[1.0, 27.0, 15.0, 31.0, 45.0]}, Vector{values=[2.0, 28.0, 16.0, 32.0, 46.0]}]
4
[Vector{values=[0.9999999999999993, -1.9999999999999998, 1.0, 0.0, 0.0, 0.0]}, Vector{values=[1.9999999999999998, -3.0, 0.0, 1.0, 0.0, 0.0]}, Vector{values=[3.0, -4.0, 0.0, 0.0, 1.0, 0.0]}, Vector{values=[3.9999999999999996, -5.0, 0.0, 0.0, 0.0, 1.0]}]
3
[Vector{values=[-0.4615384615384621, -0.5384615384615384, 1.0, 0.0, 0.0]}, Vector{values=[0.1538461538461533, -1.1538461538461537, 0.0, 1.0, 0.0]}, Vector{values=[0.6923076923076898, -1.692307692307692, 0.0, 0.0, 1.0]}]
[Vector{values=[2.0, 1.0]}, Vector{values=[-0.19999999999999996, 0.4]}]
[Vector{values=[0.8944271909999159, 0.4472135954999579]}, Vector{values=[-0.4472135954999579, 0.8944271909999159]}]
Matrix{values=[[0.8944271909999159, -0.4472135954999579],[0.4472135954999579, 0.8944271909999159]]}
Matrix{values=[[0.9999999999999999, 0.0],[0.0, 0.9999999999999999]]}
Matrix{values=[[0.5773502691896258, 0.4082482904638628, 0.7071067811865475],[0.5773502691896258, 0.4082482904638628, -0.7071067811865476],[0.5773502691896258, -0.8164965809277263, 0.0]]}
Matrix{values=[[1.7320508075688776, 1.1547005383792517, 1.1547005383792517],[-6.661338147750939E-16, 0.8164965809277256, 0.8164965809277256],[-1.1102230246251565E-16, -1.1102230246251565E-16, 1.414213562373095]]}
Matrix{values=[[0.9999999999999999, 0.9999999999999997, 1.9999999999999996],[1.0, 0.9999999999999999, -2.220446049250313E-16],[1.0000000000000007, 3.3306690738754696E-16, 3.3306690738754696E-16]]}
Vector{values=[12.0, 8.0]}
Vector{values=[1.9999999999999996, 2.0]}
Vector{values=[-15.999999999999995, 13.999999999999996]}
Vector{values=[11.999999999999998, 8.0]}
Python代码
from .Vector import Vector
from ._global import is_zero
class Matrix:
def __init__(self, list2d):
if isinstance(list2d[0], list):
self._values = [row[:] for row in list2d]
elif isinstance(list2d[0], Vector):
self._values = [row.underlying_list() for row in list2d]
@classmethod
def zero(cls, r, c):
# 返回一个r行c列的零矩阵
return cls([[0] * c for _ in range(r)])
@classmethod
def identity(cls, n):
# 返回一个n行n列的单位矩阵
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 1
return cls(m)
def trans(self):
# 返回矩阵的转置矩阵
return Matrix([[e for e in self.col_vector(i)]
for i in range(self.col_num())])
def inv_func(self):
# 返回矩阵的逆
from .LinearSystemFunc import LinearSystemFunc
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemFunc(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab]
return Matrix(invA)
def inv_matrix(self):
# 返回矩阵的逆
from .LinearSystemMatrix import LinearSystemMatrix
if self.row_num() != self.col_num():
return None
n = self.row_num()
ls = LinearSystemMatrix(self, Matrix.identity(n))
if not ls.gauss_jordan_elimination():
return None
invA = [[row[i] for i in range(n, 2 * n)] for row in ls.Ab._values]
return Matrix(invA)
def lu(self):
# 方阵的LU分解
assert self.row_num() == self.col_num(), "矩阵必须为方阵"
n = self.row_num()
A = [self.row_vector(i) for i in range(n)]
L = [[1 if i == j else 0 for i in range(n)] for j in range(n)]
for i in range(n):
# 看A[i][i]位置是否可以为主元
if is_zero(A[i][i]):
return None, None
else:
for j in range(i + 1, n):
p = A[j][i] / A[i][i]
A[j] = A[j] - p * A[i]
L[j][i] = p
return Matrix(L), Matrix([A[i].underlying_list() for i in range(n)])
def rank(self):
# 矩阵的秩
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return sum([row != zero for row in ls.Ab])
def row_base(self):
# 行空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero = Vector.zero(self.col_num() + 1)
return [new_row for new_row in [Vector(row[:self.col_num()]) for row in ls.Ab if row != zero]]
def col_base(self):
# 列空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
return [self.col_vector(i) for i in ls.pivots]
def dimension_null_space(self):
# 零空间的维度
return self.col_num() - self.rank()
def null_base(self):
# 零空间的一组基
from .LinearSystemFunc import LinearSystemFunc
zero = Vector.zero(self.row_num())
ls = LinearSystemFunc(self, zero)
ls.gauss_jordan_elimination()
zero_base_list = []
for i in range(self.col_num()):
if i not in ls.pivots:
temp = Vector.zero(self.col_num()).underlying_list()
col = Matrix(ls.Ab).col_vector(i)
for j in range(len(temp)):
if j < len(col) and not(is_zero(col[j])):
temp[j] = -col[j]
if i == j:
temp[j] = 1
zero_base_list.append(temp)
return [Vector(item) for item in zero_base_list]
def dimension_left_null_space(self):
# 左零空间的维度
return self.row_num() - self.rank()
def left_null_base(self):
# 左零空间的一组基
return self.trans().null_base()
@classmethod
def gram_schmidt_process(cls, basis):
# 根据空间的一组基生成空间的一组正交基
matrix = Matrix(basis)
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
res = [basis[0]]
for i in range(1, len(basis)):
p = basis[i]
for r in res:
p = r.rectangular(p)
res.append(p)
return res
@classmethod
def orthonormal_basis(cls, basis):
# 根据空间的一组基生成空间的一组标准正交基
bas = cls.gram_schmidt_process(basis)
return [row.normalize() for row in bas]
@classmethod
def orthonormal_matrix(cls, basis):
# 由一组标准正交基生成一个标准正交矩阵
return Matrix([[basis[i][j] for i in range(len(basis[0]))] for j in range(len(basis))])
def qr(self):
# 矩阵的QR分解
assert self.row_num() == self.col_num(), \
"矩阵必须为一个方阵"
assert self.rank() == self.col_num(), \
"矩阵的列向量必须线性无关"
basis = [self.col_vector(i) for i in range(self.col_num())]
sp = Matrix.orthonormal_basis(basis)
Q = Matrix.orthonormal_matrix(sp)
R = Q.trans().dot(self)
return Q, R
@classmethod
def _build_col_matrix(cls, basis):
# 根据空间的一组基建立一个列向量矩阵
matrix = Matrix([[basis[i][j] for i in range(len(basis[0]))] for j in range(len(basis))])
assert matrix.row_num() == matrix.col_num(), \
"矩阵必须为一个方阵"
assert matrix.rank() == len(basis), \
"列表中的向量并非空间的一组基"
return matrix
@classmethod
def other_to_standard(cls, other_basis, other_vector):
# 其他坐标系坐标转换标准坐标系坐标
matrix = cls._build_col_matrix(other_basis)
return matrix.dot(other_vector)
@classmethod
def standard_to_other(cls, other_basis, vector):
# 标准坐标系坐标转换其他坐标系坐标
matrix = cls._build_col_matrix(other_basis)
return matrix.inv_func().dot(vector)
@classmethod
def one_to_another(cls, basis, another_basis, vector):
# 一个坐标系坐标转换另一个坐标系坐标
standard_vector = cls.other_to_standard(basis, vector)
return cls.standard_to_other(another_basis, standard_vector)
def __add__(self, another):
# 返回两个矩阵的加法结果
assert self.shape() == another.shape(), \
"加法错误,两个矩阵的形状必须相同"
return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def __sub__(self, another):
# 返回两个矩阵的减法结果
assert self.shape() == another.shape(), \
"减法错误,两个矩阵的形状必须相同"
return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
for i in range(self.row_num())])
def dot(self, another):
if isinstance(another, Vector):
# 矩阵和向量的乘法
assert self.col_num() == len(another), \
"矩阵列数需要与向量的长度相等"
return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
if isinstance(another, Matrix):
# 矩阵和矩阵的乘法
assert self.col_num() == another.row_num(), \
"当前矩阵列数必须等于点乘矩阵行数"
return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
for i in range(self.row_num())])
def __mul__(self, k):
# 返回矩阵的数量乘结果: self * k
return Matrix([[e * k for e in self.row_vector(i)]
for i in range(self.row_num())])
def __rmul__(self, k):
# 返回矩阵的数量乘结果: k * self
return self * k
def __truediv__(self, k):
# 返回数量除法的结果矩阵: self / k
return (1 / k) * self
def __pos__(self):
# 返回矩阵取正的结果
return 1 * self
def __neg__(self):
# 返回矩阵取负的结果
return -1 * self
def row_vector(self, index):
# 返回矩阵的第index个行向量
return Vector(self._values[index])
def col_vector(self, index):
# 返回矩阵的第index个列向量
return Vector([row[index] for row in self._values])
def __getitem__(self, pos):
# 返回矩阵pos位置的元素
r, c = pos
return self._values[r][c]
def __setitem__(self, pos, value):
# 设置pos位置的元素
r, c = pos
self._values[r][c] = value
def size(self):
# 返回矩阵中元素的个数
r, c = self.shape()
return r * c
def row_num(self):
# 返回矩阵的行数
return self.shape()[0]
__len__ = row_num
def col_num(self):
# 返回矩阵的列数
return self.shape()[1]
def shape(self):
# 返回矩阵的形状:(行数,列数)
return len(self._values), len(self._values[0])
def __repr__(self):
return "Matrix({})".format(self._values)
__str__ = __repr__
from playLA.Matrix import Matrix
from playLA.Vector import Vector
if __name__ == "__main__":
matrix = Matrix([[1, 2, 3], [3, 4, 5]])
print(matrix)
print("matrix.shape = {}".format(matrix.shape()))
print("matrix.size = {}".format(matrix.size()))
print("len(matrix) = {}".format(len(matrix)))
print("matrix[0][0] = {}".format(matrix[0, 0]))
print(matrix.row_vector(1))
print(matrix.col_vector(0))
matrix2 = Matrix([[7, 8, 9], [10, 20, 30]])
print("add: {}".format(matrix + matrix2))
print("subtract: {}".format(matrix2 - matrix))
print("scalar-mul: {}".format(matrix * 3))
print("scalar-mul: {}".format(3 * matrix))
print("zero_2_3: {}".format(Matrix.zero(2, 3)))
vec = Vector([23, 65, 79])
print("matrix.dot(vec) = {}".format(matrix.dot(vec)))
matrix3 = Matrix([[7, 9], [11, 33], [42, 97]])
print("matrix.dot(matrix3) = {}".format(matrix.dot(matrix3)))
print("matrix.trans = {}".format(matrix.trans()))
I = Matrix.identity(4)
print(I)
idenTest = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
print(idenTest.dot(I))
print(I.dot(idenTest))
A = Matrix([[1, 2], [3, 4]])
print(A.inv_func())
print(A.inv_matrix())
B = Matrix([[1, 2, 3], [4, 5, 6], [3, -3, 5]])
L, U = B.lu()
print(L)
print(U)
print(L.dot(U))
N = Matrix([[2, 0, 0], [-1, 0, 0], [0, 0, 1]])
print(N.rank())
print(N.row_base())
print(N.col_base())
print(N.dimension_null_space())
print(N.null_base())
M = Matrix([[-1, 2, 3], [1, -4, -13], [-3, 5, 4]])
print(M.rank())
print(M.row_base())
print(M.col_base())
print(M.dimension_null_space())
print(M.null_base())
F = Matrix([[1, 2, 3, 4, 5, 6], [27, 28, 29, 30, 31, 32], [15, 16, 17, 18, 19, 20],
[31, 32, 33, 34, 35, 36], [45, 46, 47, 48, 49, 50]])
print(F.rank())
print(F.row_base())
print(F.col_base())
print(F.dimension_null_space())
print(F.null_base())
print(F.dimension_left_null_space())
print(F.left_null_base())
basis = [Vector([2, 1]), Vector([1, 1])]
res = Matrix.gram_schmidt_process(basis)
print(res)
res = Matrix.orthonormal_basis(basis)
print(res)
orthonormal_matrix = Matrix.orthonormal_matrix(res)
print(orthonormal_matrix)
print(orthonormal_matrix.dot(orthonormal_matrix.trans()))
A1 = Matrix([[1, 1, 2], [1, 1, 0], [1, 0, 0]])
Q, R = A1.qr()
print(Q)
print(R)
print(Q.dot(R))
other_basis = [Vector([4, 1]), Vector([2, 3])]
other_vector = Vector([2, 2])
vector_stard = Matrix.other_to_standard(other_basis, other_vector)
print(vector_stard)
print(Matrix.standard_to_other(other_basis, vector_stard))
another_basis = [Vector([1, 3]), Vector([2, 4])]
vector_another = Matrix.one_to_another(other_basis, another_basis, other_vector)
print(vector_another)
print(Matrix.other_to_standard(another_basis, vector_another))
运行结果
Matrix([[1, 2, 3], [3, 4, 5]])
matrix.shape = (2, 3)
matrix.size = 6
len(matrix) = 2
matrix[0][0] = 1
(3, 4, 5)
(1, 3)
add: Matrix([[8, 10, 12], [13, 24, 35]])
subtract: Matrix([[6, 6, 6], [7, 16, 25]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
scalar-mul: Matrix([[3, 6, 9], [9, 12, 15]])
zero_2_3: Matrix([[0, 0, 0], [0, 0, 0]])
matrix.dot(vec) = (390, 724)
matrix.dot(matrix3) = Matrix([[155, 366], [275, 644]])
matrix.trans = Matrix([[1, 3], [2, 4], [3, 5]])
Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[-1.9999999999999996, 0.9999999999999998], [1.4999999999999998, -0.4999999999999999]])
Matrix([[1, 0, 0], [4.0, 1, 0], [3.0, 3.0, 1]])
Matrix([[1, 2, 3], [0.0, -3.0, -6.0], [0.0, 0.0, 14.0]])
Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [3.0, -3.0, 5.0]])
2
[Vector([1.0, 0.0, 0.0]), Vector([0.0, 0.0, 1.0])]
[Vector([2, -1, 0]), Vector([0, 0, 1])]
1
[Vector([0, 1, 0])]
2
[Vector([1.0, 0.0, 7.0]), Vector([-0.0, 1.0, 5.0])]
[Vector([-1, 1, -3]), Vector([2, -4, 5])]
1
[Vector([-7.0, -5.0, 1])]
2
[Vector([1.0, 0.0, -1.0000000000000007, -2.0000000000000018, -3.0000000000000013, -4.000000000000002]), Vector([0.0, 1.0, 2.0000000000000004, 3.000000000000001, 4.000000000000001, 5.000000000000002])]
[Vector([1, 27, 15, 31, 45]), Vector([2, 28, 16, 32, 46])]
4
[Vector([1.0000000000000007, -2.0000000000000004, 1, 0, 0, 0]), Vector([2.0000000000000018, -3.000000000000001, 0, 1, 0, 0]), Vector([3.0000000000000013, -4.000000000000001, 0, 0, 1, 0]), Vector([4.000000000000002, -5.000000000000002, 0, 0, 0, 1])]
3
[Vector([-0.4615384615384617, -0.5384615384615384, 1, 0, 0]), Vector([0.1538461538461533, -1.1538461538461537, 0, 1, 0]), Vector([0.6923076923076934, -1.6923076923076923, 0, 0, 1])]
[Vector([2, 1]), Vector([-0.19999999999999996, 0.4])]
[Vector([0.8944271909999159, 0.4472135954999579]), Vector([-0.44721359549995787, 0.894427190999916])]
Matrix([[0.8944271909999159, -0.44721359549995787], [0.4472135954999579, 0.894427190999916]])
Matrix([[0.9999999999999999, 0.0], [0.0, 1.0000000000000002]])
Matrix([[0.5773502691896258, 0.4082482904638628, 0.7071067811865475], [0.5773502691896258, 0.4082482904638628, -0.7071067811865476], [0.5773502691896258, -0.8164965809277263, 0.0]])
Matrix([[1.7320508075688776, 1.1547005383792517, 1.1547005383792517], [-6.661338147750939e-16, 0.8164965809277256, 0.8164965809277256], [-1.1102230246251565e-16, -1.1102230246251565e-16, 1.414213562373095]])
Matrix([[0.9999999999999999, 0.9999999999999997, 1.9999999999999996], [1.0, 0.9999999999999999, -2.220446049250313e-16], [1.0000000000000007, 3.3306690738754696e-16, 3.3306690738754696e-16]])
(12, 8)
(1.9999999999999996, 2.0)
(-15.999999999999995, 13.999999999999996)
(11.999999999999998, 8.0)
线性变换
一般说变换,指的是一个函数,一个变换T(x)称为线性变换,必须满足两个条件:
,对于两个向量加起来做变换就等于分别对两个向量做变换再相加
其中R为实数,对于一个向量与实数相乘做变换等于先将这个向量做变换再做数量乘法
我们可以把矩阵看作是是向量的函数
,矩阵所表示的变换,均为线性变换
证明:
这是通过满足线性变换的两个条件来直接证明的,因此得证
一个矩阵,既可以看作是空间(我们把空间的一组基当作矩阵的列向量排列起来,这个矩阵就可以代表空间,这个矩阵也可以代表这个空间的坐标系,以完成坐标系的转换工作),可以看作是变换(可以对一个点集的变换,从而完成一个图形或者是图像的变换),其实这两个视角是等价的,空间就是变换,变换就是空间。不同的空间对应着不同的基,对应着不同的坐标系,进行矩阵乘法就可以看作是不同的基之间的变换,反过来不同的变换肯定也就对应着不同的基和不同的坐标系。
所有的矩阵都可以用来表示一个线性变换,用矩阵表示空间的视角和用矩阵表示变换的视角是等价的。
我们之前的坐标转换都是在同等维度上的转换,它的主要应用在二维和三维动画中
但也有不同维度空间的转换,比如3D的静态图像,3D空间转换到2D空间
这个话题本身也是图形学领域要处理的一个非常重要的话题,我们可以专门到图形学专门的教程中去了解它的解决方案,但是它背后所用到的线性代数的知识就是这样的一个坐标转换。
从低维空间向高维空间的转换也是非常有意义的,比如计算机视觉,比方说一张二维的照片,它里面蕴含了很多三维的信息
比如说这张图片,哪个球离我们更近,远处的人哪个更高。这些就是计算机视觉,虽然它离图像学的关系非常近,不过计算机视觉已经是一个单独的领域。它背后的原理依然是将二维空间映射到三维空间中去提取那个三维空间的信息。所以线性代数可以帮我们更好的进入这些领域,是一个基础。
同维度空间转换的应用:压缩
在机器学习领域,很多时候我们都需要对数据进行压缩处理。这是因为海量的数据直接扔进我们的算法中,它们的计算速度太慢,不仅如此,还有可能最终计算出来的效果并不理想
比方说在黑色坐标系中的每一个蓝色数据点,它们都保持着两个维度的信息,但如果我们找到了一个红色坐标系,经过坐标变换,使得这些蓝色的点的Y轴的数值都很小,这样我们只需要保留这个红色坐标系的X轴的信息,相应的Y轴的坐标,我们直接丢弃,这样信息量就被压缩了一倍。在高维空间中更是如此,现在的摄像头的分辨率越来越高,一张照片动辄就好几M,如果海量的照片的存储量就非常大。这其实是因为每张照片的维度都非常高,每个点上都有RGB的信息,点数也是千万级别的,我们的每一个数据点都在极高的维度上,我们可以找到这个高维空间相应的另外一组基,看在这组基上,看在很多坐标轴上相应的数是不是都特别的小,我们就可以在这些坐标轴上相应的信息给扔掉,这样一来就实现了整个压缩过程,其实这就是压缩的基本原理。它的本质就是一个坐标系的转换,就是一个基变换。
很多压缩算法的本质就是找一组基!比如我们常见的JPEG图片,它背后就是这样的一个压缩算法。不同的算法找的基是不一样的。比如傅立叶变换和小波变换,它们都可以用来找这样的一组基。只不过找的基不同,给我们提供的信息就会不同,对于不同的目的,需要找出不同的基。