Bidiagonalizace

příprava

In [1]:
import numpy as np;
import math;

matice pro příklad:

In [4]:
A = np.array([[3,   -5,   15,   -4],
              [7,    7,    9,   -1],
              [0,    8,   -1,    6],
              [-10,  7,    8,  -10]])

funkce na vytvoření Householderova reflektoru

In [10]:
def make_householder(x,y):
    w = (x - y) / np.linalg.norm(x - y);    
    return (np.identity(len(x)) - 2 * np.dot(w[:,None],w[None,:]))

ukázka použití Householderova reflektoru.

In [11]:
x = A[:,0]
y = np.array([np.linalg.norm(x),0,0,0])
H = make_householder(x,y)
np.dot(H,A)
Out[11]:
array([[  1.25698051e+01,  -2.86400622e+00,   2.22756040e+00,
          6.44401400e+00],
       [  8.88178420e-16,   5.43759029e+00,   1.83426226e+01,
         -8.63945528e+00],
       [  0.00000000e+00,   8.00000000e+00,  -1.00000000e+00,
          6.00000000e+00],
       [ -6.66133815e-16,   9.23201388e+00,  -5.34660370e+00,
          9.13507541e-01]])

pro zpřehlednění výsledku, zaokrouhlíme

In [13]:
np.around(np.dot(H,A),2)
Out[13]:
array([[ 12.57,  -2.86,   2.23,   6.44],
       [  0.  ,   5.44,  18.34,  -8.64],
       [  0.  ,   8.  ,  -1.  ,   6.  ],
       [ -0.  ,   9.23,  -5.35,   0.91]])

pokračujeme pro submatici

In [15]:
A1 = np.transpose(np.dot(H,A))[1:,:]
A1
Out[15]:
array([[ -2.86400622,   5.43759029,   8.        ,   9.23201388],
       [  2.2275604 ,  18.34262259,  -1.        ,  -5.3466037 ],
       [  6.444014  ,  -8.63945528,   6.        ,   0.91350754]])
In [20]:
x = A1[:,0]
y = np.array([np.linalg.norm(x),0,0]);

W1 = make_householder(x,y)

WT = np.pad(W1,((1,0),(1,0)),'constant')
WT[0,0] = 1

WT
Out[20]:
array([[ 1.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        , -0.38727592,  0.30121461,  0.87137083],
       [ 0.        ,  0.30121461,  0.93459827, -0.18919785],
       [ 0.        ,  0.87137083, -0.18919785,  0.45267765]])
In [21]:
np.around(np.dot(np.dot(H,A),WT),2)
Out[21]:
array([[ 12.57,   7.4 ,  -0.  ,  -0.  ],
       [  0.  ,  -4.11,  20.42,  -2.64],
       [  0.  ,   1.83,   0.34,   9.88],
       [ -0.  ,  -4.39,  -2.39,   9.47]])

uděláme bidiagonalizační proceduru

In [25]:
def bidiagonalize_step(A):
    x = A[:,0]
    y = np.zeros(np.size(x))
    y[0] = np.linalg.norm(x);
    H = make_householder(x,y)
    return(H)

def bidiagonalize(A):
    
    colnum = np.size(A,1)
    
    H = np.identity(colnum)
    W = np.identity(colnum)
            
    for i in range(colnum-1):
        
        xlist = [0]
        if (i!=colnum-2): xlist = [0,1]
        
        for col in xlist:
            
            A1 = A
            if (col): A1 = np.transpose(A);
            A1 = A1[i+col:,i:]   
                
            HH = bidiagonalize_step(A1)
            HH = np.pad(HH,((i+col,0),(i+col,0)),'constant')
            
            for k in range(i+col):
                HH[k,k]=1;

            if (col):
                W = np.dot(W,HH)
                A = np.dot(A,HH)
            else:
                H = np.dot(HH,H)
                A = np.dot(HH,A)
                
    return [np.transpose(H),A,np.transpose(W)]

testneme

In [30]:
[H,B,W] = bidiagonalize(A)
In [31]:
np.around(H,2)
Out[31]:
array([[ 0.24,  0.19, -0.87, -0.39],
       [ 0.56, -0.79, -0.12,  0.21],
       [ 0.  ,  0.29, -0.34,  0.89],
       [-0.8 , -0.5 , -0.34,  0.03]])
