Skip to content

interfaces

eigenkit.core.interfaces

Differentiation interfaces, which connect the core to automatic differentiation.

The core Circuit computes forward values and analytic NumPy jacobians (with the parameter-shift rule, the chain rule or the adjoint method). An interface connects this NumPy code to the automatic differentiation of a framework. It wraps the NumPy run and jacobians of the circuit into a differentiable operation of that framework (a torch.autograd.Function now, a jax.custom_vjp later), and it converts between the framework and NumPy.

NumPy needs no interface, because the core returns arrays directly. Frameworks register themselves when their package is imported. Adding JAX therefore takes a new adapter module and one register_interface() call. The core never changes and never imports a framework.

get_interface("torch") imports the PyTorch package (eigenkit.torch) the first time it is needed, and raises a clear error if PyTorch is not installed.

Interface

Bases: Protocol

An adapter from the NumPy core to the automatic differentiation of a framework.

run_circuit receives the core Circuit (for compiled, provider.gradient_method, observables and the jacobian helpers), and the weights and inputs as tensors of the framework. It returns a differentiable output, also as a tensor of the framework.

run_circuit(circuit, weights, inputs)

Run circuit on tensors of the framework and return a differentiable result.

An implementation that builds its own default inputs (for a circuit that takes none) must call circuit._check_parameter_lengths(weights, inputs) once that default exists. The core cannot run this check before it passes the call here, and without it an input of the wrong size can be cut short without any error.

Parameters:

Name Type Description Default
circuit Circuit

The core circuit being run.

required
weights Any

The weights, as a tensor of the framework.

required
inputs Any

The inputs, as a tensor of the framework.

required

Returns:

Name Type Description
result Any

A differentiable result, as a tensor of the framework.

get_interface(name)

Return the interface registered under name, importing its package if needed.

Parameters:

Name Type Description Default
name str

The registered name.

required

Returns:

Type Description
Interface

The registered interface.

Raises:

Type Description
ImportError

If the package of the interface is known but its framework is not installed. The message says how to install it.

KeyError

If no interface is registered under name.

register_interface(name, interface)

Register the interface of a framework under name (for example "torch").

Parameters:

Name Type Description Default
name str

The name to register.

required
interface Interface

The adapter to register.

required

registered_interfaces()

Return the names of the interfaces registered so far.

An interface appears only once its package has been imported, so this lists what is loaded now, not everything that is installed.

Example
from eigenkit.core.interfaces import registered_interfaces

print(registered_interfaces())   # []

import eigenkit.torch  # registers itself on import
print(registered_interfaces())   # ['torch']

Returns:

Type Description
list[str]

The registered interface names.