The Central Quantum Nervous System

While Luna primarily focuses on optimization services, its capabilities extend beyond that domain. With LunaQ, we provide a framework that greatly simplifies the process of accessing various quantum hardware providers. You can use this framework to deploy your custom quantum algorithms.

Running Qiskit Programs on IBM Quantum

In this tutorial, let's imagine you have a Qiskit program locally that you wish to run on IBM Quantum's servers. Through LunaQ, we offer the capability to submit arbitrary programs to IBM. LunaQ accepts an OpenQASM 2.0 string as input. Using the built-in function of qiskit you can also simply send a qiskit.QuantumCircuit object.

Let's start with an OpenQASM 2.0 string. As an example, we will define a quantum circuit for the Bernstein-Vazirani algorithm with a secret string '10101'.

from qiskit import QuantumCircuit

circuit_qasm = """OPENQASM 2.0;

include "qelib1.inc";

// Declare a quantum register with 6 qubits and a classical register with 5 bits
qreg q[6];
creg c[5];

// Initialize the qubits in superposition
h q[0];
h q[1];
h q[2];
h q[3];
h q[4];

// Prepare the auxiliary qubit in state |-> to facilitate phase kickback
x q[5];
h q[5];

// Oracle operation: apply CNOT gates based on the secret string '10101'
cx q[0],q[5];
cx q[2],q[5];
cx q[4],q[5];

// Apply Hadamard gates again to interfere qubits and extract the secret string
h q[0];
h q[1];
h q[2];
h q[3];
h q[4];

// Add a barrier to ensure all operations above are completed before measurement
barrier q[0],q[1],q[2],q[3],q[4],q[5];

// Measure the qubits to collapse the state to the secret string
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[2] -> c[2];
measure q[3] -> c[3];
measure q[4] -> c[4];
"""

print(QuantumCircuit.from_qasm_str(circuit_qasm))
     ┌───┐          ┌───┐           ░ ┌─┐            
q_0: ┤ H ├───────■──┤ H ├───────────░─┤M├────────────
     ├───┤┌───┐  │  └───┘           ░ └╥┘┌─┐         
q_1: ┤ H ├┤ H ├──┼──────────────────░──╫─┤M├─────────
     ├───┤└───┘  │       ┌───┐      ░  ║ └╥┘┌─┐      
q_2: ┤ H ├───────┼────■──┤ H ├──────░──╫──╫─┤M├──────
     ├───┤┌───┐  │    │  └───┘      ░  ║  ║ └╥┘┌─┐   
q_3: ┤ H ├┤ H ├──┼────┼─────────────░──╫──╫──╫─┤M├───
     ├───┤└───┘  │    │       ┌───┐ ░  ║  ║  ║ └╥┘┌─┐
q_4: ┤ H ├───────┼────┼────■──┤ H ├─░──╫──╫──╫──╫─┤M├
     ├───┤┌───┐┌─┴─┐┌─┴─┐┌─┴─┐└───┘ ░  ║  ║  ║  ║ └╥┘
q_5: ┤ X ├┤ H ├┤ X ├┤ X ├┤ X ├──────░──╫──╫──╫──╫──╫─
     └───┘└───┘└───┘└───┘└───┘      ░  ║  ║  ║  ║  ║ 
c: 5/══════════════════════════════════╩══╩══╩══╩══╩═
                                       0  1  2  3  4 

To execute this circuit on quantum hardware, you first need to create a LunaQ client.

# Load the LunaQ package
from luna_sdk.controllers import LunaQ

# Create a LunaQ client to communicate with the Luna platform
lunaQ = LunaQ(email="YOUREMAIL", password="YOURPASSWORD")

If you have not already done so, you will need to set your QPU token for the quantum hardware you wish to access, in this case IBM. This only needs to be done once for your account. So if you have already done this, you can skip this step.

from luna_sdk.schemas.enums.circuit import CircuitProviderEnum

# Set a new personal QPU token for your account
lunaQ.qpu_token.create_qpu_token(
    name="TOKENNAME",
    provider=CircuitProviderEnum.IBM,
    token="<TOKEN>"
)

With just a single line of code, you can run this program on IBM's quantum hardware via LunaQ.

job = lunaQ.circuit.create(
    circuit=circuit_qasm, 
    provider=CircuitProviderEnum.IBM, 
    # parameters for the quantum hardware, in this case the "least_busy" backend from IBM.
    params={"backend_name": "least_busy"}
)

Depending on the selected quantum hardware, the execution might take some time. To prevent you from waiting for the code to complete, we've designed the process to be asynchronous. When you request a solution, LunaSolve handles all the required steps in the background. This way, you can continue with other tasks while the solution is being computed. You can simply return when the execution is finished.

After the program has finished, you can simply retrieve the output again via LunaQ.

result_qasm = lunaQ.circuit.get(job)

As already mentioned, apart from OpenQASM 2.0 strings, you can also simply pass a qiskit.QuantumCircuit object. Let's take a quick look at a basic example.

from qiskit import QuantumRegister

qr = QuantumRegister(2)
qc = QuantumCircuit(qr)

qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.measure_all()

print(qc)
        ┌───┐      ░ ┌─┐   
  q6_0: ┤ H ├──■───░─┤M├───
        └───┘┌─┴─┐ ░ └╥┘┌─┐
  q6_1: ─────┤ X ├─░──╫─┤M├
             └───┘ ░  ║ └╥┘
meas: 2/══════════════╩══╩═
                      0  1 

Using a qiskit.QuantumCircuit object does not change the workflow. You can simply pass the object after the transformation in the same way as an OpenQASM string.

job = lunaQ.circuit.create(
    circuit=qc.decompose().qasm(),
    provider=CircuitProviderEnum.IBM, 
    params={"backend_name": "least_busy"}
)

result_qc = lunaQ.circuit.get_result(job)

Using Q-CTRL's Fire Opal for Automated Error Suppression

In addition to using IBM's hardware, you can also access IBM via Fire Opal. Fire Opal is a service from Q-CTRL that allows anyone to easily run their most valuable quantum applications by abstracting hardware, automatically reducing error, and boosting algorithmic success on quantum computers in the NISQ era and beyond.

LunaQ offers a built-in function for using Fire Opal. You only need to specify the necessary parameters to access Fire Opal and the rest of the workflow remains the same.

# Set your access token for Q-CTRL's Fire Opal
lunaQ.qpu_token.create_qpu_token(
    name="TOKENNAME",
    provider=CircuitProviderEnum.QCTRL,
    token="<Fire Opal Token>"
)
 
params={
    "backend_name": "least_busy",
    # If you are a member of multiple organizations at Q-CTRL, specify your organization here
    "organization_slug": "<Organization Slug>"
}

# Run the program from the OpenQASM string on IBM's quantum hardware via Fire Opal
job_qasm = lunaQ.circuit.create(
    circuit=circuit_qasm, 
    provider=CircuitProviderEnum.QCTRL, 
    params=params
)

# Retrieve the results for the OpenQASM program
result_qasm = lunaQ.circuit.get_result(job_qasm)

# Alternatively, run the qiskit circuit on IBM's quantum hardware via Fire Opal
job_qiskit = lunaQ.circuit.create(
    circuit=qc, 
    provider=CircuitProviderEnum.QCTRL, 
    params=params
)

# Retrieve the results for the Qiskit program
result_qiskit = lunaQ.circuit.get_result(job_qiskit)

If you do not yet have an account with Fire Opal and would like to use this service, please contact us here.

Was this page helpful?