Ejemplo n.º 1
0
    def forward(self):
        # 生成初始的编码器 E 和解码器 D\n",
        E = Encoder(self.theta)
        E_dagger = dagger(E)
        D = E_dagger
        D_dagger = E

        # 编码量子态 rho_in
        rho_BA = matmul(matmul(E, self.rho_in), E_dagger)

        # 取 partial_trace() 获得 rho_encode 与 rho_trash
        rho_encode = partial_trace(rho_BA, 2**N_B, 2**N_A, 1)
        rho_trash = partial_trace(rho_BA, 2**N_B, 2**N_A, 2)

        # 解码得到量子态 rho_out
        rho_CA = kron(self.rho_C, rho_encode)
        rho_out = matmul(matmul(D, rho_CA), D_dagger)

        # 通过 rho_trash 计算损失函数

        zero_Hamiltonian = fluid.dygraph.to_variable(
            np.diag([1, 0]).astype('complex128'))
        loss = 1 - (trace(matmul(zero_Hamiltonian, rho_trash))).real

        return loss, self.rho_in, rho_out
    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 -> variable
        Ob = fluid.dygraph.to_variable(Observable(self.n))
        label_pp = fluid.dygraph.to_variable(label)

        Utheta = U_theta(self.theta, n=self.n, depth=self.depth)
        U_dagger = dagger(Utheta)

        state_out = matmul(matmul(state_in, Utheta), U_dagger)

        E_Z = trace(matmul(state_out, Ob))

        # map <Z> to the predict label
        state_predict = E_Z.real * 0.5 + 0.5 + self.bias
        loss = fluid.layers.reduce_mean((state_predict - label_pp)**2)

        is_correct = fluid.layers.where(
            fluid.layers.abs(state_predict - label_pp) < 0.5).shape[0]
        acc = is_correct / label.shape[0]

        return loss, acc, state_predict.numpy()
Ejemplo n.º 3
0
    def __measure_parameterless(self, state, which_qubits, result_desired):
        r"""进行 01 测量。

        Args:
            state (ComplexVariable): 输入的量子态
            which_qubits (list): 测量作用的量子比特编号
            result_desired (list): 期望得到的测量结果,如 ``"0"``、``"1"`` 或者 ``["0", "1"]``

        Returns:
            ComplexVariable: 测量坍塌后的量子态
            ComplexVariable:测量坍塌得到的概率
            list: 测量得到的结果(0 或 1)
        """
        n = self.get_qubit_number()
        assert len(which_qubits) == len(result_desired), \
            "the length of qubits wanted to be measured and the result desired should be same"
        op_list = [np.eye(2, dtype=np.complex128)] * n
        for i, ele in zip(which_qubits, result_desired):
            k = int(ele)
            rho = np.zeros((2, 2), dtype=np.complex128)
            rho[int(k), int(k)] = 1
            op_list[i] = rho
        if n > 1:
            measure_operator = fluid.dygraph.to_variable(NKron(*op_list))
        else:
            measure_operator = fluid.dygraph.to_variable(op_list[0])
        state_measured = matmul(matmul(measure_operator, state),
                                dagger(measure_operator))
        prob = trace(
            matmul(matmul(dagger(measure_operator), measure_operator),
                   state)).real
        state_measured = elementwise_div(state_measured, prob)
        return state_measured, prob, result_desired
Ejemplo n.º 4
0
    def forward(self, input_state, H, N, N_SYS_B, D):
        """
        Args:
            input_state: The initial state with default |0..>
            H: The target Hamiltonian
        Returns:
            The loss.
        """

        out_state = U_theta(self.theta, input_state, N, D)

        # rho_AB = utils.matmul(utils.matrix_conjugate_transpose(out_state), out_state)
        rho_AB = matmul(
            transpose(
                fluid.framework.ComplexVariable(out_state.real,
                                                -out_state.imag),
                perm=[1, 0]),
            out_state)

        # compute the partial trace and three losses
        rho_B = partial_trace(rho_AB, 2**(N - N_SYS_B), 2**(N_SYS_B), 1)
        rho_B_squre = matmul(rho_B, rho_B)
        loss1 = (trace(matmul(rho_B, H))).real
        loss2 = (trace(rho_B_squre)).real * 2
        loss3 = -(trace(matmul(rho_B_squre, rho_B))).real / 2

        loss = loss1 + loss2 + loss3  # 损失函数

        # option: if you want to check whether the imaginary part is 0, uncomment the following
        # print('loss_iminary_part: ', loss.numpy()[1])
        return loss - 3 / 2, rho_B
