diff --git a/applications/algorithms/path-finding/README.md b/applications/algorithms/path-finding/README.md new file mode 100644 index 0000000000..1cdf50f4ce --- /dev/null +++ b/applications/algorithms/path-finding/README.md @@ -0,0 +1,18 @@ +# Path Finding Applications + +We are in the application layer, so we offer all the verticals for path finding, such as Dijkstra oin various forms, A*, Yens, you name it. + +And we package them in a neat facade so that we are easily used from e.g. the Neo4j integration layer. + +## Facade design + +We offer facades segmented by mode, e.g. writes or estimates. +Because these facades are the top level thing in the path finding segment of this layer, +we should make it very useful and usable. That is their purpose. +A single dependency that grants access. + +We should capture reuse here that different UIs need. Neo4j Procedures coming in, maybe Arrow, let's make life easy for them. + +Concretely, we have UI layers inject result rendering as that is bespoke. We delegate downwards for the actual computations. + +Importantly, each segment-facade decides which, if any, mutate or write hooks need to be injected. We pick those from a catalog since they are all the same - relationship-centric for path finding. diff --git a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/AlgorithmLabels.java b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/AlgorithmLabels.java new file mode 100644 index 0000000000..916eda0389 --- /dev/null +++ b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/AlgorithmLabels.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.applications.algorithms.pathfinding; + +/** + * We need human-readable labels for e.g. progress tracking + */ +interface AlgorithmLabels { + String A_STAR = "AStar"; + String DIJKSTRA = "Dijkstra"; + String YENS = "Yens"; +} diff --git a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsBusinessFacade.java b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsBusinessFacade.java deleted file mode 100644 index c3c5d5ebf5..0000000000 --- a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsBusinessFacade.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.gds.applications.algorithms.pathfinding; - -import org.neo4j.gds.api.GraphName; -import org.neo4j.gds.paths.SourceTargetShortestPathBaseConfig; -import org.neo4j.gds.paths.astar.AStarMemoryEstimateDefinition; -import org.neo4j.gds.paths.astar.config.ShortestPathAStarBaseConfig; -import org.neo4j.gds.paths.astar.config.ShortestPathAStarMutateConfig; -import org.neo4j.gds.paths.astar.config.ShortestPathAStarStreamConfig; -import org.neo4j.gds.paths.dijkstra.DijkstraMemoryEstimateDefinition; -import org.neo4j.gds.paths.dijkstra.PathFindingResult; -import org.neo4j.gds.paths.dijkstra.config.AllShortestPathsDijkstraMutateConfig; -import org.neo4j.gds.paths.dijkstra.config.AllShortestPathsDijkstraStreamConfig; -import org.neo4j.gds.paths.dijkstra.config.ShortestPathDijkstraMutateConfig; -import org.neo4j.gds.paths.dijkstra.config.ShortestPathDijkstraStreamConfig; -import org.neo4j.gds.paths.yens.YensMemoryEstimateDefinition; -import org.neo4j.gds.paths.yens.config.ShortestPathYensBaseConfig; -import org.neo4j.gds.paths.yens.config.ShortestPathYensMutateConfig; -import org.neo4j.gds.paths.yens.config.ShortestPathYensStreamConfig; -import org.neo4j.gds.results.MemoryEstimateResult; - -import java.util.Optional; - -/** - * Here is the top level business facade for all your path finding needs. - * It will have all pathfinding algorithms on it, each in four modes {mutate, stats, stream, write}, - * and algorithm estimates too. - *

- * That could get really long so consider something cleverer, like per mode sub-facades, or algorithm sub-facades. - * Prolly the former because cohesion. - *

- * Because this is the top level thing, we should make it very useful and usable, - * in the sense that we can capture reuse here that different UIs need. Neo4j Procedures coming in, maybe Arrow, - * let's make life easy for them. - *

