Archived
0

change predicate to route specification for depending targets

This commit is contained in:
iMoHax
2015-07-21 15:34:15 +03:00
parent 5893c99b71
commit 64b82dd76f
8 changed files with 152 additions and 46 deletions

View File

@@ -9,7 +9,6 @@ import ru.trader.core.Profile;
import ru.trader.core.Vendor; import ru.trader.core.Vendor;
import java.util.*; import java.util.*;
import java.util.function.Predicate;
public class RouteSearcher { public class RouteSearcher {
private final static Logger LOG = LoggerFactory.getLogger(RouteSearcher.class); private final static Logger LOG = LoggerFactory.getLogger(RouteSearcher.class);
@@ -25,15 +24,14 @@ public class RouteSearcher {
} }
public List<List<Edge<Place>>> getPaths(Place from, Collection<Place> places){ public List<List<Edge<Place>>> getPaths(Place from, Collection<Place> places){
Predicate<Edge<Place>> isFoundFunc = e -> places.parallelStream().filter(e::isConnect).findFirst().isPresent(); return search(from, from, places, scorer.getProfile().getRoutesCount(), RouteSpecificationByTargets.any(places));
return search(from, from, places, scorer.getProfile().getRoutesCount(), isFoundFunc);
} }
public List<List<Edge<Place>>> getPaths(Place from, Place to, Collection<Place> places){ public List<List<Edge<Place>>> getPaths(Place from, Place to, Collection<Place> places){
return search(from, to, places, scorer.getProfile().getRoutesCount(), null); return search(from, to, places, scorer.getProfile().getRoutesCount(), null);
} }
private List<List<Edge<Place>>> search(Place source, Place target, Collection<Place> places, int count, Predicate<Edge<Place>> isFoundFunc){ private List<List<Edge<Place>>> search(Place source, Place target, Collection<Place> places, int count, RouteSpecification<Place> specification){
Profile profile = scorer.getProfile(); Profile profile = scorer.getProfile();
LOG.trace("Start search path from {} to {} ", source, target); LOG.trace("Start search path from {} to {} ", source, target);
ConnectibleGraph<Place> graph = new ConnectibleGraph<>(profile); ConnectibleGraph<Place> graph = new ConnectibleGraph<>(profile);
@@ -41,7 +39,7 @@ public class RouteSearcher {
graph.build(source, places); graph.build(source, places);
LOG.trace("Graph is builds"); LOG.trace("Graph is builds");
List<List<Edge<Place>>> paths = new ArrayList<>(); List<List<Edge<Place>>> paths = new ArrayList<>();
Crawler<Place> crawler = isFoundFunc != null ? new CCrawler<>(graph, isFoundFunc, paths::add) : new CCrawler<>(graph, paths::add); Crawler<Place> crawler = specification != null ? new CCrawler<>(graph, specification, paths::add) : new CCrawler<>(graph, paths::add);
crawler.setMaxSize(profile.getJumps()); crawler.setMaxSize(profile.getJumps());
if (profile.getPathPriority() == Profile.PATH_PRIORITY.FAST){ if (profile.getPathPriority() == Profile.PATH_PRIORITY.FAST){
crawler.findFast(target, count); crawler.findFast(target, count);
@@ -58,18 +56,17 @@ public class RouteSearcher {
public List<Route> getRoutes(Collection<Vendor> fVendors, Collection<Vendor> toVendors, Collection<Vendor> vendors){ public List<Route> getRoutes(Collection<Vendor> fVendors, Collection<Vendor> toVendors, Collection<Vendor> vendors){
List<Route> res = new LimitedQueue<>(scorer.getProfile().getRoutesCount()); List<Route> res = new LimitedQueue<>(scorer.getProfile().getRoutesCount());
int count = (int) Math.ceil(scorer.getProfile().getRoutesCount() / fVendors.size()); int count = (int) Math.ceil(scorer.getProfile().getRoutesCount() / fVendors.size());
Predicate<Edge<Vendor>> isFoundFunc = e -> toVendors.parallelStream().filter(e::isConnect).findFirst().isPresent(); RouteSpecification<Vendor> specification = RouteSpecificationByTargets.any(toVendors);
for (Vendor fromVendor : fVendors) { for (Vendor fromVendor : fVendors) {
count = count / toVendors.size(); count = count / toVendors.size();
Collection<Route> routes = search(fromVendor, fromVendor, vendors, count, isFoundFunc); Collection<Route> routes = search(fromVendor, fromVendor, vendors, count, specification);
res.addAll(routes); res.addAll(routes);
} }
return res; return res;
} }
public List<Route> getRoutes(Vendor from, Collection<Vendor> vendors){ public List<Route> getRoutes(Vendor from, Collection<Vendor> vendors){
Predicate<Edge<Vendor>> isFoundFunc = e -> vendors.parallelStream().filter(e::isConnect).findFirst().isPresent(); return search(from, from, vendors, scorer.getProfile().getRoutesCount(), RouteSpecificationByTargets.any(vendors));
return search(from, from, vendors, scorer.getProfile().getRoutesCount(), isFoundFunc);
} }
public List<Route> getRoutes(Vendor from, Vendor to, Collection<Vendor> vendors){ public List<Route> getRoutes(Vendor from, Vendor to, Collection<Vendor> vendors){
@@ -80,14 +77,14 @@ public class RouteSearcher {
return search(source, target, vendors, count, null); return search(source, target, vendors, count, null);
} }
private List<Route> search(Vendor source, Vendor target, Collection<Vendor> vendors, int count, Predicate<Edge<Vendor>> isFoundFunc){ private List<Route> search(Vendor source, Vendor target, Collection<Vendor> vendors, int count, RouteSpecification<Vendor> specification){
LOG.trace("Start search route from {} to {}", source, target); LOG.trace("Start search route from {} to {}", source, target);
VendorsGraph vGraph = new VendorsGraph(scorer); VendorsGraph vGraph = new VendorsGraph(scorer);
LOG.trace("Build vendors graph"); LOG.trace("Build vendors graph");
vGraph.build(source, vendors); vGraph.build(source, vendors);
LOG.trace("Graph is builds"); LOG.trace("Graph is builds");
RouteCollector collector = new RouteCollector(); RouteCollector collector = new RouteCollector();
Crawler<Vendor> crawler = isFoundFunc != null ? vGraph.crawler(isFoundFunc, collector::add) : vGraph.crawler(collector::add); Crawler<Vendor> crawler = specification != null ? vGraph.crawler(specification, collector::add) : vGraph.crawler(collector::add);
crawler.setMaxSize(scorer.getProfile().getLands()); crawler.setMaxSize(scorer.getProfile().getLands());
crawler.findMin(target, count); crawler.findMin(target, count);
return collector.get(); return collector.get();

View File

@@ -0,0 +1,21 @@
package ru.trader.analysis;
import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.Traversal;
public interface RouteSpecification<T> {
public boolean specified(Edge<T> edge, Traversal<T> entry);
default RouteSpecification<T> and(final RouteSpecification<T> other){
return (edge, entry) -> RouteSpecification.this.specified(edge, entry) && other.specified(edge, entry);
}
default RouteSpecification<T> or(final RouteSpecification<T> other){
return (edge, entry) -> RouteSpecification.this.specified(edge, entry) || other.specified(edge, entry);
}
default RouteSpecification<T> negate(){
return (edge, entry) -> !specified(edge, entry);
}
}

View File

@@ -0,0 +1,17 @@
package ru.trader.analysis;
import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.Traversal;
public class RouteSpecificationByTarget<T> implements RouteSpecification<T> {
protected final T target;
public RouteSpecificationByTarget(T target) {
this.target = target;
}
@Override
public boolean specified(Edge<T> edge, Traversal<T> entry) {
return edge.isConnect(target);
}
}

View File

@@ -0,0 +1,52 @@
package ru.trader.analysis;
import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.Traversal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class RouteSpecificationByTargets<T> implements RouteSpecification<T> {
protected final Collection<T> targets;
protected final boolean all;
private RouteSpecificationByTargets(Collection<T> targets, boolean all) {
this.all = all;
this.targets = new ArrayList<>(targets);
}
@Override
public boolean specified(Edge<T> edge, Traversal<T> entry) {
return all ? containsAll(edge, entry) : containsAny(edge, entry);
}
private boolean containsAll(Edge<T> edge, Traversal<T> entry) {
T obj = edge.getTarget().getEntry();
Collection<T> set = new ArrayList<>(targets.size());
set.add(obj);
entry.routeIterator().forEachRemaining(e -> set.add(e.getTarget().getEntry()));
return targets.containsAll(set);
}
private boolean containsAny(Edge<T> edge, Traversal<T> entry) {
T obj = edge.getTarget().getEntry();
if (targets.contains(obj)) return true;
Iterator<Edge<T>> iterator = entry.routeIterator();
while (iterator.hasNext()){
if (targets.contains(iterator.next().getTarget().getEntry())){
return true;
}
}
return false;
}
public static <T> RouteSpecificationByTargets<T> all(Collection<T> targets){
return new RouteSpecificationByTargets<>(targets, true);
}
public static <T> RouteSpecificationByTargets<T> any(Collection<T> targets){
return new RouteSpecificationByTargets<>(targets, false);
}
}

View File

@@ -34,8 +34,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
return new VendorsCrawler(onFoundFunc); return new VendorsCrawler(onFoundFunc);
} }
public VendorsCrawler crawler(Predicate<Edge<Vendor>> isFoundFunc,Predicate<List<Edge<Vendor>>> onFoundFunc){ public VendorsCrawler crawler(RouteSpecification<Vendor> specification, Predicate<List<Edge<Vendor>>> onFoundFunc){
return new VendorsCrawler(isFoundFunc, onFoundFunc); return new VendorsCrawler(specification, onFoundFunc);
} }
@Override @Override
@@ -514,8 +514,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
startBalance = getProfile().getBalance(); startBalance = getProfile().getBalance();
} }
protected VendorsCrawler(Predicate<Edge<Vendor>> isFoundFunc, Predicate<List<Edge<Vendor>>> onFoundFunc) { protected VendorsCrawler(RouteSpecification<Vendor> specification, Predicate<List<Edge<Vendor>>> onFoundFunc) {
super(VendorsGraph.this, isFoundFunc, onFoundFunc); super(VendorsGraph.this, specification, onFoundFunc);
startFuel = getShip().getTank(); startFuel = getShip().getTank();
startBalance = getProfile().getBalance(); startBalance = getProfile().getBalance();
} }
@@ -563,7 +563,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
protected boolean check(Edge<Vendor> e){ protected boolean check(Edge<Vendor> e){
VendorsBuildEdge edge = (VendorsBuildEdge) e; VendorsBuildEdge edge = (VendorsBuildEdge) e;
return fuel <= edge.getMaxFuel() && (fuel >= edge.getMinFuel() || edge.getSource().getEntry().canRefill()) && (edge.getProfit() > 0 || isFound(edge)); return fuel <= edge.getMaxFuel() && (fuel >= edge.getMinFuel() || edge.getSource().getEntry().canRefill())
&& (edge.getProfit() > 0 || isFound(edge, this));
} }
protected VendorsEdge wrap(Edge<Vendor> e) { protected VendorsEdge wrap(Edge<Vendor> e) {
@@ -574,21 +575,14 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
@Override @Override
public double getWeight() { public double getWeight() {
if (weight == null){ if (weight == null){
VendorsEdge edge = (VendorsEdge) getEdge();
Optional<Traversal<Vendor>> head = getHead();
double profit = 0; double time = 0; double profit = 0; double time = 0;
if (edge != null){ Iterator<Edge<Vendor>> iterator = routeIterator();
profit = edge.getProfitByTonne(); while (iterator.hasNext()){
time = edge.getTime(); VendorsEdge edge = (VendorsEdge)iterator.next();
}
while (head.isPresent()){
VendorsTraversalEntry hEntry = (VendorsTraversalEntry) head.get();
edge = (VendorsEdge) hEntry.getEdge();
if (edge != null){ if (edge != null){
profit += edge.getProfitByTonne(); profit += edge.getProfitByTonne();
time += edge.getTime(); time += edge.getTime();
} }
head = hEntry.getHead();
} }
weight = profit > 1 ? time / profit : time; weight = profit > 1 ? time / profit : time;
} }

View File

@@ -2,6 +2,7 @@ package ru.trader.analysis.graph;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ru.trader.analysis.RouteSpecification;
import ru.trader.core.Profile; import ru.trader.core.Profile;
import ru.trader.core.Ship; import ru.trader.core.Ship;
import ru.trader.graph.Connectable; import ru.trader.graph.Connectable;
@@ -20,8 +21,8 @@ public class CCrawler<T extends Connectable<T>> extends Crawler<T> {
startFuel = getShip().getTank(); startFuel = getShip().getTank();
} }
public CCrawler(ConnectibleGraph<T> graph, Predicate<Edge<T>> isFoundFunc, Predicate<List<Edge<T>>> onFoundFunc) { public CCrawler(ConnectibleGraph<T> graph, RouteSpecification<T> specification, Predicate<List<Edge<T>>> onFoundFunc) {
super(graph, isFoundFunc, onFoundFunc); super(graph, specification, onFoundFunc);
startFuel = getShip().getTank(); startFuel = getShip().getTank();
} }

View File

@@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ru.trader.analysis.LimitedQueue; import ru.trader.analysis.LimitedQueue;
import ru.trader.analysis.RouteSpecification;
import java.util.*; import java.util.*;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
@@ -18,7 +19,7 @@ public class Crawler<T> {
protected final Graph<T> graph; protected final Graph<T> graph;
private final Predicate<List<Edge<T>>> onFoundFunc; private final Predicate<List<Edge<T>>> onFoundFunc;
private final Predicate<Edge<T>> isFound; private final RouteSpecification<T> specification;
private T target; private T target;
private int maxSize; private int maxSize;
@@ -26,14 +27,14 @@ public class Crawler<T> {
this.graph = graph; this.graph = graph;
maxSize = graph.getRoot().getLevel(); maxSize = graph.getRoot().getLevel();
this.onFoundFunc = onFoundFunc; this.onFoundFunc = onFoundFunc;
this.isFound = this::isTarget; this.specification = (edge, entry) -> isTarget(edge);
} }
public Crawler(Graph<T> graph, Predicate<Edge<T>> isFoundFunc, Predicate<List<Edge<T>>> onFoundFunc) { public Crawler(Graph<T> graph, RouteSpecification<T> specification, Predicate<List<Edge<T>>> onFoundFunc) {
this.graph = graph; this.graph = graph;
maxSize = graph.getRoot().getLevel(); maxSize = graph.getRoot().getLevel();
this.onFoundFunc = onFoundFunc; this.onFoundFunc = onFoundFunc;
this.isFound = isFoundFunc; this.specification = specification;
} }
protected List<Edge<T>> getCopyList(Traversal<T> head, Edge<T> tail){ protected List<Edge<T>> getCopyList(Traversal<T> head, Edge<T> tail){
@@ -58,8 +59,8 @@ public class Crawler<T> {
return edge.isConnect(this.target); return edge.isConnect(this.target);
} }
protected boolean isFound(Edge<T> edge){ protected boolean isFound(Edge<T> edge, Traversal<T> head){
return isFound.test(edge); return specification.specified(edge, head);
} }
public int getMaxSize() { public int getMaxSize() {
@@ -157,7 +158,7 @@ public class Crawler<T> {
boolean stop = false; boolean stop = false;
if (deep == source.getLevel()){ if (deep == source.getLevel()){
for (Edge<T> next : entry.getEdges()) { for (Edge<T> next : entry.getEdges()) {
if (isFound(next)){ if (isFound(next, entry)){
List<Edge<T>> res = getCopyList(entry, next); List<Edge<T>> res = getCopyList(entry, next);
LOG.debug("Last edge found, path {}", res); LOG.debug("Last edge found, path {}", res);
found++; found++;
@@ -198,7 +199,7 @@ 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 (isFound(edge)){ if (isFound(edge, entry)){
List<Edge<T>> res = getCopyList(entry, edge); List<Edge<T>> res = getCopyList(entry, edge);
LOG.debug("Last edge found, path {}", res); LOG.debug("Last edge found, path {}", res);
found++; found++;
@@ -228,7 +229,7 @@ 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 (isFound(edge)) { if (isFound(edge, entry)) {
List<Edge<T>> res = entry.toEdges(); List<Edge<T>> res = entry.toEdges();
LOG.debug("Path found {}", res); LOG.debug("Path found {}", res);
found++; found++;
@@ -249,7 +250,7 @@ public class Crawler<T> {
while (iterator.hasNext()){ while (iterator.hasNext()){
edge = iterator.next(); edge = iterator.next();
boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel(); boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel();
if (canDeep || isFound(edge)){ if (canDeep || isFound(edge, entry)){
LOG.trace("Add edge {} to queue", edge); LOG.trace("Add edge {} to queue", edge);
queue.add(travers(entry, edge)); queue.add(travers(entry, edge));
} }
@@ -334,15 +335,13 @@ public class Crawler<T> {
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
cmp = Integer.compare(entry.size(), o.entry.size()); cmp = Integer.compare(entry.size(), o.entry.size());
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
CostTraversal<T> cur = entry; Iterator<Edge<T>> iter1 = entry.routeIterator();
CostTraversal<T> oCur = o.entry; Iterator<Edge<T>> iter2 = o.entry.routeIterator();
while (!cur.isRoot()){ while (iter1.hasNext()){
Edge<T> edge = cur.getEdge(); Edge<T> edge = iter1.next();
Edge<T> oEdge = oCur.getEdge(); Edge<T> oEdge = iter2.next();
cmp = oEdge.compareTo(edge); cmp = oEdge.compareTo(edge);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
cur = (CostTraversal<T>) cur.getHead().get();
oCur = (CostTraversal<T>) oCur.getHead().get();
} }
return 0; return 0;
} }
@@ -419,7 +418,7 @@ 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 = isFound(edge); boolean isTarget = isFound(edge, entry);
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); CostTraversalEntry nextEntry = travers(entry, edge);

View File

@@ -44,4 +44,29 @@ public interface Traversal<T> {
} }
return Arrays.asList(res); return Arrays.asList(res);
} }
default Iterator<Edge<T>> routeIterator(){
return new Iterator<Edge<T>>() {
private Edge<T> next = getEdge();
private Traversal<T> entry = Traversal.this;
@Override
public boolean hasNext() {
return next != null;
}
@Override
public Edge<T> next() {
Edge<T> res = next;
Optional<Traversal<T>> head = entry.getHead();
if (head.isPresent()){
entry = head.get();
next = entry.getEdge();
} else {
next = null;
}
return res;
}
};
}
} }