diff --git a/core/src/main/java/ru/trader/analysis/RouteSpecification.java b/core/src/main/java/ru/trader/analysis/RouteSpecification.java index c50a006..e4e9033 100644 --- a/core/src/main/java/ru/trader/analysis/RouteSpecification.java +++ b/core/src/main/java/ru/trader/analysis/RouteSpecification.java @@ -6,6 +6,10 @@ import ru.trader.analysis.graph.Traversal; public interface RouteSpecification { public boolean specified(Edge edge, Traversal entry); + public default int lastFound(Edge edge, Traversal entry){ + return specified(edge, entry) ? 0 : matchCount(); + } + public default int matchCount(){return 1;} public default boolean updateMutated(){return false;} public default boolean mutable(){return false;} public default void update(Traversal entry){} @@ -17,6 +21,16 @@ public interface RouteSpecification { return RouteSpecification.this.specified(edge, entry) && other.specified(edge, entry); } + @Override + public int lastFound(Edge edge, Traversal entry) { + return RouteSpecification.this.lastFound(edge, entry) + other.lastFound(edge, entry); + } + + @Override + public int matchCount() { + return RouteSpecification.this.matchCount() + other.matchCount(); + } + @Override public boolean updateMutated() { return RouteSpecification.this.updateMutated() || other.updateMutated(); @@ -42,6 +56,16 @@ public interface RouteSpecification { return RouteSpecification.this.specified(edge, entry) || other.specified(edge, entry); } + @Override + public int lastFound(Edge edge, Traversal entry) { + return Math.min(RouteSpecification.this.lastFound(edge, entry), other.lastFound(edge, entry)); + } + + @Override + public int matchCount() { + return Math.min(RouteSpecification.this.matchCount(), other.matchCount()); + } + @Override public boolean updateMutated() { return RouteSpecification.this.updateMutated() || other.updateMutated(); diff --git a/core/src/main/java/ru/trader/analysis/RouteSpecificationByTargets.java b/core/src/main/java/ru/trader/analysis/RouteSpecificationByTargets.java index 389a7eb..ec4e097 100644 --- a/core/src/main/java/ru/trader/analysis/RouteSpecificationByTargets.java +++ b/core/src/main/java/ru/trader/analysis/RouteSpecificationByTargets.java @@ -20,30 +20,46 @@ public class RouteSpecificationByTargets implements RouteSpecification { @Override public boolean specified(Edge edge, Traversal entry) { + return all ? containsAll(edge, entry) == 0 : containsAny(edge, entry) == 0; + } + + @Override + public int lastFound(Edge edge, Traversal entry) { return all ? containsAll(edge, entry) : containsAny(edge, entry); } - private boolean containsAll(Edge edge, Traversal entry) { + @Override + public int matchCount() { + return all ? targets.size() : 1; + } + + private int containsAll(Edge edge, Traversal entry) { T obj = edge.getTarget().getEntry(); Collection set = new ArrayList<>(targets.size()); set.add(obj); entry.routeIterator().forEachRemaining(e -> set.add(e.getTarget().getEntry())); - return set.containsAll(targets); + int last = targets.size(); + for (T target : targets) { + if (set.contains(target)){ + last--; + } + } + return last; } - private boolean containsAny(Edge edge, Traversal entry) { + private int containsAny(Edge edge, Traversal entry) { T obj = edge.getTarget().getEntry(); - if (targets.contains(obj)) return true; + if (targets.contains(obj)) return 0; if (targetOnly){ - return false; + return 1; } Iterator> iterator = entry.routeIterator(); while (iterator.hasNext()){ if (targets.contains(iterator.next().getTarget().getEntry())){ - return true; + return 0; } } - return false; + return 1; } public static RouteSpecificationByTargets all(Collection targets){ diff --git a/core/src/main/java/ru/trader/analysis/graph/Crawler.java b/core/src/main/java/ru/trader/analysis/graph/Crawler.java index 31d6298..48aeb70 100644 --- a/core/src/main/java/ru/trader/analysis/graph/Crawler.java +++ b/core/src/main/java/ru/trader/analysis/graph/Crawler.java @@ -65,6 +65,10 @@ public class Crawler { return specification.specified(edge, head); } + protected int lastFound(Edge edge, Traversal head){ + return specification.lastFound(edge, head); + } + private void updateState(Traversal entry){ if (specification.mutable()){ specification.update(entry); @@ -511,8 +515,9 @@ public class Crawler { CostTraversalEntry entry = curr.entry; if (skip()) continue; LOG.trace("Check edge {}, entry {}, weight {}, curr {}", edge, entry, entry.weight, curr); - boolean isTarget = isFound(edge, entry); - boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel() && entry.size() < maxSize-1; + int lastFound = lastFound(edge, entry); + boolean isTarget = lastFound == 0; + boolean canDeep = !entry.getTarget().isSingle() && deep < entry.getTarget().getLevel() && entry.size()+lastFound < maxSize; if (canDeep || isTarget){ CostTraversalEntry nextEntry = travers(entry, edge); if (canDeep){