def dagdependency_to_circuit(dagdependency): """Build a ``QuantumCircuit`` object from a ``DAGDependency``. Args: dagdependency (DAGDependency): the input dag. Return: QuantumCircuit: the circuit representing the input dag dependency. """ name = dagdependency.name or None circuit = QuantumCircuit(dagdependency.qubits, dagdependency.clbits, *dagdependency.qregs.values(), *dagdependency.cregs.values(), name=name) circuit.metadata = dagdependency.metadata circuit.calibrations = dagdependency.calibrations for node in dagdependency.get_nodes(): # Get arguments for classical control (if any) inst = node.op.copy() inst.condition = node.condition circuit._append(inst, node.qargs, node.cargs) return circuit
def dagdependency_to_circuit(dagdependency): """Build a ``QuantumCircuit`` object from a ``DAGDependency``. Args: dagdependency (DAGDependency): the input dag. Return: QuantumCircuit: the circuit representing the input dag dependency. """ name = dagdependency.name or None circuit = QuantumCircuit( dagdependency.qubits, dagdependency.clbits, *dagdependency.qregs.values(), *dagdependency.cregs.values(), name=name, ) circuit.metadata = dagdependency.metadata circuit.calibrations = dagdependency.calibrations for node in dagdependency.get_nodes(): circuit._append( CircuitInstruction(node.op.copy(), node.qargs, node.cargs)) return circuit
def _define(self): """Calculate a subcircuit that implements this unitary.""" if self.num_qubits == 1: q = QuantumRegister(1, "q") qc = QuantumCircuit(q, name=self.name) theta, phi, lam, global_phase = _DECOMPOSER1Q.angles_and_phase(self.to_matrix()) qc._append(U3Gate(theta, phi, lam), [q[0]], []) qc.global_phase = global_phase self.definition = qc elif self.num_qubits == 2: self.definition = two_qubit_cnot_decompose(self.to_matrix()) else: self.definition = qs_decomposition(self.to_matrix())
def dag_to_circuit(dag): """Build a ``QuantumCircuit`` object from a ``DAGCircuit``. Args: dag (DAGCircuit): the input dag. Return: QuantumCircuit: the circuit representing the input dag. Example: .. jupyter-execute:: from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.dagcircuit import DAGCircuit from qiskit.converters import circuit_to_dag from qiskit.circuit.library.standard_gates import CHGate, U2Gate, CXGate from qiskit.converters import dag_to_circuit %matplotlib inline q = QuantumRegister(3, 'q') c = ClassicalRegister(3, 'c') circ = QuantumCircuit(q, c) circ.h(q[0]) circ.cx(q[0], q[1]) circ.measure(q[0], c[0]) circ.rz(0.5, q[1]).c_if(c, 2) dag = circuit_to_dag(circ) circuit = dag_to_circuit(dag) circuit.draw() """ name = dag.name or None circuit = QuantumCircuit( dag.qubits, dag.clbits, *dag.qregs.values(), *dag.cregs.values(), name=name, global_phase=dag.global_phase, ) circuit.metadata = dag.metadata circuit.calibrations = dag.calibrations for node in dag.topological_op_nodes(): circuit._append( CircuitInstruction(node.op.copy(), node.qargs, node.cargs)) circuit.duration = dag.duration circuit.unit = dag.unit return circuit
def _define(self): """Calculate a subcircuit that implements this unitary.""" if self.num_qubits == 1: q = QuantumRegister(1, "q") qc = QuantumCircuit(q, name=self.name) theta, phi, lam = _DECOMPOSER1Q.angles(self.to_matrix()) qc._append(U3Gate(theta, phi, lam), [q[0]], []) self.definition = qc elif self.num_qubits == 2: self.definition = two_qubit_cnot_decompose(self.to_matrix()) else: q = QuantumRegister(self.num_qubits, "q") qc = QuantumCircuit(q, name=self.name) qc.append(isometry.Isometry(self.to_matrix(), 0, 0), qargs=q[:]) self.definition = qc
def inverse(self): """Return the inverse. Note that the resulting gate has an empty ``params`` property. """ inverse_gate = Gate( name=self.name + "_dg", num_qubits=self.num_qubits, params=[]) # removing the params because arrays are deprecated definition = QuantumCircuit(*self.definition.qregs) for inst in reversed(self._definition): definition._append( inst.replace(operation=inst.operation.inverse())) inverse_gate.definition = definition return inverse_gate
def dag_to_circuit(dag): """Build a ``QuantumCircuit`` object from a ``DAGCircuit``. Args: dag (DAGCircuit): the input dag. Return: QuantumCircuit: the circuit representing the input dag. Example: .. jupyter-execute:: from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.dagcircuit import DAGCircuit from qiskit.converters import circuit_to_dag from qiskit.circuit.library.standard_gates import CHGate, U2Gate, CXGate from qiskit.converters import dag_to_circuit %matplotlib inline q = QuantumRegister(3, 'q') c = ClassicalRegister(3, 'c') circ = QuantumCircuit(q, c) circ.h(q[0]) circ.cx(q[0], q[1]) circ.measure(q[0], c[0]) circ.rz(0.5, q[1]).c_if(c, 2) dag = circuit_to_dag(circ) circuit = dag_to_circuit(dag) circuit.draw() """ name = dag.name or None circuit = QuantumCircuit(*dag.qregs.values(), *dag.cregs.values(), name=name) for node in dag.topological_op_nodes(): # Get arguments for classical control (if any) inst = node.op.copy() inst.condition = node.condition circuit._append(inst, node.qargs, node.cargs) return circuit
def _unify_circuit_resources_rebuild( # pylint: disable=invalid-name # (it's too long?!) true_body: QuantumCircuit, false_body: QuantumCircuit ) -> Tuple[QuantumCircuit, QuantumCircuit]: """ Ensure that ``true_body`` and ``false_body`` have all the same qubits and clbits, and that they are defined in the same order. The order is important for binding when the bodies are used in the 3-tuple :obj:`.Instruction` context. This function will always rebuild the two parameters into new :obj:`.QuantumCircuit` instances. """ qubits = list(set(true_body.qubits).union(false_body.qubits)) clbits = list(set(true_body.clbits).union(false_body.clbits)) # We use the inner `_append` method because everything is already resolved. true_out = QuantumCircuit(qubits, clbits, *true_body.qregs, *true_body.cregs) for data in true_body.data: true_out._append(*data) false_out = QuantumCircuit(qubits, clbits, *false_body.qregs, *false_body.cregs) for data in false_body.data: false_out._append(*data) return _unify_circuit_registers(true_out, false_out)
def run(self, dag): """Run the Optimize1qGatesDecomposition pass on `dag`. Args: dag (DAGCircuit): the DAG to be optimized. Returns: DAGCircuit: the optimized DAG. """ if not self.basis: LOG.info("Skipping pass because no basis is set") return dag runs = dag.collect_1q_runs() for run in runs: # Don't try to optimize a single 1q gate if len(run) <= 1: params = run[0].op.params # Remove single identity gates if len(params) > 0 and np.array_equal(run[0].op.to_matrix(), np.eye(2)): dag.remove_op_node(run[0]) continue new_circs = [] q = QuantumRegister(1, "q") qc = QuantumCircuit(1) for gate in run: qc._append(gate.op, [q[0]], []) operator = Operator(qc) for decomposer in self.basis: new_circs.append(decomposer(operator)) if new_circs: new_circ = min(new_circs, key=lambda circ: circ.depth()) if qc.depth() > new_circ.depth(): new_dag = circuit_to_dag(new_circ) dag.substitute_node_with_dag(run[0], new_dag) # Delete the other nodes in the run for current_node in run[1:]: dag.remove_op_node(current_node) return dag
def _gate_rules_to_qiskit_circuit(self, node, params): """From a gate definition in qasm, to a QuantumCircuit format.""" rules = [] qreg = QuantumRegister(node['n_bits']) bit_args = {node['bits'][i]: q for i, q in enumerate(qreg)} exp_args = {node['args'][i]: Real(q) for i, q in enumerate(params)} for child_op in node['body'].children: qparams = [] eparams = [] for param_list in child_op.children[1:]: if param_list.type == 'id_list': qparams = [bit_args[param.name] for param in param_list.children] elif param_list.type == 'expression_list': for param in param_list.children: eparams.append(param.sym(nested_scope=[exp_args])) op = self._create_op(child_op.name, params=eparams) rules.append((op, qparams, [])) circ = QuantumCircuit(qreg) for instr, qargs, cargs in rules: circ._append(instr, qargs, cargs) return circ
def dag_to_circuit(dag): """Build a ``QuantumCircuit`` object from a ``DAGCircuit``. Args: dag (DAGCircuit): the input dag. Return: QuantumCircuit: the circuit representing the input dag. """ name = dag.name or None circuit = QuantumCircuit(*dag.qregs.values(), *dag.cregs.values(), name=name) for node in dag.topological_op_nodes(): # Get arguments for classical control (if any) inst = node.op.copy() inst.condition = node.condition circuit._append(inst, node.qargs, node.cargs) return circuit
def repeat(self, n): """Creates an instruction with `gate` repeated `n` amount of times. Args: n (int): Number of times to repeat the instruction Returns: qiskit.circuit.Instruction: Containing the definition. Raises: CircuitError: If n < 1. """ if int(n) != n or n < 1: raise CircuitError( "Repeat can only be called with strictly positive integer.") n = int(n) instruction = self._return_repeat(n) qargs = [] if self.num_qubits == 0 else QuantumRegister( self.num_qubits, "q") cargs = [] if self.num_clbits == 0 else ClassicalRegister( self.num_clbits, "c") if instruction.definition is None: # pylint: disable=cyclic-import from qiskit.circuit import QuantumCircuit, CircuitInstruction qc = QuantumCircuit() if qargs: qc.add_register(qargs) if cargs: qc.add_register(cargs) circuit_instruction = CircuitInstruction(self, qargs, cargs) for _ in [None] * n: qc._append(circuit_instruction) instruction.definition = qc return instruction
def _define(self): """Allow unrolling to a Kraus instruction""" q = QuantumRegister(self.num_qubits, "q") qc = QuantumCircuit(q, name=self.name) qc._append(Kraus(self._quantum_error).to_instruction(), q, []) self.definition = qc
def build( self, all_qubits: FrozenSet[Qubit], all_clbits: FrozenSet[Clbit] ) -> "qiskit.circuit.QuantumCircuit": """Build this scoped block into a complete :obj:`.QuantumCircuit` instance. This will build a circuit which contains all of the necessary qubits and clbits and no others. The ``qubits`` and ``clbits`` arguments should be sets that contains all the resources in the outer scope; these will be passed down to inner placeholder instructions, so they can apply themselves across the whole scope should they need to. The resulting :obj:`.QuantumCircuit` will be defined over a (nonstrict) subset of these resources. This is used to let ``break`` and ``continue`` span all resources, even if they are nested within several :obj:`.IfElsePlaceholder` objects, without requiring :obj:`.IfElsePlaceholder` objects *without* any ``break`` or ``continue`` statements to be full-width. Args: all_qubits: all the qubits in the containing scope of this block. The block may expand to use some or all of these qubits, but will never gain qubits that are not in this set. all_clbits: all the clbits in the containing scope of this block. The block may expand to use some or all of these clbits, but will never gain clbits that are not in this set. Returns: A circuit containing concrete versions of all the instructions that were in the scope, and using the minimal set of resources necessary to support them, within the enclosing scope. """ from qiskit.circuit import QuantumCircuit # There's actually no real problem with building a scope more than once. This flag is more # so _other_ operations, which aren't safe can be forbidden, such as mutating instructions # that may have been built into other objects. self._built = True potential_qubits = all_qubits - self.qubits potential_clbits = all_clbits - self.clbits # We start off by only giving the QuantumCircuit the qubits we _know_ it will need, and add # more later as needed. out = QuantumCircuit(list(self.qubits), list(self.clbits), *self.registers) for instruction in self.instructions: if isinstance(instruction.operation, InstructionPlaceholder): operation, resources = instruction.operation.concrete_instruction( all_qubits, all_clbits ) qubits = tuple(resources.qubits) clbits = tuple(resources.clbits) instruction = CircuitInstruction(operation, qubits, clbits) # We want to avoid iterating over the tuples unnecessarily if there's no chance # we'll need to add bits to the circuit. if potential_qubits and qubits: add_qubits = potential_qubits.intersection(qubits) if add_qubits: potential_qubits -= add_qubits out.add_bits(add_qubits) if potential_clbits and clbits: add_clbits = potential_clbits.intersection(clbits) if add_clbits: potential_clbits -= add_clbits out.add_bits(add_clbits) for register in itertools.chain(resources.qregs, resources.cregs): if register not in self.registers: # As of 2021-12-09, QuantumCircuit doesn't have an efficient way to check if # a register is already present, so we use our own tracking. self.add_register(register) out.add_register(register) if getattr(instruction.operation, "condition", None) is not None: for register in condition_registers(instruction.operation.condition): if register not in self.registers: self.add_register(register) out.add_register(register) # We already did the broadcasting and checking when the first call to # QuantumCircuit.append happened (which the user wrote), and added the instruction into # this scope. We just need to finish the job now. out._append(instruction) return out
def _define(self): """Calculate a subcircuit that implements this unitary.""" q = QuantumRegister(self.num_qubits, 'q') qc = QuantumCircuit(q, name=self.name) qc._append(UnitaryGate(self.to_matrix()), q[:], []) self.definition = qc