Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding batchhafnian code #21

Merged
merged 43 commits into from
Jul 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
11e3cd5
Adding batchhafnian serial code to the repo along with corresponidng …
bgupt Jun 28, 2019
aa7ae01
Adding batchhafnian files along with googletests and python tests.
bgupt Jun 28, 2019
f3dcdae
Adding python test for batchhafnian.
bgupt Jun 28, 2019
24420a7
Adding permanent file.
bgupt Jun 28, 2019
96971a6
Increasing the tolerance for hafnian_approx test.
bgupt Jun 28, 2019
bd67897
Merge branch 'master' into batchhafnian
josh146 Jul 1, 2019
5918566
Apply suggestions from code review
josh146 Jul 1, 2019
a758609
fix unittest
josh146 Jul 1, 2019
c013920
Changing input matrices in batchhafnians to R and y. Modify the googl…
bgupt Jul 8, 2019
89abd16
Adding renormalization to batchhafnian functions. Current tests only …
bgupt Jul 9, 2019
63059ce
Fixed the renormalization in batch hafnian as per Nico's suggestions.…
bgupt Jul 10, 2019
4c471ea
Minor changes in hafnian.hpp
nquesada Jul 10, 2019
986080d
Adding renormalization to batchhafnian along with googletest and Pyth…
bgupt Jul 12, 2019
82d216a
Merge branch 'batchhafnian' of https://github.com/xanaduai/hafnian in…
nquesada Jul 12, 2019
ba966b6
Renaming functions to streamline python library.
bgupt Jul 12, 2019
8de965b
Removes white space
nquesada Jul 12, 2019
515c4d5
Fixed merge
nquesada Jul 12, 2019
364ba0c
Adding _hermite_multidimensional.py
bgupt Jul 12, 2019
72b4e41
Merge branch 'batchhafnian' of https://github.com/xanaduai/hafnian in…
nquesada Jul 12, 2019
020aaeb
Renamed src/batchhafnian.hpp -> src/hermite_multidimensional.hpp
bgupt Jul 12, 2019
7bedc7b
Changes to hafnian.cpp
nquesada Jul 12, 2019
5392b78
Merge branch 'batchhafnian' of https://github.com/xanaduai/hafnian in…
nquesada Jul 12, 2019
3dcdb70
Added new functions hafnian_batched and multiple tests
nquesada Jul 12, 2019
b89adb2
Added assert statements in python tests, reformatting and minor chang…
bgupt Jul 15, 2019
86006cd
The test_coherent_squeezed is still not passing
nquesada Jul 15, 2019
f3a1f5f
Test pass now linting cleaning
nquesada Jul 15, 2019
76f8884
Linted and blacked. Also the test go through all the new code except …
nquesada Jul 15, 2019
355fe38
Removed lingering printing commands
nquesada Jul 15, 2019
4d2d9d7
Update hafnian/_hermite_multidimensional.py
nquesada Jul 16, 2019
865af95
Update hafnian/_hermite_multidimensional.py
nquesada Jul 16, 2019
a2395e4
Update hafnian/_hermite_multidimensional.py
nquesada Jul 16, 2019
3447dd7
Applied code review for docstrings adding returns before args and ret…
nquesada Jul 16, 2019
6073a88
Added suggestions from codefactor
nquesada Jul 16, 2019
0e11876
Added suggestions from codefactor
nquesada Jul 16, 2019
8f9ca82
removes superflous import
nquesada Jul 16, 2019
cfd9a39
Adding -fopenmp to makefile for googletest
bgupt Jul 17, 2019
c50ed27
Removing -lomp from googletest Makefile.
bgupt Jul 17, 2019
98af9e7
Merge branch 'master' into batchhafnian
nquesada Jul 17, 2019
206b7af
increasing rtol to 0.2 in sample_test_hafnian.
bgupt Jul 17, 2019
d7ae9f1
Changing the random seed.
bgupt Jul 17, 2019
3238b65
Merge branch 'batchhafnian' of https://github.com/XanaduAI/hafnian in…
bgupt Jul 17, 2019
0b20f9f
incresing tolerance on tests.
bgupt Jul 17, 2019
ee2ca7b
Changes test probability vacuum
nquesada Jul 17, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions hafnian/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,21 @@
.. autosummary::
hafnian
hafnian_repeated
hafnian_batched
hermite_multidimensional
tor
perm
permanent_repeated
reduction
version

