Ejemplo n.º 1
0
def partial_trace(rho_AB, dim1, dim2, A_or_B):
    r"""计算量子态的偏迹。

    Args:
        rho_AB (Tensor): 输入的量子态
        dim1 (int): 系统A的维数
        dim2 (int): 系统B的维数
        A_or_B (int): 1或者2,1表示计算系统A上的偏迹,2表示计算系统B上的偏迹

    Returns:
        Tensor: 输入的量子态的偏迹

    """
    if A_or_B == 2:
        dim1, dim2 = dim2, dim1

    idty_np = np.identity(dim2).astype("complex128")
    idty_B = to_tensor(idty_np)

    zero_np = np.zeros([dim2, dim2], "complex128")
    res = to_tensor(zero_np)

    for dim_j in range(dim1):
        row_top = zeros([1, dim_j], dtype="float64")
        row_mid = ones([1, 1], dtype="float64")
        row_bot = zeros([1, dim1 - dim_j - 1], dtype="float64")
        bra_j = concat([row_top, row_mid, row_bot], axis=1)
        bra_j = paddle.cast(bra_j, 'complex128')

        if A_or_B == 1:
            row_tmp = kron(bra_j, idty_B)
            row_tmp_conj = paddle.conj(row_tmp)
            res = add(
                res,
                matmul(
                    matmul(row_tmp, rho_AB),
                    transpose(row_tmp_conj, perm=[1, 0]),
                ),
            )

        if A_or_B == 2:
            row_tmp = kron(idty_B, bra_j)
            row_tmp_conj = paddle.conj(row_tmp)
            res = add(
                res,
                matmul(
                    matmul(row_tmp, rho_AB),
                    transpose(row_tmp_conj, perm=[1, 0]),
                ),
            )

    return res
Ejemplo n.º 2
0
    def test_case_with_output(self):
        a = np.random.randn(10, 10).astype(np.float64)
        b = np.random.randn(10, 10).astype(np.float64)

        main = fluid.Program()
        start = fluid.Program()
        with fluid.unique_name.guard():
            with fluid.program_guard(main, start):
                a_var = fluid.data("a", [-1, -1], dtype="float64")
                b_var = fluid.data("b", [-1, -1], dtype="float64")
                out_var = fluid.layers.create_tensor("float64", "c")
                paddle.kron(a_var, b_var, out=out_var)

        place = fluid.CPUPlace()
        exe = fluid.Executor(place)
        exe.run(start)
        c, = exe.run(main, feed={'a': a, 'b': b}, fetch_list=[out_var])
        np.testing.assert_allclose(c, np.kron(a, b))