In [32]:
np.around(B,2)
Out[32]:
array([[ 12.57,   7.4 ,   0.  ,  -0.  ],
       [ -0.  ,   6.28,  11.75,   0.  ],
       [ -0.  ,  -0.  ,  15.91,   6.76],
       [ -0.  ,  -0.  ,  -0.  ,  13.42]])
In [33]:
np.around(W,2)
Out[33]:
array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  , -0.39,  0.3 ,  0.87],
       [ 0.  , -0.45, -0.89,  0.11],
       [ 0.  ,  0.81, -0.35,  0.48]])
In [34]:
np.around(np.dot(np.dot(H,B),W),2)
Out[34]:
array([[  3.,  -5.,  15.,  -4.],
       [  7.,   7.,   9.,  -1.],
       [  0.,   8.,  -1.,   6.],
       [-10.,   7.,   8., -10.]])
In [35]:
A
Out[35]:
array([[  3,  -5,  15,  -4],
       [  7,   7,   9,  -1],
       [  0,   8,  -1,   6],
       [-10,   7,   8, -10]])
In [41]:
T = np.dot(B,np.transpose(B))
np.around(T)
Out[41]:
array([[ 213.,   46.,   -0.,   -0.],
       [  46.,  178.,  187.,   -0.],
       [  -0.,  187.,  299.,   91.],
       [  -0.,   -0.,   91.,  180.]])

QR algorithmus pro tridiagonální matici

Budeme potřebovat QR rozklad tridiagonalní matice

In [37]:
def QRdecomp(T):
    
    siz = np.size(T,0);
    Q = np.identity(siz)

    for i in range(siz-1):
        alpha = math.atan(T[i+1,i]/T[i,i])
        rot = np.identity(siz)
        
        s = math.sin(alpha)
        c = math.cos(alpha)
        
        rot[i,i] = c
        rot[i+1,i+1] = c
        rot[i,i+1] = s
        rot[i+1,i] = -s
        
        T = np.dot(rot,T)
        Q = np.dot(rot,Q)
    return([np.transpose(Q),T])

test

In [42]:
[Q,R]=QRdecomp(T)
In [43]:
np.around(Q)
Out[43]:
array([[ 1., -0.,  0., -0.],
       [ 0.,  1., -0.,  1.],
       [ 0.,  1.,  0., -1.],
       [ 0.,  0.,  1.,  1.]])
In [44]:
np.around(R)
Out[44]:
array([[ 218.,   83.,   40.,   -0.],
       [  -0.,  248.,  345.,   68.],
       [  -0.,   -0.,  108.,  183.],
       [  -0.,    0.,   -0.,   49.]])
In [45]:
np.around(np.dot(Q,R))
Out[45]:
array([[ 213.,   46.,   -0.,   -0.],
       [  46.,  178.,  187.,   -0.],
       [  -0.,  187.,  299.,   91.],
       [  -0.,   -0.,   91.,  180.]])
In [46]:
np.around(np.dot(R,Q))
Out[46]:
array([[ 230.,   53.,   -0.,   -0.],
       [  53.,  420.,   81.,    0.],
       [  -0.,   81.,  192.,   41.],
       [  -0.,   -0.,   41.,   27.]])

nyní můžeme vytvořit QR algoritmus

In [49]:
def QR(T):
    
    siz = np.size(T,0);
    QQ = np.identity(siz)
    
    for i in range(100):
        [Q,R] = QRdecomp(T)
        T = np.dot(R,Q)
    
        QQ = np.dot(QQ,Q)
    
    return(QQ,T)
In [50]:
[Q,TT] = QR(T)
In [51]:
np.around(Q)
Out[51]:
array([[ 0., -1.,  0., -0.],
       [ 1., -0., -0.,  1.],
       [ 1.,  0., -0., -1.],
       [ 0.,  0.,  1.,  0.]])
In [52]:
np.around(TT)
Out[52]:
array([[ 457.,    0.,   -0.,    0.],
       [  -0.,  225.,    0.,    0.],
       [  -0.,    0.,  171.,   -0.],
       [  -0.,   -0.,    0.,   16.]])
