crate::ix!();
pub fn build_random_skeleton(
seed: u64,
total_nodes: usize,
p_aggregator: f32,
p_dispatch: f32,
) -> Skeleton {
let mut rng = StdRng::seed_from_u64(seed);
let root_kind = if p_aggregator >= p_dispatch && p_aggregator >= 0.3 {
NodeKind::Aggregate
} else if p_dispatch >= 0.3 {
NodeKind::Dispatch
} else {
NodeKind::LeafHolder
};
let root = SkeletonNodeBuilder::default()
.id(0)
.name("rootRand") .original_key("rootRand") .build(root_kind)
.unwrap();
let mut nodes = vec![root];
for i in 1..(total_nodes as u16) {
let r: f32 = rng.r#gen::<f32>(); let kind = if r < p_aggregator {
NodeKind::Aggregate
} else if r < p_aggregator + p_dispatch {
NodeKind::Dispatch
} else {
NodeKind::LeafHolder
};
let node = SkeletonNodeBuilder::default()
.id(i)
.name(format!("node_{}", i)) .original_key(format!("node_{}", i))
.build(kind)
.unwrap();
nodes.push(node);
}
let max_depth = 10;
let mut levels: Vec<Vec<u16>> = vec![vec![0]]; let mut current_depth = 1u8;
let mut next_node_idx = 1u16;
while current_depth < max_depth && next_node_idx < total_nodes as u16 {
let pick_count = rng.gen_range(1..=5).min((total_nodes as u16) - next_node_idx);
if pick_count == 0 { break; }
let mut this_level = Vec::new();
for _ in 0..pick_count {
this_level.push(next_node_idx);
next_node_idx += 1;
if next_node_idx >= total_nodes as u16 {
break;
}
}
levels.push(this_level);
current_depth += 1;
}
for d in 0..(levels.len().saturating_sub(1)) {
let parent_ids = &levels[d];
let child_ids = &levels[d+1];
for &pid in parent_ids {
let mut chosen = vec![];
for &cid in child_ids {
let prob: f64 = rng.r#gen::<f64>(); if prob < 0.3 {
chosen.push(cid);
}
}
if let Some(node_ref) = nodes.iter_mut().find(|n| n.id() == pid) {
match node_ref {
SkeletonNode::Aggregate { child_ids, .. } => {
*child_ids = chosen;
},
SkeletonNode::Dispatch { child_ids, .. } => {
*child_ids = chosen;
},
SkeletonNode::LeafHolder { .. } => { }
}
}
}
}
SkeletonBuilder::default()
.nodes(nodes)
.root_id(Some(0))
.build()
.unwrap()
}