Getting Started with SemanticSpacetime.jl
Simon Frost
Introduction
SemanticSpacetime.jl is a Julia implementation of the Semantic Spacetime (SST) knowledge graph framework, based on Mark Burgess’s Promise Theory and spacetime process semantics. Unlike traditional knowledge graphs that store flat triples, SST classifies every relationship along a spacetime spectrum — from spatial proximity (NEAR) through causal ordering (LEADSTO) and containment (CONTAINS) to expressive properties (EXPRESS).
This vignette walks through the basics: creating an in-memory graph, adding nodes and edges, and querying the store.
Loading the Package
using SemanticSpacetimeCreating a MemoryStore
The MemoryStore is an in-memory graph that requires no database. It is ideal for experimentation, testing, and lightweight applications.
store = MemoryStore()
println("Nodes: $(node_count(store)), Links: $(link_count(store))")Nodes: 0, Links: 0Registering Arrow Types
Before adding edges, we must register the arrow types (relationship kinds) we plan to use. Each arrow belongs to one of the four SST types and has a direction ("+" for forward, "-" for inverse).
# Reset any previously registered arrows
SemanticSpacetime.reset_arrows!()
SemanticSpacetime.reset_contexts!()
# LEADSTO arrows — causal / temporal ordering
fwd = insert_arrow!("LEADSTO", "then", "leads to next", "+")
bwd = insert_arrow!("LEADSTO", "prev", "preceded by", "-")
insert_inverse_arrow!(fwd, bwd)
# CONTAINS arrows — membership / part-of
has = insert_arrow!("CONTAINS", "has", "contains element", "+")
partof = insert_arrow!("CONTAINS", "part-of", "is part of", "-")
insert_inverse_arrow!(has, partof)
# EXPRESS arrows — properties / attributes
note_fwd = insert_arrow!("EXPRESS", "note", "has note", "+")
# NEAR arrows — similarity / proximity
like = insert_arrow!("NEAR", "like", "is similar to", "+")
println("Arrows registered successfully.")Arrows registered successfully.Adding Nodes
Nodes are created with mem_vertex!, which takes a store, a name (text label), and a chapter (section/topic grouping). Node creation is idempotent — adding the same name and chapter twice returns the existing node.
# Create nodes about a simple process
boil = mem_vertex!(store, "boil water", "cooking")
add_tea = mem_vertex!(store, "add tea leaves", "cooking")
steep = mem_vertex!(store, "steep for 5 minutes", "cooking")
pour = mem_vertex!(store, "pour into cup", "cooking")
println("Created $(node_count(store)) nodes")
println("Node: '$(boil.s)' in chapter '$(boil.chap)'")Created 4 nodes
Node: 'boil water' in chapter 'cooking'Each node has a NodePtr — a two-part identifier consisting of a text-size class and an index. This bucketing by text length is a core SST design for efficient storage.
println("NodePtr for 'boil water': class=$(boil.nptr.class), index=$(boil.nptr.cptr)")NodePtr for 'boil water': class=2, index=1Adding Edges
Edges connect nodes with a named arrow type. The arrow name must match a registered arrow.
# Build a causal chain: boil → add tea → steep → pour
mem_edge!(store, boil, "then", add_tea)
mem_edge!(store, add_tea, "then", steep)
mem_edge!(store, steep, "then", pour)
println("Created $(link_count(store)) links")Created 6 linksEdges can also carry context (topic tags) and weight (numerical strength):
# Add a note with context
tip = mem_vertex!(store, "use freshly drawn water", "cooking")
mem_edge!(store, boil, "note", tip, ["tips", "quality"])
# Add a similarity link with custom weight
kettle = mem_vertex!(store, "heat water in kettle", "cooking")
mem_edge!(store, boil, "like", kettle, String[], 0.9f0)
println("Graph now has $(node_count(store)) nodes and $(link_count(store)) links")Graph now has 6 nodes and 8 linksQuerying the Store
Look up nodes by name or search by text substring:
# Find nodes by exact name
results = mem_get_nodes_by_name(store, "boil water")
for n in results
println("Found: '$(n.s)' in chapter '$(n.chap)'")
endFound: 'boil water' in chapter 'cooking'# Search nodes by text substring
matches = mem_search_text(store, "tea")
for n in matches
println("Match: '$(n.s)'")
endMatch: 'add tea leaves'# List all chapters
chapters = mem_get_chapters(store)
println("Chapters: ", join(chapters, ", "))Chapters: cookingRetrieving a Node by Pointer
If you have a NodePtr, you can retrieve the full node:
node = mem_get_node(store, boil.nptr)
if node !== nothing
println("Retrieved: '$(node.s)'")
endRetrieved: 'boil water'Inspecting Node Structure
Every node has an incidence list organized into 7 channels corresponding to the signed STType spectrum (-EXPRESS to +EXPRESS). Let’s inspect the links from our “boil water” node:
for (i, links) in enumerate(boil.incidence)
if !isempty(links)
println("Channel $i: $(length(links)) link(s)")
for link in links
dst = mem_get_node(store, link.dst)
arrow = get_arrow_by_ptr(link.arr)
if dst !== nothing
println(" → '$(dst.s)' via '$(arrow.short)'")
end
end
end
endChannel 4: 1 link(s)
→ 'heat water in kettle' via 'like'
Channel 5: 1 link(s)
→ 'add tea leaves' via 'then'
Channel 7: 1 link(s)
→ 'use freshly drawn water' via 'note'What’s Next?
This was a quick introduction to SemanticSpacetime.jl. Subsequent vignettes cover:
- SST Types — the spacetime type system (NEAR, LEADSTO, CONTAINS, EXPRESS)
- Building Graphs — modelling a real domain with chapters and contexts
- N4L Language — the Notes for Learning markup for declarative graph construction
- Search & Discovery — finding nodes and navigating the graph
- Graph Analysis — centrality, sources, sinks, and loops
- Paths & Cones — causal reasoning with forward/backward cones
- RDF Integration — interoperating with the Semantic Web