Execution Tutorial - Part 1
This tutorial covers the basics of executing a quantum program using Classiq directly through the Python SDK. It is also possible to use the Classiq Platform to execute quantum algorithms.
For this, we will start by synthesizing the following example from the synthesis tutorial:
from classiq import *
@qfunc
def main(x: Output[QNum[3]], y: Output[QNum]) -> None:
allocate(x)
hadamard_transform(x)
y |= x**2 + 1
qprog = synthesize(main)
show(qprog)
Quantum program link: https://platform.classiq.io/circuit/30HuOnn0LwUGqLIKMlUETImaIfc
This quantum program evaluates the function \(y(x) = x^2 + 1\), for all integers \(x \in [0,7]\). To execute a quantum program and save its results in the Python SDK, create an ExecutionSession
. To sample the states using this object, one can use sample
:
with ExecutionSession(qprog) as es:
results = es.sample()
gio: https://platform.classiq.io/circuit/30HuOnn0LwUGqLIKMlUETImaIfc?login=True&version=0.86.1: Operation not supported
The information from the outputs of the quantum program can be obtained in the form of a dataframe using the dataframe
attribute:
results.dataframe
x | y | count | probability | bitstring | |
---|---|---|---|---|---|
0 | 1 | 2 | 285 | 0.139160 | 000010001 |
1 | 7 | 50 | 262 | 0.127930 | 110010111 |
2 | 5 | 26 | 260 | 0.126953 | 011010101 |
3 | 4 | 17 | 254 | 0.124023 | 010001100 |
4 | 2 | 5 | 253 | 0.123535 | 000101010 |
5 | 6 | 37 | 251 | 0.122559 | 100101110 |
6 | 3 | 10 | 249 | 0.121582 | 001010011 |
7 | 0 | 1 | 234 | 0.114258 | 000001000 |
The information displayed in the dataframe is:
-
counts
shows the number of times each state was measured. -
bitstring
is the bitstring that represents each state measured. -
x
andy
are the numerical representation of the states associated with the measurement. -
probability
is the probability associated with each measured state.
By default, the number of executions of the quantum program is \(2048\). This quantity, called the number of shots, can be modified using ExecutionPreferences
. For instance, if we want to execute the same circuit with \(10{,}000\) shots:
prefs_more_shots = ExecutionPreferences(num_shots=10000)
with ExecutionSession(qprog, execution_preferences=prefs_more_shots) as es:
results_more_shots = es.sample()
The number of counts for each state will grow proportionally with the number of shots:
results_more_shots.dataframe
x | y | count | probability | bitstring | |
---|---|---|---|---|---|
0 | 7 | 50 | 1274 | 0.1274 | 110010111 |
1 | 2 | 5 | 1273 | 0.1273 | 000101010 |
2 | 1 | 2 | 1267 | 0.1267 | 000010001 |
3 | 6 | 37 | 1266 | 0.1266 | 100101110 |
4 | 4 | 17 | 1254 | 0.1254 | 010001100 |
5 | 5 | 26 | 1226 | 0.1226 | 011010101 |
6 | 3 | 10 | 1224 | 0.1224 | 001010011 |
7 | 0 | 1 | 1216 | 0.1216 | 000001000 |
Backend selection
The backend of an execution is the hardware or simulator where the quantum program is executed. To select a specific backend, it is necessary to use its correct Backend Preferences. Check the different Cloud Providers and their backend preferences for execution.
In this section, we will explore two different examples for clarification:
First example: Execution using the state vector simulator from Classiq
A state vector simulator outputs the amplitudes of a quantum program. On real hardware, obtaining these amplitudes requires quantum tomography — the process of measuring in different bases to reconstruct the output state.
Since Classiq provides its own state vector simulator backend, we will use ClassiqBackendPreferences
to define it as the state vector simulator. This information is provided on the Cloud Providers page.
To define the quantum program's execution preferences, use execution_preferences
under ExecutionSession
. In this example, we will perform a simulation with num_shots=1
since the state vector simulator performs an exact simulation of the quantum program.
If no backend is defined in the preferences, then the Classiq simulator is selected by default.
backend_preferences = ClassiqBackendPreferences(
backend_name="simulator_statevector"
) # Always check the Cloud Providers to correctly define the backend.
execution_preferences = ExecutionPreferences(
num_shots=1, backend_preferences=backend_preferences
)
Now, execute the quantum program using execute
.
with ExecutionSession(qprog, execution_preferences=execution_preferences) as es:
results_statevector = es.sample()
The outputs of the quantum program can be displayed using the dataframe
property:
results_statevector.dataframe.head()
x | y | amplitude | probability | bitstring | |
---|---|---|---|---|---|
0 | 7 | 18 | 3.923208e-15+2.775558e- 17j | 1.539233e-29 | 010010111 |
1 | 0 | 33 | 3.014272e-15+0.000000e+ 00j | 9.085836e-30 | 100001000 |
2 | 4 | 49 | 1.538630e-15-5.551115e- 17j | 2.370465e-30 | 110001100 |
3 | 3 | 42 | 1.303117e-15+2.775558e- 17j | 1.698883e-30 | 101010011 |
4 | 5 | 58 | 1.185360e-15+1.387779e- 16j | 1.424337e-30 | 111010101 |
The outputs from the execution obtained via statevector simulator will differ from the default simulator:
-
state_vector
will output adict
containing the bitstrings followed by its numerically evaluated amplitudes. -
parsed_state_vector
will output alist
ofSimulatedState
, each containing the values ofx
andy
followed by its bitstrings and its numerically evaluated amplitudes.