M.Hiroi's Home Page

Python3 Programming

お気楽 NumPy プログラミング超入門

[ Home | Light | Python3 ]

●複素数

今回は Python (NumPy) の複素数について簡単にまとめてみました。

>>> import numpy as np
>>> import cmath
>>> a = complex(1, 2)
>>> a
(1+2j)
>>> b = 3 + 4j
>>> b
(3+4j)
>>> c = np.array([a, b])
>>> c
array([ 1.+2.j,  3.+4.j])
>>> type(a)
<class 'complex'>
>>> np.iscomplex(a)
True
>>> np.iscomplex(c)
array([ True,  True], dtype=bool)
>>> np.iscomplex(1.234)
False
>>> np.isreal(a)
False
>>> np.isreal(c)
array([False, False], dtype=bool)
>>> np.isreal(1.2345)
True

>>> a + b
(4+6j)
>>> a - b
(-2-2j)
>>> a * b
(-5+10j)
>>> a / b
(0.44+0.08j)
>>> a ** 2
(-3+4j)
>>> a ** 3
(-11-2j)
>>> a == a
True
>>> a != a
False
>>> a != b
True

>>> a.real
1.0
>>> a.imag
2.0
>>> np.real(a)
1.0
>>> np.real(c)
array([ 1.,  3.])
>>> np.imag(a)
2.0
>>> np.imag(c)
array([ 2.,  4.])

>>> abs(a)
2.23606797749979
>>> abs(b)
5.0
>>> np.abs(c)
array([ 2.23606798,  5.        ])
>>> cmath.phase(a)
1.1071487177940904
>>> np.angle(a)
1.1071487177940904
>>> cmath.phase(b)
0.9272952180016122
>>> np.angle(b)
0.92729521800161219
>>> np.angle(c)
array([ 1.10714872,  0.92729522])

>>> cmath.polar(a)
(2.23606797749979, 1.1071487177940904)
>>> cmath.polar(b)
(5.0, 0.9272952180016122)
>>> cmath.rect(2.23606797749979, 1.1071487177940904)
(1.0000000000000002+2j)
>>> cmath.rect(5.0, 0.9272952180016122)
(3.0000000000000004+3.9999999999999996j)

>>> a.conjugate()
(1-2j)
>>> b.conjugate()
(3-4j)
>>> np.conj(a)
(1-2j)
>>> np.conj(b)
(3-4j)
>>> np.conj(c)
array([ 1.-2.j,  3.-4.j])

>>> cmath.sqrt(-1)
1j
>>> cmath.sqrt(-2)
1.4142135623730951j
>>> np.sqrt(-1+0j)
1j
>>> np.sqrt(-2+0j)
1.4142135623730951j
>>> np.sqrt(c)
array([ 1.27201965+0.78615138j,  2.00000000+1.j        ])
>>> cmath.exp(complex(0,cmath.pi/4))
(0.7071067811865476+0.7071067811865475j)
>>> cmath.exp(complex(0,cmath.pi)) + 1
1.2246467991473532e-16j
>>> np.exp(a)
(-1.1312043837568135+2.4717266720048188j)
>>> np.exp(b)
(-13.128783081462158-15.200784463067954j)
>>> np.exp(c)
array([ -1.13120438 +2.47172667j, -13.12878308-15.20078446j])

●複素ベクトル

>>> import numpy as np
>>> a = np.array([1+2j,3+4j])
>>> a
array([ 1.+2.j,  3.+4.j])
>>> b = np.array([5+6j, 7+8j])
>>> b
array([ 5.+6.j,  7.+8.j])
>>> np.conjugate(a)
array([ 1.-2.j,  3.-4.j])
>>> np.conj(b)
array([ 5.-6.j,  7.-8.j])

>>> a + b
array([  6. +8.j,  10.+12.j])
>>> a - b
array([-4.-4.j, -4.-4.j])
>>> a * b
array([ -7.+16.j, -11.+52.j])
>>> a / b
array([ 0.27868852+0.06557377j,  0.46902655+0.03539823j])

>>> c = 1 - 1j
>>> a + c
array([ 2.+1.j,  4.+3.j])
>>> a - c
array([ 0.+3.j,  2.+5.j])
>>> a * c
array([ 3.+1.j,  7.+1.j])
>>> a / c
array([-0.5+1.5j, -0.5+3.5j])

>>> np.vdot(a, b)
(70-8j)
>>> np.vdot(b, a)
(70+8j)
>>> np.conj(a) @ b
(70-8j)
>>> a @ np.conj(b)
(70+8j)
>>> a @ b
(-18+68j)

>>> np.vdot(a, a)
(30+0j)
>>> np.vdot(b, b)
(174+0j)
>>> np.linalg.norm(a)
5.4772255750516612
>>> np.linalg.norm(b)
13.19090595827292

●複素行列

>>> a = np.array([[1+1j, 1-1j], [2+3j, 2+1j]])
>>> a
array([[ 1.+1.j,  1.-1.j],
       [ 2.+3.j,  2.+1.j]])
>>> a.T
array([[ 1.+1.j,  2.+3.j],
       [ 1.-1.j,  2.+1.j]])

>>> def htr(a): return np.conj(a.T)
...
>>> htr(a)
array([[ 1.-1.j,  2.-3.j],
       [ 1.+1.j,  2.-1.j]])
