Giter VIP home page Giter VIP logo

thewalrus's Introduction

The Walrus

Tests

Codecov coverage

CodeFactor Grade

Read the Docs

PyPI - Python Version

JOSS - The Journal of Open Source Software

A library for the calculation of hafnians, Hermite polynomials and Gaussian boson sampling. For more information, please see the documentation.

Features

  • Fast calculation of hafnians, loop hafnians, and torontonians of general and certain structured matrices.
  • An easy to use interface to use the loop hafnian for Gaussian quantum state calculations.
  • Sampling algorithms for hafnian and torontonians of graphs.
  • Efficient classical methods for approximating the hafnian of non-negative matrices.
  • Easy to use implementations of the multidimensional Hermite polynomials, which can also be used to calculate hafnians of all reductions of a given matrix.

Installation

The Walrus requires Python version 3.7, 3.8, 3.9, or 3.10. Installation of The Walrus, as well as all dependencies, can be done using pip:

Compiling from source

The Walrus has the following dependencies:

You can compile the latest development version by cloning the git repository, and installing using pip in development mode.

$ git clone https://github.com/XanaduAI/thewalrus.git
$ cd thewalrus && python -m pip install -e .

Software tests

To ensure that The Walrus library is working correctly after installation, the test suite can be run locally using pytest.

Additional packages are required to run the tests. These dependencies can be found in requirements-dev.txt and can be installed using pip:

$ pip install -r requirements-dev.txt

To run the tests, navigate to the source code folder and run the command

$ make test

Documentation

The Walrus documentation is available online on Read the Docs.

Additional packages are required to build the documentation locally as specified in doc/requirements.txt. These packages can be installed using:

$ sudo apt install pandoc
$ pip install -r docs/requirements.txt

To build the HTML documentation, go to the top-level directory and run the command

$ make doc

The documentation can then be found in the docs/_build/html/ directory.

Contributing to The Walrus

We welcome contributions - simply fork The Walrus repository, and then make a pull request containing your contribution. All contributors to The Walrus will be listed as authors on the releases.

We also encourage bug reports, suggestions for new features and enhancements, and even links to projects, applications or scientific publications that use The Walrus.

Authors

The Walrus is the work of many contributors.

If you are doing research using The Walrus, please cite our paper:

Brajesh Gupt, Josh Izaac and Nicolas Quesada. The Walrus: a library for the calculation of hafnians, Hermite polynomials and Gaussian boson sampling. Journal of Open Source Software, 4(44), 1705 (2019)

Support

If you are having issues, please let us know by posting the issue on our Github issue tracker.

License

The Walrus is free and open source, released under the Apache License, Version 2.0.

thewalrus's People

Contributors

ajmartinezc avatar bastianzim avatar benjaminlanthier avatar bgupt avatar brownj85 avatar co9olguy avatar dependabot[bot] avatar dleclerc33 avatar emaballarin avatar fab1an-q avatar gregorymorse avatar heltluke avatar ilan-tz avatar jakeffbulmer avatar josh146 avatar knw500 avatar maliasadi avatar mandrenkov avatar mhoude2 avatar nagaj avatar nquesada avatar rachelchadwick avatar sduquemesa avatar soranjh avatar thisac avatar thonic avatar timjank avatar trevor-vincent avatar ziofil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thewalrus's Issues

Stop calculating a sample early with minimum/maximum click condition

The user may sometimes only be interested in having samples with a minimum number of photons or clicks. During the calculation of a sample, it may be clear that the number of clicks in the sample may not reach the minimum specified by the user. For example, suppose the user wants samples with 4 or more clicks from a 6 mode device - if in a given sample three modes have returned no clicks, then this sample will never reach the 4 click minimum. Would it be possible to add functionality to stop sampling early if a minimum number of clicks will not be met?

Likewise, the user may be interested in/only care about having samples with a maximum number of photons or clicks. Would it be possible to add functionality to stop sampling early if a maximum number of clicks has already been recorded?

Why is hbar=2? Physicist may assume hbar=1

Before posting an issue

Search existing GitHub issues to make sure the issue does not already exist:
https://github.com/XanaduAI/thewalrus/issues

If posting a library issue, delete everything above the dashed line, and fill
in the template.

If making a feature request, delete the following template and describe, in detail,
the feature and why it is needed.

For general technical details check out our documentation:
https://the-walrus.readthedocs.io


Issue description

Description of the issue - include code snippets and screenshots here
if relevant. You may use the following template below

  • Expected behavior: (What you expect to happen)

  • Actual behavior: (What actually happens)

  • Reproduces how often: (What percentage of the time does it reproduce?)

  • System information: (include operating system version, Python version,
    how you installed The Walrus, and anything else that might be relevant)

Source code and tracebacks

Please include any additional code snippets and error tracebacks related
to the issue here.

Additional information

Any additional information, configuration or data that might be necessary
to reproduce the issue.

Specification of hbar in density matrix function

At line 387 in

thewalrus/quantum.py

beta is calculated with any specification of hbar. Is this correct? I assumed it should inherit the hbar value passed to the density matrix function.

Thanks

Port over to GitHub actions for building the wheels/continuous deployment

It might make sense to port the wheel building CI away from a combination of CircleCI/Appveyor, for a couple of reasons:

  • GitHub actions supports all three platforms (Windows/MacOS/Linux), avoiding the need to split the CI between numerous services.

  • The Appveyor account used is my personal account, so other members of development team are unable to modify the settings or manage builds.

In addition, we could also set up continuous deployment; when a new GitHub release is made, the wheels could be automatically built, tested, and uploaded.

It is worth starting from the GitHub Action workflow used over in the PennyLane-Lightning repo:

One big question mark is the performance --- GitHub actions might be slower than our current combination of CircleCI/Appveyor.

Remove bullet points from documentation tips

Currently, the 'tips' used in the documentation contain bullet points:

.. tip::

   * To obtain the overlap of a *pure* gaussian state with quadrature covariance matrix
     :math:`\mathbf{V}` and vector of means :math:`\mathbf{r}` and a given Fock state
     :math:`\langle \mathbf{n}|` use the function
     :func:`thewalrus.quantum.pure_state_amplitude`.

This looks a bit strange in the documentation, since the 'tip' boxes are only used for a single statement each:
image

We should remove the bullet points, so that they look better:

image

Installation - UnicodeDecodeError

Hi,
I'm trying to install hafnian in my ubuntu, but it displays an error

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3125: ordinal not in range(128)

The full information is

