/// <summary> /// 各ベクトルの相関を求める. /// </summary> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="target"></param> /// <returns></returns> public static Matrix Correlate(Matrix X, Matrix Y, Target target) { MatrixChecker.SizeEquals(X, Y); Matrix ret = null; if (target == Target.EachRow) { ret = new Matrix(X.RowSize, X.RowSize); for (int ry = 0; ry < ret.RowSize; ++ry) { for (int rx = 0; rx < ret.ColumnSize; ++rx) { ret[ry, rx] = Correlate(Y.Rows[ry], X.Rows[rx]); } } } else { ret = new Matrix(X.ColumnSize, X.ColumnSize); for (int cy = 0; cy < ret.RowSize; ++cy) { for (int cx = 0; cx < ret.ColumnSize; ++cx) { ret[cy, cx] = Correlate(Y.Columns[cy], X.Columns[cx]); } } } return(ret); }
/// <summary> /// 逆行列を返す. /// </summary> /// <param name="m">逆行列を求める行列(書き換えられることはない)</param> /// <returns></returns> public static Matrix Inverse(Matrix m) { MatrixChecker.IsSquare(m); Solved result = Func.Solve(m, (new Matrix(m.RowSize, m.ColumnSize)).Identity()); return(result.X); }
/// <summary> /// 指定された行列の逆行列を作成する. /// </summary> /// <param name="X">逆行列を求める行列(書き換えられることはない)</param> /// <returns>Xの逆行列</returns> public static Matrix Inverse(Matrix X) { MatrixChecker.IsSquare(X); Solver solver = new Solver(X, (new Matrix(X.RowSize, X.ColumnSize)).Identity()); return(solver.X); }
/// <summary> /// 固有値分解 /// </summary> /// <param name="x">正方行列</param> /// <returns></returns> public static Eigen Eigen(Matrix x) { MatrixChecker.IsSquare(x); if (x.RowSize < 2) { throw new ArgumentException("Matrix size is less than 2."); } Matrix tmp = new Matrix(x); Vector _reValues = new Vector(); Vector _imValues = new Vector(); double[][] r_vecs = null; double[][] i_vecs = null; krdlab.law.func.dgeev(tmp._body, tmp._rsize, tmp._csize, ref _reValues._body, ref _imValues._body, ref r_vecs, ref i_vecs); List <Vector> _reVectors = new List <Vector>(); List <Vector> _imVectors = new List <Vector>(); foreach (double[] vec in r_vecs) { _reVectors.Add(new Vector(vec)); } foreach (double[] vec in i_vecs) { _imVectors.Add(new Vector(vec)); } return(new Eigen(_reValues, _imValues, _reVectors, _imVectors)); }
/// <summary> /// 直接スカラ値で除算する. /// <code>this /= d;</code> を表しているが,代入演算子のように結果オブジェクトが生成されることはない. /// </summary> /// <param name="d">スカラ値</param> /// <returns>除算後の自身への参照</returns> /// <exception cref="Exception.ValueIsLessThanLimitException"> /// 指定されたスカラ値が,ライブラリで扱う値の下限値未満である場合に throw される. /// </exception> public Matrix Div(double d) { MatrixChecker.ValueIsLessThanLimit(d); for (int i = 0; i < this._body.Length; ++i) { this._body[i] /= d; } return(this); }
/// <summary> /// Matrixオブジェクトを直接減算する. /// <code>this -= m;</code> を表しているが,代入演算子のように結果オブジェクトが生成されることはない. /// </summary> /// <param name="m">減算するMatrixオブジェクト</param> /// <returns>減算後の自身への参照</returns> /// <exception cref="Exception.MismatchSizeException"> /// 行列のサイズが一致しなかった場合に throw される. /// </exception> public Matrix Sub(Matrix m) { MatrixChecker.SizeEquals(this, m); for (int i = 0; i < this._body.Length; ++i) { this._body[i] -= m._body[i]; } return(this); }
/// <summary> /// 行ベクトルと行列の乗算 /// </summary> /// <param name="rv">行ベクトル</param> /// <param name="m">行列</param> /// <returns>乗算結果の行ベクトル</returns> public static RowVector operator *(RowVector rv, Matrix m) { MatrixChecker.CanMultiply(rv, m); RowVector ret = new RowVector(); clapack.Function.dgemv(ref ret._body, rv._body, m._body, m._rsize, m._csize); return(ret); }
/// <summary> /// 行列と列ベクトルの乗算 /// </summary> /// <param name="m">行列</param> /// <param name="cv">列ベクトル</param> /// <returns>乗算結果の列ベクトル</returns> public static ColumnVector operator *(Matrix m, ColumnVector cv) { MatrixChecker.CanMultiply(m, cv); ColumnVector ret = new ColumnVector(); clapack.Function.dgemv(ref ret._body, m._body, m._rsize, m._csize, cv._body); return(ret); }
/// <summary> /// 行ベクトルと行列の乗算 /// </summary> /// <param name="rv">行ベクトル</param> /// <param name="m">行列</param> /// <returns>乗算結果の行ベクトル</returns> public static RowVector operator *(RowVector rv, Matrix m) { MatrixChecker.CanMultiply(rv, m); RowVector ret = new RowVector(); krdlab.law.func.dgemv(ref ret._body, rv._body, m._body, m._rsize, m._csize); return(ret); }
/// <summary> /// この行列を単位行列(I = diag(1,1,...,1))にする. /// </summary> /// <returns></returns> public Matrix Identity() { MatrixChecker.IsSquare(this); this.Zero(); for (int i = 0; i < this.RowSize; ++i) { this[i, i] = 1; } return(this); }
/// <summary> /// AX = B を解く. /// </summary> /// <param name="a">[n, n] 行列</param> /// <param name="b">[n, *] 行列</param> /// <returns></returns> public static Solved Solve(Matrix a, Matrix b) { MatrixChecker.IsSquare(a); Matrix _a = new Matrix(a); Matrix _b = new Matrix(b); Matrix x = new Matrix(); krdlab.law.func.dgesv(ref x._body, ref x._rsize, ref x._csize, _a._body, _a._rsize, _a._csize, _b._body, _b._rsize, _b._csize); return(new Solved(x)); }
/// <summary> /// 行列どうしを乗算する. /// </summary> /// <param name="m1">左項となる行列</param> /// <param name="m2">右項となる行列</param> /// <returns>乗算結果の行列</returns> public static Matrix operator *(Matrix m1, Matrix m2) { MatrixChecker.CanMultiply(m1, m2); double[] ret = null; int rsize = 0; int csize = 0; clapack.Function.dgemm(ref ret, ref rsize, ref csize, m1._body, m1._rsize, m1._csize, m2._body, m2._rsize, m2._csize); return(new Matrix(ret, rsize, csize)); }
/// <summary> /// 逆行列化する. /// </summary> /// <returns>逆行列化後の自身への参照</returns> /// <exception cref="Exception.NotSquareMatrixException"> /// 正方行列でないときに throw される. /// </exception> public Matrix Inverse() { MatrixChecker.IsSquare(this); Matrix A = new Matrix(this); this.Identity(); clapack.Function.dgesv(ref this._body, ref this._rsize, ref this._csize, A._body, A._rsize, A._csize, this._body, this._rsize, this._csize); return(this); }
/// <summary> /// 逆行列化する. /// </summary> /// <returns>逆行列化後の自身への参照</returns> /// <exception cref="System.ArgumentException"> /// 正方行列でないときに throw される. /// </exception> public Matrix Inverse() { MatrixChecker.IsSquare(this); Matrix A = new Matrix(this); this.Identity(); krdlab.law.func.dgesv(ref this._body, ref this._rsize, ref this._csize, A._body, A._rsize, A._csize, this._body, this._rsize, this._csize); return(this); }
/// <summary> /// 指定されたベクトルから新しい行列を作成する. /// 指定された各ベクトルは,新しい行列の各列にコピーされる. /// </summary> /// <param name="arr"></param> public Matrix(params ColumnVector[] arr) { // 入力の検証 VectorChecker.IsNotZeroSize(arr[0]); int rsize = arr[0].Size; MatrixChecker.EqualAllSizes(rsize, arr); // 構築 int csize = arr.Length; Resize(rsize, csize); for (int c = 0; c < csize; ++c) { this.Columns[c] = arr[c]; } }
/// <summary> /// ベクトル配列から新しい行列を作成する. /// 指定された各ベクトルは,新しい行列の各行にコピーされる. /// </summary> /// <param name="arr"></param> public Matrix(params RowVector[] arr) { // 入力の検証 VectorChecker.IsNotZeroSize(arr[0]); int csize = arr[0].Size; MatrixChecker.EqualAllSizes(csize, arr); // 構築 int rsize = arr.Length; Resize(rsize, csize); for (int r = 0; r < rsize; ++r) { this.Rows[r] = arr[r]; } }
/// <summary> /// LU 分解 /// </summary> /// <param name="x"></param> /// <returns></returns> public static Lud Lud(Matrix x) { MatrixChecker.IsNotZeroSize(x); Matrix lu = new Matrix(x); int[] p = new int[0]; int zeroValueIndex = -1; int ret = krdlab.law.func.dgetrf(lu._body, lu._rsize, lu._csize, ref p); if (0 < ret) { zeroValueIndex = ret - 1; } // 置換行列を構成 /* * 配列 p には,例えば2行目と3行目が置換された場合に, * p = {1, 3, 3}; * ↑1回だけ発生したということが解る * と格納されている. */ int permutationCount = 0; Matrix _p = Matrix.Identity(lu.RowSize); // row==column, row < column の場合は p.Length == lu.RowSize // row > column の場合は p.Length < lu.RowSize // どうも下から入れ替えないといけないみたい // p[0] = 2 // p[1] = 1 // p[2] = 4 <- 「0と入れ替えた後の2と交換」なのか「入れ替える前の2と交換」なのか? => どうも後者のようだ for (int from = p.Length - 1; 0 <= from; --from) { int to = p[from]; if (0 <= to && from != to) { _p.Rows.Swap(from, to); //this.p[from, from] = this.p[to, to] = 0; //this.p[to, from] = 1; //this.p[from, to] = 1; if (to < p.Length && p[to] == from) { p[to] = -1; // 置換が完了していることを示すフラグ } // 置換が発生したときだけカウントアップ ++permutationCount; } } int minSize = Math.Min(lu.RowSize, lu.ColumnSize); Matrix _l = Matrix.Zero(lu.RowSize, minSize); Matrix _u = Matrix.Zero(minSize, lu.ColumnSize); // set L for (int r = 0; r < lu.RowSize; ++r) { for (int c = 0; c <= r; ++c) { if (_l.ColumnSize <= c) { break; } _l[r, c] = (r == c ? 1.0 : lu[r, c]); } } // set U for (int r = 0; r < _u.RowSize; ++r) { for (int c = r; c < lu.ColumnSize; ++c) { _u[r, c] = lu[r, c]; } } return(new Lud(_p, _l, _u, permutationCount, zeroValueIndex)); }