How to submit Q# programs with Visual Studio Code

Learn how to use Visual Studio Code to create and submit Q# programs to real quantum hardware. You can submit quantum computing jobs to Azure Quantum as a standalone Q# program, combine Q# with Python in a Q# project, and run a Jupyter Notebook.

Submitting Q# jobs to Azure Quantum

Learn how to use VS Code to run, debug, and submit a Q# program to Azure Quantum.

Prerequisites

For installation details, see Installing the QDK on VS Code.

Load a Q# sample program

  1. In VS Code, select File > New Text File and save the file as RandomNum.qs.

  2. Open RandomNum.qs and type sample, then select Random Bit sample from the list of options and save the file.

    Screenshot the Q# file in Visual Studio Code showing the list of code samples when writing the word sample in the file.

Note

You can also open your own Q# file. If you run an older Q# program and run into errors, see Testing and debugging.

Run a Q# program

  1. To test run your program locally on the built-in simulator, click on Run from the list of commands next to the entry point operation, or press Ctrl+F5. Your output will appear in the debug console.

  2. To debug your program before submitting it to Azure Quantum, click on Debug from the list of commands next to the entry point operation, or press F5. Use the debugging controls at the top to step over, into, and out of the code. For more information about debugging Q# programs, see Testing and debugging.

    Screenshot the Q# file in Visual Studio Code showing where to find the code lens with run and debug commands.

Visualize the frequency histogram

The frequency histogram represents the distribution of results obtained from running a quantum program multiple times, or "shots". Each bar in the histogram corresponds to a possible outcome, and its height represents the number of times that outcome is observed. The frequency histogram helps visualize the probability distribution of these outcomes.

  1. Select View -> Command Palette and type “histogram” which should bring up the Q#: Run file and show histogram option. You can also click on Histogram from the list of commands next to the entry point operation. Select this option to open the Q# histogram window.

    Screenshot the Q# file in Visual Studio Code showing where to find the code lens with histogram command.

  2. Enter a number of shots to execute the program, for example, 100 shots, and press Enter. The histogram will display in the Q# histogram window.

  3. Click the top-left settings icon to display options.

    Screenshot the Q# histogram window in Visual Studio Code showing how to display settings.

  4. Click on a bar to display the percentage of that outcome. In this case there are two possible outcomes, 0 and 1, and the percentage of each outcome is close to 50%.

    Screenshot the Q# histogram window in Visual Studio Code.

Tip

You can zoom the histogram using the mouse scroll wheel or a trackpad gesture. When zoomed in, you can pan the chart by pressing 'Alt' while scrolling.

Visualize the quantum circuit

Quantum circuit diagrams are a visual representation of quantum operations. They show the flow of qubits through the quantum program, including the gates and measurements applied to them. For more information, see Quantum circuit diagrams in Visual Studio Code.

  1. Select View -> Command Palette and type “circuit” which should bring up the Q#: Show circuit option. You can also click on Circuit from the list of commands next to the entry point operation.

    Screenshot the Q# file in Visual Studio Code showing where to find the code lens circuit command.

  2. The circuit is displayed in the Q# circuit window. The circuit diagram shows one qubit register which it's initialized to the |0⟩ state. Then, a Hadamard gate, H, is applied to the qubit, followed by a measurement operation, which is represented by a meter symbol. For more information, see Quantum circuits conventions.

    Screenshot the Q# circuit window showing the resulting circuit diagram for the random bit operation.

Connect to Azure Quantum and submit your job

