見出し画像

Tips Python 数学モジュール/ライブラリ

簡易的なメモです。

Sympy : 代数演算

・sympy.var('x y'):シンボリック変数

・sympy.logcombine():対数の式をまとめる関数

対数公式
 $${log(x)+log(y)=log(x∗y)}$$
 $${y∗log(x)=log(x^y)}$$
を確かめる。

# xとyをシンボリック変数とする
sympy.var('x y') # シンボリック変数
f = sympy.log(x) + sympy.log(y) # 式を定義
sympy.logcombine(f, force=True)  # log(x*y) を出力
g = y*sympy.log(x)
sympy.logcombine(g, force=True)  # log(x**y) を出力

・sympy.diff( ) <- 微分

import sympy
# xをシンボリック変数として定義
sympy.var('x')   # x が出力

# 関数に名前をつけて定義
f = x**3 + x**2 + x

# 微分(一階)
sympy.diff(f)  # 3*x**2 + 2*x + 1 が出力

# 指数表記など数式を見やすく表示する設定
sympy.init_printing() 

# 微分(一階)
sympy.diff(f)  # 以下の結果が出力

>> 出力結果
   2          
3⋅x  + 2⋅x + 1

・sympy.solve() <- 方程式を解く。解は[-1,1]のようにリスト型。
     この0番目の解を取り出すにはsympy.solve()[0]とします。

・subs()メソッド:式の変数に数値代入。
         式.subs(変数, 数値)

# 代数演算ライブラリSymPyモジュールをインポートします
import sympy

# xをシンボリック変数として定義します。
sympy.var('x')

# 2次関数 y = -x2 + x を定義します
y = -x**2 + x

# y の微分 y'を求めます。sympy.diff(y)
# 微分y'=0 という方程式を解いて解(リスト)を求めます。sympy.solve()
# 解リストの0番目を取り出したものを変数solxに代入します。sympy.solve()[0]
solx = sympy.solve(sympy.diff(y))[0]

# y=-x2+x のxに解solを数値代入します。
y.subs(x, solx)

・sympy.integrate(関数):不定積分を返します。積分定数は0です。

import sympy

# xをシンボリック変数と定義
sympy.var('x')

# 式を見やすく表示する設定
sympy.init_printin()

#積分
sympy.integrate(x)  # 以下の結果が出力

>>出力結果
 2
x 
──
2

sympy.integrate(sympy.cos(x))  # sin(x) が出力
sympy.integrate(sympy.exp(x))  # 以下の結果が出力
>>出力結果
 x
ℯ

sympy.integrate(1/x)  # log(x) が出力

#### 定積分 ####
# sympy.integrate(関数, (x, a, b))は下端a、上端bの定積分の値を返します。
sympy.integrate(x, (x, 0, 1))  # 1/2 が出力

sympy.integrate(sympy.exp(x), (x, 0, 1))  # -1 + ℯ が出力

sympy.integrate(1/x, (x, 1, 2))  # log(2) が出力

isprime() <- 素数の判定
sieve.primerange() <- 素数リストの生成

from sympy import isprime, sieve
isprime(11)  # True と出力
isprime(10)  # False と出力
print([i for i in sieve.primerange(1,100)])  
# 1以上100未満の素数をリストアップします 
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

・sympy.N() / evalf()メソッド<- Calls x.evalf(n, **options).

Both .n() and N() are equivalent to .evalf(); use the one that you like better. See also the docstring of .evalf() for information on the options.

>>> from sympy import Sum, oo, N
>>> from sympy.abc import k
>>> Sum(1/k**k, (k, 1, oo))
Sum(k**(-k), (k, 1, oo))
>>> N(_, 4)
1.291

・等差数列

 等差数列の4つのパラメータ:【初項】【末項】【公差】【項数】
       公差 =(末項 ー 初項)/(項数-1)

・range(初項a, STOP, 公差d):数列は0スタート(初項が第0項)、range(n)の引数nは項数。
    ・少数を扱えない。
    ・
末項は計算してみないとわからない

