def test_open_controlled_gate(self): """ Test controlled gates with control on '0' """ base_gate = XGate() base_mat = base_gate.to_matrix() num_ctrl_qubits = 3 ctrl_state = 5 cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state) target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertEqual(Operator(cgate), Operator(target_mat)) ctrl_state = None cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state) target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertEqual(Operator(cgate), Operator(target_mat)) ctrl_state = 0 cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state) target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertEqual(Operator(cgate), Operator(target_mat)) ctrl_state = 7 cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state) target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertEqual(Operator(cgate), Operator(target_mat)) ctrl_state = '110' cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state) target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertEqual(Operator(cgate), Operator(target_mat))
def test_multi_control_toffoli_matrix_advanced_dirty_ancillas( self, num_controls): """Test the multi-control Toffoli gate with dirty ancillas (advanced). Based on the test moved here from Aqua: https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mct.py """ q_controls = QuantumRegister(num_controls) q_target = QuantumRegister(1) qc = QuantumCircuit(q_controls, q_target) q_ancillas = None if num_controls <= 4: num_ancillas = 0 else: num_ancillas = 1 q_ancillas = QuantumRegister(num_ancillas) qc.add_register(q_ancillas) qc.mct(q_controls, q_target[0], q_ancillas, mode='advanced') simulated = execute( qc, BasicAer.get_backend('unitary_simulator')).result().get_unitary(qc) if num_ancillas > 0: simulated = simulated[:2**(num_controls + 1), :2**(num_controls + 1)] base = XGate().to_matrix() expected = _compute_control_matrix(base, num_controls) self.assertTrue(matrix_equal(simulated, expected, atol=1e-8))
def test_single_controlled_rotation_gates(self, gate, cgate): """Test the controlled rotation gates controlled on one qubit.""" if gate.name == 'rz': iden = Operator.from_label('I') zgen = Operator.from_label('Z') op_mat = (np.cos(0.5 * self.theta) * iden - 1j * np.sin(0.5 * self.theta) * zgen).data else: op_mat = Operator(gate).data ref_mat = Operator(cgate).data cop_mat = _compute_control_matrix(op_mat, self.num_ctrl) self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True)) cqc = QuantumCircuit(self.num_ctrl + self.num_target) cqc.append(cgate, cqc.qregs[0]) dag = circuit_to_dag(cqc) unroller = Unroller(['u3', 'cx']) uqc = dag_to_circuit(unroller.run(dag)) self.log.info('%s gate count: %d', cgate.name, uqc.size()) self.log.info('\n%s', str(uqc)) # these limits could be changed if gate.name == 'ry': self.assertTrue(uqc.size() <= 32) elif gate.name == 'rz': self.assertTrue(uqc.size() <= 40) else: self.assertTrue(uqc.size() <= 20)
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): """Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: Invalid ctrl_state. ExtensionError: Non-unitary controlled unitary. """ mat = self.to_matrix() cmat = _compute_control_matrix(mat, num_ctrl_qubits, ctrl_state=None) iso = isometry.Isometry(cmat, 0, 0) return ControlledGate( "c-unitary", num_qubits=self.num_qubits + num_ctrl_qubits, params=[mat], label=label, num_ctrl_qubits=num_ctrl_qubits, definition=iso.definition, ctrl_state=ctrl_state, base_gate=self.copy(), )
def test_multi_control_u3(self): """Test the matrix representation of the controlled and controlled-controlled U3 gate.""" import qiskit.extensions.standard.u3 as u3 num_ctrl = 3 # U3 gate params alpha, beta, gamma = 0.2, 0.3, 0.4 # cnu3 gate u3gate = u3.U3Gate(alpha, beta, gamma) cnu3 = u3gate.control(num_ctrl) width = cnu3.num_qubits qr = QuantumRegister(width) qcnu3 = QuantumCircuit(qr) qcnu3.append(cnu3, qr, []) # U3 gate qu3 = QuantumCircuit(1) qu3.u3(alpha, beta, gamma, 0) # CU3 gate qcu3 = QuantumCircuit(2) qcu3.cu3(alpha, beta, gamma, 0, 1) # c-cu3 gate width = 3 qr = QuantumRegister(width) qc_cu3 = QuantumCircuit(qr) cu3gate = u3.CU3Gate(alpha, beta, gamma) c_cu3 = cu3gate.control(1) qc_cu3.append(c_cu3, qr, []) job = execute([qcnu3, qu3, qcu3, qc_cu3], BasicAer.get_backend('unitary_simulator'), basis_gates=['u1', 'u2', 'u3', 'id', 'cx']) result = job.result() # Circuit unitaries mat_cnu3 = result.get_unitary(0) mat_u3 = result.get_unitary(1) mat_cu3 = result.get_unitary(2) mat_c_cu3 = result.get_unitary(3) # Target Controlled-U3 unitary target_cnu3 = _compute_control_matrix(mat_u3, num_ctrl) target_cu3 = np.kron(mat_u3, np.diag([0, 1])) + np.kron(np.eye(2), np.diag([1, 0])) target_c_cu3 = np.kron(mat_cu3, np.diag([0, 1])) + np.kron(np.eye(4), np.diag([1, 0])) tests = [('check unitary of u3.control against tensored unitary of u3', target_cu3, mat_cu3), ('check unitary of cu3.control against tensored unitary of cu3', target_c_cu3, mat_c_cu3), ('check unitary of cnu3 against tensored unitary of u3', target_cnu3, mat_cnu3)] for itest in tests: info, target, decomp = itest[0], itest[1], itest[2] with self.subTest(i=info): self.log.info(info) self.assertTrue(matrix_equal(target, decomp, ignore_phase=True))
def test_multi_controlled_u1_matrix(self, num_controls): """Test the matrix representation of the multi-controlled CU1 gate. Based on the test moved here from Aqua: https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mcu1.py """ # registers for the circuit q_controls = QuantumRegister(num_controls) q_target = QuantumRegister(1) # iterate over all possible combinations of control qubits for ctrl_state in range(2 ** num_controls): bitstr = bin(ctrl_state)[2:].zfill(num_controls)[::-1] lam = 0.3165354 * pi qc = QuantumCircuit(q_controls, q_target) for idx, bit in enumerate(bitstr): if bit == '0': qc.x(q_controls[idx]) qc.mcu1(lam, q_controls, q_target[0]) # for idx in subset: for idx, bit in enumerate(bitstr): if bit == '0': qc.x(q_controls[idx]) backend = BasicAer.get_backend('unitary_simulator') simulated = execute(qc, backend).result().get_unitary(qc) base = U1Gate(lam).to_matrix() expected = _compute_control_matrix(base, num_controls, ctrl_state=ctrl_state) with self.subTest(msg='control state = {}'.format(ctrl_state)): self.assertTrue(matrix_equal(simulated, expected))
def test_relative_phase_toffoli_gates(self, num_ctrl_qubits): """Test the relative phase Toffoli gates. This test compares the matrix representation of the relative phase gate classes (i.e. RCCXGate().to_matrix()), the matrix obtained from the unitary simulator, and the exact version of the gate as obtained through `_compute_control_matrix`. """ # get target matrix (w/o relative phase) base_mat = XGate().to_matrix() target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits) # build the matrix for the relative phase toffoli using the unitary simulator circuit = QuantumCircuit(num_ctrl_qubits + 1) if num_ctrl_qubits == 2: circuit.rccx(0, 1, 2) else: # num_ctrl_qubits == 3: circuit.rcccx(0, 1, 2, 3) simulator = BasicAer.get_backend('unitary_simulator') simulated_mat = execute(circuit, simulator).result().get_unitary() # get the matrix representation from the class itself if num_ctrl_qubits == 2: repr_mat = RCCXGate().to_matrix() else: # num_ctrl_qubits == 3: repr_mat = RC3XGate().to_matrix() # test up to phase # note, that all entries may have an individual phase! (as opposed to a global phase) self.assertTrue(matrix_equal(np.abs(simulated_mat), target_mat)) # compare simulated matrix with the matrix representation provided by the class self.assertTrue(matrix_equal(simulated_mat, repr_mat))
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): r"""Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: invalid ctrl_state """ cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits) iso = isometry.Isometry(cmat, 0, 0) cunitary = ControlledGate('c-unitary', self.num_qubits + num_ctrl_qubits, cmat, definition=iso.definition, label=label) cunitary.base_gate = self.copy() cunitary.base_gate.label = self.label return cunitary
def test_open_controlled_unitary_z(self, num_ctrl_qubits, ctrl_state): """Test that UnitaryGate with control returns params.""" umat = np.array([[1, 0], [0, -1]]) ugate = UnitaryGate(umat) cugate = ugate.control(num_ctrl_qubits, ctrl_state=ctrl_state) ref_mat = _compute_control_matrix(umat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertEqual(Operator(cugate), Operator(ref_mat))
def test_multi_control_u1(self): """Test the matrix representation of the controlled and controlled-controlled U1 gate.""" import qiskit.circuit.library.standard_gates.u1 as u1 num_ctrl = 3 # U1 gate params theta = 0.2 # cnu1 gate u1gate = u1.U1Gate(theta) cnu1 = u1gate.control(num_ctrl) width = cnu1.num_qubits qr = QuantumRegister(width) qcnu1 = QuantumCircuit(qr) qcnu1.append(cnu1, qr, []) # U1 gate qu1 = QuantumCircuit(1) qu1.u1(theta, 0) # CU1 gate qcu1 = QuantumCircuit(2) qcu1.cu1(theta, 0, 1) # c-cu1 gate width = 3 qr = QuantumRegister(width) qc_cu1 = QuantumCircuit(qr) cu1gate = u1.CU1Gate(theta) c_cu1 = cu1gate.control(1) qc_cu1.append(c_cu1, qr, []) job = execute([qcnu1, qu1, qcu1, qc_cu1], BasicAer.get_backend('unitary_simulator'), basis_gates=['u1', 'u2', 'u3', 'id', 'cx']) result = job.result() # Circuit unitaries mat_cnu1 = result.get_unitary(0) # trace out ancillae mat_u1 = result.get_unitary(1) mat_cu1 = result.get_unitary(2) mat_c_cu1 = result.get_unitary(3) # Target Controlled-U1 unitary target_cnu1 = _compute_control_matrix(mat_u1, num_ctrl) target_cu1 = np.kron(mat_u1, np.diag([0, 1])) + np.kron(np.eye(2), np.diag([1, 0])) target_c_cu1 = np.kron(mat_cu1, np.diag([0, 1])) + np.kron(np.eye(4), np.diag([1, 0])) tests = [('check unitary of u1.control against tensored unitary of u1', target_cu1, mat_cu1), ('check unitary of cu1.control against tensored unitary of cu1', target_c_cu1, mat_c_cu1), ('check unitary of cnu1 against tensored unitary of u1', target_cnu1, mat_cnu1)] for itest in tests: info, target, decomp = itest[0], itest[1], itest[2] with self.subTest(i=info): self.log.info(info) self.assertTrue(matrix_equal(target, decomp, ignore_phase=True))
def test_multi_control_toffoli_matrix_clean_ancillas(self, num_controls): """Test the multi-control Toffoli gate with clean ancillas. Based on the test moved here from Aqua: https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mct.py """ # set up circuit q_controls = QuantumRegister(num_controls) q_target = QuantumRegister(1) qc = QuantumCircuit(q_controls, q_target) if num_controls > 2: num_ancillas = num_controls - 2 q_ancillas = QuantumRegister(num_controls) qc.add_register(q_ancillas) else: num_ancillas = 0 q_ancillas = None # apply hadamard on control qubits and toffoli gate qc.mct(q_controls, q_target[0], q_ancillas, mode='basic') # execute the circuit and obtain statevector result backend = BasicAer.get_backend('unitary_simulator') simulated = execute(qc, backend).result().get_unitary(qc) # compare to expectation if num_ancillas > 0: simulated = simulated[:2**(num_controls + 1), :2**(num_controls + 1)] base = XGate().to_matrix() expected = _compute_control_matrix(base, num_controls) self.assertTrue(matrix_equal(simulated, expected))
def __array__(self, dtype=None): """Return a numpy.array for the C4X gate.""" mat = _compute_control_matrix(self.base_gate.to_matrix(), self.num_ctrl_qubits, ctrl_state=self.ctrl_state) if dtype: return numpy.asarray(mat, dtype=dtype) return mat
def test_controlled_random_unitary(self, num_ctrl_qubits): """Test the matrix data of an Operator based on a random UnitaryGate.""" num_target = 2 base_gate = random_unitary(2**num_target).to_instruction() base_mat = base_gate.to_matrix() cgate = base_gate.control(num_ctrl_qubits) test_op = Operator(cgate) cop_mat = _compute_control_matrix(base_mat, num_ctrl_qubits) self.assertTrue(matrix_equal(cop_mat, test_op.data, ignore_phase=True))
def test_multi_controlled_y_rotation_matrix_basic_mode( self, num_controls, use_basis_gates): """Test the multi controlled Y rotation using the mode 'basic'. Based on the test moved here from Aqua: https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mcr.py """ # get the number of required ancilla qubits if num_controls <= 2: num_ancillas = 0 else: num_ancillas = num_controls - 2 q_controls = QuantumRegister(num_controls) q_target = QuantumRegister(1) for ctrl_state in range(2**num_controls): bitstr = bin(ctrl_state)[2:].zfill(num_controls)[::-1] theta = 0.871236 * pi if num_ancillas > 0: q_ancillas = QuantumRegister(num_ancillas) qc = QuantumCircuit(q_controls, q_target, q_ancillas) else: qc = QuantumCircuit(q_controls, q_target) q_ancillas = None for idx, bit in enumerate(bitstr): if bit == '0': qc.x(q_controls[idx]) qc.mcry(theta, q_controls, q_target[0], q_ancillas, mode='basic', use_basis_gates=use_basis_gates) for idx, bit in enumerate(bitstr): if bit == '0': qc.x(q_controls[idx]) rot_mat = RYGate(theta).to_matrix() backend = BasicAer.get_backend('unitary_simulator') simulated = execute(qc, backend).result().get_unitary(qc) if num_ancillas > 0: simulated = simulated[:2**(num_controls + 1), :2**(num_controls + 1)] expected = _compute_control_matrix(rot_mat, num_controls, ctrl_state=ctrl_state) with self.subTest(msg='control state = {}'.format(ctrl_state)): self.assertTrue(matrix_equal(simulated, expected))
def test_controlled_controlled_unitary(self): """Test that global phase in iso decomposition of unitary is handled.""" umat = np.array([[1, 0], [0, -1]]) ugate = UnitaryGate(umat) cugate = ugate.control() ccugate = cugate.control() ccugate2 = ugate.control(2) ref_mat = _compute_control_matrix(umat, 2) self.assertTrue(Operator(ccugate2).equiv(Operator(ref_mat))) self.assertTrue(Operator(ccugate).equiv(Operator(ccugate2)))
def test_multi_control_u3(self): """Test the matrix representation of the controlled and controlled-controlled U3 gate.""" import qiskit.circuit.library.standard_gates.u3 as u3 num_ctrl = 3 # U3 gate params alpha, beta, gamma = 0.2, 0.3, 0.4 # cnu3 gate u3gate = u3.U3Gate(alpha, beta, gamma) cnu3 = u3gate.control(num_ctrl) width = cnu3.num_qubits qr = QuantumRegister(width) qcnu3 = QuantumCircuit(qr) qcnu3.append(cnu3, qr, []) # U3 gate qu3 = QuantumCircuit(1) qu3.u3(alpha, beta, gamma, 0) # CU3 gate qcu3 = QuantumCircuit(2) qcu3.cu3(alpha, beta, gamma, 0, 1) # c-cu3 gate width = 3 qr = QuantumRegister(width) qc_cu3 = QuantumCircuit(qr) cu3gate = u3.CU3Gate(alpha, beta, gamma) c_cu3 = cu3gate.control(1) qc_cu3.append(c_cu3, qr, []) # Circuit unitaries mat_cnu3 = Operator(qcnu3).data mat_u3 = Operator(qu3).data mat_cu3 = Operator(qcu3).data mat_c_cu3 = Operator(qc_cu3).data # Target Controlled-U3 unitary target_cnu3 = _compute_control_matrix(mat_u3, num_ctrl) target_cu3 = np.kron(mat_u3, np.diag([0, 1])) + np.kron(np.eye(2), np.diag([1, 0])) target_c_cu3 = np.kron(mat_cu3, np.diag([0, 1])) + np.kron(np.eye(4), np.diag([1, 0])) tests = [('check unitary of u3.control against tensored unitary of u3', target_cu3, mat_cu3), ('check unitary of cu3.control against tensored unitary of cu3', target_c_cu3, mat_c_cu3), ('check unitary of cnu3 against tensored unitary of u3', target_cnu3, mat_cnu3)] for itest in tests: info, target, decomp = itest[0], itest[1], itest[2] with self.subTest(i=info): self.assertTrue(matrix_equal(target, decomp, ignore_phase=True, atol=1e-8, rtol=1e-5))
def test_multi_controlled_rotation_gate_matrices(self, num_controls, base_gate_name, use_basis_gates): """Test the multi controlled rotation gates without ancillas. Based on the test moved here from Aqua: https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mcr.py """ q_controls = QuantumRegister(num_controls) q_target = QuantumRegister(1) # iterate over all possible combinations of control qubits for ctrl_state in range(2**num_controls): bitstr = bin(ctrl_state)[2:].zfill(num_controls)[::-1] theta = 0.871236 * pi qc = QuantumCircuit(q_controls, q_target) for idx, bit in enumerate(bitstr): if bit == '0': qc.x(q_controls[idx]) # call mcrx/mcry/mcrz if base_gate_name == 'y': qc.mcry(theta, q_controls, q_target[0], None, mode='noancilla', use_basis_gates=use_basis_gates) else: # case 'x' or 'z' only support the noancilla mode and do not have this keyword getattr(qc, 'mcr' + base_gate_name)( theta, q_controls, q_target[0], use_basis_gates=use_basis_gates) for idx, bit in enumerate(bitstr): if bit == '0': qc.x(q_controls[idx]) backend = BasicAer.get_backend('unitary_simulator') simulated = execute(qc, backend).result().get_unitary(qc) if base_gate_name == 'x': rot_mat = RXGate(theta).to_matrix() elif base_gate_name == 'y': rot_mat = RYGate(theta).to_matrix() else: # case 'z' rot_mat = U1Gate(theta).to_matrix() expected = _compute_control_matrix(rot_mat, num_controls, ctrl_state=ctrl_state) with self.subTest(msg='control state = {}'.format(ctrl_state)): self.assertTrue(matrix_equal(simulated, expected))
def test_controlled_global_phase(self, num_ctrl_qubits): """ Test controlled global phase on base gate. """ theta = pi / 4 circ = QuantumCircuit(2, global_phase=theta) base_gate = circ.to_gate() base_mat = Operator(base_gate).data target = _compute_control_matrix(base_mat, num_ctrl_qubits) cgate = base_gate.control(num_ctrl_qubits) ccirc = circ.control(num_ctrl_qubits) self.assertEqual(Operator(cgate), Operator(target)) self.assertEqual(Operator(ccirc), Operator(target))
def test_rz_composite_global_phase(self, num_ctrl_qubits): """ Test controlling CX with global phase """ theta = pi / 4 circ = QuantumCircuit(2, global_phase=theta) circ.rz(0.1, 0) circ.rz(0.2, 1) ccirc = circ.control(num_ctrl_qubits) base_gate = circ.to_gate() cgate = base_gate.control(num_ctrl_qubits) base_mat = Operator(base_gate).data target = _compute_control_matrix(base_mat, num_ctrl_qubits) self.assertEqual(Operator(cgate), Operator(target)) self.assertEqual(Operator(ccirc), Operator(target))
def test_controlled_standard_gates(self, num_ctrl_qubits, gate_class): """Test controlled versions of all standard gates.""" theta = pi / 2 ctrl_state_ones = 2**num_ctrl_qubits - 1 ctrl_state_zeros = 0 ctrl_state_mixed = ctrl_state_ones >> int(num_ctrl_qubits / 2) numargs = len(_get_free_params(gate_class)) args = [theta] * numargs if gate_class in [MSGate, Barrier]: args[0] = 2 elif gate_class in [MCU1Gate]: args[1] = 2 elif issubclass(gate_class, MCXGate): args = [5] gate = gate_class(*args) for ctrl_state in { ctrl_state_ones, ctrl_state_zeros, ctrl_state_mixed }: with self.subTest(i='{0}, ctrl_state={1}'.format( gate_class.__name__, ctrl_state)): if hasattr( gate, 'num_ancilla_qubits') and gate.num_ancilla_qubits > 0: # skip matrices that include ancilla qubits continue try: cgate = gate.control(num_ctrl_qubits, ctrl_state=ctrl_state) except (AttributeError, QiskitError): # 'object has no attribute "control"' # skipping Id and Barrier continue if gate.name == 'rz': iden = Operator.from_label('I') zgen = Operator.from_label('Z') base_mat = (np.cos(0.5 * theta) * iden - 1j * np.sin(0.5 * theta) * zgen).data else: base_mat = Operator(gate).data target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=ctrl_state) self.assertTrue( matrix_equal(Operator(cgate).data, target_mat, ignore_phase=True))
def test_multi_control_toffoli_matrix_noancilla_dirty_ancillas(self, num_controls): """Test the multi-control Toffoli gate with dirty ancillas (noancilla). Based on the test moved here from Aqua: https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mct.py """ q_controls = QuantumRegister(num_controls) q_target = QuantumRegister(1) qc = QuantumCircuit(q_controls, q_target) qc.mct(q_controls, q_target[0], None, mode='noancilla') simulated = execute(qc, BasicAer.get_backend('unitary_simulator')).result().get_unitary(qc) base = XGate().to_matrix() expected = _compute_control_matrix(base, num_controls) self.assertTrue(matrix_equal(simulated, expected, atol=1e-8))
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): r"""Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: invalid ctrl_state """ cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits) return UnitaryGate(cmat, label=label)
def test_controlled_unitary(self, num_ctrl_qubits): """Test the matrix data of an Operator, which is based on a controlled gate.""" num_target = 1 q_target = QuantumRegister(num_target) qc1 = QuantumCircuit(q_target) # for h-rx(pi/2) theta, phi, lamb = 1.57079632679490, 0.0, 4.71238898038469 qc1.u3(theta, phi, lamb, q_target[0]) base_gate = qc1.to_gate() # get UnitaryGate version of circuit base_op = Operator(qc1) base_mat = base_op.data cgate = base_gate.control(num_ctrl_qubits) test_op = Operator(cgate) cop_mat = _compute_control_matrix(base_mat, num_ctrl_qubits) self.assertTrue(is_unitary_matrix(base_mat)) self.assertTrue(matrix_equal(cop_mat, test_op.data, ignore_phase=True))
def test_open_controlled_to_matrix(self, gate_class, ctrl_state): """Test open controlled to_matrix.""" num_free_params = len(_get_free_params(gate_class.__init__, ignore=['self'])) free_params = [0.1 * i for i in range(1, num_free_params + 1)] if gate_class in [MCU1Gate]: free_params[1] = 3 elif gate_class in [MCXGate]: free_params[0] = 3 cgate = gate_class(*free_params) cgate.ctrl_state = ctrl_state base_mat = Operator(cgate.base_gate).data target = _compute_control_matrix(base_mat, cgate.num_ctrl_qubits, ctrl_state=ctrl_state) try: actual = cgate.to_matrix() except CircuitError as cerr: self.skipTest(cerr) self.assertTrue(np.allclose(actual, target))
def test_cx_global_phase(self): """ Test controlling CX with global phase """ theta = pi / 2 circ = QuantumCircuit(2, global_phase=theta) circ.cx(0, 1) cx = circ.to_gate() self.assertNotEqual(Operator(CXGate()), Operator(cx)) ccx = cx.control(1) base_mat = Operator(cx).data target = _compute_control_matrix(base_mat, 1) self.assertEqual(Operator(ccx), Operator(target)) expected = QuantumCircuit(*ccx.definition.qregs) expected.ccx(0, 1, 2) expected.u1(theta, 0) self.assertEqual(ccx.definition, expected)
def test_single_controlled_composite_gate(self): """Test a singly controlled composite gate.""" num_ctrl = 1 # create composite gate sub_q = QuantumRegister(2) cgate = QuantumCircuit(sub_q, name='cgate') cgate.h(sub_q[0]) cgate.cx(sub_q[0], sub_q[1]) num_target = cgate.width() gate = cgate.to_gate() cont_gate = gate.control(num_ctrl_qubits=num_ctrl) control = QuantumRegister(num_ctrl, 'control') target = QuantumRegister(num_target, 'target') qc = QuantumCircuit(control, target) qc.append(cont_gate, control[:] + target[:]) op_mat = Operator(cgate).data cop_mat = _compute_control_matrix(op_mat, num_ctrl) ref_mat = Operator(qc).data self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True))
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): r"""Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: Invalid ctrl_state. ExtensionError: Non-unitary controlled unitary. """ cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits, ctrl_state=ctrl_state) iso = isometry.Isometry(cmat, 0, 0) cunitary = ControlledGate('c-unitary', num_qubits=self.num_qubits + num_ctrl_qubits, params=[cmat], label=label, num_ctrl_qubits=num_ctrl_qubits, definition=iso.definition, ctrl_state=ctrl_state) from qiskit.quantum_info import Operator # hack to correct global phase; should fix to prevent need for correction here pmat = (Operator(iso.inverse()).data @ cmat) diag = numpy.diag(pmat) if not numpy.allclose(diag, diag[0]): raise ExtensionError('controlled unitary generation failed') phase = numpy.angle(diag[0]) if phase: qreg = cunitary.definition.qregs[0] cunitary.definition.u3(numpy.pi, phase, phase - numpy.pi, qreg[0]) cunitary.definition.u3(numpy.pi, 0, numpy.pi, qreg[0]) cunitary.base_gate = self.copy() cunitary.base_gate.label = self.label return cunitary
def test_single_controlled_composite_gate(self): """Test a singly controlled composite gate.""" num_ctrl = 1 # create composite gate sub_q = QuantumRegister(2) cgate = QuantumCircuit(sub_q, name='cgate') cgate.h(sub_q[0]) cgate.cx(sub_q[0], sub_q[1]) num_target = cgate.width() gate = cgate.to_gate() cont_gate = gate.control(num_ctrl_qubits=num_ctrl) control = QuantumRegister(num_ctrl, 'control') target = QuantumRegister(num_target, 'target') qc = QuantumCircuit(control, target) qc.append(cont_gate, control[:] + target[:]) simulator = BasicAer.get_backend('unitary_simulator') op_mat = execute(cgate, simulator).result().get_unitary(0) cop_mat = _compute_control_matrix(op_mat, num_ctrl) ref_mat = execute(qc, simulator).result().get_unitary(0) self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True))
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): """Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: Invalid ctrl_state. ExtensionError: Non-unitary controlled unitary. """ mat = self.to_matrix() cmat = _compute_control_matrix(mat, num_ctrl_qubits, ctrl_state=None) iso = isometry.Isometry(cmat, 0, 0) cunitary = ControlledGate( "c-unitary", num_qubits=self.num_qubits + num_ctrl_qubits, params=[mat], label=label, num_ctrl_qubits=num_ctrl_qubits, definition=iso.definition, ctrl_state=ctrl_state, base_gate=self.copy(), ) from qiskit.quantum_info import Operator # hack to correct global phase; should fix to prevent need for correction here pmat = Operator(iso.inverse()).data @ cmat diag = numpy.diag(pmat) if not numpy.allclose(diag, diag[0]): raise ExtensionError("controlled unitary generation failed") phase = numpy.angle(diag[0]) if phase: # need to apply to _definition since open controls creates temporary definition cunitary._definition.global_phase = phase return cunitary
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): r"""Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: invalid ctrl_state """ from qiskit.extensions.quantum_initializer.isometry import Isometry cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits) iso = Isometry(cmat, 0, 0) return ControlledGate('c-unitary', self.num_qubits + num_ctrl_qubits, cmat, definition=iso.definition, label=label)