プログラムについて
乱数で生成した正方行列をCSV形式で出力するプログラムです.
以下の行列が生成できます.
- 非対称行列
- 対称行列
環境
- Ubuntu 20.04.5 LTS
プログラム
クラスファイル
make_matrix.hpp
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <vector>
enum MatrixType
{
Symmetric,
Asymmetric
};
class MakeSquareMatrix
{
private:
int N;
std::vector<std::vector<double>> matrix;
std::vector<int> NonZeroList;
public:
MakeSquareMatrix(int size, enum MatrixType type, double density)
{
N = size;
matrix.resize(N, std::vector<double>(N));
NonZeroList.resize(N);
for (int i = 0; i < N; i++)
{
switch (type)
{
// 対称正方行列の生成
case Symmetric:
for (int j = i; j < N; j++)
{
double random_number = ((double)rand() / (RAND_MAX));
double probability = ((double)rand() / (RAND_MAX));
if (probability < density)
{
if (j != i)
{
matrix[i][j] = random_number;
matrix[j][i] = random_number;
NonZeroList[i]++;
NonZeroList[j]++;
}
else
{
matrix[i][i] = random_number;
NonZeroList[i]++;
}
}
else
{
matrix[i][j] = 0;
matrix[j][i] = 0;
}
}
break;
// 非対称正方行列の生成
case Asymmetric:
for (int j = 0; j < N; j++)
{
double random_number = ((double)rand() / (RAND_MAX));
double probability = ((double)rand() / (RAND_MAX));
if (probability < density)
{
matrix[i][j] = random_number;
NonZeroList[i]++;
}
else
{
matrix[i][j] = 0;
}
}
break;
default:
break;
}
}
}
void outputToCSV(std::string filename)
{
int NonZero = 0;
int MaxNonZero = 0;
std::ofstream ofs(filename);
// 非ゼロ要素数を数える
for (int i = 0; i < N; i++)
{
NonZero += NonZeroList[i];
int tmp = NonZeroList[i];
// 各行における最大非ゼロ要素数を見つける
if (tmp > MaxNonZero)
{
MaxNonZero = tmp;
}
}
ofs << N << "," << NonZero << "," << MaxNonZero << "\n";
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (j < N - 1)
{
ofs << matrix[i][j] << ",";
}
else
{
ofs << matrix[i][j] << "\n";
}
}
}
ofs.close();
}
};
make_matrix.cpp
#include "make_matrix.hpp"
int main()
{
srand(time(0));
int N;
std::cout << "Enter the size of the matrix: ";
std::cin >> N;
std::string filename;
std::cout << "Enter the filename: ";
std::cin >> filename;
filename = filename + ".csv";
enum MatrixType type;
int type_num;
std::cout << "Enter the type of the matrix, 0 or 1:\n";
std::cout << "0:Symmetric, 1:Asymmetric ";
std::cin >> type_num;
if (type_num == 0)
{
type = Symmetric;
}
else if (type_num == 1)
{
type = Asymmetric;
}
// sparse .. dense
// 0 .. 1
double density;
std::cout << "Enter the density of the matrix(0 .. 1): ";
std::cin >> density;
MakeSquareMatrix matrix(N, type, density);
matrix.outputToCSV(filename);
return 0;
}
実行方法
実行すると,以下の入力が求められますので,生成したい行列に応じて入力して下さい.
-
1行目: 行列の大きさを指定
-
2行目: ファイル名を指定
-
3行目: 対称行列か非対称行列かを0か1で指定
-
4行目: 非ゼロ要素数の割合を指定(0:疎 ~ 1:密)
./a.out
Enter the size of the matrix: 5
Enter the filename: matrix
Enter the type of the matrix, 0 or 1:
0:Symmetric, 1:Asymmetric 0
Enter the density of the matrix(0 .. 1): 0.8
実行結果
生成されたファイル
5,17,5
0.634102,0.896232,0.601307,0.564086,0.159429
0.896232,0,0.45777,0,0.358383
0.601307,0.45777,0.910682,0,0.0695973
0.564086,0,0,0,0
0.159429,0.358383,0.0695973,0,0.487071
生成したファイルの読み込み
プログラム
read_matrix.cpp
#include <iostream>
#include <fstream>
#include <sstream>
int main(int argc, char *argv[])
{
// コマンドラインからファイル名を取得
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
return 1;
}
const std::string filename = argv[1];
// CSVファイルを開く
std::ifstream csv_file(filename);
if (!csv_file.is_open())
{
std::cerr << "Failed to open file " << filename << std::endl;
return 1;
}
// 行列の大きさ -> N
// 非ゼロ要素数 -> NonZero
// 各行における最大非ゼロ要素数 -> MaxNonZero
int N, NonZero, MaxNonZero;
std::string line;
std::getline(csv_file, line);
std::stringstream ss(line);
for (int j = 0; j < 3; ++j)
{
std::string cell;
std::getline(ss, cell, ',');
if (j == 0)
{
N = std::stoi(cell);
}
else if (j == 1)
{
NonZero = std::stoi(cell);
}
else if (j == 2)
{
MaxNonZero = std::stoi(cell);
}
}
std::cout << N << "," << NonZero << "," << MaxNonZero << std::endl;
double matrix[N][N];
// 正方行列のデータを読み込む
for (int i = 0; i < N; ++i)
{
std::string line;
std::getline(csv_file, line);
std::stringstream ss(line);
for (int j = 0; j < N; ++j)
{
std::string cell;
std::getline(ss, cell, ',');
matrix[i][j] = std::stod(cell);
}
}
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
std::cout << matrix[i][j] << ",";
}
std::cout << "\n";
}
return 0;
}
実行方法
読み込んだ行列を出力するだけのプログラムになっています.必要に応じて修正して下さい.
./main matrix.csv
5,17,5
0.634102,0.896232,0.601307,0.564086,0.159429,
0.896232,0,0.45777,0,0.358383,
0.601307,0.45777,0.910682,0,0.0695973,
0.564086,0,0,0,0,
0.159429,0.358383,0.0695973,0,0.487071,