In [54]:
BB = np.dot(np.dot(Q,TT),np.transpose(Q));
np.around(BB)
Out[54]:
array([[ 213.,   46.,    0.,   -0.],
       [  46.,  178.,  187.,    0.],
       [   0.,  187.,  299.,   91.],
       [  -0.,    0.,   91.,  180.]])
In [55]:
AA = np.dot(np.dot(H,BB),np.transpose(H));
np.around(AA,4)
Out[55]:
array([[ 275.,  125.,  -79.,   95.],
       [ 125.,  180.,   41.,   61.],
       [ -79.,   41.,  101.,  -12.],
       [  95.,   61.,  -12.,  313.]])
In [56]:
np.dot(A,np.transpose(A))
Out[56]:
array([[275, 125, -79,  95],
       [125, 180,  41,  61],
       [-79,  41, 101, -12],
       [ 95,  61, -12, 313]])

Wilkinsonovův posun

In [69]:
def QR_wilkshift(T):    
    I = np.identity(np.size(T,0))
    n = np.size(T,0);
    for i in range(5):
        mu=wilkshift(T[n-2:n,n-2:n]);
        [Q,R]=QRdecomp(T-mu*I)
        T= np.dot(R,Q) +mu*I
        print(np.around(T,2))
    return(T)

def wilkshift(T):
    l,ll = np.linalg.eig(T);
    if (abs(l[0]-T[1,1]) < abs(l[1]-T[1,1])):
        return(l[0]);
    else:
        return(l[1]);
In [71]:
QR_wilkshift(T)
[[ 244.07   92.87    0.     -0.  ]
 [  92.87  327.63 -171.19   -0.  ]
 [   0.   -171.19  127.14  -24.29]
 [  -0.     -0.    -24.29  170.16]]
[[ 387.58  141.75   -0.     -0.  ]
 [ 141.75  133.24  100.66    0.  ]
 [  -0.    100.66  177.2    -2.51]
 [  -0.      0.     -2.51  170.97]]
[[  4.41440000e+02  -8.07100000e+01   0.00000000e+00  -0.00000000e+00]
 [ -8.07100000e+01   4.06300000e+01  -4.26800000e+01   0.00000000e+00]
 [ -0.00000000e+00  -4.26800000e+01   2.16030000e+02  -3.00000000e-02]
 [ -0.00000000e+00   0.00000000e+00  -3.00000000e-02   1.70900000e+02]]
[[ 452.91   44.01   -0.     -0.  ]
 [  44.01   21.74   15.17    0.  ]
 [  -0.     15.17  223.46   -0.  ]
 [  -0.      0.     -0.    170.9 ]]
[[ 456.06  -23.89   -0.     -0.  ]
 [ -23.89   17.62   -5.26    0.  ]
 [  -0.     -5.26  224.41   -0.  ]
 [  -0.      0.      0.    170.9 ]]
Out[71]:
array([[  4.56063955e+02,  -2.38859575e+01,  -1.42108547e-14,
         -3.21551103e-14],
       [ -2.38859575e+01,   1.76244512e+01,  -5.26488250e+00,
          1.76087227e-14],
       [ -1.20805713e-14,  -5.26488250e+00,   2.24413073e+02,
         -1.68443336e-15],
       [ -1.50326906e-14,   5.36905992e-15,   5.28220246e-16,
          1.70898521e+02]])

Toto není celé, .. Dodělejte za domácí úkol.

In [72]:
U = np.dot(H,Q)
Sigma = np.diag(np.sqrt(np.diag(TT)))
In [73]:
AA
Out[73]:
array([[ 275.,  125.,  -79.,   95.],
       [ 125.,  180.,   41.,   61.],
       [ -79.,   41.,  101.,  -12.],
       [  95.,   61.,  -12.,  313.]])
In [74]:
U_Sigma = np.dot(U,Sigma)
In [78]:
np.around(np.dot(U_Sigma,np.transpose(U_Sigma)))
Out[78]:
array([[ 275.,  125.,  -79.,   95.],
       [ 125.,  180.,   41.,   61.],
       [ -79.,   41.,  101.,  -12.],
       [  95.,   61.,  -12.,  313.]])
