blob: 303299d46d692d191ae6d7e5d0290651f004a785 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tinkerpop.gremlin.process.computer.search.path;
import org.apache.tinkerpop.gremlin.LoadGraphWith;
import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
import org.apache.tinkerpop.gremlin.process.traversal.Path;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.junit.Before;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.CREW;
import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.GRATEFUL;
import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Daniel Kuppitz (http://gremlin.guru)
*/
public class ShortestPathVertexProgramTest extends AbstractGremlinProcessTest {
private ShortestPathTestHelper helper;
@Before
public void initializeHelper() throws Exception {
this.helper = new ShortestPathTestHelper(this, g);
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindAllShortestPathsWithDefaultParameters() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build().create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS).map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindAllShortestPathsWithEdgesIncluded() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build().includeEdges(true).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS).map(p -> helper.makePath(true, p))
.collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindOutDirectedShortestPaths() throws Exception {
final List<ShortestPathVertexProgram> programs = Arrays.asList(
ShortestPathVertexProgram.build().edgeTraversal(__.outE()).create(graph),
ShortestPathVertexProgram.build().edgeDirection(Direction.OUT).create(graph));
for (final ShortestPathVertexProgram program : programs) {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(program).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> (p[0].equals("marko") && !p[p.length - 1].equals("peter"))
|| (p[0].equals("vadas") && p.length == 1)
|| (p[0].equals("lop") && p.length == 1)
|| (p[0].equals("josh") && Arrays.asList("lop", "josh", "ripple").contains(p[p.length - 1]))
|| (p[0].equals("ripple") && p.length == 1)
|| (p[0].equals("peter") && Arrays.asList("lop", "peter").contains(p[p.length - 1])))
.map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindInDirectedShortestPaths() throws Exception {
final List<ShortestPathVertexProgram> programs = Arrays.asList(
ShortestPathVertexProgram.build().edgeTraversal(__.inE()).create(graph),
ShortestPathVertexProgram.build().edgeDirection(Direction.IN).create(graph));
for (final ShortestPathVertexProgram program : programs) {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(program).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> (p[0].equals("marko") && p.length == 1)
|| (p[0].equals("vadas") && Arrays.asList("marko", "vadas").contains(p[p.length - 1]))
|| (p[0].equals("lop") && Arrays.asList("marko", "lop", "josh", "peter").contains(p[p.length - 1]))
|| (p[0].equals("josh") && Arrays.asList("marko", "josh").contains(p[p.length - 1]))
|| (p[0].equals("ripple") && Arrays.asList("marko", "josh", "ripple").contains(p[p.length - 1]))
|| (p[0].equals("peter") && p.length == 1))
.map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindDirectedShortestPathsWithEdgesIncluded() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build().edgeTraversal(__.outE()).includeEdges(true).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> (p[0].equals("marko") && !p[p.length - 1].equals("peter"))
|| (p[0].equals("vadas") && p.length == 1)
|| (p[0].equals("lop") && p.length == 1)
|| (p[0].equals("josh") && Arrays.asList("lop", "josh", "ripple").contains(p[p.length - 1]))
|| (p[0].equals("ripple") && p.length == 1)
|| (p[0].equals("peter") && Arrays.asList("lop", "peter").contains(p[p.length - 1])))
.map(p -> helper.makePath(true, p)).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindShortestPathsWithStartVertexFilter() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build().source(__.has("name", "marko")).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> p[0].equals("marko")).map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindShortestPathsWithEndVertexFilter() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build().target(__.has("name", "marko")).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> p[p.length - 1].equals("marko")).map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldFindShortestPathsWithStartEndVertexFilter() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build()
.source(__.has("name", "marko"))
.target(__.hasLabel("software")).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p ->
p[0].equals("marko") && Arrays.asList("lop", "ripple").contains(p[p.length - 1]))
.map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldUseCustomDistanceProperty() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build()
.source(__.has("name", "marko"))
.target(__.has("name", "josh"))
.distanceProperty("weight").create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
assertEquals(1, shortestPaths.size());
assertEquals(helper.makePath("marko", "lop", "josh"), shortestPaths.get(0));
}
@Test
@LoadGraphWith(CREW)
public void shouldFindEqualLengthPaths() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build()
.edgeTraversal(__.bothE("uses"))
.source(__.has("name", "daniel"))
.target(__.has("name", "stephen")).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.asList(
helper.makePath("daniel", "gremlin", "stephen"),
helper.makePath("daniel", "tinkergraph", "stephen"));
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(GRATEFUL)
public void shouldFindEqualLengthPathsUsingDistanceProperty() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build()
.edgeTraversal(__.outE("followedBy"))
.source(__.has("song", "name", "MIGHT AS WELL"))
.target(__.has("song", "name", "MAYBE YOU KNOW HOW I FEEL"))
.distanceProperty("weight")
.create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.asList(
helper.makePath("MIGHT AS WELL", "DRUMS", "MAYBE YOU KNOW HOW I FEEL"),
helper.makePath("MIGHT AS WELL", "SHIP OF FOOLS", "MAYBE YOU KNOW HOW I FEEL"));
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldRespectMaxDistance() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build()
.source(__.has("name", "marko"))
.maxDistance(1).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> p[0].equals("marko") && p.length <= 2).map(helper::makePath).collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
@Test
@LoadGraphWith(MODERN)
public void shouldRespectMaxCustomDistance() throws Exception {
final ComputerResult result = graph.compute(graphProvider.getGraphComputer(graph).getClass()).
program(ShortestPathVertexProgram.build()
.source(__.has("name", "vadas"))
.distanceProperty("weight").maxDistance(1.3).create(graph)).submit().get();
assertTrue(result.memory().exists(ShortestPathVertexProgram.SHORTEST_PATHS));
final List<Path> shortestPaths = result.memory().get(ShortestPathVertexProgram.SHORTEST_PATHS);
final List<Path> expected = Stream.concat(Arrays.stream(ALL_SHORTEST_PATHS)
.filter(p -> p[0].equals("vadas") &&
Arrays.asList("vadas", "marko", "lop", "peter").contains(p[p.length - 1]))
.map(helper::makePath),
Stream.of(helper.makePath("vadas", "marko", "lop", "josh")))
.collect(Collectors.toList());
helper.checkResults(expected, shortestPaths);
}
public static String[][] ALL_SHORTEST_PATHS = new String[][]{
new String[]{"marko"},
new String[]{"marko", "vadas"},
new String[]{"marko", "lop"},
new String[]{"marko", "lop", "peter"},
new String[]{"marko", "josh"},
new String[]{"marko", "josh", "ripple"},
new String[]{"vadas"},
new String[]{"vadas", "marko"},
new String[]{"vadas", "marko", "lop"},
new String[]{"vadas", "marko", "lop", "peter"},
new String[]{"vadas", "marko", "josh", "ripple"},
new String[]{"vadas", "marko", "josh"},
new String[]{"lop"},
new String[]{"lop", "marko"},
new String[]{"lop", "marko", "vadas"},
new String[]{"lop", "josh"},
new String[]{"lop", "josh", "ripple"},
new String[]{"lop", "peter"},
new String[]{"josh"},
new String[]{"josh", "marko"},
new String[]{"josh", "marko", "vadas"},
new String[]{"josh", "lop"},
new String[]{"josh", "lop", "peter"},
new String[]{"josh", "ripple"},
new String[]{"ripple"},
new String[]{"ripple", "josh"},
new String[]{"ripple", "josh", "marko"},
new String[]{"ripple", "josh", "marko", "vadas"},
new String[]{"ripple", "josh", "lop"},
new String[]{"ripple", "josh", "lop", "peter"},
new String[]{"peter"},
new String[]{"peter", "lop"},
new String[]{"peter", "lop", "marko"},
new String[]{"peter", "lop", "marko", "vadas"},
new String[]{"peter", "lop", "josh"},
new String[]{"peter", "lop", "josh", "ripple"}
};
}