ALP User Documentation 0.7.0
Algebraic Programming User Documentation
kcore_decomposition.hpp
Go to the documentation of this file.
1
2/*
3 * Copyright 2021 Huawei Technologies Co., Ltd.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
28#ifndef _H_GRB_KCORE_DECOMPOSITION
29#define _H_GRB_KCORE_DECOMPOSITION
30
31#include <graphblas.hpp>
32
33
34namespace grb {
35
36 namespace algorithms {
37
136 template<
138 bool criticalSection = false,
139 typename IOType, typename NZType
140 >
142 const Matrix< NZType > &A,
143 Vector< IOType > &core,
144 Vector< IOType > &distances,
145 Vector< IOType > &temp,
146 Vector< IOType > &update,
147 Vector< bool > &status,
148 IOType &k
149 ) {
150 // Add constants/expressions
151 Semiring<
154 > ring;
155 Monoid<
158 > lorMonoid;
159
160 // Runtime sanity checks
161 const size_t n = nrows(A);
162 {
163 // Verify that A is square
164 if( n != ncols( A )){
165 return ILLEGAL;
166 }
167 // Verify sizes of vectors
168 if( size( core ) != n ||
169 size( distances ) != n ||
170 size( temp ) != n ||
171 size( update ) != n ||
172 size( status ) != n
173 ) {
174 return MISMATCH;
175 }
176 // Verify capacity
177 if( capacity( core ) != n ||
178 capacity( distances ) != n ||
179 capacity( temp ) != n ||
180 capacity( update ) != n ||
181 capacity( status ) != n
182 ) {
183 return ILLEGAL;
184 }
185 }
186
187 // Initialise
188 IOType current_k = 0; // current coreness level
189
190 // Set initial values
191 RC ret = grb::SUCCESS;
192 ret = ret ? ret : set( temp, static_cast< IOType >( 1 ) );
193 ret = ret ? ret : set( distances, static_cast< IOType >( 0 ) );
194 ret = ret ? ret : set( core, static_cast< IOType >( 0 ) );
195 ret = ret ? ret : set( status, true );
196 ret = ret ? ret : clear( update );
197 assert( ret == SUCCESS );
198
199 ret = ret ? ret : grb::mxv< descr | descriptors::dense >(
200 distances, A, temp, ring );
201 assert( ret == SUCCESS );
202
203 if( SUCCESS != ret ) {
204 std::cerr << " Initialization of k-core decomposition failed with error "
205 << grb::toString( ret ) << "\n";
206 return ret;
207 }
208
209 size_t count = 0;
210 while( count < n && SUCCESS == ret ) {
211 bool flag = true;
212
213 // Update filter to exclude completed nodes
214 ret = ret ? ret : set( update, status, status );
215
216 while( flag ) {
217 flag = false;
218
219 // Update nodes in parallel
220 if( criticalSection ) {
221 ret = ret ? ret : clear( temp );
222 ret = ret ? ret : eWiseLambda( [ &, current_k ]( const size_t i ) {
223 if( status[ i ] && distances[ i ] <= current_k ) {
224 core[ i ] = current_k;
225 // Remove node from checking
226 status[ i ] = false;
227 // Set update
228 flag = true;
229 #pragma omp critical
230 {
231 // Add node index to update neighbours
232 setElement( temp, 1, i );
233 }
234 }
235 }, update,
236 status, distances, core, temp
237 );
238 // WARN: even with the below, this variant does not auto-parallelise in
239 // the distributed-memory sense. The reason is a performance
240 // contract violation by the above critical section -- setElement
241 // should be a collective call, but its use from within eWiseLambda
242 // does not ensure a collective call. The result is that PANIC will
243 // at some point be returned.
244 //ret = ret ? ret : collectives<>::allreduce( flag,
245 // lorMonoid.getOperator() );
246 } else {
247 ret = ret ? ret : eWiseApply( temp, status, distances, current_k,
249 ret = ret ? ret : foldl( core, temp, current_k,
251 ret = ret ? ret : foldl( status, temp, false,
253 ret = ret ? ret : foldl( flag, temp, lorMonoid );
254 ret = ret ? ret : set( update, temp, 1 );
255 if( ret == SUCCESS ) {
256 std::swap( update, temp );
257 }
258 }
259 assert( ret == SUCCESS );
260
261 if( ret == SUCCESS && flag ) {
262 ret = clear( update );
263 assert( ret == SUCCESS );
264
265 // Increase number of nodes completed
266 count += nnz( temp );
267
268 // Get the neighbours of the updated nodes
269 ret = ret ? ret : grb::mxv< descr >( update, A, temp, ring );
270 assert( ret == SUCCESS );
271
272 // Decrease distances of the neighbours
273 ret = ret ? ret : grb::eWiseApply( distances, distances, update,
275 assert( ret == SUCCESS );
276 }
277 }
278 (void) ++current_k;
279 }
280
281 if( SUCCESS != ret ){
282 std::cerr << " Excecution of k-core decomposition failed with error "
283 << grb::toString(ret) << "\n";
284 } else {
285 k = current_k;
286 }
287
288 return ret;
289 }
290
291 } // namespace algorithms
292
293} // namespace grb
294
295#endif // end _H_GRB_KCORE_DECOMPOSITION
296
An ALP/GraphBLAS matrix.
Definition: matrix.hpp:71
A generalised monoid.
Definition: monoid.hpp:54
A generalised semiring.
Definition: semiring.hpp:186
A GraphBLAS vector.
Definition: vector.hpp:64
Standard identitity for the logical or operator.
Definition: identities.hpp:151
Standard identity for numerical multiplication.
Definition: identities.hpp:79
Standard identity for numerical addition.
Definition: identities.hpp:57
This operator takes the sum of the two input parameters and writes it to the output variable.
Definition: ops.hpp:177
This operation returns whether the left operand compares less-than or equal to the right operand.
Definition: ops.hpp:738
The logical or.
Definition: ops.hpp:464
This operator multiplies the two input parameters and writes the result to the output variable.
Definition: ops.hpp:210
This operator discards all left-hand side input and simply copies the right-hand side input to the ou...
Definition: ops.hpp:117
Numerical substraction of two numbers.
Definition: ops.hpp:303
The main header to include in order to use the ALP/GraphBLAS API.
RC eWiseLambda(const Func f, const Vector< DataType, backend, Coords > &x, Args...)
Executes an arbitrary element-wise user-defined function f on any number of vectors of equal length.
Definition: blas1.hpp:3746
RC eWiseApply(Vector< OutputType, backend, Coords > &z, const InputType1 alpha, const InputType2 beta, const OP &op=OP(), const Phase &phase=EXECUTE, const typename std::enable_if< !grb::is_object< OutputType >::value &&!grb::is_object< InputType1 >::value &&!grb::is_object< InputType2 >::value &&grb::is_operator< OP >::value, void >::type *const =nullptr)
Computes , out of place, operator version.
Definition: blas1.hpp:208
RC foldl(IOType &x, const Vector< InputType, backend, Coords > &y, const Vector< MaskType, backend, Coords > &mask, const Monoid &monoid=Monoid(), const typename std::enable_if< !grb::is_object< IOType >::value &&!grb::is_object< InputType >::value &&!grb::is_object< MaskType >::value &&grb::is_monoid< Monoid >::value, void >::type *const =nullptr)
Reduces, or folds, a vector into a scalar.
Definition: blas1.hpp:3840
RC set(Vector< DataType, backend, Coords > &x, const T val, const Phase &phase=EXECUTE, const typename std::enable_if< !grb::is_object< DataType >::value &&!grb::is_object< T >::value, void >::type *const =nullptr) noexcept
Sets all elements of a vector to the given value.
Definition: io.hpp:857
size_t nnz(const Vector< DataType, backend, Coords > &x) noexcept
Request the number of nonzeroes in a given vector.
Definition: io.hpp:479
size_t size(const Vector< DataType, backend, Coords > &x) noexcept
Request the size of a given vector.
Definition: io.hpp:235
size_t ncols(const Matrix< InputType, backend, RIT, CIT, NIT > &A) noexcept
Requests the column size of a given matrix.
Definition: io.hpp:339
size_t capacity(const Vector< InputType, backend, Coords > &x) noexcept
Queries the capacity of the given ALP/GraphBLAS container.
Definition: io.hpp:388
RC setElement(Vector< DataType, backend, Coords > &x, const T val, const size_t i, const Phase &phase=EXECUTE, const typename std::enable_if< !grb::is_object< DataType >::value &&!grb::is_object< T >::value, void >::type *const =nullptr)
Sets the element of a given vector at a given position to a given value.
Definition: io.hpp:1128
size_t nrows(const Matrix< InputType, backend, RIT, CIT, NIT > &A) noexcept
Requests the row size of a given matrix.
Definition: io.hpp:286
RC clear(Vector< DataType, backend, Coords > &x) noexcept
Clears a given vector of all nonzeroes.
Definition: io.hpp:574
RC kcore_decomposition(const Matrix< NZType > &A, Vector< IOType > &core, Vector< IOType > &distances, Vector< IOType > &temp, Vector< IOType > &update, Vector< bool > &status, IOType &k)
The -core decomposition algorithm.
Definition: kcore_decomposition.hpp:141
static constexpr Descriptor no_operation
Indicates no additional pre- or post-processing on any of the GraphBLAS function arguments.
Definition: descriptors.hpp:63
The ALP/GraphBLAS namespace.
Definition: graphblas.hpp:452
RC
Return codes of ALP primitives.
Definition: rc.hpp:47
@ ILLEGAL
A call to a primitive has determined that one of its arguments was illegal as per the specification o...
Definition: rc.hpp:143
@ MISMATCH
One or more of the ALP/GraphBLAS objects passed to the primitive that returned this error have mismat...
Definition: rc.hpp:90
@ SUCCESS
Indicates the primitive has executed successfully.
Definition: rc.hpp:54
unsigned int Descriptor
Descriptors indicate pre- or post-processing for some or all of the arguments to an ALP/GraphBLAS cal...
Definition: descriptors.hpp:54
std::string toString(const RC code)