213 lines
6.7 KiB
Rust
213 lines
6.7 KiB
Rust
//! Core domain trait and types for cross-domain transfer learning.
|
|
//!
|
|
//! A domain defines a problem space with:
|
|
//! - A task generator (produces training instances)
|
|
//! - An evaluator (scores solutions on [0.0, 1.0])
|
|
//! - Embedding extraction (maps solutions into a shared representation space)
|
|
//!
|
|
//! True IQ growth appears when a kernel trained on Domain 1 improves Domain 2
|
|
//! faster than Domain 2 alone. That is generalization.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use std::fmt;
|
|
|
|
/// Unique identifier for a domain.
|
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct DomainId(pub String);
|
|
|
|
impl fmt::Display for DomainId {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
|
|
/// A single task instance within a domain.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Task {
|
|
/// Unique task identifier.
|
|
pub id: String,
|
|
/// Domain this task belongs to.
|
|
pub domain_id: DomainId,
|
|
/// Difficulty level [0.0, 1.0].
|
|
pub difficulty: f32,
|
|
/// Structured task specification (domain-specific JSON).
|
|
pub spec: serde_json::Value,
|
|
/// Optional constraints the solution must satisfy.
|
|
pub constraints: Vec<String>,
|
|
}
|
|
|
|
/// A candidate solution to a domain task.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Solution {
|
|
/// The task this solves.
|
|
pub task_id: String,
|
|
/// Raw solution content (e.g., Rust source, plan steps, tool calls).
|
|
pub content: String,
|
|
/// Structured solution data (domain-specific).
|
|
pub data: serde_json::Value,
|
|
}
|
|
|
|
/// Evaluation result for a solution.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Evaluation {
|
|
/// Overall score [0.0, 1.0] where 1.0 is perfect.
|
|
pub score: f32,
|
|
/// Correctness: does it produce the right answer?
|
|
pub correctness: f32,
|
|
/// Efficiency: resource usage relative to optimal.
|
|
pub efficiency: f32,
|
|
/// Elegance: structural quality, idiomatic patterns.
|
|
pub elegance: f32,
|
|
/// Per-constraint pass/fail results.
|
|
pub constraint_results: Vec<bool>,
|
|
/// Diagnostic notes from the evaluator.
|
|
pub notes: Vec<String>,
|
|
}
|
|
|
|
impl Evaluation {
|
|
/// Create a zero-score evaluation (failure).
|
|
pub fn zero(notes: Vec<String>) -> Self {
|
|
Self {
|
|
score: 0.0,
|
|
correctness: 0.0,
|
|
efficiency: 0.0,
|
|
elegance: 0.0,
|
|
constraint_results: Vec::new(),
|
|
notes,
|
|
}
|
|
}
|
|
|
|
/// Compute composite score from weighted sub-scores.
|
|
pub fn composite(correctness: f32, efficiency: f32, elegance: f32) -> Self {
|
|
let score = 0.6 * correctness + 0.25 * efficiency + 0.15 * elegance;
|
|
Self {
|
|
score: score.clamp(0.0, 1.0),
|
|
correctness,
|
|
efficiency,
|
|
elegance,
|
|
constraint_results: Vec::new(),
|
|
notes: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Embedding vector for cross-domain representation.
|
|
/// Solutions from different domains are projected into a shared space
|
|
/// so that transfer learning can identify structural similarities.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct DomainEmbedding {
|
|
/// The embedding vector.
|
|
pub vector: Vec<f32>,
|
|
/// Which domain produced this embedding.
|
|
pub domain_id: DomainId,
|
|
/// Dimensionality.
|
|
pub dim: usize,
|
|
}
|
|
|
|
impl DomainEmbedding {
|
|
/// Create a new embedding.
|
|
pub fn new(vector: Vec<f32>, domain_id: DomainId) -> Self {
|
|
let dim = vector.len();
|
|
Self {
|
|
vector,
|
|
domain_id,
|
|
dim,
|
|
}
|
|
}
|
|
|
|
/// Cosine similarity with another embedding.
|
|
pub fn cosine_similarity(&self, other: &DomainEmbedding) -> f32 {
|
|
assert_eq!(self.dim, other.dim, "Embedding dimensions must match");
|
|
|
|
let mut dot = 0.0f32;
|
|
let mut norm_a = 0.0f32;
|
|
let mut norm_b = 0.0f32;
|
|
|
|
for i in 0..self.dim {
|
|
dot += self.vector[i] * other.vector[i];
|
|
norm_a += self.vector[i] * self.vector[i];
|
|
norm_b += other.vector[i] * other.vector[i];
|
|
}
|
|
|
|
let denom = (norm_a.sqrt() * norm_b.sqrt()).max(1e-10);
|
|
dot / denom
|
|
}
|
|
}
|
|
|
|
/// Core trait that every domain must implement.
|
|
///
|
|
/// Domains are problem spaces: Rust program synthesis, structured planning,
|
|
/// tool orchestration, etc. Each domain knows how to generate tasks,
|
|
/// evaluate solutions, and embed solutions into a shared representation space.
|
|
pub trait Domain: Send + Sync {
|
|
/// Unique identifier for this domain.
|
|
fn id(&self) -> &DomainId;
|
|
|
|
/// Human-readable name.
|
|
fn name(&self) -> &str;
|
|
|
|
/// Generate a batch of tasks at the given difficulty level.
|
|
///
|
|
/// # Arguments
|
|
/// * `count` - Number of tasks to generate
|
|
/// * `difficulty` - Target difficulty [0.0, 1.0]
|
|
fn generate_tasks(&self, count: usize, difficulty: f32) -> Vec<Task>;
|
|
|
|
/// Evaluate a solution against its task.
|
|
fn evaluate(&self, task: &Task, solution: &Solution) -> Evaluation;
|
|
|
|
/// Project a solution into the shared embedding space.
|
|
/// This enables cross-domain transfer by finding structural similarities
|
|
/// between solutions across different problem domains.
|
|
fn embed(&self, solution: &Solution) -> DomainEmbedding;
|
|
|
|
/// Embedding dimensionality for this domain.
|
|
fn embedding_dim(&self) -> usize;
|
|
|
|
/// Generate a reference (optimal or near-optimal) solution for a task.
|
|
/// Used for computing efficiency ratios and as training signal.
|
|
fn reference_solution(&self, task: &Task) -> Option<Solution>;
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_domain_id_display() {
|
|
let id = DomainId("rust_synthesis".to_string());
|
|
assert_eq!(format!("{}", id), "rust_synthesis");
|
|
}
|
|
|
|
#[test]
|
|
fn test_evaluation_zero() {
|
|
let eval = Evaluation::zero(vec!["compile error".to_string()]);
|
|
assert_eq!(eval.score, 0.0);
|
|
assert_eq!(eval.notes.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_evaluation_composite() {
|
|
let eval = Evaluation::composite(1.0, 0.8, 0.6);
|
|
// 0.6*1.0 + 0.25*0.8 + 0.15*0.6 = 0.6 + 0.2 + 0.09 = 0.89
|
|
assert!((eval.score - 0.89).abs() < 1e-4);
|
|
}
|
|
|
|
#[test]
|
|
fn test_embedding_cosine_similarity() {
|
|
let id = DomainId("test".to_string());
|
|
let a = DomainEmbedding::new(vec![1.0, 0.0, 0.0], id.clone());
|
|
let b = DomainEmbedding::new(vec![1.0, 0.0, 0.0], id.clone());
|
|
assert!((a.cosine_similarity(&b) - 1.0).abs() < 1e-6);
|
|
|
|
let c = DomainEmbedding::new(vec![0.0, 1.0, 0.0], id);
|
|
assert!(a.cosine_similarity(&c).abs() < 1e-6);
|
|
}
|
|
|
|
#[test]
|
|
fn test_evaluation_clamp() {
|
|
let eval = Evaluation::composite(1.0, 1.0, 1.0);
|
|
assert!(eval.score <= 1.0);
|
|
}
|
|
}
|