Commit 086716cb authored by Roman Flury's avatar Roman Flury

rest of website..

parent 61ea7a66
Pipeline #948 passed with stage
in 2 seconds
......@@ -4,3 +4,4 @@ spam/.Rproj.user
.DS_Store
*.o
*.so
.Rproj.user
......@@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>License • spam</title>
<title>Articles • spam</title>
<!-- jquery -->
<script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha384-nrOSfDHtoPMzJHjVTdCopGqIqeYETSXhZDFyniQ8ZHcVy08QesyHcnOUpMpqnmWq" crossorigin="anonymous"></script>
......@@ -25,12 +25,12 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/sticky-kit/1.1.3/sticky-kit.min.js" integrity="sha256-c4Rlo1ZozqTPE2RLuvbusY3+SU1pQaJC0TjuhygMipw=" crossorigin="anonymous"></script>
<!-- pkgdown -->
<link href="pkgdown.css" rel="stylesheet">
<script src="pkgdown.js"></script>
<link href="../pkgdown.css" rel="stylesheet">
<script src="../pkgdown.js"></script>
<meta property="og:title" content="License" />
<meta property="og:title" content="Articles" />
......@@ -46,7 +46,7 @@
</head>
<body>
<div class="container template-title-body">
<div class="container template-article-index">
<header>
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
......@@ -57,7 +57,7 @@
<span class="icon-bar"></span>
</button>
<span class="navbar-brand">
<a class="navbar-link" href="index.html">spam</a>
<a class="navbar-link" href="../index.html">spam</a>
<span class="label label-default" data-toggle="tooltip" data-placement="bottom" title="Released package">2.2.1</span>
</span>
</div>
......@@ -65,19 +65,19 @@
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<a href="index.html">
<a href="../index.html">
<span class="fa fa-home"></span>
</a>
</li>
<li>
<a href="articles/spam.html">Vignette</a>
<a href="../articles/spam.html">Vignette</a>
</li>
<li>
<a href="reference/index.html">Reference</a>
<a href="../reference/index.html">Reference</a>
</li>
<li>
<a href="news/index.html">Changelog</a>
<a href="../news/index.html">Changelog</a>
</li>
</ul>
......@@ -106,21 +106,22 @@
</header>
<div class="row">
<div class="contents col-md-9">
<div class="col-md-9 contents">
<div class="page-header">
<h1>License</h1>
<h1>Articles</h1>
</div>
<pre>YEAR: 1996-2008
COPYRIGHT HOLDER: D.C. Sorensen, R.B. Lehoucq, C. Yang, and K. Maschhoff
ORGANIZATION: Rice University
</pre>
<div class="section ">
<h3>All vignettes</h3>
<p class="section-desc"></p>
<ul>
<li><a href="spam.html">Illustrations and Examples</a></li>
</ul>
</div>
</div>
</div>
<footer>
<div class="copyright">
<p>Developed by Reinhard Furrer.</p>
......
<!DOCTYPE html>
<!-- Generated by pkgdown: do not edit by hand --><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Illustrations and Examples • spam</title>
<!-- jquery --><script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha384-nrOSfDHtoPMzJHjVTdCopGqIqeYETSXhZDFyniQ8ZHcVy08QesyHcnOUpMpqnmWq" crossorigin="anonymous"></script><!-- Bootstrap --><link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/yeti/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><!-- Font Awesome icons --><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
<!-- clipboard.js --><script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js" integrity="sha384-cV+rhyOuRHc9Ub/91rihWcGmMmCXDeksTtCihMupQHSsi8GIIRDG0ThDc3HGQFJ3" crossorigin="anonymous"></script><!-- sticky kit --><script src="https://cdnjs.cloudflare.com/ajax/libs/sticky-kit/1.1.3/sticky-kit.min.js" integrity="sha256-c4Rlo1ZozqTPE2RLuvbusY3+SU1pQaJC0TjuhygMipw=" crossorigin="anonymous"></script><!-- pkgdown --><link href="../pkgdown.css" rel="stylesheet">
<script src="../pkgdown.js"></script><meta property="og:title" content="Illustrations and Examples">
<meta property="og:description" content="">
<meta name="twitter:card" content="summary">
<!-- mathjax --><script src="https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container template-article">
<header><div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">spam</a>
<span class="label label-default" data-toggle="tooltip" data-placement="bottom" title="Released package">2.2.1</span>
</span>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<a href="../index.html">
<span class="fa fa-home"></span>
</a>
</li>
<li>
<a href="../articles/spam.html">Vignette</a>
</li>
<li>
<a href="../reference/index.html">Reference</a>
</li>
<li>
<a href="../news/index.html">Changelog</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<a href="https://git.math.uzh.ch/reinhard.furrer/spam">
<span class="fa fa-lg fa-github"></span>
github
</a>
</li>
<li>
<a href="http://twitter.com/ReinhardFurrer">
<span class="fa fa-lg fa-twitter"></span>
twitter
</a>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
<!--/.container -->
</div>
<!--/.navbar -->
</header><div class="row">
<div class="col-md-9 contents">
<div class="page-header toc-ignore">
<h1>Illustrations and Examples</h1>
<h4 class="author">Reinhard Furrer, Roman Flury</h4>
<h4 class="date">2018-10-05</h4>
<div class="hidden name"><code>spam.Rmd</code></div>
</div>
<div id="rational-for-spam" class="section level1">
<h1 class="hasAnchor">
<a href="#rational-for-spam" class="anchor"></a>Rational for spam</h1>
<p>At the core of drawing multivariate normal random variables, calculating or maximizing multivariate normal log-likelihoods, calculating determinants, etc., we need to solve a large (huge) linear system involving a variance matrix, i.e., a symmetric, positive definite matrix.</p>
<p>Assume that we have such a symmetric, positive definite matrix <span class="math inline">\(\boldsymbol{Q}\)</span> of size <span class="math inline">\(n\times n\)</span> that contains many zeros (through tapering, <span class="citation">Furrer, Genton, and Nychka (2006)</span>, <span class="citation">Furrer and Bengtsson (2007)</span>, or through a Markovian conditional construction). Typically, <span class="math inline">\(\boldsymbol{Q}\)</span> contains only <span class="math inline">\(\mathcal{O}(n)\)</span> non-zero elements compared to <span class="math inline">\(\mathcal{O}(n^2)\)</span> for a regular, <strong>full</strong> matrix. To take advantage of the few non-zero elements, special structures to represent the matrix are required, i.e., only the positions of the non-zeros and their values are kept in memory. Further, new algorithms work with these structures are required. The package <code>spam</code> provides this functionality, see <span class="citation">Furrer and Sain (2010)</span> for a detailed exposition.</p>
</div>
<div id="a-simple-example" class="section level1">
<h1 class="hasAnchor">
<a href="#a-simple-example" class="anchor"></a>A Simple Example</h1>
<p>This first section illustrates with a simple example how to work with <code>spam</code>. Within a running R we install and load the current <code>spam</code> version from CRAN.</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">install.packages</span>(<span class="st">"spam"</span>)
<span class="kw">library</span>(<span class="st">"spam"</span>)</code></pre></div>
<p>We create a trivial matrix and “coerce” it to a sparse matrix.</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">Fmat &lt;-<span class="st"> </span><span class="kw">matrix</span>(<span class="kw">c</span>(<span class="dv">3</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">2</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">3</span>), <span class="dt">nrow =</span> <span class="dv">3</span>, <span class="dt">ncol =</span> <span class="dv">3</span>)
Smat &lt;-<span class="st"> </span><span class="kw"><a href="../reference/spam.creation.html">as.spam</a></span>(Fmat)</code></pre></div>
<p><code>spam</code> is conceptualized such that for many operations, the user proceeds as with ordinary full matrices. For example:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">Fmat
<span class="co">#&gt; [,1] [,2] [,3]</span>
<span class="co">#&gt; [1,] 3 0 1</span>
<span class="co">#&gt; [2,] 0 2 0</span>
<span class="co">#&gt; [3,] 1 0 3</span>
Smat
<span class="co">#&gt; [,1] [,2] [,3]</span>
<span class="co">#&gt; [1,] 3 0 1</span>
<span class="co">#&gt; [2,] 0 2 0</span>
<span class="co">#&gt; [3,] 1 0 3</span>
<span class="co">#&gt; Class 'spam' (32-bit)</span>
Smat <span class="op">%*%</span><span class="st"> </span><span class="kw">t</span>(Smat)
<span class="co">#&gt; [,1] [,2] [,3]</span>
<span class="co">#&gt; [1,] 10 0 6</span>
<span class="co">#&gt; [2,] 0 4 0</span>
<span class="co">#&gt; [3,] 6 0 10</span>
<span class="co">#&gt; Class 'spam' (32-bit)</span>
Fmat <span class="op">%*%</span><span class="st"> </span><span class="kw">t</span>(Smat)
<span class="co">#&gt; [,1] [,2] [,3]</span>
<span class="co">#&gt; [1,] 10 0 6</span>
<span class="co">#&gt; [2,] 0 4 0</span>
<span class="co">#&gt; [3,] 6 0 10</span>
<span class="co">#&gt; Class 'spam' (32-bit)</span></code></pre></div>
<p>Hence, the user should not be worried which objects are sparse matrices and which are not. Of course not all operations result in sparse objects again,</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">rep</span>(<span class="dv">1</span>, <span class="dv">3</span>) <span class="op">%*%</span><span class="st"> </span>Smat
<span class="co">#&gt; [,1] [,2] [,3]</span>
<span class="co">#&gt; [1,] 4 2 4</span></code></pre></div>
<p>However, other operations yield to different results when applied to full or sparse matrices</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">range</span>(Fmat)
<span class="co">#&gt; [1] 0 3</span>
<span class="kw">range</span>(Smat)
<span class="co">#&gt; [1] 1 3</span></code></pre></div>
</div>
<div id="creating-sparse-matrices" class="section level1">
<h1 class="hasAnchor">
<a href="#creating-sparse-matrices" class="anchor"></a>Creating Sparse Matrices</h1>
<p>The implementation of <code>spam</code> is designed as a trade-off between the following competing philosophical maxims. It should be competitively fast compared to existing tools or approaches in R and it should be easy to use, modify and extend. The former is imposed to assure that the package will be useful and used in practice. The latter is necessary since statistical methods and approaches are often very specific and no single package could cover all potential tools. Hence, the user needs to understand quickly the underlying structure of the implementation of <code>spam</code> and to be able to extend it without getting desperate. (When faced with huge amounts of data, sub-sampling is one possibility; using <code>spam</code> is another.) This philosophical approach also suggests trying to assure <code>S3</code> and <code>S4</code> compatibility, <span class="citation">Chambers (1998)</span>, see also <span class="citation">Lumley (2004)</span>. <code>S4</code> has higher priority but there are only a handful cases of <code>S3</code> discrepancies, which do however not affect normal usage.</p>
<p>To store the non-zero elements, <code>spam</code> uses the “old Yale sparse format”. In this format, a (sparse) matrix is stored with four elements (vectors), which are (1) the nonzero values row by row, (2) the ordered column indices of nonzero values, (3) the position in the previous two vectors corresponding to new rows, given as pointers, and (4) the column dimension of the matrix. We refer to this format as compressed sparse row (CSR) format. Hence, to store a matrix with <span class="math inline">\(z\)</span> nonzero elements we thus need <span class="math inline">\(z\)</span> reals and <span class="math inline">\(z+n+2\)</span> integers compared to <span class="math inline">\(n \times n\)</span> reals. Section Representation describes the format in more details.</p>
<p>The package <code>spam</code> provides two classes, first, <code>spam</code> representing sparse matrices and, second, <code>spam.chol.NgPeyton</code> representing Cholesky factors. A class definition specifies the objects belonging to the class, these objects are called slots in R and accessed with the <code>@</code> operator, see for a more thorough discussion. The four vectors of the CSR representation are implemented as slots. In <code>spam</code>, all operations can be performed without a detailed knowledge about the slots. However, advanced users may want to work on the slots of the class <code>spam</code> directly because of computational savings, for example, changing only the contents of a matrix while maintaining its sparsity structure, see Section Tips. The Cholesky factor requires additional information (e.g., the used permutation) hence the class <code>spam.chol.NgPeyton</code> contains more slots, which are less intuitive. There are only very few, specific cases, where the user has to access these slots directly. Therefore, user-visibility has been disregarded for the sake of speed. The two classes are discussed in the more technical Section Representation.</p>
</div>
<div id="displaying" class="section level1">
<h1 class="hasAnchor">
<a href="#displaying" class="anchor"></a>Displaying</h1>
<p>As seen in Section A Simple Example, printing small matrices result in an expected output, i.e., the content of the matrix plus a line indicating the class of the object:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">Smat
<span class="co">#&gt; [,1] [,2] [,3]</span>
<span class="co">#&gt; [1,] 3 0 1</span>
<span class="co">#&gt; [2,] 0 2 0</span>
<span class="co">#&gt; [3,] 1 0 3</span>
<span class="co">#&gt; Class 'spam' (32-bit)</span></code></pre></div>
<p>For larger objects, not all the elements are printed. For example:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw"><a href="../reference/diag.html">diag.spam</a></span>(<span class="dv">100</span>)
<span class="co">#&gt; Matrix of dimension 100x100 with (row-wise) nonzero elements:</span>
<span class="co">#&gt; </span>
<span class="co">#&gt; [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1</span>
<span class="co">#&gt; [36] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1</span>
<span class="co">#&gt; [71] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1</span>
<span class="co">#&gt; Class 'spam' (32-bit)</span></code></pre></div>
<p>The size of the matrix when switching from the first printing format to the second is a <code>spam</code> option, see Section Options. Naturally, we can also use the <code>str</code> command which gives us further insight into the individual slots of the <code>spam</code> object:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">str</span>(Smat)
<span class="co">#&gt; Formal class 'spam' [package "spam"] with 4 slots</span>
<span class="co">#&gt; ..@ entries : num [1:5] 3 1 2 1 3</span>
<span class="co">#&gt; ..@ colindices : int [1:5] 1 3 2 1 3</span>
<span class="co">#&gt; ..@ rowpointers: int [1:4] 1 3 4 6</span>
<span class="co">#&gt; ..@ dimension : int [1:2] 3 3</span></code></pre></div>
<p>Alternatively, calling <code>summary</code> gives additional information of the matrix.</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">summary</span>(Smat)
<span class="co">#&gt; Matrix object of class 'spam' of dimension 3x3,</span>
<span class="co">#&gt; with 5 (row-wise) nonzero elements.</span>
<span class="co">#&gt; Density of the matrix is 55.6%.</span>
<span class="co">#&gt; Class 'spam'</span></code></pre></div>
<p><code>summary</code> itself prints on the standard output but also returns a list containing the number of non-zeros (<code>nnz</code>) and the density (<code>density</code>) (percentage of <code>nnz</code> over the total number of elements).</p>
<p>Quite often, it is interesting to look at the sparsity structure of a sparse matrix. This is implemented with the command <code>display</code>. Again, depending on the size, the structure is shown as proper rectangles or as points. Figure is the result of the following code.</p>
<div class="figure" style="text-align: center">
<img src="spam_files/figure-html/disp6-1.png" alt="\label{fig:display_spam}Sparsity structure of sparse matrices." width="700"><p class="caption">
Sparsity structure of sparse matrices.
</p>
</div>
<p>Additionally, compare Figures of this document. Depending on the <code>cex</code> value, the <code>image</code> may issue a warning, meaning that the dot-size is probably not optimal. In fact, visually the density of the matrix <code>Smat1</code> seems to be around some percentage whereas the actual density is 0.024.</p>
<p>The function <code>image</code> goes beyond the structure of the matrix by using a specified color scheme for the values. Labels can be added manually or with <code>image.plot</code> from the package <code>fields</code>.</p>
</div>
<div id="solving-linear-systems" class="section level1">
<h1 class="hasAnchor">
<a href="#solving-linear-systems" class="anchor"></a>Solving Linear Systems</h1>
<p>To be more specific about one of <code>spam</code>’s main features, assume we need to calculate <span class="math inline">\(\boldsymbol{A}^{-1}\boldsymbol{b}\)</span> with <span class="math inline">\(\boldsymbol{A}\)</span> a symmetric positive definite matrix featuring some sparsity structure, which is usually accomplished by solving <span class="math inline">\(\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}\)</span>. We proceed by factorizing <span class="math inline">\(\boldsymbol{A}\)</span> into <span class="math inline">\(\boldsymbol{R}^T\boldsymbol{R}\)</span>, where <span class="math inline">\(\boldsymbol{R}\)</span> is an upper triangular matrix, called the Cholesky factor or Cholesky triangle of <span class="math inline">\(\boldsymbol{A}\)</span>, followed by solving <span class="math inline">\(\boldsymbol{R}^T\boldsymbol{y}=\boldsymbol{b}\)</span> and <span class="math inline">\(\boldsymbol{R}\boldsymbol{x}=\boldsymbol{y}\)</span>, called forwardsolve and backsolve, respectively. To reduce the fill-in of the Cholesky factor <span class="math inline">\(\boldsymbol{R}\)</span>, we permute the columns and rows of <span class="math inline">\(\boldsymbol{A}\)</span> according to a (cleverly chosen) permutation <span class="math inline">\(\boldsymbol{P}\)</span>, i.e., <span class="math inline">\(\boldsymbol{U}^T\boldsymbol{U}=\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}\)</span>, with <span class="math inline">\(\boldsymbol{U}\)</span> an upper triangular matrix. There exist many different algorithms to find permutations which are optimal for specific matrices %tridiagonal matrices finite element/difference matrices defined on square grids or at least close to optimal with respect to different criteria. Note that <span class="math inline">\(\boldsymbol{R}\)</span> and <span class="math inline">\(\boldsymbol{U}\)</span> cannot be linked through <span class="math inline">\(\boldsymbol{P}\)</span> alone. Figure illustrates the factorization with and without permutation. For solving a linear system the two triangular solves are performed after the factorization. The determinant of <span class="math inline">\(\boldsymbol{A}\)</span> is the squared product of the diagonal elements of its Cholesky factor <span class="math inline">\(\boldsymbol{R}\)</span>. Hence the same factorization can be used to calculate determinants (a necessary and computational bottleneck in the computation of the log-likelihood of a Gaussian model), illustrating that it is very important to have a very efficient integration (with respect to calculation time and storage capacity) of the Cholesky factorization. In the case of GMRF, the off-diagonal non-zero elements correspond to the conditional dependence structure. However, for the calculation of the Cholesky factor, the values themselves are less important than the sparsity structure, which is often represented using a graph with edges representing the non-zero elements or using a “pixel” image of the zero/non-zero structure, see Figure .</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">i &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">2</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">5</span>)
j &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">1</span>, <span class="dv">3</span>)
A &lt;-<span class="st"> </span><span class="kw"><a href="../reference/spam.creation.html">spam</a></span>(<span class="dv">0</span>, <span class="dt">nrow =</span> <span class="dv">5</span>, <span class="dt">ncol =</span> <span class="dv">5</span>)
A[<span class="kw"><a href="../reference/xybind.html">cbind</a></span>(i, j)] &lt;-<span class="st"> </span><span class="kw">rep</span>(<span class="fl">0.5</span>, <span class="kw">length</span>(i))
A &lt;-<span class="st"> </span><span class="kw">t</span>(A) <span class="op">+</span><span class="st"> </span>A <span class="op">+</span><span class="st"> </span><span class="kw"><a href="../reference/diag.html">diag.spam</a></span>(<span class="dv">5</span>)
A
<span class="co">#&gt; [,1] [,2] [,3] [,4] [,5]</span>
<span class="co">#&gt; [1,] 1.0 0.5 0.0 0.5 0.5</span>
<span class="co">#&gt; [2,] 0.5 1.0 0.0 0.5 0.0</span>
<span class="co">#&gt; [3,] 0.0 0.0 1.0 0.0 0.5</span>
<span class="co">#&gt; [4,] 0.5 0.5 0.0 1.0 0.0</span>
<span class="co">#&gt; [5,] 0.5 0.0 0.5 0.0 1.0</span>
<span class="co">#&gt; Class 'spam' (32-bit)</span>
U &lt;-<span class="st"> </span><span class="kw">chol</span>(A)</code></pre></div>
<div class="figure" style="text-align: center">
<img src="figures/tree.png" alt="\label{fig:tree}On the left side the associated graph to the matrix $\boldsymbol{A}$ is visualized. The nodes of the graph are labeled according to $\boldsymbol{A}$ (upright) and $\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}$ (italics). On the right side the sparsity structure of $\boldsymbol{A}$ and $\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}$ (top row) and the Cholesky factors $\boldsymbol{R}$ and $\boldsymbol{U}$ of $\boldsymbol{A}$ and $\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}$ respectively are given in the bottom row. The dashed lines in $\boldsymbol{U}$ indicate the supernode partition." width="40%"><img src="figures/ill.png" alt="\label{fig:tree}On the left side the associated graph to the matrix $\boldsymbol{A}$ is visualized. The nodes of the graph are labeled according to $\boldsymbol{A}$ (upright) and $\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}$ (italics). On the right side the sparsity structure of $\boldsymbol{A}$ and $\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}$ (top row) and the Cholesky factors $\boldsymbol{R}$ and $\boldsymbol{U}$ of $\boldsymbol{A}$ and $\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}$ respectively are given in the bottom row. The dashed lines in $\boldsymbol{U}$ indicate the supernode partition." width="40%"><p class="caption">
On the left side the associated graph to the matrix <span class="math inline">\(\boldsymbol{A}\)</span> is visualized. The nodes of the graph are labeled according to <span class="math inline">\(\boldsymbol{A}\)</span> (upright) and <span class="math inline">\(\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}\)</span> (italics). On the right side the sparsity structure of <span class="math inline">\(\boldsymbol{A}\)</span> and <span class="math inline">\(\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}\)</span> (top row) and the Cholesky factors <span class="math inline">\(\boldsymbol{R}\)</span> and <span class="math inline">\(\boldsymbol{U}\)</span> of <span class="math inline">\(\boldsymbol{A}\)</span> and <span class="math inline">\(\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}\)</span> respectively are given in the bottom row. The dashed lines in <span class="math inline">\(\boldsymbol{U}\)</span> indicate the supernode partition.
</p>
</div>
<p>The Cholesky factor of a banded matrix is again a banded matrix. But arbitrary matrices may produce full Cholesky factors. To reduce this so-called <em>fill-in</em> of the Cholesky factor <span class="math inline">\(\boldsymbol{R}\)</span>, we permute the columns and rows of <span class="math inline">\(\boldsymbol{A}\)</span> according to a (cleverly chosen) permutation <span class="math inline">\(\boldsymbol{P}\)</span>, i.e., <span class="math inline">\(\boldsymbol{U}^T\boldsymbol{U}=\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}\)</span>, with <span class="math inline">\(\boldsymbol{U}\)</span> an upper triangular matrix. There exist many different algorithms to find permutations which are optimal for specific matrices or at least close to optimal with respect to different criteria. The cost of finding a good permutation matrix <span class="math inline">\(\boldsymbol{P}\)</span> is at least of order <span class="math inline">\(\mathcal{O}(n^{3/2})\)</span>. However, there exist good, but suboptimal, approaches for <span class="math inline">\(\mathcal{O}(n\log(n))\)</span>.</p>
<p>A typical Cholesky factorization of a sparse matrix consists of the steps illustrated in the following pseudo code algorithm.</p>
<table class="table">
<colgroup>
<col width="3%">
<col width="96%">
</colgroup>
<thead><tr class="header">
<th>Step</th>
<th>Description</th>
</tr></thead>
<tbody>
<tr class="odd">
<td>[1]</td>
<td>Determine permutation and permute the input matrix <span class="math inline">\(\boldsymbol{A}\)</span> to obtain <span class="math inline">\(\boldsymbol{P}^T\boldsymbol{A}\boldsymbol{P}\)</span>
</td>
</tr>
<tr class="even">
<td>[2]</td>
<td>Symbolic factorization, where the sparsity structure of <span class="math inline">\(\boldsymbol{U}\)</span> is constructed</td>
</tr>
<tr class="odd">
<td>[3]</td>
<td>Numeric factorization, where the elements of <span class="math inline">\(\boldsymbol{U}\)</span> are computed</td>
</tr>
</tbody>
</table>
<p>When factorizing matrices with the same sparsity structure Step 1 and 2 do not need to be repeated. In MCMC algorithms, this is commonly the case, and exploiting this shortcut leads to very considerable gains in computational efficiency (also noticed by <span class="citation">Rue and Held (2005)</span>, page 51). However, none of the existing sparse matrix packages in R (<code>SparseM</code>, <code>Matrix</code>) provide the possibility to carry out Step 3 separately and <code>spam</code> fills this gap.</p>
<p>As for Step 1, there are many different algorithms to find a permutation, for example, the multiple minimum degree (MMD) algorithm, <span class="citation">Liu (1985)</span>, and the reverse Cuthill-McKee (RCM) algorithm, <span class="citation">George (1971)</span>. The resulting sparsity structure in the permuted matrix determines the sparsity structure of the Cholesky factor. As an illustration, Figure shows the sparsity structure of the Cholesky factor resulting from an MMD, an RCM, and no permutation of a precision matrix induced by a second-order neighbor structure of the US counties.</p>
<p>How much fill-in with zeros is present depends on the permutation algorithm, in the example of Figure @ref{fig:ch2:factor} there are <span class="math inline">\(146735\)</span>, <span class="math inline">\(256198\)</span> and <span class="math inline">\(689615\)</span> non-zero elements in the Cholesky factors resulting from the MMD, RCM, and no permutation, respectively. Note that the actual number of non-zero elements of the Cholesky factor may be smaller than what the constructed sparsity structure indicates. Here, there are <span class="math inline">\(14111\)</span>, <span class="math inline">\(97565\)</span> and <span class="math inline">\(398353\)</span> zero elements (up to machine precision) that are not exploited.</p>
<div class="figure" style="text-align: center">
<img src="figures/fig_ch2_factors.png" alt="\label{fig:ch2:factor}Sparsity structure of the Cholesky factor with MMD, RCM and no permutation of a precision matrix induced by a second-order neighbor structure of the US counties. The values *nnzR* and *fillin* are the number of non-zero elements in the sparsity structure of the factor and the fill-in, respectively." width="420"><p class="caption">
Sparsity structure of the Cholesky factor with MMD, RCM and no permutation of a precision matrix induced by a second-order neighbor structure of the US counties. The values <em>nnzR</em> and <em>fillin</em> are the number of non-zero elements in the sparsity structure of the factor and the fill-in, respectively.
</p>
</div>
</div>
<div id="more-about-methods" class="section level1">
<h1 class="hasAnchor">
<a href="#more-about-methods" class="anchor"></a>More about Methods</h1>
<p>For both sparse classes of <code>spam</code> standard methods like <code>plot</code>, <code>dim</code>, <code>backsolve</code>/<code>forwardsolve</code>, <code>determinant</code> (based on a Cholesky factor) are implemented and behave as in the case of full matrices. Print methods display the sparse matrix as a full matrix in case of small matrices and display only the non-zero values otherwise. The corresponding cutoff value as well as other parameters can be set and read via <code>spam.options</code>.</p>
<div id="methods-with-particular-behavior" class="section level2">
<h2 class="hasAnchor">
<a href="#methods-with-particular-behavior" class="anchor"></a>Methods with Particular Behavior</h2>
<p>For the <code>spam</code> class additional methods are defined, for examples <code>rbind</code>/<code>cbind</code>, <code>dim&lt;-</code>, etc. The group generic functions from <code>Math</code>, <code>Math2</code> and <code>Summary</code> are treated particularly since they operate only on the nonzero entries of the <code>spam</code> class. For example, for the matrix <code>A</code> presented in the introduction <code>range(A)</code> is the vector <code>c(0.5, 1)</code>, i.e. the zeros are omitted from the calculation. The help lists further available methods and highlights the (dis-)similarities compared to when applied to regular matrices or arrays.</p>
</div>
<div id="particular-methods-with-ordinary-behavior" class="section level2">
<h2 class="hasAnchor">
<a href="#particular-methods-with-ordinary-behavior" class="anchor"></a>Particular Methods with Ordinary Behavior</h2>
<p>Besides the two sparse classes mentioned above, <code>spam</code> does not maintain different classes for different types of sparse matrices, such as symmetric or diagonal matrices. Doing so would result in some storage and computational gain for some matrix operations, at the cost of user visibility. Instead of creating more classes we consider additional specific operators. As an illustration, consider multiplying a diagonal matrix with a sparse matrix. The operator <code>\%d*\%</code> uses standard matrix multiplication if both sides are matrices or multiplies each column according the diagonal entry if the left hand side is a diagonal matrix represented by vector.</p>
</div>
<div id="importing-foreign-formats" class="section level2">
<h2 class="hasAnchor">
<a href="#importing-foreign-formats" class="anchor"></a>Importing Foreign Formats</h2>
<p><code>spam</code> is not the only R package for sparse matrix algebra. The packages <code>SparseM</code> <span class="citation">Koenker and Ng (2003)</span> and <code>Matrix</code> <span class="citation">Bates and Maechler (2006)</span> contain similar functionalities for handling sparse matrices, however, both packages do not provide the possibility to split up the Cholesky factorization as discussed previously. We briefly discuss the major differences with respect to <code>spam</code>; for a detailed description see their manual.</p>
<p><code>SparseM</code> is also based on the Fortran Cholesky factorization of <span class="citation">E. G. Ng and Peyton (1993)</span> using the MMD permutation and almost exclusively on <code>SparseKit</code>. It was originally designed for large least squares problems and later also ported to <code>S4</code> but is in a few cases inconsistent with existing R methods. It supports different sparse storage systems.</p>
<p><code>Matrix</code> incorporates many classes for sparse and full matrices and is based on C. For sparse matrices, it uses different storage formats, defines classes for different types of matrices and uses a Cholesky factorization based on UMFPACK, <span class="citation">Davis (2004)</span>.</p>
<p><code>spam</code> has a few functions that allow to transform matrix formats of the different packages.</p>
<p><code>spam</code> also contains functions that download matrices from MatrixMarket, a web side that stores many different sparse matrices. The function <code><a href="../reference/import.html">read.MM(file)</a></code>, very similar to the function <code>readMM</code> from <code>Matrix</code>, opens a connection, specified by the argument, and reads a matrix market file. However, as entries of <code>spam</code> matrices are of mode <code>double</code>, integers matrices are coerced to doubles, patterns lead to matrices containing ones and complex are coerced to the real part thereof. In these aforementioned cases, a warning is issued.</p>
<p>MatrixMarket also defines an array format, in which case a (possibly) dense <code>spam</code> object is return (retaining only elements which are larger than <code>getOption('spam.eps')</code>), a warning is issued.</p>
<p>Similarly to <code><a href="../reference/import.html">read.MM(file)</a></code>, the function <code><a href="../reference/import.html">read.HB(file)</a></code> reads matrices in the Harwell-Boeing format. Currently, only real assembled Harwell-Boeing can be read with <code>read.HB</code>. Reading MatrixMarket formats is more flexible.</p>
<p>The functions are based on <code>readHB</code> and <code>readMM</code> from the library <code>Matrix</code> to build the connection and read the raw data. At present, <code><a href="../reference/import.html">read.MM(file)</a></code> is more flexible than <code>readMM</code>.</p>
<p>For many operations, <code>spam</code> is faster than <code>Matrix</code> and <code>SparseM</code>. It would also be interesting to compare <code>spam</code> and the sparse matrix routines of <code>Matlab</code> (see Figure 6 of <span class="citation">Furrer, Genton, and Nychka (2006)</span> for a comparison between <code>SparseM</code> and Matlab).</p>
</div>
</div>
<div id="bibliography" class="section level1 unnumbered">
<h1 class="hasAnchor">
<a href="#bibliography" class="anchor"></a>Bibliography</h1>
<div id="refs" class="references">
<div id="ref-Bates:06">
<p>Bates, Douglas, and Martin Maechler. 2006. <em>Matrix: A Matrix Package for R</em>.</p>
</div>
<div id="ref-Cham:93">
<p>Chambers, John M. 1998. <em>Programming with Data: A Guide to the S Language</em>. Secaucus, NJ, USA: Springer-Verlag New York, Inc.</p>
</div>
<div id="ref-Davi:04">
<p>Davis, Timothy A. 2004. “Algorithm 832: UMFPACK V4.3—an Unsymmetric-Pattern Multifrontal Method.” <em>ACM Transactions on Mathematical Software (TOMS)</em> 30 (2). New York, NY, USA: ACM: 196–99. doi:<a href="https://doi.org/10.1145/992200.992206">10.1145/992200.992206</a>.</p>
</div>
<div id="ref-Furr:Beng:07">
<p>Furrer, R., and T. Bengtsson. 2007. “Estimation of High-Dimensional Prior and Posteriori Covariance Matrices in Kalman Filter Variants.” <em>J. Multivariate Anal.</em> 98 (2): 227–55. doi:<a href="https://doi.org/10.1016/j.jmva.2006.08.003">10.1016/j.jmva.2006.08.003</a>.</p>
</div>
<div id="ref-Furr:Sain:10">
<p>Furrer, R., and S. R. Sain. 2010. “spam: A Sparse Matrix R Package with Emphasis on MCMC Methods for Gaussian Markov Random Fields.” <em>Journal of Statistical Software</em> 36 (10): 1–25. <a href="http://www.jstatsoft.org/v36/i10/" class="uri">http://www.jstatsoft.org/v36/i10/</a>.</p>
</div>
<div id="ref-Furr:Gent:Nych:06">
<p>Furrer, R., M. G. Genton, and D. Nychka. 2006. “Covariance Tapering for Interpolation of Large Spatial Datasets.” <em>J. Comput. Graph. Statist.</em> 15 (3): 502–23.</p>
</div>
<div id="ref-Geor:71">
<p>George, John Alan. 1971. “Computer Implementation of the Finite Element Method.” PhD thesis, Stanford, CA, USA: Stanford University.</p>
</div>
<div id="ref-Koen:Ng:03">
<p>Koenker, Roger, and Pin Ng. 2003. <em>SparseM: Sparse Matrix Package for R</em>.</p>
</div>
<div id="ref-Liu:85">
<p>Liu, Joseph W. H. 1985. “Modification of the Minimum-Degree Algorithm by Multiple Elimination.” <em>ACM Transactions on Mathematical Software (TOMS)</em> 11 (2). New York, NY, USA: ACM: 141–53. doi:<a href="https://doi.org/10.1145/214392.214398">10.1145/214392.214398</a>.</p>
</div>
<div id="ref-Luml:04">
<p>Lumley, Thomas. 2004. “Programmers’ Niche: A Simple Class, in S3 and S4.” <em>R News</em> 4(1) (1): 33–36.</p>
</div>
<div id="ref-Ng:Peyt:93">
<p>Ng, Esmond G., and Barry W. Peyton. 1993. “Block Sparse Cholesky Algorithms on Advanced Uniprocessor Computers.” <em>SIAM Journal on Scientific Computing</em> 14 (5). Philadelphia, PA, USA: Society for Industrial; Applied Mathematics: 1034–56. doi:<a href="https://doi.org/10.1137/0914063">10.1137/0914063</a>.</p>
</div>
<div id="ref-Rue:Held:05">
<p>Rue, H., and L. Held. 2005. <em>Gaussian Markov Random Fields: Theory and Applications</em>. Chapman &amp; Hall, London.</p>
</div>
</div>
</div>
</div>
<div class="col-md-3 hidden-xs hidden-sm" id="sidebar">
<div id="tocnav">
<h2 class="hasAnchor">
<a href="#tocnav" class="anchor"></a>Contents</h2>
<ul class="nav nav-pills nav-stacked">
<li><a href="#rational-for-spam">Rational for spam</a></li>
<li><a href="#a-simple-example">A Simple Example</a></li>
<li><a href="#creating-sparse-matrices">Creating Sparse Matrices</a></li>
<li><a href="#displaying">Displaying</a></li>
<li><a href="#solving-linear-systems">Solving Linear Systems</a></li>
<li>
<a href="#more-about-methods">More about Methods</a><ul class="nav nav-pills nav-stacked">
<li><a href="#methods-with-particular-behavior">Methods with Particular Behavior</a></li>
<li><a href="#particular-methods-with-ordinary-behavior">Particular Methods with Ordinary Behavior</a></li>
<li><a href="#importing-foreign-formats">Importing Foreign Formats</a></li>
</ul>
</li>
<li><a href="#bibliography">Bibliography</a></li>
</ul>
</div>
</div>
</div>
<footer><div class="copyright">
<p>Developed by Reinhard Furrer.</p>
</div>
<div class="pkgdown">
<p>Site built with <a href="http://pkgdown.r-lib.org/">pkgdown</a>.</p>
</div>
</footer>
</div>
</body>
</html>
......@@ -144,7 +144,7 @@
<p>Gerber F, Moesinger K, Furrer R (2017).
&ldquo;Extending R packages to support 64-bit compiled code: An illustration with spam64 and GIMMS NDVI3g data.&rdquo;
<em>Computer &amp; Geoscience</em>, <b>104</b>, 109&ndash;119.
ISSN 0098-3004, doi: <a href="https://doi.org/10.1016/j.cageo.2016.11.015">10.1016/j.cageo.2016.11.015</a>.
ISSN 0098-3004, doi: <a href="http://doi.org/10.1016/j.cageo.2016.11.015">10.1016/j.cageo.2016.11.015</a>.
</p>
<pre>@Article{,
title = {Extending {R} packages to support 64-bit compiled code: An illustration with spam64 and {GIMMS} {NDVI3g} data},
......
/* Docsearch -------------------------------------------------------------- */
/*
Source: https://github.com/algolia/docsearch/
License: MIT
*/
.algolia-autocomplete {
display: block;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1
}
.algolia-autocomplete .ds-dropdown-menu {
width: 100%;
min-width: none;
max-width: none;
padding: .75rem 0;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, .1);
box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175);
}
@media (min-width:768px) {
.algolia-autocomplete .ds-dropdown-menu {
width: 175%
}
}
.algolia-autocomplete .ds-dropdown-menu::before {
display: none
}
.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] {
padding: 0;
background-color: rgb(255,255,255);
border: 0;
max-height: 80vh;
}
.algolia-autocomplete .ds-dropdown-menu .ds-suggestions {
margin-top: 0
}
.algolia-autocomplete .algolia-docsearch-suggestion {
padding: 0;
overflow: visible
}
.algolia-autocomplete .algolia-docsearch-suggestion--category-header {
padding: .125rem 1rem;
margin-top: 0;
font-size: 1.3em;
font-weight: 500;
color: #00008B;
border-bottom: 0
}
.algolia-autocomplete .algolia-docsearch-suggestion--wrapper {
float: none;
padding-top: 0
}
.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column {
float: none;
width: auto;
padding: 0;
text-align: left
}
.algolia-autocomplete .algolia-docsearch-suggestion--content {
float: none;
width: auto;
padding: 0
}
.algolia-autocomplete .algolia-docsearch-suggestion--content::before {
display: none
}
.algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header {
padding-top: .75rem;
margin-top: .75rem;
border-top: 1px solid rgba(0, 0, 0, .1)
}
.algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column {
display: block;
padding: .1rem 1rem;
margin-bottom: 0.1;
font-size: 1.0em;
font-weight: 400
/* display: none */
}
.algolia-autocomplete .algolia-docsearch-suggestion--title {
display: block;
padding: .25rem 1rem;
margin-bottom: 0;
font-size: 0.9em;
font-weight: 400
}
.algolia-autocomplete .algolia-docsearch-suggestion--text {
padding: 0 1rem .5rem;
margin-top: -.25rem;
font-size: 0.8em;
font-weight: 400;
line-height: 1.25
}
.algolia-autocomplete .algolia-docsearch-footer {
width: 110px;
height: 20px;
z-index: 3;
margin-top: 10.66667px;
float: right;
font-size: 0;
line-height: 0;
}
.algolia-autocomplete .algolia-docsearch-footer--logo {
background-image: url("data:image/svg+xml;utf8,<svg viewBox='0 0 130 18' xmlns='http://www.w3.org/2000/svg'><defs><linearGradient x1='-36.868%' y1='134.936%' x2='129.432%' y2='-27.7%' id='a'><stop stop-color='%2300AEFF' offset='0%'/><stop stop-color='%233369E7' offset='100%'/></linearGradient></defs><g fill='none' fill-rule='evenodd'><path d='M59.399.022h13.299a2.372 2.372 0 0 1 2.377 2.364V15.62a2.372 2.372 0 0 1-2.377 2.364H59.399a2.372 2.372 0 0 1-2.377-2.364V2.381A2.368 2.368 0 0 1 59.399.022z' fill='url(%23a)'/><path d='M66.257 4.56c-2.815 0-5.1 2.272-5.1 5.078 0 2.806 2.284 5.072 5.1 5.072 2.815 0 5.1-2.272 5.1-5.078 0-2.806-2.279-5.072-5.1-5.072zm0 8.652c-1.983 0-3.593-1.602-3.593-3.574 0-1.972 1.61-3.574 3.593-3.574 1.983 0 3.593 1.602 3.593 3.574a3.582 3.582 0 0 1-3.593 3.574zm0-6.418v2.664c0 .076.082.131.153.093l2.377-1.226c.055-.027.071-.093.044-.147a2.96 2.96 0 0 0-2.465-1.487c-.055 0-.11.044-.11.104l.001-.001zm-3.33-1.956l-.312-.311a.783.783 0 0 0-1.106 0l-.372.37a.773.773 0 0 0 0 1.101l.307.305c.049.049.121.038.164-.011.181-.245.378-.479.597-.697.225-.223.455-.42.707-.599.055-.033.06-.109.016-.158h-.001zm5.001-.806v-.616a.781.781 0 0 0-.783-.779h-1.824a.78.78 0 0 0-.783.779v.632c0 .071.066.12.137.104a5.736 5.736 0 0 1 1.588-.223c.52 0 1.035.071 1.534.207a.106.106 0 0 0 .131-.104z' fill='%23FFF'/><path d='M102.162 13.762c0 1.455-.372 2.517-1.123 3.193-.75.676-1.895 1.013-3.44 1.013-.564 0-1.736-.109-2.673-.316l.345-1.689c.783.163 1.819.207 2.361.207.86 0 1.473-.174 1.84-.523.367-.349.548-.866.548-1.553v-.349a6.374 6.374 0 0 1-.838.316 4.151 4.151 0 0 1-1.194.158 4.515 4.515 0 0 1-1.616-.278 3.385 3.385 0 0 1-1.254-.817 3.744 3.744 0 0 1-.811-1.351c-.192-.539-.29-1.504-.29-2.212 0-.665.104-1.498.307-2.054a3.925 3.925 0 0 1 .904-1.433 4.124 4.124 0 0 1 1.441-.926 5.31 5.31 0 0 1 1.945-.365c.696 0 1.337.087 1.961.191a15.86 15.86 0 0 1 1.588.332v8.456h-.001zm-5.954-4.206c0 .893.197 1.885.592 2.299.394.414.904.621 1.528.621.34 0 .663-.049.964-.142a2.75 2.75 0 0 0 .734-.332v-5.29a8.531 8.531 0 0 0-1.413-.18c-.778-.022-1.369.294-1.786.801-.411.507-.619 1.395-.619 2.223zm16.12 0c0 .719-.104 1.264-.318 1.858a4.389 4.389 0 0 1-.904 1.52c-.389.42-.854.746-1.402.975-.548.229-1.391.36-1.813.36-.422-.005-1.26-.125-1.802-.36a4.088 4.088 0 0 1-1.397-.975 4.486 4.486 0 0 1-.909-1.52 5.037 5.037 0 0 1-.329-1.858c0-.719.099-1.411.318-1.999.219-.588.526-1.09.92-1.509.394-.42.865-.741 1.402-.97a4.547 4.547 0 0 1 1.786-.338 4.69 4.69 0 0 1 1.791.338c.548.229 1.01