>>> htr(htr(a))
array([[ 1.+1.j,  1.-1.j],
       [ 2.+3.j,  2.+1.j]])

>>> b = np.array([[1+0j, 1+1j],[1-1j, 0+1j]])
>>> b
array([[ 1.+0.j,  1.+1.j],
       [ 1.-1.j,  0.+1.j]])
>>> htr(a + b)
array([[ 2.-1.j,  3.-2.j],
       [ 2.-0.j,  2.-2.j]])
>>> htr(a) + htr(b)
array([[ 2.-1.j,  3.-2.j],
       [ 2.+0.j,  2.-2.j]])
>>> c
(1-1j)
>>> htr(c * a)
array([[ 2.-0.j,  5.-1.j],
       [ 0.+2.j,  3.+1.j]])
>>> np.conj(c) * htr(a)
array([[ 2.+0.j,  5.-1.j],
       [ 0.+2.j,  3.+1.j]])
>>> htr(a @ b)
array([[ 1.+1.j,  5.-2.j],
       [ 1.-3.j, -2.-7.j]])
>>> htr(b) @ htr(a)
array([[ 1.+1.j,  5.-2.j],
       [ 1.-3.j, -2.-7.j]])

>>> np.linalg.det(a)
(-4.0000000000000009+2.0000000000000009j)
>>> np.linalg.det(htr(a))
(-4-2j)
>>> np.conj(np.linalg.det(a))
(-4.0000000000000009-2.0000000000000009j)
>>> np.linalg.inv(a)
array([[-0.3-0.4j,  0.3-0.1j],
       [ 0.1+0.8j, -0.1-0.3j]])
>>> htr(np.linalg.inv(a))
array([[-0.3+0.4j,  0.1-0.8j],
       [ 0.3+0.1j, -0.1+0.3j]])
>>> np.linalg.inv(htr(a))
array([[-0.3+0.4j,  0.1-0.8j],
       [ 0.3+0.1j, -0.1+0.3j]])

>>> u = np.array([1+2j, 3+4j])
>>> u
array([ 1.+2.j,  3.+4.j])
>>> v = np.array([5+6j, 7+8j])
>>> v
array([ 5.+6.j,  7.+8.j])
>>> a @ u
array([ 6. +4.j, -2.+18.j])
>>> np.vdot(a @ u, v)
(184-126j)
>>> np.vdot(u, htr(a) @ v)
(184-126j)

●複素関数のグラフ

参考文献, URL を参考にして、複素関数 w = f(z) の値域 (w) をグラフにしてみました。下図に示す複素平面を考えます。

複素平面は横軸が実軸で、縦軸が虚軸となります。実軸と虚軸は黒 (black) で描画します。横線を青 (blue と darkblue) で、縦線を緑 (lime と green) で、原点を中心とした円を赤 (red と darkred) で描画しています。これを複素関数 sqrt, exp, log, sin, arcsin, cos, arccos, tan, arctan, sinh, arcsinh, cosh, arccosh, tanh, arctanh に渡して、評価結果を複素平面に描画します。

●プログラムリスト

リスト : 複素関数の描画

import math
import numpy as np
import matplotlib.pyplot as plt

plt.figure(figsize=(6, 6))
plt.subplots_adjust(left=0.1, right=0.95, bottom=0.1, top=0.95)
plt.xlim(-4.1, 4.1)
plt.ylim(-4.1, 4.1)

# 描画する複素関数をセットする
cfunc = np.sqrt

for i in np.linspace(-4.0, 4.0, 9):
    # 横線
    x = np.linspace(-10.0, 10.0, 1600)
    y = np.full(1600, i)
    z = np.array([complex(a, b) for a in x for b in y])
    w = cfunc(z)
    if i > 0.0:
        c = 'blue'
    elif i < 0.0:
        c = 'darkblue'
    else:
        c = 'black'
    plt.plot(np.real(w), np.imag(w), ',', color = c)
    # 縦線
    y = np.linspace(-10.0, 10.0, 1600)
    x = np.full(1600, i)
    z = np.array([complex(a, b) for a in x for b in y])
    w = cfunc(z)
    if i > 0.0:
        c = 'lime'
    elif i < 0.0:
        c = 'green'
    else:
        c = 'black'
    plt.plot(np.real(w), np.imag(w), ',', color= c)
# 円
for r, n in [(0.25, 800), (0.5, 800), (1.0, 800), (2.0, 1600), (4.0, 1600), (8.0, 3200)]:
    theta = np.linspace(-math.pi, math.pi, n)
    z = np.array([complex(r * math.cos(x), r * math.sin(x)) for x in theta])
    w = cfunc(z)
    if r > 1.0:
        c = 'darkred'
    else:
        c = 'red'
    plt.plot(np.real(w), np.imag(w), ',', color = c)

plt.gca().set_aspect('equal')
plt.show()

●参考文献, URL

  1. Guy L. Steele Jr., 『COMMON LISP 第 2 版』, 共立出版, 1991
  2. 複素関数で遊ぼう, (雑記帳 | 人生やっていき)

Copyright (C) 2021-2023 Makoto Hiroi
All rights reserved.

[ Home | Light | Python3 ]