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/v5.0.1/lib/python3.12/site-packages/numpy/__init__.py'>
fallback_np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/v5.0.1/lib/python3.12/site-packages/numpy/__init__.py'>
forward_pass_np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/v5.0.1/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.

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/

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.

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, columns)

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

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.

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.

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.