I have a graph like this:
for example I want to know the dependency of node 8 which are : 1,2,3,5 . can some body give me some code or may be pseudo code to solve this problem?
Thanks
Dependency structure is a partially ordered set. I had similar case which I covered with 2 methods (in python):
nodes_to_update( to_proc ) parameter is a set of nodes to start with (e.g. set([8])). Returns two set of nodes: set of all nodes on which given nodes depend and set of leaf nodes. Idea is to recursively visit all nodes on which depend visited nodes.
sequence_to_update( to_proc ) parameter is like above. Return (ordered) list of nodes so that nodes in list depend only on nodes before in list. It is done by adding leaf node to the ordered list, and updating set of nodes to processed (all and leaf nodes).
Dependent nodes are get with method down_nodes(o_id) and nodes that depends on are get with up_nodes(o_id).
def nodes_to_update(self, to_proc):
all_to_update, first_to_update = set(), set()
while to_proc:
n = to_proc.pop()
all_to_update.add(n)
ds = self.down_nodes(n) # nodes on which n depends
if not ds:
first_to_update.add(n)
else:
to_proc.update(ds)
return all_to_update, first_to_update
def sequence_to_update(self, to_proc):
all_to_update, first_to_update = self.nodes_to_update(to_proc)
update_in_order = []
while first_to_update:
n_id = first_to_update.pop()
all_to_update.discard(n_id)
update_in_order.append(n_id)
# nodes which depend on n_id (intersection of upper nodes and all nodes to update)
for up_id in (self.up_nodes(n_id) & all_to_update):
if all(d not in all_to_update for d in self.down_nodes(up_id)):
first_to_update.add(up_id)
return update_in_order
Related
I have this large network created with vis-network:
When clicking on the nodes I create clusters. For example if I click on the 2 green boxes the result is:
In this new view I have two regular nodes ("Program #3289" and "Task #7300") and two clusters ("Project #3415" and "Project #3416") that contain their children.
If I use dataset.get() it returns all my 106 initial nodes.
If I use network.body.nodes it returns all my 106 initial nodes + my two clusters.
What I want: a way to only get the visible nodes in my network. In that case, I should get only 2 regular nodes and 2 clusters.
Did I miss a function that permits to do it?
Thank you
I finally came up with the below solution:
var visibleNodes = [];
for (var nodeId in visNetwork.body.nodes) {
// we check if the node is inside a cluster
if (!visNetwork.clustering.clusteredNodes[nodeId]) {
visibleNodes.push(nodeId)
}
}
I am new in neo4j, I created a graph following this steps, based on a data model from GTFS. I would like to find all the shortest indirect routes in the graph (with transfers).
Data model of graph database contains 4 entities: Route, Trip, Stop, Stoptime. Here is a screenshot of db.scheme().
Based on query which wrote Bruggen, I modified it for my use:
MATCH
(from:Stop {code:'VBR'})--(st_from:Stoptime),
(to:Stop {code:'VIR'})--(st_to:Stoptime),
p1=((st_from)-[:PRECEDES*]->(st_midway_arr:Stoptime)),
(st_midway_arr)--(midway:Stop),
(midway)--(st_midway_dep:Stoptime),
p2=((st_midway_dep)-[:PRECEDES*]->(st_to))
WHERE
st_from.departure_time > '00:00'
AND st_from.departure_time < '23:00'
AND st_midway_arr.arrival_time > st_from.departure_time
AND st_midway_dep.departure_time > st_midway_arr.arrival_time
AND st_to.arrival_time > st_midway_dep.departure_time
RETURN
from,st_from,to,st_to,p1,p2,midway
order by (st_to.arrival_time_int-st_from.departure_time_int) ASC
limit 1;
This query is not using the shortest path, and it takes in average 30s to find a path, but the output of the query is good.
So I tried to write another query, with method allshortestpaths, it really fast (0,3s). But it returns me also trips which run in a different direction (VIR -> VBR)... another problem is the timing od that connection.
Could you help me, how to access to the transfer node (Station) when I am using allshortestpath method? I want to write a condition for timing and stop_sequence to be sure that's the right direction.
match (from:Stop {code:'VBR'}),(to:Stop {code:'VIR'})
with from,to
match p = allshortestpaths((from)-[*]-(to))
where NONE (x in relationships(p) where type(x)="OPERATES")
return p
limit 10;
match (from:Stop {code:'VBR'}),(to:Stop {code:'VIR'})
with from,to
match p = allshortestpaths((from)-[*]->(to)) // here you needed you give the direction to make sure paths are from 'VBR' to 'VIR'
where NONE (x in relationships(p) where type(x)="OPERATES")
return p
limit 10;
Next , if you want to see the nodes in the path , then you can use the nodes(p)
match (from:Stop {code:'VBR'}),(to:Stop {code:'VIR'})
with from,to
match p = allshortestpaths((from)-[*]->(to))
where NONE (x in relationships(p) where type(x)="OPERATES")
AND ALL(node in nodes WHERE node = from OR node = to OR YOUR CONDTION ON TRANSFER NODE)
limit 10
I'm looking for paths to get from one vertex to the other, avoiding vertices with properties already matched on that path.
Consider this example:
Graph graph = TinkerGraph.open();
GraphTraversalSource t = graph.traversal();
Vertex A = t.addV().property("age", 19).next();
Vertex B = t.addV().property("age", 21).next();
Vertex C = t.addV().property("age", 20).next();
Vertex D = t.addV().property("age", 21).next();
Vertex E = t.addV().property("age", 22).next();
t.V(A).addE("knows").to(B).iterate();
t.V(B).addE("knows").to(C).iterate();
t.V(C).addE("knows").to(D).iterate();
t.V(D).addE("knows").to(E).iterate();
t.V(C).addE("knows").to(E).iterate();
List<Path> paths = t.V(A)
.repeat(
out()
).times(5).emit()
.has("age", 22).path().toList();
Assert.assertEquals(1, paths.size());
I'm looking for ways to go from A to E. There are two paths:
A->B->C->D->E
A->B->C->E
What I'm looking for is just the second one, because in the first path, B and D has the same age.
I tried to filter using as and by, but I failed to scale that to whole path. For instance, I can check the vertices not to match the first vertex' property, by doing the following:
List<Path> paths = t.V(A).as("first")
.repeat(
out()
.where(P.neq("first")).by("age")
).times(5).emit()
.has("age", 22).path().toList();
Assert.assertEquals(1, paths.size());
But as you can imagine, it doesn't filter the collisions in the middle of the path. I feel like there should be an easier way to do this that I'm missing. Is there a statement like as(), but instead of replacing the previous assignment, it keeps them in an array or something? How can I achieve this?
Thanks
You need to compare the current age against all previously seen ages. If there's any match, let the traverser die:
t.V(A).as("a").
repeat(filter(loops().is(lt(5))).out().
not(values("age").as("current"). /* current age */
select(all, "a").unfold(). /* previous ages */
values("age").
where(eq("current"))).as("a")). /* not() negates the match */
until(has("age", 22)).
path()
I'm trying to copy a vertex node and retain it's relationships in ArangoDB. I'm getting a "access after data-modification" error (1579). It doesn't like it when I iterate over the source node's edges and insert an edge copy within the loop. This makes sense but I'm struggling to figure out how to do what I'm wanting within a single transaction.
var query = arangojs.aqlQuery`
let tmpNode = (FOR v IN vertices FILTER v._id == ${nodeId} RETURN v)[0]
let nodeCopy = UNSET(tmpNode, '_id', '_key', '_rev')
let nodeCopyId = (INSERT nodeCopy IN 'vertices' RETURN NEW._id)[0]
FOR e IN GRAPH_EDGES('g', ${nodeId}, {'includeData': true, 'maxDepth': 1})
let tmpEdge = UNSET(e, '_id', '_key', '_rev')
let edgeCopy = MERGE(tmpEdge, {'_from': nodeCopyId})
INSERT edgeCopy IN 'edges'
`;
This quesion is somewhat similar to 'In AQL how to re-parent a vertex' - so let me explain this in a similar way.
One should use the ArangoDB 2.8 pattern matching traversals to solve this.
We will copy Alice to become Sally with similar relations:
let alice=DOCUMENT("persons/alice")
let newSally=UNSET(MERGE(alice, {_key: "sally", name: "Sally"}), '_id')
let r=(for v,e in 1..1 ANY alice GRAPH "knows_graph"
LET me = UNSET(e, "_id", "_key", "_rev")
LET newEdge = (me._to == "persons/alice") ?
MERGE(me, {_to: "persons/sally"}) :
MERGE(me, {_from: "persons/sally"})
INSERT newEdge IN knows RETURN newEdge)
INSERT newSally IN persons RETURN newSally
We therefore first load Alice. We UNSET the properties ArangoDB should set on its own. We change the properties that have to be uniq to be uniq for Alice so we have a Sally afterwards.
Then we open a subquery to traverse ANY first level relations of Alice. In this subequery we want to copy the edges - e. We need to UNSET once more the document attributes that have to be autogenerated by ArangoDB. We need to find out which side of _from and _to pointed to Alice and relocate it to Sally.
The final insert of Sally has to be outside of the subquery, else this statement will attempt to insert one Sally per edge we traverse. We can't insert Saly in front of the query as you already found out - no subsequent fetches are allowed after the insert.
I am trying to implement a force directed network similar to this. However, each of my nodes are assigned a group value for example
Node Group
node1 1
node2 1
node3 2
node4 3
node5 3
And I would like the network to grow i.e. after a period of time (say 2 seconds), the subsequent node group is added with their links.
Is this attainable?
Yes. the trick is to encapsulate the part that draws the graph in a function. Add the specific groups after the approppriate intervals to the graph data structure and call that function. The code would look roughly like this.
function update(graph) {
var link = svg.selectAll("line.link")
.data(graph.links)
.enter().append("line");
var node = svg.selectAll("circle.node")
.data(graph.nodes)
.enter().append("circle")
.call(force.drag);
node.append("title")
.text(function(d) { return d.name; });
force.start();
}
You should be able to reuse everything else basically as it is.