def test_purity_mixed_state(self): state_1 = 0.5 * (projector(basis_state('0', 1)) + projector(basis_state('1', 1))) state_2 = (1 / 3.0) * (projector(basis_state('00', 2)) + projector( basis_state('01', 2)) + projector(basis_state('10', 2))) self.assertEqual(purity(state_1), 0.5) self.assertEqual(purity(state_2), 1.0 / 3)
def test_purity_list_input(self): rho1 = [[1, 0], [0, 0]] rho2 = [[0.5, 0], [0, 0.5]] rho3 = 0.7 * np.array(rho1) + 0.3 * np.array(rho2) test_pass = (purity(rho1) == 1.0 and purity(rho2) == 0.5 and round(purity(rho3), 10) == 0.745) self.assertTrue(test_pass)
def test_purity_basis_state_input(self): state_1 = basis_state('0', 1) state_2 = basis_state('11', 2) state_3 = basis_state('010', 3) self.assertEqual(purity(state_1), 1.0) self.assertEqual(purity(state_2), 1.0) self.assertEqual(purity(state_3), 1.0)
def test_purity_equivalence(self): """Test purity is same for equivalent inputs""" for alpha, beta in [(0, 0), (0, 0.25), (0.25, 0), (0.33, 0.33), (0.5, 0.5), (0.75, 0.25), (0, 0.75)]: psi = Statevector( [alpha, beta, 0, 1j * np.sqrt(1 - alpha**2 - beta**2)]) rho = DensityMatrix(psi) self.assertAlmostEqual(purity(psi), purity(rho))
def test_purity_pure_state(self): state_1 = (1/np.sqrt(2))*(basis_state('0', 1) + basis_state('1', 1)) state_2 = (1/np.sqrt(3))*(basis_state('00', 2) + basis_state('01', 2) + basis_state('11', 2)) state_3 = 0.5*(basis_state('000', 3) + basis_state('001', 3) + basis_state('010', 3) + basis_state('100', 3)) self.assertEqual(purity(state_1), 1.0) self.assertEqual(purity(state_2), 1.0) self.assertEqual(purity(state_3), 1.0)
def test_purity_pure_matrix_state(self): state_1 = (1/np.sqrt(2))*(basis_state('0', 1) + basis_state('1', 1)) state_1 = projector(state_1) state_2 = (1/np.sqrt(3))*(basis_state('00', 2) + basis_state('01', 2) + basis_state('11', 2)) state_2 = projector(state_2) state_3 = 0.5*(basis_state('000', 3) + basis_state('001', 3) + basis_state('010', 3) + basis_state('100', 3)) state_3 = projector(state_3) self.assertAlmostEqual(purity(state_1), 1.0, places=10) self.assertAlmostEqual(purity(state_2), 1.0, places=10) self.assertEqual(purity(state_3), 1.0)
def test_purity_density_matrix(self): """Test purity function on density matrix inputs""" rho = DensityMatrix(np.diag([1, 0, 0, 0])) self.assertEqual(purity(rho), 1) self.assertEqual(purity(rho, validate=True), 1) self.assertEqual(purity(rho, validate=False), 1) rho = np.diag([0.25, 0.25, 0.25, 0.25]) self.assertEqual(purity(rho), 0.25) self.assertEqual(purity(rho, validate=True), 0.25) self.assertEqual(purity(rho, validate=False), 0.25) rho = [[0.5, 0, 0, 0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0.5, 0, 0, 0.5]] self.assertEqual(purity(rho), 1) self.assertEqual(purity(rho, validate=True), 1) self.assertEqual(purity(rho, validate=False), 1) rho = np.diag([1, 0, 0, 1]) self.assertRaises(QiskitError, purity, rho) self.assertRaises(QiskitError, purity, rho, validate=True) self.assertEqual(purity(rho, validate=False), 2)
def test_purity_statevector(self): """Test purity function on statevector inputs""" psi = Statevector([1, 0, 0, 0]) self.assertEqual(purity(psi), 1) self.assertEqual(purity(psi, validate=True), 1) self.assertEqual(purity(psi, validate=False), 1) psi = [0.70710678118654746, 0.70710678118654746] self.assertAlmostEqual(purity(psi), 1) self.assertAlmostEqual(purity(psi, validate=True), 1) self.assertAlmostEqual(purity(psi, validate=False), 1) psi = np.array([0.5, 0.5j, -0.5j, -0.5]) self.assertAlmostEqual(purity(psi), 1) self.assertAlmostEqual(purity(psi, validate=True), 1) self.assertAlmostEqual(purity(psi, validate=False), 1) psi = Statevector([1, 0, 0, 1]) self.assertRaises(QiskitError, purity, psi) self.assertRaises(QiskitError, purity, psi, validate=True) self.assertEqual(purity(psi, validate=False), 4)
def test_purity_statevector_density_matrix(self): """Test purity is same for equivalent statevector and density matrix inputs""" psi = Statevector([0.5, -0.5, 0.5j, -0.5j]) rho = DensityMatrix(psi) self.assertAlmostEqual(purity(psi), purity(rho)) psi = Statevector([0.5, 0, 0, -0.5j]) rho = DensityMatrix(psi) self.assertAlmostEqual(purity(psi, validate=False), purity(rho, validate=False)) psi = Statevector([1, 1]) rho = DensityMatrix(psi) self.assertAlmostEqual(purity(psi, validate=False), purity(rho, validate=False))
def test_purity_1d_list_input(self): input_state = [1, 0] res = purity(input_state) self.assertEqual(1, res)
def __init__(self, initial_state: InitialState, operator: Optional[BaseOperator] = None, q: Optional[float] = 0.5, num_ancillae: Optional[int] = 0, var_form: Optional[VariationalForm] = None, optimizer: Optional[Optimizer] = None, initial_point: Optional[np.ndarray] = None, max_evals_grouped: int = 1, callback: Optional[Callable[[int, np.ndarray, float, float], None]] = None, quantum_instance: Optional[Union[QuantumInstance, BaseBackend]] = None) -> None: """ Constructor. Args: initial_state (InitialState): The state to be diagonalized operator (BaseOperator): The density matrix of the initial state q (int): Free parameter that ones to tailer the VQSD method num_ancillae (int): The number of ancillae qubits if the initial state is a mixed state var_form: A parameterized variational form (ansatz). optimizer: A classical optimizer. initial_point: An optional initial point (i.e. initial parameter values) for the optimizer. If ``None`` then VQE will look to the variational form for a preferred point and if not will simply compute a random one. max_evals_grouped: Max number of evaluations performed simultaneously. Signals the given optimizer that more than one set of parameters can be supplied so that potentially the expectation values can be computed in parallel. Typically this is possible when a finite difference gradient is used by the optimizer such that multiple points to compute the gradient can be passed and if computed in parallel improve overall execution time. callback: a callback that can access the intermediate data during the optimization. Four parameter values are passed to the callback as follows during each evaluation by the optimizer for its current set of parameters as it works towards the minimum. These are: the evaluation count, the optimizer parameters for the variational form, the evaluated global cost, local cost and weighted cost quantum_instance: Quantum Instance or Backend """ validate_min('max_evals_grouped', max_evals_grouped, 1) validate_range('num_ancillae', num_ancillae, 0, initial_state._num_qubits - 1) validate_range('q', q, 0.0, 1.0) if var_form is None: # TODO after ansatz refactor num qubits can be set later so we do not have to have # an operator to create a default if initial_state is not None: var_form = RY(initial_state._num_qubits - num_ancillae) if optimizer is None: optimizer = SLSQP() if operator is None: initial_state_vector = initial_state.construct_circuit(mode='vector') mat = np.outer(initial_state_vector, np.conj(initial_state_vector)) operator = DensityMatrix(mat) # TODO after ansatz refactor we may still not be able to do this # if num qubits is not set on var form if initial_point is None and var_form is not None: initial_point = var_form.preferred_init_points self._max_evals_grouped = max_evals_grouped super().__init__(var_form=var_form, optimizer=optimizer, cost_fn=self._cost_evaluation, initial_point=initial_point, quantum_instance=quantum_instance) self._callback = callback self._use_simulator_snapshot_mode = None self._ret = None self._eval_time = None self._eval_count = 0 logger.info(self.print_settings()) self._var_form_params = None if self.var_form is not None: self._var_form_params = ParameterVector('θ', self.var_form.num_parameters) self._parameterized_circuits = None self._initial_state = initial_state self._q = q self._num_ancillae = num_ancillae self._num_working_qubits = initial_state._num_qubits - num_ancillae self._operator = operator self.initial_state = initial_state # TODO : Verify that if the ancillae qubits form an orthonormal basis # Compute state purity if self._num_ancillae > 0: # pylint: disable=import-outside-toplevel from qiskit.quantum_info import purity, partial_trace rho = self._operator.data ancillae_idx = list(set(range(self._initial_state._num_qubits)) - set(range(self._num_ancillae))) self._operator = partial_trace(rho, ancillae_idx) self._purity = purity(self._operator) else: self._purity = 1.0