diff --git a/docs/src/igraphs.md b/docs/src/igraphs.md new file mode 100644 index 000000000..99568fdff --- /dev/null +++ b/docs/src/igraphs.md @@ -0,0 +1,32 @@ +# IGraphs integration (igraph C library) + +`IGraphs.jl` (https://github.com/JuliaGraphs/IGraphs.jl) is the idiomatic +Julia wrapper around the C `igraph` library (see JuliaGraphs/Graphs.jl#446). + +## Design pattern (proof of concept) + +To avoid a hard binary dependency, `Graphs.jl` only declares: + + `Graphs.isomorphism_igraph`, and `Graphs.to_igraph`, which throw an + informative error telling the user to install `IGraphs.jl`. + +`IGraphs.jl` then provides, for example: + +struct IGraphLouvain <: Graphs.IGraphAlgorithm end +Graphs.community_detection_igraph(g::AbstractGraph, ::IGraphLouvain) = + community_detection_igraph(to_igraph(g), IGraphLouvain()) + +where `to_igraph(::AbstractGraph)` converts (copy or zero-copy view) a +`Graphs.jl` graph to the C `igraph_t` structure, preserving directedness, +vertex numbering (`1:n`), and edge multiplicities as documented in `IGraphs.jl`. + +## Conformance + +`IGraph` graph types must satisfy the full `Graphs.jl` `AbstractGraph` +interface and are validated with `GraphsInterfaceChecker.jl` in the +`IGraphs.jl` test suite: + +using Graphs, GraphsInterfaceChecker, IGraphs +@test test_graph(IGraphGraph(SimpleGraph(4, 3))) + +See `src/igraphs.jl` for the stub definitions and docstrings. diff --git a/src/Graphs.jl b/src/Graphs.jl index 9df01764e..215f28a3a 100644 --- a/src/Graphs.jl +++ b/src/Graphs.jl @@ -1,5 +1,8 @@ module Graphs +include("igraphs.jl") +export IGraphAlgorithm, community_detection_igraph, isomorphism_igraph, to_igraph + using SimpleTraits ### Remove the following line once #915 is closed diff --git a/src/igraphs.jl b/src/igraphs.jl new file mode 100644 index 000000000..5fb5d52ad --- /dev/null +++ b/src/igraphs.jl @@ -0,0 +1,63 @@ +""" + IGraphs integration hooks (proof of concept) + +Declares the interface pattern for dispatching `Graphs.jl` operations to the +C `igraph` library via the `IGraphs.jl` package, without taking a hard +dependency on it (see JuliaGraphs/Graphs.jl#446). + +Pattern: + +1. `Graphs.jl` declares a lightweight algorithm trait, e.g. + `IGraphAlgorithm <: AbstractGraphAlgorithm`, and generic stubs for + igraph-only algorithms that throw an informative error. +2. `IGraphs.jl` defines concrete subtypes (e.g. `IGraphLouvain()`) and + methods `f(g::AbstractGraph, alg::IGraphAlgorithm)` that convert `g` + to an `IGraph` view/copy when needed and `ccall` into `libigraph`. +""" + +"""Trait for algorithms whose reference implementation lives in `IGraphs.jl`.""" +abstract type IGraphAlgorithm end + +_igraphs_hint(fname::Symbol) = error( + "`Graphs.$(fname)` requires the `IGraphs.jl` package, " * + "the idiomatic Julia wrapper around the C `igraph` library. " * + "Install it with `using Pkg; Pkg.add(\"IGraphs\")`, then `using IGraphs` " * + "and retry. See https://github.com/JuliaGraphs/IGraphs.jl. " * + "(JuliaGraphs/Graphs.jl#446)", +) + +""" + community_detection_igraph(g::AbstractGraph, alg::IGraphAlgorithm) + +Placeholder for igraph-provided community-detection algorithms (e.g. Louvain, +Leiden, Walktrap) not implemented natively in `Graphs.jl`. +The concrete `alg` subtypes and methods are defined in `IGraphs.jl`, which +converts `g` to an `IGraph` graph if necessary before dispatching to C. +""" +function community_detection_igraph end +community_detection_igraph(::AbstractGraph, ::IGraphAlgorithm) = + _igraphs_hint(:community_detection_igraph) +community_detection_igraph(::AbstractGraph) = + _igraphs_hint(:community_detection_igraph) + +""" + isomorphism_igraph(g::AbstractGraph, h::AbstractGraph, alg::IGraphAlgorithm) + +Placeholder for igraph-provided (sub)graph-isomorphism routines (e.g. VF2/BLISS +variants). Implemented in `IGraphs.jl` via `ccall` to `libigraph`. +""" +function isomorphism_igraph end +isomorphism_igraph(::AbstractGraph, ::AbstractGraph, ::IGraphAlgorithm) = + _igraphs_hint(:isomorphism_igraph) +isomorphism_igraph(::AbstractGraph, ::AbstractGraph) = + _igraphs_hint(:isomorphism_igraph) + +""" + to_igraph(g::AbstractGraph) -> Any + +Convert `g` to the corresponding `IGraphs.jl` graph type (copy by default; +`IGraphs.jl` may provide zero-copy views). This stub throws an informative +error until `IGraphs.jl` is loaded, which defines the actual method. +""" +function to_igraph end +to_igraph(::AbstractGraph) = _igraphs_hint(:to_igraph)