{
  "__type": "IngestedDoc",
  "__tag": 4010,
  "_content": {
    "Notes": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Warns": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Raises": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Yields": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Methods": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Returns": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Summary": {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "No Docstrings"
            }
          ]
        }
      ],
      "title": [],
      "level": 0,
      "target": null
    },
    "Receives": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Warnings": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Attributes": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Parameters": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Extended Summary": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Other Parameters": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    }
  },
  "_ordered_sections": [
    "Summary",
    "Extended Summary",
    "Parameters",
    "Attributes",
    "Methods",
    "Returns",
    "Yields",
    "Receives",
    "Other Parameters",
    "Raises",
    "Warns",
    "Warnings",
    "Notes"
  ],
  "item_file": "/scipy/linalg/interpolative.py",
  "item_line": 0,
  "item_type": "module",
  "aliases": [
    "scipy.linalg.interpolative"
  ],
  "example_section_data": {
    "__type": "Section",
    "__tag": 4015,
    "children": [],
    "title": [],
    "level": 0,
    "target": null
  },
  "see_also": [],
  "signature": null,
  "references": null,
  "qa": "scipy.linalg.interpolative",
  "arbitrary": [
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "versionadded",
          "base_type": "neutral",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "versionadded 0.13"
                }
              ]
            }
          ]
        },
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "versionchanged",
          "base_type": "neutral",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "versionchanged 1.15.0"
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "The underlying algorithms have been ported to Python from the original Fortran77 code. See references below for more details."
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "An interpolative decomposition (ID) of a matrix "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A \\in \\mathbb{C}^{m \\times n}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " of rank "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "k \\leq \\min \\{ m, n \\}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is a factorization"
            }
          ]
        },
        {
          "__type": "Math",
          "__tag": 4058,
          "value": "A \\Pi =\n\\begin{bmatrix}\n A \\Pi_{1} & A \\Pi_{2}\n\\end{bmatrix} =\nA \\Pi_{1}\n\\begin{bmatrix}\n I & T\n\\end{bmatrix},"
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "where "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "\\Pi = [\\Pi_{1}, \\Pi_{2}]"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is a permutation matrix with "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "\\Pi_{1} \\in \\{ 0, 1 \\}^{n \\times k}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", i.e., "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A \\Pi_{2} = A \\Pi_{1} T"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ". This can equivalently be written as "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A = BP"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", where "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "B = A \\Pi_{1}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "P = [I, T] \\Pi^{\\mathsf{T}}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " are the "
            },
            {
              "__type": "Emphasis",
              "__tag": 4047,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "skeleton"
                }
              ]
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "Emphasis",
              "__tag": 4047,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "interpolation matrices"
                }
              ]
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", respectively."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "If "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " does not have exact rank "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "k"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", then there exists an approximation in the form of an ID such that "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A = BP + E"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", where "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "\\| E \\| \\sim \\sigma_{k + 1}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is on the order of the "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "(k + 1)"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "-th largest singular value of "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ". Note that "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "\\sigma_{k + 1}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is the best possible error for a rank-"
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "k"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " approximation and, in fact, is achieved by the singular value decomposition (SVD) "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "A \\approx U S V^{*}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", where "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "U \\in \\mathbb{C}^{m \\times k}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "V \\in \\mathbb{C}^{n \\times k}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " have orthonormal columns and "
            },
            {
              "__type": "InlineMath",
              "__tag": 4057,
              "value": "S = \\mathop{\\mathrm{diag}} (\\sigma_{i}) \\in \\mathbb{C}^{k \\times k}"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is diagonal with nonnegative entries. The principal advantages of using an ID over an SVD are that:"
            }
          ]
        },
        {
          "__type": "BulletList",
          "__tag": 4053,
          "ordered": false,
          "start": 1,
          "children": [
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "it is cheaper to construct;"
                    }
                  ]
                }
              ]
            },
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "it preserves the structure of "
                    },
                    {
                      "__type": "InlineMath",
                      "__tag": 4057,
                      "value": "A"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "; and"
                    }
                  ]
                }
              ]
            },
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "it is more efficient to compute with in light of the identity submatrix of "
                    },
                    {
                      "__type": "InlineMath",
                      "__tag": 4057,
                      "value": "P"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "."
                    }
                  ]
                }
              ]
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Interpolative matrix decomposition ("
        },
        {
          "__type": "InlineRole",
          "__tag": 4003,
          "value": "scipy.linalg.interpolative",
          "domain": null,
          "role": "mod",
          "inventory": null
        },
        {
          "__type": "Text",
          "__tag": 4046,
          "value": ")"
        }
      ],
      "level": 0,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Main functionality:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ".. autosummary:: \n    :toctree:generated/\n    interp_decomp\n    reconstruct_matrix_from_id\n    reconstruct_interp_matrix\n    reconstruct_skel_matrix\n    id_to_svd\n    svd\n    estimate_spectral_norm\n    estimate_spectral_norm_diff\n    estimate_rank",
          "execution_status": null
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Routines"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This module uses the algorithms found in ID software package "
            },
            {
              "__type": "FootnoteReference",
              "__tag": 4066,
              "label": "1"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " by Martinsson, Rokhlin, Shkolnisky, and Tygert, which is a Fortran library for computing IDs using various algorithms, including the rank-revealing QR approach of "
            },
            {
              "__type": "FootnoteReference",
              "__tag": 4066,
              "label": "2"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and the more recent randomized methods described in "
            },
            {
              "__type": "FootnoteReference",
              "__tag": 4066,
              "label": "3"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", "
            },
            {
              "__type": "FootnoteReference",
              "__tag": 4066,
              "label": "4"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", and "
            },
            {
              "__type": "FootnoteReference",
              "__tag": 4066,
              "label": "5"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We advise the user to consult also the documentation for the "
            },
            {
              "__type": "Link",
              "__tag": 4049,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "ID package"
                }
              ],
              "url": "http://tygert.com/software.html",
              "title": ""
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        },
        {
          "__type": "Footnote",
          "__tag": 4067,
          "label": "1",
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "P.G. Martinsson, V. Rokhlin, Y. Shkolnisky, M. Tygert. \"ID: a     software package for low-rank approximation of matrices via interpolative     decompositions, version 0.2.\" http://tygert.com/id_doc.4.pdf."
                }
              ]
            }
          ]
        },
        {
          "__type": "Footnote",
          "__tag": 4067,
          "label": "2",
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "compression of low rank matrices.\" "
                },
                {
                  "__type": "Emphasis",
                  "__tag": 4047,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "SIAM J. Sci. Comput."
                    }
                  ]
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " 26 (4): 1389--1404,     2005. "
                },
                {
                  "__type": "InlineRole",
                  "__tag": 4003,
                  "value": "10.1137/030602678",
                  "domain": null,
                  "role": "doi",
                  "inventory": null
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            }
          ]
        },
        {
          "__type": "Footnote",
          "__tag": 4067,
          "label": "3",
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Tygert. \"Randomized algorithms for the low-rank approximation of matrices.\"     "
                },
                {
                  "__type": "Emphasis",
                  "__tag": 4047,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Proc. Natl. Acad. Sci. U.S.A."
                    }
                  ]
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " 104 (51): 20167--20172, 2007.     "
                },
                {
                  "__type": "InlineRole",
                  "__tag": 4003,
                  "value": "10.1073/pnas.0709640104",
                  "domain": null,
                  "role": "doi",
                  "inventory": null
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            }
          ]
        },
        {
          "__type": "Footnote",
          "__tag": 4067,
          "label": "4",
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "P.G. Martinsson, V. Rokhlin, M. Tygert. \"A randomized     algorithm for the decomposition of matrices.\" "
                },
                {
                  "__type": "Emphasis",
                  "__tag": 4047,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Appl. Comput. Harmon. Anal."
                    }
                  ]
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " 30     (1): 47--68,  2011. "
                },
                {
                  "__type": "InlineRole",
                  "__tag": 4003,
                  "value": "10.1016/j.acha.2010.02.003",
                  "domain": null,
                  "role": "doi",
                  "inventory": null
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            }
          ]
        },
        {
          "__type": "Footnote",
          "__tag": 4067,
          "label": "5",
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "randomized algorithm for the approximation of matrices.\" "
                },
                {
                  "__type": "Emphasis",
                  "__tag": 4047,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Appl. Comput.\n    Harmon. Anal."
                    }
                  ]
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " 25 (3): 335--366, 2008. "
                },
                {
                  "__type": "InlineRole",
                  "__tag": 4003,
                  "value": "10.1016/j.acha.2007.12.002",
                  "domain": null,
                  "role": "doi",
                  "inventory": null
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "References"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Tutorial"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The first step is to import "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "scipy.linalg.interpolative",
              "reference": {
                "__type": "LocalRef",
                "__tag": 4022,
                "kind": "module",
                "path": "scipy.linalg.interpolative"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " by issuing the command:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> import scipy.linalg.interpolative as sli",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Now let's build a matrix. For this, we consider a Hilbert matrix, which is well know to have low rank:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> from scipy.linalg import hilbert\n>>> n = 1000\n>>> A = hilbert(n)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We can also do this explicitly via:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> import numpy as np\n>>> n = 1000\n>>> A = np.empty((n, n), order='F')\n>>> for j in range(n):\n...     for i in range(n):\n...         A[i,j] = 1. / (i + j + 1)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Note the use of the flag "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "order='F'"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " in "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "numpy.empty",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "numpy",
                "version": "*",
                "kind": "api",
                "path": "numpy:empty"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ". This instantiates the matrix in Fortran-contiguous order and is important for avoiding data copying when passing to the backend."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We then define multiplication routines for the matrix by regarding it as a "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "scipy.sparse.linalg.LinearOperator",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "scipy",
                "version": "*",
                "kind": "api",
                "path": "scipy.sparse.linalg._interface:LinearOperator"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ":"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> from scipy.sparse.linalg import aslinearoperator\n>>> L = aslinearoperator(A)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This automatically sets up methods describing the action of the matrix and its adjoint on a vector."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Initializing"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We have several choices of algorithm to compute an ID. These fall largely according to two dichotomies:"
            }
          ]
        },
        {
          "__type": "BulletList",
          "__tag": 4053,
          "ordered": true,
          "start": 1,
          "children": [
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "how the matrix is represented, i.e., via its entries or via its action on a    vector; and"
                    }
                  ]
                }
              ]
            },
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "whether to approximate it to a fixed relative precision or to a fixed rank."
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We step through each choice in turn below."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "In all cases, the ID is represented by three parameters:"
            }
          ]
        },
        {
          "__type": "BulletList",
          "__tag": 4053,
          "ordered": true,
          "start": 1,
          "children": [
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "a rank "
                    },
                    {
                      "__type": "InlineCode",
                      "__tag": 4051,
                      "value": "k"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": ";"
                    }
                  ]
                }
              ]
            },
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "an index array "
                    },
                    {
                      "__type": "InlineCode",
                      "__tag": 4051,
                      "value": "idx"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "; and"
                    }
                  ]
                }
              ]
            },
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "interpolation coefficients "
                    },
                    {
                      "__type": "InlineCode",
                      "__tag": 4051,
                      "value": "proj"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "."
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The ID is specified by the relation "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "np.dot(A[:,idx[:k]], proj) == A[:,idx[k:]]"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Computing an ID"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We first consider a matrix given in terms of its entries."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an ID to a fixed precision, type:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> eps = 1e-3\n>>> k, idx, proj = sli.interp_decomp(A, eps)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "where "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "eps < 1"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is the desired precision."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an ID to a fixed rank, use:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> idx, proj = sli.interp_decomp(A, k)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "where "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "k >= 1"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is the desired rank."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Both algorithms use random sampling and are usually faster than the corresponding older, deterministic algorithms, which can be accessed via the commands:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> k, idx, proj = sli.interp_decomp(A, eps, rand=False)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "and:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> idx, proj = sli.interp_decomp(A, k, rand=False)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "respectively."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "From matrix entries"
        }
      ],
      "level": 3,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Now consider a matrix given in terms of its action on a vector as a "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "scipy.sparse.linalg.LinearOperator",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "scipy",
                "version": "*",
                "kind": "api",
                "path": "scipy.sparse.linalg._interface:LinearOperator"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an ID to a fixed precision, type:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> k, idx, proj = sli.interp_decomp(L, eps)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an ID to a fixed rank, use:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> idx, proj = sli.interp_decomp(L, k)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "These algorithms are randomized."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "From matrix action"
        }
      ],
      "level": 3,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The ID routines above do not output the skeleton and interpolation matrices explicitly but instead return the relevant information in a more compact (and sometimes more useful) form. To build these matrices, write:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> B = sli.reconstruct_skel_matrix(A, k, idx)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "for the skeleton matrix and:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> P = sli.reconstruct_interp_matrix(idx, proj)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "for the interpolation matrix. The ID approximation can then be computed as:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> C = np.dot(B, P)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This can also be constructed directly using:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> C = sli.reconstruct_matrix_from_id(B, idx, proj)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "without having to first compute "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "P"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Alternatively, this can be done explicitly as well using:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> B = A[:,idx[:k]]\n>>> P = np.hstack([np.eye(k), proj])[:,np.argsort(idx)]\n>>> C = np.dot(B, P)",
          "execution_status": null
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Reconstructing an ID"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "An ID can be converted to an SVD via the command:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> U, S, V = sli.id_to_svd(B, idx, proj)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The SVD approximation is then:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> approx = U @ np.diag(S) @ V.conj().T",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The SVD can also be computed \"fresh\" by combining both the ID and conversion steps into one command. Following the various ID algorithms above, there are correspondingly various SVD algorithms that one can employ."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Computing an SVD"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "We consider first SVD algorithms for a matrix given in terms of its entries."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an SVD to a fixed precision, type:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> U, S, V = sli.svd(A, eps)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an SVD to a fixed rank, use:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> U, S, V = sli.svd(A, k)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Both algorithms use random sampling; for the deterministic versions, issue the keyword "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "rand=False"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " as above."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "From matrix entries"
        }
      ],
      "level": 3,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Now consider a matrix given in terms of its action on a vector."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an SVD to a fixed precision, type:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> U, S, V = sli.svd(L, eps)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To compute an SVD to a fixed rank, use:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> U, S, V = sli.svd(L, k)",
          "execution_status": null
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "From matrix action"
        }
      ],
      "level": 3,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Several utility routines are also available."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To estimate the spectral norm of a matrix, use:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> snorm = sli.estimate_spectral_norm(A)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This algorithm is based on the randomized power method and thus requires only matrix-vector products. The number of iterations to take can be set using the keyword "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "its"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " (default: "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "its=20"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "). The matrix is interpreted as a "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "scipy.sparse.linalg.LinearOperator",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "scipy",
                "version": "*",
                "kind": "api",
                "path": "scipy.sparse.linalg._interface:LinearOperator"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", but it is also valid to supply it as a "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "numpy.ndarray",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "numpy",
                "version": "*",
                "kind": "api",
                "path": "numpy:ndarray"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", in which case it is trivially converted using "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "scipy.sparse.linalg.aslinearoperator",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "scipy",
                "version": "*",
                "kind": "api",
                "path": "scipy.sparse.linalg._interface:aslinearoperator"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The same algorithm can also estimate the spectral norm of the difference of two matrices "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "A1"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "A2"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " as follows:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> A1, A2 = A**2, A\n>>> diff = sli.estimate_spectral_norm_diff(A1, A2)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This is often useful for checking the accuracy of a matrix approximation."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Some routines in "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "scipy.linalg.interpolative",
              "reference": {
                "__type": "LocalRef",
                "__tag": 4022,
                "kind": "module",
                "path": "scipy.linalg.interpolative"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " require estimating the rank of a matrix as well. This can be done with either:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> k = sli.estimate_rank(A, eps)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "or:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": ">>> k = sli.estimate_rank(L, eps)",
          "execution_status": null
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "depending on the representation. The parameter "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "eps"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " controls the definition of the numerical rank."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Finally, the random number generation required for all randomized routines can be controlled via providing NumPy pseudo-random generators with a fixed seed. See "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "numpy.random.Generator",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "numpy",
                "version": "*",
                "kind": "api",
                "path": "numpy.random._generator:Generator"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "numpy.random.default_rng",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "numpy",
                "version": "*",
                "kind": "api",
                "path": "numpy.random:default_rng"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " for more details."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Utility routines"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The above functions all automatically detect the appropriate interface and work with both real and complex data types, passing input arguments to the proper backend routine."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Remarks"
        }
      ],
      "level": 2,
      "target": null
    }
  ],
  "local_refs": []
}