### CMake Configuration for CPU-only OPNIC Applications Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide This CMake example demonstrates the basic configuration required for building CPU-only applications that utilize the OPNIC SDK. It sets the C++ standard to C++20, finds the necessary `opnic` and `OpenSSL` packages, defines an executable, and links it against the appropriate OPNIC library for CPU execution. ```CMake # OPNIC SDK requires C++20 set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Find opnic library and its OpenSSL dependency find_package(opnic CONFIG REQUIRED) find_package(OpenSSL REQUIRED) # Add the executable add_executable(hello_cpu ${CMAKE_SOURCE_DIR}/hello_cpu.cpp) # Link the application to the opnic SDK. # If the library was built for a GH200 without a GPU, link to qm::opnic instead target_link_libraries(hello_cpu PRIVATE qm::opnic-cuda) ``` -------------------------------- ### Install QM SaaS Python Client Source: https://docs.quantum-machines.co/latest/docs/Guides/qm_saas_guide Instructions for installing the `qm-saas` client Python package, which is necessary to interact with the QM Simulator as a Service. This package is available on PyPi and can be installed using pip. ```Bash pip install -U qm-saas ``` -------------------------------- ### Initialize QuantumMachinesManager in Python Source: https://docs.quantum-machines.co/latest/docs/Hardware/opx+installation This snippet demonstrates how to import and initialize the `QuantumMachinesManager` object in Python to establish communication with the Quantum Machines cluster. It requires passing correct arguments for cluster access. ```Python from qm import QuantumMachinesManager QuantumMachinesManager(*args) ``` -------------------------------- ### Full QUA Program for DGX Communication Example Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide A complete QUA program demonstrating the declaration of packet structs and streams, assigning a value to an outgoing packet, sending it to the GH200, receiving a response, and saving both sent and received data for analysis. ```QUA with program() as prog: # Define two types of packets (with the same structure) inc_struct = declare_struct(TestPacket) out_struct = declare_struct(TestPacket) # Define the incoming and outgoing streams, which use the above packet structure inc_stream = declare_external_stream(TestPacket, stream_id_incoming, QuaStreamDirection.INCOMING) out_stream = declare_external_stream(TestPacket, stream_id_outgoing, QuaStreamDirection.OUTGOING) # Assign a value to the packet assign(out_struct.data[0], 554); # Send the packet to the GH200 send_to_external_stream(out_stream, out_struct); # Wait for the result. This is a blocking call receive_from_external_stream(inc_stream, inc_struct); # Save both values - the one that was sent and the one that was received save(inc_struct.data[0], "inc_data"); save(out_struct.data[0], "out_data"); ``` -------------------------------- ### Install QM-QUA Python Package Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation This command installs or upgrades the `qm-qua` Python package using pip. This package provides the necessary libraries for interacting with Quantum Machines hardware from a Python environment. ```Shell pip install --upgrade qm-qua ``` -------------------------------- ### Example QUA Configuration Structure in Python Source: https://docs.quantum-machines.co/latest/docs/Introduction/config This snippet illustrates the top-level structure of a QUA configuration dictionary in Python. It outlines the primary sections such as 'version', 'controllers', 'elements', and 'pulses', each representing a distinct part of the quantum machine setup. The configuration is presented as a Python dictionary containing nested dictionaries for various components. ```Python config = { 'version': 1, 'controllers': {...}, 'octaves': {...}, 'elements': {...}, 'pulses': {...}, 'waveforms': {...}, 'digital_waveforms': {...}, 'integration_weights': {...}, 'mixers': {...}, 'oscillators': {...} } ``` -------------------------------- ### Python Example: Add Job to Queue Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Examples demonstrating how to add a program to the job queue, either at the end or at a specific position. ```Python qm.queue.add(program) # adds at the end of the queue qm.queue.insert(program, position) # adds at position ``` -------------------------------- ### Python Example: Get Job Queue Count Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Example demonstrating how to retrieve the number of jobs currently in the queue using the 'count' property. ```Python qm.queue.count ``` -------------------------------- ### Install Quantum Machines Python Package Source: https://docs.quantum-machines.co/latest/docs/Hardware/opx%2Binstallation Command to install or upgrade the 'qm-qua' Python package using pip, ensuring the latest version is available in the desired Python environment. ```Shell pip install --upgrade qm-qua ``` -------------------------------- ### QuantumMachinesManager API Reference Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation Reference for the `QuantumMachinesManager` class, used to establish and manage connections to the Quantum Machines cluster. ```APIDOC Class: QuantumMachinesManager Description: Manages connection to the Quantum Machines cluster. Constructor: __init__(*args) Parameters: *args: Variable arguments required for connecting to the cluster. Refer to network configuration documentation for details. Returns: An instance of QuantumMachinesManager. ``` -------------------------------- ### OPX1000 Connectivity for 5 Devices Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation Details the required Clock, QSync, and Communication port connections for a system with five OPX1000 devices. Each OPX1000 needs at least two FEMs installed in slots 1 and 5. ```APIDOC Clock Connections: - From OPX1, Clock Out Port 1 -> To OPX2, Clock In Port 1 - From OPX1, Clock Out Port 2 -> To OPX3, Clock In Port 1 - From OPX1, Clock Out Port 3 -> To OPX4, Clock In Port 1 - From OPX1, Clock Out Port 4 -> To OPX5, Clock In Port 1 QSync Connections: - From OPX1, QSync Port 1 -> To OPX2, QSync Port 1 - From OPX1, QSync Port 2 -> To OPX3, QSync Port 1 - From OPX1, QSync Port 3 -> To OPX4, QSync Port 1 - From OPX1, QSync Port 4 -> To OPX5, QSync Port 1 Communication Connections: - From OPX1, Comm Port 4 -> To OPX2, Comm Port 4 - From OPX1, Comm Port 3 -> To OPX3, Comm Port 4 - From OPX1, Comm Port 2 -> To OPX4, Comm Port 4 - From OPX1, Comm Port 1 -> To OPX5, Comm Port 4 - From OPX2, Comm Port 3 -> To OPX3, Comm Port 3 - From OPX2, Comm Port 2 -> To OPX4, Comm Port 3 - From OPX2, Comm Port 1 -> To OPX5, Comm Port 3 - From OPX3, Comm Port 2 -> To OPX4, Comm Port 2 - From OPX3, Comm Port 1 -> To OPX5, Comm Port 2 - From OPX4, Comm Port 1 -> To OPX5, Comm Port 1 ``` -------------------------------- ### OPX1000 Connectivity for 2 Devices Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation Details the required Clock, QSync, and Communication port connections for a system with two OPX1000 devices. Each OPX1000 needs at least one FEM installed in slot 1. ```APIDOC Clock Connections: - From OPX1, Clock Out Port 1 -> To OPX2, Clock In Port 1 QSync Connections: - From OPX1, QSync Port 1 -> To OPX2, QSync Port 1 Communication Connections: - From OPX1, Comm Port 4 -> To OPX2, Comm Port 4 ``` -------------------------------- ### OPX1000 Connectivity for 3 Devices Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation Details the required Clock, QSync, and Communication port connections for a system with three OPX1000 devices. Each OPX1000 needs at least one FEM installed in slot 1. ```APIDOC Clock Connections: - From OPX1, Clock Out Port 1 -> To OPX2, Clock In Port 1 - From OPX1, Clock Out Port 2 -> To OPX3, Clock In Port 1 QSync Connections: - From OPX1, QSync Port 1 -> To OPX2, QSync Port 1 - From OPX1, QSync Port 2 -> To OPX3, QSync Port 1 Communication Connections: - From OPX1, Comm Port 4 -> To OPX2, Comm Port 4 - From OPX1, Comm Port 3 -> To OPX3, Comm Port 4 - From OPX2, Comm Port 3 -> To OPX3, Comm Port 3 ``` -------------------------------- ### Additional CMake Configuration for GPU-enabled OPNIC Applications Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide This CMake snippet provides the additional configuration steps required to enable GPU support for OPNIC applications. It specifies CUDA compiler options, sets the target CUDA architecture to 'native' for optimal performance on the host machine, and links the application against both the `qm::opnic-cuda` library and the CUDA runtime library (`CUDA::cudart`). This configuration is appended to the base CPU CMake setup. ```CMake # OPNIC applications on the gpu require this CUDA compiler flag target_compile_options(hello_gpu PRIVATE $<$:--expt-relaxed-constexpr>) # Indicate to CUDA to use the GPU architecture located on this machine ('native') set_target_properties(hello_gpu PROPERTIES CUDA_ARCHITECTURES "native" ) # Link the application to the OPNIC SDK and CUDA runtime target_link_libraries(hello_gpu PRIVATE qm::opnic-cuda CUDA::cudart ) ``` -------------------------------- ### OPX1000 Connectivity for 4 Devices Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation Details the required Clock, QSync, and Communication port connections for a system with four OPX1000 devices. Each OPX1000 needs at least two FEMs installed in slots 1 and 5. ```APIDOC Clock Connections: - From OPX1, Clock Out Port 1 -> To OPX2, Clock In Port 1 - From OPX1, Clock Out Port 2 -> To OPX3, Clock In Port 1 - From OPX1, Clock Out Port 3 -> To OPX4, Clock In Port 1 QSync Connections: - From OPX1, QSync Port 1 -> To OPX2, QSync Port 1 - From OPX1, QSync Port 2 -> To OPX3, QSync Port 1 - From OPX1, QSync Port 3 -> To OPX4, QSync Port 1 Communication Connections: - From OPX1, Comm Port 4 -> To OPX2, Comm Port 4 - From OPX1, Comm Port 3 -> To OPX3, Comm Port 4 - From OPX1, Comm Port 2 -> To OPX4, Comm Port 4 - From OPX2, Comm Port 3 -> To OPX3, Comm Port 3 - From OPX2, Comm Port 2 -> To OPX4, Comm Port 3 - From OPX3, Comm Port 2 -> To OPX4, Comm Port 2 ``` -------------------------------- ### Python Example: Basic and Advanced `play` Usage in QUA Source: https://docs.quantum-machines.co/latest/docs/API_references/qua/dsl_main This example illustrates how to use the `play` command within a QUA program. It demonstrates basic pulse playback, amplitude modulation with both fixed and variable values, and the implementation of timestamp streaming for collecting execution results. ```python with program() as prog: v1 = declare(fixed) assign(v1, 0.3) play('pulse1', 'element1') play('pulse1' * amp(0.5), 'element1') play('pulse1' * amp(v1), 'element1') play('pulse1' * amp(0.9, v1, -v1, 0.9), 'element_iq_pair') time_stream = declare_stream() # Supported on QOP2.2+ play('pulse1', 'element1', duration=16, timestamp_stream='t1') play('pulse1', 'element1', duration=16, timestamp_stream=time_stream) with stream_processing(): stream.buffer(10).save_all('t2') ``` -------------------------------- ### GPU Stream Declaration for OPX1000 Communication in C++ Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide This C++ snippet illustrates the declaration of incoming and outgoing data streams configured to run on the GPU, leveraging the `opnic.hpp` library. It defines the same packet structure as the CPU example but specifies `qm::StreamType::GPU` for stream instantiation, indicating an intent for GPU-accelerated processing. The provided example is partial, hinting at parallel reduction operations. ```C++ #include // Define the stream IDs. Each stream needs a unique ID, between 1 and 1023 (stream 0 is reserved) #define OUTGOING_STREAM_ID 1 #define INCOMING_STREAM_ID 2 // Define the buffer size for the incoming stream. The OPX1000 side may send packets asynchronously, and the buffer is cyclic. #define BUFFER_SIZE 100 // In units of packets // Define a packet struct. In this example we use the same packet structure for both streams, so we define it once struct MyPacket { // We define one field, an integer array of size '1' (every field is an array, even if it's only one item). // Available types are int, bool, double (cast from qua-fixed) and qm::fixed (does not cast from qua-fixed type) qm::Value data; // Mandatory macro to declare the packet (needed by the SDK for serialization/deserialization). // If we have more than one struct field, append them as additional arguments QM_DECLARE_PACKET(MyPacket, data); }; // Declare the streams. In this example we declare two streams, one for incoming packets and one for outgoing packets. // Each stream runs on the GPU using InStream = qm::IncomingStream; using OutStream = qm::OutgoingStream; // In this example we show a parallel reduction of the incoming packets. // We will sum the values of the incoming packets and send the result to the outgoing stream. ``` -------------------------------- ### Add QmJob to Start of Queue Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_api Adds a `QmJob` to the start of the queue. Programs in the queue will play as soon as possible. ```APIDOC QmQueue.add_to_start(program: Program, compiler_options: Optional[CompilerOptionArguments] = None) program: A QUA program compiler_options: Optional arguments for compilation ``` -------------------------------- ### Simulate with LoopbackInterface in Python Source: https://docs.quantum-machines.co/latest/docs/API_references/simulator_api Example demonstrating how to use `LoopbackInterface` within `SimulationConfig` to simulate a loopback connection from an output to an input on a controller. ```python job = qmm.simulate(config, prog, SimulationConfig( duration=20000, # loopback from output 1 to input 2 of controller 1: simulation_interface=LoopbackInterface([("con1", 1, "con1", 2)]) ``` -------------------------------- ### Install QUA Tools Python Package Source: https://docs.quantum-machines.co/latest/docs/Libraries/tools_repository Installs or upgrades the `qualang-tools` Python package using pip. This package provides various tools useful for writing QUA programs and performing experiments. Note that some tools may require additional package installations. ```Shell pip install --upgrade qualang-tools ``` -------------------------------- ### OPX1000 Connectivity for 6-8 Devices Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation Details the required Clock and QSync port connections for a system with six to eight OPX1000 devices. Each OPX1000 needs at least four FEMs installed in slots 1, 3, 5, and 7. The communication table for this configuration is not provided in the source documentation. ```APIDOC Clock Connections: - From OPX1, Clock Out Port 1 -> To OPX2, Clock In Port 1 - From OPX1, Clock Out Port 2 -> To OPX3, Clock In Port 1 - From OPX1, Clock Out Port 3 -> To OPX4, Clock In Port 1 - From OPX1, Clock Out Port 4 -> To OPX5, Clock In Port 1 - From OPX2, Clock Out Port 1 -> To OPX6, Clock In Port 1 - From OPX2, Clock Out Port 2 -> To OPX7, Clock In Port 1 - From OPX2, Clock Out Port 3 -> To OPX8, Clock In Port 1 QSync Connections: - From OPX1, QSync Port 1 -> To OPX2, QSync Port 1 - From OPX1, QSync Port 2 -> To OPX3, QSync Port 1 ``` -------------------------------- ### Python Example: Set Output DC Offset by Element Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Examples demonstrating how to use the 'qm.set_output_dc_offset_by_element' function to adjust DC offsets for different element configurations. ```Python qm.set_output_dc_offset_by_element('flux', 'single', 0.1) qm.set_output_dc_offset_by_element('qubit', 'I', -0.01) qm.set_output_dc_offset_by_element('qubit', ('I', 'Q'), (-0.01, 0.05)) ``` -------------------------------- ### Simulate with RawInterface in Python Source: https://docs.quantum-machines.co/latest/docs/API_references/simulator_api Example demonstrating how to use `RawInterface` within `SimulationConfig` to define raw samples as input to a controller. ```python job = qmm.simulate(config, prog, SimulationConfig( duration=20000, # 500 ns of DC 0.2 V into con1 input 1 simulation_interface=RawInterface([("con1", 1, [0.2]*500)]) ``` -------------------------------- ### Compile QUA Program and Add to Queue (Python) Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Demonstrates how to compile a QUA program using `qm.compile` to obtain a `program_id`, then add it to the queue and wait for it to start running. ```python program_id = qm.compile(program) job = qm.add_to_queue(program_id) job.wait_until("running") ``` -------------------------------- ### Legacy QUA Stream Declaration with save_all() Source: https://docs.quantum-machines.co/latest/docs/Guides/stream_proc Provides an example of the older, equivalent syntax for declaring a QUA stream and terminating it directly with `save_all()` within the `stream_processing` block, demonstrating a simpler way to save all results to a terminal without intermediate pipeline steps. ```Python with program() as prog: my_stream = declare_stream() a = declare(fixed) assign(a, 0.3) save(a, my_stream) with stream_processing(): my_stream.save_all('a_results') ``` -------------------------------- ### Python Example: Get Pending Job by ID Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Example demonstrating how to retrieve a specific pending job from the queue using its job ID. ```Python qm.queue.get(job_id) ``` -------------------------------- ### QUA Stream Buffer and Skip Example Source: https://docs.quantum-machines.co/latest/docs/API_references/qua/result_stream Illustrates the buffer_and_skip method for gathering stream items into vectors while skipping elements. The example shows how different length and skip parameters affect the output, demonstrating the difference between buffer(n) and buffer_and_skip(n, n) and other skip patterns. The expected output for a sample input stream is provided. ```python # The stream input is [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] with stream_processing(): stream.buffer(3).save_all("example1") stream.buffer_and_skip(3, 3).save_all("example2") stream.buffer_and_skip(3, 2).save_all("example3") stream.buffer_and_skip(3, 5).save_all("example4") # example1 -> [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # example2 -> [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # example3 -> [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]] # example4 -> [[1, 2, 3], [6, 7, 8]] ``` -------------------------------- ### API Reference: qm_saas.client.ClusterConfig Source: https://docs.quantum-machines.co/latest/docs/API_references/simulator_api Configuration class for defining a cluster setup within the QM SAAS client, including controller details. ```APIDOC qm_saas.client.ClusterConfig: properties: controllers controller methods: to_dict() ``` -------------------------------- ### Add Job to Queue Start Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_api Adds a QUA program to the very beginning of the job queue. Programs added this way will be played as soon as possible, prioritizing them over other queued jobs. ```APIDOC qm.jobs.job_queue_base.QmQueueBase.add_to_start( program: Program, compiler_options: Optional[CompilerOptionArguments] = None ) ``` -------------------------------- ### Initialize QuantumMachinesManager in Python Source: https://docs.quantum-machines.co/latest/docs/Hardware/OPX1000_installation This snippet demonstrates how to import and instantiate the `QuantumMachinesManager` object from the `qm` library. This object is essential for establishing and managing connections to the Quantum Machines cluster. It requires specific arguments for connection, which are detailed in the network overview documentation. ```Python from qm import QuantumMachinesManager qmm = QuantumMachinesManager(*args) ``` -------------------------------- ### Create Quantum Machines Simulator with Specific QOP Version Source: https://docs.quantum-machines.co/latest/docs/Guides/qm_saas_guide This example shows how to initialize a Quantum Machines simulator instance with a specific QOP version using `QOPVersion` and `client.simulator()`. It also demonstrates how to integrate this instance with `QuantumMachinesManager` for program simulation. ```Python from qm_saas import QOPVersion from qm import QuantumMachinesManager with client.simulator(QOPVersion("v3_3_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 ``` -------------------------------- ### Access Specific Result Handles in Python Source: https://docs.quantum-machines.co/latest/docs/Guides/stream_proc Demonstrates how to retrieve a specific result handle from a `RunningQmJob` object's `results_handles` property using either the `get()` method or a shorthand attribute access for convenience. ```python my_result = job.results_handles.get("my_result") ``` ```python my_result = job.results_handles.my_result ``` -------------------------------- ### Initialize QmSaas Client for Cloud Simulator Source: https://docs.quantum-machines.co/latest/docs/Guides/qm_saas_guide Demonstrates how to import the `QmSaas` class from the `qm_saas` package and create an instance of the client. This client object requires an email and password provided by QM to authenticate and interact with the cloud simulator service. ```Python from qm_saas import QmSaas client = QmSaas(email="jondoe@gmail.com", password="password_from_qm") ``` -------------------------------- ### qm_saas.client Module API Reference Source: https://docs.quantum-machines.co/latest/docs/API_references/simulator_api API documentation for the `qm_saas.client` module, including `ClusterConfig`, `ControllerConfig`, `FemType`, and `QOPVersion` classes, their properties, and methods. ```APIDOC qm_saas.client.ClusterConfig: Description: A configuration of the cluster and its controllers. Methods: controllers (property): Returns: dict Description: Get the controllers' configuration. controller(): Returns: qm_saas.client.ControllerConfig Description: Add a controller to the cluster configuration. to_dict(): Returns: dict Description: Convert the cluster configuration to a dictionary. qm_saas.client.ControllerConfig: Description: A configuration of a controller and its FEMs in the cluster. Methods: slots (property): Returns: dict Description: Get the slots' FEM configuration. lf_fems(*slots: int = ()): Description: Add LF FEMs to numbered slots in the cluster configuration. mw_fems(*slots: int = ()): Description: Add MW FEMs to numbered slots in the cluster configuration. qm_saas.client.FemType (enum): Description: An enum containing the available Front-End Module (FEM) types. qm_saas.client.QOPVersion: Description: Represents a Quantum Orchestration Platform (QOP) version. Constructor: __init__(name: str): Description: Initialize a QmSaasInstanceVersion instance. Attributes: name (property): str Description: The name of the version. major (property): int Description: The major version number. minor (property): int Description: The minor version number. patch (property): int Description: The patch version number. ``` -------------------------------- ### QUA Packet Structure and Stream Definition Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide Defines a QUA struct `TestPacket` for data transfer and declares incoming/outgoing external streams using this packet structure. This setup is fundamental for establishing communication channels between QUA and external systems like the GH200. ```QUA from qm import DictQuaConfig, QuantumMachinesManager from qm.qua import * stream_id_outgoing = 1 stream_id_incoming = 2 # Define a qua_struct with the packet structure. In this example each packet has one qua-int # Note that each field of the struct is a qua-array, even if it has only one element @qua_struct class TestPacket: data: QuaArray[int, 1] ``` -------------------------------- ### API Documentation for get_config method Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_api Gets the current config of the qm. ```APIDOC get_config() -> DictQuaConfig Returns: DictQuaConfig: A dictionary with the QMs config ``` -------------------------------- ### Declare Packet Structure for DGX Quantum Communication Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide This snippet demonstrates how to define a custom packet structure for data exchange between the OPX1000 and GH200. It includes examples for both QUA and C++, showing how to declare fields for various data types (integer, fixed-point, boolean) that will be used in streams. ```QUA @qua_struct class MyPacket: data_int: QuaArray[int, 1] data_fixed: QuaArray[fixed, 2] data_bool: QuaArray[bool, 2] with program() as prog: incoming_pkt = declare_struct(MyPacket) ``` ```C++ struct MyPacket { qm::Value int_data; qm::Value fixed_data; qm::Value bool_data; QM_DECLARE_PACKET(MyPacket, int_data, fixed_data, bool_data); }; ``` -------------------------------- ### Configure and simulate OPX1000 with custom FEMs using qm_saas Source: https://docs.quantum-machines.co/latest/docs/Guides/qm_saas_guide This Python code demonstrates how to define a custom FEM configuration for the OPX1000 simulator. It initializes a `ClusterConfig`, adds LF and MW FEMs to a controller, and then uses this configuration to create a simulator instance. The example proceeds to set up a `QuantumMachinesManager` and simulate a QUA program, finally plotting the simulated samples. ```python from qm_saas import ClusterConfig, client, QOPVersion cluster_config = ClusterConfig() controller = cluster_config.controller() controller.lf_fems(1, 2, 3, 4) controller.mw_fems(5, 6, 7, 8) with client.simulator(QOPVersion("v3_3_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 job = qmm.simulate(qua_config, qua_program, SimulationConfig(int(1e4))) job.wait_until("Done", timeout=10) simulated_samples = job.get_simulated_samples() # Use the simulated samples to analyze the results. simulated_samples.con1.plot() ``` -------------------------------- ### Initialize QuantumMachinesManager in Python Source: https://docs.quantum-machines.co/latest/docs/Hardware/opx%2Binstallation This snippet shows how to import the 'QuantumMachinesManager' class from the 'qm' library and instantiate it. It requires passing correct arguments for cluster access to communicate with the QM system. ```Python from qm import QuantumMachinesManager QuantumMachinesManager(*args) ``` -------------------------------- ### List Supported Quantum Machines QOP Versions Source: https://docs.quantum-machines.co/latest/docs/Guides/qm_saas_guide This code iterates through and prints all available QOP versions supported by the Quantum Machines client, useful for identifying compatible simulation environments. ```Python print("Supported versions:") for version in client.versions(): print(f"\t- {version}") ``` -------------------------------- ### Declare External Streams for DGX Quantum Communication Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide This snippet illustrates how to declare external streams for asynchronous data flow between the OPX1000 and GH200. It provides examples for both QUA and C++, showing how to associate streams with a defined packet structure, specify direction (incoming/outgoing), and set properties like buffer size. ```QUA incoming_stream = declare_external_stream(MyPacket, stream_id_incoming, QuaStreamDirection.INCOMING) outgoing_stream = declare_external_stream(MyPacket, stream_id_outgoing, QuaStreamDirection.OUTGOING) ``` ```C++ using incoming_stream = qm::IncomingStream; using outgoing_stream = qm::OutgoingStream; ``` -------------------------------- ### QUA `for_` Loop for Iterative Pulse Generation Source: https://docs.quantum-machines.co/latest/docs/Guides/features Illustrates the `for_()` loop in QUA, which functions similarly to a Python `for` loop with a `(var, start, end_cond, step)` structure. This example shows how to iterate and use a QUA variable for pulse parameters like duration, playing a pulse five times. ```QUA t = declare(int) with for_(t, 10, t < 15, t+1): play('pulse', 'qe', duration=t) ``` -------------------------------- ### API Reference: qm_saas.client Module Source: https://docs.quantum-machines.co/latest/docs/API_references/simulator_api Overview of the client module for interacting with the QM Cloud Simulator as a Service (SAAS). ```APIDOC qm_saas.client ``` -------------------------------- ### OPX1000 to GH200 Handshake Synchronization Source: https://docs.quantum-machines.co/latest/docs/Guides/DGXQ_Guide Illustrates the use of `qm::sync()` for synchronizing the OPX1000 with the GH200. This blocking call ensures that streams are initialized and the handshake is completed before program execution proceeds. ```C++ qm::sync(); // blocking call, will wait for the OPX1000 to initialize the streams and send the handshake ``` -------------------------------- ### Check QM Device IP Addresses via SSH Source: https://docs.quantum-machines.co/latest/docs/Hardware/opx+installation This command-line snippet demonstrates how to check the IP addresses of connected Quantum Machines devices using SSH. It connects to the QM router's default IP (192.168.88.1) and prints the ARP table to identify device IPs based on their MAC addresses. Ensure your computer is connected to the QM router's local network (ports 2-10). ```shell ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -m hmac-sha1,hmac-md5 admin@192.168.88.1 ip arp print ``` -------------------------------- ### Simulate Loopback Connection with LoopbackInterface Source: https://docs.quantum-machines.co/latest/docs/Guides/simulator Demonstrates how to simulate a connection from an OPX output to an input using the LoopbackInterface within the qmm.simulate() method. This example creates a virtual connection from controller 'con1', output 1 to input 2. ```Python qmm.simulate(config, prog, SimulationConfig(duration, simulation_interface=LoopbackInterface([("con1", 1, "con1", 2)])) ``` -------------------------------- ### Initializing and Opening a Quantum Machine Connection Source: https://docs.quantum-machines.co/latest/docs/Introduction/use_case This code demonstrates how to create an instance of `QuantumMachinesManager` and then open a connection to a quantum machine using a predefined configuration. This establishes the interface for executing QUA programs. ```Python qmm = QuantumMachinesManager() # creates a manager instance qm = qmm.open_qm(config) # opens a quantum machine with the specified configuration ``` -------------------------------- ### QuantumMachinesManager.simulate Method and Example Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_manager_api Simulates the outputs of a deterministic QUA program. Requires a QM configuration, a QUA program object, and a simulation configuration. Returns a `QmJob` object. ```APIDOC simulate(config: A QM config, program: A QUA program, simulate: SimulationConfig, compiler_options: additional parameters, strict: deprecated, flags: deprecated) -> Union[SimulatedJob, SimulatedJobApi] config: A QM config program: A QUA program() object to execute simulate: A SimulationConfig configuration object compiler_options: additional parameters to pass to execute strict: a deprecated option for the compiler flags: deprecated way to provide flags to the compiler Returns: a QmJob object (see Job API). ``` ```Python from qm.qua import * from qm import SimulationConfig, QuantumMachinesManager qmm = QuantumMachinesManager() with program() as prog: play('pulse1', 'qe1') job = qmm.simulate(config, prog, SimulationConfig(duration=100)) ``` -------------------------------- ### Get Pending Job by Position Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_api Gets the pending job object at the specified position in the queue. ```APIDOC QmQueue.get_at(position: int) -> QmPendingJob position: An integer position in queue Returns: The pending job ``` ```python qm.queue.get(job_id) ``` -------------------------------- ### Python Example: Remove Job from Queue by ID Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Example demonstrating how to remove a specific pending job from the queue using its job ID. ```Python qm.queue.remove_by_id(job_id) ``` -------------------------------- ### QUA `measure` Function Python Example Source: https://docs.quantum-machines.co/latest/docs/API_references/qua/dsl_main Example demonstrating the usage of the `measure` function within a QUA program, including variable declaration and measurement calls. ```Python with program() as prog: I = declare(fixed) Q = declare(fixed) adc_st = declare_stream(adc_trace=True) # measure by playing 'meas_pulse' to element 'resonator', do not save raw results. # demodulate data from "out1" port of 'resonator' using 'cos_weights' and store result in I, and also # demodulate data from "out1" port of 'resonator' using 'sin_weights' and store result in Q ``` -------------------------------- ### Example Analog Output Port Configuration for OPX Source: https://docs.quantum-machines.co/latest/docs/Introduction/config This snippet illustrates a specific configuration for a single analog output port within an OPX controller's dictionary. It shows how to define an offset (e.g., 20 mV) and a delay (e.g., 71 ns) for a port, which are crucial parameters for fine-tuning quantum control signals. ```Python 1: {'offset': 0.02, 'delay': 71} ``` -------------------------------- ### API Method: get_input_dc_offset_by_element Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Deprecated - This method is going to be removed, please get the value from `qm.get_config()`. Get the current DC offset of the OPX analog input channel associated with an element. ```APIDOC get_input_dc_offset_by_element( element: str, output: str ) -> float Parameters: element (str): the name of the element to get the correction for output (str): the output key name as appears in the element config under 'outputs'. Returns: float: The offset, in volts ``` -------------------------------- ### Deserialize and Load Quantum Machines Simulator Instance Source: https://docs.quantum-machines.co/latest/docs/Guides/qm_saas_guide This snippet demonstrates how to load a previously serialized Quantum Machines simulator instance from a file using `pickle.load`. It also shows how `instance.spawn()` can be used to ensure the instance is active without creating a new one if it already exists. ```Python import pickle instance = pickle.load(open("path/to/instance.pkl", "rb")) # The spawn command will not trigger the creation of a new instance if there is already an instance opened with the # same id. instance.spawn() ... # Use the instance to simulate ... instance.close() ``` -------------------------------- ### QuantumMachinesManager.open_qm_from_file Method Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_manager_api Opens a new quantum machine with configuration loaded from a specified file on the local file system. ```APIDOC open_qm_from_file(filename: str, close_other_machines: bool = True) -> Union[QuantumMachine, QmApi] filename: The path to the file that contains the config close_other_machines: Flag whether to close all other running machines Returns: A quantum machine obj that can be used to execute programs ``` -------------------------------- ### Example Usage of rand_fixed Method Source: https://docs.quantum-machines.co/latest/docs/API_references/qua/random This example demonstrates how to initialize an instance of the `Random` class and use its `rand_fixed` method to generate a pseudo-random fixed-point number. The generated value is then assigned to a QUA variable. ```Python a = Random() assign(b, a.rand_fixed()) ``` -------------------------------- ### Full QUA Program with Stream Processing and Multiple Terminals Source: https://docs.quantum-machines.co/latest/docs/Guides/stream_proc Presents a complete QUA program demonstrating the creation of multiple streams, saving different types of data (ADC traces and variable values), and defining stream processing logic within a `with stream_processing()` block. It showcases the use of `save` and `save_all` terminals for result storage. ```Python with program() as prog: my_stream1 = declare_stream(adc_trace=True) my_stream2 = declare_stream() a = declare(fixed) assign(a, 0.3) save(a, my_stream2) measure('my_pulse', 'qe', my_stream1) with stream_processing(): my_stream1.input1().with_timestamps().save('adc_results') my_stream2.save_all('a_results') ``` -------------------------------- ### Simulate Raw ADC Signal Input with RawInterface Source: https://docs.quantum-machines.co/latest/docs/Guides/simulator Shows how to explicitly specify a signal passed into the OPX during simulation using the RawInterface. This example plays a 1 microsecond signal to input 1 of the device 'con1', also demonstrating the 'noisePower' and 'latency' options for the raw input. ```Python signal = np.linspace(0, 0.2, 1000).tolist() qmm.simulate(config, prog, SimulationConfig(duration, simulation_interface=RawInterface([("con1",1,signal)], noisePower=1, latency=100)) ``` -------------------------------- ### Python Example: Using MapFunctions.demod for Stream Processing Source: https://docs.quantum-machines.co/latest/docs/API_references/qua/result_stream Demonstrates how to use the `demod` static method within a `stream_processing` block to demodulate acquired data. Shows examples for both non-integrated and integrated demodulation results. ```Python with stream_processing(): adc_stream.input1().with_timestamps().map(FUNCTIONS.demod(freq, 1.0, 0.0, integrate=False)).average().save('cos_env') adc_stream.input1().with_timestamps().map(FUNCTIONS.demod(freq, 1.0, 0.0)).average().save('cos_result') # Default is integrate=True ``` -------------------------------- ### Basic Octave API Initialization and Calibration Source: https://docs.quantum-machines.co/latest/docs/Guides/octave Initializes `QmOctaveConfig` and `QuantumMachinesManager`, adds device info, sets the Octave clock mode to internal, and performs automatic calibration for the `resonator` element. This demonstrates the fundamental steps to interact with the Octave via QUA API. ```python from qm.octave.octave_manager import ClockMode octave_config = QmOctaveConfig() octave_config.set_calibration_db(os.getcwd()) octave_config.add_device_info("octave1", octave_ip, octave_port) qmm = QuantumMachinesManager(host=opx_ip, port=opx_port, octave=octave_config) qm = qmm.open_qm(config) # clock settings # qm.octave.set_clock("octave1", clock_mode=ClockMode.Internal) # automatic calibration # qm.calibrate_element("resonator") ``` -------------------------------- ### Python: Example of 'auto-element-thread' Compilation Flag Source: https://docs.quantum-machines.co/latest/docs/Guides/features This specific example illustrates how to apply the 'auto-element-thread' compilation flag using `CompilerOptionArguments` when executing a QUA program. This flag enables automatic core allocation during execution. ```python my_compiler_options = CompilerOptionArguments(flags=['auto-element-thread']) qm.execute(prog, compiler_options=my_compiler_options) # execution ``` -------------------------------- ### API Method: get_output_dc_offset_by_element Source: https://docs.quantum-machines.co/latest/docs/API_references/qm_opx1000_api Deprecated - This method is going to be removed, please get idle value from `qm.get_config()` or current value from job `job.get_output_dc_offset_by_element()`. Get the current DC offset of the OPX analog output channel associated with an element. ```APIDOC get_output_dc_offset_by_element( element: str - the name of the element to get the correction for iq_input: Optional[Literal['I', 'Q', 'single']] = None - the port name as appears in the element config. Options: 'single' for an element with a single input 'I' or 'Q' for an element with mixer inputs ) RETURNS: float - the offset, in volts ``` -------------------------------- ### QUA DSL: `while_` Loop Example Source: https://docs.quantum-machines.co/latest/docs/API_references/qua/dsl_main Example demonstrating the usage of the `while_` context manager in QUA. This snippet shows how to declare and assign an integer variable, then use it as a condition to control a loop that plays a pulse and increments the variable. ```QUA x = declare(int) assign(x, 0) with while_(x<=30): play('pulse', 'element') assign(x, x+1) ``` -------------------------------- ### Add Jobs to Queue using QmApi Source: https://docs.quantum-machines.co/latest/docs/Guides/multi-users Demonstrates how to add jobs to the queue using the `qm.queue.add` and `qm.queue.add_to_start` methods of the `QmApi` object. Jobs can be added at the end or the beginning of the queue. ```Python # Adding to the queue qm.queue.add(program) # adds at the end of the queue qm.queue.add_to_start(program) # adds at the start of the queue ``` -------------------------------- ### OPX Simulator API Reference Source: https://docs.quantum-machines.co/latest/docs/Guides/simulator This section provides an overview of the key classes and methods used for simulating QUA programs with the OPX simulator, including how to initiate simulations and retrieve results. ```APIDOC Class: qm.quantum_machines_manager.QuantumMachinesManager Method: simulate(config, prog, simulation_config) Description: Initiates a simulation of a QUA program. Parameters: config: The configuration for the QUA program. prog: The QUA program to simulate. simulation_config: An instance of qm.simulate.interface.SimulationConfig, specifying simulation parameters like duration. Returns: A simulated_job object (instance of qm.jobs.simulated_job.SimulatedJob). Class: qm.simulate.interface.SimulationConfig Description: Configuration object for defining simulation parameters. Constructor/Properties: duration: int - The duration of the simulation in cycles (e.g., 2500 cycles for 10 us). Class: qm.jobs.simulated_job.SimulatedJob Method: get_simulated_samples() Description: Retrieves the simulated samples from the job. Returns: Simulated samples (specific type not detailed in text). ``` -------------------------------- ### Buffer Limitation Example Source: https://docs.quantum-machines.co/latest/docs/Guides/stream_proc Highlights the limitation of processing buffered variables, showing that processing `my_stream1` alone is fine, but adding `my_stream2` exceeds the 100 million variable limit. When using `with_timestamps()`, each variable should be calculated as two variables. ```Python my_stream1.buffer(int(100e6)).save() my_stream2.buffer(int(3e5)).save() ```