def test_get_experiment_results_raises_simulation_error_when_no_histogram(self): api = Mock() api.get_jobs_from_project.return_value = [{'id': 42, 'results': '{}'}] api.get_result_from_job.return_value = {'histogram': [], 'raw_text': 'Error'} job = Mock() job.job_id.return_value = '42' simulator = QuantumInspireBackend(api, Mock()) with self.assertRaises(QisKitBackendError) as error: simulator.get_experiment_results(job) self.assertEqual(('Result from backend contains no histogram data!\nError',), error.exception.args)
def test_get_experiment_results_returns_correct_value(self): number_of_shots = 100 instructions = [{'name': 'h', 'qubits': [0]}, {'name': 'cx', 'qubits': [0, 1]}, {'name': 'measure', 'qubits': [1], 'memory': [1]}, {'name': 'measure', 'qubits': [0], 'memory': [0]}] experiment = self._instructions_to_two_qubit_experiment(instructions) api = Mock() api.get_result_from_job.return_value = {'id': 1, 'histogram': {'1': 0.6, '3': 0.4}, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/'} api.get_raw_data_from_result.return_value = [1] * 60 + [3] * 40 jobs = self._basic_job_dictionary measurements = QuantumInspireBackend._collect_measurements(experiment) user_data = {'name': 'name', 'memory_slots': 2, 'creg_sizes': [['c1', 2]], 'measurements': measurements} jobs['user_data'] = json.dumps(user_data) api.get_jobs_from_project.return_value = [jobs] job = QIJob('backend', '42', api) simulator = QuantumInspireBackend(api, Mock()) experiment_result = simulator.get_experiment_results(job)[0] self.assertEqual(experiment_result.data.counts['0x1'], 60) self.assertEqual(experiment_result.data.counts['0x3'], 40) self.assertEqual(experiment_result.data.probabilities['0x1'], 0.6) self.assertEqual(experiment_result.data.probabilities['0x3'], 0.4) self.assertEqual(len(experiment_result.data.memory), 100) self.assertEqual(experiment_result.data.memory.count('0x1'), 60) self.assertEqual(experiment_result.data.memory.count('0x3'), 40) self.assertEqual(experiment_result.name, 'circuit0') self.assertEqual(experiment_result.shots, number_of_shots)
def test_get_experiment_results_multiple_single_shots(self): one_shot_results = {'0x0': 0, '0x1': 0, '0x2': 0, '0x3': 0} np.random.seed(2019) for i in range(10000): number_of_shots = 1 self._basic_job_dictionary['number_of_shots'] = number_of_shots instructions = [{'name': 'h', 'qubits': [0]}, {'name': 'cx', 'qubits': [0, 1]}, {'name': 'measure', 'qubits': [1], 'memory': [1]}, {'name': 'measure', 'qubits': [0], 'memory': [0]}] experiment = self._instructions_to_two_qubit_experiment(instructions) api = Mock() api.get_result_from_job.return_value = {'id': 1, 'histogram': {'0': 0.2, '1': 0.3, '2': 0.4, '3': 0.1}, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/'} api.get_raw_data_from_result.return_value = [] jobs = self._basic_job_dictionary measurements = QuantumInspireBackend._collect_measurements(experiment) user_data = {'name': 'name', 'memory_slots': 2, 'creg_sizes': [['c1', 2]], 'measurements': measurements} jobs['user_data'] = json.dumps(user_data) api.get_jobs_from_project.return_value = [jobs] job = QIJob('backend', '42', api) simulator = QuantumInspireBackend(api, Mock()) experiment_result = simulator.get_experiment_results(job)[0] # Exactly one value in memory self.assertEqual(len(experiment_result.data.memory), 1) # The only value in memory is the same as the value in the counts histogram. self.assertEqual(list(experiment_result.data.counts.keys())[0], experiment_result.data.memory[0]) one_shot_results[experiment_result.data.memory[0]] += 1 self.assertEqual(one_shot_results['0x0'], 2066) self.assertEqual(one_shot_results['0x1'], 2947) self.assertEqual(one_shot_results['0x2'], 4003) self.assertEqual(one_shot_results['0x3'], 984)
def test_get_experiment_results_returns_single_shot(self): number_of_shots = 1 self._basic_job_dictionary['number_of_shots'] = number_of_shots instructions = [{'name': 'h', 'qubits': [0]}, {'name': 'cx', 'qubits': [0, 1]}, {'name': 'measure', 'qubits': [1], 'memory': [1]}, {'name': 'measure', 'qubits': [0], 'memory': [0]}] experiment = self._instructions_to_two_qubit_experiment(instructions) api = Mock() api.get_result_from_job.return_value = {'id': 1, 'histogram': {'0': 0.5, '3': 0.5}, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/'} api.get_raw_data_from_result.return_value = [] api.get_backend_type_by_name.return_value = {'max_number_of_shots': 4096} jobs = self._basic_job_dictionary measurements = QuantumInspireBackend._collect_measurements(experiment) user_data = {'name': 'name', 'memory_slots': 2, 'creg_sizes': [['c1', 2]], 'measurements': measurements} jobs['user_data'] = json.dumps(user_data) api.get_jobs_from_project.return_value = [jobs] job = QIJob('backend', '42', api) simulator = QuantumInspireBackend(api, Mock()) experiment_result = simulator.get_experiment_results(job)[0] self.assertEqual(experiment_result.data.probabilities['0x0'], 0.5) self.assertEqual(experiment_result.data.probabilities['0x3'], 0.5) self.assertTrue(hasattr(experiment_result.data, 'memory')) # Exactly one value in counts histogram self.assertEqual(len(experiment_result.data.counts), 1) # The single value in counts histogram has count 1 self.assertEqual(list(experiment_result.data.counts.values())[0], 1) # Exactly one value in memory self.assertEqual(len(experiment_result.data.memory), 1) # The only value in memory is the same as the value in the counts histogram. self.assertEqual(list(experiment_result.data.counts.keys())[0], experiment_result.data.memory[0]) self.assertEqual(experiment_result.name, 'circuit0') self.assertEqual(experiment_result.shots, number_of_shots)
class TestQiSimulatorPyHistogram(unittest.TestCase): def setUp(self): self.mock_api = ApiMock(spec=QuantumInspireAPI) self.mock_provider = Mock(spec=QuantumInspireProvider) self.simulator = QuantumInspireBackend(self.mock_api, self.mock_provider) self._basic_job_dictionary = OrderedDict([ ('url', 'http://saevar-qutech-nginx/api/jobs/24/'), ('name', 'BLA_BLU'), ('id', 24), ('status', 'COMPLETE'), ('input', 'http://saevar-qutech-nginx/api/assets/26/'), ('backend', 'http://saevar-qutech-nginx/api/backends/1/'), ('backend_type', 'http://saevar-qutech-nginx/api/backendtypes/1/'), ('results', 'http://saevar-qutech-nginx/api/jobs/24/result/'), ('queued_at', '2018-12-07T09:11:45.976617Z'), ('number_of_shots', 1000), ('full_state_projection', True), ('user_data', '') ]) def run_histogram_test(self, single_experiment, mock_result1, mock_result2, expected_histogram, expected_histogram_prob, expected_memory): self.mock_api.set(mock_result1, mock_result2) jobs = self._basic_job_dictionary measurements = QuantumInspireBackend._collect_measurements( QobjExperiment.from_dict(single_experiment)) user_data = { 'name': 'name', 'memory_slots': 2, 'creg_sizes': [['c1', 2]], 'measurements': measurements } jobs['user_data'] = json.dumps(user_data) self.mock_api.get_jobs_from_project.return_value = [jobs] job = QIJob('backend', '42', self.mock_api) result = self.simulator.get_experiment_results(job) number_of_shots = jobs['number_of_shots'] self.assertEqual(1, len(result)) first_experiment = first_item(result) actual = first_experiment.data.counts.to_dict() self.assertDictEqual(expected_histogram, actual) probabilities = first_experiment.data.probabilities.to_dict() self.assertTrue( len(expected_histogram_prob.keys() - probabilities.keys()) == 0) for key in set(probabilities.keys()) & set( expected_histogram_prob.keys()): self.assertTrue( np.isclose(expected_histogram_prob[key], probabilities[key])) self.assertTrue(len(first_experiment.data.memory) == number_of_shots) self.assertListEqual(expected_memory, first_experiment.data.memory) @staticmethod def _instructions_to_experiment(instructions, memory_slots=2): experiment_dictionary = { 'instructions': instructions, 'header': { 'n_qubits': 2, 'memory_slots': memory_slots, 'name': 'test_circuit', 'qubit_labels': [['q0', 0], ['q0', 1]], 'clbit_labels': [['c0', 0], ['c1', 1]] } } return experiment_dictionary def test_convert_histogram_NormalMeasurement(self): self.run_histogram_test( single_experiment=self._instructions_to_experiment([{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [0], 'memory': [0] }, { 'name': 'measure', 'qubits': [1], 'memory': [1] }]), mock_result1={ 'id': 1, 'histogram': { '0': 0.1, '1': 0.2, '2': 0.3, '3': 0.4 }, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[0] * 100 + [1] * 200 + [2] * 300 + [3] * 400, expected_histogram={ '0x0': 100, '0x1': 200, '0x2': 300, '0x3': 400 }, expected_histogram_prob={ '0x0': 0.1, '0x1': 0.2, '0x2': 0.3, '0x3': 0.4 }, expected_memory=['0x0'] * 100 + ['0x1'] * 200 + ['0x2'] * 300 + ['0x3'] * 400) def test_classical_bits_are_displayed_correctly(self): self.run_histogram_test( single_experiment=self._instructions_to_experiment( [{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [0], 'memory': [0] }, { 'name': 'measure', 'qubits': [0], 'memory': [3] }, { 'name': 'measure', 'qubits': [1], 'memory': [4] }, { 'name': 'measure', 'qubits': [1], 'memory': [7] }], memory_slots=8), mock_result1={ 'id': 1, 'histogram': { '0': 0.1, '1': 0.2, '2': 0.3, '3': 0.4 }, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[0] * 100 + [1] * 200 + [2] * 300 + [3] * 400, expected_histogram={ '0x0': 100, '0x9': 200, '0x90': 300, '0x99': 400 }, expected_histogram_prob={ '0x0': 0.1, '0x9': 0.2, '0x90': 0.3, '0x99': 0.4 }, expected_memory=['0x0'] * 100 + ['0x9'] * 200 + ['0x90'] * 300 + ['0x99'] * 400) def test_convert_histogram_SwappedClassicalQubits(self): self.run_histogram_test( single_experiment=self._instructions_to_experiment([{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [0], 'memory': [1] }, { 'name': 'measure', 'qubits': [1], 'memory': [0] }]), mock_result1={ 'id': 1, 'histogram': { '0': 0.1, '1': 0.2, '2': 0.3, '3': 0.4 }, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[0] * 100 + [1] * 200 + [2] * 300 + [3] * 400, expected_histogram={ '0x0': 100, '0x1': 300, '0x2': 200, '0x3': 400 }, expected_histogram_prob={ '0x0': 0.1, '0x1': 0.3, '0x2': 0.2, '0x3': 0.4 }, expected_memory=['0x0'] * 100 + ['0x2'] * 200 + ['0x1'] * 300 + ['0x3'] * 400) def test_convert_histogram_LessMeasurementsQubitOne(self): self.run_histogram_test( single_experiment=self._instructions_to_experiment([{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [0], 'memory': [0] }]), mock_result1={ 'id': 1, 'histogram': { '0': 0.1, '1': 0.2, '2': 0.3, '3': 0.4 }, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[0] * 100 + [1] * 200 + [2] * 300 + [3] * 400, expected_histogram={ '0x0': 400, '0x1': 600 }, expected_histogram_prob={ '0x0': 0.4, '0x1': 0.6 }, expected_memory=['0x0'] * 100 + ['0x1'] * 200 + ['0x0'] * 300 + ['0x1'] * 400) def test_convert_histogram_LessMeasurementsQubitTwo(self): self.run_histogram_test( single_experiment=self._instructions_to_experiment([{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [1], 'memory': [1] }]), mock_result1={ 'id': 1, 'histogram': { '0': 0.1, '1': 0.2, '2': 0.3, '3': 0.4 }, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[0] * 100 + [1] * 200 + [2] * 300 + [3] * 400, expected_histogram={ '0x0': 300, '0x2': 700 }, expected_histogram_prob={ '0x0': 0.3, '0x2': 0.7 }, expected_memory=['0x0'] * 300 + ['0x2'] * 700) def test_convert_histogram_ClassicalBitsMeasureSameQubits(self): self.run_histogram_test( single_experiment={ 'instructions': [{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [0], 'memory': [0] }, { 'name': 'measure', 'qubits': [1], 'memory': [0] }], 'header': { 'n_qubits': 2, 'memory_slots': 2, 'name': 'test', 'qubit_labels': [['q0', 0], ['q0', 1]], 'clbit_labels': [['c0', 0], ['c1', 1]] } }, mock_result1={ 'id': 1, 'histogram': { '0': 0.1, '1': 0.2, '2': 0.3, '3': 0.4 }, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[0] * 100 + [1] * 200 + [2] * 300 + [3] * 400, expected_histogram={ '0x0': 300, '0x1': 700 }, expected_histogram_prob={ '0x0': 0.3, '0x1': 0.7 }, expected_memory=['0x0'] * 300 + ['0x1'] * 700) def test_empty_histogram(self): with self.assertRaises(QisKitBackendError) as error: self.run_histogram_test( single_experiment=self._instructions_to_experiment([{ 'name': 'h', 'params': [], 'texparams': [], 'qubits': [0] }, { 'name': 'cx', 'params': [], 'texparams': [], 'qubits': [0, 1] }, { 'name': 'measure', 'qubits': [1], 'memory': [1] }]), mock_result1={ 'id': 1, 'histogram': {}, 'execution_time_in_seconds': 2.1, 'number_of_qubits': 2, 'raw_text': 'oopsy daisy', 'raw_data_url': 'http://saevar-qutech-nginx/api/results/24/raw-data/' }, mock_result2=[], expected_histogram={}, expected_histogram_prob={}, expected_memory=[]) self.assertEqual( ('Result from backend contains no histogram data!\noopsy daisy', ), error.exception.args)