in flex/engines/graph_db/runtime/common/operators/retrieve/path_expand.cc [406:539]
static bool single_source_single_dest_shortest_path_impl(
const GraphReadInterface& graph, const ShortestPathParams& params,
vid_t src, vid_t dst, std::vector<vid_t>& path) {
std::queue<vid_t> q1;
std::queue<vid_t> q2;
std::queue<vid_t> tmp;
label_t v_label = params.labels[0].src_label;
label_t e_label = params.labels[0].edge_label;
auto vertices = graph.GetVertexSet(v_label);
GraphReadInterface::vertex_array_t<int> pre(vertices, -1);
GraphReadInterface::vertex_array_t<int> dis(vertices, 0);
q1.push(src);
dis[src] = 1;
q2.push(dst);
dis[dst] = -1;
while (true) {
if (q1.size() <= q2.size()) {
if (q1.empty()) {
break;
}
while (!q1.empty()) {
int x = q1.front();
if (dis[x] >= params.hop_upper + 1) {
return false;
}
q1.pop();
auto oe_iter = graph.GetOutEdgeIterator(v_label, x, v_label, e_label);
while (oe_iter.IsValid()) {
int y = oe_iter.GetNeighbor();
if (dis[y] == 0) {
dis[y] = dis[x] + 1;
tmp.push(y);
pre[y] = x;
} else if (dis[y] < 0) {
while (x != -1) {
path.emplace_back(x);
x = pre[x];
}
std::reverse(path.begin(), path.end());
while (y != -1) {
path.emplace_back(y);
y = pre[y];
}
int len = path.size() - 1;
return len >= params.hop_lower && len < params.hop_upper;
}
oe_iter.Next();
}
auto ie_iter = graph.GetInEdgeIterator(v_label, x, v_label, e_label);
while (ie_iter.IsValid()) {
int y = ie_iter.GetNeighbor();
if (dis[y] == 0) {
dis[y] = dis[x] + 1;
tmp.push(y);
pre[y] = x;
} else if (dis[y] < 0) {
while (x != -1) {
path.emplace_back(x);
x = pre[x];
}
std::reverse(path.begin(), path.end());
while (y != -1) {
path.emplace_back(y);
y = pre[y];
}
int len = path.size() - 1;
return len >= params.hop_lower && len < params.hop_upper;
}
ie_iter.Next();
}
}
std::swap(q1, tmp);
} else {
if (q2.empty()) {
break;
}
while (!q2.empty()) {
int x = q2.front();
if (dis[x] <= -params.hop_upper - 1) {
return false;
}
q2.pop();
auto oe_iter = graph.GetOutEdgeIterator(v_label, x, v_label, e_label);
while (oe_iter.IsValid()) {
int y = oe_iter.GetNeighbor();
if (dis[y] == 0) {
dis[y] = dis[x] - 1;
tmp.push(y);
pre[y] = x;
} else if (dis[y] > 0) {
while (y != -1) {
path.emplace_back(y);
y = pre[y];
}
std::reverse(path.begin(), path.end());
while (x != -1) {
path.emplace_back(x);
x = pre[x];
}
int len = path.size() - 1;
return len >= params.hop_lower && len < params.hop_upper;
}
oe_iter.Next();
}
auto ie_iter = graph.GetInEdgeIterator(v_label, x, v_label, e_label);
while (ie_iter.IsValid()) {
int y = ie_iter.GetNeighbor();
if (dis[y] == 0) {
dis[y] = dis[x] - 1;
tmp.push(y);
pre[y] = x;
} else if (dis[y] > 0) {
while (y != -1) {
path.emplace_back(y);
y = pre[y];
}
std::reverse(path.begin(), path.end());
while (x != -1) {
path.emplace_back(x);
x = pre[x];
}
int len = path.size() - 1;
return len >= params.hop_lower && len < params.hop_upper;
}
ie_iter.Next();
}
}
std::swap(q2, tmp);
}
}
return false;
}