You can connect and submit jobs directly from VS Code. For this example, you'll submit a job to the Rigetti simulator.

  1. Select View -> Command Palette and type Q#: Connect to an Azure Quantum workspace. Press Enter.

  2. Select Azure account, and follow the prompts to connect to your preferred directory, subscription, and workspace.

    Note

    If you have a connection string, you can select Connection string and paste the connection string corresponding to your Azure Quantum workspace. For more information, see Connect to a Quantum workspace using a connection string.

  3. Once you are connected, in the Explorer pane, expand Quantum Workspaces.

  4. Expand your workspace and expand the Rigetti provider.

    Note

    If there is an issue connecting to Azure Quantum, a warning icon displays next to the workspace name. Hover over the workspace name to display error information.

  5. Select rigetti.sim.qvm as your target.

    Screenshot of Visual Studio Code showing how to select Rigetti simulator as target.

  6. Select the play icon to the right of the target name to start submitting the current Q# program. If you get a popup, select Change the QIR target profile and continue.

    Screenshot of Visual Studio Code showing how to run Rigetti simulator as target.

  7. Add a name to identify the job.

  8. Add the number of shots, or number of times that the program is run.

  9. Press Enter to submit the job. The job status will display at the bottom of the screen.

  10. Expand Jobs and hover over your job, which displays the times and status of your job.

  11. To view the results, select the cloud icon next to the job name to download the results from your workspace storage and display it in VS Code.

    Screenshot of Visual Studio Code showing how to download and view the results of your quantum job.

Submitting Jupyter Notebooks jobs to Azure Quantum

Learn how to use VS Code to run, debug, and submit a Q# Jupyter Notebook to Azure Quantum. The steps in this article also apply to Jupyter Notebooks on your local Jupyter server or notebooks in the Azure Quantum portal.

Prerequisites

For installation details, see Installing the QDK on VS Code.

Run and test your program in the local simulator

  1. In VS Code, select View > Command palette and select Create: New Jupyter Notebook.

  2. In the top-right, VS Code will detect and display the version of Python and the virtual Python environment that was selected for the notebook. If you have multiple Python environments, you may need to select a kernel using the kernel picker in the top right. If no environment was detected, see Jupyter Notebooks in VS Code for setup information.

  3. In the first cell of the notebook, run the following Python code to import the necessary modules:

    import qsharp
    import azure.quantum
    
    • The qsharp module activates the %%qsharp magic command that lets you enter Q# code directly into a cell.
    • The azure-quantum module provides connectivity to your Azure Quantum workspace.

    Note

    If the Jupyter Python kernel ipykernel is not detected, VS Code will prompt you to install it.

  4. Add another cell and enter this Q# code that returns a user-specified number of random bits:

    Note

    Notice that as soon as you type in the magic command %%qsharp, the notebook cell changes type from Python to Q#.

    %%qsharp
    
    operation Random() : Result {
        use q = Qubit();
        H(q);
        let result = M(q);
        Reset(q);
        return result
    }
    
    operation RandomNBits(N: Int): Result[] {
        mutable results = [];
        for i in 0 .. N - 1 {
            let r = Random();
            set results += [r];
        }
        return results
    }
    
  5. To test your operation, you can use the eval method, which can call any Q# operation previously defined in the notebook:

    qsharp.eval("RandomNBits(4)")
    
    [Zero, One, One, Zero]
    
  6. To run your program to the local simulator, use the run method. Specify the shots, or number of times to run the program, and the simulator returns the results as a Python list.

    qsharp.run("RandomNBits(4)", shots=10)
    
    [[One, One, One, One],
    [Zero, Zero, One, Zero],
    [One, Zero, Zero, One],
    [Zero, One, Zero, Zero],
    [One, Zero, One, One],
    [One, Zero, One, Zero],
    [One, One, One, Zero],
    [One, One, One, One],
    [Zero, Zero, Zero, One],
    [One, Zero, Zero, One]]
    

Visualize the quantum circuit

You can visualize quantum circuits using the qsharp-widgets package. This package provides a widget that renders a quantum circuit diagram as an SVG image. For more information, see Quantum circuit diagrams with Jupyter Notebooks.

Add the following code to a new cell to visualize the circuit:

from qsharp_widgets import Circuit

Circuit(qsharp.circuit("RandomNBits(4)"))

Screenshot of Jupyter Notebook showing how to visualize the circuit for a Q# operation.

For more information, see Quantum circuits conventions.

Compile your job using the Base profile

When you run programs on the local quantum simulator, you can submit any type of Q# program. However, Azure Quantum hardware targets do not yet support the full capabilities required to run all Q# programs. In order to compile and submit Q# programs to Azure Quantum, you need to set your target profile to tell Q# which capabilities your target hardware supports. Currently, that is the Base profile. For more information, see Profile types in Azure Quantum.

