def Observable(n): """ :param n: number of qubits :return: local observable: Z \otimes I \otimes ...\otimes I """ Ob = pauli_str_to_matrix([[1.0, 'z0']], n) return Ob
def Observable(n, measure_index=0): """ :param n: number of qubits :return: local observable: Z \otimes I \otimes ...\otimes I """ Ob = fluid.dygraph.to_variable(pauli_str_to_matrix([[1.0, 'z'+str(measure_index)]], n)) return Ob
def benchmark_QAOA(classical_graph_adjacency=None, N=None): """ This function benchmarks the performance of QAOA. Indeed, it compares its approximate solution obtained from QAOA with predetermined parameters, such as iteration step = 120 and learning rate = 0.1, to the exact solution to the classical problem. """ # Generate the graph and its adjacency matrix from the classical problem, such as the Max-Cut problem if all(var is None for var in (classical_graph_adjacency, N)): N = 4 _, classical_graph_adjacency = generate_graph(N, 1) # Convert the Hamiltonian's list form to matrix form H_matrix = pauli_str_to_matrix(H_generator(N, classical_graph_adjacency), N) H_diag = diag(H_matrix).real # Compute the exact solution of the original problem to benchmark the performance of QAOA H_max = max(H_diag) H_min = min(H_diag) print('H_max:', H_max, ' H_min:', H_min) # Load the data of QAOA x1 = load('./output/summary_data.npz') H_min = ones([len(x1['iter'])]) * H_min # Plot it pyplot.figure(1) loss_QAOA, = pyplot.plot(x1['iter'], x1['energy'], alpha=0.7, marker='', linestyle="--", linewidth=2, color='m') benchmark, = pyplot.plot(x1['iter'], H_min, alpha=0.7, marker='', linestyle=":", linewidth=2, color='b') pyplot.xlabel('Number of iteration') pyplot.ylabel('Performance of the loss function for QAOA') pyplot.legend( handles=[loss_QAOA, benchmark], labels=[ r'Loss function $\left\langle {\psi \left( {\bf{\theta }} \right)} ' r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $', 'The benchmark result', ], loc='best') # Show the picture pyplot.show()
def H_generator(N): """ Generate a Hamiltonian with trivial descriptions Returns: A Hamiltonian """ # 生成用泡利字符串表示的随机哈密顿量 hamiltonian = random_pauli_str_generator(N, terms=10) print("Random Hamiltonian in Pauli string format = \n", hamiltonian) # 生成哈密顿量的矩阵信息 H = pauli_str_to_matrix(hamiltonian, N) return H
def H_generator(N): """ Generate a Hamiltonian with trivial descriptions Returns: A Hamiltonian """ # Generate the Pauli string representing a random Hamiltonian hamiltonian = random_pauli_str_generator(N, terms=10) print("Random Hamiltonian in Pauli string format = \n", hamiltonian) # Generate the marix form of the Hamiltonian H = pauli_str_to_matrix(hamiltonian, N) return H
def benchmark_result(): # Read H and calc using numpy sysStr = platform.system() if sysStr == 'Windows': # Windows does not support SCF, using H2_generator instead print('Molecule data will be read from built-in function') Hamiltonian, N = H2_generator() print('Read Process Finished') elif sysStr == 'Linux' or sysStr == 'Darwin': # for linux only from paddle_quantum.VQE.chemistrygen import read_calc_H # Hamiltonian and cnot module preparing, must be executed under Linux # Read the H2 molecule data print('Molecule data will be read from h2.xyz') Hamiltonian, N = read_calc_H(geo_fn='h2.xyz') print('Read Process Finished') else: print("Don't support this os.") result = numpy.load('./output/summary_data.npz') eig_val, eig_state = numpy.linalg.eig(pauli_str_to_matrix(Hamiltonian, N)) min_eig_H = numpy.min(eig_val.real) min_loss = numpy.ones([len(result['iter'])]) * min_eig_H plt.figure(1) func1, = plt.plot(result['iter'], result['energy'], alpha=0.7, marker='', linestyle="-", color='r') func_min, = plt.plot(result['iter'], min_loss, alpha=0.7, marker='', linestyle=":", color='b') plt.xlabel('Number of iteration') plt.ylabel('Energy (Ha)') plt.legend( handles=[func1, func_min], labels=[ r'$\left\langle {\psi \left( {\theta } \right)} ' r'\right|H\left| {\psi \left( {\theta } \right)} \right\rangle $', 'Ground-state energy', ], loc='best') # plt.savefig("vqe.png", bbox_inches='tight', dpi=300) plt.show()
def Generate_H_D(E, n): """ This is to construct Hamiltonia H_D Args: E: edges of the graph Returns: Hamiltonia list Hamiltonia H_D """ H_D_list = [] for (u, v) in E: H_D_list.append([-1.0, 'z' + str(u) + ',z' + str(v)]) print(H_D_list) H_D_matrix = pauli_str_to_matrix(H_D_list, n) return H_D_list, H_D_matrix
def main(): # 生成用泡利字符串表示的特定的哈密顿量 H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']] # 生成哈密顿量的矩阵信息 N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数 hamiltonian = pauli_str_to_matrix(H, N_SYS_B) # 生成理想情况下的目标吉布斯态 rho beta = 1.5 # 设置逆温度参数 beta rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace(scipy.linalg.expm(-1 * beta * hamiltonian)) # 设置成 Paddle quantum 所支持的数据类型 hamiltonian = hamiltonian.astype("complex128") rho_G = rho_G.astype("complex128") rho_B = Paddle_GIBBS(hamiltonian, rho_G) print(rho_B)
def main(): # Generate Pauli string representing a specific Hamiltonian H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']] # Generate the marix form of the Hamiltonian N_SYS_B = 3 # Number of qubits in subsystem B used to generate Gibbs state hamiltonian = pauli_str_to_matrix(H, N_SYS_B) # Generate the target Gibbs state rho beta = 1.5 # Set inverse temperature beta rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace( scipy.linalg.expm(-1 * beta * hamiltonian)) # Convert to the data type supported by Paddle Quantum hamiltonian = hamiltonian.astype("complex128") rho_G = rho_G.astype("complex128") rho_B = Paddle_GIBBS(hamiltonian, rho_G) print(rho_B)
def expecval(self, H): r"""量子线路输出的量子态关于可观测量 H 的期望值。 Hint: 如果想输入的可观测量的矩阵为 :math:`0.7Z\otimes X\otimes I+0.2I\otimes Z\otimes I` 。则 ``H`` 应为 ``[[0.7, 'z0,x1'], [0.2, 'z1']]`` 。 Args: H (list): 可观测量的相关信息 Returns: Tensor: 量子线路输出的量子态关于 H 的期望值 代码示例: .. code-block:: python import numpy as np import paddle from paddle_quantum.circuit import UAnsatz n = 5 H_info = [[0.1, 'x1'], [0.2, 'y0,z4']] theta = paddle.to_tensor(np.ones(3)) cir = UAnsatz(n) cir.rx(theta[0], 0) cir.rz(theta[1], 1) cir.rx(theta[2], 2) cir.run_state_vector() expect_value = cir.expecval(H_info).numpy() print(f'Calculated expectation value of {H_info} is {expect_value}') :: Calculated expectation value of [[0.1, 'x1'], [0.2, 'y0,z4']] is [-0.1682942] """ if self.__run_state == 'state_vector': return real(vec_expecval(H, self.__state)) elif self.__run_state == 'density_matrix': state = self.__state H_mat = paddle.to_tensor(pauli_str_to_matrix(H, self.n)) return real(trace(matmul(state, H_mat))) else: # Raise error raise ValueError( "no state for measurement; please run the circuit first")
def main(n=4): paddle.seed(SEED) p = 4 # number of layers in the circuit ITR = 120 # number of iterations LR = 0.1 # learning rate G = nx.cycle_graph(4) V = list(G.nodes()) E = list(G.edges()) # Draw the original graph pos = nx.circular_layout(G) nx.draw_networkx(G, pos, **options) ax = plt.gca() ax.margins(0.20) plt.axis("off") plt.show() # construct the Hamiltonian H_D_list = maxcut_hamiltonian(E) H_D_matrix = pauli_str_to_matrix(H_D_list, n) H_D_diag = np.diag(H_D_matrix).real H_max = np.max(H_D_diag) print(H_D_diag) print('H_max:', H_max) cut_bitstring, _ = find_cut(G, p, ITR, LR, print_loss=True, plot=True) print("The bit string form of the cut found:", cut_bitstring) node_cut = ["blue" if cut_bitstring[v] == "1" else "red" for v in V] edge_cut = [ "solid" if cut_bitstring[u] == cut_bitstring[v] else "dashed" for (u, v) in G.edges() ] nx.draw(G, pos, node_color=node_cut, style=edge_cut, **options) ax = plt.gca() ax.margins(0.20) plt.axis("off") plt.show()
def H_generator(): """ Generate a Hamiltonian with trivial descriptions Returns: A Hamiltonian """ # Generate Pauli string representing a specific Hamiltonian H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']] # Generate the matrix form of the Hamiltonian N_SYS_B = 3 # Number of qubits in subsystem B used to generate Gibbs state hamiltonian = pauli_str_to_matrix(H, N_SYS_B) # Generate the target Gibbs state rho beta = 1.5 # Set inverse temperature beta rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace( scipy.linalg.expm(-1 * beta * hamiltonian)) # Convert to the data type supported by Paddle Quantum hamiltonian = hamiltonian.astype("complex128") rho_G = rho_G.astype("complex128") return hamiltonian, rho_G
def H_generator(): """ Generate a Hamiltonian with trivial descriptions Returns: A Hamiltonian """ # 生成用泡利字符串表示的特定的哈密顿量 H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']] # 生成哈密顿量的矩阵信息 N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数 hamiltonian = pauli_str_to_matrix(H, N_SYS_B) # 生成理想情况下的目标吉布斯态 rho beta = 1.5 # 设置逆温度参数 beta rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace( scipy.linalg.expm(-1 * beta * hamiltonian)) # 设置成 Paddle quantum 所支持的数据类型 hamiltonian = hamiltonian.astype("complex128") rho_G = rho_G.astype("complex128") return hamiltonian, rho_G
def main(N=4): # number of qubits or number of nodes in the graph N = 4 classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1) print(classical_graph_adjacency) # Convert the Hamiltonian's list form to matrix form H_matrix = pauli_str_to_matrix(H_generator(N, classical_graph_adjacency), N) H_diag = np.diag(H_matrix).real H_max = np.max(H_diag) H_min = np.min(H_diag) print(H_diag) print('H_max:', H_max, ' H_min:', H_min) pos = nx.circular_layout(classical_graph) nx.draw(classical_graph, pos, width=4, with_labels=True, font_weight='bold') plt.show() classical_graph, classical_graph_adjacency = generate_graph(N, 1) opt_cir = Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, LR=0.1) # Load the data of QAOA x1 = np.load('./output/summary_data.npz') H_min = np.ones([len(x1['iter'])]) * H_min # Plot loss loss_QAOA, = plt.plot(x1['iter'], x1['energy'], alpha=0.7, marker='', linestyle="--", linewidth=2, color='m') benchmark, = plt.plot(x1['iter'], H_min, alpha=0.7, marker='', linestyle=":", linewidth=2, color='b') plt.xlabel('Number of iteration') plt.ylabel('Performance of the loss function for QAOA') plt.legend( handles=[loss_QAOA, benchmark], labels=[ r'Loss function $\left\langle {\psi \left( {\bf{\theta }} \right)} ' r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $', 'The benchmark result', ], loc='best') # Show the plot plt.show() with fluid.dygraph.guard(): # Measure the output state of the QAOA circuit for 1024 shots by default prob_measure = opt_cir.measure(plot=True) # Find the max value in measured probability of bitstrings max_prob = max(prob_measure.values()) # Find the bitstring with max probability solution_list = [ result[0] for result in prob_measure.items() if result[1] == max_prob ] print("The output bitstring:", solution_list) # Draw the graph representing the first bitstring in the solution_list to the MaxCut-like problem head_bitstring = solution_list[0] node_cut = [ "blue" if head_bitstring[node] == "1" else "red" for node in classical_graph ] edge_cut = [ "solid" if head_bitstring[node_row] == head_bitstring[node_col] else "dashed" for node_row, node_col in classical_graph.edges() ] nx.draw( classical_graph, pos, node_color=node_cut, style=edge_cut, width=4, with_labels=True, font_weight="bold", ) plt.show()
def expecval(self, H): r"""量子线路输出的量子态关于可观测量H的期望值。 Hint: 如果想输入的可观测量的矩阵为 :math:`0.7Z\otimes X\otimes I+0.2I\otimes Z\otimes I` 。则 ``H`` 应为 ``[[0.7, 'z0,x1'], [0.2, 'z1']]`` 。 Args: H (list): 可观测量的相关信息 Returns: Variable: 量子线路输出的量子态关于H的期望值 代码示例: .. code-block:: python import numpy as np from paddle import fluid from paddle_quantum.circuit import UAnsatz n = 5 H_info = [[0.1, 'x1'], [0.2, 'y0,z4']] theta = np.ones(3) input_state = np.ones(2**n)+0j input_state = input_state / np.linalg.norm(input_state) with fluid.dygraph.guard(): input_state_var = fluid.dygraph.to_variable(input_state) theta = fluid.dygraph.to_variable(theta) cir = UAnsatz(n) cir.rx(theta[0], 0) cir.rz(theta[1], 1) cir.rx(theta[2], 2) cir.run_state_vector(input_state_var) expect_value = cir.expecval(H_info).numpy() print(f'计算得到的{H_info}期望值是{expect_value}') :: 计算得到的[[0.1, 'x1'], [0.2, 'y0,z4']]期望值是[0.05403023] .. code-block:: python import numpy as np from paddle import fluid from paddle_quantum.circuit import UAnsatz n = 5 H_info = [[0.1, 'x1'], [0.2, 'y0,z4']] theta = np.ones(3) input_state = np.diag(np.arange(2**n))+0j input_state = input_state / np.trace(input_state) with fluid.dygraph.guard(): input_state_var = fluid.dygraph.to_variable(input_state) theta = fluid.dygraph.to_variable(theta) cir = UAnsatz(n) cir.rx(theta[0], 0) cir.ry(theta[1], 1) cir.rz(theta[2], 2) cir.run_density_matrix(input_state_var) expect_value = cir.expecval(H_info).numpy() print(f'计算得到的{H_info}期望值是{expect_value}') :: 计算得到的[[0.1, 'x1'], [0.2, 'y0,z4']]期望值是[-0.02171538] """ if self.__run_state == 'state_vector': return vec_expecval(H, self.__state).real elif self.__run_state == 'density_matrix': state = self.__state H_mat = fluid.dygraph.to_variable(pauli_str_to_matrix(H, self.n)) return trace(matmul(state, H_mat)).real else: # Raise error raise ValueError( "no state for measurement; please run the circuit first")