Suppose I have the unit vector, u.
from numpy import mat
u = mat([[0.9**0.5], [-(0.1)**0.5]])
# [ 0.9486833 -0.31622777]
The unit vector is an eigenvector of a matrix with integer entries. I also know that the eigenvalues are integers. So, the unit vector will contain irrational decimals that, when squared, are decimal approximations of rational numbers.
Is there any good way to find the smallest value k such that all entries of ku are integers? In general, k will be the square root of an integer.
A naive approach would be to square each entry in the vector and find the smallest ki that produces an integer. Then, k will be the square root the of LCM of all ki. I'm hoping there is a better approach than this.
Note that this is not a duplicate of this question.
I've improved the methodology provided by Christian in order to accept a wider range of fractions. The trick was to "pre-normalize" the unit vector by dividing it by the smallest non-zero entry. This works reliably for all fractions of a specified maximum denominator.
from fractions import Fraction, gcd
def recover_integer_vector(u, denom=50):
'''
For a given vector u, return the smallest vector with all integer entries.
'''
# make smallest non-zero entry 1
u /= min(abs(x) for x in u if x)
# get the denominators of the fractions
denoms = (Fraction(x).limit_denominator(denom).denominator for x in u)
# multiply the scaled u by LCM(denominators)
lcm = lambda a, b: a * b / gcd(a, b)
return u * reduce(lcm, denoms)
The following code was used to ensure that all fractions in the given range work correctly.
import numpy as np
from numpy import array
from itertools import combinations_with_replacement
for t in combinations_with_replacement(range(1, 50), 3):
if reduce(gcd, t) != 1: continue
v = array(map(float, t))
u = v / np.linalg.norm(v)
w = recover_integer_vector(u)
assert np.allclose(w, v) or np.allclose(w, -v)
As can be seen by the testing time, this code is not very quick. It took my computer about 6 seconds to test. I'm not sure whether the timing can be improved.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With