Skip to content

Commit

Permalink
enhanced Shortest Path algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
luigidellaquila committed Jun 11, 2015
1 parent 5809738 commit a6558ca
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 51 deletions.
Expand Up @@ -83,49 +83,103 @@ public List<ORID> execute(Object iThis, final OIdentifiable iCurrentRecord, Obje
}

Direction direction = Direction.BOTH;
Direction reverseDirection = Direction.BOTH;
if (iParams.length > 2 && iParams[2] != null) {
direction = Direction.valueOf(iParams[2].toString().toUpperCase());
}
if (direction == Direction.OUT) {
reverseDirection = Direction.IN;
} else if (direction == Direction.IN) {
reverseDirection = Direction.OUT;
}

Object edgeType = null;
if (iParams.length > 3) {
edgeType = iParams[3];
}

final ArrayDeque<OrientVertex> queue = new ArrayDeque<OrientVertex>();
final ArrayDeque<OrientVertex> queue1 = new ArrayDeque<OrientVertex>();
final ArrayDeque<OrientVertex> queue2 = new ArrayDeque<OrientVertex>();

final Set<ORID> visited = new HashSet<ORID>();

final Set<ORID> leftVisited = new HashSet<ORID>();
final Set<ORID> rightVisited = new HashSet<ORID>();

final Map<ORID, ORID> previouses = new HashMap<ORID, ORID>();
final Map<ORID, ORID> nexts = new HashMap<ORID, ORID>();

queue.add(sourceVertex);
queue1.add(sourceVertex);
visited.add(sourceVertex.getIdentity());

queue2.add(destinationVertex);
visited.add(destinationVertex.getIdentity());

