From 7626b0e12a72eb57f2673c42ae9170ba8d7d27c4 Mon Sep 17 00:00:00 2001 From: BoxiLi Date: Sun, 16 Apr 2023 18:56:59 +0200 Subject: [PATCH 1/6] Update changelog.rst --- doc/source/changelog.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index e8684008..44faa962 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -3,6 +3,19 @@ Changelog ********* +Version 0.3.0 (June 1, 2023) +++++++++++++++++++++++++++++ + +This release adds to major features to the package. + +New features +------------ +- **MAJOR** Add Variational Quantum Algorithms in a new module :obj:`qutip_qip.vqa`. `Unitary fund microgrant project `_ (`#123 `_) +- **MAJOR** qutip-qip backends for qiskit :obj:`qutip_qip.qiskit`. `Google Summer of Code project 2022 `_ (`#155 `_, `#159 `_) +- Add class representation of quantum gates. (`#147 `_) + + + Version 0.2.3 (December 12, 2022) +++++++++++++++++++++++++++++++++ From 0cdafe29920a411f9ac86a34fc5f05f360099d19 Mon Sep 17 00:00:00 2001 From: Boxi Li Date: Sun, 7 May 2023 22:50:50 +0200 Subject: [PATCH 2/6] Fix a small typo in the installation guide --- doc/source/installation.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/source/installation.rst b/doc/source/installation.rst index e696be00..9e073b2a 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -131,6 +131,7 @@ If you want to edit the code, use instead To test the installation from a download of the source code, run from the `qutip-qip` directory -``` -pytest tests -``` +.. code-block:: bash + + pytest tests + From 2a890e33f4bfb9e022a624bbbd56d20b2c2751b9 Mon Sep 17 00:00:00 2001 From: Boxi Li Date: Fri, 16 Jun 2023 09:34:51 +0200 Subject: [PATCH 3/6] Merge pull request #207 from rum1887/qutip-qip-tuts Automatically generating the tutorial list --- .github/workflows/build_documentation.yml | 5 + doc/Makefile | 8 ++ doc/requirements.txt | 2 +- doc/source/contribution-docs.rst | 4 +- doc/source/index.rst | 2 +- .../create_tutorials_html.py | 136 ++++++++++++++++++ .../tutorials-website/tutorials.html.jinja | 39 +++++ doc/source/tutorials.rst | 10 -- 8 files changed, 193 insertions(+), 13 deletions(-) create mode 100644 doc/source/tutorials-website/create_tutorials_html.py create mode 100644 doc/source/tutorials-website/tutorials.html.jinja delete mode 100644 doc/source/tutorials.rst diff --git a/.github/workflows/build_documentation.yml b/.github/workflows/build_documentation.yml index a74276b6..d41d71ff 100644 --- a/.github/workflows/build_documentation.yml +++ b/.github/workflows/build_documentation.yml @@ -15,6 +15,11 @@ jobs: name: Install Python with: python-version: '3.8' + + - name: Install Pandoc + run: | + sudo apt update + sudo apt install -y pandoc - name: Install documentation dependencies run: | diff --git a/doc/Makefile b/doc/Makefile index 92dd33a1..d7a445ed 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -18,3 +18,11 @@ help: # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +create_tutorials: + python3 source/tutorials-website/create_tutorials_html.py + +#Modify the html target to include create_tutorials as a prerequisite +html: create_tutorials + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + diff --git a/doc/requirements.txt b/doc/requirements.txt index dfc3adf5..5afd9fe0 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -11,4 +11,4 @@ docutils==0.17.1 sphinxcontrib-bibtex==2.4.2 pyqir-generator==0.6.2 pyqir-parser==0.6.2 -qiskit==0.37.2 +qiskit==0.37.2 \ No newline at end of file diff --git a/doc/source/contribution-docs.rst b/doc/source/contribution-docs.rst index 9fdd68e4..ceab4907 100644 --- a/doc/source/contribution-docs.rst +++ b/doc/source/contribution-docs.rst @@ -8,7 +8,7 @@ Contributing to the documentation The user guide provides an overview of the package's functionality. The guide is composed of individual reStructuredText (**.rst**) files which each get rendered as a webpage. -Each page typically tackles one area of functionality. +Each page typically tackles one area of functionality. A few **.rst** files are generated runtime from **html** files using the `Pandoc `_ tool. To learn more about how to write **.rst** files, it is useful to follow the `sphinx guide `_. @@ -32,6 +32,8 @@ To build and test the documentation, the following packages are required: sphinx numpydoc sphinx_rtd_theme doctest +The generation of documentation also requires Pandoc. Follow this `link `_ to install Pandoc for your operating system. + Under the ``doc`` directory, use .. code-block:: bash diff --git a/doc/source/index.rst b/doc/source/index.rst index ea653ab2..60ea94d8 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -29,7 +29,7 @@ qutip-qip |version|: QuTiP quantum information processing :maxdepth: 2 :caption: Tutorials - tutorials.rst + tutorials_v5.rst .. toctree:: :maxdepth: 2 diff --git a/doc/source/tutorials-website/create_tutorials_html.py b/doc/source/tutorials-website/create_tutorials_html.py new file mode 100644 index 00000000..a5e5063c --- /dev/null +++ b/doc/source/tutorials-website/create_tutorials_html.py @@ -0,0 +1,136 @@ +#Adapted from https://github.com/qutip/qutip-tutorials/blob/1d1da2fc623372fa11ad5370a4fcd19452aad8fa/website/create_index.py + +import os +import re +from jinja2 import Environment, FileSystemLoader, select_autoescape +import shutil +import subprocess +import tempfile + +def atoi(text): + return int(text) if text.isdigit() else text + +def natural_keys(text): + return [atoi(c) for c in re.split('(\d+)', text)] + +class notebook: + def __init__(self, path, title): + # remove ../ from path + self.path = path.replace('../', '') + self.title = title + # set url and update from markdown to ipynb + self.url = url_prefix + self.path.replace(".md", ".ipynb") + self.url=self.url.replace(cloned_repo_dir,"") + +def get_title(filename): + """ Reads the title from a markdown notebook """ + with open(filename, 'r') as f: + # get first row that starts with "# " + for line in f.readlines(): + # trim leading/trailing whitespaces + line = line.lstrip().rstrip() + # check if line is the title + if line[0:2] == '# ': + # return title + return line[2:] + +def sort_files_titles(files, titles): + """ Sorts the files and titles either by filenames or titles """ + # identify numbered files and sort them + nfiles = [s for s in files if s.split('/')[-1][0].isdigit()] + nfiles = sorted(nfiles, key=natural_keys) + ntitles = [titles[files.index(s)] for s in nfiles] + # sort the files without numbering by the alphabetic order of the titles + atitles = [titles[files.index(s)] for s in files if s not in nfiles] + atitles = sorted(atitles, key=natural_keys) + afiles = [files[titles.index(s)] for s in atitles] + # merge the numbered and unnumbered sorting + return nfiles + afiles, ntitles + atitles + +def get_notebooks(path): + """ Gets a list of all notebooks in a directory """ + # get list of files and their titles + try: + files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.md')] + except FileNotFoundError: + return {} + titles = [get_title(f) for f in files] + # sort the files and titles for display + files_sorted, titles_sorted = sort_files_titles(files, titles) + # generate notebook objects from the sorted lists and return + notebooks = [notebook(f, t) for f, t in zip(files_sorted, titles_sorted)] + return notebooks + +def generate_index_html(version_directory, tutorial_directories, title, version_note): + """ Generates the index HTML file from the given data """ + # get tutorials from the different directories + tutorials = {} + for dir in tutorial_directories: + tutorials[dir] = get_notebooks(os.path.join(version_directory, dir)) + + # Load environment for Jinja and template + env = Environment( + loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), "../")), + autoescape=select_autoescape() + ) + template = env.get_template("tutorials-website/tutorials.html.jinja") + + # render template and return + html = template.render(tutorials=tutorials, title=title, version_note=version_note) + return html + +# Clone the qutip-tutorials repository +repo_url = 'https://github.com/qutip/qutip-tutorials.git' +cloned_repo_dir = tempfile.mkdtemp() +subprocess.run(['git', 'clone', repo_url, cloned_repo_dir]) + +# Set the necessary variables +url_prefix = "https://nbviewer.org/urls/qutip.org/qutip-tutorials" +tutorial_directories = [ + 'pulse-level-circuit-simulation', + 'quantum-circuits', +] + +# Perform the operations on the cloned repository +prefix = "" +suffix = "" +#with open('prefix.html', 'r') as f: + # prefix = f.read() +#with open('suffix.html', 'r') as f: +# suffix = f.read() + +# Version 4 index file +title = 'Tutorials for QuTiP Version 4' +version_note = 'These are the tutorials for QuTiP Version 4. You can find the tutorials for QuTiP Version 5 here.' +html = generate_index_html(os.path.join(cloned_repo_dir, 'tutorials-v4/'), tutorial_directories, title, version_note) +with open('source/tutorials-website/qutip-qip.html', 'w+') as f: + #f.write(prefix) + f.write(html) + #f.write(suffix) + +# Version 5 index file +title = 'Tutorials for QuTiP Version 5' +version_note = 'These are the tutorials for QuTiP Version 5. You can find the tutorials for QuTiP Version 4 here.' +html = generate_index_html(os.path.join(cloned_repo_dir, 'tutorials-v5/'), tutorial_directories, title, version_note) +with open('source/tutorials-website/qutip-qip-v5.html', 'w+') as f: + #f.write(prefix) + f.write(html) + #f.write(suffix) + +# Wipe off the cloned repository +shutil.rmtree(cloned_repo_dir) + +def convert_html_to_rst(html_file_path, rst_file_path): + # Use the subprocess module to call the pandoc command-line tool + subprocess.run(['pandoc', html_file_path, '-o', rst_file_path]) + +html_file_path = 'source/tutorials-website/qutip-qip.html' +html_file_path_v5 = 'source/tutorials-website/qutip-qip-v5.html' + +rst_file_path = 'source/tutorials.rst' +rst_file_path_v5 = 'source/tutorials_v5.rst' + +#convert_html_to_rst(html_file_path, rst_file_path) +convert_html_to_rst(html_file_path_v5, rst_file_path_v5) + + diff --git a/doc/source/tutorials-website/tutorials.html.jinja b/doc/source/tutorials-website/tutorials.html.jinja new file mode 100644 index 00000000..2fc559c8 --- /dev/null +++ b/doc/source/tutorials-website/tutorials.html.jinja @@ -0,0 +1,39 @@ +
+
+