t = range(初項a, STOP, 公差d)
数列t[k]:初項aから公差dでSTOPを超えない範囲の等差数列
t[0]=a, t[1]=a+d, t[2]=a+2d, …, t[?]=? < STOP 

# range(STOP)は、初項0、公差1、項数STOP、末項STOP-1の等差数列を生成
t = range(5)
print(t[0])  # 0 が出力
print(t[4])  # 4 が出力
print(list(t))  # [0, 1, 2, 3, 4] が出力

# range(初項a,STOP)は、初項a、公差1、項数STOP、末項STOP-1の等差数列
t = range(1, 5)
print(list(t))  # [1, 2, 3, 4] が出力

# range(初項a, STOP, 公差d)は、初項a、公差dの等差数列をSTOPを超えない範囲で生成
t = range(1, 10, 2)
print(list(t))  # [1, 3, 5, 7, 9] が出力

t = range(1, 10, 3)
print(list(t))  # [1, 4, 7] が出力

・numpy.arange(初項a, STOP, 公差d):数列は0スタート(初項が第0項)、arange(n)の引数nは項数。
    ・少数を扱えない。
    ・
末項は計算してみないとわからない少数を扱える。

import numpy
t = numpy.arange(初項a, STOP, 公差d)

#数列t[k]:初項aから公差dでSTOPを超えない範囲の等差数列
t[0]=a, t[1]=a+d, t[2]=a+2d, …, t[?]=? < n

# numpy.arange(STOP)は、初項0、公差1、項数STOP、末項STOP-1の等差数列
t = numpy.arange(5)
print(t[0])  # 0 が出力
print(t[4])  # 4 が出力
print(list(t))  # [0, 1, 2, 3, 4] が出力

# numpy.arange(初項a,STOP)は、初項a、公差1、項数STOP、末項STOP-1の等差数列
t = numpy.arange(1, 5)
print(list(t))  # [1, 2, 3, 4] が出力

t = numpy.arange(0.5, 3, 0.5)
print(list(t))  # [0.5, 1. , 1.5, 2. , 2.5] が出力

t = numpy.arange(1, 10, 2.5)
print(list(t))  # [1. , 3.5, 6. , 8.5] が出力

・numpy.linspace(初項a, 末項b, 項数N):数列は0スタート(初項が第0項)。
    ・末項を引数に持つようにした
    ・公差が計算してみないとわからない
    ・numpy.linspace(初項a, 末項b, 項数N)の公差:d = (b-a)/(N-1)
  ・sum( )
メソッド:数列の和

import numpy
t = numpy.linspace(初項a, 末項b, 項数N)

#数列t[k]:初項aから末項dまで項数Nの等差数列
#t[0]=a, t[1]=a+d, t[2]=a+2d, …, t[N-1]=b
#ただし、公差d=(b-a)/(N-1)

# numpy.linspace(初項a, 末項b)は、初項a、末項b、項数50(省略した場合)の等差数列を生成
t = numpy.linspace(1, 50)
print(t[0])  # 1.0 が出力
print(t[49])  # 50.0 が出力

# 公差:d = (b-a)/(N-1)
t = numpy.linspace(0, 5, 11)  # 公差d = (5-0)/(11-1) = 0.5
print(list(t))  # [0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ] が出力

t = numpy.linspace(1, 10, 4)  # 公差d = (10-1)/(4-1) = 3 
print(list(t))  # [ 1.,  4.,  7., 10.] が出力

# sum メソッド
# [1, 2, 3, 4]の和1+2+3+4を求める
numpy.arange(1, 5).sum()  # 10 が出力
# [ 1., 4., 7., 10.]の和1+4+7+10を求める
numpy.linspace(1, 10, 4).sum()  # 22.0 が出力
# [1, 2, 3, 4]それぞれの2乗和12+22+32+42を求める
(numpy.arange(1, 5)**2).sum()  # 30 が出力

Numpy

ベクトル

・numpy.array( ):ベクトルの定義
・len( ):ベクトルの次元(要素数)
・numpy.linalg.norm( ):ベクトルの大きさ 
・numpy.dot(a, b):ベクトルの内積 
・numpy.cross(a, b):ベクトルの外積 (クロス積)

