merlin.algorithms.kernels module
- class merlin.algorithms.kernels.AutoDiffProcess(sampling_method='multinomial')
Bases:
objectHandles automatic differentiation backend and sampling noise integration.
- autodiff_backend(needs_gradient, apply_sampling, shots)
Determine sampling configuration based on gradient requirements.
- Return type:
tuple[bool,int]
- class merlin.algorithms.kernels.Callable
Bases:
object
- class merlin.algorithms.kernels.CircuitBuilder(n_modes)
Bases:
objectBuilder for quantum circuits using a declarative API.
- add_angle_encoding(modes=None, name=None, *, scale=1.0, subset_combinations=False, max_order=None)
Convenience method for angle-based input encoding.
- Return type:
- Args:
modes: Optional list of circuit modes to target. Defaults to all modes. name: Prefix used for generated input parameters. Defaults to
"px". scale: Global scaling factor applied before angle mapping. subset_combinations: WhenTrue, generate higher-order featurecombinations (up to
max_order) similar to the legacyFeatureEncoder.- max_order: Optional cap on the size of feature combinations when
subset_combinationsis enabled.Noneuses all orders.
- Returns:
CircuitBuilder:
selffor fluent chaining.
- add_entangling_layer(modes=None, *, trainable=True, model='mzi', name=None, trainable_inner=None, trainable_outer=None)
Add an entangling layer spanning a range of modes.
- Return type:
- Args:
- modes: Optional list describing the span.
Nonetargets all modes; one element targets
modes[0]through the final mode; two elements target the inclusive range[modes[0], modes[1]].
trainable: Whether internal phase shifters should be trainable. model:
"mzi"or"bell"to select the internal interferometer template. name: Optional prefix used for generated parameter names. trainable_inner: Override for the internal (between-beam splitter) phase shifters. trainable_outer: Override for the output phase shifters at the exit of the interferometer.- modes: Optional list describing the span.
- Raises:
ValueError: If the provided modes are invalid or span fewer than two modes.
- Returns:
CircuitBuilder:
selffor fluent chaining.
- add_rotations(modes=None, *, axis='z', trainable=False, as_input=False, angle=None, value=None, name=None, role=None)
Add one or multiple rotations across the provided modes.
- Return type:
- Args:
modes: Single mode, list of modes, module group or
None(all modes). axis: Axis of rotation for each inserted phase shifter. trainable: Promote the rotations to trainable parameters (legacy flag). as_input: Mark the rotations as input-driven parameters (legacy flag). angle: Optional fixed value for the rotations (alias ofvalue). value: Optional fixed value for the rotations (alias ofangle). name: Optional stem used for generated parameter names. role: ExplicitParameterRoletaking precedence over other flags.- Returns:
CircuitBuilder:
selffor fluent chaining.
- add_superpositions(targets=None, *, depth=1, theta=0.785398, phi=0.0, trainable=None, trainable_theta=None, trainable_phi=None, modes=None, name=None)
Add one or more superposition (beam splitter) components.
- Return type:
- Args:
- targets: Tuple or list of tuples describing explicit mode pairs. When
omitted, nearest neighbours over
modes(or all modes) are used.
depth: Number of sequential passes to apply (
>=1). theta: Baseline mixing angle for fixed beam splitters. phi: Baseline relative phase for fixed beam splitters. trainable: Convenience flag to mark boththetaandphitrainable. trainable_theta: Whether the mixing angle should be trainable. trainable_phi: Whether the relative phase should be trainable. modes: Optional mode list/module group used whentargetsis omitted. name: Optional stem used for generated parameter names.- Returns:
CircuitBuilder:
selffor fluent chaining.
- property angle_encoding_specs: dict[str, dict[str, Any]]
Return metadata describing configured angle encodings.
- Returns:
Dict[str, Dict[str, Any]]: Mapping from encoding prefix to combination metadata.
- build()
Build and return the circuit.
- Return type:
- Returns:
Circuit: Circuit instance populated with components.
- classmethod from_circuit(circuit)
Create a builder from an existing circuit.
- Return type:
- Args:
circuit: Circuit object whose components should seed the builder.
- Returns:
CircuitBuilder: A new builder instance wrapping the provided circuit.
- property input_parameter_prefixes: list[str]
Expose the order-preserving set of input prefixes.
- Returns:
List[str]: Input parameter stems emitted during encoding.
- to_pcvl_circuit(pcvl_module=None)
Convert the constructed circuit into a Perceval circuit.
- Args:
pcvl_module: Optional Perceval module. If
None, attempts to importperceval.- Returns:
A
pcvl.Circuitinstance mirroring the components tracked by this builder.- Raises:
ImportError: If
percevalis not installed and no module is provided.
- property trainable_parameter_prefixes: list[str]
Expose the unique set of trainable prefixes in insertion order.
- Returns:
List[str]: Trainable parameter stems discovered so far.
- class merlin.algorithms.kernels.CircuitConverter(circuit, input_specs=None, dtype=torch.complex64, device=device(type='cpu'))
Bases:
objectConvert a parameterized Perceval circuit into a differentiable PyTorch unitary matrix.
This class converts Perceval quantum circuits into PyTorch tensors that can be used in neural network training with automatic differentiation. It supports batch processing for efficient training and handles various quantum components like beam splitters, phase shifters, and unitary operations.
- Supported Components:
PS (Phase Shifter)
BS (Beam Splitter)
PERM (Permutation)
Unitary (Generic unitary matrix)
Barrier (no-op, removed during compilation)
- Attributes:
circuit: The Perceval circuit to convert param_mapping: Maps parameter names to tensor indices device: PyTorch device for tensor operations tensor_cdtype: Complex tensor dtype tensor_fdtype: Float tensor dtype
- Example:
Basic usage with a single phase shifter:
>>> import torch >>> import perceval as pcvl >>> from merlin.pcvl_pytorch.locirc_to_tensor import CircuitConverter >>> >>> # Create a simple circuit with one phase shifter >>> circuit = pcvl.Circuit(1) // pcvl.PS(pcvl.P("phi")) >>> >>> # Convert to PyTorch with gradient tracking >>> converter = CircuitConverter(circuit, input_specs=["phi"]) >>> phi_params = torch.tensor([0.5], requires_grad=True) >>> unitary = converter.to_tensor(phi_params) >>> print(unitary.shape) # torch.Size([1, 1])
Multiple parameters with grouping:
>>> # Circuit with multiple phase shifters >>> circuit = (pcvl.Circuit(2) ... // pcvl.PS(pcvl.P("theta1")) ... // (1, pcvl.PS(pcvl.P("theta2")))) >>> >>> converter = CircuitConverter(circuit, input_specs=["theta"]) >>> theta_params = torch.tensor([0.1, 0.2], requires_grad=True) >>> unitary = converter.to_tensor(theta_params) >>> print(unitary.shape) # torch.Size([2, 2])
Batch processing for training:
>>> # Batch of parameter values >>> batch_params = torch.tensor([[0.1], [0.2], [0.3]], requires_grad=True) >>> converter = CircuitConverter(circuit, input_specs=["phi"]) >>> batch_unitary = converter.to_tensor(batch_params) >>> print(batch_unitary.shape) # torch.Size([3, 1, 1])
Training integration:
>>> # Training loop with beam splitter >>> circuit = pcvl.Circuit(2) // pcvl.BS.Rx(pcvl.P("theta")) >>> converter = CircuitConverter(circuit, ["theta"]) >>> theta = torch.tensor([0.5], requires_grad=True) >>> optimizer = torch.optim.Adam([theta], lr=0.01) >>> >>> for step in range(10): ... optimizer.zero_grad() ... unitary = converter.to_tensor(theta) ... loss = some_loss_function(unitary) ... loss.backward() ... optimizer.step()
- set_dtype(dtype)
Set the tensor data types for float and complex operations.
- Args:
dtype: Target dtype (float32/complex64 or float64/complex128)
- Raises:
TypeError: If dtype is not supported
- to(dtype, device)
Move the converter to a specific device and dtype.
- Args:
dtype: Target tensor dtype (float32/complex64 or float64/complex128) device: Target device (string or torch.device)
- Returns:
Self for method chaining
- Raises:
TypeError: If device type or dtype is not supported
- to_tensor(*input_params, batch_size=None)
Convert the parameterized circuit to a PyTorch unitary tensor.
- Return type:
- Args:
*input_params: Variable number of parameter tensors. Each tensor has shape (num_params,) or (batch_size, num_params) corresponding to input_specs order. batch_size: Explicit batch size. If None, inferred from input tensors.
- Returns:
- Complex unitary tensor of shape (circuit.m, circuit.m) for single samples
or (batch_size, circuit.m, circuit.m) for batched inputs.
- Raises:
ValueError: If wrong number of input tensors provided. TypeError: If input_params is not a list or tuple.
- class merlin.algorithms.kernels.DetectorTransform(simulation_keys, detectors, *, dtype=None, device=None, partial_measurement=False)
Bases:
ModuleLinear map applying per-mode detector rules to a Fock probability vector.
- Args:
- simulation_keys: Iterable describing the raw Fock states produced by the
simulator (as tuples or lists of integers).
- detectors: One detector per optical mode. Each detector must expose the
detect()method fromperceval.Detector.- dtype: Optional torch dtype for the transform matrix. Defaults to
torch.float32.
device: Optional device used to stage the transform matrix. partial_measurement: When
True, only the modes whose detector entry isnot
Noneare measured. The transform then operates on complex amplitudes and returns per-outcome dictionaries (seeforward()).
- forward(tensor)
Apply the detector transform.
- Args:
- tensor: Probability distribution (complete mode) or amplitudes
(partial measurement). The last dimension must match the simulator basis.
- Returns:
Complete mode: real probability tensor expressed in the detector basis.
Partial mode: list indexed by remaining photon count. Each entry is a dictionary whose keys are full-length mode tuples (unmeasured modes set to
None) and whose values are lists of (probability, normalized remaining-mode amplitudes) pairs – one per perfect measurement branch.
- property is_identity: bool
Whether the transform reduces to the identity (ideal PNR detectors).
- property output_keys: list[tuple[int, ...]]
Return the classical detection outcome keys.
- property output_size: int
Number of classical outcomes produced by the detectors.
- property partial_measurement: bool
Return True when the transform runs in partial measurement mode.
- remaining_basis(remaining_n=None)
Return the ordered Fock-state basis for the unmeasured modes.
- Return type:
list[tuple[int,...]]
- Args:
- remaining_n: Optional photon count used to select a specific block.
When omitted, the method returns the concatenation of every remaining-mode basis enumerated during detector initialisation.
- Returns:
List of tuples describing the photon distribution over the unmeasured modes.
- class merlin.algorithms.kernels.FeatureMap(circuit=None, input_size=None, *, builder=None, experiment=None, input_parameters, trainable_parameters=None, dtype=torch.float32, device=None, encoder=None)
Bases:
objectQuantum Feature Map
FeatureMap embeds a datapoint within a quantum circuit and computes the associated unitary for quantum kernel methods.
- Args:
circuit: Pre-compiled
pcvl.Circuitto encode features. input_size: Dimension of incoming classical data (required). builder: OptionalCircuitBuilderto compile into a circuit. experiment: Optionalpcvl.Experimentproviding both the circuit and detector configuration.Exactly one of
circuit,builder, orexperimentmust be supplied.input_parameters: Parameter prefix(es) that host the classical data. dtype: Torch dtype used when constructing the unitary. device: Torch device on which unitaries are evaluated.
- compute_unitary(x, *training_parameters)
Generate the circuit unitary after encoding
xand applying trainables.- Return type:
- Args:
x: Single datapoint to embed; accepts scalars, numpy arrays, or tensors. *training_parameters: Optional overriding trainable tensors.
- Returns:
Tensor: Complex unitary matrix representing the prepared circuit.
- is_datapoint(x)
Determine if
xdescribes one sample or a batch.- Return type:
bool
- Args:
x: Candidate input data.
- Returns:
bool:
Truewhenxcorresponds to a single datapoint.
- classmethod simple(input_size, n_modes, n_photons=None, *, dtype=torch.float32, device=None, angle_encoding_scale=1.0, trainable=True, trainable_prefix='phi')
Simple factory method to create a FeatureMap with minimal configuration.
- Return type:
- Args:
input_size: Classical feature dimension. n_modes: Number of photonic modes used by the helper circuit. n_photons: Optional photon count (defaults to
input_size). dtype: Target dtype for internal tensors. device: Optional torch device handle. angle_encoding_scale: Global scaling applied to angle encoding features. trainable: Whether to expose a trainable rotation layer. trainable_prefix: Prefix used for the generated trainable parameter names.- Returns:
FeatureMap: Configured feature-map instance.
- class merlin.algorithms.kernels.FidelityKernel(feature_map, input_state, *, shots=None, sampling_method='multinomial', no_bunching=False, force_psd=True, device=None, dtype=None)
Bases:
ModuleFidelity Quantum Kernel
For a given input Fock state, \(|s \rangle\) and feature map, \(U\), the fidelity quantum kernel estimates the following inner product using SLOS: .. math:
|\langle s | U^{\dagger}(x_2) U(x_1) | s \rangle|^{2}
Transition probabilities are computed in parallel for each pair of datapoints in the input datasets.
- Parameters:
feature_map (
FeatureMap) – Feature map object that encodes a given datapoint within its circuitinput_state (
list[int]) – Input state into circuit.shots (
Optional[int]) – Number of circuit shots. If None, the exact transition probabilities are returned. Default: None.sampling_method (
str) – Probability distributions are post- processed with some pseudo-sampling method: ‘multinomial’, ‘binomial’ or ‘gaussian’.no_bunching (
bool) – Whether or not to post-select out results with bunching. Default: False.force_psd (
bool) – Projects training kernel matrix to closest positive semi-definite. Default: True.device (
Optional[device]) – Device on which to perform SLOSdtype (
UnionType[str,dtype,None]) – Datatype with which to perform SLOS
Examples
For a given training and test datasets, one can construct the training and test kernel matrices in the following structure: .. code-block:: python
>>> circuit = Circuit(2) // PS(P("X0") // BS() // PS(P("X1") // BS() >>> feature_map = FeatureMap(circuit, ["X"]) >>> >>> quantum_kernel = FidelityKernel( >>> feature_map, >>> input_state=[0, 4], >>> no_bunching=False, >>> ) >>> # Construct the training & test kernel matrices >>> K_train = quantum_kernel(X_train) >>> K_test = quantum_kernel(X_test, X_train)
Use with scikit-learn for kernel-based machine learning:. .. code-block:: python
>>> from sklearn import SVC >>> # For a support vector classification problem >>> svc = SVC(kernel='precomputed') >>> svc.fit(K_train, y_train) >>> y_pred = svc.predict(K_test)
- forward(x1, x2=None)
Calculate the quantum kernel for input data x1 and x2. If x1 and x2 are datapoints, a scalar value is returned. For input datasets the kernel matrix is computed.
- classmethod simple(input_size, n_modes, n_photons=None, input_state=None, *, shots=0, sampling_method='multinomial', no_bunching=False, force_psd=True, trainable=True, dtype=torch.float32, device=None, angle_encoding_scale=1.0)
Simple factory method to create a FidelityKernel with minimal configuration.
- Return type:
- class merlin.algorithms.kernels.KernelCircuitBuilder
Bases:
objectBuilder class for creating quantum kernel circuits with photonic backends.
This class provides a fluent interface for building quantum kernel circuits with various configurations, inspired by the core.layer architecture.
- angle_encoding(*, scale=1.0)
Configure the angle encoding scale.
- Return type:
- bandwidth_tuning(enabled=True)
Enable or disable bandwidth tuning.
- Return type:
- build_feature_map()
Build and return a FeatureMap instance.
- Return type:
- Returns:
Configured FeatureMap
- Raises:
ValueError – If required parameters are missing
- build_fidelity_kernel(input_state=None, *, shots=0, sampling_method='multinomial', no_bunching=False, force_psd=True)
Build and return a FidelityKernel instance.
- Parameters:
input_state (
Optional[list[int]]) – Input Fock state. If None, automatically generatedshots (
int) – Number of sampling shotssampling_method (
str) – Sampling method for shotsno_bunching (
bool) – Whether to exclude bunched statesforce_psd (
bool) – Whether to project to positive semi-definite
- Return type:
- Returns:
Configured FidelityKernel
- device(device)
Set the computation device.
- Return type:
- dtype(dtype)
Set the data type for computations.
- Return type:
- input_size(size)
Set the input dimensionality.
- Return type:
- n_modes(modes)
Set the number of modes in the circuit.
- Return type:
- n_photons(photons)
Set the number of photons.
- Return type:
- trainable(enabled=True, *, prefix='phi')
Enable or disable trainable rotations generated by the helper.
- Return type:
- class merlin.algorithms.kernels.PhotonLossTransform(simulation_keys, survival_probs, *, dtype=None, device=None)
Bases:
ModuleLinear map applying per-mode photon loss to a Fock probability vector.
- Args:
- simulation_keys: Iterable describing the raw Fock states produced by the
simulator (as tuples or lists of integers).
survival_probs: One survival probability per optical mode. dtype: Optional torch dtype for the transform matrix. Defaults to
torch.float32.device: Optional device used to stage the transform matrix.
- forward(distribution)
Apply the photon loss transform to a Fock probability vector.
- Return type:
- Args:
distribution: A Fock probability vector as a 1D torch tensor.
- Returns:
A Fock probability vector after photon loss.
- property is_identity: bool
Whether the transform corresponds to perfect transmission.
- property output_keys: list[tuple[int, ...]]
Classical Fock keys after photon loss.
- property output_size: int
Number of classical outcomes after photon loss.
- to(*args, **kwargs)
Move and/or cast the parameters and buffers.
This can be called as
- to(device=None, dtype=None, non_blocking=False)
- to(dtype, non_blocking=False)
- to(tensor, non_blocking=False)
- to(memory_format=torch.channels_last)
Its signature is similar to
torch.Tensor.to(), but only accepts floating point or complexdtypes. In addition, this method will only cast the floating point or complex parameters and buffers todtype(if given). The integral parameters and buffers will be moveddevice, if that is given, but with dtypes unchanged. Whennon_blockingis set, it tries to convert/move asynchronously with respect to the host if possible, e.g., moving CPU Tensors with pinned memory to CUDA devices.See below for examples.
Note
This method modifies the module in-place.
- Args:
- device (
torch.device): the desired device of the parameters and buffers in this module
- dtype (
torch.dtype): the desired floating point or complex dtype of the parameters and buffers in this module
- tensor (torch.Tensor): Tensor whose dtype and device are the desired
dtype and device for all parameters and buffers in this module
- memory_format (
torch.memory_format): the desired memory format for 4D parameters and buffers in this module (keyword only argument)
- device (
- Returns:
Module: self
Examples:
>>> # xdoctest: +IGNORE_WANT("non-deterministic") >>> linear = nn.Linear(2, 2) >>> linear.weight Parameter containing: tensor([[ 0.1913, -0.3420], [-0.5113, -0.2325]]) >>> linear.to(torch.double) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1913, -0.3420], [-0.5113, -0.2325]], dtype=torch.float64) >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_CUDA1) >>> gpu1 = torch.device("cuda:1") >>> linear.to(gpu1, dtype=torch.half, non_blocking=True) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16, device='cuda:1') >>> cpu = torch.device("cpu") >>> linear.to(cpu) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16) >>> linear = nn.Linear(2, 2, bias=None).to(torch.cdouble) >>> linear.weight Parameter containing: tensor([[ 0.3741+0.j, 0.2382+0.j], [ 0.5593+0.j, -0.4443+0.j]], dtype=torch.complex128) >>> linear(torch.ones(3, 2, dtype=torch.cdouble)) tensor([[0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j]], dtype=torch.complex128)
- class merlin.algorithms.kernels.StateGenerator
Bases:
objectUtility class for generating photonic input states.
- static generate_state(n_modes, n_photons, state_pattern)
Generate an input state based on specified pattern.
- enum merlin.algorithms.kernels.StatePattern(value)
Bases:
EnumInput photon state patterns.
Valid values are as follows:
- DEFAULT = <StatePattern.DEFAULT: 'default'>
- SPACED = <StatePattern.SPACED: 'spaced'>
- SEQUENTIAL = <StatePattern.SEQUENTIAL: 'sequential'>
- PERIODIC = <StatePattern.PERIODIC: 'periodic'>
- class merlin.algorithms.kernels.Tensor
Bases:
TensorBase- align_to(*names)
Permutes the dimensions of the
selftensor to match the order specified innames, adding size-one dims for any new names.All of the dims of
selfmust be named in order to use this method. The resulting tensor is a view on the original tensor.All dimension names of
selfmust be present innames.namesmay contain additional names that are not inself.names; the output tensor has a size-one dimension for each of those new names.namesmay contain up to one Ellipsis (...). The Ellipsis is expanded to be equal to all dimension names ofselfthat are not mentioned innames, in the order that they appear inself.Python 2 does not support Ellipsis but one may use a string literal instead (
'...').- Args:
- names (iterable of str): The desired dimension ordering of the
output tensor. May contain up to one Ellipsis that is expanded to all unmentioned dim names of
self.
Examples:
>>> tensor = torch.randn(2, 2, 2, 2, 2, 2) >>> named_tensor = tensor.refine_names('A', 'B', 'C', 'D', 'E', 'F') # Move the F and E dims to the front while keeping the rest in order >>> named_tensor.align_to('F', 'E', ...)
Warning
The named tensor API is experimental and subject to change.
- backward(gradient=None, retain_graph=None, create_graph=False, inputs=None)
Computes the gradient of current tensor wrt graph leaves.
The graph is differentiated using the chain rule. If the tensor is non-scalar (i.e. its data has more than one element) and requires gradient, the function additionally requires specifying a
gradient. It should be a tensor of matching type and shape, that represents the gradient of the differentiated function w.r.t.self.This function accumulates gradients in the leaves - you might need to zero
.gradattributes or set them toNonebefore calling it. See Default gradient layouts for details on the memory layout of accumulated gradients.Note
If you run any forward ops, create
gradient, and/or callbackwardin a user-specified CUDA stream context, see Stream semantics of backward passes.Note
When
inputsare provided and a given input is not a leaf, the current implementation will call its grad_fn (though it is not strictly needed to get this gradients). It is an implementation detail on which the user should not rely. See https://github.com/pytorch/pytorch/pull/60521#issuecomment-867061780 for more details.- Args:
- gradient (Tensor, optional): The gradient of the function
being differentiated w.r.t.
self. This argument can be omitted ifselfis a scalar.- retain_graph (bool, optional): If
False, the graph used to compute the grads will be freed. Note that in nearly all cases setting this option to True is not needed and often can be worked around in a much more efficient way. Defaults to the value of
create_graph.- create_graph (bool, optional): If
True, graph of the derivative will be constructed, allowing to compute higher order derivative products. Defaults to
False.- inputs (sequence of Tensor, optional): Inputs w.r.t. which the gradient will be
accumulated into
.grad. All other tensors will be ignored. If not provided, the gradient is accumulated into all the leaf Tensors that were used to compute thetensors.
- detach()
Returns a new Tensor, detached from the current graph.
The result will never require gradient.
This method also affects forward mode AD gradients and the result will never have forward mode AD gradients.
Note
Returned Tensor shares the same storage with the original one. In-place modifications on either of them will be seen, and may trigger errors in correctness checks.
- detach_()
Detaches the Tensor from the graph that created it, making it a leaf. Views cannot be detached in-place.
This method also affects forward mode AD gradients and the result will never have forward mode AD gradients.
- dim_order(*, ambiguity_check=False)
Returns the uniquely determined tuple of int describing the dim order or physical layout of
self.The dim order represents how dimensions are laid out in memory of dense tensors, starting from the outermost to the innermost dimension.
Note that the dim order may not always be uniquely determined. If ambiguity_check is True, this function raises a RuntimeError when the dim order cannot be uniquely determined; If ambiguity_check is a list of memory formats, this function raises a RuntimeError when tensor can not be interpreted into exactly one of the given memory formats, or it cannot be uniquely determined. If ambiguity_check is False, it will return one of legal dim order(s) without checking its uniqueness. Otherwise, it will raise TypeError.
- Args:
ambiguity_check (bool or List[torch.memory_format]): The check method for ambiguity of dim order.
Examples:
>>> torch.empty((2, 3, 5, 7)).dim_order() (0, 1, 2, 3) >>> torch.empty((2, 3, 5, 7)).transpose(1, 2).dim_order() (0, 2, 1, 3) >>> torch.empty((2, 3, 5, 7), memory_format=torch.channels_last).dim_order() (0, 2, 3, 1) >>> torch.empty((1, 2, 3, 4)).dim_order() (0, 1, 2, 3) >>> try: ... torch.empty((1, 2, 3, 4)).dim_order(ambiguity_check=True) ... except RuntimeError as e: ... print(e) The tensor does not have unique dim order, or cannot map to exact one of the given memory formats. >>> torch.empty((1, 2, 3, 4)).dim_order( ... ambiguity_check=[torch.contiguous_format, torch.channels_last] ... ) # It can be mapped to contiguous format (0, 1, 2, 3) >>> try: ... torch.empty((1, 2, 3, 4)).dim_order(ambiguity_check="ILLEGAL") ... except TypeError as e: ... print(e) The ambiguity_check argument must be a bool or a list of memory formats.
Warning
The dim_order tensor API is experimental and subject to change.
- eig(eigenvectors=False)
Checks if tensor is in shared memory.
This is always
Truefor CUDA tensors.
- istft(n_fft, hop_length=None, win_length=None, window=None, center=True, normalized=False, onesided=None, length=None, return_complex=False)
See
torch.istft()
- lstsq(other)
- lu(pivot=True, get_infos=False)
See
torch.lu()
- module_load(other, assign=False)
Defines how to transform
otherwhen loading it intoselfinload_state_dict().Used when
get_swap_module_params_on_conversion()isTrue.It is expected that
selfis a parameter or buffer in annn.Moduleandotheris the value in the state dictionary with the corresponding key, this method defines howotheris remapped before being swapped withselfviaswap_tensors()inload_state_dict().Note
This method should always return a new object that is not
selforother. For example, the default implementation returnsself.copy_(other).detach()ifassignisFalseorother.detach()ifassignisTrue.- Args:
other (Tensor): value in state dict with key corresponding to
selfassign (bool): the assign argument passed tonn.Module.load_state_dict()
- norm(p='fro', dim=None, keepdim=False, dtype=None)
See
torch.norm()
- refine_names(*names)
Refines the dimension names of
selfaccording tonames.Refining is a special case of renaming that “lifts” unnamed dimensions. A
Nonedim can be refined to have any name; a named dim can only be refined to have the same name.Because named tensors can coexist with unnamed tensors, refining names gives a nice way to write named-tensor-aware code that works with both named and unnamed tensors.
namesmay contain up to one Ellipsis (...). The Ellipsis is expanded greedily; it is expanded in-place to fillnamesto the same length asself.dim()using names from the corresponding indices ofself.names.Python 2 does not support Ellipsis but one may use a string literal instead (
'...').- Args:
- names (iterable of str): The desired names of the output tensor. May
contain up to one Ellipsis.
Examples:
>>> imgs = torch.randn(32, 3, 128, 128) >>> named_imgs = imgs.refine_names('N', 'C', 'H', 'W') >>> named_imgs.names ('N', 'C', 'H', 'W') >>> tensor = torch.randn(2, 3, 5, 7, 11) >>> tensor = tensor.refine_names('A', ..., 'B', 'C') >>> tensor.names ('A', None, None, 'B', 'C')
Warning
The named tensor API is experimental and subject to change.
- register_hook(hook)
Registers a backward hook.
The hook will be called every time a gradient with respect to the Tensor is computed. The hook should have the following signature:
hook(grad) -> Tensor or None
The hook should not modify its argument, but it can optionally return a new gradient which will be used in place of
grad.This function returns a handle with a method
handle.remove()that removes the hook from the module.Note
See backward-hooks-execution for more information on how when this hook is executed, and how its execution is ordered relative to other hooks.
Example:
>>> v = torch.tensor([0., 0., 0.], requires_grad=True) >>> h = v.register_hook(lambda grad: grad * 2) # double the gradient >>> v.backward(torch.tensor([1., 2., 3.])) >>> v.grad 2 4 6 [torch.FloatTensor of size (3,)] >>> h.remove() # removes the hook
- register_post_accumulate_grad_hook(hook)
Registers a backward hook that runs after grad accumulation.
The hook will be called after all gradients for a tensor have been accumulated, meaning that the .grad field has been updated on that tensor. The post accumulate grad hook is ONLY applicable for leaf tensors (tensors without a .grad_fn field). Registering this hook on a non-leaf tensor will error!
The hook should have the following signature:
hook(param: Tensor) -> None
Note that, unlike other autograd hooks, this hook operates on the tensor that requires grad and not the grad itself. The hook can in-place modify and access its Tensor argument, including its .grad field.
This function returns a handle with a method
handle.remove()that removes the hook from the module.Note
See backward-hooks-execution for more information on how when this hook is executed, and how its execution is ordered relative to other hooks. Since this hook runs during the backward pass, it will run in no_grad mode (unless create_graph is True). You can use torch.enable_grad() to re-enable autograd within the hook if you need it.
Example:
>>> v = torch.tensor([0., 0., 0.], requires_grad=True) >>> lr = 0.01 >>> # simulate a simple SGD update >>> h = v.register_post_accumulate_grad_hook(lambda p: p.add_(p.grad, alpha=-lr)) >>> v.backward(torch.tensor([1., 2., 3.])) >>> v tensor([-0.0100, -0.0200, -0.0300], requires_grad=True) >>> h.remove() # removes the hook
- reinforce(reward)
- rename(*names, **rename_map)
Renames dimension names of
self.There are two main usages:
self.rename(**rename_map)returns a view on tensor that has dims renamed as specified in the mappingrename_map.self.rename(*names)returns a view on tensor, renaming all dimensions positionally usingnames. Useself.rename(None)to drop names on a tensor.One cannot specify both positional args
namesand keyword argsrename_map.Examples:
>>> imgs = torch.rand(2, 3, 5, 7, names=('N', 'C', 'H', 'W')) >>> renamed_imgs = imgs.rename(N='batch', C='channels') >>> renamed_imgs.names ('batch', 'channels', 'H', 'W') >>> renamed_imgs = imgs.rename(None) >>> renamed_imgs.names (None, None, None, None) >>> renamed_imgs = imgs.rename('batch', 'channel', 'height', 'width') >>> renamed_imgs.names ('batch', 'channel', 'height', 'width')
Warning
The named tensor API is experimental and subject to change.
- resize(*sizes)
- resize_as(tensor)
Moves the underlying storage to shared memory.
This is a no-op if the underlying storage is already in shared memory and for CUDA tensors. Tensors in shared memory cannot be resized.
See
torch.UntypedStorage.share_memory_()for more details.
- solve(other)
- split(split_size, dim=0)
See
torch.split()
- stft(n_fft, hop_length=None, win_length=None, window=None, center=True, pad_mode='reflect', normalized=False, onesided=None, return_complex=None, align_to_window=None)
See
torch.stft()Warning
This function changed signature at version 0.4.1. Calling with the previous signature may cause error or return incorrect result.
- storage() torch.TypedStorage
Returns the underlying
TypedStorage.Warning
TypedStorageis deprecated. It will be removed in the future, andUntypedStoragewill be the only storage class. To access theUntypedStoragedirectly, useTensor.untyped_storage().
- storage_type() type
Returns the type of the underlying storage.
- symeig(eigenvectors=False)
- to_sparse_coo()
Convert a tensor to coordinate format.
Examples:
>>> dense = torch.randn(5, 5) >>> sparse = dense.to_sparse_coo() >>> sparse._nnz() 25
- unique(sorted=True, return_inverse=False, return_counts=False, dim=None)
Returns the unique elements of the input tensor.
See
torch.unique()
- unique_consecutive(return_inverse=False, return_counts=False, dim=None)
Eliminates all but the first element from every consecutive group of equivalent elements.
See
torch.unique_consecutive()
- merlin.algorithms.kernels.build_slos_graph(m, n_photons, output_map_func=None, computation_space=None, no_bunching=None, keep_keys=True, device=None, dtype=torch.float32, index_photons=None)
Construct a reusable SLOS computation graph.
- Return type:
Parameters
- mint
Number of modes in the circuit.
- n_photonsint
Total number of photons injected in the circuit.
- output_map_funccallable, optional
Mapping applied to each output Fock state, allowing post-processing.
computation_space : ComputationSpace, optional keep_keys : bool, optional
Whether to keep the list of mapped Fock states.
- devicetorch.device, optional
Device on which tensors should be allocated.
- dtypetorch.dtype, optional
Real dtype controlling numerical precision.
- index_photonslist[tuple[int, …]], optional
Bounds for each photon placement.
Returns
- SLOSComputeGraph
Pre-built computation graph ready for repeated evaluations.
- merlin.algorithms.kernels.cast(typ, val)
Cast a value to a type.
This returns the value unchanged. To the type checker this signals that the return value has the designated type, but at runtime we intentionally don’t check anything (we want this to be as fast as possible).
- merlin.algorithms.kernels.resolve_detectors(experiment, n_modes)
Build a per-mode detector list from a Perceval experiment.
- Return type:
tuple[list[Detector],bool]
- Args:
experiment: Perceval experiment carrying detector configuration. n_modes: Number of photonic modes to cover.
- Returns:
- normalized: list[pcvl.Detector]
List of detectors (defaulting to ideal PNR where unspecified),
- empty_detectors: bool
If True, no Detector was defined in experiment. If False, at least one Detector was defined in experiement.
- merlin.algorithms.kernels.resolve_photon_loss(experiment, n_modes)
Resolve photon loss from the experiment’s noise model.
- Return type:
tuple[list[float],bool]
- Args:
experiment: The quantum experiment carrying the noise model. n_modes: Number of photonic modes to cover.
- Returns:
Tuple containing the per-mode survival probabilities and a flag indicating whether an effective noise model was provided.
- merlin.algorithms.kernels.to_torch_dtype(dtype_like, *, default=None)
Convert common dtype representations (strings, numpy dtypes, torch dtypes) into torch dtypes.
- Return type:
dtype
- Args:
dtype_like: Input representation to convert. default: Fallback dtype if the representation is unknown. Defaults to torch.float32.
- Returns:
torch.dtype corresponding to the requested representation.
- Raises:
TypeError: If the value cannot be mapped and no default is provided.
Note
When the wrapped FeatureMap exposes a
perceval.Experiment, fidelity kernels compose the attached
perceval.NoiseModel (photon loss) before applying any detector
transforms. The resulting kernel values therefore reflect both survival
probabilities and detector post-processing.
Examples
Quickstart: Fidelity kernel in a few lines
import torch
from merlin.algorithms.kernels import FidelityKernel
# Build a kernel where inputs of size 2 are encoded in a 4-mode circuit
kernel = FidelityKernel.simple(
input_size=2,
n_modes=4,
shots=0, # exact probabilities (no sampling)
no_bunching=False, # allow bunched outcomes if needed
dtype=torch.float32,
device=torch.device("cpu"),
)
# X_train: (N, 2), X_test: (M, 2)
X_train = torch.rand(10, 2)
X_test = torch.rand(5, 2)
K_train = kernel(X_train) # (N, N)
K_test = kernel(X_test, X_train) # (M, N)
Custom experiment with FeatureMap
import torch
import perceval as pcvl
from merlin.algorithms.kernels import FeatureMap, FidelityKernel
# Define a photonic circuit
circuit = pcvl.Circuit(6)
# Add whatever to the circuit...
# Define the Experiment
experiment = pcvl.Experiment(circuit)
# Add noise models, detectors, etc...
experiment.noise = pcvl.NoiseModel(brightness=0.9)
experiment.detectors[0] = pcvl.Detector.threshold()
experiment.detectors[5] = pcvl.Detector.ppnr(n_wires=3)
# Use the experiment to create a FeatureMap automatically
feature_map = FeatureMap.from_photonic_backend(
input_size=0,
experiment=experiment,
)
# Build the kernel with a specific input state
kernel = FidelityKernel(
feature_map=feature_map,
input_state=[2, 0, 2, 0, 2, 0],
no_bunching=False,
)
X = torch.rand(8, 3)
K = kernel(X) # (8, 8)
Use with scikit-learn (precomputed kernel)
import torch
from sklearn.svm import SVC
from merlin.algorithms.kernels import FidelityKernel
# Build kernel and compute Gram matrices
kernel = FidelityKernel.simple(input_size=4, n_modes=6)
K_train = kernel(X_train)
K_test = kernel(X_test, X_train)
# Train a precomputed-kernel SVM
clf = SVC(kernel="precomputed")
clf.fit(K_train, y_train)
y_pred = clf.predict(K_test)