diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7b28e0da988..cb8ef2f8b0d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -116,7 +116,7 @@ /src/account/ @zikalino -/src/azext_quantum/ @anpaz-msft +/src/quantum/ @anpaz-msft /src/datashare/ @fengzhou-msft diff --git a/src/quantum/README.rst b/src/quantum/README.rst index 0dfa9304465..5d4c1a18f13 100644 --- a/src/quantum/README.rst +++ b/src/quantum/README.rst @@ -12,3 +12,150 @@ 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/ + +# Using the `az quantum` extension to list and manage jobs in Azure Quantum + +1. Log in to Azure using your credentials. + ```dotnetcli + az login + ``` +>[!NOTE] In case you have more than one subscription associated with your Azure account you must specify the +>subscription you want to use. You can do this with the command `az account set -s `. + +2. You can see all the Azure Quantum workspaces in your subscription with the `az quantum workspace list` command: + ```dotnetcli + az quantum workspace list + ``` + +3. You can use `quantum workspace set` to select a default workspace you want to use + to list and submit jobs. Note that you also need to specify the resource group. + ```dotnetcli + az quantum workspace set -g MyResourceGroup -w MyWorkspace -o table + + Location Name ResourceGroup + ----------- --------------------------------- -------------------------------- + westus ws-yyyyyy rg-yyyyyyyyy + ``` + +4. You can check the current default workspace with the command `az quantum workspace show`. + + ```dotnetcli + az quantum workspace show -o table + + Location Name ResourceGroup + ----------- --------------------------------- -------------------------------- + westus ws-yyyyyy rg-yyyyyyyyy + ``` + +5. You can see all the jobs submitted a workspace using `az quantum job list`. + + ```dotnetcli + az quantum job list -o table + + Id State Target Submission time + ------------------------------------ ------- -------------- --------------------------------- + yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy Waiting MyProvider.MyTarget 2020-06-12T14:20:18.6109317+00:00 + ``` + The console will output the information about the job, including the ID of the job. + +6. You can use the ID of the job to track its status: + ```dotnetcli + az quantum job show -id yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy -o table + + Id State Target Submission time + ------------------------------------ ------- -------------- --------------------------------- + yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy Waiting MyProvider.MyTarget 2020-06-12T14:20:18.6109317+00:00 + ``` + +7. Once the job finishes you can visualize the job's results with `az quantum job output`: + ```dotnetcli + az quantum job output -id yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy -o table + + Result Frequency + -------- ----------- ------------------------- + [0,0] 0.25000000 ▐█████ | + [1,0] 0.25000000 ▐█████ | + [0,1] 0.25000000 ▐█████ | + [1,1] 0.25000000 ▐█████ | + ``` + + + +# Submitting Q# programs for execution from the command line + +## Prerequisites + +- You need to have an Azure Quantum workspace in your subscription. +- Install the [Quantum Development Kit](https://docs.microsoft.com/quantum/install-guide/standalone), if you haven't already. + + +## Write your quantum application + +First you need to have the Q# quantum application that you want to execute in +Azure Quantum. + +>[!TIP] If this is the first time for you to create Q# quantum applications, you can learn +>how in our [Microsoft Learn +>module](https://docs.microsoft.com/en-us/learn/modules/qsharp-create-first-quantum-development-kit/). +> + +In this case we will use a simple quantum random bit generator. We create a Q# +project and substitute the content of `Program.qs` with the following code: + +```qsharp +namespace RandomBit { + + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Measurement; + + @EntryPoint() + operation GenerateRandomBit() : Result { + using (q = Qubit()) { + H(q); + return MResetZ(q); + } + } +} +``` +Note that the `@EntryPoint` attribute tells Q# which operation to run when the program starts. + +### Submit the job + +In this example we are going to use IonQ as the provider and the +`ionq.simulator` as target. To submit the job to the currently selected +default quantum workspace `az quantum job submit`: + +``` +az quantum job submit --target-id ionq.simulator --job-name Hello -o table + +Name Id Status Target Submission time +----- ------------------------------------ -------- -------------- --------------------------------- +Hello yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy Waiting ionq.simulator 2020-06-17T17:07:07.3484901+00:00 + +``` + +Once the job completes (i.e. it's in a **Successful** state), use `az quantum job output` to see the results: +``` +az quantum job output -id yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy -o table + +Result Frequency +-------- ----------- ------------------------- +[0,0] 0.25000000 ▐█████ | +[0,1] 0.75000000 ▐████████████████ | +``` +The output shows a histogram with the frequency a specific results was measured. In the example above +the result `[0,1]` was observed 75% of the times. + + +Finally, you can use `az quantum execute` as a shortcut for both, submitting and getting the results of execution. +``` +az quantum execute --target-id ionq.simulator --job-name Hello2 -o table +..... +Result Frequency +-------- ----------- ------------------------- +[0,0] 0.25000000 ▐█████ | +[0,1] 0.75000000 ▐████████████████ | +``` + + diff --git a/src/quantum/azext_quantum/_params.py b/src/quantum/azext_quantum/_params.py index c6e3306177d..d27e0631c1e 100644 --- a/src/quantum/azext_quantum/_params.py +++ b/src/quantum/azext_quantum/_params.py @@ -9,12 +9,12 @@ 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.') + program_args_type = CLIArgumentType(nargs='*', help='List of arguments expected by the Q# operation specified as --name=value after `--`.') + target_id_type = CLIArgumentType(options_list=['--target-id', '-t'], help='Target id.') + project_type = CLIArgumentType(help='The location of the Q# project to submit. Defaults to current folder.') + job_name_type = CLIArgumentType(help='A friendly name to give to this execution of the program.') + shots_type = CLIArgumentType(help='The number of times to execute the Q# program on the given target.') + no_build_type = 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) @@ -26,20 +26,20 @@ def load_arguments(self, _): 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) + c.argument('target_id', target_id_type) + c.argument('project', project_type) + c.argument('job_name', job_name_type) + c.argument('shots', shots_type) + c.argument('no_build', no_build_type) with self.argument_context('quantum job submit') as c: - c.positional('program_args', program_args) + c.positional('program_args', program_args_type) 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) + c.argument('target_id', target_id_type) + c.argument('project', project_type) + c.argument('job_name', job_name_type) + c.argument('shots', shots_type) + c.argument('no_build', no_build_type) + c.positional('program_args', program_args_type) diff --git a/src/quantum/azext_quantum/commands.py b/src/quantum/azext_quantum/commands.py index 9ce3969d04e..46488121f40 100644 --- a/src/quantum/azext_quantum/commands.py +++ b/src/quantum/azext_quantum/commands.py @@ -86,11 +86,11 @@ def load_command_table(self, _): 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 target', target_ops) as t: + t.command('list', 'list', validator=validate_workspace_info, table_transformer=transform_targets) + t.command('show', 'show', validator=validate_target_info) + t.command('set', 'set', validator=validate_target_info) + t.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) diff --git a/src/quantum/azext_quantum/operations/job.py b/src/quantum/azext_quantum/operations/job.py index 31e15650463..12b94e8a9bd 100644 --- a/src/quantum/azext_quantum/operations/job.py +++ b/src/quantum/azext_quantum/operations/job.py @@ -18,7 +18,7 @@ def list(cmd, resource_group_name=None, workspace_name=None): """ - Returns the list of jobs in a Quantum Workspace. + Get the list of jobs in a Quantum Workspace. """ info = WorkspaceInfo(cmd, resource_group_name, workspace_name) client = cf_jobs(cmd.cli_ctx, info.subscription, info.resource_group, info.name) @@ -27,7 +27,7 @@ def list(cmd, resource_group_name=None, workspace_name=None): def show(cmd, job_id, resource_group_name=None, workspace_name=None): """ - Shows the job's status and details. + Get the job's status and details. """ info = WorkspaceInfo(cmd, resource_group_name, workspace_name) client = cf_jobs(cmd.cli_ctx, info.subscription, info.resource_group, info.name) @@ -36,7 +36,7 @@ def show(cmd, job_id, resource_group_name=None, workspace_name=None): def build(cmd, target_id=None, project=None): """ - Compiles a Q# program for execution to Azure Quantum. + Compile a Q# program for execution to Azure Quantum. """ target = TargetInfo(cmd, target_id) @@ -116,7 +116,7 @@ def _generate_submit_args(program_args, ws, target, token, project, job_name, sh def submit(cmd, program_args, resource_group_name=None, workspace_name=None, target_id=None, project=None, job_name=None, shots=None, no_build=False): """ - Submits a Q# project for execution to Azure Quantum. + Submit a Q# project for execution to Azure Quantum. """ # We first build and then call run. @@ -161,7 +161,9 @@ def _parse_blob_url(url): def output(cmd, job_id, resource_group_name=None, workspace_name=None): - """ Returns back the results of a Q# execution """ + """ + Get the results of a Q# execution. + """ import tempfile import json import os @@ -223,10 +225,10 @@ def has_completed(job): def execute(cmd, program_args, resource_group_name=None, workspace_name=None, target_id=None, project=None, job_name=None, shots=None, no_build=False): """ - Submits a job for quantum execution on Azure Quantum, and waits for the result. + Submit a job for quantum execution on Azure Quantum, and waits for the result. """ job = submit(cmd, program_args, resource_group_name, workspace_name, target_id, project, job_name, shots, no_build) - print("Job id:", job.id) + logger.warning("Job id: %s", job.id) logger.debug(job) job = wait(cmd, job.id, resource_group_name, workspace_name) diff --git a/src/quantum/azext_quantum/operations/target.py b/src/quantum/azext_quantum/operations/target.py index 00601550a12..03dd62b1176 100644 --- a/src/quantum/azext_quantum/operations/target.py +++ b/src/quantum/azext_quantum/operations/target.py @@ -35,7 +35,7 @@ def save(self, cmd): def show(cmd, target_id=None): """ - Returns the details of the given (or current) target to use when submitting jobs to Azure Quantum. + Get the details of the given (or current) target to use when submitting jobs to Azure Quantum. """ info = TargetInfo(cmd, target_id) return info @@ -43,7 +43,7 @@ def show(cmd, target_id=None): def set(cmd, target_id=None): """ - Selects the default target to use when submitting jobs to Azure Quantum. + Select the default target to use when submitting jobs to Azure Quantum. """ info = TargetInfo(cmd, target_id) if info: @@ -53,7 +53,7 @@ def set(cmd, target_id=None): def list(cmd, resource_group_name=None, workspace_name=None): """ - Returns the list of providers and their targets in a Quantum Workspace. + Get the list of providers and their targets in an Azure Quantum workspace. """ info = WorkspaceInfo(cmd, resource_group_name, workspace_name) client = cf_providers(cmd.cli_ctx, info.subscription, info.resource_group, info.name) @@ -62,7 +62,7 @@ def list(cmd, resource_group_name=None, workspace_name=None): def clear(cmd): """ - Unsets the default target-id. + Unset the default target-id. """ info = TargetInfo(cmd) info.clear() diff --git a/src/quantum/azext_quantum/operations/workspace.py b/src/quantum/azext_quantum/operations/workspace.py index 5f8bd0aee42..fbb7d83510a 100644 --- a/src/quantum/azext_quantum/operations/workspace.py +++ b/src/quantum/azext_quantum/operations/workspace.py @@ -46,7 +46,7 @@ def save(self, cmd): def list(cmd, resource_group_name=None, tag=None, location=None): """ - Returns the list of Quantum Workspaces available. + Get the list of Azure Quantum workspaces available. """ from azure.cli.command_modules.resource.custom import list_resources return list_resources(cmd, resource_group_name=resource_group_name, resource_type="Microsoft.Quantum/Workspaces", tag=tag, location=location) @@ -54,7 +54,7 @@ def list(cmd, resource_group_name=None, tag=None, location=None): def show(cmd, resource_group_name=None, workspace_name=None): """ - Returns the details of the given (or current) Quantum Workspace. + Get the details of the given (or current) Azure Quantum workspace. """ client = cf_workspaces(cmd.cli_ctx) info = WorkspaceInfo(cmd, resource_group_name, workspace_name) @@ -66,7 +66,7 @@ def show(cmd, resource_group_name=None, workspace_name=None): def set(cmd, workspace_name, resource_group_name=None): """ - Sets the default Quantum Workspace. + Set the default Azure Quantum workspace. """ client = cf_workspaces(cmd.cli_ctx) info = WorkspaceInfo(cmd, resource_group_name, workspace_name) @@ -78,7 +78,7 @@ def set(cmd, workspace_name, resource_group_name=None): def clear(cmd): """ - Unsets the default Quantum Workspace. + Unset the default Azure Quantum workspace. """ info = WorkspaceInfo(cmd) info.clear() diff --git a/src/quantum/azext_quantum/profiles.py b/src/quantum/azext_quantum/profiles.py deleted file mode 100644 index 34913fb394d..00000000000 --- a/src/quantum/azext_quantum/profiles.py +++ /dev/null @@ -1,4 +0,0 @@ -# -------------------------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# -------------------------------------------------------------------------------------------- diff --git a/src/quantum/setup.cfg b/src/quantum/setup.cfg index 3c6e79cf31d..af57bc0b387 100644 --- a/src/quantum/setup.cfg +++ b/src/quantum/setup.cfg @@ -1,2 +1 @@ [bdist_wheel] -universal=1 diff --git a/src/quantum/setup.py b/src/quantum/setup.py index 1306708acd2..65d4126a52f 100644 --- a/src/quantum/setup.py +++ b/src/quantum/setup.py @@ -16,7 +16,7 @@ # TODO: Confirm this is the right version number you want and it matches your # HISTORY.rst entry. -VERSION = '0.11.2906.2' +VERSION = '0.11.2906.3' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers @@ -32,9 +32,7 @@ 'License :: OSI Approved :: MIT License', ] -# TODO: Add any additional SDK dependencies here DEPENDENCIES = [ - 'azure-cli-core' ] with open('README.rst', 'r', encoding='utf-8') as f: