From 1a4cad61dd3134b3e134608c18437f42356cda01 Mon Sep 17 00:00:00 2001 From: iMoHax Date: Fri, 17 Jul 2015 16:10:58 +0300 Subject: [PATCH] remove old classes --- .../java/ru/trader/services/AnalyzerTask.java | 2 +- core/src/main/java/ru/trader/graph/Edge.java | 60 --- core/src/main/java/ru/trader/graph/Graph.java | 358 -------------- .../java/ru/trader/graph/GraphCallBack.java | 2 + core/src/main/java/ru/trader/graph/Path.java | 138 ------ .../main/java/ru/trader/graph/PathRoute.java | 446 ------------------ .../main/java/ru/trader/graph/RouteGraph.java | 90 ---- .../java/ru/trader/graph/RouteSearcher.java | 145 ------ .../main/java/ru/trader/graph/TopList.java | 96 ---- .../src/main/java/ru/trader/graph/Vertex.java | 88 ---- 10 files changed, 3 insertions(+), 1422 deletions(-) delete mode 100644 core/src/main/java/ru/trader/graph/Edge.java delete mode 100644 core/src/main/java/ru/trader/graph/Graph.java delete mode 100644 core/src/main/java/ru/trader/graph/Path.java delete mode 100644 core/src/main/java/ru/trader/graph/PathRoute.java delete mode 100644 core/src/main/java/ru/trader/graph/RouteGraph.java delete mode 100644 core/src/main/java/ru/trader/graph/RouteSearcher.java delete mode 100644 core/src/main/java/ru/trader/graph/TopList.java delete mode 100644 core/src/main/java/ru/trader/graph/Vertex.java diff --git a/client/src/main/java/ru/trader/services/AnalyzerTask.java b/client/src/main/java/ru/trader/services/AnalyzerTask.java index 9acbffc..6866bca 100644 --- a/client/src/main/java/ru/trader/services/AnalyzerTask.java +++ b/client/src/main/java/ru/trader/services/AnalyzerTask.java @@ -4,6 +4,7 @@ import javafx.application.Platform; import javafx.beans.property.LongProperty; import javafx.beans.property.SimpleLongProperty; import javafx.concurrent.Task; +import ru.trader.analysis.graph.Vertex; import ru.trader.core.MarketAnalyzer; import ru.trader.core.MarketAnalyzerCallBack; import ru.trader.core.Place; @@ -11,7 +12,6 @@ import ru.trader.core.Vendor; import ru.trader.graph.Connectable; import ru.trader.graph.GraphCallBack; import ru.trader.graph.RouteSearcherCallBack; -import ru.trader.graph.Vertex; import ru.trader.model.MarketModel; import ru.trader.view.support.Localization; diff --git a/core/src/main/java/ru/trader/graph/Edge.java b/core/src/main/java/ru/trader/graph/Edge.java deleted file mode 100644 index 24f12f9..0000000 --- a/core/src/main/java/ru/trader/graph/Edge.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.trader.graph; - -public class Edge> { - protected double length; - protected final Vertex target; - protected final Vertex source; - - public Edge(Vertex source, T target) { - this(source, new Vertex<>(target)); - } - - public Edge(Vertex source, Vertex target) { - this.target = target; - this.source = source; - this.length = source.getEntry().getDistance(target.getEntry()); - } - - public double getLength(){ - return length; - } - - public boolean isConnect(T other){ - return target.getEntry().equals(other); - } - - public boolean isConnect(Vertex target){ - return getTarget().equals(target); - } - - public Vertex getTarget(){ - return target; - } - - public Vertex getSource() { - return source; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Edge edge = (Edge) o; - - return source.equals(edge.source) && target.equals(edge.target); - - } - - @Override - public int hashCode() { - int result = target.hashCode(); - result = 31 * result + source.hashCode(); - return result; - } - - @Override - public String toString() { - return source.toString() + " -> " + target.toString(); - } -} diff --git a/core/src/main/java/ru/trader/graph/Graph.java b/core/src/main/java/ru/trader/graph/Graph.java deleted file mode 100644 index f3f0078..0000000 --- a/core/src/main/java/ru/trader/graph/Graph.java +++ /dev/null @@ -1,358 +0,0 @@ -package ru.trader.graph; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.RecursiveAction; -import java.util.function.Predicate; - -public class Graph> { - private final static ForkJoinPool POOL = new ForkJoinPool(); - private final static int THRESHOLD = 4; - private final static int DEFAULT_COUNT = 200; - - @FunctionalInterface - public interface PathConstructor> { - Path build(Vertex source); - } - - private final static Logger LOG = LoggerFactory.getLogger(Graph.class); - - protected final Vertex root; - protected final Map> vertexes; - private final GraphCallBack callback; - - protected final double stock; - protected final double maxDistance; - protected final boolean withRefill; - private final PathConstructor pathFabric; - protected int minJumps; - - - public Graph(T start, Collection set, double stock, int maxDeep) { - this(start, set, stock, stock, false, maxDeep, Path::new); - } - - public Graph(T start, Collection set, double stock, double maxDistance, int maxDeep) { - this(start, set, stock, maxDistance, true, maxDeep, Path::new); - } - - public Graph(T start, Collection set, double stock, boolean withRefill, int maxDeep) { - this(start, set, stock, stock, withRefill, maxDeep, Path::new); - } - - public Graph(T start, Collection set, double stock, boolean withRefill, int maxDeep, PathConstructor pathFabric) { - this(start, set, stock, stock, withRefill, maxDeep, pathFabric); - } - - public Graph(T start, Collection set, double stock, double maxDistance, boolean withRefill, int maxDeep, PathConstructor pathFabric) { - this(start, set, stock, maxDistance, withRefill, maxDeep, pathFabric, new GraphCallBack<>()); - } - - public Graph(T start, Collection set, double stock, double maxDistance, boolean withRefill, int maxDeep, PathConstructor pathFabric, GraphCallBack callback) { - this.maxDistance = maxDistance; - this.stock = stock; - this.withRefill = withRefill; - this.pathFabric = pathFabric; - this.callback = callback; - root = new Vertex<>(start); - root.setLevel(maxDeep); - vertexes = new ConcurrentHashMap<>(50, 0.9f, THRESHOLD); - vertexes.put(root.getEntry(), root); - callback.onStartBuild(start); - build(root, set, maxDeep, stock); - callback.onEndBuild(); - } - - private void build(Vertex root, Collection set, int maxDeep, double stock) { - POOL.invoke(new GraphBuilder(root, set, maxDeep - 1, stock)); - if (set.size() > vertexes.size()){ - minJumps = maxDeep; - } else { - minJumps = 1; - for (Vertex vertex : vertexes.values()) { - int jumps = maxDeep - vertex.getLevel(); - if (jumps > minJumps) minJumps = jumps; - } - } - } - - public boolean isAccessible(T entry){ - return vertexes.containsKey(entry); - } - - public Vertex getVertex(T entry){ - return vertexes.get(entry); - } - - private void findPathsTo(Vertex target, TopList> res, int deep){ - callback.onStartFind(root, target); - POOL.invoke(new PathFinder(res, pathFabric.build(root), target, deep-1, stock)); - callback.onEndFind(); - } - - public List> getPathsTo(T entry){ - return getPathsTo(entry, DEFAULT_COUNT); - } - - public List> getPathsTo(T entry, int max){ - return getPathsTo(entry, max, root.getLevel()).getList(); - } - - public TopList> getPathsTo(T entry, int max, int deep){ - Vertex target = getVertex(entry); - TopList> paths = newTopList(max); - callback.setMax(1); - findPathsTo(target, paths, deep); - callback.inc(); - paths.finish(); - return paths; - } - - public List> getPaths(int count){ - return getPaths(count, root.getLevel()).getList(); - } - - public TopList> getPaths(int count, int deep){ - TopList> paths = newTopList(count); - callback.setMax(vertexes.size()); - for (Vertex target : vertexes.values()) { - if (callback.isCancel()) break; - TopList> p = newTopList(minJumps); - findPathsTo(target, p, deep); - for (Path path : p.getList()) { - paths.add(path); - } - callback.inc(); - } - paths.finish(); - return paths; - } - - protected TopList> newTopList(int count){ - return new TopList<>(count); - } - - public Path getFastPathTo(T entry){ - Vertex target = getVertex(entry); - if (target == null) return null; - return findFastPath(pathFabric.build(root), target, target.getLevel()+1, stock); - } - - private Path findFastPath(Path head, Vertex target, int deep, double limit) { - Vertex source = head.getTarget(); - LOG.trace("Find fast path from {} to {}, deep {}, limit {}, head {}", source, target, deep, limit, head); - DistanceFilter distanceFilter = new DistanceFilter(limit, source.getEntry()); - if (deep == source.getLevel()){ - Optional> last = source.getEdges().parallelStream() - .filter(next -> next.isConnect(target) && distanceFilter.test(next.getLength()) && !head.isConnect(next.getTarget())) - .findFirst(); - if (last.isPresent()){ - Path path = head.connectTo(last.get().getTarget(), limit < last.get().getLength()); - path.finish(); - LOG.trace("Last edge find, path {}", path); - return path; - } - } - if (deep < source.getLevel()){ - LOG.trace("Search around"); - Optional> res = source.getEdges().parallelStream() - .filter(next -> next.getTarget().getLevel() < source.getLevel() && distanceFilter.test(next.getLength())) - .map((next) -> { - Path path = head.connectTo(next.getTarget(), limit < next.getLength()); - double nextLimit = withRefill ? limit - next.getLength(): stock; - // refill - if (nextLimit < 0 ) nextLimit = stock - next.getLength(); - return findFastPath(path, target, deep, nextLimit); - }) - .filter(path -> path != null) - .findFirst(); - if (res.isPresent()) return res.get(); - } - return null; - } - - public T getRoot() { - return root.getEntry(); - } - - public int getMinJumps() { - return minJumps; - } - - private class DistanceFilter implements Predicate { - private final double limit; - private final T source; - - private DistanceFilter(double limit, T source) { - this.limit = limit; - this.source = source; - } - - @Override - public boolean test(Double distance) { - return distance <= Math.min(limit, maxDistance) || (withRefill && distance <= maxDistance && source.canRefill()); - } - } - - private class GraphBuilder extends RecursiveAction { - private final Vertex vertex; - private final Collection set; - private final int deep; - private final double limit; - private final DistanceFilter distanceFilter; - - private GraphBuilder(Vertex vertex, Collection set, int deep, double limit) { - this.vertex = vertex; - this.set = set; - this.deep = deep; - this.limit = limit; - distanceFilter = new DistanceFilter(limit, vertex.getEntry()); - } - - @Override - protected void compute() { - LOG.trace("Build graph from {}, limit {}, deep {}", vertex, limit, deep); - ArrayList subTasks = new ArrayList<>(set.size()); - Iterator iterator = set.iterator(); - while (iterator.hasNext()) { - if (callback.isCancel()) break; - T entry = iterator.next(); - if (entry == vertex.getEntry()) continue; - double distance = vertex.getEntry().getDistance(entry); - if (distanceFilter.test(distance)) { - Vertex next = vertexes.get(entry); - if (next == null) { - LOG.trace("Is new vertex"); - next = new Vertex<>(entry); - vertexes.put(entry, next); - } - LOG.trace("Add edge from {} to {}", vertex, next); - vertex.addEdge(new Edge<>(vertex, next)); - // If level >= deep when vertex already added on upper deep - if (next.getLevel() < deep) { - next.setLevel(vertex.getLevel() - 1); - if (deep > 0) { - double nextLimit = withRefill ? limit - distance : stock; - if (nextLimit < 0) { - LOG.trace("Refill"); - nextLimit = stock - distance; - } - //Recursive build - GraphBuilder task = new GraphBuilder(next, set, deep - 1, nextLimit); - task.fork(); - subTasks.add(task); - } - } - } else { - LOG.trace("Vertex {} is far away, {}", entry, distance); - } - if (subTasks.size() == THRESHOLD || !iterator.hasNext()){ - for (GraphBuilder subTask : subTasks) { - if (callback.isCancel()){ - subTask.cancel(true); - } else { - subTask.join(); - } - } - subTasks.clear(); - } - } - if (!subTasks.isEmpty()){ - for (GraphBuilder subTask : subTasks) { - if (callback.isCancel()){ - subTask.cancel(true); - } else { - subTask.join(); - } - } - subTasks.clear(); - } - LOG.trace("End build graph from {} on deep {}", vertex, deep); - } - } - - private class PathFinder extends RecursiveAction { - private final TopList> paths; - private final Path head; - private final Vertex target; - private final int deep; - private final double limit; - private final DistanceFilter distanceFilter; - - private PathFinder(TopList> paths, Path head, Vertex target, int deep, double limit) { - this.paths = paths; - this.head = head; - this.target = target; - this.deep = deep; - this.limit = limit; - distanceFilter = new DistanceFilter(limit, head.getTarget().getEntry()); - } - - @Override - protected void compute() { - if (target == null || isCancelled()) return; - Vertex source = head.getTarget(); - LOG.trace("Find path to deep from {} to {}, deep {}, limit {}, head {}", source, target, deep, limit, head); - Edge edge = source.getEdge(target); - if (edge != null){ - if (distanceFilter.test(edge.getLength())){ - Path path = head.connectTo(edge.getTarget(), limit < edge.getLength()); - path.finish(); - LOG.trace("Last edge find, add path {}", path); - synchronized (paths){ - if (!paths.add(path)) complete(null); - } - callback.onFound(); - } - } - if (deep > 0 ){ - if (source.getEdgesCount() > 0){ - LOG.trace("Search around"); - ArrayList subTasks = new ArrayList<>(source.getEdges().size()); - Iterator> iterator = source.getEdges().iterator(); - while (iterator.hasNext()) { - Edge next = iterator.next(); - if (isDone() || callback.isCancel()) break; - // target already added if source consist edge - if (next.isConnect(target)) continue; - if (!distanceFilter.test(next.getLength())) continue; - Path path = head.connectTo(next.getTarget(), limit < next.getLength()); - double nextLimit = withRefill ? limit - next.getLength() : stock; - // refill - if (nextLimit < 0) nextLimit = stock - next.getLength(); - //Recursive search - PathFinder task = new PathFinder(paths, path, target, deep - 1, nextLimit); - task.fork(); - subTasks.add(task); - if (subTasks.size() == THRESHOLD || !iterator.hasNext()){ - for (PathFinder subTask : subTasks) { - if (isDone() || callback.isCancel()) { - subTask.cancel(callback.isCancel()); - } else { - subTask.join(); - } - } - subTasks.clear(); - } - } - if (!subTasks.isEmpty()){ - for (PathFinder subTask : subTasks) { - if (isDone() || callback.isCancel()) { - subTask.cancel(callback.isCancel()); - } else { - subTask.join(); - } - } - subTasks.clear(); - } - } - } - } - } - - -} diff --git a/core/src/main/java/ru/trader/graph/GraphCallBack.java b/core/src/main/java/ru/trader/graph/GraphCallBack.java index 3709831..8e622a6 100644 --- a/core/src/main/java/ru/trader/graph/GraphCallBack.java +++ b/core/src/main/java/ru/trader/graph/GraphCallBack.java @@ -1,5 +1,7 @@ package ru.trader.graph; +import ru.trader.analysis.graph.Vertex; + public class GraphCallBack> { private volatile boolean cancel = false; diff --git a/core/src/main/java/ru/trader/graph/Path.java b/core/src/main/java/ru/trader/graph/Path.java deleted file mode 100644 index ca5684c..0000000 --- a/core/src/main/java/ru/trader/graph/Path.java +++ /dev/null @@ -1,138 +0,0 @@ -package ru.trader.graph; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; - -public class Path> { - private final Path head; - private final Vertex target; - private boolean refill; - - - public Path(Vertex source) { - this.head = null; - this.target = source; - this.refill = false; - } - - protected Path(Path head, Vertex vertex, boolean refill) { - this.head = head; - this.target = vertex; - this.refill = refill; - } - - public Path connectTo(Vertex vertex, boolean refill){ - return new Path<>(this, vertex, refill); - } - - protected void finish(){ - if (!isRoot()){ - head.finish(); - } - } - - public boolean isRoot(){ - return head == null; - } - - public Path getRoot(){ - if (isRoot()) return this; - return head.getRoot(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Path)) return false; - - Path path = (Path) o; - return (isRoot() ? path.isRoot() : head.equals(path.head)) && target.equals(path.target); - - } - - @Override - public int hashCode() { - int result = head != null ? head.hashCode() : 0; - result = 31 * result + target.hashCode(); - return result; - } - - @Override - public String toString(){ - if (isRoot()) return target.getEntry().toString(); - final StringBuilder sb = new StringBuilder(head.toString()); - if (refill) sb.append("(R)"); - sb.append(" -> ").append(target.getEntry()); - return sb.toString(); - } - - public boolean isConnect(Vertex vertex) { - return target.equals(vertex) || (!isRoot() && head.isConnect(vertex)); - } - - public boolean isConnect(T entry) { - return target.getEntry().equals(entry) || (!isRoot() && head.isConnect(entry)); - } - - public boolean isPathFrom(T entry) { - return !isRoot() && head.target.getEntry().equals(entry); - } - - @SafeVarargs - public static > Path toPath(T... items){ - T t = items[0]; - Path path = new Path<>(new Vertex<>(t)); - for (int i = 1; i < items.length; i++) { - t = items[i]; - path = new Path<>(path, new Vertex<>(t), false); - } - return path; - } - - public Vertex getTarget() { - return target; - } - - public T get() { - return target.getEntry(); - } - - public boolean isRefill(){ - return refill; - } - - public void setRefill(boolean refill) { - this.refill = refill; - } - - protected Path getPrevious(){ - return head; - } - - public int getLength(){ - return isRoot() ? 0 : 1 + getPrevious().getLength(); - } - - public Collection getEntries(){ - Collection res = new HashSet<>(); - res.add(target.getEntry()); - Path p = getPrevious(); - while (p != null){ - res.add(p.target.getEntry()); - p = p.getPrevious(); - } - return res; - } - - public boolean contains(Collection items){ - if (items.isEmpty()) return true; - Collection remains = new ArrayList<>(items); - remains.remove(target.getEntry()); - if (isRoot()) { - return remains.isEmpty(); - } - return getPrevious().contains(remains); - } -} diff --git a/core/src/main/java/ru/trader/graph/PathRoute.java b/core/src/main/java/ru/trader/graph/PathRoute.java deleted file mode 100644 index 80eef48..0000000 --- a/core/src/main/java/ru/trader/graph/PathRoute.java +++ /dev/null @@ -1,446 +0,0 @@ -package ru.trader.graph; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ru.trader.core.Offer; -import ru.trader.core.Order; -import ru.trader.core.Vendor; - -import java.util.*; - -public class PathRoute extends Path { - private final static Logger LOG = LoggerFactory.getLogger(PathRoute.class); - - private final ArrayList orders = new ArrayList<>(); - private final boolean byAvg; - private double profit = 0; - private double balance = 0; - private double distance = 0; - private int landsCount = 0; - private PathRoute tail; - public final static Order TRANSIT = null; - - public PathRoute(Vertex source) { - this(source, false); - } - - public static PathRoute buildAvg(Vertex source){ - return new PathRoute(source, true); - } - - private PathRoute(Vertex source, boolean byAvg) { - super(source); - this.byAvg = byAvg; - } - - - private PathRoute(PathRoute head, Vertex vertex, boolean refill) { - super(head, vertex, refill); - assert head.tail == null; - head.tail = this; - byAvg = head.byAvg; - //transit - orders.add(TRANSIT); - } - - @Override - public Path connectTo(Vertex vertex, boolean refill) { - LOG.trace("Connect path {} to {}", this, vertex); - return new PathRoute(this.getCopy(), vertex, refill); - } - - public PathRoute add(PathRoute path, boolean noSort) { - LOG.trace("Add path {} to {}", path, this); - PathRoute res = this; - path = path.getRoot(); - if (!path.getTarget().equals(getTarget())){ - LOG.trace("Is not connected path, add edge from {} to {}", path.getTarget(), getTarget()); - res = new PathRoute(res, path.getTarget(), true); - res.updateDistance(); - } - while (path.hasNext()){ - path = path.getNext(); - res = new PathRoute(res, path.getTarget(), path.isRefill()); - if (noSort){ - copyField(path, res); - } - } - if (noSort){ - update(); - } else { - res.finish(); - } - return res; - } - - private void copyField(PathRoute source, PathRoute dest){ - dest.orders.clear(); - dest.orders.addAll(source.getOrders()); - dest.distance = source.distance; - dest.profit = source.profit; - dest.balance = source.balance; - dest.landsCount = source.landsCount; - } - - public PathRoute getCopy(){ - return getCopy(false); - } - - public PathRoute getCopy(boolean withOrders){ - PathRoute path = getRoot(); - PathRoute res = new PathRoute(path.getTarget(), path.byAvg); - if (withOrders) { - copyField(path, res); - } - while (path.hasNext()){ - path = path.getNext(); - res = new PathRoute(res, path.getTarget(), path.isRefill()); - if (withOrders) { - copyField(path, res); - } - } - return res; - } - - private void addOrder(Order order){ - LOG.trace("Add order {} to path {}", order, this); - orders.add(order); - } - - public void refresh(){ - getEnd().finish(); - } - - @Override - protected void finish() { - if (!isRoot()){ - fillOrders(); - getPrevious().finish(); - } - updateDistance(); - } - - private void update(){ - PathRoute p = this; - p.updateBalance(); - while (p.hasNext()){ - p = p.getNext(); - p.updateBalance(); - } - p = this; - p.updateProfit(); - p.updateLandsCount(); - while (!p.isRoot()){ - p = p.getPrevious(); - p.updateProfit(); - p.updateLandsCount(); - } - p.updateDistance(); - } - - private void fillOrders(){ - orders.clear(); - orders.add(TRANSIT); - LOG.trace("Fill orders of path {}", this); - Vendor seller = getPrevious().get(); - for (Offer sell : seller.getAllSellOffers()) { - PathRoute p = this; - while (p != null) { - Vendor buyer = p.get(); - Offer buy = buyer.getBuy(sell.getItem()); - if (buy != null){ - Order order = new Order(sell, buy, 1); - if (order.getProfit() <= 0) { - LOG.trace("{} - is no profit, skip", order); - } else { - addOrder(order); - } - } - p = p.getNext(); - } - } - } - - public List getOrders() { - return Collections.unmodifiableList(orders); - } - - public boolean isEmpty(){ - return orders.size() <= 1; - } - - @Override - protected PathRoute getPrevious() { - return (PathRoute) super.getPrevious(); - } - - public PathRoute getNext() { - return tail; - } - - public boolean hasNext(){ - return tail != null; - } - - public void sort(double balance, long cargo){ - // start on root only - if (isRoot()){ - this.balance = balance; - if (hasNext()){ - getNext().forwardSort(cargo); - } - } else { - getPrevious().sort(balance, cargo); - } - } - - private void forwardSort(long cargo){ - updateBalance(); - boolean needSort = false; - for (Order order : orders) { - if (order == TRANSIT) continue; - if (order.getCount() < cargo){ - needSort = true; - order.setMax(balance, cargo); - } - } - if (needSort){ - LOG.trace("Simple sort"); - orders.sort(this::simpleCompareOrders); - LOG.trace("New order of orders {}", orders); - } - if (hasNext()){ - getNext().forwardSort(cargo); - } else { - LOG.trace("Start back sort"); - Order best = orders.get(0); - profit = best == TRANSIT ? 0 : best.getProfit(); - LOG.trace("Max profit from {} = {}", getPrevious().get(), profit); - updateLandsCount(); - getPrevious().backwardSort(); - } - } - - private void backwardSort(){ - orders.sort(byAvg ? this::compareByAvgProfit : this::compareOrders); - LOG.trace("New order of orders {}", orders); - updateProfit(); - updateLandsCount(); - if (!isRoot()) - getPrevious().backwardSort(); - } - - private void updateBalance() { - PathRoute p = getPrevious(); - balance = p.balance; - if (!p.isRoot()) { - Vendor buyer = p.get(); - while (!p.isRoot()){ - for (Order order : p.orders) { - if (order == TRANSIT) continue; - if (order.isBuyer(buyer) && balance < p.balance + order.getProfit()){ - balance = p.balance + order.getProfit(); - LOG.trace("Order {} is best to {}, new balance {}", order, buyer, balance); - } - - } - p = p.getPrevious(); - } - } - LOG.trace("Max balance on {} = {}", getPrevious().get(), balance); - } - - - private void updateProfit() { - Order best = orders.isEmpty()? TRANSIT : orders.get(0); - if (best == TRANSIT) profit = getTransitProfit(); - else profit = getProfit(best); - LOG.trace("Max profit from {} = {}", isRoot() ? get() : getPrevious().get(), profit); - } - - private double getTransitProfit(){ - return hasNext() ? getNext().getProfit() : 0; - } - - public double getProfit(){ - return profit; - } - - public double getAvgProfit(){ - return isRoot()? profit/landsCount : getPrevious().getAvgProfit(); - } - - public double getBalance() { - return balance; - } - - public double getProfit(Order order){ - return getProfit(order, true); - } - - private double getProfit(Order order, boolean first){ - if (order == TRANSIT) return getTransitProfit(); - if (isPathFrom(order.getBuyer())) { - return first ? order.getProfit() : order.getProfit() + profit; - } - return hasNext() ? getNext().getProfit(order, false) : order.getProfit(); - } - - private int simpleCompareOrders(Order o1, Order o2){ - if (o1 != TRANSIT && o2 != TRANSIT){ - return o2.compareTo(o1); - } - return o1 == TRANSIT ? o2 == TRANSIT ? 0 : Double.compare(o2.getProfit(), 0) : Double.compare(0, o1.getProfit()); - } - - private int compareOrders(Order o1, Order o2){ - if (o1 != TRANSIT && o2 != TRANSIT){ - if (!hasNext() || o1.isBuyer(o2.getBuyer())) - return o2.compareTo(o1); - } - double profit1 = getProfit(o1); - double profit2 = getProfit(o2); - return Double.compare(profit2, profit1); - } - - private int compareByAvgProfit(Order o1, Order o2){ - if (o1 != TRANSIT && o2 != TRANSIT){ - if (!hasNext() || o1.isBuyer(o2.getBuyer())) - return o2.compareTo(o1); - } - double profit1 = getProfit(o1)/computeLandsCount(o1); - double profit2 = getProfit(o2)/computeLandsCount(o2); - return Double.compare(profit2, profit1); - } - - - @Override - public PathRoute getRoot() { - return (PathRoute) super.getRoot(); - } - - public PathRoute getEnd() { - return hasNext()? getNext().getEnd() : this; - } - - public Order getBest(){ - if (orders.isEmpty()) return null; - return orders.get(0); - } - - private double computeDistance(){ - if (isRoot()){ - double res = 0; - PathRoute p = this; - while (p.hasNext()){ - p = p.getNext(); - res += p.computeDistance(); - } - return res; - } - else return getPrevious().get().getDistance(get()); - } - - private void updateDistance(){ - this.distance = computeDistance(); - } - - public double getDistance(){ - return distance; - } - - private int computeLandsCount(Order order){ - int res = 0; - PathRoute p = isRoot()? getNext() : this; - while (p.hasNext()){ - p = p.getNext(); - // lands for sell - if (order != null && p.isPathFrom(order.getBuyer())){ - LOG.trace("{} is lands for sell by order {}", p, order); - return res + p.getLandsCount() + 1; - } else { - if (order == null){ - order = p.getBest(); - if (order != null){ - LOG.trace("{} is lands for buy by order {}", p, order); - return res + p.getLandsCount() + 1; - } - } else { - if (p.isRefill()){ - LOG.trace("{} is lands for refill", p); - res++; - } - } - } - - } - LOG.trace("{} is end, landing", p); - res++; - return res; - } - - private void updateLandsCount(){ - Order best = isRoot() ? getNext().getBest() : getBest(); - landsCount = computeLandsCount(best); - LOG.trace("Lands count from {} = {}", isRoot() ? get() : getPrevious().get(), landsCount); - } - - public int getLandsCount() { - return landsCount; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Order order = getBest(); - if (order != TRANSIT){ - sb.append(order.getBuy().getItem()); - sb.append(" (").append(order.getBuyer()).append(") "); - } - String o = sb.toString(); - sb = new StringBuilder(); - if (isRoot()){ - sb.append(get()); - if (o.length()>0) sb.append(" (").append(o).append(") "); - } else { - sb.append(getPrevious().toString()); - sb.append(" ").append(balance).append(" "); - if (isRefill()) sb.append("(R)"); - if (o.length()>0) sb.append(" (").append(o).append(") "); - sb.append(" -> ").append(get()); - } - return sb.toString(); - } - - public void setOrder(Order order) { - orders.set(0, order); - } - - public PathRoute dropTo(Vendor vendor){ - PathRoute p = getCopy(true).getEnd(); - while (!p.isRoot() && !p.get().equals(vendor)){ - p = p.getPrevious(); - } - p.tail = null; - return p; - } - - public static PathRoute toPathRoute(Vendor... items){ - Vendor t = items[0]; - PathRoute path = new PathRoute(new Vertex<>(t)); - for (int i = 1; i < items.length; i++) { - t = items[i]; - path = new PathRoute(path, new Vertex<>(t), false); - } - return path; - } - - public boolean isRoute(PathRoute path){ - return this == path || (isRoot() ? path.isRoot() : !path.isRoot() && getPrevious().isRoute(path.getPrevious())) - && this.getTarget().equals(path.getTarget()) - && this.profit == path.profit - && this.balance == path.balance - && (this.getBest() == null && path.getBest() == null || this.getBest().equals(path.getBest())); - - } -} diff --git a/core/src/main/java/ru/trader/graph/RouteGraph.java b/core/src/main/java/ru/trader/graph/RouteGraph.java deleted file mode 100644 index cfabdf3..0000000 --- a/core/src/main/java/ru/trader/graph/RouteGraph.java +++ /dev/null @@ -1,90 +0,0 @@ -package ru.trader.graph; - -import ru.trader.core.Vendor; - -import java.util.*; - -public class RouteGraph extends Graph { - - private double balance; - private int cargo; - private boolean groupRes; - - public static Comparator byProfitComparator = (p1, p2) -> { - PathRoute r1 = p1.getRoot(); - PathRoute r2 = p2.getRoot(); - int cmp = Double.compare(r2.getAvgProfit(), r1.getAvgProfit()); - if (cmp != 0 ) return cmp; - cmp = Double.compare(r1.getDistance(), r2.getDistance()); - if (cmp != 0) return cmp; - cmp = Double.compare(r1.getLandsCount(), r2.getLandsCount()); - if (cmp != 0) return cmp; - return cmp; - }; - - public static Comparator groupByLengthComparator = (p1, p2) -> { - int cmp = Integer.compare(p1.getLength(), p2.getLength()); - if (cmp != 0 ) return cmp; - return byProfitComparator.compare(p1, p2); - }; - - public RouteGraph(Vendor start, Collection set, double stock, double maxDistance, boolean withRefill, int maxDeep) { - this(start, set, stock, maxDistance, withRefill, maxDeep, false); - } - public RouteGraph(Vendor start, Collection set, double stock, double maxDistance, boolean withRefill, int maxDeep, boolean groupRes) { - this(start, set, stock, maxDistance, withRefill, maxDeep, groupRes, new GraphCallBack<>()); - } - - public RouteGraph(Vendor start, Collection set, double stock, double maxDistance, boolean withRefill, int maxDeep, boolean groupRes, GraphCallBack callback) { - super(start, set, stock, maxDistance, withRefill, maxDeep, groupRes ? PathRoute::buildAvg : PathRoute::new, callback); - if (groupRes){ - this.groupRes = maxDeep > minJumps; - } - } - - public void setBalance(double balance) { - this.balance = balance; - } - - public void setCargo(int cargo) { - this.cargo = cargo; - } - - @Override - protected TopList> newTopList(int count) { - int groupSize = 0; - if (groupRes && getMinJumps() > 1){ - groupSize = Math.floorDiv(count, root.getLevel()); - } - return new TopRoutes(count, groupSize); - } - - private class TopRoutes extends TopList> { - private final int groupSize; - - public TopRoutes(int limit, int groupSize) { - super(limit, (p1, p2) -> groupSize > 0 ? groupByLengthComparator.compare((PathRoute)p1, (PathRoute)p2) : RouteGraph.byProfitComparator.compare((PathRoute)p1, (PathRoute)p2)); - this.groupSize = groupSize; - } - - @Override - public boolean add(Path entry) { - if (comparator != null){ - ((PathRoute)entry).sort(balance, cargo); - } - if (groupSize>0){ - addToGroupTop(list, entry, limit, comparator, (e) -> e.getLength()-1, groupSize); - } else { - if (comparator != null){ - addToTop(list, entry, limit, comparator); - } else { - if (list.size() >= limit) return false; - list.add(entry); - if (list.size() >= limit) return false; - } - } - return true; - } - } - -} diff --git a/core/src/main/java/ru/trader/graph/RouteSearcher.java b/core/src/main/java/ru/trader/graph/RouteSearcher.java deleted file mode 100644 index 6642297..0000000 --- a/core/src/main/java/ru/trader/graph/RouteSearcher.java +++ /dev/null @@ -1,145 +0,0 @@ -package ru.trader.graph; - - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ru.trader.core.Vendor; - -import java.util.*; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.RecursiveTask; - -public class RouteSearcher { - private final static Logger LOG = LoggerFactory.getLogger(RouteSearcher.class); - private final static ForkJoinPool POOL = new ForkJoinPool(); - private final static int THRESHOLD = (int) Math.ceil(Runtime.getRuntime().availableProcessors()/2.0); - - private final RouteSearcherCallBack callback; - private final double maxDistance; - private final double stock; - private final int segmentSize; - - public RouteSearcher(double maxDistance, double stock) { - this(maxDistance, stock, 0, new RouteSearcherCallBack()); - } - public RouteSearcher(double maxDistance, double stock, int segmentSize, RouteSearcherCallBack callback) { - this.maxDistance = maxDistance; - this.stock = stock; - this.segmentSize = segmentSize; - this.callback = callback; - } - - public List getPaths(Vendor from, Vendor to, Collection vendors, int jumps, double balance, int cargo, int limit){ - return POOL.invoke(new SegmentSearcher(from, to, vendors, jumps, balance, cargo, limit)); - } - - public List getPaths(Vendor from, Collection vendors, int jumps, double balance, int cargo, int limit){ - return POOL.invoke(new SegmentSearcher(from, null, vendors, jumps, balance, cargo, limit)); - } - - public class SegmentSearcher extends RecursiveTask> { - protected final Vendor source; - protected final Vendor target; - protected final Collection vendors; - protected final int jumps; - protected final double balance; - protected final int cargo; - protected int limit; - - public SegmentSearcher(Vendor source, Vendor target, Collection vendors, int jumps, double balance, int cargo, int limit) { - this.source = source; - this.target = target; - this.vendors = vendors; - this.jumps = jumps; - this.balance = balance; - this.cargo = cargo; - this.limit = limit; - } - - @Override - protected List compute() { - if (callback.isCancel()) return Collections.emptyList(); - LOG.trace("Start search route to {} from {}, jumps {}", source, target, jumps); - GraphCallBack gCallBack = callback.onStart(); - RouteGraph sGraph = new RouteGraph(source, vendors, stock, maxDistance, true, jumps, true, gCallBack); - int jumpsToAll = sGraph.getMinJumps(); - LOG.trace("Segment jumps {}", jumpsToAll); - sGraph.setCargo(cargo); - sGraph.setBalance(balance); - TopList res = new TopList<>(limit, RouteGraph.byProfitComparator); - if (jumps <= jumpsToAll){ - LOG.trace("Is last segment"); - List> paths; - if (target == null){ - paths = sGraph.getPaths(limit); - } else { - paths = sGraph.getPathsTo(target, limit); - } - for (Path path : paths) { - res.add((PathRoute) path); - } - } else { - LOG.trace("Split to segments"); - List> paths = sGraph.getPaths(getPathsOnSegmentCount(sGraph), jumpsToAll).getList(); - int i = 0; - ArrayList subTasks = new ArrayList<>(THRESHOLD); - while (i < paths.size()) { - if (target != null){ - PathRoute path = (PathRoute) paths.get(i); - if (path.getTarget().isEntry(target)){ - LOG.trace("Is path to target, add to res"); - res.add(path); - } - } - if (callback.isCancel()) break; - subTasks.clear(); - for (int taskIndex = 0; taskIndex < THRESHOLD && i+taskIndex < paths.size(); taskIndex++) { - if (callback.isCancel()) break; - PathRoute path = (PathRoute) paths.get(i+taskIndex); - double newBalance = balance + path.getRoot().getProfit(); - SegmentSearcher task = new SegmentSearcher(path.get(), target, vendors, jumps - path.getLength(), newBalance, cargo, 1); - task.fork(); - subTasks.add(task); - } - for (int taskIndex = 0; taskIndex < subTasks.size(); taskIndex++) { - PathRoute path = (PathRoute) paths.get(i+taskIndex); - add(subTasks.get(taskIndex), path, res); - } - i+=subTasks.size(); - } - } - res.finish(); - callback.onEnd(gCallBack); - return res.getList(); - } - - private int getPathsOnSegmentCount(RouteGraph graph){ - if (segmentSize ==0){ - return graph.vertexes.size()*graph.minJumps; - } else { - return segmentSize; - } - } - - - private void add(SegmentSearcher task, PathRoute path, TopList res){ - if (callback.isCancel()){ - task.cancel(true); - return; - } - List tail = task.join(); - if (tail.isEmpty()){ - LOG.trace("Not found route from {} to {}, jumps {}", task.source, task.target, task.jumps); - } else { - path = path.add(tail.get(0), false); - path.sort(balance, cargo); - res.add(path); - } - } - - - - } - - -} diff --git a/core/src/main/java/ru/trader/graph/TopList.java b/core/src/main/java/ru/trader/graph/TopList.java deleted file mode 100644 index 97fcd77..0000000 --- a/core/src/main/java/ru/trader/graph/TopList.java +++ /dev/null @@ -1,96 +0,0 @@ -package ru.trader.graph; - -import java.util.*; -import java.util.function.Function; - -public class TopList { - protected final List list; - protected final int limit; - protected final Comparator comparator; - - public TopList(int limit) { - this(limit, null); - } - - - public TopList(int limit, Comparator comparator) { - this.list = new ArrayList<>(limit); - this.limit = limit; - this.comparator = comparator; - } - - //return true if is last entry or list is full - public boolean add(T entry){ - if (comparator != null){ - addToTop(list, entry, limit, comparator); - } else { - if (list.size() >= limit) return false; - list.add(entry); - if (list.size() >= limit) return false; - } - return true; - } - - public void finish(){ - if (comparator != null && list.size() < limit) - list.sort(comparator); - } - - public List getList() { - return list; - } - - public static void addToGroupTop(List list, T entry, int limit, Comparator comparator, Function getGroup, int groupSize) { - boolean isFull = list.size() >= limit; - int group = getGroup.apply(entry); - int groupStart = groupSize * group; - int groupEnd = groupSize * (group + 1); - if (!isFull){ - if (groupStart >= list.size()) groupStart = list.size(); - if (groupEnd >= list.size()) groupEnd = list.size(); - } - List groupList = list.subList(groupStart, groupEnd); - T removeEntry = addToTop(groupList, entry, groupSize, comparator); - if (!isFull && removeEntry != null && group != getGroup.apply(removeEntry)){ - addToGroupTop(list, removeEntry, limit, comparator, getGroup, groupSize); - } - } - - public static T addToTop(List list, T entry, int limit, Comparator comparator) { - if (list.size() == limit) { - int index = Collections.binarySearch(list, entry, comparator); - if (index < 0) index = -1 - index; - if (index == limit || list.get(index).equals(entry)) return null; - list.add(index, entry); - return list.remove(limit); - - } else { - if (list.size() < limit - 1) { - list.add(entry); - } else { - list.add(entry); - list.sort(comparator); - } - } - return null; - } - - public static void addAllToTop(List list, Collection sortEntries, int limit, Comparator comparator) { - for (T entry : sortEntries) { - if (list.size() == limit) { - int index = Collections.binarySearch(list, entry, comparator); - if (index < 0) index = -1 - index; - if (index == limit || list.get(index).equals(entry)) return; - list.add(index, entry); - list.remove(limit); - } else { - if (list.size() < limit - 1) { - list.add(entry); - } else { - list.add(entry); - list.sort(comparator); - } - } - } - } -} \ No newline at end of file diff --git a/core/src/main/java/ru/trader/graph/Vertex.java b/core/src/main/java/ru/trader/graph/Vertex.java deleted file mode 100644 index 3e2eede..0000000 --- a/core/src/main/java/ru/trader/graph/Vertex.java +++ /dev/null @@ -1,88 +0,0 @@ -package ru.trader.graph; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; - -public class Vertex> { - private final ArrayList> edges = new ArrayList<>(); - private final T entry; - private volatile int level = -1; - - public Vertex(T entry) { - this.entry = entry; - } - - public T getEntry() { - return entry; - } - - public boolean isEntry(T entry){ - return this.entry.equals(entry); - } - - public boolean isConnected(Vertex other){ - return isConnected(other.entry); - } - - public boolean isConnected(T other){ - return edges.stream().anyMatch((e) -> e.isConnect(other)); - } - - public void addEdge(Edge edge){ - synchronized (edges){ - if (edges.contains(edge)) return; - edges.add(edge); - } - } - - public Collection> getEdges() { - return edges; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Vertex vertex = (Vertex) o; - return entry.equals(vertex.entry); - - } - - @Override - public int hashCode() { - return entry.hashCode(); - } - - public void sortEdges(Comparator comparator){ - edges.sort(comparator); - } - - public int getLevel() { - return level; - } - - public void setLevel(int level) { - this.level = level; - } - - public int getEdgesCount(){ - return edges.size(); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("Vertex{"); - sb.append(entry); - sb.append(", lvl=").append(level); - sb.append('}'); - return sb.toString(); - } - - public Edge getEdge(Vertex target) { - for (Edge edge : edges) { - if (edge.isConnect(target)) return edge; - } - return null; - } -}