# qnet.algebra.circuit_algebra module¶

This module defines the circuit algebra for quantum optical feedback and feedforward circuits in the zero-internal time-delay limit. For more details see Circuit Algebra.

References:

 [1] (1, 2) Gough, James & Nurdin (2010). Squeezing components in linear quantum feedback networks. Physical Review A, 81(2). doi:10.1103/PhysRevA.81.023804
 [2] Gough & James (2008). Quantum Feedback Networks: Hamiltonian Formulation. Communications in Mathematical Physics, 287(3), 1109-1132. doi:10.1007/s00220-008-0698-8
 [3] Gough & James (2009). The Series Product and Its Application to Quantum Feedforward and Feedback Networks. IEEE Transactions on Automatic Control, 54(11), 2530-2544. doi:10.1109/TAC.2009.2031205

## Summary¶

Exceptions:

 CannotConvertToABCD Is raised when a circuit algebra object cannot be converted to a concrete ABCD object. CannotConvertToSLH Is raised when a circuit algebra object cannot be converted to a concrete SLH object. CannotEliminateAutomatically Raised when attempted automatic adiabatic elimination fails. CannotVisualize Is raised when a circuit algebra object cannot be visually represented. IncompatibleBlockStructures Is raised when a circuit decomposition into a block-structure is requested that is icompatible with the actual block structure of the circuit expression. WrongCDimError Is raised when two object are tried to joined together in series but have different channel dimensions.

Classes:

 ABCD ABCD model class in amplitude representation. CPermutation The channel permuting circuit. Circuit Abstract base class for the circuit algebra elements. CircuitSymbol Circuit Symbol object, parametrized by an identifier (name) and channel dimension. Concatenation The concatenation product circuit operation. Feedback The circuit feedback operation applied to a circuit of channel dimension > 1 and an from an output port index to an input port index. SLH SLH class to encapsulate an open system model that is parametrized as SeriesInverse Symbolic series product inversion operation. SeriesProduct The series product circuit operation.

Functions:

Data:

 CIdentity Single channel circuit identity system, the neutral element of single channel series products. CircuitZero The zero circuit system, the neutral element of Concatenation. cid_1 Single channel circuit identity system, the neutral element of single channel series products.

## Reference¶

exception qnet.algebra.circuit_algebra.CannotConvertToSLH[source]

Is raised when a circuit algebra object cannot be converted to a concrete SLH object.

exception qnet.algebra.circuit_algebra.CannotConvertToABCD[source]

Is raised when a circuit algebra object cannot be converted to a concrete ABCD object.

exception qnet.algebra.circuit_algebra.CannotVisualize[source]

Is raised when a circuit algebra object cannot be visually represented.

exception qnet.algebra.circuit_algebra.WrongCDimError[source]

Is raised when two object are tried to joined together in series but have different channel dimensions.

exception qnet.algebra.circuit_algebra.IncompatibleBlockStructures[source]

Is raised when a circuit decomposition into a block-structure is requested that is icompatible with the actual block structure of the circuit expression.

exception qnet.algebra.circuit_algebra.CannotEliminateAutomatically[source]

Raised when attempted automatic adiabatic elimination fails.

qnet.algebra.circuit_algebra.check_cdims(cls, ops, kwargs)[source]

Check that all operands (ops) have equal channel dimension.

class qnet.algebra.circuit_algebra.Circuit[source]

Bases: object

Abstract base class for the circuit algebra elements.

cdim

The channel dimension of the circuit expression, i.e. the number of external bosonic noises/inputs that the circuit couples to.

block_structure

If the circuit is reducible (i.e., it can be represented as a :py:class:Concatenation: of individual circuit expressions), this gives a tuple of cdim values of the subblocks. E.g. if A and B are irreducible and have A.cdim = 2, B.cdim = 3

>>> A = CircuitSymbol('A', 2)
>>> B = CircuitSymbol('B', 3)

Then the block structure of their Concatenation is:

>>> (A + B).block_structure
(2, 3)

while

>>> A.block_structure
(2,)
>>> B.block_structure
(3,)
index_in_block(channel_index: int) → int[source]

Return the index a channel has within the subblock it belongs to. I.e., only for reducible circuits, this gives a result different from the argument itself.

Parameters: channel_index (int) – The index of the external channel ValueError – for an invalid channel_index
get_blocks(block_structure=None)[source]

For a reducible circuit, get a sequence of subblocks that when concatenated again yield the original circuit. The block structure given has to be compatible with the circuits actual block structure, i.e. it can only be more coarse-grained.

