Skip to content

Commit 162b6c1

Browse files
committed
new algorithm
1 parent 0268446 commit 162b6c1

File tree

2 files changed

+122
-54
lines changed

2 files changed

+122
-54
lines changed

src/graph/executor/algo/MultiShortestPathExecutor.cpp

+114-49
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,17 @@ folly::Future<Status> MultiShortestPathExecutor::execute() {
3939
})
4040
.thenValue([this](auto&& resp) {
4141
UNUSED(resp);
42-
preLeftPaths_.swap(leftPaths_);
43-
preRightPaths_.swap(rightPaths_);
44-
leftPaths_.clear();
45-
rightPaths_.clear();
42+
preRightPaths_ = rightPaths_;
43+
// update history
44+
for (auto& iter : leftPaths_) {
45+
historyLeftPaths_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
46+
std::make_move_iterator(iter.second.end()));
47+
}
48+
for (auto& iter : rightPaths_) {
49+
historyRightPaths_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
50+
std::make_move_iterator(iter.second.end()));
51+
}
52+
4653
step_++;
4754
DataSet ds;
4855
ds.colNames = pathNode_->colNames();
@@ -58,7 +65,8 @@ void MultiShortestPathExecutor::init() {
5865
for (; rIter->valid(); rIter->next()) {
5966
auto& vid = rIter->getColumn(0);
6067
if (rightVids.emplace(vid).second) {
61-
preRightPaths_[vid].push_back({Path(Vertex(vid, {}), {})});
68+
std::vector<Path> tmp({Path(Vertex(vid, {}), {})});
69+
preRightPaths_[vid].emplace(vid, std::move(tmp));
6270
}
6371
}
6472

@@ -70,12 +78,24 @@ void MultiShortestPathExecutor::init() {
7078
for (const auto& leftVid : leftVids) {
7179
for (const auto& rightVid : rightVids) {
7280
if (leftVid != rightVid) {
73-
terminationMap_.emplace(std::make_pair(leftVid, rightVid), true);
81+
terminationMap_.emplace(leftVid, std::make_pair(rightVid, true));
7482
}
7583
}
7684
}
7785
}
7886

87+
std::vector<Path> MultiShortestPathExecutor::createPaths(const std::vector<Path>& paths,
88+
const Edge& edge) {
89+
std::vector<Path> newPaths;
90+
newPaths.reserve(paths.size());
91+
for (const auto& p : paths) {
92+
Path path = p;
93+
path.steps.emplace_back(Step(Vertex(edge.dst, {}), edge.type, edge.name, edge.ranking, {}));
94+
newPaths.emplace_back(std::move(path));
95+
}
96+
return newPaths;
97+
}
98+
7999
Status MultiShortestPathExecutor::buildPath(bool reverse) {
80100
auto iter = reverse ? ectx_->getResult(pathNode_->rightInputVar()).iter()
81101
: ectx_->getResult(pathNode_->leftInputVar()).iter();
@@ -96,10 +116,25 @@ Status MultiShortestPathExecutor::buildPath(bool reverse) {
96116
Path path;
97117
path.src = Vertex(src, {});
98118
path.steps.emplace_back(Step(Vertex(dst, {}), edge.type, edge.name, edge.ranking, {}));
99-
currentPaths[dst].emplace_back(std::move(path));
119+
auto foundDst = currentPaths.find(dst);
120+
if (foundDst != currentPaths.end()) {
121+
auto foundSrc = foundDst->second.find(src);
122+
if (foundSrc != foundDst->second.end()) {
123+
// same <src, dst>, different edge type or rank
124+
foundSrc->second.emplace_back(std::move(path));
125+
} else {
126+
std::vector<Path> tmp({std::move(path)});
127+
foundDst->second.emplace(src, std::move(tmp));
128+
}
129+
} else {
130+
std::vector<Path> tmp({std::move(path)});
131+
currentPaths[dst].emplace(src, std::move(tmp));
132+
}
133+
std::vector<Path> start({Path(Vertex(src, {}), {})});
134+
currentPaths[src].emplace(src, std::move(start));
100135
}
101136
} else {
102-
auto& historyPaths = reverse ? preRightPaths_ : preLeftPaths_;
137+
auto& historyPaths = reverse ? historyRightPaths_ : historyLeftPaths_;
103138
for (; iter->valid(); iter->next()) {
104139
auto edgeVal = iter->getEdge();
105140
if (UNLIKELY(!edgeVal.isEdge())) {
@@ -108,16 +143,59 @@ Status MultiShortestPathExecutor::buildPath(bool reverse) {
108143
auto& edge = edgeVal.getEdge();
109144
auto& src = edge.src;
110145
auto& dst = edge.dst;
111-
for (const auto& histPath : historyPaths[src]) {
112-
Path path = histPath;
113-
path.steps.emplace_back(Step(Vertex(dst, {}), edge.type, edge.name, edge.ranking, {}));
114-
if (path.hasDuplicateVertices()) {
115-
continue;
146+
auto& prePaths = historyPaths[src];
147+
148+
auto foundHistDst = historyPaths.find(dst);
149+
if (foundHistDst == historyPaths.end()) {
150+
// dst not in history
151+
auto foundDst = currentPaths.find(dst);
152+
if (foundDst == currentPaths.end()) {
153+
// dst not in current, new edge
154+
for (const auto& prePath : prePaths) {
155+
currentPaths[dst].emplace(prePath.first, createPaths(prePath.second, edge));
156+
}
157+
} else {
158+
// dst in current
159+
for (const auto& prePath : prePaths) {
160+
auto newPaths = createPaths(prePath.second, edge);
161+
auto foundSrc = foundDst->second.find(prePath.first);
162+
if (foundSrc == foundDst->second.end()) {
163+
foundDst->second.emplace(prePath.first, std::move(newPaths));
164+
} else {
165+
foundSrc->second.insert(foundSrc->second.begin(),
166+
std::make_move_iterator(newPaths.begin()),
167+
std::make_move_iterator(newPaths.end()));
168+
}
169+
}
170+
}
171+
} else {
172+
// dst in history
173+
auto& historyDstPaths = foundHistDst->second;
174+
for (const auto& prePath : prePaths) {
175+
if (historyDstPaths.find(prePath.first) != historyDstPaths.end()) {
176+
// loop: a->b->c->a or a->b->c->b,
177+
// filter out path that with duplicate vertex or have already been found before
178+
continue;
179+
}
180+
auto foundDst = currentPaths.find(dst);
181+
if (foundDst == currentPaths.end()) {
182+
currentPaths[dst].emplace(prePath.first, createPaths(prePath.second, edge));
183+
} else {
184+
auto newPaths = createPaths(prePath.second, edge);
185+
auto foundSrc = foundDst->second.find(prePath.first);
186+
if (foundSrc == foundDst->second.end()) {
187+
foundDst->second.emplace(prePath.first, std::move(newPaths));
188+
} else {
189+
foundSrc->second.insert(foundSrc->second.begin(),
190+
std::make_move_iterator(newPaths.begin()),
191+
std::make_move_iterator(newPaths.end()));
192+
}
193+
}
116194
}
117-
currentPaths[dst].emplace_back(std::move(path));
118195
}
119196
}
120197
}
198+
121199
// set nextVid
122200
const auto& nextVidVar = reverse ? pathNode_->rightVidVar() : pathNode_->leftVidVar();
123201
setNextStepVid(currentPaths, nextVidVar);
@@ -126,46 +204,33 @@ Status MultiShortestPathExecutor::buildPath(bool reverse) {
126204

127205
DataSet MultiShortestPathExecutor::doConjunct(
128206
const std::vector<std::pair<Interims::iterator, Interims::iterator>>& iters) {
207+
auto buildPaths =
208+
[](const std::vector<Path>& leftPaths, const std::vector<Path>& rightPaths, DataSet& ds) {
209+
for (const auto& leftPath : leftPaths) {
210+
for (const auto& rightPath : rightPaths) {
211+
auto forwardPath = leftPath;
212+
auto backwardPath = rightPath;
213+
backwardPath.reverse();
214+
forwardPath.append(std::move(backwardPath));
215+
Row row;
216+
row.values.emplace_back(std::move(forwardPath));
217+
ds.rows.emplace_back(std::move(row));
218+
}
219+
}
220+
};
221+
129222
DataSet ds;
130223
for (const auto& iter : iters) {
131224
const auto& leftPaths = iter.first->second;
132225
const auto& rightPaths = iter.second->second;
133-
if (leftPaths.size() < rightPaths.size()) {
134-
for (const auto& leftPath : leftPaths) {
135-
const auto& srcVid = leftPath.src.vid;
136-
for (const auto& rightPath : rightPaths) {
137-
const auto& dstVid = rightPath.src.vid;
138-
auto found = terminationMap_.find({srcVid, dstVid});
139-
if (found == terminationMap_.end()) {
140-
continue;
141-
}
142-
auto forwardPath = leftPath;
143-
auto backwardPath = rightPath;
144-
backwardPath.reverse();
145-
forwardPath.append(std::move(backwardPath));
146-
Row row;
147-
row.values.emplace_back(std::move(forwardPath));
148-
ds.rows.emplace_back(std::move(row));
149-
found->second = false;
150-
}
151-
}
152-
} else {
226+
for (const auto& leftPath : leftPaths) {
227+
auto range = terminationMap_.equal_range(leftPath.first);
153228
for (const auto& rightPath : rightPaths) {
154-
const auto& dstVid = rightPath.src.vid;
155-
for (const auto& leftPath : leftPaths) {
156-
const auto& srcVid = leftPath.src.vid;
157-
auto found = terminationMap_.find({srcVid, dstVid});
158-
if (found == terminationMap_.end()) {
159-
continue;
229+
for (auto found = range.first; found != range.second; ++found) {
230+
if (found->second.first == rightPath.first) {
231+
buildPaths(leftPath.second, rightPath.second, ds);
232+
found->second.second = false;
160233
}
161-
auto forwardPath = leftPath;
162-
auto backwardPath = rightPath;
163-
backwardPath.reverse();
164-
forwardPath.append(std::move(backwardPath));
165-
Row row;
166-
row.values.emplace_back(std::move(forwardPath));
167-
ds.rows.emplace_back(std::move(row));
168-
found->second = false;
169234
}
170235
}
171236
}
@@ -228,7 +293,7 @@ folly::Future<bool> MultiShortestPathExecutor::conjunctPath(bool oddStep) {
228293
}
229294

230295
for (auto iter = terminationMap_.begin(); iter != terminationMap_.end();) {
231-
if (!iter->second) {
296+
if (!iter->second.second) {
232297
iter = terminationMap_.erase(iter);
233298
} else {
234299
++iter;

src/graph/executor/algo/MultiShortestPathExecutor.h

+8-5
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@ class MultiShortestPathExecutor final : public Executor {
5757
folly::Future<Status> execute() override;
5858

5959
private:
60-
// k: dst, v: paths to dst
61-
using Interims = std::unordered_map<Value, std::vector<Path>>;
60+
// key: dst, value: {key : src, value: paths}
61+
using Interims = std::unordered_map<Value, std::unordered_map<Value, std::vector<Path>>>;
6262

6363
void init();
64+
std::vector<Path> createPaths(const std::vector<Path>& paths, const Edge& edge);
6465
Status buildPath(bool reverse);
6566
folly::Future<bool> conjunctPath(bool oddStep);
6667
DataSet doConjunct(const std::vector<std::pair<Interims::iterator, Interims::iterator>>& iters);
@@ -70,11 +71,13 @@ class MultiShortestPathExecutor final : public Executor {
7071
const MultiShortestPath* pathNode_{nullptr};
7172
size_t step_{1};
7273
std::string terminationVar_;
73-
std::unordered_map<std::pair<Value, Value>, bool> terminationMap_;
74+
// {src, <dst, true>}
75+
std::unordered_multimap<Value, std::pair<Value, bool>> terminationMap_;
7476
Interims leftPaths_;
75-
Interims preLeftPaths_;
76-
Interims preRightPaths_;
7777
Interims rightPaths_;
78+
Interims preRightPaths_;
79+
Interims historyLeftPaths_;
80+
Interims historyRightPaths_;
7881
DataSet currentDs_;
7982
};
8083

0 commit comments

Comments
 (0)