API Reference
Core Types and Functions
GraphCore.AdjGraph — TypeAdjGraph{D} <: GraphInterfaceDynamic graph using adjacency lists (Vector{Vector{Int32}}) for neighbor storage. Optimized for structural mutations with reasonable query performance.
Type Parameters
D::Bool: Directedness flag (true = directed, false = undirected)
Fields (Internal - Access via interface methods)
neighbors::Vector{Vector{Int32}}: Per-vertex neighbor listsneighbor_to_edge::Vector{Vector{Int32}}: Maps neighbor positions to edge indices (undirected only)num_edges::Int32: Number of (undirected) edges
Construction
Use build_adj_graph() or build_graph(AdjGraph, ...) for safe construction:
# Basic construction
edges = [(1,2), (2,3), (1,3)]
g = build_adj_graph(edges; directed=false)
# Direct type construction with mutation
g = build_graph(AdjGraph, edges; directed=false)
add_edge!(g, 4, 1) # Efficient dynamic modificationMemory Layout Example
For graph with edges [(1,2), (2,3), (1,3)], undirected:
neighbors = [[2,3], [1,3], [1,2]] # Vertex 1: neighbors 2,3; Vertex 2: neighbors 1,3, etc.
neighbor_to_edge = [[1,3], [1,2], [3,2]] # Maps: v1's neighbor 2→edge 1, v1's neighbor 3→edge 3, etc.Performance Notes
- Best for: Dynamic graphs with frequent add/remove operations
- Mutations: O(1) additions, O(degree) removals
- Memory: ~16-24 bytes per directed edge (vector overhead + pointers)
- Cache: Good for sparse graphs, less optimal for dense graphs
Mutation Support
# Efficient dynamic operations
new_vertex = add_vertex!(g) # O(1) - just adds empty vectors
edge_idx = add_edge!(g, u, v) # O(1) amortized - vector push
success = remove_edge!(g, u, v) # O(degree) - find and remove
success = remove_vertex!(g, v) # O(V + incident edges) - updates all references
# ⚠️ Warning: Removals may invalidate edge indices
# External arrays indexed by edges will become inconsistentGraphCore.AdjGraph — MethodAdjGraph(g::GraphInterface) -> AdjGraphConvert any GraphInterface implementation to an AdjGraph using constructor syntax. This is an idiomatic Julia alternative to to_adj_graph(g).
Examples
# Constructor style (idiomatic)
adj_g = AdjGraph(core_graph)
# Equivalent to conversion function
adj_g = to_adj_graph(core_graph)GraphCore.AdjGraph — MethodAdjGraph{D}(g::GraphInterface) -> AdjGraph{D}Convert any GraphInterface to an AdjGraph with explicit directedness type parameter. The source graph must have the same directedness as specified by the type parameter.
Examples
# Type-safe conversions (will succeed)
directed_adj = AdjGraph{true}(directed_core_graph)
undirected_adj = AdjGraph{false}(undirected_core_graph)
# Type mismatch (will throw AssertionError)
# AdjGraph{true}(undirected_graph) # ERROR!GraphCore.CoreGraph — TypeCoreGraph{D} <: GraphInterfaceHigh-performance graph using Compressed Sparse Row (CSR) storage format.
Type Parameters
D::Bool: Directedness flag (true = directed, false = undirected)
Fields (Internal - Access via interface methods)
vertex_offsets::Vector{Int32}: CSR row pointers (length = nv + 1)neighbors::Vector{Int32}: Flattened neighbor listsneighbor_to_edge::Vector{Int32}: Maps neighbor positions to undirected edge indices (undirected only)num_edges::Int32: Number of (undirected) edges
Construction
Use build_core_graph() or build_graph(CoreGraph, ...) for safe construction:
# Basic construction
edges = [(1,2), (2,3), (1,3)]
g = build_core_graph(edges; directed=false)
# With validation disabled (faster, but unsafe)
g = build_graph(CoreGraph, edges; directed=false, validate=false)Memory Layout Example
For graph with edges [(1,2), (2,3), (1,3)], undirected:
vertex_offsets = [1, 3, 6, 8] # Vertex 1: neighbors[1:2], Vertex 2: neighbors[3:5], etc.
neighbors = [2, 3, 1, 3, 1, 2] # Flattened: [neighbors(1), neighbors(2), neighbors(3)]
neighbor_to_edge = [1, 3, 1, 2, 3, 2] # Maps each neighbor to its edge indexPerformance Notes
- Best for: Static graphs with frequent neighbor access
- Avoid for: Graphs requiring frequent structural modifications
- Memory: ~12-16 bytes per directed edge (depending on architecture)
- Cache: Excellent locality for neighbor iteration
GraphCore.CoreGraph — MethodCoreGraph(g::GraphInterface) -> CoreGraphConvert any GraphInterface implementation to a CoreGraph using constructor syntax. This is an idiomatic Julia alternative to to_core_graph(g).
Examples
# Constructor style (idiomatic)
core_g = CoreGraph(adj_graph)
# Equivalent to conversion function
core_g = to_core_graph(adj_graph)GraphCore.CoreGraph — MethodCoreGraph{D}(g::GraphInterface) -> CoreGraph{D}Convert any GraphInterface to a CoreGraph with explicit directedness type parameter. The source graph must have the same directedness as specified by the type parameter.
Examples
# Type-safe conversions (will succeed)
directed_core = CoreGraph{true}(directed_adj_graph)
undirected_core = CoreGraph{false}(undirected_adj_graph)
# Type mismatch (will throw TypeError)
# CoreGraph{true}(undirected_graph) # ERROR!GraphCore.GraphInterface — TypeGraphInterface <: AbstractGraph{Int32}Base abstract type for all graphs in the GraphCore ecosystem. All vertices are indexed by Int32 integers 1, 2, ..., num_vertices(g).
GraphCore.PropertyGraph — TypePropertyGraph{G,V,E} <: PropertyGraphInterface{V,E}Universal property graph that wraps any base graph type with typed vertex and edge properties.
Type Parameters
G<:GraphInterface: Base graph type (CoreGraph, WeightedGraph, AdjGraph, etc.)V: Vertex property typeE: Edge property type
Design Benefits
- Universal wrapper: Works with any GraphInterface implementation
- Zero-cost delegation: All structural operations forwarded to base graph
- Type safety: Compile-time property type guarantees
- Automatic mutations: Inherits mutation capabilities from base graph
- Memory efficiency: No overhead when properties are unused
Usage Patterns
# Static analysis with CoreGraph base
core_g = build_core_graph(edges; directed=false)
vertex_labels = ["Alice", "Bob", "Charlie"]
edge_types = ["friend", "colleague", "family"]
pg = PropertyGraph(core_g, vertex_labels, edge_types)
# Access patterns
name = pg[1] # Vertex property via indexing
edge_type = edge_property(pg, 2) # Edge property by index
pg[1] = "Alice Updated" # Property modification
# Dynamic graphs with AdjGraph base
adj_g = build_adj_graph(edges; directed=false)
pg_mut = PropertyGraph(adj_g, vertex_labels, edge_types)
# Efficient mutations (when base graph supports them)
new_vertex = add_vertex!(pg_mut, "David") # O(1) addition
edge_idx = add_edge!(pg_mut, 1, new_vertex, "buddy") # O(1) addition
# Combined with weights
weighted_g = build_weighted_graph(edges, weights; directed=false)
pg = PropertyGraph(weighted_g, vertex_labels, edge_types)
# Now has both weights and properties availableMutation Behavior
# Mutations work when base graph supports them
adj_pg = PropertyGraph(build_adj_graph(edges), v_props, e_props)
add_edge!(adj_pg, u, v, edge_prop) # ✅ Works - AdjGraph supports mutations
# Mutations fail gracefully when base graph doesn't support them
core_pg = PropertyGraph(build_core_graph(edges), v_props, e_props)
add_edge!(core_pg, u, v, edge_prop) # ❌ MethodError - CoreGraph is immutable
# Property arrays are automatically maintained during mutations
original_count = length(adj_pg.edge_properties)
edge_idx = add_edge!(adj_pg, u, v, edge_prop)
@assert length(adj_pg.edge_properties) == original_count + 1Performance Notes
- Delegation overhead: Typically optimized away by compiler
- Mutation performance: Same as underlying graph type
- Property management: Automatic with minimal overhead
- Memory: Base graph memory + property arrays + small wrapper overhead
GraphCore.PropertyGraphInterface — TypePropertyGraphInterface{V,E,W} <: GraphInterface
Abstract interface for property graphs, which support vertex and edge properties.GraphCore.WeightedAdjGraph — TypeWeightedAdjGraph{W,D} <: WeightedGraphInterface{W}Weighted dynamic graph extending AdjGraph with parallel weight storage. Combines the mutation efficiency of adjacency lists with type-safe weights.
Type Parameters
W<:Number: Weight type (Float64, Int32, etc.)D::Bool: Directedness flag
Key Features
- Same mutation performance as AdjGraph for structural operations
- Type-safe weights with compile-time guarantees
- Directional weights even for undirected graphs
- Parallel storage maintaining weight-neighbor correspondence
Weight Semantics
Important: Weights are always directional, even for undirected graphs. This allows asymmetric edge properties while maintaining undirected connectivity.
# For undirected edge with different directional costs:
g = build_weighted_adj_graph([(1,2)], [1.5]; directed=false)
# Internally stores: neighbors[1]=[2], weights[1]=[1.5]
# neighbors[2]=[1], weights[2]=[1.5]
# But weights can be modified independently if needed
# Access via directional indexing:
idx_12 = find_directed_edge_index(g, 1, 2) # Different from (2,1)
idx_21 = find_directed_edge_index(g, 2, 1)
weight_12 = edge_weight(g, idx_12) # Initial: 1.5
weight_21 = edge_weight(g, idx_21) # Initial: 1.5 (same value, different storage)Mutation Examples
edges = [(1,2), (2,3)]
weights = [1.0, 2.0]
g = build_weighted_adj_graph(edges, weights; directed=false)
# Add weighted edge
edge_idx = add_edge!(g, 3, 1, 1.5) # O(1) amortized
# Efficient weight access during iteration
for (neighbor, weight) in neighbor_weights(g, v)
process_weighted_neighbor(neighbor, weight)
endGraphCore.WeightedAdjGraph — MethodWeightedAdjGraph(g::WeightedGraphInterface{W}) -> WeightedAdjGraph{W}
WeightedAdjGraph{W}(g::WeightedGraphInterface{W}) -> WeightedAdjGraph{W}
WeightedAdjGraph{W,D}(g::WeightedGraphInterface{W}) -> WeightedAdjGraph{W,D}Convert any WeightedGraphInterface to a WeightedAdjGraph using constructor syntax. Supports multiple forms with different levels of type specification.
Constructor Forms
WeightedAdjGraph(g): Auto-infer weight type and directednessWeightedAdjGraph{W}(g): Explicit weight type parameterWeightedAdjGraph{W,D}(g): Explicit weight type and directedness parameters
Examples
# Basic constructor (auto-infer types)
weighted_adj = WeightedAdjGraph(weighted_core_graph)
# Explicit weight type
weighted_adj = WeightedAdjGraph{Float64}(core_graph)
# Full type specification
# Full type specification with directedness assertion
directed_weighted_adj = WeightedAdjGraph{Float64,true}(directed_weighted_graph) # ✅ OK
undirected_weighted_adj = WeightedAdjGraph{Float64,false}(undirected_weighted_graph) # ✅ OK
# WeightedAdjGraph{Float64,true}(undirected_graph) # ❌ ERROR: directedness mismatch
# Equivalent to conversion function
weighted_adj = to_weighted_adj_graph(weighted_core_graph)GraphCore.WeightedGraph — TypeWeightedGraph{W,D} <: WeightedGraphInterface{W}Weighted graph extending CoreGraph with parallel weight storage.
Type Parameters
W<:Number: Weight type (Float64, Int32, etc.)D::Bool: Directedness flag
Key Features
- Same performance as CoreGraph for structural operations
- Type-safe weights with compile-time guarantees
- Directional weights even for undirected graphs
- Parallel storage for cache-efficient weight access
Weight Semantics
Important: Weights are always directional, even for undirected graphs. This allows asymmetric edge properties (e.g., different costs per direction).
# For undirected edge (1,2) with weight 1.5:
edge_weight(g, find_directed_edge_index(g, 1, 2)) # → 1.5
edge_weight(g, find_directed_edge_index(g, 2, 1)) # → 1.5 (same value, different index)
# But can be set differently if needed:
weights = [1.5, 2.0] # Different costs for each direction
g = build_weighted_graph([(1,2), (2,1)], weights; directed=true)Construction Examples
# Undirected weighted graph
edges = [(1,2), (2,3)]
weights = [1.5, 2.0]
g = build_weighted_graph(edges, weights; directed=false)
# Type-specific construction
g = build_graph(WeightedGraph{Float32}, edges; weights=weights, directed=false)GraphCore.WeightedGraph — MethodWeightedGraph(g::WeightedGraphInterface{W}) -> WeightedGraph{W}
WeightedGraph{W}(g::WeightedGraphInterface{W}) -> WeightedGraph{W}
WeightedGraph{W,D}(g::WeightedGraphInterface{W}) -> WeightedGraph{W,D}Convert any WeightedGraphInterface to a WeightedGraph using constructor syntax. Supports multiple forms with different levels of type specification.
Constructor Forms
WeightedGraph(g): Auto-infer weight type and directednessWeightedGraph{W}(g): Explicit weight type parameterWeightedGraph{W,D}(g): Explicit weight type and directedness parameters (with type assertion)
Examples
# Basic constructor (auto-infer types)
weighted_g = WeightedGraph(weighted_adj_graph)
# Explicit weight type
weighted_g = WeightedGraph{Float64}(adj_graph)
# Full type specification with directedness assertion
directed_weighted = WeightedGraph{Float64,true}(directed_weighted_graph) # ✅ OK
undirected_weighted = WeightedGraph{Float64,false}(undirected_weighted_graph) # ✅ OK
# WeightedGraph{Float64,true}(undirected_graph) # ❌ ERROR: directedness mismatch
# Equivalent to conversion function
weighted_g = to_weighted_graph(weighted_adj_graph)GraphCore.WeightedGraphInterface — TypeWeightedGraphInterface <: GraphInterfaceInterface for weighted graphs, extending the core graph interface. W is the type of edge weights, typically a numeric type.
GraphCore.add_edge! — Functionadd_edge!(g::GraphInterface, u::Integer, v::Integer, ...) -> Int32Add an edge from u to v with the optinal properties. Returns the edge index of the newly added edge, or 0 if edge already exists. For undirected graphs, this adds the edge in both directions internally. Only available for mutable graph types.
GraphCore.add_edge! — Methodadd_edge!(g::AdjGraph, u::Integer, v::Integer) -> Int32Add an edge from u to v and return the edge index (or 0 if already exists).
Performance
- Time Complexity: O(1) amortized (vector push operations)
- Space Complexity: O(1) per direction
- Index Stability: All existing indices remain valid, new edge gets max+1
Behavior Details
- Directed graphs: Adds only u→v edge
- Undirected graphs: Adds both u→v and v→u internally with same edge index
- Duplicate detection: Returns 0 if edge already exists (no modification)
- Index assignment: New edges get next available index
Examples
g = build_adj_graph([(1,2)]; directed=false)
@assert num_edges(g) == 1
# Add new edge
edge_idx = add_edge!(g, 2, 3)
@assert edge_idx == 2 # Next available index
@assert num_edges(g) == 2
@assert has_edge(g, 2, 3) && has_edge(g, 3, 2) # Both directions for undirected
# Try duplicate
duplicate_idx = add_edge!(g, 1, 2)
@assert duplicate_idx == 0 # Already exists
@assert num_edges(g) == 2 # No changeError Conditions
Throws BoundsError if vertices u or v don't exist in the graph. Use add_vertex! first if needed.
GraphCore.add_edge! — Methodadd_edge!(g::CoreGraph, u::Integer, v::Integer) -> Int32Add an edge from u to v and return the edge index (or 0 if edge already exists).
Efficient Implementation: O(degree) operation that extends the CSR arrays and updates offsets.
For undirected graphs, this adds the edge in both directions internally.
Example
g = build_core_graph([(1,2)]; directed=false)
edge_idx = add_edge!(g, 1, 3) # Returns edge index
@assert has_edge(g, 1, 3) && has_edge(g, 3, 1) # Both directions for undirectedGraphCore.add_edge! — Methodadd_edge!(g::WeightedGraph{W}, u::Integer, v::Integer, weight::W) -> Int32Add a weighted edge from u to v and return the edge index (or 0 if edge already exists).
Efficient Implementation: O(degree) operation that extends the CSR arrays and updates offsets.
GraphCore.add_edge! — Methodadd_edge!(g::PropertyGraph{G,V,E}, u::Integer, v::Integer, edge_prop::E) -> Int32Add an edge from u to v with the specified edge property. Returns the edge index of the newly added edge, or 0 if edge already exists.
Only available when the base graph type supports add_edge!. Property arrays are automatically maintained.
GraphCore.add_edge! — Methodadd_edge!(g::PropertyGraph{<:WeightedGraphInterface,V,E}, u::Integer, v::Integer,
weight::W, edge_prop::E) -> Int32Add a weighted edge from u to v with the specified weight and edge property. Returns the edge index of the newly added edge, or 0 if edge already exists.
Only available when the base graph type supports weighted add_edge!.
GraphCore.add_edge! — Methodadd_edge!(g::WeightedAdjGraph{W}, u::Integer, v::Integer, weight::W) -> Int32Add a weighted edge from u to v in the graph. Returns the edge index of the newly added edge, or 0 if edge already exists. For undirected graphs, both directions get the same weight.
GraphCore.add_vertex! — Functionadd_vertex!(g::GraphInterface, ...) -> Int32Add a new vertex with optional properties. Returns the index of the newly added vertex. Only available for mutable graph types.
GraphCore.add_vertex! — Methodadd_vertex!(g::AdjGraph) -> Int32Add a new isolated vertex to the graph and return its index.
Performance
- Time Complexity: O(1)
- Space Complexity: O(1) - just adds empty vectors
- Index Stability: All existing vertex/edge indices remain valid
Implementation Details
Creates empty neighbor list and empty neighbortoedge mapping. New vertex has no neighbors initially and can be connected via add_edge!.
Examples
g = build_adj_graph([(1,2), (2,3)]; directed=false)
@assert num_vertices(g) == 3
new_v = add_vertex!(g)
@assert new_v == 4
@assert num_vertices(g) == 4
@assert degree(g, new_v) == 0 # Isolated vertex
# Connect new vertex
add_edge!(g, 1, new_v)
@assert degree(g, new_v) == 1GraphCore.add_vertex! — Methodadd_vertex!(g::CoreGraph) -> Int32Add a new isolated vertex to the graph and return its index.
Efficient Implementation: O(1) operation that simply extends the vertex_offsets array.
Example
g = build_core_graph([(1,2), (2,3)]; directed=false)
new_vertex = add_vertex!(g) # Returns 4
@assert num_vertices(g) == 4
@assert length(neighbor_indices(g, new_vertex)) == 0 # Isolated vertexGraphCore.add_vertex! — Methodadd_vertex!(g::PropertyGraph{G,V,E}, vertex_prop::V) -> Int32Add a new vertex to the property graph with the specified property. Returns the index of the new vertex.
Only available when the base graph type supports add_vertex!.
GraphCore.add_vertex! — Methodadd_vertex!(g::WeightedAdjGraph{W}) -> Int32 where WAdd a new vertex to the weighted graph and return its index. The new vertex has no neighbors initially.
GraphCore.add_vertex! — Methodadd_vertex!(g::WeightedGraph) -> Int32Add a new isolated vertex to the weighted graph and return its index.
Efficient Implementation: O(1) operation that simply extends the vertex_offsets array.
GraphCore.all_directed_edges — Methodall_directed_edges(g::GraphInterface) -> IteratorReturn an iterator over all directed edges in the graph.
- For directed graphs: yields (source, target) pairs for each directed edge
- For undirected graphs: yields (u, v) and (v, u) pairs for each undirected edge
Examples
for (u, v) in all_directed_edges(g)
println("Directed edge from ", u, " to ", v)
endGraphCore.all_edges — Methodall_edges(g::GraphInterface) -> IteratorAlias for edges(g). Provided for disambiguation when using multiple graph libraries.
See also: edges
GraphCore.build_adj_graph — MethodBuild adjacency list graph with same interface as CoreGraph.
GraphCore.build_core_graph — MethodBuild unweighted core graph (most common case)
GraphCore.build_graph — Methodbuild_graph(::Type{PropertyGraph{G,V,E}}, edges; kwargs...) where {G,V,E}Build a property graph with vertex and edge properties. The underlying graph type G determines performance characteristics (CoreGraph for CSR, AdjGraph for adjacency list).
Arguments
edges: Vector of (u,v) tuples/pairs representing graph edgesdirected=true: Whether the graph is directedvertex_properties=[]: Properties for each vertex (type V)edge_properties=[]: Properties for each edge (type E)weights=[]: Edge weights (optional)validate=true: Whether to validate inputs
Examples
# Property graph with CoreGraph backend
g = build_graph(PropertyGraph{CoreGraph,String,String}, [(1,2), (2,3)];
vertex_properties=["A", "B", "C"], edge_properties=["e1", "e2"])
# Property graph with AdjGraph backend for dynamic use
g = build_graph(PropertyGraph{AdjGraph,Int,Symbol}, [(1,2), (2,3)];
vertex_properties=[1, 2, 3], edge_properties=[:a, :b])GraphCore.build_graph — Methodbuild_graph(::Type{G}, edges; kwargs...) where {G<:AdjGraphTypes}Build adjacency list graph optimized for dynamic modifications and mutations.
Arguments
edges: Vector of (u,v) tuples/pairs representing graph edgesdirected=true: Whether to build a directed graphweights=[]: Edge weights (for WeightedAdjGraph types)validate=true: Enable input validation
Performance Characteristics
- Dynamic-friendly: Efficient vertex/edge additions and removals
- Memory flexible: Grows naturally, higher overhead than CSR
- Mutation-optimized: O(1) edge additions, efficient vertex operations
Use AdjGraph types when frequent graph modifications are expected. For static graphs with performance-critical traversals, prefer CoreGraph types.
GraphCore.build_graph — Methodbuild_graph(::Type{G}, edges; kwargs...) -> GBuild a graph from an edge list with comprehensive validation and flexible options.
Arguments
edges: Vector of (u,v) tuples/pairs representing graph edgesdirected=true: Whether to build a directed graphn=0: Number of vertices (0 = auto-detect from edges)weights=[]: Edge weights (for WeightedGraph types)validate=true: Enable input validation (recommended for safety)
Examples
# Basic graphs
g = build_graph(CoreGraph, [(1,2), (2,3)]; directed=false)
wg = build_graph(WeightedGraph{Float64}, [(1,2), (2,3)]; weights=[1.5, 2.0], directed=false)
# Graph with isolated vertices
g = build_graph(CoreGraph, [(1,2)]; n=5, directed=false) # Creates isolated vertices 3,4,5
# High-performance mode (skip validation)
g = build_graph(CoreGraph, trusted_edges; directed=false, validate=false)Optimized for CSR representation with efficient construction and memory usage. For dynamic graphs requiring frequent mutations, consider AdjGraph types.
GraphCore.build_property_adj_graph — Methodbuild_property_adj_graph(edges, vertex_properties, edge_properties; directed=true, kwargs...)Build a PropertyGraph with AdjGraph backend (supports efficient mutations).
Arguments
edges: Vector of (u,v) tuples representing graph edgesvertex_properties: Vector of vertex propertiesedge_properties: Vector of edge propertiesdirected=true: Whether to build a directed graphkwargs...: Additional arguments passed to underlying graph construction
Example
edges = [(1,2), (2,3)]
vertex_props = [1, 2, 3]
edge_props = [:a, :b]
pg = build_property_adj_graph(edges, vertex_props, edge_props; directed=false)GraphCore.build_property_graph — Methodbuild_property_graph(edges, vertex_properties, edge_properties; directed=true, kwargs...)Build a PropertyGraph with CoreGraph backend.
Arguments
edges: Vector of (u,v) tuples representing graph edgesvertex_properties: Vector of vertex propertiesedge_properties: Vector of edge propertiesdirected=true: Whether to build a directed graphkwargs...: Additional arguments passed to underlying graph construction
Example
edges = [(1,2), (2,3), (1,3)]
vertex_props = ["Alice", "Bob", "Charlie"]
edge_props = ["friend", "colleague", "family"]
pg = build_property_graph(edges, vertex_props, edge_props; directed=false)GraphCore.build_weighted_graph — MethodBuild weighted graph
GraphCore.canonicalize_edges — Methodcanonicalize_edges(edges) -> Vector{Tuple{Int,Int}}Convert symmetric edge format to canonical format for undirected graphs.
Arguments
edges: Vector of (u,v) tuples representing edges
Returns
- Vector of canonical edges where u ≤ v for each edge
Format Conversion
- Input:
[(1,2), (2,1), (2,3), (3,2)](both directions) - Output:
[(1,2), (2,3)](canonical: u ≤ v)
Use when your input has both directions listed for undirected edges. This removes duplicates and ensures a consistent canonical representation.
Example
edges = [(1,2), (2,1), (2,3), (3,2), (1,3), (3,1)]
canonical = GraphCore.canonicalize_edges(edges)
# Result: [(1,2), (1,3), (2,3)]GraphCore.canonicalize_edges — Methodcanonicalize_edges(edges, weights::AbstractVector{W}) -> (canonical_edges, canonical_weights)Convert symmetric format to canonical, keeping weights for canonical edges only.
Arguments
edges: Vector of (u,v) tuples representing edgesweights: Vector of weights corresponding to edges
Returns
- Tuple of (canonicaledges, canonicalweights)
Behavior
When multiple weights exist for the same undirected edge, keeps the first encountered weight. This is useful when processing datasets that list both directions with potentially different weights.
Example
edges = [(1,2), (2,1), (2,3), (3,2)]
weights = [1.5, 1.5, 2.0, 2.1] # Note: slight difference in last weight
canonical_edges, canonical_weights = GraphCore.canonicalize_edges(edges, weights)
# Result: edges = [(1,2), (2,3)], weights = [1.5, 2.0]GraphCore.degree — Methoddegree(g::GraphInterface, v::Integer) -> Int32Return the degree of vertex v (number of neighbors).
GraphCore.directed_edge_index — Functiondirected_edge_index(g::GraphInterface, v::Integer, i::Integer) -> Int32Get the directed edge index for the i-th neighbor of vertex v.
Similar to edge_index but for directional properties. Always provides directional indexing even for undirected graphs.
Key difference: For undirected graphs:
edge_index(g, u, i) == edge_index(g, v, j)if neighbors are the same edgedirected_edge_index(g, u, i) ≠ directed_edge_index(g, v, j)(always directional)
This enables asymmetric properties on undirected graphs (e.g., different costs for traversing an edge in each direction).
GraphCore.directed_edge_indices — Functiondirected_edge_indices(g::GraphInterface, v::Integer) -> view or iteratorReturn an iterator over the directed edge indices for edges from vertex v. The i-th edge index corresponds to the i-th neighbor in neighbor_indices(g, v). For directed graphs this is the same asdirectededgeindices(g, v)`.
GraphCore.directed_edge_indices — Methoddirected_edge_indices(g::GraphInterface) -> UnitRange{Int}Return a range over all directed edge indices. Suitable for sizing and indexing external directed edge property arrays.
GraphCore.edge_index — Functionedge_index(g::GraphInterface, v::Integer, i::Integer) -> Int32Get the undirected edge index for the i-th neighbor of vertex v.
This provides O(1) conversion from neighbor position to edge index, enabling efficient indexing into external edge property arrays.
Relationship: edge_index(g, v, i) == find_edge_index(g, v, neighbor_indices(g, v)[i])
Use case: Processing neighbors with associated edge data
edge_weights = Vector{Float64}(undef, num_edges(g))
for (i, neighbor) in enumerate(neighbor_indices(g, v))
edge_idx = edge_index(g, v, i) # O(1) - no search needed!
weight = edge_weights[edge_idx] # Direct array access
process_neighbor_with_weight(neighbor, weight)
endIndex stability: Edge indices remain stable during graph analysis, but may be invalidated by structural modifications (add/remove operations).
GraphCore.edge_indices — Functionedge_indices(g::GraphInterface, v::Integer) -> view or iteratorReturn an iterator over the undirected edge indices for edges from vertex v. The i-th edge index corresponds to the i-th neighbor in neighbor_indices(g, v).
GraphCore.edge_indices — Methodedge_indices(g::GraphInterface) -> UnitRange{Int}Return a range over all undirected edge indices. Suitable for sizing and indexing external edge property arrays.
GraphCore.edge_properties — Functionedge_properties(g::PropertyGraphInterface) -> iteratorReturn an iterator over all edge properties in edge index order.
GraphCore.edge_property — Functionedge_property(g::PropertyGraphInterface, edge_idx::Integer) -> EGet the property associated with edge at the given edge index. Uses undirected edge indexing (1:num_edges).
GraphCore.edge_property — Methodedge_property(g::GraphInterface, u::Integer, v::Integer) -> EGet the property of the edge between u and v. Uses undirected edge indexing - for undirected graphs, this returns the same property regardless of direction.
GraphCore.edge_weight — Functionedge_weight(g::WeightedGraphInterface, directed_edge_idx::Integer) -> W
edge_weight(g::WeightedGraphInterface, edge::Pair{<:Integer,<:Integer}) -> WGet the weight of the directed edge at the given directed edge index. Uses the directional indexing system for O(1) weight lookups. The second form allows querying by vertex pair, equivalent to edge_weight(g, find_edge_index(g, u, v)).
GraphCore.edge_weights — Functionedge_weights(g::WeightedGraphInterface, v::Integer) -> view or iterator
edge_weights(g::WeightedGraphInterface) -> view or iteratorReturn weights for edges from vertex v, or all edge weights.
Important: Weights are always directional, even for undirected graphs. This design allows asymmetric weights (e.g., different traversal costs in each direction).
Ordering: The i-th weight corresponds to the i-th neighbor in neighbor_indices(g, v).
Examples
# Process neighbors with weights
for (neighbor, weight) in zip(neighbor_indices(g, v), edge_weights(g, v))
process_weighted_edge(v, neighbor, weight)
end
# More convenient combined iteration
for (neighbor, weight) in neighbor_weights(g, v)
process_weighted_edge(v, neighbor, weight)
endGraphCore.edges — Methodedges(g::GraphInterface) -> IteratorReturn an iterator over all edges in the graph.
- For directed graphs: yields (source, target) pairs for each directed edge
- For undirected graphs: yields (u, v) pairs where u ≤ v (each edge once)
Examples
for (u, v) in edges(g)
println("Edge from ", u, " to ", v)
end
# Collect all edges
edge_list = collect(edges(g))GraphCore.find_directed_edge_index — Functionfind_directed_edge_index(g::GraphInterface, u::Integer, v::Integer) -> Int32Find the directed edge index for the directed edge from vertices u to v of the graph g. Returns 0 if no such edge exists.
Always directional: find_directed_edge_index(g, u, v) ≠ find_directed_edge_index(g, v, u)
This index is used for directed edge weight access and other directional properties, and for indexing external arrays of size num_directed_edges(g).
GraphCore.find_edge_index — Functionfind_edge_index(g::GraphInterface, u::Integer, v::Integer) -> Int32Find the undirected edge index for the edge between vertices u and v of the graph g. Returns 0 if no such edge exists.
For undirected graphs: find_edge_index(g, u, v) == find_edge_index(g, v, u) For directed graphs: only finds the edge in the specified direction (u -> v)
This index is used for edge property access (shared properties) and for indexing external arrays of size numedges(g). For directed graphs this is the same as `finddirectededgeindex(g, u, v)`
GraphCore.has_edge — Functionhas_edge(g::GraphInterface, u::Integer, v::Integer) -> BoolTest whether there is a directed edge from vertex u to vertex v. For undirected graphs, has_edge(g, u, v) == has_edge(g, v, u).
GraphCore.has_vertex — Functionhas_vertex(g::GraphInterface, v::Integer) -> BoolTest whether vertex v exists in the graph. Vertices are always integers in range 1:num_vertices(g).
GraphCore.is_directed_graph — Functionis_directed_graph(g::GraphInterface) -> BoolReturn true if the graph is directed, false if undirected. This affects the interpretation of edges and neighbor relationships.
GraphCore.neighbor — Functionneighbor(g::GraphInterface, v::Integer, i::Integer) -> Int32Return the i-th neighbor of vertex v in the graph g.
Default implementation provided - concrete types may override for efficiency.
GraphCore.neighbor_indices — Functionneighbor_indices(g::GraphInterface, v::Integer) -> view or iteratorReturn an iterator over the neighbor indices of vertex v.
For directed graphs: Returns out-neighbors only For undirected graphs: Returns all neighbors
Performance guarantee: The returned iterator must support:
- Fast iteration:
for neighbor in neighbor_indices(g, v) - Length query:
length(neighbor_indices(g, v)) - Index access:
neighbor_indices(g, v)[i](implementation dependent)
Memory efficiency: Implementations should return views when possible to avoid allocation during neighbor traversal.
Examples
# Basic iteration
for neighbor in neighbor_indices(g, v)
process_neighbor(neighbor)
end
# Combined with indexing for edge properties
for (i, neighbor) in enumerate(neighbor_indices(g, v))
edge_idx = edge_index(g, v, i) # O(1) edge index lookup
process_edge(neighbor, edge_idx)
endGraphCore.neighbor_weights — Functionneighbor_weights(g::WeightedGraphInterface, v::Integer) -> iteratorReturn an iterator over (neighbor_index, weight) pairs for vertex v. More efficient than separate iteration over neighbor_indices(g, v) and edge_weights(g, v).
Usage:
for (neighbor, weight) in neighbor_weights(g, v)
# process neighbor and weight together
endSee also: neighbor_indices, edge_weights
GraphCore.num_directed_edges — Functionnum_directed_edges(g::GraphInterface) -> Int32Return the total number of directed edges in the graph.
- For undirected graphs:
2 * num_edges(g) - For directed graphs: actual count of directed edges
This count determines the size needed for directed edge property arrays.
GraphCore.num_edges — Functionnum_edges(g::GraphInterface) -> Int32Return the number of edges in the graph. For undirected graphs, this counts each edge once. For directed graphs, this counts directed edges.
GraphCore.num_vertices — Functionnum_vertices(g::GraphInterface) -> Int32Return the number of vertices in the graph.
GraphCore.remove_edge! — Functionremove_edge!(g::GraphInterface, u::Integer, v::Integer) -> BoolRemove the edge from u to v. Returns true if successful, false if edge doesn't exist. Only available for mutable graph types.
GraphCore.remove_edge! — Methodremove_edge!(g::AdjGraph, u::Integer, v::Integer) -> BoolRemove the edge from u to v from the graph. Returns true if successful, false if edge doesn't exist.
Performance
- Time Complexity: O(degree(u)) + O(degree(v)) for undirected
- Space Complexity: O(1) - only removes data
- Index Stability: ⚠️ MAY BREAK STABILITY - edge indices may be invalidated
Implementation Details
- Directed graphs: Removes only u→v edge
- Undirected graphs: Removes both u→v and v→u internal representations
- Search cost: Linear search in neighbor vectors to find edge
- Array operations: Uses
deleteat!which may shift subsequent elements
Edge Index Invalidation
g = build_adj_graph([(1,2), (2,3), (1,3)]; directed=false)
# Edge indices: (1,2)→1, (2,3)→2, (1,3)→3
# External edge data
edge_weights = [1.0, 2.0, 1.5] # Indexed by edge indices
remove_edge!(g, 2, 3) # Remove edge with index 2
# Now: remaining edges (1,2)→1, (1,3)→?
# ⚠️ Edge index for (1,3) may have changed!
# edge_weights[2] might now refer to wrong edgeSafe Usage Patterns
# ✅ SAFE: Use PropertyGraph for automatic edge property management
pg = PropertyGraph(g, vertex_props, edge_props)
remove_edge!(pg, u, v) # Edge properties automatically maintained
# ✅ SAFE: Use edge-based operations instead of index-based
for (u, v) in edges(g)
weight = compute_weight_from_vertices(u, v) # No index dependency
end
# ❌ UNSAFE: Assume edge indices remain stable across removals
edge_data = Vector{Float64}(undef, num_edges(g))
remove_edge!(g, u, v)
# edge_data indices now potentially inconsistent!Performance Considerations
For graphs with frequent edge removals, consider:
- Batch operations: Remove many edges at once, then rebuild external arrays
- Alternative storage: Use Dict{Tuple{Int,Int}, T} for edge properties
- Conversion workflow: AdjGraph for building → CoreGraph for analysis
GraphCore.remove_edge! — Methodremove_edge!(g::PropertyGraph, u::Integer, v::Integer) -> BoolRemove the edge from u to v from the property graph. Returns true if successful, false if edge doesn't exist.
Only available when the base graph type supports remove_edge!. Property arrays are automatically maintained.
⚠️ Index Invalidation Warning: Removing edges may invalidate edge indices and external arrays indexed by edge numbers.
GraphCore.remove_edge! — Methodremove_edge!(g::WeightedAdjGraph, u::Integer, v::Integer) -> BoolRemove the weighted edge from u to v from the graph. Returns true if successful, false if edge doesn't exist.
Performance
- Time Complexity: O(degree(u)) + O(degree(v)) for undirected
- Space Complexity: O(1) - only removes data
- Index Stability: ⚠️ MAY BREAK STABILITY - edge indices may be invalidated
Implementation Details
- Directed graphs: Removes only u→v edge
- Undirected graphs: Removes both u→v and v→u internal representations
- Search cost: Linear search in neighbor vectors to find edge
- Array operations: Uses
deleteat!which may shift subsequent elements
Edge Index Invalidation
g = build_weighted_adj_graph([(1,2), (2,3), (1,3)]; directed=false)
# Edge indices: (1,2)→1, (2,3)→2, (1,3)→3
# External edge data
edge_weights = [1.0, 2.0, 1.5] # Indexed by edge indices
remove_edge!(g, 2, 3) # Remove edge with index 2
# Now: remaining edges (1,2)→1, (1,3)→?
# ⚠️ Edge index for (1,3) may have changed!
# edge_weights[2] might now refer to wrong edgeSafe Usage Patterns
# ✅ SAFE: Use PropertyGraph for automatic edge property management
pg = PropertyGraph(g, vertex_props, edge_props)
remove_edge!(pg, u, v) # Edge properties automatically maintained
# ✅ SAFE: Use edge-based operations instead of index-based
for (u, v) in edges(g)
weight = compute_weight_from_vertices(u, v) # No index dependency
end
# ❌ UNSAFE: Assume edge indices remain stable across removals
edge_data = Vector{Float64}(undef, num_edges(g))
remove_edge!(g, u, v)
# edge_data indices now potentially inconsistent!Performance Considerations
For graphs with frequent edge removals, consider:
- Batch operations: Remove many edges at once, then rebuild external arrays
- Alternative storage: Use Dict{Tuple{Int,Int}, T} for edge properties
- Conversion workflow: AdjGraph for building → CoreGraph for analysis
GraphCore.remove_edge! — Methodremove_edge!(g::CoreGraph, u::Integer, v::Integer) -> BoolRemove the edge from u to v from the graph. Returns true if successful, false if edge doesn't exist.
Efficient Implementation: O(degree) operation that removes entries from CSR arrays and updates offsets.
For frequent mutations, consider using AdjGraph instead.
Example
g = build_core_graph([(1,2), (2,3), (1,3)]; directed=false)
success = remove_edge!(g, 1, 2) # Returns true
@assert !has_edge(g, 1, 2) && !has_edge(g, 2, 1) # Both directions removed for undirectedGraphCore.remove_edge! — Methodremove_edge!(g::WeightedGraph, u::Integer, v::Integer) -> BoolRemove the edge from u to v from the weighted graph. Returns true if successful, false if edge doesn't exist.
Efficient Implementation: O(degree) operation that removes entries from CSR arrays and updates offsets.
GraphCore.remove_vertex! — Functionremove_vertex!(g::GraphInterface, v::Integer) -> BoolRemove vertex v and all its incident edges. Returns true if successful, false if vertex doesn't exist. Only available for mutable graph types.
GraphCore.remove_vertex! — Methodremove_vertex!(g::AdjGraph, v::Integer) -> BoolRemove vertex v and all its incident edges from the graph. Returns true if successful, false if vertex doesn't exist.
Performance
- Time Complexity: O(V + incident_edges) - must update all vertex references
- Space Complexity: O(1) - only removes data
- Index Stability: ⚠️ BREAKS STABILITY - vertex indices > v are decremented
Implementation Details
- Edge Removal: All incident edges are removed first (affects edge count)
- Vertex Deletion: Vertex v is removed from adjacency structures
- Index Update: All references to vertices > v are decremented by 1
- Property Cleanup: For PropertyGraph, properties are also removed
Index Invalidation Warning
g = build_adj_graph([(1,2), (2,3), (3,4)]; directed=false)
# Before: vertices [1,2,3,4], vertex 3 has neighbors [2,4]
success = remove_vertex!(g, 2) # Remove vertex 2
# After: vertices [1,2,3], old vertex 3→new vertex 2, old vertex 4→new vertex 3
# ⚠️ External arrays indexed by old vertex numbers are now INVALID!
# External vertex properties become inconsistent:
vertex_labels = ["A", "B", "C", "D"] # Indexed by old vertex numbers
# After removal: vertex_labels[3] no longer corresponds to current vertex 3!Safe Usage Patterns
# ✅ SAFE: Use PropertyGraph for automatic property management
pg = PropertyGraph(g, vertex_labels, edge_labels)
remove_vertex!(pg, 2) # Properties automatically updated
# ✅ SAFE: Rebuild external arrays after removal
external_data = rebuild_after_removal(external_data, removed_vertex)
# ❌ UNSAFE: Assume external arrays remain valid after removal
remove_vertex!(g, v)
old_label = vertex_labels[some_vertex] # May be wrong!GraphCore.remove_vertex! — Methodremove_vertex!(g::PropertyGraph, v::Integer) -> BoolRemove vertex v and all its incident edges from the property graph. Returns true if successful, false if vertex doesn't exist.
Only available when the base graph type supports remove_vertex!. Property arrays are automatically maintained and indices updated.
⚠️ Index Invalidation Warning: Removing vertices renumbers remaining vertices and invalidates external arrays indexed by vertex numbers.
GraphCore.remove_vertex! — Methodremove_vertex!(g::WeightedAdjGraph, v::Integer) -> BoolRemove vertex v and all its incident edges from the weighted graph. Returns true if successful, false if vertex doesn't exist.
Performance
- Time Complexity: O(V + incident_edges) - must update all vertex references
- Space Complexity: O(1) - only removes data
- Index Stability: ⚠️ BREAKS STABILITY - vertex indices > v are decremented
Implementation Details
- Edge Removal: All incident edges are removed first (affects edge count)
- Vertex Deletion: Vertex v is removed from adjacency structures
- Index Update: All references to vertices > v are decremented by 1
- Property Cleanup: For PropertyGraph, properties are also removed
Index Invalidation Warning
g = build_weighted_adj_graph([(1,2), (2,3), (3,4)]; directed=false)
# Before: vertices [1,2,3,4], vertex 3 has neighbors [2,4]
success = remove_vertex!(g, 2) # Remove vertex 2
# After: vertices [1,2,3], old vertex 3→new vertex 2, old vertex 4→new vertex 3
# ⚠️ External arrays indexed by old vertex numbers are now INVALID!
# External vertex properties become inconsistent:
vertex_labels = ["A", "B", "C", "D"] # Indexed by old vertex numbers
# After removal: vertex_labels[3] no longer corresponds to current vertex 3!Safe Usage Patterns
# ✅ SAFE: Use PropertyGraph for automatic property management
pg = PropertyGraph(g, vertex_labels, edge_labels)
remove_vertex!(pg, 2) # Properties automatically updated
# ✅ SAFE: Rebuild external arrays after removal
external_data = rebuild_after_removal(external_data, removed_vertex)
# ❌ UNSAFE: Assume external arrays remain valid after removal
remove_vertex!(g, v)
old_label = vertex_labels[some_vertex] # May be wrong!GraphCore.remove_vertex! — Methodremove_vertex!(g::CoreGraph, v::Integer) -> BoolRemove vertex v and all its incident edges from the graph. Returns true if successful, false if vertex doesn't exist.
⚠️ Performance Note: O(V + E) operation due to vertex renumbering requirement. ⚠️ Index Invalidation: Removes vertex v and renumbers vertices v+1, v+2, ... to v, v+1, ... This invalidates any external arrays indexed by vertex numbers.
Implementation: More efficient than full reconstruction but still requires renumbering.
Example
g = build_core_graph([(1,2), (2,3), (1,3)]; directed=false)
success = remove_vertex!(g, 2) # Returns true
@assert num_vertices(g) == 2
@assert has_edge(g, 1, 2) # What was vertex 3 is now vertex 2GraphCore.remove_vertex! — Methodremove_vertex!(g::WeightedGraph, v::Integer) -> BoolRemove vertex v and all its incident edges from the weighted graph. Returns true if successful, false if vertex doesn't exist.
⚠️ Performance Note: O(V + E) operation due to vertex renumbering requirement. ⚠️ Index Invalidation: Removes vertex v and renumbers vertices v+1, v+2, ... to v, v+1, ... This invalidates any external arrays indexed by vertex numbers.
Implementation: More efficient than full reconstruction but still requires renumbering.
Example
g = build_weighted_graph([(1,2,1.0), (2,3,2.0), (1,3,3.0)]; directed=false)
success = remove_vertex!(g, 2) # Returns true
@assert num_vertices(g) == 2
@assert has_edge(g, 1, 2) # What was vertex 3 is now vertex 2GraphCore.set_edge_property! — Functionset_edge_property!(g::PropertyGraphInterface{V,E,W}, edge_idx::Integer, prop::E) -> propSet the property of edge at edge_idx to prop. Only available for mutable graph types.
GraphCore.set_vertex_property! — Functionset_vertex_property!(g::PropertyGraphInterface{V,E,W}, v::Integer, prop::V) -> propSet the property of vertex v to prop. Only available for mutable graph types.
GraphCore.symmetrize_edges — Methodsymmetrize_edges(edges) -> Vector{Tuple{Int,Int}}Convert canonical format to symmetric format (both directions).
Arguments
edges: Vector of (u,v) tuples in canonical format
Returns
- Vector of edges with both directions included
Format Conversion
- Input:
[(1,2), (2,3)](canonical) - Output:
[(1,2), (2,1), (2,3), (3,2)](both directions)
Use when you need to create a directed graph from undirected edges, or when working with algorithms that expect symmetric adjacency representations.
Example
canonical = [(1,2), (2,3), (1,3)]
symmetric = GraphCore.symmetrize_edges(canonical)
# Result: [(1,2), (2,1), (2,3), (3,2), (1,3), (3,1)]Note
Self-loops (u,u) are not duplicated to avoid redundancy.
GraphCore.symmetrize_edges — Methodsymmetrize_edges(edges, weights::AbstractVector{W}) -> (symmetric_edges, symmetric_weights)Convert canonical format to symmetric, duplicating weights for both directions.
Arguments
edges: Vector of (u,v) tuples in canonical formatweights: Vector of weights corresponding to edges
Returns
- Tuple of (symmetricedges, symmetricweights)
Behavior
Each weight is duplicated for both directions of the edge. This creates a symmetric weight matrix suitable for undirected graph algorithms.
Example
edges = [(1,2), (2,3)]
weights = [1.5, 2.0]
symmetric_edges, symmetric_weights = GraphCore.symmetrize_edges(edges, weights)
# Result:
# edges = [(1,2), (2,1), (2,3), (3,2)]
# weights = [1.5, 1.5, 2.0, 2.0]GraphCore.to_adj_graph — Methodto_adj_graph(g::GraphInterface) -> AdjGraphConvert any GraphInterface graph to an AdjGraph. Preserves the directedness of the original graph.
GraphCore.to_core_graph — Methodto_core_graph(g::GraphInterface) -> CoreGraphConvert any GraphInterface implementation to a CoreGraph. Preserves the directedness of the original graph.
GraphCore.to_weighted_graph — Methodto_weighted_graph(g::WeightedGraphInterface{W}) -> WeightedGraph{W}Convert any WeightedGraphInterface to a WeightedGraph. Preserves the directedness and all weights of the original graph.
GraphCore.vertex_properties — Functionvertex_properties(g::PropertyGraphInterface) -> iteratorReturn an iterator over all vertex properties in order.
Example
g = build_property_graph(edges, ["A", "B", "C"], edge_props, 3)
for (i, prop) in enumerate(vertex_properties(g))
println("Vertex ", i, " has property: ", prop)
endGraphCore.vertex_property — Functionvertex_property(g::GraphInterface, v::Integer) -> VGet the property associated with vertex v.
GraphCore.vertices — Methodvertices(g::GraphInterface) -> UnitRange{Int}Return a range over all vertex indices.
Graph Construction
GraphCore.Builders.GraphBuilder — TypeGraphBuilder{V,E,W}Builder for constructing graphs incrementally. Optimized for fast additions during construction phase.
GraphCore.Builders.build_from_function — Methodbuild_from_function(vertex_fn::Function, edge_fn::Function, nv::Int; directed=true)Build a graph by calling vertexfn(i) for each vertex and edgefn(u,v) for potential edges.
GraphCore.add_edge! — Methodadd_edge!(builder::GraphBuilder{Nothing,Nothing,Nothing}, u::Integer, v::Integer) -> Int32Convenience method for basic (unweighted, no properties) graph builders.
GraphCore.add_edge! — Methodadd_edge!(builder::GraphBuilder, u::Integer, v::Integer;
edge_property=nothing, weight=nothing) -> Int32Add an edge with optional properties and weights using keyword arguments. Returns the edge index (1-based).
Examples
# Basic edge
add_edge!(builder, 1, 2)
# Weighted edge
add_edge!(builder, 1, 2; weight=1.5)
# Edge with property
add_edge!(builder, 1, 2; edge_property="connection")
# Both weight and property
add_edge!(builder, 1, 2; edge_property="highway", weight=2.5)GraphCore.add_vertex! — Methodadd_vertex!(builder::GraphBuilder [, prop]) -> Int32Add a vertex with optional property. Returns the vertex index. For non-property builders, prop should be omitted.
GraphCore.build_graph — Methodbuild_graph(builder::GraphBuilder{V,E,W}) -> GraphInterfaceConvert the builder to an optimized graph representation. Automatically chooses the most appropriate graph type among: CoreGraph, WeightedGraph{W}, PropertyGraph{G,V,E}.
GraphCore.build_graph — Methodbuild_graph(builder::GraphBuilder, ::Type{G}) -> GConvert builder to a specific graph type G, where G can be one of: CoreGraph, WeightedGraph{W}, PropertyGraph, AdjGraph, WeightedAdjGraph{W}, PropertyAdjGraph. Note that the builder must be compatible with the target graph type. Also note that the order of the arguments, builder, graph type, is opposite to the usual order.
Conversions
GraphCore.Conversions.from_adjacency_matrix — Methodfrom_adjacency_matrix(::Type{G}, adj_matrix::AbstractMatrix{W}) where {G<:GraphInterface,W} -> GConstruct a graph of appropriate type from an adjacency matrix.
- Non-zero entries in adj_matrix become edges with those weights
- If
directedis not specified, it is inferred from the symmetry of adj_matrix
For undirected graphs, adj_matrix should be symmetric.
GraphCore.Conversions.from_graphs_jl — Methodfrom_graphs_jl(g::Graphs.AbstractGraph; directed::Bool = Graphs.is_directed(g)) -> CoreGraphConvert a graph from the Graphs.jl ecosystem to a CoreGraph.
GraphCore.Conversions.from_weighted_graphs_jl — Methodfrom_weighted_graphs_jl(g::Graphs.AbstractGraph, weights::AbstractVector{W};
directed::Bool = Graphs.is_directed(g)) -> WeightedGraph{W}Convert a weighted graph from the Graphs.jl ecosystem to a WeightedGraph.
GraphCore.Conversions.to_adjacency_matrix — Methodto_adjacency_matrix(g::GraphInterface) -> SparseMatrixCSC{W} where {W}Convert a graph to its adjacency matrix representation.
- For directed graphs, the matrix is not required to be symmetric.
- For undirected graphs, the matrix will be symmetric if the weights are.
- For unweighted graphs, entries are 1 where edges exist.
- For weighted graphs, entries are the edge weights (which are not necessarily symmetric even for undirected graphs).
GraphCore.Conversions.to_graphs_jl — Methodto_graphs_jl(g::GraphInterface) -> Graphs.SimpleGraph or Graphs.SimpleDiGraphConvert a property graph to a Graphs.jl graph (losing properties and weights). Returns SimpleGraph for undirected graphs, SimpleDiGraph for directed graphs.
GraphCore.Conversions.to_weighted_graphs_jl — Methodto_weighted_graphs_jl(g::GraphInterface{V,E,W}) where {V,E,W} ->
SimpleWeightedGraphs.SimpleWeightedGraph or SimpleWeightedGraphs.SimpleWeightedDiGraphConvert a WeightedGraphInterface graph to a weighted SimpleWeightedGraphs.jl graph (preserving weights, losing other properties). Requires SimpleWeightedGraphs.jl package.
Lattices
GraphCore.Lattices.HypercubicLattice — TypeHypercubicLattice{D,T} <: GraphInterfaceA D-dimensional hypercubic lattice graph with side length of type T.
Type Parameters
D::Int: Dimension of the lattice (1D=line, 2D=grid, 3D=cube, etc.)T<:Integer: Type for lattice size/coordinates
Storage
Uses mathematical coordinate mapping instead of explicit edge storage. Memory usage: O(1) regardless of lattice size!
Coordinate System
- Vertices are numbered 1 to prod(sizes)
- Coordinates are 0-indexed: (0,0,...,0) to (size₁-1, size₂-1, ..., sizeD-1)
- Periodic boundary conditions optional
Examples
# 2D grid: 10×10
lattice_2d = HypercubicLattice{2,Int}((10, 10))
# 3D cube: 5×5×5
lattice_3d = HypercubicLattice{3,Int}((5, 5, 5))
# 1D chain: 100 vertices
lattice_1d = HypercubicLattice{1,Int}((100,))GraphCore.Lattices.coord_to_vertex — Methodcoord_to_vertex(g::HypercubicLattice{D,T}, coord::NTuple{D,T}) -> Int32Convert coordinates to vertex index using optimized arithmetic. Specialized for common dimensions with loop unrolling.
GraphCore.Lattices.lattice_dimension — MethodGet the dimensions of the lattice.
GraphCore.Lattices.lattice_distance — Methodlattice_distance(g::HypercubicLattice, u::Integer, v::Integer) -> Float64Compute the Manhattan distance between two vertices on the lattice. Accounts for periodic boundary conditions.
GraphCore.Lattices.lattice_neighbors — Methodlattice_neighbors(g::HypercubicLattice, v::Integer) -> Vector{Int32}Alias for neighbor_indices with better name for lattice context.
GraphCore.Lattices.lattice_size — MethodGet the size tuple of the lattice.
GraphCore.Lattices.vertex_to_coord — Methodvertex_to_coord(g::HypercubicLattice{D,T}, v::Integer) -> NTuple{D,T}Convert vertex index to coordinates using optimized integer arithmetic. Fully inlined and branch-free for maximum performance.
GraphCore.PowerOfTwoLattices.PowerOfTwoLattice — TypePowerOfTwoLattice{D} <: GraphInterfaceUltra-fast D-dimensional hypercubic lattice where all sizes are powers of 2. Uses bit operations for coordinate conversion and neighbor lookup.
Restrictions
- D ≤ 5 (keeps neighbor tuples reasonable)
- All sizes must be powers of 2: 2, 4, 8, 16, 32, 64, 128, ...
- Periodic boundary conditions (makes bit operations clean)
Type Parameters
- D::Int: Dimension (1 ≤ D ≤ 5)
Examples
# 2D: 16×32 grid (2^4 × 2^5)
g2d = P2Grid2D(4, 5) # log₂ sizes
# 3D: 8×8×16 cube (2^3 × 2^3 × 2^4)
g3d = P2Grid3D(3, 3, 4)
# 1D: 64-element chain (2^6)
g1d = P2Chain1D(6)GraphCore.PowerOfTwoLattices.P2Chain1D — Method1D chain: size = 2^log_size
GraphCore.PowerOfTwoLattices.P2Grid2D — Method2D grid: sizes = 2^logwidth × 2^logheight
GraphCore.PowerOfTwoLattices.P2Grid3D — Method3D cube: sizes = 2^logwidth × 2^logheight × 2^log_depth
GraphCore.PowerOfTwoLattices.lattice_dimension — MethodGet lattice dimensions.
GraphCore.PowerOfTwoLattices.lattice_size — MethodGet actual sizes.