多様体上の最適化


```bash
(base) $ conda create -n py37_manifold python=3.7 anaconda
```


```bash
(base) $ source activate py37_manifold
(py37_manifold) $ 
```


## autograd インストール

```bash
(py37_manifold) $ pip install autograd

Collecting autograd
  Downloading autograd-1.3.tar.gz (38 kB)
Requirement already satisfied: numpy>=1.12 in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_manifold/lib/python3.7/site-packages (from autograd) (1.20.1)
Requirement already satisfied: future>=0.15.2 in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_manifold/lib/python3.7/site-packages (from autograd) (0.18.2)
Building wheels for collected packages: autograd
  Building wheel for autograd (setup.py) ... done
  Created wheel for autograd: filename=autograd-1.3-py3-none-any.whl size=47989 sha256=5c0ad6c3fbd42a402118ce0201e9446001f6b34f6f61d4b1d34905856546eab6
  Stored in directory: /home/[user_name]/.cache/pip/wheels/ef/32/31/0e87227cd0ca1d99ad51fbe4b54c6fa02afccf7e483d045e04
Successfully built autograd
Installing collected packages: autograd
Successfully installed autograd-1.3
```

## pip install pymanopt

```bash
pip install pymanopt

Collecting pymanopt
  Downloading pymanopt-0.2.5-py3-none-any.whl (59 kB)
     |████████████████████████████████| 59 kB 8.3 MB/s 
Requirement already satisfied: numpy>=1.16 in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_manifold/lib/python3.7/site-packages (from pymanopt) (1.20.1)
Requirement already satisfied: scipy in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_manifold/lib/python3.7/site-packages (from pymanopt) (1.6.2)
Installing collected packages: pymanopt
Successfully installed pymanopt-0.2.5
```

# simple example 

```python
import autograd.numpy as np

from pymanopt.manifolds import Stiefel
from pymanopt import Problem
from pymanopt.solvers import SteepestDescent

# (1) Instantiate a manifold
manifold = Stiefel(5, 2)

# (2) Define the cost function (here using autograd.numpy)
def cost(X): return np.sum(X)

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver
solver = SteepestDescent()

# let Pymanopt do the rest
Xopt = solver.solve(problem)
print(Xopt)

##### result ####
Compiling cost function...
Computing gradient of cost function...
 iter		   cost val	    grad. norm
    1	-1.4015650825981624e-01	3.11267080e+00
    2	-2.3990107640612464e+00	2.04513436e+00
    3	-2.6112734104347544e+00	1.57854640e+00
    4	-3.0634139985391604e+00	5.57823862e-01
    5	-3.1596369194162239e+00	1.15449706e-01
    6	-3.1619163364504663e+00	4.52108520e-02
    7	-3.1621110359538047e+00	3.24263239e-02
    8	-3.1622727108364495e+00	5.56752756e-03
    9	-3.1622776332134630e+00	3.15987307e-04
   10	-3.1622776495823297e+00	2.52182846e-04
   11	-3.1622776563767903e+00	1.54478928e-04
   12	-3.1622776577606118e+00	1.23397289e-04
   13	-3.1622776601144684e+00	1.84594057e-05
   14	-3.1622776601611871e+00	6.74250561e-06
   15	-3.1622776601655738e+00	4.21226109e-06
   16	-3.1622776601674873e+00	2.37418501e-06
   17	-3.1622776601683746e+00	1.74615286e-07
Terminated - min grad norm reached after 17 iterations, 0.01 seconds.

[[-0.9231764   0.29072086]
 [-0.11354918 -0.51890635]
 [-0.20623625 -0.42621928]
 [-0.30163413 -0.33082138]
 [-0.03654288 -0.59591268]]

```

動くことを確認。




# PCA (１番重要な成分)

```math
{\bf Data} =
\begin{bmatrix}
x \\
y \\
z \\
\end{bmatrix}
\sim 

\exp 
\left[
- \frac{1}{2} ({\bf Data} - {\bf \mu})^T \Sigma^{-1} ({\bf Data} - {\bf \mu})
\right]
```

のような場合を考える。
[x,y,z] のデータが5000点あった場合に、このデータを主成分分析する。
結果としてcovariant matrix の固有ベクトルが出てくればOK




```python
import numpy
import autograd.numpy as np

from pymanopt.manifolds import Stiefel
from pymanopt import Problem
from pymanopt.solvers import SteepestDescent

from matplotlib import pyplot

```

Generate data

```python
mean = [0, 0, 0]
cov = [[4, 0, 0], 
       [0, 100, 0], 
       [0, 0, 1]]

x, y, z = np.random.multivariate_normal(mean, cov, 5000).T
```

Find primary component

