Graph Analysis API

Adjacency Matrix

SemanticSpacetime.AdjacencyMatrixType
AdjacencyMatrix

Sparse adjacency representation for an SST graph using Dict-based storage. Maps each node to its set of outgoing neighbours with weights.

SemanticSpacetime.add_edge!Function
add_edge!(adj::AdjacencyMatrix, src::NodePtr, dst::NodePtr, weight::Float64=1.0)

Add a directed edge from src to dst with the given weight.

SemanticSpacetime.build_adjacencyFunction
build_adjacency(sst::SSTConnection; arrows::Vector{ArrowPtr}=ArrowPtr[], chapter::String="") -> AdjacencyMatrix

Build an adjacency matrix from the SST database. If arrows is non-empty, only links using those arrow types are included. If chapter is non-empty, only nodes in matching chapters are included.

build_adjacency(store::MemoryStore; arrows::Vector{ArrowPtr}=ArrowPtr[], chapter::String="") -> AdjacencyMatrix

Build an adjacency matrix from a MemoryStore.

SemanticSpacetime.find_sinksFunction
find_sinks(adj::AdjacencyMatrix) -> Vector{NodePtr}

Find sink nodes — nodes with no outgoing links.

SemanticSpacetime.detect_loopsFunction
detect_loops(adj::AdjacencyMatrix) -> Vector{Vector{NodePtr}}

Find all simple cycles in the directed graph using DFS. Each cycle is returned as a vector of NodePtrs forming the loop.

SemanticSpacetime.eigenvector_centralityFunction
eigenvector_centrality(adj::AdjacencyMatrix; max_iter::Int=100, tol::Float64=1e-6) -> Dict{NodePtr, Float64}

Compute eigenvector centrality via power iteration on the adjacency matrix. The result is normalized so the maximum value is 1.0.

SemanticSpacetime.symmetrizeFunction
symmetrize(adj::AdjacencyMatrix) -> AdjacencyMatrix

Create a symmetric (undirected) version of the adjacency matrix. For each directed edge (u,v) with weight w, the symmetric version has both (u,v) and (v,u) with combined weight.

SemanticSpacetime.graph_summaryFunction
graph_summary(adj::AdjacencyMatrix) -> String

Generate a text summary of graph properties: node count, link count, sources, sinks, and top eigenvector centrality nodes.

Graph Traversal

SemanticSpacetime.adjoint_arrowsFunction
adjoint_arrows(arrowptrs::Vector{ArrowPtr}) -> Vector{ArrowPtr}

Return the inverse of each arrow pointer, deduplicated. Arrows without a registered inverse are silently dropped.

SemanticSpacetime.adjoint_sttypeFunction
adjoint_sttype(sttypes::Vector{Int}) -> Vector{Int}

Return negated and reversed ST types (adjoint in the ST spectrum).

SemanticSpacetime.adjoint_link_pathFunction
adjoint_link_path(path::Vector{Link}) -> Vector{Link}

Reverse a link path and replace each arrow with its inverse. Links whose arrows have no registered inverse are kept with the original arrow.

SemanticSpacetime.wave_frontFunction
wave_front(paths::Vector{Vector{Link}}, num::Int) -> Vector{NodePtr}

Collect the wave front: the last Dst from each path. num is unused but kept for API compatibility with the Go version.

SemanticSpacetime.nodes_overlapFunction
nodes_overlap(left::Vector{NodePtr}, right::Vector{NodePtr}) -> Dict{Int,Vector{Int}}

Find matching NodePtrs between left and right wave fronts. Returns a dict mapping left-index => [right-indices] where left[l] == right[r]. (Indices are 1-based.)

SemanticSpacetime.wave_fronts_overlapFunction
wave_fronts_overlap(store::AbstractSSTStore,
                    left_paths::Vector{Vector{Link}},
                    right_paths::Vector{Vector{Link}},
                    ldepth::Int, rdepth::Int)

Expand wave fronts from left (forward) and right (backward) path sets, find overlapping nodes, and splice paths together.

Returns (solutions::Vector{Vector{Link}}, loops::Vector{Vector{Link}}).

SemanticSpacetime.left_joinFunction
left_join(splice::Vector{Link}, seq::Vector{Link}) -> Vector{Link}

Concatenate two link sequences.

SemanticSpacetime.right_complement_joinFunction
right_complement_join(splice::Vector{Link}, adjoint::Vector{Link}) -> Vector{Link}

Concatenate splice with adjoint, skipping the first element of adjoint (which is the overlap node).

SemanticSpacetime.is_dagFunction
is_dag(seq::Vector{Link}) -> Bool

Check that no NodePtr destination appears more than once in the link sequence.

SemanticSpacetime.together!Function
together!(matroid::Vector{Vector{NodePtr}}, n1::NodePtr, n2::NodePtr)

Group n1 and n2 into the same supernode set within the matroid. If either node already belongs to a set, the other is merged into it. If both belong to different sets, the sets are merged. If neither exists, a new set is created.