To reinitialize the Q# interpreter and compile your program with the base profile:

  1. Use the init method to set the profile:

    qsharp.init(target_profile=qsharp.TargetProfile.Base)
    
  2. Since you reinitialized the interpreter, you need to run your code again with the new profile:

    %%qsharp
    
    operation Random() : Result {
        use q = Qubit();
        H(q);
        let result = M(q);
        Reset(q);
        return result
    }
    
    operation RandomNBits(N: Int): Result[] {
        mutable results = [];
        for i in 0 .. N - 1 {
            let r = Random();
            set results += [r];
        }
        return results
    }
    
  3. Next, use the compile method to specify the operation or function that is the entry point to your program. This compiles your code into QIR format, which can then be submitted to any quantum hardware:

    MyProgram = qsharp.compile("RandomNBits(4)")
    

Connect to Azure Quantum and submit your job

Now that you have your program compiled into the correct format, create an azure.quantum.Workspace object to connect to Azure Quantum. You'll use the Resource ID of your Azure Quantum workspace in order to connect. The Resource ID and location can be copied from your workspace overview page in the Azure portal.

  1. In a new cell, fill in your resource ID and location from your Azure Quantum workspace:

    MyWorkspace = azure.quantum.Workspace(
        resource_id = "MyResourceID",
        location = "MyLocation"
    )
    
  2. Use the get_targets method to see the available hardware targets in your workspace:

    MyTargets = MyWorkspace.get_targets()
    print("This workspace's targets:")
    MyTargets
    
  3. Select the rigetti.sim.qvm target:

    MyTarget = MyWorkspace.get_targets("rigetti.sim.qvm")
    
  4. Lastly, use the submit method to submit your program with its parameters and display the results:

    job = MyTarget.submit(MyProgram, "MyQuantumJob", shots=100)
    job.get_results()
    
    {'[0, 1, 1, 1]': 0.08,
     '[1, 1, 0, 0]': 0.1,
     '[0, 0, 1, 0]': 0.04,
     '[0, 1, 0, 0]': 0.05,
     '[1, 0, 1, 0]': 0.05,
     '[1, 0, 0, 0]': 0.07,
     '[0, 1, 0, 1]': 0.07,
     '[1, 0, 1, 1]': 0.07,
     '[0, 0, 0, 0]': 0.08,
     '[1, 1, 1, 0]': 0.05,
     '[0, 0, 0, 1]': 0.1,
     '[0, 0, 1, 1]': 0.04,
     '[0, 1, 1, 0]': 0.09,
     '[1, 0, 0, 1]': 0.04,
     '[1, 1, 1, 1]': 0.05,
     '[1, 1, 0, 1]': 0.02}
    
  5. All the properties of the job are accessible in job.details, for example:

    print(job.details)
    print("\nJob name:", job.details.name)
    print("Job status:", job.details.status)
    print("Job ID:", job.details.id)
    
    {'additional_properties': {'isCancelling': False}, 'id': '0150202e-9638-11ee-be2f-b16153380354', 'name': 'MyQuantumJob', 'provider_id': 'rigetti'...}
    Job name: MyQuantumJob
    Job status: Succeeded
    Job ID: 0150202e-9638-11ee-be2f-b16153380354
    

Additional job details

