Skip to content

Commit e4f1ac1

Browse files
authored
Quantum: Various bug fixes for Azure Quantum (#9253)
* Fix various bugs in azure cli * Remove unnecessary string * Fix tests and obfuscate more headers * Update release log and version * Fix linter error * Fix job submission * Update release version to suggested version in PR * Fix missing help * Add one more release note
1 parent 551d6d0 commit e4f1ac1

33 files changed

+2695
-2247
lines changed

src/quantum/HISTORY.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@
33
Release History
44
===============
55

6+
1.0.0b10
7+
++++++
8+
* Fixed broken dependency on blob_data_service_factory and replaced with vendored_sdk for azure_storage_blob
9+
* Fixed bug where workspace params were being ignored during job submission if workspace was not set as default
10+
* Fixed bug where job submission asked for interactive authentication instead of using azure cli credentials
11+
* Removed QIO and ADFT features, since those are no longer supported for Azure Quantum service and have both been deprecated
12+
* During job submit, updated default shots to 100
13+
* During job submit, updated default format to microsoft.quantum-results.v2
14+
* During job submit, removed requirement for entrypoint, since most modern providers no longer require the entrypoint field
15+
* During job submit, simplify logic for content_type and default to qir.v1 for QIR jobs and text/plain for others
16+
* During job output -o table, added support for fields from new microsoft.quantum-results.v2 format
17+
* During workspace create, added check for duplicate provider ids to fail fast before sending to service
18+
619
1.0.0b9
720
++++++
821
* Update minCliCoreVersion

src/quantum/azext_quantum/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
# pylint: disable=line-too-long
77

88
from azure.cli.core import AzCommandsLoader
9+
from azure.cli.core.extension import get_extension
910

11+
# This is required to populate help for the extension
1012
import azext_quantum._help # pylint: disable=unused-import
1113

12-
1314
# This is the version reported by the CLI to the service when submitting requests.
14-
# This should be in sync with the extension version in 'setup.py', unless we need to
15-
# submit using a different version.
16-
CLI_REPORTED_VERSION = "1.0.0b8"
15+
# This will be the version of the quantum extension that is currently installed
16+
# This does not work for `azdev extension add` for local dev; install wheel file to mimic real extension installation.
17+
ext = get_extension("quantum")
18+
CLI_REPORTED_VERSION = ext.version if ext else "unknown"
1719

1820

1921
class QuantumCommandsLoader(AzCommandsLoader):

src/quantum/azext_quantum/_help.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@
6868
- name: Get the list of jobs from an Azure Quantum workspace.
6969
text: |-
7070
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation
71-
- name: List jobs that used the microsoft-elements provider.
71+
- name: List jobs that used the quantinuum provider.
7272
text: |-
73-
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --provider-id microsoft-elements
74-
- name: List jobs that ran on the microsoft.dft target.
73+
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --provider-id quantinuum
74+
- name: List jobs that ran on the ionq.simulator target.
7575
text: |-
76-
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --target-id microsoft.dft
76+
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --target-id ionq.simulator
7777
- name: List jobs that completed successfully.
7878
text: |-
7979
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --status Succeeded
@@ -128,7 +128,7 @@
128128
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
129129
-t rigetti.sim.qvm --job-name MyJob --job-input-file MyProgram.quil \\
130130
--job-input-format rigetti.quil.v1 --job-output-format rigetti.quil-results.v1
131-
- name: Submit a Qiskit circuit to the IonQ simulator with job params.
131+
- name: Submit a IonQ JSON circuit to the IonQ simulator with job params.
132132
text: |-
133133
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
134134
-t ionq.simulator --job-name MyJobName --job-input-file MyCircuit.json \\

src/quantum/azext_quantum/_params.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def load_arguments(self, _): # pylint: disable=too-many-locals
3636
storage_account_name_type = CLIArgumentType(options_list=['--storage-account', '-a'], help='Name of the storage account to be used by a quantum workspace.')
3737
target_id_type = CLIArgumentType(options_list=['--target-id', '-t'], help='Execution engine for quantum computing jobs. When a workspace is configured with a set of providers, they each enable one or more targets. You can configure the default target using `az quantum target set`.', configured_default='target_id')
3838
job_name_type = CLIArgumentType(help='A friendly name to give to this run of the program.')
39+
job_name_filter_type = CLIArgumentType(help='Job name to be listed (search by prefix), example "My Job".')
3940
job_id_type = CLIArgumentType(options_list=['--job-id', '-j'], help='Job unique identifier in GUID format.')
4041
job_params_type = CLIArgumentType(options_list=['--job-params'], help='Job parameters passed to the target as a list of key=value pairs, json string, or `@{file}` with json content.', action=JobParamsAction, nargs='+')
4142
target_capability_type = CLIArgumentType(options_list=['--target-capability'], help='Target-capability parameter passed to the compiler.')
@@ -52,8 +53,7 @@ def load_arguments(self, _): # pylint: disable=too-many-locals
5253
job_input_file_type = CLIArgumentType(help='The location of the input file to submit.')
5354
job_input_format_type = CLIArgumentType(help='The format of the file to submit.')
5455
job_output_format_type = CLIArgumentType(help='The expected job output format')
55-
entry_point_type = CLIArgumentType(help='The entry point for the QIR program or circuit. Required for QIR jobs.')
56-
item_type = CLIArgumentType(help='The item index in a batching job.')
56+
entry_point_type = CLIArgumentType(help='The entry point for the QIR program or circuit. Required for some provider QIR jobs.')
5757
skip_autoadd_type = CLIArgumentType(help='If specified, the plans that offer free credits will not automatically be added.')
5858
key_type = CLIArgumentType(options_list=['--key-type'], help='The api keys to be regenerated, should be Primary and/or Secondary.')
5959
enable_key_type = CLIArgumentType(options_list=['--enable-api-key'], help='Enable or disable API key authentication.')
@@ -92,10 +92,10 @@ def load_arguments(self, _): # pylint: disable=too-many-locals
9292
c.argument('shots', shots_type)
9393
c.argument('storage', storage_type)
9494
c.argument('max_poll_wait_secs', max_poll_wait_secs_type)
95-
c.argument('item', item_type)
9695

9796
with self.argument_context('quantum job list') as c:
9897
c.argument('job_type', job_type_type)
98+
c.argument('job_name', job_name_filter_type)
9999
c.argument('item_type', item_type_type)
100100
c.argument('provider_id', provider_id_type)
101101
c.argument('job_status', job_status_type)

src/quantum/azext_quantum/commands.py

Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ def one(key, value):
7878
('', f"\u007C{barra:<20}\u007C")
7979
])
8080

