#define LG_FREE_WORK \
{ \
GrB_free (&squares) ; \
GrB_free (&denom) ; \
GrB_free (&neg_denom) ; \
GrB_free (&P2) ; \
GrB_free (&D) ; \
}
#define LG_FREE_ALL \
{ \
LG_FREE_WORK ; \
GrB_free (&r) ; \
}
#include <LAGraph.h>
#include <LAGraphX.h>
#include <LG_internal.h>
int LAGraph_SquareClustering
(
GrB_Vector *square_clustering,
LAGraph_Graph G,
char *msg
)
{
LG_CLEAR_MSG ;
GrB_Vector squares = NULL ;
GrB_Vector denom = NULL ;
GrB_Vector neg_denom = NULL ;
GrB_Vector r = NULL ;
GrB_Matrix D = NULL ;
GrB_Matrix P2 = NULL ;
GrB_Vector deg = G->out_degree ;
GrB_Matrix A = G->A ;
GrB_Index n = 0 ;
LG_ASSERT (square_clustering != NULL, GrB_NULL_POINTER) ;
(*square_clustering) = NULL ;
LG_ASSERT_MSG (deg != NULL,
LAGRAPH_NOT_CACHED, "G->out_degree is required") ;
LG_TRY (LAGraph_CheckGraph (G, msg)) ;
LG_ASSERT_MSG ((G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
(G->kind == LAGraph_ADJACENCY_DIRECTED &&
G->is_symmetric_structure == LAGraph_TRUE)),
LAGRAPH_SYMMETRIC_STRUCTURE_REQUIRED,
"G->A must be known to be symmetric") ;
GRB_TRY (GrB_Matrix_nrows (&n, A)) ;
GRB_TRY (GrB_Matrix_diag(&D, deg, 0)) ;
GRB_TRY (GrB_Matrix_new (&P2, GrB_INT64, n, n)) ;
GRB_TRY (GrB_mxm (P2, D, NULL, LAGraph_plus_one_int64, A, A, GrB_DESC_SCT1)) ;
GRB_TRY (GrB_Matrix_eWiseMult_BinaryOp (D, NULL, NULL, GrB_FIRST_INT64, P2,
A, NULL)) ;
GRB_TRY (GrB_Vector_new (&neg_denom, GrB_INT64, n)) ;
GRB_TRY (GrB_Matrix_reduce_Monoid (neg_denom, NULL, NULL,
GrB_PLUS_MONOID_INT64, D, NULL)) ;
GrB_free (&D) ;
GRB_TRY (GrB_Matrix_apply_BinaryOp2nd_INT64 (P2, NULL, GrB_TIMES_INT64,
GrB_MINUS_INT64, P2, 1, NULL)) ;
GRB_TRY (GrB_Vector_new (&squares, GrB_INT64, n)) ;
GRB_TRY (GrB_Matrix_reduce_Monoid (squares, NULL, NULL,
GrB_PLUS_MONOID_INT64, P2, NULL)) ;
GrB_free (&P2) ;
GRB_TRY (GrB_Vector_apply_BinaryOp2nd_INT64 (squares, squares, NULL,
GrB_DIV_INT64, squares, 2, GrB_DESC_R)) ;
GRB_TRY (GrB_Vector_new (&denom, GrB_INT64, n)) ;
GRB_TRY (GrB_Vector_apply_BinaryOp2nd_INT64(denom, squares, NULL,
GrB_MINUS_INT64, deg, 1, GrB_DESC_S)) ;
GRB_TRY (GrB_Vector_eWiseMult_BinaryOp(neg_denom, NULL, GrB_PLUS_INT64,
GrB_TIMES_INT64, deg, denom, NULL)) ;
GRB_TRY (GrB_mxv(denom, denom, GrB_TIMES_INT64,
GrB_PLUS_TIMES_SEMIRING_INT64, A, deg, GrB_DESC_S)) ;
GRB_TRY (GrB_Vector_eWiseMult_BinaryOp(denom, NULL, GrB_MINUS_INT64,
GrB_PLUS_INT64, neg_denom, squares, NULL)) ;
GRB_TRY (GrB_Vector_new (&r, GrB_FP64, n)) ;
GRB_TRY (GrB_Vector_eWiseMult_BinaryOp (r, NULL, NULL, GrB_DIV_FP64,
squares, denom, NULL)) ;
(*square_clustering) = r ;
LG_FREE_WORK ;
return (GrB_SUCCESS) ;
}