// Path: src/main/java/com/maxdemarzi/processing/NodeCounter.java
// public class NodeCounter {
//     public int getNodeCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH (n) RETURN max(id(n)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
// 
//     }
//     public int getRelationshipCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH ()-[r]->() RETURN max(id(r)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
//     }
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/OpsRunner.java
// public interface OpsRunner {
//     void run(int node) throws EntityNotFoundException;
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/Utils.java
// public class Utils {
//     static final int BATCH_SIZE  = 100_000;
// 
//     public static int toInt(double value) {
//         return (int) (100_000*value);
//     }
//     public static double toFloat(int value) {
//         return value / 100_000.0;
//     }
// 
//     public static SingleSourceShortestPath<Double> getSingleSourceShortestPath(RelationshipType relationshipType)
//     {
//         return new SingleSourceShortestPathDijkstra<Double>( 0.0, null,
//                 new CostEvaluator<Double>()
//                 {
//                     public Double getCost( Relationship relationship,
//                                            Direction direction )
//                     {
//                         return 1.0;
//                     }
//                 }, new org.neo4j.graphalgo.impl.util.DoubleAdder(),
//                 new org.neo4j.graphalgo.impl.util.DoubleComparator(),
//                 Direction.BOTH, relationshipType );
//     }
// 
// 
//     static ExecutorService createPool(int threads, int queueSize) {
//         return new ThreadPoolExecutor(1, threads, 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>(queueSize),
//                 new ThreadPoolExecutor.CallerRunsPolicy());
//     }
// 
//     public static int waitForTasks(List<Future> futures) {
//         int total = 0;
//         for (Future future : futures) {
//             try {
//                 future.get();
//                 total ++;
//             } catch (InterruptedException | ExecutionException e) {
//                 e.printStackTrace();
//             }
//         }
//         futures.clear();
//         return total;
//     }
// 
//     public static void runOperations(ExecutorService pool, final PrimitiveLongIterator it, int totalCount, ReadOperations ops, OpsRunner runner) {
//         List<Future> futures = new ArrayList<>((int)(totalCount / BATCH_SIZE));
//         while (it.hasNext()) {
//             futures.add(pool.submit(new BatchRunnable(ops, it, BATCH_SIZE,runner)));
//         }
//         Utils.waitForTasks(futures);
//     }
// }


import com.maxdemarzi.processing.NodeCounter;
import com.maxdemarzi.processing.OpsRunner;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.impl.api.RelationshipVisitor;
import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicIntegerArray;
import static com.maxdemarzi.processing.Utils.*;
                runOperations(pool, rels, relCount , ops, new OpsRunner() {
                    public void run(int id) throws EntityNotFoundException {
                        ops.relationshipVisit(id, visitor);
                    }
                });
            }
            tx.success();
        } catch (EntityNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void startIteration(int[] src, AtomicIntegerArray dst, int[] degrees) {
        for (int node = 0; node < this.nodeCount; node++) {
            if (degrees[node] == -1) continue;
            src[node]= toInt(ALPHA * toFloat(dst.getAndSet(node, ONE_MINUS_ALPHA_INT)) / degrees[node]);

        }
    }

    private int[] computeDegrees(ReadOperations ops, int labelId, int relationshipId) throws EntityNotFoundException {
        int[] degree = new int[nodeCount];
        Arrays.fill(degree,-1);
        PrimitiveLongIterator it = ops.nodesGetForLabel(labelId);
        int totalCount = nodeCount;
        runOperations(pool, it, totalCount, ops, new OpsRunner() {
            public void run(int id) throws EntityNotFoundException {
                degree[id] = ops.nodeGetDegree(id, Direction.OUTGOING, relationshipId);
            }
        });
// Path: src/main/java/com/maxdemarzi/processing/NodeCounter.java
// public class NodeCounter {
//     public int getNodeCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH (n) RETURN max(id(n)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
// 
//     }
//     public int getRelationshipCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH ()-[r]->() RETURN max(id(r)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
//     }
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/OpsRunner.java
// public interface OpsRunner {
//     void run(int node) throws EntityNotFoundException;
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/Utils.java
// public class Utils {
//     static final int BATCH_SIZE  = 100_000;
// 
//     public static int toInt(double value) {
//         return (int) (100_000*value);
//     }
//     public static double toFloat(int value) {
//         return value / 100_000.0;
//     }
// 
//     public static SingleSourceShortestPath<Double> getSingleSourceShortestPath(RelationshipType relationshipType)
//     {
//         return new SingleSourceShortestPathDijkstra<Double>( 0.0, null,
//                 new CostEvaluator<Double>()
//                 {
//                     public Double getCost( Relationship relationship,
//                                            Direction direction )
//                     {
//                         return 1.0;
//                     }
//                 }, new org.neo4j.graphalgo.impl.util.DoubleAdder(),
//                 new org.neo4j.graphalgo.impl.util.DoubleComparator(),
//                 Direction.BOTH, relationshipType );
//     }
// 
// 
//     static ExecutorService createPool(int threads, int queueSize) {
//         return new ThreadPoolExecutor(1, threads, 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>(queueSize),
//                 new ThreadPoolExecutor.CallerRunsPolicy());
//     }
// 
//     public static int waitForTasks(List<Future> futures) {
//         int total = 0;
//         for (Future future : futures) {
//             try {
//                 future.get();
//                 total ++;
//             } catch (InterruptedException | ExecutionException e) {
//                 e.printStackTrace();
//             }
//         }
//         futures.clear();
//         return total;
//     }
// 
//     public static void runOperations(ExecutorService pool, final PrimitiveLongIterator it, int totalCount, ReadOperations ops, OpsRunner runner) {
//         List<Future> futures = new ArrayList<>((int)(totalCount / BATCH_SIZE));
//         while (it.hasNext()) {
//             futures.add(pool.submit(new BatchRunnable(ops, it, BATCH_SIZE,runner)));
//         }
//         Utils.waitForTasks(futures);
//     }
// }


// Path: src/main/java/com/maxdemarzi/processing/pagerank/PageRankArrayStorageParallelSPI.java
import com.maxdemarzi.processing.NodeCounter;
import com.maxdemarzi.processing.OpsRunner;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.impl.api.RelationshipVisitor;
import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicIntegerArray;
import static com.maxdemarzi.processing.Utils.*;

                runOperations(pool, rels, relCount , ops, new OpsRunner() {
                    public void run(int id) throws EntityNotFoundException {
                        ops.relationshipVisit(id, visitor);
                    }
                });
            }
            tx.success();
        } catch (EntityNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void startIteration(int[] src, AtomicIntegerArray dst, int[] degrees) {
        for (int node = 0; node < this.nodeCount; node++) {
            if (degrees[node] == -1) continue;
            src[node]= toInt(ALPHA * toFloat(dst.getAndSet(node, ONE_MINUS_ALPHA_INT)) / degrees[node]);

        }
    }

    private int[] computeDegrees(ReadOperations ops, int labelId, int relationshipId) throws EntityNotFoundException {
        int[] degree = new int[nodeCount];
        Arrays.fill(degree,-1);
        PrimitiveLongIterator it = ops.nodesGetForLabel(labelId);
        int totalCount = nodeCount;
        runOperations(pool, it, totalCount, ops, new OpsRunner() {
            public void run(int id) throws EntityNotFoundException {
                degree[id] = ops.nodeGetDegree(id, Direction.OUTGOING, relationshipId);
            }
        });
        return degree;