aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc/C07_TutorialReductionsVisitorsBroadcasting.dox
blob: 1930d7a942e1a5bdd4f93e03487e32c31af64305 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
namespace Eigen {

/** \page TutorialReductionsVisitorsBroadcasting Tutorial page 7 - Reductions, visitors and broadcasting
    \ingroup Tutorial

\li \b Previous: \ref TutorialLinearAlgebra
\li \b Next: \ref TutorialGeometry

This tutorial explains Eigen's reductions, visitors and broadcasting and how they are used with
\link MatrixBase matrices \endlink and \link ArrayBase arrays \endlink.

\b Table \b of \b contents
  - \ref TutorialReductionsVisitorsBroadcastingReductions
    - \ref TutorialReductionsVisitorsBroadcastingReductionsNorm
    - \ref TutorialReductionsVisitorsBroadcastingReductionsBool
    - FIXME: .redux()
  - \ref TutorialReductionsVisitorsBroadcastingVisitors
  - \ref TutorialReductionsVisitorsBroadcastingPartialReductions
    - \ref TutorialReductionsVisitorsBroadcastingPartialReductionsCombined
  - \ref TutorialReductionsVisitorsBroadcastingBroadcasting
    - \ref TutorialReductionsVisitorsBroadcastingBroadcastingCombined


\section TutorialReductionsVisitorsBroadcastingReductions Reductions
In Eigen, a reduction is a function that is applied to a certain matrix or array, returning a single 
value of type scalar. One of the most used reductions is \link DenseBase::sum() .sum() \endlink,
which returns the addition of all the coefficients inside a given matrix or array.

<table class="tutorial_code"><tr><td>
Example: \include tut_arithmetic_redux_basic.cpp
</td>
<td>
Output: \include tut_arithmetic_redux_basic.out
</td></tr></table>

The \em trace of a matrix, as returned by the function \c trace(), is the sum of the diagonal coefficients and can also be computed as efficiently using <tt>a.diagonal().sum()</tt>, as we will see later on.


\subsection TutorialReductionsVisitorsBroadcastingReductionsNorm Norm reductions
Eigen also provides reductions to obtain the norm or squared norm of a vector with \link DenseBase::norm() norm() \endlink and \link DenseBase::squaredNorm() squaredNorm() \endlink respectively.
These operations can also operate on objects such as Matrices or Arrays, as shown in the following example:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_reductions_norm.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_reductions_norm.out
</td></tr></table>

\subsection TutorialReductionsVisitorsBroadcastingReductionsBool Boolean-like reductions

Another interesting type of reductions are the ones that deal with \b true and \b false values:
  - \link DenseBase::all() all() \endlink returns \b true if all of the coefficients in a given Matrix or \link ArrayBase Array \endlink are \b true .
  - \link DenseBase::any() any() \endlink returns \b true if at least one of the coefficients in a given Matrix or \link ArrayBase Array \endlink are \b true .
  - \link DenseBase::count() count() \endlink returns the number of \b true coefficients in a given Matrix or \link ArrayBase Array \endlink.

Their behaviour can be seen in the following example:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_reductions_bool.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_reductions_bool.out
</td></tr></table>


\section TutorialReductionsVisitorsBroadcastingVisitors Visitors
Visitors are useful when the location of a coefficient inside a Matrix or 
\link ArrayBase Array \endlink wants to be obtained. The simplest example are the
\link MatrixBase::maxCoeff() maxCoeff(&x,&y) \endlink and 
\link MatrixBase::minCoeff() minCoeff(&x,&y) \endlink, that can be used to find
the location of the greatest or smallest coefficient in a Matrix or 
\link ArrayBase Array \endlink:

The arguments passed to a visitor are pointers to the variables where the
row and column position are to be stored. These variables are of type 
\link DenseBase::Index Index \endlink (FIXME: link ok?), as shown below:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_visitors.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_visitors.out
</td></tr></table>

Note that both functions also return the value of the minimum or maximum coefficient if needed,
as if it was a typical reduction operation.

\section TutorialReductionsVisitorsBroadcastingPartialReductions Partial reductions
Partial reductions are reductions that can operate column- or row-wise on a Matrix or 
\link ArrayBase Array \endlink, applying the reduction operation on each column or row and 
returning a column or row-vector with the corresponding values. Partial reductions are applied 
with \link DenseBase::colwise() colwise() \endlink or \link DenseBase::rowwise() rowwise() \endlink.

A simple example is obtaining the sum of the elements 
in each column in a given matrix, storing the result in a row-vector:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_colwise.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_colwise.out
</td></tr></table>

The same operation can be performed row-wise:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_rowwise.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_rowwise.out
</td></tr></table>

<b>Note that column-wise operations return a 'row-vector' while row-wise operations
return a 'column-vector'</b>

\subsection TutorialReductionsVisitorsBroadcastingPartialReductionsCombined Combining partial reductions with other operations
It is also possible to use the result of a partial reduction to do further processing.
Here there is another example that aims to find the the column whose sum of elements is the maximum
 within a matrix. With column-wise partial reductions this can be coded as:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_maxnorm.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_maxnorm.out
</td></tr></table>

The previous example applies the \link DenseBase::sum() sum() \endlink reduction on each column
though the \link DenseBase::colwise() colwise() \endlink visitor, obtaining a new matrix whose
size is 1x4.

Therefore, if
\f[
\mbox{m} = \begin{bmatrix} 1 & 2 & 6 & 9 \\
                    3 & 1 & 7 & 2 \end{bmatrix}
\f]

then

\f[
\mbox{m.colwise().sum()} = \begin{bmatrix} 4 & 3 & 13 & 11 \end{bmatrix}
\f]

The \link DenseBase::maxCoeff() maxCoeff() \endlink reduction is finally applied 
to obtain the column index where the maximum sum is found, 
which is the column index 2 (third column) in this case.


\section TutorialReductionsVisitorsBroadcastingBroadcasting Broadcasting
The concept behind broadcasting is similar to partial reductions, with the difference that broadcasting 
constructs an expression where a vector (column or row) is interpreted as a matrix by replicating it in 
one direction.

A simple example is to add a certain column-vector to each column in a matrix. 
This can be accomplished with:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_broadcast_simple.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_broadcast_simple.out
</td></tr></table>

It is important to point out that the vector to be added column-wise or row-wise must be of type Vector,
and cannot be a Matrix. If this is not met then you will get compile-time error. This also means that
broadcasting operations can only be applied with an object of type Vector, when operating with Matrix.
The same applies for the \link ArrayBase Array \endlink class, where the equivalent for VectorXf is ArrayXf.

Therefore, to perform the same operation row-wise we can do:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_broadcast_simple_rowwise.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_broadcast_simple_rowwise.out
</td></tr></table>

\subsection TutorialReductionsVisitorsBroadcastingBroadcastingCombined Combining broadcasting with other operations
Broadcasting can also be combined with other operations, such as Matrix or \link ArrayBase Array \endlink operations, 
reductions and partial reductions.

Now that broadcasting, reductions and partial reductions have been introduced, we can dive into a more advanced example that finds
the nearest neighbour of a vector <tt>v</tt> within the columns of matrix <tt>m</tt>. The Euclidean distance will be used in this example,
computing the squared Euclidean distance with the partial reduction named \link DenseBase::squaredNorm() squaredNorm() \endlink:

<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ReductionsVisitorsBroadcasting_broadcast_1nn.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ReductionsVisitorsBroadcasting_broadcast_1nn.out
</td></tr></table>

The line that does the job is 
\code
  (m.colwise() - v).colwise().squaredNorm().minCoeff(&index);
\endcode

We will go step by step to understand what is happening:

  - <tt>m.colwise() - v</tt> is a broadcasting operation, substracting <tt>v</tt> from each column in <tt>m</tt>. The result of this operation
would be a new matrix whose size is the same as matrix <tt>m</tt>: \f[
  \mbox{m.colwise() - v} = 
  \begin{bmatrix}
    -1 & 21 & 4 & 7 \\
     0 & 8  & 4 & -1
  \end{bmatrix}
\f]

  - <tt>(m.colwise() - v).colwise().squaredNorm()</tt> is a partial reduction, computing the squared norm column-wise. The result of
this operation would be a row-vector where each coefficient is the squared Euclidean distance between each column in <tt>m</tt> and <tt>v</tt>: \f[
  \mbox{(m.colwise() - v).colwise().squaredNorm()} =
  \begin{bmatrix}
     1 & 505 & 32 & 50
  \end{bmatrix}
\f]

  - Finally, <tt>minCoeff(&index)</tt> is used to obtain the index of the column in <tt>m</tt> that is closer to <tt>v</tt> in terms of Euclidean
distance.

\li \b Next: \ref TutorialGeometry

*/

}