def partial_trace(rho_AB, dim1, dim2, A_or_B): r"""计算量子态的偏迹。 Args: rho_AB (ComplexVariable): 输入的量子态 dim1 (int): 系统A的维数 dim2 (int): 系统B的维数 A_or_B (int): 1或者2,1表示去除A,2表示去除B Returns: ComplexVariable: 量子态的偏迹 """ if A_or_B == 2: dim1, dim2 = dim2, dim1 idty_np = identity(dim2).astype("complex128") idty_B = to_variable(idty_np) zero_np = np_zeros([dim2, dim2], "complex128") res = to_variable(zero_np) for dim_j in range(dim1): row_top = pp_zeros([1, dim_j], dtype="float64") row_mid = ones([1, 1], dtype="float64") row_bot = pp_zeros([1, dim1 - dim_j - 1], dtype="float64") bra_j_re = concat([row_top, row_mid, row_bot], axis=1) bra_j_im = pp_zeros([1, dim1], dtype="float64") bra_j = ComplexVariable(bra_j_re, bra_j_im) if A_or_B == 1: row_tmp = pp_kron(bra_j, idty_B) res = elementwise_add( res, matmul( matmul(row_tmp, rho_AB), pp_transpose(ComplexVariable(row_tmp.real, -row_tmp.imag), perm=[1, 0]), ), ) if A_or_B == 2: row_tmp = pp_kron(idty_B, bra_j) res = elementwise_add( res, matmul( matmul(row_tmp, rho_AB), pp_transpose(ComplexVariable(row_tmp.real, -row_tmp.imag), perm=[1, 0]), ), ) return res
def U(self): r"""量子线路的酉矩阵形式。 Returns: ComplexVariable: 当前线路的酉矩阵表示 代码示例: .. code-block:: python from paddle import fluid from paddle_quantum.circuit import UAnsatz n = 2 with fluid.dygraph.guard(): cir = UAnsatz(2) cir.h(0) cir.cnot([0, 1]) matrix = cir.U print("The unitary matrix of the circuit for Bell state preparation is\n",matrix.numpy()) :: The unitary matrix of the circuit for Bell state preparation is [[ 0.70710678+0.j 0. +0.j 0.70710678+0.j 0. +0.j] [ 0. +0.j 0.70710678+0.j 0. +0.j 0.70710678+0.j] [ 0. +0.j 0.70710678+0.j 0. +0.j -0.70710678+0.j] [ 0.70710678+0.j 0. +0.j -0.70710678+0.j 0. +0.j]] """ state = ComplexVariable(eye(2**self.n, dtype='float64'), zeros([2**self.n, 2**self.n], dtype='float64')) shape = (2**self.n, 2**self.n) num_ele = reduce(lambda x, y: x * y, shape) state = ComplexVariable(reshape(state.real, [num_ele]), reshape(state.imag, [num_ele])) for history_ele in self.__history: if history_ele[0] == 'u': state = StateTranfer(state, 'u', history_ele[1], history_ele[2]) elif history_ele[0] in {'x', 'y', 'z', 'h'}: state = StateTranfer(state, history_ele[0], history_ele[1], params=history_ele[2]) elif history_ele[0] == 'SWAP': state = StateTranfer(state, 'SWAP', history_ele[1]) elif history_ele[0] == 'CNOT': state = StateTranfer(state, 'CNOT', history_ele[1]) return ComplexVariable(reshape(state.real, shape), reshape(state.imag, shape))
def partial_trace(rho_AB, dim1, dim2, A_or_B): r"""求AB复合系统下的偏迹 Args: rho_AB (Variable): AB复合系统的密度矩阵 dim1 (int): A系统的维度 dim2 (int): B系统的维度 A_orB (int): 1表示求系统A,2表示求系统B Returns: ComplexVariable: 求得的偏迹 """ # dim_total = dim1 * dim2 if A_or_B == 2: dim1, dim2 = dim2, dim1 idty_np = identity(dim2).astype("complex64") idty_B = to_variable(idty_np) zero_np = np_zeros([dim2, dim2], "complex64") res = to_variable(zero_np) for dim_j in range(dim1): row_top = pp_zeros([1, dim_j], dtype="float32") row_mid = ones([1, 1], dtype="float32") row_bot = pp_zeros([1, dim1 - dim_j - 1], dtype="float32") bra_j_re = concat([row_top, row_mid, row_bot], axis=1) bra_j_im = pp_zeros([1, dim1], dtype="float32") bra_j = ComplexVariable(bra_j_re, bra_j_im) if A_or_B == 1: row_tmp = pp_kron(bra_j, idty_B) res = elementwise_add( res, matmul( matmul(row_tmp, rho_AB), pp_transpose(ComplexVariable(row_tmp.real, -row_tmp.imag), perm=[1, 0]), ), ) if A_or_B == 2: row_tmp = pp_kron(idty_B, bra_j) res += matmul( matmul(row_tmp, rho_AB), pp_transpose(ComplexVariable(row_tmp.real, -row_tmp.imag), perm=[1, 0]), ) return res
def hermitian(matrix): r"""计算矩阵的埃尔米特转置,即Hermitian transpose。 Args: matrix (ComplexVariable): 需要埃尔米特转置的矩阵 Returns: ComplexVariable: 输入矩阵的埃尔米特转置 代码示例: .. code-block:: python from paddle_quantum.utils import hermitian from paddle import fluid import numpy as np with fluid.dygraph.guard(): rho = fluid.dygraph.to_variable(np.array([[1+1j, 2+2j], [3+3j, 4+4j]])) print(hermitian(rho).numpy()) :: [[1.-1.j 3.-3.j] [2.-2.j 4.-4.j]] """ matrix_dagger = pp_transpose(ComplexVariable(matrix.real, -matrix.imag), perm=[1, 0]) return matrix_dagger
def forward(self, state_in, label): """ Args: state_in: The input quantum state, shape [-1, 1, 2^n] label: label for the input state, shape [-1, 1] Returns: The loss: L = ((<Z> + 1)/2 + bias - label)^2 """ # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable Ob = fluid.dygraph.to_variable(Observable(self.n)) #pdb.set_trace() label_pp = fluid.dygraph.to_variable(label) # 按照随机初始化的参数 theta Utheta = U_theta(self.theta, n=self.n, depth=self.depth) # 因为 Utheta是学习得到的,我们这里用行向量运算来提速而不会影响训练效果 state_out = matmul(state_in, Utheta) # 维度 [-1, 1, 2 ** n] # 测量得到泡利 Z 算符的期望值 <Z> E_Z = matmul(matmul(state_out, Ob), transpose(ComplexVariable(state_out.real, -state_out.imag), perm=[0, 2, 1])) # 映射 <Z> 处理成标签的估计值 state_predict = E_Z.real[:, 0] * 0.5 + 0.5 + self.bias loss = fluid.layers.reduce_mean((state_predict - label_pp) ** 2) #pdb.set_trace() # 计算交叉验证正确率 #is_correct = fluid.layers.where( #fluid.layers.abs(state_predict - label_pp) < 0.5).shape[0] #acc = is_correct / label.shape[0] return loss, state_predict.numpy()
def partial_trace(rho_AB, dim1, dim2, A_or_B): """ :param rho_AB: the input density matrix :param dim1: dimension for system A :param dim2: dimension for system B :param A_or_B: 1 or 2, choose the system that you want trace out. :return: partial trace """ # dim_total = dim1 * dim2 if A_or_B == 2: dim1, dim2 = dim2, dim1 idty_np = identity(dim2).astype("complex64") idty_B = to_variable(idty_np) zero_np = np_zeros([dim2, dim2], "complex64") res = to_variable(zero_np) for dim_j in range(dim1): row_top = pp_zeros([1, dim_j], dtype="float32") row_mid = ones([1, 1], dtype="float32") row_bot = pp_zeros([1, dim1 - dim_j - 1], dtype="float32") bra_j_re = concat([row_top, row_mid, row_bot], axis=1) bra_j_im = pp_zeros([1, dim1], dtype="float32") bra_j = ComplexVariable(bra_j_re, bra_j_im) if A_or_B == 1: row_tmp = pp_kron(bra_j, idty_B) res = elementwise_add( res, matmul( matmul(row_tmp, rho_AB), pp_transpose( ComplexVariable(row_tmp.real, -row_tmp.imag), perm=[1, 0]), ), ) if A_or_B == 2: row_tmp = pp_kron(idty_B, bra_j) res += matmul( matmul(row_tmp, rho_AB), pp_transpose( ComplexVariable(row_tmp.real, -row_tmp.imag), perm=[1, 0]), ) return res
def vec_expecval(H, vec): r""" It returns expectation value of H with respect to vector vec Note: 这是内部函数,你并不需要直接调用到该函数。 """ vec_conj = ComplexVariable(vec.real, -vec.imag) result = paddle.complex.sum(elementwise_mul(vec_conj, H_vec(H, vec))) return result
def rotation_y(theta): """ :param theta: must be a scale, shape [1], 'float32' :return: """ cos_value = cos(theta/2) sin_value = sin(theta/2) ry_re = concat([cos_value, -sin_value, sin_value, cos_value], axis=0) ry_im = pp_zeros([2, 2], "float32") return ComplexVariable(reshape(ry_re, [2, 2]), ry_im)
def rotation_z(theta): """ :param theta: must be a scale, shape [1], 'float32' :return: """ cos_value = cos(theta/2) sin_value = sin(theta/2) zero_pd = pp_zeros([1], "float32") rz_re = concat([cos_value, zero_pd, zero_pd, cos_value], axis=0) rz_im = concat([-sin_value, zero_pd, zero_pd, sin_value], axis=0) return ComplexVariable(reshape(rz_re, [2, 2]), reshape(rz_im, [2, 2]))
def rotation_y(theta): r"""生成单量子比特Y门 Args: theta (Variable): Y门的旋转角度 Returns: ComplexVariable: 单量子比特Y门的矩阵形式 """ cos_value = cos(theta / 2) sin_value = sin(theta / 2) ry_re = concat([cos_value, -sin_value, sin_value, cos_value], axis=0) ry_im = pp_zeros([2, 2], "float32") return ComplexVariable(reshape(ry_re, [2, 2]), ry_im)
def rotation_z(theta): r"""生成单量子比特Z门 Args: theta (Variable): Z门的旋转角度 Returns: ComplexVariable: 单量子比特Z门的矩阵形式 """ cos_value = cos(theta / 2) sin_value = sin(theta / 2) zero_pd = pp_zeros([1], "float32") rz_re = concat([cos_value, zero_pd, zero_pd, cos_value], axis=0) rz_im = concat([-sin_value, zero_pd, zero_pd, sin_value], axis=0) return ComplexVariable(reshape(rz_re, [2, 2]), reshape(rz_im, [2, 2]))
def forward(self, state_in, origin_state): """ Args: state_in: The input quantum state, shape [-1, 1, 2^n] label: label for the input state, shape [-1, 1] Returns: The loss: L = ((<Z> + 1)/2 + bias - label)^2 """ # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable Ob = self.Ob # 按照随机初始化的参数 theta Encoder = AE_encoder(self.theta1, n=self.n, z_n=self.n_z, depth=self.depth) Decoder = AE_decoder(self.theta2, n=self.n, z_n=self.n_z, depth=self.depth) # State in to input state initial_state = np.array([1]+[0]*(2**(self.n-self.n_z)-1)).astype('complex128') initial_state = fluid.dygraph.to_variable(initial_state) input_state = kron(initial_state, state_in) # 因为 Utheta是学习得到的,我们这里用行向量运算来提速而不会影响训练效果 state_z = matmul(input_state, Encoder) state_out = matmul(state_z, Decoder) # 测量得到泡利 Z 算符的期望值 <Z> E_Z = [matmul(matmul(state_out, Ob[i]), transpose(ComplexVariable(state_out.real, -state_out.imag), perm=[0, 2, 1])).real for i in range(self.n)] output_state = fluid.layers.concat(E_Z, axis=-1) # Calcualate Loss loss = fluid.layers.mean((output_state-origin_state)**2) origin_len = fluid.layers.reduce_sum(origin_state**2, -1) ** 0.5 output_len = fluid.layers.reduce_sum(output_state**2, -1) ** 0.5 dot_product = fluid.layers.reduce_sum(output_state*origin_state, -1) fidelity = fluid.layers.mean(dot_product/origin_len/output_len) return loss, fidelity, output_state.numpy()
def forward(self, state_in, label): """ Args: state_in: The input quantum state, shape [-1, 1, 2^n] label: label for the input state, shape [-1, 1] Returns: The loss: L = ((<Z> + 1)/2 + bias - label)^2 """ state_z = self.net.encoder(state_in) state_z = fluid.dygraph.to_variable(state_z.numpy()) # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable unused_n = self.n - self.n_z Ob = fluid.dygraph.to_variable(Observable(2*self.n-self.n_z, measure_index=unused_n)) label_pp = fluid.dygraph.to_variable(label) # 按照随机初始化的参数 theta unused_n = self.n - self.n_z Utheta = U_theta(self.theta, n=self.n_z, depth=self.depth) empty_half = fluid.dygraph.to_variable(np.eye(2**unused_n).astype('complex128')) Utheta = kron(empty_half, Utheta) Utheta = kron(Utheta, empty_half) # 因为 Utheta是学习得到的,我们这里用行向量运算来提速而不会影响训练效果 state_out = matmul(state_z, Utheta) # 维度 [-1, 1, 2 ** n] # 测量得到泡利 Z 算符的期望值 <Z> E_Z = matmul(matmul(state_out, Ob), transpose(ComplexVariable(state_out.real, -state_out.imag), perm=[0, 2, 1])) # 映射 <Z> 处理成标签的估计值 state_predict = E_Z.real[:, 0] * 0.5 + 0.5 + self.bias loss = fluid.layers.reduce_mean((state_predict - label_pp) ** 2) return loss, state_predict.numpy()
def run_state_vector(self, input_state=None, store_state=True): r"""运行当前的量子线路,输入输出的形式为态矢量。 Args: input_state (ComplexVariable, optional): 输入的态矢量,默认为 :math:`|00...0\rangle` store_state (Bool, optional): 是否存储输出的态矢量,默认为 ``True`` ,即存储 Returns: ComplexVariable: 量子线路输出的态矢量 代码示例: .. code-block:: python import numpy as np from paddle import fluid from paddle_quantum.circuit import UAnsatz n = 2 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.ry(theta[1], 1) cir.rz(theta[2], 1) vec = cir.run_state_vector(input_state_var).numpy() print(f"运行后的向量是 {vec}") :: 运行后的向量是 [0.17470783-0.09544332j 0.59544332+0.32529217j 0.17470783-0.09544332j 0.59544332+0.32529217j] """ state = init_state_gen(self.n, 0) if input_state is None else input_state old_shape = state.shape assert reduce( lambda x, y: x * y, old_shape ) == 2**self.n, 'The length of the input vector is not right' state = complex_reshape(state, (2**self.n, )) state_conj = ComplexVariable(state.real, -state.imag) assert fluid.layers.abs(paddle.complex.sum(elementwise_mul(state_conj, state)).real - 1) < 1e-8, \ 'Input state is not a normalized vector' for history_ele in self.__history: if history_ele[0] == 'u': state = StateTranfer(state, 'u', history_ele[1], history_ele[2]) elif history_ele[0] in {'x', 'y', 'z', 'h'}: state = StateTranfer(state, history_ele[0], history_ele[1], params=history_ele[2]) elif history_ele[0] == 'CNOT': state = StateTranfer(state, 'CNOT', history_ele[1]) if store_state: self.__state = state # Add info about which function user called self.__run_state = 'state_vector' return complex_reshape(state, old_shape)