Parameters: block_structure (tuple) – The block structure according to which the subblocks are generated (default = None, corresponds to the circuit’s own block structure) A tuple of subblocks that the circuit consists of. IncompatibleBlockStructures
series_inverse() → qnet.algebra.circuit_algebra.Circuit[source]

Return the inverse object (under the series product) for a circuit. In general for any X

>>> X = CircuitSymbol('X', cdim=3)
>>> (X << X.series_inverse() == X.series_inverse() << X ==
...  cid(X.cdim))
True
feedback(*, out_port=None, in_port=None)[source]

Return a circuit with self-feedback from the output port (zero-based) out_port to the input port in_port.

Parameters: out_port (int or NoneType) – The output port from which the feedback connection leaves (zero-based, default = None corresponds to the last port). in_port (int or NoneType) – The input port into which the feedback connection goes (zero-based, default = None corresponds to the last port).
show()[source]

Show the circuit expression in an IPython notebook.

render(fname='')[source]

Render the circuit expression and store the result in a file

Parameters: fname (str) – Path to an image file to store the result in. The path to the image file
creduce() → qnet.algebra.circuit_algebra.Circuit[source]

If the circuit is reducible, try to reduce each subcomponent once. Depending on whether the components at the next hierarchy-level are themselves reducible, successive circuit.creduce() operations yields an increasingly fine-grained decomposition of a circuit into its most primitive elements.

toSLH() → qnet.algebra.circuit_algebra.SLH[source]

Return the SLH representation of a circuit. This can fail if there are un-substituted pure circuit all_symbols (CircuitSymbol) left in the expression or if the circuit includes non-passive ABCD models (cf. [1])

toABCD(linearize=False) → qnet.algebra.circuit_algebra.ABCD[source]

Return the ABCD representation of a circuit expression. If linearize=True all operator expressions giving rise to non-linear equations of motion are dropped. This can fail if there are un-substituted pure circuit all_symbols (CircuitSymbol) left in the expression or if linearize = False and the circuit includes non-linear SLH models. (cf. [1])

coherent_input(*input_amps) → qnet.algebra.circuit_algebra.Circuit[source]

Feed coherent input amplitudes into the circuit. E.g. For a circuit with channel dimension of two, C.coherent_input(0,1) leads to an input amplitude of zero into the first and one into the second port.

Parameters: input_amps (SCALAR_TYPES) – The coherent input amplitude for each port The circuit including the coherent inputs. Circuit WrongCDimError
space

Hilbert space of the circuit

class qnet.algebra.circuit_algebra.SLH(S, L, H)[source]

SLH class to encapsulate an open system model that is parametrized as described in [2] , [3]

Parameters: S (Matrix) – The scattering matrix (with in general Operator-valued elements) L (Matrix) – The coupling vector (with in general Operator-valued elements) H (Operator) – The internal Hamiltonian operator
S

Scattering matrix

L

Coupling vector

H

Hamiltonian

args
Ls

Lindblad operators (entries of the L vector), as a list

cdim

The circuit dimension

space

Total Hilbert space

all_symbols()[source]

Set of all symbols occcuring in S, L, or H

series_with_slh(other)[source]

Evaluate the series product with another :py:class:SLH object.

Parameters: other (SLH) – An upstream SLH circuit. The combines system. SLH
concatenate_slh(other)[source]

Evaluate the concatenation product with another SLH object.

expand()[source]

Expand out all operator expressions within S, L and H and return a new SLH object with these expanded expressions.

simplify_scalar()[source]

Simplify all scalar expressions within S, L and H and return a new SLH object with the simplified expressions.

symbolic_liouvillian()[source]
symbolic_master_equation(rho=None)[source]

Compute the symbolic Liouvillian acting on a state rho. If no rho is given, an OperatorSymbol is created in its place. This correspnds to the RHS of the master equation in which an average is taken over the external noise degrees of freedom.

Parameters: rho (Operator) – A symbolic density matrix operator The RHS of the master equation. Operator
symbolic_heisenberg_eom(X=None, noises=None, expand_simplify=True)[source]

Compute the symbolic Heisenberg equations of motion of a system operator X. If no X is given, an OperatorSymbol is created in its place. If no noises are given, this correspnds to the ensemble-averaged Heisenberg equation of motion.

Parameters: X (Operator) – A system operator noises (Operator) – A vector of noise inputs The RHS of the Heisenberg equations of motion of X. Operator
class qnet.algebra.circuit_algebra.ABCD(A, B, C, D, w, space)[source]

ABCD model class in amplitude representation.

ABCD(A, B, C, D, w, space)

