Пример #1
0
    def __measure_parameterless(self, state, which_qubits, result_desired):
        r"""进行 01 测量。

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

        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 = [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 = paddle.to_tensor(NKron(*op_list))
        else:
            measure_operator = paddle.to_tensor(op_list[0])
        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
Пример #2
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
Пример #3
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 trace 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 = paddle.real(trace(matmul(rho_B, H)))
        loss2 = paddle.real(trace(rho_B_squre)) * 2 / beta
        loss3 = -(paddle.real(trace(matmul(rho_B_squre, rho_B))) + 3) / (2 *
                                                                         beta)

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

        return loss, rho_B
Пример #4
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:
            Tensor: 量子线路输出的量子态关于 H 的期望值

        代码示例:
        
        .. code-block:: python
            
            import numpy as np
            import paddle
            from paddle_quantum.circuit import UAnsatz
            n = 5
            H_info = [[0.1, 'x1'], [0.2, 'y0,z4']]
            theta = paddle.to_tensor(np.ones(3))
            cir = UAnsatz(n)
            cir.rx(theta[0], 0)
            cir.rz(theta[1], 1)
            cir.rx(theta[2], 2)
            cir.run_state_vector()
            expect_value = cir.expecval(H_info).numpy()
            print(f'Calculated expectation value of {H_info} is {expect_value}')

        ::

            Calculated expectation value of [[0.1, 'x1'], [0.2, 'y0,z4']] is [-0.1682942]

        """
        if self.__run_state == 'state_vector':
            return real(vec_expecval(H, self.__state))
        elif self.__run_state == 'density_matrix':
            state = self.__state
            H_mat = paddle.to_tensor(pauli_str_to_matrix(H, self.n))
            return real(trace(matmul(state, H_mat)))
        else:
            # Raise error
            raise ValueError(
                "no state for measurement; please run the circuit first")
Пример #5
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 paddle.real(loss), rho_tilde
Пример #6
0
    def run_density_matrix(self, input_state=None, store_state=True):
        r"""运行当前的量子线路,输入输出的形式为密度矩阵。
        
        Args:
            input_state (Tensor, optional): 输入的密度矩阵,默认为 :math:`|00...0\rangle \langle00...0|`
            store_state (bool, optional): 是否存储输出的密度矩阵,默认为 ``True`` ,即存储
        
        Returns:
            Tensor: 量子线路输出的密度矩阵

        代码示例:

        .. code-block:: python

            import numpy as np
            import paddle
            from paddle_quantum.circuit import UAnsatz
            from paddle_quantum.state import density_op
            n = 1
            theta = np.ones(3)

            input_state = paddle.to_tensor(density_op(n))
            theta = paddle.to_tensor(theta)
            cir = UAnsatz(n)
            cir.rx(theta[0], 0)
            cir.ry(theta[1], 0)
            cir.rz(theta[2], 0)
            density_matrix = cir.run_density_matrix(input_state).numpy()
            print(f"The output density matrix is\n{density_matrix}")

        ::

            The output density matrix is
            [[0.64596329+0.j         0.47686058+0.03603751j]
            [0.47686058-0.03603751j 0.35403671+0.j        ]]
        """
        state = paddle.to_tensor(density_op(
            self.n)) if input_state is None else input_state

        assert paddle.real(state).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
Пример #7
0
    def forward(self, H, N):
        # Apply QNN onto the initial state
        U = U_theta(self.theta, N)

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

        # 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
