Archived
0

change graph implementation

This commit is contained in:
iMoHax
2015-05-16 17:25:40 +03:00
parent 42a958ecb2
commit 0fd99b0ac2
12 changed files with 1275 additions and 2 deletions

View File

@@ -0,0 +1,281 @@
package ru.trader.analysis.graph;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.TestUtil;
import ru.trader.core.Profile;
import ru.trader.core.Ship;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CrawlerTest extends Assert {
private final static Logger LOG = LoggerFactory.getLogger(CrawlerTest.class);
private final static ArrayList<Point> entrys = new ArrayList<>();
private final static Point x1 = new Point("x1", -40);
private final static Point x2 = new Point("x2", -20);
private final static Point x3 = new Point("x3", -10, true);
private final static Point x4 = new Point("x4", -5, true);
private final static Point x5 = new Point("x5", 0);
private final static Point x6 = new Point("x6", 5);
private final static Point x7 = new Point("x7", 20);
private final static Point x8 = new Point("x8", 30);
private final static Point x9 = new Point("x9", 40);
private final static Point x10 = new Point("x10", 50);
@Before
public void setUp() throws Exception {
entrys.add(x1);
entrys.add(x2);
entrys.add(x3);
entrys.add(x4);
entrys.add(x5);
entrys.add(x6);
entrys.add(x7);
entrys.add(x8);
entrys.add(x9);
entrys.add(x10);
}
private void assertEdges(List<Edge<Point>> edges, Point ... points){
for (int i = 1; i < points.length; i++) {
if (i > edges.size()){
Assert.fail(String.format("Wrong edges count. Expected: %s Actual: %s", points.length-1, edges.size()));
}
Edge<Point> edge = edges.get(i-1);
Point expSource = points[i-1];
Point expTarget = points[i];
if (!edge.getSource().isEntry(expSource)){
Assert.fail(String.format("Edge start differed. Expected: %s Actual: %s", expSource, edge.getSource().getEntry()));
}
if (!edge.getTarget().isEntry(expTarget)){
Assert.fail(String.format("Edge end differed. Expected: %s Actual: %s", expTarget, edge.getTarget().getEntry()));
}
}
}
private void assertPaths(List<List<Edge<Point>>> paths, PPath... points) {
assertPaths(false, paths, points);
}
private void assertPaths(boolean saveOrder, List<List<Edge<Point>>> paths, PPath... points){
Collection<PPath> actual = new ArrayList<>(paths.size());
paths.forEach(p -> actual.add(PPath.of(p)));
if (saveOrder) {
TestUtil.assertCollectionEquals(actual, points);
} else {
TestUtil.assertCollectionContainAll(actual, points);
}
}
@Test
public void testGetPaths() throws Exception {
LOG.info("Start get paths test");
//max distance 5.126, 1 jump tank
Ship ship = new Ship();
ship.setMass(64);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(2); profile.setRefill(false);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4, x5 <-> x6
SimpleCollector paths = new SimpleCollector();
Crawler<Point> crawler = new Crawler<>(graph, paths::add);
crawler.findMin(x4, 10);
assertPaths(paths.get(), PPath.of(x5, x4));
paths.clear();
crawler.findMin(x6, 10);
assertPaths(paths.get(), PPath.of(x5, x6));
paths.clear();
crawler.findMin(x7, 10);
assertEquals(paths.get().size(), 0);
paths.clear();
}
@Test
public void testGetPaths2() throws Exception {
LOG.info("Start get paths test2");
//max distance 15.6, 1 jump tank
Ship ship = new Ship();
ship.setMass(18);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(3); profile.setRefill(false);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4 <-> x3 <-> x2, x5 <-> x6 <-> x7 <-> x8
// x5 <-> x3, x4 <-> x2, x3 <-> x6, x4 <-> x6
SimpleCollector paths = new SimpleCollector();
Crawler<Point> crawler = new Crawler<>(graph, paths::add);
crawler.findMin(x8, 10);
assertPaths(paths.get(), PPath.of(x5, x6, x7, x8));
paths.clear();
crawler.findMin(x7, 10);
assertPaths(paths.get(), PPath.of(x5, x6, x7), PPath.of(x5, x4, x6, x7), PPath.of(x5, x3, x6, x7));
paths.clear();
crawler.findMin(x7);
assertEquals(1, paths.get().size());
assertPaths(paths.get(), PPath.of(x5, x6, x7));
paths.clear();
crawler.findMin(x4, 20);
assertPaths(true, paths.get(), PPath.of(x5, x4), PPath.of(x5, x3, x4), PPath.of(x5, x6, x4),
PPath.of(x5, x6, x5, x4), PPath.of(x5, x4, x3, x4), PPath.of(x5, x4, x5, x4),
PPath.of(x5, x6, x3, x4), PPath.of(x5, x4, x6, x4),
PPath.of(x5, x3, x5, x4), PPath.of(x5, x3, x2, x4),
PPath.of(x5, x4, x2, x4), PPath.of(x5, x3, x6, x4)
);
paths.clear();
crawler.findMin(x5, 20);
assertPaths(paths.get(), PPath.of(x5, x4, x5), PPath.of(x5, x4, x6, x5), PPath.of(x5, x4, x3, x5),
PPath.of(x5, x6, x5), PPath.of(x5, x6, x4, x5), PPath.of(x5, x6, x3, x5), PPath.of(x5, x3, x5),
PPath.of(x5, x3, x4, x5), PPath.of(x5, x3, x6, x5));
paths.clear();
crawler.findFast(x8);
assertEdges(paths.get(0), x5, x6, x7, x8);
paths.clear();
crawler.findFast(x7, 10);
assertEdges(paths.get(0), x5, x6, x7);
assertPaths(paths.get(), PPath.of(x5, x6, x7), PPath.of(x5, x4, x6, x7), PPath.of(x5, x3, x6, x7));
paths.clear();
crawler.findFast(x4);
assertEdges(paths.get(0), x5, x4);
paths.clear();
}
@Test
public void testGetRefillPaths() throws Exception {
LOG.info("Start get refill paths");
//max distance 10.1, 1 jump tank
Ship ship = new Ship();
ship.setMass(30.3);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(3); profile.setRefill(false);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4 <- refill -> x3 <- refill -> x2, x5 <-> x6
// x5 <-> x3 <- refill -> x2, x5 <-> x4 <- refill -> x6
SimpleCollector paths = new SimpleCollector();
Crawler<Point> crawler = new Crawler<>(graph, paths::add);
crawler.findMin(x1, 10);
assertTrue(paths.get().isEmpty());
paths.clear();
crawler.findMin(x2, 10);
assertPaths(paths.get(), PPath.of(x5, x4, x3, x2), PPath.of(x5, x3, x2));
paths.clear();
crawler.findMin(x6, 10);
assertPaths(true, paths.get(), PPath.of(x5, x6), PPath.of(x5, x4, x6),
PPath.of(x5, x6, x5, x6), PPath.of(x5, x4, x5, x6),
PPath.of(x5, x3, x5, x6), PPath.of(x5, x3, x4, x6),
PPath.of(x5, x6, x4, x6));
paths.clear();
crawler.findFast(x2);
assertPaths(paths.get(), PPath.of(x5, x3, x2));
paths.clear();
}
@Test
public void testGetRefillPaths2() throws Exception {
LOG.info("Start get refill paths 2 ");
//max distance 15.6, 1 jump tank
Ship ship = new Ship();
ship.setMass(18);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(4);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4 <-> x3 - refill -> x2,
// x5 <-> x6 <-> x4 <-refill -> x2
// x5 <-> x3 <- refill -> x2
// x5 <-> x4 <- refill -> x6
SimpleCollector paths = new SimpleCollector();
Crawler<Point> crawler = new Crawler<>(graph, paths::add);
crawler.findMin(x1, 10);
assertTrue(paths.get().isEmpty());
paths.clear();
crawler.findMin(x2, 20);
assertPaths(paths.get(), PPath.of(x5, x3, x4, x2), PPath.of(x5, x3, x2),
PPath.of(x5, x4, x3, x2), PPath.of(x5, x4, x2), PPath.of(x5, x3, x5, x4, x2),
PPath.of(x5, x6, x4, x2), PPath.of(x5, x6, x4, x3, x2), PPath.of(x5, x4, x3, x4, x2),
PPath.of(x5, x4, x5, x4, x2), PPath.of(x5, x6, x5, x4, x2), PPath.of(x5, x3, x4, x3, x2),
PPath.of(x5, x3, x4, x3, x2), PPath.of(x5, x3, x4, x3, x2), PPath.of(x5, x3, x4, x3, x2));
paths.clear();
crawler.findMin(x6, 30);
assertPaths(paths.get(), PPath.of(x5, x6), PPath.of(x5, x4, x6),
PPath.of(x5, x3, x4, x6), PPath.of(x5, x3, x6), PPath.of(x5, x4, x3, x6),
PPath.of(x5, x3, x4, x3, x6), PPath.of(x5, x3, x4, x5, x6), PPath.of(x5, x3, x5, x6),
PPath.of(x5, x3, x5, x4, x6), PPath.of(x5, x4, x3, x4, x6), PPath.of(x5, x4, x3, x5, x6),
PPath.of(x5, x4, x5, x6), PPath.of(x5, x4, x5, x4, x6), PPath.of(x5, x4, x5, x3, x6),
PPath.of(x5, x6, x5, x6), PPath.of(x5, x6, x4, x6), PPath.of(x5, x4, x6, x5, x6),
PPath.of(x5, x6, x4, x5, x6), PPath.of(x5, x6, x5, x4, x6), PPath.of(x5, x6, x5, x3, x6),
PPath.of(x5, x4, x6, x4, x6), PPath.of(x5, x6, x4, x3, x6)
);
paths.clear();
crawler.findMin(x7, 10);
assertTrue(paths.get().isEmpty());
paths.clear();
crawler.findFast(x2);
assertPaths(paths.get(), PPath.of(x5, x3, x2));
paths.clear();
}
@After
public void tearDown() throws Exception {
entrys.clear();
}
private class SimpleCollector {
private List<List<Edge<Point>>> paths = new ArrayList<>();
public void add(List<Edge<Point>> path){
paths.add(path);
}
public List<List<Edge<Point>>> get() {
return paths;
}
public List<Edge<Point>> get(int indx) {
if (indx >= paths.size()) return Collections.emptyList();
return paths.get(indx);
}
public void clear(){
paths.clear();
}
}
}