a = numpy.array([1, 2])
print(a)  # [1 2] が出力

# ベクトルの次元
a = numpy.array([1, 2])
b = numpy.array([1, 2, 3])
print(len(a))  # 2 が出力
print(len(b))  # 3 が出力

# ベクトルの大きさ(ノルム)
a = numpy.array([3, 4])
numpy.linalg.norm(a)  # 5.0 が出力

b = numpy.array([1, 1, 1])
numpy.linalg.norm(b)  # 1.7320508075688772 が出力

# ベクトルの和、差、スカラー倍
a = numpy.array([5, 7])
b = numpy.array([2, 3])
print(a+b)  # [ 7 10] が出力
print(a-b)  # [3 4] が出力
print(2*a)  # [10 14] が出力
print(-3*b)  # [-6 -9] が出力

# ベクトル\vec{a} とベクトル\vec{b} の内積はnumpy.dot(a, b)を使います。
# これは、内積はdot product(ドット積)とも呼ばれることに由来しています。
a = numpy.array([5, 7])
b = numpy.array([2, 3])
print(numpy.dot(a, b))  # 31 が出力

c = numpy.array([1, 2, 3])
d = numpy.array([2, 3, 4])
print(numpy.dot(c, d))  # 20 が出力

# 2つの空間ベクトル(3次元ベクトル)に対し、それらに垂直なベク トルが外積です。
# ベクトル\vec{a} とベクトル\vec{b} の外積はnumpy.cross(a, b)を使います。
# これは、外積がcross product(クロス積)とも呼ばれることに由来しています。

a = numpy.array([1, 2, 3])
b = numpy.array([-1, 0, 2])
print(numpy.cross(a, b))  # [ 4 -5  2] が出力

a = numpy.array([1, 0, 0])  # x軸
b = numpy.array([0, 1, 0])  # y軸
print(numpy.cross(a, b))  # [0 0 1] (z軸)が出力

行列

 行ベクトルを集めたものが行列

・numpy.array( ):行列の定義
  A[行-1, 列-1]:行列Aの(行, 列)成分を取得する。
  Pythonルール:ナンバリングは0スタートより、1行(列)、2行(列)、3行(列)は、Pythonではそれぞれ0、1、2となります
 ・A.shape  メソッド:行列Aの行と列をタプル(行, 列)として取得。
 ・A.size メソッド:行列Aの要素数を取得する
・numpy.dot(A, B):行列の積AB
・numpy.dot(A, x):行列Aとベクトルxの積
・numpy.linalg.inv(A):行列Aの逆行列(inverse matrix)
 [逆行列を用いた方程式の解]
    Av=cから、解ベクトル$${\vec{v}v}}$$を、
   $${\vec{v}=A^{-1}cv=A−1c}$$として求める

A = numpy.array([[1, 2], [3, 4]])
print(A)

[[1 2]
 [3 4]]

B = numpy.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
print(B)

[[1 2 3]
 [4 5 6]
 [7 8 9]]

# 行列の形状 
A = numpy.array([[1, 2], [3, 4]])
print(A.shape)  # (2, 2) が出力

B = numpy.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
print(B.shape)  # (3, 3) が出力

C = numpy.array([[11, 12, 13], [21, 22, 23]])
print(C.shape)  # (2, 3) が出力

# 要素数の取得
A = numpy.array([[1, 2], [3, 4]])
print(A.size)  # 4 が出力

B = numpy.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
print(B.size)  # 9 が出力

C = numpy.array([[11, 12, 13], [21, 22, 23]])
print(C.size)  # 6 が出力

# 行列の積ABABはnumpy.dot(A, B)
A = numpy.array([[1, 2], [3, 4]])
B = numpy.array([[1, 1], [1, 1]])

print(numpy.dot(A, B))

[[3 3]
 [7 7]]

# 行列Aとベクトルxの積
A = numpy.array([[1, 2], [3, 4]])
x = numpy.array([5, 6])
print(numpy.dot(A, x))  # [17 39] が出力
print(A@x)  # [17 39] が出力