The azure.quantum Python package includes additional methods to display more detailed job data.

  • job.get_results_histogram(): This method returns a dictionary of the outcomes and shot count for each unique measurement. For example, the results for the previous job would be

    print(job.get_results_histogram()) 
    
    {   
        '[0, 1, 1, 1]' : {'Outcome' : [0, 1, 1, 1], 'Count' : 8},  
        '[1, 1, 0, 0]' : {'Outcome' : [1, 1, 0, 0], 'Count' : 10},
        '[0, 0, 1, 0]' : {'Outcome' : [0, 0, 1, 0], 'Count' : 4},
        '[0, 1, 0, 0]' : {'Outcome' : [0, 1, 0, 0], 'Count' : 5},
        '[1, 0, 1, 0]' : {'Outcome' : [1, 0, 1, 0], 'Count' : 5},  
        '[1, 0, 0, 0]' : {'Outcome' : [1, 0, 0, 0], 'Count' : 7},
        '[0, 1, 0, 1]' : {'Outcome' : [0, 1, 0, 1], 'Count' : 7},
        '[1, 0, 1, 1]' : {'Outcome' : [1, 0, 1, 1], 'Count' : 7},
        '[0, 0, 0, 0]' : {'Outcome' : [0, 0, 0, 0], 'Count' : 8},  
        '[1, 1, 1, 0]' : {'Outcome' : [1, 1, 1, 0], 'Count' : 5},
        '[0, 0, 0, 1]' : {'Outcome' : [0, 0, 0, 1], 'Count' : 10},
        '[0, 0, 1, 1]' : {'Outcome' : [0, 0, 1, 1], 'Count' : 4},
        '[0, 1, 1, 0]' : {'Outcome' : [0, 1, 1, 0], 'Count' : 9},  
        '[1, 0, 0, 1]' : {'Outcome' : [1, 0, 0, 1], 'Count' : 4},
        '[1, 1, 1, 1]' : {'Outcome' : [1, 1, 1, 1], 'Count' : 5},
        '[1, 1, 0, 1]' : {'Outcome' : [1, 1, 0, 1], 'Count' : 2}
    }
    
  • job.get_results_shots() : This method returns a list of each shot result. For example, the results for the previous job would be

    print(job.get_results_shots()) 
    
    [ [0, 1, 1, 1], [1, 0, 1, 1], [0, 0, 1, 1], [1, 1, 0, 1], [1, 0, 0, 0], [1, 0, 1, 1], [1, 1, 0, 1], ...]
    

Submitting Python with Q# jobs to Azure Quantum

Learn how to use VS Code to write a Python program that calls Q# operations, connect to Azure using the Python commands or Azure CLI, and submit your job.

Prerequisites

For installation details, see Installing the QDK on VS Code.

Create and import your Q# operations

With the qsharp package, you can store your functions and operations in Q# files and create Q# projects that let you call into any of them from your Python code. This especially helpful when you need to launch a program that takes input parameters.

  1. Follow the steps to create a Q# project.

  2. Open a new text file, add the following Q# code that returns a user-specified number of random bits, and save the file to the /src directory in your project as Source.qs.

    
        operation Random() : Result {
        use q = Qubit();
        H(q);
        let result = M(q);
        Reset(q);
        return result
    }
    
    operation RandomNBits(N: Int): Result[] {
        mutable results = [];
        for i in 0 .. N - 1 {
            let r = Random();
            set results += [r];
        }
        return results
    }
    
  3. In the project root folder (with the qsharp.json file), open another file and save it as randomNum.py.

  4. Add the following code to import the qsharp and azure.quantum modules.

    import qsharp
    import azure.quantum
    
  5. Next, add code to define the Q# project root folder and test run the target operation on the local simulator. The operation is called by <namespace>.<operation_name( )>, and in this case, you are passing in the number of random bits to return.

    Note

    Because no namespace was specified in Source.qs, the compiler uses the file name as the default namespace - Source.RandomNBits(). For more information, see Projects and implicit namespaces.

    qsharp.init(project_root = '../MyProjectRootFolder')
    print(qsharp.eval("Source.RandomNBits(4)"))
    
    [Zero, One, One, Zero]
    
  6. You can also test the operation with the run method, which passes an additional shots parameter, and returns the results in a Python list. In randomNum.py, replace the previous print statement with the following:

    result = qsharp.run("Source.RandomNBits(4)", shots=10)
    for x in result:
        print(x)
    
    [[One, One, One, One],
    [Zero, Zero, One, Zero],
    [One, Zero, Zero, One],
    [Zero, One, Zero, Zero],
    [One, Zero, One, One],
    [One, Zero, One, Zero],
    [One, One, One, Zero],
    [One, One, One, One],
    [Zero, Zero, Zero, One],
    [One, Zero, Zero, One]]
    

Compile your job using the Base profile

