Add calibrate agent, link-set command, and dominating-set query stage
calibrate.agent: Haiku-based agent that reads a node and all its neighbors, then assigns appropriate link strengths relative to each other. Designed for high-volume runs across the whole graph. graph link-set: Set strength of an existing link (0.0-1.0). dominating-set query stage: Greedy 3-covering dominating set — finds the minimum set of nodes such that every node in the input is within 1 hop of at least 3 selected nodes. Use with calibrate agent to ensure every link gets assessed from multiple perspectives. Usage: poc-memory query "content ~ 'bcachefs' | dominating-set"
This commit is contained in:
parent
7fc1270d6f
commit
19e181665d
5 changed files with 166 additions and 1 deletions
|
|
@ -157,6 +157,7 @@ pub enum Filter {
|
|||
pub enum Transform {
|
||||
Sort(SortField),
|
||||
Limit(usize),
|
||||
DominatingSet,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -257,6 +258,11 @@ impl Stage {
|
|||
return Ok(Stage::Generator(Generator::All));
|
||||
}
|
||||
|
||||
// Transform: "dominating-set"
|
||||
if s == "dominating-set" {
|
||||
return Ok(Stage::Transform(Transform::DominatingSet));
|
||||
}
|
||||
|
||||
// Try algorithm parse first (bare words, no colon)
|
||||
if !s.contains(':') {
|
||||
if let Ok(algo) = AlgoStage::parse(s) {
|
||||
|
|
@ -348,6 +354,7 @@ impl fmt::Display for Stage {
|
|||
Stage::Filter(filt) => write!(f, "{}", filt),
|
||||
Stage::Transform(Transform::Sort(field)) => write!(f, "sort:{:?}", field),
|
||||
Stage::Transform(Transform::Limit(n)) => write!(f, "limit:{}", n),
|
||||
Stage::Transform(Transform::DominatingSet) => write!(f, "dominating-set"),
|
||||
Stage::Algorithm(a) => write!(f, "{}", a.algo),
|
||||
}
|
||||
}
|
||||
|
|
@ -508,7 +515,7 @@ fn eval_filter(filt: &Filter, key: &str, store: &Store, now: i64) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn run_transform(
|
||||
pub fn run_transform(
|
||||
xform: &Transform,
|
||||
mut items: Vec<(String, f64)>,
|
||||
store: &Store,
|
||||
|
|
@ -564,6 +571,56 @@ fn run_transform(
|
|||
items.truncate(*n);
|
||||
items
|
||||
}
|
||||
Transform::DominatingSet => {
|
||||
// Greedy 3-covering dominating set: pick the node that covers
|
||||
// the most under-covered neighbors, repeat until every node
|
||||
// has been covered 3 times (by 3 different selected seeds).
|
||||
use std::collections::HashMap as HMap;
|
||||
let input_keys: std::collections::HashSet<String> = items.iter().map(|(k, _)| k.clone()).collect();
|
||||
let mut cover_count: HMap<String, usize> = items.iter().map(|(k, _)| (k.clone(), 0)).collect();
|
||||
let mut selected: Vec<(String, f64)> = Vec::new();
|
||||
let mut selected_set: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
const REQUIRED_COVERAGE: usize = 3;
|
||||
|
||||
loop {
|
||||
// Find the unselected node that covers the most under-covered nodes
|
||||
let best = items.iter()
|
||||
.filter(|(k, _)| !selected_set.contains(k.as_str()))
|
||||
.map(|(k, _)| {
|
||||
let mut value = 0usize;
|
||||
// Count self if under-covered
|
||||
if cover_count.get(k).copied().unwrap_or(0) < REQUIRED_COVERAGE {
|
||||
value += 1;
|
||||
}
|
||||
for (nbr, _) in graph.neighbors(k) {
|
||||
if input_keys.contains(nbr.as_str()) {
|
||||
if cover_count.get(nbr.as_str()).copied().unwrap_or(0) < REQUIRED_COVERAGE {
|
||||
value += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
(k.clone(), value)
|
||||
})
|
||||
.max_by_key(|(_, v)| *v);
|
||||
|
||||
let Some((key, value)) = best else { break };
|
||||
if value == 0 { break; } // everything covered 3x
|
||||
|
||||
// Mark coverage
|
||||
*cover_count.entry(key.clone()).or_default() += 1;
|
||||
for (nbr, _) in graph.neighbors(&key) {
|
||||
if let Some(c) = cover_count.get_mut(nbr.as_str()) {
|
||||
*c += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let score = items.iter().find(|(k, _)| k == &key).map(|(_, s)| *s).unwrap_or(1.0);
|
||||
selected.push((key.clone(), score));
|
||||
selected_set.insert(key);
|
||||
}
|
||||
|
||||
selected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue