def _circuit_zsx(theta, phi, lam, phase, simplify=True, atol=DEFAULT_ATOL): # Shift theta and phi so decomposition is # RZ(phi+pi).SX.RZ(theta+pi).SX.RZ(lam) theta = _mod2pi(theta + np.pi) phi = _mod2pi(phi + np.pi) circuit = QuantumCircuit(1, global_phase=phase - np.pi / 2) # Check for decomposition into minimimal number required SX gates if simplify and np.isclose(abs(theta), np.pi, atol=atol): if not np.isclose(_mod2pi(abs(lam + phi + theta)), [0., 2 * np.pi], atol=atol).any(): circuit.append(RZGate(_mod2pi(lam + phi + theta)), [0]) circuit.global_phase += 0.5 * _mod2pi(lam + phi + theta) circuit.global_phase += np.pi / 2 elif simplify and np.isclose(abs(theta), [np.pi / 2, 3 * np.pi / 2], atol=atol).any(): if not np.isclose(_mod2pi(abs(lam + theta)), [0., 2 * np.pi], atol=atol).any(): circuit.append(RZGate(_mod2pi(lam + theta)), [0]) circuit.global_phase += 0.5 * _mod2pi(lam + theta) circuit.append(SXGate(), [0]) if not np.isclose(_mod2pi(abs(phi + theta)), [0., 2 * np.pi], atol=atol).any(): circuit.append(RZGate(_mod2pi(phi + theta)), [0]) circuit.global_phase += 0.5 * _mod2pi(phi + theta) if np.isclose(theta, [-np.pi / 2, 3 * np.pi / 2], atol=atol).any(): circuit.global_phase += np.pi / 2 else: if not np.isclose(abs(lam), [0., 2 * np.pi], atol=atol).any(): circuit.append(RZGate(lam), [0]) circuit.global_phase += 0.5 * lam circuit.append(SXGate(), [0]) if not np.isclose(abs(theta), [0., 2 * np.pi], atol=atol).any(): circuit.append(RZGate(theta), [0]) circuit.global_phase += 0.5 * theta circuit.append(SXGate(), [0]) if not np.isclose(abs(phi), [0., 2 * np.pi], atol=atol).any(): circuit.append(RZGate(phi), [0]) circuit.global_phase += 0.5 * phi return circuit
def template_nct_6a_4(): """ Returns: QuantumCircuit: template as a quantum circuit. """ qc = QuantumCircuit(3) qc.cx(1, 2) qc.ccx(0, 2, 1) qc.cx(1, 2) qc.cx(2, 1) qc.ccx(0, 1, 2) qc.cx(2, 1) return qc
def _define(self): """Define the MCX gate using a V-chain of CX gates.""" # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(self.num_qubits, name='q') qc = QuantumCircuit(q, name=self.name) q_controls = q[:self.num_ctrl_qubits] q_target = q[self.num_ctrl_qubits] q_ancillas = q[self.num_ctrl_qubits + 1:] definition = [] if self._dirty_ancillas: i = self.num_ctrl_qubits - 3 ancilla_pre_rule = [ (U2Gate(0, numpy.pi), [q_target], []), (CXGate(), [q_target, q_ancillas[i]], []), (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_target, q_ancillas[i]], []), (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), ] for inst in ancilla_pre_rule: definition.append(inst) for j in reversed(range(2, self.num_ctrl_qubits - 1)): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i - 1], q_ancillas[i]], [])) i -= 1 definition.append( (RCCXGate(), [q_controls[0], q_controls[1], q_ancillas[0]], [])) i = 0 for j in range(2, self.num_ctrl_qubits - 1): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i], q_ancillas[i + 1]], [])) i += 1 if self._dirty_ancillas: ancilla_post_rule = [ (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_target, q_ancillas[i]], []), (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_target, q_ancillas[i]], []), (U2Gate(0, numpy.pi), [q_target], []), ] for inst in ancilla_post_rule: definition.append(inst) else: definition.append( (CCXGate(), [q_controls[-1], q_ancillas[i], q_target], [])) for j in reversed(range(2, self.num_ctrl_qubits - 1)): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i - 1], q_ancillas[i]], [])) i -= 1 definition.append( (RCCXGate(), [q_controls[0], q_controls[1], q_ancillas[i]], [])) if self._dirty_ancillas: for i, j in enumerate(list(range(2, self.num_ctrl_qubits - 1))): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i], q_ancillas[i + 1]], [])) for instr, qargs, cargs in definition: qc._append(instr, qargs, cargs) self.definition = qc
def template_9d_1(): """ Returns: QuantumCircuit: template as a quantum circuit. """ qc = QuantumCircuit(2) qc.cx(0, 1) qc.x(1) qc.cx(1, 0) qc.x(1) qc.cx(0, 1) qc.cx(1, 0) qc.x(1) qc.cx(0, 1) qc.cx(1, 0) return qc
def circuit_to_gate(circuit, parameter_map=None, equivalence_library=None, label=None): """Build a ``Gate`` object from a ``QuantumCircuit``. The gate is anonymous (not tied to a named quantum register), and so can be inserted into another circuit. The gate will have the same string name as the circuit. Args: circuit (QuantumCircuit): the input circuit. parameter_map (dict): For parameterized circuits, a mapping from parameters in the circuit to parameters to be used in the gate. If None, existing circuit parameters will also parameterize the Gate. equivalence_library (EquivalenceLibrary): Optional equivalence library where the converted gate will be registered. label (str): Optional gate label. Raises: QiskitError: if circuit is non-unitary or if parameter_map is not compatible with circuit Return: Gate: a Gate equivalent to the action of the input circuit. Upon decomposition, this gate will yield the components comprising the original circuit. """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit if circuit.clbits: raise QiskitError("Circuit with classical bits cannot be converted " "to gate.") for inst, _, _ in circuit.data: if not isinstance(inst, Gate): raise QiskitError( ("One or more instructions cannot be converted to" ' a gate. "{}" is not a gate instruction').format(inst.name)) if parameter_map is None: parameter_dict = {p: p for p in circuit.parameters} else: parameter_dict = circuit._unroll_param_dict(parameter_map) if parameter_dict.keys() != circuit.parameters: raise QiskitError(("parameter_map should map all circuit parameters. " "Circuit parameters: {}, parameter_map: {}").format( circuit.parameters, parameter_dict)) gate = Gate( name=circuit.name, num_qubits=sum(qreg.size for qreg in circuit.qregs), params=[*parameter_dict.values()], label=label, ) gate.condition = None target = circuit.assign_parameters(parameter_dict, inplace=False) if equivalence_library is not None: equivalence_library.add_equivalence(gate, target) rules = target.data if gate.num_qubits > 0: q = QuantumRegister(gate.num_qubits, "q") qubit_map = {bit: q[idx] for idx, bit in enumerate(circuit.qubits)} # The 3rd parameter in the output tuple) is hard coded to [] because # Gate objects do not have cregs set and we've verified that all # instructions are gates rules = [(inst, [qubit_map[y] for y in qargs], []) for inst, qargs, _ in rules] qc = QuantumCircuit(q, name=gate.name, global_phase=target.global_phase) for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) gate.definition = qc return gate
def _circuit_u1x(theta, phi, lam, simplify=True, atol=DEFAULT_ATOL): # Shift theta and phi so decomposition is # U1(phi).X90.U1(theta).X90.U1(lam) theta += np.pi phi += np.pi # Check for decomposition into minimimal number required X90 pulses if simplify and np.isclose(abs(theta), np.pi, atol=atol): # Zero X90 gate decomposition circuit = QuantumCircuit(1) circuit.append(U1Gate(lam + phi + theta), [0]) return circuit if simplify and np.isclose(abs(theta), np.pi/2, atol=atol): # Single X90 gate decomposition circuit = QuantumCircuit(1) circuit.append(U1Gate(lam + theta), [0]) circuit.append(RXGate(np.pi / 2), [0]) circuit.append(U1Gate(phi + theta), [0]) return circuit # General two-X90 gate decomposition circuit = QuantumCircuit(1) circuit.append(U1Gate(lam), [0]) circuit.append(RXGate(np.pi / 2), [0]) circuit.append(U1Gate(theta), [0]) circuit.append(RXGate(np.pi / 2), [0]) circuit.append(U1Gate(phi), [0]) return circuit
def xx_circuit_step(source, strength, target, embodiment): """ Builds a single step in an XX-based circuit. `source` and `target` are positive canonical coordinates; `strength` is the interaction strength at this step in the circuit as a canonical coordinate (so that CX = RZX(pi/2) corresponds to pi/4); and `embodiment` is a Qiskit circuit which enacts the canonical gate of the prescribed interaction `strength`. """ permute_source_for_overlap, permute_target_for_overlap = None, None # apply all possible reflections, shifts to the source for source_reflection_name in reflection_options: reflected_source_coord, source_reflection, reflection_phase_shift = apply_reflection( source_reflection_name, source ) for source_shift_name in shift_options: shifted_source_coord, source_shift, shift_phase_shift = apply_shift( source_shift_name, reflected_source_coord ) # check for overlap, back out permutation source_shared, target_shared = None, None for i, j in [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]: if ( abs(np.mod(abs(shifted_source_coord[i] - target[j]), np.pi)) < EPSILON or abs(np.mod(abs(shifted_source_coord[i] - target[j]), np.pi) - np.pi) < EPSILON ): source_shared, target_shared = i, j break if source_shared is None: continue # pick out the other coordinates source_first, source_second = (x for x in [0, 1, 2] if x != source_shared) target_first, target_second = (x for x in [0, 1, 2] if x != target_shared) # check for arccos validity r, s, u, v, x, y = decompose_xxyy_into_xxyy_xx( float(target[target_first]), float(target[target_second]), float(shifted_source_coord[source_first]), float(shifted_source_coord[source_second]), float(strength), ) if any(math.isnan(val) for val in (r, s, u, v, x, y)): continue # OK: this combination of things works. # save the permutation which rotates the shared coordinate into ZZ. permute_source_for_overlap = canonical_rotation_circuit(source_first, source_second) permute_target_for_overlap = canonical_rotation_circuit(target_first, target_second) break if permute_source_for_overlap is not None: break if permute_source_for_overlap is None: raise QiskitError( "Error during RZX decomposition: Could not find a suitable Weyl " f"reflection to match {source} to {target} along {strength}." ) prefix_circuit, affix_circuit = QuantumCircuit(2), QuantumCircuit(2) # the basic formula we're trying to work with is: # target^p_t_f_o = # rs * (source^s_reflection * s_shift)^p_s_f_o * uv * operation * xy # but we're rearranging it into the form # target = affix source prefix # and computing just the prefix / affix circuits. # the outermost prefix layer comes from the (inverse) target permutation. prefix_circuit.compose(permute_target_for_overlap.inverse(), inplace=True) # the middle prefix layer comes from the local Z rolls. prefix_circuit.rz(2 * x, [0]) prefix_circuit.rz(2 * y, [1]) prefix_circuit.compose(embodiment, inplace=True) prefix_circuit.rz(2 * u, [0]) prefix_circuit.rz(2 * v, [1]) # the innermost prefix layer is source_reflection, shifted by source_shift, # finally conjugated by p_s_f_o. prefix_circuit.compose(permute_source_for_overlap, inplace=True) prefix_circuit.compose(source_reflection, inplace=True) prefix_circuit.global_phase += -np.log(reflection_phase_shift).imag prefix_circuit.global_phase += -np.log(shift_phase_shift).imag # the affix circuit is constructed in reverse. # first (i.e., innermost), we install the other half of the source transformations and p_s_f_o. affix_circuit.compose(source_reflection.inverse(), inplace=True) affix_circuit.compose(source_shift, inplace=True) affix_circuit.compose(permute_source_for_overlap.inverse(), inplace=True) # then, the other local rolls in the middle. affix_circuit.rz(2 * r, [0]) affix_circuit.rz(2 * s, [1]) # finally, the other half of the p_t_f_o conjugation. affix_circuit.compose(permute_target_for_overlap, inplace=True) return {"prefix_circuit": prefix_circuit, "affix_circuit": affix_circuit}
def _circuit_kak( theta, phi, lam, phase, simplify=True, atol=DEFAULT_ATOL, allow_non_canonical=True, k_gate=RZGate, a_gate=RYGate, ): """ Installs the angles phi, theta, and lam into a KAK-type decomposition of the form K(phi) . A(theta) . K(lam) , where K and A are an orthogonal pair drawn from RZGate, RYGate, and RXGate. Args: theta (float): The middle KAK parameter. Expected to lie in [0, pi). phi (float): The first KAK parameter. lam (float): The final KAK parameter. phase (float): The input global phase. k_gate (Callable): The constructor for the K gate Instruction. a_gate (Callable): The constructor for the A gate Instruction. simplify (bool): Indicates whether gates should be elided / coalesced where possible. allow_non_canonical (bool): Indicates whether we are permitted to reverse the sign of the middle parameter, theta, in the output. When this and `simplify` are both enabled, we take the opportunity to commute half-rotations in the outer gates past the middle gate, which permits us to coalesce them at the cost of reversing the sign of theta. Returns: QuantumCircuit: The assembled circuit. """ gphase = phase - (phi + lam) / 2 qr = QuantumRegister(1, "qr") circuit = QuantumCircuit(qr) if not simplify: atol = -1.0 # Early return for the middle-gate-free case if abs(theta) < atol: lam, phi = lam + phi, 0 # NOTE: The following normalization is safe, because the gphase correction below # fixes a particular diagonal entry to 1, which prevents any potential phase # slippage coming from _mod_2pi injecting multiples of 2pi. lam = _mod_2pi(lam, atol) if abs(lam) > atol: circuit._append(k_gate(lam), [qr[0]], []) gphase += lam / 2 circuit.global_phase = gphase return circuit if abs(theta - np.pi) < atol: gphase += phi lam, phi = lam - phi, 0 if allow_non_canonical and (abs(_mod_2pi(lam + np.pi)) < atol or abs(_mod_2pi(phi + np.pi)) < atol): lam, theta, phi = lam + np.pi, -theta, phi + np.pi lam = _mod_2pi(lam, atol) if abs(lam) > atol: gphase += lam / 2 circuit._append(k_gate(lam), [qr[0]], []) circuit._append(a_gate(theta), [qr[0]], []) phi = _mod_2pi(phi, atol) if abs(phi) > atol: gphase += phi / 2 circuit._append(k_gate(phi), [qr[0]], []) circuit.global_phase = gphase return circuit
def two_qubit_kak(unitary): """Decompose a two-qubit gate over SU(2)+CNOT using the KAK decomposition. Args: unitary (Operator): a 4x4 unitary operator to decompose. Returns: QuantumCircuit: a circuit implementing the unitary over SU(2)+CNOT Raises: QiskitError: input not a unitary, or error in KAK decomposition. """ if hasattr(unitary, 'to_operator'): # If input is a BaseOperator subclass this attempts to convert # the object to an Operator so that we can extract the underlying # numpy matrix from `Operator.data`. unitary = unitary.to_operator().data if hasattr(unitary, 'to_matrix'): # If input is Gate subclass or some other class object that has # a to_matrix method this will call that method. unitary = unitary.to_matrix() # Convert to numpy array incase not already an array unitary_matrix = np.array(unitary, dtype=complex) # Check input is a 2-qubit unitary if unitary_matrix.shape != (4, 4): raise QiskitError("two_qubit_kak: Expected 4x4 matrix") if not is_unitary_matrix(unitary_matrix): raise QiskitError("Input matrix is not unitary.") phase = la.det(unitary_matrix)**(-1.0 / 4.0) # Make it in SU(4), correct phase at the end U = phase * unitary_matrix # B changes to the Bell basis B = (1.0 / math.sqrt(2)) * np.array( [[1, 1j, 0, 0], [0, 0, 1j, 1], [0, 0, 1j, -1], [1, -1j, 0, 0]], dtype=complex) # We also need B.conj().T below Bdag = B.conj().T # U' = Bdag . U . B Uprime = Bdag.dot(U.dot(B)) # M^2 = trans(U') . U' M2 = Uprime.T.dot(Uprime) # Diagonalize M2 # Must use diagonalization routine which finds a real orthogonal matrix P # when M2 is real. D, P = la.eig(M2) D = np.diag(D) # If det(P) == -1 then in O(4), apply a swap to make P in SO(4) if abs(la.det(P) + 1) < 1e-5: swap = np.array( [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=complex) P = P.dot(swap) D = swap.dot(D.dot(swap)) Q = np.sqrt(D) # array from elementwise sqrt # Want to take square root so that Q has determinant 1 if abs(la.det(Q) + 1) < 1e-5: Q[0, 0] = -Q[0, 0] # Q^-1*P.T = P' -> QP' = P.T (solve for P' using Ax=b) Pprime = la.solve(Q, P.T) # K' now just U' * P * P' Kprime = Uprime.dot(P.dot(Pprime)) K1 = B.dot(Kprime.dot(P.dot(Bdag))) A = B.dot(Q.dot(Bdag)) K2 = B.dot(P.T.dot(Bdag)) # KAK = K1 * A * K2 KAK = K1.dot(A.dot(K2)) # Verify decomp matches input unitary. if la.norm(KAK - U) > 1e-6: raise QiskitError("two_qubit_kak: KAK decomposition " + "does not return input unitary.") # Compute parameters alpha, beta, gamma so that # A = exp(i * (alpha * XX + beta * YY + gamma * ZZ)) xx = np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]], dtype=complex) yy = np.array([[0, 0, 0, -1], [0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0]], dtype=complex) zz = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], dtype=complex) A_real_tr = A.real.trace() alpha = math.atan2(A.dot(xx).imag.trace(), A_real_tr) beta = math.atan2(A.dot(yy).imag.trace(), A_real_tr) gamma = math.atan2(A.dot(zz).imag.trace(), A_real_tr) # K1 = kron(U1, U2) and K2 = kron(V1, V2) # Find the matrices U1, U2, V1, V2 # Find a block in K1 where U1_ij * [U2] is not zero L = K1[0:2, 0:2] if la.norm(L) < 1e-9: L = K1[0:2, 2:4] if la.norm(L) < 1e-9: L = K1[2:4, 2:4] # Remove the U1_ij prefactor Q = L.dot(L.conj().T) U2 = L / math.sqrt(Q[0, 0].real) # Now grab U1 given we know U2 R = K1.dot(np.kron(np.identity(2), U2.conj().T)) U1 = np.zeros((2, 2), dtype=complex) U1[0, 0] = R[0, 0] U1[0, 1] = R[0, 2] U1[1, 0] = R[2, 0] U1[1, 1] = R[2, 2] # Repeat K1 routine for K2 L = K2[0:2, 0:2] if la.norm(L) < 1e-9: L = K2[0:2, 2:4] if la.norm(L) < 1e-9: L = K2[2:4, 2:4] Q = np.dot(L, np.transpose(L.conjugate())) V2 = L / np.sqrt(Q[0, 0]) R = np.dot(K2, np.kron(np.identity(2), np.transpose(V2.conjugate()))) V1 = np.zeros_like(U1) V1[0, 0] = R[0, 0] V1[0, 1] = R[0, 2] V1[1, 0] = R[2, 0] V1[1, 1] = R[2, 2] if la.norm(np.kron(U1, U2) - K1) > 1e-4: raise QiskitError("two_qubit_kak: K1 != U1 x U2") if la.norm(np.kron(V1, V2) - K2) > 1e-4: raise QiskitError("two_qubit_kak: K2 != V1 x V2") test = la.expm(1j * (alpha * xx + beta * yy + gamma * zz)) if la.norm(A - test) > 1e-4: raise QiskitError("two_qubit_kak: " + "Matrix A does not match xx,yy,zz decomposition.") # Circuit that implements K1 * A * K2 (up to phase), using # Vatan and Williams Fig. 6 of quant-ph/0308006v3 # Include prefix and suffix single-qubit gates into U2, V1 respectively. V2 = np.array([[np.exp(1j * np.pi / 4), 0], [0, np.exp(-1j * np.pi / 4)]], dtype=complex).dot(V2) U1 = U1.dot( np.array([[np.exp(-1j * np.pi / 4), 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex)) # Corrects global phase: exp(ipi/4)*phase' U1 = U1.dot( np.array([[np.exp(1j * np.pi / 4), 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex)) U1 = phase.conjugate() * U1 # Test g1 = np.kron(V1, V2) g2 = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex) theta = 2 * gamma - np.pi / 2 Ztheta = np.array( [[np.exp(1j * theta / 2), 0], [0, np.exp(-1j * theta / 2)]], dtype=complex) kappa = np.pi / 2 - 2 * alpha Ykappa = np.array( [[math.cos(kappa / 2), math.sin(kappa / 2)], [-math.sin(kappa / 2), math.cos(kappa / 2)]], dtype=complex) g3 = np.kron(Ztheta, Ykappa) g4 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], dtype=complex) zeta = 2 * beta - np.pi / 2 Yzeta = np.array( [[math.cos(zeta / 2), math.sin(zeta / 2)], [-math.sin(zeta / 2), math.cos(zeta / 2)]], dtype=complex) g5 = np.kron(np.identity(2), Yzeta) g6 = g2 g7 = np.kron(U1, U2) V = g2.dot(g1) V = g3.dot(V) V = g4.dot(V) V = g5.dot(V) V = g6.dot(V) V = g7.dot(V) if la.norm(V - U * phase.conjugate()) > 1e-6: raise QiskitError("two_qubit_kak: " + "sequence incorrect, unknown error") v1_param = euler_angles_1q(V1) v2_param = euler_angles_1q(V2) u1_param = euler_angles_1q(U1) u2_param = euler_angles_1q(U2) v1_gate = U3Gate(v1_param[0], v1_param[1], v1_param[2]) v2_gate = U3Gate(v2_param[0], v2_param[1], v2_param[2]) u1_gate = U3Gate(u1_param[0], u1_param[1], u1_param[2]) u2_gate = U3Gate(u2_param[0], u2_param[1], u2_param[2]) q = QuantumRegister(2) return_circuit = QuantumCircuit(q) return_circuit.append(v1_gate, [q[1]]) return_circuit.append(v2_gate, [q[0]]) return_circuit.append(CnotGate(), [q[0], q[1]]) gate = U3Gate(0.0, 0.0, -2.0 * gamma + np.pi / 2.0) return_circuit.append(gate, [q[1]]) gate = U3Gate(-np.pi / 2.0 + 2.0 * alpha, 0.0, 0.0) return_circuit.append(gate, [q[0]]) return_circuit.append(CnotGate(), [q[1], q[0]]) gate = U3Gate(-2.0 * beta + np.pi / 2.0, 0.0, 0.0) return_circuit.append(gate, [q[0]]) return_circuit.append(CnotGate(), [q[0], q[1]]) return_circuit.append(u1_gate, [q[1]]) return_circuit.append(u2_gate, [q[0]]) return return_circuit
def _build(self) -> None: """Build the circuit.""" if self._data: return _ = self._check_configuration() self._data = [] if self.num_qubits == 0: return circuit = QuantumCircuit(*self.qregs, name=self.name) # use the initial state as starting circuit, if it is set if self.initial_state: if isinstance(self.initial_state, QuantumCircuit): initial = self.initial_state.copy() else: initial = self.initial_state.construct_circuit( "circuit", register=self.qregs[0]) circuit.compose(initial, inplace=True) param_iter = iter(self.ordered_parameters) # build the prepended layers self._build_additional_layers(circuit, "prepended") # main loop to build the entanglement and rotation layers for i in range(self.reps): # insert barrier if specified and there is a preceding layer if self._insert_barriers and (i > 0 or len(self._prepended_blocks) > 0): circuit.barrier() # build the rotation layer self._build_rotation_layer(circuit, param_iter, i) # barrier in between rotation and entanglement layer if self._insert_barriers and len(self._rotation_blocks) > 0: circuit.barrier() # build the entanglement layer self._build_entanglement_layer(circuit, param_iter, i) # add the final rotation layer if not self._skip_final_rotation_layer: if self.insert_barriers and self.reps > 0: circuit.barrier() self._build_rotation_layer(circuit, param_iter, self.reps) # add the appended layers self._build_additional_layers(circuit, "appended") # cast global phase to float if it has no free parameters if isinstance(circuit.global_phase, ParameterExpression): try: circuit.global_phase = float(circuit.global_phase._symbol_expr) # RuntimeError is raised if symengine is used, for SymPy it is a TypeError except (RuntimeError, TypeError): # expression contains free parameters pass try: block = circuit.to_gate() except QiskitError: block = circuit.to_instruction() self.append(block, self.qubits)
def _circuit_psx(theta, phi, lam, simplify=True, atol=DEFAULT_ATOL): # Shift theta and phi so decomposition is # Phase(phi+pi).SX.Phase(theta+pi).SX.Phase(lam) theta = _mod2pi(theta + np.pi) phi = _mod2pi(phi + np.pi) circuit = QuantumCircuit(1) # Check for decomposition into minimimal number required SX gates if simplify and np.isclose(abs(theta), np.pi, atol=atol): if not np.isclose(_mod2pi(abs(lam + phi + theta)), [0., 2*np.pi], atol=atol).any(): circuit.append(PhaseGate(_mod2pi(lam + phi + theta)), [0]) elif simplify and np.isclose(abs(theta), [np.pi/2, 3*np.pi/2], atol=atol).any(): if not np.isclose(_mod2pi(abs(lam + theta)), [0., 2*np.pi], atol=atol).any(): circuit.append(PhaseGate(_mod2pi(lam + theta)), [0]) circuit.append(SXGate(), [0]) if not np.isclose(_mod2pi(abs(phi + theta)), [0., 2*np.pi], atol=atol).any(): circuit.append(PhaseGate(_mod2pi(phi + theta)), [0]) else: if not np.isclose(abs(lam), [0., 2*np.pi], atol=atol).any(): circuit.append(PhaseGate(lam), [0]) circuit.append(SXGate(), [0]) if not np.isclose(abs(theta), [0., 2*np.pi], atol=atol).any(): circuit.append(PhaseGate(theta), [0]) circuit.append(SXGate(), [0]) if not np.isclose(abs(phi), [0., 2*np.pi], atol=atol).any(): circuit.append(PhaseGate(phi), [0]) return circuit
def add_layer( self, other: Union["NLocal", Instruction, QuantumCircuit], entanglement: Optional[Union[List[int], str, List[List[int]]]] = None, front: bool = False, ) -> "NLocal": """Append another layer to the NLocal. Args: other: The layer to compose, can be another NLocal, an Instruction or Gate, or a QuantumCircuit. entanglement: The entanglement or qubit indices. front: If True, ``other`` is appended to the front, else to the back. Returns: self, such that chained composes are possible. Raises: TypeError: If `other` is not compatible, i.e. is no Instruction and does not have a `to_instruction` method. """ block = self._convert_to_block(other) if entanglement is None: entanglement = [list(range(block.num_qubits))] elif isinstance(entanglement, list) and not isinstance(entanglement[0], list): entanglement = [entanglement] if front: self._prepended_blocks += [block] self._prepended_entanglement += [entanglement] else: self._appended_blocks += [block] self._appended_entanglement += [entanglement] if isinstance(entanglement, list): num_qubits = 1 + max(max(indices) for indices in entanglement) if num_qubits > self.num_qubits: self._invalidate() # rebuild circuit self.num_qubits = num_qubits # modify the circuit accordingly if self._data and front is False: if self._insert_barriers and len(self._data) > 0: self.barrier() if isinstance(entanglement, str): entangler_map = get_entangler_map(block.num_qubits, self.num_qubits, entanglement) else: entangler_map = entanglement layer = QuantumCircuit(self.num_qubits) for i in entangler_map: params = self.ordered_parameters[-len(get_parameters(block)):] parameterized_block = self._parameterize_block(block, params=params) layer.compose(parameterized_block, i, inplace=True) self.compose(layer, inplace=True) else: # cannot prepend a block currently, just rebuild self._invalidate() return self
def template_7b_1(): """ Returns: QuantumCircuit: template as a quantum circuit. """ qc = QuantumCircuit(3) qc.x(0) qc.cx(0, 1) qc.cx(1, 2) qc.ccx(0, 1, 2) qc.cx(0, 1) qc.x(0) qc.ccx(0, 1, 2) return qc
def _define(self): """ gate cphase(lambda) a,b { phase(lambda/2) a; cx a,b; phase(-lambda/2) b; cx a,b; phase(lambda/2) b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) qc.p(self.params[0] / 2, 0) qc.cx(0, 1) qc.p(-self.params[0] / 2, 1) qc.cx(0, 1) qc.p(self.params[0] / 2, 1) self.definition = qc
def _circuit_rr(theta, phi, lam, simplify=True, atol=DEFAULT_ATOL): circuit = QuantumCircuit(1) if not simplify or not np.isclose(theta, -np.pi, atol=atol): circuit.append(RGate(theta + np.pi, np.pi / 2 - lam), [0]) circuit.append(RGate(-np.pi, 0.5 * (phi - lam + np.pi)), [0]) return circuit
def clifford_6_5(): """ Returns: QuantumCircuit: template as a quantum circuit. """ qc = QuantumCircuit(2) qc.cz(0, 1) qc.cx(0, 1) qc.s(0) qc.sdg(1) qc.cx(0, 1) qc.s(1) return qc
def _circuit_zxz(theta, phi, lam, simplify=False, atol=DEFAULT_ATOL): if simplify and np.isclose(theta, 0.0, atol=atol): circuit = QuantumCircuit(1) circuit.append(RZGate(phi + lam), [0]) return circuit circuit = QuantumCircuit(1) if not simplify or not np.isclose(lam, 0.0, atol=atol): circuit.append(RZGate(lam), [0]) if not simplify or not np.isclose(theta, 0.0, atol=atol): circuit.append(RXGate(theta), [0]) if not simplify or not np.isclose(phi, 0.0, atol=atol): circuit.append(RZGate(phi), [0]) return circuit
def circuit_to_instruction(circuit, parameter_map=None, equivalence_library=None): """Build an ``Instruction`` object from a ``QuantumCircuit``. The instruction is anonymous (not tied to a named quantum register), and so can be inserted into another circuit. The instruction will have the same string name as the circuit. Args: circuit (QuantumCircuit): the input circuit. parameter_map (dict): For parameterized circuits, a mapping from parameters in the circuit to parameters to be used in the instruction. If None, existing circuit parameters will also parameterize the instruction. equivalence_library (EquivalenceLibrary): Optional equivalence library where the converted instruction will be registered. Raises: QiskitError: if parameter_map is not compatible with circuit Return: qiskit.circuit.Instruction: an instruction equivalent to the action of the input circuit. Upon decomposition, this instruction will yield the components comprising the original circuit. Example: .. jupyter-execute:: from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.converters import circuit_to_instruction %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) circuit_to_instruction(circ) """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit if parameter_map is None: parameter_dict = {p: p for p in circuit.parameters} else: parameter_dict = circuit._unroll_param_dict(parameter_map) if parameter_dict.keys() != circuit.parameters: raise QiskitError(('parameter_map should map all circuit parameters. ' 'Circuit parameters: {}, parameter_map: {}').format( circuit.parameters, parameter_dict)) instruction = Instruction( name=circuit.name, num_qubits=sum([qreg.size for qreg in circuit.qregs]), num_clbits=sum([creg.size for creg in circuit.cregs]), params=sorted(parameter_dict.values(), key=lambda p: p.name)) instruction.condition = None def find_bit_position(bit): """find the index of a given bit (Register, int) within a flat ordered list of bits of the circuit """ if isinstance(bit, Qubit): ordered_regs = circuit.qregs else: ordered_regs = circuit.cregs reg_index = ordered_regs.index(bit.register) return sum([reg.size for reg in ordered_regs[:reg_index]]) + bit.index target = circuit.assign_parameters(parameter_dict, inplace=False) if equivalence_library is not None: equivalence_library.add_equivalence(instruction, target) definition = target.data regs = [] if instruction.num_qubits > 0: q = QuantumRegister(instruction.num_qubits, 'q') regs.append(q) if instruction.num_clbits > 0: c = ClassicalRegister(instruction.num_clbits, 'c') regs.append(c) definition = list( map( lambda x: (x[0], list(map(lambda y: q[find_bit_position(y)], x[1])), list(map(lambda y: c[find_bit_position(y)], x[2]))), definition)) # fix condition for rule in definition: condition = rule[0].condition if condition: reg, val = condition if reg.size == c.size: rule[0].condition = (c, val) else: raise QiskitError( 'Cannot convert condition in circuit with ' 'multiple classical registers to instruction') qc = QuantumCircuit(*regs, name=instruction.name) qc._data = definition if circuit.global_phase: qc.global_phase = circuit.global_phase instruction.definition = qc return instruction
def _two_qubit_evolution(pauli, time, cx_structure): # Get the Paulis and the qubits they act on. # Note that all phases are removed from the pauli label and are only in the coefficients. # That's because the operators we evolved have all been translated to a SparsePauliOp. labels_as_array = np.array(list(reversed(pauli.to_label()))) qubits = np.where(labels_as_array != "I")[0] labels = np.array([labels_as_array[idx] for idx in qubits]) definition = QuantumCircuit(pauli.num_qubits) # go through all cases we have implemented in Qiskit if all(labels == "X"): # RXX definition.rxx(2 * time, qubits[0], qubits[1]) elif all(labels == "Y"): # RYY definition.ryy(2 * time, qubits[0], qubits[1]) elif all(labels == "Z"): # RZZ definition.rzz(2 * time, qubits[0], qubits[1]) elif labels[0] == "Z" and labels[1] == "X": # RZX definition.rzx(2 * time, qubits[0], qubits[1]) elif labels[0] == "X" and labels[1] == "Z": # RXZ definition.rzx(2 * time, qubits[1], qubits[0]) else: # all the others are not native in Qiskit, so use default the decomposition definition = _multi_qubit_evolution(pauli, time, cx_structure) return definition
def _experiments_to_circuits(qobj): """Return a list of QuantumCircuit object(s) from a qobj. Args: qobj (Qobj): The Qobj object to convert to QuantumCircuits Returns: list: A list of QuantumCircuit objects from the qobj """ if not qobj.experiments: return None circuits = [] for exp in qobj.experiments: quantum_registers = [ QuantumRegister(i[1], name=i[0]) for i in exp.header.qreg_sizes ] classical_registers = [ ClassicalRegister(i[1], name=i[0]) for i in exp.header.creg_sizes ] circuit = QuantumCircuit(*quantum_registers, *classical_registers, name=exp.header.name) qreg_dict = collections.OrderedDict() creg_dict = collections.OrderedDict() for reg in quantum_registers: qreg_dict[reg.name] = reg for reg in classical_registers: creg_dict[reg.name] = reg conditional = {} for i in exp.instructions: name = i.name qubits = [] params = getattr(i, "params", []) try: for qubit in i.qubits: qubit_label = exp.header.qubit_labels[qubit] qubits.append(qreg_dict[qubit_label[0]][qubit_label[1]]) except Exception: # pylint: disable=broad-except pass clbits = [] try: for clbit in i.memory: clbit_label = exp.header.clbit_labels[clbit] clbits.append(creg_dict[clbit_label[0]][clbit_label[1]]) except Exception: # pylint: disable=broad-except pass if hasattr(circuit, name): instr_method = getattr(circuit, name) if i.name in ["snapshot"]: _inst = instr_method(i.label, snapshot_type=i.snapshot_type, qubits=qubits, params=params) elif i.name == "initialize": _inst = instr_method(params, qubits) elif i.name == "isometry": _inst = instr_method(*params, qubits, clbits) elif i.name in ["mcx", "mcu1", "mcp"]: _inst = instr_method(*params, qubits[:-1], qubits[-1], *clbits) else: _inst = instr_method(*params, *qubits, *clbits) elif name == "bfunc": conditional["value"] = int(i.val, 16) full_bit_size = sum(creg_dict[x].size for x in creg_dict) mask_map = {} raw_map = {} raw = [] for creg in creg_dict: size = creg_dict[creg].size reg_raw = [1] * size if not raw: raw = reg_raw else: for pos, val in enumerate(raw): if val == 1: raw[pos] = 0 raw = reg_raw + raw mask = [0] * (full_bit_size - len(raw)) + raw raw_map[creg] = mask mask_map[int("".join(str(x) for x in mask), 2)] = creg if bin(int(i.mask, 16)).count("1") == 1: cbit = int(math.log2(int(i.mask, 16))) for reg in creg_dict: size = creg_dict[reg].size if cbit >= size: cbit -= size else: conditional["register"] = creg_dict[reg][cbit] break mask_str = bin(int(i.mask, 16))[2:].zfill(full_bit_size) mask = [int(item) for item in list(mask_str)] else: creg = mask_map[int(i.mask, 16)] conditional["register"] = creg_dict[creg] mask = raw_map[creg] val = int(i.val, 16) for j in reversed(mask): if j == 0: val = val >> 1 else: conditional["value"] = val break else: _inst = temp_opaque_instruction = Instruction( name=name, num_qubits=len(qubits), num_clbits=len(clbits), params=params) circuit.append(temp_opaque_instruction, qubits, clbits) if conditional and name != "bfunc": _inst.c_if(conditional["register"], conditional["value"]) conditional = {} pulse_lib = qobj.config.pulse_library if hasattr( qobj.config, "pulse_library") else [] parametric_pulses = (qobj.config.parametric_pulses if hasattr( qobj.config, "parametric_pulses") else []) # The dict update method did not work here; could investigate in the future if hasattr(qobj.config, "calibrations"): circuit.calibrations = dict( **circuit.calibrations, **_qobj_to_circuit_cals(qobj, pulse_lib, parametric_pulses)) if hasattr(exp.config, "calibrations"): circuit.calibrations = dict( **circuit.calibrations, **_qobj_to_circuit_cals(exp, pulse_lib, parametric_pulses)) circuits.append(circuit) return circuits
def circuit_to_gate(circuit, parameter_map=None, equivalence_library=None, label=None): """Build a ``Gate`` object from a ``QuantumCircuit``. The gate is anonymous (not tied to a named quantum register), and so can be inserted into another circuit. The gate will have the same string name as the circuit. Args: circuit (QuantumCircuit): the input circuit. parameter_map (dict): For parameterized circuits, a mapping from parameters in the circuit to parameters to be used in the gate. If None, existing circuit parameters will also parameterize the Gate. equivalence_library (EquivalenceLibrary): Optional equivalence library where the converted gate will be registered. label (str): Optional gate label. Raises: QiskitError: if circuit is non-unitary or if parameter_map is not compatible with circuit Return: Gate: a Gate equivalent to the action of the input circuit. Upon decomposition, this gate will yield the components comprising the original circuit. """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit if circuit.clbits: raise QiskitError('Circuit with classical bits cannot be converted ' 'to gate.') for inst, _, _ in circuit.data: if not isinstance(inst, Gate): raise QiskitError( ('One or more instructions cannot be converted to' ' a gate. "{}" is not a gate instruction').format(inst.name)) if parameter_map is None: parameter_dict = {p: p for p in circuit.parameters} else: parameter_dict = circuit._unroll_param_dict(parameter_map) if parameter_dict.keys() != circuit.parameters: raise QiskitError(('parameter_map should map all circuit parameters. ' 'Circuit parameters: {}, parameter_map: {}').format( circuit.parameters, parameter_dict)) gate = Gate(name=circuit.name, num_qubits=sum([qreg.size for qreg in circuit.qregs]), params=sorted(parameter_dict.values(), key=lambda p: p.name), label=label) gate.condition = None def find_bit_position(bit): """find the index of a given bit (Register, int) within a flat ordered list of bits of the circuit """ if isinstance(bit, Qubit): ordered_regs = circuit.qregs else: ordered_regs = circuit.cregs reg_index = ordered_regs.index(bit.register) return sum([reg.size for reg in ordered_regs[:reg_index]]) + bit.index target = circuit.assign_parameters(parameter_dict, inplace=False) if equivalence_library is not None: equivalence_library.add_equivalence(gate, target) rules = target.data if gate.num_qubits > 0: q = QuantumRegister(gate.num_qubits, 'q') # The 3rd parameter in the output tuple) is hard coded to [] because # Gate objects do not have cregs set and we've verified that all # instructions are gates rules = list( map( lambda x: (x[0], list(map(lambda y: q[find_bit_position(y)], x[1])), []), rules)) qc = QuantumCircuit(q, name=gate.name) qc.data = rules gate.definition = qc return gate
def _convert_to_block(self, layer: Union[str, type, Gate, QuantumCircuit]) -> QuantumCircuit: """For a layer provided as str (e.g. 'ry') or type (e.g. RYGate) this function returns the according layer type along with the number of parameters (e.g. (RYGate, 1)). Args: layer: The qubit layer. Returns: The specified layer with the required number of parameters. Raises: TypeError: The type of `layer` is invalid. ValueError: The type of `layer` is str but the name is unknown. ValueError: The type of `layer` is type but the layer type is unknown. Note: Outlook: If layers knew their number of parameters as static property, we could also allow custom layer types. """ if isinstance(layer, QuantumCircuit): return layer # check the list of valid layers # this could be a lot easier if the standard layers would have `name` and `num_params` # as static types, which might be something they should have anyways theta = Parameter("θ") valid_layers = { "ch": CHGate(), "cx": CXGate(), "cy": CYGate(), "cz": CZGate(), "crx": CRXGate(theta), "cry": CRYGate(theta), "crz": CRZGate(theta), "h": HGate(), "i": IGate(), "id": IGate(), "iden": IGate(), "rx": RXGate(theta), "rxx": RXXGate(theta), "ry": RYGate(theta), "ryy": RYYGate(theta), "rz": RZGate(theta), "rzx": RZXGate(theta), "rzz": RZZGate(theta), "s": SGate(), "sdg": SdgGate(), "swap": SwapGate(), "x": XGate(), "y": YGate(), "z": ZGate(), "t": TGate(), "tdg": TdgGate(), } # try to exchange `layer` from a string to a gate instance if isinstance(layer, str): try: layer = valid_layers[layer] except KeyError as ex: raise ValueError(f"Unknown layer name `{layer}`.") from ex # try to exchange `layer` from a type to a gate instance if isinstance(layer, type): # iterate over the layer types and look for the specified layer instance = None for gate in valid_layers.values(): if isinstance(gate, layer): instance = gate if instance is None: raise ValueError(f"Unknown layer type`{layer}`.") layer = instance if isinstance(layer, Instruction): circuit = QuantumCircuit(layer.num_qubits) circuit.append(layer, list(range(layer.num_qubits))) return circuit raise TypeError( f"Invalid input type {type(layer)}. " + "`layer` must be a type, str or QuantumCircuit." )
def __call__(self, target, basis_fidelity=None): """Decompose a two-qubit unitary over fixed basis + SU(2) using the best approximation given that each basis application has a finite fidelity. """ basis_fidelity = basis_fidelity or self.basis_fidelity if hasattr(target, 'to_operator'): # If input is a BaseOperator subclass this attempts to convert # the object to an Operator so that we can extract the underlying # numpy matrix from `Operator.data`. target = target.to_operator().data if hasattr(target, 'to_matrix'): # If input is Gate subclass or some other class object that has # a to_matrix method this will call that method. target = target.to_matrix() # Convert to numpy array incase not already an array target = np.asarray(target, dtype=complex) # Check input is a 2-qubit unitary if target.shape != (4, 4): raise QiskitError("TwoQubitBasisDecomposer: expected 4x4 matrix for target") if not is_unitary_matrix(target): raise QiskitError("TwoQubitBasisDecomposer: target matrix is not unitary.") target_decomposed = TwoQubitWeylDecomposition(target) traces = self.traces(target_decomposed) expected_fidelities = [trace_to_fid(traces[i]) * basis_fidelity**i for i in range(4)] best_nbasis = np.argmax(expected_fidelities) decomposition = self.decomposition_fns[best_nbasis](target_decomposed) decomposition_euler = [self._decomposer1q(x) for x in decomposition] q = QuantumRegister(2) return_circuit = QuantumCircuit(q) for i in range(best_nbasis): return_circuit.compose(decomposition_euler[2*i], [q[0]], inplace=True) return_circuit.compose(decomposition_euler[2*i+1], [q[1]], inplace=True) return_circuit.append(self.gate, [q[0], q[1]]) return_circuit.compose(decomposition_euler[2*best_nbasis], [q[0]], inplace=True) return_circuit.compose(decomposition_euler[2*best_nbasis+1], [q[1]], inplace=True) return return_circuit
def run(self, dag): """Run the ConsolidateBlocks pass on `dag`. Iterate over each block and replace it with an equivalent Unitary on the same wires. """ if self.decomposer is None: return dag # compute ordered indices for the global circuit wires global_index_map = {wire: idx for idx, wire in enumerate(dag.qubits)} blocks = self.property_set["block_list"] basis_gate_name = self.decomposer.gate.name all_block_gates = set() for block in blocks: if len(block) == 1 and (self.basis_gates and block[0].name not in self.basis_gates): all_block_gates.add(block[0]) dag.substitute_node(block[0], UnitaryGate(block[0].op.to_matrix())) else: basis_count = 0 outside_basis = False block_qargs = set() block_cargs = set() for nd in block: block_qargs |= set(nd.qargs) if isinstance(nd, DAGOpNode) and nd.op.condition: block_cargs |= set(nd.op.condition[0]) all_block_gates.add(nd) q = QuantumRegister(len(block_qargs)) qc = QuantumCircuit(q) if block_cargs: c = ClassicalRegister(len(block_cargs)) qc.add_register(c) block_index_map = self._block_qargs_to_indices(block_qargs, global_index_map) for nd in block: if nd.op.name == basis_gate_name: basis_count += 1 if self.basis_gates and nd.op.name not in self.basis_gates: outside_basis = True qc.append(nd.op, [q[block_index_map[i]] for i in nd.qargs]) unitary = UnitaryGate(Operator(qc)) max_2q_depth = 20 # If depth > 20, there will be 1q gates to consolidate. if ( # pylint: disable=too-many-boolean-expressions self.force_consolidate or unitary.num_qubits > 2 or self.decomposer.num_basis_gates(unitary) < basis_count or len(block) > max_2q_depth or (self.basis_gates is not None and outside_basis) ): dag.replace_block_with_op(block, unitary, block_index_map, cycle_check=False) # If 1q runs are collected before consolidate those too runs = self.property_set["run_list"] or [] for run in runs: if run[0] in all_block_gates: continue if len(run) == 1 and self.basis_gates and run[0].name not in self.basis_gates: dag.substitute_node(run[0], UnitaryGate(run[0].op.to_matrix())) else: qubit = run[0].qargs[0] operator = run[0].op.to_matrix() already_in_block = False for gate in run[1:]: if gate in all_block_gates: already_in_block = True operator = gate.op.to_matrix().dot(operator) if already_in_block: continue unitary = UnitaryGate(operator) dag.replace_block_with_op(run, unitary, {qubit: 0}, cycle_check=False) return dag
def _experiments_to_circuits(qobj): """Return a list of QuantumCircuit object(s) from a qobj. Args: qobj (Qobj): The Qobj object to convert to QuantumCircuits Returns: list: A list of QuantumCircuit objects from the qobj """ if not qobj.experiments: return None circuits = [] for exp in qobj.experiments: quantum_registers = [ QuantumRegister(i[1], name=i[0]) for i in exp.header.qreg_sizes ] classical_registers = [ ClassicalRegister(i[1], name=i[0]) for i in exp.header.creg_sizes ] circuit = QuantumCircuit(*quantum_registers, *classical_registers, name=exp.header.name) qreg_dict = collections.OrderedDict() creg_dict = collections.OrderedDict() for reg in quantum_registers: qreg_dict[reg.name] = reg for reg in classical_registers: creg_dict[reg.name] = reg conditional = {} for i in exp.instructions: name = i.name qubits = [] params = getattr(i, "params", []) try: for qubit in i.qubits: qubit_label = exp.header.qubit_labels[qubit] qubits.append(qreg_dict[qubit_label[0]][qubit_label[1]]) except Exception: # pylint: disable=broad-except pass clbits = [] try: for clbit in i.memory: clbit_label = exp.header.clbit_labels[clbit] clbits.append(creg_dict[clbit_label[0]][clbit_label[1]]) except Exception: # pylint: disable=broad-except pass if hasattr(circuit, name): instr_method = getattr(circuit, name) if i.name in ["snapshot"]: _inst = instr_method(i.label, snapshot_type=i.snapshot_type, qubits=qubits, params=params) elif i.name == "initialize": _inst = instr_method(params, qubits) elif i.name == "isometry": _inst = instr_method(*params, qubits, clbits) elif i.name in ["mcx", "mcu1", "mcp"]: _inst = instr_method(*params, qubits[:-1], qubits[-1], *clbits) else: _inst = instr_method(*params, *qubits, *clbits) elif name == "bfunc": conditional["value"] = int(i.val, 16) full_bit_size = sum([creg_dict[x].size for x in creg_dict]) mask_map = {} raw_map = {} raw = [] for creg in creg_dict: size = creg_dict[creg].size reg_raw = [1] * size if not raw: raw = reg_raw else: for pos, val in enumerate(raw): if val == 1: raw[pos] = 0 raw = reg_raw + raw mask = [0] * (full_bit_size - len(raw)) + raw raw_map[creg] = mask mask_map[int("".join(str(x) for x in mask), 2)] = creg creg = mask_map[int(i.mask, 16)] conditional["register"] = creg_dict[creg] val = int(i.val, 16) mask = raw_map[creg] for j in reversed(mask): if j == 0: val = val >> 1 else: conditional["value"] = val break else: _inst = temp_opaque_instruction = Instruction( name=name, num_qubits=len(qubits), num_clbits=len(clbits), params=params) circuit.append(temp_opaque_instruction, qubits, clbits) if conditional and name != "bfunc": _inst.c_if(conditional["register"], conditional["value"]) conditional = {} circuits.append(circuit) return circuits
def __init__(self, adjacency_matrix: Union[List[List[int]], np.ndarray]) -> None: """Create new HLF circuit. Args: adjacency_matrix: a symmetric n-by-n list of 0-1 lists. n will be the number of qubits. Raises: CircuitError: If A is not symmetric. """ adjacency_matrix = np.asarray(adjacency_matrix) if not np.allclose(adjacency_matrix, adjacency_matrix.transpose()): raise CircuitError("The adjacency matrix must be symmetric.") num_qubits = len(adjacency_matrix) circuit = QuantumCircuit(num_qubits, name="hlf: %s" % adjacency_matrix) circuit.h(range(num_qubits)) for i in range(num_qubits): for j in range(i + 1, num_qubits): if adjacency_matrix[i][j]: circuit.cz(i, j) for i in range(num_qubits): if adjacency_matrix[i][i]: circuit.s(i) circuit.h(range(num_qubits)) super().__init__(*circuit.qregs, name=circuit.name) self.compose(circuit.to_gate(), qubits=self.qubits, inplace=True)
def _define(self): from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(1, 'q') qc = QuantumCircuit(q, name=self.name) qc.u(self.params[0], self.params[1], self.params[2], 0) self.definition = qc
def _circuit_u3(theta, phi, lam, simplify=True, atol=DEFAULT_ATOL): # pylint: disable=unused-argument circuit = QuantumCircuit(1) circuit.append(U3Gate(theta, phi, lam), [0]) return circuit
def _define(self): """ gate c3x a,b,c,d { h d; p(pi/8) a; p(pi/8) b; p(pi/8) c; p(pi/8) d; cx a, b; p(-pi/8) b; cx a, b; cx b, c; p(-pi/8) c; cx a, c; p(pi/8) c; cx b, c; p(-pi/8) c; cx a, c; cx c, d; p(-pi/8) d; cx b, d; p(pi/8) d; cx c, d; p(-pi/8) d; cx a, d; p(pi/8) d; cx c, d; p(-pi/8) d; cx b, d; p(pi/8) d; cx c, d; p(-pi/8) d; cx a, d; h d; } """ from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(4, name='q') qc = QuantumCircuit(q, name=self.name) qc.h(3) qc.p(pi / 8, [0, 1, 2, 3]) qc.cx(0, 1) qc.p(-pi / 8, 1) qc.cx(0, 1) qc.cx(1, 2) qc.p(-pi / 8, 2) qc.cx(0, 2) qc.p(pi / 8, 2) qc.cx(1, 2) qc.p(-pi / 8, 2) qc.cx(0, 2) qc.cx(2, 3) qc.p(-pi / 8, 3) qc.cx(1, 3) qc.p(pi / 8, 3) qc.cx(2, 3) qc.p(-pi / 8, 3) qc.cx(0, 3) qc.p(pi / 8, 3) qc.cx(2, 3) qc.p(-pi / 8, 3) qc.cx(1, 3) qc.p(pi / 8, 3) qc.cx(2, 3) qc.p(-pi / 8, 3) qc.cx(0, 3) qc.h(3) self.definition = qc
def _circuit_u(theta, phi, lam, phase, simplify=True, atol=DEFAULT_ATOL): # pylint: disable=unused-argument circuit = QuantumCircuit(1, global_phase=phase) circuit.u(theta, phi, lam, 0) return circuit