```python

# (1) Instantiate a manifold
manifold = Stiefel(3,1)

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 
    A = np.dot(np.dot(np.dot(np.transpose(X),Data), Data.T), X)
    
    return A #np.sum(X)

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver
solver = SteepestDescent()

# let Pymanopt do the rest
Xopt = solver.solve(problem)
print(Xopt)

### result ###
Compiling cost function...
Computing gradient of cost function...
 iter		   cost val	    grad. norm
    1	+5.2481256509930645e+03	3.05029353e+03
    2	+5.2438277680737319e+03	1.11796033e+04
    3	+5.2277299499084174e+03	9.76012298e+03
    4	+5.1832913753482308e+03	3.89396089e+03
    5	+5.1730543591517953e+03	2.25383446e+03
    6	+5.1674731117783276e+03	4.15006278e+03
    7	+5.1569814507044375e+03	1.77263618e+03
    8	+5.1548307584959221e+03	4.98835962e+03
    9	+5.1475628151428082e+03	3.46102793e+03
... 
  160	+5.1177163774291039e+03	4.20826319e-03
  161	+5.1177163774290912e+03	4.00752296e-03
  162	+5.1177163774290766e+03	2.64975638e-03
  163	+5.1177163774290730e+03	5.44183447e-03
  164	+5.1177163774290630e+03	3.23481435e-03
  165	+5.1177163774290530e+03	2.77523335e-03
  166	+5.1177163774290530e+03	3.64588563e-03
Terminated - min stepsize reached after 166 iterations, 0.13 seconds.

[[ 2.86165457e-02]
 [-7.81434337e-04]
 [-9.99590157e-01]]

```

```python
print('1st component')
print(Xopt[:,0])

### 
1st component
[ 2.86165457e-02 -7.81434337e-04 -9.99590157e-01]
```

# PCA (2番目に重要な成分まで)


```python

# (1) Instantiate a manifold
manifold = Stiefel(3,2) #(3,M) 3-dimensional data, upto M components

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 
    u1 = X[:,0]
    u2 = X[:,1]
    A = np.dot(np.dot(np.dot(np.transpose(u1),Data), Data.T), u1)
    B = np.dot(np.dot(np.dot(np.transpose(u2),Data), Data.T), u2)
   
    total = 10*A + B  
    return total

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver
solver = SteepestDescent()

# let Pymanopt do the rest
Xopt = solver.solve(problem)
print(Xopt)


### result ###
Compiling cost function...
Computing gradient of cost function...
 iter		   cost val	    grad. norm
    1	+4.5909422299787309e+05	6.73632726e+05
    2	+3.9998838651279337e+05	8.60920616e+05
    3	+3.7217143449324067e+05	1.09219324e+06
    4	+2.9760867757966439e+05	4.61126532e+05
    5	+2.6485839779132232e+05	5.88725860e+05
    6	+2.4115454199115711e+05	4.13853795e+05
    7	+2.3286327975641249e+05	5.18976670e+05
    8	+2.1573780797139945e+05	1.82309867e+05
    9	+2.0890522151030271e+05	4.42702316e+05
...
  378	+7.1325205578285662e+04	2.28983102e-02
  379	+7.1325205578285648e+04	4.54266215e-02
  380	+7.1325205578285590e+04	3.48791035e-02
  381	+7.1325205578285531e+04	2.98695457e-02
  382	+7.1325205578285502e+04	1.62483957e-02
  383	+7.1325205578285430e+04	2.44885487e-02
  384	+7.1325205578285386e+04	2.96063775e-02
  385	+7.1325205578285328e+04	2.70866242e-02
  386	+7.1325205578285269e+04	1.77460039e-02
  387	+7.1325205578285269e+04	3.29106454e-02
Terminated - min stepsize reached after 387 iterations, 0.46 seconds.

[[-2.86166598e-02  9.99582533e-01]
 [ 7.81441481e-04 -3.96006759e-03]
 [ 9.99590154e-01  2.86195374e-02]]
​
```

```python
print('1st component')
print(Xopt[:,0])

print('2nd component')
print(Xopt[:,1])

### 

1st component
[-2.86166598e-02  7.81441481e-04  9.99590154e-01]
2nd component
[ 0.99958253 -0.00396007  0.02861954]
```


# PCA (3番目に重要な成分まで)

