def get_ccsd(n_qubit, n_electron, param_list): ''' coupled cluster single and double model. J-W transform on CCSD, get paulioperator ''' if n_electron > n_qubit: assert False elif n_electron == n_qubit: return PauliOperator(dict()) param_n = 0 # ccsd is each electron jump to the excited level, and also each two result_op = PauliOperator(dict()) for i in range(n_electron): for ex in range(n_electron, n_qubit): result_op += get_fermion_jordan_wigner( 'c', ex) * get_fermion_jordan_wigner('a', i) * param_list[param_n] param_n += 1 for i in range(n_electron): for j in range(i + 1, n_electron): for ex1 in range(n_electron, n_qubit): for ex2 in range(ex1 + 1, n_qubit): result_op+=get_fermion_jordan_wigner('c',ex2)* \ get_fermion_jordan_wigner('c',ex1)* \ get_fermion_jordan_wigner('a',j)* \ get_fermion_jordan_wigner('a',i)* param_list[param_n] param_n += 1 return result_op
def hamiltonian_operator_overload(): op_dict={'X2 z1 y3 x4':5.0, "z0 X2 y5":8} op_dict2={'X2 z0 y3 x4 y1':-5} m1=PauliOperator(op_dict) m2=PauliOperator(op_dict2) print(m1) print(m2) m1+=m2 m1.arrange() print(m1)
def get_ccsd_n_term(n_qubit, n_electron): ''' coupled cluster single and double model. e.g. 4 qubits, 2 electrons then 0 and 1 are occupied,just consider 0->2,0->3,1->2,1->3,01->23 ''' if n_electron > n_qubit: assert False elif n_electron == n_qubit: return 0 param_n = 0 # ccsd is each electron jump to the excited level, and also each two result_op = PauliOperator(dict()) for i in range(n_electron): for ex in range(n_electron, n_qubit): param_n += 1 for i in range(n_electron): for j in range(i + 1, n_electron): for ex1 in range(n_electron, n_qubit): for ex2 in range(ex1 + 1, n_qubit): param_n += 1 return param_n
def get_fermion_jordan_wigner(fermion_type, op_qubit): ''' fermion_op = ('a',1) or ('c',1) 'a' is for annihilation 'c' is for creation ''' opstr = '' for i in range(op_qubit): opstr = opstr + 'Z' + str(i) + ' ' opstr1 = opstr + 'X' + str(op_qubit) opstr2 = opstr + 'Y' + str(op_qubit) if fermion_type == 'a': return PauliOperator({opstr1: 1, opstr2: 1j}) elif fermion_type == 'c': return PauliOperator({opstr1: 1, opstr2: -1j}) else: assert False
def convert_operator(str): ''' construct Hamiltonian based on str,str has molecule information ''' terms = str.split(' +\n') tuplelist = dict() for term in terms: data = term.split(' ', 1) tuplelist[data[1][1:-1]] = eval(data[0]) operator = PauliOperator(tuplelist) return operator
def flatten(pauliOperator): ''' if all coefficients of paulioperator can be written as C+0j, transform coefficients to float style, else, return error ''' new_ops = deepcopy(pauliOperator.ops) for term in new_ops: if abs(new_ops[term].imag) < pauliOperator.m_error_threshold: new_ops[term] = float(new_ops[term].real) else: assert False return PauliOperator(new_ops)
def get_matrix(pauliOperator): op = pauliOperator.ops n_qubit = pauliOperator.get_qubit_count() #preparation for numpy array I_ = np.eye(1 << n_qubit, dtype='complex128') result = np.zeros((1 << n_qubit, 1 << n_qubit), dtype='complex128') for term in op: one_term_result = deepcopy(I_) tuplelist = PauliOperator.parse_pauli(term) for pauli_tuple in tuplelist: one_term_result = one_term_result.dot( get_dense_pauli(pauli_tuple, n_qubit)) result += one_term_result * op[term] return result
def transform_base(qubitlist, base): ''' choose measurement basis, it means rotate all axis to z-axis ''' tuple_list = PauliOperator.parse_pauli(base) qcircuit = QCircuit() for i in tuple_list: if i[0] == 'X': qcircuit.insert(H(qubitlist[i[1]])) elif i[0] == 'Y': qcircuit.insert(RX(qubitlist[i[1]], pi / 2)) elif i[0] == 'Z': pass else: assert False return qcircuit
def parity_check(string, paulis): ''' string has element '0' or '1',paulis is a str like 'X1 Y2 Z3'. parity check of partial element of string, number of paulis are invloved position, to be repaired ''' check = 0 tuplelist = PauliOperator.parse_pauli(paulis) qubit_idx_list = list() for term in tuplelist: qubit_idx_list.append(term[1]) for i in qubit_idx_list: if string[i] == '1': check += 1 return check % 2
def get_expectation(qubit_list, program, Hamiltonian): ''' get Hamiltonian's expectation ''' expectation = 0 for op in Hamiltonian.ops: if op == '': expectation += Hamiltonian.ops[op] else: actual_qlist = [] tuplelist = PauliOperator.parse_pauli(op) for i in tuplelist: actual_qlist.append(qubit_list[i[1]]) prog = QProg() prog.insert(program).insert(transform_base(actual_qlist, op)) expectation += get_one_expectation_component( prog, actual_qlist) * Hamiltonian.ops[op] return expectation
def to_dense(pauliOperator): ''' get eigenvalues and eigenvectors of PauliOperator ''' op = pauliOperator.ops n_qubit = pauliOperator.get_qubit_count() #preparation for numpy array I_ = np.eye(1 << n_qubit, dtype='complex128') result = np.zeros((1 << n_qubit, 1 << n_qubit), dtype='complex128') for term in op: one_term_result = deepcopy(I_) tuplelist = PauliOperator.parse_pauli(term) for pauli_tuple in tuplelist: one_term_result = one_term_result.dot( get_dense_pauli(pauli_tuple, n_qubit)) result += one_term_result * op[term] eigval, _ = eig(result) # return min(eigval).real return eig(result)
def get_one_component_of_partial_derivative(self, qubit_list, label): ''' label[0]:position of hamiltonian's component label[1]:gamma or beta label[2]:position of gamma or beta label[3]:Hp's component ,such as 'Z0 Z4' <E>=f1(theta)f2(theta)...fn(theta) <E>=<E1>+<E2>...+<Em> return: d<Ei>/d(theta)中的一项 get_one_component_of_partial_derivative ''' prog0 = QProg() prog1 = QProg() prog0.insert(single_gate_apply_to_all(gate=H, qubit_list=qubit_list)) prog1.insert(single_gate_apply_to_all(gate=H, qubit_list=qubit_list)) coef = 0 if label[1] == 0: coef = 2 * self.Hp.ops[label[0]] else: coef = 2 for i in range(len(self.gamma)): if label[2] != i: prog0.insert(simulate_pauliZ_hamiltonian(qubit_list,self.Hp,2*self.gamma[i]))\ .insert(pauliX_model(qubit_list,self.beta[i])) prog1.insert(simulate_pauliZ_hamiltonian(qubit_list,self.Hp,2*self.gamma[i]))\ .insert(pauliX_model(qubit_list,self.beta[i])) else: if label[1] == 0: ''' Hp:gamma ''' for j in self.Hp.ops: if j != label[0]: prog0.insert( simulate_one_term(qubit_list, j, self.Hp.ops[j], 2 * self.gamma[i])) prog1.insert( simulate_one_term(qubit_list, j, self.Hp.ops[j], 2 * self.gamma[i])) else: prog0.insert( simulate_one_term( qubit_list, j, self.Hp.ops[j], 2 * self.gamma[i] + pi / 2 / self.Hp.ops[j])) prog1.insert( simulate_one_term( qubit_list, j, self.Hp.ops[j], 2 * self.gamma[i] - pi / 2 / self.Hp.ops[j])) prog0.insert(pauliX_model(qubit_list, self.beta[i])) prog1.insert(pauliX_model(qubit_list, self.beta[i])) elif label[1] == 1: ''' Hd:beta ''' prog0.insert( simulate_pauliZ_hamiltonian(qubit_list, self.Hp, 2 * self.gamma[i])) prog1.insert( simulate_pauliZ_hamiltonian(qubit_list, self.Hp, 2 * self.gamma[i])) for j in range(self.qnum): if j != label[0]: prog0.insert(RX(qubit_list[j], self.beta[i] * 2)) prog1.insert(RX(qubit_list[j], self.beta[i] * 2)) else: prog0.insert( RX(qubit_list[j], self.beta[i] * 2 + pi / 2)) prog1.insert( RX(qubit_list[j], self.beta[i] * 2 - pi / 2)) actual_qlist = [] tuplelist = PauliOperator.parse_pauli(label[3]) for i in tuplelist: actual_qlist.append(qubit_list[i[1]]) expectation0 = get_one_expectation_component(prog0, actual_qlist) expectation1 = get_one_expectation_component(prog1, actual_qlist) return (expectation0 - expectation1) / 2 * coef