azure-quantum 3.2.0__py3-none-any.whl → 3.3.0__py3-none-any.whl
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/_client/_version.py +1 -1
- azure/quantum/job/job.py +2 -2
- azure/quantum/target/__init__.py +0 -1
- azure/quantum/version.py +1 -1
- {azure_quantum-3.2.0.dist-info → azure_quantum-3.3.0.dist-info}/METADATA +1 -1
- {azure_quantum-3.2.0.dist-info → azure_quantum-3.3.0.dist-info}/RECORD +8 -12
- azure/quantum/target/microsoft/elements/__init__.py +0 -1
- azure/quantum/target/microsoft/elements/dft/__init__.py +0 -6
- azure/quantum/target/microsoft/elements/dft/job.py +0 -171
- azure/quantum/target/microsoft/elements/dft/target.py +0 -316
- {azure_quantum-3.2.0.dist-info → azure_quantum-3.3.0.dist-info}/WHEEL +0 -0
- {azure_quantum-3.2.0.dist-info → azure_quantum-3.3.0.dist-info}/top_level.txt +0 -0
azure/quantum/job/job.py
CHANGED
|
@@ -111,7 +111,7 @@ class Job(BaseJob, FilteredJob):
|
|
|
111
111
|
Raises :class:`ValueError` if job output is malformed or output format is not compatible.
|
|
112
112
|
|
|
113
113
|
Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
|
|
114
|
-
but failure results could still be retrieved
|
|
114
|
+
but failure results could still be retrieved.
|
|
115
115
|
|
|
116
116
|
:param timeout_secs: Timeout in seconds, defaults to 300
|
|
117
117
|
:type timeout_secs: float
|
|
@@ -274,7 +274,7 @@ class Job(BaseJob, FilteredJob):
|
|
|
274
274
|
Raises :class:`ValueError` if job output is malformed or output format is not compatible.
|
|
275
275
|
|
|
276
276
|
Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
|
|
277
|
-
but failure results could still be retrieved
|
|
277
|
+
but failure results could still be retrieved.
|
|
278
278
|
|
|
279
279
|
:param timeout_secs: Timeout in seconds, defaults to 300
|
|
280
280
|
:type timeout_secs: float
|
azure/quantum/target/__init__.py
CHANGED
|
@@ -10,7 +10,6 @@ from .ionq import IonQ
|
|
|
10
10
|
from .quantinuum import Quantinuum
|
|
11
11
|
from .rigetti import Rigetti
|
|
12
12
|
from .pasqal import Pasqal
|
|
13
|
-
from .microsoft.elements.dft import MicrosoftElementsDft, MicrosoftElementsDftJob
|
|
14
13
|
|
|
15
14
|
# Default targets to use when there is no target class
|
|
16
15
|
# associated with a given target ID
|
azure/quantum/version.py
CHANGED
|
@@ -2,7 +2,7 @@ azure/quantum/__init__.py,sha256=Za8xZY4lzFkW8m4ero-bqrfN437D2NRukM77ukb4GPM,508
|
|
|
2
2
|
azure/quantum/_constants.py,sha256=nDL_QrGdI_Zz_cvTB9nVgfE7J6A_Boo1ollMYqsiEBs,3499
|
|
3
3
|
azure/quantum/_workspace_connection_params.py,sha256=KoT90U89Dj6pVwAKp_ENJL1hyTF0oQe7w0QioOGvjXg,21685
|
|
4
4
|
azure/quantum/storage.py,sha256=_4bMniDk9LrB_K5CQwuCivJFZXdmhRvU2b6Z3xxXw9I,12556
|
|
5
|
-
azure/quantum/version.py,sha256=
|
|
5
|
+
azure/quantum/version.py,sha256=yFZaZzIK6r33ln03-vVtefApA1zWBz3pvQF1jin-hgk,235
|
|
6
6
|
azure/quantum/workspace.py,sha256=9oO4vjwIn1pdHFLZCQcEPQ_xjQjTNO4UIWSBQpj6Cgo,35574
|
|
7
7
|
azure/quantum/_authentication/__init__.py,sha256=bniNZlS0hMIjO_y7DevGBAS6MixyA5pbPHcdGipUWM4,236
|
|
8
8
|
azure/quantum/_authentication/_chained.py,sha256=0rdohB_fVGFHUhlly9sGxqQTBTZGpGxtlBqNHDFbAqE,4848
|
|
@@ -14,7 +14,7 @@ azure/quantum/_client/_configuration.py,sha256=FFUHJPp6X0015GpD-YLmYCoq8GI86nHCn
|
|
|
14
14
|
azure/quantum/_client/_model_base.py,sha256=hu7OdRS2Ra1igfBo-R3zS3dzO3YhFC4FGHJ_WiyZgNg,43736
|
|
15
15
|
azure/quantum/_client/_patch.py,sha256=YTV6yZ9bRfBBaw2z7v4MdzR-zeHkdtKkGb4SU8C25mE,694
|
|
16
16
|
azure/quantum/_client/_serialization.py,sha256=bBl0y0mh-0sDd-Z8_dj921jQQhqhYWTOl59qSLuk01M,86686
|
|
17
|
-
azure/quantum/_client/_version.py,sha256=
|
|
17
|
+
azure/quantum/_client/_version.py,sha256=lVYNMqxgvpsfmcBW1y_FXP__aNVaVme9UgQv-jHbWdM,495
|
|
18
18
|
azure/quantum/_client/py.typed,sha256=dcrsqJrcYfTX-ckLFJMTaj6mD8aDe2u0tkQG-ZYxnEg,26
|
|
19
19
|
azure/quantum/_client/models/__init__.py,sha256=MR2av7s_tCP66hicN9JXCmTngJ4_-ozM4cmblGjPwn8,1971
|
|
20
20
|
azure/quantum/_client/models/_enums.py,sha256=RNCPXxeae4d7wtPqcSxu5JZBLFLZZYVZbALjui_f1fM,4288
|
|
@@ -35,7 +35,7 @@ azure/quantum/cirq/targets/target.py,sha256=1EEog72dFZoiOTQP7obOrCuO3VH0yjXGAIMe
|
|
|
35
35
|
azure/quantum/job/__init__.py,sha256=nFuOsG25a8WzYFLwA2fhA0JMNWtblfDjV5WRgB6UQbw,829
|
|
36
36
|
azure/quantum/job/base_job.py,sha256=GDwoJDxoaCwGz9TBuzlkuqXdU84L6FliO_2YWxnLnrE,14399
|
|
37
37
|
azure/quantum/job/filtered_job.py,sha256=qZfxTuDp0hzK4wermn4GRzLxnDy4yM-j6oZQ3D0O4vI,1877
|
|
38
|
-
azure/quantum/job/job.py,sha256=
|
|
38
|
+
azure/quantum/job/job.py,sha256=uMn0ET7DX9EUwN8xerZzm8MflbvbU1NOGM1uCvh8c-g,17607
|
|
39
39
|
azure/quantum/job/job_failed_with_results_error.py,sha256=bSqOZ0c6FNbS9opvwkCXG9mfTkAiyZRvp_YA3V-ktEs,1597
|
|
40
40
|
azure/quantum/job/session.py,sha256=EEJVKEEB5g0yyH963aaR0GY0Cd0axrX-49gwDWxBcfE,11961
|
|
41
41
|
azure/quantum/job/workspace_item.py,sha256=lyBIJCtUfIZMGJYJkX7Se8IDnXhXe4JU0RnqzSuhhI4,1380
|
|
@@ -49,23 +49,19 @@ azure/quantum/qiskit/backends/ionq.py,sha256=exXdWL63CxlIIiK4bfSFpJCKXzJgjLKz5OL
|
|
|
49
49
|
azure/quantum/qiskit/backends/qci.py,sha256=c0YK-znG8TSAnFmeszo7mpKhM624QHszTQoapOqOvHg,4794
|
|
50
50
|
azure/quantum/qiskit/backends/quantinuum.py,sha256=1ThH4mmk4CUG-2RTvwsFEXQ3TEvHPJnW7Lo6QYpC3QE,12705
|
|
51
51
|
azure/quantum/qiskit/backends/rigetti.py,sha256=lTsa0UjPdsAZUvvfnBge7H22TvA7c-_3fU09ZTA4ARs,4146
|
|
52
|
-
azure/quantum/target/__init__.py,sha256=
|
|
52
|
+
azure/quantum/target/__init__.py,sha256=hK4OqAOkgwO8W52YvPp6QeoMTFj_eum3iexMmpCMEsI,606
|
|
53
53
|
azure/quantum/target/ionq.py,sha256=2iS4H-fBJYRTCM7VJse3Hqya_y2iEuU5QBG3Oj4c-SU,3931
|
|
54
54
|
azure/quantum/target/params.py,sha256=Txpq_AKdVV8OeZjK1z48CIym--_a6wncorj4LmmlQ_E,9128
|
|
55
55
|
azure/quantum/target/quantinuum.py,sha256=5xvYb0Q2KSQr6FJ_A1bc2904Gz6NF_Xmn8UJ79NMOZU,3306
|
|
56
56
|
azure/quantum/target/target.py,sha256=jmB4mU32rQIViJ_Zq5qYh-ktLr9vv_vz-sKpvR8GY-M,16658
|
|
57
57
|
azure/quantum/target/target_factory.py,sha256=jjZ9zxWaNDkcvslKV02GSP8rtXwStJ7EmVXQSOFh_j8,5266
|
|
58
|
-
azure/quantum/target/microsoft/elements/__init__.py,sha256=gVVpaN5086iuBnajtvTjSd7MLExtnsR6RDCmcgz6xpE,70
|
|
59
|
-
azure/quantum/target/microsoft/elements/dft/__init__.py,sha256=kCXOA9HT-gb23An-A0eyktlB66VoH6EwNO4gPM97l3U,224
|
|
60
|
-
azure/quantum/target/microsoft/elements/dft/job.py,sha256=6v7lZwXyUGrOI8J17akanMrFXrPVDhsZR3c6AFpa5So,6942
|
|
61
|
-
azure/quantum/target/microsoft/elements/dft/target.py,sha256=10el-q7QO3k19sytnoBfRaMzd5H2RvGHqm4N5IZfcjQ,12826
|
|
62
58
|
azure/quantum/target/pasqal/__init__.py,sha256=qbe6oWTQTsnTYwY3xZr32z4AWaYIchx71bYlqC2rQqw,348
|
|
63
59
|
azure/quantum/target/pasqal/result.py,sha256=SUvpnrtgvCGiepmNpyifW8b4p14-SZZ1ToCC0NAdIwg,1463
|
|
64
60
|
azure/quantum/target/pasqal/target.py,sha256=K_vqavov6gvS84voRKeBx9pO8g4LrtWrlZ5-RMLWozw,5139
|
|
65
61
|
azure/quantum/target/rigetti/__init__.py,sha256=I1vyzZBYGI540pauTqJd0RSSyTShGqkEL7Yjo25_RNY,378
|
|
66
62
|
azure/quantum/target/rigetti/result.py,sha256=65mtAZxfdNrTWNjWPqgfwt2BZN6Nllo4g_bls7-Nm68,2334
|
|
67
63
|
azure/quantum/target/rigetti/target.py,sha256=HFrng9SigibPn_2KWhD5qWHiP_RNz3CNRkv288tf-z8,7586
|
|
68
|
-
azure_quantum-3.
|
|
69
|
-
azure_quantum-3.
|
|
70
|
-
azure_quantum-3.
|
|
71
|
-
azure_quantum-3.
|
|
64
|
+
azure_quantum-3.3.0.dist-info/METADATA,sha256=GrqD7EGCoJapqc_YNzvK_Ng8_37VeRXD_i59TBZM2v4,7359
|
|
65
|
+
azure_quantum-3.3.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
66
|
+
azure_quantum-3.3.0.dist-info/top_level.txt,sha256=S7DhWV9m80TBzAhOFjxDUiNbKszzoThbnrSz5MpbHSQ,6
|
|
67
|
+
azure_quantum-3.3.0.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""Defines classes for interacting with Microsoft Elements services"""
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import collections.abc
|
|
2
|
-
import logging
|
|
3
|
-
from typing import Any, Dict, Union, Optional
|
|
4
|
-
from azure.quantum.job import JobFailedWithResultsError
|
|
5
|
-
from azure.quantum.job.base_job import BaseJob, ContentType
|
|
6
|
-
from azure.quantum.job.job import Job, DEFAULT_TIMEOUT
|
|
7
|
-
from azure.quantum._client.models import JobDetails
|
|
8
|
-
from azure.quantum.workspace import Workspace
|
|
9
|
-
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
class MicrosoftElementsDftJob(Job):
|
|
13
|
-
"""
|
|
14
|
-
A dedicated job class for jobs from the microsoft.dft target.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
def __init__(self, workspace, job_details: JobDetails, **kwargs):
|
|
18
|
-
"""Azure Quantum Job that is submitted to a given Workspace.
|
|
19
|
-
|
|
20
|
-
:param workspace: Workspace instance to submit job to
|
|
21
|
-
:type workspace: Workspace
|
|
22
|
-
:param job_details: Job details model,
|
|
23
|
-
contains Job ID, name and other details
|
|
24
|
-
:type job_details: JobDetails
|
|
25
|
-
"""
|
|
26
|
-
super().__init__(workspace, job_details, **kwargs)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def get_results(self, timeout_secs: float = DEFAULT_TIMEOUT) -> Dict[str, Any]:
|
|
30
|
-
"""Get job results by downloading the results blob from the
|
|
31
|
-
storage container linked via the workspace.
|
|
32
|
-
|
|
33
|
-
:param timeout_secs: Timeout in seconds, defaults to 300
|
|
34
|
-
:type timeout_secs: float
|
|
35
|
-
:raises: :class:`RuntimeError` if job execution failed.
|
|
36
|
-
:raises: :class:`azure.quantum.job.JobFailedWithResultsError` if job execution failed,
|
|
37
|
-
but failure results could still be retrieved.
|
|
38
|
-
:return: Results dictionary.
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
try:
|
|
42
|
-
job_results = super().get_results(timeout_secs)
|
|
43
|
-
return job_results
|
|
44
|
-
except JobFailedWithResultsError as e:
|
|
45
|
-
failure_results = e.get_failure_results()
|
|
46
|
-
if MicrosoftElementsDftJob._is_dft_failure_results(failure_results):
|
|
47
|
-
error = failure_results["results"][0]["error"]
|
|
48
|
-
message = f'{e.get_message()} Error type: {error["error_type"]}. Message: {error["error_message"]}'
|
|
49
|
-
raise JobFailedWithResultsError(message, failure_results) from None
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@classmethod
|
|
53
|
-
def _allow_failure_results(cls) -> bool:
|
|
54
|
-
"""
|
|
55
|
-
Allow to download job results even if the Job status is "Failed".
|
|
56
|
-
"""
|
|
57
|
-
return True
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@staticmethod
|
|
61
|
-
def _is_dft_failure_results(failure_results: Union[Dict[str, Any], str]) -> bool:
|
|
62
|
-
return isinstance(failure_results, dict) \
|
|
63
|
-
and "results" in failure_results \
|
|
64
|
-
and isinstance(failure_results["results"], collections.abc.Sequence) \
|
|
65
|
-
and len(failure_results["results"]) > 0 \
|
|
66
|
-
and isinstance(failure_results["results"][0], dict) \
|
|
67
|
-
and "error" in failure_results["results"][0] \
|
|
68
|
-
and isinstance(failure_results["results"][0]["error"], dict) \
|
|
69
|
-
and "error_type" in failure_results["results"][0]["error"] \
|
|
70
|
-
and "error_message" in failure_results["results"][0]["error"]
|
|
71
|
-
|
|
72
|
-
@classmethod
|
|
73
|
-
def from_input_data_container(
|
|
74
|
-
cls,
|
|
75
|
-
workspace: "Workspace",
|
|
76
|
-
name: str,
|
|
77
|
-
target: str,
|
|
78
|
-
input_data: bytes,
|
|
79
|
-
batch_input_blobs: Dict[str, bytes],
|
|
80
|
-
content_type: ContentType = ContentType.json,
|
|
81
|
-
blob_name: str = "inputData",
|
|
82
|
-
encoding: str = "",
|
|
83
|
-
job_id: str = None,
|
|
84
|
-
container_name: str = None,
|
|
85
|
-
provider_id: str = None,
|
|
86
|
-
input_data_format: str = None,
|
|
87
|
-
output_data_format: str = None,
|
|
88
|
-
input_params: Dict[str, Any] = None,
|
|
89
|
-
session_id: Optional[str] = None,
|
|
90
|
-
**kwargs
|
|
91
|
-
) -> "BaseJob":
|
|
92
|
-
"""Create a new Azure Quantum job based on a list of input_data.
|
|
93
|
-
|
|
94
|
-
:param workspace: Azure Quantum workspace to submit the input_data to
|
|
95
|
-
:type workspace: Workspace
|
|
96
|
-
:param name: Name of the job
|
|
97
|
-
:type name: str
|
|
98
|
-
:param target: Azure Quantum target
|
|
99
|
-
:type target: str
|
|
100
|
-
:param input_data: Raw input data to submit
|
|
101
|
-
:type input_data: Dict
|
|
102
|
-
:param blob_name: Dict of Input data json to gives a table of contents
|
|
103
|
-
:type batch_input_blobs: Dict
|
|
104
|
-
:param blob_name: Dict of QcSchema Data where the key is the blob name to store it in the container
|
|
105
|
-
:type blob_name: str
|
|
106
|
-
:param content_type: Content type, e.g. "application/json"
|
|
107
|
-
:type content_type: ContentType
|
|
108
|
-
:param encoding: input_data encoding, e.g. "gzip", defaults to empty string
|
|
109
|
-
:type encoding: str
|
|
110
|
-
:param job_id: Job ID, defaults to None
|
|
111
|
-
:type job_id: str
|
|
112
|
-
:param container_name: Container name, defaults to None
|
|
113
|
-
:type container_name: str
|
|
114
|
-
:param provider_id: Provider ID, defaults to None
|
|
115
|
-
:type provider_id: str
|
|
116
|
-
:param input_data_format: Input data format, defaults to None
|
|
117
|
-
:type input_data_format: str
|
|
118
|
-
:param output_data_format: Output data format, defaults to None
|
|
119
|
-
:type output_data_format: str
|
|
120
|
-
:param input_params: Input parameters, defaults to None
|
|
121
|
-
:type input_params: Dict[str, Any]
|
|
122
|
-
:param input_params: Input params for job
|
|
123
|
-
:type input_params: Dict[str, Any]
|
|
124
|
-
:return: Azure Quantum Job
|
|
125
|
-
:rtype: Job
|
|
126
|
-
"""
|
|
127
|
-
# Generate job ID if not specified
|
|
128
|
-
if job_id is None:
|
|
129
|
-
job_id = cls.create_job_id()
|
|
130
|
-
|
|
131
|
-
# Create container if it does not yet exist
|
|
132
|
-
container_uri = workspace.get_container_uri(
|
|
133
|
-
job_id=job_id,
|
|
134
|
-
container_name=container_name
|
|
135
|
-
)
|
|
136
|
-
logger.debug(f"Container URI: {container_uri}")
|
|
137
|
-
|
|
138
|
-
# Upload Input Data
|
|
139
|
-
input_data_uri = cls.upload_input_data(
|
|
140
|
-
container_uri=container_uri,
|
|
141
|
-
input_data=input_data,
|
|
142
|
-
content_type=content_type,
|
|
143
|
-
blob_name=blob_name,
|
|
144
|
-
encoding=encoding,
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
# Upload data to container
|
|
148
|
-
for blob_name, input_data_item in batch_input_blobs.items():
|
|
149
|
-
cls.upload_input_data(
|
|
150
|
-
container_uri=container_uri,
|
|
151
|
-
input_data=input_data_item,
|
|
152
|
-
content_type=content_type,
|
|
153
|
-
blob_name=blob_name,
|
|
154
|
-
encoding=encoding,
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
# Create and submit job
|
|
158
|
-
return cls.from_storage_uri(
|
|
159
|
-
workspace=workspace,
|
|
160
|
-
job_id=job_id,
|
|
161
|
-
target=target,
|
|
162
|
-
input_data_uri=input_data_uri,
|
|
163
|
-
container_uri=container_uri,
|
|
164
|
-
name=name,
|
|
165
|
-
input_data_format=input_data_format,
|
|
166
|
-
output_data_format=output_data_format,
|
|
167
|
-
provider_id=provider_id,
|
|
168
|
-
input_params=input_params,
|
|
169
|
-
session_id=session_id,
|
|
170
|
-
**kwargs
|
|
171
|
-
)
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import warnings
|
|
2
|
-
|
|
3
|
-
from azure.quantum.job.base_job import ContentType
|
|
4
|
-
from azure.quantum.job.job import Job
|
|
5
|
-
from azure.quantum.target.target import Target
|
|
6
|
-
from azure.quantum.workspace import Workspace
|
|
7
|
-
from azure.quantum.target.params import InputParams
|
|
8
|
-
from typing import Any, Dict, Type, Union, List
|
|
9
|
-
from .job import MicrosoftElementsDftJob
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
import copy
|
|
12
|
-
import json
|
|
13
|
-
from collections import defaultdict
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class MicrosoftElementsDft(Target):
|
|
17
|
-
"""
|
|
18
|
-
Microsoft Elements Dft target from the microsoft-elements provider.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
target_names = [
|
|
22
|
-
"microsoft.dft"
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
workspace: "Workspace",
|
|
29
|
-
name: str = "microsoft.dft",
|
|
30
|
-
**kwargs
|
|
31
|
-
):
|
|
32
|
-
"""
|
|
33
|
-
Initializes a new DFT target.
|
|
34
|
-
|
|
35
|
-
:param workspace: Associated workspace
|
|
36
|
-
:type workspace: Workspace
|
|
37
|
-
:param name: Target name
|
|
38
|
-
"""
|
|
39
|
-
# There is only a single target name for this target
|
|
40
|
-
assert name == self.target_names[0]
|
|
41
|
-
|
|
42
|
-
# make sure to not pass argument twice
|
|
43
|
-
kwargs.pop("provider_id", None)
|
|
44
|
-
|
|
45
|
-
super().__init__(
|
|
46
|
-
workspace=workspace,
|
|
47
|
-
name=name,
|
|
48
|
-
input_data_format="microsoft.xyz.v1",
|
|
49
|
-
output_data_format="microsoft.dft-results.v1",
|
|
50
|
-
provider_id="microsoft-elements",
|
|
51
|
-
content_type=ContentType.text_plain,
|
|
52
|
-
**kwargs
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def submit(self,
|
|
57
|
-
input_data: Any,
|
|
58
|
-
name: str = "azure-quantum-dft-job",
|
|
59
|
-
shots: int = None,
|
|
60
|
-
input_params: Union[Dict[str, Any], InputParams, None] = None,
|
|
61
|
-
**kwargs) -> MicrosoftElementsDftJob:
|
|
62
|
-
"""
|
|
63
|
-
Submit DFT job to Azure Quantum Services.
|
|
64
|
-
|
|
65
|
-
:param input_data: Input data
|
|
66
|
-
:type input_data: Any
|
|
67
|
-
:param name: Job name
|
|
68
|
-
:type name: str
|
|
69
|
-
:param shots: Number of shots. Ignored in DFT job. Defaults to None
|
|
70
|
-
:type shots: int
|
|
71
|
-
:param input_params: Input parameters
|
|
72
|
-
:type input_params: Dict[str, Any]
|
|
73
|
-
:return: Azure Quantum job
|
|
74
|
-
:rtype: Job
|
|
75
|
-
"""
|
|
76
|
-
|
|
77
|
-
if shots is not None:
|
|
78
|
-
warnings.warn("The 'shots' parameter is ignored in Microsoft Elements Dft job.")
|
|
79
|
-
|
|
80
|
-
if isinstance(input_data, list):
|
|
81
|
-
|
|
82
|
-
if len(input_data) < 1:
|
|
83
|
-
raise ValueError("Input data list has no elements.")
|
|
84
|
-
|
|
85
|
-
if all(isinstance(task,str) for task in input_data):
|
|
86
|
-
qcschema_data = self.assemble_qcschema_from_files(input_data, input_params)
|
|
87
|
-
|
|
88
|
-
qcschema_blobs = {}
|
|
89
|
-
for i in range(len(qcschema_data)):
|
|
90
|
-
qcschema_blobs[f"inputData_{i}"] = self._encode_input_data(qcschema_data[i])
|
|
91
|
-
|
|
92
|
-
toc_str = self._create_table_of_contents(input_data, list(qcschema_blobs.keys()))
|
|
93
|
-
elif all(isinstance(task,dict) for task in input_data):
|
|
94
|
-
qcschema_blobs = {}
|
|
95
|
-
for i in range(len(input_data)):
|
|
96
|
-
qcschema_blobs[f"inputData_{i}"] = self._encode_input_data(input_data[i])
|
|
97
|
-
toc_str = '{"description": "QcSchema Objects were given for input."}'
|
|
98
|
-
else:
|
|
99
|
-
raise ValueError(f"Unsupported batch submission. Please use List[str] or List[dict].")
|
|
100
|
-
toc = self._encode_input_data(toc_str)
|
|
101
|
-
|
|
102
|
-
input_params = {} if input_params is None else input_params
|
|
103
|
-
return self._get_job_class().from_input_data_container(
|
|
104
|
-
workspace=self.workspace,
|
|
105
|
-
name=name,
|
|
106
|
-
target=self.name,
|
|
107
|
-
input_data=toc,
|
|
108
|
-
batch_input_blobs=qcschema_blobs,
|
|
109
|
-
input_params={ 'numberOfFiles': len(input_data), "inputFiles": list(qcschema_blobs.keys()), **input_params },
|
|
110
|
-
content_type=kwargs.pop('content_type', self.content_type),
|
|
111
|
-
encoding=kwargs.pop('encoding', self.encoding),
|
|
112
|
-
provider_id=self.provider_id,
|
|
113
|
-
input_data_format=kwargs.pop('input_data_format', 'microsoft.qc-schema.v1'),
|
|
114
|
-
output_data_format=kwargs.pop('output_data_format', self.output_data_format),
|
|
115
|
-
session_id=self.get_latest_session_id(),
|
|
116
|
-
**kwargs
|
|
117
|
-
)
|
|
118
|
-
else:
|
|
119
|
-
return super().submit(
|
|
120
|
-
input_data=input_data,
|
|
121
|
-
name=name,
|
|
122
|
-
shots=shots,
|
|
123
|
-
input_params=input_params,
|
|
124
|
-
**kwargs
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
@classmethod
|
|
130
|
-
def assemble_qcschema_from_files(self, input_data: Union[List[str]], input_params: Dict) -> List[Dict]:
|
|
131
|
-
"""
|
|
132
|
-
Convert a list of files to a list of QcSchema objects that are ready for submission.
|
|
133
|
-
|
|
134
|
-
:param input_data: Input data
|
|
135
|
-
:type input_data: List[str]
|
|
136
|
-
:param input_params: Input parameters
|
|
137
|
-
:type input_params: Dict[str, Any]
|
|
138
|
-
:rtype: List[Dict]
|
|
139
|
-
"""
|
|
140
|
-
|
|
141
|
-
self._check_file_paths(input_data)
|
|
142
|
-
|
|
143
|
-
qcshema_objects = []
|
|
144
|
-
for file in input_data:
|
|
145
|
-
file_path = Path(file)
|
|
146
|
-
|
|
147
|
-
file_data = file_path.read_text()
|
|
148
|
-
if file_path.suffix == '.xyz':
|
|
149
|
-
mol = self._xyz_to_qcschema_mol(file_data)
|
|
150
|
-
new_qcschema = self._new_qcshema( input_params, mol )
|
|
151
|
-
qcshema_objects.append(new_qcschema)
|
|
152
|
-
elif file_path.suffix == '.json':
|
|
153
|
-
if input_params is not None and len(input_params.keys()) > 0:
|
|
154
|
-
warnings.warn('Input parameters were given along with a QcSchema file which contains parameters, using QcSchema parameters as is.')
|
|
155
|
-
with open(file_path, 'r') as f:
|
|
156
|
-
qcshema_objects.append( json.load(f) )
|
|
157
|
-
else:
|
|
158
|
-
raise ValueError(f"File type '{file_path.suffix}' for file '{file_path}' is not supported.")
|
|
159
|
-
|
|
160
|
-
return qcshema_objects
|
|
161
|
-
|
|
162
|
-
@classmethod
|
|
163
|
-
def _check_file_paths( self, input_data: List[str]):
|
|
164
|
-
"""Check the file types and make sure they are supported by our parsers."""
|
|
165
|
-
|
|
166
|
-
warn_task_count = 1000
|
|
167
|
-
if len(input_data) >= warn_task_count:
|
|
168
|
-
warnings.warn(f'Number of tasks is greater than {warn_task_count}.')
|
|
169
|
-
|
|
170
|
-
supported_ext = ['.xyz', '.json']
|
|
171
|
-
prev_ext = None
|
|
172
|
-
for path_str in input_data:
|
|
173
|
-
path = Path(path_str)
|
|
174
|
-
|
|
175
|
-
if not path.exists():
|
|
176
|
-
raise FileNotFoundError(f"File {path_str} does not exist.")
|
|
177
|
-
|
|
178
|
-
if path.suffix not in supported_ext:
|
|
179
|
-
raise ValueError(f"'{path.suffix}' file type is not supported. Please use one of {supported_ext}.")
|
|
180
|
-
|
|
181
|
-
if prev_ext is not None and prev_ext != path.suffix:
|
|
182
|
-
raise ValueError(f"Multiple file types were provided ('{path.suffix}', '{prev_ext}'). Please submit only one file type.")
|
|
183
|
-
else:
|
|
184
|
-
prev_ext = path.suffix
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
@classmethod
|
|
188
|
-
def _new_qcshema( self, input_params: Dict[str,Any], mol: Dict[str,Any], ) -> Dict[str, Any]:
|
|
189
|
-
"""
|
|
190
|
-
Create a new default qcshema object.
|
|
191
|
-
"""
|
|
192
|
-
|
|
193
|
-
self._sanity_check_params(input_params, mol)
|
|
194
|
-
|
|
195
|
-
if input_params.get("driver").lower() == "go":
|
|
196
|
-
copy_input_params = copy.deepcopy(input_params)
|
|
197
|
-
copy_input_params["driver"] = "gradient"
|
|
198
|
-
new_object = {
|
|
199
|
-
"schema_name": "qcschema_optimization_input",
|
|
200
|
-
"schema_version": 1,
|
|
201
|
-
"initial_molecule": mol,
|
|
202
|
-
}
|
|
203
|
-
if copy_input_params.get("go_keywords"):
|
|
204
|
-
new_object["keywords"] = copy_input_params.pop("go_keywords")
|
|
205
|
-
new_object["input_specification"] = copy_input_params
|
|
206
|
-
return new_object
|
|
207
|
-
elif input_params.get("driver").lower() == "bomd":
|
|
208
|
-
copy_input_params = copy.deepcopy(input_params)
|
|
209
|
-
copy_input_params["driver"] = "gradient"
|
|
210
|
-
new_object = {
|
|
211
|
-
"schema_name": "madft_molecular_dynamics_input",
|
|
212
|
-
"schema_version": 1,
|
|
213
|
-
"initial_molecule": mol,
|
|
214
|
-
}
|
|
215
|
-
if copy_input_params.get("bomd_keywords"):
|
|
216
|
-
new_object["keywords"] = copy_input_params.pop("bomd_keywords")
|
|
217
|
-
new_object["input_specification"] = copy_input_params
|
|
218
|
-
return new_object
|
|
219
|
-
else:
|
|
220
|
-
new_object = copy.deepcopy(input_params)
|
|
221
|
-
new_object.update({
|
|
222
|
-
"schema_name": "qcschema_input",
|
|
223
|
-
"schema_version": 1,
|
|
224
|
-
"molecule": mol,
|
|
225
|
-
})
|
|
226
|
-
return new_object
|
|
227
|
-
|
|
228
|
-
@classmethod
|
|
229
|
-
def _sanity_check_params(self, input_params, mol):
|
|
230
|
-
|
|
231
|
-
# QM/MM is not supported for GO, BOMD and Hessian.
|
|
232
|
-
driver = input_params.get("driver",'').lower()
|
|
233
|
-
if driver in ["go", "bomd", "hessian"]:
|
|
234
|
-
if "extras" in mol and "mm_charges" in mol["extras"]:
|
|
235
|
-
raise ValueError(f"'{driver}' does not support QM/MM.")
|
|
236
|
-
|
|
237
|
-
# Top level params
|
|
238
|
-
self._check_dict_for_required_keys(input_params, 'input_params', ['driver', 'model'])
|
|
239
|
-
|
|
240
|
-
# Check Model params
|
|
241
|
-
self._check_dict_for_required_keys(input_params['model'], 'input_params["model"]', ['method', 'basis'])
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
@classmethod
|
|
245
|
-
def _check_dict_for_required_keys(self, input_params: dict, dict_name: str, required_keys: list[str]):
|
|
246
|
-
"""Check dictionary for required keys and if it doesn't have then raise ValueError."""
|
|
247
|
-
|
|
248
|
-
for required_key in required_keys:
|
|
249
|
-
if required_key not in input_params.keys():
|
|
250
|
-
raise ValueError(f"Required key ({required_key}) was not provided in {dict_name}.")
|
|
251
|
-
|
|
252
|
-
@classmethod
|
|
253
|
-
def _xyz_to_qcschema_mol(self, file_data: str ) -> Dict[str, Any]:
|
|
254
|
-
"""
|
|
255
|
-
Convert xyz format to qcschema molecule.
|
|
256
|
-
"""
|
|
257
|
-
|
|
258
|
-
lines = file_data.split("\n")
|
|
259
|
-
if len(lines) < 3 or not lines[0]:
|
|
260
|
-
raise ValueError("Invalid xyz format.")
|
|
261
|
-
n_atoms = int(lines.pop(0))
|
|
262
|
-
comment = lines.pop(0)
|
|
263
|
-
mol = defaultdict(list)
|
|
264
|
-
mol['extras'] = defaultdict(list)
|
|
265
|
-
bohr_to_angstrom = 0.52917721092
|
|
266
|
-
for line in lines:
|
|
267
|
-
if line:
|
|
268
|
-
elements = line.split()
|
|
269
|
-
if len(elements) == 4:
|
|
270
|
-
symbol, x, y, z = elements
|
|
271
|
-
mol["symbols"].append(symbol)
|
|
272
|
-
mol["geometry"] += [float(x)/bohr_to_angstrom, float(y)/bohr_to_angstrom, float(z)/bohr_to_angstrom]
|
|
273
|
-
elif len(elements) == 5:
|
|
274
|
-
symbol, x, y, z, q = elements
|
|
275
|
-
if symbol[0] != '-':
|
|
276
|
-
raise ValueError("Invalid xyz format. Molecular Mechanics atoms requires '-' at the beginning of the atom type.")
|
|
277
|
-
mol["extras"]["mm_symbols"].append(symbol.replace('-', ''))
|
|
278
|
-
mol["extras"]["mm_geometry"] += [float(x)/bohr_to_angstrom, float(y)/bohr_to_angstrom, float(z)/bohr_to_angstrom]
|
|
279
|
-
mol["extras"]["mm_charges"].append(float(q))
|
|
280
|
-
else:
|
|
281
|
-
raise ValueError("Invalid xyz format.")
|
|
282
|
-
else:
|
|
283
|
-
break
|
|
284
|
-
|
|
285
|
-
# Convert defaultdict to dict
|
|
286
|
-
mol = dict(mol)
|
|
287
|
-
mol["extras"] = dict(mol["extras"])
|
|
288
|
-
|
|
289
|
-
if len(mol["symbols"])+len(mol["extras"].get("mm_symbols",[])) != n_atoms:
|
|
290
|
-
raise ValueError("Number of inputs does not match the number of atoms in xyz file.")
|
|
291
|
-
|
|
292
|
-
return mol
|
|
293
|
-
|
|
294
|
-
@classmethod
|
|
295
|
-
def _get_job_class(cls) -> Type[Job]:
|
|
296
|
-
return MicrosoftElementsDftJob
|
|
297
|
-
|
|
298
|
-
@classmethod
|
|
299
|
-
def _create_table_of_contents(cls, input_files: List[str], input_blobs: List[str]) -> Dict[str,Any]:
|
|
300
|
-
"""Create the table of contents for a batched job that contains a description of file and the mapping between the file names and the blob names"""
|
|
301
|
-
|
|
302
|
-
assert len(input_files) == len(input_blobs), "Internal error: number of blobs is not that same as the number of files."
|
|
303
|
-
|
|
304
|
-
toc = []
|
|
305
|
-
for i in range(len(input_files)):
|
|
306
|
-
toc.append(
|
|
307
|
-
{
|
|
308
|
-
"inputFileName": input_files[i],
|
|
309
|
-
"qcschemaBlobName": input_blobs[i],
|
|
310
|
-
}
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
"description": "This files contains the mapping between the xyz file name that were submitted and the qcschema blobs that are used for the calculation.",
|
|
315
|
-
"tableOfContents": toc,
|
|
316
|
-
}
|
|
File without changes
|
|
File without changes
|