```python

# (1) Instantiate a manifold
manifold = Stiefel(3,3) #(3,M) 3-dimensional data, upto M components

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 
    u1 = X[:,0]
    u2 = X[:,1]
    u3 = X[:,2]
    A = np.dot(np.dot(np.dot(np.transpose(u1),Data), Data.T), u1)
    B = np.dot(np.dot(np.dot(np.transpose(u2),Data), Data.T), u2)
    C = np.dot(np.dot(np.dot(np.transpose(u3),Data), Data.T), u3)
    
    total = 100*A + 10*B + C
    return total

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver
solver = SteepestDescent()

# let Pymanopt do the rest
Xopt = solver.solve(problem)
print(Xopt)


### result ###
Compiling cost function...
Computing gradient of cost function...
 iter		   cost val	    grad. norm
    1	+7.5515693235367984e+06	1.84313213e+07
    2	+7.5140587271768823e+06	1.82693517e+07
    3	+7.3652525450036600e+06	1.79735368e+07
    4	+6.7905087199882809e+06	1.67585726e+07
    5	+4.8652095463687042e+06	1.14282554e+07
    6	+3.3966843449406191e+06	3.87973088e+06
    7	+3.1966327865994191e+06	4.20827848e+06
    8	+3.0344506122366516e+06	4.16634281e+06
    9	+2.8484096269338191e+06	3.03847060e+06
...
  202	+1.1948746632160679e+06	2.20285927e-01
  203	+1.1948746632160579e+06	4.73657545e-01
  204	+1.1948746632160575e+06	5.18645036e-01
  205	+1.1948746632160563e+06	3.58986049e-01
  206	+1.1948746632160549e+06	2.63097893e-01
  207	+1.1948746632160544e+06	2.39725167e-01
  208	+1.1948746632160537e+06	1.50571670e-01
  209	+1.1948746632160535e+06	1.06912027e-01
  210	+1.1948746632160530e+06	1.69717464e-01
  211	+1.1948746632160530e+06	3.12776693e-01
Terminated - min stepsize reached after 211 iterations, 0.33 seconds.

[[ 2.86165557e-02 -9.99582536e-01  3.98080911e-03]
 [-7.81442415e-04  3.96006767e-03  9.99991854e-01]
 [-9.99590157e-01 -2.86194333e-02 -6.67792694e-04]]

```

```python
print('1st component')
print(Xopt[:,0])

print('2nd component')
print(Xopt[:,1])

print('3rd component')
print(Xopt[:,2])

###

1st component
[ 2.86165557e-02 -7.81442415e-04 -9.99590157e-01]
2nd component
[-0.99958254  0.00396007 -0.02861943]
3rd component
[ 3.98080911e-03  9.99991854e-01 -6.67792694e-04]
```

## 球面上の最適化

```math 
A=
\begin{bmatrix}
\phantom{-}3, \;-1, \;-1 \\
-1, \;\phantom{-}3, \;-1 \\
-1, \;-1, \;\phantom{-}2
\end{bmatrix}
```

```math 
\text{minimize} \;
f({\bf x}) = {\bf x}^T A {\bf x} \\

\text{subject to} \;\; {\bf x} \in S^{n-1} (=\{ {\bf R}^n | {\bf x}^T {\bf x} = 1 \})
```

```python 
matrixA = np.array([
    [ 3, -1, -1],
    [-1,  3, -1],
    [-1, -1,  2]
])
```

```python
import numpy
import autograd.numpy as np

from pymanopt.manifolds import Sphere
#from pymanopt.manifolds import Stiefel
from pymanopt import Problem
from pymanopt.solvers import SteepestDescent

from matplotlib import pyplot



# (1) Instantiate a manifold
manifold = Sphere(3) # (S^2 = 3D points on a 3D sphere)

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 
    #u1 = X[:,0]
    f = np.dot(np.dot(np.transpose(X),matrixA), X)

    return f

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver
solver = SteepestDescent()

# let Pymanopt do the rest
Xopt = solver.solve(problem)
print(Xopt)


#### result ####
Compiling cost function...
Computing gradient of cost function...
 iter		   cost val	    grad. norm
    1	+9.5168367573129098e-01	1.90613530e+00
    2	+6.1345913743880875e-01	5.64279290e-01
    3	+5.9362092815753753e-01	3.05986125e-01
    4	+5.8643680511659246e-01	9.15532788e-02
    5	+5.8588971695808445e-01	3.72569230e-02
    6	+5.8579775993223548e-01	1.24230572e-02
    7	+5.8578644403132785e-01	2.83158692e-04
    8	+5.8578644116450529e-01	2.14553844e-04
    9	+5.8578643905021832e-01	1.38044960e-04
   10	+5.8578643797209740e-01	6.84790725e-05
   11	+5.8578643773653183e-01	3.86640960e-05
   12	+5.8578643762754434e-01	2.94998009e-06
   13	+5.8578643762697613e-01	9.85281400e-07
Terminated - min grad norm reached after 13 iterations, 0.01 seconds.

[0.5000001  0.4999999  0.70710678]

```

### 途中経過を見る。

これで一応結果は出る。途中の様子を調べるために、少し汚いやり方だが途中結果を表示させる。


