-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathLAGraph.h
More file actions
2695 lines (2433 loc) · 109 KB
/
Copy pathLAGraph.h
File metadata and controls
2695 lines (2433 loc) · 109 KB
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//------------------------------------------------------------------------------
// LAGraph.h: user-visible include file for LAGraph
//------------------------------------------------------------------------------
// LAGraph, (c) 2019-2025 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
//------------------------------------------------------------------------------
// LAGraph is a package of graph algorithms based on GraphBLAS. GraphBLAS
// defines a set of sparse matrix operations on an extended algebra of
// semirings, using an almost unlimited variety of operators and types. When
// applied to sparse adjacency matrices, these algebraic operations are
// equivalent to computations on graphs. GraphBLAS provides a powerful and
// expressive framework creating graph algorithms based on the elegant
// mathematics of sparse matrix operations on a semiring.
// However, GraphBLAS itself does not have graph algorithms. The purpose of
// LAGraph is to provide a robust, easy-to-use high-performance library of
// graph algorithms that rely on GraphBLAS.
//------------------------------------------------------------------------------
#ifndef LAGRAPH_H
#define LAGRAPH_H
//==============================================================================
// LAGraph version
//==============================================================================
// See also the LAGraph_Version utility method, which returns these values.
// These definitions are derived from LAGraph/CMakeLists.txt.
#define LAGRAPH_DATE "Sept 8, 2025"
#define LAGRAPH_VERSION_MAJOR 1
#define LAGRAPH_VERSION_MINOR 2
#define LAGRAPH_VERSION_UPDATE 1
//==============================================================================
// include files and helper macros
//==============================================================================
// vanilla vs SuiteSparse:
#if !defined ( LAGRAPH_VANILLA )
// by default, set LAGRAPH_VANILLA to false
#define LAGRAPH_VANILLA 0
#endif
#if LAGRAPH_VANILLA
// SuiteSparse:GraphBLAS uses this #define to disable all GxB extensions.
// Other GraphBLAS implementations can ignore this #define:
#define GRAPHBLAS_VANILLA
#endif
#include <GraphBLAS.h>
#if defined ( _OPENMP )
#include <omp.h>
#endif
// LAGRAPH_MIN/MAX: suitable for integers, and non-NaN floating point
#define LAGRAPH_MIN(x,y) (((x) < (y)) ? (x) : (y))
#define LAGRAPH_MAX(x,y) (((x) > (y)) ? (x) : (y))
//==============================================================================
// GraphBLAS platform specifics
//==============================================================================
// GraphBLAS C API specification, OpenMP, and vanilla vs
// SuiteSparse:GraphBLAS GxB extensions.
#if ( GRB_VERSION < 2 )
#error "The GraphBLAS library must support the v2.0 C API Specification"
#endif
#if ( _MSC_VER && !__INTEL_COMPILER && LG_DLL )
#ifdef LG_LIBRARY
// compiling LAGraph itself, exporting symbols to user apps
#define LAGRAPH_PUBLIC __declspec ( dllexport )
#else
// compiling the user application, importing symbols from LAGraph
#define LAGRAPH_PUBLIC __declspec ( dllimport )
#endif
#else
// for other compilers
#define LAGRAPH_PUBLIC
#endif
#if defined ( __cplusplus )
// C++ does not have the restrict keyword
#define LAGRAPH_RESTRICT
#elif ( _MSC_VER && !__INTEL_COMPILER )
// Microsoft Visual Studio uses __restrict instead of restrict for C
#define LAGRAPH_RESTRICT __restrict
#else
// use the restrict keyword for ANSI C99 compilers
#define LAGRAPH_RESTRICT restrict
#endif
#if ( !LAGRAPH_VANILLA ) && defined ( GxB_SUITESPARSE_GRAPHBLAS )
// use SuiteSparse, and its GxB* extensions
#if GxB_IMPLEMENTATION < GxB_VERSION (9,0,0)
#error "If using SuiteSparse::GraphBLAS, version 9.0.0 or later is required"
#endif
#define LAGRAPH_SUITESPARSE 1
#else
// use any GraphBLAS library (possibly SuiteSparse) but with no GxB*
#define LAGRAPH_SUITESPARSE 0
#endif
// maximum length of the name of a GrB type, including the null-terminator
#if LAGRAPH_SUITESPARSE
#define LAGRAPH_MAX_NAME_LEN GxB_MAX_NAME_LEN
#else
#define LAGRAPH_MAX_NAME_LEN 128
#endif
//==============================================================================
// LAGraph error handling: return values and msg string
//==============================================================================
/**
* Nearly all LAGraph methods return an int to denote their status, and
* have a final string (msg) that captures any error messages.
*
* LAGraph has a single function that does not follow this rule.
* @sphinxref{LAGraph_WallClockTime} has no error handling mechanism (it
* returns a value of type double, and does not have an final msg string
* parameter.
*
* All other methods return an int to denote their status: zero if they are
* successful (which is the value of GrB_SUCCESS), negative on error, or
* positive for an informational value (such as GrB_NO_VALUE). Integers in the
* range -999 to 999 are reserved for GraphBLAS GrB_Info return values:
*
* \rst_star{
* successful results:
* - GrB_SUCCESS = 0 // all is well
* - GrB_NO_VALUE = 1 // A(i,j) requested but not there
*
* errors:
* - GrB_UNINITIALIZED_OBJECT = -1 // object has not been initialized
* - GrB_NULL_POINTER = -2 // input pointer is NULL
* - GrB_INVALID_VALUE = -3 // generic error; some value is bad
* - GrB_INVALID_INDEX = -4 // row or column index is out of bounds
* - GrB_DOMAIN_MISMATCH = -5 // object domains are not compatible
* - GrB_DIMENSION_MISMATCH = -6 // matrix dimensions do not match
* - GrB_OUTPUT_NOT_EMPTY = -7 // output matrix already has values
* - GrB_NOT_IMPLEMENTED = -8 // method not implemented
* - GrB_PANIC = -101 // unknown error
* - GrB_OUT_OF_MEMORY = -102 // out of memory
* - GrB_INSUFFICIENT_SPACE = -103, // output array not large enough
* - GrB_INVALID_OBJECT = -104 // object is corrupted
* - GrB_INDEX_OUT_OF_BOUNDS = -105 // row or col index out of bounds
* - GrB_EMPTY_OBJECT = -106 // an object does not contain a value
* }
* LAGraph returns any errors it receives from GraphBLAS, and also uses the
* GrB_* error codes in these cases:
* - GrB_INVALID_INDEX: if a source node id is out of range
* - GrB_INVALID_VALUE: if an enum to select an option is out of range
* - GrB_NOT_IMPLEMENTED: if a type is not supported, or when SuiteSparse
* GraphBLAS is required.
*
* Summary of return values for all LAGraph functions that return int:
* - GrB_SUCCESS if successful
* - a negative GrB_Info value on error (in range -999 to -1)
* - a positive GrB_Info value if successful but with extra information
* (in range 1 to 999)
* - -1999 to -1000: a common LAGraph-specific error, see list above
* - 1000 to 1999: if successful, with extra LAGraph-specific information
* - <= -2000: an LAGraph error specific to a particular LAGraph method
* - >= 2000: an LAGraph warning specific to a particular LAGraph method
*
* Many LAGraph methods share common error cases, described below. These
* return values are in the range -1000 to -1999. Return values of -2000 or
* greater may be used by specific LAGraph methods, which denote errors not in
* the following list:
* \rst_star{
* - LAGRAPH_INVALID_GRAPH (-1000):
* The input graph is invalid; the details are given in the error msg
* string returned by the method.
* - LAGRAPH_SYMMETRIC_STRUCTURE_REQUIRED (-1001):
* The method requires an undirected graph, or a directed graph with
* an adjacency matrix that is known to have a symmetric structure.
* LAGraph_Cached_IsSymmetricStructure can be used to determine this
* cached property.
* - LAGRAPH_IO_ERROR (-1002):
* A file input or output method failed, or an input file has an
* incorrect format that cannot be parsed.
* - LAGRAPH_NOT_CACHED (-1003):
* Some methods require one or more cached properties to be computed
* before calling them (AT, out_degree, or in_degree. Use
* LAGraph_Cached_AT, LAGraph_Cached_OutDegree, and/or
* LAGraph_Cached_InDegree to compute them.
* - LAGRAPH_NO_SELF_EDGES_ALLOWED (-1004):
* Some methods requires that the graph have no self edges, which
* correspond to the entries on the diagonal of the adjacency matrix.
* If the G->nself_edges cached property is nonzero or unknown, this
* error condition is returned. Use LAGraph_Cached_NSelfEdges to
* compute G->nself_edges, or LAGraph_DeleteSelfEdges to remove all
* diagonal entries from G->A.
* - LAGRAPH_CONVERGENCE_FAILURE (-1005):
* An iterative process failed to converge to a good solution.
* - LAGRAPH_CACHE_NOT_NEEDED (1000):
* This is a warning, not an error. It is returned by
* LAGraph_Cached_* methods when asked to compute cached properties
* that are not needed. These include G->AT and G->in_degree for an
* undirected graph.
* }
*/
#define LAGRAPH_RETURN_VALUES
#define LAGRAPH_INVALID_GRAPH (-1000)
#define LAGRAPH_SYMMETRIC_STRUCTURE_REQUIRED (-1001)
#define LAGRAPH_IO_ERROR (-1002)
#define LAGRAPH_NOT_CACHED (-1003)
#define LAGRAPH_NO_SELF_EDGES_ALLOWED (-1004)
#define LAGRAPH_CONVERGENCE_FAILURE (-1005)
#define LAGRAPH_CACHE_NOT_NEEDED ( 1000)
/**
* All LAGraph functions (except for @sphinxref{LAGraph_WallClockTime})
* have a final msg parameter that is a pointer to a user-allocated string in
* which an algorithm-specific error message can be returned. If msg is NULL,
* no error message is returned. This is not itself an error condition, it
* just indicates that the caller does not need the message returned. If the
* message string is provided but no error occurs, an empty string is returned.
*
* LAGRAPH_MSG_LEN is the minimum required length of a message string.
*
* For example, the following call computes the breadth-first-search of an
* LAGraph_Graph G, starting at a given source node. It returns a status of
* zero if it succeeds and a negative value on failure.
*
* GrB_Vector level, parent ;
* char msg [LAGRAPH_MSG_LEN] ;
* int status = LAGr_BreadthFirstSearch (&level, &parent, G, src, msg) ;
* if (status < 0)
* {
* printf ("status %d, error: %s\n", status, msg) ;
* ... take corrective action here ...
* }
*
* Error handling is simplified by the @sphinxref{LAGRAPH_TRY} / LAGRAPH_CATCH
* mechanism described below. For example, assuming the user application
* defines a single LAGRAPH_CATCH mechanism for all error handling, the
* above example would become:
*
* GrB_Vector level, parent ;
* char msg [LAGRAPH_MSG_LEN] ;
* #define LAGRAPH_CATCH(status) \
* { \
* printf ("status %d, error: %s\n", status, msg) ; \
* ... take corrective action here ... \
* }
* ...
* LAGRAPH_TRY (LAGr_BreadthFirstSearch (&level, &parent, G, src, msg)) ;
*
* The advantage of the second use case is that the error-handling block of
* code needs to be written only once.
*/
#define LAGRAPH_MSG_LEN 256
//------------------------------------------------------------------------------
// LAGRAPH_TRY: try an LAGraph method and check for errors
//------------------------------------------------------------------------------
/** LAGRAPH_TRY: try an LAGraph method and check for errors.
*
* In a robust application, the return values from each call to LAGraph and
* GraphBLAS should be checked, and corrective action should be taken if an
* error occurs. The LAGRAPH_TRY and @sphinxref{GRB_TRY} macros assist in this
* effort.
*
* LAGraph and GraphBLAS are written in C, and so they cannot rely on the
* try/catch mechanism of C++. To accomplish a similar goal, each LAGraph file
* must `#define` its own file-specific macro called LAGRAPH_CATCH. The typical
* usage of macro is to free any temporary matrices/vectors or workspace when
* an error occurs, and then "throw" the error by returning to the caller. A
* user application may also `#define LAGRAPH_CATCH` and use these macros.
* The LAGRAPH_CATCH macro takes a single argument, which is the return value
* from an LAGraph method.
*
* A typical example of a user function that calls LAGraph might define
* LAGRAPH_CATCH as follows. Suppose workvector is a GrB_vector used for
* computations internal to the mybfs function, and W is a (double *) space
* created by malloc.
*
* // an example user-defined LAGRAPH_CATCH macro, which prints the error
* // then frees any workspace or results, and returns to the caller:
* #define LAGRAPH_CATCH(status) \
* { \
* printf ("LAGraph error: (%d): file: %s, line: %d\n%s\n", \
* status, __FILE__, __LINE__, msg) ; \
* GrB_free (*parent) ; \
* GrB_free (workvector) ; \
* LAGraph_Free ((void **) &W, NULL) ; \
* return (status) ; \
* }
*
* // an example user function that uses LAGRAPH_TRY / LAGRAPH_CATCH
* int mybfs (LAGraph_Graph G, GrB_Vector *parent, int64_t src)
* {
* GrB_Vector workvector = NULL ;
* double *W = NULL ;
* char msg [LAGRAPH_MSG_LEN] ;
* (*parent) = NULL ;
* LAGRAPH_TRY (LAGr_BreadthFirstSearch (NULL, parent, G, src, true,
* msg)) ;
* // ...
* return (GrB_SUCCESS) ;
* }
*
* LAGRAPH_TRY is defined as follows:
*
* #define LAGRAPH_TRY(LAGraph_method) \
* { \
* int LG_status = LAGraph_method ; \
* if (LG_status < GrB_SUCCESS) \
* { \
* LAGRAPH_CATCH (LG_status) ; \
* } \
* }
*/
#define LAGRAPH_TRY(LAGraph_method) \
{ \
int LG_status = LAGraph_method ; \
if (LG_status < GrB_SUCCESS) \
{ \
LAGRAPH_CATCH (LG_status) ; \
} \
}
//------------------------------------------------------------------------------
// GRB_TRY: try a GraphBLAS method and check for errors
//------------------------------------------------------------------------------
/** GRB_TRY: LAGraph provides a similar functionality as @sphinxref{LAGRAPH_TRY}
* for calling GraphBLAS methods, with the GRB_TRY macro. GraphBLAS returns info
* = 0 (GrB_SUCCESS) or 1 (GrB_NO_VALUE) on success, and a value < 0 on failure.
* The user application must `#define GRB_CATCH` to use GRB_TRY.
*
* GraphBLAS and LAGraph both use the convention that negative values are
* errors, and the LAGraph_status is a superset of the GrB_Info enum. As a
* result, the user can define LAGRAPH_CATCH and GRB_CATCH as the same
* operation. The main difference between the two would be the error message
* string. For LAGraph, the string is the last parameter, and LAGRAPH_CATCH
* can optionally print it out. For GraphBLAS, the GrB_error mechanism can
* return a string.
*
* GRB_TRY is defined as follows:
*
* #define GRB_TRY(GrB_method) \
* { \
* GrB_Info LG_GrB_Info = GrB_method ; \
* if (LG_GrB_Info < GrB_SUCCESS) \
* { \
* GRB_CATCH (LG_GrB_Info) ; \
* } \
* }
*
*/
#define GRB_TRY(GrB_method) \
{ \
GrB_Info LG_GrB_Info = GrB_method ; \
if (LG_GrB_Info < GrB_SUCCESS) \
{ \
GRB_CATCH (LG_GrB_Info) ; \
} \
}
//==============================================================================
// for C++ applications:
//==============================================================================
#if defined ( __cplusplus )
extern "C"
{
#endif
//==============================================================================
// LAGraph memory management
//==============================================================================
// LAGraph provides wrappers for the malloc/calloc/realloc/free set of memory
// management functions, initialized by LAGraph_Init or LAGr_Init. By default,
// the following are pointers to the ANSI C11 malloc/calloc/realloc/free
// functions.
LAGRAPH_PUBLIC extern void * (* LAGraph_Malloc_function ) (size_t) ;
LAGRAPH_PUBLIC extern void * (* LAGraph_Calloc_function ) (size_t, size_t) ;
LAGRAPH_PUBLIC extern void * (* LAGraph_Realloc_function ) (void *, size_t) ;
LAGRAPH_PUBLIC extern void (* LAGraph_Free_function ) (void *) ;
//------------------------------------------------------------------------------
// LAGraph_Malloc: allocate a block of memory (wrapper for malloc)
//------------------------------------------------------------------------------
/** LAGraph_Malloc: allocates a block of memory. Uses the ANSI C11 malloc
* function if LAGraph_Init was used, or the user_malloc_function passed to
* LAGr_Init.
*
* @param[out] p handle to allocated memory.
* @param[in] nitems number of items to allocate, each of size size_of_item.
* @param[in] size_of_item bytes allocted = nitems*size_of_item.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_OUT_OF_MEMORY if out of memory.
* @retval GrB_NULL_POINTER if p is NULL on input.
*/
LAGRAPH_PUBLIC
int LAGraph_Malloc
(
// output:
void **p, // pointer to allocated block of memory
// input:
size_t nitems, // number of items
size_t size_of_item, // size of each item
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_Calloc: allocate a block of memory (wrapper for calloc)
//------------------------------------------------------------------------------
/** LAGraph_Calloc: allocates a block of memory and sets it to zero. Uses the
* ANSI C11 malloc and memset functions if LAGraph_Init was used or if NULL
* was passed to LAGr_Init for the user_calloc_function, or the non-NULL
* user_calloc_function passed to LAGr_Init otherwise.
*
* @param[out] p handle to allocated memory.
* @param[in] nitems number of items to allocate, each of size size_of_item.
* @param[in] size_of_item bytes allocted = nitems*size_of_item.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_OUT_OF_MEMORY if out of memory.
* @retval GrB_NULL_POINTER if p is NULL on input.
*/
LAGRAPH_PUBLIC
int LAGraph_Calloc
(
// output:
void **p, // pointer to allocated block of memory
// input:
size_t nitems, // number of items
size_t size_of_item, // size of each item
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_Realloc: reallocate a block of memory (wrapper for realloc)
//------------------------------------------------------------------------------
/** LAGraph_Realloc: reallocates a block of memory. Uses the ANSI C11 malloc,
* memcpy, and free functions if LAGraph_Init was used or if NULL was passed to
* LAGr_Init for the user_realloc_function, or the non-NULL
* user_realloc_function passed to LAGr_Init otherwise. Note that unlike the
* ANSI C11 realloc function, this function requires the old size of block to
* be provided on input (nitems_old). This size must be exact; behavior is
* undefined if the incorrect size is given. The value nitems_old*size_of_item
* must be the same as nitems*size_of_item when the block of memory was
* allocated by LAGraph_Malloc or LAGraph_Calloc, or equal to
* nitems_new*size_of_item from the last call to LAGraph_Realloc.
*
* @param[in,out] p handle to allocated memory.
* @param[in] nitems_new new number of items to allocate.
* @param[in] nitems_old prior number of items allocated.
* @param[in] size_of_item size of each item.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_OUT_OF_MEMORY if out of memory.
* @retval GrB_NULL_POINTER if p is NULL on input.
*/
LAGRAPH_PUBLIC
int LAGraph_Realloc
(
// input/output:
void **p, // old block to reallocate
// input:
size_t nitems_new, // new number of items in the object
size_t nitems_old, // old number of items in the object
size_t size_of_item, // size of each item
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_Free: free a block of memory (wrapper for free)
//------------------------------------------------------------------------------
/** LAGraph_Free: frees a block of memory. The block must have been previously
* allocated by LAGraph_Malloc or LAGraph_Calloc. If LAGraph_Malloc (&p, ...)
* is the pointer to the allocated block of memory, LAGraph_Free (&p, ...) is
* the method to free it. The parameter is passed as &p so that p can be set
* to NULL on return, to guard against double-free. LAGraph_Free does nothing
* if &p or p are NULL on input; this is not an error.
*
* @param[in,out] p handle to allocated memory.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS in all cases.
*/
LAGRAPH_PUBLIC
int LAGraph_Free // free a block of memory and set p to NULL
(
// input/output:
void **p, // pointer to object to free, does nothing if NULL
char *msg
) ;
//==============================================================================
// LAGraph data structures
//==============================================================================
// In addition to relying on underlying GraphBLAS objects (GrB_Matrix,
// GrB_Vector, GrB_Descriptor, ...), LAGraph adds the LAGraph_Graph. This
// object contains a representation of a graph and its associated data. Unlike
// the GrB_* objects, the LAGraph_Graph is not opaque.
// LAGRAPH_UNKNOWN is used for all scalars whose value is not known
#define LAGRAPH_UNKNOWN (-1)
//------------------------------------------------------------------------------
// LAGraph_Kind: the kind of a graph
//------------------------------------------------------------------------------
/** LAGraph_Kind: the kind of a graph. Currently, only two types of graphs are
* supported: undirected graphs and directed graphs. Edge weights are assumed
* to be present. Unweighted graphs can be represented by setting all entries
* present in the sparsity structure to the same value, typically 1.
* Additional types of graphs will be added in the future.
*/
typedef enum
{
LAGraph_ADJACENCY_UNDIRECTED = 0, ///< undirected graph.
///< G->A is square and symmetric; both upper and lower triangular parts
///< are present. A(i,j) is the edge (i,j). Results are undefined if
///< A is unsymmetric.
LAGraph_ADJACENCY_DIRECTED = 1, ///< directed graph.
///< G->A is square; A(i,j) is the edge (i,j).
// possible future kinds of graphs:
// LAGraph_ADJACENCY_UNDIRECTED_UNWEIGHTED
// LAGraph_ADJACENCY_DIRECTED_UNWEIGHTED
// LAGraph_ADJACENCY_UNDIRECTED_TRIL
// LAGraph_ADJACENCY_UNDIRECTED_TRIU
// LAGraph_BIPARTITE
// LAGraph_BIPARTITE_DIRECTED
// LAGraph_BIPARTITE_UNDIRECTED
// LAGraph_INCIDENCE_*
// LAGraph_MULTIGRAPH_*
// LAGraph_HYPERGRAPH
// LAGraph_HYPERGRAPH_DIRECTED
// ...
LAGraph_KIND_UNKNOWN = LAGRAPH_UNKNOWN ///< unknown kind of graph (-1).
}
LAGraph_Kind ;
//------------------------------------------------------------------------------
// LAGraph_Boolean: true, false, or unknown
//------------------------------------------------------------------------------
/** LAGraph_Boolean: a boolean value (true or false) or unknown (-1).
*/
typedef enum
{
LAGraph_FALSE = 0, ///< the Boolean value is known to be false.
LAGraph_TRUE = 1, ///< the Boolean value is known to be true.
LAGraph_BOOLEAN_UNKNOWN = LAGRAPH_UNKNOWN ///< Boolean value is unknown.
}
LAGraph_Boolean ;
//------------------------------------------------------------------------------
// LAGraph_State: value, bound, or unknown
//------------------------------------------------------------------------------
/** LAGraph_State describes the status of a cached property of a graph. If the
* cached property is computed in floating-point arithmetic, it may have been
* computed with roundoff error, but it may still be declared as "value" if the
* roundoff error is expected to be small, or if the cached property was
* computed as carefully as possible (to within reasonable roundoff error).
* The "bound" state indicates that the cached property is an upper or lower
* bound, depending on the particular cached property. If computed in
* floating-point arithmetic, an "upper bound" cached property may be actually
* slightly lower than the actual upper bound, because of floating-point
* roundoff.
*/
typedef enum
{
LAGraph_VALUE = 0, ///< cached property is a known value.
LAGraph_BOUND = 1, ///< cached property is a bound.
///< The bound is upper or lower, depending on the particular cached
///< property.
LAGraph_STATE_UNKNOWN = LAGRAPH_UNKNOWN, ///< the property is unknown.
}
LAGraph_State ;
//------------------------------------------------------------------------------
// LAGraph_Graph: the primary graph data structure of LAGraph
//------------------------------------------------------------------------------
/** LAGraph_Graph: a representation of a graph.
*
* The LAGraph_Graph G contains a GrB_Matrix G->A as its primary component.
* For graphs represented with adjacency matrices, A(i,j) denotes the edge
* (i,j). Unlike GrB_* objects in GraphBLAS, the LAGraph_Graph data structure
* is not opaque. User applications have full access to its contents.
*
* An LAGraph_Graph G contains two kinds of components:
* 1. Primary components of the graph, which fully define the graph.
* 2. Cached properties of the graph, which can be recreated any time.
*/
// (1) primary components:
// A the adjacency matrix of the graph
// kind the kind of graph (undirected, directed, bipartite, ...)
// (2) cached properties:
// AT AT = A'
// out_degree out_degree(i) = # of entries in A(i,:)
// in_degree in_degree(j) = # of entries in A(:,j)
// is_symmetric_structure: true if the structure of A is symmetric
// nself_edges the number of entries on the diagonal of A
// emin minimum edge weight
// emax maximum edge weight
struct LAGraph_Graph_struct
{
//--------------------------------------------------------------------------
// primary components of the graph
//--------------------------------------------------------------------------
/** @name Primary Components */
//@{
GrB_Matrix A ; ///< the adjacency matrix of the graph
LAGraph_Kind kind ; ///< the kind of graph
//@}
// possible future components:
// multigraph ..
// GrB_Matrix *Amult ; // array of size nmatrices
// int nmatrices ;
// GrB_Vector NodeWeights ;
//--------------------------------------------------------------------------
// cached properties of the graph
//--------------------------------------------------------------------------
/** @name Cached Properties
*
* All of these components may be deleted or set to 'unknown' at any time.
* For example, if AT is NULL, then the transpose of A has not been
* computed. A scalar cached property of type LAGraph_Boolean would be set
* to LAGRAPH_UNKNOWN to denote that its value is unknown.
*
* If present, the cached properties must be valid and accurate. If the
* graph changes, these cached properties can either be recomputed or
* deleted to denote the fact that they are unknown. This choice is up to
* individual LAGraph methods and utilities.
*
* LAGraph methods can set non-scalar cached properties only if they are
* constructing the graph. They cannot modify them or create them if the
* graph is declared as a read-only object in the parameter list of the
* method.
*/
//@{
GrB_Matrix AT ; ///< AT = A', the transpose of A, with the same type.
GrB_Vector out_degree ; ///< a GrB_INT64 vector of length m, if A is m-by-n.
///< where out_degree(i) is the number of entries in A(i,:). If
///< out_degree is sparse and the entry out_degree(i) is not present,
///< then it is assumed to be zero.
GrB_Vector in_degree ; ///< a GrB_INT64 vector of length n, if A is m-by-n.
///< where in_degree(j) is the number of entries in A(:,j). If
///< in_degree is sparse and the entry in_degree(j) is not present,
///< then it is assumed to be zero. If A is known to have a
///< symmetric structure, the convention is that the degree is held
///< in G->out_degree, and in G->in_degree is left as NULL.
// FUTURE: If G is held as an incidence matrix, then G->A might be
// rectangular, in the future, but the graph G may have a symmetric
// structure anyway.
LAGraph_Boolean is_symmetric_structure ; ///< For an undirected
///< graph, this cached property will always be implicitly true and
///< can be ignored. The matrix A for a directed weighted graph
///< will typically be unsymmetric, but might have a symmetric
///< structure. In that case, this scalar cached property can be
///< set to true. By default, this cached property is set to
///< LAGRAPH_UNKNOWN.
int64_t nself_edges ; ///< number of entries on the diagonal of A, or
///< LAGRAPH_UNKNOWN if unknown. For the adjacency matrix of a
///< directed or undirected graph, this is the number of self-edges
///< in the graph.
GrB_Scalar emin ; ///< minimum edge weight: value, lower bound, or unknown
LAGraph_State emin_state ;
///< - VALUE: emin is equal to the smallest entry, min(G->A)
///< - BOUND: emin <= min(G->A)
///< - UNKNOWN: emin is unknown
GrB_Scalar emax ; ///< maximum edge weight: value, upper bound, or unknown
LAGraph_State emax_state ;
///< - VALUE: emax is equal to the largest entry, max(G->A)
///< - BOUND: emax >= max(G->A)
///< - UNKNOWN: emax is unknown
//@}
// FUTURE: possible future cached properties:
// Some algorithms may want to know if the graph has any edge weights
// exactly equal to zero. In some cases, this can be inferred from the
// emin/emax bounds, or it can be indicated via the following cached
// property:
// LAGraph_Boolean nonzero ; // If true, then all entries in
// G->A are known to be nonzero. If false, G->A may contain
// entries in its structure that are identically equal to zero. If
// unknown, then G->A may or may not have entries equal to zero.
// other edge weight metrics: median, standard deviation.... Might be
// useful for computing Delta for a Basic SSSP.
// GrB_Vector row_sum, col_sum ;
// row_sum(i) = sum(abs(A(i,:))), regardless of kind
// col_sum(j) = sum(abs(A(:,j))), regardless of kind
// LAGraph_Boolean connected ; // true if G is a connected graph
} ;
typedef struct LAGraph_Graph_struct *LAGraph_Graph ;
//==============================================================================
// LAGraph utilities
//==============================================================================
//------------------------------------------------------------------------------
// LAGraph_Init: start GraphBLAS and LAGraph
//------------------------------------------------------------------------------
/** LAGraph_Init: initializes GraphBLAS and LAGraph. This method must be
* called before calling any other GrB* or LAGraph* method. It initializes
* GraphBLAS with GrB_init and then performs LAGraph-specific initializations.
* In particular, the LAGraph semirings listed below are created. GrB_init can
* also safely be called before calling @sphinxref{LAGr_Init} or LAGraph_Init.
*
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_INVALID_VALUE if LAGraph_Init or LAGr_Init has already been
* called by the user application.
* @returns any GraphBLAS errors that may have been encountered.
*/
LAGRAPH_PUBLIC
int LAGraph_Init
(
char *msg
) ;
// FUTURE: include these as built-in semirings in v2.1 C API, Table 3.9:
// LAGraph semirings, created by LAGraph_Init or LAGr_Init:
LAGRAPH_PUBLIC extern GrB_Semiring
// LAGraph_plus_first_T: using the GrB_PLUS_MONOID_T monoid and the
// corresponding GrB_FIRST_T multiplicative operator.
LAGraph_plus_first_int8 ,
LAGraph_plus_first_int16 ,
LAGraph_plus_first_int32 ,
LAGraph_plus_first_int64 ,
LAGraph_plus_first_uint8 ,
LAGraph_plus_first_uint16 ,
LAGraph_plus_first_uint32 ,
LAGraph_plus_first_uint64 ,
LAGraph_plus_first_fp32 ,
LAGraph_plus_first_fp64 ,
// LAGraph_plus_second_T: using the GrB_PLUS_MONOID_T monoid and the
// corresponding GrB_SECOND_T multiplicative operator.
LAGraph_plus_second_int8 ,
LAGraph_plus_second_int16 ,
LAGraph_plus_second_int32 ,
LAGraph_plus_second_int64 ,
LAGraph_plus_second_uint8 ,
LAGraph_plus_second_uint16 ,
LAGraph_plus_second_uint32 ,
LAGraph_plus_second_uint64 ,
LAGraph_plus_second_fp32 ,
LAGraph_plus_second_fp64 ,
// LAGraph_plus_one_T: using the GrB_PLUS_MONOID_T monoid and the
// corresponding GrB_ONEB_T multiplicative operator.
LAGraph_plus_one_int8 ,
LAGraph_plus_one_int16 ,
LAGraph_plus_one_int32 ,
LAGraph_plus_one_int64 ,
LAGraph_plus_one_uint8 ,
LAGraph_plus_one_uint16 ,
LAGraph_plus_one_uint32 ,
LAGraph_plus_one_uint64 ,
LAGraph_plus_one_fp32 ,
LAGraph_plus_one_fp64 ,
// LAGraph_any_one_T: using the GrB_MIN_MONOID_T for non-boolean types or
// GrB_LOR_MONOID_BOOL for boolean, and the GrB_ONEB_T multiplicative op.
// These semirings are very useful for unweighted graphs, or for algorithms
// that operate only on the sparsity structure of unweighted graphs.
LAGraph_any_one_bool , // (or, true) semiring
LAGraph_any_one_int8 , // (min, 1) semiring
LAGraph_any_one_int16 ,
LAGraph_any_one_int32 ,
LAGraph_any_one_int64 ,
LAGraph_any_one_uint8 ,
LAGraph_any_one_uint16 ,
LAGraph_any_one_uint32 ,
LAGraph_any_one_uint64 ,
LAGraph_any_one_fp32 ,
LAGraph_any_one_fp64 ;
//------------------------------------------------------------------------------
// LAGraph_Version: determine the version of LAGraph
//------------------------------------------------------------------------------
/** LAGraph_Version: determines the version of LAGraph. The version number and
* date can also be obtained via compile-time constants from LAGraph.h.
* However, it is possible to compile a user application that includes one
* version of LAGraph.h and then links with another version of the LAGraph
* library later on, so the version number and date may differ from the
* compile-time constants.
*
* The LAGraph_Version method allows the library itself to be queried, after it
* is linked in with the user application.
*
* The version_number array is set to LAGRAPH_VERSION_MAJOR,
* LAGRAPH_VERSION_MINOR, and LAGRAPH_VERSION_UPDATE, in that order. The
* LAGRAPH_DATE string is copied into the user-provided version_date string,
* and is null-terminated.
*
* @param[out] version_number an array of size 3; with the major, minor,
* and update versions of LAGraph, in that order.
* @param[out] version_date an array of size >= LAGraph_MSG_LEN, returned
* with the date of this version of LAGraph.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_NULL_POINTER if version_number or version_date are NULL.
*/
LAGRAPH_PUBLIC
int LAGraph_Version
(
// output:
int version_number [3], // user-provided array of size 3
char *version_date, // user-provided array of size >= LAGRAPH_MSG_LEN
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_Finalize: finish LAGraph
//------------------------------------------------------------------------------
/** LAGraph_Finalize: finish LAGraph and GraphBLAS. Must be called as the last
* LAGraph method. It calls GrB_finalize and frees any LAGraph objects created
* by @sphinxref{LAGraph_Init} or @sphinxref{LAGr_Init}. After calling this
* method, no LAGraph or GraphBLAS methods may be used.
*
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @returns any GraphBLAS errors that may have been encountered.
*/
LAGRAPH_PUBLIC
int LAGraph_Finalize
(
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_New: create a new graph
//------------------------------------------------------------------------------
/** LAGraph_New: creates a new graph G. The cached properties G->AT,
* G->out_degree, and G->in_degree are set to NULL, and scalar cached
* properties are set to LAGRAPH_UNKNOWN.
*
* @param[out] G handle to the newly created graph, as &G.
* @param[in,out] A adjacency matrix. A is moved into G as G->A, and A
* itself is set to NULL to denote that is now a part of
* G. That is, { G->A = A ; A = NULL ; } is performed.
* When G is deleted, G->A is freed. If A is NULL, the
* graph is invalid until G->A is set.
* @param[in] kind the kind of graph to create. This may be
* LAGRAPH_UNKNOWN, which must then be revised later
* before the graph can be used.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_NULL_POINTER if G is null.
* @returns any GraphBLAS errors that may have been encountered.
*/
LAGRAPH_PUBLIC
int LAGraph_New
(
// output:
LAGraph_Graph *G, // the graph to create, NULL if failure
// input/output:
GrB_Matrix *A, // the adjacency matrix of the graph, may be NULL.
// input:
LAGraph_Kind kind, // the kind of graph.
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_Delete: free a graph and all its contents
//------------------------------------------------------------------------------
/** LAGraph_Delete: frees a graph G. The adjacency matrix G->A and the cached
* properties G->AT, G->out_degree, and G->in_degree are all freed.
*
* @param[in,out] G handle to the graph to be free. *G is NULL on output.
* To keep G->A while deleting the graph G, use:
* { A = G->A ; G->A = NULL ; LAGraph_Delete (&G, msg) ; }
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @returns any GraphBLAS errors that may have been encountered.
*/
LAGRAPH_PUBLIC
int LAGraph_Delete
(
// input/output:
LAGraph_Graph *G, // the graph to delete; G set to NULL on output.
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_DeleteCached: free any internal cached properties of a graph
//------------------------------------------------------------------------------
/** LAGraph_DeleteCached: frees all cached properies of a graph G. The graph is
* still valid. This method should be used if G->A changes, since such changes
* will normally invalidate G->AT, G->out_degree, and/or G->in_degree.
*
* @param[in,out] G handle to the graph to modified. The graph G remains
* valid on output, but with all cached properties freed.
* G may be NULL, in which case nothing is done.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @returns any GraphBLAS errors that may have been encountered.
*/
LAGRAPH_PUBLIC
int LAGraph_DeleteCached
(
// input/output:
LAGraph_Graph G, // G stays valid, only cached properties are freed
char *msg
) ;
//------------------------------------------------------------------------------
// LAGraph_Cached_AT: construct G->AT for a graph
//------------------------------------------------------------------------------
/** LAGraph_Cached_AT: constructs G->AT, the transpose of G->A. This matrix is
* required by some of the algorithms. Basic algorithms may construct G->AT if
* they require it. The matrix G->AT is then available for subsequent use. If
* G->A changes, G->AT should be freed and recomputed. If G->AT already
* exists, it is left unchanged (even if it is not equal to the transpose of
* G->A). As a result, if G->A changes, G->AT should be explictly freed.
*
* @param[in,out] G graph for which G->AT is computed.
* @param[in,out] msg any error messages.
*
* @retval GrB_SUCCESS if successful.
* @retval GrB_NULL_POINTER if G is NULL.