def _compute_samples_display_value(display: ops.SamplesDisplay, state: np.ndarray, qubit_order: ops.QubitOrder, qubit_map: Dict[ops.Qid, int]): n = len(qubit_map) state = np.reshape(state, (2,) * n * 2) basis_change = ops.flatten_op_tree(display.measurement_basis_change()) for op in basis_change: # TODO: Use apply_channel similar to apply_unitary. indices = [qubit_map[qubit] for qubit in op.qubits] gate = cast(ops.GateOperation, op).gate unitary = protocols.unitary(gate) krauss_tensor = np.reshape(unitary, (2,) * gate.num_qubits() * 2) state = linalg.targeted_left_multiply(krauss_tensor, state, indices) # TODO add a test that fails if the below is not performed state = linalg.targeted_left_multiply( np.conjugate(krauss_tensor), state, [x + n for x in indices]) state = state.reshape((2**n, 2**n)) indices = [qubit_map[qubit] for qubit in display.qubits] samples = density_matrix_utils.sample_density_matrix( state, indices, display.num_samples) return display.value_derived_from_samples(samples)
def _compute_samples_display_value(display: ops.SamplesDisplay, state: np.ndarray, qubit_order: ops.QubitOrder, qubit_map: Dict[ops.Qid, int]): basis_change_circuit = circuits.Circuit(display.measurement_basis_change()) modified_state = basis_change_circuit.final_wavefunction( state, qubit_order=qubit_order, qubits_that_should_be_present=qubit_map.keys()) indices = [qubit_map[qubit] for qubit in display.qubits] samples = wave_function.sample_state_vector( modified_state, indices, repetitions=display.num_samples) return display.value_derived_from_samples(samples)