diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/centrality/CentralityAlgorithmsStatsBusinessFacade.java b/algo/src/main/java/org/neo4j/gds/algorithms/centrality/CentralityAlgorithmsStatsBusinessFacade.java index d5daa6b959..0ae2c0a077 100644 --- a/algo/src/main/java/org/neo4j/gds/algorithms/centrality/CentralityAlgorithmsStatsBusinessFacade.java +++ b/algo/src/main/java/org/neo4j/gds/algorithms/centrality/CentralityAlgorithmsStatsBusinessFacade.java @@ -23,6 +23,7 @@ import org.neo4j.gds.algorithms.StatsResult; import org.neo4j.gds.algorithms.centrality.specificfields.CentralityStatisticsSpecificFields; import org.neo4j.gds.algorithms.centrality.specificfields.DefaultCentralitySpecificFields; +import org.neo4j.gds.algorithms.centrality.specificfields.PageRankSpecificFields; import org.neo4j.gds.algorithms.runner.AlgorithmRunner; import org.neo4j.gds.betweenness.BetweennessCentralityStatsConfig; import org.neo4j.gds.closeness.ClosenessCentralityStatsConfig; @@ -30,6 +31,8 @@ import org.neo4j.gds.core.concurrency.DefaultPool; import org.neo4j.gds.degree.DegreeCentralityStatsConfig; import org.neo4j.gds.harmonic.HarmonicCentralityStatsConfig; +import org.neo4j.gds.pagerank.PageRankResult; +import org.neo4j.gds.pagerank.PageRankStatsConfig; import org.neo4j.gds.result.CentralityStatistics; import java.util.function.Supplier; @@ -115,16 +118,45 @@ public StatsResult harmonicCentrality( ); } + public StatsResult pageRank( + String graphName, + PageRankStatsConfig configuration, + boolean shouldComputeCentralityDistribution + ) { + // 1. Run the algorithm and time the execution + var intermediateResult = AlgorithmRunner.runWithTiming( + () -> centralityAlgorithmsFacade.pageRank(graphName, configuration) + ); - StatsResult statsResult( + CentralityFunctionSupplier centralityFunctionSupplier = CentralityAlgorithmResult::centralityScoreProvider; + SpecificFieldsWithCentralityDistributionSupplier specificFieldsSupplier = + (r, c) -> new PageRankSpecificFields(r.iterations(), r.didConverge(), c); + + Supplier emptyASFSupplier = () -> PageRankSpecificFields.EMPTY; + + return statsResult( + intermediateResult.algorithmResult, + configuration, + centralityFunctionSupplier, + specificFieldsSupplier, + shouldComputeCentralityDistribution, + intermediateResult.computeMilliseconds, + emptyASFSupplier + ); + + } + + + private StatsResult statsResult( AlgorithmComputationResult algorithmResult, CONFIG configuration, boolean shouldComputeCentralityDistribution, long computeMilliseconds ) { - CentralityFunctionSupplier centralityFunctionSupplier = (r) -> r.centralityScoreProvider(); - SpecificFieldsWithCentralityDistributionSupplier specificFieldsSupplier = (r, c) -> new DefaultCentralitySpecificFields( - c); + CentralityFunctionSupplier centralityFunctionSupplier = CentralityAlgorithmResult::centralityScoreProvider; + SpecificFieldsWithCentralityDistributionSupplier specificFieldsSupplier = + (r, c) -> new DefaultCentralitySpecificFields(c); + Supplier emptyASFSupplier = () -> DefaultCentralitySpecificFields.EMPTY; return statsResult( diff --git a/algo/src/main/java/org/neo4j/gds/algorithms/centrality/specificfields/PageRankSpecificFields.java b/algo/src/main/java/org/neo4j/gds/algorithms/centrality/specificfields/PageRankSpecificFields.java new file mode 100644 index 0000000000..d24f624581 --- /dev/null +++ b/algo/src/main/java/org/neo4j/gds/algorithms/centrality/specificfields/PageRankSpecificFields.java @@ -0,0 +1,58 @@ +/* + * 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.algorithms.centrality.specificfields; + +import java.util.Map; + +public class PageRankSpecificFields implements CentralityStatisticsSpecificFields { + + public static final PageRankSpecificFields EMPTY = new PageRankSpecificFields( + 0, + false, + Map.of() + ); + + private final long ranIterations; + private final boolean didConverge; + private final Map centralityDistribution; + + public PageRankSpecificFields( + long ranIterations, + boolean didConverge, + Map centralityDistribution + ) { + this.ranIterations = ranIterations; + this.didConverge = didConverge; + this.centralityDistribution = centralityDistribution; + } + + public long ranIterations() { + return ranIterations; + } + + public boolean didConverge() { + return didConverge; + } + + @Override + public Map centralityDistribution() { + return centralityDistribution; + } +} diff --git a/proc/centrality/src/main/java/org/neo4j/gds/pagerank/PageRankStatsProc.java b/proc/centrality/src/main/java/org/neo4j/gds/pagerank/PageRankStatsProc.java index de969071c7..b44653a877 100644 --- a/proc/centrality/src/main/java/org/neo4j/gds/pagerank/PageRankStatsProc.java +++ b/proc/centrality/src/main/java/org/neo4j/gds/pagerank/PageRankStatsProc.java @@ -21,9 +21,10 @@ import org.neo4j.gds.BaseProc; import org.neo4j.gds.executor.MemoryEstimationExecutor; -import org.neo4j.gds.executor.ProcedureExecutor; +import org.neo4j.gds.procedures.GraphDataScience; import org.neo4j.gds.procedures.centrality.pagerank.PageRankStatsResult; import org.neo4j.gds.results.MemoryEstimateResult; +import org.neo4j.procedure.Context; import org.neo4j.procedure.Description; import org.neo4j.procedure.Name; import org.neo4j.procedure.Procedure; @@ -35,16 +36,16 @@ public class PageRankStatsProc extends BaseProc { + @Context + public GraphDataScience facade; + @Procedure(value = "gds.pageRank.stats", mode = READ) @Description(STATS_DESCRIPTION) public Stream stats( @Name(value = "graphName") String graphName, @Name(value = "configuration", defaultValue = "{}") Map configuration ) { - return new ProcedureExecutor<>( - new PageRankStatsSpec(), - executionContext() - ).compute(graphName, configuration); + return facade.centrality().pageRankStats(graphName, configuration); } @Procedure(value = "gds.pageRank.stats.estimate", mode = READ) diff --git a/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/CentralityProcedureFacade.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/CentralityProcedureFacade.java index be0b7d7b4e..c279e2dd97 100644 --- a/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/CentralityProcedureFacade.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/CentralityProcedureFacade.java @@ -48,9 +48,12 @@ import org.neo4j.gds.harmonic.HarmonicCentralityWriteConfig; import org.neo4j.gds.procedures.centrality.alphaharmonic.AlphaHarmonicStreamResult; import org.neo4j.gds.procedures.centrality.alphaharmonic.AlphaHarmonicWriteResult; +import org.neo4j.gds.pagerank.PageRankStatsConfig; import org.neo4j.gds.pagerank.PageRankStreamConfig; import org.neo4j.gds.procedures.centrality.betacloseness.BetaClosenessCentralityMutateResult; import org.neo4j.gds.procedures.centrality.betacloseness.BetaClosenessCentralityWriteResult; +import org.neo4j.gds.procedures.centrality.pagerank.PageRankComputationalResultTransformer; +import org.neo4j.gds.procedures.centrality.pagerank.PageRankStatsResult; import org.neo4j.gds.procedures.configparser.ConfigurationParser; import org.neo4j.gds.results.MemoryEstimateResult; @@ -499,6 +502,23 @@ public Stream pageRankStream( return DefaultCentralityComputationalResultTransformer.toStreamResult(computationResult); } + + public Stream pageRankStats( + String graphName, + Map configuration + ) { + var config = createConfig(configuration, PageRankStatsConfig::of); + + var computationResult = statsBusinessFacade.pageRank( + graphName, + config, + procedureReturnColumns.contains("centralityDistribution") + ); + + return Stream.of(PageRankComputationalResultTransformer.toStatsResult(computationResult, config)); + } + + // ################################################################################################################ // FIXME: the following two methods are duplicate, find a good place for them. diff --git a/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/pagerank/PageRankComputationalResultTransformer.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/pagerank/PageRankComputationalResultTransformer.java new file mode 100644 index 0000000000..00c437c645 --- /dev/null +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/centrality/pagerank/PageRankComputationalResultTransformer.java @@ -0,0 +1,45 @@ +/* + * 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.procedures.centrality.pagerank; + +import org.neo4j.gds.algorithms.StatsResult; +import org.neo4j.gds.algorithms.centrality.specificfields.PageRankSpecificFields; +import org.neo4j.gds.pagerank.PageRankStatsConfig; + +public final class PageRankComputationalResultTransformer { + + private PageRankComputationalResultTransformer() {} + + public static PageRankStatsResult toStatsResult( + StatsResult computationResult, + PageRankStatsConfig configuration + ) { + return new PageRankStatsResult( + computationResult.algorithmSpecificFields().ranIterations(), + computationResult.algorithmSpecificFields().didConverge(), + computationResult.algorithmSpecificFields().centralityDistribution(), + computationResult.preProcessingMillis(), + computationResult.computeMillis(), + computationResult.postProcessingMillis(), + configuration.toMap() + ); + } + +}