View File

@@ -0,0 +1,202 @@
package ru.trader.analysis.graph;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.core.Profile;
import ru.trader.core.Ship;
import java.util.ArrayList;
public class GraphTest extends Assert {
private final static Logger LOG = LoggerFactory.getLogger(GraphTest.class);
private final static ArrayList<Point> entrys = new ArrayList<>();
private final static Point x1 = new Point("x1",-40);
private final static Point x2 = new Point("x2",-20);
private final static Point x3 = new Point("x3",-10, true);
private final static Point x4 = new Point("x4",-5, true);
private final static Point x5 = new Point("x5",0);
private final static Point x6 = new Point("x6",5);
private final static Point x7 = new Point("x7",20);
private final static Point x8 = new Point("x8",30);
private final static Point x9 = new Point("x9",40);
private final static Point x10 = new Point("x10",50);
@Before
public void setUp() throws Exception {
entrys.add(x1);
entrys.add(x2);
entrys.add(x3);
entrys.add(x4);
entrys.add(x5);
entrys.add(x6);
entrys.add(x7);
entrys.add(x8);
entrys.add(x9);
entrys.add(x10);
}
@Test
public void testBuild0() throws Exception {
LOG.info("Start graph build test0");
//max distance 4.95, 1 jump tank
Ship ship = new Ship();
ship.setMass(67);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(10);
profile.setRefill(false);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5
assertFalse(graph.isAccessible(x1));
assertFalse(graph.isAccessible(x2));
assertFalse(graph.isAccessible(x3));
assertFalse(graph.isAccessible(x4));
assertTrue(graph.isAccessible(x5));
assertFalse(graph.isAccessible(x6));
assertFalse(graph.isAccessible(x7));
assertFalse(graph.isAccessible(x8));
assertFalse(graph.isAccessible(x9));
assertFalse(graph.isAccessible(x10));
}
@Test
public void testBuild1() throws Exception {
LOG.info("Start graph build test1");
//max distance 5.167, 1 jump tank
Ship ship = new Ship();
ship.setMass(64);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(2);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4 <-refill-> x3, x5 -> x6
assertFalse(graph.isAccessible(x1));
assertFalse(graph.isAccessible(x2));
assertTrue(graph.isAccessible(x3));
assertTrue(graph.isAccessible(x4));
assertTrue(graph.isAccessible(x5));
assertTrue(graph.isAccessible(x6));
assertFalse(graph.isAccessible(x7));
assertFalse(graph.isAccessible(x8));
assertFalse(graph.isAccessible(x9));
assertFalse(graph.isAccessible(x10));
Vertex<Point> x = graph.getVertex(x5);
// x5 -> x4, x5 -> x6
checkEdges(x, new Point[]{x4, x6}, new Point[]{x1, x2, x3, x7, x8, x9, x10});
// x4 -> x5
x = graph.getVertex(x4);
checkEdges(x, new Point[]{x5, x3}, new Point[]{x1, x2, x6, x7, x8, x9, x10});
// x6 <- x5
x = graph.getVertex(x6);
checkEdges(x, new Point[]{}, new Point[]{x1, x2, x3, x4, x5, x7, x8, x9, x10});
}
private void checkEdges(Vertex<Point> vertex, Point[] trueEdge, Point[] falseEdge){
for (Point point : trueEdge) {
assertTrue(String.format("%s must have edge to %s", vertex, point), vertex.isConnected(point));
}
for (Point point : falseEdge) {
assertFalse(String.format("%s must not have edge to %s", vertex, point), vertex.isConnected(point));
}
}
@Test
public void testBuild2() throws Exception {
LOG.info("Start graph build test2");
//max distance 5.167, 1 jump tank
Ship ship = new Ship();
ship.setMass(64);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(3);profile.setRefill(false);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4 <-> x3, x5 <-> x6
assertFalse(graph.isAccessible(x1));
assertFalse(graph.isAccessible(x2));
assertTrue(graph.isAccessible(x3));
assertTrue(graph.isAccessible(x4));
assertTrue(graph.isAccessible(x5));
assertTrue(graph.isAccessible(x6));
assertFalse(graph.isAccessible(x7));
assertFalse(graph.isAccessible(x8));
assertFalse(graph.isAccessible(x9));
assertFalse(graph.isAccessible(x10));
Vertex<Point> x = graph.getVertex(x5);
// x5 -> x4, x5 -> x6
checkEdges(x, new Point[]{x4, x6}, new Point[]{x1, x2, x3, x7, x8, x9, x10});
// x3 -> x4
x = graph.getVertex(x3);
checkEdges(x, new Point[]{x4}, new Point[]{x1, x2, x5, x6, x7, x8, x9, x10});
// x4 -> x5, x4 -> x3
x = graph.getVertex(x4);
checkEdges(x, new Point[]{x3, x5}, new Point[]{x1, x2, x6, x7, x8, x9, x10});
// x6 -> x5
x = graph.getVertex(x6);
checkEdges(x, new Point[]{x5}, new Point[]{x1, x2, x3, x4, x7, x8, x9, x10});
}
@Test
public void testBuild4() throws Exception {
LOG.info("Start graph build test4");
//max distance 15.6, 1 jump tank
Ship ship = new Ship();
ship.setMass(18);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(3); profile.setRefill(false);
LOG.info("Ship = {}, Jumps = {}", profile.getShip(), profile.getJumps());
ConnectibleGraph<Point> graph = new ConnectibleGraph<>(profile);
graph.build(x5, entrys);
// x5 <-> x4 <-> x3 -> x2, x5 <-> x6 <-> x7 -> x8
// x5 <-> x3, x5 <-> x4 <-> x2, x3 <-> x6, x4 <-> x6
assertFalse(graph.isAccessible(x1));
assertTrue(graph.isAccessible(x2));
assertTrue(graph.isAccessible(x3));
assertTrue(graph.isAccessible(x4));
assertTrue(graph.isAccessible(x5));
assertTrue(graph.isAccessible(x6));
assertTrue(graph.isAccessible(x7));
assertTrue(graph.isAccessible(x8));
assertFalse(graph.isAccessible(x9));
assertFalse(graph.isAccessible(x10));
Vertex<Point> x = graph.getVertex(x5);
// x5 -> x4, x5 -> x3, x5 -> x6
checkEdges(x, new Point[]{x3, x4, x6}, new Point[]{x1, x2, x7, x8, x9, x10});
// x2 -> x3, x2 -> x4
x = graph.getVertex(x2);
checkEdges(x, new Point[]{x3, x4}, new Point[]{x1, x5, x6, x7, x8, x9, x10});
// x3 -> x4, x3 -> x2, x3 -> x5, x3 -> x6
x = graph.getVertex(x3);
checkEdges(x, new Point[]{x2, x4, x5, x6}, new Point[]{x1, x7, x8, x9, x10});
// x4 -> x5, x4 -> x3, x4 -> x2, x4 -> x6
x = graph.getVertex(x4);
checkEdges(x, new Point[]{x2, x3, x5, x6}, new Point[]{x1, x7, x8, x9, x10});
// x6 -> x5, x6 -> x7, x6 -> x3, x6 -> x4
x = graph.getVertex(x6);
checkEdges(x, new Point[]{x5, x7, x3, x4}, new Point[]{x1, x2, x8, x9, x10});
// x7 -> x6, x7 -> x8
x = graph.getVertex(x7);
checkEdges(x, new Point[]{x6, x8}, new Point[]{x1, x2, x3, x4, x5, x9, x10});
// x8 <- x7
x = graph.getVertex(x8);
checkEdges(x, new Point[]{}, new Point[]{x1, x2, x3, x4, x5, x6, x7, x9, x10});
}
@After
public void tearDown() throws Exception {
entrys.clear();
}
}

