Skip to content

Commit

Permalink
Initial: Add append methods
Browse files Browse the repository at this point in the history
  • Loading branch information
raynelfss committed Oct 16, 2024
1 parent 631eab5 commit 926ed66
Showing 1 changed file with 218 additions and 0 deletions.
218 changes: 218 additions & 0 deletions crates/circuit/src/dag_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.

use std::cell::RefCell;
use std::hash::{Hash, Hasher};

use ahash::RandomState;
Expand Down Expand Up @@ -6933,6 +6934,223 @@ impl DAGCircuit {
}
}

pub struct DAGCircuitConcat<'a> {
dag: RefCell<&'a mut DAGCircuit>,
last_clbits: Vec<Option<NodeIndex>>,
last_qubits: Vec<Option<NodeIndex>>,
// TODO: Keep track of vars.
}

impl<'a> DAGCircuitConcat<'a> {
pub fn new(dag: &'a mut DAGCircuit) -> Self {
let num_qubits = dag.num_qubits();
let num_clbits = dag.num_clbits();
Self {
dag: dag.into(),
last_qubits: Vec::with_capacity(num_qubits),
last_clbits: Vec::with_capacity(num_clbits),
}
}

pub fn end(self) {
// Re-connects all of the output nodes with their respective last nodes.
todo!()
}

pub fn apply_operation_back(
&self,
op: PackedOperation,
qubits: &[Qubit],
clbits: &[Clbit],
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: Option<ExtraInstructionAttributes>,
#[cfg(feature = "cache_pygates")] py_op: PyObject,
) {
let instruction = self.pack_instruction(
op,
qubits,
clbits,
params,
extra_attrs,
#[cfg(feature = "cache_pygates")]
py_op,
);
todo!()
}

pub fn apply_operation_owned(
&self,
op: PackedOperation,
qubits: Vec<Qubit>,
clbits: Vec<Clbit>,
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: Option<ExtraInstructionAttributes>,
#[cfg(feature = "cache_pygates")] py_op: PyObject,
) {
let instruction = self.pack_instruction_owned(op, qubits, clbits, params, extra_attrs);
todo!()
}

fn push_back(&self, inst: PackedInstruction) {
// let mut dag_mut = self.dag.borrow_mut();
// let op_name = inst.op.name();
// let (all_cbits, vars): (Vec<Clbit>, Option<Vec<PyObject>>) = {
// if dag_mut.may_have_additional_wires(py, &inst) {
// let mut clbits: HashSet<Clbit> =
// HashSet::from_iter(dag_mut.cargs_interner.get(inst.clbits).iter().copied());
// let (additional_clbits, additional_vars) =
// dag_mut.additional_wires(py, inst.op.view(), inst.condition())?;
// for clbit in additional_clbits {
// clbits.insert(clbit);
// }
// (clbits.into_iter().collect(), Some(additional_vars))
// } else {
// (dag_mut.cargs_interner.get(inst.clbits).to_vec(), None)
// }
// };

// // Increment the operation count
// dag_mut.increment_op(op_name);

// // Get the correct qubit indices
// let qubits_id = inst.qubits;

// // Insert op-node to graph.
// let new_node = dag_mut.dag.add_node(NodeType::Operation(inst));

// // Check all the qubits in this instruction.
// for qubit in dag_mut.qargs_interner.get(qubits_id) {
// // Retrieve each qubit's last node
// let qubit_last_node = *qubit_last_nodes.entry(*qubit).or_insert_with(|| {
// // If the qubit is not in the last nodes collection, the edge between the output node and its predecessor.
// // Then, store the predecessor's NodeIndex in the last nodes collection.
// let output_node = dag_mut.qubit_io_map[qubit.0 as usize][1];
// let (edge_id, predecessor_node) = dag_mut
// .dag
// .edges_directed(output_node, Incoming)
// .next()
// .map(|edge| (edge.id(), edge.source()))
// .unwrap();
// dag_mut.dag.remove_edge(edge_id);
// predecessor_node
// });
// qubit_last_nodes
// .entry(*qubit)
// .and_modify(|val| *val = new_node);
// dag_mut.dag
// .add_edge(qubit_last_node, new_node, Wire::Qubit(*qubit));
// }

// // Check all the clbits in this instruction.
// for clbit in all_cbits {
// let clbit_last_node = *clbit_last_nodes.entry(clbit).or_insert_with(|| {
// // If the qubit is not in the last nodes collection, the edge between the output node and its predecessor.
// // Then, store the predecessor's NodeIndex in the last nodes collection.
// let output_node = dag_mut.clbit_io_map[clbit.0 as usize][1];
// let (edge_id, predecessor_node) = self
// .dag
// .edges_directed(output_node, Incoming)
// .next()
// .map(|edge| (edge.id(), edge.source()))
// .unwrap();
// dag_mut.dag.remove_edge(edge_id);
// predecessor_node
// });
// clbit_last_nodes
// .entry(clbit)
// .and_modify(|val| *val = new_node);
// dag_mut.dag
// .add_edge(clbit_last_node, new_node, Wire::Clbit(clbit));
// }

// // If available, check all the vars in this instruction
// for var in vars.iter().flatten() {
// let var_last_node = if let Some(result) = vars_last_nodes.get_item(var)? {
// let node: usize = result.extract()?;
// vars_last_nodes.del_item(var)?;
// NodeIndex::new(node)
// } else {
// // If the var is not in the last nodes collection, the edge between the output node and its predecessor.
// // Then, store the predecessor's NodeIndex in the last nodes collection.
// let output_node = dag_mut.var_output_map.get(py, var).unwrap();
// let (edge_id, predecessor_node) = self
// .dag
// .edges_directed(output_node, Incoming)
// .next()
// .map(|edge| (edge.id(), edge.source()))
// .unwrap();
// dag_mut.dag.remove_edge(edge_id);
// predecessor_node
// };

// // Because `DAGCircuit::additional_wires` can return repeated instances of vars,
// // we need to make sure to skip those to avoid cycles.
// vars_last_nodes.set_item(var, new_node.index())?;
// if var_last_node == new_node {
// continue;
// }
// dag_mut.dag
// .add_edge(var_last_node, new_node, Wire::Var(var.clone_ref(py)));
// }
}

#[inline]
fn pack_instruction(
&self,
op: PackedOperation,
qubits: &[Qubit],
clbits: &[Clbit],
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: Option<ExtraInstructionAttributes>,
#[cfg(feature = "cache_pygates")] py_op: PyObject,
) -> PackedInstruction {
let extra_attrs = extra_attrs.unwrap_or_default();
#[cfg(feature = "cache_pygates")]
let py_op = if let Some(py_op) = py_op {
py_op.into()
} else {
OnceCell::new()
};
PackedInstruction {
op,
qubits: self.dag.borrow_mut().qargs_interner.insert(qubits),
clbits: self.dag.borrow_mut().cargs_interner.insert(clbits),
params: params.map(|x| x.into()),
extra_attrs,
#[cfg(feature = "cache_pygates")]
py_op,
}
}

#[inline]
fn pack_instruction_owned(
&self,
op: PackedOperation,
qubits: Vec<Qubit>,
clbits: Vec<Clbit>,
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: Option<ExtraInstructionAttributes>,
#[cfg(feature = "cache_pygates")] py_op: PyObject,
) -> PackedInstruction {
let extra_attrs = extra_attrs.unwrap_or_default();
#[cfg(feature = "cache_pygates")]
let py_op = if let Some(py_op) = py_op {
py_op.into()
} else {
OnceCell::new()
};
PackedInstruction {
op,
qubits: self.dag.borrow_mut().qargs_interner.insert_owned(qubits),
clbits: self.dag.borrow_mut().cargs_interner.insert_owned(clbits),
params: params.map(|x| x.into()),
extra_attrs,
#[cfg(feature = "cache_pygates")]
py_op,
}
}
}

/// Add to global phase. Global phase can only be Float or ParameterExpression so this
/// does not handle the full possibility of parameter values.
fn add_global_phase(py: Python, phase: &Param, other: &Param) -> PyResult<Param> {
Expand Down

0 comments on commit 926ed66

Please sign in to comment.