2020 *
2121 * Implements the triangle counting algorithm, using different methods.
2222 *
23- * @author B. Lozes
23+ * @author Benjamin Lozes
2424 * @date: May 10th, 2023
2525 */
2626
3535
3636#include < graphblas.hpp>
3737
38- constexpr bool Debug = false ;
39-
4038namespace grb {
4139
4240 namespace algorithms {
4341
44- namespace utils {
45-
46- template < class Iterator >
47- void printSparseMatrixIterator ( size_t rows, size_t cols, Iterator begin, Iterator end, const std::string & name = " " , std::ostream & os = std::cout ) {
48- std::cout << " Matrix \" " << name << " \" (" << rows << " x" << cols << " ):" << std::endl << " [" << std::endl;
49- if ( rows > 100 || cols > 100 ) {
50- os << " Matrix too large to print" << std::endl;
51- } else {
52- // os.precision( 3 );
53- for ( size_t y = 0 ; y < rows; y++ ) {
54- os << std::string ( 3 , ' ' );
55- for ( size_t x = 0 ; x < cols; x++ ) {
56- auto nnz_val = std::find_if ( begin, end, [ y, x ]( const typename std::iterator_traits< Iterator >::value_type & a ) {
57- return a.first .first == y && a.first .second == x;
58- } );
59- if ( nnz_val != end )
60- os << std::fixed << ( *nnz_val ).second ;
61- else
62- os << ' _' ;
63- os << " " ;
64- }
65- os << std::endl;
66- }
67- }
68- os << " ]" << std::endl;
69- }
70-
71- template < bool debug, typename D >
72- void printSparseMatrix ( const grb::Matrix< D > & mat, const std::string & name = " " , std::ostream & os = std::cout ) {
73- if ( ! debug )
74- return ;
75- grb::wait ( mat );
76- printSparseMatrixIterator ( grb::nrows ( mat ), grb::ncols ( mat ), mat.cbegin (), mat.cend (), name, os );
77- }
78-
79- template < bool debug >
80- void printf ( const std::string & msg, std::ostream & os = std::cout ) {
81- if ( ! debug )
82- return ;
83- os << msg;
84- }
85- } // namespace utils
86-
8742 enum class TriangleCountAlgorithm { Burkhardt, Cohen, Sandia_TT };
8843
89- std::map< TriangleCountAlgorithm, std::string > TriangleCountAlgorithmNames = { { TriangleCountAlgorithm::Burkhardt, " Burkhardt" }, { TriangleCountAlgorithm::Cohen, " Cohen" },
90- { TriangleCountAlgorithm::Sandia_TT, " Sandia_TT" } };
44+ std::map< TriangleCountAlgorithm, std::string > TriangleCountAlgorithmNames = {
45+ { TriangleCountAlgorithm::Burkhardt, " Burkhardt" },
46+ { TriangleCountAlgorithm::Cohen, " Cohen" },
47+ { TriangleCountAlgorithm::Sandia_TT, " Sandia_TT" }
48+ };
9149
9250 template <
9351 class Semiring , class MulMonoid , class SumMonoid ,
@@ -103,47 +61,41 @@ namespace grb {
10361 >
10462 RC triangle_count_generic (
10563 size_t & count,
106- Matrix< D1, grb:: config::default_backend, RIT1, CIT1, NIT1 > & MXM_out,
107- const Matrix< D2, grb:: config::default_backend, RIT2, CIT2, NIT2 > & MXM_lhs,
108- const Matrix< D3, grb:: config::default_backend, RIT3, CIT3, NIT3 > & MXM_rhs,
109- Matrix< D4, grb:: config::default_backend, RIT4, CIT4, NIT4 > & EWA_out,
110- const Matrix< D5, grb:: config::default_backend, RIT5, CIT5, NIT5 > & EWA_rhs,
64+ Matrix< D1, config::default_backend, RIT1, CIT1, NIT1 > & MXM_out,
65+ const Matrix< D2, config::default_backend, RIT2, CIT2, NIT2 > & MXM_lhs,
66+ const Matrix< D3, config::default_backend, RIT3, CIT3, NIT3 > & MXM_rhs,
67+ Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & EWA_out,
68+ const Matrix< D5, config::default_backend, RIT5, CIT5, NIT5 > & EWA_rhs,
11169 const D6 div_factor,
11270 const Semiring mxm_semiring = Semiring(),
11371 const MulMonoid ewiseapply_monoid = MulMonoid(),
114- const SumMonoid sumreduce_monoid = SumMonoid() ) {
115- RC rc = RC::SUCCESS;
72+ const SumMonoid sumreduce_monoid = SumMonoid()
73+ ) {
74+ if ( ( &MXM_out == &MXM_lhs ) || ( &MXM_out == &MXM_rhs ) ) {
75+ return ILLEGAL;
76+ }
11677
117- rc = ( &MXM_out == &MXM_lhs ) ? RC::ILLEGAL : rc;
118- rc = ( &MXM_out == &MXM_rhs ) ? RC::ILLEGAL : rc;
78+ RC rc = SUCCESS;
11979
12080 // Compute MXM_out = Mlhs * Mrhs
121- utils::printSparseMatrix< Debug >( MXM_lhs, " MXM_lhs" );
122- utils::printSparseMatrix< Debug >( MXM_rhs, " MXM_rhs" );
12381 rc = rc ? rc : mxm< descr_mxm >( MXM_out, MXM_lhs, MXM_rhs, mxm_semiring, Phase::RESIZE );
12482 rc = rc ? rc : mxm< descr_mxm >( MXM_out, MXM_lhs, MXM_rhs, mxm_semiring, Phase::EXECUTE );
125- utils::printSparseMatrix< Debug >( MXM_out, " MXM_out = mxm( MXM_lhs, MXM_rhs )" );
12683
12784 // Compute MXM_out .*= EWA_rhs
128- utils::printSparseMatrix< Debug >( EWA_rhs, " EWA_rhs" );
129-
13085 // FIXME: Replace by a foldl( Matrix[in,out], Matrix[in], Monoid ) - not implemented yet
13186 // Will then become:
13287 // rc = rc ? rc : eWiseApply< descr_ewa >( MXM_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::RESIZE );
13388 // rc = rc ? rc : eWiseApply< descr_ewa >( MXM_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::EXECUTE );
13489 // Instead of:
13590 rc = rc ? rc : eWiseApply< descr_ewa >( EWA_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::RESIZE );
13691 rc = rc ? rc : eWiseApply< descr_ewa >( EWA_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::EXECUTE );
137- utils::printSparseMatrix< Debug >( EWA_out, " EWA_out = ewiseapply( MXM_out, EWA_rhs )" );
13892
139- // Compute a sum reduction over <EWA_out> in <count>
93+ // Compute a sum reduction over <EWA_out> into <count>
14094 count = static_cast < size_t >( 0 );
14195 rc = rc ? rc : foldl< descr_reduce >( count, EWA_out, sumreduce_monoid );
142- utils::printf< Debug >( " count = foldl(EWA_out) = " + std::to_string ( count ) + " \n " );
14396
14497 // Apply the div_factor to the reduction result
14598 count /= div_factor;
146- utils::printf< Debug >( " count = count / div_factor = " + std::to_string ( count ) + " \n " );
14799
148100 return rc;
149101 }
@@ -187,57 +139,63 @@ namespace grb {
187139 typename D2, typename RIT2, typename CIT2, typename NIT2,
188140 typename D3, typename RIT3, typename CIT3, typename NIT3,
189141 typename D4, typename RIT4, typename CIT4, typename NIT4,
190- class Semiring = grb::Semiring< operators::add< D1 >, operators::mul< D1 >, identities::zero, identities::one >,
191- class MulMonoid = grb::Monoid< grb::operators::mul< D1 >, identities::one >,
192- class SumMonoid = grb::Monoid< operators::add< size_t , D1, size_t >, identities::zero > >
142+ class Semiring = Semiring< operators::add< D1 >,
143+ operators::mul< D1 >,
144+ identities::zero,
145+ identities::one >,
146+ class MulMonoid = Monoid< operators::mul< D1 >,
147+ identities::one >,
148+ class SumMonoid = Monoid< operators::add< size_t , D1, size_t >,
149+ identities::zero >
150+ >
193151 RC triangle_count (
194152 const TriangleCountAlgorithm algo,
195153 size_t & count,
196- const Matrix< D1, grb:: config::default_backend, RIT1, CIT1, NIT1 > & A,
197- Matrix< D2, grb:: config::default_backend, RIT2, CIT2, NIT2 > & MXM_out,
198- Matrix< D3, grb:: config::default_backend, RIT3, CIT3, NIT3 > & EWA_out,
199- Matrix< D4, grb:: config::default_backend, RIT4, CIT4, NIT4 > & L = { 0 , 0 },
200- Matrix< D4, grb:: config::default_backend, RIT4, CIT4, NIT4 > & U = { 0 , 0 }
154+ const Matrix< D1, config::default_backend, RIT1, CIT1, NIT1 > & A,
155+ Matrix< D2, config::default_backend, RIT2, CIT2, NIT2 > & MXM_out,
156+ Matrix< D3, config::default_backend, RIT3, CIT3, NIT3 > & EWA_out,
157+ Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & L = { 0 , 0 },
158+ Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & U = { 0 , 0 }
201159 ) {
202160 // Static assertions
203161 static_assert ( std::is_integral< D1 >::value, " Type D1 must be integral" );
204162
205163 // Sanity checks
206164 if ( nrows ( A ) != ncols ( A ) ) {
207165 std::cerr << " Matrix A must be square" << std::endl;
208- return RC:: MISMATCH;
166+ return MISMATCH;
209167 }
210168 if ( ncols ( L ) != nrows ( L ) ) {
211169 std::cerr << " Matrix L must be square" << std::endl;
212- return RC:: MISMATCH;
170+ return MISMATCH;
213171 }
214172 if ( nrows ( A ) != ncols ( L ) ) {
215173 std::cerr << " Matrices A and L must have the same dimensions" << std::endl;
216- return RC:: MISMATCH;
174+ return MISMATCH;
217175 }
218176 if ( ncols ( U ) != nrows ( U ) ) {
219177 std::cerr << " Matrix U must be square" << std::endl;
220- return RC:: MISMATCH;
178+ return MISMATCH;
221179 }
222180 if ( nrows ( A ) != ncols ( U ) ) {
223181 std::cerr << " Matrices A and U must have the same dimensions" << std::endl;
224- return RC:: MISMATCH;
182+ return MISMATCH;
225183 }
226184 if ( ncols ( MXM_out ) != nrows ( MXM_out ) ) {
227185 std::cerr << " Matrix MXM_out must be square" << std::endl;
228- return RC:: MISMATCH;
186+ return MISMATCH;
229187 }
230188 if ( nrows ( A ) != ncols ( MXM_out ) ) {
231189 std::cerr << " Matrices A and MXM_out must have the same dimensions" << std::endl;
232- return RC:: MISMATCH;
190+ return MISMATCH;
233191 }
234192 if ( ncols ( EWA_out ) != nrows ( EWA_out ) ) {
235193 std::cerr << " Matrix EWA_out must be square" << std::endl;
236- return RC:: MISMATCH;
194+ return MISMATCH;
237195 }
238196 if ( nrows ( A ) != ncols ( EWA_out ) ) {
239197 std::cerr << " Matrices A and EWA_out must have the same dimensions" << std::endl;
240- return RC:: MISMATCH;
198+ return MISMATCH;
241199 }
242200
243201 // Dispatch to the appropriate algorithm
@@ -252,11 +210,11 @@ namespace grb {
252210 case TriangleCountAlgorithm::Cohen: {
253211 if ( nrows ( L ) == 0 || ncols ( L ) == 0 ) {
254212 std::cerr << " Matrix L must be provided for the Cohen algorithm" << std::endl;
255- return RC:: MISMATCH;
213+ return MISMATCH;
256214 }
257215 if ( nrows ( U ) == 0 || ncols ( U ) == 0 ) {
258216 std::cerr << " Matrix U must be provided for the Cohen algorithm" << std::endl;
259- return RC:: MISMATCH;
217+ return MISMATCH;
260218 }
261219
262220 return triangle_count_generic<
@@ -267,21 +225,21 @@ namespace grb {
267225 case TriangleCountAlgorithm::Sandia_TT: {
268226 if ( ( nrows ( U ) == 0 || ncols ( U ) == 0 ) && ( nrows ( L ) == 0 || ncols ( L ) == 0 ) ) {
269227 std::cerr << " Matrix L or U must be provided for the Sandia_TT algorithm" << std::endl;
270- return RC:: MISMATCH;
228+ return MISMATCH;
271229 }
272230
273- const Matrix< D4, grb:: config::default_backend, RIT4, CIT4, NIT4 > & T = ( nrows ( U ) == 0 || ncols ( U ) == 0 ) ? L : U;
231+ const Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & T = ( nrows ( U ) == 0 || ncols ( U ) == 0 ) ? L : U;
274232 return triangle_count_generic<
275233 Semiring, MulMonoid, SumMonoid
276234 >( count, MXM_out, T, T, EWA_out, T, 1UL );
277235 }
278236
279237 default :
280238 std::cerr << " Unknown TriangleCountAlgorithm enum value" << std::endl;
281- return RC:: ILLEGAL;
239+ return ILLEGAL;
282240 }
283241
284- return RC:: SUCCESS;
242+ return SUCCESS;
285243 }
286244
287245 } // namespace algorithms
0 commit comments