Connectors

Alongside NumPy, Piquasso also supports TensorFlow and JAX as simulators for calculations.

NumPy connector

class NumpyConnector

The calculations for a simulation using NumPy (and SciPy).

This is enabled by default in the built-in simulators.

np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/stable/lib/python3.12/site-packages/numpy/__init__.py'>
fallback_np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/stable/lib/python3.12/site-packages/numpy/__init__.py'>
forward_pass_np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/stable/lib/python3.12/site-packages/numpy/__init__.py'>
block_diag(*args, **kwargs)

Putting together matrices as a block diagonal matrix.

Equivalent to scipy.linalg.block_diag().

block(*args, **kwargs)

Assembling submatrices into a single matrix.

Equivalent to numpy.block().

logm(*args, **kwargs)

Matrix logarithm.

Equivalent to scipy.linalg.logm().

Parameters:

matrix (numpy.ndarray) – The input matrix.

expm(*args, **kwargs)

Matrix exponential.

Equivalent to scipy.linalg.expm().

Parameters:

matrix (numpy.ndarray) – The input matrix.

powm(*args, **kwargs)

Matrix power.

Equivalent to numpy.linalg.matrix_power().

Parameters:

matrix (numpy.ndarray) – The input matrix.

polar(*args, **kwargs)

Polar decomposition.

Equivalent to scipy.linalg.polar().

Parameters:
  • matrix (numpy.ndarray) – The input matrix

  • side (str, optional) – The order of the decomposition. Defaults to “right”.

permanent(*args, **kwargs)

Calculates the permanent of a matrix with row and column repetitions.

permanent_laplace(*args, **kwargs)

Calculates the permanent of a matrix corresponding to the Laplace expansion.

Here, the sum of rows is equal to the sum of cols plus one, and all the permanents corresponding to the row multiplicities given by rows and column multiplicities given by cols minus one from each column are calculated.

Parameters:
  • matrix (numpy.ndarray) – The input matrix.

  • rows (Tuple[int, ...]) – Multiplicity vector specifying how many times each row is repeated (i.e., the row multiplicities).

  • cols (Tuple[int, ...]) – Multiplicity vector specifying how many times each column is repeated (i.e., the column multiplicities).

Returns:

The permanents of the submatrices corresponding to the

Laplace expansion.

Return type:

numpy.ndarray

hafnian(*args, **kwargs)

Calculates the hafnian of a matrix with prescribed reduction array.

This function first performs a reduction by a reduction array \(S\), and then calculates the hafnian. Succintly, this function should implement \(A \mapsto \operatorname{haf}(A_{(S)})\).

Parameters:
Returns:

The hafnian of the matrix.

Return type:

float

loop_hafnian(*args, **kwargs)

Calculates the hafnian of a matrix with prescribed reduction array.

This function first fills the diagonals with \(D\), then performs a reduction by a reduction array \(S\) and then calculates the hafnian. Succintly, this function should implement \(A \mapsto \operatorname{lhaf}(\operatorname{filldiag}(A, D)_{(S)})\).

Parameters:
Returns:

The hafnian of the matrix.

Return type:

float

loop_hafnian_batch(*args, **kwargs)

Batch loop hafnian calculation.

Same as loop_hafnian(), but with batching, according to https://arxiv.org/abs/2108.01622.

calculate_interferometer_on_fock_space(*args, **kwargs)

This implementation uses Eq. (71) from https://quantum-journal.org/papers/q-2020-11-30-366/pdf/

calculate_interferometer_on_fermionic_fock_space(*args, **kwargs)

Calculates the representation of the interferometer matrix on the Fock space.

This algorithm calculates the determinants of the submatrices recursively using Laplace’s expansion. For this, it is easiest to work in the first quantized picture.

preprocess_input_for_custom_gradient(value)

Applies modifications to inputs in custom gradients.

assign(array, index, value)

Item assignment.

scatter(indices, updates, shape)

Filling an array of a given shape with the given indices and update values.

Equivalent to tf.scatter_nd().

TensorFlow connector

class TensorflowConnector(decorate_with=None)

Connector enabling calculating the gradients of certain instructions.

This connector is similar to NumpyConnector, but it enables the simulator to use Tensorflow to be able to compute gradients.

Example usage:

import piquasso as pq
import tensorflow as tf

r = tf.Variable(0.43)

tensorflow_connector = pq.TensorflowConnector()

simulator = pq.PureFockSimulator(d=1, connector=tensorflow_connector)

with pq.Program() as program:
    pq.Q() | pq.Vacuum()

    pq.Q(0) | pq.Displacement(r=r)

with tf.GradientTape() as tape:
    state = simulator.execute(program).state

    mean = state.mean_photon_number()

gradient = tape.gradient(mean, [r])

