def test_list_op_eval_coeff_with_nonlinear_combofn(self): """Test evaluating a ListOp with non-linear combo function works with coefficients.""" state = One op = ListOp(5 * [I], coeff=2, combo_fn=numpy.prod) expr1 = ~StateFn(op) @ state expr2 = ListOp(5 * [~state @ I @ state], coeff=2, combo_fn=numpy.prod) self.assertEqual(expr1.eval(), 2) # if the coeff is propagated too far the result is 4 self.assertEqual(expr2.eval(), 2)
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