API Reference

Complete reference for all public interfaces, models, and services in the RichLearning namespace. The library targets .NET 10 with nullable reference types enabled.

Abstractions

IGraphMemory

Core interface for the topological graph store. Implemented by LiteDbGraphMemory and Neo4jGraphMemory. Extends IAsyncDisposable.

namespace RichLearning.Abstractions;

public interface IGraphMemory : IAsyncDisposable
{
    // Schema
    Task InitialiseSchemaAsync();

    // Node Operations
    Task UpsertLandmarkAsync(StateLandmark landmark);
    Task<StateLandmark?> GetLandmarkAsync(string id);
    Task<IReadOnlyList<StateLandmark>> GetAllLandmarksAsync();
    Task<(StateLandmark Landmark, double Distance)?>
        NearestNeighbourAsync(double[] embedding, IStateEncoder encoder);

    // Edge Operations
    Task UpsertTransitionAsync(StateTransition transition);
    Task<IReadOnlyList<StateTransition>>
        GetOutgoingTransitionsAsync(string landmarkId);

    // Graph Queries
    Task<IReadOnlyList<string>> ShortestPathAsync(
        string fromId, string toId);
    Task<IReadOnlyList<string>> DetectCycleInTrajectoryAsync(
        IReadOnlyList<string> recentIds);
    Task<IReadOnlyList<StateLandmark>> GetFrontierLandmarksAsync(
        int topK = 5);
    Task<IReadOnlyList<StateTransition>> PrioritisedSampleAsync(
        int batchSize, long currentTimestep);

    // Graph Maintenance
    Task AssignClustersAsync(int rounds = 5);
    Task<(int Landmarks, int Transitions)> GetGraphStatsAsync();
}

IStateEncoder

Converts raw state observations into fixed-length vector embeddings for nearest-neighbour distance computation.

namespace RichLearning.Abstractions;

public interface IStateEncoder
{
    int EmbeddingDimension { get; }
    double[] Encode(double[] rawState);

    // Default: pattern-match object → double[]
    double[] Encode(object rawState);

    // Default: cosine distance
    double Distance(double[] a, double[] b);
}

Exploration Strategies

Four injectable strategy interfaces for customising exploration behaviour:

// Score frontier landmarks for exploration priority
public interface IFrontierScorer
{
    double Score(double noveltyScore, int visitCount, int outDegree);
}

// Decide if an observation warrants a new landmark
public interface INoveltyGate
{
    bool ShouldCreateLandmark(double distanceToNearest);
}

// Compute replay buffer priority
public interface IPrioritySampler
{
    double ComputePriority(
        double tdError, int transitionCount, long staleness);
}

// Escape from detected trajectory loops
public interface ILoopEscapeStrategy
{
    Task<SubgoalDirective?> SelectEscapeTargetAsync(
        IReadOnlyList<string> cycleNodeIds,
        IReadOnlyList<StateLandmark> frontiers,
        IGraphMemory memory,
        string currentLandmarkId);
}

Models

StateLandmark

Sealed record — represents a graph node (mapped state).

namespace RichLearning.Models;

public sealed record StateLandmark
{
    public required string Id { get; init; }
    public required double[] Embedding { get; init; }
    public int VisitCount { get; set; }
    public double ValueEstimate { get; set; }
    public double NoveltyScore { get; set; } = 1.0;
    public double UncertaintyScore { get; set; } = 1.0;
    public int ClusterId { get; set; }
    public int HierarchyLevel { get; set; }
    public IReadOnlyList<string> ChildNodeIds { get; init; }
    public long LastVisitedTimestep { get; set; }
    public long CreatedTimestep { get; init; }
    public Dictionary<int, int> ActionCounts { get; init; }

    // Computed
    public IReadOnlyDictionary<int, double> GetPolicyDistribution();
    public double PolicyEntropy { get; }  // Shannon entropy

    // Episodic memory
    public List<EpisodicTrace> EpisodicTraces { get; init; }
    public const int MaxEpisodicTraces = 10;
}

StateTransition

Sealed record — represents a directed graph edge between two landmarks.

namespace RichLearning.Models;