```python
import pprint

import numpy
import autograd.numpy as np

from pymanopt.manifolds import Sphere
#from pymanopt.manifolds import Stiefel
from pymanopt import Problem
from pymanopt.solvers import SteepestDescent

from matplotlib import pyplot

global count
#count = 0
#list_x = np.zeros((100,3))
#list_f = np.zeros(100)

# (1) Instantiate a manifold
manifold = Sphere(3) # (S^2 = 3D points on a 3D sphere)

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 
    #print('-'*10)
    #global count
    #u1 = X[:,0]
    f = np.dot(np.dot(np.transpose(X),matrixA), X)
    #list_x[count] = X
    #list_f[count] = f
    print(np.array(X)[0], np.array(X)[1],np.array(X)[2])
    #print(f)
    #count += 1
    return f

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver

"""
solver = SteepestDescent()

# let Pymanopt do the rest
Xopt = solver.solve(problem)
print(Xopt)
"""

solver = SteepestDescent(logverbosity=2)
problem = Problem(manifold, cost, verbosity=0)

print('-'*20)
Xopt, optlog = solver.solve(problem)

print(Xopt)
print('-'*20)

print("Optimization log:")
pprint.pprint(optlog)

```

```shell
--------------------
0.9616324363358425 0.16984109339558884 -0.21544618906117285
Autograd ArrayBox with value 0.9616324363358425 Autograd ArrayBox with value 0.16984109339558884 Autograd ArrayBox with value -0.21544618906117285
0.7187205780055337 0.5801385239928188 0.38324929710415
0.7187205780055337 0.5801385239928188 0.38324929710415
Autograd ArrayBox with value 0.7187205780055337 Autograd ArrayBox with value 0.5801385239928188 Autograd ArrayBox with value 0.38324929710415
-0.2575326064010628 0.0971188143445837 0.961376561260247
-0.07874225379683075 0.21812410557045137 0.9727391901409577
0.19002774090151275 0.3769113266799731 0.9065469152273423
0.19002774090151275 0.3769113266799731 0.9065469152273423
Autograd ArrayBox with value 0.19002774090151275 Autograd ArrayBox with value 0.3769113266799731 Autograd ArrayBox with value 0.9065469152273423
0.21858326650134283 0.3876526096875978 0.895514829474084
0.21858326650134283 0.3876526096875978 0.895514829474084
Autograd ArrayBox with value 0.21858326650134283 Autograd ArrayBox with value 0.3876526096875978 Autograd ArrayBox with value 0.895514829474084
0.3330946075812808 0.42843076548111614 0.8399375343378443
0.3330946075812808 0.42843076548111614 0.8399375343378443
Autograd ArrayBox with value 0.3330946075812808 Autograd ArrayBox with value 0.42843076548111614 Autograd ArrayBox with value 0.8399375343378443
0.73230648901949 0.5333821456801862 0.42335646069187133
0.5765930854538771 0.5079693723414078 0.6399277541799965
0.5765930854538771 0.5079693723414078 0.6399277541799965
Autograd ArrayBox with value 0.5765930854538771 Autograd ArrayBox with value 0.5079693723414078 Autograd ArrayBox with value 0.6399277541799965
0.010726967217156233 0.4178920105409806 0.9084333765886958
0.27619510786373086 0.4823865912308825 0.8312757899715302
0.4283231430188422 0.5028271611532393 0.7508023249571317
0.4283231430188422 0.5028271611532393 0.7508023249571317
Autograd ArrayBox with value 0.4283231430188422 Autograd ArrayBox with value 0.5028271611532393 Autograd ArrayBox with value 0.7508023249571317
0.49145672491644626 0.4947841927424519 0.7167000001022749
0.49145672491644626 0.4947841927424519 0.7167000001022749
Autograd ArrayBox with value 0.49145672491644626 Autograd ArrayBox with value 0.4947841927424519 Autograd ArrayBox with value 0.7167000001022749
0.803166550141483 0.5957192770235286 -0.006483495692386204
0.7346269833035809 0.6023830328792305 0.3121824420134803
0.6395506200667743 0.5687777894589698 0.5171719545667305
0.5715908712554448 0.5369426644994201 0.620464705634176
0.532863685927178 0.5170855981747948 0.6698348874016019
0.5124655076022505 0.5062262193496307 0.6936239026741706
0.5020333536484216 0.5005759206223315 0.7052561658841586
0.5020333536484216 0.5005759206223315 0.7052561658841586
Autograd ArrayBox with value 0.5020333536484216 Autograd ArrayBox with value 0.5005759206223315 Autograd ArrayBox with value 0.7052561658841586
0.40223080950948376 0.4779696317590877 0.780868367266486
0.45284659460775595 0.4902198422485852 0.7447244242120241
0.4776587630700046 0.4956457007074899 0.7253808967932743
0.48990561651582243 0.49817391478158235 0.7154126344547213
0.49598496907488165 0.4993908219360912 0.7103574574943126
0.4990131057472392 0.4999873623735211 0.7078125159668089
0.4990131057472392 0.4999873623735211 0.7078125159668089
Autograd ArrayBox with value 0.4990131057472392 Autograd ArrayBox with value 0.4999873623735211 Autograd ArrayBox with value 0.7078125159668089
0.5074146689926476 0.499281875708236 0.7023161412642793
0.5032203654490438 0.4996409364835715 0.7050731865467232
0.5011183352702268 0.49981573056173606 0.7064450789261926
0.5000661179356378 0.4999019419626531 0.7071293559984262
0.5000661179356378 0.4999019419626531 0.7071293559984262
Autograd ArrayBox with value 0.5000661179356378 Autograd ArrayBox with value 0.4999019419626531 Autograd ArrayBox with value 0.7071293559984262
0.48745371290356493 0.517084371702963 0.7035713398917561
0.4937880028832201 0.5085238438253783 0.705391315845087
0.4969342223647298 0.5042203786988719 0.7062706197680374
0.4985019779504116 0.5020630083159331 0.7067025637849935
0.499284502044205 0.5009829341888 0.7069166044662203
0.49967542378329705 0.5004425524689227 0.7070231414496785
0.49987079934127054 0.5001722757678877 0.7070762890375347
0.499968465763084 0.5000371159975171 0.7071028325974894
0.499968465763084 0.5000371159975171 0.7071028325974894
Autograd ArrayBox with value 0.499968465763084 Autograd ArrayBox with value 0.5000371159975171 Autograd ArrayBox with value 0.7071028325974894
0.5002898975626755 0.49966914189671735 0.7071356072444137
0.5001291966637323 0.4998531439190305 0.7071192411176144
0.5000488349618154 0.4999451337033208 0.7071110421565341
0.5000086512993258 0.49999112578693927 0.7071069387017345
0.5000086512993258 0.49999112578693927 0.7071069387017345
Autograd ArrayBox with value 0.5000086512993258 Autograd ArrayBox with value 0.49999112578693927 Autograd ArrayBox with value 0.7071069387017345
0.4997570255502936 0.5002480480905828 0.7071031083192078
0.49988284650255127 0.5001195950285521 0.7071050349424643
0.4999457509211369 0.5000553624294147 0.7071059896801096
0.49997720161537623 0.5000232446134969 0.707106464905426
0.49999292658364913 0.5000071853265359 0.7071067019822064
0.49999292658364913 0.5000071853265359 0.7071067019822064
Autograd ArrayBox with value 0.49999292658364913 Autograd ArrayBox with value 0.5000071853265359 Autograd ArrayBox with value 0.7071067019822064
0.5000001648990525 0.499999852276824 0.7071067690413341
0.5000001648990525 0.499999852276824 0.7071067690413341
Autograd ArrayBox with value 0.5000001648990525 Autograd ArrayBox with value 0.499999852276824 Autograd ArrayBox with value 0.7071067690413341
0.49932307489204364 0.5006175877041056 0.7071481441407286
0.49966167239869824 0.5003087726979442 0.7071275309993328
0.49983093178802784 0.5001543256520737 0.7071171686216021
0.4999155516299982 0.500077092254098 0.7071119734816835
0.49995785908634865 0.5000384730876828 0.7071093724240499
0.49997901219818236 0.500019162887785 0.7071080710233256
0.4999895885999912 0.5000095076336845 0.7071074201049881
0.4999948767623657 0.5000046799680988 0.7071070945913256
0.4999975208339201 0.5000022661256724 0.7071069318208709
0.49999884286728913 0.5000010592020511 0.7071068504322378
0.49999950388337144 0.5000004557396381 0.7071068097370696
0.49999983439126217 0.5000001540082812 0.7071067893892728
0.4999999996451699 0.5000000031425651 0.7071067792153212
0.4999999996451699 0.5000000031425651 0.7071067792153212
Autograd ArrayBox with value 0.4999999996451699 Autograd ArrayBox with value 0.5000000031425651 Autograd ArrayBox with value 0.7071067792153212
0.5000050907346681 0.499975116305243 0.7071207763281852
0.5000025452424944 0.49998755977647474 0.7071137778461071
0.5000012724569759 0.49999378147266305 0.7071102785493023
0.5000006360543588 0.4999968923108999 0.7071085288869587
0.5000003178505859 0.49999844772755403 0.7071076540523017
0.5000001587480832 0.4999992254352649 0.7071072166341019
0.5000000791966779 0.4999996142889664 0.7071069979247842
0.5000000394209367 0.49999980871577854 0.7071068885700708
0.5000000195330566 0.4999999059291751 0.7071068338927006
0.5000000095891141 0.49999995453587087 0.707106806554012
0.5000000046171422 0.49999997883921826 0.707106792884667
0.5000000021311561 0.49999999099089176 0.7071067860499941
0.500000000888163 0.49999999706672843 0.7071067826326577
0.500000000888163 0.49999999706672843 0.7071067826326577
[0.5        0.5        0.70710678]
--------------------
Optimization log:
{'final_values': {'f(x)': 0.5857864376269051,
                  'gradnorm': 2.3105300826104378e-08,
                  'iterations': 16,
                  'stepsize': 7.080890617239676e-09,
                  'time': 0.03498029708862305,
                  'x': array([0.5       , 0.5       , 0.70710678])},
 'iterations': {'f(x)': [3.1144768507635914,
                         1.0236313099379908,
                         1.0070117489576917,
                         0.9427980082326093,
                         0.7298214946316288,
                         0.6166259782315944,
                         0.6073312222042916,
                         0.5863333404681332,
                         0.5858093788068447,
                         0.5857908795908238,
                         0.5857864865240018,
                         0.5857864457604113,
                         0.5857864381513724,
                         0.5857864379740152,
                         0.5857864376270726,
                         0.5857864376269051],
                'gradnorm': [2.353614139885464,
                             2.06485754158584,
                             2.048316194268212,
                             1.9088304182493465,
                             1.2581503050164926,
                             0.6032761553307061,
                             0.5139047540981841,
                             0.07893409327144905,
                             0.016372054280831456,
                             0.007351986800183721,
                             0.0008130328968911645,
                             0.00033297378316843177,
                             8.46300478236599e-05,
                             6.885021403005702e-05,
                             1.5125974561020596e-06,
                             2.3105300826104378e-08],
                'iteration': [1,
                              2,
                              3,
                              4,
                              5,
                              6,
                              7,
                              8,
                              9,
                              10,
                              11,
                              12,
                              13,
                              14,
                              15,
                              16],
                'time': [1629823535.2125227,
                         1629823535.2156942,
                         1629823535.2177083,
                         1629823535.2187235,
                         1629823535.2217562,
                         1629823535.2232406,
                         1629823535.2250435,
                         1629823535.2262852,
                         1629823535.229165,
                         1629823535.231763,
                         1629823535.2336075,
                         1629823535.2363164,
                         1629823535.2381444,
                         1629823535.2401714,
                         1629823535.2412515,
                         1629823535.2451806],
                'x': [array([ 0.96163244,  0.16984109, -0.21544619]),
                      array([0.71872058, 0.58013852, 0.3832493 ]),
                      array([0.19002774, 0.37691133, 0.90654692]),
                      array([0.21858327, 0.38765261, 0.89551483]),
                      array([0.33309461, 0.42843077, 0.83993753]),
                      array([0.57659309, 0.50796937, 0.63992775]),
                      array([0.42832314, 0.50282716, 0.75080232]),
                      array([0.49145672, 0.49478419, 0.7167    ]),
                      array([0.50203335, 0.50057592, 0.70525617]),
                      array([0.49901311, 0.49998736, 0.70781252]),
                      array([0.50006612, 0.49990194, 0.70712936]),
                      array([0.49996847, 0.50003712, 0.70710283]),
                      array([0.50000865, 0.49999113, 0.70710694]),
                      array([0.49999293, 0.50000719, 0.7071067 ]),
                      array([0.50000016, 0.49999985, 0.70710677]),
                      array([0.5       , 0.5       , 0.70710678])]},
 'solver': 'SteepestDescent',
 'solverparams': {'linesearcher': <pymanopt.solvers.linesearch.LineSearchBackTracking object at 0x7f277c1eb850>},
 'stoppingcriteria': {'maxcostevals': 5000,
                      'maxiter': 1000,
                      'maxtime': 1000,
                      'mingradnorm': 1e-06,
                      'minstepsize': 1e-10},
 'stoppingreason': 'Terminated - min grad norm reached after 16 iterations, '
                   '0.03 seconds.'}

```

