Beispiel #1
0
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
Beispiel #2
0
    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))
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
    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()
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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)
Beispiel #9
0
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]))
Beispiel #10
0
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)
Beispiel #11
0
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]))
Beispiel #12
0
    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()
Beispiel #13
0
    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()
Beispiel #14
0
    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)