def number_operator(fer_op, mode_number=None): """Find the qubit operator for the number operator in bravyi_kitaev_fast representation. Args: fer_op (FermionicOperator): the fermionic operator in the second quanitzed form mode_number (int): index, it corresponds to the mode for which number operator is required. Returns: Operator: the qubit operator """ modes = fer_op.h1.modes edge_list = bravyi_kitaev_fast_edge_list(fer_op) num_qubits = edge_list.shape[1] num_operator = Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) if mode_number is None: for i in range(modes): num_operator -= edge_operator_bi(edge_list, i) num_operator += Operator( paulis=[[1.0 * modes, Pauli.from_label('I' * num_qubits)]]) else: num_operator += ( Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) - edge_operator_bi(edge_list, mode_number)) num_operator.scaling_coeff(0.5) return num_operator
def number_operator(fer_op, mode_number=None): """Find the number operator in BKSF representation. This operator can be used to examine the number of particle in a given eigenstate. If `mode_number` is None, it checks how many particles in the eigenstate. If `mode_number` is not None, it will only check whether or not that particle at `mode_number` in the eigenstate. Args: fer_op (FermionicOperator): the fermionic operator in the second quanitzed form mode_number (int): index, it corresponds to the mode for which number operator is required. Returns: Operator: the qubit operator """ modes = fer_op.h1.modes edge_list = bksf_edge_list(fer_op) num_qubits = edge_list.shape[1] num_operator = Operator(paulis=[[1.0, label_to_pauli('I' * num_qubits)]]) if mode_number is None: for i in range(modes): num_operator -= edge_operator_bi(edge_list, i) num_operator += Operator( paulis=[[1.0 * modes, label_to_pauli('I' * num_qubits)]]) else: num_operator += ( Operator(paulis=[[1.0, label_to_pauli('I' * num_qubits)]]) - edge_operator_bi(edge_list, mode_number)) num_operator.scaling_coeff(0.5) return num_operator
def vacuum_operator(fer_op): """Use the stabilizers to find the vacuum state in bravyi_kitaev_fast. Args: fer_op (FermionicOperator): the fermionic operator in the second quanitzed form Returns: Operator: the qubit operator """ edge_list = bravyi_kitaev_fast_edge_list(fer_op) num_qubits = edge_list.shape[1] vac_operator = Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) g = networkx.Graph() g.add_edges_from(tuple(edge_list.transpose())) stabs = np.asarray(networkx.cycle_basis(g)) for stab in stabs: a = Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) stab = np.asarray(stab) for i in range(np.size(stab)): a = a * edge_operator_aij(edge_list, stab[i], stab[(i + 1) % np.size(stab)]) a.scaling_coeff(1j) a += Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) vac_operator = vac_operator * a vac_operator.scaling_coeff(np.sqrt(2)) return vac_operator
def vacuum_operator(fer_op): """Use the stabilizers to find the vacuum state in BKSF. This operator can be used to generate the vaccum state for BKSF mapping. Upon having this operator, operate it on `orignal` vaccum state |000...>, and resulted state is the vacuum state for bksf mapping. Args: fer_op (FermionicOperator): the fermionic operator in the second quanitzed form Returns: Operator: the qubit operator """ edge_list = bksf_edge_list(fer_op) num_qubits = edge_list.shape[1] vac_operator = Operator(paulis=[[1.0, label_to_pauli('I' * num_qubits)]]) g = networkx.Graph() g.add_edges_from(tuple(edge_list.transpose())) stabs = np.asarray(networkx.cycle_basis(g)) for stab in stabs: a = Operator(paulis=[[1.0, label_to_pauli('I' * num_qubits)]]) stab = np.asarray(stab) for i in range(np.size(stab)): a = a * edge_operator_aij(edge_list, stab[i], stab[(i + 1) % np.size(stab)]) a.scaling_coeff(1j) a += Operator(paulis=[[1.0, label_to_pauli('I' * num_qubits)]]) vac_operator = vac_operator * a vac_operator.scaling_coeff(np.sqrt(2)) return vac_operator
def stabilizers(fer_op): edge_list = bravyi_kitaev_fast_edge_list(fer_op) num_qubits = edge_list.shape[1] # vac_operator = Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) g = networkx.Graph() g.add_edges_from(tuple(edge_list.transpose())) stabs = np.asarray(networkx.cycle_basis(g)) stabilizers = [] for stab in stabs: a = Operator(paulis=[[1.0, Pauli.from_label('I' * num_qubits)]]) stab = np.asarray(stab) for i in range(np.size(stab)): a = a * edge_operator_aij(edge_list, stab[i], stab[(i + 1) % np.size(stab)]) a.scaling_coeff(1j) stabilizers.append(a) return stabilizers
def test_scaling_coeff(self): """ test scale """ pauli_a = 'IXYZ' pauli_b = 'ZYIX' coeff_a = 0.5 coeff_b = 0.5 pauli_term_a = [coeff_a, label_to_pauli(pauli_a)] pauli_term_b = [coeff_b, label_to_pauli(pauli_b)] opA = Operator(paulis=[pauli_term_a]) opB = Operator(paulis=[pauli_term_b]) opA += opB self.assertEqual(2, len(opA.paulis)) opA.scaling_coeff(0.7) self.assertEqual(2, len(opA.paulis)) self.assertEqual(0.35, opA.paulis[0][0])
def test_scaling_coeff(self): """ test scale """ pauli_a = 'IXYZ' pauli_b = 'ZYIX' coeff_a = 0.5 coeff_b = 0.5 pauli_term_a = [coeff_a, Pauli.from_label(pauli_a)] pauli_term_b = [coeff_b, Pauli.from_label(pauli_b)] op_a = Operator(paulis=[pauli_term_a]) op_b = Operator(paulis=[pauli_term_b]) op_a += op_b self.assertEqual(2, len(op_a.paulis)) op_a.scaling_coeff(0.7) self.assertEqual(2, len(op_a.paulis)) self.assertEqual(0.35, op_a.paulis[0][0])
def test_negation_operator(self): paulis = ['IXYZ', 'XXZY', 'IIZZ', 'XXYY', 'ZZXX', 'YYYY'] coeffs = [0.2, 0.6, 0.8, -0.2, -0.6, -0.8] op1 = Operator(paulis=[]) for coeff, pauli in zip(coeffs, paulis): pauli_term = [coeff, label_to_pauli(pauli)] op1 += Operator(paulis=[pauli_term]) paulis = ['IXYZ', 'XXZY', 'IIZZ', 'XXYY', 'ZZXX', 'YYYY'] coeffs = [-0.2, -0.6, -0.8, 0.2, 0.6, 0.8] op2 = Operator(paulis=[]) for coeff, pauli in zip(coeffs, paulis): pauli_term = [coeff, label_to_pauli(pauli)] op2 += Operator(paulis=[pauli_term]) self.assertNotEqual(op1, op2) self.assertEqual(op1, -op2) self.assertEqual(-op1, op2) op1.scaling_coeff(-1.0) self.assertEqual(op1, op2)