######## Tutorial ######## In this guide, we will walk you through the fundamental procedures for simulating a quantum circuit using MIMIQ-CIRC product developed by QPerfect. Throughout the tutorial, we will furnish links to detailed documentation and examples that can provide a deeper understanding of each topic. In order to use MIMIQ-CIRC Python version, you need to first install the `mimiqcircuits` Python module within your workspace by following this step: .. code:: python from mimiqcircuits import * Building a Quantum circuit ========================== The first step in executing quantum algorithm on MIMIQ-CIRC always consists in defining one implementation of the algorithm as a quantum circuit, a sequence of quantum operations (quantum gates, measurements, resets, etc...) that act on a set of qubits. In MIMIQ-CIRC we always start by defining an empty circuit: .. code:: python circuit = Circuit() .. code:: python circuit empty circuit In :file:`mimiq-circuits-python` we do not need to specify the number of qubits of a circuit, or a list of quantum registers to use. Qubits will be allocated up to the maximum used index It's important to note that in :file:`mimiq-circuits-python`, qubit indices start from 0, following the standard Python indexing convention. Therefore, qubit indices are allowed values between 0 and 2^63. A circuit is made up of quantum operations. Gates, or unitary operations, are the simplest and most common ones. Lists are provided by the documentation of :file:`mimiq-circuits-python`. Please check out in the :class:`~mimiqcircuits.Circuit` class for more details about available operations. To add operations to circuits in Python we will be using the :meth:`~mimiqcircuits.Circuit.push` function, which takes multiple arguments, but usually: the circuit to add the operation to, the operation to be added, and as many target qubits as possible. In this first simple example [mimiqcircuits.GateH], only needs one target: .. code:: python circuit.push(GateH(),0) .. code:: 1-qubit circuit with 1 instructions: └── H @ q0 The text representation H @ q1 informs us that there is an instruction which applies the Hadamard gate to the qubit of index 0. Multiple gates can be added at once through the same `push` syntax. In the following example we add 9 CX or control-X gates between the qubit 0 and all the qubits from 1 to 9. .. code:: python circuit.push(GateCX(),0, range(1,10)) .. code:: 10-qubit circuit with 10 instructions: ├── H @ q0 ├── CX @ q0, q1 ├── CX @ q0, q2 ├── CX @ q0, q3 ├── CX @ q0, q4 ├── CX @ q0, q5 ├── CX @ q0, q6 ├── CX @ q0, q7 ├── CX @ q0, q8 └── CX @ q0, q9 This syntax is not dissimilar to the OpenQASM one, and can be seen as equivalent of: .. code:: python for i in range(1,10): circuit.push(GateCX(), 0, i) The same is true for adding operations that act also on classical bits .. code:: python circuit.push(Measure(),range(0,10), range(0,10)) .. code:: 10-qubit circuit with 20 instructions: ├── H @ q0 ├── CX @ q0, q1 ├── CX @ q0, q2 ├── CX @ q0, q3 ├── CX @ q0, q4 ├── CX @ q0, q5 ├── CX @ q0, q6 ├── CX @ q0, q7 ├── CX @ q0, q8 ├── CX @ q0, q9 ├── Measure @ q0, c0 ├── Measure @ q1, c1 ├── Measure @ q2, c2 ├── Measure @ q3, c3 ├── Measure @ q4, c4 ├── Measure @ q5, c5 ├── Measure @ q6, c6 ├── Measure @ q7, c7 ├── Measure @ q8, c8 └── Measure @ q9, c9 which is equivalent to: .. code:: python for i in range(0,10): circuit.push(Measure(), i, i) The number of quantum bits and classical bits of a circuit is defined by the maximum index used, so in this case 10 for both. .. code:: python circuit.num_bits(), circuit.num_qubits() With these informations, it is already possible to build any quantum circuit. However, for alternative advanced circuit building utilities see the documentation of :file:`mimiqcircuits-python` in this page :ref:`API References `. Remote execution on MIMIQ-CIRC ============================== In order to execute the implemented circuit on MIMIQ-CIRC three more steps are required: * **Make a connection**: opening a connection to the MIMIQ Remote Services, * **Send a Circuit to be executed**: send a circuit for execution, * **Retrieve the results**: retrieve the results of the execution. Connecting to MIMIQ =================== In most cases, connecting to MIMIQ can achieved by a single instruction: .. code:: python conn = MimiqConnection() conn.connect() Now, you will be redirected to a local webpage, which will automatically open in your default browser. Here, you'll be prompted to enter your authentication username and password. After providing your authentication details you will be able to send jobs. .. Note:: In order to complete this step you need an active subscription to MIMIQ-CIRC. To obtain one, please `contact us `__ or, if your organization already has a subscription, contact the organization account holder. executing a Circuit on MIMIQ ============================= Once a connection is established an execution can be sent to the remote services. .. code:: python job = conn.execute(circuit) .. code:: job '657b1a76d263121c8649f715' This will execute a simulation of the given circuit with default parameters. The default choice of algorithm is "auto". Generally, there are three available options: * **auto** for the automatically selecting the best algorithm according to circuit size and complexity. * **statevector** for a highly optimized state vector engine. * **mps** for a large-scale Matrix Product States (MPS) method. Please check out :class:`~mimiqcircuits.MimiqConnection` class for more details. Retrieving execution results ============================ Once the execution has terminated on MIMIQ, the results can be retrieved via the :meth:`~mimiqcircuits.MimiqConnection.get_results` function, which returns a :class:`~mimiqcircuits.QCSResults` structure. .. code:: python res = conn.get_results(job) .. code:: res QCSResults: ├── simulator: MIMIQ-StateVector 0.12.1 ├── amplitudes time: 1.18e-07s ├── apply time: 7.8685e-05s ├── total time: 0.01071431s ├── sample time: 0.000524353s ├── compression time: 1.7545e-05s ├── fidelity estimate (min,max): (1.000, 1.000) ├── average ≥2-qubit gate error (min,max): (0.000, 0.000) ├── 1 executions ├── 0 amplitudes └── 1000 samples Name and version of the simulator, samples, and timings can be retrieved from the aggregated results. For example, to make an histogram out of the retrieved samples, it suffices to execute .. code:: python res.histogram() {frozenbitarray('1111111111'): 494, frozenbitarray('0000000000'): 506} And for plotting the results simply execute this command: .. code:: bash plothistogram(res) .. image:: hist.png :alt: Alternative Text Retrieving execsubmitted remote jobs ==================================== There is also possibility to retrieve your submitted jobs parameters: .. code:: circuit, parameters = conn.get_inputs(job) .. code:: circuit 10-qubit circuit with 20 instructions: ├── H @ q0 ├── CX @ q0, q1 ├── CX @ q0, q2 ├── CX @ q0, q3 ├── CX @ q0, q4 ├── CX @ q0, q5 ├── CX @ q0, q6 ├── CX @ q0, q7 ├── CX @ q0, q8 ├── CX @ q0, q9 ├── Measure @ q0, c0 ├── Measure @ q1, c1 ├── Measure @ q2, c2 ├── Measure @ q3, c3 ├── Measure @ q4, c4 ├── Measure @ q5, c5 ├── Measure @ q6, c6 ├── Measure @ q7, c7 ├── Measure @ q8, c8 └── Measure @ q9, c9 .. code:: parameters {'executor': 'Circuits', 'timelimit': 300, 'files': [{'name': 'circuit.pb', 'hash': '6624a5fea70bc461cbb9138a9de5e0c58baffe7fac4884b6b0bfc068b36ec388'}], 'parameters': {'algorithm': 'auto', 'bitstrings': [], 'samples': 1000, 'seed': 122635094871933542, 'apilang: ': 'python', 'apiversion': '0.6.1', 'circuitsapiversion': '0.6.1', 'bondDimension': 256}}