Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8005033
create
anpaz Apr 23, 2020
7eaaa28
max version
anpaz Apr 23, 2020
2d52c70
sdks
anpaz Apr 23, 2020
fa3f6a0
rm version
anpaz Apr 23, 2020
d47424d
ws show
anpaz Apr 23, 2020
9bf6b08
jobs
anpaz Apr 23, 2020
86b95ab
base_url
anpaz Apr 23, 2020
3537eb5
typo rp
anpaz May 7, 2020
26daee3
ws list
anpaz May 8, 2020
46a4e02
ws show
anpaz May 8, 2020
a8a5f8d
offers list
anpaz May 8, 2020
0c7fe63
ws set
anpaz May 8, 2020
d327e40
ws clear
anpaz May 8, 2020
9dc593b
job list
anpaz May 8, 2020
6036bc1
job show
anpaz May 8, 2020
f8ee4c2
job submit
anpaz May 8, 2020
c445c85
job output
anpaz May 8, 2020
1277c03
whitespace
anpaz May 8, 2020
d484995
job details
anpaz May 8, 2020
8cb96cb
job output
anpaz May 8, 2020
2c92a20
target set
anpaz May 11, 2020
a23bafb
submit standalone
anpaz May 11, 2020
d4fe8ea
version
anpaz May 11, 2020
166d29e
Support passing additional arguments to the Q# program (#1)
bamarsha May 13, 2020
f6db8b7
base_url
anpaz May 12, 2020
24de5ec
histogram display
anpaz May 12, 2020
3ea8bee
job execute
anpaz May 12, 2020
ffd8eaf
quantum execute
anpaz May 13, 2020
e7222ed
output translation
anpaz May 13, 2020
8da90f0
no_build
anpaz May 26, 2020
3c605f9
0.4.1
anpaz Jun 2, 2020
d49fdec
update api
anpaz Jun 2, 2020
6eb038c
cleanup: validators
anpaz Jun 2, 2020
c99b214
build
anpaz Jun 3, 2020
1240b55
target list
anpaz Jun 3, 2020
8790a20
target list
anpaz Jun 3, 2020
5659722
test workspace
anpaz Jun 3, 2020
312c3a4
test targets
anpaz Jun 3, 2020
c9541e4
job tests
anpaz Jun 3, 2020
26d2bee
test jobs
anpaz Jun 3, 2020
0c7de2d
recordings
anpaz Jun 3, 2020
054c63b
version
anpaz Jun 3, 2020
805fcc1
help-1
anpaz Jun 3, 2020
d7e52b7
tests subs
anpaz Jun 11, 2020
b618370
skip tests
anpaz Jun 11, 2020
b9bdc62
feedback 1.
anpaz Jun 11, 2020
cca1917
group help
anpaz Jun 12, 2020
86bb904
readme
anpaz Jun 12, 2020
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
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,5 @@
/src/hpc-cache/ @qianwens

/src/account/ @zikalino

/src/azext_quantum/ @anpaz-msft
9 changes: 9 additions & 0 deletions src/quantum/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. :changelog:

Release History
===============

0.11.2906.2
++++++
* Initial release. Version intended to work with Azure Quantum Private Preview
and with QDK version 0.11.2906.*
14 changes: 14 additions & 0 deletions src/quantum/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Microsoft Azure CLI 'quantum' Extension
==========================================

Azure Quantum is the first open Quantum computing platform. It offers a range of services
from quantum hardware to full-state simulators and quantum inspired optimizations,
providing developers and customers access to the most competitive quantum offering
on the market.

To learn more about azure quantum visit:
https://azure.microsoft.com/en-us/services/quantum/

To learn more about quantum computing and Microsoft's Quantum Development Kit visit:
https://docs.microsoft.com/quantum/

26 changes: 26 additions & 0 deletions src/quantum/azext_quantum/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=import-outside-toplevel
from azure.cli.core import AzCommandsLoader

import azext_quantum._help # pylint: disable=unused-import

class QuantumCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
super(QuantumCommandsLoader, self).__init__(cli_ctx=cli_ctx)

def load_command_table(self, args):
from azext_quantum.commands import load_command_table
load_command_table(self, args)
return self.command_table

def load_arguments(self, command):
from azext_quantum._params import load_arguments
load_arguments(self, command)


COMMAND_LOADER_CLS = QuantumCommandsLoader
43 changes: 43 additions & 0 deletions src/quantum/azext_quantum/_client_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=import-outside-toplevel,line-too-long

import os

def is_env(name):
return 'AZURE_QUANTUM_ENV' in os.environ and os.environ['AZURE_QUANTUM_ENV'] == name