root@e8c01b001d47:/# python3.6 -m pip install hafnian
Collecting hafnian
  Using cached https://files.pythonhosted.org/packages/fe/0f/dd394adfc0f93cc239d0c0f3eb63c116fa92d14031ad3b05e8d4cffcba6b/Hafnian-0.1.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-yfs7j_wf/hafnian/setup.py", line 73, in <module>
        'long_description': open('README.rst').read(),
      File "/usr/local/lib/python3.6/encodings/ascii.py", line 26, in decode
        return codecs.ascii_decode(input, self.errors)[0]
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3125: ordinal not in range(128)

Could you fix it? Thank you!

Different conventions for Gaussian Matrix elements

When calling The Walrus to calculate the matrix element <i_1,i_2,...,i_N | \rho |j_1,j_2,....,j_N> two different types of tensors can be obtained. If the the routines involve multidimensional polynomials one the tensor above is returned in the following order

tensor[i_1, i_2, ..., i_N, j_1, j_2, ..., j_N]

otherwise they come in the following "strawberryfields" order

tensor[i_1, j_1, i_2, j_2, ..., i_N,j_N]

this is confusing and a unified notation should be established.

Testing using pytest failed on i586 microarchitecture

Hello,

I'm packaging python-thewalrus on linux openSUSE Tumbleweed.
Testing thewalrus with pytest failed on i586 microarchitecture but pass on x86.

python3-Cython-0.29.21
python3-dask-2.21.0
python3-numba-0.49.1
python3-pytest-5.4.3
python3-numpy-devel-1.18.4
python3-numpy-1.18.4
python3-scipy-1.4.1
gcc-c++-10-1.14
eigen3-devel-3.3.7
gtest-1.10.0

Full log here: https://build.opensuse.org/build/home:andythe_great:branches:home:andythe_great/openSUSE_Tumbleweed/i586/python-thewalrus/_log

[ 2668s] =================================== FAILURES ===================================
[ 2668s] __________________ TestHafnian.test_ones[complex128-8-False] ___________________
[ 2668s] 
[ 2668s] self = <test_hafnian.TestHafnian object at 0xa17a1400>, n = 8
[ 2668s] dtype = <class 'numpy.complex128'>, recursive = False
[ 2668s] 
[ 2668s]     @pytest.mark.parametrize("n", [6, 8])
[ 2668s]     def test_ones(self, n, dtype, recursive):
[ 2668s]         """Check hafnian(J_2n)=(2n)!/(n!2^n)"""
[ 2668s]         A = dtype(np.ones([2 * n, 2 * n]))
[ 2668s]         haf = hafnian(A, recursive=recursive)
[ 2668s]         expected = fac(2 * n) / (fac(n) * (2 ** n))
[ 2668s] >       assert np.allclose(haf, expected)
[ 2668s] E       assert False
[ 2668s] E        +  where False = <function allclose at 0xaa7cdda8>(-841421295.0000107, 2027025.0)
[ 2668s] E        +    where <function allclose at 0xaa7cdda8> = np.allclose
[ 2668s] 
[ 2668s] thewalrus/tests/test_hafnian.py:197: AssertionError
[ 2668s] ____________________ TestHafnian.test_ones[float64-8-False] ____________________
[ 2668s] 
[ 2668s] self = <test_hafnian.TestHafnian object at 0xa15aa448>, n = 8
[ 2668s] dtype = <class 'numpy.float64'>, recursive = False
[ 2668s] 
[ 2668s]     @pytest.mark.parametrize("n", [6, 8])
[ 2668s]     def test_ones(self, n, dtype, recursive):
[ 2668s]         """Check hafnian(J_2n)=(2n)!/(n!2^n)"""
[ 2668s]         A = dtype(np.ones([2 * n, 2 * n]))
[ 2668s]         haf = hafnian(A, recursive=recursive)
[ 2668s]         expected = fac(2 * n) / (fac(n) * (2 ** n))
[ 2668s] >       assert np.allclose(haf, expected)
[ 2668s] E       assert False
[ 2668s] E        +  where False = <function allclose at 0xaa7cdda8>(-841421295.0000104, 2027025.0)
[ 2668s] E        +    where <function allclose at 0xaa7cdda8> = np.allclose
[ 2668s] 
[ 2668s] thewalrus/tests/test_hafnian.py:197: AssertionError
[ 2668s] _______________ TestHafnian.test_block_ones[complex128-8-False] ________________
[ 2668s] 
[ 2668s] self = <test_hafnian.TestHafnian object at 0xa154d3d0>, n = 8
[ 2668s] dtype = <class 'numpy.complex128'>, recursive = False
[ 2668s] 
[ 2668s]     @pytest.mark.parametrize("n", [6, 8])
[ 2668s]     def test_block_ones(self, n, dtype, recursive):
[ 2668s]         """Check hafnian([[0, I_n], [I_n, 0]])=n!"""
[ 2668s]         O = np.zeros([n, n])
[ 2668s]         B = np.ones([n, n])
[ 2668s]         A = np.vstack([np.hstack([O, B]), np.hstack([B, O])])
[ 2668s]         A = dtype(A)
[ 2668s]         haf = hafnian(A, recursive=recursive)
[ 2668s]         expected = float(fac(n))
[ 2668s] >       assert np.allclose(haf, expected)
[ 2668s] E       assert False
[ 2668s] E        +  where False = <function allclose at 0xaa7cdda8>(-1158006571.0937524, 40320.0)
[ 2668s] E        +    where <function allclose at 0xaa7cdda8> = np.allclose
[ 2668s] 
[ 2668s] thewalrus/tests/test_hafnian.py:208: AssertionError
[ 2668s] _________________ TestHafnian.test_block_ones[float64-8-False] _________________
[ 2668s] 
[ 2668s] self = <test_hafnian.TestHafnian object at 0xa15aa880>, n = 8
[ 2668s] dtype = <class 'numpy.float64'>, recursive = False
[ 2668s] 
[ 2668s]     @pytest.mark.parametrize("n", [6, 8])
[ 2668s]     def test_block_ones(self, n, dtype, recursive):
[ 2668s]         """Check hafnian([[0, I_n], [I_n, 0]])=n!"""
[ 2668s]         O = np.zeros([n, n])
[ 2668s]         B = np.ones([n, n])
[ 2668s]         A = np.vstack([np.hstack([O, B]), np.hstack([B, O])])
[ 2668s]         A = dtype(A)
[ 2668s]         haf = hafnian(A, recursive=recursive)
[ 2668s]         expected = float(fac(n))
[ 2668s] >       assert np.allclose(haf, expected)
[ 2668s] E       assert False
[ 2668s] E        +  where False = <function allclose at 0xaa7cdda8>(-869641728.3203143, 40320.0)
[ 2668s] E        +    where <function allclose at 0xaa7cdda8> = np.allclose
[ 2668s] 
[ 2668s] thewalrus/tests/test_hafnian.py:208: AssertionError
[ 2668s] =========================== short test summary info ============================
[ 2668s] FAILED thewalrus/tests/test_hafnian.py::TestHafnian::test_ones[complex128-8-False]
[ 2668s] FAILED thewalrus/tests/test_hafnian.py::TestHafnian::test_ones[float64-8-False]
[ 2668s] FAILED thewalrus/tests/test_hafnian.py::TestHafnian::test_block_ones[complex128-8-False]
[ 2668s] FAILED thewalrus/tests/test_hafnian.py::TestHafnian::test_block_ones[float64-8-False]
[ 2668s] ================== 4 failed, 947 passed in 2398.51s (0:39:58) ==================

