MCPcopy Create free account
hub / github.com/RedisGraph/RedisGraph / _AllPathsCtx_NextPath

Function _AllPathsCtx_NextPath

src/algorithms/all_paths.c:234–289  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

232}
233
234static Path *_AllPathsCtx_NextPath(AllPathsCtx *ctx) {
235 // As long as path is not empty OR there are neighbors to traverse.
236 while(Path_NodeCount(ctx->path) || _AllPathsCtx_LevelNotEmpty(ctx, 0)) {
237 uint32_t depth = Path_NodeCount(ctx->path);
238
239 // Can we advance?
240 if(_AllPathsCtx_LevelNotEmpty(ctx, depth)) {
241 // Get a new frontier.
242 LevelConnection frontierConnection = array_pop(ctx->levels[depth]);
243 Node frontierNode = frontierConnection.node;
244
245 /* See if frontier is already on path,
246 * it is OK for a path to contain an entity twice,
247 * such as in the case of a cycle, but in such case we
248 * won't expand frontier.
249 * i.e. closing a cycle and continuing traversal. */
250 bool frontierAlreadyOnPath = Path_ContainsNode(ctx->path, &frontierNode);
251
252 // Add frontier to path.
253 Path_AppendNode(ctx->path, frontierNode);
254
255 /* If depth is 0 this is the source node, there is no leading edge to it.
256 * For depth > 0 for each frontier node, there is a leading edge. */
257 if(depth > 0) Path_AppendEdge(ctx->path, frontierConnection.edge);
258
259 // Update path depth.
260 depth++;
261
262 /* Introduce neighbors only if path depth < maximum path length.
263 * and frontier wasn't already expanded. */
264 if(depth < ctx->maxLen && !frontierAlreadyOnPath) {
265 addNeighbors(ctx, &frontierConnection, depth, ctx->dir);
266 }
267
268 // See if we can return path.
269 /* TODO Note that further calls to this function will continue to operate on
270 * this path, so it is essential that the caller does not modify it (or creates
271 * a copy beforehand). If future features like an algorithm API use this routine,
272 * they should either be responsible for memory safety or a memory-safe boolean/routine
273 * should be offered. */
274 if(depth >= ctx->minLen && depth <= ctx->maxLen) {
275 if(ctx->dst != NULL) {
276 Node dst = Path_Head(ctx->path);
277 if(ENTITY_GET_ID(ctx->dst) != ENTITY_GET_ID(&dst)) continue;
278 }
279 return ctx->path;
280 }
281 } else {
282 // No way to advance, backtrack.
283 Path_PopNode(ctx->path);
284 if(Path_EdgeCount(ctx->path)) Path_PopEdge(ctx->path);
285 }
286 }
287 // Couldn't find a path.
288 return NULL;
289}
290
291Path *AllPathsCtx_NextPath(AllPathsCtx *ctx) {

Callers 1

AllPathsCtx_NextPathFunction · 0.85

Calls 10

Path_NodeCountFunction · 0.85
Path_ContainsNodeFunction · 0.85
Path_AppendNodeFunction · 0.85
Path_AppendEdgeFunction · 0.85
Path_HeadFunction · 0.85
Path_PopNodeFunction · 0.85
Path_EdgeCountFunction · 0.85
Path_PopEdgeFunction · 0.85
addNeighborsFunction · 0.70

Tested by

no test coverage detected