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
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
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
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")
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
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
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
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)
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)