perm() returns 0.0 for large matrices

Consider the following code with hafnian++

import hafnian as haf
import numpy as np

n = 16
A = np.array([[0.308549, 0.350677], [0.350677, 0.398558]])
Atot = haf.kron_reduced(A,[n,n])
print(haf.perm(Atot))

it produces 0.0 as an outcome almost instantaneously. The same code with n=15 provides an output ~5e16 after a few seconds. The zero outcome with n=16 doesn't look right...

Dead links in the docs

The links to thewalrus.quantum and thewalrus.samples are not being produced in read the docs or when compiled locally.

Add support for calculating the permanent using the BBFG algorithm

Issue description

Currently, The Walrus uses the Ryser formula to calculate permanents of arbitrary matrices (https://en.wikipedia.org/wiki/Computing_the_permanent#Ryser_formula). Another useful algorithm to calculate permanents is the Balasubramanian–Bax–Franklin–Glynn (BBFG) formula (https://en.wikipedia.org/wiki/Computing_the_permanent#Balasubramanian%E2%80%93Bax%E2%80%93Franklin%E2%80%93Glynn_formula). Having both methods implemented will allow for performance and accuracy comparisons and trade-offs.

Required tasks:

  • Implement a templated version of the BBFG formula in C++, located in the ./include directory (see existing implementation)
  • Add tests for the new algorithm to the /tests directory
  • The implemented algorithm should also be callable from python (Note: this can be achieved by adding the correct headers and wrapper functions in setup.py, /include/libwalrus.hpp and /include/libwalrus.pyx)

'pip install thewalrus' fails in Python 3.9.

Issue description

Trying to install thewalrus with "pip install thewalrus" fails when using python 3.9.

  • Expected behavior: (What you expect to happen)
    Clean install.

  • Actual behavior: (What actually happens)
    image

I suspect this isn't necessary as the issue is lack of a wheel for python 3.9

  • Reproduces how often: (What percentage of the time does it reproduce?)
    Every time.

  • System information: (include operating system version, Python version,
    how you installed The Walrus, and anything else that might be relevant)
    Python 3.9.1.
    Windows 10.0.19041

[openSUSE Linux] E ModuleNotFoundError: No module named 'thewalrus'

Hello,
I am trying to package thewalrus into linux openSUSE Tumbleweed.

I write spec file that contain compile instruction for the source code.
Which can be found here: https://build.opensuse.org/package/show/home:andythe_great/python-thewalrus
With full error log here: https://build.opensuse.org/package/live_build_log/home:andythe_great/python-thewalrus/openSUSE_Tumbleweed/x86_64

The dependencies installed are as follows.

Python 3.8.4
gcc-c++ 10-1
python3-Cython-0.29
python3-dask-2.21
python3-numba-0.49
python3-numpy-1.18.4
python3-pytest-5.4.3
python3-scipy-1.4.1
eigen3 3.3.7
lapacke-devel 3.8.0

I encounter an issue during testing using pytest. I'm uncertain why the error occured.
Thanks

[  276s] + pytest
[  277s] ============================= test session starts ==============================
[  277s] platform linux -- Python 3.8.4, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
[  277s] rootdir: /home/abuild/rpmbuild/BUILD/thewalrus-0.12.0
[  278s] collected 0 items / 13 errors
[  278s] 
[  278s] ==================================== ERRORS ====================================
[  278s] ___________ ERROR collecting thewalrus/tests/test_fock_gradients.py ____________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_fock_gradients.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_fock_gradients.py:16: in <module>
[  278s]     from thewalrus.fock_gradients import (
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] _______________ ERROR collecting thewalrus/tests/test_hafnian.py _______________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_hafnian.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_hafnian.py:21: in <module>
[  278s]     import thewalrus as hf
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] ___________ ERROR collecting thewalrus/tests/test_hafnian_approx.py ____________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_hafnian_approx.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_hafnian_approx.py:21: in <module>
[  278s]     from thewalrus import hafnian, haf_real
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] __________ ERROR collecting thewalrus/tests/test_hafnian_repeated.py ___________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_hafnian_repeated.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_hafnian_repeated.py:21: in <module>
[  278s]     from thewalrus import hafnian_repeated
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] ______ ERROR collecting thewalrus/tests/test_hermite_multidimensional.py _______
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_hermite_multidimensional.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_hermite_multidimensional.py:22: in <module>
[  278s]     from thewalrus import hermite_multidimensional, hafnian_batched, hafnian_repeated
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] _____________ ERROR collecting thewalrus/tests/test_integration.py _____________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_integration.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_integration.py:20: in <module>
[  278s]     from thewalrus.quantum import density_matrix, state_vector, probabilities, update_probabilities_with_loss
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] ______________ ERROR collecting thewalrus/tests/test_permanent.py ______________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_permanent.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_permanent.py:21: in <module>
[  278s]     from thewalrus import perm, perm_real, perm_complex, permanent_repeated
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] _______________ ERROR collecting thewalrus/tests/test_quantum.py _______________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_quantum.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_quantum.py:24: in <module>
[  278s]     from thewalrus.symplectic import rotation, squeezing, interferometer, two_mode_squeezing, beam_splitter, loss
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] ______________ ERROR collecting thewalrus/tests/test_reference.py ______________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_reference.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_reference.py:21: in <module>
[  278s]     from thewalrus.reference import T, spm, pmp, hafnian
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] _______________ ERROR collecting thewalrus/tests/test_samples.py _______________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_samples.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_samples.py:21: in <module>
[  278s]     from thewalrus.samples import (
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] __________ ERROR collecting thewalrus/tests/test_samples_classical.py __________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_samples_classical.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_samples_classical.py:20: in <module>
[  278s]     from thewalrus.csamples import rescale_adjacency_matrix_thermal, generate_thermal_samples
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] _____________ ERROR collecting thewalrus/tests/test_symplectic.py ______________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_symplectic.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_symplectic.py:21: in <module>
[  278s]     from thewalrus import symplectic
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] _____________ ERROR collecting thewalrus/tests/test_torontonian.py _____________
[  278s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/thewalrus-0.12.0/thewalrus/tests/test_torontonian.py'.
[  278s] Hint: make sure your test modules/packages have valid Python names.
[  278s] Traceback:
[  278s] thewalrus/tests/test_torontonian.py:20: in <module>
[  278s]     from thewalrus import tor
[  278s] E   ModuleNotFoundError: No module named 'thewalrus'
[  278s] =========================== short test summary info ============================
[  278s] ERROR thewalrus/tests/test_fock_gradients.py
[  278s] ERROR thewalrus/tests/test_hafnian.py
[  278s] ERROR thewalrus/tests/test_hafnian_approx.py
[  278s] ERROR thewalrus/tests/test_hafnian_repeated.py
[  278s] ERROR thewalrus/tests/test_hermite_multidimensional.py
[  278s] ERROR thewalrus/tests/test_integration.py
[  278s] ERROR thewalrus/tests/test_permanent.py
[  278s] ERROR thewalrus/tests/test_quantum.py
[  278s] ERROR thewalrus/tests/test_reference.py
[  278s] ERROR thewalrus/tests/test_samples.py
[  278s] ERROR thewalrus/tests/test_samples_classical.py
[  278s] ERROR thewalrus/tests/test_symplectic.py
[  278s] ERROR thewalrus/tests/test_torontonian.py
[  278s] !!!!!!!!!!!!!!!!!!! Interrupted: 13 errors during collection !!!!!!!!!!!!!!!!!!!
[  278s] ============================== 13 errors in 1.81s ==============================
[  279s] error: Bad exit status from /var/tmp/rpm-tmp.xH9I3J (%check)

My guess is that

Convenience functions to change ordering of quadratures

Functions to switch the ordering of the vector of means and covariance matrix from xxpp to xpxp should be provided in the quantum.conversions module. These functions should operate by permuting the elements of the array using fancy indexing and not by multiplying by permutation matrices.

Build/package The Walrus using PEP 517/518

PEP 517 and PEP 518 introduced a new paradigm for building/packaging Python projects.

  • Configuring requirements and build settings is now done via a top-level pyproject.toml configuration file

  • The build system (e.g., setuptools, Poetry) is independent of project requirements and build settings, allowing the build system to be switched out independently.

  • The interim package pep517 can be used to trigger various build/packaging hooks.

The major advantage are the requirements being separated from the build. Currently in The Walrus, the setup.py file requires Cython for the line

from Cython.Build import cythonize

This import occurs before the call to the setup() function, so a user installing from source must manually install Cython before running pip (this has been a recurring issue with The Walrus installations). Using PEP 517, however, Cython would be automatically installed, if needed.

Missing documentation

The following modules/functionality is lacking documentation:

  • symplectic

  • csamples

  • The fock_tensor function from quantum

  • fock_gradients

Speed up photon number covariance

It would be nice to vectorize and possibly just-in-time compile the function photon_number_covmat.
The current one is unnecessarily slow.

[unitaryhack] Improve the calculation of multidimensional hermite polynomials

This issue has been tagged for a bounty during unitaryHACK

Currently all calculations of multidimensional hermite polynomials are carried in double precision even though the C++ functions to do these calculations are templated to allow for any datatype.

A useful addition to The Walrus would be to allow the Python modules to have the C++ functions do calculations in long double precision. Note that even if the input and output of the C++ functions is ultimately casted to double it is still useful to internally do the calculations in long double given that numerical errors can accumulate very fast. Similar issues for the calculations of hafnians have been solved by doing its internal calculation in long double.

Two alternatives come to mind to achieve this:

  1. Make a wrapper function that takes as input the matrix R and vector y as double precision arrays and then converts them to long double and pass them to the templated version of hermite_multidimensional_cpp. An array in long double would be returned and then the wrapper function would cast this array into double precision and return it to Python using the ArrayWrapper for double datatypes in libwalrus.pyx.

  2. A second option that would avoid any type conversion is to write new array wrappers that allow to pass transparently long double arrays into numpy np.longdouble.

An important caveat for testing is that in MS Visual C++ long double is an alias for double so no gain in precision can be obtained by using this compiler.

Heralded non-Gaussian state preparation gallery

There are a number of non-Gaussian states that can be prepared by heralding Gaussian states using photon-number-resolving detectors. For example in https://journals.aps.org/pra/abstract/10.1103/PhysRevA.100.022341 several recipes for generating Fock, cat and cubic-phase states are studied. More recently there are preprints by Shringarpure and Franson (https://arxiv.org/abs/1908.08028) and Thekkadath et al. (https://arxiv.org/abs/1908.10314) discussing new setups to generate non-Gaussian states. It would be good to setup a gallery in The Walrus documentation where each of these schemes (and any other that I am missing or that are developed in the future) can be found and studied using the tools available in this library.

Add support for Python 3.8

Now that llvmlite supports Python 3.8, we could feasibly create Python wheels for 3.8. I believe llvmlite was the last dependency holdout, but I could be mistaken.

This should be as simple as removing cp38-* from the environment variable CIBW_SKIP in .circleci/config.yml and appveyor.yml, and the new wheels should start being built. However, additional debugging could be required.

More information about configuring Appveyor and CircleCI for building wheels can be found over at the cibuildwheel repository.

Implementation of A matrix correct?


Hi, I am a grad student working through the GBS literature and I have started using thewalrus, I mainly want to make sure the library is working as expected.

Issue description

Here,
you seem to calculate the "A matrix" as \boldsymbol{A} = \boldsymbol{X}( I - \sigma_Q^{-1} )^* where the * denotes the complex conjugate. However, in the literature, there is no complex conjugate there? Why is it in your code?

Something along the same lines: When I was going through the calculation for the probabilities in GBS, I actually always get that \bf{A} = \bf{B}^*  \oplus \bf{B}
instead of \bf{A} = \bf{B}  \oplus \bf{B}^*
as is written in the original papers? Can you confirm this, or am I messing up?

Allow user to choose algorithm in hafnian wrapper

Currently, when calling the hafnian Python wrapper, all you specify is whether recursive is True or False:

hafnian(A, loop=True, recursive=True, quad=True, approx=False, etc...)

We then apply logic to call the best case hafnian algorithm considering the matrix+options the user has provided.

We should modify it to look like this:

hafnian(A, loop=True, algorithm="best", options={})

where algorithm is a string containing the algorithm to use:

  • best is the current logic (and the default)

  • recursive

  • trace

  • approx

and options are the algorithm specific options, i.e. options={'samples': 100} for the approx algorithm, options={'quad': True} for the recursive, options={'powtrace': 'eigenvalues'} for the trace algorithm, etc.

Note: the moment/repeated hafnian will have to remain its own function, since it also takes rpt as an argument.

Running `make` within `examples/` fails due to missing `example-f90` target

It appears that the line

all: example-f90 example-cpp

in examples/Makefile should be modified to remove the example-f90 target, as there does not seem to be any f90 wrapper for example.o.

This extraneous target leads to an error when running make in examples/ of the form:

(base) poulson@bartelby:~/Source/thewalrus/examples$ make
make: *** No rule to make target 'example-f90', needed by 'all'.  Stop.

P ( [ ℓ ] ) is not defined. Is it the power set of (0, 1, ...l-1)?

Before posting an issue

Search existing GitHub issues to make sure the issue does not already exist:
https://github.com/XanaduAI/thewalrus/issues

If posting a library issue, delete everything above the dashed line, and fill
in the template.

If making a feature request, delete the following template and describe, in detail,
the feature and why it is needed.

For general technical details check out our documentation:
https://the-walrus.readthedocs.io


Issue description

Description of the issue - include code snippets and screenshots here
if relevant. You may use the following template below

  • Expected behavior: (What you expect to happen)

  • Actual behavior: (What actually happens)

  • Reproduces how often: (What percentage of the time does it reproduce?)

  • System information: (include operating system version, Python version,
    how you installed The Walrus, and anything else that might be relevant)

Source code and tracebacks

Please include any additional code snippets and error tracebacks related
to the issue here.

Additional information

Any additional information, configuration or data that might be necessary
to reproduce the issue.

Update docs with xp-covariance matrix

In the current version of the documentation Gaussian states are described in terms of complex normal covariance matrix even tough the input to almost every function related to GBS is an xp-covariance matrix.

Fix tests broken due to PyTest update

pytest has just been updated to version 5.4.0, and have changed the behaviour of pytest.mark.parametrize. Previously, you could use the decorator to 'inject' values of undefined fixtures directly into a test function. This was an undocument feature, and no longer works. Now, you must include any parametrized arguments directly in the test function signature.

This affects the following two tests:

==================================== ERRORS ====================================
__________ ERROR collecting thewalrus/tests/test_hafnian_repeated.py ___________
In function "test_2x2":
Parameter "dtype" should be declared explicitly via indirect or in function itself
______________ ERROR collecting thewalrus/tests/test_permanent.py ______________
In function "test_complex":
Parameter "dtype" should be declared explicitly via indirect or in function itself

This can be fixed by including dtype directly in the arguments of the two test functions above.

Linear algebra of small matrices

The Walrus currently uses eigen to do linear algebra in C++, this allows for flexibility. Typically linear algebra routines are optimised for dealing with big matrices, however, in the walrus one will never deal with a matrix that is larger than say 120. It would be good to know what are the best linear algebra libraries for "small" matrices.

Instability in quantum.probabilities


Issue description

Description of the issue: When using the function quantum.probabilities, I found that for some input parameters, the photon statistics probability vector is not even close to being normalized to unity. The issue is not due to an insufficient cutoff. Find a screenshot below for the output of probabilities for a single-mode displaced squeezed state vs a coherent state
image

Here, while the output of probabilities for a coherent state is as expected, the output for the squeezed state with the same displacement is off. In particular, this behavior seems to be very much dependent on the parameters of squeezing/displacement amplitude.

  • Expected behavior: probabilities should always output a vector that is properly normalized to unity

  • Actual behavior: for most parameters, the output is normalized, but for some special parameters it is not

  • Reproduces how often: No idea, I found this because I was studying the output distribution of displaced squeezed states vs coherent states depending on the squeezing/displacement ratio. Additionally, as I found out in the book of Gerry/Knight, the relative phase is important.

  • System information: I installed TheWalrus 0.14 via pip.

Source code and tracebacks

Here, I will simply paste the code that I used to get the above plot. The parameters entering are basically the squeezing degree r and the complex displacement amplitude alpha which consists of an absolute value alpha_abs and a phase theta. I have played around with these parameters and for most of these, the output of probabilities seems just fine.

# coding: utf-8

# In[3]:


import numpy as np
from scipy.linalg import block_diag
import matplotlib.pyplot as plt

from thewalrus.quantum import probabilities


# In[14]:


# Single mode with displacement of alpha
alpha_abs = np.sqrt(50)
theta = 1.1780972450961724
alpha = alpha_abs * np.exp(1j * theta)

# Vector of means of length 2
mu = np.sqrt(2) * np.array([alpha.real, alpha.imag])

# Covariance matrix of squeezed state
rs = np.array([0.5])
S = block_diag(np.diag(np.exp(rs)), np.diag(np.exp(-rs))) 

cov = 0.5 * S @ S.T

cutoff = 100
    
probs_displaced_squeezed = probabilities(mu, cov, cutoff, hbar=1.0)
print(f"normalization of probabilities: {np.sum(probs_displaced_squeezed)}")


# In[19]:


cov_coh = 0.5 * np.identity(2)
probs_coherent = probabilities(mu, cov_coh, cutoff, hbar=1.0)


# In[22]:


xticks = np.arange(len(probs_displaced_squeezed))
plt.bar(xticks, probs_displaced_squeezed, alpha=0.5, color="b", label="displaced_squeezed", align="center")
plt.bar(xticks, probs_coherent, color="r", alpha=0.5, label="coh", align="center")

plt.xlabel("$n$")
plt.ylabel("$p(n)$")
plt.legend()
plt.show()

Additional information

I could also directly send a jupyter notebook to you if you want me to. It would be superb if you could let me know if you can reproduce this behavior.

FTBFS with more stiff CFLAGS

Issue description

Description of the issue - include code snippets and screenshots here
if relevant. You may use the following template below

  • Expected behavior: build passes

  • Actual behavior:

[   30s] + /usr/bin/python3 setup.py build '--executable=/usr/bin/python3 -s'
[   31s] Compiling thewalrus/libwalrus.pyx because it changed.
[   31s] [1/1] Cythonizing thewalrus/libwalrus.pyx
[   31s] running build
[   31s] running config_cc
[   31s] unifing config_cc, config, build_clib, build_ext, build commands --compiler options
[   31s] running config_fc
[   31s] unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
[   31s] running build_src
[   31s] build_src
[   31s] building extension "libwalrus" sources
[   31s] build_src: building npy-pkg config files
[   31s] running build_py
[   31s] creating build
[   31s] creating build/lib.linux-x86_64-3.8
[   31s] creating build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/__init__.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/_hafnian.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/_hermite_multidimensional.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/_low_rank_haf.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/_permanent.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/_torontonian.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/_version.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/csamples.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/fock_gradients.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/quantum.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/random.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/reference.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/samples.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] copying thewalrus/symplectic.py -> build/lib.linux-x86_64-3.8/thewalrus
[   31s] package init file 'thewalrus/tests/__init__.py' not found (or not a regular file)
[   31s] creating build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/conftest.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_fock_gradients.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_hafnian.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_hafnian_approx.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_hafnian_repeated.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_hermite_multidimensional.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_integration.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_low_rank_haf.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_permanent.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_quantum.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_reference.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_samples.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_samples_classical.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_symplectic.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] copying thewalrus/tests/test_torontonian.py -> build/lib.linux-x86_64-3.8/thewalrus/tests
[   31s] package init file 'thewalrus/tests/__init__.py' not found (or not a regular file)
[   31s] running build_ext
[   31s] customize UnixCCompiler
[   31s] customize UnixCCompiler using build_ext
[   31s] customize UnixCCompiler
[   31s] customize UnixCCompiler using build_ext
[   31s] building 'libwalrus' extension
[   31s] compiling C++ sources
[   31s] C compiler: g++ -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -g -DOPENSSL_LOAD_CONF -fwrapv -fno-semantic-interposition -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -g -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -g -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -fPIC
[   31s] 
[   31s] creating build/temp.linux-x86_64-3.8/thewalrus
[   31s] compile options: '-Ithewalrus -I -I/usr/lib64/python3.8/site-packages/numpy/core/include -I/usr/local/include/eigen3 -I/usr/include/eigen3 -Iinclude -I/usr/lib64/python3.8/site-packages/numpy/core/include -I/usr/include/python3.8 -c'
[   31s] extra options: '-std=c++11 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -I/usr/lib64/python3.8/site-packages/numpy/core/include'
[   31s] g++: thewalrus/libwalrus.cpp
[   39s] In file included from /usr/lib64/python3.8/site-packages/numpy/core/include/numpy/ndarraytypes.h:1822,
[   39s]                  from /usr/lib64/python3.8/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,
[   39s]                  from /usr/lib64/python3.8/site-packages/numpy/core/include/numpy/arrayobject.h:4,
[   39s]                  from thewalrus/libwalrus.cpp:679:
[   39s] /usr/lib64/python3.8/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning "Using deprecated NumPy API, disable it with " "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
[   39s]    17 | #warning "Using deprecated NumPy API, disable it with " \
[   39s]       |  ^~~~~~~
[   39s] In file included from thewalrus/../include/libwalrus.hpp:16,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/eigenvalue_hafnian.hpp:143: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   143 |     #pragma omp parallel for
[   39s]       | 
[   39s] include/eigenvalue_hafnian.hpp:199: warning: ignoring ‘#pragma omp critical’ [-Wunknown-pragmas]
[   39s]   199 |         #pragma omp critical
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:16,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/eigenvalue_hafnian.hpp:229: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   229 |     #pragma omp parallel for
[   39s]       | 
[   39s] include/eigenvalue_hafnian.hpp:316: warning: ignoring ‘#pragma omp critical’ [-Wunknown-pragmas]
[   39s]   316 |         #pragma omp critical
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:17,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/recursive_hafnian.hpp:62: warning: ignoring ‘#pragma omp task’ [-Wunknown-pragmas]
[   39s]    62 |     #pragma omp task shared(h1)
[   39s]       | 
[   39s] include/recursive_hafnian.hpp:84: warning: ignoring ‘#pragma omp task’ [-Wunknown-pragmas]
[   39s]    84 |     #pragma omp task shared(h2)
[   39s]       | 
[   39s] include/recursive_hafnian.hpp:87: warning: ignoring ‘#pragma omp taskwait’ [-Wunknown-pragmas]
[   39s]    87 |     #pragma omp taskwait
[   39s]       | 
[   39s] include/recursive_hafnian.hpp:119: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   119 |     #pragma omp parallel for
[   39s]       | 
[   39s] include/recursive_hafnian.hpp:128: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   128 |     #pragma omp parallel
[   39s]       | 
[   39s] include/recursive_hafnian.hpp:129: warning: ignoring ‘#pragma omp single’ [-Wunknown-pragmas]
[   39s]   129 |     #pragma omp single nowait
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:18,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/repeated_hafnian.hpp:104: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   104 | #pragma omp parallel
[   39s]       | 
[   39s] include/repeated_hafnian.hpp:178: warning: ignoring ‘#pragma omp critical’ [-Wunknown-pragmas]
[   39s]   178 | #pragma omp critical
[   39s]       | 
[   39s] include/repeated_hafnian.hpp:214: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   214 | #pragma omp parallel
[   39s]       | 
[   39s] include/repeated_hafnian.hpp:304: warning: ignoring ‘#pragma omp critical’ [-Wunknown-pragmas]
[   39s]   304 | #pragma omp critical
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:19,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/hafnian_approx.hpp:77: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]    77 |     #pragma omp parallel for shared(determinants)
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:20,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/torontonian.hpp:121: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   121 |     #pragma omp parallel for shared(localsum)
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:21,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/permanent.hpp:129: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   129 |     #pragma omp parallel for shared(tot)
[   39s]       | 
[   39s] include/permanent.hpp:224: warning: ignoring ‘#pragma omp parallel’ [-Wunknown-pragmas]
[   39s]   224 |     #pragma omp parallel for shared(tot)
[   39s]       | 
[   39s] In file included from thewalrus/../include/libwalrus.hpp:18,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/repeated_hafnian.hpp: In function ‘T libwalrus::hafnian_rpt(std::vector<T>&, std::vector<int>&)’:
[   39s] include/repeated_hafnian.hpp:124:18: error: there are no arguments to ‘omp_get_num_threads’ that depend on a template parameter, so a declaration of ‘omp_get_num_threads’ must be available [-fpermissive]
[   39s]   124 |     int chunks = omp_get_num_threads();
[   39s]       |                  ^~~~~~~~~~~~~~~~~~~
[   39s] include/repeated_hafnian.hpp:124:18: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
[   39s] include/repeated_hafnian.hpp:125:14: error: there are no arguments to ‘omp_get_thread_num’ that depend on a template parameter, so a declaration of ‘omp_get_thread_num’ must be available [-fpermissive]
[   39s]   125 |     int id = omp_get_thread_num();
[   39s]       |              ^~~~~~~~~~~~~~~~~~
[   39s] include/repeated_hafnian.hpp: In function ‘T libwalrus::loop_hafnian_rpt(std::vector<T>&, std::vector<T>&, std::vector<int>&)’:
[   39s] include/repeated_hafnian.hpp:219:18: error: there are no arguments to ‘omp_get_num_threads’ that depend on a template parameter, so a declaration of ‘omp_get_num_threads’ must be available [-fpermissive]
[   39s]   219 |     int chunks = omp_get_num_threads();
[   39s]       |                  ^~~~~~~~~~~~~~~~~~~
[   39s] include/repeated_hafnian.hpp:220:34: error: there are no arguments to ‘omp_get_thread_num’ that depend on a template parameter, so a declaration of ‘omp_get_thread_num’ must be available [-fpermissive]
[   39s]   220 |     int id = (chunks == 1) ? 0 : omp_get_thread_num();
[   39s]       |                                  ^~~~~~~~~~~~~~~~~~
[   39s] include/repeated_hafnian.hpp: In instantiation of ‘T libwalrus::hafnian_rpt(std::vector<T>&, std::vector<int>&) [with T = std::complex<long double>]’:
[   39s] include/repeated_hafnian.hpp:344:32:   required from here
[   39s] include/repeated_hafnian.hpp:124:37: error: ‘omp_get_num_threads’ was not declared in this scope
[   39s]   124 |     int chunks = omp_get_num_threads();
[   39s]       |                  ~~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp:125:32: error: ‘omp_get_thread_num’ was not declared in this scope
[   39s]   125 |     int id = omp_get_thread_num();
[   39s]       |              ~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp: In instantiation of ‘T libwalrus::hafnian_rpt(std::vector<T>&, std::vector<int>&) [with T = long double]’:
[   39s] include/repeated_hafnian.hpp:381:32:   required from here
[   39s] include/repeated_hafnian.hpp:124:37: error: ‘omp_get_num_threads’ was not declared in this scope
[   39s]   124 |     int chunks = omp_get_num_threads();
[   39s]       |                  ~~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp:125:32: error: ‘omp_get_thread_num’ was not declared in this scope
[   39s]   125 |     int id = omp_get_thread_num();
[   39s]       |              ~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp: In instantiation of ‘T libwalrus::loop_hafnian_rpt(std::vector<T>&, std::vector<T>&, std::vector<int>&) [with T = std::complex<long double>]’:
[   39s] include/repeated_hafnian.hpp:422:42:   required from here
[   39s] include/repeated_hafnian.hpp:219:37: error: ‘omp_get_num_threads’ was not declared in this scope
[   39s]   219 |     int chunks = omp_get_num_threads();
[   39s]       |                  ~~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp:220:52: error: ‘omp_get_thread_num’ was not declared in this scope
[   39s]   220 |     int id = (chunks == 1) ? 0 : omp_get_thread_num();
[   39s]       |                                  ~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp: In instantiation of ‘T libwalrus::loop_hafnian_rpt(std::vector<T>&, std::vector<T>&, std::vector<int>&) [with T = long double]’:
[   39s] include/repeated_hafnian.hpp:462:42:   required from here
[   39s] include/repeated_hafnian.hpp:219:37: error: ‘omp_get_num_threads’ was not declared in this scope
[   39s]   219 |     int chunks = omp_get_num_threads();
[   39s]       |                  ~~~~~~~~~~~~~~~~~~~^~
[   39s] include/repeated_hafnian.hpp:220:52: error: ‘omp_get_thread_num’ was not declared in this scope
[   39s]   220 |     int id = (chunks == 1) ? 0 : omp_get_thread_num();
[   39s]       |                                  ~~~~~~~~~~~~~~~~~~^~
[   39s] In file included from thewalrus/../include/libwalrus.hpp:20,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/torontonian.hpp: In instantiation of ‘double libwalrus::torontonian_fsum(std::vector<T>&) [with T = std::complex<double>]’:
[   39s] thewalrus/libwalrus.cpp:3878:100:   required from here
[   39s] include/torontonian.hpp:211:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long long unsigned int’ [-Wsign-compare]
[   39s]   211 |     for (int k = 0; k < x; k++) {
[   39s]       |                     ~~^~~
[   39s] include/torontonian.hpp: In instantiation of ‘double libwalrus::torontonian_fsum(std::vector<T>&) [with T = double]’:
[   39s] thewalrus/libwalrus.cpp:4107:84:   required from here
[   39s] include/torontonian.hpp:211:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long long unsigned int’ [-Wsign-compare]
[   39s] In file included from thewalrus/../include/libwalrus.hpp:22,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/hermite_multidimensional.hpp: In instantiation of ‘T* libwalrus::hermite_multidimensional_cpp(const std::vector<T>&, const std::vector<T>&, const int&) [with T = std::complex<double>]’:
[   39s] thewalrus/libwalrus.cpp:6334:127:   required from here
[   39s] include/hermite_multidimensional.hpp:105:11: warning: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘struct std::complex<double>’; use assignment or value-initialization instead [-Wclass-memaccess]
[   39s]   105 |     memset(&H[0],0,sizeof(T)*Hdim);
[   39s]       |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
[   39s] In file included from include/stdafx.h:19,
[   39s]                  from include/eigenvalue_hafnian.hpp:21,
[   39s]                  from thewalrus/../include/libwalrus.hpp:16,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] /usr/include/c++/10/complex:1227:12: note: ‘struct std::complex<double>’ declared here
[   39s]  1227 |     struct complex<double>
[   39s]       |            ^~~~~~~~~~~~~~~
[   39s] In file included from thewalrus/../include/libwalrus.hpp:22,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/hermite_multidimensional.hpp: In instantiation of ‘T* libwalrus::renorm_hermite_multidimensional_cpp(const std::vector<T>&, const std::vector<T>&, const int&) [with T = std::complex<double>]’:
[   39s] thewalrus/libwalrus.cpp:6816:134:   required from here
[   39s] include/hermite_multidimensional.hpp:162:11: warning: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘struct std::complex<double>’; use assignment or value-initialization instead [-Wclass-memaccess]
[   39s]   162 |     memset(&H[0],0,sizeof(T)*Hdim);
[   39s]       |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
[   39s] In file included from include/stdafx.h:19,
[   39s]                  from include/eigenvalue_hafnian.hpp:21,
[   39s]                  from thewalrus/../include/libwalrus.hpp:16,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] /usr/include/c++/10/complex:1227:12: note: ‘struct std::complex<double>’ declared here
[   39s]  1227 |     struct complex<double>
[   39s]       |            ^~~~~~~~~~~~~~~
[   39s] In file included from thewalrus/../include/libwalrus.hpp:22,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] include/hermite_multidimensional.hpp: In instantiation of ‘T* libwalrus::interferometer_cpp(const std::vector<T>&, const int&) [with T = std::complex<double>]’:
[   39s] thewalrus/libwalrus.cpp:7263:102:   required from here
[   39s] include/hermite_multidimensional.hpp:214:11: warning: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘struct std::complex<double>’; use assignment or value-initialization instead [-Wclass-memaccess]
[   39s]   214 |     memset(&H[0],0,sizeof(T)*Hdim);
[   39s]       |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
[   39s] In file included from include/stdafx.h:19,
[   39s]                  from include/eigenvalue_hafnian.hpp:21,
[   39s]                  from thewalrus/../include/libwalrus.hpp:16,
[   39s]                  from thewalrus/libwalrus.cpp:691:
[   39s] /usr/include/c++/10/complex:1227:12: note: ‘struct std::complex<double>’ declared here
[   39s]  1227 |     struct complex<double>
[   39s]       |            ^~~~~~~~~~~~~~~
[   39s] /usr/lib64/python3.8/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /home/abuild/rpmbuild/BUILD/thewalrus-0.13.0/thewalrus/libwalrus.pyx
[   39s]   tree = Parsing.p_module(s, pxd, full_module_name)
[   39s] error: Command "g++ -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -g -DOPENSSL_LOAD_CONF -fwrapv -fno-semantic-interposition -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -g -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -g -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -fPIC -Ithewalrus -I -I/usr/lib64/python3.8/site-packages/numpy/core/include -I/usr/local/include/eigen3 -I/usr/include/eigen3 -Iinclude -I/usr/lib64/python3.8/site-packages/numpy/core/include -I/usr/include/python3.8 -c thewalrus/libwalrus.cpp -o build/temp.linux-x86_64-3.8/thewalrus/libwalrus.o -MMD -MF build/temp.linux-x86_64-3.8/thewalrus/libwalrus.o.d -std=c++11 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -I/usr/lib64/python3.8/site-packages/numpy/core/include" failed with exit status 1
[   39s] error: Bad exit status from /var/tmp/rpm-tmp.72eZNY (%build)
[   39s] 
[   39s] 
[   39s] RPM build errors:
[   39s]     Bad exit status from /var/tmp/rpm-tmp.72eZNY (%build)
[   39s] 
[   39s] stitny failed "build python-thewalrus.spec" at Mon Sep 21 15:04:13 UTC 2020.
[   39s] 
  • Reproduces how often: always

  • System information:
    export 'CFLAGS=-O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto'