I.e. for a doubled up vector a = (a_1, …, a_n, a_1^*, … a_n^*)^T = double_up((a_1, …, a_n)^T) and doubled up noises dA = (dA_1, …, dA_m, dA_1^*, …, dA_m^*)^T = double_up((dA_1, …, dA_n)^T) The equation of motion for a is

$da = A a dt + B (dA + double_up(w) dt)$

The output field dA’ is given by

$dA' = C a dt + D (dA + double_up(w) dt)$
Parameters: A (Matrix) – Coupling matrix: internal to internal, scalar valued elements, shape = (2*n,2*n) B (Matrix) – Coupling matrix external input to internal, scalar valued elements, shape = (2*n,2*m) C (Matrix) – Coupling matrix internal to external output, scalar valued elements, shape = (2*m,2*n) D (Matrix) – Coupling matrix external input to output, scalar valued elements, shape = (2*m,2*m) w (Matrix) – Coherent input amplitude vector, NOT DOUBLED UP, scalar valued elements, shape = (m,1) space (HilbertSpace) – Hilbert space with exactly n local factor spaces corresponding to the n internal degrees of freedom.
space

Total Hilbert space

args
n

The number of oscillators (int).

m

The number of external fields (int)

cdim

Dimension of circuit

class qnet.algebra.circuit_algebra.CircuitSymbol(name, cdim)[source]

Circuit Symbol object, parametrized by an identifier (name) and channel dimension.

name
args
all_symbols()[source]
cdim

Dimension of circuit

space

FullSpace (Circuit Symbols are not restricted to a particular Hilbert space)

class qnet.algebra.circuit_algebra.CPermutation(permutation)[source]

The channel permuting circuit. This circuit expression is only a rearrangement of input and output fields. A channel permutation is given as a tuple of image points. Permutations are usually represented as

A permutation $$\sigma \in \Sigma_n$$ of $$n$$ elements is often represented in the following form

$\begin{split}\begin{pmatrix} 1 & 2 & \dots & n \\ \sigma(1) & \sigma(2) & \dots & \sigma(n) \end{pmatrix},\end{split}$

but obviously it is fully sufficient to specify the tuple of images $$(\sigma(1), \sigma(2), \dots, \sigma(n))$$. We thus parametrize our permutation circuits only in terms of the image tuple. Moreover, we will be working with zero-based indices!

A channel permutation circuit for a given permutation (represented as a python tuple of image indices) scatters the $$j$$-th input field to the $$\sigma(j)$$-th output field.

It is instantiated as

CPermutation(permutation)
Parameters: permutation (tuple) – Channel permutation image tuple.
classmethod create(permutation)[source]
args
block_perms

If the circuit is reducible into permutations within subranges of the full range of channels, this yields a tuple with the internal permutations for each such block.

Type: tuple
permutation

The permutation image tuple.

cdim
series_with_permutation(other)[source]

Compute the series product with another channel permutation circuit.

Returns: The composite permutation circuit (could also be the identity circuit for n channels) Circuit
space

TrivialSpace

qnet.algebra.circuit_algebra.CIdentity = CIdentity[source]

Single channel circuit identity system, the neutral element of single channel series products.

qnet.algebra.circuit_algebra.CircuitZero = CircuitZero[source]

The zero circuit system, the neutral element of Concatenation. No ports, no internal dynamics.

qnet.algebra.circuit_algebra.cid_1 = CIdentity

Single channel circuit identity system, the neutral element of single channel series products.

class qnet.algebra.circuit_algebra.SeriesProduct(*operands, **kwargs)[source]

The series product circuit operation. It can be applied to any sequence of circuit objects that have equal channel dimension.

SeriesProduct(*operands)
Parameters: operands – Circuits in feedforward configuration.
neutral_element = neutral_element[source]

Generic neutral element checker of the SeriesProduct, it works for any channel dimension.

cdim
space

Hilbert space of the series product (product space of all operators)

class qnet.algebra.circuit_algebra.Concatenation(*operands)[source]

The concatenation product circuit operation. It can be applied to any sequence of circuit objects.

Concatenation(*operands)
Parameters: operands (Circuit) – Circuits in parallel configuration.
neutral_element = CircuitZero

The zero circuit system, the neutral element of Concatenation. No ports, no internal dynamics.

cdim

Circuit dimension (sum of dimensions of the operands)

space

Hilbert space of the Concatenation (Product space of all operators)

class qnet.algebra.circuit_algebra.Feedback(circuit: qnet.algebra.circuit_algebra.Circuit, *, out_port: int, in_port: int)[source]

The circuit feedback operation applied to a circuit of channel dimension > 1 and an from an output port index to an input port index.