def base_url():
if 'AZURE_QUANTUM_BASEURL' in os.environ:
return os.environ['AZURE_QUANTUM_BASEURL']
if is_env('canary'):
return "https://app-jobs-canarysouthcentralus.azurewebsites.net/"
return "https://app-jobscheduler-prod.azurewebsites.net/"

def _get_data_credentials(cli_ctx, subscription_id=None):
from azure.cli.core._profile import Profile
profile = Profile(cli_ctx=cli_ctx)
creds, _, _ = profile.get_login_credentials(subscription_id=subscription_id, resource="https://quantum.microsoft.com")
return creds

def cf_quantum(cli_ctx, subscription_id=None, resource_group_name=None, workspace_name=None):
from .vendored_sdks.azure_quantum import QuantumClient
creds = _get_data_credentials(cli_ctx, subscription_id)
return QuantumClient(creds, subscription_id, resource_group_name, workspace_name, base_url=base_url())

def cf_quantum_mgmt(cli_ctx, *_):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from .vendored_sdks.azure_mgmt_quantum import QuantumManagementClient
return get_mgmt_service_client(cli_ctx, QuantumManagementClient)

def cf_workspaces(cli_ctx, *_):
return cf_quantum_mgmt(cli_ctx).workspaces

def cf_providers(cli_ctx, subscription_id=None, resource_group_name=None, workspace_name=None):
return cf_quantum(cli_ctx, subscription_id, resource_group_name, workspace_name).providers

def cf_jobs(cli_ctx, subscription_id=None, resource_group_name=None, workspace_name=None):
return cf_quantum(cli_ctx, subscription_id, resource_group_name, workspace_name).jobs
27 changes: 27 additions & 0 deletions src/quantum/azext_quantum/_help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# coding=utf-8
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from knack.help_files import helps # pylint: disable=unused-import

helps['quantum'] = """
type: group
short-summary: Manage Azure Quantum Workspaces and submit jobs to Azure Quantum Providers.
"""

helps['quantum job'] = """
type: group
short-summary: Manage jobs for Azure Quantum.
"""

helps['quantum target'] = """
type: group
short-summary: Manage execution targets for Azure Quantum workspaces.
"""

helps['quantum workspace'] = """
type: group
short-summary: Manage Azure Quantum workspaces.
"""
44 changes: 44 additions & 0 deletions src/quantum/azext_quantum/_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
# pylint: disable=line-too-long

from knack.arguments import CLIArgumentType

def load_arguments(self, _):
workspace_name_type = CLIArgumentType(options_list=['--workspace-name', '-w'], help='Name of the Quantum Workspace. You can configure the default workspace using `az quantum workspace set`.', id_part=None, required=False)
program_args = CLIArgumentType(nargs='*', help='List of arguments expected by the Q# operation specified as --name=value after `--`.')
target_id = CLIArgumentType(options_list=['--target-id', '-t'], help='Target id.')
project = CLIArgumentType(help='The location of the Q# project to submit. Defaults to current folder.')
job_name = CLIArgumentType(help='A friendly name to give to this execution of the program.')
shots = CLIArgumentType(help='The number of times to execute the Q# program on the given target.')
no_build = CLIArgumentType(help='If specified, the Q# program is not built before submitting.')

with self.argument_context('quantum workspace') as c:
c.argument('workspace_name', workspace_name_type)

with self.argument_context('quantum target') as c:
c.argument('workspace_name', workspace_name_type)
c.argument('target_id', options_list=['--target-id', '-t'], help='Target id.')

with self.argument_context('quantum job') as c:
c.argument('workspace_name', workspace_name_type)
c.argument('job_id', options_list=['--job-id', '-id'], help='Job id.')
c.argument('target_id', target_id)
c.argument('project', project)
c.argument('job_name', job_name)
c.argument('shots', shots)
c.argument('no_build', no_build)

with self.argument_context('quantum job submit') as c:
c.positional('program_args', program_args)

with self.argument_context('quantum execute') as c:
c.argument('workspace_name', workspace_name_type)
c.argument('target_id', target_id)
c.argument('project', project)
c.argument('job_name', job_name)
c.argument('shots', shots)
c.argument('no_build', no_build)
c.positional('program_args', program_args)
51 changes: 51 additions & 0 deletions src/quantum/azext_quantum/_validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long

import os

from .operations.workspace import WorkspaceInfo
from .operations.target import TargetInfo

def validate_workspace_info(cmd, namespace):
"""
Makes sure all parameters for a workspace are available.
"""
group = getattr(namespace, 'resource_group_name', None)
name = getattr(namespace, 'workspace_name', None)
ws = WorkspaceInfo(cmd, group, name)

