2016-12-22 2 views
0

Я работаю над процедурой, которая должна найти путь с наименьшим весом между двумя узлами с использованием алгоритма Дейкстры. Процедура должна возвращать только пути, все узлы которых соответствуют определенным критериям (т. Е. Все узлы должны иметь свойства со специфическими значениями). Если хотя бы один узел в пути не соответствует критериям, то путь становится недействительным, и алгоритм должен искать следующий низкоуглеродистый путь.Как работает PathExpanderBuilder.addNodeFilter?

Для этого я использую PathExpanderBuilder с узловыми фильтрами, но они, похоже, не фильтруют ничего.

Вот мой код:

public class Demo { 
    @Procedure 
    @Description("apoc.algo.dijkstraWithFilters(startNode, endNode, " + 
      "'distance', 10, 'prop1', 2, 'prop2', [100, 200], 'prop3') " + 
      " YIELD path, weight - run dijkstra with relationship property name as cost function" + 
      " and a default weight if the property does not exist") 
    public Stream<WeightedPathResult> dijkstraWithFilters(
      @Name("startNode") Node startNode, 
      @Name("endNode") Node endNode, 
      @Name("weightPropertyName") String weightPropertyName, 
      @Name("defaultWeight") double defaultWeight, 
      @Name("longPropName") String longPropName, 
      @Name("longPropValue") long longPropValue, 
      @Name("listPropName") String listPropName, 
      @Name("listPropValues") List<Long> listPropValues, 
      @Name("boolPropName") String boolPropName) { 

     PathFinder<WeightedPath> algo = GraphAlgoFactory.dijkstra(
       buildPathExpanderByPermissions(longPropName, longPropValue, listPropName, listPropValues, boolPropName), 
       (relationship, direction) -> convertToDouble(relationship.getProperty(weightPropertyName, defaultWeight)) 
     ); 
     return WeightedPathResult.streamWeightedPathResult(startNode, endNode, algo); 
    } 

    private double convertToDouble(Object property) { 
     if (property instanceof Double) 
      return (double) property; 
     else if (property instanceof Long) 
      return ((Long) property).doubleValue(); 
     else if (property instanceof Integer) 
      return ((Integer) property).doubleValue(); 
     return 1; 
    } 

    private PathExpander<Object> buildPathExpanderByPermissions(
      String longPropName, 
      long longPropValue, 
      String listPropName, 
      List<Long> listPropValue, 
      String boolPropName 
    ) { 
     PathExpanderBuilder builder = PathExpanderBuilder.allTypesAndDirections(); 
     builder.addNodeFilter(
       node -> !node.hasProperty(longPropName) || 
         node.getProperty(longPropName) instanceof Long && 
           (long) node.getProperty(longPropName) < longPropValue 
     ); 
     builder.addNodeFilter(
       node -> { 
        try { 
         return !node.hasProperty(listPropName) || 
           (boolean) node.getProperty(boolPropName, false) || 
           !Collections.disjoint((List<Long>) node.getProperty(listPropName), listPropValue); 
        } 
        catch (Exception e){ 
         return false; 
        } 
       } 
     ); 
     return builder.build(); 
    } 
} 

Что я здесь отсутствует? Я неправильно использую PathExpanderBuilder?

ответ

0

PathExpanderBuilder являются неизменяемыми и, таким образом, вызываются, например. addNodeFilter возвращает новый PathExpanderBuilder с добавленным фильтром, поэтому вам нужно повторно назначить builder с возвращенным экземпляром.

 Смежные вопросы

  • Нет связанных вопросов^_^