th_rust/circuit/
circuit.rs1use na::{DMatrix};
2use crate::gate::Gate;
3
4pub struct Circuit {
5 pub gates: Vec<Box<dyn Gate>>,
6 pub weight: DMatrix<i32>,
7 pub bias: Vec<i32>,
8}
9
10impl Circuit {
11 pub fn new() -> Circuit {
12 Circuit { gates: Vec::new(), weight: DMatrix::<i32>::from_vec(1, 1, vec![0]), bias: Vec::new() }
13 }
14
15 pub fn from_vector(gates: Vec<Box<dyn Gate>>) -> Circuit {
16 Circuit { gates, weight: DMatrix::<i32>::from_vec(1, 1, vec![0]), bias: Vec::new() }
17 }
18
19 pub fn append(&mut self, gate: Box<dyn Gate>) {
20 self.gates.push(gate);
21 }
22
23 pub fn compile(&mut self) {
24 if self.gates.len() == 1 {
26 self.weight = self.gates[0].weight().clone();
27 self.bias = self.gates[0].bias().clone();
28 return;
29 }
30
31 let (max_row, max_col) = self.grid_space();
33 let to_linear = |row: usize, col: usize| -> usize {
34 row * (max_col + 1) + col
35 };
36
37 let mut visited = vec![false; (max_row + 1) * (max_col + 1)];
39 let mut weight: DMatrix<i32> = self.gates[0].weight().clone();
40 let mut bias: Vec<i32> = self.gates[0].bias().clone();
41
42
43 for gate in self.gates.iter() {
45 for pbit in gate.pbits() {
46 let index = to_linear(pbit.coordinates().0, pbit.coordinates().1);
47 let other_weight = gate.weight();
48 let other_bias = gate.bias();
49
50 if visited[index] {
51 (weight, bias) = self.compose_weights_and_bias(index, &weight, &bias, other_weight, other_bias);
52 }
53
54 visited[index] = true;
55 }
56 }
57
58 self.weight = weight;
59 self.bias = bias;
60 }
61
62 fn compose_weights_and_bias(
63 &self,
64 linear_index: usize,
65 weight: &DMatrix<i32>,
66 bias: &Vec<i32>,
67 other_weight: &DMatrix<i32>,
68 other_bias: &Vec<i32>
69 ) -> (DMatrix<i32>, Vec<i32>) {
70 let (other_row, _) = other_weight.shape();
72
73 let additional_columns = other_row - 1;
74
75 let mut new_weight = weight.clone();
76 let mut new_other_weight = other_weight.clone();
77
78 for i in 0..additional_columns {
79 new_weight = new_weight.insert_column(linear_index + i + 1, 0);
80 new_weight = new_weight.insert_row(linear_index + i + 1, 0);
81 new_other_weight = new_other_weight.insert_column(i, 0);
82 new_other_weight = new_other_weight.insert_row(i, 0);
83 }
84
85 new_weight += new_other_weight;
87
88 let mut new_bias = bias.clone();
89 let new_other_bias = other_bias.clone();
90
91 new_bias[linear_index] += new_other_bias[0];
92 for (i, bias_value) in new_other_bias.iter().enumerate() {
93 if i == 0 {
94 continue;
95 }
96
97 new_bias.push(*bias_value);
98 }
99
100 (new_weight, new_bias)
101 }
102
103 fn grid_space(&self) -> (usize, usize) {
104 let mut x = 0;
105 let mut y = 0;
106 for gate in self.gates.iter() {
107 for pbit in gate.pbits().iter() {
108 if pbit.coordinates().0 > x {
109 x = pbit.coordinates().0;
110 }
111 if pbit.coordinates().1 > y {
112 y = pbit.coordinates().1;
113 }
114 }
115 }
116
117 (x, y)
118 }
119}