OrientVertex current;
while (!queue.isEmpty()) {
current = queue.poll();

Iterable<Vertex> neighbors;
if (edgeType == null) {
neighbors = current.getVertices(direction);
} else {
neighbors = current.getVertices(direction, new String[] { "" + edgeType });
OrientVertex reverseCurrent;

while (true) {
if (queue1.isEmpty() && queue2.isEmpty()) {
break;
}
for (Vertex neighbor : neighbors) {
final OrientVertex v = (OrientVertex) neighbor;
final ORID neighborIdentity = v.getIdentity();

if (!visited.contains(neighborIdentity)) {
if (!queue1.isEmpty()) {
current = queue1.poll();

previouses.put(neighborIdentity, current.getIdentity());
Iterable<Vertex> neighbors;
if (edgeType == null) {
neighbors = current.getVertices(direction);
} else {
neighbors = current.getVertices(direction, new String[] { "" + edgeType });
}
for (Vertex neighbor : neighbors) {
final OrientVertex v = (OrientVertex) neighbor;
final ORID neighborIdentity = v.getIdentity();

if (rightVisited.contains(neighborIdentity)) {
previouses.put(neighborIdentity, current.getIdentity());
return computePath(previouses, nexts, neighborIdentity);
}
if (!visited.contains(neighborIdentity)) {
previouses.put(neighborIdentity, current.getIdentity());

queue1.offer(v);
visited.add(neighborIdentity);
leftVisited.add(neighborIdentity);
}

if (destinationVertex.equals(neighbor))
return computePath(previouses, neighborIdentity);
}
}

queue.offer(v);
visited.add(neighborIdentity);
if (!queue2.isEmpty()) {
reverseCurrent = queue2.poll();

Iterable<Vertex> neighbors;
if (edgeType == null) {
neighbors = reverseCurrent.getVertices(reverseDirection);
} else {
neighbors = reverseCurrent.getVertices(reverseDirection, new String[] { "" + edgeType });
}
for (Vertex neighbor : neighbors) {
final OrientVertex v = (OrientVertex) neighbor;
final ORID neighborIdentity = v.getIdentity();

if (leftVisited.contains(neighborIdentity)) {
nexts.put(neighborIdentity, reverseCurrent.getIdentity());
return computePath(previouses, nexts, neighborIdentity);
}
if (!visited.contains(neighborIdentity)) {

nexts.put(neighborIdentity, reverseCurrent.getIdentity());

queue2.offer(v);
visited.add(neighborIdentity);
rightVisited.add(neighborIdentity);
}

}
}
}

return new ArrayList<ORID>();
} finally {
if (shutdownFlag.getValue())
Expand All @@ -138,14 +192,21 @@ public String getSyntax() {
return "shortestPath(<sourceVertex>, <destinationVertex>, [<direction>, [ <edgeTypeAsString> ]])";
}

private List<ORID> computePath(final Map<ORID, ORID> distances, final ORID neighbor) {
private List<ORID> computePath(final Map<ORID, ORID> leftDistances, final Map<ORID, ORID> rightDistances, final ORID neighbor) {
final List<ORID> result = new ArrayList<ORID>();

ORID current = neighbor;
while (current != null) {
result.add(0, current);
current = leftDistances.get(current);
}

current = distances.get(current);
current = neighbor;
while (current != null) {
current = rightDistances.get(current);
if (current != null) {
result.add(current);
}
}

return result;
Expand Down
Expand Up @@ -2,24 +2,23 @@

import com.orientechnologies.orient.core.command.OBasicCommandContext;
import com.orientechnologies.orient.core.id.ORID;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;

public class OSQLFunctionShortestPathTest {

private OrientGraph graph;
private Vertex v1;
private Vertex v2;
private Vertex v3;
private Vertex v4;
private Map<Integer, Vertex> vertices = new HashMap<Integer, Vertex>();

private OSQLFunctionShortestPath function;

@Before
Expand All @@ -37,44 +36,67 @@ public void tearDown() throws Exception {
private void setUpDatabase() {
graph = new OrientGraph("memory:OSQLFunctionShortestPath");

v1 = graph.addVertex(null);
v2 = graph.addVertex(null);
v3 = graph.addVertex(null);
v4 = graph.addVertex(null);

v1.setProperty("node_id", "A");
v2.setProperty("node_id", "B");
v3.setProperty("node_id", "C");
v4.setProperty("node_id", "D");

Edge e1 = graph.addEdge(null, v1, v2, "Edge1");
Edge e2 = graph.addEdge(null, v2, v3, "Edge1");
Edge e3 = graph.addEdge(null, v1, v3, "Edge2");
Edge e4 = graph.addEdge(null, v3, v4, "Edge1");
vertices.put(1, graph.addVertex(null));
vertices.put(2, graph.addVertex(null));
vertices.put(3, graph.addVertex(null));
vertices.put(4, graph.addVertex(null));

vertices.get(1).setProperty("node_id", "A");
vertices.get(2).setProperty("node_id", "B");
vertices.get(3).setProperty("node_id", "C");
vertices.get(4).setProperty("node_id", "D");

for (int i = 5; i <= 20; i++) {
vertices.put(i, graph.addVertex(null));
vertices.get(i).setProperty("node_id", "V" + i);
graph.addEdge(null, vertices.get(i - 1), vertices.get(i), "Edge1");
if (i % 2 == 0) {
graph.addEdge(null, vertices.get(i - 2), vertices.get(i), "Edge1");
}
}

graph.addEdge(null, vertices.get(1), vertices.get(2), "Edge1");
graph.addEdge(null, vertices.get(2), vertices.get(3), "Edge1");
graph.addEdge(null, vertices.get(1), vertices.get(3), "Edge2");
graph.addEdge(null, vertices.get(3), vertices.get(4), "Edge1");
graph.commit();
}

@Test
public void testExecute() throws Exception {
final List<ORID> result = function.execute(null, null, null, new Object[] { v1, v4 }, new OBasicCommandContext());
final List<ORID> result = function.execute(null, null, null, new Object[] { vertices.get(1), vertices.get(4) },
new OBasicCommandContext());

assertEquals(3, result.size());
assertEquals(v1.getId(), result.get(0));
assertEquals(v3.getId(), result.get(1));
assertEquals(v4.getId(), result.get(2));
assertEquals(vertices.get(1).getId(), result.get(0));
assertEquals(vertices.get(3).getId(), result.get(1));
assertEquals(vertices.get(4).getId(), result.get(2));
}

@Test
public void testExecuteOnlyEdge1() throws Exception {
final List<ORID> result = function
.execute(null, null, null, new Object[] { v1, v4, null, "Edge1" }, new OBasicCommandContext());
final List<ORID> result = function.execute(null, null, null, new Object[] { vertices.get(1), vertices.get(4), null, "Edge1" },
new OBasicCommandContext());

assertEquals(4, result.size());
assertEquals(v1.getId(), result.get(0));
assertEquals(v2.getId(), result.get(1));
assertEquals(v3.getId(), result.get(2));
assertEquals(v4.getId(), result.get(3));
assertEquals(vertices.get(1).getId(), result.get(0));
assertEquals(vertices.get(2).getId(), result.get(1));
assertEquals(vertices.get(3).getId(), result.get(2));
assertEquals(vertices.get(4).getId(), result.get(3));
}

@Test
public void testLong() throws Exception {
final List<ORID> result = function.execute(null, null, null, new Object[] { vertices.get(1), vertices.get(20) },
new OBasicCommandContext());

assertEquals(11, result.size());
assertEquals(vertices.get(1).getId(), result.get(0));
assertEquals(vertices.get(3).getId(), result.get(1));
int next = 2;
for (int i = 4; i <= 20; i += 2) {
assertEquals(vertices.get(i).getId(), result.get(next++));
}
}

}

0 comments on commit a6558ca

Please sign in to comment.