- * Concretely, we have UI layers inject result rendering as that is bespoke. - * We delegate downwards for the actual computations. - * But importantly, this is where we decide which, if any, mutate or write hooks need to be injected. - */ -public class PathFindingAlgorithmsBusinessFacade { - private final AlgorithmProcessingTemplate algorithmProcessingTemplate; - private final AlgorithmEstimationTemplate algorithmEstimationTemplate; - - private final PathFindingAlgorithms pathFindingAlgorithms; - - public PathFindingAlgorithmsBusinessFacade( - AlgorithmProcessingTemplate algorithmProcessingTemplate, - AlgorithmEstimationTemplate algorithmEstimationTemplate, - PathFindingAlgorithms pathFindingAlgorithms - ) { - this.algorithmProcessingTemplate = algorithmProcessingTemplate; - this.pathFindingAlgorithms = pathFindingAlgorithms; - this.algorithmEstimationTemplate = algorithmEstimationTemplate; - } - - public MemoryEstimateResult singlePairShortestPathAStarEstimate( - ShortestPathAStarBaseConfig configuration, - Object graphNameOrConfiguration - ) { - var memoryEstimation = new AStarMemoryEstimateDefinition().memoryEstimation(configuration); - - return algorithmEstimationTemplate.estimate( - configuration, - graphNameOrConfiguration, - memoryEstimation - ); - } - - public RESULT singlePairShortestPathAStarMutate( - GraphName graphName, - ShortestPathAStarMutateConfig configuration, - ResultBuilder resultBuilder - ) { - var mutateStep = new ShortestPathMutateStep(configuration); - - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "AStar", - () -> new AStarMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singlePairShortestPathAStar(graph, configuration), - Optional.of(mutateStep), - resultBuilder - ); - } - - public RESULT singlePairShortestPathAStarStream( - GraphName graphName, - ShortestPathAStarStreamConfig configuration, - ResultBuilder resultBuilder - ) { - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "AStar", - () -> new AStarMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singlePairShortestPathAStar(graph, configuration), - Optional.empty(), - resultBuilder - ); - } - - public MemoryEstimateResult singlePairShortestPathDijkstraEstimate( - SourceTargetShortestPathBaseConfig configuration, - Object graphNameOrConfiguration - ) { - var memoryEstimation = new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration); - - return algorithmEstimationTemplate.estimate( - configuration, - graphNameOrConfiguration, - memoryEstimation - ); - } - - public RESULT singlePairShortestPathDijkstraMutate( - GraphName graphName, - ShortestPathDijkstraMutateConfig configuration, - ResultBuilder resultBuilder - ) { - var mutateStep = new ShortestPathMutateStep(configuration); - - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "Dijkstra", - () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singlePairShortestPathDijkstra(graph, configuration), - Optional.of(mutateStep), - resultBuilder - ); - } - - public RESULT singlePairShortestPathDijkstraStream( - GraphName graphName, - ShortestPathDijkstraStreamConfig configuration, - ResultBuilder resultBuilder - ) { - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "Dijkstra", - () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singlePairShortestPathDijkstra(graph, configuration), - Optional.empty(), - resultBuilder - ); - } - - public MemoryEstimateResult singlePairShortestPathYensEstimate( - ShortestPathYensBaseConfig configuration, - Object graphNameOrConfiguration - ) { - var memoryEstimation = new YensMemoryEstimateDefinition().memoryEstimation(configuration); - - return algorithmEstimationTemplate.estimate( - configuration, - graphNameOrConfiguration, - memoryEstimation - ); - } - - public RESULT singlePairShortestPathYensMutate( - GraphName graphName, - ShortestPathYensMutateConfig configuration, - ResultBuilder resultBuilder - ) { - var mutateStep = new ShortestPathMutateStep(configuration); - - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "Yens", - () -> new YensMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singlePairShortestPathYens(graph, configuration), - Optional.of(mutateStep), - resultBuilder - ); - } - - public RESULT singlePairShortestPathYensStream( - GraphName graphName, - ShortestPathYensStreamConfig configuration, - ResultBuilder resultBuilder - ) { - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "Yens", - () -> new YensMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singlePairShortestPathYens(graph, configuration), - Optional.empty(), - resultBuilder - ); - } - - public RESULT singleSourceShortestPathDijkstraMutate( - GraphName graphName, - AllShortestPathsDijkstraMutateConfig configuration, - ResultBuilder resultBuilder - ) { - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "Dijkstra", - () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singleSourceShortestPathDijkstra(graph, configuration), - Optional.of(new ShortestPathMutateStep(configuration)), - resultBuilder - ); - } - - public RESULT singleSourceShortestPathDijkstraStream( - GraphName graphName, - AllShortestPathsDijkstraStreamConfig configuration, - ResultBuilder resultBuilder - ) { - return algorithmProcessingTemplate.processAlgorithm( - graphName, - configuration, - "Dijkstra", - () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), - graph -> pathFindingAlgorithms.singleSourceShortestPathDijkstra(graph, configuration), - Optional.empty(), - resultBuilder - ); - } -} diff --git a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsEstimationModeBusinessFacade.java b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsEstimationModeBusinessFacade.java new file mode 100644 index 0000000000..680a694642 --- /dev/null +++ b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsEstimationModeBusinessFacade.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.applications.algorithms.pathfinding; + +import org.neo4j.gds.AlgorithmMemoryEstimateDefinition; +import org.neo4j.gds.config.AlgoBaseConfig; +import org.neo4j.gds.paths.SourceTargetShortestPathBaseConfig; +import org.neo4j.gds.paths.astar.AStarMemoryEstimateDefinition; +import org.neo4j.gds.paths.astar.config.ShortestPathAStarBaseConfig; +import org.neo4j.gds.paths.dijkstra.DijkstraMemoryEstimateDefinition; +import org.neo4j.gds.paths.yens.YensMemoryEstimateDefinition; +import org.neo4j.gds.paths.yens.config.ShortestPathYensBaseConfig; +import org.neo4j.gds.results.MemoryEstimateResult; + +/** + * Here is the top level business facade for all your path finding memory estimation needs. + * It will have all pathfinding algorithms on it, in estimate mode. + */ +public class PathFindingAlgorithmsEstimationModeBusinessFacade { + private final AlgorithmEstimationTemplate algorithmEstimationTemplate; + + public PathFindingAlgorithmsEstimationModeBusinessFacade(AlgorithmEstimationTemplate algorithmEstimationTemplate) { + this.algorithmEstimationTemplate = algorithmEstimationTemplate; + } + + public MemoryEstimateResult singlePairShortestPathAStarEstimate( + ShortestPathAStarBaseConfig configuration, + Object graphNameOrConfiguration + ) { + return runEstimation(new AStarMemoryEstimateDefinition(), configuration, graphNameOrConfiguration); + } + + public MemoryEstimateResult singlePairShortestPathDijkstraEstimate( + SourceTargetShortestPathBaseConfig configuration, + Object graphNameOrConfiguration + ) { + return runEstimation(new DijkstraMemoryEstimateDefinition(), configuration, graphNameOrConfiguration); + } + + public MemoryEstimateResult singlePairShortestPathYensEstimate( + ShortestPathYensBaseConfig configuration, + Object graphNameOrConfiguration + ) { + return runEstimation(new YensMemoryEstimateDefinition(), configuration, graphNameOrConfiguration); + } + + private MemoryEstimateResult runEstimation( + AlgorithmMemoryEstimateDefinition memoryEstimateDefinition, + CONFIGURATION configuration, + Object graphNameOrConfiguration + ) { + var memoryEstimation = memoryEstimateDefinition.memoryEstimation(configuration); + + return algorithmEstimationTemplate.estimate( + configuration, + graphNameOrConfiguration, + memoryEstimation + ); + } +} diff --git a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsMutateModeBusinessFacade.java b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsMutateModeBusinessFacade.java new file mode 100644 index 0000000000..9370ad0213 --- /dev/null +++ b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsMutateModeBusinessFacade.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.applications.algorithms.pathfinding; + +import org.neo4j.gds.api.GraphName; +import org.neo4j.gds.paths.astar.AStarMemoryEstimateDefinition; +import org.neo4j.gds.paths.astar.config.ShortestPathAStarMutateConfig; +import org.neo4j.gds.paths.dijkstra.DijkstraMemoryEstimateDefinition; +import org.neo4j.gds.paths.dijkstra.PathFindingResult; +import org.neo4j.gds.paths.dijkstra.config.AllShortestPathsDijkstraMutateConfig; +import org.neo4j.gds.paths.dijkstra.config.ShortestPathDijkstraMutateConfig; +import org.neo4j.gds.paths.yens.YensMemoryEstimateDefinition; +import org.neo4j.gds.paths.yens.config.ShortestPathYensMutateConfig; + +import java.util.Optional; + +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.A_STAR; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.DIJKSTRA; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.YENS; + +/** + * Here is the top level business facade for all your path finding mutate needs. + * It will have all pathfinding algorithms on it, in mutate mode. + */ +public class PathFindingAlgorithmsMutateModeBusinessFacade { + private final AlgorithmProcessingTemplate algorithmProcessingTemplate; + + private final PathFindingAlgorithms pathFindingAlgorithms; + + public PathFindingAlgorithmsMutateModeBusinessFacade( + AlgorithmProcessingTemplate algorithmProcessingTemplate, + PathFindingAlgorithms pathFindingAlgorithms + ) { + this.algorithmProcessingTemplate = algorithmProcessingTemplate; + this.pathFindingAlgorithms = pathFindingAlgorithms; + } + + public RESULT singlePairShortestPathAStarMutate( + GraphName graphName, + ShortestPathAStarMutateConfig configuration, + ResultBuilder resultBuilder + ) { + var mutateStep = new ShortestPathMutateStep(configuration); + + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + A_STAR, + () -> new AStarMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singlePairShortestPathAStar(graph, configuration), + Optional.of(mutateStep), + resultBuilder + ); + } + + public RESULT singlePairShortestPathDijkstraMutate( + GraphName graphName, + ShortestPathDijkstraMutateConfig configuration, + ResultBuilder resultBuilder + ) { + var mutateStep = new ShortestPathMutateStep(configuration); + + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + DIJKSTRA, + () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singlePairShortestPathDijkstra(graph, configuration), + Optional.of(mutateStep), + resultBuilder + ); + } + + public RESULT singlePairShortestPathYensMutate( + GraphName graphName, + ShortestPathYensMutateConfig configuration, + ResultBuilder resultBuilder + ) { + var mutateStep = new ShortestPathMutateStep(configuration); + + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + YENS, + () -> new YensMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singlePairShortestPathYens(graph, configuration), + Optional.of(mutateStep), + resultBuilder + ); + } + + public RESULT singleSourceShortestPathDijkstraMutate( + GraphName graphName, + AllShortestPathsDijkstraMutateConfig configuration, + ResultBuilder resultBuilder + ) { + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + DIJKSTRA, + () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singleSourceShortestPathDijkstra(graph, configuration), + Optional.of(new ShortestPathMutateStep(configuration)), + resultBuilder + ); + } +} diff --git a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsStreamModeBusinessFacade.java b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsStreamModeBusinessFacade.java new file mode 100644 index 0000000000..5a8ebd2d50 --- /dev/null +++ b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsStreamModeBusinessFacade.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.applications.algorithms.pathfinding; + +import org.neo4j.gds.api.GraphName; +import org.neo4j.gds.paths.astar.AStarMemoryEstimateDefinition; +import org.neo4j.gds.paths.astar.config.ShortestPathAStarStreamConfig; +import org.neo4j.gds.paths.dijkstra.DijkstraMemoryEstimateDefinition; +import org.neo4j.gds.paths.dijkstra.PathFindingResult; +import org.neo4j.gds.paths.dijkstra.config.AllShortestPathsDijkstraStreamConfig; +import org.neo4j.gds.paths.dijkstra.config.ShortestPathDijkstraStreamConfig; +import org.neo4j.gds.paths.yens.YensMemoryEstimateDefinition; +import org.neo4j.gds.paths.yens.config.ShortestPathYensStreamConfig; + +import java.util.Optional; + +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.A_STAR; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.DIJKSTRA; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.YENS; + +/** + * Here is the top level business facade for all your path finding stream needs. + * It will have all pathfinding algorithms on it, in stream mode. + */ +public class PathFindingAlgorithmsStreamModeBusinessFacade { + private final AlgorithmProcessingTemplate algorithmProcessingTemplate; + + private final PathFindingAlgorithms pathFindingAlgorithms; + + public PathFindingAlgorithmsStreamModeBusinessFacade( + AlgorithmProcessingTemplate algorithmProcessingTemplate, + PathFindingAlgorithms pathFindingAlgorithms + ) { + this.algorithmProcessingTemplate = algorithmProcessingTemplate; + this.pathFindingAlgorithms = pathFindingAlgorithms; + } + + public RESULT singlePairShortestPathAStarStream( + GraphName graphName, + ShortestPathAStarStreamConfig configuration, + ResultBuilder resultBuilder + ) { + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + A_STAR, + () -> new AStarMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singlePairShortestPathAStar(graph, configuration), + Optional.empty(), + resultBuilder + ); + } + + public RESULT singlePairShortestPathDijkstraStream( + GraphName graphName, + ShortestPathDijkstraStreamConfig configuration, + ResultBuilder resultBuilder + ) { + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + DIJKSTRA, + () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singlePairShortestPathDijkstra(graph, configuration), + Optional.empty(), + resultBuilder + ); + } + + public RESULT singlePairShortestPathYensStream( + GraphName graphName, + ShortestPathYensStreamConfig configuration, + ResultBuilder resultBuilder + ) { + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + YENS, + () -> new YensMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singlePairShortestPathYens(graph, configuration), + Optional.empty(), + resultBuilder + ); + } + + public RESULT singleSourceShortestPathDijkstraStream( + GraphName graphName, + AllShortestPathsDijkstraStreamConfig configuration, + ResultBuilder resultBuilder + ) { + return algorithmProcessingTemplate.processAlgorithm( + graphName, + configuration, + DIJKSTRA, + () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), + graph -> pathFindingAlgorithms.singleSourceShortestPathDijkstra(graph, configuration), + Optional.empty(), + resultBuilder + ); + } +} diff --git a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsWriteModeBusinessFacade.java b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsWriteModeBusinessFacade.java index 29857cb1fb..740b272a76 100644 --- a/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsWriteModeBusinessFacade.java +++ b/applications/algorithms/path-finding/src/main/java/org/neo4j/gds/applications/algorithms/pathfinding/PathFindingAlgorithmsWriteModeBusinessFacade.java @@ -40,21 +40,13 @@ import java.util.Optional; import java.util.function.Supplier; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.A_STAR; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.DIJKSTRA; +import static org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmLabels.YENS; + /** - * Here is the top level business facade for all your path finding needs. - * It will have all pathfinding algorithms on it, each in four modes {mutate, stats, stream, write}, - * and algorithm estimates too. - *

- * That could get really long so consider something cleverer, like per mode sub-facades, or algorithm sub-facades. - * Prolly the former because cohesion. - *

- * Because this is the top level thing, we should make it very useful and usable, - * in the sense that we can capture reuse here that different UIs need. Neo4j Procedures coming in, maybe Arrow, - * let's make life easy for them. - *

- * Concretely, we have UI layers inject result rendering as that is bespoke. - * We delegate downwards for the actual computations. - * But importantly, this is where we decide which, if any, mutate or write hooks need to be injected. + * Here is the top level business facade for all your path finding write needs. + * It will have all pathfinding algorithms on it, in write mode. */ public class PathFindingAlgorithmsWriteModeBusinessFacade { private final Log log; @@ -90,7 +82,7 @@ public RESULT singlePairShortestPathAStarWrite( return runAlgorithmAndWrite( graphName, configuration, - "AStar", + A_STAR, () -> new AStarMemoryEstimateDefinition().memoryEstimation(configuration), graph -> pathFindingAlgorithms.singlePairShortestPathAStar(graph, configuration), resultBuilder @@ -105,7 +97,7 @@ public RESULT singlePairShortestPathDijkstraWrite( return runAlgorithmAndWrite( graphName, configuration, - "Dijkstra", + DIJKSTRA, () -> new DijkstraMemoryEstimateDefinition().memoryEstimation(configuration), graph -> pathFindingAlgorithms.singlePairShortestPathDijkstra(graph, configuration), resultBuilder @@ -120,7 +112,7 @@ public RESULT singlePairShortestPathYensWrite( return runAlgorithmAndWrite( graphName, configuration, - "Yens", + YENS, () -> new YensMemoryEstimateDefinition().memoryEstimation(configuration), graph -> pathFindingAlgorithms.singlePairShortestPathYens(graph, configuration), resultBuilder @@ -135,13 +127,13 @@ private algorithm, ResultBuilder resultBuilder ) { - Optional> writeStep = Optional.of(new ShortestPathWriteStep<>( + ShortestPathWriteStep writeStep = new ShortestPathWriteStep<>( log, relationshipStreamExporterBuilder, taskRegistryFactory, terminationFlag, configuration - )); + ); return algorithmProcessingTemplate.processAlgorithm( graphName, @@ -149,7 +141,7 @@ private singlePairShortestPathAStarMutate( graphName, configuration, ShortestPathAStarMutateConfig::of, - facade::singlePairShortestPathAStarMutate + mutateModeFacade::singlePairShortestPathAStarMutate ) ); } @@ -103,7 +111,7 @@ public Stream singlePairShortestPathAStarMutateEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathAStarMutateConfig::of, - configuration -> facade.singlePairShortestPathAStarEstimate( + configuration -> estimationModeFacade.singlePairShortestPathAStarEstimate( configuration, graphNameOrConfiguration ) @@ -120,7 +128,7 @@ public Stream singlePairShortestPathAStarStream( graphName, configuration, ShortestPathAStarStreamConfig::of, - facade::singlePairShortestPathAStarStream + streamModeFacade::singlePairShortestPathAStarStream ); } @@ -131,7 +139,7 @@ public Stream singlePairShortestPathAStarStreamEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathAStarStreamConfig::of, - configuration -> facade.singlePairShortestPathAStarEstimate( + configuration -> estimationModeFacade.singlePairShortestPathAStarEstimate( configuration, graphNameOrConfiguration ) @@ -161,7 +169,7 @@ public Stream singlePairShortestPathAStarWriteEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathAStarWriteConfig::of, - configuration -> facade.singlePairShortestPathAStarEstimate( + configuration -> estimationModeFacade.singlePairShortestPathAStarEstimate( configuration, graphNameOrConfiguration ) @@ -179,7 +187,7 @@ public Stream singlePairShortestPathDijkstraMutate( graphName, configuration, ShortestPathDijkstraMutateConfig::of, - facade::singlePairShortestPathDijkstraMutate + mutateModeFacade::singlePairShortestPathDijkstraMutate ) ); } @@ -191,7 +199,7 @@ public Stream singlePairShortestPathDijkstraMutateEstimate var result = runEstimation( algorithmConfiguration, ShortestPathDijkstraMutateConfig::of, - configuration -> facade.singlePairShortestPathDijkstraEstimate( + configuration -> estimationModeFacade.singlePairShortestPathDijkstraEstimate( configuration, graphNameOrConfiguration ) @@ -208,7 +216,7 @@ public Stream singlePairShortestPathDijkstraStream( graphName, configuration, ShortestPathDijkstraStreamConfig::of, - facade::singlePairShortestPathDijkstraStream + streamModeFacade::singlePairShortestPathDijkstraStream ); } @@ -219,7 +227,7 @@ public Stream singlePairShortestPathDijkstraStreamEstimate var result = runEstimation( algorithmConfiguration, ShortestPathDijkstraStreamConfig::of, - configuration -> facade.singlePairShortestPathDijkstraEstimate( + configuration -> estimationModeFacade.singlePairShortestPathDijkstraEstimate( configuration, graphNameOrConfiguration ) @@ -249,7 +257,7 @@ public Stream singlePairShortestPathDijkstraWriteEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathDijkstraWriteConfig::of, - configuration -> facade.singlePairShortestPathDijkstraEstimate( + configuration -> estimationModeFacade.singlePairShortestPathDijkstraEstimate( configuration, graphNameOrConfiguration ) @@ -267,7 +275,7 @@ public Stream singlePairShortestPathYensMutate( graphName, configuration, ShortestPathYensMutateConfig::of, - facade::singlePairShortestPathYensMutate + mutateModeFacade::singlePairShortestPathYensMutate ) ); } @@ -279,7 +287,7 @@ public Stream singlePairShortestPathYensMutateEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathYensMutateConfig::of, - configuration -> facade.singlePairShortestPathYensEstimate( + configuration -> estimationModeFacade.singlePairShortestPathYensEstimate( configuration, graphNameOrConfiguration ) @@ -296,7 +304,7 @@ public Stream singlePairShortestPathYensStream( graphName, configuration, ShortestPathYensStreamConfig::of, - facade::singlePairShortestPathYensStream + streamModeFacade::singlePairShortestPathYensStream ); } @@ -307,7 +315,7 @@ public Stream singlePairShortestPathYensStreamEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathYensStreamConfig::of, - configuration -> facade.singlePairShortestPathYensEstimate( + configuration -> estimationModeFacade.singlePairShortestPathYensEstimate( configuration, graphNameOrConfiguration ) @@ -337,7 +345,7 @@ public Stream singlePairShortestPathYensWriteEstimate( var result = runEstimation( algorithmConfiguration, ShortestPathYensWriteConfig::of, - configuration -> facade.singlePairShortestPathYensEstimate( + configuration -> estimationModeFacade.singlePairShortestPathYensEstimate( configuration, graphNameOrConfiguration ) @@ -355,7 +363,7 @@ public Stream singleSourceShortestPathDijkstraMutate( graphName, configuration, AllShortestPathsDijkstraMutateConfig::of, - facade::singleSourceShortestPathDijkstraMutate + mutateModeFacade::singleSourceShortestPathDijkstraMutate ) ); } @@ -368,7 +376,7 @@ public Stream singleSourceShortestPathDijkstraStream( graphName, configuration, AllShortestPathsDijkstraStreamConfig::of, - facade::singleSourceShortestPathDijkstraStream + streamModeFacade::singleSourceShortestPathDijkstraStream ); } diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmProcedureFacadeProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmProcedureFacadeProvider.java index cf50310193..f68c4ad814 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmProcedureFacadeProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmProcedureFacadeProvider.java @@ -55,7 +55,9 @@ import org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmEstimationTemplate; import org.neo4j.gds.applications.algorithms.pathfinding.AlgorithmProcessingTemplate; import org.neo4j.gds.applications.algorithms.pathfinding.PathFindingAlgorithms; -import org.neo4j.gds.applications.algorithms.pathfinding.PathFindingAlgorithmsBusinessFacade; +import org.neo4j.gds.applications.algorithms.pathfinding.PathFindingAlgorithmsEstimationModeBusinessFacade; +import org.neo4j.gds.applications.algorithms.pathfinding.PathFindingAlgorithmsMutateModeBusinessFacade; +import org.neo4j.gds.applications.algorithms.pathfinding.PathFindingAlgorithmsStreamModeBusinessFacade; import org.neo4j.gds.applications.algorithms.pathfinding.PathFindingAlgorithmsWriteModeBusinessFacade; import org.neo4j.gds.core.utils.progress.TaskRegistryFactory; import org.neo4j.gds.core.utils.warnings.UserLogRegistryFactory; @@ -232,9 +234,15 @@ PathFindingProcedureFacade createPathFindingProcedureFacade() { userLogRegistryFactory ); - var pathFindingAlgorithmsFacade = new PathFindingAlgorithmsBusinessFacade( + var estimationModeFacade = new PathFindingAlgorithmsEstimationModeBusinessFacade(algorithmEstimationTemplate); + + var mutateModeFacade = new PathFindingAlgorithmsMutateModeBusinessFacade( + algorithmProcessingTemplate, + pathFindingAlgorithms + ); + + var streamModeFacade = new PathFindingAlgorithmsStreamModeBusinessFacade( algorithmProcessingTemplate, - algorithmEstimationTemplate, pathFindingAlgorithms ); @@ -252,7 +260,9 @@ PathFindingProcedureFacade createPathFindingProcedureFacade() { configurationCreator, nodeLookup, returnColumns, - pathFindingAlgorithmsFacade, + estimationModeFacade, + mutateModeFacade, + streamModeFacade, writeModeFacade ); }