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 |