Ejemplo n.º 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()
Ejemplo n.º 6
0
    def __measure_parameterized(self, state, which_qubits, result_desired,
                                theta):
        r"""进行参数化的测量。

        Args:
            state (ComplexVariable): 输入的量子态
            which_qubits (list): 测量作用的量子比特编号
            result_desired (list): 期望得到的测量结果,如 ``"0"``、``"1"`` 或者 ``["0", "1"]``
            theta (Variable): 测量运算的参数

        Returns:
            ComplexVariable: 测量坍塌后的量子态
            Variable:测量坍塌得到的概率
            list: 测量得到的结果(0 或 1)
        """
        n = self.get_qubit_number()
        assert len(which_qubits) == len(result_desired), \
            "the length of qubits wanted to be measured and the result desired should be same"
        op_list = [fluid.dygraph.to_variable(np.eye(2, dtype=np.complex128))
                   ] * n
        for idx in range(0, len(which_qubits)):
            i = which_qubits[idx]
            ele = result_desired[idx]
            if int(ele) == 0:
                basis0 = fluid.dygraph.to_variable(
                    np.array([[1, 0], [0, 0]], dtype=np.complex128))
                basis1 = fluid.dygraph.to_variable(
                    np.array([[0, 0], [0, 1]], dtype=np.complex128))
                rho0 = elementwise_mul(basis0, cos(theta[idx]))
                rho1 = elementwise_mul(basis1, sin(theta[idx]))
                rho = elementwise_add(rho0, rho1)
                op_list[i] = rho
            elif int(ele) == 1:
                # rho = diag(concat([cos(theta[idx]), sin(theta[idx])]))
                # rho = ComplexVariable(rho, zeros((2, 2), dtype="float64"))
                basis0 = fluid.dygraph.to_variable(
                    np.array([[1, 0], [0, 0]], dtype=np.complex128))
                basis1 = fluid.dygraph.to_variable(
                    np.array([[0, 0], [0, 1]], dtype=np.complex128))
                rho0 = elementwise_mul(basis0, sin(theta[idx]))
                rho1 = elementwise_mul(basis1, cos(theta[idx]))
                rho = elementwise_add(rho0, rho1)
                op_list[i] = rho
            else:
                print("cannot recognize the results_desired.")
            # rho = ComplexVariable(ones((2, 2), dtype="float64"), zeros((2, 2), dtype="float64"))
        measure_operator = fluid.dygraph.to_variable(op_list[0])
        if n > 1:
            for idx in range(1, len(op_list)):
                measure_operator = kron(measure_operator, op_list[idx])
        state_measured = matmul(matmul(measure_operator, state),
                                dagger(measure_operator))
        prob = trace(
            matmul(matmul(dagger(measure_operator), measure_operator),
                   state)).real
        state_measured = elementwise_div(state_measured, prob)
        return state_measured, prob, result_desired
Ejemplo n.º 7
0
    def forward(self, N):
        # 施加量子神经网络
        U = U_theta(self.theta, N)

        # rho_tilde 是将 U 作用在 rho 后得到的量子态 U*rho*U^dagger
        rho_tilde = matmul(matmul(U, self.rho), hermitian(U))

        # 计算损失函数
        loss = trace(matmul(self.sigma, rho_tilde))

        return loss.real, rho_tilde
Ejemplo n.º 8
0
    def forward(self, N):
        # Apply quantum neural network onto the initial state
        U = U_theta(self.theta, N)

        # rho_tilda is the quantum state obtained by acting U on rho, which is U*rho*U^dagger
        rho_tilde = matmul(matmul(U, self.rho), dagger(U))

        # Calculate loss function
        loss = trace(matmul(self.sigma, rho_tilde))

        return loss.real, rho_tilde
