diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..f673191 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,2 @@ +# PyQuafu Documentation by Sphinx + diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/source/apiref/apiref_0.3.5.rst b/doc/source/apiref/apiref_0.3.5.rst index 8aed751..e9b1bfb 100644 --- a/doc/source/apiref/apiref_0.3.5.rst +++ b/doc/source/apiref/apiref_0.3.5.rst @@ -5,6 +5,8 @@ API Reference This page is still under refinement, the contents you see may be incomplete at present. +.. _quantum_circuit: + Quantum Circuit ------------------ @@ -17,7 +19,7 @@ Quantum Elements .. hint:: hello -.. autoclass:: quafu.elements.quantum_element.Instruction +.. autoclass:: quafu.elements.Instruction :members: diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..23531d8 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,38 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- package path ------------------------------------------- +import sys +import os + +package_path = os.path.join(os.getcwd(), '..\\..\\src\\') +sys.path.insert(0, package_path) + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'PyQuafu-Docs' +copyright = '2023, BAQIS-ScQ-Cloud' +author = 'BAQIS-ScQ-Cloud' +release = '0.3.6' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.napoleon' + ] # 'sphinx.ext.autosummary' + +templates_path = ['_templates'] +exclude_patterns = [] + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "sphinx_rtd_theme" +html_static_path = ['_static'] + +# Use Napoleon interpreter to support Google style docstrings +autodoc_typehints = 'description' diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..9bafb6b --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,28 @@ +.. PyQuafuDoc documentation master file, created by + sphinx-quickstart on Wed Sep 13 18:54:07 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to PyQuafu's documentation! +====================================== + +`Quafu `_ shares open access to +super-conducting quantum (ScQ) computing resources with public users from all around +the world. As the python SDK of `Quafu `_, ``pyquafu`` +provides not only flexible and advanced interfaces to the experimental backends, +but also useful toolkits for simulating, visualizing and more about quantum computation. +This documentation describes its basic syntax and usages. + +Contents +==================================== +.. toctree:: + :maxdepth: 2 + + User Guide + API Reference + Historical Version + +Links +==================================== + +Quafu Cloud Platform: `http://quafu.baqis.ac.cn/ `_ diff --git a/doc/source/release_note/Release Notes - v0.3.6.md b/doc/source/release_note/Release Notes - v0.3.6.md new file mode 100644 index 0000000..dff9f61 --- /dev/null +++ b/doc/source/release_note/Release Notes - v0.3.6.md @@ -0,0 +1,11 @@ +Release Notes - v0.3.6 + +- Fixed bug of status code mixed up during receiving results. +- Added attributes ``named_paras`` and ``named_pos`` into ``Instruction`` and all of its subclasses. This is to further unify interface of instructions. Added ``instructions`` into ``QuantumCircuit``, the former existing ``gates`` will contain only instances of ``QuantumGate`` in future. +- Fixed some icon-missing bugs in ``CircuitPlotManager``, plots of all basic gates was tested. + +发布说明 - v0.3.6 + +- 修复了接收结果时状态码混淆的bug。 +- 添加了属性 ``named_paras`` 和``named_pos`` 到 ``Instruction`` 和它的所有子类。这是为了进一步统一 ``Instruction`` 的接口。在 ``QuantumCircuit``中添加属性 ``instructions`` ,先前存在的``gates``在稍后的版本中将只包含``QuantumGate`` 的实例。 +- 修复了``CircuitPlotManager``中一些图标缺失的bug,测试了所有基本门的绘图。 \ No newline at end of file diff --git a/doc/source/release_note/historical_version.rst b/doc/source/release_note/historical_version.rst new file mode 100644 index 0000000..cee8bf2 --- /dev/null +++ b/doc/source/release_note/historical_version.rst @@ -0,0 +1,7 @@ +.. _historical_version: + +Historical Version +================== + +.. note:: + Historical version and release notes will be loaded later. diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_23_0.png b/doc/source/user_guide/quafu_doc_0.3.5/output_23_0.png new file mode 100644 index 0000000..1293d68 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_23_0.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_28_0.png b/doc/source/user_guide/quafu_doc_0.3.5/output_28_0.png new file mode 100644 index 0000000..1e05baf Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_28_0.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_37_1.png b/doc/source/user_guide/quafu_doc_0.3.5/output_37_1.png new file mode 100644 index 0000000..75a8dc8 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_37_1.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_39_0.png b/doc/source/user_guide/quafu_doc_0.3.5/output_39_0.png new file mode 100644 index 0000000..9c5b880 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_39_0.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_41_0.png b/doc/source/user_guide/quafu_doc_0.3.5/output_41_0.png new file mode 100644 index 0000000..6071d6b Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_41_0.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_45_0.png b/doc/source/user_guide/quafu_doc_0.3.5/output_45_0.png new file mode 100644 index 0000000..3f12476 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_45_0.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_55_0.png b/doc/source/user_guide/quafu_doc_0.3.5/output_55_0.png new file mode 100644 index 0000000..e5acc94 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_55_0.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_55_1.png b/doc/source/user_guide/quafu_doc_0.3.5/output_55_1.png new file mode 100644 index 0000000..06403e7 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_55_1.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/output_67_1.png b/doc/source/user_guide/quafu_doc_0.3.5/output_67_1.png new file mode 100644 index 0000000..72f74c3 Binary files /dev/null and b/doc/source/user_guide/quafu_doc_0.3.5/output_67_1.png differ diff --git a/doc/source/user_guide/quafu_doc_0.3.5/quafu_doc_0_3_5.rst b/doc/source/user_guide/quafu_doc_0.3.5/quafu_doc_0_3_5.rst new file mode 100644 index 0000000..bb393ba --- /dev/null +++ b/doc/source/user_guide/quafu_doc_0.3.5/quafu_doc_0_3_5.rst @@ -0,0 +1,613 @@ +User Guide +========== + +.. note:: + PyQuafu is under active development and this is user guide + for the latest version(0.3.5). If you are using ``pyquafu<=0.2``, + please see :ref:`historical_version`. + +Installation +------------ + +``pyquafu`` requires ``python>=3.8``. And it’s suggested to activate an +individual virtual environment for it, see for axample +`quafu-tutorial-venv `__. + +For the latest stable version, run the following codes in the command +line/terminal: + +:: + + pip install pyquafu + +Set up your Quafu account +------------------------- + +If you haven’t have an account, you may register on the +`Quafu `__ website at first. Then you will +find your apitoken ```` on the ``Dashboard`` page, +which is required when you send tasks to ScQ-chips. + +By executing the following codes your token will be saved to your local +device. + +.. code:: python + + from quafu import User + user = User("") + user.save_apitoken() + +Once you’ve done this, you may look over the available ScQ-chips in the +experimental backends. + +.. code:: python + + available_backends = user.get_available_backends() + +:: + + system_name qubits status + ScQ-P10 10 Online + ScQ-P18 18 Online + ScQ-P136 136 Online + +*Note*: The next time you visit ``pyquafu``, you don’t have to save the +token again. Yet a quafu token is not permanently validating, from time +to time you may click **``refresh``** to get a new one on +`Quafu `__ webpage . + +Build your first quantum circuit +-------------------------------- + +Let’s start by initializing a circuit with 5 qubits, + +.. code:: python + + import numpy as np + from quafu import QuantumCircuit + + qc = QuantumCircuit(5) + +Apply Gates +~~~~~~~~~~~ + +``PyQuafu`` supports ‘``qc.name(args)``’ style to apply gates and also +other instructions. + +.. code:: python + + qc.x(0) + qc.x(1) + qc.cnot(2, 1) + qc.ry(1, np.pi/2) + qc.rx(2, np.pi) + qc.rz(3, 0.1) + qc.cz(2, 3) + +:: + + + +Alternatively, you may manually instantiate a gate and add it to the +circuit. + +.. code:: python + + # equivalent to qc.x(0) + import quafu.elements.element_gates as qeg + gate = qeg.XGate(pos=0) + qc.add_gate(gate) + +This is actually what ``.name(args)`` functions do. You would find +the second style convenient when build a new circuit from existing one. + +For quantum gates Quafu supports, please check the API reference for :ref:`quantum_circuit` +or use python-buitin ``dir()`` method. + +.. code:: python + + print(dir(qc)) + +:: + + ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_used_qubits', 'add_gate', 'add_pulse', 'barrier', 'circuit', 'cnot', 'cp', 'cs', 'ct', 'cx', 'cy', 'cz', 'delay', 'draw_circuit', 'fredkin', 'from_openqasm', 'gates', 'h', 'id', 'iswap', 'layered_circuit', 'mcx', 'mcy', 'mcz', 'measure', 'measures', 'num', 'openqasm', 'p', 'plot_circuit', 'rx', 'rxx', 'ry', 'ryy', 'rz', 'rzz', 's', 'sdg', 'sw', 'swap', 'sx', 'sxdg', 'sy', 'sydg', 't', 'tdg', 'to_openqasm', 'toffoli', 'unitary', 'used_qubits', 'w', 'x', 'xy', 'y', 'z'] + +Measure +~~~~~~~ + +Add measurement information including qubits measured (``measures``) and +the classical bits keeping the measured results (``cbits``). If there is +no measurement information provided, all qubits are measured by default. + +.. code:: python + + measures = [0, 1, 2, 3, 4] + cbits = [0, 1, 2, 4, 3] + qc.measure(measures, cbits=cbits) + qc.measures + +:: + + {0: 0, 1: 1, 2: 2, 3: 4, 4: 3} + +Visualize +~~~~~~~~~ + +From ``version=0.3.2``, ``PyQuafu`` provides two similiar ways to +visualize quantum circuits. You can draw the circuit using the +``draw_circuit`` method and use ``width`` parameter to adjust the length of the circuit. + +.. code:: python + + qc.draw_circuit(width=4) + +:: + + q[0] ------X--------X-------------------- M->c[0] + + q[1] ------X--------+----RY(1.571)------- M->c[1] + | + q[2] ---------------*----RX(3.142)----*-- M->c[2] + | + q[3] --RZ(0.100)----------------------Z-- M->c[4] + + q[4] ------------------------------------ M->c[3] + +Alternatively, you may create a figure by + +.. code:: python + + qc.plot_circuit(title='A Quantum Circuit') + +| ​ +| |png| ​ + +The latter visualization uses ``matplotlib`` as the backend and you may +save the figure as any format that ``matplotlib`` supports. + +OPENQASM Support +~~~~~~~~~~~~~~~~ + +``pyquafu`` is backward compatible with quantum gates in +`OPENQASM2.0 `__. You can store your +quantum circuit as openqasm string, and also initialize your quantum +circuit with openqasm text. + +.. code:: python + + qasm = qc.to_openqasm() + print(qasm) + +:: + + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[5]; + creg meas[5]; + x q[0]; + x q[1]; + cx q[2],q[1]; + ry(1.5707963267948966) q[1]; + rx(3.141592653589793) q[2]; + rz(0.1) q[3]; + cz q[2],q[3]; + x q[0]; + measure q[0] -> meas[0]; + measure q[1] -> meas[1]; + measure q[2] -> meas[2]; + measure q[3] -> meas[4]; + measure q[4] -> meas[3]; + +​ + +.. code:: python + + del qc + qc = QuantumCircuit(5) + qc.from_openqasm(qasm) + qc.plot_circuit('Recovered from QASM') + +| ​ +| |image1| ​ + +Execution and Simulation +------------------------ + +Now you are ready to submit the circuit to the experimental backend. +First, initialize a Task object + +.. code:: python + + from quafu import Task + task = Task() + +You can configure your task properties using the +``config`` method. Here we +choose the backend (``backend``) as ``ScQ-P18``, the single shots number +(``shots``) as 2000 and compile the circuit on the backend +(``compile``). + +.. code:: python + + task.config(backend="ScQ-P18", shots=2000, compile=True) + +If you set the ``compile`` parameter to ``False``, make sure that you +know the topology of the backend well and submit a valid circuit. + +Send the quantum circuit to the backend and wait for the results. + +.. code:: python + + res = task.send(qc, wait=True) + +You can use the returned results to check the count and probability of +each measured bit string. The output bits are arranged in **big-endian** +convention by default, see also the next sectioin. + +.. code:: python + + print(res.counts) #counts + print(res.probabilities) #probabilities + res.plot_probabilities() + +:: + + OrderedDict([('00100', 717), ('00110', 31), ('01000', 6), ('01100', 1185), ('01110', 39), ('10100', 22)]) + {'00100': 0.3585, '00110': 0.0155, '01000': 0.003, '01100': 0.5925, '01110': 0.0195, '10100': 0.011} + +.. figure:: output_37_1.png + :alt: png + + png + +The returned results contain also the **compiled circuit**, from which +you may find optimization was made. + +.. code:: python + + res.transpiled_circuit.plot_circuit("Compiled Circuit") + +| ​ +| |image2| ​ + +If you want to check the correctness of the executed results. Quafu +provide simple circuit similator + +.. code:: python + + from quafu import simulate + simu_res = simulate(qc, output="probabilities") + simu_res.plot_probabilities() + +| ​ +| |image3| ​ + +If you don’t want to plot the results for basis with zero probabilities, +set the parameter ``full`` in method +``plot_probabilities`` to False. Note that this parameter is only valid for results returned by +the simulator. + +A Subtle detail +~~~~~~~~~~~~~~~ + +There are two different conventions when writing a computational basis +as a bit-string. That is, for example, to denote the state where only +the first qubit is excited, some may write 10…000 while others use +000…01. This subtle detail sometimes causes confusion and even serious +error in computation. The following experiment demonstrates conventions +used in ``pyquafu``. + +.. code:: python + + from quafu import QuantumCircuit, simulate + + n = 3 + qc = QuantumCircuit(n) # |000> + qc.h(0) # |100> + |000> + qc.measure() + + res = simulate(qc) + res.plot_probabilities() + +| ​ +| |image4| ​ + +Here you see that in ``pyquafu``, ``counts`` obeys so-called +‘big-endian’. However, for some historical reasons, the state-vector use +small-endian instead. + +.. code:: python + + res = simulate(qc, output='state_vector') + print(res.state_vector[:2]) + state_tensor = res.state_vector.reshape(tuple(n*[2])).transpose([-3, -2, -1]) + print(state_tensor[0, 0, 0]) + print(state_tensor[0, 0, 1]) + print(state_tensor[1, 0, 0]) + +:: + + [0.70710678+0.j 0.70710678+0.j] + (0.7071067811865475+0j) + (0.7071067811865475+0j) + 0j + +If this is not the convention you are used to, ``ndarray.transpose`` may +help + +.. code:: python + + state_tensor = state_tensor.transpose(tuple(range(n-1, -1, -1))) + +Measure observables +------------------- + +Quafu provides measuring observables with an executed quantum circuit. +You can input Pauli operators that need to measure expectation values to +the ``submit`` `__ method. For +example, you can input [[“XYX”, [0, 1, 2]], [“Z”, [1]]] to calculate the +expectation of operators :math:`\sigma^x_0\sigma^y_1\sigma^x_2` and +:math:`\sigma^z_1`. The +``submit`` `__ method will +minimize the executing times of the circuit with different measurement +basis that can calculate all expectations of input operators. + +Here we show how to measure the energy expectation of the Ising chain + +.. math:: H=\sum_i \sigma^z_i \sigma^z_{i+1} + g \sum_i \sigma^x_i. + +First, we initialize a circuit with three Hadamard gate + +.. code:: python + + q = QuantumCircuit(5) + + for i in range(5): + if i % 2 == 0: + q.h(i) + + measures = list(range(5)) + q.measure(measures) + q.draw_circuit() + +:: + + q[0] --H-- M->c[0] + + q[1] ----- M->c[1] + + q[2] --H-- M->c[2] + + q[3] ----- M->c[3] + + q[4] --H-- M->c[4] + +Next, we set operators that need to be measured to calculate the energy +expectation, and submit the circuit using +``submit`` method + +.. code:: python + + test_Ising = [["X", [i]] for i in range(5)] + test_Ising.extend([["ZZ", [i, i+1]] for i in range(4)]) + res, obsexp = task.submit(q, test_Ising) + +:: + + Job start, need measured in [['XXXXX', [0, 1, 2, 3, 4]], ['ZZZZZ', [0, 1, 2, 3, 4]]] + +The function return measurement results and operator expectations. The +measurement results only contain two ExecResult objects since the +circuit is only executed twice, with measurement basis [[‘XXXXX’, [0, 1, +2, 3, 4]] and [‘ZZZZZ’, [0, 1, 2, 3, 4]]] respectively. + +.. code:: python + + res[0].plot_probabilities() + res[1].plot_probabilities() + +| ​ +| |image5| ​ + +.. figure:: output_55_1.png + :alt: png + + png + +The return operator expectations (``obsexp``) is a list with a length +equal to the input operator number. We can use it to calculate the +energy expectation + +.. code:: python + + print(obsexp) + g = 0.5 + E = g*sum(obsexp[:5])+sum(obsexp[5:]) + print(E) + +:: + + [1.0, 0.046999999999999986, 1.0, 0.03699999999999998, 0.998, 0.00899999999999995, 0.08499999999999996, 0.08299999999999996, 0.008999999999999952] + 1.7269999999999999 + +Submit task asynchronously +-------------------------- + +In the above examples, we chose opening python kernal and waiting for +the result. You may also set the ``wait=False`` in +``send`` function to submit +the task asynchronously. Here we use another example that measures the +qubit decoherence time :math:`T_1` to demonstrate the usage. + +.. code:: python + + task = Task() + task.config(backend="ScQ-P10", shots=2000, compile=False, priority=2) + +Prepare parameters of a group of tasks and send the task asynchronously. + +.. code:: python + + ts = range(0, 21, 1) + names = ["%dus" %t for t in ts] + for name, t in zip(names, ts): + q = QuantumCircuit(3) + q.x(2) + q.delay(2, t, unit="us") + q.measure([2]) + res = task.send(q, wait=False, name=name, group="Q3_T1") + +Here the ``delay`` options will idle the target qubit ``2`` for a +duration ``t`` in the time unit ``us`` (microsecond) and do nothing. In +the send function, we set ``wait`` to false to execute the task +asynchronously, give each task a name by duration time and set all tasks +to a group named "Q3_T1". + +Now we can try to retrieve the group of tasks using the +``retrieve_group`` +method. + +.. code:: python + + group_res = task.retrieve_group("Q3_T1") + probs = [res.probabilities["1"] for res in group_res] + +:: + + Group: Q3_T1 + task_id task_name status + 326564501AF5CF47 0us Completed + 32656450226701BD 1us Completed + 326564502A80CC5D 2us Completed + 3265645032D98C32 3us Completed + 326564503AEFE7EA 4us Completed + 326564600CFE2817 5us Completed + 3265646014FFEA5F 6us Completed + 326564601C2E9597 7us Completed + 32656460240A93E6 8us Completed + 326564602C15CFFB 9us Completed + 3265646033EEBD20 10us Running + 326564603B1A478D 11us In Queue + 3265647006C96D3D 12us In Queue + 326564700F71B85A 13us In Queue + 32656470204A3472 14us In Queue + 32656470384DCD98 15us In Queue + 3265648004FB6BCF 16us In Queue + 326564800DA63F54 17us In Queue + 3265648022DAC675 18us In Queue + 3265648036F7EA24 19us In Queue + 326564901AB566FF 20us In Queue + +Once all the tasks are completed, we can do the next step to get +:math:`T_1`. + +.. code:: python + + group_res = task.retrieve_group("Q3_T1") + probs = [res.probabilities["1"] for res in group_res] + +:: + + Group: Q3_T1 + task_id task_name status + 326564501AF5CF47 0us Completed + 32656450226701BD 1us Completed + 326564502A80CC5D 2us Completed + 3265645032D98C32 3us Completed + 326564503AEFE7EA 4us Completed + 326564600CFE2817 5us Completed + 3265646014FFEA5F 6us Completed + 326564601C2E9597 7us Completed + 32656460240A93E6 8us Completed + 326564602C15CFFB 9us Completed + 3265646033EEBD20 10us Completed + 326564603B1A478D 11us Completed + 3265647006C96D3D 12us Completed + 326564700F71B85A 13us Completed + 32656470204A3472 14us Completed + 32656470384DCD98 15us Completed + 3265648004FB6BCF 16us Completed + 326564800DA63F54 17us Completed + 3265648022DAC675 18us Completed + 3265648036F7EA24 19us Completed + 326564901AB566FF 20us Completed + +.. code:: python + + import matplotlib.pyplot as plt + from scipy.optimize import curve_fit + def func(x, a, b): + return a*np.exp(-b*x) + + paras, pconv = curve_fit(func, ts, probs) + plt.plot(ts, probs, "o") + plt.plot(ts, func(ts, *paras), "--") + plt.xlabel("$t (\mu s)$") + plt.ylabel("prob") + plt.text(16, 0.9, r"$T_1=%.2f \mu s$" %(1/paras[1])) + +:: + + Text(16, 0.9, '$T_1=24.18 \\mu s$') + +| ​ +| |image6| ​ + +Note that ``group_name`` and submite history are kept in the ``task`` +object only when ``python`` kernal is running. For data persistence, we +provide ``TaskDatabase`` which use ``qslite3`` as the backend. It may +help you to save task information to your local computer. + +We would not devote too much into developing ``TaskDatabase`` since the +web-backends will prodive more powerful and convenient usages in the +future. However, if you are interested in manipulating database freely +by ``qslite3``, we do provide +`tutorial `__ +for a quick start. + +.. code:: python + + from quafu.tasks.task_database import QuafuTaskDatabase, print_task_info + + with QuafuTaskDatabase() as db: + for res in group_res: + db.insert_task(res.taskid, res.task_status, group_name="Q3_T1", task_name=res.taskname, priority=2) + print('Tasks info stored') + print("Task list:") + for task_info in db.find_all_tasks(): + print_task_info(task_info) + break # this is to avoid demo too long, you may cancel this line to view the whole info + +:: + + Tasks info stored + Task list: + Task ID: 326564501AF5CF47 + Group Name: Q3_T1 + Task Name: 0us + Status: Completed + Priority: 2 + Send Time: None + Finish Time: None + ------------------------ + +Finally, you can also retrieve a single task using its unique +``task_id``, and download all the historical tasks in +`Quafu `__ webpage. + +.. code:: python + + res_20us = task.retrieve("1663B8403AE76050") + print(res_20us.probabilities) + +:: + + {'0': 0.662, '1': 0.338} + +.. |png| image:: output_23_0.png +.. |image1| image:: output_28_0.png +.. |image2| image:: output_39_0.png +.. |image3| image:: output_41_0.png +.. |image4| image:: output_45_0.png +.. |image5| image:: output_55_0.png +.. |image6| image:: output_67_1.png diff --git a/quafu/elements/element_gates/clifford.py b/quafu/elements/element_gates/clifford.py index c8fa0b9..0ca22c5 100644 --- a/quafu/elements/element_gates/clifford.py +++ b/quafu/elements/element_gates/clifford.py @@ -1,5 +1,9 @@ from .element_gates import HGate, SGate, CXGate +""" +TODO: add documentation about Clifford gates. +""" + __all__ = ['HGate', 'SGate', 'CXGate'] diff --git a/src/qfvm_clifford/README.md b/src/qfvm_clifford/README.md new file mode 100644 index 0000000..c23be0c --- /dev/null +++ b/src/qfvm_clifford/README.md @@ -0,0 +1,67 @@ +# Clifford Simulator + +Usage of Clifford simulator in ``pyquafu`` is very similar with the default simulator, but applies only to circuits with a limited gate set. + +## Supported Gates + +### x + +The Pauli X gate. The bit flip gate. + +### y + +The Pauli Y gate. + +### z + +The Pauli Z gate. The phase flip gate + +### h + +The Hadamard gate. Swap the X and Z axes. Alternate name: `h_xz` + +### h_yz + +The variant of the Hadamard gate that swaps the Y and Z axes (instead of X and Z) + +### s + +Principal square root of Z gate. Phases the amplitue of |1> by i. Alternate name: `sqrt_z` + +### s_dag + +Adjoint of the principal square root of z gate. Phases the amplitube of |1> by -i. Alternate name: `sqrt_z_dag` + +### cnot + +The Z-controlled X gate. Applies an X gate to the target if the control is in the |1> state. Equivalently: negates the amplitude of the |1>|-> state. The first qubit is called the control, and the second qubit is the target. Alternate name: `cx`, `zcx` + +### swap + +Swap two qubits. + +### measure + +Z-basis measurement. Projects each target qubit into |0> or |1> and reports its value (false=|0>, true=|1>). + +### reset + +Z-basis reset. Forces each target qubit into the |0> state by silently measuring it in the Z basis and applying an X gate if it ended up in the |1> state. + +## Simple Example + +```python +from quafu import QuantumCircuit, simulate + +qc = QuantumCircuit(4, 4) +qc.x(0) +qc.x(1) +qc.measure([1, 2], [1, 0]) +qc.measure([3, 0], [2, 3]) + +result = simulate(qc=qc, shots=10, simulator="qfvm_clifford", output="count_dict") +counts = result.count + +# {"0101": 10} +print(counts) +```