In [79]:
[Q,TT2] = QR(np.dot(np.transpose(B),B))
In [80]:
Q
Out[80]:
array([[ 0.06091791, -0.75331117,  0.37653632, -0.53575338],
       [ 0.19618207, -0.53927564,  0.05224741,  0.817291  ],
       [ 0.88787085, -0.00369461, -0.41958229, -0.18873897],
       [ 0.41168793,  0.37641786,  0.8242823 ,  0.09685727]])
In [82]:
np.diag(TT2)
Out[82]:
array([ 457.36176039,  224.54545526,  170.89852103,   16.19426332])
In [86]:
V = np.dot(np.transpose(Q),W)
In [87]:
V
Out[87]:
array([[ 0.06091791, -0.13972957, -0.87231299,  0.46458014],
       [-0.75331117,  0.51423891, -0.28955581, -0.29023792],
       [ 0.37653632,  0.83202133,  0.10294412,  0.39416166],
       [-0.53575338, -0.15418979,  0.3803025 ,  0.73794568]])
In [91]:
np.around(np.dot(U,np.dot(Sigma,V)))
Out[91]:
array([[  3.,  -5.,  15.,  -4.],
       [  7.,   7.,   9.,  -1.],
       [ -0.,   8.,  -1.,   6.],
       [-10.,   7.,   8., -10.]])
In [95]:
[_U,_Sigma,_V] = np.linalg.svd(A, full_matrices=True)
print(_U)
print(_Sigma)
print(_V)
[[ 0.65751436 -0.53477469 -0.23430165  0.47622855]
 [ 0.41462037 -0.26622039  0.68785784 -0.53298053]
 [-0.11886071  0.17764884  0.68219398  0.69923129]
 [ 0.61776772  0.78203812 -0.08102902 -0.01461941]]
[ 21.38601787  14.98484085  13.07281611   4.02420965]
[[-0.06091791  0.13972957  0.87231299 -0.46458014]
 [-0.75331117  0.51423891 -0.28955581 -0.29023792]
 [ 0.37653632  0.83202133  0.10294412  0.39416166]
 [-0.53575338 -0.15418979  0.3803025   0.73794568]]
In [96]:
U
Out[96]:
array([[-0.65751436, -0.53477469, -0.23430165,  0.47622855],
       [-0.41462037, -0.26622039,  0.68785784, -0.53298053],
       [ 0.11886071,  0.17764884,  0.68219398,  0.69923129],
       [-0.61776772,  0.78203812, -0.08102902, -0.01461941]])
In [97]:
V
Out[97]:
array([[ 0.06091791, -0.13972957, -0.87231299,  0.46458014],
       [-0.75331117,  0.51423891, -0.28955581, -0.29023792],
       [ 0.37653632,  0.83202133,  0.10294412,  0.39416166],
       [-0.53575338, -0.15418979,  0.3803025 ,  0.73794568]])