Пример #8
0
    def measure(self, which_qubits=None, shots=2**10, plot=False):
        r"""对量子线路输出的量子态进行测量。

        Warning:
            当 ``plot`` 为 ``True`` 时,当前量子线路的量子比特数需要小于 6 ,否则无法绘制图片,会抛出异常。

        Args:
            which_qubits (list, optional): 要测量的qubit的编号,默认全都测量
            shots (int, optional): 该量子线路输出的量子态的测量次数,默认为 1024 次;若为 0,则返回测量结果的精确概率分布
            plot (bool, optional): 是否绘制测量结果图,默认为 ``False`` ,即不绘制
        
        Returns:
            dict: 测量的结果

        代码示例:

        .. code-block:: python
        
            import paddle
            from paddle_quantum.circuit import UAnsatz
            cir = UAnsatz(2)
            cir.h(0)
            cir.cnot([0,1])
            cir.run_state_vector()
            result = cir.measure(shots = 2048, which_qubits = [1])
            print(f"The results of measuring qubit 1 2048 times are {result}")

        ::

            The results of measuring qubit 1 2048 times are {'0': 964, '1': 1084}

        .. code-block:: python

            import paddle
            from paddle_quantum.circuit import UAnsatz
            cir = UAnsatz(2)
            cir.h(0)
            cir.cnot([0,1])
            cir.run_state_vector()
            result = cir.measure(shots = 0, which_qubits = [1])
            print(f"The probability distribution of measurement results on qubit 1 is {result}")

        ::

            The probability distribution of measurement results on qubit 1 is {'0': 0.4999999999999999, '1': 0.4999999999999999}
        """
        if self.__run_state == 'state_vector':
            state = self.__state
        elif self.__run_state == 'density_matrix':
            # Take the diagonal of the density matrix as a probability distribution
            diag = np.diag(self.__state.numpy())
            state = paddle.to_tensor(np.sqrt(diag))
        else:
            # Raise error
            raise ValueError(
                "no state for measurement; please run the circuit first")

        if shots == 0:  # Returns probability distribution over all measurement results
            dic2to10, dic10to2 = dic_between2and10(self.n)
            result = {}
            for i in range(2**self.n):
                result[dic10to2[i]] = (real(state)[i]**2 +
                                       imag(state)[i]**2).numpy()[0]

            if which_qubits is not None:
                new_result = [(self.__process_string(key, which_qubits), value)
                              for key, value in result.items()]
                result = self.__process_similiar(new_result)
        else:
            if which_qubits is None:  # Return all the qubits
                result = measure_state(state, shots)
            else:
                assert all([e < self.n
                            for e in which_qubits]), 'Qubit index out of range'
                which_qubits.sort()  # Sort in ascending order

                collapse_all = measure_state(state, shots)
                new_collapse_all = [(self.__process_string(key, which_qubits),
                                     value)
                                    for key, value in collapse_all.items()]
                result = self.__process_similiar(new_collapse_all)

        return result if not plot else self.__measure_hist(
            result, which_qubits, shots)
Пример #9
0
    def run_state_vector(self, input_state=None, store_state=True):
        r"""运行当前的量子线路,输入输出的形式为态矢量。
        
        Args:
            input_state (Tensor, optional): 输入的态矢量,默认为 :math:`|00...0\rangle`
            store_state (Bool, optional): 是否存储输出的态矢量,默认为 ``True`` ,即存储
        
        Returns:
            Tensor: 量子线路输出的态矢量
        
        代码示例:

        .. code-block:: python

            import numpy as np
            import paddle
            from paddle_quantum.circuit import UAnsatz
            from paddle_quantum.state import vec
            n = 2
            theta = np.ones(3)

            input_state = paddle.to_tensor(vec(n))
            theta = paddle.to_tensor(theta)
            cir = UAnsatz(n)
            cir.h(0)
            cir.ry(theta[0], 1)
            cir.rz(theta[1], 1)
            output_state = cir.run_state_vector(input_state).numpy()
            print(f"The output state vector is {output_state}")

        ::

            The output state vector is [[0.62054458+0.j 0.18316521+0.28526291j 0.62054458+0.j 0.18316521+0.28526291j]]
        """
        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 = paddle.conj(state)
        assert paddle.abs(paddle.real(paddle.sum(multiply(state_conj, state))) - 1) < 1e-8, \
            'Input state is not a normalized vector'

        for history_ele in self.__history:
            if history_ele[0] == 'u':
                state = StateTransfer(state, 'u', history_ele[1],
                                      history_ele[2])
            elif history_ele[0] in {'x', 'y', 'z', 'h'}:
                state = StateTransfer(state,
                                      history_ele[0],
                                      history_ele[1],
                                      params=history_ele[2])
            elif history_ele[0] == 'SWAP':
                state = StateTransfer(state, 'SWAP', history_ele[1])
            elif history_ele[0] == 'CNOT':
                state = StateTransfer(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)