3

たとえば、 Numpy マトリックスがありnumpy.matrix([[-1, 2],[1, -2]], dtype='int')ます。もしあれば、その整数値の固有ベクトルを取得したい。たとえば、numpy.array([[-1], [1]])上記のマトリックスの場合。Numpy が返すものは、浮動小数点数の固有ベクトルであり、単位長になるようにスケーリングされます。

Sage でこれを行うことができます。行列のフィールド (つまり、データ型) を指定でき、行列に対して実行される操作は、指定したフィールドを尊重します。

Pythonでこれをうまく行う方法のアイデアはありますか? よろしくお願いします。

4

2 に答える 2

2

私は個人的に次の解決策に満足しています。私sageは Python で呼び出し、sage必要なものを計算させました。sage、数学指向であるため、実数以外のフィールドを含む計算ではかなり用途が広いです。

以下は私のスクリプトcompute_intarrs.pyで、インストールする必要sageがあります。少し遅いので注意。

import subprocess
import re
import numpy as np

# construct a numpy matrix
mat = np.matrix([[1,-1],[-1,1]])
# convert the matrix into a string recognizable by sage
matstr = re.sub('\s|[a-z]|\(|\)', '', mat.__repr__())

# write a (sage) python script "mat.py";
# for more info of the sage commands: 
# www.sagemath.org/doc/faq/faq-usage.html#how-do-i-import-sage-into-a-python-script
# www.sagemath.org/doc/tutorial/tour_linalg.html
f = open('mat.py', 'w')
f.write('from sage.all import *\n\n')
f.write('A = matrix(ZZ, %s)\n\n' % matstr)
f.write('print A.kernel()')  # this returns the left nullspace vectors
f.close()

# call sage and run mat.py
p = subprocess.Popen(['sage', '-python', 'mat.py'], stdout=subprocess.PIPE)

# process the output from sage
arrstrs = p.communicate()[0].split('\n')[2:-1]
arrs = [np.array(eval(re.sub('(?<=\d)\s*(?=\d|-)', ',', arrstr))) 
        for arrstr in arrstrs]
print arrs

結果:

In [1]: %run compute_intarrs.py

[array([1, 1])]

于 2013-01-30T17:35:55.553 に答える
1

dtype = objectfractions.Fractionクラスを使用して、かなりクールなことを行うことができます。

>>> A = np.array([fractions.Fraction(1, j) for j in xrange(1, 13)]).reshape(3, 4)
>>> A
array([[1, 1/2, 1/3, 1/4],
       [1/5, 1/6, 1/7, 1/8],
       [1/9, 1/10, 1/11, 1/12]], dtype=object)
>>> B = np.array([fractions.Fraction(1, j) for j in xrange(1, 13)]).reshape(4, 3)
>>> B
array([[1, 1/2, 1/3],
       [1/4, 1/5, 1/6],
       [1/7, 1/8, 1/9],
       [1/10, 1/11, 1/12]], dtype=object)
>>> np.dot(A, B)
array([[503/420, 877/1320, 205/432],
       [3229/11760, 751/4620, 1217/10080],
       [1091/6930, 1871/19800, 1681/23760]], dtype=object)

残念ながら、np.linalgモジュールfloatは何かを行う前にすべてを変換するため、整数や有理数として直接解を得ることは期待できません。ただし、計算後はいつでも次のことができます。

def scale_to_int(x) :
    fracs = [fractions.Fraction(j) for j in x.ravel()]
    denominators = [j.denominator for j in fracs]
    lcm = reduce(lambda a, b: max(a, b) / fractions.gcd(a, b) * min(a, b),
                 denominators)
    fracs = map(lambda x : lcm * x, fracs)
    gcd = reduce(lambda a, b: fractions.gcd(a, b), fracs)
    fracs = map(lambda x: x / gcd, fracs)
    return np.array(fracs).reshape(x.shape)

これは遅く、丸め誤差に非常に敏感です。

>>> scale_to_int(np.linspace(0, 1, 5)) # [0, 0.25, 0.5, 0.75, 1]
array([0, 1, 2, 3, 4], dtype=object)
>>> scale_to_int(np.linspace(0, 1, 4)) # [0, 0.33333333, 0.66666667, 1]
array([0, 6004799503160661, 12009599006321322, 18014398509481984], dtype=object)

limit_denominatorの方法を使用してその一部を軽減できますがFraction、おそらくそれほど堅牢ではありません。

于 2013-01-19T04:16:03.987 に答える