In Cypher, nodes are queried if they have edges type A. How to display other edge type they have? - cypher

In my graph the edges have two types: A and B. I want to query all the nodes having edges type A. Within those nodes, if they have edges B then they should be displayed as well. So for example, if we have (node1)-[A]-(node2), (node3)-[A]-(node4), and if there are B edges between those 4 nodes, then only them should be displayed, not all other Bs.
I try both:
match (n)-[r:A]-(m)
match (n)-[s:B]-(m)
return n,r,s,m
and
match (n)-[r:A]-(m),
(n)-[s:B]-(m)
return n,r,s,m
But none of them works.
I don't use Neo4j Browser, so the edges need to be explicitly queried. The manual for MATCH doesn't help.

Try this, since you seem to be looking for triangles
MATCH (n)-[r1:A]-(m)-[r2:A]-(k)
OPTIONAL MATCH (k)-[r3:B]-(n)

Related

A way to restrict the domain of a variable?

I have a code snippet for a transport problem like:
set i /1*50/
d /1*10/
Alias(i,j,k)
parameter
edge(i,j)
distance(i,j)
possible(i,d) 'a collection of possible nodes for d'
possible_edge(i,j,d) 'a collection of possible edge for d';
binary variable x(i,j,d);
I import all the edges from an excel file. But to reduce the number of variables, I'd like to create another parameter like possible node and possible edge.
suppose we run a shortest path algorithm form a source node i and we define possible(i,d) to be all i where distance(i,j) is smaller than a predefined threshold.
In other words, when the network node become larger and larger, I want to find out if there's any possibility to not define x(i,j,d) for every (i,j) combination? Like forcing to only have x(i,j,d)$possible_edge(i,j,d)?? Is there anything like this??
Yes, you can limit the domain of variables in the model statement, like this
Model m / all, x(possible_edge) /;
So, here, the variable x would be limited by the set possible_edge wherever it occurs in model m. Note, that possible_edge must be a set here, not a parameter.
You can find more info about this concept here: https://www.gams.com/latest/docs/UG_ModelSolve.html#UG_ModelSolve_LimitedDomain

Blender: split object with a shape

I've got a flat object that I want to split in multiple pieces (background: I want to print it later, but the surface of my printer is not large enough). I've modeled a simple puzzle-shape:
I would like to use this shape to cut through my object, but if I use the boolean modifier, blender generates vertexes where the shape and the object intersects, but it won't cut the object since my shape got a thickness of 0:
I don't want to make my shape thicker, because otherwise it would delete something of my object...
You are able to separate the two sides of the object from each other, and then rejoin them afterwards if you need to. (This does include the use of the boolean modifier)
First, you should add the boolean modifier to the main mesh where you want it, with the 'difference' operation. Then in edit mode, as you explained before, the vertexes are created but there isn't the actual 'cut' that you were looking for.
I recreated the scenario with a plane intersecting a cube:
This is what it looks like in edit mode after having applied the boolean modifier:
Second what you can do is (after applying the boolean modifier) select the faces you want to be separated in edit mode. Then, pressing P (shortcut for separate, you can get to it by right clicking) click on 'selection' and you should have two separate objects. One of the objects will have what looks like a missing face: If you wanted two separate objects, then you just need to add a face on the object with the missing face and you can look no further. If you wanted separate parts of objects that are separate within edit mode (all together one object in object mode) then you can select the two objects and press crtl+j. Hope this helps somehwhat!
I have selected half of the cube that I want cut out (the selection does not include the face in the middle):
There are now two objects, completely seperated from each other:

What is a concatenated term and in what contexts are they unexpected?

