Exemplo n.º 1
0
 def _define(self):
     diag_circuit = self._dec_diag()
     gate = diag_circuit.to_instruction()
     q = QuantumRegister(self.num_qubits)
     diag_circuit = QuantumCircuit(q)
     diag_circuit.append(gate, q[:])
     self.definition = diag_circuit
Exemplo n.º 2
0
 def _define(self):
     mcg_up_diag_circuit, _ = self._dec_mcg_up_diag()
     gate = mcg_up_diag_circuit.to_instruction()
     q = QuantumRegister(self.num_qubits)
     mcg_up_diag_circuit = QuantumCircuit(q)
     mcg_up_diag_circuit.append(gate, q[:])
     self.definition = mcg_up_diag_circuit
Exemplo n.º 3
0
 def _dec_mcg_up_diag(self):
     """
     Call to create a circuit with gates that implement the MCG up to a diagonal gate.
     Remark: The qubits the gate acts on are ordered in the following way:
         q=[q_target,q_controls,q_ancilla_zero,q_ancilla_dirty]
     """
     diag = np.ones(2**(self.num_controls + 1)).tolist()
     q = QuantumRegister(self.num_qubits)
     circuit = QuantumCircuit(q)
     (q_target, q_controls, q_ancillas_zero,
      q_ancillas_dirty) = self._define_qubit_role(q)
     # ToDo: Keep this threshold updated such that the lowest gate count is achieved:
     # ToDo: we implement the MCG with a UCGate up to diagonal if the number of controls is
     # ToDo: smaller than the threshold.
     threshold = float("inf")
     if self.num_controls < threshold:
         # Implement the MCG as a UCGate (up to diagonal)
         gate_list = [np.eye(2, 2) for i in range(2**self.num_controls)]
         gate_list[-1] = self.params[0]
         ucg = UCGate(gate_list, up_to_diagonal=True)
         circuit.append(ucg, [q_target] + q_controls)
         diag = ucg._get_diagonal()
         # else:
         # ToDo: Use the best decomposition for MCGs up to diagonal gates here
         # ToDo: (with all available ancillas)
     return circuit, diag
Exemplo n.º 4
0
 def _dec_single_qubit_unitary(self):
     """
     Call to create a circuit with gates that implement the single qubit unitary u.
     Returns: QuantumCircuit: circuit for implementing u
              (up to a diagonal if up_to_diagonal=True)
     """
     diag = [1., 1.]
     q = QuantumRegister(self.num_qubits)
     circuit = QuantumCircuit(q)
     # First, we find the rotation angles (where we can ignore the global phase)
     (a, b, c, _) = self._zyz_dec()
     # Add the gates to o the circuit
     is_identity = True
     if abs(a) > _EPS:
         circuit.rz(a, q[0])
         is_identity = False
     if abs(b) > _EPS:
         circuit.ry(b, q[0])
         is_identity = False
     if abs(c) > _EPS:
         if self.up_to_diagonal:
             diag = [np.exp(-1j * c / 2.), np.exp(1j * c / 2.)]
         else:
             circuit.rz(c, q[0])
             is_identity = False
     if is_identity:
         circuit.iden(q[0])
     return circuit, diag
Exemplo n.º 5
0
 def _define(self):
     squ_circuit, _ = self._dec_single_qubit_unitary()
     gate = squ_circuit.to_instruction()
     q = QuantumRegister(self.num_qubits)
     squ_circuit = QuantumCircuit(q)
     squ_circuit.append(gate, q[:])
     self.definition = squ_circuit.data
Exemplo n.º 6
0
 def _define(self):
     ucr_circuit = self._dec_ucrot()
     gate = ucr_circuit.to_instruction()
     q = QuantumRegister(self.num_qubits)
     ucr_circuit = QuantumCircuit(q)
     ucr_circuit.append(gate, q[:])
     self.definition = ucr_circuit