Ejemplo n.º 9
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
Ejemplo n.º 10
0
    def run_density_matrix(self, input_state=None, store_state=True):
        r"""运行当前的量子线路,输入输出的形式为密度矩阵。
        
        Args:
            input_state (ComplexVariable, optional): 输入的密度矩阵,默认为 :math:`|00...0\rangle \langle00...0|`
            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 = 1
            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], 0)
                cir.rz(theta[2], 0)
                density = cir.run_density_matrix(input_state_var).numpy()
                print(f"密度矩阵是\n{density}")

        ::

            密度矩阵是
            [[ 0.35403671+0.j         -0.47686058-0.03603751j]
            [-0.47686058+0.03603751j  0.64596329+0.j        ]]
        """
        state = dygraph.to_variable(density_op(
            self.n)) if input_state is None else input_state

        assert state.real.shape == [2**self.n,
                                    2**self.n], "The dimension is not right"
        state = matmul(self.U, matmul(state, dagger(self.U)))

        if store_state:
            self.__state = state
            # Add info about which function user called
            self.__run_state = 'density_matrix'

        return state
Ejemplo n.º 11
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
Ejemplo n.º 12
0
    def cnot(self, control):
        r"""添加一个CONT门。

        对于2量子比特的量子线路,当control为[0, 1]时,其矩阵形式为:

        .. math::

            \begin{align}
            CNOT &=|0\rangle \langle 0|\otimes I + |1 \rangle \langle 1|\otimes X\\
            &=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix}
            \end{align}

        Args:
            control (list): 作用在的qubit的编号,control[0]为控制位,control[1]为目标位,其值都应该在[0, n)范围内,n为该量子线路的量子比特数。

        ..  code-block:: python

            num_qubits = 2
            with fluid.dygraph.guard():
                cir = UAnsatz(num_qubits)
                cir.cnot([0, 1])
        """

        cnot = dygraph.to_variable(cnot_construct(self.n, control))
        self.state = matmul(self.state, cnot)
Ejemplo n.º 13
0
    def rz(self, theta, which_qubit):
        r"""添加关于y轴的单量子比特旋转门。

        其矩阵形式为:

        .. math::

            \begin{bmatrix} \exp{-i\frac{\theta}{2}} & 0 \\ 0 & \exp{i\frac{\theta}{2}} \end{bmatrix}

        Args:
            theta (Variable): 旋转角度
            which_qubit (int): 作用在的qubit的编号,其值应该在[0, n)范围内,n为该量子线路的量子比特数。

        Returns:
            Variable: 当前量子线路输出的态矢量或者当前量子线路的矩阵表示

        ..  code-block:: python

            theta = np.array([np.pi], np.float64)
            with fluid.dygraph.guard():
                theta = fluid.dygraph.to_variable(theta)
                num_qubits = 1
                cir = UAnsatz(num_qubits)
                which_qubit = 1
                cir.ry(theta[0], which_qubit)
        """

        transform = single_gate_construct(rotation_z(theta), self.n,
                                          which_qubit)
        self.state = matmul(self.state, transform)
Ejemplo n.º 14
0
    def rz(self, theta, which_qubit):
        """
        Rz: the single qubit Z rotation
        """

        transform = single_gate_construct(rotation_z(theta), self.n,
                                          which_qubit)
        self.state = matmul(self.state, transform)
Ejemplo n.º 15
0
    def forward(self, H, N, N_SYS_B, beta, D):
        # 施加量子神经网络
        rho_AB = U_theta(self.initial_state, self.theta, N, D)

        # 计算偏迹 partial trace 来获得子系统B所处的量子态 rho_B
        rho_B = partial_trace(rho_AB, 2**(N - N_SYS_B), 2**(N_SYS_B), 1)

        # 计算三个子损失函数
        rho_B_squre = matmul(rho_B, rho_B)
        loss1 = (trace(matmul(rho_B, H))).real
        loss2 = (trace(rho_B_squre)).real * 2 / beta
        loss3 = -((trace(matmul(rho_B_squre, rho_B))).real + 3) / (2 * beta)

        # 最终的损失函数
        loss = loss1 + loss2 + loss3

        return loss, rho_B
Ejemplo n.º 16
0
    def forward(self, H, N, N_SYS_B, beta, D):
        # Apply quantum neural network onto the initial state
        rho_AB = U_theta(self.initial_state, self.theta, N, D)

        # Calculate the partial tarce to get the state rho_B of subsystem B
        rho_B = partial_trace(rho_AB, 2**(N - N_SYS_B), 2**(N_SYS_B), 1)

        # Calculate the three components of the loss function
        rho_B_squre = matmul(rho_B, rho_B)
        loss1 = (trace(matmul(rho_B, H))).real
        loss2 = (trace(rho_B_squre)).real * 2 / beta
        loss3 = -((trace(matmul(rho_B_squre, rho_B))).real + 3) / (2 * beta)

        # Get the final loss function
        loss = loss1 + loss2 + loss3

        return loss, rho_B
