Types
At the top of the type hierachy we have AbstractEdge
s and AbstractNode
s. These are pretty abstract in the sense that they capture anything that might somehow be interpreted as an edge or node. More concrete (but still not concrete concrete) are Edge
and Node
.
StenoGraphs.AbstractNode
— TypeAbstractNode
At the top of the type hierarchy of StenoGraphs
. Anything that might resemble a node.
StenoGraphs.AbstractEdge
— TypeAbstractEdge
At the top of the type hierarchy of StenoGraphs
. Anything that might resemble an edge.
Edge/Node
Edge and Node are still not concrete but have fields of reliable types to interface with.
StenoGraphs
implements DirectedEdge
and UndirectedEdge
as concrete subtypes of Edge
as well as SimpleNode
as concrete subtype of Node
.
StenoGraphs.Node
— TypeNode
Subtype of AbstractNode
. Any subtype of Node
must have the field node
(and no other) that uniquily identifies the node.
StenoGraphs.Edge
— TypeEdge
Subtype of AbstractEdge
. Any subtype of Edge
must have the fields src
and dst
(and no other), which must be a subtype of AbstractNode
. Any implementation might be stricter about typing.
SimpleNode/UndirectedEdge/DirectedEdge
These are the concrete Node
and Edge
types implemented by StenoGraphs
.
StenoGraphs.SimpleNode
— TypeStenoGraphs.DirectedEdge
— TypeDirectedEdge(src, dst)
Subtype of Edge
. Directed edge from src
to dst
.
Example
julia> DirectedEdge(Node(:a), Node(:b))
a → b
StenoGraphs.UndirectedEdge
— TypeUndirectedEdge(src, dst)
Subtype of Edge
. Undirected edge from src
to dst
. What is what does not matter.
Example
julia> e1 = UndirectedEdge(Node(:a), Node(:b))
a ↔ b
julia> e2 = UndirectedEdge(Node(:b), Node(:a))
b ↔ a
julia> isequal(e1, e2)
true
julia> unique([e1, e2])
a ↔ b
MetaEdge/MetaNode
These types store a node/edge alongside metadata.
StenoGraphs.MetaNode
— TypeMetaNode
Subtype of AbstractNode
. Any subtype of MetaNode
must have a field node
of subtype Node
, but may have any number of other fields containing metadata.
StenoGraphs.MetaEdge
— TypeMetaEdge
Subtype of AbstractEdge
. Any subtype of MetaEdge
must have a field edge
of subtype Edge
, but may have any number of other fields containing metadata.
Modified Nodes and Edges
These concrete types store a node/edge alongside modifiers (either NodeModifier
s or EdgeModifier
s) as metadata.
StenoGraphs.ModifiedNode
— TypeModifiedNode
Subtype of MetaNode
that contains two fields (node
and modifiers
). modifiers
is a Dict{Symbol, NodeModifier}
where the keys are nameof(typeof(NodeModifier))
. Modifiying a node with several modifiers of the same type will therefore overwrite old modifiers.
Example
julia> struct Observed <: NodeModifier end
julia> struct Label{N <: String} <: NodeModifier s::N end
julia> Node(:b) ^ Label("some label") ^ Observed()
b^[Observed(), Label{String}("some label")]
julia> Node(:b) ^ Label("some label") ^ Observed() ^ Label("some other label")
b^[Observed(), Label{String}("some other label")]
StenoGraphs.ModifyingNode
— TypeModifyingNode
Subtype of MetaNode
that contains two fields (node
and modifiers
). modifiers
is a Dict{Symbol, EdgeModifier}
where the keys are nameof(typeof(EdgeModifier))
. Modifiying an node with several modifiers of the same type will therefore overwrite old modifiers. A ModifyingNode
is created by multiplying it (*
) with an EdgeModifier
since it will modify edges build upon it. If you want to modify the node use ^
and see ModifiedNode
.
Example
julia> struct Weight{N <: Number} <: EdgeModifier w::N end
julia> struct Start{N <: Number} <: EdgeModifier s::N end
julia> @StenoGraph a → b * Weight(3) * Start(2)
a → b * [Start{Int64}(2), Weight{Int64}(3)]
julia> @StenoGraph a → b * Weight(3) * Start(2) * Weight(2)
a → b * [Start{Int64}(2), Weight{Int64}(2)]
StenoGraphs.ModifiedEdge
— TypeModifiedEdge
Subtype of MetaEdge
that contains two fields (edge
and modifiers
). modifiers
is a Dict{Symbol, EdgeModifier}
where the keys are nameof(typeof(EdgeModifier))
. Modifiying an edge with several modifiers of the same type will therefore overwrite old modifiers. A ModifiedEdge
is created by modifying an edge directly (with *
) or via ModifyingNode
s where a node is modified that than modifies the edge.
Example
julia> struct Weight{N <: Number} <: EdgeModifier w::N end
julia> struct Start{N <: Number} <: EdgeModifier s::N end
julia> ModifiedEdge(Edge(Node(:a), Node(:b)), Weight(3))
a → b * Weight{Int64}(3)
julia> ModifiedEdge(Edge(Node(:a), Node(:b)), Weight(3)) == Edge(Node(:a), Node(:b)) * Weight(3)
true
julia> ModifiedEdge(Edge(Node(:a), Node(:b)), [Weight(3), Start(2)])
a → b * [Start{Int64}(2), Weight{Int64}(3)]
julia> @StenoGraph a → b * Weight(3) * Start(2)
a → b * [Start{Int64}(2), Weight{Int64}(3)]
julia> @StenoGraph a → b * Weight(3) * Start(2) * Weight(2)
a → b * [Start{Int64}(2), Weight{Int64}(2)]
Modifiers
StenoGraphs.Modifier
— TypeModifier
The abstract type that powers EdgeModifier and NodeModifier. StenoGraphs
does not implement any concrete modifiers.
StenoGraphs.NodeModifier
— TypeNodeModifier
Subtype of Modifier
. ModifiedNode
s require NodeModifier
s. NodeModifier
s usually make use of ^
for creating ModifiedNode
s. Since StenoGraphs
does not implement any NodeModifier
users must implement them. If these may contain any mutable fields (i.e. strings, vectors, arrays, etc.) users must take care to implement comparison methods.
Example
# `StenoGraphs` does not implement any `NodeModifier`s
julia> struct Label <: NodeModifier l end
julia> import Base.==
julia> ==(x::Label, y::Label) = x.l == y.l;
julia> ModifiedNode(Node(:a), Label("hi")) == Node(:a)^Label("hi")
true
StenoGraphs.EdgeModifier
— TypeEdgeModifier
Subtype of Modifier
. ModifiedEdge
s require EdgeModifier
s. EdgeModifier
s usually make use of *
for creating ModifiedEdge
s/ModifyingNode
s. One special application for EdgeModifier
s is the creation of ModifyingNode
s. Since StenoGraphs
does not implement any EdgeModifier
users must implement them. If these are not atomic they must take care to implement comparison methods (see examples in NodeModifier
)
Example
# `StenoGraphs` does not implement any `EdgeModifier`s
julia> struct Weight{N <: Number} <: EdgeModifier w::N end
julia> ModifiedEdge(Edge(Node(:a), Node(:b)), Weight(.5)) == # directly create ModifiedEdge
Edge(Node(:a), Node(:b)) * Weight(.5) == # modify an edge
Edge(Node(:a), Node(:b) * Weight(.5)) # modify Edge through a ModifyingNode
true