def convert( self, operator: OperatorBase, params: Optional[Dict[Union[ParameterExpression, ParameterVector], Union[float, List[float], List[List[float]]]]] = None ) -> OperatorBase: r""" Converts the Operator to one in which the CircuitStateFns are replaced by DictStateFns or VectorStateFns. Extracts the CircuitStateFns out of the Operator, caches them, calls ``sample_circuits`` below to get their converted replacements, and replaces the CircuitStateFns in operator with the replacement StateFns. Args: operator: The Operator to convert params: A dictionary mapping parameters to either single binding values or lists of binding values. The dictionary can also contain pairs of ParameterVectors with lists of parameters or lists of lists of parameters to bind to them. Returns: The converted Operator with CircuitStateFns replaced by DictStateFns or VectorStateFns. """ if self._last_op is None or id(operator) != id(self._last_op): # Clear caches self._last_op = operator self._reduced_op_cache = None self._circuit_ops_cache = None self._transpiled_circ_cache = None self._transpile_before_bind = True if not self._reduced_op_cache: operator_dicts_replaced = operator.to_circuit_op() self._reduced_op_cache = operator_dicts_replaced.reduce() if not self._circuit_ops_cache: self._circuit_ops_cache = {} self._extract_circuitstatefns(self._reduced_op_cache) if params: num_parameterizations = len(list(params.values())[0]) param_bindings = [{ param: value_list[i] for (param, value_list) in params.items() } for i in range(num_parameterizations)] else: param_bindings = None num_parameterizations = 1 # Don't pass circuits if we have in the cache, the sampling function knows to use the cache circs = list(self._circuit_ops_cache.values() ) if not self._transpiled_circ_cache else None sampled_statefn_dicts = self.sample_circuits( circuit_sfns=circs, param_bindings=param_bindings) def replace_circuits_with_dicts(operator, param_index=0): if isinstance(operator, CircuitStateFn): return sampled_statefn_dicts[id(operator)][param_index] elif isinstance(operator, ListOp): return operator.traverse( partial(replace_circuits_with_dicts, param_index=param_index)) else: return operator if params: return ListOp([ replace_circuits_with_dicts(self._reduced_op_cache, param_index=i) for i in range(num_parameterizations) ]) else: return replace_circuits_with_dicts(self._reduced_op_cache, param_index=0)
def convert( self, operator: OperatorBase, params: Optional[Dict[Parameter, Union[float, List[float], List[List[float]]]]] = None ) -> OperatorBase: r""" Converts the Operator to one in which the CircuitStateFns are replaced by DictStateFns or VectorStateFns. Extracts the CircuitStateFns out of the Operator, caches them, calls ``sample_circuits`` below to get their converted replacements, and replaces the CircuitStateFns in operator with the replacement StateFns. Args: operator: The Operator to convert params: A dictionary mapping parameters to either single binding values or lists of binding values. Returns: The converted Operator with CircuitStateFns replaced by DictStateFns or VectorStateFns. Raises: AquaError: if extracted circuits are empty. """ if self._last_op is None or id(operator) != id(self._last_op): # Clear caches self._last_op = operator self._reduced_op_cache = None self._circuit_ops_cache = None self._transpiled_circ_cache = None self._transpile_before_bind = True if not self._reduced_op_cache: operator_dicts_replaced = operator.to_circuit_op() self._reduced_op_cache = operator_dicts_replaced.reduce() if not self._circuit_ops_cache: self._circuit_ops_cache = {} self._extract_circuitstatefns(self._reduced_op_cache) if not self._circuit_ops_cache: raise AquaError( 'Circuits are empty. ' 'Check that the operator is an instance of CircuitStateFn or its ListOp.' ) if params is not None and len(params.keys()) > 0: p_0 = list(params.values())[0] # type: ignore if isinstance(p_0, (list, np.ndarray)): num_parameterizations = len(cast(List, p_0)) param_bindings = [ { param: value_list[i] # type: ignore for (param, value_list) in params.items() } for i in range(num_parameterizations) ] else: num_parameterizations = 1 param_bindings = [params] # type: ignore else: param_bindings = None num_parameterizations = 1 # Don't pass circuits if we have in the cache, the sampling function knows to use the cache circs = list(self._circuit_ops_cache.values() ) if not self._transpiled_circ_cache else None p_b = cast(List[Dict[Parameter, float]], param_bindings) sampled_statefn_dicts = self.sample_circuits(circuit_sfns=circs, param_bindings=p_b) def replace_circuits_with_dicts(operator, param_index=0): if isinstance(operator, CircuitStateFn): return sampled_statefn_dicts[id(operator)][param_index] elif isinstance(operator, ListOp): return operator.traverse( partial(replace_circuits_with_dicts, param_index=param_index)) else: return operator if params: return ListOp([ replace_circuits_with_dicts(self._reduced_op_cache, param_index=i) for i in range(num_parameterizations) ]) else: return replace_circuits_with_dicts(self._reduced_op_cache, param_index=0)