Neo4j and Lucene multikey queries (or: should I use Cypher?) - graph

I have a graph in Neo4j in which nodes represent random points in the plane, each node having the coordinates stored as properties (x and y, the value type is double).
I create the nodes and index them:
IndexManager index = graph.index();
Index<Node> nodesIndex = index.forNodes("points");
for (int i = 0; i < points.length; i++) {
Point p = points[i];
Node n;
Transaction tx = graph.beginTx();
try {
n = graph.createNode();
n.setProperty("x", p.getX());
n.setProperty("y", p.getY());
nodesIndex.add(n, "x", new ValueContext(p.getX()).indexNumeric());
nodesIndex.add(n, "y", new ValueContext(p.getY()).indexNumeric());
tx.success();
} finally {
tx.finish();
}
}
Now, what I need to do, is query for the nodes which are in a square area. So for example I made this query:
http://localhost:7474/db/data/index/node/points?query=x:[0.0 TO 3.0] AND y:[0.0 TO 3.0]
And this is the response:
Node
Properties
y 1.0
x 14.0
Node info
self /db/data/node/10
Node
Properties
y 1.0
x 2.0
Node info
self /db/data/node/7
Node
Properties
y 1.0
x 6.0
Node info
self /db/data/node/8
Node
Properties
y 1.0
x 7.0
Node info
self /db/data/node/9
[Etc...]
As you see it is not working. And I don't understand why (maybe I need to configure the index?).
Note that I haven't got to use Lucene. If there is a way to gather that information with Cypher (starting from a node centered in the square area) would be actually better, for I also need the relationships between the nodes found.
Additional informations
If that matters, the graph represents a Delaunay triangolation on a random set of points on the plane. In more abstract terms, I need to "extract" the entire subgraph that lays in a given area.
Any help is really appreciated!

I am afraid you can't do this via Cypher. There is no way Cypher can infer that you want to use a numeric Value context for this query (could probably be in some indexing meta info in future releases), and you need that to be able to query Lucene the way you want to. Easiest way over REST is probably to use Groovy, see custom sorting (same issue) at http://docs.neo4j.org/chunked/snapshot/gremlin-plugin.html#rest-api-send-an-arbitrary-groovy-script---lucene-sorting

Related

Partition graph into groups of neighbours having the same class

Using JGraphT, I would like partition a graph into groups where each group consists of a connected sub-graph of vertices that have the same "class" (denoted using colors below).
Example -- the desired groups are in red:
I think this is a rather simple demand and yet I can't find a (built-in) way to do this. I notice there is a PartitioningImpl class, that one constructs using a List<Set<V>> classes, yet I don't see a way to use this to partition a graph.
Ideally, I'd provide something with my graph and vertex classes (a map of V-->Integer for instance) and it would return something like a List<Set<V>> of partitioned vertex groups.
Sometimes you just cannot avoid writing some code
LOOP over classes
LOOP over nodes that are in class
Copy node to new graph
LOOP over edges that connect nodes in class
Copy edge to new graph
LOOP over connected components in new graph
Save component as a group graph for class
This is a fairly simple approach using JGraphT:
First remove edges linking neighbouring vertices that belong to different classes and then use ConnectivityInspector on the reduced graph to find connected components, which form the groups.
SimpleGraph<V, E> graph; // given by user
Map<V, Integer> classes; // given by user
List<E> toRemove = new ArrayList<>();
graph.edgeSet().forEach(e -> {
V a = graph.getEdgeSource(e);
V b = graph.getEdgeTarget(e);
if (!classes.get(a).equals(classes.get(b))) {
toRemove.add(e);
}
});
graph.removeAllEdges(toRemove);
ConnectivityInspector<V, E> ci = new ConnectivityInspector<>(graph);
List<Set<V>> groups = ci.connectedSets();

How to code a pathfinding player in godot using A*?