SemanticSpacetime.get_constrained_cone_pathsFunction
get_constrained_cone_paths(store::AbstractSSTStore, start::Vector{NodePtr},
                           depth::Int; chapter::String="",
                           context::Vector{String}=String[],
                           arrows::Vector{ArrowPtr}=ArrowPtr[],
                           sttypes::Vector{Int}=Int[],
                           limit::Int=100, forward::Bool=true)

Expand cone from each start node, filtering by chapter, context, arrow types, and ST types. When forward=true (default), follows positive ST channels; when forward=false, follows negative ST channels. Returns (paths, count).

SemanticSpacetime.get_constrained_fwd_linksFunction
get_constrained_fwd_links(store::AbstractSSTStore, start::Vector{NodePtr};
                          chapter::String="", context::Vector{String}=String[],
                          sttypes::Vector{Int}=Int[],
                          arrows::Vector{ArrowPtr}=ArrowPtr[],
                          limit::Int=100)

Get immediate forward links from start nodes matching constraints. Returns Vector{Link}.

SemanticSpacetime.get_paths_and_symmetriesFunction
get_paths_and_symmetries(store::AbstractSSTStore,
                         start_set::Vector{NodePtr},
                         end_set::Vector{NodePtr};
                         chapter::String="",
                         context::Vector{String}=String[],
                         arrows::Vector{ArrowPtr}=ArrowPtr[],
                         sttypes::Vector{Int}=Int[],
                         mindepth::Int=1, maxdepth::Int=10)

Bidirectional search using wave front overlap. Expands forward from startset and backward (adjoint) from endset, splicing at overlap.

Returns (solutions::Vector{Vector{Link}}, loops::Vector{Vector{Link}}).

SemanticSpacetime.get_longest_axial_pathFunction
get_longest_axial_path(store::AbstractSSTStore, nptr::NodePtr,
                       arrowptr::ArrowPtr; limit::Int=100) -> Vector{Link}

Follow a single arrow type from nptr as far as possible, returning the longest chain of links using only that arrow.

SemanticSpacetime.truncate_paths_by_arrowFunction
truncate_paths_by_arrow(path::Vector{Link}, arrow::ArrowPtr)

Truncate path at the first link that does not match arrow. Returns the prefix of matching links.

Node Orbits and Centrality

SemanticSpacetime.get_node_orbitFunction
get_node_orbit(store::AbstractSSTStore, nptr::NodePtr;
               exclude_vector::String="", limit::Int=100)

Compute the orbit of a node — its neighborhood organized by ST type. Returns Vector{Vector{Orbit}} of length ST_TOP, where each inner vector contains Orbit entries for that ST channel.

Uses forward cone expansion to sweep the neighborhood, then assembles satellites by ST type index.

SemanticSpacetime.assemble_satellites_by_sttypeFunction
assemble_satellites_by_sttype(store::AbstractSSTStore, stindex::Int,
                              satellite::Vector{Orbit},
                              sweep::Vector{Vector{Link}};
                              exclude_vector::String="",
                              probe_radius::Int=3,
                              limit::Int=100) -> Vector{Orbit}

From the sweep paths, extract links belonging to the given ST type index and assemble them into Orbit entries with radius information.

SemanticSpacetime.idemp_add_satellite!Function
idemp_add_satellite!(list::Vector{Orbit}, item::Orbit, already::Set{String})

Idempotent add: push item only if its text is not already in the set.

SemanticSpacetime.tally_pathFunction
tally_path(store::AbstractSSTStore, path::Vector{Link},
           between::Dict{String,Int}) -> Dict{String,Int}

Increment the betweenness counter for each node destination along a path. Returns the updated dictionary.

SemanticSpacetime.betweenness_centralityFunction
betweenness_centrality(adj::AdjacencyMatrix) -> Dict{NodePtr, Float64}

Compute betweenness centrality for each node using Brandes' algorithm. Measures how often a node lies on shortest paths between other pairs.

betweenness_centrality(store::AbstractSSTStore,
                       solutions::Vector{Vector{Link}}) -> Vector{String}

Compute betweenness centrality from a set of solution paths. Returns node names sorted by descending frequency of appearance across all paths.

SemanticSpacetime.super_nodes_by_conic_pathFunction
super_nodes_by_conic_path(solutions::Vector{Vector{Link}},
                          maxdepth::Int) -> Vector{Vector{NodePtr}}

Group nodes that appear at the same depth across different solution paths into supernode equivalence classes (matroid).

SemanticSpacetime.super_nodesFunction
super_nodes(store::AbstractSSTStore, solutions::Vector{Vector{Link}},
            maxdepth::Int) -> Vector{String}

Compute supernodes and return their text names. Each supernode group is represented as a string "n1 | n2 | ...".

SemanticSpacetime.get_path_transverse_super_nodesFunction
get_path_transverse_super_nodes(store::AbstractSSTStore,
                                solutions::Vector{Vector{Link}},
                                maxdepth::Int) -> Vector{Vector{NodePtr}}

Find transverse supernodes — nodes that appear across multiple solution paths at any depth.

Coordinates

SemanticSpacetime.relative_orbitFunction
relative_orbit(origin::Coords, radius::Float64, n::Int, max::Int) -> Coords

