2013-01-18 59 views
3

我有一個Numpy矩陣,例如,numpy.matrix([[-1, 2],[1, -2]], dtype='int')。我想要得到它的整數 -valued特徵向量,如果有的話;例如,上述矩陣的numpy.array([[-1], [1]])。 Numpy返回的是浮點數的特徵向量,縮放爲單位長度。如何獲得Numpy矩陣的整數特徵向量?

可以在Sage中做到這一點,其中可以指定矩陣的字段(即數據類型),並且在矩陣上完成的操作將遵循指定的字段。

任何想法如何在Python中很好地做到這一點?提前謝謝了。

+1

我想你指的是什麼是模數有限域上?如果是這樣,那麼NumPy不能這樣做,因爲NumPy是用於Numerics的。 –

+0

感謝您的評論!不,我不這樣做。由於矩陣的特徵向量被確定爲乘法常數,因此我正在尋找一種方法來獲取特徵向量,使得所有條目都是整數。例如,對於我的問題中的矩陣,Numpy會返回'numpy.array([[ - 0.70710678],[0.70710678]])'作爲答案,其中0.70710678確實是srqt(2)/ 2,使其成爲一個單位向量。對於一個任意的特徵向量,是否有一種很好的方法來知道如何重新調整向量使其成爲整數值? – Lei

回答

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,但可能不會那麼健壯。

+0

非常感謝Jaime提供的信息!我覺得它很有趣。不幸的是,當'numpy'將一個向量縮放到一個單位向量時,這些元素通常變得不合理。例如,'numpy.array([1,1])'將成爲'numpy.array([0.70710678,0.70710678])',其元素爲sqrt(2)/ 2。所以你介紹的'fractions'模塊不適用於這種情況。 – Lei

2

我個人滿意以下解決方案:我在Python中調用sage,並讓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])]

相關問題