Exemplo n.º 7
0
 def _dec_ucrot(self):
     """
     finds a decomposition of a UC rotation gate into elementary gates
     (C-NOTs and single-qubit rotations).
     """
     q = QuantumRegister(self.num_qubits)
     circuit = QuantumCircuit(q)
     q_target = q[0]
     q_controls = q[1:]
     if not q_controls:  # equivalent to: if len(q_controls) == 0
         if self.rot_axes == "X":
             if np.abs(self.params[0]) > _EPS:
                 circuit.rx(self.params[0], q_target)
         if self.rot_axes == "Y":
             if np.abs(self.params[0]) > _EPS:
                 circuit.ry(self.params[0], q_target)
         if self.rot_axes == "Z":
             if np.abs(self.params[0]) > _EPS:
                 circuit.rz(self.params[0], q_target)
     else:
         # First, we find the rotation angles of the single-qubit rotations acting
         #  on the target qubit
         angles = self.params.copy()
         _dec_uc_rotations(angles, 0, len(angles), False)
         # Now, it is easy to place the C-NOT gates to get back the full decomposition.s
         for (i, angle) in enumerate(angles):
             if self.rot_axes == "X":
                 if np.abs(angle) > _EPS:
                     circuit.rx(angle, q_target)
             if self.rot_axes == "Y":
                 if np.abs(angle) > _EPS:
                     circuit.ry(angle, q_target)
             if self.rot_axes == "Z":
                 if np.abs(angle) > _EPS:
                     circuit.rz(angle, q_target)
             # Determine the index of the qubit we want to control the C-NOT gate.
             # Note that it corresponds
             # to the number of trailing zeros in the binary representaiton of i+1
             if not i == len(angles) - 1:
                 binary_rep = np.binary_repr(i + 1)
                 q_contr_index = len(binary_rep) - len(
                     binary_rep.rstrip('0'))
             else:
                 # Handle special case:
                 q_contr_index = len(q_controls) - 1
             # For X rotations, we have to additionally place some Ry gates around the
             # C-NOT gates. They change the basis of the NOT operation, such that the
             # decomposition of for uniformly controlled X rotations works correctly by symmetry
             # with the decomposition of uniformly controlled Z or Y rotations
             if self.rot_axes == "X":
                 circuit.ry(np.pi / 2, q_target)
             circuit.cx(q_controls[q_contr_index], q_target)
             if self.rot_axes == "X":
                 circuit.ry(-np.pi / 2, q_target)
     return circuit
Exemplo n.º 8
0
 def _define(self):
     ucr_circuit = self._dec_ucrot()
     gate_num = len(ucr_circuit.data)
     gate = ucr_circuit.to_instruction()
     q = QuantumRegister(self.num_qubits)
     ucr_circuit = QuantumCircuit(q)
     if gate_num == 0:
         # ToDo: if we would not add the identity here, this would lead to troubles
         # ToDo: simulating the circuit afterwards.
         #  this should probably be fixed in the bahaviour of QuantumCircuit.
         ucr_circuit.iden(q[0])
     else:
         ucr_circuit.append(gate, q[:])
     self.definition = ucr_circuit.data
Exemplo n.º 9
0
def _compose_dag(dag_list):
    """Compose each dag and return new multitask dag"""

    """FIXME 下記と同様
    """
    name_list = []
    #################
    qubit_counter = 0
    clbit_counter = 0
    composed_multidag = DAGCircuit()
    for i, dag in enumerate(dag_list):
        num_qubits = dag.num_qubits()
        num_clbits = dag.num_clbits()
        """FIXME
        Problem:
            register_name: register nameを定義すると、outputの `new_dag` に対して `dag_to_circuit()`
            を実行した時、
            qiskit.circuit.exceptions.CircuitError: 'register name "定義した名前" already exists'
            が発生するため、任意のレジスター名をつけることができない

        Code:
            reg_name_tmp = dag.qubits[0].register.name
            register_name = reg_name_tmp if (reg_name_tmp not in name_list) and (
                not reg_name_tmp == 'q') else None
            name_list.append(register_name)
        """
        ############################################################
        reg_name_tmp = dag.qubits[0].register.name
        register_name = reg_name_tmp if (reg_name_tmp not in name_list) and (not reg_name_tmp == 'q') else None
        name_list.append(register_name)
        ############################################################

        qr = QuantumRegister(size=num_qubits, name=register_name)
        composed_multidag.add_qreg(qr)
        qubits = composed_multidag.qubits[qubit_counter : qubit_counter + num_qubits]

        if num_clbits > 0: 
            cr = ClassicalRegister(size=num_clbits, name=None)
            composed_multidag.add_creg(cr)
            clbits = composed_multidag.clbits[clbit_counter : clbit_counter + num_clbits]

            composed_multidag.compose(dag, qubits=qubits, clbits=clbits)
        else: 
            composed_multidag.compose(dag, qubits=qubits)

        qubit_counter += num_qubits
        clbit_counter += num_clbits
    return composed_multidag
Exemplo n.º 10
0
 def _dec_diag(self):
     """
     Call to create a circuit implementing the diagonal gate.
     """
     q = QuantumRegister(self.num_qubits)
     circuit = QuantumCircuit(q)
     # Since the diagonal is a unitary, all its entries have absolute value one and the diagonal
     # is fully specified by the phases of its entries
     diag_phases = [cmath.phase(z) for z in self.params]
     n = len(self.params)
     while n >= 2:
         angles_rz = []
         for i in range(0, n, 2):
             diag_phases[i // 2], rz_angle = _extract_rz(diag_phases[i], diag_phases[i + 1])
             angles_rz.append(rz_angle)
         num_act_qubits = int(np.log2(n))
         contr_qubits = q[self.num_qubits - num_act_qubits + 1:self.num_qubits]
         target_qubit = q[self.num_qubits - num_act_qubits]
         circuit.ucrz(angles_rz, contr_qubits, target_qubit)
         n //= 2
     return circuit