Repository: Qiskit/qiskit

Issue:
Results object should inform user if multiple results of same name
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: 0.8.0
- **Python version**: 3.7.1
- **Operating system**: Mac OS X

### What is the current behavior?
The device appears to be returning the same results for different circuits. 
5 separate circuits were ran, and the exact same results were returned each time:

<img width="1153" alt="Screen Shot 2019-10-06 at 12 13 52 AM" src="https://user-images.githubusercontent.com/46495807/66264175-3af62580-e7ce-11e9-9fb7-1d46fd62d9cd.png">


### Steps to reproduce the problem
A state vector was passed to the circuit initializer. The initializer was transpiled with varying optimization levels. When the optimized circuits were ran on the device, the exact same results were returned for each circuit. It seemed as if the device had simply run the first circuit once, and then duplicated the results again and again. It seems as if the other circuits were simply not run. An example is shown below: 

`init.initialize(state_vector, range(4))`
`circ = transpile(init, basis_gates = ['u3', 'cx']`
`opt0 = transpile(circ, backend=backend, seed_transpiler=11, optimization_level=0)`
`opt1 = transpile(circ, backend=backend, seed_transpiler=11, optimization_level=1)`
`opt2 = transpile(circ, backend=backend, seed_transpiler=11, optimization_level=2)`
`opt3 = transpile(circ, backend=backend, seed_transpiler=11, optimization_level=3)`

### What is the expected behavior?
It would be expected for the circuits transpiled with higher optimization levels to have better performance. However, at the very least, the randomness of the quantum hardware should guarantee that each circuit have different results. 

It is evident that different circuits are in fact being passed into the device, 

<img width="884" alt="Screen Shot 2019-10-06 at 12 15 45 AM" src="https://user-images.githubusercontent.com/46495807/66264186-7abd0d00-e7ce-11e9-91e5-37193bcefcd5.png">


### Suggested solutions
It may be that the device is cancelling redundant circuits. 




Discussion:
Hi @tboen1 , thanks for reporting. Can you include the code you used to select a backend, run the circuits and fetch the results?

Thanks for the reply! 
```
circuit_list = [circ, opt0, opt1, opt2, opt3]
device = 'ibmq_ourense'
shots = 8000
backend = qk.IBMQ.get_backend(device)
experiment = qk.execute(circuit_list, backend, shots=shots, optimization_level = 0)
result = experiment.result()
for i in range(len(circuit_list)):
    print(result.get_counts(circuit_list[i]))
```

Hope this helps, the circuits specified in `circuit_list` are shown in the original report
All of your circuits probably have the same name. 
Try checking `circ.name`, `opt0.name`, etc.

You can fix this by changing the last line to:
```
    print(result.get_counts(i))
```

We have to check in the results by name (it gets sent over wire and the QuantumCircuit instance may have been destroyed). The ability to look up by the circuit instance is merely a convenience. But I agree that this can be confusing, and the Result should warn you that multiple experiment results of same name are available.

Resolving patch:
diff --git a/qiskit/result/result.py b/qiskit/result/result.py
--- a/qiskit/result/result.py
+++ b/qiskit/result/result.py
@@ -13,6 +13,7 @@
 """Model for schema-conformant Results."""
 
 import copy
+import warnings
 
 from qiskit.circuit.quantumcircuit import QuantumCircuit
 from qiskit.pulse.schedule import Schedule
@@ -353,14 +354,22 @@ def _get_experiment(self, key=None):
         if isinstance(key, int):
             exp = self.results[key]
         else:
-            try:
-                # Look into `result[x].header.name` for the names.
-                exp = next(result for result in self.results
-                           if getattr(getattr(result, 'header', None),
-                                      'name', '') == key)
-            except StopIteration:
+            # Look into `result[x].header.name` for the names.
+            exp = [result for result in self.results
+                   if getattr(getattr(result, 'header', None),
+                              'name', '') == key]
+
+            if len(exp) == 0:
                 raise QiskitError('Data for experiment "%s" could not be found.' %
                                   key)
+            if len(exp) == 1:
+                exp = exp[0]
+            else:
+                warnings.warn(
+                    'Result object contained multiple results matching name "%s", '
+                    'only first match will be returned. Use an integer index to '
+                    'retrieve results for all entries.' % key)
+                exp = exp[0]
 
         # Check that the retrieved experiment was successful
         if getattr(exp, 'success', False):


Test patch:
diff --git a/test/python/result/test_result.py b/test/python/result/test_result.py
--- a/test/python/result/test_result.py
+++ b/test/python/result/test_result.py
@@ -57,6 +57,17 @@ def test_counts_header(self):
 
         self.assertEqual(result.get_counts(0), processed_counts)
 
+    def test_counts_duplicate_name(self):
+        """Test results containing multiple entries of a single name will warn."""
+        data = models.ExperimentResultData(counts=dict())
+        exp_result_header = QobjExperimentHeader(name='foo')
+        exp_result = models.ExperimentResult(shots=14, success=True,
+                                             data=data, header=exp_result_header)
+        result = Result(results=[exp_result] * 2, **self.base_result_args)
+
+        with self.assertWarnsRegex(UserWarning, r'multiple.*foo'):
+            result.get_counts('foo')
+
     def test_result_repr(self):
         """Test that repr is contstructed correctly for a results object."""
         raw_counts = {'0x0': 4, '0x2': 10}