MatrixClass.dll には Matrix と Vector クラスが含まれています。
Vector クラスは実数のベクトル、Matrix クラスは実数の行列をモデル化したクラスです。
この DLL のソリューションエクスプローラは次の画像のようになっています。
クラスの定義
名前空間
MatrixClass
クラス
- Vector 実数のベクトル
- Matrix 実数の行列
Vector クラス
コンストラクタ
- Vector(int) パラメータで指定した長さの Vector オブジェクトを構築する。
- Vector(double[]) 配列を元に Vector オブジェクトを構築する。
プロパティ
- Length ベクトルの要素数 (読みのみ)
- this[int] 指定した位置の要素の値 (読み書き可能)
メソッド
- Zero() 要素をすべてゼロクリアする。
- Inv() 要素の符号をすべて反転する。
- ToArray() 配列に変換する(メソッドの戻り値として返す)
- ToString() 文字列表現を返す。
- Clone() クローンを作成してその参照を返す。
- Equals(object) オーバーライドメソッド。パラメータと比較して等しければ true、そうでなければ false を返す。
- Dot(Vector, Vector) スタティックメソッド。ベクトルの内積の値を返す。
演算子
- operator + (Vector, double[]) Vector と実数配列の和を求める。結果は実数配列。
- operator + (Vector, Vector) Vector と Vector の和を求める。結果は Vector。
- operator – (Vector, double[]) Vector と実数配列の差を求める。結果は実数配列。
- operator – (Vector, Vector) Vector と Vector の差を求める。結果は Vector。
- operator + (double, Vector) スカラーと Vector の掛け算を行う。結果は Vector。
Matrix クラス
コンストラクタ
- Matrix(int, int) 行と列を指定して Matrix オブジェクトを構築する。
- Matrix(double[ , ]) 2次元配列を元にして Matrix オブジェクトを構築する。
- Matrix(double[][]) 2次元ジャグ配列 (配列の配列) を元に Matrix オブジェクトを構築する。
プロパティ
- Size int[] で行数、列数を返す。
- this[int, int] 行、列で指定した要素の値。(読み書き可能)
メソッド
- Get(int, int) 行、列で指定した要素の値を返す。
- Set(int, int, double) 行、列で指定した要素の値を変更する。
- AppendRow(double[]) 行を追加する。追加後の行数を返す。
- GetRow(int) 指定した行を double[] で返す。
- GetColumn(int) 指定した列を double[] で返す。
- Zero() 行列の要素をすべてゼロクリアする。
- Inv() 行列の要素の符号をすべて反転する。
- Clone() この行列オブジェクトのクローンを作る。(新しい Matrix オブジェクトを返す)
- ToString() オーバーライドメソッド。文字列表現を返す。
- Equals(object) Matrix オブジェクトの要素がすべて等しいか判別する。等しい場合は true を返す。
演算子
- operator + (Matrix, Matrix) Matrix オブジェクトどうしの加算。結果は Matrix オブジェクト。
- operator – (Matrix, Matrix) Matrix オブジェクトどうしの減算。結果は Matrix オブジェクト。
- operator * (Matrix, Matrix) Matrix オブジェクトどうしの乗算。結果は Matrix オブジェクト。
- operator * (double, Matrix) スカラーとMatrix オブジェクトの乗算。結果は Matrix オブジェクト。
- operator * (Matrix, Vector) Matrix オブジェクトと Vector オブジェクトの乗算。結果は Vector オブジェクト。
ソースプログラム
using System;
using System.Text;
using System.Collections.Generic;
namespace MatrixClass
{
/// <summary>
/// ベクトルクラス (Vector)
/// </summary>
public class Vector
{
protected List<double> vector;
/// <summary>
/// 空のベクトルを作る。
/// </summary>
/// <param name="n"></param>
public Vector(int n)
{
vector = new List<double>();
for (int i = 0; i < n; i++)
{
vector.Add(0.0);
}
}
/// <summary>
/// 配列を元にベクトルを作る。
/// </summary>
/// <param name="a">配列</param>
public Vector(double[] a)
{
vector = new List<double>(a);
}
/// <summary>
/// 要素の数
/// </summary>
public int Length
{
get
{
return this.vector.Count;
}
}
/// <summary>
/// ゼロクリアする。
/// </summary>
public void Zero()
{
vector.ForEach((x) => { x = 0.0; });
}
/// <summary>
/// 符号を反転する。
/// </summary>
public void Inv()
{
vector.ForEach((x) => { x = -x; });
}
/// <summary>
/// 配列に変換する。
/// </summary>
/// <returns></returns>
public double[] ToArray()
{
return vector.ToArray();
}
/// <summary>
/// 文字列表現を返す。
/// </summary>
/// <returns></returns>
public override string ToString()
{
var sb = new StringBuilder();
foreach (double x in this.vector)
{
sb.Append(x);
sb.Append(" ");
}
return sb.ToString().Trim();
}
/// <summary>
/// クローンを作る。
/// </summary>
/// <returns>Vector のクローン</returns>
public Vector Clone()
{
var v = new Vector(this.Length);
for (int i = 0; i < this.Length; i++)
{
v[i] = this.vector[i];
}
return v;
}
/// <summary>
/// ベクトルの要素
/// </summary>
/// <param name="n">要素のインデックス</param>
/// <returns>要素の値</returns>
public double this[int n]
{
get
{
return this.vector[n];
}
set
{
this.vector[n] = value;
}
}
/// <summary>
/// ベクトルの加算 (Vector+Array)
/// </summary>
/// <param name="v">Vector オブジェクト</param>
/// <param name="a">配列</param>
/// <returns></returns>
public static double[] operator + (Vector v, double[] a)
{
var v2 = v.Clone();
for (int i = 0; i < a.Length; i++)
{
v2[i] = v[i] + a[i];
}
return v2.ToArray();
}
/// <summary>
/// ベクトルの加算 (Vector+Vector)
/// </summary>
/// <param name="v">Vector オブジェクト</param>
/// <param name="a">Vector オブジェクト</param>
/// <returns></returns>
public static Vector operator + (Vector v, Vector a)
{
var v2 = v.Clone();
for (int i = 0; i < a.Length; i++)
{
v2[i] = v[i] + a[i];
}
return v2;
}
/// <summary>
/// ベクトルの減算 (Vector-Array)
/// </summary>
/// <param name="v">Vector オブジェクト</param>
/// <param name="a">配列</param>
/// <returns></returns>
public static double[] operator -(Vector v, double[] a)
{
var v2 = v.Clone();
for (int i = 0; i < a.Length; i++)
{
v2[i] = v[i] - a[i];
}
return v2.ToArray();
}
/// <summary>
/// ベクトルの減算 (Vector-Vector)
/// </summary>
/// <param name="v">Vector オブジェクト</param>
/// <param name="a">Vector オブジェクト</param>
/// <returns></returns>
public static Vector operator -(Vector v, Vector a)
{
var v2 = v.Clone();
for (int i = 0; i < a.Length; i++)
{
v2[i] = v[i] - a[i];
}
return v2;
}
/// <summary>
/// スカラーとベクトルの積
/// </summary>
/// <param name="r">スカラー</param>
/// <param name="v">ベクトル</param>
/// <returns></returns>
public static Vector operator * (double r, Vector v)
{
var v2 = v.Clone();
for (int i = 0; i < v.Length; i++)
{
v2[i] *= r;
}
return v2;
}
/// <summary>
/// ベクトルの内積
/// </summary>
/// <param name="u">Vector オブジェクト</param>
/// <param name="v">Vector オブジェクト</param>
/// <returns>内積</returns>
public static double Dot(Vector u, Vector v)
{
double y = 0.0;
for (int i = 0; i < u.Length; i++)
{
y += u[i] * v[i];
}
return y;
}
/// <summary>
/// Vector どうしの比較
/// </summary>
/// <param name="obj">比較対象のベクトル</param>
/// <returns>等しいければ true</returns>
public override bool Equals(object obj)
{
var vec = obj as Vector;
if (vec.Length != this.Length)
{
return false;
}
for (int i = 0; i < this.Length; i++)
{
if (this[i] != vec[i])
{
return false;
}
}
return true;
}
/// <summary>
/// ハッシュコードを返す。
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
}
/// <summary>
/// 行列クラス (Matrix)
/// </summary>
public class Matrix
{
/// <summary>
/// 行列オブジェクト
/// </summary>
protected List<double[]> matrix;
/// <summary>
/// 空の行列を作る。
/// </summary>
/// <param name="m">行数</param>
/// <param name="n">列数</param>
public Matrix(int m, int n)
{
matrix = new List<double[]>();
for (int i = 0; i < m; i++)
{
matrix.Add(new double[n]);
}
}
/// <summary>
/// 2次元配列から行列を作る。
/// </summary>
/// <param name="a">元となる配列</param>
public Matrix(double[,] a)
{
matrix = new List<double[]>();
int m = a.GetLength(0);
int n = a.GetLength(1);
for (int i = 0; i < m; i++)
{
var v = new double[n];
for (int j = 0; j < n; j++)
{
v[j] = a[i, j];
}
matrix.Add(v);
}
}
/// <summary>
/// ジャグ配列で初期化
/// </summary>
/// <param name="a"></param>
public Matrix(double[][] a)
{
matrix = new List<double[]>();
int m = a.Length;
for (int i = 0; i < m; i++)
{
matrix.Add(a[i]);
}
}
/// <summary>
/// 行列のサイズ [行数、列数]
/// </summary>
public int[] Size
{
get
{
var size = new int[2];
size[0] = matrix.Count;
size[1] = matrix[0].Length;
return size;
}
}
/// <summary>
/// 行列の要素を得る。
/// </summary>
/// <param name="m">行の指定</param>
/// <param name="n">列の指定</param>
/// <returns>要素の値</returns>
public double Get(int m, int n)
{
double[] row = matrix[m];
return row[n];
}
/// <summary>
/// 行列の要素の値を変更する。
/// </summary>
/// <param name="m">行の指定</param>
/// <param name="n">列の指定</param>
/// <param name="v">要素の値</param>
public void Set(int m, int n, double v)
{
double[] row = matrix[m];
row[n] = v;
}
/// <summary>
/// 行列の要素
/// </summary>
/// <param name="m"></param>
/// <param name="n"></param>
/// <returns></returns>
public double this[int m, int n]
{
get
{
return Get(m, n);
}
set
{
Set(m, n, value);
}
}
/// <summary>
/// 配列を行として追加する。
/// </summary>
/// <param name="a">追加する配列</param>
/// <returns>追加後の行数</returns>
public int AppendRow(double[] a)
{
if (matrix.Count > 0 && matrix[0].Length != a.Length)
throw new Exception("行列の列数と入力ベクトルの整合性がありません。");
matrix.Add(a);
return matrix.Count;
}
/// <summary>
/// 指定した行を配列として取得する。
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
public double[] GetRow(int n)
{
int[] size = this.Size;
double[] row = new double[size[1]];
for (int i = 0; i < size[1]; i++)
{
row[i] = this[n, i];
}
return row;
}
/// <summary>
/// 指定した列を配列として取得する。
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public double[] GetColumn(int m)
{
int[] size = this.Size;
double[] col = new double[size[0]];
for (int i = 0; i < size[0]; i++)
{
col[i] = this[i, m];
}
return col;
}
/// <summary>
/// 行列の要素をゼロクリアする。
/// </summary>
public void Zero()
{
for (int i = 0; i < this.Size[0]; i++)
{
double[] row = matrix[i];
for (int j = 0; j < this.Size[1]; j++)
{
row[j] = 0.0;
}
}
}
/// <summary>
/// 行列の要素の符号を反転させる。
/// </summary>
public void Inv()
{
for (int i = 0; i < this.Size[0]; i++)
{
double[] row = matrix[i];
for (int j = 0; j < this.Size[1]; j++)
{
row[j] = -row[j];
}
}
}
/// <summary>
/// 行列のクローンを作る。
/// </summary>
/// <param name="a">行列</param>
/// <returns>クローン</returns>
public Matrix Clone()
{
int m = this.Size[0];
int n = this.Size[1];
Matrix mx = new Matrix(m, n);
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
mx[i, j] = this[i, j];
}
}
return mx;
}
/// <summary>
/// 文字列表現を返す。
/// </summary>
/// <returns>文字列</returns>
public override string ToString()
{
var sb = new StringBuilder();
int m = this.Size[0];
int n = this.Size[1];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
sb.Append(Get(i, j).ToString());
sb.Append(" ");
}
sb.Append("\n");
}
return sb.ToString();
}
/// <summary>
/// 行列の加算
/// </summary>
/// <param name="a">行列</param>
/// <param name="b">行列</param>
/// <returns>行列</returns>
public static Matrix operator + (Matrix a, Matrix b)
{
var size = a.Size;
Matrix m = a.Clone();
for (int i = 0; i < size[0]; i++)
{
for (int j = 0; j < size[1]; j++)
{
m[i, j] += b[i, j];
}
}
return m;
}
/// <summary>
/// 行列の減算
/// </summary>
/// <param name="a">行列</param>
/// <param name="b">行列</param>
/// <returns>行列</returns>
public static Matrix operator -(Matrix a, Matrix b)
{
var size = a.Size;
Matrix m = a.Clone();
for (int i = 0; i < size[0]; i++)
{
for (int j = 0; j < size[1]; j++)
{
m[i, j] -= b[i, j];
}
}
return m;
}
/// <summary>
/// 行列の掛け算
/// </summary>
/// <param name="a">行列</param>
/// <param name="b">行列</param>
/// <returns>行列</returns>
public static Matrix operator *(Matrix a, Matrix b)
{
var size = a.Size;
double[,] y = new double[size[0], size[1]];
for (int i = 0; i < size[0]; i++)
{
for (int j = 0; j < size[1]; j++)
{
y[i, j] = 0.0;
}
}
for (int i = 0; i < size[0]; i++)
{
for (int j = 0; j < size[1]; j++)
{
double[] row = a.GetRow(i);
double[] col = b.GetColumn(j);
y[i, j] = InnerProduct(row, col);
}
}
return new Matrix(y);
}
public static double InnerProduct(double[] a, double[] b)
{
double s = 0.0;
for (int i = 0; i < a.Length; i++)
{
s += a[i] * b[i];
}
return s;
}
/// <summary>
/// スカラーと行列の掛け算
/// </summary>
/// <param name="r">スカラー</param>
/// <param name="a">行列</param>
/// <returns>行列</returns>
public static Matrix operator * (double r, Matrix a)
{
var size = a.Size;
Matrix m = a.Clone();
for (int i = 0; i < size[0]; i++)
{
for (int j = 0; j < size[1]; j++)
{
m[i, j] = r * a[i, j];
}
}
return m;
}
/// <summary>
/// 行列とベクトルの掛け算
/// </summary>
/// <param name="a">行列</param>
/// <param name="v">ベクトル</param>
/// <returns>ベクトル</returns>
public static Vector operator * (Matrix a, Vector v)
{
var u = new Vector(v.Length);
int m = a.Size[0];
int n = a.Size[1];
for (int i = 0; i < m; i++)
{
u[i] = 0.0;
for (int j = 0; j < n; j++)
{
u[i] += a[i, j] * v[j];
}
}
return u;
}
/// <summary>
/// 行列の比較
/// </summary>
/// <param name="obj">比較対象の行列</param>
/// <returns>等しければ true</returns>
public override bool Equals(object obj)
{
var mat = obj as Matrix;
var size = this.Size;
if (size[0] == mat.Size[0] && size[1] == mat.Size[1])
{
for (int i = 0; i < size[0]; i++)
{
for (int j = 0; j < size[1]; j++)
{
if (this[i, j] != mat[i, j])
{
return false;
}
}
}
}
else
{
return false;
}
return true;
}
/// <summary>
/// ハッシュコードを返す。
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
使用例
using System;
using MatrixClass;
namespace TestMatrixClass
{
/// <summary>
/// MatrixClass のテスト
/// </summary>
class Program
{
static void Main(string[] args)
{
Console.WriteLine("MatrixClass のテスト");
if (args.Length == 0)
{
// Matrix のテスト (1)
var mat1 = new MatrixClass.Matrix(3, 3);
mat1.Zero();
mat1.Set(0, 0, 1.0);
Console.WriteLine(mat1.Get(0, 0));
double[,] a = new double[,] { { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 }, { 7.0, 8.0, 9.0 } };
var mat2 = new MatrixClass.Matrix(a);
Console.WriteLine(mat2.Get(1, 1));
double[][] b = new double[3][];
b[0] = new double[3] { 1.0, 2.0, 3.0 };
b[1] = new double[3] { 4.0, 5.0, 6.0 };
b[2] = new double[3] { 7.0, 8.0, 9.0 };
var mat3 = new MatrixClass.Matrix(b);
Console.WriteLine(mat3.Get(2, 2));
Console.WriteLine(mat3[2, 2]);
Console.WriteLine(mat3.ToString());
}
else
{
switch (args[0])
{
case "-v":
{
// Vector のテスト
var v1 = new Vector(3);
v1.Zero();
var v2 = new Vector(new double[] { 1.0, 2.0, 3.0 });
Console.WriteLine(v1.ToString());
Console.WriteLine(v2.ToString());
v1[0] = -1.0;
v1[1] = -2.0;
v1[2] = -3.0;
Vector v = v1 + v2;
Console.WriteLine(v.ToString());
Vector u = v1 - v2;
Console.WriteLine(u.ToString());
Vector w = 3.0 * v1;
Console.WriteLine(w);
double x = Vector.Dot(v1, v2);
Console.WriteLine(x);
}
break;
case "-m":
{
// Matrix 演算のテスト
var m1 = new Matrix(2, 2);
m1.Zero();
m1[0, 0] = 1.0;
m1[1, 1] = 1.0;
Console.WriteLine("m1 = \n" + m1.ToString());
var m2 = new Matrix(new double[,] { { 1.0, -1.0 }, { 0.0, 1.0 } });
Console.WriteLine("m2 = \n" + m2.ToString());
var m3 = new Matrix(new double[][] { new double[] {2.0, 1.0 }, new double[] {-1.0, -3.0 } });
Console.WriteLine("m3 = \n" + m3.ToString());
var m = m1 + m2;
Console.WriteLine("m1 + m2 = \n" + m.ToString());
m = m3 - m2;
Console.WriteLine("m3 - m2 = \n" + m.ToString());
}
break;
default:
break;
}
}
}
}
}
PowerShell で MatrixClass を使う例
Matrix クラスの使用例
using namespace System.Numerics
if ($PSVersionTable.Platform -eq "Unix") {
Add-Type -Path "/home/user/lib/NET5/MatrixClass.dll"
}
else {
Add-Type -Path "d:/lib/NET5/MatrixClass.dll"
}
$Matrix = [MatrixClass.Matrix]
$Vector = [MatrixClass.Vector]
$m0 = $Matrix::new(2, 2)
$m0.Zero()
$m0.Set(1, 1, 1)
$m0[0, 1] = 2
$m0.Get(1, 1)
$m0[0, 1]
$m0.ToString()
$a = ((1, 0), (0, 1))
$m1 = $Matrix::new($a)
$m1.ToString()
$b = (1.5, -2.0), (0, 3.0)
$m2 = $Matrix::new($b)
$m2.ToString()
$mx = $m1 + $m2
$mx.ToString()
$mx = $m1 - $m2
$mx.ToString()
$mx = $m1 * $m2
$mx.ToString()
$v = $Vector::new((2, 2))
$mx = $m1 * $v
$mx.ToString()
実行例
PS D:\workspace\PowerShell\NET5DLL> .\Matrix.ps1 1 2 0 2 0 1 1 0 0 1 1.5 -2 0 3 2.5 -2 0 4 -0.5 2 0 -2 1.5 -2 0 3 2 2
Vector クラスの使用例
using namespace System.Numerics
if ($PSVersionTable.Platform -eq "Unix") {
Add-Type -Path "/home/user/lib/NET5/MatrixClass.dll"
}
else {
Add-Type -Path "D:/lib/NET5/MatrixClass.dll"
}
$Vector = [MatrixClass.Vector]
$v0 = $Vector::new(3);
$v1 = $Vector::new((-1, 0, 1))
$v0.Zero()
$v0.ToString()
$v1.ToString()
$v0[1] = 2.0
$v0.ToString()
$v2 = $v0 + $v1
$V2.ToString()
$a = $v2.ToArray()
$a.GetType()
$a
$Vector::dot($v1, $v2)
実行例
PS D:\workspace\PowerShell\NET5DLL> .\Vector.ps1 0 0 0 -1 0 1 0 2 0 -1 2 1 IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Double[] System.Array -1 2 1 2