Ejemplo n.º 17
0
    def cnot(self, control):
        """
        :param control: [1,3], the 1st qubit controls 3rd qubit
        :return: cnot module
        """

        cnot = dygraph.to_variable(cnot_construct(self.n, control))
        self.state = matmul(self.state, cnot)
Ejemplo n.º 18
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
Ejemplo n.º 19
0
    def forward(self, input_state, H, N, D):
        """
        :param input_state: The initial state with default |0..>, 'mat'
        :param H: The target Hamiltonian, 'mat'
        :return: The loss, 'float'
        """

        out_state = U_theta(self.theta, input_state, N, D)
        loss = matmul(
            matmul(out_state, H),
            transpose(
                fluid.framework.ComplexVariable(out_state.real,
                                                -out_state.imag),
                perm=[1, 0],
            ),
        )

        return loss.real
Ejemplo n.º 20
0
    def forward(self, H, N):
        # 施加量子神经网络
        U = U_theta(self.theta, N)

        # 计算损失函数
        loss_struct = matmul(matmul(dagger(U), H), U).real

        # 输入计算基去计算每个子期望值,相当于取 U^dagger*H*U 的对角元
        loss_components = [
            loss_struct[0][0], loss_struct[1][1], loss_struct[2][2],
            loss_struct[3][3]
        ]

        # 最终加权求和后的损失函数
        loss = 4 * loss_components[0] + 3 * loss_components[
            1] + 2 * loss_components[2] + 1 * loss_components[3]

        return loss, loss_components
Ejemplo n.º 21
0
    def forward(self, H, N):
        # Apply QNN onto the initial state
        U = U_theta(self.theta, N)

        # Calculate loss function
        loss_struct = matmul(matmul(dagger(U), H), U).real

        # Use computational basis to calculate each expectation value, which is the same
        # as a diagonal element in U^dagger*H*U
        loss_components = [
            loss_struct[0][0], loss_struct[1][1], loss_struct[2][2],
            loss_struct[3][3]
        ]

        # Calculate the weighted loss function
        loss = 4 * loss_components[0] + 3 * loss_components[
            1] + 2 * loss_components[2] + 1 * loss_components[3]

        return loss, loss_components
Ejemplo n.º 22
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()
    def forward(self, x):
        rho_in = fluid.dygraph.to_variable(x)
        E = Encoder(self.theta)
        E_dagger = dagger(E)
        D = E_dagger
        D_dagger = E

        rho_BA = matmul(matmul(E, rho_in), E_dagger)

        rho_encode = partial_trace(rho_BA, 2**N_B, 2**N_A, 1)
        rho_trash = partial_trace(rho_BA, 2**N_B, 2**N_A, 2)

        rho_CA = kron(self.rho_C, rho_encode)
        rho_out = matmul(matmul(D, rho_CA), D_dagger)

        zero_Hamiltonian = fluid.dygraph.to_variable(
            np.diag([1, 0]).astype('complex128'))
        loss = 1 - (trace(matmul(zero_Hamiltonian, rho_trash))).real

        return loss, rho_out, rho_encode
Ejemplo n.º 24
0
    def encoder(self, state_in):
        # 按照随机初始化的参数 theta 
        Encoder = AE_encoder(self.theta1, 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)

        return state_z
Ejemplo n.º 25
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()
Ejemplo n.º 26
0
    def forward(self, H, N):
        """
        Args:
            input_state: The initial state with default |0..>
            H: The target Hamiltonian
        Returns:
            The loss.
        """
        out_state = U_theta(self.theta, N)

        loss_struct = matmul(
            matmul(
                transpose(fluid.framework.ComplexVariable(
                    out_state.real, -out_state.imag),
                          perm=[1, 0]), H), out_state).real

        loss_components = [
            loss_struct[0][0], loss_struct[1][1], loss_struct[2][2],
            loss_struct[3][3]
        ]

        loss = 4 * loss_components[0] + 3 * loss_components[
            1] + 2 * loss_components[2] + 1 * loss_components[3]
        return loss, loss_components
Ejemplo n.º 27
0
    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")