I apologise for the title, I realise it isn't especially descriptive. I'll try to describe my problem in greater detail.
I have a set of "nodes", for sake of example we'll title them A, B, C, D, and E. These nodes are unique from one another in the sense that they have are "related" to each other, though only to specific nodes. In my real implantation, there could be thousands of nodes and I would like to develop an algorithm which could place them appropriately, regardless of their quantity.
We'll pretend the associations are as follows:
A: B, D
B: A, C, D
C: E
D: A, B
E: C
This format means that A is related to B and D, etc.
My goal is to display these relationships on a 2D plane by drawing each node as a circle, and drawing a line between them. I would like to display them in a "web" type fashion, meaning that the nodes do not overlap whatsoever, and the distance between related nodes is minimized. I would like for the diagram to suggest that by starting at A, for instance, one could travel next to B, then to C, and finally to E.
In a case such as B's, where it itself is related to C while C is not related to B, there does not have to be a distinction to suggest that. That is to say, showing that A:B and B:A can be the same as saying that B:C, despite C is not related to B.
I hope I have made myself clear in what I would like to accomplish. I don't think I'll have very much trouble coding the actual algorithm, I just for the life of me can't think of a way logical way to approach the problem.
Any suggestions at all are greatly appreciated, I don't need pseudocode or step by step instructions, just some advice from some more seasoned programmers who may be able to look at the problem from a different perspective.
Thanks!
Try searching for "force directed graph drawing".
The basic idea is as follows:
Initialize node positions randomly (putting them with equal distances on a circle turned out to be good)
Apply Forces between the nodes:
Nodes push off each other
if they are related, they are additionally pulled towards each other
Repeat step 2 until you have a nice layout.
There is a live example at http://getspringy.com/
Related
I need to help to define a relationship in conceptual model for database. I'm doing it in PowerDesiner. I have 3 entities (let's call them A, B and C).
A doesn't have to have B, if A has B then only once.
B has to have at least one A.
B may have C, but doesn't have to.
C have precisely two B.
C has at least one A.
C can have A only if A is part of B, which is in relationship with C (one of the two B to C).
A may have C, but doesn't have to.
It's too complicated for me, I had an idea, but it turned out to be completely wrong. It's only a part of project, but the rest don't affect those 3. I need to do those limits on conceptual level, which is exactly my problem.
My first and propably the best idea was this http://i.snag.gy/Ofdze.jpg but it doesn't include the condition that C can have A only if A is part of B, which is in relationship with C (one of the two B to C)
Then I came up with this http://i.snag.gy/gKNQ9.jpg but as the solution before I think that it doesn't contains the same condition, even worse seems to be really messed up solution.
Ok,
for clarity I will refer to your relation conditions to the # of line you have described it, so Row_1-2 will refer to statements in 1st and 2nd row of your question.
Please, pay attention, there is a logical error in your 5th and 6th statements.
You say C has at least one A and C can have A only if.., the two are not possible toghether.
I will skip the 5th and keep the 6th in my answer.
Let's see, first of all add the relation between A and B
Then select the relation and right click it and select Change to Entity,
you will get:
Pay attention this new entity identifies the relation between A and B, you will need it to fulfill your 6th statement.
Now add relations between C and B and between C and A (through Rel_A-B)
Note, I have adjusted cardinalities in relation between B and C (2,2)
Relationship/Arrows in Neo4j can not get more than one type/label (see here, and here). I have a data model that edges need to get labels and (probably) properties. If I decide to use Neo4j (instead of OriendDB which supports labeled arrow), I think I would have then two options to model an arrow, say f, between two nodes A and B:
1) encode an arrow f as a span, say A<--f-->B, such that f is also a node and --> and <-- are arrows.
or
2) encode an arrow f as A --> f -->B, such that f is a node again and two --> are arrows.
Though this seems to be adding unnecessary complexity on my data model, it does not seem to be any other option at the moment if I want to use Neo4j. Then, I am trying to see which of the above encoding might fit better in my queries (queries are the core of my system). For doing so, I need to resort to examples. So I have two question:
First Question:
part1) I have nodes labeled as Person and father, and there are arrows between them like Person<-[:sr]-father-[:tr]->Person in order to model who is father of who (tr is father of sr). For a given person p1 how can I get all of his ancestors.
part2) If I had Person-[:sr]->father-[:tr]->Person structure instead, for modeling father relationship, how the above same query would look like.
This is answered here when father is considered as a simple relationship (instead of being encoded as a node)
Second Question:
part1) I have nodes labeled as A nodes with the property p1 for each. I want to query A nodes, get those elements that p1<5, then create the following structure: for each a1 in the query result I create qa1<-[:sr]-isA-[:tr]->a1 such that isA and qa1 are nodes.
part2) What if I wanted to create qa1-[:sr]->isA-[:tr]->qa1 instead?
This question is answered here when isA is considered as a simple arrow (instead of being modeled as a node).
First, some terminology; relationships don't have labels, they only have types. And yes, one type per relationship.
Second, relative to modeling, I think the direction of the relationship isn't always super important, since with neo4j you can traverse it both ways easily. So the difference between A-->f-->B and A<--f-->B I think should be entirely driven what what makes sense semantically for your domain, nothing else. So your options (1) and (2) at the top seem the same to me in terms of overall complexity, which brings me to point #3:
Your main choice is between making a complex relationship into a node (which I think we're calling f here) or keeping it as a relationship. Making "a relationship into a node" is called reification and I think it's considered a fairly standard practice to accommodate a number of modeling issues. It does add complexity (over a simple relationship) but adds flexibility. That's a pretty standard engineering tradeoff everywhere.
So with all of that said, for your first question I wouldn't recommend an intermediate node at all. :father is a very simple relationship, and I don't see why you'd ever need more than one label on it. So for question one, I would pick "neither of the options you list" and would instead model it as (personA)-[:father]->(personB). More simple. You'd query that by saying
MATCH (personA { name: "Bob"})-[:father]->(bobsDad) RETURN bobsDad
Yes, you could model this as (personA)-[:sr]->(fatherhood)-[:tr]->(personB) but I don't see how this gains you much. As for the relationship direction, again it doesn't matter for performance or query, only for semantics of whatever :tr and :sr are supposed to mean.
I have nodes labeled as A nodes with the property p1 for each. I want
to query A nodes, get those elements that p1<5, then create the
following structure: for each a1 in the query result I create
qa1<-[:sr]-isA-[:tr]->a1 such that isA and qa1 are nodes.
That's this:
MATCH (aNode:A)
WHERE aNode.p1 < 5
WITH aNode
MATCH (qa1 { label: "some qa1 node" })
CREATE (qa1)<-[:sr]-(isA)-[:tr]->aNode;
Note that you'll need to adjust the criteria for qa1 and also specify something meaningful for isA.
What if I wanted to create qa1-[:sr]->isA-[:tr]->qa1 instead?
It should be trivial to modify that query above, just change the direction of the arrows, same query.
I have two nodes, A and B,
A talks to B and B talks to A, (A)-[:talksTo]-(B)
A has a sentiment value towards B, and B has a sentiment value towards A.
So there is the problem, I need A to B relationship to store a value that the B to A relationship will also want to store (same key).
So I will try to do queries such as, MATCH (A:person)-[:talksTo]-(B:person) where A.sentiment < -2 return A;
So here A's sentiment toward B will be different the B's sentiment toward A, thus the needed separation.
I have tried to make unique key names to specify direction - but that makes queries difficult unless I can query with a wild card ex: ... where A.Asentiment < -2 would be queried as ... where A.*sentiment < -2
Another way I can think of to do this is make two different graphs, 1) A talks to B graph and B talks to A graph... but this would make queries tricky as I may get back more then one node for single node queries OR if I have to update a single node key:value to something else. I would prefer to have one node name per person.
Any ideas?
I don't know that this is a solution, but I don't think I understand enough so it might be a foil for better understanding:
MATCH (A:Person)-[dir1:talksTo]->(B:Person), (A)<-[dir2:talksTo]-(B)
WHERE dir1.sentiment < 2
RETURN A, B
Is there a query for a Neo4J graph that could traverse said graph and find nodes based on mutual relationships? For example, if Node A is related to Node B (bidirectionally), B is related to C, C is related to D, D is related to A, A is related to C, and B is related to D, such that there is a subgraph in which every node is connected to every other node, is there an efficient way to return that subgraph or group of Nodes?
I realize my explanation is poor, so I provide an example graph in the console: http://console.neo4j.org/r/qb2xmp
Here, I have created a graph, and I would like to return groups that are mutually related of 3 or more - so, in this case, I would ideally like to be returning the group of Scott, Josh, Frank, and Ben, as well as the group of Frank, Ben, and Eric. If possible, I would like to be able to identify who composes those individual groups.
This is an instance of the Clique Problem and is NP-Complete.
Here is a related question on SO with a good explanation!
Sorry I hit enter too soon. So there is no "efficient" way to do this. It is not unattemptable though in certain cases, and you will have the best luck looking for an algorithm that solves this general problem and implementing it in Neo4J.
did you find any solutions for this?
I implemented something like this on my project for text network visualization but it launches Gephi Toolkit (on Java) to perform some metric calculations on the graph, detect communities, etc. But that's too heavy...
You might be interested to look into Gephi's algorithms though, especially the Force Atlas layout implemented in Sigma.Js and especially the modularity algorithm used in Gephi itself. This might give you some clues as to how to proceed...
Suppose you have two circular linked lists , one is of size M and the other is of size N and M < N. If you don't know which list is of size M, what is the worst-case complexity to concatenate the two lists into a single list?
I was thinking O(M) but that is not correct. And no, I guess there is no specific place to concatenate at.
If there are no further restrictions, and your lists are mutable (like normal linked lists in languages like C, C#, Java, ...), just split the two lists open at whatever nodes you have and join them together (involves up to four nodes). Since it's homework, I leave working out the complexity to you, but it should be easy, there's a strong hint in the preceding.
If the lists are immutable, as would normally be the case in a pure functional language, you'd have to copy a number of nodes and get a different complexity. What complexity exactly would depend on restrictions on the sort of result (e.g. does it have to be a circular linked list?).