Giter Site home page Giter Site logo

neo4j-labs / graph Goto Github PK

View Code? Open in Web Editor NEW
379.0 15.0 18.0 861 KB

A library for high-performant graph algorithms.

License: MIT License

Rust 86.59% Emacs Lisp 0.01% Python 6.45% Jupyter Notebook 6.95%
graph data-structures csr hacktoberfest algorithms graph-algorithms

graph's Introduction

graph โ€ƒ GitHub Actions workflow status Latest version on crates.io Latest version on PyPI License: MIT

A library that provides a collection of high-performant graph algorithms. This crate builds on top of the graph_builder crate, which can be used as a building block for custom graph algorithms.

graph_builder provides implementations for directed and undirected graphs. Graphs can be created programatically or read from custom input formats in a type-safe way. The library uses rayon to parallelize all steps during graph creation. The implementation uses a Compressed-Sparse-Row (CSR) data structure which is tailored for fast and concurrent access to the graph topology.

graph provides graph algorithms which take graphs created using graph_builder as input. The algorithm implementations are designed to run efficiently on large-scale graphs with billions of nodes and edges.

Note: The development is mainly driven by Neo4j developers. However, the library is not an official product of Neo4j.

What is a graph?

A graph consists of nodes and edges where edges connect exactly two nodes. A graph can be either directed, i.e., an edge has a source and a target node or undirected where there is no such distinction.

In a directed graph, each node u has outgoing and incoming neighbors. An outgoing neighbor of node u is any node v for which an edge (u, v) exists. An incoming neighbor of node u is any node v for which an edge (v, u) exists.

In an undirected graph there is no distinction between source and target node. A neighbor of node u is any node v for which either an edge (u, v) or (v, u) exists.

How to use graph?

The library provides a builder that can be used to construct a graph from a given list of edges.

For example, to create a directed graph that uses usize as node identifier, one can use the builder like so:

use graph::prelude::*;

let graph: DirectedCsrGraph<usize> = GraphBuilder::new()
    .csr_layout(CsrLayout::Sorted)
    .edges(vec![(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)])
    .build();

assert_eq!(graph.node_count(), 4);
assert_eq!(graph.edge_count(), 5);

assert_eq!(graph.out_degree(1), 2);
assert_eq!(graph.in_degree(1), 1);

assert_eq!(graph.out_neighbors(1).as_slice(), &[2, 3]);
assert_eq!(graph.in_neighbors(1).as_slice(), &[0]);

To build an undirected graph using u32 as node identifer, we only need to change the expected types:

use graph::prelude::*;

let graph: UndirectedCsrGraph<u32> = GraphBuilder::new()
    .csr_layout(CsrLayout::Sorted)
    .edges(vec![(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)])
    .build();

assert_eq!(graph.node_count(), 4);
assert_eq!(graph.edge_count(), 5);

assert_eq!(graph.degree(1), 3);

assert_eq!(graph.neighbors(1).as_slice(), &[0, 2, 3]);

Check out the graph_builder crate for for more examples on how to build graphs from various input formats.

How to run algorithms

In the following we will demonstrate running Page Rank, a graph algorithm to determine the importance of nodes in a graph based on the number and quality of their incoming edges.

Page Rank requires a directed graph and returns the rank value for each node.

use graph::prelude::*;

// https://en.wikipedia.org/wiki/PageRank#/media/File:PageRanks-Example.svg
let graph: DirectedCsrGraph<usize> = GraphBuilder::new()
    .edges(vec![
           (1,2), // B->C
           (2,1), // C->B
           (4,0), // D->A
           (4,1), // D->B
           (5,4), // E->D
           (5,1), // E->B
           (5,6), // E->F
           (6,1), // F->B
           (6,5), // F->E
           (7,1), // G->B
           (7,5), // F->E
           (8,1), // G->B
           (8,5), // G->E
           (9,1), // H->B
           (9,5), // H->E
           (10,1), // I->B
           (10,5), // I->E
           (11,5), // J->B
           (12,5), // K->B
    ])
    .build();

let (ranks, iterations, _) = page_rank(&graph, PageRankConfig::new(10, 1E-4, 0.85));

assert_eq!(iterations, 10);

let expected = vec![
    0.024064068,
    0.3145448,
    0.27890152,
    0.01153846,
    0.029471997,
    0.06329483,
    0.029471997,
    0.01153846,
    0.01153846,
    0.01153846,
    0.01153846,
    0.01153846,
    0.01153846,
];

assert_eq!(ranks, expected);

License: MIT

graph's People

Contributors

adamnsch avatar github-actions[bot] avatar knutwalker avatar lhooge avatar s1ck avatar saguywalker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graph's Issues

Isolated vertex with largest node id

Hi there,
is there a way of building a graph where the highest node index in the edge list does not correspond to the number of vertices; thus: there are isolated vertices with higher node indices? Maybe I missed it but I did not find such a way in the documentation.

Allow relabeling and changing layout when calling to_undirected

  • to_undirected in the Rust API accepts an optional layout, which is not exposed in the Python API
  • Additionally, allow relabelling in the same step
  • Maybe we can extend the Layout enum to smth like { Unsorted, SortedById, SortedByDegree, DeduplicatedById, DeduplicatedByDegree } ?

Partitioning?

I just saw your FOSDEM presentation and am curious if you think partitioning is in-scope for this project, and if so, if you've thought about how/where it should go? My interests are in k-way partitioning similar to packages like METIS and SCOTCH, with graph coarsening and KL/FM refinement, as well as the closely related problem of computing nested dissection orderings for sparse direct solvers.

Some problem with atypical graph

Hello,

I have some trouble with your librairy with graph like this one :

Node(0).
Node(1).
Node(2).
Node(3).
Node(4).
Node(5).
Node(6).
Node(7).
Node(8).
Node(9).
Node(10).
Node(11).
Node(12).
Node(13).
Node(14).
edge(12,9).
edge(11,6).
edge(5,4).
edge(12,7).

As you can see some nodes exist but aren't linked to any nodes.
I can't add them to the graph by the edges() function.
I'm also try to compute the page rank of this graph.
Is there is a trick i can do like when a node is alone it has always the same ranking or something, so that i don't have to had it it the graph ?
Or can we find a solution about that ?

Thank you

Associated Edge Data

I'm looking at graph for backing a RVSDG implementation which is centered around edge "kinds" that hold various data, ex a value edge or a control flow edge. The ability to store data within edges and to query against it effectively (sometimes you just want to see state nodes from a given source to destination) is essential for that, so that'd be a really great addition.
This also requires the ability to have multiple (possibly identical) edges going between nodes and the multiplicity of the edges being retained, if that's a concern.
Thanks!

Conda package

Hi there, quick question: do you have any plans to release graph-mate as conda package on conda-forge? I know I could just pip install it in a conda environment, but for my use-case a native conda package would be a better fit.

If not, no worries, I might give it a go myself. Just never packaged a package with rust bindings.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.