{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import networkx as nx\n",
    "import time\n",
    "import math\n",
    "import pandas as pd\n",
    "import scipy as sp\n",
    "import plotly.express as px\n",
    "import plotly.graph_objs as go\n",
    "from scipy.sparse import *\n",
    "from scipy import linalg\n",
    "from scipy.sparse.linalg import norm\n",
    "from scipy.optimize import least_squares"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Algorithm 2 testing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# def Arnoldi(A, v, m): \n",
    "#     beta = norm(v)\n",
    "#     v = v/beta # dimension of v is n x 1\n",
    "#     H = sp.sparse.lil_matrix((m,m)) # dimension of H is m x m \n",
    "#     V = sp.sparse.lil_matrix((A.shape[0],m))\n",
    "#     V[:,0] = v # each column of V is a vector v\n",
    "\n",
    "#     for j in range(m):\n",
    "#         print(\"j = \", j)\n",
    "#         w = A @ v  \n",
    "#         for i in range(j):\n",
    "#             tmp = v.T @ w  \n",
    "#             H[i,j] = tmp[0,0]\n",
    "#             w = w - H[i,j]*v \n",
    "            \n",
    "#         H[j,j-1] = norm(w) \n",
    "\n",
    "#         if H[j,j-1] == 0: \n",
    "#             print(\"Arnoldi breakdown\")\n",
    "#             m = j\n",
    "#             v = 0\n",
    "#             break\n",
    "#         else:\n",
    "#             if j < m-1:\n",
    "#                 v = w/H[j,j-1]\n",
    "#                 # for i in range(A.shape[0]):\n",
    "#                 #     V[i,j+1] = v[i,0]\n",
    "#                 V[:,j+1] = v\n",
    "\n",
    "#     print(j, \" iterations completed\")\n",
    "#     print(\"V = \", V.shape)\n",
    "#     print(\"H = \", H.shape)\n",
    "#     print(\"v = \", v.shape)\n",
    "#     print(\"beta = \", beta)\n",
    "\n",
    "#     return V, H, v, beta, j"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Defined as Algorithm 2 in the paper. It's needed since it's called by Algorithm 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Arnoldi(A,v0,m):\n",
    "    v = v0\n",
    "    beta = norm(v)\n",
    "    v = v/beta\n",
    "    H = sp.sparse.lil_matrix((m+1,m)) \n",
    "    V = sp.sparse.lil_matrix((A.shape[0],m+1))\n",
    "    V[:,0] = v # each column of V is a vector v\n",
    "\n",
    "    for j in range(m):\n",
    "        # print(\"j = \", j)\n",
    "        w = A @ v  \n",
    "        for i in range(j):\n",
    "            tmp = v.T @ w # tmp is a 1x1 matrix, so it's O(1) in memory\n",
    "            H[i,j] = tmp[0,0] \n",
    "            w = w - H[i,j]*v \n",
    "            \n",
    "        H[j+1,j] = norm(w)\n",
    "\n",
    "        if H[j+1,j] == 0:\n",
    "            print(\"Arnoldi breakdown\")\n",
    "            m = j\n",
    "            v = 0\n",
    "            break\n",
    "        else:\n",
    "            if j < m-1:\n",
    "                v = w/H[j+1,j]\n",
    "                V[:,j+1] = v\n",
    "\n",
    "    print(j, \" iterations completed\")\n",
    "    print(\"V = \", V.shape)\n",
    "    print(\"H = \", H.shape)\n",
    "    print(\"v = \", v.shape)\n",
    "    print(\"beta = \", beta)\n",
    "\n",
    "    return V, H, v, beta, j  \n",
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Creating a small test case"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "m = 100\n",
    "n = 110\n",
    "A = sp.sparse.rand(n,n, density=0.1, format='lil')\n",
    "# generate a probability vector, with all the entries as 1/n\n",
    "v = sp.sparse.lil_matrix((n,1))\n",
    "for i in range(n):\n",
    "    v[i] = 1/n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "99  iterations completed\n",
      "V =  (110, 101)\n",
      "H =  (101, 100)\n",
      "v =  (110, 1)\n",
      "beta =  0.09534625892455922\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(<110x101 sparse matrix of type '<class 'numpy.float64'>'\n",
       " \twith 11000 stored elements in List of Lists format>,\n",
       " <101x100 sparse matrix of type '<class 'numpy.float64'>'\n",
       " \twith 4879 stored elements in List of Lists format>,\n",
       " <110x1 sparse matrix of type '<class 'numpy.float64'>'\n",
       " \twith 110 stored elements in Compressed Sparse Row format>,\n",
       " 0.09534625892455922,\n",
       " 99)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Arnoldi(A,v,m)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.6 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
