QuBOX Simulator

QuBOX is a portable hardware device embedding simulators developed by Quantuloop. Designed to assist in teaching and research in quantum computing, the QuBOX simulator is a practical solution for accelerating the quantum execution of applications written in Ket.

The QuBOX Simulator is designed to be easily transported to classrooms or laboratories, requiring no infrastructure other than network and power access. At UFSC, the QuBOX simulator is available for cloud access, requiring minimal configuration to accelerate your quantum applications.

Specifications

The simulator offers two simulation modes, sparse and dense, with simulation time complexities depending on specific characteristics of quantum computing:

  1. Sparse Mode: Simulation time depends on the number of computational basis states needed to represent the quantum state.

  2. Dense Mode: Simulation time directly depends on the number of qubits in the system.

Mathematically, the complexity of simulating the preparation of a state \(\sum_{k=0}^{2^n-1}\alpha_k\left|k\right>\), where \(n\) is the number of qubits, increases as follows:

  • Exponential with \(n\) in dense mode.

  • Log-linear with the number of states where \(\alpha_k \neq 0\) in sparse mode.

For example:

  • To prepare a GHZ state \(\frac{1}{\sqrt{2}}(\left|0\dots0\right>+\left|1\dots1\right>)\) of \(n\) qubits, \(n-1\) CNOT gates are required. In sparse mode, each CNOT gate has constant time complexity relative to the number of qubits, while in dense mode, the complexity is exponential.

  • To prepare the state \(\frac{1}{\sqrt{2^n}}\sum_{k=0}^{2^n-1}\left|k\right>\) of \(n\) qubits, \(n\) Hadamard gates are required, resulting in:
    • Complexity \(O(2^n \log{2^n})\) in sparse mode.

    • Complexity \(O(n 2^n)\) in dense mode.

Note

The simulation mode should be chosen based on the specific characteristics of each quantum algorithm.

Note

The function dump() is disabled on QuBOX because the result of a dump operation can easily exceed 10GB of information, making its execution infeasible in a remote environment.

Installation and Configuration

To access the simulator, you need Ket v0.8.1 or later and the Requests library. Both can be installed using pip with the commands below:

pip install pip -U
pip install ket-lang requests -U

The Remote class is used to access the simulator. To do this, simply instantiate the class and connect it to a Process.

In the constructor of the Remote class, you need to provide the URL https://qubox.ufsc.br/sim. Additionally, when connecting to the process using the connect() method, you must pass the named arguments num_qubits= and simulator=.

See the example below:

from ket import Process
from ket.remote import Remote

# Instantiate the Remote class with the simulator URL
qubox = Remote("https://qubox.ufsc.br/sim")

# Connect to the simulator specifying the number of qubits and the model
process = Process(qubox.connect(num_qubits=2, simulator="quantuloop::dense"))

The available quantum simulators are:

  • quantuloop::dense: Dense Simulator

  • quantuloop::sparse: Sparse Simulator

Try It Yourself

If you are using Ket, using QuBOX is extremely simple: just change two lines of code. The example below implements a quantum phase estimation algorithm, whose result is an approximation of the number π. It is possible to increase the number of qubits (num_qubits) to improve the result’s precision, but this also increases computation time.

After completing the Ket installation procedure, you can run the code below and observe the difference in execution time between your computer and QuBOX.

from math import pi
from functools import partial
from ket import Process, Quant, H, X, control, PHASE, SWAP, adj, measure
from ket.remote import Remote
from time import time


def qft(qubits: Quant, invert: bool = True):
    if len(qubits) == 1:
        H(qubits)
    else:
        *init, last = qubits
        H(last)
        for i, ctrl_qubit in enumerate(reversed(init)):
            with control(ctrl_qubit):
                PHASE(pi / 2 ** (i + 1), last)
        qft(init, invert=False)
    if invert:
        size = len(qubits)
        for i in range(size // 2):
            SWAP(qubits[i], qubits[size - i - 1])


def phase_estimator(oracle_gate, qubits: Quant) -> float:
    ctr = H(qubits[:-1])
    tgr = X(qubits[-1])
    precision = len(ctr)

    for i, c in enumerate(ctr):
        with control(c):
            oracle_gate(i, tgr)
    adj(qft)(ctr)

    return measure(reversed(ctr)).get() / 2**precision


def oracle(phase: float, i: int, tgr):
    PHASE(2 * pi * phase * 2**i, tgr)


estimate_pi = partial(phase_estimator, partial(oracle, pi / 10))


if __name__ == "__main__":
    num_qubits = 25

    begin = time()
    local_execution = Process(simulator="dense", num_qubits=num_qubits, execution="batch")
    local_qubits = local_execution.alloc(num_qubits)
    local_result = estimate_pi(local_qubits) * 10
    end = time()
    print(f"Local simulation: result={local_result}, time {end-begin}s")

    begin = time()
    qubox = Remote("https://qubox.ufsc.br/sim")
    remote_process = Process(qubox.connect(num_qubits=num_qubits, simulator="quantuloop::dense"))
    remote_qubits = remote_process.alloc(num_qubits)
    remote_result = estimate_pi(remote_qubits) * 10
    end = time()

    print(f"QuBOX simulation: result={remote_result}, time {end-begin}s")