{{ title }}


+
+
+ +

Quantum information processing

+

This section contains tutorials for QuTiP Version 5. You can find the tutorials for QuTiP Version 4 here. To check the version of QuTiP, you can use the qutip.about() command.

+ +
Quantum circuits and algorithms
+
    +{% for item in tutorials['quantum-circuits'] %} +
  • {{ item.title }}
  • +{% endfor %} +
+ + +
Pulse-level circuit simulation
+
    +{% for item in tutorials['pulse-level-circuit-simulation'] %} +
  • {{ item.title }}
  • +{% endfor %} +
+ +
+
+

Contributing

+

If you would like to contribute a notebook or report a bug, you may open +an issue or pull request in the +qutip-tutorials +GitHub repository. +

+

A few of the notebooks are still maintained in the repository +qutip-notebooks and +a complete archive of older versions of the tutorials is maintained there. +

+ +
+
diff --git a/doc/source/tutorials.rst b/doc/source/tutorials.rst deleted file mode 100644 index 358df2e0..00000000 --- a/doc/source/tutorials.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _tutorials: - -************ -Tutorials -************ - -Tutorials related to using quantum gates and circuits in ``qutip-qip`` can be -found `here `_ and -those related to using noise simulators are available at this -`link `_. From 6b81b1eef89abdd7505ba4fd8e7e3c98ac6ce536 Mon Sep 17 00:00:00 2001 From: Boxi Li Date: Sun, 16 Jul 2023 17:12:02 +0200 Subject: [PATCH 4/6] Include the newest change --- doc/source/changelog.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 44faa962..c2cb3827 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -3,7 +3,7 @@ Changelog ********* -Version 0.3.0 (June 1, 2023) +Version 0.3.0 (July 19, 2023) ++++++++++++++++++++++++++++ This release adds to major features to the package. @@ -14,7 +14,9 @@ New features - **MAJOR** qutip-qip backends for qiskit :obj:`qutip_qip.qiskit`. `Google Summer of Code project 2022 `_ (`#155 `_, `#159 `_) - Add class representation of quantum gates. (`#147 `_) - +Documentation +------------- +- Add synced qutip-qip tutorials to documentation on Read the docs (`#207 `_) Version 0.2.3 (December 12, 2022) +++++++++++++++++++++++++++++++++ From df096bfb4ab3670529b51d1146f9bc2895209f8c Mon Sep 17 00:00:00 2001 From: Boxi Li Date: Sun, 16 Jul 2023 17:15:19 +0200 Subject: [PATCH 5/6] Fix the short title underline --- doc/source/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index c2cb3827..05a00ee4 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -4,7 +4,7 @@ Changelog Version 0.3.0 (July 19, 2023) -++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ This release adds to major features to the package. From 8e721bfe1a6da070f56d476067c28cf4e50d9727 Mon Sep 17 00:00:00 2001 From: Boxi Li Date: Sun, 16 Jul 2023 18:28:42 +0200 Subject: [PATCH 6/6] Merge pull request #210 from BoxiLi/testing_bug Remove run_module_suite --- src/qutip_qip/vqa.py | 16 ++++++++-------- tests/test_noise.py | 2 +- tests/test_optpulseprocessor.py | 2 +- tests/test_processor.py | 2 +- tests/test_pulse.py | 2 +- tests/test_qft.py | 5 +---- tests/test_qubits.py | 6 +----- 7 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/qutip_qip/vqa.py b/src/qutip_qip/vqa.py index 1d23946f..156750f1 100644 --- a/src/qutip_qip/vqa.py +++ b/src/qutip_qip/vqa.py @@ -805,20 +805,20 @@ def plot(self, S=None, label_sets=False, top_ten=False, display=True): labels = [ self._label_to_sets(S, bitstring) for bitstring in bitstrings ] - plt.bar( + fig, ax = plt.subplots() + ax.bar( list(range(len(bitstrings))), probs, tick_label=labels if label_sets else bitstrings, width=0.8, ) - plt.xticks(rotation=30) - plt.tight_layout() - plt.xlabel("Measurement outcome") - plt.ylabel("Probability") - plt.title( + ax.tick_params(axis="x", labelrotation=30) + ax.set_xlabel("Measurement outcome") + ax.set_ylabel("Probability") + ax.set_title( "Measurement Outcomes after Optimisation. " f"Cost: {round(min_cost, 2)}" ) - plt.tight_layout() + fig.tight_layout() if display: - plt.show() + fig.show() diff --git a/tests/test_noise.py b/tests/test_noise.py index 6dd90621..9f4640ba 100644 --- a/tests/test_noise.py +++ b/tests/test_noise.py @@ -1,4 +1,4 @@ -from numpy.testing import assert_, run_module_suite, assert_allclose +from numpy.testing import assert_, assert_allclose import numpy as np import pytest diff --git a/tests/test_optpulseprocessor.py b/tests/test_optpulseprocessor.py index 7e1b6163..828fbcfc 100644 --- a/tests/test_optpulseprocessor.py +++ b/tests/test_optpulseprocessor.py @@ -1,6 +1,6 @@ import os -from numpy.testing import (assert_, run_module_suite, assert_allclose, +from numpy.testing import (assert_, assert_allclose, assert_equal) import numpy as np import pytest diff --git a/tests/test_processor.py b/tests/test_processor.py index 83d0b505..63506da2 100644 --- a/tests/test_processor.py +++ b/tests/test_processor.py @@ -2,7 +2,7 @@ from packaging.version import parse as parse_version from numpy.testing import ( - assert_, run_module_suite, assert_allclose, assert_equal) + assert_, assert_allclose, assert_equal) import numpy as np import pytest diff --git a/tests/test_pulse.py b/tests/test_pulse.py index 76fd4fd8..920b0481 100644 --- a/tests/test_pulse.py +++ b/tests/test_pulse.py @@ -1,6 +1,6 @@ from packaging.version import parse as parse_version import numpy as np -from numpy.testing import assert_, run_module_suite, assert_allclose +from numpy.testing import assert_, assert_allclose import pytest import qutip diff --git a/tests/test_qft.py b/tests/test_qft.py index 9aad86e9..3a42d212 100644 --- a/tests/test_qft.py +++ b/tests/test_qft.py @@ -1,4 +1,4 @@ -from numpy.testing import assert_, assert_equal, assert_string_equal, run_module_suite +from numpy.testing import assert_, assert_equal, assert_string_equal from qutip_qip.algorithms.qft import qft, qft_steps, qft_gate_sequence from qutip_qip.operations import gate_sequence_product @@ -59,6 +59,3 @@ def testQFTGateSequenceWithCNOT(self): circuit = qft_gate_sequence(N, swapping=False, to_cnot=True) assert not any([gate.name == "CPHASE" for gate in circuit.gates]) - -if __name__ == "__main__": - run_module_suite() diff --git a/tests/test_qubits.py b/tests/test_qubits.py index 3220c4d9..ed12a529 100644 --- a/tests/test_qubits.py +++ b/tests/test_qubits.py @@ -1,4 +1,4 @@ -from numpy.testing import assert_, run_module_suite +from numpy.testing import assert_ from qutip_qip.qubits import qubit_states from qutip import (tensor, basis) @@ -22,7 +22,3 @@ def testQubitStates(self): psi01_a = tensor(psi0_a, psi1_a) psi01_b = qubit_states(N=2, states=[0, 1]) assert_(psi01_a == psi01_b) - - -if __name__ == "__main__": - run_module_suite()