81+
# Handle Quantum Results v2 format
82+
if 'DataFormat' in results and results['DataFormat'] == 'microsoft.quantum-results.v2':
83+
total_shots = sum(results['Results'][0]['Histogram'][i]['Count'] for i in range(len(results['Results'][0]['Histogram'])))
84+
return [one(results['Results'][0]['Histogram'][i]['Display'], results['Results'][0]['Histogram'][i]['Count'] / total_shots) for i in range(len(results['Results'][0]['Histogram']))]
85+
86+
# Handle Quantum Results v1 format
8187
if 'Histogram' in results:
8288
histogram = results['Histogram']
8389
# The Histogram serialization is odd entries are key and even entries values
@@ -95,59 +101,6 @@ def one(key, value):
95101
histogram = results['histogram']
96102
return [one(key, histogram[key]) for key in histogram]
97103

98-
elif 'reportData' in results:
99-
table = []
100-
for group in results['reportData']['groups']:
101-
table.append(OrderedDict([
102-
("Label", (f"---{group['title']}---")),
103-
('Value', '---'),
104-
('Description', '---')
105-
]))
106-
for entry in group['entries']:
107-
val = results
108-
for key in entry['path'].split("/"):
109-
val = val[key]
110-
table.append(OrderedDict([
111-
("Label", entry['label']),
112-
('Value', val),
113-
('Description', entry['description'])
114-
]))
115-
return table
116-
117-
elif isinstance(results, list) and len(results) > 0 and 'reportData' in results[0]: # pylint: disable=too-many-nested-blocks
118-
table = []
119-
120-
indices = range(len(results))
121-
122-
for group_index, group in enumerate(results[0]['reportData']['groups']):
123-
table.append(OrderedDict([
124-
("Label", f"---{group['title']}---"),
125-
*[(f"{i}", '---') for i in indices]
126-
]))
127-
128-
visited_entries = set()
129-
130-
for entry in [entry for index in indices for entry in results[index]['reportData']['groups'][group_index]['entries']]:
131-
label = entry['label']
132-
if label in visited_entries:
133-
continue
134-
visited_entries.add(label)
135-
136-
row = [("Label", label)]
137-
138-
for index in indices:
139-
val = results[index]
140-
for key in entry['path'].split("/"):
141-
if key in val:
142-
val = val[key]
143-
else:
144-
val = "N/A"
145-
break
146-
row.append((f"{index}", val))
147-
table.append(OrderedDict(row))
148-
149-
return table
150-
151104
elif 'errorData' in results:
152105
notFound = 'Not found'
153106
errorData = results['errorData']

0 commit comments

Comments
 (0)