My main question is what an "unexpected concatenated term". I have some context for the error below though there seem to be a slew of other issues that might be confounding this one.
I have a term foo of sort Map and a term bar also of sort Map. foo takes a list of expressions and the goal is to place them all into a Map. To that end for each expression I call bar on it and concatenate. From the syntax of Map I believe it should be enough to then say bar(exp) foo(exps) to get the entire Map.
This compiles fine however when I try to run it as soon as I rewrite into bar(exp) foo(exps) I get a
[Error] Critical: unexpected concatenated termfoo(...) while evaluating function _Map_. I removed the expressions themselves for brevity.
I believe the issue may be with the Map union having a higher priority than my foo and bar so I tried assigning bar as a function though because bar is strict in its arguments this caused an error with sorts KItem and Exp being incompatible.
#ALee we would need to see your code to be sure, but I think the confusion here is that you are trying to union two maps together, and K actually doesn't support map union.
We have the constructor _Map_, which lets you, for example, build the Map which looks like this: "a" |-> 3 "b" |-> 4. But you cannot take two arbitrary maps and use this constructor to put them together.
The reason for this is that the resulting term may not be well-defined (what if both maps define the same key, but have different values?).
Instead, if you want this behavior, you need to write your own map union operator, which makes a choice about what to do when there are overlapping keys in the two maps. This example prefers the keys from the second Map argument (over-writing the value of the first map if the same key exists there):
syntax Map ::= union ( Map , Map ) [function]
rule union(M, .Map) => M
rule union(M, K |-> V M') => union(M [ K <- V ], M')

How to find an example instance of a cyclic dependency in jQAssistant?

I found the output of the dependency:packageCycles constraint shipped with jQAssistant hard to interpret. Specifically I'm keen on finding an example instance of classes that make up the cyclic dependency.
Given I found a cyclce of packages, for each pair of adjunct packages I would need to find two classes that connect them.
This is my first attempt at the Cypher query, but there are still some relevant parts missing:
MATCH nodes = (p1:Package)-[:DEPENDS_ON]->(p2: Package)-[:DEPENDS_ON*]->(p1)
WHERE p1 <> p2
WITH extract(x IN relationships(nodes) |
(:Type)<--(:Package)-[x]->(:Package)-->(:Type)) AS cs
RETURN cs
Specifically, in order to really connect the two packages, the two types should be related to each other with DEPENDS_ON as shown below:
(:Type)<--(:Package)-[x]->(:Package)-->(:Type)
| ^
| DEPENDS_ON |
+--------------------------------------+
For above pattern I would have to return the two types (and not the packages, for instance). Preferably the output for a single cyclic dependency consists of a list of qualified class names (otherwise multiple one cannot possibly distinguish the class chains of more than one cyclic dependency).
For this specific purpose I find Cypher to be very limited, support for identifying and collecting new graph patterns during path traversal does not seem to be the easiest thing to do. Also the attempt to give names to the (:Type) nodes resulted in syntax errors.
Also I messed a lot around with UNWIND, but to no avail. It lets you introduce new MATCH clauses on per-element basis (say, the elements of relationships(nodes)), but I do not know of another method to undo the damaging effects of unwind: the surrounding list structure is removed, such that the traces of multiple cyclic dependencies merge into each other. Additionally the results appear permuted to me. That being said below query is conceptually also very close on what I am trying to achieve but does not work:
MATCH nodes = (p1:Package)-[:DEPENDS_ON]->(p2: Package)-[:DEPENDS_ON*]->(p1)
WHERE p1 <> p2
WITH relationships(nodes) as rel
UNWIND rel AS x
MATCH (t0:Type)<-[:CONTAINS]-(:Package)-[x]->(:Package)-[:CONTAINS]->(t1:Type),
(t0)-[:DEPENDS_ON]->(t1)
RETURN t0.fqn, t1.fqn
I do appreciate that there seems to be some scripting support within jQAssistant. However, this would really be my last resort, since it is surely more difficult to maintain than a Cypher query.
To rephrase it: given a path, I'm looking for a method to identify a sub-pattern for each element, project a node out of that match, and to collect the result.
Do you have any ideas on how could one accomplish that with Cypher?
Edit #1: Within one package, one has also to consider that the class that is target to the inbound edge of type DEPENDS_ON may not be the same class that is source to the outgoing edge. In other words, as a result
two classes of the same package may be part of the trace
if one wanted to express the cyclic dependency trace as a path, one must take into account detours that navigate to classes in the same package. For instance (edges in bold mark package entry / exit; an edge of type DEPENDS_ON is absent between the two types):
-[:DEPENDS_ON]->(:Type)<-[:CONTAINS]-(:Package)-[:CONTAINS]->(:Type)-[DEPENDS_ON]->
Maybe it gets a little clearer using the following picture:
Clearly "a, b, c" is a package cycle and "TestA, TestB1, TestB2, TestC" is a type-level trace for justifying the package-level dependency.
The following query extends the package cycle constraint by drilling down on type level:
MATCH
(p1:Package)-[:DEPENDS_ON]->(p2:Package),
path=shortestPath((p2)-[:DEPENDS_ON*]->(p1))
WHERE
p1 <> p2
WITH
p1, p2
MATCH
(p1)-[:CONTAINS]->(t1:Type),
(p2)-[:CONTAINS]->(t2:Type),
(p1)-[:CONTAINS]->(t3:Type),
(t1)-[:DEPENDS_ON]->(t2),
path=shortestPath((t2)-[:DEPENDS_ON*]->(t3))
RETURN
p1.fqn, t1.fqn, EXTRACT(t IN nodes(path) | t.fqn) AS Cycle
I'm not sure how well the query will work on large projects, we'll need to give it a try.
Edit 1: Updated the query to match on any type t3 which is located in the same package as t1.
Edit 2: The answer is not correct, see discussion below.

