reshapeについてjuliaとpythonで違うところまとめ
reshapeを使うときに、juliaとpythonで違う点があったので、その違いについて紹介する。
一次元配列を二次元配列にするとき
Julia
例えば、一次元配列を2×3の行列になおしてみる。
a = [1,2,3,4,5,6]
b = reshape(1:6, 2,3)
結果は、
2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
1 3 5
2 4 6
1,2の配置を見てわかるように、juliaでは行が最初に変わることになるので、行列の行が優先して変わることになる。
python
import numpy as np
a = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
b = a.reshape(2,3)
結果は
array([[1., 2., 3.],
[4., 5., 6.]])
juliaの場合と結果が異なる。pythonでは1,2,3の配置を見てわかるように、列が最初に変わっているので、行列の列が優先して値が変わることになる。
二次元配列を一次元にする
Julia
A = Vector(1:16) # 16-element Vector{Int64}:
b = reshape(A, 2, :)
2×8 Matrix{Int64}:
1 3 5 7 9 11 13 15
2 4 6 8 10 12 14 16
reshape(b, 1, :)
1×16 Matrix{Int64}:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
このとき、reshapeの内部で大体行われていることは
c = []
for j in 1:8
for i in 1:2
push!(c, b[i,j])
end
end
このように行列の足bijの内、juliaではiのループが先に走ることになる。これはメモリ空間で行優先であることに対応がつく。
python
a = np.arange(6).reshape(2, 3)
a
===== 結果=========
array([[0, 1, 2],
[3, 4, 5]])
==================
a.reshape(-1)
=======結果==========
array([0, 1, 2, 3, 4, 5])
==================
reshapeの内部では以下のようなことが行われている。
a = np.arange(6).reshape(2, 3)
l = []
for i in range(2):
for j in range(3):
l.append(a[i,j])
np.array(l)
このようにjのループが先に走ることになる。これはメモリ空間では列優先であることに対応する。
多次元配列
以下はおまけです。
最後に突然だが、物性物理に出てくる2サイトハバードモデルのハミルトニアンを作ってみる。
python
import numpy as np
nsites = 2
up = 0
down = 1
t = 1.0
tij = np.zeros((nsites, 2, nsites, 2))
for isite in range(nsites-1):
tij[isite, up, isite+1, up] = t
tij[isite+1, up, isite, up] = t
tij[isite, down, isite+1, down] = t
tij[isite+1, down, isite, down] = t
tij = np.reshape(tij, (2*nsites, 2*nsites))
確認
print(tij[0, 2]) #1サイト目のup 2サイト目のupのホッピング
print(tij[2, 0]) #上の1<->2をした場合
print(tij[1,3]) #1サイト目のdown 2サイト目のdownのホッピング
print(tij[3,1]) #上の1<->2をした場合
クーロン相互作用の項は、
nsites = 2
up = 0
down = 1
U = 1.0
Uijlk = np.zeros((nsites, 2, nsites, 2, nsites, 2, nsites, 2))
for isite in range(nsites):
Uijlk[isite, up, isite, down , isite, up, isite, down] = U
Uijlk[isite, down, isite, up, isite, down, isite, up] = U
#print(Uijlk)
Uijlk = np.reshape(Uijlk, (2*nsites, 2*nsites, 2*nsites, 2*nsites));
print(Uijlk)
結果
print(Uijlk[0, 1, 0, 1])
#1サイト目のupの生成, 1サイト目のdown生成, 1サイトめのupの消滅, 1サイトめのdownの消滅演算子
print(Uijlk[2, 3, 2, 3])
#2サイト目のupの生成, 2サイト目のdownの生成, 2サイトめのupの消滅, 2サイトめのdownの消滅演算子
欲しい結果が得られた。
Julia
上のpythonコードのtij,Uijlkをisite先ではなく、up or down を先に書くようにコードを変えれば良いです。
まとめ
juliaとpythonでreshapeの違いについて理解を深めました。