1use rlx_ir::infer::GraphExt;
18use rlx_ir::{DType, Graph, NodeId, Shape};
19
20#[derive(Debug, Clone)]
22pub struct ParamSlot {
23 pub name: String,
24 pub shape: Vec<usize>,
25 pub param: NodeId,
26 pub grad: Option<NodeId>,
27}
28
29impl ParamSlot {
30 pub fn numel(&self) -> usize {
31 self.shape.iter().product()
32 }
33}
34
35pub fn mlp_trunk(
37 g: &mut Graph,
38 x: NodeId,
39 in_dim: usize,
40 hidden: &[usize],
41 prefix: &str,
42 params: &mut Vec<ParamSlot>,
43) -> (NodeId, usize) {
44 let f = DType::F32;
45 let mut h = x;
46 let mut in_d = in_dim;
47
48 for (li, &hd) in hidden.iter().enumerate() {
49 let w_name = format!("{prefix}_w{li}");
50 let b_name = format!("{prefix}_b{li}");
51 let w = g.param(&w_name, Shape::new(&[in_d, hd], f));
52 let b = g.param(&b_name, Shape::new(&[hd], f));
53 params.push(ParamSlot {
54 name: w_name,
55 shape: vec![in_d, hd],
56 param: w,
57 grad: None,
58 });
59 params.push(ParamSlot {
60 name: b_name,
61 shape: vec![hd],
62 param: b,
63 grad: None,
64 });
65 h = g.mm(h, w);
66 h = g.add(h, b);
67 h = g.tanh(h);
68 in_d = hd;
69 }
70 (h, in_d)
71}
72
73pub fn mlp_layers(
75 g: &mut Graph,
76 x: NodeId,
77 in_dim: usize,
78 hidden: &[usize],
79 out_dim: usize,
80 prefix: &str,
81 params: &mut Vec<ParamSlot>,
82) -> NodeId {
83 let f = DType::F32;
84 let (h, in_d) = mlp_trunk(g, x, in_dim, hidden, prefix, params);
85 let w_name = format!("{prefix}_w_out");
86 let b_name = format!("{prefix}_b_out");
87 let w = g.param(&w_name, Shape::new(&[in_d, out_dim], f));
88 let b = g.param(&b_name, Shape::new(&[out_dim], f));
89 params.push(ParamSlot {
90 name: w_name,
91 shape: vec![in_d, out_dim],
92 param: w,
93 grad: None,
94 });
95 params.push(ParamSlot {
96 name: b_name,
97 shape: vec![out_dim],
98 param: b,
99 grad: None,
100 });
101 let out = g.mm(h, w);
102 g.add(out, b)
103}
104
105pub fn flow_map_jump(
106 g: &mut Graph,
107 a_r: NodeId,
108 u: NodeId,
109 r: NodeId,
110 t: NodeId,
111 batch: usize,
112) -> NodeId {
113 let dt = g.sub(t, r);
114 let dt_col = g.reshape_(dt, vec![batch as i64, 1]);
115 let scaled = g.mul(u, dt_col);
116 g.add(a_r, scaled)
117}
118
119pub fn mse_mean(g: &mut Graph, pred: NodeId, target: NodeId) -> NodeId {
120 let diff = g.sub(pred, target);
121 let sq = g.mul(diff, diff);
122 let rank = g.shape(sq).rank();
123 let axes: Vec<usize> = (0..rank).collect();
124 g.mean(sq, axes, false)
125}
126
127pub fn concat_features(g: &mut Graph, parts: Vec<NodeId>) -> NodeId {
128 g.concat_(parts, 1)
129}
130
131pub fn init_mat(
132 w: &mut crate::graph::actor::WeightStore,
133 name: &str,
134 rows: usize,
135 cols: usize,
136 seed: &mut u64,
137) {
138 let scale = (2.0 / (rows + cols) as f32).sqrt();
139 let n = rows * cols;
140 let mut v = vec![0.0f32; n];
141 for x in &mut v {
142 *seed = crate::buffer::rand_like(*seed);
143 let u = (*seed >> 11) as f32 / (1u32 << 21) as f32;
144 *seed = crate::buffer::rand_like(*seed);
145 let n2 = (*seed >> 11) as f32 / (1u32 << 21) as f32;
146 *x = (u * 2.0 * std::f32::consts::PI * n2).sin() * scale;
147 }
148 w.0.insert(name.to_string(), v);
149}
150
151pub fn init_vec(w: &mut crate::graph::actor::WeightStore, name: &str, n: usize, seed: &mut u64) {
152 let mut v = vec![0.0f32; n];
153 for x in &mut v {
154 *seed = crate::buffer::rand_like(*seed);
155 *x = 0.01 * ((*seed >> 11) as f32 / (1u32 << 21) as f32 - 0.5);
156 }
157 w.0.insert(name.to_string(), v);
158}