Skip to content

Simulator Access through Cloud Service

QM can provide access to the QOP simulator in a cloud environment. This product is called QM Simulator as a Service (QM SaaS). The service is available to customers on request to QM and can be used independently of the OPX hardware.

SaaS gives the user access to the QOP simulator, which is a software simulator that emulates the output samples of the OPX hardware. This is particularly useful for development of QUA programs, exploration of OPX features or for integration of testing into CI workflows, all while not requiring access to the hardware.

Installation and Initialization

To use the simulator, you need to have the qm-saas client python package in your python environment (alongside qm-qua and an access token to a cloud service provided by QM. The client package is available on PyPi and can simply be installed via pip or any other package manager with access to the PyPi repository.

pip install qm-saas

The client package provides a client class QmSaas that allows you to interact with the simulator service. This client class provides methods to open and close simulator instances. On construction, it needs to be provided with the user email and password, provided by QM.

from qm_saas import QmSaas

client = QmSaas(email="jondoe@gmail.com", password="password_from_qm")

Handling Simulator Instances

The created client object allows to spawn simulator instances and use them to simulate QUA programs as you would on real OPX hardware. The way this is achieved is that the instance provides connection details for the QuantumMachinesManager object, which direct the QUA program to the cloud simulator. The instance needs to be called with a specific version of the QOP simulator that is supported by the cloud service, which allows to simulate the different feature sets provided by the available QOP software packages.

from qm_saas import QoPVersion

with client.simulator(QoPVersion.v3_2_0) as instance:
    # Use the instance object to simulate QUA programs
    qmm = QuantumMachinesManager(host=instance.host,
                                 port=instance.port,
                                 connection_headers=instance.default_connection_headers)
    # Continue as usual with opening a quantum machine and simulation of a qua program

Note the usage of the additional connection_headers keyword argument in the QuantumMachinesManager object. This is only required when connecting to a cloud simulator instance and not for usage with real hardware (where it is simply None).

Usage of the context manager ensures that the simulator instance is properly spawned before usage and closed when the context is exited. It is also possible to handle the instance manually using spawn() and close() methods on the instance object. We recommend the use of the context manager, not only to ensure that the instance is properly closed after use, but also to ensure the limit of simulator instance is not reached.

instance = client.simulator(QoPVersion.v3_2_0)
instance.spawn()
# Use the simulator instance object to simulate QUA programs
instance.close()

Simulator Instance Lifetime

Each user can have up to 3 connected instances at the same time. The instances are automatically closed after 15 minutes. This is a hard time limit and can lead to loosing access to the instance in the middle of a session. To check the status of the instance, the is_alive() and expires_at() methods can be used, e.g.:

if instance.is_alive():
    print(f"Instance is alive and will expire at {instance.expires_at()}")
else:
    print("Instance is not alive anymore")

Furthermore, one can make sure that no instances are open under by calling the close_all() method on the client object. This will close all the users instances and make sure resources are available. This is useful when the old simulator instance objects are not available anymore.

client.close_all()

Simulation options

The QM SaaS supports the simulation of the OPX+ and OPX1000 products. This is achieved by selecting the respectve QOP version through the QoPVersion enum. The QOP version is passed to the open_instance method when creating an instance. QoPVersion.v2_X_Y will give instances of OPX+ simulators and QoPVersion.v3_X_Y will give instances of OPX1000 simulators, respectively.

Simulation of different OPX+ hardware configurations

For details about simulating different OPX+ hardware configurations, see the QOP simulator guide.

Simulation of different OPX1000 hardware configurations

When simulating the OPX1000, there is a default configuration of 1 OPX1000 with LF-FEMs in slots 1-4 and MW-FEMs in slots 5-8. It is possible to define a custom FEM configuration of the simulator instance. This is done by creating a ClusterConfig object and adding the required controllers and FEMs to it. Initially a controller needs to be added to the configuration via ClusterConfig.controller(). The FEMs can then be added to this controller object via the lf_fem(List[int]) and mw_fem(List[int]) methods. Available slots are 1-8, and both LF FEMs and MW FEMs can be added. Trying to add two FEMs to a single slot will raise an error. Multiple controllers can be added; they are automatically named con1, con2, etc., according to their creation order when leaving the function signature empty, or can be named explicitly on creation, e.g., ClusterConfig.controller("con2").

The ClusterConfig object is then passed to the open_instance method along with the QoPVersion to create an instance with the given configuration.

from qm_saas import ClusterConfig, QoPVersion

cluster_config = ClusterConfig()
controller = cluster_config.controller()
controller.lf_fem([1, 2, 3, 4])
controller.mw_fem([5, 6, 7, 8])

simulated_samples = []

with client.open_instance(QoPVersion.v3_2_0, cluster_config) as instance:
    # Use the instance object to simulate QUA programs on a config of 4 LF and 4 MW FEMs
    qmm = QuantumMachinesManager(host=instance.host,
                                 port=instance.port,
                                 connection_headers=instance.default_connection_headers)
    # Continue as usual with opening a quantum machine and simulation of a qua program
    simulated_job = qmm.simulate(qua_program, qua_config, SimulatorConfig())
    simulated_samples = simulated_job.get_simulated_samples()

# Use the simulated samples to analyze the results.
simulated_samples.con1.plot()