Archived
0

use custom function for checking targets

This commit is contained in:
iMoHax
2015-07-01 15:56:54 +03:00
parent 3f2ed90df8
commit 17f4f1f60c
3 changed files with 90 additions and 39 deletions

View File

@@ -8,18 +8,24 @@ import ru.trader.graph.Connectable;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class CCrawler<T extends Connectable<T>> extends Crawler<T> { public class CCrawler<T extends Connectable<T>> extends Crawler<T> {
private final static Logger LOG = LoggerFactory.getLogger(CCrawler.class); private final static Logger LOG = LoggerFactory.getLogger(CCrawler.class);
private double startFuel; private double startFuel;
public CCrawler(ConnectibleGraph<T> graph, Consumer<List<Edge<T>>> onFoundFunc) { public CCrawler(Graph<T> graph, Function<List<Edge<T>>, Boolean> onFoundFunc) {
super(graph, onFoundFunc); super(graph, onFoundFunc);
startFuel = getShip().getTank(); startFuel = getShip().getTank();
} }
public CCrawler(Graph<T> graph, Function<Edge<T>, Boolean> isFoundFunc, Function<List<Edge<T>>, Boolean> onFoundFunc) {
super(graph, isFoundFunc, onFoundFunc);
startFuel = getShip().getTank();
}
protected Ship getShip(){ protected Ship getShip(){
return ((ConnectibleGraph<T>)graph).getShip(); return ((ConnectibleGraph<T>)graph).getShip();
} }
@@ -39,7 +45,7 @@ public class CCrawler<T extends Connectable<T>> extends Crawler<T> {
} }
@Override @Override
protected CCostTraversalEntry travers(CostTraversalEntry entry, Edge<T> edge, T target) { protected CCostTraversalEntry travers(CostTraversalEntry entry, Edge<T> edge) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
CCostTraversalEntry cEntry = (CCostTraversalEntry)entry; CCostTraversalEntry cEntry = (CCostTraversalEntry)entry;
ConnectibleEdge<T> cEdge = (ConnectibleEdge<T>) edge; ConnectibleEdge<T> cEdge = (ConnectibleEdge<T>) edge;

View File

@@ -8,7 +8,7 @@ import ru.trader.analysis.LimitedQueue;
import java.util.*; import java.util.*;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveAction;
import java.util.function.Consumer; import java.util.function.Function;
public class Crawler<T> { public class Crawler<T> {
private final static Logger LOG = LoggerFactory.getLogger(Crawler.class); private final static Logger LOG = LoggerFactory.getLogger(Crawler.class);
@@ -17,13 +17,23 @@ public class Crawler<T> {
private final static int SPLIT_SIZE = 3; private final static int SPLIT_SIZE = 3;
protected final Graph<T> graph; protected final Graph<T> graph;
private final Consumer<List<Edge<T>>> onFoundFunc; private final Function<List<Edge<T>>,Boolean> onFoundFunc;
private final Function<Edge<T>,Boolean> isFound;
private T target;
private int maxSize; private int maxSize;
public Crawler(Graph<T> graph, Consumer<List<Edge<T>>> onFoundFunc) { public Crawler(Graph<T> graph, Function<List<Edge<T>>, Boolean> onFoundFunc) {
this.graph = graph; this.graph = graph;
maxSize = graph.getRoot().getLevel(); maxSize = graph.getRoot().getLevel();
this.onFoundFunc = onFoundFunc; this.onFoundFunc = onFoundFunc;
this.isFound = this::isTarget;
}
public Crawler(Graph<T> graph, Function<Edge<T>,Boolean> isFoundFunc, Function<List<Edge<T>>,Boolean> onFoundFunc) {
this.graph = graph;
maxSize = graph.getRoot().getLevel();
this.onFoundFunc = onFoundFunc;
this.isFound = isFoundFunc;
} }
protected List<Edge<T>> getCopyList(Traversal<T> head, Edge<T> tail){ protected List<Edge<T>> getCopyList(Traversal<T> head, Edge<T> tail){
@@ -33,6 +43,29 @@ public class Crawler<T> {
return res; return res;
} }
public T getTarget() {
return target;
}
private void setTarget(T target) {
if (this.target != null && target != null){
throw new IllegalStateException("Crawler is busy");
}
this.target = target;
}
private boolean isTarget(Edge<T> edge){
return edge.isConnect(this.target);
}
protected boolean isFound(Edge<T> edge){
return isFound.apply(edge);
}
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) { public void setMaxSize(int maxSize) {
this.maxSize = maxSize; this.maxSize = maxSize;
} }
@@ -60,14 +93,16 @@ public class Crawler<T> {
Optional<Vertex<T>> t = graph.getVertex(target); Optional<Vertex<T>> t = graph.getVertex(target);
int found = 0; int found = 0;
if (t.isPresent()) { if (t.isPresent()) {
if (count > 1) { setTarget(target);
if (count > 1 || s.isEntry(target)) {
int maxDeep = maxSize - (s.isEntry(target) ? graph.getMinJumps() * 2 : graph.getMinJumps()); int maxDeep = maxSize - (s.isEntry(target) ? graph.getMinJumps() * 2 : graph.getMinJumps());
found = bfs(start(s), target, maxDeep, count); found = bfs(start(s), maxDeep, count);
} else { } else {
found = dfs(start(s), target, t.get().getLevel() + 1, count); found = dfs(start(s), t.get().getLevel() + 1, count);
} }
} }
LOG.debug("Found {} paths", found); LOG.debug("Found {} paths", found);
setTarget(null);
} }
public void findMin(T target){ public void findMin(T target){
@@ -93,46 +128,51 @@ public class Crawler<T> {
Optional<Vertex<T>> t = graph.getVertex(target); Optional<Vertex<T>> t = graph.getVertex(target);
int found = 0; int found = 0;
if (t.isPresent()) { if (t.isPresent()) {
setTarget(target);
int maxDeep = s.isEntry(target) ? maxSize - graph.getMinJumps() * 2 : graph.getMinLevel(); int maxDeep = s.isEntry(target) ? maxSize - graph.getMinJumps() * 2 : graph.getMinLevel();
if (maxDeep < 0) maxDeep = 0; if (maxDeep < 0) maxDeep = 0;
if (maxSize - maxDeep <= SPLIT_SIZE){ if (maxSize - maxDeep <= SPLIT_SIZE){
found = ucs(start(s), target, maxDeep, count); found = ucs(start(s), maxDeep, count);
} else { } else {
found = ucs2(start(s), target, maxDeep, count); found = ucs2(start(s), maxDeep, count);
} }
} }
LOG.debug("Found {} paths", found); LOG.debug("Found {} paths", found);
setTarget(null);
} }
protected CostTraversalEntry start(Vertex<T> vertex){ protected CostTraversalEntry start(Vertex<T> vertex){
return new CostTraversalEntry(vertex); return new CostTraversalEntry(vertex);
} }
protected CostTraversalEntry travers(CostTraversalEntry entry, Edge<T> edge, T target){ protected CostTraversalEntry travers(CostTraversalEntry entry, Edge<T> edge){
return new CostTraversalEntry(entry, edge); return new CostTraversalEntry(entry, edge);
} }
private int dfs(CostTraversalEntry entry, T target, int deep, int count) { private int dfs(CostTraversalEntry entry, int deep, int count) {
int found = 0; int found = 0;
Vertex<T> source = entry.vertex; Vertex<T> source = entry.vertex;
LOG.trace("DFS from {} to {}, deep {}, count {}, entry {}", source, target, deep, count, entry); LOG.trace("DFS from {} to {}, deep {}, count {}, entry {}", source, target, deep, count, entry);
boolean stop = false;
if (deep == source.getLevel()){ if (deep == source.getLevel()){
for (Edge<T> next : entry.getEdges()) { for (Edge<T> next : entry.getEdges()) {
if (next.isConnect(target)){ if (isFound(next)){
List<Edge<T>> res = getCopyList(entry, next); List<Edge<T>> res = getCopyList(entry, next);
LOG.debug("Last edge find, path {}", res); LOG.debug("Last edge found, path {}", res);
onFoundFunc.accept(res);
found++; found++;
if (!onFoundFunc.apply(res)){
stop = true;
}
break; break;
} }
} }
} }
if (found < count){ if (!stop && found < count){
if (deep < source.getLevel() && entry.size() < maxSize-1) { if (deep < source.getLevel() && entry.size() < maxSize-1) {
LOG.trace("Search around"); LOG.trace("Search around");
for (Edge<T> edge : entry.getEdges()) { for (Edge<T> edge : entry.getEdges()) {
if (edge.getTarget().isSingle()) continue; if (edge.getTarget().isSingle()) continue;
found += dfs(travers(entry, edge, target), target, deep, count-found); found += dfs(travers(entry, edge), deep, count-found);
if (found >= count) break; if (found >= count) break;
} }
} }
@@ -140,7 +180,7 @@ public class Crawler<T> {
return found; return found;
} }
private int bfs(CostTraversalEntry root, T target, int deep, int count) { private int bfs(CostTraversalEntry root, int deep, int count) {
LOG.trace("BFS from {} to {}, deep {}, count {}", root.vertex, target, deep, count); LOG.trace("BFS from {} to {}, deep {}, count {}", root.vertex, target, deep, count);
int found = 0; int found = 0;
LinkedList<CostTraversalEntry> queue = new LinkedList<>(); LinkedList<CostTraversalEntry> queue = new LinkedList<>();
@@ -157,16 +197,18 @@ public class Crawler<T> {
Iterator<Edge<T>> iterator = entry.iterator(); Iterator<Edge<T>> iterator = entry.iterator();
while (iterator.hasNext()){ while (iterator.hasNext()){
Edge<T> edge = iterator.next(); Edge<T> edge = iterator.next();
if (edge.isConnect(target)){ if (isFound(edge)){
List<Edge<T>> res = getCopyList(entry, edge); List<Edge<T>> res = getCopyList(entry, edge);
LOG.debug("Last edge find, path {}", res); LOG.debug("Last edge found, path {}", res);
onFoundFunc.accept(res);
found++; found++;
if (!onFoundFunc.apply(res)){
break;
}
} }
if (found >= count) break; if (found >= count) break;
if (edge.getTarget().isSingle()) continue; if (edge.getTarget().isSingle()) continue;
if (deep < source.getLevel()) { if (deep < source.getLevel()) {
CostTraversalEntry nextEntry = travers(entry, edge, target); CostTraversalEntry nextEntry = travers(entry, edge);
nextEntry.sort(); nextEntry.sort();
queue.add(nextEntry); queue.add(nextEntry);
} }
@@ -175,7 +217,7 @@ public class Crawler<T> {
return found; return found;
} }
private int ucs(CostTraversalEntry root, T target, int deep, int count) { private int ucs(CostTraversalEntry root, int deep, int count) {
LOG.trace("UCS from {} to {}, deep {}, count {}", root.vertex, target, deep, count); LOG.trace("UCS from {} to {}, deep {}, count {}", root.vertex, target, deep, count);
int found = 0; int found = 0;
PriorityQueue<CostTraversalEntry> queue = new PriorityQueue<>(); PriorityQueue<CostTraversalEntry> queue = new PriorityQueue<>();
@@ -185,11 +227,13 @@ public class Crawler<T> {
LOG.trace("Check path entry {}, weight {}", entry, entry.weight); LOG.trace("Check path entry {}, weight {}", entry, entry.weight);
Edge<T> edge = entry.getEdge(); Edge<T> edge = entry.getEdge();
if (edge != null) { if (edge != null) {
if (edge.isConnect(target)) { if (isFound(edge)) {
List<Edge<T>> res = entry.toEdges(); List<Edge<T>> res = entry.toEdges();
LOG.debug("Path found {}", res); LOG.debug("Path found {}", res);
onFoundFunc.accept(res);
found++; found++;
if (!onFoundFunc.apply(res)){
break;
}
if (found >= count) break; if (found >= count) break;
} }
if (edge.getTarget().isSingle()){ if (edge.getTarget().isSingle()){
@@ -207,14 +251,14 @@ public class Crawler<T> {
boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel(); boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel();
if (canDeep || isTarget){ if (canDeep || isTarget){
LOG.trace("Add edge {} to queue", edge); LOG.trace("Add edge {} to queue", edge);
queue.add(travers(entry, edge, target)); queue.add(travers(entry, edge));
} }
} }
} }
return found; return found;
} }
private int ucs2(CostTraversalEntry root, T target, int deep, int count) { private int ucs2(CostTraversalEntry root, int deep, int count) {
LOG.trace("UCS2 from {} to {}, deep {}, count {}", root.vertex, target, deep, count); LOG.trace("UCS2 from {} to {}, deep {}, count {}", root.vertex, target, deep, count);
int found = 0; int found = 0;
double limit = Double.MAX_VALUE; double limit = Double.MAX_VALUE;
@@ -236,8 +280,10 @@ public class Crawler<T> {
if (isTarget) { if (isTarget) {
List<Edge<T>> res = entry.toEdges(); List<Edge<T>> res = entry.toEdges();
LOG.trace("Path found {}", res); LOG.trace("Path found {}", res);
onFoundFunc.accept(res);
found++; found++;
if (!onFoundFunc.apply(res)){
break;
}
if (found >= count) break; if (found >= count) break;
CTEntrySupport next = targetsQueue.peek(); CTEntrySupport next = targetsQueue.peek();
limit = next != null ? next.entry.getWeight() : Double.MAX_VALUE; limit = next != null ? next.entry.getWeight() : Double.MAX_VALUE;
@@ -252,7 +298,7 @@ public class Crawler<T> {
LOG.trace("Is limit deep"); LOG.trace("Is limit deep");
continue; continue;
} }
DFS task = new DFS(curr, target, deep, count - found, limit); DFS task = new DFS(curr, deep, count - found, limit);
POOL.invoke(task); POOL.invoke(task);
targetsQueue.addAll(task.getTargets()); targetsQueue.addAll(task.getTargets());
queue.addAll(task.getQueue()); queue.addAll(task.getQueue());
@@ -322,20 +368,18 @@ public class Crawler<T> {
private final CTEntrySupport root; private final CTEntrySupport root;
private final int count; private final int count;
private final int deep; private final int deep;
private final T target;
private final Collection<CTEntrySupport> queue; private final Collection<CTEntrySupport> queue;
private final Collection<CTEntrySupport> targets; private final Collection<CTEntrySupport> targets;
private final ArrayList<DFS> subTasks; private final ArrayList<DFS> subTasks;
private final boolean isSubTask; private final boolean isSubTask;
private double limit; private double limit;
private DFS(CTEntrySupport root, T target, int deep, int count, double limit) { private DFS(CTEntrySupport root, int deep, int count, double limit) {
this(root, target, deep, count, limit, false); this(root, deep, count, limit, false);
} }
private DFS(CTEntrySupport root, T target, int deep, int count, double limit, boolean subtask) { private DFS(CTEntrySupport root, int deep, int count, double limit, boolean subtask) {
this.root = root; this.root = root;
this.target = target;
this.deep = deep; this.deep = deep;
this.count = count; this.count = count;
this.limit = limit; this.limit = limit;
@@ -368,10 +412,10 @@ public class Crawler<T> {
Edge<T> edge = curr.next(); Edge<T> edge = curr.next();
CostTraversalEntry entry = curr.entry; CostTraversalEntry entry = curr.entry;
LOG.trace("Check edge {}, entry {}, weight {}", edge, entry, entry.weight); LOG.trace("Check edge {}, entry {}, weight {}", edge, entry, entry.weight);
boolean isTarget = edge.isConnect(target); boolean isTarget = isFound(edge);
boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel() && entry.size() < maxSize-1; boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel() && entry.size() < maxSize-1;
if (canDeep || isTarget){ if (canDeep || isTarget){
CostTraversalEntry nextEntry = travers(entry, edge, target); CostTraversalEntry nextEntry = travers(entry, edge);
nextEntry.sort(); nextEntry.sort();
curr = new CTEntrySupport(curr, nextEntry); curr = new CTEntrySupport(curr, nextEntry);
if (isTarget){ if (isTarget){
@@ -413,7 +457,7 @@ public class Crawler<T> {
private boolean addSubTask(CTEntrySupport entry){ private boolean addSubTask(CTEntrySupport entry){
if (subTasks.size() < THRESHOLD){ if (subTasks.size() < THRESHOLD){
DFS subTask = new DFS(entry, target, deep, count, limit, true); DFS subTask = new DFS(entry, deep, count, limit, true);
subTask.fork(); subTask.fork();
subTasks.add(subTask); subTasks.add(subTask);
return true; return true;

View File

@@ -12,8 +12,9 @@ import java.util.stream.Collectors;
public class SimpleCollector<T> { public class SimpleCollector<T> {
private List<List<Edge<T>>> paths = new ArrayList<>(); private List<List<Edge<T>>> paths = new ArrayList<>();
public void add(List<Edge<T>> path){ public boolean add(List<Edge<T>> path){
paths.add(path); paths.add(path);
return true;
} }
public List<List<Edge<T>>> get() { public List<List<Edge<T>>> get() {