iterationで保存された結果は

```python

iteration = numpy.array(optlog['iterations']['iteration'], dtype='int') 
xi = numpy.array(optlog['iterations']['x'])[:,0]
yi = numpy.array(optlog['iterations']['x'])[:,1]
zi = numpy.array(optlog['iterations']['x'])[:,2]
fx = numpy.array(optlog['iterations']['f(x)'])

```
のようにしてアクセスできる。ただし、直線（？）探索が行われている過程のすべてが保存されるわけではなく、各iterationでの結果が格納されている模様。

```python

fig,axs=pyplot.subplots(2,2, figsize=(12,12))

#xmin,xmax=-1, 0
#ymin,ymax=-1, 0
#zmin,zmax=-1, 0

xmin,xmax=0, 1
ymin,ymax=0, 1
zmin,zmax=-1, 1


ax=axs[0,0]
ax.plot(Xopt[0],Xopt[1], marker='o', markeredgecolor='r', color='None', markersize=10)
ax.plot(xi, yi, 'k+')
ax.plot(xi, yi, 'k-')
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.set_xlabel('x',fontsize=20)
ax.set_ylabel('y',fontsize=20)

ax=axs[0,1]
ax.plot(Xopt[2],Xopt[1], marker='o', markeredgecolor='r', color='None', markersize=10)
ax.plot(zi, yi, 'k+')
ax.plot(zi, yi, 'k-')
ax.set_xlim([zmin,zmax])
ax.set_ylim([ymin,ymax])
ax.set_xlabel('z',fontsize=20)
ax.set_ylabel('y',fontsize=20)


ax=axs[1,0]
ax.plot(Xopt[0],Xopt[2], marker='o', markeredgecolor='r', color='None', markersize=10)
ax.plot(xi, zi, 'k+')
ax.plot(xi, zi, 'k-')
ax.set_xlim([xmin,xmax])
ax.set_ylim([zmin,zmax])
ax.set_xlabel('x',fontsize=20)
ax.set_ylabel('z',fontsize=20)


ax=axs[1,1]
#ax.plot(optlog['iterations']['f(x)'], marker='o', markeredgecolor='r', color='None', markersize=10)
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['f(x)'], 'k+')
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['f(x)'], 'k-')
ax.plot(optlog['iterations']['iteration'][-1], optlog['iterations']['f(x)'][-1], marker='o', markeredgecolor='r', color='None', markersize=10)
#ax.plot(xi, zi, 'k-')
#ax.set_xlim([xmin,xmax])
#ax.set_ylim([zmin,zmax])
ax.set_xlabel('iteration',fontsize=20)
ax.set_ylabel(r'$f({\bf x})$',fontsize=20)

```

