def get_rotation_matrix_3d(angle): ''' Returns the 3D rotation matrix for the angle [x, y, z]. Each angle represents a rotation around the corresponding axis. ''' s_ax = sin(angle[0]) c_ax = cos(angle[0]) s_ay = sin(angle[1]) c_ay = cos(angle[1]) s_az = sin(angle[2]) c_az = cos(angle[2]) return np_matmul( np_matmul( [ [1, 0, 0], [0, c_ax, s_ax], [0, -s_ax, c_ax] ], [ [c_ay, 0, -s_ay], [0, 1, 0], [s_ay, 0, c_ay] ] ), [ [c_az, s_az, 0], [-s_az, c_az, 0], [0, 0, 1] ] )
def matmul(a, b, out=None, comm=MPI.COMM_WORLD, dist='b'): if out is not None: raise NotSupportedError("'out' field not supported") #Numpy only arrays if not isinstance(a, MPIArray) and not isinstance(b, MPIArray): return Distribution_Dict[dist](np_matmul(a, b), comm=comm) #Numpy and MPIArray if not isinstance(a, MPIArray) or not isinstance(b, MPIArray): return Distribution_Dict[dist](np_matmul(a, b), comm=comm) #Replicated MPIArrays if a.dist == b.dist == 'r': return Distribution_Dict[dist](np_matmul(a, b), comm=comm) return _block_mat_mult(a, b, comm=comm)
def density_op_random(n, real_or_complex=2, rank=None): r"""随机生成一个密度矩阵的 numpy 形式。 Args: n (int): 量子比特数量 real_or_complex (int, optional): 默认为 2,即生成复数组,若为 1,则生成实数组 rank (int, optional): 矩阵的秩,默认为 :math:`2^n` (当 ``rank`` 为 ``None`` 时) Returns: numpy.ndarray: 一个形状为 ``(2**n, 2**n)`` 的 numpy 数组 """ assert n > 0, 'qubit number must be positive' rank = rank if rank is not None else 2**n assert 0 < rank <= 2**n, 'rank is an invalid number' if real_or_complex == 1: psi = np_random.randn(2**n, rank) else: psi = np_random.randn(2**n, rank) + 1j * np_random.randn(2**n, rank) psi_dagger = psi.conj().T rho = np_matmul(psi, psi_dagger) rho = rho / np_trace(rho) return rho.astype('complex128')
def purity(rho): r"""计算量子态的纯度。 .. math:: P = \text{tr}(\rho^2) Args: rho (numpy.ndarray): 量子态的密度矩阵形式 Returns: float: 输入的量子态的纯度 """ gamma = np_trace(np_matmul(rho, rho)) return gamma.real
def main(): n = int(sys.argv[1]) t = int(sys.argv[2]) for i in range(t): width = 2**i shape = (width, width) A_np = uniform(-1, 1, shape) B_np = uniform(-1, 1, shape) A_py = list(A_np) B_py = list(B_np) A_tf = constant(A_np) B_tf = constant(B_np) print((n, t, width)) print('py:', timeit(lambda: py_matmul(A_py, B_py), number=n) / n) print('np:', timeit(lambda: np_matmul(A_np, B_np), number=n) / n) print('tf:', timeit(lambda: tf_matmul(A_tf, B_tf), number=n) / n)
def gate_fidelity(U, V): r"""计算两个量子门的保真度。 .. math:: F(U, V) = |\text{tr}(UV^\dagger)|/2^n :math:`U` 是一个 :math:`2^n\times 2^n` 的 Unitary 矩阵。 Args: U (numpy.ndarray): 量子门的酉矩阵形式 V (numpy.ndarray): 量子门的酉矩阵形式 Returns: float: 输入的量子门之间的保真度 """ assert U.shape == V.shape, 'The shape of two unitary matrices are different' dim = U.shape[0] fidelity = absolute(np_trace(np_matmul(U, V.conj().T))) / dim return fidelity
def matmul(*args, **kwargs): warnings.warn( 'This function is deprecated, as it is available in all NumPy versions ' 'that this version of Astropy supports. You should use ' 'numpy.matmul directly.', AstropyDeprecationWarning) return np_matmul(*args, **kwargs)
def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, LR=0.1): """ This is the core function to run QAOA. Args: classical_graph_adjacency: adjacency matrix to describe the graph which encodes the classical problem N: number of qubits (default value N=4) P: number of layers of blocks in the QAOA circuit (default value P=4) METHOD: which version of the QAOA circuit is used: 1, standard circuit (default); 2, extended circuit ITR: number of iteration steps for QAOA (default value ITR=120) LR: learning rate for the gradient-based optimization method (default value LR=0.1) Returns: optimized parameters theta and the bitstrings sampled from the output state with maximal probability """ out_state_store = [] with fluid.dygraph.guard(): # Preparing the initial state _initial_state = ones([1, 2**N]).astype("complex64") / sqrt(2**N) initial_state = fluid.dygraph.to_variable(_initial_state) # Construct the net or QAOA circuits based on the standard modules if METHOD == 1: net = Net(shape=[P, 2]) # Construct the net or QAOA circuits based on the extended modules elif METHOD == 2: net = Net(shape=[P, 4]) else: raise ValueError("Wrong method called!") # Classical optimizer opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters()) # Gradient descent loop summary_iter, summary_loss = [], [] for itr in range(1, ITR + 1): loss = net(initial_state, classical_graph_adjacency, out_state_store, N, P, METHOD) loss.backward() opt.minimize(loss) net.clear_gradients() print("iter:", itr, " loss:", "%.4f" % loss.numpy()) summary_loss.append(loss[0][0].numpy()) summary_iter.append(itr) theta_opt = net.parameters()[0].numpy() print(theta_opt) os.makedirs("output", exist_ok=True) savez("./output/summary_data", iter=summary_iter, energy=summary_loss) # Output the measurement probability distribution sampled from the output state of optimized QAOA circuit. prob_measure = zeros([1, 2**N]).astype("complex") rho_out = out_state_store[-1] rho_out = np_matmul(conjugate(rho_out).T, rho_out).astype("complex") for index in range(0, 2**N): comput_basis = zeros([1, 2**N]) comput_basis[0][index] = 1 prob_measure[0][index] = real( np_matmul(np_matmul(comput_basis, rho_out), comput_basis.T)) return prob_measure