Skip to content

Commit 970bded

Browse files
committed
First follow with a section on copying containers and masking them
1 parent 707c85c commit 970bded

File tree

2 files changed

+142
-2
lines changed

2 files changed

+142
-2
lines changed

ALP_Tutorial.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ \subsection{Copying, Masking, and Standard Matrices}
252252
\end{lstlisting}
253253
\href{http://albert-jan.yzelman.net/alp/v0.8-preview/classgrb_1_1algorithms_1_1matrices.html#a1336accbaf6a61ebd890bef9da4116fc}{Other regular patterns supported} are \emph{eye} (similar to identity but not required to be a square matrix) and \emph{diag} (which takes an optional parameter $k$ to generate offset the diagonal, e.g., to generate a superdiagonal matrix). The class includes a set of constructors that result in dense matrices as well, including \emph{dense}, \emph{full}, \emph{zeros}, and \emph{ones}; note, however, that ALP/GraphBLAS is not optimised to handle dense matrices efficiently and so their use is discouraged\footnote{for similar reasons, actually, there is no primitive \texttt{grb::set(matrix,scalar)} in the GraphBLAS API}. While constructing matrices from standard file formats and through general iterators hence are key features for usability, it is also possible to derive matrices from existing ones via \texttt{grb::set(matrix,mask,value)}.
254254

255-
\noindent \textbf{Exercise 6.} Copy the code from the previous exercise, and modify it to determine whether $A$ holds explicit zeroes; i.e., entries in $A$ that have numerical value zero. \textbf{Hint:} it is possible to complete this exercise using only masking and copiying. For bonus points, consider making use of the \texttt{grb::descriptors::invert\_mask} descriptor described \href{http://albert-jan.yzelman.net/alp/v0.8-preview/namespacegrb_1_1descriptors.html}{here}.
255+
\noindent \textbf{Exercise 6.} Copy the code from the previous exercise, and modify it to determine whether $A$ holds explicit zeroes; i.e., entries in $A$ that have numerical value zero. \textbf{Hint:} it is possible to complete this exercise using only masking and copiying. You may also want to change the element type of $A$ to \texttt{double} (or convince yourself that this is not required).
256256

257-
\noindent \textbf{Exercise 7.} Determine how many explicit zeroes exist on the diagonal, superdiagonal, and subdiagonal of $A$; i.e., compute $|\{A_{ij}\ |\ A_{ij}=0, |i-j|\leq1, 0\leq i,j<497\}|$.
257+
\noindent \textbf{Exercise 7.} Determine how many explicit zeroes exist on the diagonal, superdiagonal, and subdiagonal of $A$; i.e., compute $|\{A_{ij}\in A\ |\ A_{ij}=0, |i-j|\leq1, 0\leq i,j<497\}|$.
258258

259259
\noindent \textbf{Bonus question.} How much memory beyond that which is required to store the $n\times n$ identity matrix will a call to \texttt{matrices< double >::identity( n )} consume? \textbf{Hint:} consider that the iterators passed to \texttt{buildMatrixUnique} iterate over regular index sequences that can easily be systematically enumerated.
260260

solutions/6-7-masking.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
2+
#include <cstddef>
3+
#include <cstring>
4+
5+
#include <graphblas.hpp>
6+
#include <graphblas/utils/parser.hpp>
7+
#include <graphblas/algorithms/matrix_factory.hpp>
8+
9+
#include <assert.h>
10+
11+
12+
constexpr size_t max_fn_size = 255;
13+
typedef char Filename[ max_fn_size ];
14+
15+
void hello_world( const Filename &in, int &out ) {
16+
grb::Vector< bool > x( 497 ), y( 497, 1 );
17+
grb::Matrix< double > A( 497, 497, 1727 );
18+
19+
grb::RC rc = grb::set( x, false );
20+
rc = rc ? rc : grb::setElement( y, true, 200 );
21+
if( rc != grb::SUCCESS ) {
22+
out = 10;
23+
return;
24+
}
25+
26+
std::cout << "elements in x: " << grb::nnz( x ) << "\n";
27+
std::cout << "elements in y: " << grb::nnz( y ) << "\n";
28+
std::cout << "cacacity of y: " << grb::capacity( y ) << "\n";
29+
30+
for( const auto &pair : y ) {
31+
std::cout << "y[ " << pair.first << " ] = " << pair.second << "\n";
32+
}
33+
34+
size_t x_nnz = 0;
35+
for( const auto &pair : x ) {
36+
(void) ++x_nnz;
37+
if( pair.second ) {
38+
std::cerr << "x[ " << pair.first << " ] reads true "
39+
<< "but false was expected!\n";
40+
out = 20;
41+
return;
42+
}
43+
}
44+
if( x_nnz != 497 ) {
45+
std::cerr << "Output iterator of x retrieved " << x_nnz << " elements, "
46+
<< "expected 497!\n";
47+
out = 30;
48+
return;
49+
}
50+
51+
grb::utils::MatrixFileReader< double > parser( in, true );
52+
if( parser.m() != 497 || parser.n() != 497 ) {
53+
std::cerr << in << " corresponds to a matrix of unexpected size\n";
54+
out = 40;
55+
return;
56+
}
57+
{
58+
const auto iterator = parser.begin();
59+
std::cout << "First parsed entry: ( " << iterator.i() << ", " << iterator.j() << " ) = " << iterator.v() << "\n";
60+
}
61+
62+
rc = grb::buildMatrixUnique(
63+
A,
64+
parser.begin( grb::SEQUENTIAL ), parser.end( grb::SEQUENTIAL ),
65+
grb::SEQUENTIAL
66+
);
67+
if( rc != grb::SUCCESS ) {
68+
std::cerr << "Error encountered during reading " << in << "\n";
69+
out = 50;
70+
return;
71+
}
72+
std::cout << "nonzeroes in A: " << grb::nnz( A ) << "\n";
73+
74+
// exercise 6
75+
grb::Matrix< double > B( 497, 497 ), C( 497, 497 );
76+
rc = grb::set( B, A, grb::RESIZE );
77+
rc = rc ? rc : grb::set( B, A, grb::EXECUTE );
78+
rc = rc ? rc : grb::set( C, B, A, grb::RESIZE );
79+
rc = rc ? rc : grb::set( C, B, A, grb::EXECUTE );
80+
if( rc != grb::SUCCESS ) {
81+
std::cerr << "Error during computing solution to ex. 6\n";
82+
out = 60;
83+
return;
84+
}
85+
std::cout << "capacity of C: " << grb::capacity( C ) << "\n";
86+
std::cout << "number of elements in C (==number of nonzeroes in A): "
87+
<< grb::nnz( C ) << "\n";
88+
assert( grb::nnz(A) >= grb::nnz(C) );
89+
std::cout << "number of explicit (numerical) zeroes in A: " <<
90+
(grb::nnz(A) - grb::nnz(C)) << "\n";
91+
92+
// exercise 7
93+
size_t nzs = 0;
94+
grb::Matrix< bool > mask =
95+
grb::algorithms::matrices< double >::eye( 497, 497, true, 1 );
96+
rc = grb::set( B, mask1, A );
97+
rc = rc ? rc : grb::set( C, B, A );
98+
// note that capacities of B and C are guaranteed sufficient in the above
99+
if( rc == grb::SUCCESS ) { nzs += grb::nnz( B ) - grb::nnz( C ); }
100+
mask = grb::algorithms::matrices< double >::eye( 497, 497, true, 0 );
101+
rc = rc ? rc : grb::set( B, mask2, A );
102+
rc = rc ? rc : grb::set( C, B, A );
103+
if( rc == grb::SUCCESS ) { nzs += grb::nnz( B ) - grb::nnz( C ); }
104+
mask = grb::algorithms::matrices< double >::eye( 497, 497, true, -1 );
105+
rc = rc ? rc : grb::set( B, mask3, A );
106+
rc = rc ? rc : grb::set( C, B, A );
107+
if( rc == grb::SUCCESS ) { nzs += grb::nnz( B ) - grb::nnz( C ); } else {
108+
std::cerr << "Error during computing solution to ex. 7\n";
109+
out = 70;
110+
return;
111+
}
112+
std::cout << "Number of explicit (numerical) zeroes in the subdiagonal, "
113+
<< "diagonal, and superdiagonal of A combined: " << nzs << "\n";
114+
115+
// all OK
116+
out = 0;
117+
}
118+
119+
int main( int argc, char ** argv ) {
120+
if( argc < 2 || argc > 2 ) {
121+
std::cout << "Usage: " << argv[ 0 ] << " </path/to/west0497.mtx>\n";
122+
return 0;
123+
}
124+
125+
// get input
126+
Filename fn;
127+
(void) std::strncpy( fn, argv[ 1 ], max_fn_size );
128+
129+
// set up output field
130+
int error_code = 100;
131+
132+
// launch hello world program
133+
grb::Launcher< grb::AUTOMATIC > launcher;
134+
assert( launcher.exec( &hello_world, fn, error_code, true )
135+
== grb::SUCCESS );
136+
137+
// return with the hello_world error code
138+
return error_code;
139+
}
140+

0 commit comments

Comments
 (0)