Iam nooby in godot, I have to use A* to traslate the player to the goal position, but I do not know how to start, pls help!! basically I have just 2 tiles in the tilemap, 1 of them is allowed to pass over it, I have to extract I guess the allowed tile and calculate the distance between the position player with the position goal, getting the real distance and then check cell per cell which has the lowest cost, but I do not know how to do that :c
func get_player_init_pos():
var pos = map_to_world(Vector2(54,1))pos.y += half_cell_size.y
return pos
func is_tile_vacant(pos, direction):
var curr_tile = world_to_map(pos)
var next_tile = get_cellv(curr_tile + direction)
var next_tile_pos = Vector2()
if(next_tile == 0):
next_tile_pos = map_to_world(curr_tile + direction)
else:next_tile_pos = pos
return next_tile_pos
I have this, the first part of the code is to locate the player in the map and the second is for check the tile walls in the map
You could roll your own path finding algorithm. However, there is little point in doing so, since Godot has a AStar class you can use. However, you probably don't need to use that either, because Godot has a navigation system. And that is what I'm going to suggest you to use.
First of all, you can specify both navigation and collision polygons on your tiles. You need to have the navigation polygons. Go ahead and do them.
Second you want to have a Navigation2D in the scene tree and have your TileMap as a child.
And third, you can ask the Navigation2D for a path with get_simple_path, you pass the start and end positions as arguments and you get an array of points that make up the path.
Since you mention A*, I'll briefly explain using the AStar too anyway.
First, you need to add the cells with add_point. It requires ids. It is a good idea to be clever with the ids so you can compute the id for a given position. For example x * width + y if you know the size.
So you can iterate over the tiles in your TileMap and call add_point for each one (You don't need to add cell that are not passable).
Then you need to specify the connections with connect_points (it takes the ids of the points as parameters).
And finally you can call get_point_path passing the start and end ids. Again it gives you a array of points.

Add or update an edge in Gremlin

I have a graph database in Azure CosmoDB that stores how similar vertices are and the edge contains the numeric value of how similar they are.
The complication is that I want to add an edge or update by incrementing the similarity value. This is the current code I have for adding:
g.V('A').addE('similar').to(g.V('B')).property('x', 10)
I need something that will increase X if the edge exists, or create it if not. Pseudo code exemplifying it:
g.V('A').updateE('similar').to(g.V('B')).property('x', currentValue+2).ifNulll({g.V('A').addE('similar').to(g.V('B')).property('x', 10)})
is there an easy way to achieve this ?
There is a known recipe for checking existence by using the pattern fold().coalesce(unfold()...) for vertex and similar pattern for edge. In your case, you want to update a property value as well.
Assuming there are vertices with IDs A and B, and edge goes from A-->B, the query might look like this:
g.withSack(0).V('B').as('toV').V('A').coalesce(
outE('similar').where(inV().as('toV')),
addE('similar').to('toV').property('similarity', 0)
)
.sack(assign).by('similarity').sack(sum).by(constant(2))
.property('similarity', sack())
Explanation:
Get B (target) vertex and save reference, get A (source) vertex.
Using coalesce, check if there is an edge connecting them, otherwise create such edge and set similarity to 0.
Assign the 'similarity' value to the sack, and sum the additional value.
Last, store the new value on the edge property.
Another query without using sack:
g.V('B').as('toV').V('A').coalesce(
outE('similar').where(inV().as('toV')),
addE('similar').to('toV').property('similarity', 0)
).property('similarity', values('similarity').fold(10, sum))

How to get all Graph Nodes in ArangoDB without Start-Node

Like in OrientDB, for get the All Graph Only use 'Select From v'
So far, I have use AQL in ArangoDB with start node:
for v,e,p IN 2 ANY 'user/188802' graph 'a' return p
And now I want to get all graph nodes in ArangoDB without the start node?
Graphs are a grouping of Edge collections. Each Edge collection references _from and _to documents which are stored in Document collections.
The graph traversal queries expect you to have a starting position and it returns the results for that single starting position.
It is possible to identify all possible starting positions, and then run graph traversals over those positions.
You'll need to know the names of the document collections that make up your graph, you can insert them into an AQL query like this:
FOR vertex IN UNION(
(FOR v IN document_collection_1 RETURN v._id),
(FOR v IN document_collection_2 RETURN v._id),
(FOR v IN document_collection_3 RETURN v._id)
)
FOR v, e IN 1..5 OUTBOUND vertex GRAPH 'my_graph_name' OPTIONS { uniqueVertices: true }
RETURN DISTINCT [
{
_from: e._from,
_to: e._to
}
]
Remember that in ArangoDB it is possible for a document collection to be bound to more than one graph, so you'll need to ensure you identify all document collections that are part of the graph.
This query will then extract an array of objects that contain all links defined in the graph. This query focuses only on vertices with edges that are part of the graph. If the vertex has no edge on it, it won't appear in the output as it is not part of the graph.

[graph]: build a graph of relationship

According to the books I read, they often build a graph using vertices whose value ranges from 1 to n, so every vertex has a unique name.
What if I have to build a graph using vertices whose value are strings, say
V = {'Arm', 'Bob', 'Lin', 'Kok'} #vertices
E = {('Arm', 'Lin'), (Bob, 'Lin'), ('Bob', 'Kok')} #edges
Am I supposed to map these string vertices to integers before I build the graph for them?
Any example I can refer to?
I'm gonna go out on a limb and guess you're drawing with pygraphviz
Using strings instead of numbers, the simple.py example would look like:
import pygraphviz as pgv
A=pgv.AGraph()
A.add_edge('foo', 'bar')
A.add_edge('bar', 'baz')
A.add_edge('baz', 'foo')
A.write('simple.dot')
B=pgv.AGraph('simple.dot')
B.layout()
B.draw('simple.png')
Or, if you're not drawing, just building, the code you posted is a great way to represent a graph; no need to use numbers when strings work just fine.

Resources