graph_apis.cc 11.2 KB
Newer Older
1
2
3
4
5
/*!
 *  Copyright (c) 2018 by Contributors
 * \file graph/graph.cc
 * \brief DGL graph index APIs
 */
6
#include <dgl/packed_func_ext.h>
Minjie Wang's avatar
Minjie Wang committed
7
#include <dgl/graph.h>
8
#include <dgl/immutable_graph.h>
Minjie Wang's avatar
Minjie Wang committed
9
#include <dgl/graph_op.h>
Da Zheng's avatar
Da Zheng committed
10
#include <dgl/sampler.h>
11
#include <dgl/nodeflow.h>
Lingfan Yu's avatar
Lingfan Yu committed
12
#include "../c_api_common.h"
Minjie Wang's avatar
Minjie Wang committed
13

14
15
16
17
18
using dgl::runtime::DGLArgs;
using dgl::runtime::DGLArgValue;
using dgl::runtime::DGLRetValue;
using dgl::runtime::PackedFunc;
using dgl::runtime::NDArray;
Minjie Wang's avatar
Minjie Wang committed
19
20

namespace dgl {
Minjie Wang's avatar
Minjie Wang committed
21

Minjie Wang's avatar
Minjie Wang committed
22
namespace {
Minjie Wang's avatar
Minjie Wang committed
23
// Convert EdgeArray structure to PackedFunc.
24
25
template<class EdgeArray>
PackedFunc ConvertEdgeArrayToPackedFunc(const EdgeArray& ea) {
26
  auto body = [ea] (DGLArgs args, DGLRetValue* rv) {
Minjie Wang's avatar
Minjie Wang committed
27
      const int which = args[0];
28
      if (which == 0) {
Minjie Wang's avatar
Minjie Wang committed
29
30
31
32
33
34
35
36
37
38
39
40
        *rv = std::move(ea.src);
      } else if (which == 1) {
        *rv = std::move(ea.dst);
      } else if (which == 2) {
        *rv = std::move(ea.id);
      } else {
        LOG(FATAL) << "invalid choice";
      }
    };
  return PackedFunc(body);
}

41
42
43
44
45
46
47
48
49
50
51
52
53
// Convert CSRArray structure to PackedFunc.
PackedFunc ConvertAdjToPackedFunc(const std::vector<IdArray>& ea) {
  auto body = [ea] (DGLArgs args, DGLRetValue* rv) {
      const int which = args[0];
      if ((size_t) which < ea.size()) {
        *rv = std::move(ea[which]);
      } else {
        LOG(FATAL) << "invalid choice";
      }
    };
  return PackedFunc(body);
}

Minjie Wang's avatar
Minjie Wang committed
54
55
// Convert Subgraph structure to PackedFunc.
PackedFunc ConvertSubgraphToPackedFunc(const Subgraph& sg) {
56
  auto body = [sg] (DGLArgs args, DGLRetValue* rv) {
Minjie Wang's avatar
Minjie Wang committed
57
      const int which = args[0];
Minjie Wang's avatar
Minjie Wang committed
58
      if (which == 0) {
59
        *rv = GraphRef(sg.graph);
60
      } else if (which == 1) {
Minjie Wang's avatar
Minjie Wang committed
61
        *rv = std::move(sg.induced_vertices);
62
      } else if (which == 2) {
Minjie Wang's avatar
Minjie Wang committed
63
        *rv = std::move(sg.induced_edges);
64
65
66
      } else {
        LOG(FATAL) << "invalid choice";
      }
Minjie Wang's avatar
Minjie Wang committed
67
68
69
    };
  return PackedFunc(body);
}
Minjie Wang's avatar
Minjie Wang committed
70

Minjie Wang's avatar
Minjie Wang committed
71
}  // namespace
Minjie Wang's avatar
Minjie Wang committed
72

73
74
75
///////////////////////////// Graph API ///////////////////////////////////

DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphCreateMutable")
76
.set_body([] (DGLArgs args, DGLRetValue* rv) {
77
78
    bool multigraph = args[0];
    *rv = GraphRef(Graph::Create(multigraph));
Minjie Wang's avatar
Minjie Wang committed
79
  });
Minjie Wang's avatar
Minjie Wang committed
80

81

82
83
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphCreate")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
84
85
    const IdArray src_ids = args[0];
    const IdArray dst_ids = args[1];
86
87
88
    const int multigraph = args[2];
    const int64_t num_nodes = args[3];
    const bool readonly = args[4];
89
    if (readonly) {
90
      if (multigraph == kBoolUnknown) {
91
        *rv = GraphRef(ImmutableGraph::CreateFromCOO(num_nodes, src_ids, dst_ids));
92
      } else {
93
        *rv = GraphRef(ImmutableGraph::CreateFromCOO(num_nodes, src_ids, dst_ids, multigraph));
94
      }
95
    } else {
96
      CHECK_NE(multigraph, kBoolUnknown);
97
      *rv = GraphRef(Graph::CreateFromCOO(num_nodes, src_ids, dst_ids, multigraph));
98
    }
99
100
  });

