Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/quantum/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@
Release History
===============

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

1.0.0b9
++++++
* Update minCliCoreVersion
Expand Down
10 changes: 6 additions & 4 deletions src/quantum/azext_quantum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
# pylint: disable=line-too-long

from azure.cli.core import AzCommandsLoader
from azure.cli.core.extension import get_extension

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


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


class QuantumCommandsLoader(AzCommandsLoader):
Expand Down
10 changes: 5 additions & 5 deletions src/quantum/azext_quantum/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@
- name: Get the list of jobs from an Azure Quantum workspace.
text: |-
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation
- name: List jobs that used the microsoft-elements provider.
- name: List jobs that used the quantinuum provider.
text: |-
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --provider-id microsoft-elements
- name: List jobs that ran on the microsoft.dft target.
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --provider-id quantinuum
- name: List jobs that ran on the ionq.simulator target.
text: |-
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --target-id microsoft.dft
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --target-id ionq.simulator
- name: List jobs that completed successfully.
text: |-
az quantum job list -g MyResourceGroup -w MyWorkspace -l MyLocation --status Succeeded
Expand Down Expand Up @@ -128,7 +128,7 @@
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
-t rigetti.sim.qvm --job-name MyJob --job-input-file MyProgram.quil \\
--job-input-format rigetti.quil.v1 --job-output-format rigetti.quil-results.v1
- name: Submit a Qiskit circuit to the IonQ simulator with job params.
- name: Submit a IonQ JSON circuit to the IonQ simulator with job params.
text: |-
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
-t ionq.simulator --job-name MyJobName --job-input-file MyCircuit.json \\
Expand Down
6 changes: 3 additions & 3 deletions src/quantum/azext_quantum/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def load_arguments(self, _): # pylint: disable=too-many-locals
storage_account_name_type = CLIArgumentType(options_list=['--storage-account', '-a'], help='Name of the storage account to be used by a quantum workspace.')
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')
job_name_type = CLIArgumentType(help='A friendly name to give to this run of the program.')
job_name_filter_type = CLIArgumentType(help='Job name to be listed (search by prefix), example "My Job".')
job_id_type = CLIArgumentType(options_list=['--job-id', '-j'], help='Job unique identifier in GUID format.')
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='+')
target_capability_type = CLIArgumentType(options_list=['--target-capability'], help='Target-capability parameter passed to the compiler.')
Expand All @@ -52,8 +53,7 @@ def load_arguments(self, _): # pylint: disable=too-many-locals
job_input_file_type = CLIArgumentType(help='The location of the input file to submit.')
job_input_format_type = CLIArgumentType(help='The format of the file to submit.')
job_output_format_type = CLIArgumentType(help='The expected job output format')
entry_point_type = CLIArgumentType(help='The entry point for the QIR program or circuit. Required for QIR jobs.')
item_type = CLIArgumentType(help='The item index in a batching job.')
entry_point_type = CLIArgumentType(help='The entry point for the QIR program or circuit. Required for some provider QIR jobs.')
skip_autoadd_type = CLIArgumentType(help='If specified, the plans that offer free credits will not automatically be added.')
key_type = CLIArgumentType(options_list=['--key-type'], help='The api keys to be regenerated, should be Primary and/or Secondary.')
enable_key_type = CLIArgumentType(options_list=['--enable-api-key'], help='Enable or disable API key authentication.')
Expand Down Expand Up @@ -92,10 +92,10 @@ def load_arguments(self, _): # pylint: disable=too-many-locals
c.argument('shots', shots_type)
c.argument('storage', storage_type)
c.argument('max_poll_wait_secs', max_poll_wait_secs_type)
c.argument('item', item_type)

with self.argument_context('quantum job list') as c:
c.argument('job_type', job_type_type)
c.argument('job_name', job_name_filter_type)
c.argument('item_type', item_type_type)
c.argument('provider_id', provider_id_type)
c.argument('job_status', job_status_type)
Expand Down
59 changes: 6 additions & 53 deletions src/quantum/azext_quantum/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ def one(key, value):
('', f"\u007C{barra:<20}\u007C")
])

# Handle Quantum Results v2 format
if 'DataFormat' in results and results['DataFormat'] == 'microsoft.quantum-results.v2':
total_shots = sum(results['Results'][0]['Histogram'][i]['Count'] for i in range(len(results['Results'][0]['Histogram'])))
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']))]

# Handle Quantum Results v1 format
if 'Histogram' in results:
histogram = results['Histogram']
# The Histogram serialization is odd entries are key and even entries values
Expand All @@ -95,59 +101,6 @@ def one(key, value):
histogram = results['histogram']
return [one(key, histogram[key]) for key in histogram]

elif 'reportData' in results:
table = []
for group in results['reportData']['groups']:
table.append(OrderedDict([
("Label", (f"---{group['title']}---")),
('Value', '---'),
('Description', '---')
]))
for entry in group['entries']:
val = results
for key in entry['path'].split("/"):
val = val[key]
table.append(OrderedDict([
("Label", entry['label']),
('Value', val),
('Description', entry['description'])
]))
return table

elif isinstance(results, list) and len(results) > 0 and 'reportData' in results[0]: # pylint: disable=too-many-nested-blocks
table = []

indices = range(len(results))

for group_index, group in enumerate(results[0]['reportData']['groups']):
table.append(OrderedDict([
("Label", f"---{group['title']}---"),
*[(f"{i}", '---') for i in indices]
]))

visited_entries = set()

for entry in [entry for index in indices for entry in results[index]['reportData']['groups'][group_index]['entries']]:
label = entry['label']
if label in visited_entries:
continue
visited_entries.add(label)

row = [("Label", label)]

for index in indices:
val = results[index]
for key in entry['path'].split("/"):
if key in val:
val = val[key]
else:
val = "N/A"
break
row.append((f"{index}", val))
table.append(OrderedDict(row))

return table

elif 'errorData' in results:
notFound = 'Not found'
errorData = results['errorData']
Expand Down
Loading
Loading