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
//------------------------------------------------------------------------------
// LAGraph_KCoreDecompose: Helper method to LAGraph_KCore and LAGraph_AllKCore
// that performs graph decomposition given a specified value k.
//------------------------------------------------------------------------------
// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
// SPDX-License-Identifier: BSD-2-Clause
//
// For additional details (including references to third party source code and
// other files) see the LICENSE file or contact permission@sei.cmu.edu. See
// Contributors.txt for a full list of contributors. Created, in part, with
// funding and support from the U.S. Government (see Acknowledgments.txt file).
// DM22-0790
// Contributed by Pranav Konduri, Texas A&M University
//------------------------------------------------------------------------------
// The input is a graph G and its k-core vector, decomp.
// The output is the k-core adjacency matrix D itself, with the same number of
// nodes as the input graph G, but with edges not in the k-core deleted.
#define LG_FREE_WORK \
{ \
GrB_free (&C) ; \
GrB_free (°) ; \
}
#define LG_FREE_ALL \
{ \
LG_FREE_WORK \
GrB_free (D) ; \
}
#include "LG_internal.h"
// TODO: need both basic and expert; this is advanced
// TODO: this should return D as an LAGraph_Graph, not as a GrB_Matrix
int LAGraph_KCore_Decompose
(
// outputs:
GrB_Matrix *D, // kcore decomposition
// inputs:
LAGraph_Graph G, // input graph
GrB_Vector decomp, // input decomposition vector
uint64_t k,
char *msg
)
{
#if LAGRAPH_SUITESPARSE
LG_CLEAR_MSG ;
// declare items
GrB_Matrix A = NULL, C = NULL;
GrB_Vector deg = NULL;
LG_ASSERT (D != NULL, GrB_NULL_POINTER) ;
(*D) = NULL ;
LG_TRY (LAGraph_CheckGraph (G, msg)) ;
if (G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
(G->kind == LAGraph_ADJACENCY_DIRECTED &&
G->is_symmetric_structure == LAGraph_TRUE))
{
// the structure of A is known to be symmetric
A = G->A ;
}
else
{
// A is not known to be symmetric
LG_ASSERT_MSG (false, -1005, "G->A must be symmetric") ;
}
// no self edges can be present
// todo: what would happen if there are self edges?
LG_ASSERT_MSG (G->nself_edges == 0, -1004, "G->nself_edges must be zero") ;
//create work scalars
GrB_Index nrows, n;
GRB_TRY (GrB_Matrix_nrows(&nrows, A)) ;
GRB_TRY (GrB_Vector_size(&n, decomp)) ;
LG_ASSERT_MSG (nrows == n, -1003, "Size of vector and rows of matrix must be same") ;
//Create Vectors and Matrices
GRB_TRY (GrB_Vector_new(°, GrB_INT64, n)) ;
GRB_TRY (GrB_Matrix_new(D, GrB_INT64, n, n)) ;
//create deg vector using select
GRB_TRY (GrB_select (deg, GrB_NULL, GrB_NULL, GrB_VALUEGE_INT64, decomp, k, GrB_NULL)) ;
//create decomposition matrix (C * A * C)
GRB_TRY (GrB_Matrix_diag(&C, deg, 0)) ;
GRB_TRY (GrB_mxm (*D, NULL, NULL, GxB_ANY_SECONDI_INT64, C, A, GrB_NULL)) ;
GRB_TRY (GrB_mxm (*D, NULL, NULL, GxB_MIN_SECONDI_INT64, *D, C, GrB_NULL)) ;
//Assigns all values as 1 (todo: change to something cleaner)
GRB_TRY (GrB_assign (*D, *D, NULL, (int64_t) 1, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ;
LG_FREE_WORK ;
return (GrB_SUCCESS) ;
#else
return (GrB_NOT_IMPLEMENTED) ;
#endif
}