From 89c3ae6de827ab9391c3adcd16726952ef89364f Mon Sep 17 00:00:00 2001 From: "REDMOND\\ivanbaso" Date: Fri, 20 Oct 2023 07:48:45 -0700 Subject: [PATCH] duration and num qubits constrained searches --- .../azure/quantum/target/microsoft/target.py | 18 +++++++++++------- azure-quantum/tests/unit/test_microsoft_qc.py | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/azure-quantum/azure/quantum/target/microsoft/target.py b/azure-quantum/azure/quantum/target/microsoft/target.py index 6123e097e..04a09d69a 100644 --- a/azure-quantum/azure/quantum/target/microsoft/target.py +++ b/azure-quantum/azure/quantum/target/microsoft/target.py @@ -45,13 +45,17 @@ def _check_error_rate_or_process_and_readout(name, value): raise ValueError(f"{name} must be either a float or " "MeasurementErrorRate with two fields: 'process' and 'readout'") +def check_time(name, value): + pat = r"^(\+?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(s|ms|μs|µs|us|ns)$" + if re.match(pat, value) is None: + raise ValueError(f"{name} is not a valid time string; use a " + "suffix s, ms, us, or ns") @dataclass class MeasurementErrorRate(AutoValidatingParams): process: float = field(metadata={"validate": _check_error_rate}) readout: float = field(metadata={"validate": _check_error_rate}) - @dataclass class MicrosoftEstimatorQubitParams(AutoValidatingParams): @staticmethod @@ -60,12 +64,6 @@ def check_instruction_set(name, value): "Majorana", "majorana"]: raise ValueError(f"{name} must be GateBased or Majorana") - @staticmethod - def check_time(name, value): - pat = r"^(\+?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(s|ms|μs|µs|us|ns)$" - if re.match(pat, value) is None: - raise ValueError(f"{name} is not a valid time string; use a " - "suffix s, ms, us, or ns") name: Optional[str] = None instruction_set: Optional[str] = validating_field(check_instruction_set) one_qubit_measurement_time: Optional[str] = validating_field(check_time) @@ -259,6 +257,12 @@ def at_least_one(name, value): logical_depth_factor: Optional[float] = validating_field(at_least_one) max_t_factories: Optional[int] = validating_field(at_least_one) + max_duration: Optional[int] = validating_field(check_time) + max_physical_qubits: Optional[int] = validating_field(at_least_one) + + def post_validation(self, result): + if self.max_duration is not None and self.max_physical_qubits is not None: + raise LookupError("Both duration and number of physical qubits constraints are provided, but only one is allowe at a time.") @dataclass diff --git a/azure-quantum/tests/unit/test_microsoft_qc.py b/azure-quantum/tests/unit/test_microsoft_qc.py index 8331a26ec..3139a386f 100644 --- a/azure-quantum/tests/unit/test_microsoft_qc.py +++ b/azure-quantum/tests/unit/test_microsoft_qc.py @@ -6,7 +6,7 @@ from pytest import raises from os import path import re -from azure.quantum.target.microsoft.target import DistillationUnitSpecification, ProtocolSpecificDistillationUnitSpecification, MeasurementErrorRate +from azure.quantum.target.microsoft.target import DistillationUnitSpecification, MicrosoftEstimatorConstraints, ProtocolSpecificDistillationUnitSpecification, MeasurementErrorRate from common import QuantumTestBase, DEFAULT_TIMEOUT_SECS @@ -79,7 +79,7 @@ def test_estimator_batching_job(self): estimator = MicrosoftEstimator(ws) ccnot = self._ccnot_bitcode() - params = estimator.make_params(num_items=2) + params = estimator.make_params(num_items=3) params.items[0].error_budget = 0.001 params.items[0].qubit_params.name = QubitParams.MAJ_NS_E4 @@ -116,6 +116,11 @@ def test_estimator_batching_job(self): params.items[0].distillation_unit_specifications = [specification1, specification2, specification3] params.items[1].error_budget = 0.002 + params.items[1].constraints.max_duration = "20s" + + params.items[2].error_budget = 0.003 + params.items[2].constraints.max_physical_qubits = 10000 + job = estimator.submit(ccnot, input_params=params) self.assertIsInstance(job, MicrosoftEstimatorJob) job.wait_until_completed(timeout_secs=DEFAULT_TIMEOUT_SECS) @@ -491,3 +496,10 @@ def test_batch_result_as_json(self): import json assert json.loads(result.json) == data + + def test_duration_and_physical_qubits_constraints_not_allowed_together(self): + constraints = MicrosoftEstimatorConstraints() + constraints.max_physical_qubits = 100 + constraints.max_duration = "5s" + with raises(LookupError, match="Both duration and number of physical qubits constraints are provided, but only one is allowe at a time."): + constraints.as_dict()