Parameters: circuit (Circuit) – The circuit that undergoes self-feedback out_port (int) – The output port index. in_port (int) – The input port index.
delegate_to_method = (<class 'qnet.algebra.circuit_algebra.Concatenation'>, <class 'qnet.algebra.circuit_algebra.SLH'>, <class 'qnet.algebra.circuit_algebra.CPermutation'>)
kwargs
operand

The Circuit that undergoes feedback

out_in_pair

Tuple of zero-based feedback port indices (out_port, in_port)

cdim

Circuit dimension (one less than the circuit on which the feedback acts

classmethod create(circuit: qnet.algebra.circuit_algebra.Circuit, *, out_port: int, in_port: int) → qnet.algebra.circuit_algebra.Feedback[source]
space

Hilbert space of the Feedback circuit (same as the Hilbert space of the operand)

class qnet.algebra.circuit_algebra.SeriesInverse(*operands, **kwargs)[source]

Symbolic series product inversion operation.

SeriesInverse(circuit)

One generally has

>>> C = CircuitSymbol('C', cdim=3)
>>> SeriesInverse(C) << C == cid(C.cdim)
True

and

>>> C << SeriesInverse(C) == cid(C.cdim)
True
Parameters: circuit (Circuit) – The circuit system to invert.
delegate_to_method = (<class 'qnet.algebra.circuit_algebra.SeriesProduct'>, <class 'qnet.algebra.circuit_algebra.Concatenation'>, <class 'qnet.algebra.circuit_algebra.Feedback'>, <class 'qnet.algebra.circuit_algebra.SLH'>, <class 'qnet.algebra.circuit_algebra.CPermutation'>, <class 'qnet.algebra.circuit_algebra.CIdentity'>)
operand

The un-inverted circuit

classmethod create(circuit)[source]
cdim
space

Hilbert space of the series inversion circuit (same Hilbert space as the series product being inverted)

qnet.algebra.circuit_algebra.circuit_identity(n)[source]

Return the circuit identity for n channels.

Parameters: n (int) – The channel dimension n-channel identity circuit Circuit
qnet.algebra.circuit_algebra.cid(n)

Return the circuit identity for n channels.

Parameters: n (int) – The channel dimension n-channel identity circuit Circuit
qnet.algebra.circuit_algebra.P_sigma(*permutation)[source]

Create a channel permutation circuit for the given index image values. :param permutation: image points :type permutation: int :return: CPermutation.create(permutation) :rtype: Circuit

qnet.algebra.circuit_algebra.FB(circuit, *, out_port=None, in_port=None)[source]

Wrapper for :py:class:Feedback: but with additional default values.

Parameters: circuit (Circuit) – The circuit that undergoes self-feedback out_port (int) – The output port index, default = None –> last port in_port (int) – The input port index, default = None –> last port The circuit with applied feedback operation. Circuit
qnet.algebra.circuit_algebra.get_common_block_structure(lhs_bs, rhs_bs)[source]

For two block structures aa = (a1, a2, ..., an), bb = (b1, b2, ..., bm) generate the maximal common block structure so that every block from aa and bb is contained in exactly one block of the resulting structure. This is useful for determining how to apply the distributive law when feeding two concatenated Circuit objects into each other.

Examples

(1, 1, 1), (2, 1) -> (2, 1) (1, 1, 2, 1), (2, 1, 2) -> (2, 3)

Parameters: lhs_bs (tuple) – first block structure rhs_bs (tuple) – second block structure
qnet.algebra.circuit_algebra.extract_signal(k, n)[source]

Create a permutation that maps the k-th (zero-based) element to the last element, while preserving the relative order of all other elements.

Parameters: k (int) – The index to extract n (int) – The total number of elements Permutation image tuple tuple
qnet.algebra.circuit_algebra.extract_signal_circuit(k, cdim)[source]

Create a channel permutation circuit that maps the k-th (zero-based) input to the last output, while preserving the relative order of all other channels.

Parameters: k (int) – Extracted channel index cdim (int) – The channel dimension Permutation circuit Circuit
qnet.algebra.circuit_algebra.map_signals(mapping, n)[source]

For a given {input:output} mapping in form of a dictionary, generate the permutation that achieves the specified mapping while leaving the relative order of all non-specified elements intact. :param mapping: Input-output mapping of indices (zero-based) {in1:out1, in2:out2,…} :type mapping: dict :param n: total number of elements :type n: int :return: Signal mapping permutation image tuple :rtype: tuple :raise: ValueError

qnet.algebra.circuit_algebra.map_signals_circuit(mapping, n)[source]

For a given {input:output} mapping in form of a dictionary, generate the channel permutating circuit that achieves the specified mapping while leaving the relative order of all non-specified channels intact. :param mapping: Input-output mapping of indices (zero-based) {in1:out1, in2:out2,…} :type mapping: dict :param n: total number of elements :type n: int :return: Signal mapping permutation image tuple :rtype: Circuit

Pad a circuit by ‘inserting’ an n-channel identity circuit at index k. I.e., a circuit of channel dimension N is extended to one of channel dimension N+n, where the channels k, k+1, …k+n-1, just pass through the system unaffected. E.g. let A, B be two single channel systems

>>> A = CircuitSymbol('A', 1)
>>> B = CircuitSymbol('B', 1)
A + cid(2) + B

This method can also be applied to irreducible systems, but in that case the result can not be decomposed as nicely.

Parameters: k (int) – The index at which to insert the circuit n (int) – The number of channels to pass through An extended circuit that passes through the channels k, k+1, …, k+n-1 Circuit
qnet.algebra.circuit_algebra.getABCD(slh, a0=None, doubled_up=True)[source]

Return the A, B, C, D and (a, c) matrices that linearize an SLH model about a coherent displacement amplitude a0.

The equations of motion and the input-output relation are then:

dX = (A X + a) dt + B dA_in dA_out = (C X + c) dt + D dA_in

where, if doubled_up == False

dX = [a_1, …, a_m] dA_in = [dA_1, …, dA_n]

or if doubled_up == True

dX = [a_1, …, a_m, a_1^*, … a_m^*] dA_in = [dA_1, …, dA_n, dA_1^*, …, dA_n^*]
Parameters: slh – SLH object a0 – dictionary of coherent amplitudes {a1: a1_0, a2: a2_0, …} with annihilation mode operators as keys and (numeric or symbolic) amplitude as values. doubled_up – boolean, necessary for phase-sensitive / active systems

Returns SymPy matrix objects :returns: A tuple (A, B, C, D, a, c])

