Creating a quantum program
A QuantumProgram
combines a Register
and a Drive
and serves as the main interface for compilation and execution.
from qoolqit import PiecewiseLinearfrom qoolqit import Register, Drive, QuantumProgram
# Defining the Drivewf0 = PiecewiseLinear([1.0, 2.0, 1.0], [0.0, 0.5, 0.5, 0.0])wf1 = PiecewiseLinear([1.0, 2.0, 1.0], [-1.0, -1.0, 1.0, 1.0])drive = Drive(amplitude = wf0, detuning = wf1)
# Defining the Registercoords = [(0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0)]register = Register.from_coordinates(coords)
# Creating the Programprogram = QuantumProgram(register, drive)
Quantum Program:| Register(n_qubits = 4)| Drive(duration = 4.000)| Compiled: False
At this point, the program has not been compiled to any device. As shown above, this is conveniently displayed
when printing the program. It can also be checked through the is_compiled
property.
program.is_compiled
False
Now we instantiate a device and compile the program to that device. Compiling in QoolQit means to translate the adimensional values of time, energy, and distance used when defining the program in the Rydberg analog model to a specific set of values that implement the same set of instructions in a Pulser device, taking into account the Pulser units and the specific parameters of that device. More detailed information on this conversion is provided in the Rydberg analog model page.
from qoolqit import AnalogDevice
device = AnalogDevice()
program.compile_to(device)
Quantum Program:| Register(n_qubits = 4)| Drive(duration = 4.000)| Compiled: True| Device: AnalogDevice
Now that the program has been compiled, we can inspect the compiled sequence, which is an instance of a Pulser Sequence
.
pulser_sequence = program.compiled_sequence
Finally, we can draw both the original program and the compiled sequence.
program.draw()
program.draw(compiled = True)
Compiler profiles
Section titled “Compiler profiles”In the example above the AnalogDevice
was used, and no changes were made to the unit converter. As such, the default was used, which sets the reference energy unit as the maximum amplitude, as described in the Devices page.
When a QoolQit program is compiled to Pulser, several compiler profiles can be used. You can check them in the following enumeration:
from qoolqit import CompilerProfile
print(CompilerProfile)
<Enum 'CompilerProfile':| DEFAULT = 'Default'| MAX_AMPLITUDE = 'MaxAmplitude'| MAX_DURATION = 'MaxDuration'| MIN_DISTANCE = 'MinDistance'>
By default CompilerProfile.DEFAULT
is used, which directly takes the unit converter present in the device and uses it when converting the values.
Other compiler profiles will ignore the unit converter present in the device and utilize their own logic to determine the best possible conversion to achieve a desired compilation directive.
The CompilerProfile.MAX_AMPLITUDE
maps whatever is the maximum amplitude in the drive of your QoolQit program to the device's maximum allowed amplitude:
program.compile_to(device, profile = CompilerProfile.MAX_AMPLITUDE)program.draw(compiled = True)
The CompilerProfile.MAX_DURATION
maps whatever is the duration of your QoolQit program to the device's maximum allowed sequence duration:
program.compile_to(device, profile = CompilerProfile.MAX_DURATION)program.draw(compiled = True)
The CompilerProfile.MIN_DISTANCE
maps whatever is the minimum distance in the register of your QoolQit program to the device's minimum allowed atom separation:
try: program.compile_to(device, profile = CompilerProfile.MIN_DISTANCE)except Exception as error: print(error)
Failed to compile the sequence due to:
The pulse's amplitude goes over the maximum value allowed for the chosen channel.
In this case, you can see the compilation failed because putting the atoms that close together for this program would require setting an amplitude that is larger than what the device allows.