Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Latest commit

 

History

History
99 lines (79 loc) · 5.15 KB

CONTRIBUTING.md

File metadata and controls

99 lines (79 loc) · 5.15 KB

Contributor Guide

We welcome all possible contributors and ask that you read these guidelines before starting to work on this project. Following these guidelines will reduce friction and improve the speed at which your code gets merged.

Bug reports

If you notice code that crashes, is incorrect, or is too slow, please file a bug report. The report should be raised as a github issue with a minimal working example that reproduces the condition. The example should include any data needed. If the problem is incorrectness, then please post the correct result along with an incorrect result.

Please include version numbers of all relevant libraries and Julia itself.

Development guidelines

  • Correctness is a necessary requirement; efficiency is desirable. Once you have a correct implementation, make a PR so we can help improve performance.

  • PRs should contain one logical enhancement to the codebase.

  • Squash commits in a PR.

  • Open an issue to discuss a feature before you start coding (this maximizes the likelihood of patch acceptance).

  • Minimize dependencies on external packages, and avoid introducing new dependencies. In general,

    • PRs introducing dependencies on Julia Base or the packages in the Julia Standard Library are ok.
    • PRs introducing dependencies on third-party non-core "leaf" packages (no subdependencies except for Julia Base / Standard Library packages) are less ok.
    • PRs introducing dependencies on third-party non-core non-leaf packages (that is, third-party packages that have dependencies on one or more other third-party packages) require strict scrutiny and will likely not be accepted without some compelling reason (urgent bugfix or much-needed functionality).
  • Put type assertions on all function arguments where conflict may arise (use abstract types, Union, or Any if necessary).

  • If the algorithm was presented in a paper, include a reference to the paper (e.g., a proper academic citation along with an eprint link).

  • Take steps to ensure that code works correctly and efficiently on disconnected graphs.

  • We can accept code that does not work for directed graphs as long as it comes with an explanation of what it would take to make it work for directed graphs.

  • Prefer the short circuiting conditional over if/else when convenient, and where state is not explicitly being mutated (e.g., condition && error("message") is good; condition && i += 1 is not).

  • Write code to reuse memory wherever possible. For example:

function f(g, v)
    storage = Vector{Int}(undef, nv(g))
    # some code operating on storage, g, and v.
    for i in 1:nv(g)
        storage[i] = v-i
    end
    return sum(storage)
end

should be rewritten as two functions

function f(g::AbstractGraph, v::Integer)
    storage = Vector{Int}(undef, nv(g))
    return f!(g, v, storage)
end

function f!(g::AbstractGraph, v::Integer, storage::AbstractVector{Int})
    # some code operating on storage, g, and v.
    for i in 1:nv(g)
        storage[i] = v-i
    end
    return sum(storage)
end

This gives users the option of reusing memory and improving performance.

Minimizing use of internal struct fields

Since LightGraphs supports multiple implementations of the graph datastructure using the AbstractGraph type, you should refrain from using the internal fields of structs such as fadjlist. Instead, you should use the functions provided in the api. Code that is instrumental to defining a concrete graph type can use the internal structure of that type for example graph generators in /src/StaticGraphs/generators/staticgraphs.jl use the fadjlist field in order to construct graphs efficiently.

Git usage

In order to make it easier for you to review Pull Requests (PRs), you can add this to your git config file, which should be located at $HOME/.julia/dev/LightGraphs/.git/config. Follow the instructions here.

Locate the section for your github remote in the .git/config file. It looks like this:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@github.com:JuliaGraphs/LightGraphs.jl.git

Now add the line fetch = +refs/pull/*/head:refs/remotes/origin/pr/* to this section. Obviously, change the github url to match your project's URL. It ends up looking like this:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@github.com:JuliaGraphs/LightGraphs.jl.git
    fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

Now fetch all the pull requests:

$ git fetch origin
From github.com:JuliaGraphs/LightGraphs.jl
 * [new ref]         refs/pull/1000/head -> origin/pr/1000
 * [new ref]         refs/pull/1002/head -> origin/pr/1002
 * [new ref]         refs/pull/1004/head -> origin/pr/1004
 * [new ref]         refs/pull/1009/head -> origin/pr/1009
...

To check out a particular pull request:

$ git checkout pr/999
Branch pr/999 set up to track remote branch pr/999 from origin.
Switched to a new branch 'pr/999'

Now you can test a PR by running git fetch && git checkout pr/PRNUMBER && julia -e 'Pkg.test("LightGraphs")'