def _eval_aux_ops( self, parameters: np.ndarray, aux_operators: ListOrDict[OperatorBase], expectation: ExpectationBase, threshold: float = 1e-12, ) -> ListOrDict[Tuple[complex, complex]]: # Create new CircuitSampler to avoid breaking existing one's caches. sampler = CircuitSampler(self.quantum_instance) if isinstance(aux_operators, dict): list_op = ListOp(list(aux_operators.values())) else: list_op = ListOp(aux_operators) aux_op_meas = expectation.convert(StateFn(list_op, is_measurement=True)) aux_op_expect = aux_op_meas.compose( CircuitStateFn(self.ansatz.bind_parameters(parameters))) aux_op_expect_sampled = sampler.convert(aux_op_expect) # compute means values = np.real(aux_op_expect_sampled.eval()) # compute standard deviations variances = np.real( expectation.compute_variance(aux_op_expect_sampled)) if not isinstance(variances, np.ndarray) and variances == 0.0: # when `variances` is a single value equal to 0., our expectation value is exact and we # manually ensure the variances to be a list of the correct length variances = np.zeros(len(aux_operators), dtype=float) std_devs = np.sqrt(variances / self.quantum_instance.run_config.shots) # Discard values below threshold aux_op_means = values * (np.abs(values) > threshold) # zip means and standard deviations into tuples aux_op_results = zip(aux_op_means, std_devs) # Return None eigenvalues for None operators if aux_operators is a list. # None operators are already dropped in compute_minimum_eigenvalue if aux_operators is a dict. if isinstance(aux_operators, list): aux_operator_eigenvalues = [None] * len(aux_operators) key_value_iterator = enumerate(aux_op_results) else: aux_operator_eigenvalues = {} key_value_iterator = zip(aux_operators.keys(), aux_op_results) for key, value in key_value_iterator: if aux_operators[key] is not None: aux_operator_eigenvalues[key] = value return aux_operator_eigenvalues
def _eval_aux_ops( self, parameters: np.ndarray, aux_operators: List[OperatorBase], expectation: ExpectationBase, threshold: float = 1e-12, ) -> np.ndarray: # Create new CircuitSampler to avoid breaking existing one's caches. sampler = CircuitSampler(self.quantum_instance) aux_op_meas = expectation.convert( StateFn(ListOp(aux_operators), is_measurement=True)) aux_op_expect = aux_op_meas.compose( CircuitStateFn(self.ansatz.bind_parameters(parameters))) values = np.real(sampler.convert(aux_op_expect).eval()) # Discard values below threshold aux_op_results = values * (np.abs(values) > threshold) # Deal with the aux_op behavior where there can be Nones or Zero qubit Paulis in the list _aux_op_nones = [op is None for op in aux_operators] aux_operator_eigenvalues = [ None if is_none else [result] for (is_none, result) in zip(_aux_op_nones, aux_op_results) ] # As this has mixed types, since it can included None, it needs to explicitly pass object # data type to avoid numpy 1.19 warning message about implicit conversion being deprecated aux_operator_eigenvalues = np.array([aux_operator_eigenvalues], dtype=object) return aux_operator_eigenvalues
def _get_observable_evaluator( ansatz: QuantumCircuit, observables: Union[OperatorBase, List[OperatorBase]], expectation: ExpectationBase, sampler: CircuitSampler, ) -> Callable[[np.ndarray], Union[float, List[float]]]: """Get a callable to evaluate a (list of) observable(s) for given circuit parameters.""" if isinstance(observables, list): observables = ListOp(observables) expectation_value = StateFn(observables, is_measurement=True) @ StateFn(ansatz) converted = expectation.convert(expectation_value) ansatz_parameters = ansatz.parameters def evaluate_observables(theta: np.ndarray) -> Union[float, List[float]]: """Evaluate the observables for the ansatz parameters ``theta``. Args: theta: The ansatz parameters. Returns: The observables evaluated at the ansatz parameters. """ value_dict = dict(zip(ansatz_parameters, theta)) sampled = sampler.convert(converted, params=value_dict) return sampled.eval() return evaluate_observables
def _compute_std_devs( observables_expect_sampled: OperatorBase, observables: ListOrDict[OperatorBase], expectation: ExpectationBase, quantum_instance: Union[QuantumInstance, BaseBackend, Backend], ) -> List[complex]: """ Calculates a list of standard deviations from expectation values of observables provided. Args: observables_expect_sampled: Expected values of observables. observables: A list or a dictionary of operators whose expectation values are to be calculated. expectation: An instance of ExpectationBase which defines a method for calculating expectation values. quantum_instance: A quantum instance used for calculations. Returns: A list of standard deviations. """ variances = np.real(expectation.compute_variance(observables_expect_sampled)) if not isinstance(variances, np.ndarray) and variances == 0.0: # when `variances` is a single value equal to 0., our expectation value is exact and we # manually ensure the variances to be a list of the correct length variances = np.zeros(len(observables), dtype=float) std_devs = np.sqrt(variances / quantum_instance.run_config.shots) return std_devs
def _eval_aux_ops( self, parameters: np.ndarray, aux_operators: ListOrDict[OperatorBase], expectation: ExpectationBase, threshold: float = 1e-12, ) -> ListOrDict[complex]: # Create new CircuitSampler to avoid breaking existing one's caches. sampler = CircuitSampler(self.quantum_instance) if isinstance(aux_operators, dict): list_op = ListOp(list(aux_operators.values())) else: list_op = ListOp(aux_operators) aux_op_meas = expectation.convert(StateFn(list_op, is_measurement=True)) aux_op_expect = aux_op_meas.compose( CircuitStateFn(self.ansatz.bind_parameters(parameters))) values = np.real(sampler.convert(aux_op_expect).eval()) # Discard values below threshold aux_op_results = values * (np.abs(values) > threshold) # Return None eigenvalues for None operators if aux_operators is a list. # None operators are already dropped in compute_minimum_eigenvalue if aux_operators is a dict. if isinstance(aux_operators, list): aux_operator_eigenvalues = [None] * len(aux_operators) key_value_iterator = enumerate(aux_op_results) else: aux_operator_eigenvalues = {} key_value_iterator = zip(aux_operators.keys(), aux_op_results) for key, value in key_value_iterator: if aux_operators[key] is not None: aux_operator_eigenvalues[key] = value return aux_operator_eigenvalues
def eval_observables( quantum_instance: Union[QuantumInstance, BaseBackend, Backend], quantum_state: Union[ Statevector, QuantumCircuit, OperatorBase, ], observables: ListOrDict[OperatorBase], expectation: ExpectationBase, threshold: float = 1e-12, ) -> ListOrDict[Tuple[complex, complex]]: """ Accepts a list or a dictionary of operators and calculates their expectation values - means and standard deviations. They are calculated with respect to a quantum state provided. A user can optionally provide a threshold value which filters mean values falling below the threshold. Args: quantum_instance: A quantum instance used for calculations. quantum_state: An unparametrized quantum circuit representing a quantum state that expectation values are computed against. observables: A list or a dictionary of operators whose expectation values are to be calculated. expectation: An instance of ExpectationBase which defines a method for calculating expectation values. threshold: A threshold value that defines which mean values should be neglected (helpful for ignoring numerical instabilities close to 0). Returns: A list or a dictionary of tuples (mean, standard deviation). Raises: ValueError: If a ``quantum_state`` with free parameters is provided. """ if ( isinstance( quantum_state, (QuantumCircuit, OperatorBase) ) # Statevector cannot be parametrized and len(quantum_state.parameters) > 0 ): raise ValueError( "A parametrized representation of a quantum_state was provided. It is not " "allowed - it cannot have free parameters." ) # Create new CircuitSampler to avoid breaking existing one's caches. sampler = CircuitSampler(quantum_instance) list_op = _prepare_list_op(quantum_state, observables) observables_expect = expectation.convert(list_op) observables_expect_sampled = sampler.convert(observables_expect) # compute means values = np.real(observables_expect_sampled.eval()) # compute standard deviations std_devs = _compute_std_devs( observables_expect_sampled, observables, expectation, quantum_instance ) # Discard values below threshold observables_means = values * (np.abs(values) > threshold) # zip means and standard deviations into tuples observables_results = list(zip(observables_means, std_devs)) # Return None eigenvalues for None operators if observables is a list. # None operators are already dropped in compute_minimum_eigenvalue if observables is a dict. return _prepare_result(observables_results, observables)