When you run programs on the local quantum simulator, you can submit any type of Q# program. However, Azure Quantum hardware targets do not yet support the full capabilities required to run all Q# programs. In order to compile and submit Q# programs to Azure Quantum, you need to set your target profile to tell Q# which capabilities that your target hardware supports. Currently, that is either the Base or Adpative_RI profile. For more information, see Profile types in Azure Quantum.

Note

For Q# only programs in VS Code, VS Code sets the Base profile automatically.

  1. Use the init method to set the profile:

    qsharp.init(project_root = '../MyProjectRootFolder', target_profile=qsharp.TargetProfile.Base)
    

    Note

    Because you are reinitializing your qsharp state, you need to set the project_root parameter again so the compiler knows where to find the RandomNBits operation. This could also have been done in step 5 of the previous procedure.

  2. Then use the compile method to specify the operation or function that is the entry point to your program. The compiled program can then be submitted to any quantum hardware:

    MyProgram = qsharp.compile("Source.RandomNBits(4)")
    

Connect to Azure Quantum and submit your job

You can connect to Azure Quantum and submit your job using a Python-created Workspace object, or connect and submit your job using Azure CLI. Using Azure CLI requires that you save the compiled program as a text file and submit that file using a CLI command.

Now that you have your program compiled into the correct format, create an azure.quantum.Workspace object to connect to Azure Quantum. You'll use the Resource ID of your Azure Quantum workspace in order to connect. The Resource ID and location can be copied from your workspace overview page in the Azure portal.

  1. Add the following code to randomNum.py, filling in your resource ID and location from your Azure Quantum workspace:

    workspace = azure.quantum.Workspace(
        resource_id = "MyResourceID",
        location = "MyLocation"
    )
    
  2. Use the get_targets method to display the available hardware targets in your workspace:

    MyTargets = workspace.get_targets()
    print("This workspace's targets:")
    for x in MyTargets:
        print(x)
    
  3. Select the rigetti.sim.qvm target:

    MyTarget = workspace.get_targets("rigetti.sim.qvm")
    
  4. Lastly, use the submit method to submit your program with its parameters. The job results are returned as a Python dictionary.

    job = MyTarget.submit(MyProgram, "MyPythonJob", shots=100)
    results = job.get_results()
    print("\nResults: ", results)
    
  5. To extract just the values and display them:

    for x in results:
        print(x)
    
    [0, 0, 0, 0]
    0.3
    [1, 0, 0, 0]
    0.1
    [1, 1, 1, 1]
    0.3
    [0, 1, 1, 1]
    0.3
    
  6. All the properties of the job are accessible in job.details, for example:

    print(job.details)
    print("\nJob name:", job.details.name)
    print("Job status:", job.details.status)
    print("Job ID:", job.details.id)
    
    {'additional_properties': {'isCancelling': False}, 'id': '0fc396d2-97dd-11ee-9958-6ca1004ff31f', 'name': 'MyPythonJob', 'provider_id': 'rigetti'...}
    Job name: MyPythonJob
    Job status: Succeeded
    Job ID: fc396d2-97dd-11ee-9958-6ca1004ff31f
    

Additional job details

The azure.quantum Python package includes additional methods to display more detailed job data.

  • job.get_results_histogram(): This method returns a dictionary of the outcomes and shot count for each unique measurement. For example, the results for the previous job would be

    results = job.get_results_histogram()
    for x in results.items():
        print(x)
    
    {   
        '[0, 0, 0, 0]' : {'Outcome' : [0, 0, 0, 0], 'Count' : 30},  
        '[1, 0, 0, 0]' : {'Outcome' : [1, 0, 0, 0], 'Count' : 10},
        '[1, 1, 1, 1]' : {'Outcome' : [1, 1, 1, 1], 'Count' : 30},
        '[0, 1, 1, 1]' : {'Outcome' : [0, 1, 1, 1], 'Count' : 30}
    }
    
  • job.get_results_shots() : This method returns a list of each shot result. For example, the results for the previous job would be

    print(job.get_results_shots()) 
    
    [ [0, 0, 0, 0], [1, 1, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1], [1, 0, 0, 0], [0, 1, 1, 1], [0, 0, 0, 0], ...]