if not ws.subscription:
raise ValueError("Missing subscription argument")
if not ws.resource_group:
raise ValueError("Missing resource-group argument")
if not ws.name:
raise ValueError("Missing workspace-name argument")


def validate_target_info(cmd, namespace):
"""
Makes sure all parameters for a target are available.
"""
target_id = getattr(namespace, 'target_id', None)
target = TargetInfo(cmd, target_id)

if not target.target_id:
raise ValueError("Missing target-id argument")


def validate_workspace_and_target_info(cmd, namespace):
"""
Makes sure all parameters for both, a workspace and a target are available.
"""
validate_workspace_info(cmd, namespace)
validate_target_info(cmd, namespace)

# For the time being (Private Preview), we also need the AZURE_QUANTUM_STORAGE env variable populated
# with the Azure Storage connection string to use to upload the program.
if not 'AZURE_QUANTUM_STORAGE' in os.environ:
raise ValueError(f"Please set the AZURE_QUANTUM_STORAGE environment variable with an Azure Storage's connection string.")

4 changes: 4 additions & 0 deletions src/quantum/azext_quantum/azext_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"azext.isPreview": true,
"azext.minCliCoreVersion": "2.5.1"
}
104 changes: 104 additions & 0 deletions src/quantum/azext_quantum/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long

from collections import OrderedDict
from azure.cli.core.commands import CliCommandType
from ._validators import validate_workspace_info, validate_target_info, validate_workspace_and_target_info


def transform_targets(providers):
def one(provider, target):
return OrderedDict([
('Provider', provider),
('Target-id', target['id']),
('Current Availability', target['currentAvailability']),
('Average Queue Time', target['averageQueueTime'])
])

return [
one(provider['id'], target)
for provider in providers
for target in provider['targets']
]

def transform_job(result):
result = OrderedDict([
('Id', result['id']),
('Status', result['status']),
('Target', result['target']),
('Submission time', result['creationTime']),
('Completion time', result['endExecutionTime'])
])
return result

def transform_jobs(results):
def creation(job):
return job['creationTime']

return [transform_job(job) for job in sorted(results, key=creation, reverse=True)]


def transform_output(results):
def one(key, value):
repeat = round(20 * value)
barra = "\u2588" * repeat
return OrderedDict([
('Result', key),
('Frequency', f"{value:10.8f}"),
('', f"\u2590{barra:<22} |"),
])

if 'Histogram' in results:
histogram = results['Histogram']
# The Histogram serialization is odd entries are key and even entries values
# Make sure we have even entries
if (len(histogram) % 2) == 0:
table = []
items = range(0, len(histogram), 2)
for i in items:
key = histogram[i]
value = histogram[i+1]
table.append(one(key, value))
return table

elif 'histogram' in results:
histogram = results['histogram']
return [one(key, histogram[key]) for key in histogram]

return results


def load_command_table(self, _):

workspace_ops = CliCommandType(operations_tmpl='azext_quantum.operations.workspace#{}')
job_ops = CliCommandType(operations_tmpl='azext_quantum.operations.job#{}')
target_ops = CliCommandType(operations_tmpl='azext_quantum.operations.target#{}')

with self.command_group('quantum workspace', workspace_ops) as w:
w.command('list', 'list')
w.command('show', 'show', validator=validate_workspace_info) ## TODO: argument list/help
w.command('set', 'set', validator=validate_workspace_info)
w.command('clear', 'clear')


with self.command_group('quantum target', target_ops) as w:
w.command('list', 'list', validator=validate_workspace_info, table_transformer=transform_targets)
w.command('show', 'show', validator=validate_target_info)
w.command('set', 'set', validator=validate_target_info)
w.command('clear', 'clear')


with self.command_group('quantum job', job_ops) as j:
j.command('list', 'list', validator=validate_workspace_info, table_transformer=transform_jobs)
j.command('show', 'show', validator=validate_workspace_info, table_transformer=transform_job)
j.command('submit', 'submit', validator=validate_workspace_and_target_info, table_transformer=transform_job)
j.command('wait', 'wait', validator=validate_workspace_info, table_transformer=transform_job)
j.command('output', 'output', validator=validate_workspace_info, table_transformer=transform_output)


with self.command_group('quantum', job_ops, is_preview=True) as q:
q.command('execute', 'execute', validator=validate_workspace_and_target_info, table_transformer=transform_output)
4 changes: 4 additions & 0 deletions src/quantum/azext_quantum/operations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
Loading