From e0db89ab073304eb6912216459dbefa033a278ad Mon Sep 17 00:00:00 2001 From: gadial Date: Thu, 2 May 2024 12:26:21 +0300 Subject: [PATCH 1/6] Test file with basic actual outputs but still no tests --- tests/test_primitive_output_schemas.py | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/test_primitive_output_schemas.py diff --git a/tests/test_primitive_output_schemas.py b/tests/test_primitive_output_schemas.py new file mode 100644 index 0000000..c312b56 --- /dev/null +++ b/tests/test_primitive_output_schemas.py @@ -0,0 +1,44 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2024 +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +import json +import os +import unittest +import ddt +import jsonschema + +SCHEMAS_PATH = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "schemas" +) + +@ddt.ddt +class TestEstimatorV2OutputSchema(unittest.TestCase): + """Tests the estimator output schema""" + + def setUp(self) -> None: + with open(os.path.join(SCHEMAS_PATH, "estimator_v2_output_schema.json"), "r") as fd: + self.estimator_schema = json.load(fd) + self.validator = jsonschema.Draft202012Validator(schema=self.estimator_schema) + + def test_basic_output(self): + output = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, "ensemble_standard_error": 0.012101383035893986}, "metadata": {"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, "num_randomizations": 32}}], "metadata": {"dynamical_decoupling": {"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", "scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, "num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, "zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' + +class TestSamplerV2OutputSchema(unittest.TestCase): + """Tests the sampler output schema""" + + def setUp(self) -> None: + with open(os.path.join(SCHEMAS_PATH, "sampler_v2_output_schema.json"), "r") as fd: + self.sampler_schema = json.load(fd) + self.validator = jsonschema.Draft202012Validator(schema=self.sampler_schema) + + def test_basic_output(self): + output = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"], "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' From 557e85f04b8fc99082906faafe3997145f281780 Mon Sep 17 00:00:00 2001 From: gadial Date: Mon, 6 May 2024 15:41:02 +0300 Subject: [PATCH 2/6] Change "output" to "result" --- ...as.py => test_primitive_result_schemas.py} | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) rename tests/{test_primitive_output_schemas.py => test_primitive_result_schemas.py} (76%) diff --git a/tests/test_primitive_output_schemas.py b/tests/test_primitive_result_schemas.py similarity index 76% rename from tests/test_primitive_output_schemas.py rename to tests/test_primitive_result_schemas.py index c312b56..3dbbe3f 100644 --- a/tests/test_primitive_output_schemas.py +++ b/tests/test_primitive_result_schemas.py @@ -21,24 +21,24 @@ ) @ddt.ddt -class TestEstimatorV2OutputSchema(unittest.TestCase): - """Tests the estimator output schema""" +class TestEstimatorV2ResultSchema(unittest.TestCase): + """Tests the estimator result schema""" def setUp(self) -> None: - with open(os.path.join(SCHEMAS_PATH, "estimator_v2_output_schema.json"), "r") as fd: + with open(os.path.join(SCHEMAS_PATH, "estimator_result_v2_schema.json"), "r") as fd: self.estimator_schema = json.load(fd) self.validator = jsonschema.Draft202012Validator(schema=self.estimator_schema) - def test_basic_output(self): - output = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, "ensemble_standard_error": 0.012101383035893986}, "metadata": {"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, "num_randomizations": 32}}], "metadata": {"dynamical_decoupling": {"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", "scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, "num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, "zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' + def test_basic_result(self): + result = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, "ensemble_standard_error": 0.012101383035893986}, "metadata": {"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, "num_randomizations": 32}}], "metadata": {"dynamical_decoupling": {"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", "scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, "num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, "zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' -class TestSamplerV2OutputSchema(unittest.TestCase): - """Tests the sampler output schema""" +class TestSamplerV2ResultSchema(unittest.TestCase): + """Tests the sampler result schema""" def setUp(self) -> None: - with open(os.path.join(SCHEMAS_PATH, "sampler_v2_output_schema.json"), "r") as fd: + with open(os.path.join(SCHEMAS_PATH, "sampler_v2_result_schema.json"), "r") as fd: self.sampler_schema = json.load(fd) self.validator = jsonschema.Draft202012Validator(schema=self.sampler_schema) - def test_basic_output(self): - output = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"], "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' + def test_basic_result(self): + result = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"], "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' From 81637d6683aeb317d495371fc3064a7372569ef2 Mon Sep 17 00:00:00 2001 From: gadial Date: Mon, 6 May 2024 16:36:14 +0300 Subject: [PATCH 3/6] Basic estimator result schema + test --- schemas/estimator_result_v2_schema.json | 46 +++++++++++++++++++++++++ tests/test_primitive_result_schemas.py | 9 +++-- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 schemas/estimator_result_v2_schema.json diff --git a/schemas/estimator_result_v2_schema.json b/schemas/estimator_result_v2_schema.json new file mode 100644 index 0000000..6f30774 --- /dev/null +++ b/schemas/estimator_result_v2_schema.json @@ -0,0 +1,46 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://www.qiskit.org/schemas/estimator_result_v2_schema.json", + "title": "EstimatorV2 result", + "description": "The result for an EstimatorV2 API call", + "version": "1.0.0", + "type": "object", + "required": ["results", "metadata"], + "properties": { + "results": { + "type": "array", + "description": "Array of results, one for each PUB in the original job", + "items": { + "type": "object", + "description": "A single PUB result, containing result data and metadata", + "required": ["data", "metadata"], + "properties": { + "data": { + "type": "object", + "description": "PUB results for estimator include expectation values and standard errors, which can be either numbers or multidimensional arrays of numbers, depending on the shape of the observables and parameters in the original PUB", + "required": ["evs", "stds"], + "properties": { + "evs": { + "anyOf": [{"type": "number"},{"type": "array"}] + }, + "stds": { + "anyOf": [{"type": "number"},{"type": "array"}] + }, + "ensamble_standard_error": { + "anyOf": [{"type": "number"},{"type": "array"}] + } + } + }, + "metadata": { + "type": "object", + "description": "PUB-specific metadata" + } + } + } + }, + "metadata": { + "type": "object", + "description": "Metadata for the job" + } + } +} \ No newline at end of file diff --git a/tests/test_primitive_result_schemas.py b/tests/test_primitive_result_schemas.py index 3dbbe3f..acc9367 100644 --- a/tests/test_primitive_result_schemas.py +++ b/tests/test_primitive_result_schemas.py @@ -30,7 +30,9 @@ def setUp(self) -> None: self.validator = jsonschema.Draft202012Validator(schema=self.estimator_schema) def test_basic_result(self): - result = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, "ensemble_standard_error": 0.012101383035893986}, "metadata": {"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, "num_randomizations": 32}}], "metadata": {"dynamical_decoupling": {"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", "scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, "num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, "zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' + result_str = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, "ensemble_standard_error": 0.012101383035893986}, "metadata": {"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, "num_randomizations": 32}}], "metadata": {"dynamical_decoupling": {"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", "scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, "num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, "zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' + result = json.loads(result_str) + self.validator.validate(result) class TestSamplerV2ResultSchema(unittest.TestCase): """Tests the sampler result schema""" @@ -41,4 +43,7 @@ def setUp(self) -> None: self.validator = jsonschema.Draft202012Validator(schema=self.sampler_schema) def test_basic_result(self): - result = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"], "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' + result_str = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"], "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' + result = json.loads(result_str) + print(result) + self.validator.validate(result) \ No newline at end of file From 59c33f9dadff70ae016f0e7e85f201ddab7031b8 Mon Sep 17 00:00:00 2001 From: gadial Date: Tue, 7 May 2024 08:57:38 +0300 Subject: [PATCH 4/6] Added the basic sampler result schema --- schemas/sampler_result_v2_schema.json | 49 ++++++++++++++++++++++++++ tests/test_primitive_result_schemas.py | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 schemas/sampler_result_v2_schema.json diff --git a/schemas/sampler_result_v2_schema.json b/schemas/sampler_result_v2_schema.json new file mode 100644 index 0000000..870313d --- /dev/null +++ b/schemas/sampler_result_v2_schema.json @@ -0,0 +1,49 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://www.qiskit.org/schemas/sampler_result_v2_schema.json", + "title": "EstimatorV2 result", + "description": "The result for an SamplerV2 API call", + "version": "1.0.0", + "type": "object", + "required": ["results", "metadata"], + "properties": { + "results": { + "type": "array", + "description": "Array of results, one for each PUB in the original job", + "items": { + "type": "object", + "description": "A single PUB result, containing result data and metadata", + "required": ["data", "metadata"], + "properties": { + "data": { + "type": "object", + "description": "PUB results for sampler are split according to the classical bits register names. For each register, an array of samples (in hexadecimal string format) is returned", + "additionalProperties": { + "type": "object", + "description": "The data corresponding to a specific measurement", + "properties": { + "samples": { + "type": "array", + "description": "An array of samples (given as hexadecimal strings)", + "items": {"type": "string"} + }, + "num_bits": { + "type": "integer", + "description": "The number of measured bits" + } + } + } + }, + "metadata": { + "type": "object", + "description": "PUB-specific metadata" + } + } + } + }, + "metadata": { + "type": "object", + "description": "Metadata for the job" + } + } +} \ No newline at end of file diff --git a/tests/test_primitive_result_schemas.py b/tests/test_primitive_result_schemas.py index acc9367..c86d080 100644 --- a/tests/test_primitive_result_schemas.py +++ b/tests/test_primitive_result_schemas.py @@ -38,7 +38,7 @@ class TestSamplerV2ResultSchema(unittest.TestCase): """Tests the sampler result schema""" def setUp(self) -> None: - with open(os.path.join(SCHEMAS_PATH, "sampler_v2_result_schema.json"), "r") as fd: + with open(os.path.join(SCHEMAS_PATH, "sampler_result_v2_schema.json"), "r") as fd: self.sampler_schema = json.load(fd) self.validator = jsonschema.Draft202012Validator(schema=self.sampler_schema) From 5e8205a0552d93b641e7b5360664371cd8476f3f Mon Sep 17 00:00:00 2001 From: gadial Date: Wed, 22 May 2024 10:35:18 +0300 Subject: [PATCH 5/6] linting --- tests/test_primitive_result_schemas.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/test_primitive_result_schemas.py b/tests/test_primitive_result_schemas.py index c86d080..d519344 100644 --- a/tests/test_primitive_result_schemas.py +++ b/tests/test_primitive_result_schemas.py @@ -20,30 +20,45 @@ os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "schemas" ) + @ddt.ddt class TestEstimatorV2ResultSchema(unittest.TestCase): """Tests the estimator result schema""" def setUp(self) -> None: - with open(os.path.join(SCHEMAS_PATH, "estimator_result_v2_schema.json"), "r") as fd: + with open( + os.path.join(SCHEMAS_PATH, "estimator_result_v2_schema.json"), "r" + ) as fd: self.estimator_schema = json.load(fd) self.validator = jsonschema.Draft202012Validator(schema=self.estimator_schema) def test_basic_result(self): - result_str = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, "ensemble_standard_error": 0.012101383035893986}, "metadata": {"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, "num_randomizations": 32}}], "metadata": {"dynamical_decoupling": {"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", "scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, "num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, "zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' + result_str = '{"results": [{"data": {"evs": 1.1142546245919478, "stds": 0.012101383035893986, ' \ + '"ensemble_standard_error": 0.012101383035893986}, "metadata": ' \ + '{"shots": 4096, "target_precision": 0.015625, "circuit_metadata": {}, "resilience": {}, ' \ + '"num_randomizations": 32}}], "metadata": {"dynamical_decoupling": ' \ + '{"enable": false, "sequence_type": "XX", "extra_slack_distribution": "middle", ' \ + '"scheduling_method": "alap"}, "twirling": {"enable_gates": false, "enable_measure": true, ' \ + '"num_randomizations": "auto", "shots_per_randomization": "auto", "interleave_randomizations": ' \ + 'true, "strategy": "active-accum"}, "resilience": {"measure_mitigation": true, ' \ + '"zne_mitigation": false, "pec_mitigation": false}, "version": 2}}' result = json.loads(result_str) self.validator.validate(result) + class TestSamplerV2ResultSchema(unittest.TestCase): """Tests the sampler result schema""" def setUp(self) -> None: - with open(os.path.join(SCHEMAS_PATH, "sampler_result_v2_schema.json"), "r") as fd: + with open( + os.path.join(SCHEMAS_PATH, "sampler_result_v2_schema.json"), "r" + ) as fd: self.sampler_schema = json.load(fd) self.validator = jsonschema.Draft202012Validator(schema=self.sampler_schema) def test_basic_result(self): - result_str = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"], "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' + result_str = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"],' \ + ' "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' result = json.loads(result_str) print(result) - self.validator.validate(result) \ No newline at end of file + self.validator.validate(result) From d8833921b23cd420d8dae9252cef3470180ea139 Mon Sep 17 00:00:00 2001 From: gadial Date: Tue, 18 Jun 2024 14:51:46 +0300 Subject: [PATCH 6/6] small fix --- tests/test_primitive_result_schemas.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_primitive_result_schemas.py b/tests/test_primitive_result_schemas.py index d519344..5d33ea0 100644 --- a/tests/test_primitive_result_schemas.py +++ b/tests/test_primitive_result_schemas.py @@ -60,5 +60,4 @@ def test_basic_result(self): result_str = '{"results": [{"data": {"meas": {"samples": ["0x3", "0x3", "0x3", "0x3", "0x3"],' \ ' "num_bits": 2}}, "metadata": {"circuit_metadata": {}}}], "metadata": {"version": 2}}' result = json.loads(result_str) - print(result) self.validator.validate(result)