"git@developer.sourcefind.cn:OpenDAS/ollama.git" did not exist on "1c0e092eadc9f56abd745d31ff5c57e91fddd45e"
traversal.cc 6.92 KB
Newer Older
1
2
3
4
5
6
/*!
 *  Copyright (c) 2020 by Contributors
 * \file array/cpu/traversal.cc
 * \brief Graph traversal implementation
 */

7
8
#include "./traversal.h"

9
#include <dgl/graph_traversal.h>
10

11
12
13
14
15
16
17
18
#include <algorithm>
#include <queue>

namespace dgl {
namespace aten {
namespace impl {
namespace {
// A utility view class to wrap a vector into a queue.
19
template <typename DType>
20
21
22
23
struct VectorQueueWrapper {
  std::vector<DType>* vec;
  size_t head = 0;

24
  explicit VectorQueueWrapper(std::vector<DType>* vec) : vec(vec) {}
25

26
  void push(const DType& elem) { vec->push_back(elem); }
27

28
  DType top() const { return vec->operator[](head); }
29

30
  void pop() { ++head; }
31

32
  bool empty() const { return head == vec->size(); }
33

34
  size_t size() const { return vec->size() - head; }
35
36
37
38
};

// Internal function to merge multiple traversal traces into one ndarray.
// It is similar to zip the vectors together.
39
40
template <typename DType>
IdArray MergeMultipleTraversals(const std::vector<std::vector<DType>>& traces) {
41
42
43
44
45
46
  int64_t max_len = 0, total_len = 0;
  for (size_t i = 0; i < traces.size(); ++i) {
    const int64_t tracelen = traces[i].size();
    max_len = std::max(max_len, tracelen);
    total_len += traces[i].size();
  }
47
48
49
  IdArray ret = IdArray::Empty(
      {total_len}, DGLDataType{kDGLInt, sizeof(DType) * 8, 1},
      DGLContext{kDGLCPU, 0});
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  DType* ret_data = static_cast<DType*>(ret->data);
  for (int64_t i = 0; i < max_len; ++i) {
    for (size_t j = 0; j < traces.size(); ++j) {
      const int64_t tracelen = traces[j].size();
      if (i >= tracelen) {
        continue;
      }
      *(ret_data++) = traces[j][i];
    }
  }
  return ret;
}

// Internal function to compute sections if multiple traversal traces
// are merged into one ndarray.
65
66
template <typename DType>
IdArray ComputeMergedSections(const std::vector<std::vector<DType>>& traces) {
67
68
69
70
71
  int64_t max_len = 0;
  for (size_t i = 0; i < traces.size(); ++i) {
    const int64_t tracelen = traces[i].size();
    max_len = std::max(max_len, tracelen);
  }
72
73
  IdArray ret = IdArray::Empty(
      {max_len}, DGLDataType{kDGLInt, 64, 1}, DGLContext{kDGLCPU, 0});
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  int64_t* ret_data = static_cast<int64_t*>(ret->data);
  for (int64_t i = 0; i < max_len; ++i) {
    int64_t sec_len = 0;
    for (size_t j = 0; j < traces.size(); ++j) {
      const int64_t tracelen = traces[j].size();
      if (i < tracelen) {
        ++sec_len;
      }
    }
    *(ret_data++) = sec_len;
  }
  return ret;
}

}  // namespace

90
template <DGLDeviceType XPU, typename IdType>
91
92
93
94
Frontiers BFSNodesFrontiers(const CSRMatrix& csr, IdArray source) {
  std::vector<IdType> ids;
  std::vector<int64_t> sections;
  VectorQueueWrapper<IdType> queue(&ids);
95
96
97
98
99
100
101
  auto visit = [&](const int64_t v) {};
  auto make_frontier = [&]() {
    if (!queue.empty()) {
      // do not push zero-length frontier
      sections.push_back(queue.size());
    }
  };
102
103
104
105
106
107
108
109
  BFSTraverseNodes<IdType>(csr, source, &queue, visit, make_frontier);

  Frontiers front;
  front.ids = VecToIdArray(ids, sizeof(IdType) * 8);
  front.sections = VecToIdArray(sections, sizeof(int64_t) * 8);
  return front;
}

110
111
112
113
template Frontiers BFSNodesFrontiers<kDGLCPU, int32_t>(
    const CSRMatrix&, IdArray);
template Frontiers BFSNodesFrontiers<kDGLCPU, int64_t>(
    const CSRMatrix&, IdArray);
114

115
template <DGLDeviceType XPU, typename IdType>
116
117
118
119
120
121
Frontiers BFSEdgesFrontiers(const CSRMatrix& csr, IdArray source) {
  std::vector<IdType> ids;
  std::vector<int64_t> sections;
  // NOTE: std::queue has no top() method.
  std::vector<IdType> nodes;
  VectorQueueWrapper<IdType> queue(&nodes);
122
  auto visit = [&](const IdType e) { ids.push_back(e); };
123
124
  bool first_frontier = true;
  auto make_frontier = [&] {
125
126
127
128
129
130
131
    if (first_frontier) {
      first_frontier = false;  // do not push the first section when doing edges
    } else if (!queue.empty()) {
      // do not push zero-length frontier
      sections.push_back(queue.size());
    }
  };
132
133
134
135
136
137
138
139
  BFSTraverseEdges<IdType>(csr, source, &queue, visit, make_frontier);

  Frontiers front;
  front.ids = VecToIdArray(ids, sizeof(IdType) * 8);
  front.sections = VecToIdArray(sections, sizeof(int64_t) * 8);
  return front;
}

140
141
142
143
template Frontiers BFSEdgesFrontiers<kDGLCPU, int32_t>(
    const CSRMatrix&, IdArray);
template Frontiers BFSEdgesFrontiers<kDGLCPU, int64_t>(
    const CSRMatrix&, IdArray);
144

145
template <DGLDeviceType XPU, typename IdType>
146
147
148
149
Frontiers TopologicalNodesFrontiers(const CSRMatrix& csr) {
  std::vector<IdType> ids;
  std::vector<int64_t> sections;
  VectorQueueWrapper<IdType> queue(&ids);
150
151
152
153
154
155
156
  auto visit = [&](const uint64_t v) {};
  auto make_frontier = [&]() {
    if (!queue.empty()) {
      // do not push zero-length frontier
      sections.push_back(queue.size());
    }
  };
157
158
159
160
161
162
163
164
  TopologicalNodes<IdType>(csr, &queue, visit, make_frontier);

  Frontiers front;
  front.ids = VecToIdArray(ids, sizeof(IdType) * 8);
  front.sections = VecToIdArray(sections, sizeof(int64_t) * 8);
  return front;
}

165
166
167
168
template Frontiers TopologicalNodesFrontiers<kDGLCPU, int32_t>(
    const CSRMatrix&);
template Frontiers TopologicalNodesFrontiers<kDGLCPU, int64_t>(
    const CSRMatrix&);
169

170
template <DGLDeviceType XPU, typename IdType>
171
172
173
174
175
176
Frontiers DGLDFSEdges(const CSRMatrix& csr, IdArray source) {
  const int64_t len = source->shape[0];
  const IdType* src_data = static_cast<IdType*>(source->data);
  std::vector<std::vector<IdType>> edges(len);

  for (int64_t i = 0; i < len; ++i) {
177
    auto visit = [&](IdType e, int tag) { edges[i].push_back(e); };
178
179
180
181
182
183
184
185
186
    DFSLabeledEdges<IdType>(csr, src_data[i], false, false, visit);
  }

  Frontiers front;
  front.ids = MergeMultipleTraversals(edges);
  front.sections = ComputeMergedSections(edges);
  return front;
}

187
188
template Frontiers DGLDFSEdges<kDGLCPU, int32_t>(const CSRMatrix&, IdArray);
template Frontiers DGLDFSEdges<kDGLCPU, int64_t>(const CSRMatrix&, IdArray);
189

190
template <DGLDeviceType XPU, typename IdType>
191
192
193
Frontiers DGLDFSLabeledEdges(
    const CSRMatrix& csr, IdArray source, const bool has_reverse_edge,
    const bool has_nontree_edge, const bool return_labels) {
194
195
196
197
198
199
200
201
202
203
  const int64_t len = source->shape[0];
  const IdType* src_data = static_cast<IdType*>(source->data);
  std::vector<std::vector<IdType>> edges(len);
  std::vector<std::vector<int64_t>> tags;

  if (return_labels) {
    tags.resize(len);
  }

  for (int64_t i = 0; i < len; ++i) {
204
    auto visit = [&](IdType e, int64_t tag) {
205
206
207
208
209
      edges[i].push_back(e);
      if (return_labels) {
        tags[i].push_back(tag);
      }
    };
210
211
    DFSLabeledEdges<IdType>(
        csr, src_data[i], has_reverse_edge, has_nontree_edge, visit);
212
213
214
215
216
217
218
219
220
221
222
223
  }

  Frontiers front;
  front.ids = MergeMultipleTraversals(edges);
  front.sections = ComputeMergedSections(edges);
  if (return_labels) {
    front.tags = MergeMultipleTraversals(tags);
  }

  return front;
}

224
225
226
227
template Frontiers DGLDFSLabeledEdges<kDGLCPU, int32_t>(
    const CSRMatrix&, IdArray, const bool, const bool, const bool);
template Frontiers DGLDFSLabeledEdges<kDGLCPU, int64_t>(
    const CSRMatrix&, IdArray, const bool, const bool, const bool);
228
229
230
231

}  // namespace impl
}  // namespace aten
}  // namespace dgl