In [102]:
my_data = np.genfromtxt('iris.csv', delimiter=',')[:,:-1]
In [103]:
my_data
Out[103]:
array([[ 5.1,  3.5,  1.4,  0.2],
       [ 4.9,  3. ,  1.4,  0.2],
       [ 4.7,  3.2,  1.3,  0.2],
       [ 4.6,  3.1,  1.5,  0.2],
       [ 5. ,  3.6,  1.4,  0.2],
       [ 5.4,  3.9,  1.7,  0.4],
       [ 4.6,  3.4,  1.4,  0.3],
       [ 5. ,  3.4,  1.5,  0.2],
       [ 4.4,  2.9,  1.4,  0.2],
       [ 4.9,  3.1,  1.5,  0.1],
       [ 5.4,  3.7,  1.5,  0.2],
       [ 4.8,  3.4,  1.6,  0.2],
       [ 4.8,  3. ,  1.4,  0.1],
       [ 4.3,  3. ,  1.1,  0.1],
       [ 5.8,  4. ,  1.2,  0.2],
       [ 5.7,  4.4,  1.5,  0.4],
       [ 5.4,  3.9,  1.3,  0.4],
       [ 5.1,  3.5,  1.4,  0.3],
       [ 5.7,  3.8,  1.7,  0.3],
       [ 5.1,  3.8,  1.5,  0.3],
       [ 5.4,  3.4,  1.7,  0.2],
       [ 5.1,  3.7,  1.5,  0.4],
       [ 4.6,  3.6,  1. ,  0.2],
       [ 5.1,  3.3,  1.7,  0.5],
       [ 4.8,  3.4,  1.9,  0.2],
       [ 5. ,  3. ,  1.6,  0.2],
       [ 5. ,  3.4,  1.6,  0.4],
       [ 5.2,  3.5,  1.5,  0.2],
       [ 5.2,  3.4,  1.4,  0.2],
       [ 4.7,  3.2,  1.6,  0.2],
       [ 4.8,  3.1,  1.6,  0.2],
       [ 5.4,  3.4,  1.5,  0.4],
       [ 5.2,  4.1,  1.5,  0.1],
       [ 5.5,  4.2,  1.4,  0.2],
       [ 4.9,  3.1,  1.5,  0.1],
       [ 5. ,  3.2,  1.2,  0.2],
       [ 5.5,  3.5,  1.3,  0.2],
       [ 4.9,  3.1,  1.5,  0.1],
       [ 4.4,  3. ,  1.3,  0.2],
       [ 5.1,  3.4,  1.5,  0.2],
       [ 5. ,  3.5,  1.3,  0.3],
       [ 4.5,  2.3,  1.3,  0.3],
       [ 4.4,  3.2,  1.3,  0.2],
       [ 5. ,  3.5,  1.6,  0.6],
       [ 5.1,  3.8,  1.9,  0.4],
       [ 4.8,  3. ,  1.4,  0.3],
       [ 5.1,  3.8,  1.6,  0.2],
       [ 4.6,  3.2,  1.4,  0.2],
       [ 5.3,  3.7,  1.5,  0.2],
       [ 5. ,  3.3,  1.4,  0.2],
       [ 7. ,  3.2,  4.7,  1.4],
       [ 6.4,  3.2,  4.5,  1.5],
       [ 6.9,  3.1,  4.9,  1.5],
       [ 5.5,  2.3,  4. ,  1.3],
       [ 6.5,  2.8,  4.6,  1.5],
       [ 5.7,  2.8,  4.5,  1.3],
       [ 6.3,  3.3,  4.7,  1.6],
       [ 4.9,  2.4,  3.3,  1. ],
       [ 6.6,  2.9,  4.6,  1.3],
       [ 5.2,  2.7,  3.9,  1.4],
       [ 5. ,  2. ,  3.5,  1. ],
       [ 5.9,  3. ,  4.2,  1.5],
       [ 6. ,  2.2,  4. ,  1. ],
       [ 6.1,  2.9,  4.7,  1.4],
       [ 5.6,  2.9,  3.6,  1.3],
       [ 6.7,  3.1,  4.4,  1.4],
       [ 5.6,  3. ,  4.5,  1.5],
       [ 5.8,  2.7,  4.1,  1. ],
       [ 6.2,  2.2,  4.5,  1.5],
       [ 5.6,  2.5,  3.9,  1.1],
       [ 5.9,  3.2,  4.8,  1.8],
       [ 6.1,  2.8,  4. ,  1.3],
       [ 6.3,  2.5,  4.9,  1.5],
       [ 6.1,  2.8,  4.7,  1.2],
       [ 6.4,  2.9,  4.3,  1.3],
       [ 6.6,  3. ,  4.4,  1.4],
       [ 6.8,  2.8,  4.8,  1.4],
       [ 6.7,  3. ,  5. ,  1.7],
       [ 6. ,  2.9,  4.5,  1.5],
       [ 5.7,  2.6,  3.5,  1. ],
       [ 5.5,  2.4,  3.8,  1.1],
       [ 5.5,  2.4,  3.7,  1. ],
       [ 5.8,  2.7,  3.9,  1.2],
       [ 6. ,  2.7,  5.1,  1.6],
       [ 5.4,  3. ,  4.5,  1.5],
       [ 6. ,  3.4,  4.5,  1.6],
       [ 6.7,  3.1,  4.7,  1.5],
       [ 6.3,  2.3,  4.4,  1.3],
       [ 5.6,  3. ,  4.1,  1.3],
       [ 5.5,  2.5,  4. ,  1.3],
       [ 5.5,  2.6,  4.4,  1.2],
       [ 6.1,  3. ,  4.6,  1.4],
       [ 5.8,  2.6,  4. ,  1.2],
       [ 5. ,  2.3,  3.3,  1. ],
       [ 5.6,  2.7,  4.2,  1.3],
       [ 5.7,  3. ,  4.2,  1.2],
       [ 5.7,  2.9,  4.2,  1.3],
       [ 6.2,  2.9,  4.3,  1.3],
       [ 5.1,  2.5,  3. ,  1.1],
       [ 5.7,  2.8,  4.1,  1.3],
       [ 6.3,  3.3,  6. ,  2.5],
       [ 5.8,  2.7,  5.1,  1.9],
       [ 7.1,  3. ,  5.9,  2.1],
       [ 6.3,  2.9,  5.6,  1.8],
       [ 6.5,  3. ,  5.8,  2.2],
       [ 7.6,  3. ,  6.6,  2.1],
       [ 4.9,  2.5,  4.5,  1.7],
       [ 7.3,  2.9,  6.3,  1.8],
       [ 6.7,  2.5,  5.8,  1.8],
       [ 7.2,  3.6,  6.1,  2.5],
       [ 6.5,  3.2,  5.1,  2. ],
       [ 6.4,  2.7,  5.3,  1.9],
       [ 6.8,  3. ,  5.5,  2.1],
       [ 5.7,  2.5,  5. ,  2. ],
       [ 5.8,  2.8,  5.1,  2.4],
       [ 6.4,  3.2,  5.3,  2.3],
       [ 6.5,  3. ,  5.5,  1.8],
       [ 7.7,  3.8,  6.7,  2.2],
       [ 7.7,  2.6,  6.9,  2.3],
       [ 6. ,  2.2,  5. ,  1.5],
       [ 6.9,  3.2,  5.7,  2.3],
       [ 5.6,  2.8,  4.9,  2. ],
       [ 7.7,  2.8,  6.7,  2. ],
       [ 6.3,  2.7,  4.9,  1.8],
       [ 6.7,  3.3,  5.7,  2.1],
       [ 7.2,  3.2,  6. ,  1.8],
       [ 6.2,  2.8,  4.8,  1.8],
       [ 6.1,  3. ,  4.9,  1.8],
       [ 6.4,  2.8,  5.6,  2.1],
       [ 7.2,  3. ,  5.8,  1.6],
       [ 7.4,  2.8,  6.1,  1.9],
       [ 7.9,  3.8,  6.4,  2. ],
       [ 6.4,  2.8,  5.6,  2.2],
       [ 6.3,  2.8,  5.1,  1.5],
       [ 6.1,  2.6,  5.6,  1.4],
       [ 7.7,  3. ,  6.1,  2.3],
       [ 6.3,  3.4,  5.6,  2.4],
       [ 6.4,  3.1,  5.5,  1.8],
       [ 6. ,  3. ,  4.8,  1.8],
       [ 6.9,  3.1,  5.4,  2.1],
       [ 6.7,  3.1,  5.6,  2.4],
       [ 6.9,  3.1,  5.1,  2.3],
       [ 5.8,  2.7,  5.1,  1.9],
       [ 6.8,  3.2,  5.9,  2.3],
       [ 6.7,  3.3,  5.7,  2.5],
       [ 6.7,  3. ,  5.2,  2.3],
       [ 6.3,  2.5,  5. ,  1.9],
       [ 6.5,  3. ,  5.2,  2. ],
       [ 6.2,  3.4,  5.4,  2.3],
       [ 5.9,  3. ,  5.1,  1.8]])
In [146]:
[_U,_Sigma,_V] = np.linalg.svd(my_data,full_matrices=False)
In [147]:
_Sigma
Out[147]:
array([ 95.95066751,  17.72295328,   3.46929666,   1.87891236])
In [148]:
np.shape(_U)
Out[148]:
(150, 4)
In [149]:
_Sigma
Out[149]:
array([ 95.95066751,  17.72295328,   3.46929666,   1.87891236])
In [150]:
_Sigma = np.diag(_Sigma[:2])
_Sigma
Out[150]:
array([[ 95.95066751,   0.        ],
       [  0.        ,  17.72295328]])
In [151]:
transformed_data = np.dot(_U[:,0:2],_Sigma)
In [130]:
from matplotlib import pyplot as plt
In [153]:
plt.figure(figsize=(5, 4))
plt.scatter(transformed_data[:,0],transformed_data[:,1])
plt.show()
<matplotlib.figure.Figure at 0x187a517af60>