2016-12-22 3 views
0

私は、Dijkstraのアルゴリズムを使って、2つのノード間で最も重みの小さいパスを見つけなければならない手順に取り組んでいます。このプロシージャは、すべてのノードが特定の基準に一致するパスを返す必要があります(つまり、すべてのノードは特定の値を持つプロパティを持つ必要があります)。パス内の少なくとも1つのノードが基準に一致しない場合、パスは無効になり、アルゴリズムは次に重みの小さいパスを探す必要があります。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'sは不変であるため、たとえばaddNodeFilterは、追加されたフィルタを持つ新しいPathExpanderBuilderを返します。そのため、返されたインスタンスにbuilderを再割り当てする必要があります。

関連する問題