Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
sbromberger committed Dec 7, 2015
1 parent a16c09c commit 66f4597
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 259 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ distmx[5,4] = 2.5
dijkstra_shortest_paths(g, 4, distmx=distmx).dists

# graph I/O
g = readgraph("mygraph.jgz")
write(g,"mygraph.jgz")
g = load("mygraph.jgz", "mygraph")
save(g,"mygraph.jgz"; compress=true)
```

### Current functionality
Expand Down
22 changes: 11 additions & 11 deletions doc/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ distmx[5,4] = 2.5
dijkstra_shortest_paths(g, 4, distmx=distmx).dists
# graph I/O
g = readgraph("mygraph.jgz")
write(g,"mygraph.jgz")
g = load("mygraph.jgz", "mygraph")
save("mygraph.jgz", g, "mygraph")
```
"""

Expand Down Expand Up @@ -417,21 +417,21 @@ output above.

@file "persistence.md" """
## Writing a Graph
Graphs may be written to I/O streams and files using the `write` function:
Graphs may be written to I/O streams and files using the `save` function:
{{write}}
{{save}}
## Reading a Graph From a File
Graphs stored using the `write` functions above may be loaded using `readgraph`:
Graphs stored using the `save` functions above may be loaded using `load`:
{{readgraph, readgraphml, readgml}}
{{load}}
## Examples
```julia
julia> write(STDOUT, g)
julia> write(g, "mygraph.jgz")
julia> g = readgraph("mygraph.jgz")
julia> g = readgraphml("mygraph.xml")
julia> g = readgml("mygraph.gml")
julia> save(STDOUT, g)
julia> save("mygraph.jgz", g, "mygraph"; compress=true)
julia> g = load("multiplegraphs.jgz")
julia> g = load("multiplegraphs.xml", :graphml)
julia> g = load("mygraph.gml", "mygraph", :gml)
```
"""
4 changes: 2 additions & 2 deletions doc/gettingstarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,6 @@ distmx[5,4] = 2.5
dijkstra_shortest_paths(g, 4, distmx=distmx).dists

# graph I/O
g = readgraph("mygraph.jgz")
write(g,"mygraph.jgz")
g = load("mygraph.jgz", "mygraph")
save("mygraph.jgz", g, "mygraph")
```
80 changes: 27 additions & 53 deletions doc/persistence.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,41 @@
<!-- AUTOGENERATED. See 'doc/build.jl' for source. -->
## Writing a Graph
Graphs may be written to I/O streams and files using the `write` function:
### write
Graphs may be written to I/O streams and files using the `save` function:
### save
```
write(io::IO, graphname::AbstractString, g::Union{LightGraphs.DiGraph,LightGraphs.Graph})
write(io::IO, g::LightGraphs.Graph)
write(io::IO, g::LightGraphs.DiGraph)
write(g::LightGraphs.Graph)
write(g::LightGraphs.DiGraph)
write{S<:AbstractString,G<:Union{LightGraphs.DiGraph,LightGraphs.Graph}}(graphs::Dict{S<:AbstractString,G<:Union{LightGraphs.DiGraph,LightGraphs.Graph}}, fn::AbstractString)
write(g::LightGraphs.Graph, fn::AbstractString)
write(g::LightGraphs.DiGraph, fn::AbstractString)
write(g::Union{LightGraphs.DiGraph,LightGraphs.Graph}, gname::AbstractString, fn::AbstractString)
save(io::IO, g::LightGraphs.Graph)
save(io::IO, g::LightGraphs.DiGraph)
save(io::IO, g::Union{LightGraphs.DiGraph,LightGraphs.Graph}, gname::AbstractString)
save(io::IO, g::Union{LightGraphs.DiGraph,LightGraphs.Graph}, gname::AbstractString, t::Symbol)
save(io::IO, g::LightGraphs.Graph, t::Symbol)
save(io::IO, g::LightGraphs.DiGraph, t::Symbol)
save(io::IO, d::Dict{AbstractString,Union{LightGraphs.DiGraph,LightGraphs.Graph}})
save(io::IO, d::Dict{AbstractString,Union{LightGraphs.DiGraph,LightGraphs.Graph}}, t::Symbol)
save(fn::AbstractString, x...)
```
```
write(stream, x)
```

Write the canonical binary representation of a value to the given stream. Returns the number of bytes written into the stream.

You can write multiple values with the same :func:`write` call. i.e. the following are equivalent:

```
write(stream, x, y...)
write(stream, x) + write(stream, y...)
```

Writes a dictionary of (name=>graph) to a file `fn`, with default `GZip` compression.
Saves multiple graphs in a dictionary mapping graph name to graph to stream `io` using graph type `t`.

Returns number of graphs written.

Writes a graph `g` with name `graphname` in a proprietary format to the IO stream designated by `io`.

Returns 1 (number of graphs written).
Saves a single graph `g` with name `gname` to stream `io` using graph type `t`. Returns the number of graphs written (1).

## Reading a Graph From a File
Graphs stored using the `write` functions above may be loaded using `readgraph`:
### readgraph
Graphs stored using the `save` functions above may be loaded using `load`:
### load
```
readgraph(fn::AbstractString)
readgraph(fn::AbstractString, gname::AbstractString)
load(io::IO)
load(io::IO, gname::AbstractString)
load(io::IO, gname::AbstractString, t::Symbol)
load(io::IO, t::Symbol)
load(fn::AbstractString, x...)
```
Returns a dictionary of (name=>graph) loaded from file `fn`.
Loads a single graph from stream `io` with name `gname` and graph type `t`.

### readgraphml
```
readgraphml(filename::AbstractString)
readgraphml(filename::AbstractString, gname::AbstractString)
```
Returns a dictionary (name=>graph) from file `fn` stored in [GraphML](http://en.wikipedia.org/wiki/GraphML) format. Can optionally restrict to a single graph by specifying a name in gname.

### readgml
```
readgml(filename::AbstractString)
readgml(filename::AbstractString, gname::AbstractString)
```
Returns a dictionary (name=>graph) from file `fn` stored in [GML](https://en.wikipedia.org/wiki/Graph_Modelling_Language) format. Can optionally restrict to a single graph by specifying a name in gname.
Loads multiple graphs of type `t` from stream `io`. Returns a dictionary mapping graph name to graph.

## Examples
```julia
julia> write(STDOUT, g)
julia> write(g, "mygraph.jgz")
julia> g = readgraph("mygraph.jgz")
julia> g = readgraphml("mygraph.xml")
julia> g = readgml("mygraph.gml")
julia> save(STDOUT, g)
julia> save("mygraph.jgz", g, "mygraph"; compress=true)
julia> g = load("multiplegraphs.jgz")
julia> g = load("multiplegraphs.xml", :graphml)
julia> g = load("mygraph.gml", "mygraph", :gml)
```
15 changes: 8 additions & 7 deletions src/LightGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ CombinatorialAdjacency, non_backtracking_matrix,
a_star,

# persistence
readgraph, readgraphml, readgml, writegraphml, writegexf, readdot,

# readgraph, readgraphml, readgml, writegraphml, writegexf, readdot,
load, save,
# flow
maximum_flow, EdmondsKarpAlgorithm, DinicAlgorithm, PushRelabelAlgorithm,

Expand Down Expand Up @@ -152,11 +152,12 @@ include("core.jl")
include("shortestpaths/floyd-warshall.jl")
include("spectral.jl")
include("operators.jl")
include("persistence/default.jl")
include("persistence/dot.jl")
include("persistence/gexf.jl")
include("persistence/gml.jl")
include("persistence/graphml.jl")
include("persistence/common.jl")
include("persistence/lg.jl")
include("persistence/dot.jl")
include("persistence/gexf.jl")
include("persistence/gml.jl")
include("persistence/graphml.jl")
include("randgraphs.jl")
include("smallgraphs.jl")
include("centrality/betweenness.jl")
Expand Down
61 changes: 61 additions & 0 deletions src/persistence/common.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
NI(x...) = error("This function is not implemented.")

@deprecate readgraph load

const filemap = Dict{Symbol, Tuple{Function, Function, Function, Function}}()
# :gml => (loadgml, loadgml_mult, savegml, savegml_mult)
# :graphml => (loadgraphml, loadgraphml_mult, savegraphml, savegraphml_mult)
# :md => (loadmatrixdepot, NOTIMPLEMENTED, NOTIMPLEMENTED, NOTIMPLEMENTED)

# load a single graph by name
"""Loads a single graph from stream `io` with name `gname` and graph type `t`.
"""
function load(io::IO, gname::AbstractString, t::Symbol=:lg)
t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
return filemap[t][1](io, gname)
end

"""Loads multiple graphs of type `t` from stream `io`. Returns a dictionary
mapping graph name to graph."""
function load(io::IO, t::Symbol=:lg)
t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
return filemap[t][2](io)
end

"""Saves a single graph `g` with name `gname` to stream `io` using graph type `t`.
Returns the number of graphs written (1)."""
function save(io::IO, g::SimpleGraph, gname::AbstractString, t::Symbol=:lg)
t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
return filemap[t][3](io, g, gname)
end

# save a single graph without name
save(io::IO, g::Graph, t::Symbol=:lg) = save(io, g, "Unnamed Graph", t)
save(io::IO, g::DiGraph, t::Symbol=:lg) = save(io, g, "Unnamed DiGraph", t)

# save a dictionary of graphs {"name" => graph}
"""Saves multiple graphs in a dictionary mapping graph name to graph to stream
`io` using graph type `t`."""
function save(io::IO, d::Dict{AbstractString, SimpleGraph}, t::Symbol=:lg)
t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
return filemap[t][4](io, d)
end

# load from a file
function load(fn::AbstractString, x...)
GZip.open(fn,"r") do io
load(io, x...)
end
end

# save to a file
function save(fn::AbstractString, x...; compress::Bool=false)
if compress
io = GZip.open(fn,"w")
else
io = open(fn,"w")
end
retval = save(io, x...)
close(io)
return retval
end
32 changes: 20 additions & 12 deletions src/persistence/dot.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# TODO: implement writedot

function _readonedot(pg::ParserCombinator.Parsers.DOT.Graph)

# TODO: implement save

function _dot_read_one_graph(pg::ParserCombinator.Parsers.DOT.Graph)
isdir = pg.directed
nvg = length(Parsers.DOT.nodes(pg))
nodedict = Dict(zip(collect(Parsers.DOT.nodes(pg)), 1:nvg))
Expand All @@ -17,23 +19,29 @@ function _readonedot(pg::ParserCombinator.Parsers.DOT.Graph)
return g
end

"""Returns a dictionary (name=>graph) from file `fn` stored in
[DOT](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) format.
Can optionally restrict to a single graph by specifying a name in gname.
"""
function readdot(filename::AbstractString, gname::AbstractString="")
f = open(readall,filename)
p = Parsers.DOT.parse_dot(f)
function loaddot(io::IO, gname::AbstractString)
p = Parsers.DOT.parse_dot(readall(io))
for pg in p
isdir = pg.directed
possname = isdir? Parsers.DOT.StringID("Unnamed DiGraph") : Parsers.DOT.StringID("Unnamed Graph")
name = get(pg.id, possname).id
name == gname && return _dot_read_one_graph(pg)
end
error("Graph $gname not found")
end

function loaddot_mult(io::IO)
p = Parsers.DOT.parse_dot(readall(io))

graphs = Dict{AbstractString, SimpleGraph}()

for pg in p
isdir = pg.directed
possname = isdir? Parsers.DOT.StringID("Unnamed DiGraph") : Parsers.DOT.StringID("Unnamed Graph")
name = get(pg.id, possname).id
if (gname == "") || (name == gname)
graphs[name] = _readonedot(pg)
end
graphs[name] = _dot_read_one_graph(pg)
end
return graphs
end

filemap[:dot] = (loaddot, loaddot_mult, NI, NI)
14 changes: 5 additions & 9 deletions src/persistence/gexf.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# TODO: implement readgexf

"""
Expand All @@ -7,7 +8,7 @@ to a file `f` in the
Returns 1 (number of graphs written).
"""
function writegexf(f::IO, g::SimpleGraph)
function savegexf(f::IO, g::SimpleGraph, gname::AbstractString)
xdoc = XMLDocument()
xroot = create_root(xdoc, "gexf")
set_attribute(xroot,"xmlns","http://www.gexf.net/1.2draft")
Expand All @@ -16,6 +17,8 @@ function writegexf(f::IO, g::SimpleGraph)
set_attribute(xroot,"xsi:schemaLocation","http://www.gexf.net/1.2draft/gexf.xsd")

xmeta = new_child(xroot, "meta")
xdesc = new_child(xmeta, "description")
add_text(xdesc, gname)
xg = new_child(xroot, "graph")
strdir = is_directed(g) ? "directed" : "undirected"
set_attribute(xg,"defaultedgetype",strdir)
Expand All @@ -40,11 +43,4 @@ function writegexf(f::IO, g::SimpleGraph)
return 1
end

writegexf(g::SimpleGraph) = writegexf(STDOUT, g)

function writegexf(fname::AbstractString, g::SimpleGraph)
f = open(fname, "w")
writegexf(f, g)
close(f)
return 1
end
filemap[:gexf] = (NI, NI, savegexf, NI)
Loading

0 comments on commit 66f4597

Please sign in to comment.