View File

@@ -0,0 +1,53 @@
package ru.trader.analysis.graph;
import java.util.Arrays;
import java.util.List;
public class PPath<T> {
private final T[] points;
private PPath(T[] points) {
this.points = points;
}
private PPath(List<Edge<T>> edges) {
//noinspection unchecked
points = (T[]) new Object[edges.size()+1];
for (int i = 0; i < edges.size(); i++) {
Edge<T> edge = edges.get(i);
if (i > 0 && !points[i].equals(edge.getSource().getEntry())){
throw new IllegalArgumentException(String.format("Edges by index %d and %d is not linked", i-1, i));
} else {
points[i] = edge.getSource().getEntry();
}
points[i+1] = edge.getTarget().getEntry();
}
}
@SafeVarargs
public static <V> PPath<V> of(V... entries){
return new PPath<>(entries);
}
public static <V> PPath<V> of(List<Edge<V>> edges){
return new PPath<>(edges);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PPath)) return false;
PPath pPath = (PPath) o;
return Arrays.equals(points, pPath.points);
}
@Override
public int hashCode() {
return Arrays.hashCode(points);
}
@Override
public String toString() {
return Arrays.toString(points);
}
}

View File

@@ -1,6 +1,7 @@
package ru.trader.graph;
package ru.trader.analysis.graph;
import org.jetbrains.annotations.NotNull;
import ru.trader.graph.Connectable;
import java.util.Objects;

View File

@@ -4,4 +4,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p: %d{dd.MM.yyyy HH:mm:ss} (%F:%L) - %m%n
#log4j.logger.ru.trader.analysis.graph.Crawler = TRACE