Additional information

Complete build log

`make test-cpp` hard codes the eigen include dir to `/usr/include/eigen3`

As a result of tests/Makefile hardcoding the eigen3 include directory to /usr/include/eigen3, if a user follows the instructions given at https://the-walrus.readthedocs.io/en/latest/installing.html#installation.

and runs make test-cpp, they will see an error of the form:

make -C tests clean
make[1]: Entering directory '/home/poulson/Source/thewalrus/tests'
rm -rf *~ cpptests *.out *.o *.so *.pyc *.mod
make[1]: Leaving directory '/home/poulson/Source/thewalrus/tests'
echo "Going to compile C++ tests"
Going to compile C++ tests
make -C tests cpptests
make[1]: Entering directory '/home/poulson/Source/thewalrus/tests'
g++ gtest_main.cpp -std=c++11 -O3 -g -Wall -fopenmp -fPIC -I/usr/include -I../include -I/usr/include/eigen3 -I/include -march=native -c
g++ libwalrus_unittest.cpp -std=c++11 -O3 -g -Wall -fopenmp -fPIC -I/usr/include -I../include -I/usr/include/eigen3 -I/include -march=native -c
In file included from ../include/libwalrus.hpp:16,
                 from libwalrus_unittest.cpp:18:
../include/eigenvalue_hafnian.hpp:33:10: fatal error: Eigen/Eigenvalues: No such file or directory
 #include <Eigen/Eigenvalues>
          ^~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [Makefile:28: libwalrus_unittest.o] Error 1
