frontend/layouter/nodes/
circuit_outputs.rs

1//! The nodes that represent circuit outputs in the circuit DAG
2
3use itertools::{repeat_n, Itertools};
4use shared_types::Field;
5
6use crate::layouter::builder::CircuitMap;
7use remainder::{
8    circuit_layout::CircuitLocation, mle::MleIndex, output_layer::OutputLayerDescription,
9};
10
11use super::{CircuitNode, NodeId};
12
13use anyhow::Result;
14
15#[derive(Debug, Clone)]
16/// the node that represents the output of a circuit
17pub struct OutputNode {
18    id: NodeId,
19    source: NodeId,
20    _zero: bool,
21}
22
23impl CircuitNode for OutputNode {
24    fn id(&self) -> NodeId {
25        self.id
26    }
27
28    fn sources(&self) -> Vec<NodeId> {
29        vec![self.source]
30    }
31
32    fn get_num_vars(&self) -> usize {
33        todo!()
34    }
35}
36
37impl OutputNode {
38    /// Creates a new OutputNode from a source w/ some data
39    pub fn new(source: &impl CircuitNode) -> Self {
40        Self {
41            id: NodeId::new(),
42            source: source.id(),
43            _zero: false,
44        }
45    }
46
47    /// Creates a new ZeroMleRef, which constrains the source to equal a Zero Mle
48    pub fn new_zero(source: &dyn CircuitNode) -> Self {
49        Self {
50            id: NodeId::new(),
51            source: source.id(),
52            _zero: true,
53        }
54    }
55
56    /// Using the [CircuitMap], create a [OutputLayerDescription] which
57    /// represents the circuit description of an [OutputNode].
58    pub fn generate_circuit_description<F: Field>(
59        &self,
60        circuit_map: &mut CircuitMap,
61    ) -> Result<OutputLayerDescription<F>> {
62        let (circuit_location, num_vars) =
63            circuit_map.get_location_num_vars_from_node_id(&self.source)?;
64
65        let CircuitLocation {
66            prefix_bits,
67            layer_id,
68        } = circuit_location;
69
70        let total_indices = prefix_bits
71            .iter()
72            .map(|bit| MleIndex::Fixed(*bit))
73            .chain(repeat_n(MleIndex::Free, *num_vars))
74            .collect_vec();
75
76        let out = OutputLayerDescription::new_zero(*layer_id, &total_indices);
77
78        Ok(out)
79    }
80}