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
def reset_state(self, status, state, which_qubits): r"""用于重置你想要的量子比特上的部分量子态。 Args: status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list`` state (ComplexVariable): 输入的量子态的矩阵形式 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
def partial_state(self, status, which_qubits, is_desired=True): r"""得到你想要的部分量子比特上的量子态。 Args: status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list`` which_qubits (tuple or list): 指定的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list`` is_desired (bool, optional): 默认是 ``True`` ,即返回量子比特上的部分量子态。如果为 ``False`` ,则抛弃这部分量子比特上的量子态,返回剩下的部分量子态 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] cir = UAnsatz(n) for a, b in swap_list: cir.swap([a, b]) if isinstance(status, LoccStatus): state = cir.run_density_matrix(status.state) if is_desired: state = partial_trace(state, 2**m, 2**(n - m), 2) else: state = partial_trace(state, 2**m, 2**(n - m), 1) new_status = LoccStatus(state, status.prob, status.measured_result) elif isinstance(status, list): new_status = list() for each_status in status: state = cir.run_density_matrix(each_status.state) if is_desired: state = partial_trace(state, 2**m, 2**(n - m), 2) else: state = partial_trace(state, 2**m, 2**(n - m), 1) new_status.append( LoccStatus(state, each_status.prob, each_status.measured_result)) else: raise ValueError("can't recognize the input status") return new_status
def partial_state(self, status, which_qubits, is_desired=True): r"""得到你想要的部分量子比特上的量子态。 Args: status (LoccStatus or list): 输入的 LOCC 态节点,其类型应该为 ``LoccStatus`` 或者由其组成的 ``list`` which_qubits (tuple or list): 指定的量子比特编号,其形式为 ``(party_id, qubit_id)`` 的 ``tuple`` ,或者由其组成的 ``list`` is_desired (bool, optional): 默认是 ``True`` ,即返回量子比特上的部分量子态。如果为 ``False`` ,则抛弃这部分量子比特上的量子态,返回剩下的部分量子态 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)) cir = UAnsatz(n) for i, ele in enumerate(qubits_list): if qubit2idx[ele] != i: # if qubit2idx[ele] is i, then swap([ele, i]) is identity cir.swap([i, qubit2idx[ele]]) qubit2idx[idx2qubit[i]] = qubit2idx[ele] idx2qubit[qubit2idx[ele]] = idx2qubit[i] idx2qubit[i] = ele qubit2idx[ele] = i if isinstance(status, LoccStatus): state = cir.run_density_matrix(status.state) if is_desired: state = partial_trace(state, 2**m, 2**(n - m), 2) else: state = partial_trace(state, 2**m, 2**(n - m), 1) new_status = LoccStatus(state, status.prob, status.measured_result) elif isinstance(status, list): new_status = list() for each_status in status: state = cir.run_density_matrix(each_status.state) if is_desired: state = partial_trace(state, 2**m, 2**(n - m), 2) else: state = partial_trace(state, 2**m, 2**(n - m), 1) new_status.append( LoccStatus(state, each_status.prob, each_status.measured_result)) else: raise ValueError("can't recognize the input status") return new_status