Calculators#

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

class NumpyCalculator#

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

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

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().

class TensorflowCalculator(decorate_with=None)#

Calculator enabling calculating the gradients of certain instructions.

This calculator is similar to NumpyCalculator, 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_calculator = pq.TensorflowCalculator()

simulator = pq.PureFockSimulator(d=1, calculator=tensorflow_calculator)

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.

Note

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

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().

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.

class JaxCalculator#

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_calculator = pq.JaxCalculator()

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

    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”.