def _try_set_expectation_value_from_factory( self, operator: OperatorBase) -> None: if operator is not None and self.quantum_instance is not None: self._set_expectation( ExpectationFactory.build(operator=operator, backend=self.quantum_instance, include_custom=self._include_custom))
def test_aer_simulator_pauli_sum(self): """Test expectation selection with Aer's qasm_simulator.""" backend = Aer.get_backend("aer_simulator") op = 0.2 * (X ^ X) + 0.1 * (Z ^ I) with self.subTest("Defaults"): expectation = ExpectationFactory.build(op, backend, include_custom=False) self.assertIsInstance(expectation, PauliExpectation) with self.subTest("Include custom"): expectation = ExpectationFactory.build(op, backend, include_custom=True) self.assertIsInstance(expectation, AerPauliExpectation)
def construct_expectation( self, parameter: Union[List[float], List[Parameter], np.ndarray], operator: OperatorBase, return_expectation: bool = False, ) -> Union[OperatorBase, Tuple[OperatorBase, ExpectationBase]]: r""" Generate the ansatz circuit and expectation value measurement, and return their runnable composition. Args: parameter: Parameters for the ansatz circuit. operator: Qubit operator of the Observable return_expectation: If True, return the ``ExpectationBase`` expectation converter used in the construction of the expectation value. Useful e.g. to compute the standard deviation of the expectation value. Returns: The Operator equalling the measurement of the ansatz :class:`StateFn` by the Observable's expectation :class:`StateFn`, and, optionally, the expectation converter. Raises: AlgorithmError: If no operator has been provided. AlgorithmError: If no expectation is passed and None could be inferred via the ExpectationFactory. """ if operator is None: raise AlgorithmError("The operator was never provided.") self._check_operator_ansatz(operator) # if expectation was never created, try to create one if self.expectation is None: expectation = ExpectationFactory.build( operator=operator, backend=self.quantum_instance, include_custom=self._include_custom, ) else: expectation = self.expectation param_dict = dict(zip(self._ansatz_params, parameter)) # type: Dict wave_function = self.ansatz.assign_parameters(param_dict) observable_meas = expectation.convert( StateFn(operator, is_measurement=True)) ansatz_circuit_op = CircuitStateFn(wave_function) expect_op = observable_meas.compose(ansatz_circuit_op).reduce() if return_expectation: return expect_op, expectation return expect_op
def test_eval_observables(self, observables: ListOrDict[OperatorBase]): """Tests evaluator of auxiliary operators for algorithms.""" ansatz = EfficientSU2(2) parameters = np.array( [ 1.2, 4.2, 1.4, 2.0, 1.2, 4.2, 1.4, 2.0, 1.2, 4.2, 1.4, 2.0, 1.2, 4.2, 1.4, 2.0 ], dtype=float, ) bound_ansatz = ansatz.bind_parameters(parameters) expected_result = self.get_exact_expectation(bound_ansatz, observables) for backend_name in self.backend_names: shots = 4096 if backend_name == "qasm_simulator" else 1 decimal = (1 if backend_name == "qasm_simulator" else 6 ) # to accommodate for qasm being imperfect with self.subTest(msg=f"Test {backend_name} backend."): backend = BasicAer.get_backend(backend_name) quantum_instance = QuantumInstance( backend=backend, shots=shots, seed_simulator=self.seed, seed_transpiler=self.seed, ) expectation = ExpectationFactory.build( operator=self.h2_op, backend=quantum_instance, ) with self.subTest(msg="Test QuantumCircuit."): self._run_test( expected_result, bound_ansatz, decimal, expectation, observables, quantum_instance, ) with self.subTest(msg="Test Statevector."): statevector = Statevector(bound_ansatz) self._run_test( expected_result, statevector, decimal, expectation, observables, quantum_instance, )
def test_trotter_qrte_trotter_single_qubit_aux_ops(self): """Test for default TrotterQRTE on a single qubit with auxiliary operators.""" operator = SummedOp([X, Z]) # LieTrotter with 1 rep aux_ops = [X, Y] initial_state = Zero time = 3 evolution_problem = EvolutionProblem(operator, time, initial_state, aux_ops) expected_evolved_state = VectorStateFn( Statevector([0.98008514 + 0.13970775j, 0.01991486 + 0.13970775j], dims=(2,)) ) expected_aux_ops_evaluated = [(0.078073, 0.0), (0.268286, 0.0)] expected_aux_ops_evaluated_qasm = [ (0.05799999999999995, 0.011161518713866855), (0.2495, 0.010826759383582883), ] for backend_name in self.backends_names_not_none: with self.subTest(msg=f"Test {backend_name} backend."): algorithm_globals.random_seed = 0 backend = self.backends_dict[backend_name] expectation = ExpectationFactory.build( operator=operator, backend=backend, ) trotter_qrte = TrotterQRTE(quantum_instance=backend, expectation=expectation) evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal( evolution_result.evolved_state.eval(), expected_evolved_state ) if backend_name == "qi_qasm": expected_aux_ops_evaluated = expected_aux_ops_evaluated_qasm np.testing.assert_array_almost_equal( evolution_result.aux_ops_evaluated, expected_aux_ops_evaluated )
def _calculate_observable( self, solution: QuantumCircuit, observable: Optional[Union[LinearSystemObservable, BaseOperator]] = None, observable_circuit: Optional[QuantumCircuit] = None, post_processing: Optional[Callable[[Union[float, List[float]]], Union[float, List[float]]]] = None ) -> Tuple[Union[float, List[float]], Union[float, List[float]]]: """Calculates the value of the observable(s) given. Args: solution: The quantum circuit preparing the solution x to the system. observable: Information to be extracted from the solution. observable_circuit: Circuit to be applied to the solution to extract information. post_processing: Function to compute the value of the observable. Returns: The value of the observable(s) and the circuit results before post-processing as a tuple. """ # Get the number of qubits nb = solution.qregs[0].size nl = solution.qregs[1].size na = solution.num_ancillas # if the observable is given construct post_processing and observable_circuit if observable is not None: observable_circuit = observable.observable_circuit(nb) post_processing = observable.post_processing if isinstance(observable, LinearSystemObservable): observable = observable.observable(nb) # in the other case use the identity as observable else: observable = I ^ nb # Create the Operators Zero and One zero_op = (I + Z) / 2 one_op = (I - Z) / 2 is_list = True if not isinstance(observable_circuit, list): is_list = False observable_circuit = [observable_circuit] observable = [observable] expectations = [] for circ, obs in zip(observable_circuit, observable): circuit = QuantumCircuit(solution.num_qubits) circuit.append(solution, circuit.qubits) circuit.append(circ, range(nb)) ob = one_op ^ TensoredOp((nl + na) * [zero_op]) ^ obs expectations.append(~StateFn(ob) @ StateFn(circuit)) if is_list: # execute all in a list op to send circuits in batches expectations = ListOp(expectations) else: expectations = expectations[0] # check if an expectation converter is given if self._expectation is not None: expectations = self._expectation.convert(expectations) # if otherwise a backend was specified, try to set the best expectation value elif self._sampler is not None: if is_list: op = expectations.oplist[0] else: op = expectations self._expectation = ExpectationFactory.build( op, self._sampler.quantum_instance) if self._sampler is not None: expectations = self._sampler.convert(expectations) # evaluate expectation_results = expectations.eval() # apply post_processing result = post_processing(expectation_results, nb, self.scaling) return result, expectation_results