101
102
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphCSRCreate")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
103
104
    const IdArray indptr = args[0];
    const IdArray indices = args[1];
105
    const std::string shared_mem_name = args[2];
106
    const int multigraph = args[3];
107
108
109
110
111
112
113
    const std::string edge_dir = args[4];

    IdArray edge_ids = IdArray::Empty({indices->shape[0]},
                                      DLDataType{kDLInt, 64, 1}, DLContext{kDLCPU, 0});
    int64_t *edge_data = static_cast<int64_t *>(edge_ids->data);
    for (size_t i = 0; i < edge_ids->shape[0]; i++)
      edge_data[i] = i;
114
115
    if (shared_mem_name.empty()) {
      if (multigraph == kBoolUnknown) {
116
        *rv = GraphRef(ImmutableGraph::CreateFromCSR(indptr, indices, edge_ids, edge_dir));
117
      } else {
118
119
        *rv = GraphRef(ImmutableGraph::CreateFromCSR(
            indptr, indices, edge_ids, multigraph, edge_dir));
120
121
122
      }
    } else {
      if (multigraph == kBoolUnknown) {
123
124
        *rv = GraphRef(ImmutableGraph::CreateFromCSR(
            indptr, indices, edge_ids, edge_dir, shared_mem_name));
125
      } else {
126
127
        *rv = GraphRef(ImmutableGraph::CreateFromCSR(indptr, indices, edge_ids,
            multigraph, edge_dir, shared_mem_name));
128
129
      }
    }
130
131
132
133
134
135
136
  });

DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphCSRCreateMMap")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
    const std::string shared_mem_name = args[0];
    const int64_t num_vertices = args[1];
    const int64_t num_edges = args[2];
137
    const bool multigraph = args[3];
138
    const std::string edge_dir = args[4];
139
    // TODO(minjie): how to know multigraph
140
    *rv = GraphRef(ImmutableGraph::CreateFromCSR(
141
      shared_mem_name, num_vertices, num_edges, multigraph, edge_dir));
Minjie Wang's avatar
Minjie Wang committed
142
  });
Minjie Wang's avatar
Minjie Wang committed
143

144
145
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphAddVertices")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
146
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
147
    uint64_t num_vertices = args[1];
148
    g->AddVertices(num_vertices);
Minjie Wang's avatar
Minjie Wang committed
149
  });
Minjie Wang's avatar
Minjie Wang committed
150

151
152
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphAddEdge")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
153
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
154
155
    const dgl_id_t src = args[1];
    const dgl_id_t dst = args[2];
156
    g->AddEdge(src, dst);
Minjie Wang's avatar
Minjie Wang committed
157
  });
Minjie Wang's avatar
Minjie Wang committed
158

159
160
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphAddEdges")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
161
    GraphRef g = args[0];
162
163
    const IdArray src = args[1];
    const IdArray dst = args[2];
164
    g->AddEdges(src, dst);
Minjie Wang's avatar
Minjie Wang committed
165
166
  });

167
168
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphClear")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
169
170
    GraphRef g = args[0];
    g->Clear();
Minjie Wang's avatar
Minjie Wang committed
171
  });
Minjie Wang's avatar
Minjie Wang committed
172

173
174
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphIsMultigraph")
.set_body([] (DGLArgs args, DGLRetValue *rv) {
175
176
    GraphRef g = args[0];
    *rv = g->IsMultigraph();
177
178
  });

179
180
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphIsReadonly")
.set_body([] (DGLArgs args, DGLRetValue *rv) {
181
182
    GraphRef g = args[0];
    *rv = g->IsReadonly();
183
184
  });

185
186
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphNumVertices")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
187
188
    GraphRef g = args[0];
    *rv = static_cast<int64_t>(g->NumVertices());
Minjie Wang's avatar
Minjie Wang committed
189
  });
Minjie Wang's avatar
Minjie Wang committed
190

191
192
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphNumEdges")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
193
194
    GraphRef g = args[0];
    *rv = static_cast<int64_t>(g->NumEdges());
Minjie Wang's avatar
Minjie Wang committed
195
196
  });

197
198
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphHasVertex")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
199
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
200
    const dgl_id_t vid = args[1];
201
    *rv = g->HasVertex(vid);
Minjie Wang's avatar
Minjie Wang committed
202
203
  });

204
205
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphHasVertices")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
206
    GraphRef g = args[0];
207
    const IdArray vids = args[1];
208
    *rv = g->HasVertices(vids);
209
210
  });

211
212
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphHasEdgeBetween")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
213
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
214
215
    const dgl_id_t src = args[1];
    const dgl_id_t dst = args[2];
216
    *rv = g->HasEdgeBetween(src, dst);
Minjie Wang's avatar
Minjie Wang committed
217
218
  });

219
220
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphHasEdgesBetween")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
221
    GraphRef g = args[0];
222
223
    const IdArray src = args[1];
    const IdArray dst = args[2];
224
    *rv = g->HasEdgesBetween(src, dst);
Minjie Wang's avatar
Minjie Wang committed
225
226
  });

227
228
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphPredecessors")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
229
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
230
231
    const dgl_id_t vid = args[1];
    const uint64_t radius = args[2];
