use crate::{gate::Gate, gate_type::GateType}; #[derive(Debug, Clone)] pub struct Circuit { pub input_bits: Vec, // Input wires pub gates: Vec, // All gates } impl Circuit { pub fn eval(self) -> bool { let mut evaluated_gates = vec!(); for gate in self.gates { let result = gate.eval(&self.input_bits, &evaluated_gates); evaluated_gates.push(result); } match evaluated_gates.pop() { Some(result) => result, None => panic!("Bruh moment") } } /* This method should create a circuit that outputs 1 if the first number A (encoded in the first n bits) is greater than the second number B (encoded in the next n bits) . */ pub fn compare_n_bit_numbers(input_bits: Vec, n: usize) -> Self { if input_bits.len() < 2*n { panic!("Expected input_bits to be of at least length {}, but it was {}", 2*n, input_bits.len()) } /* base case n=1: 1-bit: A B | A > B ----------- 0 0 | 0 0 1 | 0 1 0 | 1 1 1 | 0 n+1 case: 2-bit: A1 A0 B1 B0 | A > B | (A1 > B1) || ((A1 == B1) && (A0 > B0)) ----------------------|------------------------------------ 0 0 0 0 | 0 | 0 0 0 0 1 | 0 | 0 0 0 1 0 | 0 | 0 0 0 1 1 | 0 | 0 0 1 0 0 | 1 | 1 0 1 0 1 | 0 | 0 0 1 1 0 | 0 | 0 0 1 1 1 | 1 | 1 1 0 0 0 | 1 | 1 1 0 0 1 | 1 | 1 1 0 1 0 | 0 | 0 1 0 1 1 | 0 | 0 1 1 0 0 | 1 | 1 1 1 0 1 | 1 | 1 1 1 1 0 | 1 | 1 1 1 1 1 | 0 | 0 The inductive pattern should become apparent now. For illustration here's the case for n=4, which should show the recursive characteristics of the formula. (A3 > B3) || ((A3 == B3) && (A2 > B2)) || ((A3 == B3) && (A2 == B2) && (A1 > B1)) || ((A3 == B3) && (A2 == B2) && (A1 == B1)) && (A0 > B0)) */ let gates = create_n_bit_comparator_gates(n); return Circuit { input_bits, gates } } } fn create_n_bit_comparator_gates(n: usize) -> Vec{ let mut indices: Vec = vec![0; n]; let mut all_gates: Vec = vec!(); let mut and_gate_indices: Vec = vec!(); rec_n_bit_comperator_gates(0, n, &mut all_gates, &mut and_gate_indices, &mut indices, ); // the OR spanning all ANDs let or_gate = Gate::new( GateType::Or, and_gate_indices, vec!()); all_gates.push(or_gate); return all_gates; } fn rec_n_bit_comperator_gates(curr: usize, max: usize, all_gates: &mut Vec, and_gate_incides: &mut Vec, indices: &mut Vec){ // Incrementing gate index let a_curr_gt_b_curr_gate_index = all_gates.len(); // Gate(A_current > B_current) let a_curr_gt_b_curr_gate = Gate::new(GateType::Bigger, vec!(), vec!(curr, curr+max)); // A_current>B_current //print!(" ( ({}) ", format!("{} > {}", format!("A{}", max-1-curr), format!("B{}", max-1-curr))); all_gates.push(a_curr_gt_b_curr_gate); let mut this_recursion_gate_indices: Vec = vec!(a_curr_gt_b_curr_gate_index); for i in 0..curr { let key = max-1-i; if i == curr-1 { // Gate(A_current > B_current) let a_i_eq_b_i_gate = Gate::new(GateType::Equal, vec!(), vec!(i, i+max)); let a_curr_gt_b_curr_gate_index = all_gates.len(); indices[key] = a_curr_gt_b_curr_gate_index; all_gates.push(a_i_eq_b_i_gate); } let eq_gate_index = indices[key]; //print!("&& ({}) ", format!("{} = {}", format!("A{}", key), format!("B{}", key))); // Index of this equality gate this_recursion_gate_indices.push(eq_gate_index); } let and_curr_index = all_gates.len(); let and_curr_gate = Gate::new(GateType::And, this_recursion_gate_indices, vec!()); all_gates.push(and_curr_gate); and_gate_incides.push(and_curr_index); if curr+1 == max { //println!(")"); return; } //println!(") ||"); return rec_n_bit_comperator_gates(curr+1, max, all_gates, and_gate_incides, indices); }