Ejemplo n.º 3
0
    def __measure_parameterized(self, state, which_qubits, result_desired,
                                theta):
        r"""进行参数化的测量。

        Args:
            state (Tensor): 输入的量子态
            which_qubits (list): 测量作用的量子比特编号
            result_desired (str): 期望得到的测量结果
            theta (Tensor): 测量运算的参数

        Returns:
            Tensor: 测量坍塌后的量子态
            Tensor:测量坍塌得到的概率
            str: 测量得到的结果
        """
        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 = [paddle.to_tensor(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 = paddle.to_tensor(
                    np.array([[1, 0], [0, 0]], dtype=np.complex128))
                basis1 = paddle.to_tensor(
                    np.array([[0, 0], [0, 1]], dtype=np.complex128))
                rho0 = multiply(basis0, cos(theta[idx]))
                rho1 = multiply(basis1, sin(theta[idx]))
                rho = add(rho0, rho1)
                op_list[i] = rho
            elif int(ele) == 1:
                # rho = diag(concat([cos(theta[idx]), sin(theta[idx])]))
                # rho = paddle.to_tensor(rho, zeros((2, 2), dtype="float64"))
                basis0 = paddle.to_tensor(
                    np.array([[1, 0], [0, 0]], dtype=np.complex128))
                basis1 = paddle.to_tensor(
                    np.array([[0, 0], [0, 1]], dtype=np.complex128))
                rho0 = multiply(basis0, sin(theta[idx]))
                rho1 = multiply(basis1, cos(theta[idx]))
                rho = add(rho0, rho1)
                op_list[i] = rho
            else:
                print("cannot recognize the result_desired.")
            # rho = paddle.to_tensor(ones((2, 2), dtype="float64"), zeros((2, 2), dtype="float64"))
        measure_operator = paddle.to_tensor(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 = real(
            trace(
                matmul(matmul(dagger(measure_operator), measure_operator),
                       state)))
        state_measured = divide(state_measured, prob)
        return state_measured, prob, result_desired
Ejemplo n.º 4
0
    def test_case(self):
        a = np.random.randn(10, 10).astype(np.float64)
        b = np.random.randn(10, 10).astype(np.float64)

        place = fluid.CPUPlace()
        with dg.guard(place):
            a_var = dg.to_variable(a)
            b_var = dg.to_variable(b)
            c_var = paddle.kron(a_var, b_var)
            np.testing.assert_allclose(c_var.numpy(), np.kron(a, b))
Ejemplo n.º 5
0
 def forward(self, problem=1):
     jj = paddle.to_tensor(np.array([1j], dtype=np.complex64))
     # tr = paddle.trace(self.A)
     # _A = paddle.abs(self.A)
     self.A = paddle.abs(self.A)
     self.theta2 = self.theta0 + self.theta1 * jj
     if problem == 1:
         # matmul不支持不同dtype之间的运算
         loss = paddle.sum(paddle.matmul(self.theta0, self.A))
         return loss
     elif problem == 2:
         # kron在复数情况下不支持梯度反传
         tmp_theta = paddle.kron(self.theta0, self.theta2)
         tmp_A = paddle.kron(self.A, self.B)
         loss = paddle.sum(paddle.matmul(tmp_theta, tmp_A))
         return loss.real()
     elif problem == 3:
         # loss有时会越来越大
         loss = paddle.sum(paddle.matmul(self.theta2, self.A))
         # print("loss: ", loss)
         return loss.real()
     else:
         raise NotImplementedError
Ejemplo n.º 6
0
    def forward(self, x):
        #TODO:
        matrix = paddle.ones([1, 1], dtype=np.float32)
        for t in self.thetas:
            cs = paddle.cos(t / 2)
            sn = paddle.sin(t / 2)
            m = paddle.concat([
                paddle.concat([cs, -sn], axis=1),
                paddle.concat([sn, cs], axis=1),
            ],
                              axis=0)
            matrix = paddle.kron(matrix, m)

        x = paddle.matmul(matrix, x)
        return x
Ejemplo n.º 7
0
    def set_init_state(self, state, which_qubits):
        r"""对 LoccNet 的初始 LOCC 态节点进行初始化。

        Args:
            state (Tensor): 输入的量子态的矩阵形式
            which_qubits (tuple or list): 该量子态所对应的量子比特,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list``
        """
        if isinstance(which_qubits, tuple):
            which_qubits = [which_qubits]
        temp_len = int(log2(sqrt(self.init_status.state.numpy().size)))
        self.init_status.state = kron(self.init_status.state, state)
        for idx, (party_id, qubit_id) in enumerate(which_qubits):
            if isinstance(party_id, str):
                self.parties_by_name[party_id][qubit_id] = (temp_len + idx)
            elif isinstance(party_id, int):
                self.parties_by_number[party_id][qubit_id] = (temp_len + idx)
            else:
                raise ValueError
Ejemplo n.º 8
0
    def reset_state(self, status, state, which_qubits):
        r"""用于重置你想要的量子比特上的部分量子态。

        Args:
            status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list``
            state (Tensor): 输入的量子态的矩阵形式
            which_qubits (tuple or list): 指定需要被重置的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple``,或者由其组成的 ``list``

        Returns:
            LoccStatus or list: 重置部分量子比特的量子态后的 LOCC 态节点,其类型为 ``LoccStatus`` 或者由其组成的 ``list``
        """
        if isinstance(which_qubits, tuple):
            which_qubits = [which_qubits]
        qubits_list = list()
        for party_id, qubit_id in which_qubits:
            if isinstance(party_id, str):
                qubits_list.append(self.parties_by_name[party_id][qubit_id])
            elif isinstance(party_id, int):
                qubits_list.append(self.parties_by_number[party_id][qubit_id])
            else:
                raise ValueError
        m = len(qubits_list)
        if isinstance(status, LoccStatus):
            n = int(log2(sqrt(status.state.numpy().size)))
        elif isinstance(status, list):
            n = int(log2(sqrt(status[0].state.numpy().size)))
        else:
            raise ValueError("can't recognize the input status")
        assert max(qubits_list) <= n, "qubit index out of range"

        origin_seq = list(range(0, n))
        target_seq = [idx for idx in origin_seq if idx not in qubits_list]
        target_seq = qubits_list + target_seq

        swaped = [False] * n
        swap_list = []
        for idx in range(0, n):
            if not swaped[idx]:
                next_idx = idx
                swaped[next_idx] = True
                while not swaped[target_seq[next_idx]]:
                    swaped[target_seq[next_idx]] = True
                    swap_list.append((next_idx, target_seq[next_idx]))
                    next_idx = target_seq[next_idx]

        cir0 = UAnsatz(n)
        for a, b in swap_list:
            cir0.swap([a, b])

        cir1 = UAnsatz(n)
        swap_list.reverse()
        for a, b in swap_list:
            cir1.swap([a, b])

        if isinstance(status, LoccStatus):
            _state = cir0.run_density_matrix(status.state)
            _state = partial_trace(_state, 2**m, 2**(n - m), 1)
            _state = kron(state, _state)
            _state = cir1.run_density_matrix(_state)
            new_status = LoccStatus(_state, status.prob,
                                    status.measured_result)
        elif isinstance(status, list):
            new_status = list()
            for each_status in status:
                _state = cir0.run_density_matrix(each_status.state)
                _state = partial_trace(_state, 2**m, 2**(n - m), 1)
                _state = kron(state, _state)
                _state = cir1.run_density_matrix(_state)
                new_status.append(
                    LoccStatus(_state, each_status.prob,
                               each_status.measured_result))
        else:
            raise ValueError("can't recognize the input status")

        return new_status
Ejemplo n.º 9
0
 def test_kron_api(self, place):
     with dg.guard(place):
         x_var = dg.to_variable(self.x)
         y_var = dg.to_variable(self.y)
         out_var = paddle.kron(x_var, y_var)
         self.assertTrue(np.allclose(out_var.numpy(), self.ref_result))
Ejemplo n.º 10
0
    def reset_state(self, status, state, which_qubits):
        r"""用于重置你想要的量子比特上的部分量子态。

        Args:
            status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list``
            state (Tensor): 输入的量子态的矩阵形式
            which_qubits (tuple or list): 指定需要被重置的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple``,或者由其组成的 ``list``

        Returns:
            LoccStatus or list: 重置部分量子比特的量子态后的 LOCC 态节点,其类型为 ``LoccStatus`` 或者由其组成的 ``list``
        """
        if isinstance(which_qubits, tuple):
            which_qubits = [which_qubits]
        qubits_list = list()
        for party_id, qubit_id in which_qubits:
            if isinstance(party_id, str):
                qubits_list.append(self.parties_by_name[party_id][qubit_id])
            elif isinstance(party_id, int):
                qubits_list.append(self.parties_by_number[party_id][qubit_id])
            else:
                raise ValueError
        m = len(qubits_list)
        if isinstance(status, LoccStatus):
            n = int(log2(sqrt(status.state.numpy().size)))
        elif isinstance(status, list):
            n = int(log2(sqrt(status[0].state.numpy().size)))
        else:
            raise ValueError("can't recognize the input status")
        assert max(qubits_list) <= n, "qubit index out of range"

        qubit2idx = list(range(0, n))
        idx2qubit = list(range(0, n))
        swap_history = list()

        cir0 = UAnsatz(n)
        for i, ele in enumerate(qubits_list):
            if qubit2idx[
                    ele] != i:  # if qubit2idx[ele] is i, then swap([ele, i]) is identity
                swap_history.append((i, qubit2idx[ele]))
                cir0.swap([i, qubit2idx[ele]])
                qubit2idx[idx2qubit[i]] = qubit2idx[ele]
                idx2qubit[qubit2idx[ele]] = idx2qubit[i]
                idx2qubit[i] = ele
                qubit2idx[ele] = i

        cir1 = UAnsatz(n)
        swap_cnt = len(swap_history)
        for idx in range(0, swap_cnt):
            a, b = swap_history[swap_cnt - 1 - idx]
            cir1.swap([b, a])

        if isinstance(status, LoccStatus):
            _state = cir0.run_density_matrix(status.state)
            _state = partial_trace(_state, 2**m, 2**(n - m), 1)
            _state = kron(state, _state)
            _state = cir1.run_density_matrix(_state)
            new_status = LoccStatus(_state, status.prob,
                                    status.measured_result)
        elif isinstance(status, list):
            new_status = list()
            for each_status in status:
                _state = cir0.run_density_matrix(each_status.state)
                _state = partial_trace(_state, 2**m, 2**(n - m), 1)
                _state = kron(state, _state)
                _state = cir1.run_density_matrix(_state)
                new_status.append(
                    LoccStatus(_state, each_status.prob,
                               each_status.measured_result))
        else:
            raise ValueError("can't recognize the input status")

        return new_status