![manifold_xyz_fx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610740/fb83db7e-492b-9edc-0cec-1a710774395c.png)


なんとなく大円に沿って探索されているように見える。
（天文のパッケージを利用しているので座標系が銀河座標(galactic)とあるが、これは普通の球座標と同じ。）


![Screen Shot 2021-08-25 at 2.23.31 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610740/46b18ee7-10c5-4050-b931-f2b1ab2624b9.png)

収束点付近を拡大。(45 deg, 45 deg)に収束していることがわかる。

![Screen Shot 2021-08-25 at 2.39.10 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610740/7d27fe08-6de1-ddf5-5dc4-cc2c818ac366.png)


## 数値実験１（スライド 103 ページ）

```python
_n = 100

diag_matrix_A = np.eye(_n)

for i in range(_n):
    diag_matrix_A[i,i]=i+1

#### 
array([[  1.,   0.,   0., ...,   0.,   0.,   0.],
       [  0.,   2.,   0., ...,   0.,   0.,   0.],
       [  0.,   0.,   3., ...,   0.,   0.,   0.],
       ...,
       [  0.,   0.,   0., ...,  98.,   0.,   0.],
       [  0.,   0.,   0., ...,   0.,  99.,   0.],
       [  0.,   0.,   0., ...,   0.,   0., 100.]])

```

