乱数を用いた正方行列の生成プログラム(Python)


# プログラムについて
乱数で生成した正方行列をCSV形式で出力するプログラムです．
以下の行列が生成できます．
- 非対称行列
    - 密行列
    - 疎行列
- 対称行列
    - 密行列
    - 疎行列

# 環境
- MacBook Air(M1, 2020)
- Docker(Ubuntu 20.04.5 LTS)
- Python 3.8.10

# プログラム
クラスファイル

```python:Matrix.py
import numpy as np
import random

class Matrix:
    def __init__(self, matrix, N, coefficient, correction, NonZeroList):
        self.matrix = matrix
        self.N = N
        self.coefficient = coefficient
        self.correction = correction
        self.NonZeroList = NonZeroList
# 対称行列を生成する
    def SparseSymmetricMatrix(self):
        for i in range(self.N):
            for j in range(self.N):
                if j > i:
                    break
                elif i == j:
                    self.matrix[i][j] = random.random() + self.correction
                else:
                    tmp = random.random()
                    self.matrix[i][j] = tmp
                    self.matrix[j][i] = tmp
                    if random.random()  > self.coefficient:
                        self.matrix[i][j] = 0
                        self.matrix[j][i] = 0
                        self.NonZeroList[i] = self.NonZeroList[i] + 1
                        self.NonZeroList[j] = self.NonZeroList[j] + 1                   
        return self.matrix, self.NonZeroList
# 非対称行列を生成する   
    def SparseNonsymmetricMatrix(self):
        self.matrix = np.random.rand(self.N, self.N)
        for i in range(self.N):
            k = 0
            for j in range(self.N):
                if random.random()  > self.coefficient:
                    self.matrix[i][j] = 0
                    k = k + 1
                if i == j:
                    if self.matrix[i][j] == 0:
                        self.matrix[i][j] = random.random() + self.correction
                        k = k - 1
            self.NonZeroList[i] = k

        return self.matrix, self.NonZeroList
```
メインプログラム
```python:MakeMatrix.py
import numpy as np
import sys
import random
import Matrix
import datetime

#現在時刻の取得
dt_now = datetime.datetime.now()
#出力ファイル名
filename = sys.argv[1] + "_" + sys.argv[1] + "matrix" + dt_now.strftime('%Y%m%d%H%M%S') + ".csv"

# 行列の大きさを取得
N =int(sys.argv[1])

# 行列の要素を0で埋める
matrix = np.zeros((N,N))

# 行列における非零要素の割合 (0 ~ 1)
# 1であれば行列の全ての要素を乱数によって埋める
coefficient = float(sys.argv[2])

# 行列の対角成分が0とならないための補正値
correction = 0.00001

# 生成する行列が非対称行列か対称行列かを決める
# 0:非対称行列
# 1:対称行列
flag = int(sys.argv[3])

# 各行における0要素の数を格納するためのリスト
NonZeroList = [0] * N

data1 = Matrix.Matrix(matrix, N, coefficient, correction, NonZeroList)

if flag == 0:
# 非対称行列の生成
    matrix, NonZeroList = data1.SparseNonsymmetricMatrix()
else:
# 対称行列の生成
    matrix, NonZeroList = data1.SparseSymmetricMatrix()

print(matrix)
print(NonZeroList)
# 行列式の表示
print("det A = " + str(np.linalg.det(matrix)))

# ファイルに以下の情報を出力する
# 行列の大きさ,行における非零要素数の最大値,行列における0要素の数
matrix_info = str(N)+ ',' + str(N - min(NonZeroList)) + ',' + str(sum(NonZeroList))
# 行列をファイルに出力する
np.savetxt(filename, matrix, delimiter=",", header = matrix_info)

# 非零要素の数を表示
#print(sum(NonZeroList))

# 行における最大非零要素数を表示
#print(N - min(NonZeroList))
```

# 実行方法
```
python3 MakeMatrix.py N coefficient flag
```
- N: 行列の大きさ(int)

- coefficient: 行列における非零要素の割合
    値の範囲: 0 ~ 1のfloat

- flag: 生成する行列が対称行列か非対称行列かを決める
    0:非対称行列
    1:対称行列


```:実行例
python3 MakeMatrix.py 4 0.4 0
```

# 実行結果
ターミナルでは以下の結果を出力しています
- 生成した行列
- 各行における0要素の数
- 行列式

出力ファイルでは1行目に以下の内容を記録しています
- 行列の大きさ
- 行における非零要素数の最大値
- 行列における0要素の数

```:ターミナルでの出力(非対称行列)
$ python3 MakeMatrix.py 4 0.4 0
[[0.65066897 0.         0.         0.        ]
 [0.         0.26324103 0.95347185 0.        ]
 [0.         0.         0.57528549 0.        ]
 [0.         0.77893017 0.27670035 0.06987914]]
[3, 2, 3, 1]
det A = 0.006885645312935573

$ cat 4_4matrix20230109025801.csv 
# 4,3,9
6.506689652550904368e-01,0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
0.000000000000000000e+00,2.632410346860651895e-01,9.534718467392574448e-01,0.000000000000000000e+00
0.000000000000000000e+00,0.000000000000000000e+00,5.752854908460579564e-01,0.000000000000000000e+00
0.000000000000000000e+00,7.789301673589617003e-01,2.767003451180947149e-01,6.987913896584962981e-02

```

```:ターミナルでの出力(対称行列)
$ python3 MakeMatrix.py 4 0.4 1
[[0.91577758 0.         0.         0.        ]
 [0.         0.62715689 0.         0.27769902]
 [0.         0.         0.50224569 0.17688978]
 [0.         0.27769902 0.17688978 0.96498479]]
[3, 2, 2, 1]
det A = 0.22491701267021577

$ cat 4_4matrix20230109025922.csv 
# 4,3,8
9.157775837042154699e-01,0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
0.000000000000000000e+00,6.271568857682054965e-01,0.000000000000000000e+00,2.776990216306892689e-01
0.000000000000000000e+00,0.000000000000000000e+00,5.022456936930083105e-01,1.768897789438276247e-01
0.000000000000000000e+00,2.776990216306892689e-01,1.768897789438276247e-01,9.649847898813963543e-01
```