mirror of
https://github.com/TREX-CoE/irpjast.git
synced 2024-11-03 20:54:10 +01:00
627 lines
15 KiB
Org Mode
627 lines
15 KiB
Org Mode
#+TITLE: Testing Svd
|
|
#+title: Testing SVD
|
|
#+author: Vijay Gopal Chilkuri
|
|
#+email: vijay.gopal.c@gmail.com
|
|
|
|
* Generate a block random distribution of positions
|
|
|
|
Here's a small function to generate random points inside a 3D box of given length.
|
|
|
|
#+name: generate3Dpoints
|
|
#+begin_src python
|
|
|
|
|
|
def get_sphere_distribution(n, dmin, Ls, maxiter=1e4, allow_wall=True):
|
|
"""Get random points in a box with given dimensions and minimum separation.
|
|
|
|
Parameters:
|
|
|
|
- n: number of points
|
|
- dmin: minimum distance
|
|
- Ls: dimensions of box, shape (3,) array
|
|
- maxiter: maximum number of iterations.
|
|
- allow_wall: whether to allow points on wall;
|
|
(if False: points need to keep distance dmin/2 from the walls.)
|
|
|
|
Return:
|
|
|
|
- ps: array (n, 3) of point positions,
|
|
with 0 <= ps[:, i] < Ls[i]
|
|
- n_iter: number of iterations
|
|
- dratio: average nearest-neighbor distance, divided by dmin.
|
|
|
|
Note: with a fill density (sphere volume divided by box volume) above about
|
|
0.53, it takes very long. (Random close-packed spheres have a fill density
|
|
of 0.64).
|
|
|
|
Author: Han-Kwang Nienhuys (2020)
|
|
Copying: BSD, GPL, LGPL, CC-BY, CC-BY-SA
|
|
See Stackoverflow: https://stackoverflow.com/a/62895898/6228891
|
|
"""
|
|
Ls = np.array(Ls).reshape(3)
|
|
if not allow_wall:
|
|
Ls -= dmin
|
|
|
|
# filling factor; 0.64 is for random close-packed spheres
|
|
# This is an estimate because close packing is complicated near the walls.
|
|
# It doesn't work well for small L/dmin ratios.
|
|
sphere_vol = np.pi/6*dmin**3
|
|
box_vol = np.prod(Ls + 0.5*dmin)
|
|
fill_dens = n*sphere_vol/box_vol
|
|
if fill_dens > 0.64:
|
|
msg = f'Too many to fit in the volume, density {fill_dens:.3g}>0.64'
|
|
raise ValueError(msg)
|
|
|
|
# initial try
|
|
ps = np.random.uniform(size=(n, 3)) * Ls
|
|
|
|
# distance-squared matrix (diagonal is self-distance, don't count)
|
|
dsq = ((ps - ps.reshape(n, 1, 3))**2).sum(axis=2)
|
|
dsq[np.arange(n), np.arange(n)] = np.infty
|
|
|
|
for iter_no in range(int(maxiter)):
|
|
# find points that have too close neighbors
|
|
close_counts = np.sum(dsq < dmin**2, axis=1) # shape (n,)
|
|
n_close = np.count_nonzero(close_counts)
|
|
if n_close == 0:
|
|
break
|
|
|
|
# Move the one with the largest number of too-close neighbors
|
|
imv = np.argmax(close_counts)
|
|
|
|
# new positions
|
|
newp = np.random.uniform(size=3)*Ls
|
|
ps[imv]= newp
|
|
|
|
# update distance matrix
|
|
new_dsq_row = ((ps - newp.reshape(1, 3))**2).sum(axis=-1)
|
|
dsq[imv, :] = dsq[:, imv] = new_dsq_row
|
|
dsq[imv, imv] = np.inf
|
|
else:
|
|
raise RuntimeError(f'Failed after {iter_no+1} iterations.')
|
|
|
|
if not allow_wall:
|
|
ps += dmin/2
|
|
|
|
dratio = (np.sqrt(dsq.min(axis=1))/dmin).mean()
|
|
return ps, iter_no+1, dratio
|
|
#+end_src
|
|
|
|
A function that generates a block random set of points
|
|
|
|
#+name: generateBlocks
|
|
#+begin_src python :noweb yes
|
|
|
|
<<generate3Dpoints>>
|
|
|
|
def generateBlockRandomPointsAtShftApart(n,L1,dmin,shift):
|
|
"""
|
|
Parameters:
|
|
|
|
- n: number of points
|
|
- L1: dimensions of box, shape (3,) array
|
|
- dmin: minimum intra block distance
|
|
- shift: inter block distance
|
|
|
|
Return:
|
|
|
|
- r: array (n, 3) of point positions,
|
|
|
|
"""
|
|
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
|
|
# Quadrant +,+
|
|
dist11,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist11 += np.array([shift,shift,0.0])
|
|
|
|
# Quadrant -,+
|
|
dist21,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist21 += np.array([-shift,shift,0.0])
|
|
|
|
# Quadrant +,-
|
|
dist12,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist12 += np.array([shift,-shift,0.0])
|
|
|
|
# Quadrant -,-
|
|
dist22,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist22 += np.array([-shift,-shift,0.0])
|
|
|
|
xs = np.concatenate((dist11[:,0],dist12[:,0],dist21[:,0],dist22[:,0]))
|
|
ys = np.concatenate((dist11[:,1],dist12[:,1],dist21[:,1],dist22[:,1]))
|
|
zs = np.concatenate((dist11[:,2],dist12[:,2],dist21[:,2],dist22[:,2]))
|
|
|
|
return((np.array((xs,ys,zs))).T)
|
|
#+end_src
|
|
|
|
#+RESULTS: generateBlocks
|
|
#+begin_example
|
|
None
|
|
#+end_example
|
|
|
|
#+begin_src python :noweb yes :results file :exports results
|
|
import numpy as np
|
|
# matplotlib related
|
|
import matplotlib.pyplot as plt
|
|
|
|
<<generateBlocks>>
|
|
|
|
L1 = 1.0
|
|
n = 100 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
shift = -10.0
|
|
kappa = 2.0
|
|
|
|
rlist = generateBlockRandomPointsAtShftApart(n,L1,dmin,shift)
|
|
print(rlist.shape)
|
|
|
|
fig = plt.figure()
|
|
ax = fig.add_subplot(111, projection='3d')
|
|
|
|
xs = rlist.T[0]
|
|
ys = rlist.T[1]
|
|
zs = rlist.T[2]
|
|
ax.scatter(xs, ys, zs, marker='o')
|
|
|
|
fig.savefig('/tmp/test8.png')
|
|
#plt.show()
|
|
return '/tmp/test8.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/test8.png]]
|
|
|
|
#+begin_src python :noweb yes :results file :exports results
|
|
|
|
# matplotlib related
|
|
import matplotlib.pyplot as plt
|
|
# linear algebra
|
|
import numpy as np
|
|
|
|
<<generate3Dpoints>>
|
|
|
|
shift = -1.0
|
|
|
|
# Quadrant +,+
|
|
L1 = 1.0
|
|
n = 50 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
dist11,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist11 += np.array([shift,shift,0.0])
|
|
|
|
# Quadrant -,+
|
|
L1 = 1.0
|
|
n = 50 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
dist21,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist21 += np.array([-shift,shift,0.0])
|
|
|
|
# Quadrant +,-
|
|
L1 = 1.0
|
|
n = 50 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
dist12,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist12 += np.array([shift,-shift,0.0])
|
|
|
|
# Quadrant -,-
|
|
L1 = 1.0
|
|
n = 50 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
dist22,a,b = get_sphere_distribution(n,dmin,Ls)
|
|
dist22 += np.array([-shift,-shift,0.0])
|
|
|
|
|
|
fig = plt.figure()
|
|
ax = fig.add_subplot(111, projection='3d')
|
|
|
|
xs = np.concatenate((dist11[:,0],dist12[:,0],dist21[:,0],dist22[:,0]))
|
|
ys = np.concatenate((dist11[:,1],dist12[:,1],dist21[:,1],dist22[:,1]))
|
|
zs = np.concatenate((dist11[:,2],dist12[:,2],dist21[:,2],dist22[:,2]))
|
|
ax.scatter(xs, ys, zs, marker='o')
|
|
|
|
fig.savefig('/tmp/test3.png')
|
|
#plt.show()
|
|
return '/tmp/test3.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/test3.png]]
|
|
|
|
* Is the SVD decomposition of distances really useful ?
|
|
|
|
The problem is the following:
|
|
|
|
** Given a metric F(r1,r2) finding the best representatin of F(r1,r2)
|
|
|
|
*** Slater metric
|
|
|
|
The metric can be a scaled distance such as
|
|
|
|
\[
|
|
F(r_1,r_2) = \exp(-\kappa(|r_1 - r_2|))
|
|
\]
|
|
|
|
Where,\(\kappa\) is the rate of the breadth of the slater.
|
|
|
|
#+begin_src python :results file :exports results
|
|
# matplotlib related
|
|
import matplotlib
|
|
import matplotlib.pyplot as plt
|
|
# linear algebra
|
|
import numpy
|
|
|
|
# Data for plotting
|
|
|
|
kappa = 1.0/2.0
|
|
xstart = 0.0
|
|
xend = 2.0
|
|
xstep = 0.1
|
|
s = numpy.array(list(map(lambda x : numpy.exp(-x * numpy.arange(xstart,xend,xstep)), [100, 25, 10,5,2,1]))).T
|
|
#s = numpy.exp(-kappa * numpy.arange(0,1,0.1))
|
|
t = numpy.arange(xstart,xend,xstep)
|
|
|
|
fig, ax = plt.subplots()
|
|
ax.plot(t, s)
|
|
|
|
ax.set(xlabel=r'$r_{12}$', ylabel=r'$F(r_1,r_2)$',
|
|
title='Comparison of Kappa')
|
|
#ax.set_yscale('log')
|
|
ax.grid()
|
|
|
|
fig.savefig('/tmp/test1.png')
|
|
#plt.show()
|
|
return '/tmp/test1.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/test1.png]]
|
|
|
|
|
|
*** Gaussian metric
|
|
|
|
The metric can be a scaled distance such as
|
|
|
|
\[
|
|
F(r_1,r_2) = \exp(-\kappa(|r_1 - r_2|^2))
|
|
\]
|
|
|
|
Where,\(\kappa\) is the rate of the breadth of the gaussian.
|
|
|
|
#+begin_src python :results file :exports results
|
|
# matplotlib related
|
|
import matplotlib
|
|
import matplotlib.pyplot as plt
|
|
# linear algebra
|
|
import numpy
|
|
|
|
# Data for plotting
|
|
|
|
kappa = 1.0/2.0
|
|
xstart = 0.0
|
|
xend = 2.0
|
|
xstep = 0.1
|
|
s = numpy.array(list(map(lambda x : numpy.exp(-x * numpy.power(numpy.arange(xstart,xend,xstep),2)), [100, 25, 10,5,2,1]))).T
|
|
#s = numpy.exp(-kappa * numpy.arange(0,1,0.1))
|
|
t = numpy.arange(xstart,xend,xstep)
|
|
|
|
|
|
fig, ax = plt.subplots()
|
|
ax.plot(t, s)
|
|
|
|
ax.set(xlabel=r'$r_{12}$', ylabel=r'$F(r_1,r_2)$',
|
|
title='Comparison of Kappa')
|
|
#ax.set_yscale('log')
|
|
ax.grid()
|
|
|
|
fig.savefig('/tmp/test2.png')
|
|
#plt.show()
|
|
return '/tmp/test2.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/test2.png]]
|
|
|
|
* Generating a box of electrons centered around nucleii
|
|
|
|
** Generate randomly distributed nucleii
|
|
|
|
The nucleii will serve as anchors for the screening of distances for calculating the
|
|
screened \(\tilde{F}(r_1,r_2)\) metric.
|
|
|
|
|
|
|
|
* Calculating SVD of the distance vector
|
|
|
|
** Slater metric
|
|
|
|
Calculate the matrix of the \(F(r_1,r_2)\) metric i.e. the slater metric.
|
|
|
|
#+begin_src python :noweb yes :results file :exports results
|
|
import numpy as np
|
|
from functools import reduce
|
|
import matplotlib.pyplot as plt
|
|
|
|
<<generateBlocks>>
|
|
|
|
L1 = 1.0
|
|
n = 10 # number of points
|
|
dmin = 0.01 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
shift = -1.0
|
|
kappa = 0.6
|
|
|
|
rlist = generateBlockRandomPointsAtShftApart(n,L1,dmin,shift)
|
|
print(rlist.shape)
|
|
|
|
rij = np.zeros(shape=(rlist.shape[0],rlist.shape[0]))
|
|
|
|
def funcF(x,y):
|
|
return(np.exp(-kappa * np.linalg.norm(x-y)))
|
|
|
|
rij = np.array([[funcF(xval, yval) for yval in rlist] for xval in rlist])
|
|
|
|
u,d,vt = np.linalg.svd(rij)
|
|
#print(d)
|
|
#plt.imshow(rij)
|
|
#plt.colorbar()
|
|
#plt.show()
|
|
plt.plot(range(d.shape[0]),d)
|
|
plt.yscale('log')
|
|
plt.savefig('/tmp/plot3.png')
|
|
return '/tmp/plot3.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/plot3.png]]
|
|
|
|
#+begin_src python :results output
|
|
import numpy
|
|
a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
|
|
b = numpy.array([[11,12,13],[14,15,16],[17,18,19]])
|
|
print(list(zip(a,b))[0][1])
|
|
print(numpy.square(a[:,0]))
|
|
|
|
def stepExp(a):
|
|
def myexp(x):
|
|
if numpy.abs(x) > 1e+0:
|
|
return numpy.zeros_like(x)
|
|
else:
|
|
return numpy.exp(x)
|
|
|
|
res = numpy.array([[myexp(x) for x in y] for y in a])
|
|
return(res)
|
|
|
|
print(numpy.exp(a))
|
|
print(stepExp(a))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
#+begin_example
|
|
[11 12 13]
|
|
[ 1 16 49]
|
|
[[2.71828183e+00 7.38905610e+00 2.00855369e+01]
|
|
[5.45981500e+01 1.48413159e+02 4.03428793e+02]
|
|
[1.09663316e+03 2.98095799e+03 8.10308393e+03]]
|
|
[[2.71828183 0. 0. ]
|
|
[0. 0. 0. ]
|
|
[0. 0. 0. ]]
|
|
#+end_example
|
|
|
|
** Gaussian metric
|
|
|
|
Calculate the matrix of the \(FG(r_1,r_2)\) metric i.e. the gaussian metric.
|
|
|
|
#+begin_src python :noweb yes :results file :exports results
|
|
import numpy as np
|
|
from functools import reduce
|
|
import matplotlib.pyplot as plt
|
|
|
|
<<generateBlocks>>
|
|
|
|
L1 = 1.0
|
|
n = 100 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
shift = -10.0
|
|
kappa = 2.0
|
|
|
|
rlist = generateBlockRandomPointsAtShftApart(n,L1,dmin,shift)
|
|
print(rlist.shape)
|
|
|
|
rij = np.zeros(shape=(rlist.shape[0],rlist.shape[0]))
|
|
|
|
def funcF(x,y):
|
|
return(np.exp(-kappa * np.linalg.norm(x-y)))
|
|
|
|
def funcFG(x,y):
|
|
return(np.exp(-kappa * np.square(np.linalg.norm(x-y))))
|
|
|
|
def funcFGD(x,y):
|
|
rij = np.exp(-kappa * 0.1 * np.square(np.linalg.norm(x-y)))
|
|
return(rij)
|
|
|
|
rijSlater = np.array([[funcF(xval, yval) for yval in rlist] for xval in rlist])
|
|
rijGaussian = np.array([[funcFG(xval, yval) for yval in rlist] for xval in rlist])
|
|
rijDeltafn = np.array([[funcFGD(xval, yval) for yval in rlist] for xval in rlist])
|
|
|
|
u,dS,vt = np.linalg.svd(rijSlater)
|
|
dS = dS/np.linalg.norm(dS)
|
|
u,dG,vt = np.linalg.svd(rijGaussian)
|
|
dG = dG/np.linalg.norm(dG)
|
|
u,dGD,vt = np.linalg.svd(rijDeltafn)
|
|
dGD = dGD/np.linalg.norm(dGD)
|
|
|
|
#print(d)
|
|
#plt.imshow(rij)
|
|
#plt.colorbar()
|
|
#plt.show()
|
|
plt.plot(range(dG.shape[0]),np.array([dS,dG,dGD]).T)
|
|
plt.yscale('log')
|
|
plt.savefig('/tmp/plot4.png')
|
|
return '/tmp/plot4.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/plot4.png]]
|
|
|
|
** Palying around
|
|
|
|
Calculate the matrix of the \(FG(r_1,r_2)\) metric i.e. the gaussian metric.
|
|
|
|
#+begin_src python :noweb yes :results file :exports results
|
|
import numpy as np
|
|
from functools import reduce
|
|
import matplotlib.pyplot as plt
|
|
|
|
<<generateBlocks>>
|
|
|
|
L1 = 1.0
|
|
n = 100 # number of points
|
|
dmin = 0.1 # min dist between points
|
|
Ls = np.array([L1,L1,L1]) # lengths of the box
|
|
shift = -1.0
|
|
kappa = 2.0
|
|
|
|
rlist = generateBlockRandomPointsAtShftApart(n,L1,dmin,shift)
|
|
print(rlist.shape)
|
|
|
|
rij = np.zeros(shape=(rlist.shape[0],rlist.shape[0]))
|
|
|
|
|
|
def funcF(x,y):
|
|
rij = np.exp(-kappa * np.linalg.norm(x-y))
|
|
return(rij)
|
|
|
|
def funcFG(x,y):
|
|
rij = np.exp(-kappa * np.square(np.linalg.norm(x-y)))
|
|
return(rij)
|
|
|
|
def myexp(x):
|
|
if np.abs(x) > 1e-0:
|
|
return np.exp(-x)
|
|
else:
|
|
return np.exp(x)
|
|
|
|
def funcFGD(x,y):
|
|
rij = myexp(-kappa * np.square(np.linalg.norm(x-y)))
|
|
return(rij)
|
|
|
|
rijSlater = np.array([[funcF(xval, yval) for yval in rlist] for xval in rlist])
|
|
#rijSlater = rijSlater/np.max(rijSlater)
|
|
rijGaussian = np.array([[funcFG(xval, yval) for yval in rlist] for xval in rlist])
|
|
#rijGaussian = rijGaussian/np.max(rijGaussian)
|
|
rijDeltafn = np.array([[funcFGD(xval, yval) for yval in rlist] for xval in rlist])
|
|
#rijDeltafn = rijDeltafn/np.max(rijDeltafn)
|
|
|
|
u,dS,vt = np.linalg.svd(rijSlater)
|
|
dS = dS/np.linalg.norm(dS)
|
|
u,dG,vt = np.linalg.svd(rijGaussian)
|
|
dG = dG/np.linalg.norm(dG)
|
|
u,dGD,vt = np.linalg.svd(rijDeltafn)
|
|
dGD = dGD/np.linalg.norm(dGD)
|
|
|
|
#print(d)
|
|
#plt.imshow(rij)
|
|
#plt.colorbar()
|
|
#plt.show()
|
|
plt.plot(range(dG.shape[0]),np.array([dS,dG,dGD]).T)
|
|
plt.yscale('log')
|
|
plt.savefig('/tmp/plot5.png')
|
|
return '/tmp/plot5.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/plot5.png]]
|
|
#+begin_src python :results file :exports results
|
|
import numpy
|
|
import matplotlib.pyplot as plt
|
|
|
|
def myexp2(x):
|
|
if numpy.abs(x) > 1e-0:
|
|
return numpy.exp(-x)
|
|
else:
|
|
return numpy.exp(x)
|
|
|
|
def myexp(x):
|
|
return(numpy.array([myexp2(y) for y in x]))
|
|
|
|
kappa = 1.0/2.0
|
|
xstart = 0.0
|
|
xend = 2.0
|
|
xstep = 0.1
|
|
s = numpy.array(list(map(lambda x : myexp(-x * numpy.power(numpy.arange(xstart,xend,xstep),2)), [10,5,1,0.5,0.1]))).T
|
|
#s = numpy.exp(-kappa * numpy.arange(0,1,0.1))
|
|
t = numpy.arange(xstart,xend,xstep)
|
|
|
|
|
|
fig, ax = plt.subplots()
|
|
ax.plot(t, s)
|
|
|
|
ax.set(xlabel=r'$r_{12}$', ylabel=r'$F(r_1,r_2)$',
|
|
title='Comparison of Kappa')
|
|
ax.set_yscale('log')
|
|
ax.grid()
|
|
|
|
fig.savefig('/tmp/test7.png')
|
|
#plt.show()
|
|
return '/tmp/test7.png'
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
[[file:/tmp/test7.png]]
|
|
|
|
** Testing SVD for custom matrices
|
|
|
|
#+begin_src python :results output
|
|
import numpy
|
|
import matplotlib.pyplot as plt
|
|
|
|
a = numpy.array([[0,100,200],[100,0,200],[100,200,0]])
|
|
b = numpy.exp(-a)
|
|
print("Matrix A")
|
|
print(a)
|
|
print("Matrix Exp(A)")
|
|
print(numpy.around(b,10))
|
|
u,d,vt = numpy.linalg.svd(a)
|
|
d = d/numpy.linalg.norm(d)
|
|
print("Singular values of A")
|
|
print(numpy.around(d,3))
|
|
print("Singular vectors of A")
|
|
print(numpy.around(u,3))
|
|
u,d,vt = numpy.linalg.svd(b)
|
|
d = d/numpy.linalg.norm(d)
|
|
print("Singular values of Exp(A)")
|
|
print(numpy.around(d,3))
|
|
print("Singular vectors of Exp(A)")
|
|
print(numpy.around(u,3))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
#+begin_example
|
|
Matrix A
|
|
[[ 0 100 200]
|
|
[100 0 200]
|
|
[100 200 0]]
|
|
Matrix Exp(A)
|
|
[[1. 0. 0.]
|
|
[0. 1. 0.]
|
|
[0. 0. 1.]]
|
|
Singular values of A
|
|
[0.813 0.53 0.24 ]
|
|
Singular vectors of A
|
|
[[-0.67 0.142 0.728]
|
|
[-0.626 0.42 -0.657]
|
|
[-0.399 -0.896 -0.193]]
|
|
Singular values of Exp(A)
|
|
[0.577 0.577 0.577]
|
|
Singular vectors of Exp(A)
|
|
[[-1. 0. -0. ]
|
|
[-0. -0.894 -0.447]
|
|
[-0. -0.447 0.894]]
|
|
#+end_example
|