Edges

Edges (or links) connect vertices in a graph, representing relationships or connections between entities.

Edge Type

Each edge has the following properties:

type(edge_type) :: e
e%id           ! Unique identifier (integer)
e%index(2)     ! [source, target] vertex indices
e%weight       ! Edge weight (real32, default: 1.0)
e%feature(:)   ! Feature vector (real32, allocatable)

Adding Edges

Basic Edges

Connect two vertices:

! Simple undirected edge between vertices 1 and 2
call graph%add_edge(index=[1, 2])

Directed Edges

For directed graphs, use negative indices or the directed parameter:

graph%directed = .true.

! Method 1: Negative target index (from 1 to 2)
call graph%add_edge(index=[1, -2])  ! 1 → 2

! Method 2: Use directed parameter
call graph%add_edge(index=[1, 2], directed=.true.)

The negative index convention allows you to mix directed and undirected edges in the same graph.

Weighted Edges

Add edges with custom weights:

! Edge with weight 2.5
call graph%add_edge(index=[1, 2], weight=2.5)

! Default weight is 1.0
call graph%add_edge(index=[2, 3])  ! weight = 1.0

Edge Features

Edges can have feature vectors:

! Add edge with features
call graph%add_edge(index=[1, 2], weight=1.5, feature=[0.1, 0.2])

Important: Like vertices, the first edge sets the feature dimension for all subsequent edges.

Batch Operations

Connect one vertex to multiple vertices efficiently:

! Connect vertex 1 to vertices 2, 3, 4 (undirected)
call graph%set_edges(1, [2, 3, 4])

! Same but directed (1 → 2, 1 → 3, 1 → 4)
call graph%set_edges(1, [-2, -3, -4])

Accessing Edges

By Index

Access edge properties:

! Get edge endpoints
write(*,*) 'Source:', graph%edge(3)%index(1)
write(*,*) 'Target:', graph%edge(3)%index(2)

! Get weight and features
write(*,*) 'Weight:', graph%edge(3)%weight
write(*,*) 'Features:', graph%edge(3)%feature

Iterating All Edges

Loop through all edges:

do i = 1, graph%num_edges
  write(*,'(A,I0,A,I0,A,I0,A,F6.2)') &
    'Edge ', i, ': ', graph%edge(i)%index(1), &
    ' -> ', graph%edge(i)%index(2), &
    ' weight: ', graph%edge(i)%weight
end do

Modifying Edges

Updating Properties

Modify edge weights and features:

! Update weight
graph%edge(3)%weight = 5.0

! Update features
graph%edge(3)%feature = [0.5, 0.6]

! Update individual feature components
graph%edge(3)%feature(1) = 0.8

Removing Edges

Remove one or more edges:

! Remove single edge
call graph%remove_edges([3])

! Remove multiple edges
call graph%remove_edges([1, 4, 7])

Effects:

  • Updates vertex degrees

  • Updates adjacency matrix

  • Remaining edges are renumbered

Batch Removal

For efficiency when removing many edges, defer adjacency updates:

! Remove many edges without updating adjacency each time
do i = 1, n_to_remove
  call graph%remove_edges([edge_list(i)], update_adjacency=.false.)
end do

! Update adjacency once at the end
call graph%generate_adjacency()

Self-Loops

A self-loop is an edge that connects a vertex to itself.

Adding Self-Loops

! Add to all vertices
call graph%add_self_loops()

! Add to specific vertices
call graph%add_self_loops(indices=[1, 3, 5])

! With custom weight
call graph%add_self_loops(indices=[1, 3, 5], weight=2.0)

Removing Self-Loops

! Remove from all vertices
call graph%remove_self_loops()

! Remove from specific vertices
call graph%remove_self_loops(indices=[2, 4])

Edge Features

Edge features can represent:

  • Relationship strength or type

  • Distance or cost

  • Capacity or flow

  • Temporal information

  • Any numerical property of the connection

The feature size is determined by the first edge added and applies to all edges in the graph.