Are mixed type indexes acceptable in Neo4j?

I have a data set which includes a number of nodes, all of which labeled claim, which can have various properties (names P1, P2, etc., through P2000). Currently, each of the claim nodes can have only one of these properties, and each property has value, which can be of different types (i.e. P1 may be string, P2 may be float, P3 integer, etc.). I also need to be able to look up the nodes by any property (i.e. "find all nodes with P3 which equals to 42").
I have modeled it as nodes having property value and label according to the P property. Then I define schema index on label claim and property value. The lookup then would look something like:
MATCH (n:P569:claim) WHERE n.value = 42 RETURN n
My first question is - is this OK to have such index? Are mixed type indexes allowed?
The second question is that the lookup above works (though I'm not sure whether it uses index or not), but this doesn't - note the label order is switched:
neo4j-sh (?)$ MATCH (n:claim:P569) WHERE n.value>0 RETURN n;
IncomparableValuesException: Don't know how to compare that. Left: "113" (String); Right: 0 (Long)
P569 properties are all numeric, but there are string properties from other P-values one of which is "113". Somehow, even though I said the label should be both claim and P569, the "113" value is still included in the comparison, even though it has no P569 label:
neo4j-sh (?)$ MATCH (n:claim) WHERE n.value ="113" RETURN LABELS(n);
+-------------------+
| LABELS(n) |
+-------------------+
| ["claim","P1036"] |
| ["claim","P902"] |
+-------------------+
What is wrong here - why it works with one label order but not another? Can this data model be improved?
Let me at least try to side-step your question, there's another way you could model this that would resolve at least some of your problems.
You're encoding the property name as a label. Perhaps you want to do that to speed up looking up a subset of nodes where that property applies; still it seems like you're causing a lot of difficulty by shoe-horning incomparable data values all into the same property named "value".
What if, in addition to using these labels, each property was named the same as the value? I.e.:
CREATE (n:P569:claim { P569: 42});
You still get your label lookups, but by segregating the property names, you can guarantee that the query planner will never accidentally compare incomparable values in the way it builds an execution plan. Your query for this node would then be:
MATCH (n:P569:claim) WHERE n.P569 > 5 AND n.P569 < 40 RETURN n;
Note that if you know the right label to use, then you're guaranteed to know the right property name to use. By using properties of different names, if you're logging your data in such a way that P569's are always integers, you can't end up with that incomparable situation you have. (I think that's happening because of the particular way cypher is executing that query)
A possible downside here is that if you have to index all of those properties, it could be a lot of indexes, but still might be something to consider.
I think it makes sense to take a step back and think what you actually want to achieve, and why you have those 2000 properties in the first place and how you could model them differently in a graph?
Also make sure to just leave off properties you don't need and use coalesce() to provide the default.