A: coupling of modes to each other B: coupling of external input fields to modes C: coupling of internal modes to output D: coupling of external input fields to output fields

a: constant coherent input vector for mode e.o.m. c: constant coherent input vector of scattered amplitudes contributing to the output

qnet.algebra.circuit_algebra.move_drive_to_H(slh, which=[])[source]

For the given slh model, move inhomogeneities in the Lindblad operators (resulting from the presence of a coherent drive, see Displace) to the Hamiltonian.

This exploits the invariance of the Lindblad master equation under the transformation (cf. Breuer and Pettrucione, Ch 3.2.1)

\begin{align} \Op{L}_i &\longrightarrow \Op{L}_i' = \Op{L}_i - \alpha_i \\ \Op{H} &\longrightarrow \Op{H}' = \Op{H} + \frac{1}{2i} \sum_j (\alpha_j \Op{L}_j^{\dagger} - \alpha_j^* \Op{L}_j) \end{align}

In the context of SLH, this transformation is achieved by feeding slh into

$\SLH(\identity, -\mat{\alpha}, 0)$

where $$\mat{\alpha}$$ has the components $$\alpha_i$$.

The which argument allows to select which subscripts $$i$$ (circuit dimensions) should be tranformed. The default is all dimensions. If slh does not contain any inhomogeneities, it is invariant under the transformation.

Prepare the adiabatic elimination procedure for an SLH object with scaling parameter k->infty

Parameters: slh – The SLH object to take the limit for k – The scaling parameter. The objects Y, A, B, F, G, N necessary to compute the limiting system. tuple

Compute the limiting SLH model for the adiabatic approximation.

Parameters: YABFGN – The tuple (Y, A, B, F, G, N) as returned by prepare_adiabatic_limit. Ytilde – The pseudo-inverse of Y, satisfying Y * Ytilde = P0. P0 – The projector onto the null-space of Y. Limiting SLH model SLH

Attempt to automatically carry out the adiabatic elimination procedure on slh with scaling parameter k.

This will project the Y operator onto a truncated basis with dimension specified by fock_trunc. sub_P0 controls whether an attempt is made to replace the kernel projector P0 by an IdentityOperator.

qnet.algebra.circuit_algebra.connect(components, connections, force_SLH=False, expand_simplify=True)[source]

Connect a list of components according to a list of connections.

Parameters: components (list) – List of Circuit instances connections (list) – List of pairs ((c1, port1), (c2, port2)) where c1 and c2 are elements of components (or the index of the element in components, and port1 and port2 are the indices of the ports of the two components that should be connected force_SLH (bool) – If True, convert the result to an SLH object expand_simplify (bool) – If the result is an SLH object, expand and simplify the circuit after each feedback connection is added