Note

Non-deterministic operations like ParticleNumberMeasurement are non-differentiable, please use a deterministic attribute of the resulting state instead.

Parameters:

decorate_with (function, optional) – A function to decorate calculations with. Currently, only tf.function is supported. Specifying this may reduce runtime after the tracing step. See Better performance with tf.function.

Raises:

ImportError – When TensorFlow is not available.

is_abstract(value: Any) bool

Determines whether the given value is abstract (a tensor with unknown value) or concrete (has a known value).

Parameters:

value – The value to be checked.

Returns:

True if the value is abstract, False if it is concrete

Return type:

bool

property custom_gradient

Custom gradient wrapper.

Parameters:

func – The function for which custom gradient is defined.

preprocess_input_for_custom_gradient(value)

Applies modifications to inputs in custom gradients.

block_diag(*arrs)

Putting together matrices as a block diagonal matrix.

Equivalent to scipy.linalg.block_diag().

assign(array, index, value)

Item assignment.

block(arrays)

Assembling submatrices into a single matrix.

Equivalent to numpy.block().

scatter(indices, updates, shape)

Filling an array of a given shape with the given indices and update values.

Equivalent to tf.scatter_nd().

embed_in_identity(matrix, indices, dim)

Embeds a matrix in identity.

logm(matrix)

Matrix logarithm.

Equivalent to scipy.linalg.logm().

Parameters:

matrix (numpy.ndarray) – The input matrix.

expm(matrix)

Matrix exponential.

Equivalent to scipy.linalg.expm().

Parameters:

matrix (numpy.ndarray) – The input matrix.

powm(matrix, power)

Matrix power.

Equivalent to numpy.linalg.matrix_power().

Parameters:

matrix (numpy.ndarray) – The input matrix.

polar(matrix, side='right')

Polar decomposition.

Equivalent to scipy.linalg.polar().

Parameters:
  • matrix (numpy.ndarray) – The input matrix

  • side (str, optional) – The order of the decomposition. Defaults to “right”.

gather_along_axis_1(array, indices)

Gathering values along axis 1 of a matrix.

Note

Gather along axis 1 was terribly slow in Tensorflow, see https://github.com/tensorflow/ranking/issues/160.

transpose(matrix)

Matrix transposition.

Parameters:

matrix (numpy.ndarray) – The input matrix.

accumulator(dtype, size, **kwargs)

Datatype to collect NumPy arrays.

Common generalization of a Python list and tf.TensorArray.

write_to_accumulator(accumulator, index, value)

Append an element to the accumulator.

Common generalization of a Python list appending and tf.TensorArray.write.

stack_accumulator(accumulator)

Stack elements in the accumulator.

Common generalization of numpy.stack() and tf.TensorArray.stack.

permanent(matrix, rows, cols)

Calculates the permanent of a matrix with row and column repetitions.

permanent_laplace(matrix, rows, cols)

Calculates the permanent of a matrix corresponding to the Laplace expansion.

Here, the sum of rows is equal to the sum of cols plus one, and all the permanents corresponding to the row multiplicities given by rows and column multiplicities given by cols minus one from each column are calculated.

Parameters:
  • matrix (numpy.ndarray) – The input matrix.

  • rows (Tuple[int, ...]) – Multiplicity vector specifying how many times each row is repeated (i.e., the row multiplicities).

  • cols (Tuple[int, ...]) – Multiplicity vector specifying how many times each column is repeated (i.e., the column multiplicities).

Returns:

The permanents of the submatrices corresponding to the

Laplace expansion.

Return type:

numpy.ndarray

hafnian(matrix, reduce_on)

Calculates the hafnian of a matrix with prescribed reduction array.

This function first performs a reduction by a reduction array \(S\), and then calculates the hafnian. Succintly, this function should implement \(A \mapsto \operatorname{haf}(A_{(S)})\).

Parameters:
Returns:

The hafnian of the matrix.

Return type:

float

loop_hafnian(matrix, diagonal, reduce_on)

Calculates the hafnian of a matrix with prescribed reduction array.

This function first fills the diagonals with \(D\), then performs a reduction by a reduction array \(S\) and then calculates the hafnian. Succintly, this function should implement \(A \mapsto \operatorname{lhaf}(\operatorname{filldiag}(A, D)_{(S)})\).

Parameters:
Returns:

The hafnian of the matrix.

Return type:

float

loop_hafnian_batch(matrix, diagonal, reduce_on, cutoff)

Batch loop hafnian calculation.

Same as loop_hafnian(), but with batching, according to https://arxiv.org/abs/2108.01622.

JAX connector

class JaxConnector

The calculations for a simulation using JAX.

Example usage:

import numpy as np
import piquasso as pq
from jax import jit, grad

