We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
num_qubits() for DictStateFn is inefficient
To get the number of qubits, a list of all keys in the dictionary is constructed. But, only the length of the first key is used. Constructing the entire list is wasteful.

https://github.com/Qiskit/qiskit-terra/blob/c3b2d7acb80fa89043e6f38efb501275ec296616/qiskit/opflow/state_fns/dict_state_fn.py#L82

This code should work:
```python
len(next(iter(self.primitive)))
```

`%timeit` shows that the latter is faster even when the dict contains only two keys.

- **Qiskit Terra version**:  123d829ac, Feb 3 master






--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `qiskit/opflow/state_fns/dict_state_fn.py`
Content:
```
1 # This code is part of Qiskit.
2 #
3 # (C) Copyright IBM 2020, 2021.
4 #
5 # This code is licensed under the Apache License, Version 2.0. You may
6 # obtain a copy of this license in the LICENSE.txt file in the root directory
7 # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8 #
9 # Any modifications or derivative works of this code must retain this
10 # copyright notice, and modified files need to carry a notice indicating
11 # that they have been altered from the originals.
12 
13 """ DictStateFn Class """
14 
15 import itertools
16 from typing import Dict, List, Optional, Set, Union, cast
17 
18 import numpy as np
19 from scipy import sparse
20 
21 from qiskit.circuit import ParameterExpression
22 from qiskit.opflow.exceptions import OpflowError
23 from qiskit.opflow.list_ops.list_op import ListOp
24 from qiskit.opflow.operator_base import OperatorBase
25 from qiskit.opflow.state_fns.state_fn import StateFn
26 from qiskit.opflow.state_fns.vector_state_fn import VectorStateFn
27 from qiskit.quantum_info import Statevector
28 from qiskit.result import Result
29 from qiskit.utils import algorithm_globals
30 
31 
32 class DictStateFn(StateFn):
33     """ A class for state functions and measurements which are defined by a lookup table,
34     stored in a dict.
35     """
36     primitive: Dict[str, complex]
37 
38     # TODO allow normalization somehow?
39     def __init__(self,
40                  primitive: Union[str, dict, Result] = None,
41                  coeff: Union[complex, ParameterExpression] = 1.0,
42                  is_measurement: bool = False) -> None:
43         """
44             Args:
45                 primitive: The dict, single bitstring (if defining a basis sate), or Qiskit
46                     Result, which defines the behavior of the underlying function.
47                 coeff: A coefficient by which to multiply the state function.
48                 is_measurement: Whether the StateFn is a measurement operator.
49 
50             Raises:
51                 TypeError: invalid parameters.
52         """
53         # If the initial density is a string, treat this as a density dict
54         # with only a single basis state.
55         if isinstance(primitive, str):
56             primitive = {primitive: 1}
57 
58         # NOTE:
59         # 1) This is not the same as passing in the counts dict directly, as this will
60         # convert the shot numbers to
61         # probabilities, whereas passing in the counts dict will not.
62         # 2) This will extract counts for both shot and statevector simulations.
63         # To use the statevector,
64         # simply pass in the statevector.
65         # 3) This will only extract the first result.
66         if isinstance(primitive, Result):
67             counts = primitive.get_counts()
68             # NOTE: Need to square root to take correct Pauli measurements!
69             primitive = {bstr: (shots / sum(counts.values()))**.5 for
70                          (bstr, shots) in counts.items()}
71 
72         if not isinstance(primitive, dict):
73             raise TypeError(
74                 'DictStateFn can only be instantiated with dict, '
75                 'string, or Qiskit Result, not {}'.format(type(primitive)))
76 
77         super().__init__(primitive, coeff=coeff, is_measurement=is_measurement)
78 
79     def primitive_strings(self) -> Set[str]:
80         return {'Dict'}
81 
82     @property
83     def num_qubits(self) -> int:
84         return len(list(self.primitive.keys())[0])
85 
86     def add(self, other: OperatorBase) -> OperatorBase:
87         if not self.num_qubits == other.num_qubits:
88             raise ValueError(
89                 'Sum over statefns with different numbers of qubits, {} and {}, is not well '
90                 'defined'.format(self.num_qubits, other.num_qubits))
91 
92         # Right now doesn't make sense to add a StateFn to a Measurement
93         if isinstance(other, DictStateFn) and self.is_measurement == other.is_measurement:
94             # TODO add compatibility with vector and Operator?
95             if self.primitive == other.primitive:
96                 return DictStateFn(self.primitive,
97                                    coeff=self.coeff + other.coeff,
98                                    is_measurement=self.is_measurement)
99             else:
100                 new_dict = {b: (v * self.coeff) + (other.primitive.get(b, 0) * other.coeff)
101                             for (b, v) in self.primitive.items()}
102                 new_dict.update({b: v * other.coeff for (b, v) in other.primitive.items()
103                                  if b not in self.primitive})
104                 return DictStateFn(new_dict, is_measurement=self._is_measurement)
105         # pylint: disable=cyclic-import
106         from ..list_ops.summed_op import SummedOp
107         return SummedOp([self, other])
108 
109     def adjoint(self) -> "DictStateFn":
110         return DictStateFn({b: np.conj(v) for (b, v) in self.primitive.items()},
111                            coeff=self.coeff.conjugate(),
112                            is_measurement=(not self.is_measurement))
113 
114     def permute(self, permutation: List[int]) -> 'DictStateFn':
115         new_num_qubits = max(permutation) + 1
116         if self.num_qubits != len(permutation):
117             raise OpflowError("New index must be defined for each qubit of the operator.")
118 
119         # helper function to permute the key
120         def perm(key):
121             list_key = ['0'] * new_num_qubits
122             for i, k in enumerate(permutation):
123                 list_key[k] = key[i]
124             return ''.join(list_key)
125 
126         new_dict = {perm(key): value for key, value in self.primitive.items()}
127         return DictStateFn(new_dict, coeff=self.coeff, is_measurement=self.is_measurement)
128 
129     def _expand_dim(self, num_qubits: int) -> 'DictStateFn':
130         pad = '0'*num_qubits
131         new_dict = {key + pad: value for key, value in self.primitive.items()}
132         return DictStateFn(new_dict, coeff=self.coeff, is_measurement=self.is_measurement)
133 
134     def tensor(self, other: OperatorBase) -> OperatorBase:
135         # Both dicts
136         if isinstance(other, DictStateFn):
137             new_dict = {k1 + k2: v1 * v2 for ((k1, v1,), (k2, v2)) in
138                         itertools.product(self.primitive.items(), other.primitive.items())}
139             return StateFn(new_dict,
140                            coeff=self.coeff * other.coeff,
141                            is_measurement=self.is_measurement)
142         # pylint: disable=cyclic-import
143         from ..list_ops.tensored_op import TensoredOp
144         return TensoredOp([self, other])
145 
146     def to_density_matrix(self, massive: bool = False) -> np.ndarray:
147         OperatorBase._check_massive('to_density_matrix', True, self.num_qubits, massive)
148         states = int(2 ** self.num_qubits)
149         return self.to_matrix(massive=massive) * np.eye(states) * self.coeff
150 
151     def to_matrix(self, massive: bool = False) -> np.ndarray:
152         OperatorBase._check_massive('to_matrix', False, self.num_qubits, massive)
153         states = int(2 ** self.num_qubits)
154         probs = np.zeros(states) + 0.j
155         for k, v in self.primitive.items():
156             probs[int(k, 2)] = v
157         vec = probs * self.coeff
158 
159         # Reshape for measurements so np.dot still works for composition.
160         return vec if not self.is_measurement else vec.reshape(1, -1)
161 
162     def to_spmatrix(self) -> sparse.spmatrix:
163         """Same as to_matrix, but returns csr sparse matrix.
164 
165         Returns:
166             CSR sparse matrix representation of the State function.
167 
168         Raises:
169             ValueError: invalid parameters.
170         """
171 
172         indices = [int(v, 2) for v in self.primitive.keys()]
173         vals = np.array(list(self.primitive.values())) * self.coeff
174         spvec = sparse.csr_matrix((vals, (np.zeros(len(indices), dtype=int), indices)),
175                                   shape=(1, 2**self.num_qubits))
176         return spvec if not self.is_measurement else spvec.transpose()
177 
178     def to_spmatrix_op(self) -> OperatorBase:
179         """Convert this state function to a ``SparseVectorStateFn``."""
180         from .sparse_vector_state_fn import SparseVectorStateFn
181         return SparseVectorStateFn(self.to_spmatrix(), self.coeff, self.is_measurement)
182 
183     def to_circuit_op(self) -> OperatorBase:
184         """Convert this state function to a ``CircuitStateFn``."""
185         from .circuit_state_fn import CircuitStateFn
186         csfn = CircuitStateFn.from_dict(self.primitive) * self.coeff
187         return csfn.adjoint() if self.is_measurement else csfn
188 
189     def __str__(self) -> str:
190         prim_str = str(self.primitive)
191         if self.coeff == 1.0:
192             return "{}({})".format('DictStateFn' if not self.is_measurement
193                                    else 'DictMeasurement', prim_str)
194         else:
195             return "{}({}) * {}".format('DictStateFn' if not self.is_measurement
196                                         else 'DictMeasurement',
197                                         prim_str,
198                                         self.coeff)
199 
200     # pylint: disable=too-many-return-statements
201     def eval(
202         self,
203         front: Optional[
204             Union[str, Dict[str, complex], np.ndarray, OperatorBase, Statevector]
205         ] = None,
206     ) -> Union[OperatorBase, complex]:
207         if front is None:
208             sparse_vector_state_fn = self.to_spmatrix_op().eval()
209             return sparse_vector_state_fn
210 
211         if not self.is_measurement and isinstance(front, OperatorBase):
212             raise ValueError(
213                 'Cannot compute overlap with StateFn or Operator if not Measurement. Try taking '
214                 'sf.adjoint() first to convert to measurement.')
215 
216         if isinstance(front, ListOp) and front.distributive:
217             return front.combo_fn([self.eval(front.coeff * front_elem)
218                                    for front_elem in front.oplist])
219 
220         # For now, always do this. If it's not performant, we can be more granular.
221         if not isinstance(front, OperatorBase):
222             front = StateFn(front)
223 
224         # pylint: disable=cyclic-import
225         from ..operator_globals import EVAL_SIG_DIGITS
226 
227         # If the primitive is a lookup of bitstrings,
228         # we define all missing strings to have a function value of
229         # zero.
230         if isinstance(front, DictStateFn):
231             return np.round(
232                 cast(float, sum([v * front.primitive.get(b, 0) for (b, v) in
233                                  self.primitive.items()]) * self.coeff * front.coeff),
234                 decimals=EVAL_SIG_DIGITS)
235 
236         # All remaining possibilities only apply when self.is_measurement is True
237 
238         if isinstance(front, VectorStateFn):
239             # TODO does it need to be this way for measurement?
240             # return sum([v * front.primitive.data[int(b, 2)] *
241             # np.conj(front.primitive.data[int(b, 2)])
242             return np.round(
243                 cast(float, sum([v * front.primitive.data[int(b, 2)] for (b, v) in
244                                  self.primitive.items()]) * self.coeff),
245                 decimals=EVAL_SIG_DIGITS)
246 
247         from .circuit_state_fn import CircuitStateFn
248         if isinstance(front, CircuitStateFn):
249             # Don't reimplement logic from CircuitStateFn
250             self_adjoint = cast(DictStateFn, self.adjoint())
251             return np.conj(front.adjoint().eval(self_adjoint.primitive)) * self.coeff
252 
253         from .operator_state_fn import OperatorStateFn
254         if isinstance(front, OperatorStateFn):
255             return cast(Union[OperatorBase, float, complex], front.adjoint().eval(self.adjoint()))
256 
257         # All other OperatorBases go here
258         self_adjoint = cast(DictStateFn, self.adjoint())
259         adjointed_eval = cast(OperatorBase, front.adjoint().eval(self_adjoint.primitive))
260         return adjointed_eval.adjoint() * self.coeff
261 
262     def sample(self,
263                shots: int = 1024,
264                massive: bool = False,
265                reverse_endianness: bool = False) -> Dict[str, float]:
266         probs = np.square(np.abs(np.array(list(self.primitive.values()))))
267         unique, counts = np.unique(algorithm_globals.random.choice(list(self.primitive.keys()),
268                                                                    size=shots,
269                                                                    p=(probs / sum(probs))),
270                                    return_counts=True)
271         counts = dict(zip(unique, counts))
272         if reverse_endianness:
273             scaled_dict = {bstr[::-1]: (prob / shots) for (bstr, prob) in counts.items()}
274         else:
275             scaled_dict = {bstr: (prob / shots) for (bstr, prob) in counts.items()}
276         return dict(sorted(scaled_dict.items(), key=lambda x: x[1], reverse=True))
277
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/qiskit/opflow/state_fns/dict_state_fn.py b/qiskit/opflow/state_fns/dict_state_fn.py
--- a/qiskit/opflow/state_fns/dict_state_fn.py
+++ b/qiskit/opflow/state_fns/dict_state_fn.py
@@ -81,7 +81,7 @@
 
     @property
     def num_qubits(self) -> int:
-        return len(list(self.primitive.keys())[0])
+        return len(next(iter(self.primitive)))
 
     def add(self, other: OperatorBase) -> OperatorBase:
         if not self.num_qubits == other.num_qubits:

{"golden_diff": "diff --git a/qiskit/opflow/state_fns/dict_state_fn.py b/qiskit/opflow/state_fns/dict_state_fn.py\n--- a/qiskit/opflow/state_fns/dict_state_fn.py\n+++ b/qiskit/opflow/state_fns/dict_state_fn.py\n@@ -81,7 +81,7 @@\n \n     @property\n     def num_qubits(self) -> int:\n-        return len(list(self.primitive.keys())[0])\n+        return len(next(iter(self.primitive)))\n \n     def add(self, other: OperatorBase) -> OperatorBase:\n         if not self.num_qubits == other.num_qubits:\n", "issue": "num_qubits() for DictStateFn is inefficient\nTo get the number of qubits, a list of all keys in the dictionary is constructed. But, only the length of the first key is used. Constructing the entire list is wasteful.\r\n\r\nhttps://github.com/Qiskit/qiskit-terra/blob/c3b2d7acb80fa89043e6f38efb501275ec296616/qiskit/opflow/state_fns/dict_state_fn.py#L82\r\n\r\nThis code should work:\r\n```python\r\nlen(next(iter(self.primitive)))\r\n```\r\n\r\n`%timeit` shows that the latter is faster even when the dict contains only two keys.\r\n\r\n- **Qiskit Terra version**:  123d829ac, Feb 3 master\r\n\r\n\r\n\r\n\r\n\n", "before_files": [{"content": "# This code is part of Qiskit.\n#\n# (C) Copyright IBM 2020, 2021.\n#\n# This code is licensed under the Apache License, Version 2.0. You may\n# obtain a copy of this license in the LICENSE.txt file in the root directory\n# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.\n#\n# Any modifications or derivative works of this code must retain this\n# copyright notice, and modified files need to carry a notice indicating\n# that they have been altered from the originals.\n\n\"\"\" DictStateFn Class \"\"\"\n\nimport itertools\nfrom typing import Dict, List, Optional, Set, Union, cast\n\nimport numpy as np\nfrom scipy import sparse\n\nfrom qiskit.circuit import ParameterExpression\nfrom qiskit.opflow.exceptions import OpflowError\nfrom qiskit.opflow.list_ops.list_op import ListOp\nfrom qiskit.opflow.operator_base import OperatorBase\nfrom qiskit.opflow.state_fns.state_fn import StateFn\nfrom qiskit.opflow.state_fns.vector_state_fn import VectorStateFn\nfrom qiskit.quantum_info import Statevector\nfrom qiskit.result import Result\nfrom qiskit.utils import algorithm_globals\n\n\nclass DictStateFn(StateFn):\n    \"\"\" A class for state functions and measurements which are defined by a lookup table,\n    stored in a dict.\n    \"\"\"\n    primitive: Dict[str, complex]\n\n    # TODO allow normalization somehow?\n    def __init__(self,\n                 primitive: Union[str, dict, Result] = None,\n                 coeff: Union[complex, ParameterExpression] = 1.0,\n                 is_measurement: bool = False) -> None:\n        \"\"\"\n            Args:\n                primitive: The dict, single bitstring (if defining a basis sate), or Qiskit\n                    Result, which defines the behavior of the underlying function.\n                coeff: A coefficient by which to multiply the state function.\n                is_measurement: Whether the StateFn is a measurement operator.\n\n            Raises:\n                TypeError: invalid parameters.\n        \"\"\"\n        # If the initial density is a string, treat this as a density dict\n        # with only a single basis state.\n        if isinstance(primitive, str):\n            primitive = {primitive: 1}\n\n        # NOTE:\n        # 1) This is not the same as passing in the counts dict directly, as this will\n        # convert the shot numbers to\n        # probabilities, whereas passing in the counts dict will not.\n        # 2) This will extract counts for both shot and statevector simulations.\n        # To use the statevector,\n        # simply pass in the statevector.\n        # 3) This will only extract the first result.\n        if isinstance(primitive, Result):\n            counts = primitive.get_counts()\n            # NOTE: Need to square root to take correct Pauli measurements!\n            primitive = {bstr: (shots / sum(counts.values()))**.5 for\n                         (bstr, shots) in counts.items()}\n\n        if not isinstance(primitive, dict):\n            raise TypeError(\n                'DictStateFn can only be instantiated with dict, '\n                'string, or Qiskit Result, not {}'.format(type(primitive)))\n\n        super().__init__(primitive, coeff=coeff, is_measurement=is_measurement)\n\n    def primitive_strings(self) -> Set[str]:\n        return {'Dict'}\n\n    @property\n    def num_qubits(self) -> int:\n        return len(list(self.primitive.keys())[0])\n\n    def add(self, other: OperatorBase) -> OperatorBase:\n        if not self.num_qubits == other.num_qubits:\n            raise ValueError(\n                'Sum over statefns with different numbers of qubits, {} and {}, is not well '\n                'defined'.format(self.num_qubits, other.num_qubits))\n\n        # Right now doesn't make sense to add a StateFn to a Measurement\n        if isinstance(other, DictStateFn) and self.is_measurement == other.is_measurement:\n            # TODO add compatibility with vector and Operator?\n            if self.primitive == other.primitive:\n                return DictStateFn(self.primitive,\n                                   coeff=self.coeff + other.coeff,\n                                   is_measurement=self.is_measurement)\n            else:\n                new_dict = {b: (v * self.coeff) + (other.primitive.get(b, 0) * other.coeff)\n                            for (b, v) in self.primitive.items()}\n                new_dict.update({b: v * other.coeff for (b, v) in other.primitive.items()\n                                 if b not in self.primitive})\n                return DictStateFn(new_dict, is_measurement=self._is_measurement)\n        # pylint: disable=cyclic-import\n        from ..list_ops.summed_op import SummedOp\n        return SummedOp([self, other])\n\n    def adjoint(self) -> \"DictStateFn\":\n        return DictStateFn({b: np.conj(v) for (b, v) in self.primitive.items()},\n                           coeff=self.coeff.conjugate(),\n                           is_measurement=(not self.is_measurement))\n\n    def permute(self, permutation: List[int]) -> 'DictStateFn':\n        new_num_qubits = max(permutation) + 1\n        if self.num_qubits != len(permutation):\n            raise OpflowError(\"New index must be defined for each qubit of the operator.\")\n\n        # helper function to permute the key\n        def perm(key):\n            list_key = ['0'] * new_num_qubits\n            for i, k in enumerate(permutation):\n                list_key[k] = key[i]\n            return ''.join(list_key)\n\n        new_dict = {perm(key): value for key, value in self.primitive.items()}\n        return DictStateFn(new_dict, coeff=self.coeff, is_measurement=self.is_measurement)\n\n    def _expand_dim(self, num_qubits: int) -> 'DictStateFn':\n        pad = '0'*num_qubits\n        new_dict = {key + pad: value for key, value in self.primitive.items()}\n        return DictStateFn(new_dict, coeff=self.coeff, is_measurement=self.is_measurement)\n\n    def tensor(self, other: OperatorBase) -> OperatorBase:\n        # Both dicts\n        if isinstance(other, DictStateFn):\n            new_dict = {k1 + k2: v1 * v2 for ((k1, v1,), (k2, v2)) in\n                        itertools.product(self.primitive.items(), other.primitive.items())}\n            return StateFn(new_dict,\n                           coeff=self.coeff * other.coeff,\n                           is_measurement=self.is_measurement)\n        # pylint: disable=cyclic-import\n        from ..list_ops.tensored_op import TensoredOp\n        return TensoredOp([self, other])\n\n    def to_density_matrix(self, massive: bool = False) -> np.ndarray:\n        OperatorBase._check_massive('to_density_matrix', True, self.num_qubits, massive)\n        states = int(2 ** self.num_qubits)\n        return self.to_matrix(massive=massive) * np.eye(states) * self.coeff\n\n    def to_matrix(self, massive: bool = False) -> np.ndarray:\n        OperatorBase._check_massive('to_matrix', False, self.num_qubits, massive)\n        states = int(2 ** self.num_qubits)\n        probs = np.zeros(states) + 0.j\n        for k, v in self.primitive.items():\n            probs[int(k, 2)] = v\n        vec = probs * self.coeff\n\n        # Reshape for measurements so np.dot still works for composition.\n        return vec if not self.is_measurement else vec.reshape(1, -1)\n\n    def to_spmatrix(self) -> sparse.spmatrix:\n        \"\"\"Same as to_matrix, but returns csr sparse matrix.\n\n        Returns:\n            CSR sparse matrix representation of the State function.\n\n        Raises:\n            ValueError: invalid parameters.\n        \"\"\"\n\n        indices = [int(v, 2) for v in self.primitive.keys()]\n        vals = np.array(list(self.primitive.values())) * self.coeff\n        spvec = sparse.csr_matrix((vals, (np.zeros(len(indices), dtype=int), indices)),\n                                  shape=(1, 2**self.num_qubits))\n        return spvec if not self.is_measurement else spvec.transpose()\n\n    def to_spmatrix_op(self) -> OperatorBase:\n        \"\"\"Convert this state function to a ``SparseVectorStateFn``.\"\"\"\n        from .sparse_vector_state_fn import SparseVectorStateFn\n        return SparseVectorStateFn(self.to_spmatrix(), self.coeff, self.is_measurement)\n\n    def to_circuit_op(self) -> OperatorBase:\n        \"\"\"Convert this state function to a ``CircuitStateFn``.\"\"\"\n        from .circuit_state_fn import CircuitStateFn\n        csfn = CircuitStateFn.from_dict(self.primitive) * self.coeff\n        return csfn.adjoint() if self.is_measurement else csfn\n\n    def __str__(self) -> str:\n        prim_str = str(self.primitive)\n        if self.coeff == 1.0:\n            return \"{}({})\".format('DictStateFn' if not self.is_measurement\n                                   else 'DictMeasurement', prim_str)\n        else:\n            return \"{}({}) * {}\".format('DictStateFn' if not self.is_measurement\n                                        else 'DictMeasurement',\n                                        prim_str,\n                                        self.coeff)\n\n    # pylint: disable=too-many-return-statements\n    def eval(\n        self,\n        front: Optional[\n            Union[str, Dict[str, complex], np.ndarray, OperatorBase, Statevector]\n        ] = None,\n    ) -> Union[OperatorBase, complex]:\n        if front is None:\n            sparse_vector_state_fn = self.to_spmatrix_op().eval()\n            return sparse_vector_state_fn\n\n        if not self.is_measurement and isinstance(front, OperatorBase):\n            raise ValueError(\n                'Cannot compute overlap with StateFn or Operator if not Measurement. Try taking '\n                'sf.adjoint() first to convert to measurement.')\n\n        if isinstance(front, ListOp) and front.distributive:\n            return front.combo_fn([self.eval(front.coeff * front_elem)\n                                   for front_elem in front.oplist])\n\n        # For now, always do this. If it's not performant, we can be more granular.\n        if not isinstance(front, OperatorBase):\n            front = StateFn(front)\n\n        # pylint: disable=cyclic-import\n        from ..operator_globals import EVAL_SIG_DIGITS\n\n        # If the primitive is a lookup of bitstrings,\n        # we define all missing strings to have a function value of\n        # zero.\n        if isinstance(front, DictStateFn):\n            return np.round(\n                cast(float, sum([v * front.primitive.get(b, 0) for (b, v) in\n                                 self.primitive.items()]) * self.coeff * front.coeff),\n                decimals=EVAL_SIG_DIGITS)\n\n        # All remaining possibilities only apply when self.is_measurement is True\n\n        if isinstance(front, VectorStateFn):\n            # TODO does it need to be this way for measurement?\n            # return sum([v * front.primitive.data[int(b, 2)] *\n            # np.conj(front.primitive.data[int(b, 2)])\n            return np.round(\n                cast(float, sum([v * front.primitive.data[int(b, 2)] for (b, v) in\n                                 self.primitive.items()]) * self.coeff),\n                decimals=EVAL_SIG_DIGITS)\n\n        from .circuit_state_fn import CircuitStateFn\n        if isinstance(front, CircuitStateFn):\n            # Don't reimplement logic from CircuitStateFn\n            self_adjoint = cast(DictStateFn, self.adjoint())\n            return np.conj(front.adjoint().eval(self_adjoint.primitive)) * self.coeff\n\n        from .operator_state_fn import OperatorStateFn\n        if isinstance(front, OperatorStateFn):\n            return cast(Union[OperatorBase, float, complex], front.adjoint().eval(self.adjoint()))\n\n        # All other OperatorBases go here\n        self_adjoint = cast(DictStateFn, self.adjoint())\n        adjointed_eval = cast(OperatorBase, front.adjoint().eval(self_adjoint.primitive))\n        return adjointed_eval.adjoint() * self.coeff\n\n    def sample(self,\n               shots: int = 1024,\n               massive: bool = False,\n               reverse_endianness: bool = False) -> Dict[str, float]:\n        probs = np.square(np.abs(np.array(list(self.primitive.values()))))\n        unique, counts = np.unique(algorithm_globals.random.choice(list(self.primitive.keys()),\n                                                                   size=shots,\n                                                                   p=(probs / sum(probs))),\n                                   return_counts=True)\n        counts = dict(zip(unique, counts))\n        if reverse_endianness:\n            scaled_dict = {bstr[::-1]: (prob / shots) for (bstr, prob) in counts.items()}\n        else:\n            scaled_dict = {bstr: (prob / shots) for (bstr, prob) in counts.items()}\n        return dict(sorted(scaled_dict.items(), key=lambda x: x[1], reverse=True))\n", "path": "qiskit/opflow/state_fns/dict_state_fn.py"}], "after_files": [{"content": "# This code is part of Qiskit.\n#\n# (C) Copyright IBM 2020, 2021.\n#\n# This code is licensed under the Apache License, Version 2.0. You may\n# obtain a copy of this license in the LICENSE.txt file in the root directory\n# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.\n#\n# Any modifications or derivative works of this code must retain this\n# copyright notice, and modified files need to carry a notice indicating\n# that they have been altered from the originals.\n\n\"\"\" DictStateFn Class \"\"\"\n\nimport itertools\nfrom typing import Dict, List, Optional, Set, Union, cast\n\nimport numpy as np\nfrom scipy import sparse\n\nfrom qiskit.circuit import ParameterExpression\nfrom qiskit.opflow.exceptions import OpflowError\nfrom qiskit.opflow.list_ops.list_op import ListOp\nfrom qiskit.opflow.operator_base import OperatorBase\nfrom qiskit.opflow.state_fns.state_fn import StateFn\nfrom qiskit.opflow.state_fns.vector_state_fn import VectorStateFn\nfrom qiskit.quantum_info import Statevector\nfrom qiskit.result import Result\nfrom qiskit.utils import algorithm_globals\n\n\nclass DictStateFn(StateFn):\n    \"\"\" A class for state functions and measurements which are defined by a lookup table,\n    stored in a dict.\n    \"\"\"\n    primitive: Dict[str, complex]\n\n    # TODO allow normalization somehow?\n    def __init__(self,\n                 primitive: Union[str, dict, Result] = None,\n                 coeff: Union[complex, ParameterExpression] = 1.0,\n                 is_measurement: bool = False) -> None:\n        \"\"\"\n            Args:\n                primitive: The dict, single bitstring (if defining a basis sate), or Qiskit\n                    Result, which defines the behavior of the underlying function.\n                coeff: A coefficient by which to multiply the state function.\n                is_measurement: Whether the StateFn is a measurement operator.\n\n            Raises:\n                TypeError: invalid parameters.\n        \"\"\"\n        # If the initial density is a string, treat this as a density dict\n        # with only a single basis state.\n        if isinstance(primitive, str):\n            primitive = {primitive: 1}\n\n        # NOTE:\n        # 1) This is not the same as passing in the counts dict directly, as this will\n        # convert the shot numbers to\n        # probabilities, whereas passing in the counts dict will not.\n        # 2) This will extract counts for both shot and statevector simulations.\n        # To use the statevector,\n        # simply pass in the statevector.\n        # 3) This will only extract the first result.\n        if isinstance(primitive, Result):\n            counts = primitive.get_counts()\n            # NOTE: Need to square root to take correct Pauli measurements!\n            primitive = {bstr: (shots / sum(counts.values()))**.5 for\n                         (bstr, shots) in counts.items()}\n\n        if not isinstance(primitive, dict):\n            raise TypeError(\n                'DictStateFn can only be instantiated with dict, '\n                'string, or Qiskit Result, not {}'.format(type(primitive)))\n\n        super().__init__(primitive, coeff=coeff, is_measurement=is_measurement)\n\n    def primitive_strings(self) -> Set[str]:\n        return {'Dict'}\n\n    @property\n    def num_qubits(self) -> int:\n        return len(next(iter(self.primitive)))\n\n    def add(self, other: OperatorBase) -> OperatorBase:\n        if not self.num_qubits == other.num_qubits:\n            raise ValueError(\n                'Sum over statefns with different numbers of qubits, {} and {}, is not well '\n                'defined'.format(self.num_qubits, other.num_qubits))\n\n        # Right now doesn't make sense to add a StateFn to a Measurement\n        if isinstance(other, DictStateFn) and self.is_measurement == other.is_measurement:\n            # TODO add compatibility with vector and Operator?\n            if self.primitive == other.primitive:\n                return DictStateFn(self.primitive,\n                                   coeff=self.coeff + other.coeff,\n                                   is_measurement=self.is_measurement)\n            else:\n                new_dict = {b: (v * self.coeff) + (other.primitive.get(b, 0) * other.coeff)\n                            for (b, v) in self.primitive.items()}\n                new_dict.update({b: v * other.coeff for (b, v) in other.primitive.items()\n                                 if b not in self.primitive})\n                return DictStateFn(new_dict, is_measurement=self._is_measurement)\n        # pylint: disable=cyclic-import\n        from ..list_ops.summed_op import SummedOp\n        return SummedOp([self, other])\n\n    def adjoint(self) -> \"DictStateFn\":\n        return DictStateFn({b: np.conj(v) for (b, v) in self.primitive.items()},\n                           coeff=self.coeff.conjugate(),\n                           is_measurement=(not self.is_measurement))\n\n    def permute(self, permutation: List[int]) -> 'DictStateFn':\n        new_num_qubits = max(permutation) + 1\n        if self.num_qubits != len(permutation):\n            raise OpflowError(\"New index must be defined for each qubit of the operator.\")\n\n        # helper function to permute the key\n        def perm(key):\n            list_key = ['0'] * new_num_qubits\n            for i, k in enumerate(permutation):\n                list_key[k] = key[i]\n            return ''.join(list_key)\n\n        new_dict = {perm(key): value for key, value in self.primitive.items()}\n        return DictStateFn(new_dict, coeff=self.coeff, is_measurement=self.is_measurement)\n\n    def _expand_dim(self, num_qubits: int) -> 'DictStateFn':\n        pad = '0'*num_qubits\n        new_dict = {key + pad: value for key, value in self.primitive.items()}\n        return DictStateFn(new_dict, coeff=self.coeff, is_measurement=self.is_measurement)\n\n    def tensor(self, other: OperatorBase) -> OperatorBase:\n        # Both dicts\n        if isinstance(other, DictStateFn):\n            new_dict = {k1 + k2: v1 * v2 for ((k1, v1,), (k2, v2)) in\n                        itertools.product(self.primitive.items(), other.primitive.items())}\n            return StateFn(new_dict,\n                           coeff=self.coeff * other.coeff,\n                           is_measurement=self.is_measurement)\n        # pylint: disable=cyclic-import\n        from ..list_ops.tensored_op import TensoredOp\n        return TensoredOp([self, other])\n\n    def to_density_matrix(self, massive: bool = False) -> np.ndarray:\n        OperatorBase._check_massive('to_density_matrix', True, self.num_qubits, massive)\n        states = int(2 ** self.num_qubits)\n        return self.to_matrix(massive=massive) * np.eye(states) * self.coeff\n\n    def to_matrix(self, massive: bool = False) -> np.ndarray:\n        OperatorBase._check_massive('to_matrix', False, self.num_qubits, massive)\n        states = int(2 ** self.num_qubits)\n        probs = np.zeros(states) + 0.j\n        for k, v in self.primitive.items():\n            probs[int(k, 2)] = v\n        vec = probs * self.coeff\n\n        # Reshape for measurements so np.dot still works for composition.\n        return vec if not self.is_measurement else vec.reshape(1, -1)\n\n    def to_spmatrix(self) -> sparse.spmatrix:\n        \"\"\"Same as to_matrix, but returns csr sparse matrix.\n\n        Returns:\n            CSR sparse matrix representation of the State function.\n\n        Raises:\n            ValueError: invalid parameters.\n        \"\"\"\n\n        indices = [int(v, 2) for v in self.primitive.keys()]\n        vals = np.array(list(self.primitive.values())) * self.coeff\n        spvec = sparse.csr_matrix((vals, (np.zeros(len(indices), dtype=int), indices)),\n                                  shape=(1, 2**self.num_qubits))\n        return spvec if not self.is_measurement else spvec.transpose()\n\n    def to_spmatrix_op(self) -> OperatorBase:\n        \"\"\"Convert this state function to a ``SparseVectorStateFn``.\"\"\"\n        from .sparse_vector_state_fn import SparseVectorStateFn\n        return SparseVectorStateFn(self.to_spmatrix(), self.coeff, self.is_measurement)\n\n    def to_circuit_op(self) -> OperatorBase:\n        \"\"\"Convert this state function to a ``CircuitStateFn``.\"\"\"\n        from .circuit_state_fn import CircuitStateFn\n        csfn = CircuitStateFn.from_dict(self.primitive) * self.coeff\n        return csfn.adjoint() if self.is_measurement else csfn\n\n    def __str__(self) -> str:\n        prim_str = str(self.primitive)\n        if self.coeff == 1.0:\n            return \"{}({})\".format('DictStateFn' if not self.is_measurement\n                                   else 'DictMeasurement', prim_str)\n        else:\n            return \"{}({}) * {}\".format('DictStateFn' if not self.is_measurement\n                                        else 'DictMeasurement',\n                                        prim_str,\n                                        self.coeff)\n\n    # pylint: disable=too-many-return-statements\n    def eval(\n        self,\n        front: Optional[\n            Union[str, Dict[str, complex], np.ndarray, OperatorBase, Statevector]\n        ] = None,\n    ) -> Union[OperatorBase, complex]:\n        if front is None:\n            sparse_vector_state_fn = self.to_spmatrix_op().eval()\n            return sparse_vector_state_fn\n\n        if not self.is_measurement and isinstance(front, OperatorBase):\n            raise ValueError(\n                'Cannot compute overlap with StateFn or Operator if not Measurement. Try taking '\n                'sf.adjoint() first to convert to measurement.')\n\n        if isinstance(front, ListOp) and front.distributive:\n            return front.combo_fn([self.eval(front.coeff * front_elem)\n                                   for front_elem in front.oplist])\n\n        # For now, always do this. If it's not performant, we can be more granular.\n        if not isinstance(front, OperatorBase):\n            front = StateFn(front)\n\n        # pylint: disable=cyclic-import\n        from ..operator_globals import EVAL_SIG_DIGITS\n\n        # If the primitive is a lookup of bitstrings,\n        # we define all missing strings to have a function value of\n        # zero.\n        if isinstance(front, DictStateFn):\n            return np.round(\n                cast(float, sum([v * front.primitive.get(b, 0) for (b, v) in\n                                 self.primitive.items()]) * self.coeff * front.coeff),\n                decimals=EVAL_SIG_DIGITS)\n\n        # All remaining possibilities only apply when self.is_measurement is True\n\n        if isinstance(front, VectorStateFn):\n            # TODO does it need to be this way for measurement?\n            # return sum([v * front.primitive.data[int(b, 2)] *\n            # np.conj(front.primitive.data[int(b, 2)])\n            return np.round(\n                cast(float, sum([v * front.primitive.data[int(b, 2)] for (b, v) in\n                                 self.primitive.items()]) * self.coeff),\n                decimals=EVAL_SIG_DIGITS)\n\n        from .circuit_state_fn import CircuitStateFn\n        if isinstance(front, CircuitStateFn):\n            # Don't reimplement logic from CircuitStateFn\n            self_adjoint = cast(DictStateFn, self.adjoint())\n            return np.conj(front.adjoint().eval(self_adjoint.primitive)) * self.coeff\n\n        from .operator_state_fn import OperatorStateFn\n        if isinstance(front, OperatorStateFn):\n            return cast(Union[OperatorBase, float, complex], front.adjoint().eval(self.adjoint()))\n\n        # All other OperatorBases go here\n        self_adjoint = cast(DictStateFn, self.adjoint())\n        adjointed_eval = cast(OperatorBase, front.adjoint().eval(self_adjoint.primitive))\n        return adjointed_eval.adjoint() * self.coeff\n\n    def sample(self,\n               shots: int = 1024,\n               massive: bool = False,\n               reverse_endianness: bool = False) -> Dict[str, float]:\n        probs = np.square(np.abs(np.array(list(self.primitive.values()))))\n        unique, counts = np.unique(algorithm_globals.random.choice(list(self.primitive.keys()),\n                                                                   size=shots,\n                                                                   p=(probs / sum(probs))),\n                                   return_counts=True)\n        counts = dict(zip(unique, counts))\n        if reverse_endianness:\n            scaled_dict = {bstr[::-1]: (prob / shots) for (bstr, prob) in counts.items()}\n        else:\n            scaled_dict = {bstr: (prob / shots) for (bstr, prob) in counts.items()}\n        return dict(sorted(scaled_dict.items(), key=lambda x: x[1], reverse=True))\n", "path": "qiskit/opflow/state_fns/dict_state_fn.py"}]}