1 //------------------------------------------------------------------------------
2 // GraphBLAS/Demo/Program/kron_demo.c: Kronkecker product
3 //------------------------------------------------------------------------------
4
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7
8 //------------------------------------------------------------------------------
9
10 // Reads two graphs from two files and computes their Kronecker product,
11 // C = kron (A,B), writing the result to a file.
12 //
13 // kron_demo A.tsv B.tsv C.tsv
14 //
15 // Where A.tsv and B.tsv are two tab- or space-delimited triplet files with
16 // 1-based indices. Each line has the form:
17 //
18 // i j x
19 //
20 // where A(i,j)=x is performed by GrB_Matrix_build, to construct the matrix.
21 // The dimensions of A and B are assumed to be the largest row and column
22 // indices that appear in the files. The file C.tsv is the filename of the
23 // output file for C=kron(A,B), also with 1-based indices.
24
25 // macro used by OK(...) to free workspace if an error occurs
26 #define FREE_ALL \
27 GrB_Matrix_free (&A) ; \
28 GrB_Matrix_free (&B) ; \
29 GrB_Matrix_free (&C) ; \
30 if (Afile != NULL) fclose (Afile) ; \
31 if (Bfile != NULL) fclose (Bfile) ; \
32 if (Cfile != NULL) fclose (Cfile) ; \
33 if (I != NULL) free (I) ; \
34 if (J != NULL) free (J) ; \
35 if (X != NULL) free (X) ; \
36 GrB_finalize ( ) ;
37
38 #include "graphblas_demos.h"
39
main(int argc,char ** argv)40 int main (int argc, char **argv)
41 {
42 //--------------------------------------------------------------------------
43 // check inputs
44 //--------------------------------------------------------------------------
45
46 GrB_Matrix A = NULL, B = NULL, C = NULL ;
47 GrB_Index *I = NULL, *J = NULL ;
48 FILE *Afile = NULL, *Bfile = NULL, *Cfile = NULL ;
49 double *X = NULL ;
50 GrB_Info info ;
51 double tic [2], t ;
52
53 OK (GrB_init (GrB_NONBLOCKING)) ;
54 int nthreads ;
55 OK (GxB_Global_Option_get (GxB_GLOBAL_NTHREADS, &nthreads)) ;
56 fprintf (stderr, "kron demo: nthreads %d\n", nthreads) ;
57
58 // printf ("argc %d\n", argc) ;
59 if (argc != 4)
60 {
61 FREE_ALL ;
62 fprintf (stderr, "usage: kron_demo A.tsv B.tsv C.tsv\n") ;
63 exit (1) ;
64 }
65
66 Afile = fopen (argv [1], "r") ;
67 Bfile = fopen (argv [2], "r") ;
68 Cfile = fopen (argv [3], "w") ;
69 if (Afile == NULL || Bfile == NULL || Cfile == NULL)
70 {
71 FREE_ALL ;
72 fprintf (stderr, "unable to read input files or create output file\n") ;
73 exit (1) ;
74 }
75
76 //--------------------------------------------------------------------------
77 // get A and B from input files
78 //--------------------------------------------------------------------------
79
80 // this would be faster and take less memory if GraphBLAS had a built-in
81 // read-from-file operation
82 OK (read_matrix (&A, Afile, false, false, true, false, false)) ;
83 OK (read_matrix (&B, Bfile, false, false, true, false, false)) ;
84
85 fclose (Afile) ;
86 fclose (Bfile) ;
87 Afile = NULL ;
88 Bfile = NULL ;
89
90 GrB_Index anrows, ancols, bnrows, bncols, anvals, bnvals ;
91 OK (GrB_Matrix_nrows (&anrows, A)) ;
92 OK (GrB_Matrix_ncols (&ancols, A)) ;
93 OK (GrB_Matrix_nvals (&anvals, A)) ;
94 OK (GrB_Matrix_nrows (&bnrows, B)) ;
95 OK (GrB_Matrix_ncols (&bncols, B)) ;
96 OK (GrB_Matrix_nvals (&bnvals, B)) ;
97
98 //--------------------------------------------------------------------------
99 // C = kron (A,B)
100 //--------------------------------------------------------------------------
101
102 OK (GrB_Matrix_new (&C, GrB_FP64, anrows * bnrows, ancols * bncols)) ;
103
104 simple_tic (tic) ;
105 OK (GrB_Matrix_kronecker_BinaryOp (C, NULL, NULL,
106 GrB_TIMES_FP64, A, B, NULL)) ;
107 t = simple_toc (tic) ;
108
109 OK (GrB_Matrix_free (&A)) ;
110 OK (GrB_Matrix_free (&B)) ;
111
112 //--------------------------------------------------------------------------
113 // report results
114 //--------------------------------------------------------------------------
115
116 GrB_Index cnrows, cncols, cnvals ;
117 OK (GrB_Matrix_nrows (&cnrows, C)) ;
118 OK (GrB_Matrix_ncols (&cncols, C)) ;
119 OK (GrB_Matrix_nvals (&cnvals, C)) ;
120
121 // note that integers of type GrB_Index should be printed with the
122 // %PRIu64 format.
123
124 fprintf (stderr, "GraphBLAS GrB_kronecker:\n"
125 "A: %" PRIu64 "-by-%" PRIu64 ", %" PRIu64 " entries.\n"
126 "B: %" PRIu64 "-by-%" PRIu64 ", %" PRIu64 " entries.\n"
127 "C: %" PRIu64 "-by-%" PRIu64 ", %" PRIu64 " entries.\n"
128 "time: %g seconds, rate: nval(C)/t = %g million/sec\n",
129 anrows, ancols, anvals,
130 bnrows, bncols, bnvals,
131 cnrows, cncols, cnvals,
132 t, 1e-6*((double) cnvals) / t) ;
133
134 //--------------------------------------------------------------------------
135 // write C to the output file
136 //--------------------------------------------------------------------------
137
138 // this would be faster and take less memory if GraphBLAS had a built-in
139 // write-to-file operation
140
141 I = (GrB_Index *) malloc ((cnvals+1) * sizeof (GrB_Index)) ;
142 J = (GrB_Index *) malloc ((cnvals+1) * sizeof (GrB_Index)) ;
143 X = (double *) malloc ((cnvals+1) * sizeof (double )) ;
144 if (I == NULL || J == NULL || X == NULL)
145 {
146 fprintf (stderr, "out of memory\n") ;
147 FREE_ALL ;
148 exit (1) ;
149 }
150
151 OK (GrB_Matrix_extractTuples_FP64 (I, J, X, &cnvals, C)) ;
152
153 for (int64_t k = 0 ; k < cnvals ; k++)
154 {
155 fprintf (Cfile, "%" PRIu64 "\t%" PRIu64 "\t%.17g\n", 1 + I [k], 1 + J [k], X [k]) ;
156 }
157
158 FREE_ALL ;
159 return (0) ;
160 }
161
162