# 方程式の解
# NumPyモジュールをインポートします
import numpy as np

# 係数行列Aの定義
A = np.array([[1,1],[2,4]])

# 右辺の50,156を列ベクトルcとして定義
c = np.array([50,156])

# 解ベクトルvをv=A^{-1}cとして計算
v = np.dot(np.linalg.inv(A), c)

# 解ベクトルの出力
v

標準モジュール

itertools 効率的なループ実行のためのイテレータ生成関数

itertools.permutations() <- 順列

import pprint
card = ('a', 'b', 'c') 
permutations = list(itertools.permutations(card))
pprint.pprint(permutatios)

output >> 
[('a', 'b', 'c'),
 ('a', 'c', 'b'),
 ('b', 'a', 'c'),
 ('b', 'c', 'a'),
 ('c', 'a', 'b'),
 ('c', 'b', 'a')]

itertools.combinations() <- 組合せ

card = ('a', 'b', 'c', 'd', 'e') 
combinations = list(itertools.combinations(card, 3))
pprint.pprint(combinations)

output>>
[('a', 'b', 'c'),
 ('a', 'b', 'd'),
 ('a', 'b', 'e'),
 ('a', 'c', 'd'),
 ('a', 'c', 'e'),
 ('a', 'd', 'e'),
 ('b', 'c', 'd'),
 ('b', 'c', 'e'),
 ('b', 'd', 'e'),
 ('c', 'd', 'e')]

pprint データ出力の整然化

・pprint() <- Pythonの任意のデータ構造をインタープリタへの入力で使われる形式にして "pretty-print" できます

set 集合を扱う

 ・リスト型では要素に重複があるのに対し、set型では要素に重複はない
 ・
リスト型では要素に順番があるのに対し、set型では要素に順番はない

s = {1, 2, 3, 1, 2, 1, 2, 3}
print(s)  # {1, 2, 3} が出力
print(type(s))  # <class 'set'> が出力

s = {'a', 'c', 'b'}
print(s)  # {'b', 'a', 'c'} が出力
print(type(s))  # <class 'set'> が出力

s = set(('dadcba'))
print(s)  # {'b', 'd', 'a', 'c'} が出力
print(type(s))  # <class 'set'> が出力

s = {1, 2, 3}
s.add(4)
print(s)  # {1, 2, 3, 4} が出力

s = {1, 2, 3}
s.remove(2)
print(s)  # {1, 3} が出力

s = {1, 2, 3}
s.clear()
print(s)  # set() が出力

A = set('abc')
B = set('bdce')

# 和集合
print(A|B)   # {'b', 'd', 'a', 'e', 'c'} が出力
# 積集合
print(A&B)   # {'b', 'c'} が出力
# 差集合
print(A - B)   # {'a'} が出力
print(B - A)  # {'d', 'e'} が出力

decimal (十進数)

小数と誤差 Python'0.1'問題を解決

"""
0.1 + 0.2  # 0.3 と出力
0.1 + 0.1 + 0.1   # 0.30000000000000004 と出力
0.1 + 0.1 + 0.1 == 0.3   # False と出力
0.1 + 0.1 == 0.2   # True と出力
"""
from decimal import Decimal
d1 = Decimal('0.1')
d3 = Decimal('0.3')
d1 + d1 + d1 == d3  # True と出力
type(d1)    # <class 'decimal.Decimal'> と出力
format(d1 + d1 + d1,'.30f')   # format(引数, '.30f')で引数を小数点以下30桁表示  '0.300000000000000000000000000000' と出力
format(d3,'.30f')   # '0.300000000000000000000000000000' と出力

・getcontext().prec <- 有効数字の桁数の設定

random

・random.randint(a, b) <- aからbの範囲のランダムな整数値

標準関数

divmod() <- 商と余りをタプルで返す(

# 13 ÷ 4 = 3 余り 1
divmod(13, 4)    # (3, 1) が出力される

・指数関数: a**x  or pow(a, x)

2**3  # 8 が出力
pow(2, 3)  # 8 を出力





この記事が気に入ったらサポートをしてみませんか?