def test_transpose(self, label): """Test transpose method.""" value = Pauli(label).transpose() target = operator_from_label(label).transpose() self.assertEqual(Operator(value), target)
def test_tuple(self): """Test creation from tuples.""" pauli = Pauli(x=(1, 0), z=(1, 0)) self.check(pauli)
def setUp(self): """Setup.""" super().setUp() z = np.asarray([1, 0, 1, 0]).astype(np.bool) x = np.asarray([1, 1, 0, 0]).astype(np.bool) self.ref_p = Pauli(z, x) self.ref_label = 'IZXY' self.ref_matrix = np.array( [[ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 1.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 1.j, 0. + 0.j, 0. + 0.j ], [ 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. + 0.j, 0. - 1.j, 0. + 0.j, 0. + 0.j, 0. + 0.j ]])
def test_exact_two_qubit_cnot_decompose_paulis(self): """Verify exact CNOT decomposition for Paulis """ pauli_xz = Pauli(label='XZ') unitary = Operator(pauli_xz) self.check_exact_decomposition(unitary.data, two_qubit_cnot_decompose)
def test_ndarray_int(self): """Test creation from np.int.""" x = np.asarray([2, 0]).astype(np.int) z = np.asarray([2, 0]).astype(np.int) pauli = Pauli(x=x, z=z) self.check(pauli)
def pauli_z(i): return Pauli("I" * i + "Z" + "I" * (nqubits - i - 1))
def pauli_x(i): return Pauli("I" * i + "X" + "I" * (nqubits - i - 1))
def test_negate(self, phase): """Test negate method""" op = Pauli(([False], [True], phase)) neg = -op self.assertTrue(op.equiv(neg)) self.assertEqual(neg.phase, (op.phase + 2) % 4)
def test_anticommutes(self, p1, p2): """Test anticommutes method""" P1 = Pauli(p1) P2 = Pauli(p2) self.assertEqual(P1.anticommutes(P2), P1.dot(P2) == -P2.dot(P1))
def test_multiply(self, val): """Test multiply method.""" op = val * Pauli(([True, True], [False, False], 0)) phase = (-1j)**op.phase self.assertEqual(phase, val)
def test_multiply_except(self): """Test multiply method raises exceptions.""" op = Pauli('XYZ') self.assertRaises(QiskitError, op._multiply, 2)
def test_power(self, label): """Test power method.""" iden = Pauli('II') op = Pauli(label) self.assertTrue(op**2, iden)
def test_inverse(self, label): """Test inverse method.""" pauli = Pauli(label) value = pauli.inverse() target = pauli.adjoint() self.assertEqual(value, target)
def test_adjoint(self, label): """Test adjoint method.""" value = Pauli(label).adjoint() target = operator_from_label(label).adjoint() self.assertEqual(Operator(value), target)
def map(self, second_q_op: FermionicOp) -> PauliSumOp: # number of modes/sites for the BK transform (= number of fermionic modes) nmodes = second_q_op.register_length def parity_set(j, n): """ Computes the parity set of the j-th orbital in n modes. Args: j (int) : the orbital index n (int) : the total number of modes Returns: numpy.ndarray: Array of mode indices """ indices = np.array([]) if n % 2 != 0: return indices if j < n / 2: indices = np.append(indices, parity_set(j, n / 2)) else: indices = np.append( indices, np.append(parity_set(j - n / 2, n / 2) + n / 2, n / 2 - 1)) return indices def update_set(j, n): """ Computes the update set of the j-th orbital in n modes. Args: j (int) : the orbital index n (int) : the total number of modes Returns: numpy.ndarray: Array of mode indices """ indices = np.array([]) if n % 2 != 0: return indices if j < n / 2: indices = np.append(indices, np.append(n - 1, update_set(j, n / 2))) else: indices = np.append(indices, update_set(j - n / 2, n / 2) + n / 2) return indices def flip_set(j, n): """ Computes the flip set of the j-th orbital in n modes. Args: j (int) : the orbital index n (int) : the total number of modes Returns: numpy.ndarray: Array of mode indices """ indices = np.array([]) if n % 2 != 0: return indices if j < n / 2: indices = np.append(indices, flip_set(j, n / 2)) elif n / 2 <= j < n - 1: indices = np.append(indices, flip_set(j - n / 2, n / 2) + n / 2) else: indices = np.append( np.append(indices, flip_set(j - n / 2, n / 2) + n / 2), n / 2 - 1) return indices pauli_table = [] # FIND BINARY SUPERSET SIZE bin_sup = 1 # pylint: disable=comparison-with-callable while nmodes > np.power(2, bin_sup): bin_sup += 1 # DEFINE INDEX SETS FOR EVERY FERMIONIC MODE update_sets = [] update_pauli = [] parity_sets = [] parity_pauli = [] flip_sets = [] remainder_sets = [] remainder_pauli = [] for j in range(nmodes): update_sets.append(update_set(j, np.power(2, bin_sup))) update_sets[j] = update_sets[j][update_sets[j] < nmodes] parity_sets.append(parity_set(j, np.power(2, bin_sup))) parity_sets[j] = parity_sets[j][parity_sets[j] < nmodes] flip_sets.append(flip_set(j, np.power(2, bin_sup))) flip_sets[j] = flip_sets[j][flip_sets[j] < nmodes] remainder_sets.append(np.setdiff1d(parity_sets[j], flip_sets[j])) update_pauli.append( Pauli((np.zeros(nmodes, dtype=bool), np.zeros(nmodes, dtype=bool)))) parity_pauli.append( Pauli((np.zeros(nmodes, dtype=bool), np.zeros(nmodes, dtype=bool)))) remainder_pauli.append( Pauli((np.zeros(nmodes, dtype=bool), np.zeros(nmodes, dtype=bool)))) for k in range(nmodes): if np.in1d(k, update_sets[j]): update_pauli[j].x[k] = True if np.in1d(k, parity_sets[j]): parity_pauli[j].z[k] = True if np.in1d(k, remainder_sets[j]): remainder_pauli[j].z[k] = True x_j = Pauli((np.zeros(nmodes, dtype=bool), np.zeros(nmodes, dtype=bool))) x_j.x[j] = True y_j = Pauli((np.zeros(nmodes, dtype=bool), np.zeros(nmodes, dtype=bool))) y_j.z[j] = True y_j.x[j] = True pauli_table.append((parity_pauli[j] & x_j & update_pauli[j], remainder_pauli[j] & y_j & update_pauli[j])) return QubitMapper.mode_based_mapping(second_q_op, pauli_table)
def test_labels(self, label): """Test round trip label conversion""" pauli = Pauli(label) self.assertEqual(Pauli(str(pauli)), pauli)
def _pauli_id(n_qubits: int) -> SparsePauliOp: """Return the identity for `SparsePauliOp` on `n_qubits` qubits.""" return SparsePauliOp(Pauli((np.zeros(n_qubits, dtype=bool), np.zeros(n_qubits, dtype=bool))))
def test_to_operator(self, label): """Test Pauli operator conversion""" value = Operator(Pauli(label)) target = operator_from_label(label) self.assertEqual(value, target)
def _linear_encoding(self, spin: Union[Fraction, float]) -> List[PauliSumOp]: """ Generates a 'linear_encoding' of the spin S operators 'X', 'Y', 'Z' and 'identity' to qubit operators (linear combinations of pauli strings). In this 'linear_encoding' each individual spin S system is represented via 2S+1 qubits and the state |s> is mapped to the state |00...010..00>, where the s-th qubit is in state 1. Returns: The 4-element list of transformed spin S 'X', 'Y', 'Z' and 'identity' operators. I.e. spin_op_encoding[0]` corresponds to the linear combination of pauli strings needed to represent the embedded 'X' operator """ spin_op_encoding: List[PauliSumOp] = [] dspin = int(2 * spin + 1) nqubits = dspin # quick functions to generate a pauli with X / Y / Z at location `i` pauli_id = Pauli("I" * nqubits) def pauli_x(i): return Pauli("I" * i + "X" + "I" * (nqubits - i - 1)) def pauli_y(i): return Pauli("I" * i + "Y" + "I" * (nqubits - i - 1)) def pauli_z(i): return Pauli("I" * i + "Z" + "I" * (nqubits - i - 1)) # 1. build the non-diagonal X operator x_summands = [] for i, coeff in enumerate(np.diag(SpinOp("X", spin=spin).to_matrix(), 1)): x_summands.append( PauliSumOp( coeff / 2.0 * SparsePauliOp(pauli_x(i).dot(pauli_x(i + 1))) + coeff / 2.0 * SparsePauliOp(pauli_y(i).dot(pauli_y(i + 1))) ) ) spin_op_encoding.append(reduce(operator.add, x_summands)) # 2. build the non-diagonal Y operator y_summands = [] for i, coeff in enumerate(np.diag(SpinOp("Y", spin=spin).to_matrix(), 1)): y_summands.append( PauliSumOp( -1j * coeff / 2.0 * SparsePauliOp(pauli_x(i).dot(pauli_y(i + 1))) + 1j * coeff / 2.0 * SparsePauliOp(pauli_y(i).dot(pauli_x(i + 1))) ) ) spin_op_encoding.append(reduce(operator.add, y_summands)) # 3. build the diagonal Z z_summands = [] for i, coeff in enumerate(np.diag(SpinOp("Z", spin=spin).to_matrix())): # get the first upper diagonal of coeff. z_summands.append( PauliSumOp( coeff / 2.0 * SparsePauliOp(pauli_z(i)) + coeff / 2.0 * SparsePauliOp(pauli_id) ) ) z_operator = reduce(operator.add, z_summands) spin_op_encoding.append(z_operator) # 4. add the identity operator spin_op_encoding.append(PauliSumOp(1.0 * SparsePauliOp(pauli_id))) # return the lookup table for the transformed XYZI operators return spin_op_encoding
def test_to_matrix_sparse(self, label): """Test Pauli operator conversion""" spmat = Pauli(label).to_matrix(sparse=True) value = Operator(spmat.todense()) target = operator_from_label(label) self.assertEqual(value, target)
def pauli_y(i): return Pauli("I" * i + "Y" + "I" * (nqubits - i - 1))
def test_to_instruction(self, label): """Test Pauli to instruction""" pauli = Pauli(label) value = Operator(pauli.to_instruction()) target = Operator(pauli) self.assertEqual(value, target)
def test_ndarray_bool(self): """Test creation from np.bool.""" x = np.asarray([1, 0]).astype(np.bool) z = np.asarray([1, 0]).astype(np.bool) pauli = Pauli(x=x, z=z) self.check(pauli)
def test_init_single_pauli_gate(self, gate, label): """Test initialization from Pauli basis gates""" self.assertEqual(str(Pauli(gate)), label)
def test_list(self): """Test creation from lists.""" pauli = Pauli(x=[1, 0], z=[1, 0]) self.check(pauli)
def test_init_pauli_gate(self, label): """Test initialization from Pauli basis gates""" pauli = Pauli(PauliGate(label)) self.assertEqual(str(pauli), label)
def test_mix(self): """Test creation from tuples and list.""" pauli = Pauli(x=(1, 0), z=[1, 0]) self.check(pauli)
def test_len(self, label): """Test __len__ method""" self.assertEqual(len(Pauli(label)), len(label))
def pauli_y(i): return Pauli('I' * i + 'Y' + 'I' * (nqubits - i - 1))
def test_conjugate(self, label): """Test conjugate method.""" value = Pauli(label).conjugate() target = operator_from_label(label).conjugate() self.assertEqual(Operator(value), target)