Skip to main content
IBM Quantum Platform
Información sobre la traducción

Próximamente habrá traducciones a otros idiomas de esta página.

Deploy your first managed workflow

  • The code on this page was developed using the following requirements. We recommend using these versions or newer.

    qiskit[all]~=2.6.1
    qiskit-serverless~=0.38.0
    

Use this page to upload a workflow, run it, and get its result. The example workflow optimizes and simulates a Qiskit circuit. It simulates the circuit on classical hardware, so it does not use QPU time.

Before you begin, install the client package and authenticate.

Use AI skills (optional)

To deploy your own code with help from an AI assistant, use the AI skills in the Qiskit Function templates repository.


Write a workflow

Create the folder structure

A managed workflow is a folder of Python files with one entrypoint file. A managed workflow uploads everything in the folder, up to 50 MB, and runs the entrypoint as a script. Because a workflow uploads the whole folder, keep your local files, such as deploy.ipynb, outside the folder. Create the following layout:

hello_world_project/
├── deploy.ipynb         # Your local notebook: upload and run the workflow
└── source_files/         # The working directory that you upload
    └── hello_world.py   # The entrypoint

Write the hello world entrypoint

The entrypoint reads a circuit, optimizes and simulates it, and saves the counts and two-qubit depth. Save the following code as source_files/hello_world.py:

Note

If you read this page as a notebook, the code cell for hello_world.py starts with the %%writefile magic command. When you run this cell, it saves the code to the file instead of running the code.

./source_files/hello_world.py
from qiskit.primitives import StatevectorSampler
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_serverless import Job, get_arguments, save_result, update_status

# Read the arguments that you pass to run()
arguments = get_arguments()
circuit = arguments["circuit"]
shots = arguments.get("shots", 1024)

# Optimize the circuit. Printed text goes to the job's logs.
update_status(Job.OPTIMIZING_HARDWARE)
pass_manager = generate_preset_pass_manager(
    optimization_level=1, basis_gates=["cz", "rz", "sx", "x"]
)
isa_circuit = pass_manager.run(circuit)
two_qubit_depth = isa_circuit.depth(lambda instruction: instruction.operation.num_qubits == 2)
print(f"Two-qubit depth after optimization: {two_qubit_depth}", flush=True)

# Simulate the circuit and return the counts
sampler = StatevectorSampler(seed=1234)
pub_result = sampler.run([isa_circuit], shots=shots).result()[0]
save_result({"counts": pub_result.data.meas.get_counts(), "two_qubit_depth": two_qubit_depth})

The entrypoint uses three functions from qiskit_serverless:

  • get_arguments() returns the keyword arguments that you pass to run(), as a dictionary. Each value must be JSON-serializable, or an object that the client can encode, such as a QuantumCircuit. Encoded objects arrive as the same objects that you passed.
  • update_status(Job.OPTIMIZING_HARDWARE) sets the detailed status RUNNING: OPTIMIZING_FOR_HARDWARE, which you can see while the job runs. See Report progress with update_status().
  • save_result() stores a JSON-serializable value that you read later with job.result(). The workflow returns the counts as a dictionary and the two-qubit depth of the optimized circuit as an integer.

Anything that the workflow writes to standard output, such as the two-qubit depth, goes to the job's logs. To add timestamps and log levels, use the logging module. See Write logs and handle errors.


Upload the workflow

In your local notebook, run the following code from the hello_world_project folder. The code connects with your saved account, defines the workflow, and uploads it. entrypoint is the file that the workflow runs, and working_dir is the folder that you upload:

from qiskit_ibm_catalog import ManagedWorkflow, ManagedWorkflowClient

client = ManagedWorkflowClient()

hello_world = ManagedWorkflow(
    title="hello-world",
    entrypoint="hello_world.py",
    working_dir="./source_files/",
)

hello_world = client.upload(hello_world)

Run the workflow with inputs

Construct a three-qubit GHZ circuit to pass to hello_world as an input:

from qiskit import QuantumCircuit

circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure_all()

Run hello_world with the circuit and the number of shots as keyword arguments. The argument names match the keys that the entrypoint reads with get_arguments():

job = hello_world.run(circuit=circuit, shots=1024)
print(job.job_id)

Output:

54705348-5117-44b7-935b-e6986ef182fa

run() returns a Job after the workflow queues the job. It does not wait for the job to run. The job continues in the cloud after you close your Python session. To find it again later, list your recent jobs with client.jobs().


Get the status, result, and logs

Immediately after you call run(), the status is usually QUEUED:

job.status()

Output:

'QUEUED'

The status changes from QUEUED to INITIALIZING, RUNNING, and then DONE.

job.result() waits until the job ends, then returns the value that the workflow passed to save_result():

job.result()

Output:

{'counts': {'111': 514, '000': 510}, 'two_qubit_depth': 2}
from qiskit.visualization import plot_histogram

plot_histogram(job.result()["counts"])

Output:

Output of the previous code cell

You can read the logs while the job runs. The workflow uploads new lines about every 15 seconds. The logs include the line that the workflow printed:

print(job.logs())

Output:

Two-qubit depth after optimization: 2


Update the workflow

To change a workflow, edit its files and call upload() again with the same title. The new upload replaces the earlier one, and jobs that already started are not affected.

Fields such as arguments_schema and sizes_map keep their stored values when you omit them from the new upload.


Next steps

Recommendations
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.