"""
# pylint: disable=wrong-import-position
import os
import platform

import numpy as np


if platform.system() == "Windows": # pragma: no cover
extra_dll_dir = os.path.join(os.path.dirname(__file__), ".libs")
if os.path.isdir(extra_dll_dir):
os.environ["PATH"] += os.pathsep + extra_dll_dir


from ._hafnian import (
haf_complex,
haf_int,
Expand All @@ -83,10 +79,16 @@
hafnian_repeated,
reduction,
)
from ._hermite_multidimensional import hafnian_batched, hermite_multidimensional
from ._permanent import perm, perm_complex, perm_real, permanent_repeated
from ._torontonian import tor
from ._version import __version__

if platform.system() == "Windows": # pragma: no cover
extra_dll_dir = os.path.join(os.path.dirname(__file__), ".libs")
if os.path.isdir(extra_dll_dir):
os.environ["PATH"] += os.pathsep + extra_dll_dir

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isort probably moved this down, but this will have to be moved back to before the line

from ._hafnian import (

to make sure it imports correctly on windows :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bgupt can you look into this?


__all__ = [
"hafnian",
Expand All @@ -95,6 +97,8 @@
"perm",
"permanent_repeated",
"reduction",
"hafnian_batched",
"hermite_multidimensional",
"version",
]

Expand Down
5 changes: 4 additions & 1 deletion hafnian/_hafnian.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ def hafnian(


def hafnian_repeated(A, rpt, mu=None, loop=False, tol=1e-12):
r"""Returns the hafnian of matrix with repeated rows/columns.
r"""
THIS NEEDS TO BE WRITTEN

Returns the hafnian of matrix with repeated rows/columns.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a copy/paste mistake 🙂 Probably should undo this change.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is. Thanks for catching it up!


The :func:`reduction` function may be used to show the resulting matrix
with repeated rows and columns as per ``rpt``.
Expand Down
145 changes: 145 additions & 0 deletions hafnian/_hermite_multidimensional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Copyright 2019 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Hermite Multidimensional Python interface
"""
from itertools import product
import numpy as np

from .lib.libhaf import hermite_multidimensional as hm
from ._hafnian import input_validation


def return_prod(C, index):
r"""Given an array :math:`C_{i,j}` and an array or list of indices :math:`index = [i_1,i_2,i_3,\dots,i_n] `, returns :math:`prod_{k=1}^n C_{1,i_1}`.

bgupt marked this conversation as resolved.
Show resolved Hide resolved
Args:
C (array): An array
index (array): A set of indices

Returns:
complex: The product of the array elements determines by index
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
complex: The product of the array elements determines by index
complex: The product of the array elements determined by index

"""
bgupt marked this conversation as resolved.
Show resolved Hide resolved
return np.prod([C[mode, val] for mode, val in enumerate(index)])


def expansion_coeff(alpha, resolution, renorm=True):
r"""Returns the (quasi) geometric series as a vector with components :math:`alpha^i/sqrt(i!)` for :math:`0 \leq i < resolution`.

If renorm is false it omits the division by factorials
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can probably delete this line since it's already discussed in the args: list.

Suggested change
If renorm is false it omits the division by factorials


Args:
alpha (complex): Ratio of the geometric series
resoluton (int): Cutoff of the geometric series
renorm (bool): Decides whether to normalize by the factorials

Returns:
array: The power series
"""
vals = np.empty([resolution], dtype=type(alpha))
vals[0] = 1.0
if renorm:
for i in range(1, resolution):
vals[i] = vals[i - 1] * alpha / np.sqrt(i)
else:
for i in range(1, resolution):
vals[i] = vals[i - 1] * alpha
return vals


