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/latest/lib/python3.12/site-packages/numpy/__init__.py'>¶
- fallback_np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/latest/lib/python3.12/site-packages/numpy/__init__.py'>¶
- forward_pass_np: Any = <module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/piquasso/envs/latest/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:
- 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:
matrix (numpy.ndarray) – The input matrix.
reduce_on (numpy.ndarray) – The reduction array.
- Returns:
The hafnian of the matrix.
- Return type:
- 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:
matrix (numpy.ndarray) – The input matrix.
diagonal (numpy.ndarray) – The vector which will fill the diagonal.
reduce_on (numpy.ndarray) – The reduction array.
- Returns:
The hafnian of the matrix.
- Return type:
- 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
ParticleNumberMeasurementare 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:
- 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:
- 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:
matrix (numpy.ndarray) – The input matrix.
reduce_on (numpy.ndarray) – The reduction array.
- Returns:
The hafnian of the matrix.
- Return type:
- 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:
matrix (numpy.ndarray) – The input matrix.
diagonal (numpy.ndarray) – The vector which will fill the diagonal.
reduce_on (numpy.ndarray) – The reduction array.
- Returns:
The hafnian of the matrix.
- Return type:
- 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:
- 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(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:
- 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:
matrix (numpy.ndarray) – The input matrix.
reduce_on (numpy.ndarray) – The reduction array.
- Returns:
The hafnian of the matrix.
- Return type:
- 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:
matrix (numpy.ndarray) – The input matrix.
diagonal (numpy.ndarray) – The vector which will fill the diagonal.
reduce_on (numpy.ndarray) – The reduction array.
- Returns:
The hafnian of the matrix.
- Return type:
- 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.