1470 lines
82 KiB
HTML
1470 lines
82 KiB
HTML
<!--
|
|
Automatically generated HTML file from DocOnce source
|
|
(https://github.com/hplgit/doconce/)
|
|
-->
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<meta name="generator" content="DocOnce: https://github.com/hplgit/doconce/" />
|
|
<meta name="description" content="Data analysis and Machine Learning Lectures: Linear Algebra and Handling of Arrays">
|
|
|
|
<title>Data analysis and Machine Learning Lectures: Linear Algebra and Handling of Arrays</title>
|
|
|
|
|
|
<style type="text/css">
|
|
/* bloodish style */
|
|
|
|
body {
|
|
font-family: Helvetica, Verdana, Arial, Sans-serif;
|
|
color: #404040;
|
|
background: #ffffff;
|
|
}
|
|
h1 { font-size: 1.8em; color: #8A0808; }
|
|
h2 { font-size: 1.6em; color: #8A0808; }
|
|
h3 { font-size: 1.4em; color: #8A0808; }
|
|
h4 { color: #8A0808; }
|
|
a { color: #8A0808; text-decoration:none; }
|
|
tt { font-family: "Courier New", Courier; }
|
|
/* pre style removed because it will interfer with pygments */
|
|
p { text-indent: 0px; }
|
|
hr { border: 0; width: 80%; border-bottom: 1px solid #aaa}
|
|
p.caption { width: 80%; font-style: normal; text-align: left; }
|
|
hr.figure { border: 0; width: 80%; border-bottom: 1px solid #aaa}
|
|
.alert-text-small { font-size: 80%; }
|
|
.alert-text-large { font-size: 130%; }
|
|
.alert-text-normal { font-size: 90%; }
|
|
.alert {
|
|
padding:8px 35px 8px 14px; margin-bottom:18px;
|
|
text-shadow:0 1px 0 rgba(255,255,255,0.5);
|
|
border:1px solid #bababa;
|
|
border-radius: 4px;
|
|
-webkit-border-radius: 4px;
|
|
-moz-border-radius: 4px;
|
|
color: #555;
|
|
background-color: #f8f8f8;
|
|
background-position: 10px 5px;
|
|
background-repeat: no-repeat;
|
|
background-size: 38px;
|
|
padding-left: 55px;
|
|
width: 75%;
|
|
}
|
|
.alert-block {padding-top:14px; padding-bottom:14px}
|
|
.alert-block > p, .alert-block > ul {margin-bottom:1em}
|
|
.alert li {margin-top: 1em}
|
|
.alert-block p+p {margin-top:5px}
|
|
.alert-notice { background-image: url(https://cdn.rawgit.com/hplgit/doconce/master/bundled/html_images/small_gray_notice.png); }
|
|
.alert-summary { background-image:url(https://cdn.rawgit.com/hplgit/doconce/master/bundled/html_images/small_gray_summary.png); }
|
|
.alert-warning { background-image: url(https://cdn.rawgit.com/hplgit/doconce/master/bundled/html_images/small_gray_warning.png); }
|
|
.alert-question {background-image:url(https://cdn.rawgit.com/hplgit/doconce/master/bundled/html_images/small_gray_question.png); }
|
|
|
|
div { text-align: justify; text-justify: inter-word; }
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
<!-- tocinfo
|
|
{'highest level': 2,
|
|
'sections': [('Introduction', 2, None, '___sec0'),
|
|
('Important Matrix and vector handling packages',
|
|
2,
|
|
None,
|
|
'___sec1'),
|
|
('Basic Matrix Features', 2, None, '___sec2'),
|
|
('Basic Matrix Features', 2, None, '___sec3'),
|
|
('Basic Matrix Features', 2, None, '___sec4'),
|
|
('Some famous Matrices', 2, None, '___sec5'),
|
|
('Basic Matrix Features', 2, None, '___sec6'),
|
|
('Numpy and arrays', 2, None, '___sec7'),
|
|
('Matrices in Python', 2, None, '___sec8'),
|
|
('Matrix Handling in C/C++, Static and Dynamical allocation',
|
|
2,
|
|
None,
|
|
'___sec9'),
|
|
('Matrix Handling in C/C++', 2, None, '___sec10'),
|
|
('Matrix Handling in C/C++', 2, None, '___sec11'),
|
|
('Dynamic memory allocation in C/C++', 2, None, '___sec12'),
|
|
('Matrix Handling in C/C++, Dynamic Allocation',
|
|
2,
|
|
None,
|
|
'___sec13'),
|
|
('Armadillo, recommended!!', 2, None, '___sec14'),
|
|
('Armadillo, simple examples', 2, None, '___sec15'),
|
|
('Armadillo, how to compile and install', 2, None, '___sec16'),
|
|
('Armadillo, simple examples', 2, None, '___sec17'),
|
|
('Armadillo, simple examples', 2, None, '___sec18'),
|
|
('Armadillo, simple examples', 2, None, '___sec19'),
|
|
('Armadillo, simple examples', 2, None, '___sec20'),
|
|
('Armadillo, simple examples', 2, None, '___sec21'),
|
|
('Armadillo, simple examples', 2, None, '___sec22'),
|
|
('Armadillo, simple examples', 2, None, '___sec23'),
|
|
('Gaussian Elimination', 2, None, '___sec24'),
|
|
('Gaussian Elimination', 2, None, '___sec25'),
|
|
('Gaussian Elimination', 2, None, '___sec26'),
|
|
('Gaussian Elimination', 2, None, '___sec27'),
|
|
('Gaussian Elimination', 2, None, '___sec28'),
|
|
('Gaussian Elimination', 2, None, '___sec29'),
|
|
('Gaussian Elimination', 2, None, '___sec30'),
|
|
('Linear Algebra Methods', 2, None, '___sec31'),
|
|
('LU Decomposition', 2, None, '___sec32'),
|
|
('LU Decomposition', 2, None, '___sec33'),
|
|
('LU Decomposition, why?', 2, None, '___sec34'),
|
|
('LU Decomposition, linear equations', 2, None, '___sec35'),
|
|
('LU Decomposition, linear equations', 2, None, '___sec36'),
|
|
('LU Decomposition, why?', 2, None, '___sec37'),
|
|
('LU Decomposition, linear equations', 2, None, '___sec38'),
|
|
('LU Decomposition, the inverse of a matrix',
|
|
2,
|
|
None,
|
|
'___sec39'),
|
|
('LU Decomposition, the inverse of a matrix',
|
|
2,
|
|
None,
|
|
'___sec40'),
|
|
('LU Decomposition, the inverse', 2, None, '___sec41'),
|
|
('"Using Armadillo to perform an LU '
|
|
'decomposition":"https://github.com/CompPhysics/ComputationalPhysicsMSU/blob/master/doc/Programs/CppQtCodesLectures/MatrixTest/main.cpp"',
|
|
2,
|
|
None,
|
|
'___sec42')]}
|
|
end of tocinfo -->
|
|
|
|
<body>
|
|
|
|
|
|
|
|
<script type="text/x-mathjax-config">
|
|
MathJax.Hub.Config({
|
|
TeX: {
|
|
equationNumbers: { autoNumber: "AMS" },
|
|
extensions: ["AMSmath.js", "AMSsymbols.js", "autobold.js", "color.js"]
|
|
}
|
|
});
|
|
</script>
|
|
<script type="text/javascript" async
|
|
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<!-- ------------------- main content ---------------------- -->
|
|
|
|
|
|
|
|
<center><h1>Data analysis and Machine Learning Lectures: Linear Algebra and Handling of Arrays</h1></center> <!-- document title -->
|
|
|
|
<p>
|
|
<!-- author(s): Morten Hjorth-Jensen -->
|
|
|
|
<center>
|
|
<b>Morten Hjorth-Jensen</b> [1, 2]
|
|
</center>
|
|
|
|
<p>
|
|
<!-- institution(s) -->
|
|
|
|
<center>[1] <b>Department of Physics, University of Oslo</b></center>
|
|
<center>[2] <b>Department of Physics and Astronomy and National Superconducting Cyclotron Laboratory, Michigan State University</b></center>
|
|
<br>
|
|
<p>
|
|
<center><h4>May 24, 2018</h4></center> <!-- date -->
|
|
<br>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec0">Introduction </h2>
|
|
The aim of this set of lectures is to review some central linear algebra algorithms that we will need in our
|
|
data analysis part and in the construction of Machine Learning algorithms (ML).
|
|
This will allow us to introduce some central programming features of high-level languages like Python and
|
|
compiled languages like C++ and/or Fortran.
|
|
|
|
<p>
|
|
As discussed in the introductory notes, these series of lectures focuses both on using
|
|
central Python packages like <b>tensorflow</b> and <b>scikit-learn</b> as well
|
|
as writing your own codes for some central ML algorithms. The
|
|
latter can be written in a language of your choice, be it Python, Julia, R,
|
|
Rust, C++, Fortran etc. In order to avoid confusion however, in these lectures we will limit our
|
|
attention to Python, C++ and Fortran.
|
|
|
|
<p>
|
|
<!-- !split -->
|
|
|
|
<h2 id="___sec1">Important Matrix and vector handling packages </h2>
|
|
|
|
<p>
|
|
There are several central software packages for linear algebra and eigenvalue problems. Several of the more
|
|
popular ones have been wrapped into ofter software packages like those from the widely used text <b>Numerical Recipes</b>. The original source codes in many of the available packages are often taken from the widely used
|
|
software package LAPACK, which follows two other popular packages
|
|
developed in the 1970s, namely EISPACK and LINPACK. We describe them shortly here.
|
|
|
|
<ul>
|
|
<li> LINPACK: package for linear equations and least square problems.</li>
|
|
<li> LAPACK:package for solving symmetric, unsymmetric and generalized eigenvalue problems. From LAPACK's website <a href="http://www.netlib.org" target="_blank"><tt>http://www.netlib.org</tt></a> it is possible to download for free all source codes from this library. Both C/C++ and Fortran versions are available.</li>
|
|
<li> BLAS (I, II and III): (Basic Linear Algebra Subprograms) are routines that provide standard building blocks for performing basic vector and matrix operations. Blas I is vector operations, II vector-matrix operations and III matrix-matrix operations. Highly parallelized and efficient codes, all available for download from <a href="http://www.netlib.org" target="_blank"><tt>http://www.netlib.org</tt></a>.</li>
|
|
</ul>
|
|
|
|
When dealing with matrices and vectors a central issue is memory
|
|
handling and allocation. If our code is written in Python the way we
|
|
declare these objects and the way they are handled, interpreted and
|
|
used by say a linear algebra library, requires codes that interface
|
|
our Python program with such libraries. For Python programmers,
|
|
<b>Numpy</b> is by now the standard Python package for numerical arrays in
|
|
Python as well as the source of functions which act on these
|
|
arrays. These functions span from eigenvalue solvers to functions that
|
|
compute the mean value, variance or the covariance matrix. If you are
|
|
not familiar with how arrays are handled in say Python or compiled
|
|
languages like C++ and Fortran, the sections in this chapter may be
|
|
useful. For C++ programmer, <b>Armadillo</b> is widely used library for
|
|
linear algebra and eigenvalue problems. In addition it offers a
|
|
convenient way to handle and organize arrays. We discuss this library
|
|
as well. Before we proceed we believe it may be convenient to repeat some basic features of
|
|
matrices and vectors.
|
|
|
|
<p>
|
|
<!-- !split -->
|
|
|
|
<h2 id="___sec2">Basic Matrix Features </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Matrix properties reminder.</b>
|
|
<p>
|
|
$$
|
|
\mathbf{A} =
|
|
\begin{bmatrix} a_{11} & a_{12} & a_{13} & a_{14} \\
|
|
a_{21} & a_{22} & a_{23} & a_{24} \\
|
|
a_{31} & a_{32} & a_{33} & a_{34} \\
|
|
a_{41} & a_{42} & a_{43} & a_{44}
|
|
\end{bmatrix}\qquad
|
|
\mathbf{I} =
|
|
\begin{bmatrix} 1 & 0 & 0 & 0 \\
|
|
0 & 1 & 0 & 0 \\
|
|
0 & 0 & 1 & 0 \\
|
|
0 & 0 & 0 & 1
|
|
\end{bmatrix}
|
|
$$
|
|
</div>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec3">Basic Matrix Features </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
The inverse of a matrix is defined by
|
|
|
|
$$
|
|
\mathbf{A}^{-1} \cdot \mathbf{A} = I
|
|
$$
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec4">Basic Matrix Features </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Matrix Properties Reminder.</b>
|
|
<p>
|
|
|
|
<p>
|
|
<table border="1">
|
|
<thead>
|
|
<tr><th align="center"> Relations </th> <th align="center"> Name </th> <th align="center"> matrix elements </th> </tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td align="center"> \( A = A^{T} \) </td> <td align="center"> symmetric </td> <td align="center"> \( a_{ij} = a_{ji} \) </td> </tr>
|
|
<tr><td align="center"> \( A = \left (A^{T} \right )^{-1} \) </td> <td align="center"> real orthogonal </td> <td align="center"> \( \sum_k a_{ik} a_{jk} = \sum_k a_{ki} a_{kj} = \delta_{ij} \) </td> </tr>
|
|
<tr><td align="center"> \( A = A^{ * } \) </td> <td align="center"> real matrix </td> <td align="center"> \( a_{ij} = a_{ij}^{ * } \) </td> </tr>
|
|
<tr><td align="center"> \( A = A^{\dagger} \) </td> <td align="center"> hermitian </td> <td align="center"> \( a_{ij} = a_{ji}^{ * } \) </td> </tr>
|
|
<tr><td align="center"> \( A = \left (A^{\dagger} \right )^{-1} \) </td> <td align="center"> unitary </td> <td align="center"> \( \sum_k a_{ik} a_{jk}^{ * } = \sum_k a_{ki}^{ * } a_{kj} = \delta_{ij} \) </td> </tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec5">Some famous Matrices </h2>
|
|
|
|
<ul>
|
|
<li> Diagonal if \( a_{ij}=0 \) for \( i\ne j \)</li>
|
|
<li> Upper triangular if \( a_{ij}=0 \) for \( i > j \)</li>
|
|
<li> Lower triangular if \( a_{ij}=0 \) for \( i < j \)</li>
|
|
<li> Upper Hessenberg if \( a_{ij}=0 \) for \( i > j+1 \)</li>
|
|
<li> Lower Hessenberg if \( a_{ij}=0 \) for \( i < j+1 \)</li>
|
|
<li> Tridiagonal if \( a_{ij}=0 \) for \( |i -j| > 1 \)</li>
|
|
<li> Lower banded with bandwidth \( p \): \( a_{ij}=0 \) for \( i > j+p \)</li>
|
|
<li> Upper banded with bandwidth \( p \): \( a_{ij}=0 \) for \( i < j+p \)</li>
|
|
<li> Banded, block upper triangular, block lower triangular....</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec6">Basic Matrix Features </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Some Equivalent Statements.</b>
|
|
<p>
|
|
For an \( N\times N \) matrix \( \mathbf{A} \) the following properties are all equivalent
|
|
|
|
<ul>
|
|
<li> If the inverse of \( \mathbf{A} \) exists, \( \mathbf{A} \) is nonsingular.</li>
|
|
<li> The equation \( \mathbf{Ax}=0 \) implies \( \mathbf{x}=0 \).</li>
|
|
<li> The rows of \( \mathbf{A} \) form a basis of \( R^N \).</li>
|
|
<li> The columns of \( \mathbf{A} \) form a basis of \( R^N \).</li>
|
|
<li> \( \mathbf{A} \) is a product of elementary matrices.</li>
|
|
<li> \( 0 \) is not eigenvalue of \( \mathbf{A} \).</li>
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec7">Numpy and arrays </h2>
|
|
<a href="http://www.numpy.org/" target="_blank">Numpy</a> provides an easy way to handle arrays in Python. The standard way to import this library is as
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
n <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(size<span style="color: #666666">=</span>n)
|
|
<span style="color: #008000; font-weight: bold">print</span>(x)
|
|
</pre></div>
|
|
<p>
|
|
Here we have defined a vector \( x \) with \( n=10 \) elements with its values given by the Normal distribution \( N(0,1) \).
|
|
Another alternative is to declare a vector as follows
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>array([<span style="color: #666666">1</span>, <span style="color: #666666">2</span>, <span style="color: #666666">3</span>])
|
|
<span style="color: #008000; font-weight: bold">print</span>(x)
|
|
</pre></div>
|
|
<p>
|
|
Here we have defined a vector with three elements, with \( x_0=1 \), \( x_1=2 \) and \( x_2=3 \). Note that both Python and C++
|
|
start numbering array elements from \( 0 \) and on. This means that a vector with \( n \) elements has a sequence of entities \( x_0, x_1, x_2, \dots, x_{n-1} \). We could also let (recommended) Numpy to compute the logarithms of a specific array as
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([<span style="color: #666666">4</span>, <span style="color: #666666">7</span>, <span style="color: #666666">8</span>]))
|
|
<span style="color: #008000; font-weight: bold">print</span>(x)
|
|
</pre></div>
|
|
<p>
|
|
Here we have used Numpy's unary function \( np.log \). This function is
|
|
highly tuned to compute array elements since the code is vectorized
|
|
and does not require looping. We normaly recommend that you use the
|
|
Numpy intrinsic functions instead of the corresponding <b>log</b> function
|
|
from Python's <b>math</b> module. The looping is done explicitely by the
|
|
<b>np.log</b> function. The alternative, and slower way to compute the
|
|
logarithms of a vector would be to write
|
|
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">math</span> <span style="color: #008000; font-weight: bold">import</span> log
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>array([<span style="color: #666666">4</span>, <span style="color: #666666">7</span>, <span style="color: #666666">8</span>])
|
|
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(<span style="color: #666666">0</span>, <span style="color: #008000">len</span>(x)):
|
|
x[i] <span style="color: #666666">=</span> log(x[i])
|
|
<span style="color: #008000; font-weight: bold">print</span>(x)
|
|
</pre></div>
|
|
<p>
|
|
We note that our code is much longer already and we need to import the <b>log</b> function from the <b>math</b> module.
|
|
The attentive reader will also notice that the output is \( [1, 1, 2] \). Python interprets automacally our numbers as integers (like the <b>automatic</b> keyword in C++). To change this we could define our array elements to be double precision numbers as
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([<span style="color: #666666">4</span>, <span style="color: #666666">7</span>, <span style="color: #666666">8</span>], dtype <span style="color: #666666">=</span> np<span style="color: #666666">.</span>float64))
|
|
<span style="color: #008000; font-weight: bold">print</span>(x)
|
|
</pre></div>
|
|
<p>
|
|
or simply write them as double precision numbers (Python uses 64 bits as default for floating point type variables), that is
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([<span style="color: #666666">4.0</span>, <span style="color: #666666">7.0</span>, <span style="color: #666666">8.0</span>])
|
|
<span style="color: #008000; font-weight: bold">print</span>(x)
|
|
</pre></div>
|
|
<p>
|
|
To check the number of bytes (remember that one byte contains eight bits for double precision variables), you can use simple use the <b>itemsize</b> functionality (the array \( x \) is actually an object which inherits the functionalities defined in Numpy) as
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([<span style="color: #666666">4.0</span>, <span style="color: #666666">7.0</span>, <span style="color: #666666">8.0</span>])
|
|
<span style="color: #008000; font-weight: bold">print</span>(x<span style="color: #666666">.</span>itemsize)
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec8">Matrices in Python </h2>
|
|
Having defined vectors, we are now ready to try out matrices. We can define a \( 3 \times 3 \) real matrix \( \hat{A} \)
|
|
as (recall that we user lowercase letters for vectors and uppercase letters for matrices)
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
A <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([ [<span style="color: #666666">4.0</span>, <span style="color: #666666">7.0</span>, <span style="color: #666666">8.0</span>], [<span style="color: #666666">3.0</span>, <span style="color: #666666">10.0</span>, <span style="color: #666666">11.0</span>], [<span style="color: #666666">4.0</span>, <span style="color: #666666">5.0</span>, <span style="color: #666666">7.0</span>] ]))
|
|
<span style="color: #008000; font-weight: bold">print</span>(A)
|
|
</pre></div>
|
|
<p>
|
|
If we use the <b>shape</b> function we would get \( (3, 3) \) as output, that is verifying that our matrix is a \( 3\times 3 \) matrix. We can slice the matrix and print for example the first column (Python organized matrix elements in a row-major order, see below) as
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
A <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([ [<span style="color: #666666">4.0</span>, <span style="color: #666666">7.0</span>, <span style="color: #666666">8.0</span>], [<span style="color: #666666">3.0</span>, <span style="color: #666666">10.0</span>, <span style="color: #666666">11.0</span>], [<span style="color: #666666">4.0</span>, <span style="color: #666666">5.0</span>, <span style="color: #666666">7.0</span>] ]))
|
|
<span style="color: #408080; font-style: italic"># print the first column, row-major order and elements start with 0</span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(A[:,<span style="color: #666666">0</span>])
|
|
</pre></div>
|
|
<p>
|
|
We can continue this was by printing out other columns or rows. The example here prints out the second column
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
A <span style="color: #666666">=</span> np<span style="color: #666666">.</span>log(np<span style="color: #666666">.</span>array([ [<span style="color: #666666">4.0</span>, <span style="color: #666666">7.0</span>, <span style="color: #666666">8.0</span>], [<span style="color: #666666">3.0</span>, <span style="color: #666666">10.0</span>, <span style="color: #666666">11.0</span>], [<span style="color: #666666">4.0</span>, <span style="color: #666666">5.0</span>, <span style="color: #666666">7.0</span>] ]))
|
|
<span style="color: #408080; font-style: italic"># print the first column, row-major order and elements start with 0</span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(A[<span style="color: #666666">1</span>,:])
|
|
</pre></div>
|
|
<p>
|
|
Numpy contains many other functionalities that allow us to slice, subdivide etc etc arrays. We strongly recommend that you look up the <a href="http://www.numpy.org/" target="_blank">Numpy website for more details</a>. Useful functions when defining a matrix are the <b>np.zeros</b> function which declares a matrix of a given dimension and sets all elements to zero
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
n <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
|
<span style="color: #408080; font-style: italic"># define a matrix of dimension 10 x 10 and set all elements to zero</span>
|
|
A <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros( (n, n) )
|
|
<span style="color: #008000; font-weight: bold">print</span>(A)
|
|
</pre></div>
|
|
<p>
|
|
or initializing all elements to
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
n <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
|
<span style="color: #408080; font-style: italic"># define a matrix of dimension 10 x 10 and set all elements to one</span>
|
|
A <span style="color: #666666">=</span> np<span style="color: #666666">.</span>ones( (n, n) )
|
|
<span style="color: #008000; font-weight: bold">print</span>(A)
|
|
</pre></div>
|
|
<p>
|
|
or as unitarily distributed random numbers (see the material on random number generators in the statistics part)
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
n <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
|
<span style="color: #408080; font-style: italic"># define a matrix of dimension 10 x 10 and set all elements to random numbers with x \in [0, 1]</span>
|
|
A <span style="color: #666666">=</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>rand(n, n)
|
|
<span style="color: #008000; font-weight: bold">print</span>(A)
|
|
</pre></div>
|
|
<p>
|
|
As we will see throughout these lectures, there are several extremely useful functionalities in Numpy.
|
|
As an example, consider the discussion of the covariance matrix. Suppose we have defined three vectors
|
|
\( \hat{x}, \hat{y}, \hat{z} \) with \( n \) elements each. The covariance matrix is defined as
|
|
$$
|
|
\hat{\Sigma} = \begin{bmatrix} \sigma_{xx} & \sigma_{xy} & \sigma_{xz} \\
|
|
\sigma_{yx} & \sigma_{yy} & \sigma_{yz} \\
|
|
\sigma_{zx} & \sigma_{zy} & \sigma_{zz}
|
|
\end{bmatrix},
|
|
$$
|
|
|
|
where for example
|
|
$$
|
|
\sigma_{xy} =\frac{1}{n} \sum_{i=0}^{n-1}(x_i- \overline{x})(y_i- \overline{y}).
|
|
$$
|
|
|
|
The Numpy function <b>np.cov</b> calculates the covariance elements using the factor \( 1/(n-1) \) instead of \( 1/n \) since it assumes we do not have the exact mean values. For a more in-depth discussion of the covariance and covariance matrix and its meaning, we refer you to the lectures on statistics.
|
|
The following simple function uses the <b>np.vstack</b> function which takes each vector of dimension \( 1\times n \) and produces a $ 3\times n$ matrix \( \hat{W} \)
|
|
$$
|
|
\hat{W} = \begin{bmatrix} x_0 & y_0 & z_0 \\
|
|
x_1 & y_1 & z_1 \\
|
|
x_2 & y_2 & z_2 \\
|
|
\dots & \dots & \dots \\
|
|
x_{n-2} & y_{n-2} & z_{n-2} \\
|
|
x_{n-1} & y_{n-1} & z_{n-1}
|
|
\end{bmatrix},
|
|
$$
|
|
|
|
<p>
|
|
which in turn is converted into into the \( 3 times 3 \) covariance matrix
|
|
\( \hat{\Sigma} \) via the Numpy function <b>np.cov()</b>. In our review of
|
|
statistical functions and quantities we will discuss more about the
|
|
meaning of the covariance matrix. Here we note that we can calculate
|
|
the mean value of each set of samples \( \hat{x} \) etc using the Numpy
|
|
function <b>np.mean(x)</b>. We can also extract the eigenvalues of the
|
|
covariance matrix through the <b>np.linalg.eig()</b> function.
|
|
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic"># Importing various packages</span>
|
|
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
|
|
n <span style="color: #666666">=</span> <span style="color: #666666">100</span>
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(size<span style="color: #666666">=</span>n)
|
|
<span style="color: #008000; font-weight: bold">print</span>(np<span style="color: #666666">.</span>mean(x))
|
|
y <span style="color: #666666">=</span> <span style="color: #666666">4+3*</span>x<span style="color: #666666">+</span>np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(size<span style="color: #666666">=</span>n)
|
|
<span style="color: #008000; font-weight: bold">print</span>(np<span style="color: #666666">.</span>mean(y))
|
|
z <span style="color: #666666">=</span> x<span style="color: #666666">**3+</span>np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(size<span style="color: #666666">=</span>n)
|
|
<span style="color: #008000; font-weight: bold">print</span>(np<span style="color: #666666">.</span>mean(z))
|
|
W <span style="color: #666666">=</span> np<span style="color: #666666">.</span>vstack((x, y, z))
|
|
Sigma <span style="color: #666666">=</span> np<span style="color: #666666">.</span>cov(W)
|
|
<span style="color: #008000; font-weight: bold">print</span>(Sigma)
|
|
Eigvals, Eigvecs <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linalg<span style="color: #666666">.</span>eig(Sigma)
|
|
<span style="color: #008000; font-weight: bold">print</span>(Eigvals)
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec9">Matrix Handling in C/C++, Static and Dynamical allocation </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Static.</b>
|
|
<p>
|
|
We have an \( N\times N \) matrix A with \( N=100 \)
|
|
In C/C++ this would be defined as
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #B00040">int</span> N <span style="color: #666666">=</span> <span style="color: #666666">100</span>;
|
|
<span style="color: #B00040">double</span> A[<span style="color: #666666">100</span>][<span style="color: #666666">100</span>];
|
|
<span style="color: #408080; font-style: italic">// initialize all elements to zero</span>
|
|
<span style="color: #008000; font-weight: bold">for</span>(i<span style="color: #666666">=0</span> ; i <span style="color: #666666"><</span> N ; i<span style="color: #666666">++</span>) {
|
|
<span style="color: #008000; font-weight: bold">for</span>(j<span style="color: #666666">=0</span> ; j <span style="color: #666666"><</span> N ; j<span style="color: #666666">++</span>) {
|
|
A[i][j] <span style="color: #666666">=</span> <span style="color: #666666">0.0</span>;
|
|
</pre></div>
|
|
<p>
|
|
Note the way the matrix is organized, row-major order.
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec10">Matrix Handling in C/C++ </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Row Major Order, Addition.</b>
|
|
<p>
|
|
We have \( N\times N \) matrices A, B and C and we wish to
|
|
evaluate \( A=B+C \).
|
|
|
|
$$
|
|
\mathbf{A}= \mathbf{B}\pm\mathbf{C} \Longrightarrow a_{ij} = b_{ij}\pm c_{ij},
|
|
$$
|
|
|
|
In C/C++ this would be coded like
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #008000; font-weight: bold">for</span>(i<span style="color: #666666">=0</span> ; i <span style="color: #666666"><</span> N ; i<span style="color: #666666">++</span>) {
|
|
<span style="color: #008000; font-weight: bold">for</span>(j<span style="color: #666666">=0</span> ; j <span style="color: #666666"><</span> N ; j<span style="color: #666666">++</span>) {
|
|
a[i][j] <span style="color: #666666">=</span> b[i][j]<span style="color: #666666">+</span>c[i][j]
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec11">Matrix Handling in C/C++ </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Row Major Order, Multiplication.</b>
|
|
<p>
|
|
We have \( N\times N \) matrices A, B and C and we wish to
|
|
evaluate \( A=BC \).
|
|
|
|
$$
|
|
\mathbf{A}=\mathbf{BC} \Longrightarrow a_{ij} = \sum_{k=1}^{n} b_{ik}c_{kj},
|
|
$$
|
|
|
|
In C/C++ this would be coded like
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #008000; font-weight: bold">for</span>(i<span style="color: #666666">=0</span> ; i <span style="color: #666666"><</span> N ; i<span style="color: #666666">++</span>) {
|
|
<span style="color: #008000; font-weight: bold">for</span>(j<span style="color: #666666">=0</span> ; j <span style="color: #666666"><</span> N ; j<span style="color: #666666">++</span>) {
|
|
<span style="color: #008000; font-weight: bold">for</span>(k<span style="color: #666666">=0</span> ; k <span style="color: #666666"><</span> N ; k<span style="color: #666666">++</span>) {
|
|
a[i][j]<span style="color: #666666">+=</span>b[i][k]<span style="color: #666666">*</span>c[k][j];
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec12">Dynamic memory allocation in C/C++ </h2>
|
|
|
|
<p>
|
|
At least three possibilities in this course
|
|
|
|
<ul>
|
|
<li> Do it yourself</li>
|
|
<li> Use the functions provided in the library package lib.cpp</li>
|
|
<li> Use Armadillo <a href="http://arma.sourceforgenet" target="_blank"><tt>http://arma.sourceforgenet</tt></a> (a C++ linear algebra library, discussion both here and at lab).</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec13">Matrix Handling in C/C++, Dynamic Allocation </h2>
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b>Do it yourself.</b>
|
|
<p>
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #B00040">int</span> N;
|
|
<span style="color: #B00040">double</span> <span style="color: #666666">**</span> A;
|
|
A <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> <span style="color: #B00040">double</span><span style="color: #666666">*</span>[N]
|
|
<span style="color: #008000; font-weight: bold">for</span> ( i <span style="color: #666666">=</span> <span style="color: #666666">0</span>; i <span style="color: #666666"><</span> N; i<span style="color: #666666">++</span>)
|
|
A[i] <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> <span style="color: #B00040">double</span>[N];
|
|
</pre></div>
|
|
<p>
|
|
Always free space when you don't need an array anymore.
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">for</span> ( i <span style="color: #666666">=</span> <span style="color: #666666">0</span>; i <span style="color: #666666"><</span> N; i<span style="color: #666666">++</span>)
|
|
<span style="color: #008000; font-weight: bold">delete</span>[] A[i];
|
|
<span style="color: #008000; font-weight: bold">delete</span>[] A;
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec14">Armadillo, recommended!! </h2>
|
|
|
|
<ul>
|
|
<li> Armadillo is a C++ linear algebra library (matrix maths) aiming towards a good balance between speed and ease of use. The syntax is deliberately similar to Matlab.</li>
|
|
<li> Integer, floating point and complex numbers are supported, as well as a subset of trigonometric and statistics functions. Various matrix decompositions are provided through optional integration with LAPACK, or one of its high performance drop-in replacements (such as the multi-threaded MKL or ACML libraries).</li>
|
|
<li> A delayed evaluation approach is employed (at compile-time) to combine several operations into one and reduce (or eliminate) the need for temporaries. This is accomplished through recursive templates and template meta-programming.</li>
|
|
<li> Useful for conversion of research code into production environments, or if C++ has been decided as the language of choice, due to speed and/or integration capabilities.</li>
|
|
<li> The library is open-source software, and is distributed under a license that is useful in both open-source and commercial/proprietary contexts.</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec15">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic"><iostream></span><span style="color: #BC7A00"></span>
|
|
<span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic"><armadillo></span><span style="color: #BC7A00"></span>
|
|
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> std;
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> arma;
|
|
|
|
<span style="color: #B00040">int</span> <span style="color: #0000FF">main</span>(<span style="color: #B00040">int</span> argc, <span style="color: #B00040">char</span><span style="color: #666666">**</span> argv)
|
|
{
|
|
mat A <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">5</span>,<span style="color: #666666">5</span>);
|
|
mat B <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">5</span>,<span style="color: #666666">5</span>);
|
|
|
|
cout <span style="color: #666666"><<</span> A<span style="color: #666666">*</span>B <span style="color: #666666"><<</span> endl;
|
|
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">0</span>;
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec16">Armadillo, how to compile and install </h2>
|
|
|
|
<p>
|
|
For people using Ubuntu, Debian, Linux Mint, simply go to the synaptic package manager and install
|
|
armadillo from there.
|
|
You may have to install Lapack as well.
|
|
For Mac and Windows users, follow the instructions from the webpage
|
|
<a href="http://arma.sourceforge.net" target="_blank"><tt>http://arma.sourceforge.net</tt></a>.
|
|
To compile, use for example (linux/ubuntu)
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>c<span style="color: #666666">++</span> <span style="color: #666666">-</span>O2 <span style="color: #666666">-</span>o program.x program.cpp <span style="color: #666666">-</span>larmadillo <span style="color: #666666">-</span>llapack <span style="color: #666666">-</span>lblas
|
|
</pre></div>
|
|
<p>
|
|
where the <code>-l</code> option indicates the library you wish to link to.
|
|
|
|
<p>
|
|
For OS X users you may have to declare the paths to the include files and the libraries as
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>c<span style="color: #666666">++</span> <span style="color: #666666">-</span>O2 <span style="color: #666666">-</span>o program.x program.cpp <span style="color: #666666">-</span>L<span style="color: #666666">/</span>usr<span style="color: #666666">/</span>local<span style="color: #666666">/</span>lib <span style="color: #666666">-</span>I<span style="color: #666666">/</span>usr<span style="color: #666666">/</span>local<span style="color: #666666">/</span>include <span style="color: #666666">-</span>larmadillo <span style="color: #666666">-</span>llapack <span style="color: #666666">-</span>lblas
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec17">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic"><iostream></span><span style="color: #BC7A00"></span>
|
|
<span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic">"armadillo"</span><span style="color: #BC7A00"></span>
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> arma;
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> std;
|
|
|
|
<span style="color: #B00040">int</span> <span style="color: #0000FF">main</span>(<span style="color: #B00040">int</span> argc, <span style="color: #B00040">char</span><span style="color: #666666">**</span> argv)
|
|
{
|
|
<span style="color: #408080; font-style: italic">// directly specify the matrix size (elements are uninitialised)</span>
|
|
mat A(<span style="color: #666666">2</span>,<span style="color: #666666">3</span>);
|
|
<span style="color: #408080; font-style: italic">// .n_rows = number of rows (read only)</span>
|
|
<span style="color: #408080; font-style: italic">// .n_cols = number of columns (read only)</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"A.n_rows = "</span> <span style="color: #666666"><<</span> A.n_rows <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"A.n_cols = "</span> <span style="color: #666666"><<</span> A.n_cols <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// directly access an element (indexing starts at 0)</span>
|
|
A(<span style="color: #666666">1</span>,<span style="color: #666666">2</span>) <span style="color: #666666">=</span> <span style="color: #666666">456.0</span>;
|
|
A.print(<span style="color: #BA2121">"A:"</span>);
|
|
<span style="color: #408080; font-style: italic">// scalars are treated as a 1x1 matrix,</span>
|
|
<span style="color: #408080; font-style: italic">// hence the code below will set A to have a size of 1x1</span>
|
|
A <span style="color: #666666">=</span> <span style="color: #666666">5.0</span>;
|
|
A.print(<span style="color: #BA2121">"A:"</span>);
|
|
<span style="color: #408080; font-style: italic">// if you want a matrix with all elements set to a particular value</span>
|
|
<span style="color: #408080; font-style: italic">// the .fill() member function can be used</span>
|
|
A.set_size(<span style="color: #666666">3</span>,<span style="color: #666666">3</span>);
|
|
A.fill(<span style="color: #666666">5.0</span>); A.print(<span style="color: #BA2121">"A:"</span>);
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec18">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> mat B;
|
|
|
|
<span style="color: #408080; font-style: italic">// endr indicates "end of row"</span>
|
|
B <span style="color: #666666"><<</span> <span style="color: #666666">0.555950</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.274690</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.540605</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.798938</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.108929</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.830123</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.891726</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.895283</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.948014</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.973234</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.216504</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.883152</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.023787</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.675382</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.231751</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.450332</span> <span style="color: #666666"><<</span> endr;
|
|
|
|
<span style="color: #408080; font-style: italic">// print to the cout stream</span>
|
|
<span style="color: #408080; font-style: italic">// with an optional string before the contents of the matrix</span>
|
|
B.print(<span style="color: #BA2121">"B:"</span>);
|
|
|
|
<span style="color: #408080; font-style: italic">// the << operator can also be used to print the matrix</span>
|
|
<span style="color: #408080; font-style: italic">// to an arbitrary stream (cout in this case)</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"B:"</span> <span style="color: #666666"><<</span> endl <span style="color: #666666"><<</span> B <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// save to disk</span>
|
|
B.save(<span style="color: #BA2121">"B.txt"</span>, raw_ascii);
|
|
<span style="color: #408080; font-style: italic">// load from disk</span>
|
|
mat C;
|
|
C.load(<span style="color: #BA2121">"B.txt"</span>);
|
|
C <span style="color: #666666">+=</span> <span style="color: #666666">2.0</span> <span style="color: #666666">*</span> B;
|
|
C.print(<span style="color: #BA2121">"C:"</span>);
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec19">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #408080; font-style: italic">// submatrix types:</span>
|
|
<span style="color: #408080; font-style: italic">//</span>
|
|
<span style="color: #408080; font-style: italic">// .submat(first_row, first_column, last_row, last_column)</span>
|
|
<span style="color: #408080; font-style: italic">// .row(row_number)</span>
|
|
<span style="color: #408080; font-style: italic">// .col(column_number)</span>
|
|
<span style="color: #408080; font-style: italic">// .cols(first_column, last_column)</span>
|
|
<span style="color: #408080; font-style: italic">// .rows(first_row, last_row)</span>
|
|
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"C.submat(0,0,3,1) ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> C.submat(<span style="color: #666666">0</span>,<span style="color: #666666">0</span>,<span style="color: #666666">3</span>,<span style="color: #666666">1</span>) <span style="color: #666666"><<</span> endl;
|
|
|
|
<span style="color: #408080; font-style: italic">// generate the identity matrix</span>
|
|
mat D <span style="color: #666666">=</span> eye<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">4</span>,<span style="color: #666666">4</span>);
|
|
|
|
D.submat(<span style="color: #666666">0</span>,<span style="color: #666666">0</span>,<span style="color: #666666">3</span>,<span style="color: #666666">1</span>) <span style="color: #666666">=</span> C.cols(<span style="color: #666666">1</span>,<span style="color: #666666">2</span>);
|
|
D.print(<span style="color: #BA2121">"D:"</span>);
|
|
|
|
<span style="color: #408080; font-style: italic">// transpose</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"trans(B) ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> trans(B) <span style="color: #666666"><<</span> endl;
|
|
|
|
<span style="color: #408080; font-style: italic">// maximum from each column (traverse along rows)</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"max(B) ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> max(B) <span style="color: #666666"><<</span> endl;
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec20">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #408080; font-style: italic">// maximum from each row (traverse along columns)</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"max(B,1) ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> max(B,<span style="color: #666666">1</span>) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// maximum value in B</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"max(max(B)) = "</span> <span style="color: #666666"><<</span> max(max(B)) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// sum of each column (traverse along rows)</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"sum(B) ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> sum(B) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// sum of each row (traverse along columns)</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"sum(B,1) ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> sum(B,<span style="color: #666666">1</span>) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// sum of all elements</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"sum(sum(B)) = "</span> <span style="color: #666666"><<</span> sum(sum(B)) <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"accu(B) = "</span> <span style="color: #666666"><<</span> accu(B) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// trace = sum along diagonal</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"trace(B) = "</span> <span style="color: #666666"><<</span> trace(B) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #408080; font-style: italic">// random matrix -- values are uniformly distributed in the [0,1] interval</span>
|
|
mat E <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">4</span>,<span style="color: #666666">4</span>);
|
|
E.print(<span style="color: #BA2121">"E:"</span>);
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec21">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #408080; font-style: italic">// row vectors are treated like a matrix with one row</span>
|
|
rowvec r;
|
|
r <span style="color: #666666"><<</span> <span style="color: #666666">0.59499</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.88807</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.88532</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.19968</span>;
|
|
r.print(<span style="color: #BA2121">"r:"</span>);
|
|
|
|
<span style="color: #408080; font-style: italic">// column vectors are treated like a matrix with one column</span>
|
|
colvec q;
|
|
q <span style="color: #666666"><<</span> <span style="color: #666666">0.81114</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.06256</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.95989</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.73628</span>;
|
|
q.print(<span style="color: #BA2121">"q:"</span>);
|
|
|
|
<span style="color: #408080; font-style: italic">// dot or inner product</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"as_scalar(r*q) = "</span> <span style="color: #666666"><<</span> as_scalar(r<span style="color: #666666">*</span>q) <span style="color: #666666"><<</span> endl;
|
|
|
|
<span style="color: #408080; font-style: italic">// outer product</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"q*r ="</span> <span style="color: #666666"><<</span> endl;
|
|
cout <span style="color: #666666"><<</span> q<span style="color: #666666">*</span>r <span style="color: #666666"><<</span> endl;
|
|
|
|
|
|
<span style="color: #408080; font-style: italic">// sum of three matrices (no temporary matrices are created)</span>
|
|
mat F <span style="color: #666666">=</span> B <span style="color: #666666">+</span> C <span style="color: #666666">+</span> D;
|
|
F.print(<span style="color: #BA2121">"F:"</span>);
|
|
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">0</span>;
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec22">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic"><iostream></span><span style="color: #BC7A00"></span>
|
|
<span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic">"armadillo"</span><span style="color: #BC7A00"></span>
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> arma;
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> std;
|
|
|
|
<span style="color: #B00040">int</span> <span style="color: #0000FF">main</span>(<span style="color: #B00040">int</span> argc, <span style="color: #B00040">char</span><span style="color: #666666">**</span> argv)
|
|
{
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"Armadillo version: "</span> <span style="color: #666666"><<</span> arma_version<span style="color: #666666">::</span>as_string() <span style="color: #666666"><<</span> endl;
|
|
|
|
mat A;
|
|
|
|
A <span style="color: #666666"><<</span> <span style="color: #666666">0.165300</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.454037</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.995795</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.124098</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.047084</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.688782</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.036549</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.552848</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.937664</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.866401</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.348740</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.479388</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.506228</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.145673</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.491547</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.148678</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.682258</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.571154</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.874724</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.444632</span> <span style="color: #666666"><<</span> endr
|
|
<span style="color: #666666"><<</span> <span style="color: #666666">0.245726</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.595218</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.409327</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.367827</span> <span style="color: #666666"><<</span> <span style="color: #666666">0.385736</span> <span style="color: #666666"><<</span> endr;
|
|
|
|
A.print(<span style="color: #BA2121">"A ="</span>);
|
|
|
|
<span style="color: #408080; font-style: italic">// determinant</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"det(A) = "</span> <span style="color: #666666"><<</span> det(A) <span style="color: #666666"><<</span> endl;
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec23">Armadillo, simple examples </h2>
|
|
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span> <span style="color: #408080; font-style: italic">// inverse</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"inv(A) = "</span> <span style="color: #666666"><<</span> endl <span style="color: #666666"><<</span> inv(A) <span style="color: #666666"><<</span> endl;
|
|
<span style="color: #B00040">double</span> k <span style="color: #666666">=</span> <span style="color: #666666">1.23</span>;
|
|
|
|
mat B <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">5</span>,<span style="color: #666666">5</span>);
|
|
mat C <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">5</span>,<span style="color: #666666">5</span>);
|
|
|
|
rowvec r <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>rowvec<span style="color: #666666">></span>(<span style="color: #666666">5</span>);
|
|
colvec q <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>colvec<span style="color: #666666">></span>(<span style="color: #666666">5</span>);
|
|
|
|
|
|
<span style="color: #408080; font-style: italic">// examples of some expressions</span>
|
|
<span style="color: #408080; font-style: italic">// for which optimised implementations exist</span>
|
|
<span style="color: #408080; font-style: italic">// optimised implementation of a trinary expression</span>
|
|
<span style="color: #408080; font-style: italic">// that results in a scalar</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"as_scalar( r*inv(diagmat(B))*q ) = "</span>;
|
|
cout <span style="color: #666666"><<</span> as_scalar( r<span style="color: #666666">*</span>inv(diagmat(B))<span style="color: #666666">*</span>q ) <span style="color: #666666"><<</span> endl;
|
|
|
|
<span style="color: #408080; font-style: italic">// example of an expression which is optimised</span>
|
|
<span style="color: #408080; font-style: italic">// as a call to the dgemm() function in BLAS:</span>
|
|
cout <span style="color: #666666"><<</span> <span style="color: #BA2121">"k*trans(B)*C = "</span> <span style="color: #666666"><<</span> endl <span style="color: #666666"><<</span> k<span style="color: #666666">*</span>trans(B)<span style="color: #666666">*</span>C;
|
|
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">0</span>;
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec24">Gaussian Elimination </h2>
|
|
|
|
<p>
|
|
We start with the linear set of equations
|
|
|
|
$$
|
|
\mathbf{A}\mathbf{x} = \mathbf{w}.
|
|
$$
|
|
|
|
We assume also that the matrix \( \mathbf{A} \) is non-singular and that the
|
|
matrix elements along the diagonal satisfy \( a_{ii} \ne 0 \). Simple \( 4\times 4 \) example
|
|
|
|
$$
|
|
\begin{bmatrix}
|
|
a_{11}& a_{12} &a_{13}& a_{14}\\
|
|
a_{21}& a_{22} &a_{23}& a_{24}\\
|
|
a_{31}& a_{32} &a_{33}& a_{34}\\
|
|
a_{41}& a_{42} &a_{43}& a_{44}\\
|
|
\end{bmatrix} \begin{bmatrix}
|
|
x_1\\
|
|
x_2\\
|
|
x_3 \\
|
|
x_4 \\
|
|
\end{bmatrix}
|
|
=\begin{bmatrix}
|
|
w_1\\
|
|
w_2\\
|
|
w_3 \\
|
|
w_4\\
|
|
\end{bmatrix}.
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec25">Gaussian Elimination </h2>
|
|
or
|
|
|
|
$$
|
|
\begin{align}
|
|
a_{11}x_1 +a_{12}x_2 +a_{13}x_3 + a_{14}x_4=&w_1 \nonumber \\
|
|
a_{21}x_1 + a_{22}x_2 + a_{23}x_3 + a_{24}x_4=&w_2 \nonumber \\
|
|
a_{31}x_1 + a_{32}x_2 + a_{33}x_3 + a_{34}x_4=&w_3 \nonumber \\
|
|
a_{41}x_1 + a_{42}x_2 + a_{43}x_3 + a_{44}x_4=&w_4. \nonumber
|
|
\end{align}
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec26">Gaussian Elimination </h2>
|
|
|
|
<p>
|
|
The basic idea of Gaussian elimination is to use the first equation to eliminate the first unknown \( x_1 \)
|
|
from the remaining \( n-1 \) equations. Then we use the new second equation to eliminate the second unknown
|
|
\( x_2 \) from the remaining \( n-2 \) equations. With \( n-1 \) such eliminations
|
|
we obtain a so-called upper triangular set of equations of the form
|
|
|
|
$$
|
|
\begin{align}
|
|
b_{11}x_1 +b_{12}x_2 +b_{13}x_3 + b_{14}x_4=&y_1 \nonumber \\
|
|
b_{22}x_2 + b_{23}x_3 + b_{24}x_4=&y_2 \nonumber \\
|
|
b_{33}x_3 + b_{34}x_4=&y_3 \nonumber \\
|
|
b_{44}x_4=&y_4. \nonumber
|
|
\label{eq:gaussbacksub}
|
|
\end{align}
|
|
$$
|
|
|
|
We can solve this system of equations recursively starting from \( x_n \) (in our case \( x_4 \)) and proceed with
|
|
what is called a backward substitution.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec27">Gaussian Elimination </h2>
|
|
This process can be expressed mathematically as
|
|
|
|
$$
|
|
\begin{equation}
|
|
x_m = \frac{1}{b_{mm}}\left(y_m-\sum_{k=m+1}^nb_{mk}x_k\right)\quad m=n-1,n-2,\dots,1.
|
|
\label{_auto1}
|
|
\end{equation}
|
|
$$
|
|
|
|
To arrive at such an upper triangular system of equations, we start by eliminating
|
|
the unknown \( x_1 \) for \( j=2,n \). We achieve this by multiplying the first equation by \( a_{j1}/a_{11} \) and then subtract
|
|
the result from the $j$th equation. We assume obviously that \( a_{11}\ne 0 \) and that
|
|
\( \mathbf{A} \) is not singular.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec28">Gaussian Elimination </h2>
|
|
|
|
<p>
|
|
Our actual \( 4\times 4 \) example reads after the first operation
|
|
|
|
$$
|
|
\begin{bmatrix}
|
|
a_{11}& a_{12} &a_{13}& a_{14}\\
|
|
0& (a_{22}-\frac{a_{21}a_{12}}{a_{11}}) &(a_{23}-\frac{a_{21}a_{13}}{a_{11}}) & (a_{24}-\frac{a_{21}a_{14}}{a_{11}})\\
|
|
0& (a_{32}-\frac{a_{31}a_{12}}{a_{11}})& (a_{33}-\frac{a_{31}a_{13}}{a_{11}})& (a_{34}-\frac{a_{31}a_{14}}{a_{11}})\\
|
|
0&(a_{42}-\frac{a_{41}a_{12}}{a_{11}}) &(a_{43}-\frac{a_{41}a_{13}}{a_{11}}) & (a_{44}-\frac{a_{41}a_{14}}{a_{11}}) \\
|
|
\end{bmatrix} \begin{bmatrix}
|
|
x_1\\
|
|
x_2\\
|
|
x_3 \\
|
|
x_4 \\
|
|
\end{bmatrix}
|
|
=\begin{bmatrix}
|
|
y_1\\
|
|
w_2^{(2)}\\
|
|
w_3^{(2)} \\
|
|
w_4^{(2)}\\
|
|
\end{bmatrix},
|
|
$$
|
|
|
|
or
|
|
|
|
$$
|
|
\begin{align}
|
|
b_{11}x_1 +b_{12}x_2 +b_{13}x_3 + b_{14}x_4=&y_1 \nonumber \\
|
|
a^{(2)}_{22}x_2 + a^{(2)}_{23}x_3 + a^{(2)}_{24}x_4=&w^{(2)}_2 \nonumber \\
|
|
a^{(2)}_{32}x_2 + a^{(2)}_{33}x_3 + a^{(2)}_{34}x_4=&w^{(2)}_3 \nonumber \\
|
|
a^{(2)}_{42}x_2 + a^{(2)}_{43}x_3 + a^{(2)}_{44}x_4=&w^{(2)}_4, \nonumber \\
|
|
\label{_auto2}
|
|
\end{align}
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec29">Gaussian Elimination </h2>
|
|
|
|
<p>
|
|
The new coefficients are
|
|
|
|
$$
|
|
\begin{equation}
|
|
b_{1k} = a_{1k}^{(1)} \quad k=1,\dots,n,
|
|
\label{_auto3}
|
|
\end{equation}
|
|
$$
|
|
|
|
where each \( a_{1k}^{(1)} \) is equal to the original \( a_{1k} \) element. The other coefficients are
|
|
|
|
$$
|
|
\begin{equation}
|
|
a_{jk}^{(2)} = a_{jk}^{(1)}-\frac{a_{j1}^{(1)}a_{1k}^{(1)}}{a_{11}^{(1)}} \quad j,k=2,\dots,n,
|
|
\label{_auto4}
|
|
\end{equation}
|
|
$$
|
|
|
|
with a new right-hand side given by
|
|
|
|
$$
|
|
\begin{equation}
|
|
y_{1}=w_1^{(1)}, \quad w_j^{(2)} =w_j^{(1)}-\frac{a_{j1}^{(1)}w_1^{(1)}}{a_{11}^{(1)}} \quad j=2,\dots,n.
|
|
\label{_auto5}
|
|
\end{equation}
|
|
$$
|
|
|
|
We have also set \( w_1^{(1)}=w_1 \), the original vector element.
|
|
We see that the system of unknowns \( x_1,\dots,x_n \) is transformed into an \( (n-1)\times (n-1) \) problem.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec30">Gaussian Elimination </h2>
|
|
|
|
<p>
|
|
This step is called forward substitution.
|
|
Proceeding with these substitutions, we obtain the
|
|
general expressions for the new coefficients
|
|
|
|
$$
|
|
\begin{equation}
|
|
a_{jk}^{(m+1)} = a_{jk}^{(m)}-\frac{a_{jm}^{(m)}a_{mk}^{(m)}}{a_{mm}^{(m)}} \quad j,k=m+1,\dots,n,
|
|
\label{_auto6}
|
|
\end{equation}
|
|
$$
|
|
|
|
with \( m=1,\dots,n-1 \) and a
|
|
right-hand side given by
|
|
|
|
$$
|
|
\begin{equation}
|
|
w_j^{(m+1)} =w_j^{(m)}-\frac{a_{jm}^{(m)}w_m^{(m)}}{a_{mm}^{(m)}}\quad j=m+1,\dots,n.
|
|
\label{_auto7}
|
|
\end{equation}
|
|
$$
|
|
|
|
This set of \( n-1 \) elimations leads us to an equations which is solved by back substitution.
|
|
If the arithmetics is exact and the matrix \( \mathbf{A} \) is not singular, then the computed answer will be exact.
|
|
|
|
<p>
|
|
Even though the matrix elements along the diagonal are not zero,
|
|
numerically small numbers may appear and subsequent divisions may lead to large numbers, which, if added
|
|
to a small number may yield losses of precision. Suppose for example that our first division in \( (a_{22}-a_{21}a_{12}/a_{11}) \)
|
|
results in \( -10^{-7} \) and that \( a_{22} \) is one.
|
|
one. We are then
|
|
adding \( 10^7+1 \). With single precision this results in \( 10^7 \).
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec31">Linear Algebra Methods </h2>
|
|
|
|
<ul>
|
|
<li> Gaussian elimination, \( O(2/3n^3) \) flops, general matrix</li>
|
|
<li> LU decomposition, upper triangular and lower tridiagonal matrices, \( O(2/3n^3) \) flops, general matrix. Get easily the inverse, determinant and can solve linear equations with back-substitution only, \( O(n^2) \) flops</li>
|
|
<li> Cholesky decomposition. Real symmetric or hermitian positive definite matrix, \( O(1/3n^3) \) flops.</li>
|
|
<li> Tridiagonal linear systems, important for differential equations. Normally positive definite and non-singular. \( O(8n) \) flops for symmetric. Special case of banded matrices.</li>
|
|
<li> Singular value decomposition</li>
|
|
<li> the QR method will be discussed in chapter 7 in connection with eigenvalue systems. \( O(4/3n^3) \) flops.</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec32">LU Decomposition </h2>
|
|
|
|
<p>
|
|
The LU decomposition method means that we can rewrite
|
|
this matrix as the product of two matrices \( \mathbf{L} \) and \( \mathbf{U} \)
|
|
where
|
|
|
|
$$
|
|
\begin{bmatrix}
|
|
a_{11} & a_{12} & a_{13} & a_{14} \\
|
|
a_{21} & a_{22} & a_{23} & a_{24} \\
|
|
a_{31} & a_{32} & a_{33} & a_{34} \\
|
|
a_{41} & a_{42} & a_{43} & a_{44}
|
|
\end{bmatrix}
|
|
= \begin{bmatrix}
|
|
1 & 0 & 0 & 0 \\
|
|
l_{21} & 1 & 0 & 0 \\
|
|
l_{31} & l_{32} & 1 & 0 \\
|
|
l_{41} & l_{42} & l_{43} & 1
|
|
\end{bmatrix}
|
|
\begin{bmatrix}
|
|
u_{11} & u_{12} & u_{13} & u_{14} \\
|
|
0 & u_{22} & u_{23} & u_{24} \\
|
|
0 & 0 & u_{33} & u_{34} \\
|
|
0 & 0 & 0 & u_{44}
|
|
\end{bmatrix}.
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec33">LU Decomposition </h2>
|
|
|
|
<p>
|
|
LU decomposition forms the backbone of other algorithms in linear algebra, such as the
|
|
solution of linear equations given by
|
|
|
|
$$
|
|
\begin{align}
|
|
a_{11}x_1 +a_{12}x_2 +a_{13}x_3 + a_{14}x_4=&w_1 \nonumber \\
|
|
a_{21}x_1 + a_{22}x_2 + a_{23}x_3 + a_{24}x_4=&w_2 \nonumber \\
|
|
a_{31}x_1 + a_{32}x_2 + a_{33}x_3 + a_{34}x_4=&w_3 \nonumber \\
|
|
a_{41}x_1 + a_{42}x_2 + a_{43}x_3 + a_{44}x_4=&w_4. \nonumber
|
|
\end{align}
|
|
$$
|
|
|
|
The above set of equations is conveniently solved by using LU decomposition as an intermediate step.
|
|
|
|
<p>
|
|
The matrix \( \mathbf{A}\in \mathbb{R}^{n\times n} \) has an LU factorization if the determinant
|
|
is different from zero. If the LU factorization exists and \( \mathbf{A} \) is non-singular, then the LU factorization
|
|
is unique and the determinant is given by
|
|
|
|
$$
|
|
det\{\mathbf{A}\}=det\{\mathbf{LU}\}= det\{\mathbf{L}\}det\{\mathbf{U}\}=u_{11}u_{22}\dots u_{nn}.
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec34">LU Decomposition, why? </h2>
|
|
|
|
<p>
|
|
There are at least three main advantages with LU decomposition compared with standard Gaussian elimination:
|
|
|
|
<ul>
|
|
<li> It is straightforward to compute the determinant of a matrix</li>
|
|
<li> If we have to solve sets of linear equations with the same matrix but with different vectors \( \mathbf{y} \), the number of FLOPS is of the order \( n^3 \).</li>
|
|
<li> The inverse is such an operation</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec35">LU Decomposition, linear equations </h2>
|
|
|
|
<p>
|
|
With the LU decomposition it is rather
|
|
simple to solve a system of linear equations
|
|
|
|
$$
|
|
\begin{align}
|
|
a_{11}x_1 +a_{12}x_2 +a_{13}x_3 + a_{14}x_4=&w_1 \nonumber \\
|
|
a_{21}x_1 + a_{22}x_2 + a_{23}x_3 + a_{24}x_4=&w_2 \nonumber \\
|
|
a_{31}x_1 + a_{32}x_2 + a_{33}x_3 + a_{34}x_4=&w_3 \nonumber \\
|
|
a_{41}x_1 + a_{42}x_2 + a_{43}x_3 + a_{44}x_4=&w_4. \nonumber
|
|
\end{align}
|
|
$$
|
|
|
|
<p>
|
|
This can be written in matrix form as
|
|
|
|
$$ \mathbf{Ax}=\mathbf{w}. $$
|
|
|
|
<p>
|
|
where \( \mathbf{A} \) and \( \mathbf{w} \) are known and we have to solve for
|
|
\( \mathbf{x} \). Using the LU dcomposition we write
|
|
|
|
$$ \mathbf{A} \mathbf{x} \equiv \mathbf{L} \mathbf{U} \mathbf{x} =\mathbf{w}. $$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec36">LU Decomposition, linear equations </h2>
|
|
|
|
<p>
|
|
The previous equation can be calculated in two steps
|
|
|
|
$$ \mathbf{L} \mathbf{y} = \mathbf{w};\qquad \mathbf{Ux}=\mathbf{y}. $$
|
|
|
|
<p>
|
|
To show that this is correct we use to the LU decomposition
|
|
to rewrite our system of linear equations as
|
|
|
|
$$ \mathbf{LUx}=\mathbf{w}, $$
|
|
|
|
and since the determinant of \( \mathbf{L} \) is equal to 1 (by construction
|
|
since the diagonals of \( \mathbf{L} \) equal 1) we can use the inverse of
|
|
\( \mathbf{L} \) to obtain
|
|
|
|
$$
|
|
\mathbf{Ux}=\mathbf{L^{-1}w}=\mathbf{y},
|
|
$$
|
|
|
|
which yields the intermediate step
|
|
|
|
$$
|
|
\mathbf{L^{-1}w}=\mathbf{y}
|
|
$$
|
|
|
|
and as soon as we have \( \mathbf{y} \) we can obtain \( \mathbf{x} \)
|
|
through \( \mathbf{Ux}=\mathbf{y} \).
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec37">LU Decomposition, why? </h2>
|
|
|
|
<p>
|
|
For our four-dimentional example this takes the form
|
|
|
|
$$
|
|
\begin{align}
|
|
y_1=&w_1 \nonumber\\
|
|
l_{21}y_1 + y_2=&w_2\nonumber \\
|
|
l_{31}y_1 + l_{32}y_2 + y_3 =&w_3\nonumber \\
|
|
l_{41}y_1 + l_{42}y_2 + l_{43}y_3 + y_4=&w_4. \nonumber
|
|
\end{align}
|
|
$$
|
|
|
|
<p>
|
|
and
|
|
|
|
$$
|
|
\begin{align}
|
|
u_{11}x_1 +u_{12}x_2 +u_{13}x_3 + u_{14}x_4=&y_1 \nonumber\\
|
|
u_{22}x_2 + u_{23}x_3 + u_{24}x_4=&y_2\nonumber \\
|
|
u_{33}x_3 + u_{34}x_4=&y_3\nonumber \\
|
|
u_{44}x_4=&y_4 \nonumber
|
|
\end{align}
|
|
$$
|
|
|
|
<p>
|
|
This example shows the basis for the algorithm
|
|
needed to solve the set of \( n \) linear equations.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec38">LU Decomposition, linear equations </h2>
|
|
|
|
<p>
|
|
The algorithm goes as follows
|
|
|
|
<ul>
|
|
<li> Set up the matrix \( \bf A \) and the vector \( \bf w \) with their correct dimensions. This determines the dimensionality of the unknown vector \( \bf x \).</li>
|
|
<li> Then LU decompose the matrix \( \bf A \) through a call to the function <code>ludcmp(double a, int n, int indx, double &d)</code>. This functions returns the LU decomposed matrix \( \bf A \), its determinant and the vector indx which keeps track of the number of interchanges of rows. If the determinant is zero, the solution is malconditioned.</li>
|
|
<li> Thereafter you call the function <code>lubksb(double a, int n, int indx, double w)</code> which uses the LU decomposed matrix \( \bf A \) and the vector \( \bf w \) and returns \( \bf x \) in the same place as \( \bf w \). Upon exit the original content in \( \bf w \) is destroyed. If you wish to keep this information, you should make a backup of it in your calling function.</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec39">LU Decomposition, the inverse of a matrix </h2>
|
|
|
|
<p>
|
|
If the inverse exists then
|
|
|
|
$$
|
|
\mathbf{A}^{-1}\mathbf{A}=\mathbf{I},
|
|
$$
|
|
|
|
the identity matrix. With an LU decomposed matrix we can rewrite the last equation as
|
|
|
|
$$
|
|
\mathbf{LU}\mathbf{A}^{-1}=\mathbf{I}.
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec40">LU Decomposition, the inverse of a matrix </h2>
|
|
|
|
<p>
|
|
If we assume that the first column (that is column 1) of the inverse matrix
|
|
can be written as a vector with unknown entries
|
|
|
|
$$
|
|
\mathbf{A}_1^{-1}= \begin{bmatrix}
|
|
a_{11}^{-1} \\
|
|
a_{21}^{-1} \\
|
|
\dots \\
|
|
a_{n1}^{-1} \\
|
|
\end{bmatrix},
|
|
$$
|
|
|
|
then we have a linear set of equations
|
|
|
|
$$
|
|
\mathbf{LU}\begin{bmatrix}
|
|
a_{11}^{-1} \\
|
|
a_{21}^{-1} \\
|
|
\dots \\
|
|
a_{n1}^{-1} \\
|
|
\end{bmatrix} =\begin{bmatrix}
|
|
1 \\
|
|
0 \\
|
|
\dots \\
|
|
0 \\
|
|
\end{bmatrix}.
|
|
$$
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec41">LU Decomposition, the inverse </h2>
|
|
|
|
<p>
|
|
In a similar way we can compute the unknow entries of the second column,
|
|
|
|
$$
|
|
\mathbf{LU}\begin{bmatrix}
|
|
a_{12}^{-1} \\
|
|
a_{22}^{-1} \\
|
|
\dots \\
|
|
a_{n2}^{-1} \\
|
|
\end{bmatrix}=\begin{bmatrix}
|
|
0 \\
|
|
1 \\
|
|
\dots \\
|
|
0 \\
|
|
\end{bmatrix},
|
|
$$
|
|
|
|
and continue till we have solved all \( n \) sets of linear equations.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec42"><a href="https://github.com/CompPhysics/ComputationalPhysicsMSU/blob/master/doc/Programs/CppQtCodesLectures/MatrixTest/main.cpp" target="_blank">Using Armadillo to perform an LU decomposition</a> </h2>
|
|
<p>
|
|
|
|
<!-- code=c++ (!bc cppcod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic"><iostream></span><span style="color: #BC7A00"></span>
|
|
<span style="color: #BC7A00">#include</span> <span style="color: #408080; font-style: italic">"armadillo"</span><span style="color: #BC7A00"></span>
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> arma;
|
|
<span style="color: #008000; font-weight: bold">using</span> <span style="color: #008000; font-weight: bold">namespace</span> std;
|
|
|
|
<span style="color: #B00040">int</span> <span style="color: #0000FF">main</span>()
|
|
{
|
|
mat A <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>mat<span style="color: #666666">></span>(<span style="color: #666666">5</span>,<span style="color: #666666">5</span>);
|
|
vec b <span style="color: #666666">=</span> randu<span style="color: #666666"><</span>vec<span style="color: #666666">></span>(<span style="color: #666666">5</span>);
|
|
|
|
A.print(<span style="color: #BA2121">"A ="</span>);
|
|
b.print(<span style="color: #BA2121">"b="</span>);
|
|
<span style="color: #408080; font-style: italic">// solve Ax = b</span>
|
|
vec x <span style="color: #666666">=</span> solve(A,b);
|
|
<span style="color: #408080; font-style: italic">// print x</span>
|
|
x.print(<span style="color: #BA2121">"x="</span>);
|
|
<span style="color: #408080; font-style: italic">// find LU decomp of A, if needed, P is the permutation matrix</span>
|
|
mat L, U;
|
|
lu(L,U,A);
|
|
<span style="color: #408080; font-style: italic">// print l</span>
|
|
L.print(<span style="color: #BA2121">" L= "</span>);
|
|
<span style="color: #408080; font-style: italic">// print U</span>
|
|
U.print(<span style="color: #BA2121">" U= "</span>);
|
|
<span style="color: #408080; font-style: italic">//Check that A = LU</span>
|
|
(A<span style="color: #666666">-</span>L<span style="color: #666666">*</span>U).print(<span style="color: #BA2121">"Test of LU decomposition"</span>);
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">0</span>;
|
|
}
|
|
</pre></div>
|
|
<p>
|
|
|
|
<!-- ------------------- end of main content --------------- -->
|
|
|
|
|
|
<center style="font-size:80%">
|
|
<!-- copyright --> © 1999-2018, Morten Hjorth-Jensen. Released under CC Attribution-NonCommercial 4.0 license
|
|
</center>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|
|
|