def hermite_multidimensional(R, resolution, y=None, renorm=False, make_tensor=True):
r"""Returns the multidimensional Hermite polynomials :math:`H_k^{(R)}(y)`.

Here :math:`R` is an :math:n \times n: square matrix,
:math:`y` is an :math:`n` dimensional vector. The polynomials are parametrized by the multi-index :math:`k=(k_0,k_1,\ldots,k_{n-1})
and are calculated for all values :math:`0 \leq k_j < \text{resolution}`, thus a tensor of dimensions :math:`\text{resolution}^n` is returned.
This tensor can either be flattened into a vector or returned as an actual tensor with :math:`n` indices.
Note that is R = np.array([[1.0+0.0j]]) then :math:`H_k^{(R)}(y)` are precisely the well known **probabilists' Hermite polynomials** :math:`He_k(y)`:,
and if R = 2*np.array([[1.0+0.0j]]) then :math:`H_k^{(R)}(y)` are precisely the well known **physicists' Hermite polynomials** :math:`H_k(y)`:.

Args:
R (array): Square matrix parametrizing the Hermite polynomial family
resolution (int): Maximum size of the subindices in the Hermite polynomial
y (array): Vector for the argument of the Hermite polynomial
renorm (bool): If True returns :math:`H_k^{(R)}(y)/\prod(\prod_i k_i!)`
make_tensor: If False returns a flattened one dimensional array instead of a tensor with the values of the polynomial

Returns:
(array): The multidimensional Hermite polynomials.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that you'll need blank lines in three places in order for this to render properly in the docs.

  1. After the first line of the docstring. So after "Returns the multidimensional Hermite polynomials :math:H_k^{(R)}(y).", there should be an empty line.

  2. Before "Args:"

  3. Before "Returns"

"""
input_validation(R)
n, _ = R.shape
if y is None:
y = np.zeros([n], dtype=complex)

m = y.shape[0]
if m != n:
raise ValueError("The matrix R and vector y have incompatible dimensions")

values = np.array(hm(R, y, resolution, ren=renorm))

if make_tensor:
shape = resolution * np.ones([n], dtype=int)
values = np.reshape(values, shape)

return values
bgupt marked this conversation as resolved.
Show resolved Hide resolved


def hafnian_batched(A, resolution, mu=None, tol=1e-12, renorm=False, make_tensor=True):
r"""Returns the haf(reduction(A, k)) where k is a vector of (non-negative) integers with the same dimensions as the square matrix A
:math:`k = (k_0,k_1,\ldots,k_{n-1})` and where :math:`0 \leq k_j < \text{resolution}`.

If mu is not None the it instead calculates :math:`lhaf(fill_diagonal(reduction(A, k),reduction(mu, k)))`, this calculation can only be performed if
the matrix A has an inverse.

Args:
R (array): Square matrix parametrizing
resolution (int): Maximum size of the subindices in the Hermite polynomial
y (array): Vector for the argument of the Hermite polynomial
renorm (bool): If True returns :math:`haf(reduction(A, k))/\prod(\prod_i k_i!)` or :math:`lhaf(fill_diagonal(reduction(A, k),reduction(mu, k)))` is mu is not None
make_tensor: If False returns a flattened one dimensional array instead of a tensor with the values of the polynomial

Returns:
(array): The values of the hafnians.
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above re: line breaks. You can build the docs locally (make doc) to ensure the docstrings render correctly :)

# pylint: disable=too-many-return-statements,too-many-branches,too-many-arguments
input_validation(A, tol=tol)
n, _ = A.shape
if not np.allclose(A, np.zeros([n, n])):
if mu is not None:
try:
yi = np.linalg.solve(A, mu)
except np.linalg.LinAlgError:
raise ValueError("The matrix does not have an inverse")
return hermite_multidimensional(
-A, resolution, y=-yi, renorm=renorm, make_tensor=make_tensor
)
yi = np.zeros([n], dtype=complex)
return hermite_multidimensional(
-A, resolution, y=-yi, renorm=renorm, make_tensor=make_tensor
)
# Note the minus signs in the arguments. Those are intentional

if mu is None:
tensor = np.zeros([resolution ** n], dtype=complex)
tensor[0] = 1.0
else:
index = resolution * np.ones([n], dtype=int)
tensor = np.empty(index, dtype=complex)
prim = np.array([expansion_coeff(alpha, resolution, renorm=renorm) for alpha in mu])
for i in product(range(resolution), repeat=n):
tensor[i] = return_prod(prim, i)
if make_tensor:
return tensor
return tensor.flatten()
Loading