Quantcast
Channel: CodeChef Discuss - latest questions
Viewing all articles
Browse latest Browse all 39796

Cypher query to find paths through directed weighted graph to populate ordered list

$
0
0

Hi, I am new to Neo4j and am trying to query the following in Cypher:

Final output should be a list of nodes, sorted by ascending visitation order, after a run of n path iterations, each of which adds nodes on the list. The order of visitation sort depends on depth and edge cost. Because the final list represents a sequence of nodes you could also look at it as a path of paths.

Description

  • My graph has an initial starting node (START), is directional, of unknown size, and has weighted edges.

  • A node can only be added to the list once when it is first visited (e.g. when visiting a node, we compare to the final list and add if the node isn't on the list already).

  • Every edge can only be traveled once. Think of "burning" a bridge (spanning two nodes) behind you.

  • We can only visit the next adjacent, lowest-cost node.

  • There are two underlying hierarchies: depth (the closer to START the better and edge costs (the lower the cost incurred to reach the next adjacent node the better). Depth follows the alphabetical order in the example below. Cost properties are integers but are presented in the example as strings (e.g. "costs1" means edge cost = 1).

  • Each path starts with the starting node of least depth that is "available" (= possessing untraveled outbound edges). In the example below all edges emanating from START will have been exhausted at some point. Then we'll continue with A as starting node.

  • A path run is done when it cannot continue anymore (i.e. no available outbound edges to travel on)

  • We're done when the list contains y nodes, which may or may not represent a traversal.

Any ideas on how to tackle this in Cypher? (I chose Cypher because I assume it's the easiest way to solve this; feel free to correct this assumption)

Is there a way to get to the final list/path using an easier logic than what I came up with?

Example

Example Data (Neo4j console)

(Not sure why the console duplicates the graph when using share. The code is re-posted at the bottom)

  1. We start at START and travel along the lowest-cost edge available to arrive at A. --> A gets the #1 spot the list and the costs1 edge in START-[:costs1]->a gets eliminated because we've just used it.

  2. We’re on A. The lowest cost edge (costs1) circles back to START, which is a no-go, so we take this edge off the table as well and choose the next available lowest-cost edge (costs2), leading us to B. --> We output B to the list and eliminate the edge in a-[:costs2]->b.

  3. We're now on B. The lowest cost edge (costs1) circles back to START, which is a no-go, so we eliminate that edge as well. The next lowest-cost edge (costs2) leads us to C. --> We output C to the list and eliminate the just traveled edge between B and C.

  4. We're on C and continue from C over its lowest-cost relation on to G. --> We output G to the list and eliminate the edge in c-[:costs1]->g.

  5. We're on G and move on to E via g-[:costs1]->e. --> E goes on the list and the just traveled edge is eliminated.

  6. We're on E, which only has one relation with I. We incur the cost of 1 and travel on to I. --> I goes on the list and E's "costs1" edge gets eliminated.

  7. We're on I, which has no outbound edges and thus no adjacent nodes. Our path run ends and we return to START iterating the whole process with the edges that remain.

  8. We're on START. Its lowest available outbound edge is "cost3", leading us to C. --> C is already on the list, so we just eliminate the just traveled edge in START-[:costs3]->c and move on to the next available lowest-cost node, which is F. Note that now we've used up all edges emanating from START.

  9. We're on F, which leads us to J (cost =1) --> J goes on the list, the edge gets eliminated.

  10. We're on J, which leads us to L (cost = 1)--> L goes on the list, the edge gets eliminated.

  11. We're on L, which leads us to N (cost = 1)--> N goes on the list, the edge gets eliminated.

  12. We're on N, which is a dead end, meaning our second path run ends. Because we cannot start the next run from START (as it has no edges available anymore), we move on to next available node of least depth, i.e. A.

  13. We're on A, which leads us to B (cost = 2) --> B is already on the list and we dump the edge.

  14. We're on B, which leads us to D (cost = 3) --> D goes on the list, the edge gets eliminated.

  15. Etc.

Output / final list:

A
B
C
G
E
I
F
J
L
N
D
M
O
H
K
P
Q
R

Setup

CREATE (  START { n:"Start" }),(a { n:"A" }),(b { n:"B" }),(c { n:"C" }),(d { n:"D" }),(e { n:"E" }),(f { n:"F" }),(g { n:"G" }),(h { n:"H" }),(i { n:"I" }),(j { n:"J" }),(k { n:"K" }),(l { n:"L" }),(m { n:"M" }),(n { n:"N" }),(o { n:"O" }),(p { n:"P" }),(q { n:"Q" }),(r { n:"R" }),

START-[:costs1]->a, START-[:costs2]->b, START-[:costs3]->c, 
a-[:costs1]->START, a-[:costs2]->b, a-[:costs3]->c, a-[:costs4]->d, a-[:costs5]->e, 
b-[:costs1]->START, b-[:costs2]->c, b-[:costs3]->d, b-[:costs4]->f, 
c-[:costs1]->g, c-[:costs2]->f, 
d-[:costs1]->g, d-[:costs2]->f, d-[:costs3]->h, 
e-[:costs1]->i, 
f-[:costs1]->j, 
g-[:costs1]->e, g-[:costs2]->j, g-[:costs3]->k, 
j-[:costs1]->l, j-[:costs2]->m, j-[:costs3]->n, 
l-[:costs1]->n, l-[:costs2]->f, 
m-[:costs1]->o, m-[:costs2]->p, m-[:costs3]->q,
q-[:costs1]->n, q-[:costs2]->r;

Viewing all articles
Browse latest Browse all 39796

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>