public sealed record StateTransition
{
    public required string SourceId { get; init; }
    public required string TargetId { get; init; }
    public required int Action { get; init; }
    public Dictionary<int, int> ActionCounts { get; init; }
    public double Reward { get; set; }
    public double RewardVariance { get; set; }
    public int TransitionCount { get; set; } = 1;
    public double SuccessRate { get; set; } = 1.0;
    public double Confidence { get; set; } = 0.5;
    public int TemporalDistance { get; set; } = 1;
    public double TdError { get; set; }
    public long LastTrainedTimestep { get; set; }
    public bool IsMacroEdge { get; init; }
    public IReadOnlyList<string> MacroPath { get; init; }
}

SubgoalDirective

Sealed record — navigation target issued by the Cartographer.

public sealed record SubgoalDirective
{
    public required string TargetLandmarkId { get; init; }
    public string Reason { get; init; } = string.Empty;
    public IReadOnlyList<string> PlannedPath { get; init; }
}

MapSnapshot

Sealed record — point-in-time statistics of the full graph.

public sealed record MapSnapshot
{
    public int TotalLandmarks { get; init; }
    public int TotalTransitions { get; init; }
    public double MeanVisitCount { get; init; }
    public double MeanNoveltyScore { get; init; }
    public int ClusterCount { get; init; }
    public IReadOnlyDictionary<int, ClusterStats> Clusters { get; init; }
    public IReadOnlyList<StateLandmark> FrontierNodes { get; init; }
    public IReadOnlyList<StateLandmark> BottleneckNodes { get; init; }
    public IReadOnlyList<StateLandmark> StaleNodes { get; init; }
    public long Timestep { get; init; }
}

Planning

Cartographer

Sealed class — mid-level planner that reads/writes the topological graph.

namespace RichLearning.Planning;

public sealed class Cartographer
{
    // Constructor
    public Cartographer(
        IGraphMemory memory,
        IStateEncoder encoder,
        ILogger<Cartographer> logger);

    // Tuneable properties
    public double NoveltyThreshold { get; set; } = 0.3;
    public double ValueEmaAlpha { get; set; } = 0.1;
    public double NoveltyDecayRate { get; set; } = 0.05;
    public int TrajectoryWindowSize { get; set; } = 20;

    // Observe a raw state → returns landmark ID
    public Task<string> ObserveStateAsync(
        double[] rawState, double reward = 0.0);

    // Record a transition between landmarks
    public Task RecordTransitionAsync(
        string fromId, string toId, int action,
        double reward, int primitiveSteps, bool success);

    // Detect loops and return escape subgoal
    public Task<SubgoalDirective?> DetectAndBreakLoopAsync();

    // Select next exploration/exploitation target
    public Task<SubgoalDirective?> SelectNextSubgoalAsync(
        string currentLandmarkId);

    // Get prioritised replay batch
    public Task<IReadOnlyList<StateTransition>> GetReplayBatchAsync(
        int batchSize = 32);

    // Human-readable map summary
    public Task<string> GetMapSummaryAsync();
}

Memory Implementations

LiteDbGraphMemory

Embedded single-file backend. No external server needed. Uses in-process BFS for path queries and label propagation for cluster assignment.

namespace RichLearning.Memory;

public sealed class LiteDbGraphMemory : IGraphMemory
{
    public LiteDbGraphMemory(
        string dbPath,
        ILogger<LiteDbGraphMemory> logger);
}

Neo4jGraphMemory

Server-based backend using Neo4j.Driver 6.0. Leverages native Cypher for path finding, cycle detection, and cluster statistics. Adds extra analytical methods not in the base interface:

namespace RichLearning.Memory;

public sealed class Neo4jGraphMemory : IGraphMemory
{
    public Neo4jGraphMemory(
        string uri, string user, string password,
        ILogger<Neo4jGraphMemory> logger,
        string database = "neo4j");

    // Neo4j-only extensions
    public Task<IReadOnlyList<StateLandmark>>
        GetStaleLandmarksAsync(long staleThreshold, int topK = 10);

    public Task<IReadOnlyList<StateLandmark>>
        GetBottleneckLandmarksAsync(int topK = 5);

    public Task<IReadOnlyDictionary<int, ClusterStats>>
        GetClusterStatsAsync();
}

Package Dependencies

Package Version Purpose
LiteDB 5.0.21 Embedded NoSQL database
Neo4j.Driver 6.0.0 Official Neo4j .NET driver
Microsoft.Extensions.Logging 10.0.2 Structured logging
Microsoft.Extensions.Logging.Console 10.0.2 Console log output