Place a satellite node at angular position n of max around origin at the given radius. R1 orbits get a -π/6 offset, R2 orbits get +π/6.

SemanticSpacetime.set_orbit_coordsFunction
set_orbit_coords(xyz::Coords, orb::Vector{Vector{Orbit}}) -> Vector{Vector{Orbit}}

Assign OOO (origin) and XYZ (position) coordinates to each Orbit entry. Radius-1 orbits are placed around xyz, radius-2 orbits are sub-orbits anchored to the preceding radius-1 orbit.

SemanticSpacetime.assign_cone_coordinatesFunction
assign_cone_coordinates(cone::Vector{Vector{Link}}, nth::Int, swimlanes::Int) -> Dict{NodePtr,Coords}

Assign coordinates to nodes in a causal cone visualization. Deduplicates nodes, finds the longest path, counts channels per depth step, then delegates to make_coordinate_directory.

SemanticSpacetime.assign_story_coordinatesFunction
assign_story_coordinates(axis::Vector{Link}, nth::Int, swimlanes::Int;
                         limit::Int=100, already::Dict{NodePtr,Bool}=Dict{NodePtr,Bool}()) -> Dict{NodePtr,Coords}

Assign coordinates along a story/sequence axis.

SemanticSpacetime.assign_page_coordinatesFunction
assign_page_coordinates(maplines::Vector{PageMap}) -> Dict{NodePtr,Coords}

Layout notes page-by-page. Axial nodes run along the Z axis; satellite notes orbit around their axial leader.

SemanticSpacetime.assign_fragment_coordinatesFunction
assign_fragment_coordinates(origin::Coords, nth::Int, swimlanes::Int) -> Coords

Assign coordinates for fragments around a context origin on a sphere. Staggers radius for crowded display.

SemanticSpacetime.make_coordinate_directoryFunction
make_coordinate_directory(xchannels::Vector{Float64}, unique::Vector{Vector{NodePtr}},
                          maxlen_tz::Int, nth::Int, swimlanes::Int) -> Dict{NodePtr,Coords}

Core layout function: distribute nodes in a 2D grid. X-axis = swimlane position, Z-axis = time/depth step. Each step allocates horizontal space proportional to node count.

Matrix Operations

SemanticSpacetime.symbol_matrixFunction
symbol_matrix(m::Matrix{Float32}) -> Matrix{String}

Convert a numeric adjacency matrix to a symbolic representation. Non-zero entries become "r*c" (row × column indices), zero entries become "".

SemanticSpacetime.symbolic_multiplyFunction
symbolic_multiply(m1::Matrix{Float32}, m2::Matrix{Float32},
                  s1::Matrix{String}, s2::Matrix{String}) -> (Matrix{Float32}, Matrix{String})

Multiply numeric matrices and compose symbol matrices for path tracing.

SemanticSpacetime.symmetrize_matrixFunction
symmetrize_matrix(m::Matrix{Float32}) -> Matrix{Float32}

Return (m + m') / 2 — but following the Go convention of m[r,c] + m[c,r] (without the division by 2).

SemanticSpacetime.transpose_matrixFunction
transpose_matrix(m::Matrix{Float32}) -> Matrix{Float32}

Transpose a matrix. Wraps Julia's permutedims for API compatibility.

SemanticSpacetime.compute_evcFunction
compute_evc(adj::Matrix{Float32}) -> Vector{Float32}

Eigenvector centrality via power iteration on a dense adjacency matrix. Iterates up to 10 times, normalizing by max value each step.

SemanticSpacetime.find_gradient_field_topFunction
find_gradient_field_top(sadj::Matrix{Float32}, evc::Vector{Float32})
    -> (hilltops::Dict{Int,Vector{Int}}, sources::Vector{Int}, paths::Vector{Vector{Int}})

Find hill tops in the gradient field of eigenvector centrality. Each node follows gradient ascent to a local maximum; nodes are grouped by their hilltop into regions.

SemanticSpacetime.get_hill_topFunction
get_hill_top(index::Int, sadj::Matrix{Float32}, evc::Vector{Float32}) -> (Int, Vector{Int})

Follow gradient ascent from index to local maximum in the eigenvector centrality field. Returns (top_index, path).

PageMap Operations

SemanticSpacetime.get_page_mapFunction
get_page_map(store::MemoryStore; chapter::String="", context::Vector{String}=String[], page::Int=0) -> Vector{PageMap}

Retrieve page map entries matching filters. If chapter is non-empty, filter by case-insensitive substring match. If context is non-empty, filter by context pointer match. page enables pagination (60 per page).

SemanticSpacetime.get_chapters_by_chap_contextFunction
get_chapters_by_chap_context(store::MemoryStore; chapter::String="any",
                              context::Vector{String}=String[], limit::Int=100) -> Dict{String,Vector{String}}

Table of contents: chapters grouped with their contexts.

SemanticSpacetime.split_chaptersFunction
split_chapters(str::AbstractString) -> Vector{String}

Split a chapter string by commas, but only where the comma is not followed by a space (Go convention: "," splits, ", " does not).