azure-quantum 2.2.0.dev3__tar.gz → 2.2.0.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/PKG-INFO +1 -1
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/_version.py +1 -1
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/backend.py +121 -65
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/ionq.py +3 -3
- azure-quantum-2.2.0.dev5/azure/quantum/qiskit/backends/microsoft.py +161 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/qci.py +9 -4
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/quantinuum.py +2 -22
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/rigetti.py +2 -1
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/job.py +7 -2
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/ionq.py +8 -3
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/target.py +26 -7
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/pasqal/target.py +7 -1
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/quantinuum.py +7 -3
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/rigetti/target.py +13 -6
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/target.py +16 -3
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/version.py +1 -1
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure_quantum.egg-info/PKG-INFO +1 -1
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure_quantum.egg-info/requires.txt +4 -4
- azure-quantum-2.2.0.dev5/requirements-qiskit.txt +5 -0
- azure-quantum-2.2.0.dev3/azure/quantum/qiskit/backends/microsoft.py +0 -114
- azure-quantum-2.2.0.dev3/requirements-qiskit.txt +0 -5
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/README.md +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_authentication/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_authentication/_chained.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_authentication/_default.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_authentication/_token.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/_client.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/_configuration.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/_patch.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/_serialization.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/_vendor.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/models/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/models/_enums.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/models/_models.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/models/_patch.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/operations/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/operations/_operations.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_client/operations/_patch.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_constants.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/_workspace_connection_params.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/argument_types/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/argument_types/types.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/chemistry/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/job.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/service.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/targets/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/targets/ionq.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/targets/quantinuum.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/cirq/targets/target.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/base_job.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/filtered_job.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/job.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/job_failed_with_results_error.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/session.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/workspace_item.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/job/workspace_item_factory.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/provider.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/results/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/results/resource_estimator.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/storage.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/elements/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/elements/dft/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/elements/dft/job.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/elements/dft/target.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/job.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/result.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/params.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/pasqal/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/pasqal/result.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/rigetti/__init__.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/rigetti/result.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/target_factory.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/workspace.py +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure_quantum.egg-info/SOURCES.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure_quantum.egg-info/dependency_links.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure_quantum.egg-info/top_level.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/requirements-cirq.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/requirements-dev.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/requirements-pulser.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/requirements-qsharp.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/requirements-quil.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/requirements.txt +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/setup.cfg +0 -0
- {azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/setup.py +0 -0
{azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/backend.py
RENAMED
|
@@ -21,14 +21,15 @@ from abc import abstractmethod
|
|
|
21
21
|
from azure.quantum.job.session import SessionHost
|
|
22
22
|
|
|
23
23
|
try:
|
|
24
|
-
from qiskit import QuantumCircuit
|
|
24
|
+
from qiskit import QuantumCircuit
|
|
25
25
|
from qiskit.providers import BackendV1 as Backend
|
|
26
26
|
from qiskit.providers import Options
|
|
27
27
|
from qiskit.providers import Provider
|
|
28
28
|
from qiskit.providers.models import BackendConfiguration
|
|
29
29
|
from qiskit.qobj import QasmQobj, PulseQobj
|
|
30
|
-
|
|
31
|
-
from
|
|
30
|
+
import pyqir as pyqir
|
|
31
|
+
from qsharp.interop.qiskit import QSharpBackend
|
|
32
|
+
from qsharp import TargetProfile
|
|
32
33
|
|
|
33
34
|
except ImportError:
|
|
34
35
|
raise ImportError(
|
|
@@ -36,23 +37,37 @@ except ImportError:
|
|
|
36
37
|
To install run: pip install azure-quantum[qiskit]"
|
|
37
38
|
)
|
|
38
39
|
|
|
40
|
+
# barrier is handled by an extra flag which will transpile
|
|
41
|
+
# them away if the backend doesn't support them. This has
|
|
42
|
+
# to be done as a special pass as the transpiler will not
|
|
43
|
+
# remove barriers by default.
|
|
39
44
|
QIR_BASIS_GATES = [
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
45
|
+
"measure",
|
|
46
|
+
"reset",
|
|
47
|
+
"ccx",
|
|
48
|
+
"cx",
|
|
49
|
+
"cy",
|
|
50
|
+
"cz",
|
|
43
51
|
"rx",
|
|
52
|
+
"rxx",
|
|
53
|
+
"crx",
|
|
44
54
|
"ry",
|
|
55
|
+
"ryy",
|
|
56
|
+
"cry",
|
|
45
57
|
"rz",
|
|
58
|
+
"rzz",
|
|
59
|
+
"crz",
|
|
46
60
|
"h",
|
|
47
|
-
"swap",
|
|
48
|
-
"cx",
|
|
49
|
-
"cz",
|
|
50
|
-
"reset",
|
|
51
61
|
"s",
|
|
52
62
|
"sdg",
|
|
63
|
+
"swap",
|
|
53
64
|
"t",
|
|
54
65
|
"tdg",
|
|
55
|
-
"
|
|
66
|
+
"x",
|
|
67
|
+
"y",
|
|
68
|
+
"z",
|
|
69
|
+
"id",
|
|
70
|
+
"ch",
|
|
56
71
|
]
|
|
57
72
|
|
|
58
73
|
|
|
@@ -391,98 +406,139 @@ class AzureQirBackend(AzureBackendBase):
|
|
|
391
406
|
return {}
|
|
392
407
|
|
|
393
408
|
def _generate_qir(
|
|
394
|
-
self, circuits,
|
|
395
|
-
) ->
|
|
409
|
+
self, circuits: List[QuantumCircuit], target_profile: TargetProfile, **kwargs
|
|
410
|
+
) -> pyqir.Module:
|
|
411
|
+
|
|
412
|
+
if len(circuits) == 0:
|
|
413
|
+
raise ValueError("No QuantumCircuits provided")
|
|
396
414
|
|
|
397
415
|
config = self.configuration()
|
|
398
416
|
# Barriers aren't removed by transpilation and must be explicitly removed in the Qiskit to QIR translation.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
417
|
+
supports_barrier = "barrier" in config.basis_gates
|
|
418
|
+
skip_transpilation = kwargs.pop("skip_transpilation", False)
|
|
419
|
+
|
|
420
|
+
backend = QSharpBackend(
|
|
421
|
+
qiskit_pass_options={"supports_barrier": supports_barrier},
|
|
422
|
+
target_profile=target_profile,
|
|
423
|
+
skip_transpilation=skip_transpilation,
|
|
424
|
+
**kwargs,
|
|
405
425
|
)
|
|
406
426
|
|
|
407
|
-
|
|
408
|
-
|
|
427
|
+
name = "batch"
|
|
428
|
+
if len(circuits) == 1:
|
|
429
|
+
name = circuits[0].name
|
|
430
|
+
|
|
431
|
+
if isinstance(circuits, list):
|
|
432
|
+
for value in circuits:
|
|
433
|
+
if not isinstance(value, QuantumCircuit):
|
|
434
|
+
raise ValueError("Input must be List[QuantumCircuit]")
|
|
435
|
+
else:
|
|
436
|
+
raise ValueError("Input must be List[QuantumCircuit]")
|
|
437
|
+
|
|
438
|
+
context = pyqir.Context()
|
|
439
|
+
llvm_module = pyqir.qir_module(context, name)
|
|
440
|
+
for circuit in circuits:
|
|
441
|
+
qir_str = backend.qir(circuit)
|
|
442
|
+
module = pyqir.Module.from_ir(context, qir_str)
|
|
443
|
+
llvm_module.link(module)
|
|
444
|
+
err = llvm_module.verify()
|
|
445
|
+
if err is not None:
|
|
446
|
+
raise Exception(err)
|
|
447
|
+
|
|
448
|
+
return llvm_module
|
|
449
|
+
|
|
450
|
+
def _get_qir_str(
|
|
451
|
+
self,
|
|
452
|
+
circuits: List[QuantumCircuit],
|
|
453
|
+
target_profile: TargetProfile,
|
|
454
|
+
**to_qir_kwargs,
|
|
455
|
+
) -> str:
|
|
456
|
+
module = self._generate_qir(circuits, target_profile, **to_qir_kwargs)
|
|
409
457
|
return str(module)
|
|
410
458
|
|
|
411
459
|
def _translate_input(
|
|
412
|
-
self, circuits: List[QuantumCircuit], input_params: Dict[str, Any]
|
|
460
|
+
self, circuits: Union[QuantumCircuit, List[QuantumCircuit]], input_params: Dict[str, Any]
|
|
413
461
|
) -> bytes:
|
|
414
462
|
"""Translates the input values to the QIR expected by the Backend."""
|
|
415
463
|
logger.info(f"Using QIR as the job's payload format.")
|
|
416
|
-
|
|
464
|
+
if not (isinstance(circuits, list)):
|
|
465
|
+
circuits = [circuits]
|
|
417
466
|
|
|
418
|
-
|
|
419
|
-
# We will record the output by default, but allow the backend to override this, and allow the user to override the backend.
|
|
420
|
-
to_qir_kwargs = input_params.pop(
|
|
421
|
-
"to_qir_kwargs", config.azure.get("to_qir_kwargs", {"record_output": True})
|
|
422
|
-
)
|
|
423
|
-
targetCapability = input_params.pop(
|
|
424
|
-
"targetCapability",
|
|
425
|
-
self.options.get("targetCapability", "AdaptiveExecution"),
|
|
426
|
-
)
|
|
467
|
+
target_profile = self._get_target_profile(input_params)
|
|
427
468
|
|
|
428
469
|
if logger.isEnabledFor(logging.DEBUG):
|
|
429
|
-
qir = self._get_qir_str(circuits,
|
|
470
|
+
qir = self._get_qir_str(circuits, target_profile, skip_transpilation=True)
|
|
430
471
|
logger.debug(f"QIR:\n{qir}")
|
|
431
472
|
|
|
432
473
|
# We'll transpile automatically to the supported gates in QIR unless explicitly skipped.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
474
|
+
skip_transpilation = input_params.pop("skipTranspile", False)
|
|
475
|
+
|
|
476
|
+
module = self._generate_qir(
|
|
477
|
+
circuits, target_profile, skip_transpilation=skip_transpilation
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
def get_func_name(func: pyqir.Function) -> str:
|
|
481
|
+
return func.name
|
|
482
|
+
|
|
483
|
+
entry_points = list(
|
|
484
|
+
map(get_func_name, filter(pyqir.is_entry_point, module.functions))
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
if not skip_transpilation:
|
|
438
488
|
# We'll only log the QIR again if we performed a transpilation.
|
|
439
489
|
if logger.isEnabledFor(logging.DEBUG):
|
|
440
|
-
qir =
|
|
490
|
+
qir = str(module)
|
|
441
491
|
logger.debug(f"QIR (Post-transpilation):\n{qir}")
|
|
442
492
|
|
|
443
|
-
|
|
444
|
-
circuits, targetCapability, **to_qir_kwargs
|
|
445
|
-
)
|
|
446
|
-
|
|
447
|
-
if not "items" in input_params:
|
|
493
|
+
if "items" not in input_params:
|
|
448
494
|
arguments = input_params.pop("arguments", [])
|
|
449
495
|
input_params["items"] = [
|
|
450
496
|
{"entryPoint": name, "arguments": arguments} for name in entry_points
|
|
451
497
|
]
|
|
452
498
|
|
|
453
|
-
return module.
|
|
499
|
+
return str(module).encode("utf-8")
|
|
454
500
|
|
|
455
|
-
def _estimate_cost_qir(
|
|
501
|
+
def _estimate_cost_qir(
|
|
502
|
+
self, circuits: Union[QuantumCircuit, List[QuantumCircuit]], shots, options={}
|
|
503
|
+
):
|
|
456
504
|
"""Estimate the cost for the given circuit."""
|
|
457
|
-
config = self.configuration()
|
|
458
505
|
input_params = self._get_input_params(options, shots=shots)
|
|
459
506
|
|
|
460
507
|
if not (isinstance(circuits, list)):
|
|
461
508
|
circuits = [circuits]
|
|
462
|
-
|
|
463
|
-
to_qir_kwargs = input_params.pop(
|
|
464
|
-
"to_qir_kwargs", config.azure.get("to_qir_kwargs", {"record_output": True})
|
|
465
|
-
)
|
|
466
|
-
targetCapability = input_params.pop(
|
|
467
|
-
"targetCapability",
|
|
468
|
-
self.options.get("targetCapability", "AdaptiveExecution"),
|
|
469
|
-
)
|
|
470
509
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
)
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
(module, _) = self._generate_qir(
|
|
479
|
-
circuits, targetCapability, **to_qir_kwargs
|
|
510
|
+
skip_transpilation = input_params.pop("skipTranspile", False)
|
|
511
|
+
target_profile = self._get_target_profile(input_params)
|
|
512
|
+
module = self._generate_qir(
|
|
513
|
+
circuits, target_profile, skip_transpilation=skip_transpilation
|
|
480
514
|
)
|
|
481
|
-
|
|
515
|
+
|
|
482
516
|
workspace = self.provider().get_workspace()
|
|
483
517
|
target = workspace.get_targets(self.name())
|
|
484
518
|
return target.estimate_cost(module, shots=shots)
|
|
485
519
|
|
|
520
|
+
def _get_target_profile(self, input_params) -> TargetProfile:
|
|
521
|
+
# Default to Adaptive_RI if not specified on the backend
|
|
522
|
+
# this is really just a safeguard in case the backend doesn't have a default
|
|
523
|
+
default_profile = self.options.get("target_profile", TargetProfile.Adaptive_RI)
|
|
524
|
+
|
|
525
|
+
# If the user is using the old targetCapability parameter, we'll warn them
|
|
526
|
+
# and use that value for now. This will be removed in the future.
|
|
527
|
+
if "targetCapability" in input_params:
|
|
528
|
+
warnings.warn(
|
|
529
|
+
"The 'targetCapability' parameter is deprecated and will be ignored in the future. "
|
|
530
|
+
"Please, use 'target_profile' parameter instead.",
|
|
531
|
+
category=DeprecationWarning,
|
|
532
|
+
)
|
|
533
|
+
cap = input_params.pop("targetCapability")
|
|
534
|
+
if cap == "AdaptiveExecution":
|
|
535
|
+
default_profile = TargetProfile.Adaptive_RI
|
|
536
|
+
else:
|
|
537
|
+
default_profile = TargetProfile.Base
|
|
538
|
+
# If the user specifies a target profile, use that.
|
|
539
|
+
# Otherwise, use the profile we got from the backend/targetCapability.
|
|
540
|
+
return input_params.pop("target_profile", default_profile)
|
|
541
|
+
|
|
486
542
|
|
|
487
543
|
class AzureBackend(AzureBackendBase):
|
|
488
544
|
"""Base class for interfacing with a backend in Azure Quantum"""
|
|
@@ -7,7 +7,7 @@ from azure.quantum import __version__
|
|
|
7
7
|
from azure.quantum.qiskit.job import AzureQuantumJob
|
|
8
8
|
from azure.quantum.target.ionq import IonQ
|
|
9
9
|
from abc import abstractmethod
|
|
10
|
-
|
|
10
|
+
from qsharp import TargetProfile
|
|
11
11
|
from qiskit import QuantumCircuit
|
|
12
12
|
|
|
13
13
|
from .backend import (
|
|
@@ -65,7 +65,7 @@ class IonQQirBackendBase(AzureQirBackend):
|
|
|
65
65
|
**{
|
|
66
66
|
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
67
67
|
},
|
|
68
|
-
|
|
68
|
+
target_profile=TargetProfile.Base,
|
|
69
69
|
)
|
|
70
70
|
|
|
71
71
|
def _azure_config(self) -> Dict[str, str]:
|
|
@@ -147,7 +147,7 @@ class IonQAriaQirBackend(IonQQirBackendBase):
|
|
|
147
147
|
"description": "IonQ Aria QPU on Azure Quantum",
|
|
148
148
|
"basis_gates": self._basis_gates(),
|
|
149
149
|
"memory": False,
|
|
150
|
-
"n_qubits":
|
|
150
|
+
"n_qubits": 25,
|
|
151
151
|
"conditional": False,
|
|
152
152
|
"max_shots": 10000,
|
|
153
153
|
"max_experiments": 1,
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
##
|
|
5
|
+
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Union
|
|
7
|
+
from azure.quantum.version import __version__
|
|
8
|
+
from qiskit import QuantumCircuit
|
|
9
|
+
from abc import abstractmethod
|
|
10
|
+
from .backend import AzureQirBackend, QIR_BASIS_GATES
|
|
11
|
+
|
|
12
|
+
from qiskit.providers.models import BackendConfiguration
|
|
13
|
+
from qiskit.providers import Options, Provider
|
|
14
|
+
from qsharp import TargetProfile
|
|
15
|
+
from qsharp.interop.qiskit import ResourceEstimatorBackend
|
|
16
|
+
import pyqir as pyqir
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from azure.quantum.qiskit import AzureQuantumProvider
|
|
20
|
+
|
|
21
|
+
import logging
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
__all__ = ["MicrosoftBackend", "MicrosoftResourceEstimationBackend"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class MicrosoftBackend(AzureQirBackend):
|
|
29
|
+
"""Base class for interfacing with a Microsoft backend in Azure Quantum"""
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def __init__(
|
|
33
|
+
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
34
|
+
):
|
|
35
|
+
super().__init__(configuration, provider, **fields)
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def _default_options(cls):
|
|
39
|
+
return Options(target_profile=TargetProfile.Adaptive_RI)
|
|
40
|
+
|
|
41
|
+
def _azure_config(self) -> Dict[str, str]:
|
|
42
|
+
config = super()._azure_config()
|
|
43
|
+
config.update(
|
|
44
|
+
{
|
|
45
|
+
"provider_id": "microsoft-qc",
|
|
46
|
+
"output_data_format": "microsoft.resource-estimates.v1",
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
return config
|
|
50
|
+
|
|
51
|
+
def _translate_input(
|
|
52
|
+
self,
|
|
53
|
+
circuits: Union[QuantumCircuit, List[QuantumCircuit]],
|
|
54
|
+
input_params: Dict[str, Any],
|
|
55
|
+
) -> bytes:
|
|
56
|
+
"""Translates the input values to the QIR expected by the Backend."""
|
|
57
|
+
# All the logic is in the base class, but we need to override
|
|
58
|
+
# this method to ensure that the bitcode QIR format is used for RE.
|
|
59
|
+
|
|
60
|
+
# normal translation is to QIR text format in utf-8 encoded bytes
|
|
61
|
+
ir_byte_str = super()._translate_input(circuits, input_params)
|
|
62
|
+
# decode the utf-8 encoded bytes to a string
|
|
63
|
+
ir_str = ir_byte_str.decode('utf-8')
|
|
64
|
+
# convert the QIR text format to QIR bitcode format
|
|
65
|
+
module = pyqir.Module.from_ir(pyqir.Context(), ir_str)
|
|
66
|
+
return module.bitcode
|
|
67
|
+
|
|
68
|
+
def _generate_qir(
|
|
69
|
+
self, circuits: List[QuantumCircuit], target_profile: TargetProfile, **kwargs
|
|
70
|
+
) -> pyqir.Module:
|
|
71
|
+
if len(circuits) == 0:
|
|
72
|
+
raise ValueError("No QuantumCircuits provided")
|
|
73
|
+
|
|
74
|
+
name = "circuits"
|
|
75
|
+
if isinstance(circuits, QuantumCircuit):
|
|
76
|
+
name = circuits.name
|
|
77
|
+
circuits = [circuits]
|
|
78
|
+
elif isinstance(circuits, list):
|
|
79
|
+
for value in circuits:
|
|
80
|
+
if not isinstance(value, QuantumCircuit):
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"Input must be Union[QuantumCircuit, List[QuantumCircuit]]"
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
raise ValueError(
|
|
86
|
+
"Input must be Union[QuantumCircuit, List[QuantumCircuit]]"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
skip_transpilation = kwargs.pop("skip_transpilation", False)
|
|
90
|
+
backend = ResourceEstimatorBackend(
|
|
91
|
+
skip_transpilation=skip_transpilation, **kwargs
|
|
92
|
+
)
|
|
93
|
+
context = pyqir.Context()
|
|
94
|
+
llvm_module = pyqir.qir_module(context, name)
|
|
95
|
+
for circuit in circuits:
|
|
96
|
+
qir_str = backend.qir(circuit, target_profile=target_profile)
|
|
97
|
+
module = pyqir.Module.from_ir(context, qir_str)
|
|
98
|
+
llvm_module.link(module)
|
|
99
|
+
|
|
100
|
+
# Add NOOP for recording output tuples
|
|
101
|
+
# the service isn't set up to handle any output recording calls
|
|
102
|
+
# and the Q# compiler will always emit them.
|
|
103
|
+
noop_tuple_record_output = """; NOOP the extern calls to recording output tuples
|
|
104
|
+
define void @__quantum__rt__tuple_record_output(i64, i8*) {
|
|
105
|
+
ret void
|
|
106
|
+
}"""
|
|
107
|
+
noop_tuple_record_output_module = pyqir.Module.from_ir(
|
|
108
|
+
context, noop_tuple_record_output
|
|
109
|
+
)
|
|
110
|
+
llvm_module.link(noop_tuple_record_output_module)
|
|
111
|
+
|
|
112
|
+
err = llvm_module.verify()
|
|
113
|
+
if err is not None:
|
|
114
|
+
raise Exception(err)
|
|
115
|
+
|
|
116
|
+
return llvm_module
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class MicrosoftResourceEstimationBackend(MicrosoftBackend):
|
|
120
|
+
"""Backend class for interfacing with the resource estimator target"""
|
|
121
|
+
|
|
122
|
+
backend_names = ("microsoft.estimator",)
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def _default_options(cls):
|
|
126
|
+
return Options(
|
|
127
|
+
target_profile=TargetProfile.Adaptive_RI,
|
|
128
|
+
errorBudget=1e-3,
|
|
129
|
+
qubitParams={"name": "qubit_gate_ns_e3"},
|
|
130
|
+
qecScheme={"name": "surface_code"}
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs):
|
|
134
|
+
"""Constructor for class to interface with the resource estimator target"""
|
|
135
|
+
default_config = BackendConfiguration.from_dict(
|
|
136
|
+
{
|
|
137
|
+
"backend_name": name,
|
|
138
|
+
"backend_version": __version__,
|
|
139
|
+
"simulator": True,
|
|
140
|
+
"local": False,
|
|
141
|
+
"coupling_map": None,
|
|
142
|
+
"description": "Resource estimator on Azure Quantum",
|
|
143
|
+
"basis_gates": QIR_BASIS_GATES,
|
|
144
|
+
"memory": False,
|
|
145
|
+
"n_qubits": 0xFFFFFFFFFFFFFFFF, # NOTE: maximum 64-bit unsigned value
|
|
146
|
+
"conditional": True,
|
|
147
|
+
"max_shots": 1,
|
|
148
|
+
"max_experiments": 1,
|
|
149
|
+
"open_pulse": False,
|
|
150
|
+
"gates": [
|
|
151
|
+
{"name": "TODO", "parameters": [], "qasm_def": "TODO"}
|
|
152
|
+
], # NOTE: copied from other backends
|
|
153
|
+
"azure": self._azure_config(),
|
|
154
|
+
"is_default": True,
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
logger.info("Initializing MicrosoftResourceEstimationBackend")
|
|
158
|
+
configuration: BackendConfiguration = kwargs.pop(
|
|
159
|
+
"configuration", default_config
|
|
160
|
+
)
|
|
161
|
+
super().__init__(configuration=configuration, provider=provider, **kwargs)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Licensed under the MIT License.
|
|
4
4
|
##
|
|
5
5
|
|
|
6
|
-
from typing import TYPE_CHECKING, Dict
|
|
6
|
+
from typing import TYPE_CHECKING, Dict, List
|
|
7
7
|
from azure.quantum.version import __version__
|
|
8
8
|
from azure.quantum.qiskit.job import AzureQuantumJob
|
|
9
9
|
from abc import abstractmethod
|
|
@@ -14,6 +14,8 @@ from .backend import (
|
|
|
14
14
|
|
|
15
15
|
from qiskit.providers.models import BackendConfiguration
|
|
16
16
|
from qiskit.providers import Options, Provider
|
|
17
|
+
from qsharp import TargetProfile
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
if TYPE_CHECKING:
|
|
19
21
|
from azure.quantum.qiskit import AzureQuantumProvider
|
|
@@ -43,7 +45,7 @@ class QCIBackend(AzureQirBackend):
|
|
|
43
45
|
**{
|
|
44
46
|
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
45
47
|
},
|
|
46
|
-
|
|
48
|
+
target_profile=TargetProfile.Adaptive_RI,
|
|
47
49
|
)
|
|
48
50
|
|
|
49
51
|
def _azure_config(self) -> Dict[str, str]:
|
|
@@ -54,9 +56,12 @@ class QCIBackend(AzureQirBackend):
|
|
|
54
56
|
}
|
|
55
57
|
)
|
|
56
58
|
return config
|
|
57
|
-
|
|
59
|
+
|
|
60
|
+
def _basis_gates(self) -> List[str]:
|
|
61
|
+
return super()._basis_gates() + ["barrier"]
|
|
62
|
+
|
|
58
63
|
def run(
|
|
59
|
-
self,
|
|
64
|
+
self,
|
|
60
65
|
run_input=None,
|
|
61
66
|
shots: int = None,
|
|
62
67
|
**options,
|
{azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/quantinuum.py
RENAMED
|
@@ -15,7 +15,7 @@ from qiskit.providers.models import BackendConfiguration
|
|
|
15
15
|
from qiskit.providers import Options
|
|
16
16
|
from qiskit.providers import Provider
|
|
17
17
|
from qiskit.qasm2 import dumps
|
|
18
|
-
|
|
18
|
+
from qsharp import TargetProfile
|
|
19
19
|
import logging
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger(__name__)
|
|
@@ -50,23 +50,6 @@ QUANTINUUM_BASIS_GATES = [
|
|
|
50
50
|
"reset",
|
|
51
51
|
]
|
|
52
52
|
|
|
53
|
-
QUANTINUUM_QIR_BASIS_GATES = [
|
|
54
|
-
"x",
|
|
55
|
-
"y",
|
|
56
|
-
"z",
|
|
57
|
-
"rx",
|
|
58
|
-
"ry",
|
|
59
|
-
"rz",
|
|
60
|
-
"h",
|
|
61
|
-
"cx",
|
|
62
|
-
"cz",
|
|
63
|
-
"reset",
|
|
64
|
-
"s",
|
|
65
|
-
"sdg",
|
|
66
|
-
"t",
|
|
67
|
-
"tdg",
|
|
68
|
-
"measure",
|
|
69
|
-
]
|
|
70
53
|
|
|
71
54
|
QUANTINUUM_PROVIDER_ID = "quantinuum"
|
|
72
55
|
QUANTINUUM_PROVIDER_NAME = "Quantinuum"
|
|
@@ -101,7 +84,7 @@ class QuantinuumQirBackendBase(AzureQirBackend):
|
|
|
101
84
|
**{
|
|
102
85
|
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT
|
|
103
86
|
},
|
|
104
|
-
|
|
87
|
+
target_profile=TargetProfile.Adaptive_RI,
|
|
105
88
|
)
|
|
106
89
|
|
|
107
90
|
def _azure_config(self) -> Dict[str, str]:
|
|
@@ -112,9 +95,6 @@ class QuantinuumQirBackendBase(AzureQirBackend):
|
|
|
112
95
|
}
|
|
113
96
|
)
|
|
114
97
|
return config
|
|
115
|
-
|
|
116
|
-
def _basis_gates(self) -> List[str]:
|
|
117
|
-
return QUANTINUUM_QIR_BASIS_GATES
|
|
118
98
|
|
|
119
99
|
def _get_n_qubits(self, name):
|
|
120
100
|
return _get_n_qubits(name)
|
{azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/qiskit/backends/rigetti.py
RENAMED
|
@@ -11,6 +11,7 @@ from .backend import AzureQirBackend
|
|
|
11
11
|
|
|
12
12
|
from qiskit.providers.models import BackendConfiguration
|
|
13
13
|
from qiskit.providers import Options, Provider
|
|
14
|
+
from qsharp import TargetProfile
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from azure.quantum.qiskit import AzureQuantumProvider
|
|
@@ -40,7 +41,7 @@ class RigettiBackend(AzureQirBackend):
|
|
|
40
41
|
other_options = {
|
|
41
42
|
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
42
43
|
}
|
|
43
|
-
return Options(
|
|
44
|
+
return Options(target_profile=TargetProfile.Base, **other_options)
|
|
44
45
|
|
|
45
46
|
def _azure_config(self) -> Dict[str, str]:
|
|
46
47
|
config = super()._azure_config()
|
|
@@ -212,7 +212,7 @@ class AzureQuantumJob(JobV1):
|
|
|
212
212
|
|
|
213
213
|
@staticmethod
|
|
214
214
|
def _qir_to_qiskit_bitstring(obj):
|
|
215
|
-
"""Convert the data structure from Azure into the "schema" used by Qiskit
|
|
215
|
+
"""Convert the data structure from Azure into the "schema" used by Qiskit"""
|
|
216
216
|
if isinstance(obj, str) and not re.match(r"[\d\s]+$", obj):
|
|
217
217
|
obj = ast.literal_eval(obj)
|
|
218
218
|
|
|
@@ -220,7 +220,12 @@ class AzureQuantumJob(JobV1):
|
|
|
220
220
|
# the outermost implied container is a tuple, and each item is
|
|
221
221
|
# associated with a classical register. Azure and Qiskit order the
|
|
222
222
|
# registers in opposite directions, so reverse here to match.
|
|
223
|
-
return " ".join(
|
|
223
|
+
return " ".join(
|
|
224
|
+
[
|
|
225
|
+
AzureQuantumJob._qir_to_qiskit_bitstring(term)
|
|
226
|
+
for term in obj
|
|
227
|
+
]
|
|
228
|
+
)
|
|
224
229
|
elif isinstance(obj, list):
|
|
225
230
|
# a list is for an individual classical register
|
|
226
231
|
return "".join([str(bit) for bit in obj])
|
|
@@ -59,12 +59,16 @@ class IonQ(Target):
|
|
|
59
59
|
name: str = "ionq.simulator",
|
|
60
60
|
input_data_format: str = "ionq.circuit.v1",
|
|
61
61
|
output_data_format: str = "ionq.quantum-results.v1",
|
|
62
|
-
capability: str = "
|
|
62
|
+
capability: str = "",
|
|
63
63
|
provider_id: str = "IonQ",
|
|
64
64
|
content_type: str = "application/json",
|
|
65
65
|
encoding: str = "",
|
|
66
|
-
|
|
66
|
+
target_profile: Union[str, "TargetProfile"] = "Base",
|
|
67
|
+
**kwargs,
|
|
67
68
|
):
|
|
69
|
+
if capability:
|
|
70
|
+
msg = "The 'capability' parameter is not used for the Quantinuum target."
|
|
71
|
+
warn(msg, DeprecationWarning)
|
|
68
72
|
super().__init__(
|
|
69
73
|
workspace=workspace,
|
|
70
74
|
name=name,
|
|
@@ -74,7 +78,8 @@ class IonQ(Target):
|
|
|
74
78
|
provider_id=provider_id,
|
|
75
79
|
content_type=content_type,
|
|
76
80
|
encoding=encoding,
|
|
77
|
-
|
|
81
|
+
target_profile=target_profile,
|
|
82
|
+
**kwargs,
|
|
78
83
|
)
|
|
79
84
|
|
|
80
85
|
def submit(
|
{azure-quantum-2.2.0.dev3 → azure-quantum-2.2.0.dev5}/azure/quantum/target/microsoft/target.py
RENAMED
|
@@ -392,6 +392,7 @@ class MicrosoftEstimator(Target):
|
|
|
392
392
|
output_data_format="microsoft.resource-estimates.v1",
|
|
393
393
|
provider_id="microsoft-qc",
|
|
394
394
|
content_type=ContentType.json,
|
|
395
|
+
target_profile="Adaptive_RI",
|
|
395
396
|
**kwargs
|
|
396
397
|
)
|
|
397
398
|
|
|
@@ -422,14 +423,32 @@ class MicrosoftEstimator(Target):
|
|
|
422
423
|
warnings.warn("The 'shots' parameter is ignored in resource estimation job.")
|
|
423
424
|
|
|
424
425
|
try:
|
|
425
|
-
from qiskit import QuantumCircuit
|
|
426
|
-
from
|
|
427
|
-
from
|
|
426
|
+
from qiskit import QuantumCircuit
|
|
427
|
+
from qsharp import TargetProfile
|
|
428
|
+
from qsharp.interop.qiskit import ResourceEstimatorBackend
|
|
429
|
+
from pyqir import Context, Module
|
|
430
|
+
|
|
428
431
|
if isinstance(input_data, QuantumCircuit):
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
432
|
+
backend = ResourceEstimatorBackend()
|
|
433
|
+
target_profile = TargetProfile.from_str(self.target_profile)
|
|
434
|
+
qir_str = backend.qir(input_data, target_profile=target_profile)
|
|
435
|
+
context = Context()
|
|
436
|
+
module = Module.from_ir(context, qir_str)
|
|
437
|
+
# Add NOOP for recording output tuples
|
|
438
|
+
# the service isn't set up to handle any output recording calls
|
|
439
|
+
# and the Q# compiler will always emit them.
|
|
440
|
+
noop_tuple_record_output = """; NOOP the extern calls to recording output tuples
|
|
441
|
+
define void @__quantum__rt__tuple_record_output(i64, i8*) {
|
|
442
|
+
ret void
|
|
443
|
+
}"""
|
|
444
|
+
noop_tuple_record_output_module = Module.from_ir(
|
|
445
|
+
context, noop_tuple_record_output
|
|
446
|
+
)
|
|
447
|
+
module.link(noop_tuple_record_output_module)
|
|
448
|
+
|
|
449
|
+
err = module.verify()
|
|
450
|
+
if err is not None:
|
|
451
|
+
raise Exception(err)
|
|
433
452
|
input_data = module.bitcode
|
|
434
453
|
finally:
|
|
435
454
|
return super().submit(
|