```python
import pprint

import numpy
import autograd.numpy as np

from pymanopt.manifolds import Sphere
#from pymanopt.manifolds import Stiefel
from pymanopt import Problem
from pymanopt.solvers import SteepestDescent

from matplotlib import pyplot

global count


# (1) Instantiate a manifold
manifold = Sphere(_n) # (S^2 = 3D points on a 3D sphere)

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 

    f = np.dot(np.dot(np.transpose(X),diag_matrix_A), X)

    return f

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver


solver = SteepestDescent(logverbosity=2, maxiter=1000)
problem = Problem(manifold, cost, verbosity=0)

print('-'*20)
Xopt, optlog = solver.solve(problem)

print(Xopt)
print('-'*20)

print("Optimization log:")
pprint.pprint(optlog)

```

```python
fig,axs=pyplot.subplots(3,1, figsize=(6,6))


ax=axs[0]
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['gradnorm'], 'k+')
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['gradnorm'], 'k-')
ax.plot(optlog['iterations']['iteration'][-1], optlog['iterations']['gradnorm'][-1], marker='o', markeredgecolor='r', color='None', markersize=10)

ax.set_ylabel(r'gradnorm',fontsize=20)
ax.set_yscale('log')
ax.set_title('Numerical Experiment 1')


ax=axs[1]
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['f(x)'], 'k+')
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['f(x)'], 'k-')
ax.plot(optlog['iterations']['iteration'][-1], optlog['iterations']['f(x)'][-1], marker='o', markeredgecolor='r', color='None', markersize=10)

ax.set_yscale('log')
ax.set_xlabel('iteration',fontsize=20)
ax.set_ylabel(r'$f({\bf x})$',fontsize=20)



ax=axs[2]
ax.plot(optlog['iterations']['iteration'], numpy.array(optlog['iterations']['x'])[:,0], 'k+', label=r'x[0]')
ax.plot(optlog['iterations']['iteration'], numpy.array(optlog['iterations']['x'])[:,1], 'mo', label=r'x[1]')
ax.plot(optlog['iterations']['iteration'][::14], numpy.array(optlog['iterations']['x'])[::14,2], 'g^', label=r'x[2]')
ax.plot(optlog['iterations']['iteration'][::20], numpy.array(optlog['iterations']['x'])[::20,99], 'bs', label=r'x[99]')

ax.legend(loc='upper right')
ax.set_xlabel('iteration',fontsize=20)


```
![Numerical_Exp1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610740/e49bd3ae-d704-35d8-b0f8-66a027290422.png)