make[1]: Leaving directory '/home/poulson/Source/thewalrus/tests'
make: *** [Makefile:55: test-cpp] Error 2

The preferred approach would seem to be to use the EIGEN_INCLUDE_DIR environment variable if it exists, and to fall back to /usr/include/eigen3 otherwise.

Add a seed global method to make sampling stochastic

It would be useful to provide a seed global method, in order to force the sampling methods to become deterministic. Something like

import hafnian as haf
haf.samples.seed(42)
hafnian_sample_graph(A, n_mean, samples=10, cutoff=5)

This might simply be a wrapper around np.random.seed(), or it might be something more complicated.

Multidimensional Hermite polynomials improvements

  • It would be good to parallelize the calculation of Hermite polynomials which is right now done serially.

  • In line

    it is assumed that the first value of the Hermite polynomials is 1. It would be convenient to be able to set different values for this initial value in the recurrence relation defining the polynomials.

  • It would also be useful to introduce generalized multidimensional Hermite polynomials :math: \tilde H_{n}^{(B)}(\alpha) = H_{n}^{(B)}(\alpha)/\sqrt{\prod_i n_i}. This would require to construct explicitly the recursion relation of these new polynomials and implementing it. It would have the advantage of reducing overflows or underflows in the calculation of properties of Gaussian states and gates.

  • The polynomials should be defined so that they depend on :alpha: and not in :B alpha:. See this line

    H[nextCoordinate] = H[nextCoordinate] + R(k, ii) * y(ii, 0);

This matrix vector multiplication could be done ahead of time a not at each iteration.

Mark test_hafnian_approx as flaky

Issue description

Currently, the test_hafnian_approx.py tests sometimes randomly fail.

This is specific to the test_rank_one function which calls haf_real with approx=True, which in turn calls the C++ function hafnian_nonneg in libwalrus. hafnian_nonneg uses the std::default_random_engine generator (with no seed) causing the output to be random.

Fix
Mark the specific test as flaky (e.g. with https://github.com/box/flaky).

This could also be solved by passing a random seed value to hafnian_nonneq in libwalrus, although this means changing quite a few functions along the way (and might not be worth it).

[Thewalrus installation] Can not install the version later than 0.15.0


Issue description

Description of the issue -

Try to install the library with the developer mode. However, it gives me lots of errors related to the compiler.

  • Expected behavior: Installation.

  • Actual behavior: Erros.

Additional information

I tried to replace the setup.py with the old version setup.py and it works.

Then I tracked to the PR "Refactor setup.py". Maybe there is something wrong with macOS Big Sur 11.4?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.