C++で線形計算を手軽に行えるライブラリを作りました。
Vector b(100); // ベクトルを宣言
IntVector p(30); // 整数型のベクトルを宣言
Matrix A(10,10); // 行列を宣言
Matrix A;
A = B;
Vector b = c;
int n = 5;
Vector b(n); // ベクトルを宣言、b[0]~b[n]を使用可能。
b.Shift(2); // ベクトルの中身を添え字2つ分右にシフトする。添え字の範囲は0から。
// b[0]=8; b[1]=7; b[2]=6; b[3]=5; b[4]=4; b[5]=3; のときには c=b.Shift(2)は
// c[0]=0; c[1]=0; c[2]=8; c[3]=7; c[4]=6; c[5]=5; となる。
b.Shift(-1); // ベクトルの中身を添え字1つ分左にシフトする。添え字の範囲は0から。
// b[0]=8; b[1]=7; b[2]=6; b[3]=5; b[4]=4; b[5]=3; のときには c=b.Shift(-1)は
// c[0]=7; c[1]=6; c[2]=5; c[3]=4; c[4]=3; c[5]=0; となる。
b.Norm1(); // ベクトルbの1ノルムを返す。
b.Norm2(); // ベクトルbの2ノルムを返す。
b.NormInfty(); // ベクトルbの無限大ノルムを返す。
b.Size(); // ベクトルbのサイズ(添え字の最大値)を返す。この場合は5が返る。
b.Show(k); // ベクトルの中身を有効数字k桁で表示する。添え字の範囲は1から。
Matrix A(n,n); // 行列を宣言、A[0][0]~A[n][n]を使用可能。
A.Transpose(); // 行列Aの転置行列を返す。添え字の範囲は0から。
A.RowVector(k); // 行列Aのk行目をベクトルとして返す。添え字の範囲は0から。
A.ColVector(k); // 行列Aのk列目をベクトルとして返す。添え字の範囲は0から。
A.SetRowVector(k, v); // 行列Aのk行目にベクトルvをセットする。添え字の範囲は0から。
A.SetColVector(k, v); // 行列Aのk列目をベクトルvをセットする。添え字の範囲は0から。
A.Gauss(b); // Gaussの消去法を用いて Ax=b を解いた結果を返す。計算に用いる添え字の範囲は1から。
// スケーリングおよび部分ピボット選択を使用。
A.RowSize(); // 行列Aの行数(添え字の最大値)を返す。この場合は5が返る。
A.ColSize(); // 行列Aの列数(添え字の最大値)を返す。この場合は5が返る。
A.Show(k); // 行列Aの中身を有効数字k桁で表示する。添え字の範囲は1から。
#include <stdio.h>
#include <math.h>
#include "Linear.h"
// x^2+y^2+z^2=1
// y=sin(x)
// z=x+y
// を解く。プログラムではxをx[1]、yをx[2]、zをx[3]とする。
// F(x) = ( x[1]^2 + x[2]^2 + x[3]^2 - 1, x[2] - sin(x[1]), x[3]-x[1]-x[2] )
// 関数値
Vector f(Vector x)
{
Vector y(3);
y[1] = x[1]*x[1] + x[2]*x[2] + x[3]*x[3] - 1;
y[2] = x[2] - sin(x[1]);
y[3] = x[3] - x[1] - x[2];
return y;
}
// ヤコビ行列
Matrix df(Vector x)
{
Matrix y(3, 3);
y[1][1] = 2*x[1]; y[1][2] = 2*x[2]; y[1][3] = 2*x[3];
y[2][1] = -cos(x[1]); y[2][2] = 1; y[2][3] = 0;
y[3][1] = -1; y[3][2] = -1; y[3][3] = 1;
return y;
}
int main()
{
int n = 3;
Matrix J(n, n);
Vector x(n);
// 初期値
x[1]=0.5; x[2]=0.5; x[3] = 0.5;
for(int k=1; k<=10; k++){
J = df(x);
x = x - J.Gauss(f(x));
printf("x^(%d)=(%.15f,%.15f,%.15f)\n",k,x[1],x[2],x[3]);
}
return 0;
}
#include <stdio.h>
#include "Linear.h"
// x_1'=(a-b*x_2)*x_1 を解く
// x_2'=(-c+d*x_1)*x_2
Vector f(double t, Vector x)
{
Vector y(2);
y[1] = ( 1.0 - 1.0*x[2])*x[1];
y[2] = (-1.0 + 0.5*x[1])*x[2];
return y;
}
int main()
{
double a = 0.0, b = 30.0; // 計算範囲
int N=1000; // 分割数
int d = 2; // 従属変数の次元
Matrix S(d, N);
Vector t(N);
Vector x(d), k1(d), k2(d), k3(d), k4(d);
double h = (b-a)/N; // 区間幅
x[1] = 0.5; x[2] = 0.5; // 初期条件
S.SetColVector(0, x);
for(int n=0; n<=N; n++){
t[n] = a + n*h;
}
for(int n=0; n<N; n++){
k1 = h * f(t[n], x );
k2 = h * f(t[n] + h/2, x + k1/2);
k3 = h * f(t[n] + h/2, x + k2/2);
k4 = h * f(t[n] + h/2, x + k3 );
x += (k1 + 2*k2 + 2*k3 + k4)/6;
S.SetColVector(n+1, x);
}
FILE *fp;
fp = fopen("l-v.dat", "w");
for(int n=0; n<=N; n++){
fprintf(fp, "%f", t[n]);
for(int i=1; i<=d; i++){
fprintf(fp, " %f", S[i][n]);
}
fprintf(fp, "\n");
}
fclose(fp);
return 0;
}