change predicate to route specification for depending targets
This commit is contained in:
@@ -9,7 +9,6 @@ import ru.trader.core.Profile;
|
||||
import ru.trader.core.Vendor;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class RouteSearcher {
|
||||
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){
|
||||
Predicate<Edge<Place>> isFoundFunc = e -> places.parallelStream().filter(e::isConnect).findFirst().isPresent();
|
||||
return search(from, from, places, scorer.getProfile().getRoutesCount(), isFoundFunc);
|
||||
return search(from, from, places, scorer.getProfile().getRoutesCount(), RouteSpecificationByTargets.any(places));
|
||||
}
|
||||
|
||||
public List<List<Edge<Place>>> getPaths(Place from, Place to, Collection<Place> places){
|
||||
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();
|
||||
LOG.trace("Start search path from {} to {} ", source, target);
|
||||
ConnectibleGraph<Place> graph = new ConnectibleGraph<>(profile);
|
||||
@@ -41,7 +39,7 @@ public class RouteSearcher {
|
||||
graph.build(source, places);
|
||||
LOG.trace("Graph is builds");
|
||||
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());
|
||||
if (profile.getPathPriority() == Profile.PATH_PRIORITY.FAST){
|
||||
crawler.findFast(target, count);
|
||||
@@ -58,18 +56,17 @@ public class RouteSearcher {
|
||||
public List<Route> getRoutes(Collection<Vendor> fVendors, Collection<Vendor> toVendors, Collection<Vendor> vendors){
|
||||
List<Route> res = new LimitedQueue<>(scorer.getProfile().getRoutesCount());
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
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(), isFoundFunc);
|
||||
return search(from, from, vendors, scorer.getProfile().getRoutesCount(), RouteSpecificationByTargets.any(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);
|
||||
}
|
||||
|
||||
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);
|
||||
VendorsGraph vGraph = new VendorsGraph(scorer);
|
||||
LOG.trace("Build vendors graph");
|
||||
vGraph.build(source, vendors);
|
||||
LOG.trace("Graph is builds");
|
||||
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.findMin(target, count);
|
||||
return collector.get();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,8 +34,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
|
||||
return new VendorsCrawler(onFoundFunc);
|
||||
}
|
||||
|
||||
public VendorsCrawler crawler(Predicate<Edge<Vendor>> isFoundFunc,Predicate<List<Edge<Vendor>>> onFoundFunc){
|
||||
return new VendorsCrawler(isFoundFunc, onFoundFunc);
|
||||
public VendorsCrawler crawler(RouteSpecification<Vendor> specification, Predicate<List<Edge<Vendor>>> onFoundFunc){
|
||||
return new VendorsCrawler(specification, onFoundFunc);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -514,8 +514,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
|
||||
startBalance = getProfile().getBalance();
|
||||
}
|
||||
|
||||
protected VendorsCrawler(Predicate<Edge<Vendor>> isFoundFunc, Predicate<List<Edge<Vendor>>> onFoundFunc) {
|
||||
super(VendorsGraph.this, isFoundFunc, onFoundFunc);
|
||||
protected VendorsCrawler(RouteSpecification<Vendor> specification, Predicate<List<Edge<Vendor>>> onFoundFunc) {
|
||||
super(VendorsGraph.this, specification, onFoundFunc);
|
||||
startFuel = getShip().getTank();
|
||||
startBalance = getProfile().getBalance();
|
||||
}
|
||||
@@ -563,7 +563,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
|
||||
|
||||
protected boolean check(Edge<Vendor> 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) {
|
||||
@@ -574,21 +575,14 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
|
||||
@Override
|
||||
public double getWeight() {
|
||||
if (weight == null){
|
||||
VendorsEdge edge = (VendorsEdge) getEdge();
|
||||
Optional<Traversal<Vendor>> head = getHead();
|
||||
double profit = 0; double time = 0;
|
||||
if (edge != null){
|
||||
profit = edge.getProfitByTonne();
|
||||
time = edge.getTime();
|
||||
}
|
||||
while (head.isPresent()){
|
||||
VendorsTraversalEntry hEntry = (VendorsTraversalEntry) head.get();
|
||||
edge = (VendorsEdge) hEntry.getEdge();
|
||||
Iterator<Edge<Vendor>> iterator = routeIterator();
|
||||
while (iterator.hasNext()){
|
||||
VendorsEdge edge = (VendorsEdge)iterator.next();
|
||||
if (edge != null){
|
||||
profit += edge.getProfitByTonne();
|
||||
time += edge.getTime();
|
||||
}
|
||||
head = hEntry.getHead();
|
||||
}
|
||||
weight = profit > 1 ? time / profit : time;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package ru.trader.analysis.graph;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.trader.analysis.RouteSpecification;
|
||||
import ru.trader.core.Profile;
|
||||
import ru.trader.core.Ship;
|
||||
import ru.trader.graph.Connectable;
|
||||
@@ -20,8 +21,8 @@ public class CCrawler<T extends Connectable<T>> extends Crawler<T> {
|
||||
startFuel = getShip().getTank();
|
||||
}
|
||||
|
||||
public CCrawler(ConnectibleGraph<T> graph, Predicate<Edge<T>> isFoundFunc, Predicate<List<Edge<T>>> onFoundFunc) {
|
||||
super(graph, isFoundFunc, onFoundFunc);
|
||||
public CCrawler(ConnectibleGraph<T> graph, RouteSpecification<T> specification, Predicate<List<Edge<T>>> onFoundFunc) {
|
||||
super(graph, specification, onFoundFunc);
|
||||
startFuel = getShip().getTank();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.trader.analysis.LimitedQueue;
|
||||
import ru.trader.analysis.RouteSpecification;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
@@ -18,7 +19,7 @@ public class Crawler<T> {
|
||||
|
||||
protected final Graph<T> graph;
|
||||
private final Predicate<List<Edge<T>>> onFoundFunc;
|
||||
private final Predicate<Edge<T>> isFound;
|
||||
private final RouteSpecification<T> specification;
|
||||
private T target;
|
||||
private int maxSize;
|
||||
|
||||
@@ -26,14 +27,14 @@ public class Crawler<T> {
|
||||
this.graph = graph;
|
||||
maxSize = graph.getRoot().getLevel();
|
||||
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;
|
||||
maxSize = graph.getRoot().getLevel();
|
||||
this.onFoundFunc = onFoundFunc;
|
||||
this.isFound = isFoundFunc;
|
||||
this.specification = specification;
|
||||
}
|
||||
|
||||
protected List<Edge<T>> getCopyList(Traversal<T> head, Edge<T> tail){
|
||||
@@ -58,8 +59,8 @@ public class Crawler<T> {
|
||||
return edge.isConnect(this.target);
|
||||
}
|
||||
|
||||
protected boolean isFound(Edge<T> edge){
|
||||
return isFound.test(edge);
|
||||
protected boolean isFound(Edge<T> edge, Traversal<T> head){
|
||||
return specification.specified(edge, head);
|
||||
}
|
||||
|
||||
public int getMaxSize() {
|
||||
@@ -157,7 +158,7 @@ public class Crawler<T> {
|
||||
boolean stop = false;
|
||||
if (deep == source.getLevel()){
|
||||
for (Edge<T> next : entry.getEdges()) {
|
||||
if (isFound(next)){
|
||||
if (isFound(next, entry)){
|
||||
List<Edge<T>> res = getCopyList(entry, next);
|
||||
LOG.debug("Last edge found, path {}", res);
|
||||
found++;
|
||||
@@ -198,7 +199,7 @@ public class Crawler<T> {
|
||||
Iterator<Edge<T>> iterator = entry.iterator();
|
||||
while (iterator.hasNext()){
|
||||
Edge<T> edge = iterator.next();
|
||||
if (isFound(edge)){
|
||||
if (isFound(edge, entry)){
|
||||
List<Edge<T>> res = getCopyList(entry, edge);
|
||||
LOG.debug("Last edge found, path {}", res);
|
||||
found++;
|
||||
@@ -228,7 +229,7 @@ public class Crawler<T> {
|
||||
LOG.trace("Check path entry {}, weight {}", entry, entry.weight);
|
||||
Edge<T> edge = entry.getEdge();
|
||||
if (edge != null) {
|
||||
if (isFound(edge)) {
|
||||
if (isFound(edge, entry)) {
|
||||
List<Edge<T>> res = entry.toEdges();
|
||||
LOG.debug("Path found {}", res);
|
||||
found++;
|
||||
@@ -249,7 +250,7 @@ public class Crawler<T> {
|
||||
while (iterator.hasNext()){
|
||||
edge = iterator.next();
|
||||
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);
|
||||
queue.add(travers(entry, edge));
|
||||
}
|
||||
@@ -334,15 +335,13 @@ public class Crawler<T> {
|
||||
if (cmp != 0) return cmp;
|
||||
cmp = Integer.compare(entry.size(), o.entry.size());
|
||||
if (cmp != 0) return cmp;
|
||||
CostTraversal<T> cur = entry;
|
||||
CostTraversal<T> oCur = o.entry;
|
||||
while (!cur.isRoot()){
|
||||
Edge<T> edge = cur.getEdge();
|
||||
Edge<T> oEdge = oCur.getEdge();
|
||||
Iterator<Edge<T>> iter1 = entry.routeIterator();
|
||||
Iterator<Edge<T>> iter2 = o.entry.routeIterator();
|
||||
while (iter1.hasNext()){
|
||||
Edge<T> edge = iter1.next();
|
||||
Edge<T> oEdge = iter2.next();
|
||||
cmp = oEdge.compareTo(edge);
|
||||
if (cmp != 0) return cmp;
|
||||
cur = (CostTraversal<T>) cur.getHead().get();
|
||||
oCur = (CostTraversal<T>) oCur.getHead().get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -419,7 +418,7 @@ public class Crawler<T> {
|
||||
Edge<T> edge = curr.next();
|
||||
CostTraversalEntry entry = curr.entry;
|
||||
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;
|
||||
if (canDeep || isTarget){
|
||||
CostTraversalEntry nextEntry = travers(entry, edge);
|
||||
|
||||
@@ -44,4 +44,29 @@ public interface Traversal<T> {
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user