## 数値実験２（スライド 106 ページ）

```python
_n = 300
_p = 10


diag_matrix_A = np.eye(_n)
diag_matrix_N = np.eye(_p)

for i in range(_n):
    diag_matrix_A[i,i]=i+1

for i in range(_p):
    diag_matrix_N[i,i]=_p-i

```

```python
diag_matrix_N
####
array([[10.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  9.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  8.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  7.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  6.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  5.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  4.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  3.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  2.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.]])
```

```python
import pprint

import numpy
import autograd.numpy as np

#from pymanopt.manifolds import Sphere
from pymanopt.manifolds import Stiefel
from pymanopt import Problem
from pymanopt.solvers import SteepestDescent

from matplotlib import pyplot

global count


# (1) Instantiate a manifold
manifold = Stiefel(_n,_p) # Stiefel(_p,_n) did not work.

# (2) Define the cost function (here using autograd.numpy)
def cost(X): 

    f = np.trace(np.transpose(X) @ diag_matrix_A @ X @ diag_matrix_N)
    #f = np.dot(np.dot(np.transpose(X),diag_matrix_A), X)

    return f

problem = Problem(manifold=manifold, cost=cost)

# (3) Instantiate a Pymanopt solver


solver = SteepestDescent(logverbosity=2, maxiter=100000)
problem = Problem(manifold, cost, verbosity=0)

print('-'*20)
Xopt, optlog = solver.solve(problem)

print(Xopt)
print('-'*20)

#print("Optimization log:")
#pprint.pprint(optlog)

```


```python
pyplot.clf()

fig,axs=pyplot.subplots(6,1, figsize=(12,12))


ax=axs[0]
ax.set_title('Numerical Experiment 2')

ax.plot(optlog['iterations']['iteration'],optlog['iterations']['gradnorm'], 'k+')
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['gradnorm'], 'k-')
ax.plot(optlog['iterations']['iteration'][-1], optlog['iterations']['gradnorm'][-1], marker='o', markeredgecolor='r', color='None', markersize=10)


ax.axhline(y=10, c='gray')
ax.axhline(y=1, c='gray')
ax.axhline(y=0.1, c='gray')
ax.axhline(y=0.01, c='gray')
ax.axhline(y=0.001, c='gray')
ax.axhline(y=0.0001, c='gray')
ax.set_ylabel(r'gradnorm',fontsize=20)
ax.set_yscale('log')


ax=axs[1]
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['f(x)'], 'k+')
ax.plot(optlog['iterations']['iteration'],optlog['iterations']['f(x)'], 'k-')
ax.plot(optlog['iterations']['iteration'][-1], optlog['iterations']['f(x)'][-1], marker='o', markeredgecolor='r', color='None', markersize=10)

ax.set_yscale('log')
ax.set_xlabel('iteration',fontsize=20)
ax.set_ylabel(r'$f({\bf x})$',fontsize=20)



ax=axs[2]
ax.plot(optlog['iterations']['iteration'], numpy.array(optlog['iterations']['x'])[:,0], 'r-')
ax.set_ylabel('X[:,0]', fontsize=15)

ax=axs[3]
ax.plot(optlog['iterations']['iteration'], numpy.array(optlog['iterations']['x'])[:,1], 'b--')
ax.set_ylabel('X[:,1]', fontsize=15)


ax=axs[4]
ax.plot(optlog['iterations']['iteration'], numpy.array(optlog['iterations']['x'])[:,2], 'm-.')
ax.set_ylabel('X[:,2]', fontsize=15)


ax=axs[5]
ax.plot(optlog['iterations']['iteration'], numpy.array(optlog['iterations']['x'])[:,3], 'g--')
ax.set_ylabel('X[:,3]', fontsize=15)
ax.set_xlabel('iteration',fontsize=20)


pyplot.savefig('Experiment2.png')

```
![Experiment2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610740/9cf3b65b-518b-543d-8367-a9bf9fe5ef0a.png)