232
    *rv = g->Predecessors(vid, radius);
Minjie Wang's avatar
Minjie Wang committed
233
234
  });

235
236
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphSuccessors")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
237
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
238
239
    const dgl_id_t vid = args[1];
    const uint64_t radius = args[2];
240
    *rv = g->Successors(vid, radius);
Minjie Wang's avatar
Minjie Wang committed
241
242
  });

243
244
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphEdgeId")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
245
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
246
247
    const dgl_id_t src = args[1];
    const dgl_id_t dst = args[2];
248
    *rv = g->EdgeId(src, dst);
Minjie Wang's avatar
Minjie Wang committed
249
250
  });

251
252
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphEdgeIds")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
253
    GraphRef g = args[0];
254
255
    const IdArray src = args[1];
    const IdArray dst = args[2];
256
    *rv = ConvertEdgeArrayToPackedFunc(g->EdgeIds(src, dst));
257
258
  });

259
260
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphFindEdges")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
261
    GraphRef g = args[0];
262
    const IdArray eids = args[1];
263
    *rv = ConvertEdgeArrayToPackedFunc(g->FindEdges(eids));
Minjie Wang's avatar
Minjie Wang committed
264
265
  });

266
267
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphInEdges_1")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
268
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
269
    const dgl_id_t vid = args[1];
270
    *rv = ConvertEdgeArrayToPackedFunc(g->InEdges(vid));
Minjie Wang's avatar
Minjie Wang committed
271
272
  });

273
274
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphInEdges_2")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
275
    GraphRef g = args[0];
276
    const IdArray vids = args[1];
277
    *rv = ConvertEdgeArrayToPackedFunc(g->InEdges(vids));
Minjie Wang's avatar
Minjie Wang committed
278
279
  });

280
281
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphOutEdges_1")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
282
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
283
    const dgl_id_t vid = args[1];
284
    *rv = ConvertEdgeArrayToPackedFunc(g->OutEdges(vid));
Minjie Wang's avatar
Minjie Wang committed
285
286
  });

287
288
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphOutEdges_2")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
289
    GraphRef g = args[0];
290
    const IdArray vids = args[1];
291
    *rv = ConvertEdgeArrayToPackedFunc(g->OutEdges(vids));
Minjie Wang's avatar
Minjie Wang committed
292
293
  });

294
295
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphEdges")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
296
    GraphRef g = args[0];
297
    std::string order = args[1];
298
    *rv = ConvertEdgeArrayToPackedFunc(g->Edges(order));
Minjie Wang's avatar
Minjie Wang committed
299
300
  });

301
302
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphInDegree")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
303
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
304
    const dgl_id_t vid = args[1];
305
    *rv = static_cast<int64_t>(g->InDegree(vid));
Minjie Wang's avatar
Minjie Wang committed
306
307
  });

308
309
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphInDegrees")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
310
    GraphRef g = args[0];
311
    const IdArray vids = args[1];
312
    *rv = g->InDegrees(vids);
Minjie Wang's avatar
Minjie Wang committed
313
314
  });

315
316
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphOutDegree")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
317
    GraphRef g = args[0];
Minjie Wang's avatar
Minjie Wang committed
318
    const dgl_id_t vid = args[1];
319
    *rv = static_cast<int64_t>(g->OutDegree(vid));
Minjie Wang's avatar
Minjie Wang committed
320
321
  });

322
323
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphOutDegrees")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
324
    GraphRef g = args[0];
325
    const IdArray vids = args[1];
326
    *rv = g->OutDegrees(vids);
Minjie Wang's avatar
Minjie Wang committed
327
  });
Minjie Wang's avatar
Minjie Wang committed
328

329
330
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphVertexSubgraph")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
331
    GraphRef g = args[0];
332
    const IdArray vids = args[1];
333
    *rv = ConvertSubgraphToPackedFunc(g->VertexSubgraph(vids));
Minjie Wang's avatar
Minjie Wang committed
334
335
  });

336
337
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphEdgeSubgraph")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
338
    GraphRef g = args[0];
339
    const IdArray eids = args[1];
340
    bool preserve_nodes = args[2];
341
    *rv = ConvertSubgraphToPackedFunc(g->EdgeSubgraph(eids, preserve_nodes));
GaiYu0's avatar
cpp lg  
GaiYu0 committed
342
  });
GaiYu0's avatar
GaiYu0 committed
343

344
345
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphGetAdj")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
346
    GraphRef g = args[0];
347
348
    bool transpose = args[1];
    std::string format = args[2];
349
    auto res = g->GetAdj(transpose, format);
350
351
352
    *rv = ConvertAdjToPackedFunc(res);
  });

353
354
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphContext")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
355
356
    GraphRef g = args[0];
    *rv = g->Context();
357
358
  });

359
360
DGL_REGISTER_GLOBAL("graph_index._CAPI_DGLGraphNumBits")
.set_body([] (DGLArgs args, DGLRetValue* rv) {
361
362
    GraphRef g = args[0];
    *rv = g->NumBits();
363
364
  });

Minjie Wang's avatar
Minjie Wang committed
365
}  // namespace dgl