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 :math:`\sum_{k=0}^{2^n-1}\alpha_k\left|k\right>`, where :math:`n` is the number of qubits, increases as follows: - **Exponential** with :math:`n` in **dense mode**. - **Log-linear** with the number of states where :math:`\alpha_k \neq 0` in **sparse mode**. For example: - To prepare a GHZ state :math:`\frac{1}{\sqrt{2}}(\left|0\dots0\right>+\left|1\dots1\right>)` of :math:`n` qubits, :math:`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 :math:`\frac{1}{\sqrt{2^n}}\sum_{k=0}^{2^n-1}\left|k\right>` of :math:`n` qubits, :math:`n` Hadamard gates are required, resulting in: - Complexity :math:`O(2^n \log{2^n})` in **sparse mode**. - Complexity :math:`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 :func:`~ket.operations.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: 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: .. code-block:: bash pip install pip -U pip install ket-lang requests -U The :class:`~ket.remote.Remote` class is used to access the simulator. To do this, simply instantiate the class and connect it to a :class:`~ket.base.Process`. In the constructor of the :class:`~ket.remote.Remote` class, you need to provide the URL :code:`https://qubox.ufsc.br/sim`. Additionally, when connecting to the process using the :meth:`~ket.remote.Remote.connect` method, you must pass the named arguments :code:`num_qubits=` and :code:`simulator=`. See the example below: .. code-block:: python 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: - :code:`quantuloop::dense`: Dense Simulator - :code:`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 (:code:`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. .. code-block:: python 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")