def example_func(r, theta):
    jax_connector = pq.JaxConnector()

    simulator = pq.PureFockSimulator(
        d=2,
        config=pq.Config(cutoff=5, dtype=np.float32, normalize=False),
        connector=jax_connector,
    )

    with pq.Program() as program:
        pq.Q() | pq.Vacuum()

        pq.Q(0) | pq.Displacement(r=r)

        pq.Q(0, 1) | pq.Beamsplitter(theta)

    state = simulator.execute(program).state

    return state.fock_probabilities[0]

compiled_func = jit(example_func)

vacuum_probability = compiled_func(0.1, np.pi / 7)

compiled_grad_func = jit(grad(compiled_func))

vacuum_probability_grad = compiled_grad_func(0.2, np.pi / 11)

Note

This feature is still experimental.

Note

Currently JIT compilation only works with the config variable normalize=False.

Note

Only CPU calculations are supported currently.

is_abstract(value: Any) bool

Determines whether the given value is abstract (a tracer) or concrete (has a known value).

Parameters:

value – The value to be checked.

Returns:

True if the value is abstract, False if it is concrete

Return type:

bool

preprocess_input_for_custom_gradient(value)

Applies modifications to inputs in custom gradients.

assign(array, index, value)

Item assignment.

scatter(indices, updates, shape)

Filling an array of a given shape with the given indices and update values.

Equivalent to tf.scatter_nd().

polar(a, side)

Polar decomposition.

Equivalent to scipy.linalg.polar().

Parameters:
  • matrix (numpy.ndarray) – The input matrix

  • side (str, optional) – The order of the decomposition. Defaults to “right”.

block_diag(*args, **kwargs)

Putting together matrices as a block diagonal matrix.

Equivalent to scipy.linalg.block_diag().

block(*args, **kwargs)

Assembling submatrices into a single matrix.

Equivalent to numpy.block().

logm(*args, **kwargs)

Matrix logarithm.

Equivalent to scipy.linalg.logm().

Parameters:

matrix (numpy.ndarray) – The input matrix.

expm(*args, **kwargs)

Matrix exponential.

Equivalent to scipy.linalg.expm().

Parameters:

matrix (numpy.ndarray) – The input matrix.

powm(*args, **kwargs)

Matrix power.

Equivalent to numpy.linalg.matrix_power().

Parameters:

matrix (numpy.ndarray) – The input matrix.

permanent(*args, **kwargs)

Calculates the permanent of a matrix with row and column repetitions.

permanent_laplace(matrix, rows, cols)

Calculates the permanent of a matrix corresponding to the Laplace expansion.

Here, the sum of rows is equal to the sum of cols plus one, and all the permanents corresponding to the row multiplicities given by rows and column multiplicities given by cols minus one from each column are calculated.

Parameters:
  • matrix (numpy.ndarray) – The input matrix.

  • rows (Tuple[int, ...]) – Multiplicity vector specifying how many times each row is repeated (i.e., the row multiplicities).

  • cols (Tuple[int, ...]) – Multiplicity vector specifying how many times each column is repeated (i.e., the column multiplicities).

Returns:

The permanents of the submatrices corresponding to the

Laplace expansion.

Return type:

numpy.ndarray

hafnian(matrix, reduce_on)

Calculates the hafnian of a matrix with prescribed reduction array.

This function first performs a reduction by a reduction array \(S\), and then calculates the hafnian. Succintly, this function should implement \(A \mapsto \operatorname{haf}(A_{(S)})\).

Parameters:
Returns:

The hafnian of the matrix.

Return type:

float

loop_hafnian(matrix, diagonal, reduce_on)

Calculates the hafnian of a matrix with prescribed reduction array.

This function first fills the diagonals with \(D\), then performs a reduction by a reduction array \(S\) and then calculates the hafnian. Succintly, this function should implement \(A \mapsto \operatorname{lhaf}(\operatorname{filldiag}(A, D)_{(S)})\).

Parameters:
Returns:

The hafnian of the matrix.

Return type:

float

loop_hafnian_batch(matrix, diagonal, reduce_on, cutoff)

Batch loop hafnian calculation.

Same as loop_hafnian(), but with batching, according to https://arxiv.org/abs/2108.01622.

calculate_interferometer_on_fermionic_fock_space(matrix, cutoff)

Calculates the representation of the interferometer matrix on the Fock space.

This algorithm calculates the determinants of the submatrices recursively using Laplace’s expansion. For this, it is easiest to work in the first quantized picture.

apply_fermionic_passive_linear_to_state_vector(representations, state_vector, modes, d, cutoff)

Applies a passive linear gate to a state vector expressed in the Fock basis.

This function assumes that the n-particle representations of the passive linear gate has already been calculated.