Basics
using Graphs
using MetaGraphsNext
Creating an empty MetaGraph
We provide a convenience constructor for creating empty graphs, which looks as follows:
colors = MetaGraph(
Graph(); # underlying graph structure
label_type=Symbol, # color name
vertex_data_type=NTuple{3,Int}, # RGB code
edge_data_type=Symbol, # result of the addition between two colors
graph_data="additive colors", # tag for the whole graph
)
Meta graph based on a SimpleGraph{Int64} with vertex labels of type Symbol, vertex metadata of type Tuple{Int64, Int64, Int64}, edge metadata of type Symbol, graph metadata given by "additive colors", and default weight 1.0
The label_type
argument defines how vertices will be referred to. It can be anything you want, provided that pairs of labels can be compared with <
. Integer types are generally discouraged, to avoid confusion with the vertex codes used by Graphs.jl. The vertex_data_type
and edge_data_type
type determine what kind of data will be associated with each vertex and edge. Finally, graph_data
can contain an arbitrary object associated with the graph as a whole.
If you don't care about labels at all, using the integer vertex codes as labels may be reasonable. Just keep in mind that labels do not change with vertex deletion, whereas vertex codes get decreased, so the coherence will be broken.
Modifying the graph
Modifications of graph elements and the associated metadata can always be done using setindex!
(as in a dictionary) with the relevant labels.
Vertices
Use setindex!
with one key to add a new vertex with the given label and metadata. If a vertex with the given label does not exist, it will be created automatically. Otherwise, the function will simply modify the metadata for the existing vertex.
colors[:red] = (255, 0, 0);
colors[:green] = (0, 255, 0);
colors[:blue] = (0, 0, 255);
Note that you cannot use labels or metadata that is incoherent with the types you specified at construction.
Edges
Use setindex!
with two keys to add a new edge between the given labels and containing the given metadata. Beware that this time, an edge will only be added when both node labels already exist in the graph.
colors[:red, :green] = :yellow;
colors[:red, :blue] = :magenta;
colors[:green, :blue] = :cyan;
Creating a non-empty MetaGraph
There is an alternative constructor which allows you to build and fill the graph in one fell swoop. Here's how it works:
graph = Graph(Edge.([(1, 2), (1, 3), (2, 3)]))
vertices_description = [:red => (255, 0, 0), :green => (0, 255, 0), :blue => (0, 0, 255)]
edges_description = [
(:red, :green) => :yellow, (:red, :blue) => :magenta, (:green, :blue) => :cyan
]
colors2 = MetaGraph(graph, vertices_description, edges_description, "additive colors")
colors2 == colors
false
Accessing graph properties
To retrieve graph properties, we still follow a dictionary-like interface based on labels.
Existence
To check the presence of a vertex or edge, use haskey
:
haskey(colors, :red)
true
haskey(colors, :black)
false
haskey(colors, :red, :green) && haskey(colors, :green, :red)
true
!haskey(colors, :red, :black)
true
Metadata
All kinds of metadata can be accessed with getindex
:
colors[]
"additive colors"
colors[:blue]
(0, 0, 255)
colors[:green, :blue]
:cyan
Using vertex codes
In the absence of removal, vertex codes correspond to order of insertion in the underlying graph. They are the ones used by most algorithms in the Graphs.jl ecosystem.
code_for(colors, :red)
1
code_for(colors, :blue)
3
You can retrieve the associated labels as follows:
label_for(colors, 1)
:red
label_for(colors, 3)
:blue
Listing labels
The functions labels
, edge_labels
, (in/out)neighbor_labels
iterate through labels the same way that vertices
, edges
and (in/out)neighbors
iterate through codes.
collect(labels(colors))
3-element Vector{Symbol}:
:red
:green
:blue
collect(edge_labels(colors))
3-element Vector{Tuple{Symbol, Symbol}}:
(:red, :green)
(:red, :blue)
(:green, :blue)
collect(neighbor_labels(colors, :red))
2-element Vector{Symbol}:
:green
:blue
Handling weights
You can use the weight_function
field to specify a function which will transform edge metadata into a weight. This weight must always have the same type as the default_weight
, which is the value returned in case an edge does not exist.
weighted = MetaGraph(
Graph();
label_type=Symbol,
edge_data_type=Float64,
weight_function=ed -> ed^2,
default_weight=Inf,
);
weighted[:alice] = nothing;
weighted[:bob] = nothing;
weighted[:charlie] = nothing;
weighted[:alice, :bob] = 2.0;
weighted[:bob, :charlie] = 3.0;
weight_matrix = Graphs.weights(weighted)
MetaWeights of size (3, 3)
default_weight(weighted)
Inf
size(weight_matrix)
(3, 3)
weight_matrix[1, 2]
4.0
weight_matrix[2, 3]
9.0
weight_matrix[1, 3]
Inf
wf = get_weight_function(weighted)
wf(4.0)
16.0
You can then use all functions from Graphs.jl that require weighted graphs (see the rest of the tutorial).
This page was generated using Literate.jl.