Welcome to QNET’s documentation!¶
The QNET package is a set of tools to aid in the design and analysis of photonic circuit models, but it features a flexible symbolic algebra module that can be applied in a more general setting. Our proposed Quantum Hardware Description Language [QHDL] serves to describe a circuit topology and specification of a larger entity in terms of parametrizable subcomponents. By design this is analogous to the specification of electric circuitry using the structural description elements of VHDL or Verilog.
The physical systems that can be modeled within the framework include quantum optical experiments that can be described as nodes with internal degrees of freedom such as interacting quantum harmonic oscillators and/or N-level quantum systems that, in turn are coupled to a finite number of bosonic quantum fields. Furthermore, the formalism applies also to superconducting microwave circuit (Circuit QED) systems.
For a rigorous introduction to the underlying mathematical physics we refer to the original treatment of Gough and James [GoughJames08], [GoughJames09] and the references given therein.
The main components of this package are:
- A symbolic computer algebra package
qnet.algebra
for Hilbert Space quantum mechanical operators, the Gough-James circuit algebra and also an algebra for Hilbert space states and Super-operators. - The QHDL language definition and parser
qnet.qhdl
including a front-end located atbin/parse_qhdl.py
that can convert a QHDL-file into a circuit component library file. - A library of existing primitive or composite circuit components
qnet.circuit_components
that can be embedded into a new circuit definition.
In practice one might want to use these to:
- Define and specify your basic circuit component model and create a library file, Circuit Component Definition
- Use
gschem
(of gEDA) to graphically design a circuit model, Schematic Capture - Export the schematic to QHDL using
gnetlist
(also part of gEDA) or directly write a QHDL file, Netlisting - Parse the QHDL-circuit definition file into a Python circuit library component using the parser front-end
bin/parse_qhdl.py
, Parsing QHDL - Analyze the model analytically using our symbolic algebra and/or numerically using QuTiP, Symbolic Algebra, Symbolic Analysis and Simulation
This package is still work in progress and as it is currently being developed by a single developer (interested in helping?), documentation and comprehensive testing code are still somewhat lacking. Any contributions, bug reports and general feedback from end-users would be highly appreciated. If you have found a bug, it would be extremely helpful if you could try to write a minimal code example that reproduces the bug. Feature requests will definitely be considered. Higher priority will be given to things that many people ask for and that can be implemented efficiently.
To learn of how to carry out each of these steps, we recommend looking at the provided examples and reading the relevant sections in the QNET manual. Also, if you want to implement and add your own primitive device models, please consult the QNET manual.
Contents:
Installation/Setup¶
Dependencies¶
In addition to these core components, the software uses the following existing software packages:
- Python version 3.3 or higher. Python 2 is no longer supported.
- The gEDA toolsuite for its visual tool
gschem
for the creation of circuits end exporting these to QHDLgnetlist
. We have created device symbols for our primitive circuit components to be used withgschem
and we have included our owngnetlist
plugin for exporting to QHDL. - The SymPy symbolic algebra Python package to implement symbolic ‘scalar’ algebra, i.e. the coefficients of state, operator or super-operator expressions can be symbolic SymPy expressions as well as pure python numbers.
- The QuTiP python package as an extremely useful, efficient and full featured numerical backend. Operator expressions where all symbolic scalar parameters have been replaced by numeric ones, can be converted to (sparse) numeric matrix representations, which are then used to solve for the system dynamics using the tools provided by QuTiP.
- The PyX python package for visualizing circuit expressions as box/flow diagrams.
- The SciPy and NumPy packages (needed for QuTiP but also by the
qnet.algebra
package) - The PLY python package as a dependency of our Python Lex/Yacc based QHDL parser.
A convenient way of obtaining Python as well as some of the packages listed here (SymPy, SciPy, NumPy, PLY) is to download the Enthought Python Distribution (EPD) or Anaconda which are both free for academic use. A highly recommended way of working with QNET and QuTiP and just scientific python codes in action is to use the excellent IPython shell which comes both with a command-line interface as well as a very polished browser-based notebook interface.
Installation/Configuration¶
To install QNET you need a working Python installation as well as pip which comes pre-installed with both the Enthought Python distribution and Anaconda. If you have already installed PyX just run: Run:
pip install QNET
If you still need to install PyX, run:
pip install --process-dependency-links QNET
gEDA¶
Setting up gEDA/gschem/gnetlist is a bit more involved. If you are using Linux or OSX, geda is available via common package managers such as port and homebrew on OSX or apt for Linux.
To configure interoperability with QNET/QHDL this you will have to locate the installation directory of QNET. This can easily be found by running:
python -c "import qnet, os; print(os.path.join(*os.path.dirname(qnet.__file__).split('/')[:-1]))"
In BASH you can just run:
QNET=$(python -c "import qnet, os; print(os.path.join(*os.path.dirname(qnet.__file__).split('/')[:-1]))")
to store this path in a shell variable named QNET.
To configure gEDA to include our special quantum circuit component symbols you will need to copy the following configuration files from the $QNET/gEDA_support/config
directory to the $HOME/.gEDA
directory:
~/.gEDA/gafrc
~/.gEDA/gschemrc
Then install the QHDL netlister plugin within gEDA by creating a symbolic link (or copy the file there)
ln -s $QNET/gEDA_support/gnet-qhdl.scm /path/to/gEDA_resources_folder/scheme/gnet-qhdl.scm
Note that you should replace “/path/to/gEDA_resources_folder” with the full path to the gEDA resources directory!
in my case that path is given by /opt/local/share/gEDA
, but in general simply look for the gEDA-directory that contains the file named system-gafrc
.
Symbolic Algebra¶
The Abstract Algebra module¶
Warning
This overview is currently not up to date with respect to the latest
development version of QNET. Please refer to the
API
instead.
The module features generic classes for encapsulating expressions and operations on expressions. It also includes some basic pattern matching and expression rewriting capabilities.
The most important classes to derive from for implementing a custom ‘algebra’ are qnet.algebra.abstract_algebra.Expression
and qnet.algebra.abstract_algebra.Operation
,
where the second is actually a subclass of the first.
The Operation
class should be subclassed to implement any structured expression type
that can be specified in terms of a head and a (finite) sequence of operands:
Head(op1, op1, ..., opN)
An operation is assumed to have immutable operands, i.e., if one wishes to change the operands of an Operation
,
one rather creates a new Operation with modified Operands.
Defining Operation
subclasses¶
The single most important method of the Operation
class is the qnet.algebra.abstract_algebra.Operation.create()
classmethod.
Automatic expression rewriting by modifying/decorating the qnet.algebra.abstract_algebra.Operation.create()
method
A list of class decorators:
qnet.algebra.abstract_algebra.assoc()
qnet.algebra.abstract_algebra.idem()
qnet.algebra.abstract_algebra.orderby()
qnet.algebra.abstract_algebra.filter_neutral()
qnet.algebra.abstract_algebra.check_signature()
qnet.algebra.abstract_algebra.match_replace()
qnet.algebra.abstract_algebra.match_replace_binary()
Pattern matching¶
The qnet.algebra.abstract_algebra.Wildcard
class.
The qnet.algebra.abstract_algebra.match()
function.
For a relatively simple example of how an algebra can be defined, see the Hilbert space algebra defined in qnet.algebra.hilbert_space_algebra
.
Hilbert Space Algebra¶
This covers only finite dimensional or countably infinite dimensional Hilbert spaces.
The basic abstract class that features all properties of Hilbert space objects is given by: qnet.algebra.hilbert_space_algebra.HilbertSpace
.
Its most important subclasses are:
- local/primitive degrees of freedom (e.g. a single multi-level atom or a cavity mode) are described by a
qnet.algebra.hilbert_space_algebra.LocalSpace
. Every local space is identified by- composite tensor product spaces are given by instances of the
qnet.algebra.hilbert_space_algebra.ProductSpace
class.- the
qnet.algebra.hilbert_space_algebra.TrivialSpace
represents a trivial [1] Hilbert space \(\mathcal{H}_0 \simeq \mathbb{C}\)- the
qnet.algebra.hilbert_space_algebra.FullSpace
represents a Hilbert space that includes all possible degrees of freedom.
[1] | trivial in the sense that \(\mathcal{H}_0 \simeq \mathbb{C}\), i.e., all states are multiples of each other and thus equivalent. |
Examples¶
A single local space can be instantiated in several ways. It is most convenient to use the qnet.algebra.hilbert_space_algebra.local_space()
method:
>>> local_space(1)
LocalSpace(1, '')
This method also allows for the specification of the dimension
of the local degree of freedom’s state space:
>>> s = local_space(1, dimension = 10)
>>> s
LocalSpace(1, '')
>>> s.dimension
10
>>> s.basis
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Alternatively, one can pass a sequence of basis
state labels instead of the dimension
argument:
>>> lambda_atom_space = local_space('las', basis = ('e', 'h', 'g'))
>>> lambda_atom_space
LocalSpace('las', '')
>>> lambda_atom_space.dimension
3
>>> lambda_atom_space.basis
('e', 'h', 'g')
Finally, one can pass a namespace
argument, which is useful if one is working with multiple copies of identical systems, e.g. if one instantiates multiple copies of a particular circuit component with internal degrees of freedom:
>>> s_q1 = local_space('s', namespace = 'q1', basis = ('g', 'h'))
>>> s_q2 = local_space('s', namespace = 'q2', basis = ('g', 'h'))
>>> s_q1
LocalSpace('s', 'q1')
>>> s_q2
LocalSpace('s', 'q2')
>>> s_q1 * s_q2
ProductSpace(LocalSpace('s', 'q1'), LocalSpace('s', 'q2'))
The default namespace
is the empty string ''
.
Here, we have already seen the simplest way to create a tensor product of spaces:
>>> local_space(1) * local_space(2)
ProductSpace(LocalSpace(1, ''), LocalSpace(2, ''))
Note that this tensor product is commutative
>>> local_space(2) * local_space(1)
ProductSpace(LocalSpace(1, ''), LocalSpace(2, ''))
>>> local_space(2) * local_space(1) == local_space(1) * local_space(2)
True
and associative
>>> (local_space(1) * local_space(2)) * local_space(3)
ProductSpace(LocalSpace('1', ''), LocalSpace('2', ''), LocalSpace('3', ''))
The Operator Algebra module¶
This module features classes and functions to define and manipulate symbolic Operator expressions.
Operator expressions are constructed from sums (qnet.algebra.operator_algebra.OperatorPlus
) and products (qnet.algebra.operator_algebra.OperatorTimes
)
of some basic elements, most importantly local operators,
such as the annihilation (qnet.algebra.operator_algebra.Destroy
) and creation (qnet.algebra.operator_algebra.Create
) operators \(a_s, a_s^\dagger\)
of a quantum harmonic oscillator degree of freedom \(s\).
Further important elementary local operators are the switching operators
\(\sigma_{jk}^s := \left| j \right\rangle_s \left \langle k \right|_s\) (qnet.algebra.operator_algebra.LocalSigma
).
Each operator has an associated qnet.algebra.operator_algebra.Operator.space
property which gives the Hilbert space
(cf qnet.algebra.hilbert_space_algebra.HilbertSpace
) on which it acts non-trivially.
We don’t explicitly distinguish between tensor-products \(X_s\otimes Y_r\) of operators on different degrees of freedom \(s,r\)
(which we designate as local spaces) and operator-composition-products \(X_s \cdot Y_s\) of operators acting on the same degree of freedom \(s\).
Conceptionally, we assume that each operator is always implicitly tensored with identity operators acting on all un-specified degrees of freedom.
This is typically done in the physics literature and only plays a role when tansforming to a numerical representation
of the problem for the purpose of simulation, diagonalization, etc.
All Operator classes¶
A complete list of all local operators is given below:
- Harmonic oscillator mode operators \(a_s, a_s^\dagger\) (cf
qnet.algebra.operator_algebra.Destroy
,qnet.algebra.operator_algebra.Create
)- \(\sigma\)-switching operators \(\sigma_{jk}^s := \left| j \right\rangle_s \left \langle k \right|_s\) (cf
qnet.algebra.operator_algebra.LocalSigma
)- coherent displacement operators \(D_s(\alpha) := \exp{\left(\alpha a_s^\dagger - \alpha^* a_s\right)}\) (cf
qnet.algebra.operator_algebra.Displace
)- phase operators \(P_s(\phi) := \exp {\left(i\phi a_s^\dagger a_s\right)}\) (cf
qnet.algebra.operator_algebra.Phase
)- squeezing operators \(S_s(\eta) := \exp {\left[{1\over 2}\left({\eta {a_s^\dagger}^2 - \eta^* a_s^2}\right)\right]}\) (cf
qnet.algebra.operator_algebra.Squeeze
)
Furthermore, there exist symbolic representations for constants and symbols:
- the identity operator (cf
qnet.algebra.operator_algebra.IdentityOperator
)- and the zero operator (cf
qnet.algebra.operator_algebra.ZeroOperator
)- an arbitrary operator symbol (cf
qnet.algebra.operator_algebra.OperatorSymbol
)
Finally, we have the following Operator operations:
- sums of operators \(X_1 + X_2 + \dots + X_n\) (cf
qnet.algebra.operator_algebra.OperatorPlus
)- products of operators \(X_1 X_2 \cdots X_n\) (cf
qnet.algebra.operator_algebra.OperatorTimes
)- the Hilbert space adjoint operator \(X^\dagger\) (cf
qnet.algebra.operator_algebra.Adjoint
)- scalar multiplication \(\lambda X\) (cf
qnet.algebra.operator_algebra.ScalarTimesOperator
)
- pseudo-inverse of operators \(X^+\) satisfying \(X X^+ X = X\) and \(X^+ X X^+ = X^+\) as well
- as \((X^+ X)^\dagger = X^+ X\) and \((X X^+)^\dagger = X X^+\) (cf
qnet.algebra.operator_algebra.PseudoInverse
)
- the kernel projection operator \(\mathcal{P}_{{\rm Ker} X}\) satisfying both \(X \mathcal{P}_{{\rm Ker} X} = 0\)
- and \(X^+ X = 1 - \mathcal{P}_{{\rm Ker} X}\) (cf
qnet.algebra.operator_algebra.NullSpaceProjector
)- Partial traces over Operators \({\rm Tr}_s X\) (cf
qnet.algebra.operator_algebra.OperatorTrace
)
For a list of all properties and methods of an operator object, see the documentation for the basic qnet.algebra.operator_algebra.Operator
class.
Examples¶
Say we want to write a function that constructs a typical Jaynes-Cummings Hamiltonian
for a given set of numerical parameters:
def H_JaynesCummings(Delta, Theta, epsilon, g, namespace = ''):
# create Fock- and Atom local spaces
fock = local_space('fock', namespace = namespace)
tls = local_space('tls', namespace = namespace, basis = ('e', 'g'))
# create representations of a and sigma
a = Destroy(fock)
sigma = LocalSigma(tls, 'g', 'e')
H = (Delta * sigma.dag() * sigma # detuning from atomic resonance
+ Theta * a.dag() * a # detuning from cavity resonance
+ I * g * (sigma * a.dag() - sigma.dag() * a) # atom-mode coupling, I = sqrt(-1)
+ I * epsilon * (a - a.dag())) # external driving amplitude
return H
Here we have allowed for a variable namespace which would come in handy if we wanted to construct an overall model that features multiple Jaynes-Cummings-type subsystems.
By using the support for symbolic sympy
expressions as scalar pre-factors to operators, one can instantiate a Jaynes-Cummings Hamiltonian with symbolic parameters:
>>> Delta, Theta, epsilon, g = symbols('Delta, Theta, epsilon, g', real = True)
>>> H = H_JaynesCummings(Delta, Theta, epsilon, g)
>>> str(H)
'Delta Pi_e^[tls] + I*g ((a_fock)^* sigma_ge^[tls] - a_fock sigma_eg^[tls]) + I*epsilon ( - (a_fock)^* + a_fock) + Theta (a_fock)^* a_fock'
>>> H.space
ProductSpace(LocalSpace('fock', ''), LocalSpace('tls', ''))
or equivalently, represented in latex via H.tex()
this yields:
Operator products between commuting operators are automatically re-arranged such that they are ordered according to their Hilbert Space
>>> Create(2) * Create(1)
OperatorTimes(Create(1), Create(2))
There are quite a few built-in replacement rules, e.g., mode operators products are normally ordered:
>>> Destroy(1) * Create(1)
1 + Create(1) * Destroy(1)
Or for higher powers one can use the expand()
method:
>>> (Destroy(1) * Destroy(1) * Destroy(1) * Create(1) * Create(1) * Create(1)).expand()
(6 + Create(1) * Create(1) * Create(1) * Destroy(1) * Destroy(1) * Destroy(1) + 9 * Create(1) * Create(1) * Destroy(1) * Destroy(1) + 18 * Create(1) * Destroy(1))
The Circuit Algebra module¶
In their works on networks of open quantum systems [GoughJames08], [GoughJames09] Gough and James have introduced an algebraic method to derive the Quantum Markov model for a full network of cascaded quantum systems from the reduced Markov models of its constituents. A general system with an equal number \(n\) of input and output channels is described by the parameter triplet \(\left(\mathbf{S}, \mathbf{L}, H\right)\), where \(H\) is the effective internal Hamilton operator for the system, \(\mathbf{L} = (L_1, L_2, \dots, L_n)^T\) the coupling vector and \(\mathbf{S} = (S_{jk})_{j,k=1}^n\) is the scattering matrix (whose elements are themselves operators). An element \(L_k\) of the coupling vector is given by a system operator that describes the system’s coupling to the \(k\)-th input channel. Similarly, the elements \(S_{jk}\) of the scattering matrix are in general given by system operators describing the scattering between different field channels \(j\) and \(k\). The only conditions on the parameters are that the hamilton operator is self-adjoint and the scattering matrix is unitary:
We adhere to the conventions used by Gough and James, i.e. we write the imaginary unit is given by \(i := \sqrt{-1}\), the adjoint of an operator \(A\) is given by \(A^*\), the element-wise adjoint of an operator matrix \(\mathbf{M}\) is given by \(\mathbf{M}^\sharp\). Its transpose is given by \(\mathbf{M}^T\) and the combination of these two operations, i.e. the adjoint operator matrix is given by \(\mathbf{M}^\dagger = (\mathbf{M}^T)^\sharp = (\mathbf{M}^\sharp)^T\).
Fundamental Circuit Operations¶
The basic operations of the Gough-James circuit algebra are given by:

\(Q_1 \boxplus Q_2\)

\(Q_2 \lhd Q_1\)

\([Q]_{1 \to 4}\)
In [GoughJames09], Gough and James have introduced two operations that allow the construction of quantum optical ‘feedforward’ networks:
- The concatenation product describes the situation where two arbitrary systems are formally attached to each other without optical scattering between the two systems’ in- and output channels
\[\begin{split}\left(\mathbf{S}_1, \mathbf{L}_1, H_1\right) \boxplus \left(\mathbf{S}_2, \mathbf{L}_2, H_2\right) = \left(\begin{pmatrix} \mathbf{S}_1 & 0 \\ 0 & \mathbf{S}_2 \end{pmatrix}, \begin{pmatrix}\mathbf{L}_1 \\ \mathbf{L}_1 \end{pmatrix}, H_1 + H_2 \right)\end{split}\]Note however, that even without optical scattering, the two subsystems may interact directly via shared quantum degrees of freedom.
- The series product is to be used for two systems \(Q_j = \left(\mathbf{S}_j, \mathbf{L}_j, H_j \right)\), \(j=1,2\) of equal channel number \(n\) where all output channels of \(Q_1\) are fed into the corresponding input channels of \(Q_2\)
\[\left(\mathbf{S}_2, \mathbf{L}_2, H_2 \right) \lhd \left( \mathbf{S}_1, \mathbf{L}_1, H_1 \right) = \left(\mathbf{S}_2 \mathbf{S}_1,\mathbf{L}_2 + \mathbf{S}_2\mathbf{L}_1 , H_1 + H_2 + \Im\left\{\mathbf{L}_2^\dagger \mathbf{S}_2 \mathbf{L}_1\right\}\right)\]
From their definition it can be seen that the results of applying both the series product and the concatenation product not only yield valid circuit component triplets that obey the constraints, but they are also associative operations.footnote{For the concatenation product this is immediately clear, for the series product in can be quickly verified by computing \((Q_1 \lhd Q_2) \lhd Q_3\) and \(Q_1 \lhd (Q_2 \lhd Q_3)\). To make the network operations complete in the sense that it can also be applied for situations with optical feedback, an additional rule is required: The feedback operation describes the case where the \(k\)-th output channel of a system with \(n\ge 2\) is fed back into the \(l\)-th input channel. The result is a component with \(n-1\) channels:
where the effective parameters are given by [GoughJames08]
Here we have written \(\mathbf{S}_{\cancel{[k,l]}}\) as a shorthand notation for the matrix \(\mathbf{S}\) with the \(k\)-th row and \(l\)-th column removed and similarly \(\mathbf{L}_{\cancel{[k]}}\) is the vector \(\mathbf{L}\) with its \(k\)-th entry removed. Moreover, it can be shown that in the case of multiple feedback loops, the result is independent of the order in which the feedback operation is applied. Note however that some care has to be taken with the indices of the feedback channels when permuting the feedback operation.
The possibility of treating the quantum circuits algebraically offers some valuable insights: A given full-system triplet \((\mathbf{S}, \mathbf{L}, H )\) may very well allow for different ways of decomposing it algebraically into networks of physically realistic subsystems. The algebraic treatment thus establishes a notion of dynamic equivalence between potentially very different physical setups. Given a certain number of fundamental building blocks such as beamsplitters, phases and cavities, from which we construct complex networks, we can investigate what kinds of composite systems can be realized. If we also take into account the adiabatic limit theorems for QSDEs (cite Bouten2008a,Bouten2008) the set of physically realizable systems is further expanded. Hence, the algebraic methods not only facilitate the analysis of quantum circuits, but ultimately they may very well lead to an understanding of how to construct a general system \((\mathbf{S}, \mathbf{L}, H)\) from some set of elementary systems. There already exist some investigations along these lines for the particular subclass of linear systems (cite Nurdin2009a,Nurdin2009b) which can be thought of as a networked collection of quantum harmonic oscillators.
Representation as Python objects¶
This file features an implementation of the Gough-James circuit algebra rules as introduced in [GoughJames08] and [GoughJames09].
Python objects that are of the qnet.algebra.circuit_algebra.Circuit
type have some of their operators overloaded to realize symbolic circuit algebra operations:
>>> A = CircuitSymbol('A', 2)
>>> B = CircuitSymbol('B', 2)
>>> A << B
SeriesProduct(A, B)
>>> A + B
Concatenation(A, B)
>>> FB(A, 0, 1)
Feedback(A, 0, 1)
For a thorough treatment of the circuit expression simplification rules see Properties and Simplification of Circuit Algebraic Expressions.
Examples¶
Extending the JaynesCummings problem above to an open system by adding collapse operators \(L_1 = \sqrt{\kappa} a\) and \(L_2 = \sqrt{\gamma}\sigma.\)
def SLH_JaynesCummings(Delta, Theta, epsilon, g, kappa, gamma, namespace = ''):
# create Fock- and Atom local spaces
fock = local_space('fock', namespace = namespace)
tls = local_space('tls', namespace = namespace, basis = ('e', 'g'))
# create representations of a and sigma
a = Destroy(fock)
sigma = LocalSigma(tls, 'g', 'e')
# Trivial scattering matrix
S = identity_matrix(2)
# Collapse/Jump operators
L1 = sqrt(kappa) * a # Decay of cavity mode through mirror
L2 = sqrt(gamma) * sigma # Atomic decay due to spontaneous emission into outside modes.
L = Matrix([[L1], \
[L2]])
# Hamilton operator
H = (Delta * sigma.dag() * sigma # detuning from atomic resonance
+ Theta * a.dag() * a # detuning from cavity resonance
+ I * g * (sigma * a.dag() - sigma.dag() * a) # atom-mode coupling, I = sqrt(-1)
+ I * epsilon * (a - a.dag())) # external driving amplitude
return SLH(S, L, H)
Consider now an example where we feed one Jaynes-Cummings system’s output into a second one:
Delta, Theta, epsilon, g = symbols('Delta, Theta, epsilon, g', real = True)
kappa, gamma = symbols('kappa, gamma')
JC1 = SLH_JaynesCummings(Delta, Theta, epsilon, g, kappa, gamma, namespace = 'jc1')
JC2 = SLH_JaynesCummings(Delta, Theta, epsilon, g, kappa, gamma, namespace = 'jc2')
SYS = (JC2 + cid(1)) << P_sigma(0, 2, 1) << (JC1 + cid(1))
The resulting system’s block diagram is:

and its overall SLH model is given by:
The Super-Operator Algebra module¶
The specification of a quantum mechanics symbolic super-operator algebra. Each super-operator has an associated space property which gives the Hilbert space on which the operators the super-operator acts non-trivially are themselves acting non-trivially.
The most basic way to construct super-operators is by lifting ‘normal’ operators to linear pre- and post-multiplication super-operators:
>>> A, B, C = OperatorSymbol("A", FullSpace), OperatorSymbol("B", FullSpace), OperatorSymbol("C", FullSpace)
>>> SPre(A) * B
A * B
>>> SPost(C) * B
B * C
>>> (SPre(A) * SPost(C)) * B
A * B * C
>>> (SPre(A) - SPost(A)) * B # Linear super-operator associated with A that maps B --> [A,B]
A * B - B * A
There exist some useful constants to specify neutral elements of super-operator addition and multiplication:
ZeroSuperOperator
IdentitySuperOperator
Super operator objects can be added together in code via the infix ‘+’ operator and multiplied with the infix ‘*’ operator. They can also be added to or multiplied by scalar objects. In the first case, the scalar object is multiplied by the IdentitySuperOperator constant.
Super operators are applied to operators by multiplying an operator with superoperator from the left:
>>> S = SuperOperatorSymbol("S", FullSpace)
>>> A = OperatorSymbol("A", FullSpace)
>>> S * A
SuperOperatorTimesOperator(S, A)
>>> isinstance(S*A, Operator)
True
The result is an operator.
The State (Ket-) Algebra module¶
This module implements a basic Hilbert space state algebra where by default we represent states \(\psi\) as ‘Ket’ vectors \(\psi \to | \psi \rangle\). However, any state can also be represented in its adjoint Bra form, since those representations are dual:
States can be added to states of the same Hilbert space. They can be multiplied by:
- scalars, to just yield a rescaled state within the original space
- operators that act on some of the states degrees of freedom (but none that aren’t part of the state’s Hilbert space)
- other states that have a Hilbert space corresponding to a disjoint set of degrees of freedom
Furthermore,
- a
Ket
object can multiply aBra
of the same space from the left to yield aKetBra
type operator.
And conversely,
- a
Bra
can multiply aKet
from the left to create a (partial) inner product objectBraKet
. Currently, only full inner products are supported, i.e. theKet
andBra
operands need to have the same space.
Properties and Simplification of Circuit Algebraic Expressions¶
By observing that we can define for a general system \(Q = (\mat{S}, \mat{L}, H)\) its series inverse system \(Q^{\lhd -1} := (\mat{S}^\dagger, - \mat{S}^\dagger \mat{L}, - H)\)
we see that the series product induces a group structure on the set of \(n\)-channel circuit components for any \(n \ge 1\). It can easily be verified that the series inverse of the basic operations is calculated as follows
In the following, we denote the number of channels of any given system \(Q = (\mat{S}, \mat{L}, H)\) by \({\rm cdim}\;{Q} := n\). The most obvious expression simplification is the associative expansion of concatenations and series:
A further interesting property that follows intuitively from the graphical representation (cf.~Fig.~ref{fig:decomposition_law}) is the following tensor decomposition law
which is valid for \({\rm cdim}\;{A} = {\rm cdim}\;{C}\) and \({\rm cdim}\;{B} = {\rm cdim}\;{D}\).
The following figures demonstrate the ambiguity of the circuit algebra:
Here, a red box marks a series product and a blue box marks a concatenation. The second version expression has the advantage of making more explicit that the overall circuit consists of two channels without direct optical scattering.
It will most often be preferable to use the RHS expression of the tensor decomposition law above as this enables us to understand the flow of optical signals more easily from the algebraic expression. In [GoughJames09] Gough and James denote a system that can be expressed as a concatenation as reducible. A system that cannot be further decomposed into concatenated subsystems is accordingly called irreducible. As follows intuitively from a graphical representation any given complex system \(Q = (\mat{S}, \mat{L}, H)\) admits a decomposition into \(1 \le N \le {\rm cdim}\;{Q}\) irreducible subsystems \(Q = Q_1 \boxplus Q_2 \boxplus \dots \boxplus Q_N\), where their channel dimensions satisfy \({\rm cdim}\;{Q_j}\ge 1, \, j=1,2, \dots N\) and \(\sum_{j=1}^N {\rm cdim}\;{Q_j} = {\rm cdim}\;{Q}\). While their individual parameter triplets themselves are not uniquely determinedfootnote{Actually the scattering matrices \(\{\mat{S}_j\}\) and the coupling vectors \(\{\mat{L}_j\}\) are uniquely determined, but the Hamiltonian parameters \(\{H_j\}\) must only obey the constraint \(\sum_{j=1}^N H_j = H\).}, the sequence of their channel dimensions \(({\rm cdim}\;{Q_1}, {\rm cdim}\;{Q_2},\dots {\rm cdim}\;{Q_N}) =: {\rm bls}\;{Q}\) clearly is. We denote this tuple as the block structure of \(Q\). We are now able to generalize the decomposition law in the following way: Given two systems of \(n\) channels with the same block structure \({\rm bls}\;{A} = {\rm bls}\;{B} = (n_1, ... n_N)\), there exist decompositions of \(A\) and \(B\) such that
with \({\rm cdim}\;{A_j} = {\rm cdim}\;{B_j} = n_j,\, j = 1, \dots N\). However, even in the case that the two block structures are not equal, there may still exist non-trivial compatible block decompositions that at least allow a partial application of the decomposition law. Consider the example presented in Figure (block_structures).
Even in the case of a series between systems with unequal block structures, there often exists a non-trivial common block decomposition that simplifies the overall expression.
Permutation objects¶
The algebraic representation of complex circuits often requires systems that only permute channels without actual scattering. The group of permutation matrices is simply a subgroup of the unitary (operator) matrices. For any permutation matrix \(\mat{P}\), the system described by \((\mat{P},\mat{0},0)\) represents a pure permutation of the optical fields (ref fig permutation).

A graphical representation of \(\mat{P}_\sigma\) where \(\sigma \equiv (4,1,5,2,3)\) in image tuple notation.
A permutation \(\sigma\) of \(n\) elements (\(\sigma \in \Sigma_n\)) is often represented in the following form \(\begin{pmatrix} 1 & 2 & \dots & n \\ \sigma(1) & \sigma(2) & \dots & \sigma(n)\end{pmatrix}\), but obviously it is also sufficient to specify the tuple of images \((\sigma(1), \sigma(2), \dots, \sigma(n))\). We now define the permutation matrix via its matrix elements
Such a matrix then maps the \(j\)-th unit vector onto the \(\sigma(j)\)-th unit vector or equivalently the \(j\)-th incoming optical channel is mapped to the \(\sigma(j)\)-th outgoing channel. In contrast to a definition often found in mathematical literature this definition ensures that the representation matrix for a composition of permutations \(\sigma_2 \circ \sigma_1\) results from a product of the individual representation matrices in the same order \(\mat{P}_{\sigma_2 \circ \sigma_1} = \mat{P}_{\sigma_2} \mat{P}_{ \sigma_1}\). This can be shown directly on the order of the matrix elements
where the third equality corresponds simply to a reordering of the summands and the fifth equality follows from the bijectivity of \(\sigma_2\). In the following we will often write \(P_{\sigma}\) as a shorthand for \((\mat{P}_{\sigma}, \mat{0},0)\). Thus, our definition ensures that we may simplify any series of permutation systems in the most intuitive way: \(P_{\sigma_2} \lhd P_{\sigma_1} = P_{\sigma_2 \circ \sigma_1}\). Obviously the set of permutation systems of \(n\) channels and the series product are a subgroup of the full system series group of \(n\) channels. Specifically, it includes the identity \({\rm id}{n} = P_{\sigma_{{\rm id}_n}}\).
From the orthogonality of the representation matrices it directly follows that \(\mat{P}_{\sigma}^T = \mat{P}_{\sigma^{-1}}\) For future use we also define a concatenation between permutations
which satisfies \(P_{\sigma_1} \boxplus P_{\sigma_2} = P_{\sigma_1 \boxplus \sigma_2}\) by definition. Another helpful definition is to introduce a special set of permutations that map specific ports into each other but leave the relative order of all other ports intact:
We define the corresponding system objects as \(W_{l \gets k}^{(n)} := P_{\omega_{l \gets k}^{(n)}}\).
Permutations and Concatenations¶
Given a series \(P_{\sigma} \lhd (Q_1 \boxplus Q_2 \boxplus \dots \boxplus Q_N)\) where the \(Q_j\) are irreducible systems, we analyze in which cases it is possible to (partially) “move the permutation through” the concatenated expression. Obviously we could just as well investigate the opposite scenario \((Q_1 \boxplus Q_2 \boxplus \dots \boxplus Q_N) \lhd P_{\sigma}\), but this second scenario is closely relatedfootnote{Series-Inverting a series product expression also results in an inverted order of the operand inverses \((Q_1 \lhd Q_2)^{\lhd -1} = Q_2^{\lhd-1} \lhd Q_1^{\lhd-1}\). Since the inverse of a permutation (concatenation) is again a permutation (concatenation), the cases are in a way “dual” to each other.}.
Block-permuting permutations
The simples case is realized when the permutation simply permutes whole blocks intactly
A block permuting series.
Given a block structure \(\mat{n} := (n_1, n_2, \dots n_N)\) a permutation \(\sigma \in \Sigma_n\) is said to block permute \(\mat{n}\) iff there exists a permutation \(\tilde{\sigma} \in \Sigma_N\) such that
Hence, the permutation \(\sigma\), given in image tuple notation, block permutes \(\mat{n}\) iff for all \(1 \le j \le N\) and for all \(0 \le k < n_j\) we have \(\sigma(o_j + k) = \sigma(o_j) + k\), where we have introduced the block offsets \(o_j := 1 + \sum_{j' < j} n_j\). When these conditions are satisfied, \(\tilde{\sigma}\) may be obtained by demanding that \(\tilde{\sigma}(a) > \tilde{\sigma}(b) \Leftrightarrow \sigma(o_a) > \sigma(o_b)\). This equivalence reduces the computation of \(\tilde{\sigma}\) to sorting a list in a specific way.
Block-factorizing permutations
The next-to-simplest case is realized when a permutation \(\sigma\) can be decomposed \(\sigma = \sigma_{\rm b} \circ \sigma_{\rm i}\) into a permutation \(\sigma_{\rm b}\) that block permutes the block structure \(\mat{n}\) and an internal permutation \(\sigma_{\rm i}\) that only permutes within each block, i.e.~:math:sigma_{rm i} = sigma_1 boxplus sigma_2 boxplus dots boxplus sigma_N. In this case we can perform the following simplifications
We see that we have reduced the problem to the above discussed case. The result is now
In this case we say that \(\sigma\) block factorizes according to the block structure \(\mat{n}\). The following figure illustrates an example of this case.
A block factorizable series.
A permutation \(\sigma\) block factorizes according to the block structure \(\mat{n}\) iff for all \(1 \le j \le N\) we have \(\max_{0 \le k < n_j}\sigma(o_j + k) - \min_{0 \le k' < n_j}\sigma(o_j + k') = n_j - 1\), with the block offsets defined as above. In other words, the image of a single block is coherent in the sense that no other numbers from outside the block are mapped into the integer range spanned by the minimal and maximal points in the block’s image. The equivalence follows from our previous result and the bijectivity of \(\sigma\).
The general case
In general there exists no unique way how to split apart the action of a permutation on a block structure. However, it is possible to define a some rules that allow us to “move as much of the permutation” as possible to the RHS of the series. This involves the factorization \(\sigma = \sigma_{\rm x} \circ \sigma_{\rm b} \circ \sigma_{\rm i}\) defining a specific way of constructing both \(\sigma_{\rm b}\) and \(\sigma_{\rm i}\) from \(\sigma\). The remainder \(\sigma_{\rm x}\) can then be calculated through
Hence, by construction, \(\sigma_{\rm b} \circ \sigma_{\rm i}\) factorizes according to \(\mat{n}\) so only \(\sigma_{\rm x}\) remains on the exterior LHS of the expression.
So what then are the rules according to which we construct the block permuting \(\sigma_{\rm b}\) and the decomposable \(\sigma_{\rm i}\)? We wish to define \(\sigma_{\rm i}\) such that the remainder \(\sigma \circ \sigma_{\rm i}^{-1} = \sigma_{\rm x} \circ \sigma_{\rm b}\) does not cross any two signals that are emitted from the same block. Since by construction \(\sigma_{\rm b}\) only permutes full blocks anyway this means that \(\sigma_{\rm x}\) also does not cross any two signals emitted from the same block. This completely determines \(\sigma_{\rm i}\) and we can therefore calculate \(\sigma \circ \sigma_{\rm i}^{-1} = \sigma_{\rm x} \circ \sigma_{\rm b}\) as well. To construct \(\sigma_{\rm b}\) it is sufficient to define an total order relation on the blocks that only depends on the block structure \(\mat{n}\) and on \(\sigma \circ \sigma_{\rm i}^{-1}\). We define the order on the blocks such that they are ordered according to their minimal image point under \(\sigma\). Since \(\sigma \circ \sigma_{\rm i}^{-1}\) does not let any block-internal lines cross, we can thus order the blocks according to the order of the images of the first signal \(\sigma \circ \sigma_{\rm i}^{-1}(o_j)\). In (ref fig general_factorization) we have illustrated this with an example.
A general series with a non-factorizable permutation. In the intermediate step we have explicitly separated \(\sigma = \sigma_{\rm x} \circ \sigma_{\rm b} \circ \sigma_{\rm i}\).
Finally, it is a whole different question, why we would want move part of a permutation through the concatenated expression in this first place as the expressions usually appear to become more complicated rather than simpler. This is, because we are currently focussing only on single series products between two systems. In a realistic case we have many systems in series and among these there might be quite a few permutations. Here, it would seem advantageous to reduce the total number of permutations within the series by consolidating them where possible: \(P_{\sigma_2} \lhd P_{\sigma_1} = P_{\sigma_2 \circ \sigma_1}\). To do this, however, we need to try to move the permutations through the full series and collect them on one side (in our case the RHS) where they can be combined to a single permutation. Since it is not always possible to move a permutation through a concatenation (as we have seen above), it makes sense to at some point in the simplification process reverse the direction in which we move the permutations and instead collect them on the LHS. Together these two strategies achieve a near perfect permutation simplification.
Feedback of a concatenation¶
A feedback operation on a concatenation can always be simplified in one of two ways: If the outgoing and incoming feedback ports belong to the same irreducible subblock of the concatenation, then the feedback can be directly applied only to that single block. For an illustrative example see the figures below:
Reduction to feedback of subblock.
If, on the other, the outgoing feedback port is on a different subblock than the incoming, the resulting circuit actually does not contain any real feedback and we can find a way to reexpress it algebraically by means of a series product.
Reduction of feedback to series, first example
Reduction of feedback to series, second example
To discuss the case in full generality consider the feedback expression \([A \boxplus B]_{k \to l}\) with \({\rm cdim}\;{A} = n_A\) and \({\rm cdim}\;{B} = n_B\) and where \(A\) and \(B\) are not necessarily irreducible. There are four different cases to consider.
- \(k,l \le n_A\): In this case the simplified expression should be \([A]_{k \to l} \boxplus B\)
- \(k,l > n_A\): Similarly as before but now the feedback is restricted to the second operand \(A \boxplus [B]_{(k-n_A) \to (l-n_A)}\), cf. Fig. (ref fig fc_irr).
- \(k \le n_A < l\): This corresponds to a situation that is actually a series and can be re-expressed as \(({\rm id}{n_A - 1} \boxplus B) \lhd W_{(l-1) \gets k}^{(n)} \lhd (A + {\rm id}{n_B - 1})\), cf. Fig. (ref fig fc_re1).
- \(l \le n_A < k\): Again, this corresponds a series but with a reversed order compared to above \((A + {\rm id}{n_B - 1}) \lhd W_{l \gets (k-1)}^{(n)} \lhd ({\rm id}{n_A - 1} \boxplus B)\), cf. Fig. (ref fig fc_re2).
Feedback of a series¶
There are two important cases to consider for the kind of expression at either end of the series: A series starting or ending with a permutation system or a series starting or ending with a concatenation.
Reduction of series feedback with a concatenation at the RHS

\([A_3 \lhd P_\sigma]_{2 \to 1}\)

\([A_3]_{2 \to 3} \lhd P_{\tilde{\sigma}}\)
Reduction of series feedback with a permutation at the RHS
1) \([A \lhd (C \boxplus D)]_{k \to l}\): We define \(n_C = {\rm cdim}\;{C}\) and \(n_A = {\rm cdim}\;{A}\). Without too much loss of generality, let’s assume that \(l \le n_C\) (the other case is quite similar). We can then pull \(D\) out of the feedback loop: \([A \lhd (C \boxplus D)]_{k \to l} \longrightarrow [A \lhd (C \boxplus {\rm id}{n_D})]_{k \to l} \lhd ({\rm id}{n_C - 1} \boxplus D)\). Obviously, this operation only makes sense if \(D \neq {\rm id}{n_D}\). The case \(l>n_C\) is quite similar, except that we pull \(C\) out of the feedback. See Figure (ref fig fs_c) for an example.
- We now consider \([(C \boxplus D) \lhd E]_{k \to l}\) and we assume \(k \le n_C\) analogous to above. Provided that \(D \neq {\rm id}{n_D}\), we can pull it out of the feedback and get \(({\rm id}{n_C -1} \boxplus D) \lhd [(C \boxplus {\rm id}{n_D}) \lhd E]_{k \to l}\).
3) \([A \lhd P_\sigma]_{k \to l}\): The case of a permutation within a feedback loop is a lot more intuitive to understand graphically (e.g., cf. Figure ref fig fs_p). Here, however we give a thorough derivation of how a permutation can be reduced to one involving one less channel and moved outside of the feedback. First, consider the equality \([A \lhd W_{j \gets l}^{(n)}]_{k \to l} = [A]_{k \to j}\) which follows from the fact that \(W_{j \gets l}^{(n)}\) preserves the order of all incoming signals except the \(l\)-th. Now, rewrite
\[\begin{split}[A \lhd P_\sigma]_{k \to l} & = [A \lhd P_\sigma \lhd W_{l \gets n}^{(n)} \lhd W_{n \gets l}^{(n)}]_{k \to l} \\ & = [A \lhd P_\sigma \lhd W_{l \gets n}^{(n)} ]_{k \to n} \\ & = [A \lhd W_{\sigma(l) \gets n}^{(n)} \lhd (W_{n \gets \sigma(l)}^{(n)} \lhd P_\sigma \lhd W_{l \gets n}) ]_{k \to n}\end{split}\]Turning our attention to the bracketed expression within the feedback, we clearly see that it must be a permutation system \(P_{\sigma'} = W_{n \gets \sigma(l)}^{(n)} \lhd P_\sigma \lhd W_{l \gets n}^{(n)}\) that maps \(n \to l \to \sigma(l) \to n\). We can therefore write \(\sigma' = \tilde{\sigma} \boxplus \sigma_{{\rm id}_1}\) or equivalently \(P_{\sigma'} = P_{\tilde{\sigma}} \boxplus {\rm id}{1}\) But this means, that the series within the feedback ends with a concatenation and from our above rules we know how to handle this:
\[\begin{split}[A \lhd P_\sigma]_{k \to l} & = [A \lhd W_{\sigma(l) \gets n}^{(n)} \lhd (P_{\tilde{\sigma}} \boxplus {\rm id}{1})]_{k \to n} \\ & = [A \lhd W_{\sigma(l) \gets n}^{(n)}]_{k \to n} \lhd P_{\tilde{\sigma}} \\ & = [A]_{k \to \sigma(l)} \lhd P_{\tilde{\sigma}},\end{split}\]where we know that the reduced permutation is the well-defined restriction to \(n-1\) elements of \(\sigma' = \left(\omega_{n \gets \sigma{l}}^{(n)} \circ \sigma \circ \omega_{l \gets n}^{(n)}\right)\).
- The last case is analogous to the previous one and we will only state the results without a derivation:
\[[P_\sigma \lhd A]_{k \to l} & = P_{\tilde{\sigma}} \lhd [A]_{\sigma^{-1}(k) \to l},\]where the reduced permutation is given by the (again well-defined) restriction of \(\omega_{n \gets k}^{(n)} \circ \sigma \circ \omega_{\sigma^{-1}(k) \gets n}^{(n)}\) to \(n-1\) elements.
Circuit Component Definition¶
The best way to get started on defining one’s own circuit component definition is to look at the examples
provided in the component library qnet.circuit_components
.
Every circuit component object is a python class definition that derives off the class qnet.circuit_components.component.Component
.
The subclass must necessarily overwrite the following class attributes of this Component
class:
CDIM
needs to be set to the full number (int
) of input or output noises, i.e., the row dimension of the coupling vector \(\mathbf{L}\) or the scattering matrix \(\mathbf{S}\) of the corresponding \((\mathbf{S},\mathbf{L},H)\) model.
PORTSIN
needs to be set to a list of port labels for the relevant input ports of the component, i.e., those that could be connected to other components. The number of entries can be smaller or equal thanCDIM
.
PORTSOUT
needs to be set to a list of port labels for the relevant output ports of the component, i.e., those that could be connected to other components. The number of entries can be smaller or equal thanCDIM
.If your model depends on parameters you should specify this both via the
_params
attribute and by adding a class attribute with the name of the parameter and a default value that is either numeric or symbolic. Checkout some of the existing modules such asqnet.circuit_components.single_sided_opo_cc
to see how these parameters should be set.If your model has internal quantum degrees of freedom, you need to implement the
_space
property. If your model has a single quantum degree of freedom such as an empty cavity or an OPO, just follow the example ofqnet.circuit_components.single_sided_opo_cc
(click on ‘source’ to see the source-code). If your model’s space will be a tensor product of several degrees of freedom, follow the example ofqnet.circuit_components.single_sided_jaynes_cummings_cc
, which defines Hilbert space properties for the different degrees of freedom and has the_space
property return a tensor product of them.In general, it is important to properly assign a unique name and namespace to all internal degrees of freedom to rule out ambiguities when your final circuit includes more than one instance of your model.
Optionally, you may overwrite the
name
attribute to change the default name of your component.
Most importantly, the subclass must implement a _toSLH(self):
method.
Doing this requires some knowledge of how to use the operator algebra qnet.algebra.operator_algebra
.
For a component model with multiple input/output ports with no direct scattering between some ports,
i.e., the scattering matrix \(\mathbf{S}\) is (block-) diagonal
we allow for a formalism to define this substructure on the circuit-symbolic level by not just defining a component model,
but also models for the irreducible subblocks of your component.
This leads to two alternative ways of defining the circuit components:
Simple case, creating a symbolically irreducible circuit model, this is probably what you should go with:
This suffices if the purpose of defining the component is only to derive the final quantum equations of motion for an overall system, i.e., no analysis should be carried out on the level of the circuit algebra but only on the level of the underlying operator algebra of the full circuit’s \((\mathbf{S},\mathbf{L},H)\) model.
Subclassing the
Component
class takes care of implementing the class constructor__init__
and this should not be overwritten unless you are sure what you are doing. The pre-defined constructor takes care of handling the flexible specification of model parameters as well as the name and namespace via its arguments. I.e., for a model namedMyModel
whose_parameters
attribute is given by['kappa', 'gamma']
, one can either specify all or just some of the parameters as named arguments. The rest get replaced by the default values. Consider the following code examples:MyModel(name = "M") # -> MyModel(name = "M", namespace = "", kappa = MyModel.kappa, gamma = MyModel.gamma) MyModel(name = "M", kappa = 1) # -> MyModel(name = "M", namespace = "", kappa = 1, gamma = MyModel.gamma) MyModel(kappa = 1) # -> MyModel(name = MyModel.name, namespace = "", kappa = 1, gamma = MyModel.gamma)The model parameters passed to the constructor are subsequently accessible to the object’s methods as instance attributes. I.e., within the
_toSLH(self)
-method of the above example one would access the value of thekappa
parameter asself.kappa
.Complex case, create a symbolically reducible circuit model:
In this case you will need to define subcomponent model for each irreducible block of your model. We will not discuss this advanced method here, but instead refer to the following modules as examples:
A simple example¶
As an example we will now define a simple (symbolically irreducible) version of the single sided jaynes cummings model. The model is given by:
Then, we can define the corresponding component class as:
from sympy import symbols, I, sqrt
from qnet.algebra.circuit_algebra import Create, LocalSigma, SLH, Destroy, local_space, Matrix, identity_matrix
class SingleSidedJaynesCummings(Component):
CDIM = 2
name = "Q"
kappa = symbols('kappa', real = True) # decay of cavity mode through cavity mirror
gamma = symbols('gamma', real = True) # decay rate into transverse modes
g = symbols('g', real = True) # coupling between cavity mode and two-level-system
Delta_a = symbols('Delta_a', real = True) # detuning between the external driving field and the atom
Delta_f = symbols('Delta_f', real = True) # detuning between the external driving field and the cavity
FOCK_DIM = 20 # default truncated Fock-space dimension
_parameters = ['kappa', 'gamma', 'g', 'Delta_a', 'Delta_f', 'FOCK_DIM']
PORTSIN = ['In1', 'VacIn']
PORTSOUT = ['Out1', 'UOut']
@property
def fock_space(self):
"""The cavity mode's Hilbert space."""
return local_space("f", make_namespace_string(self.namespace, self.name), dimension = self.FOCK_DIM)
@property
def tls_space(self):
"""The two-level-atom's Hilbert space."""
return local_space("a", make_namespace_string(self.namespace, self.name), basis = ('h', 'g'))
@property
def _space(self):
return self.fock_space * self.tls_space
def _toSLH(self):
a = Destroy(self.fock_space)
sigma = LocalSigma(self.tls_space, 'g', 'h')
H = self.Delta_f * a.dag() * a + self.Delta_a * sigma.dag() * sigma \
+ I * self.g * (sigma.dag() * a - sigma * a.dag())
L1 = sqrt(self.kappa) * a
L2 = sqrt(self.gamma) * sigma
L = Matrix([[L1],
[L2]])
S = identity_matrix(2)
return SLH(S, L, H)
Creating custom component symbols for gschem
¶
Creating symbols in gschem is similar to the schematic capture process itself:
Using the different graphical objects (lines, boxes, arcs, text) create the symbol as you see fit.
Add pins for the symbols inputs and outputs. Define their
pintype
(in
orout
) and theirpinnumber
(which can be text or a number) according to the port names. Finally, define theirpinseq
attributes to match the order of the list in the python component definition, so for the above example, one would need 4 pins, two inputs, two outputs with the following properties:pintype=in, pinnumber=In1, pinseq=i1
pintype=in, pinnumber=VacIn, pinseq=i2
pintype=out, pinnumber=Out1, pinseq=o1
pintype=out, pinnumber=UOut, pinseq=o2
Define the parameters the model depends on, by adding a
params
attribute to the top level circuit. For the example above the correct param string would be:kappa:real;gamma:real;g:real;Delta_a:real;Delta_f:real;FOCK_DIM:int:20
Add the name of the component by setting the
device
top-level-attribute, in this example toSingleSidedJaynesCummings
Specify the default name by adding a
refdes
attribute that is equal to the default name plus an appended question mark (e.g.Q?
). When designing a circuit, this helps to quickly identify unnamed subcomponents.
The result could look something like this:
Schematic Capture¶
Here we explain how to create photonic circuits visually using gschem
From the ‘Add’ menu select ‘Component’ to open the component symbol library.
Layout components on the grid
Double-click the component symbols to edit the properties of each component instance. Be sure to set a unique instance identifier
refdes
-attribute.If a component symbol has an attribute named
params
, its value should be understood as a list of the form:param1_name:param1_type[:default_value1];param2_name:param2_type[:default_value2];...
where the default values are optional. To assign a value to a component param, add an attribute of the param name and set the value either to a corresponding numerical value or to a parameter name of the overall circuit.For all input and output ports of the circuit that are part of its external interface add dedicated input and output pad objects. Assign names to them (
refdes
-attribute) that correspond to their port names and assign sequence numbers to them, numbering the inputs asi1, i2, ...
and the outputs aso1, o2, ...
Draw all internal signals to connect component ports with each other and with port objects.
Add a
params
-attribute to the whole circuit specifying all model parameters similarly to above.Add a
module-name
-attribute to the whole circuit to specify its entity name. Please useCamelCaseConventions
for naming your circuit, because it will ultimately be the name of a Python class.
As an example, consider this screencast for creating a Pseudo-NAND-Latch.
Netlisting¶
Using gnetlist
¶
Given a well-formed gschem
circuit specification file we can use the gnetlist
tool
that comes with the gEDA
suite to export it to a QHDL-file.
Using the command-line, if the .sch
schematic file is located at the path my_dir/my_schematic.sch
,
and you wish to produce a QHDL file at the location my_other_dir/my_netlist.qhdl
, run the following command:
gnetlist -g qhdl my_dir/my_schematic.sch -o my_other_dir/my_netlist.qhdl
It is generally a very good idea to inspect the produced QHDL file code and verify that it looks like it
should before trying to compile it into a python circuit_component
library file.
The QHDL Syntax¶
A QHDL file consists of two basic parts:
An
entity
declaration, which should be thought of as defining the external interface of the specified circuit. I.e., it defines global input and output ports as well as parameters for the overall model.A corresponding
architecture
declaration, that, in turn consists of two parts:
The architecture head defines what types of components can appear in the circuit. I.e., for each
component
declaration in the architecture head, there can exist multiple instances of that component type in the circuit. The head also defines the internalsignal
lines of the circuit.The architecture body declares what instances of which component type exists in the circuit, how its ports are mapped to the internal signals or entity ports, and how its internal parameters relate to the entity parameters. In QHDL, each signal may only connect exactly two ports, where one of three cases is true:
- It connects an entity input with a component instance input
- It connects an entity output with a component instance output
- It connects a component output with a component input
Before showing some examples of QHDL files, we present the general QHDL syntax in somewhat abstract form.
Here, square brackets [optional]
denote optional keywords/syntax and the ellipses ...
denote repetition:
-- this is a comment
-- entity definition
-- this serves as the external interface to the circuit, specifying inputs and outputs
-- as well as parameters of the model
entity my_entity is
[generic ( var1: generic_type [:= default_var1]] [; var2: generic_type [...] ...]);]
port (i_1,i_2,...i_n:in fieldmode; o_1,o_2,...o_n:out fieldmode);
end entity my_entity;
-- architecture definition
-- this is the actual implementation of the entity in terms of subcomponents
architecture my_architecture of my_entity is
-- architecture head
-- each type of subcomponent, i.e. its ports and its parameters are defined here similarly
-- to the entity definition above
component my_component
[generic ( var3: generic_type [:= default_var3]] [; var4: generic_type [...] ...]);]
port (p1,p2,...pm:in fieldmode; q1,q2,...qm:out fieldmode);
end component my_component;
[component my_second_component
[generic ( var5: generic_type [:= default_var5]] [; var6: generic_type [...] ...]);]
port (p1,p2,...pr:in fieldmode; q1,q2,...qr:out fieldmode);
end component my_second_component;
...
]
-- internal signals to connect component instances
[signal s_1,s_2,s_3,...s_m fieldmode;]
begin
-- architecture body
-- here the actual component instances are defined and their ports are mapped to signals
-- or to global (i.e. entity-) ports
-- furthermore, global (entity-) parameters are mapped to component instance parameters.
COMPONENT_INSTANCE_ID1: my_component
[generic map(var1 => var3, var1 => var4);]
port map (i_1, i_2, ... i_m, s_1, s_2, ...s_m);
[COMPONENT_INSTANCE_ID2: my_component
[generic map(var1 => var3, var1 => var4);]
port map (s_1, s_2, ... s_m, o_1, o_2, ...o_m);
COMPONENT_INSTANCE_ID3: my_second_component
[generic map (...);]
port map (...);
...
]
end architecture my_architecture;
where generic_type
is one of int
, real
, or complex
.
QHDL-Example files:¶
A Mach-Zehnder-circuit¶
This toy-circuit realizes a Mach-Zehnder interferometer.
-- Structural QHDL generated by gnetlist
-- Entity declaration
ENTITY MachZehnder IS
GENERIC (
alpha : complex;
phi : real);
PORT (
a : in fieldmode;
b : in fieldmode;
c : out fieldmode;
d : out fieldmode);
END MachZehnder;
-- Secondary unit
ARCHITECTURE netlist OF MachZehnder IS
COMPONENT Phase
GENERIC (
phi : real);
PORT (
In1 : in fieldmode;
Out1 : out fieldmode);
END COMPONENT ;
COMPONENT Beamsplitter
GENERIC (
theta : real := 0.7853981633974483);
PORT (
In1 : in fieldmode;
In2 : in fieldmode;
Out1 : out fieldmode;
Out2 : out fieldmode);
END COMPONENT ;
COMPONENT Displace
GENERIC (
alpha : complex);
PORT (
VIn : in fieldmode;
Out1 : out fieldmode);
END COMPONENT ;
SIGNAL B12B2 : fieldmode;
SIGNAL W2B1 : fieldmode;
SIGNAL P2B2 : fieldmode;
SIGNAL B12P : fieldmode;
SIGNAL unnamed_net4 : fieldmode;
SIGNAL unnamed_net3 : fieldmode;
SIGNAL unnamed_net2 : fieldmode;
SIGNAL unnamed_net1 : fieldmode;
BEGIN
-- Architecture statement part
W : Displace
GENERIC MAP (
alpha => alpha);
PORT MAP (
VIn => unnamed_net1,
Out1 => W2B1);
B2 : Beamsplitter
PORT MAP (
In1 => P2B2,
In2 => B12B2,
Out1 => unnamed_net4,
Out2 => unnamed_net3);
B1 : Beamsplitter
PORT MAP (
In1 => W2B1,
In2 => unnamed_net2,
Out1 => B12B2,
Out2 => B12P);
P : Phase
GENERIC MAP (
phi => phi);
PORT MAP (
In1 => B12P,
Out1 => P2B2);
-- Signal assignment part
unnamed_net2 <= b;
unnamed_net1 <= a;
d <= unnamed_net4;
c <= unnamed_net3;
END netlist;
A Pseudo-NAND-gate¶
This circuit consists of a Kerr-nonlinear cavity, a few beamsplitters and a bias input amplitude to realize a NAND-gate for the inputs A and B. For details see [Mabuchi11].
-- Structural QHDL generated by gnetlist
-- Entity declaration
ENTITY PseudoNAND IS
GENERIC (
Delta : real;
chi : real;
kappa : real;
phi : real;
theta : real;
beta : complex);
PORT (
A : in fieldmode;
B : in fieldmode;
VIn1 : in fieldmode;
VIn2 : in fieldmode;
UOut1 : out fieldmode;
UOut2 : out fieldmode;
NAND_AB : out fieldmode;
OUT2 : out fieldmode);
END PseudoNAND;
-- Secondary unit
ARCHITECTURE netlist OF PseudoNAND IS
COMPONENT KerrCavity
GENERIC (
Delta : real;
chi : real;
kappa_1 : real;
kappa_2 : real);
PORT (
In1 : in fieldmode;
In2 : in fieldmode;
Out1 : out fieldmode;
Out2 : out fieldmode);
END COMPONENT ;
COMPONENT Phase
GENERIC (
phi : real);
PORT (
In1 : in fieldmode;
Out1 : out fieldmode);
END COMPONENT ;
COMPONENT Beamsplitter
GENERIC (
theta : real := 0.7853981633974483);
PORT (
In1 : in fieldmode;
In2 : in fieldmode;
Out1 : out fieldmode;
Out2 : out fieldmode);
END COMPONENT ;
COMPONENT Displace
GENERIC (
alpha : complex);
PORT (
VacIn : in fieldmode;
Out1 : out fieldmode);
END COMPONENT ;
SIGNAL unnamed_net11 : fieldmode;
SIGNAL unnamed_net10 : fieldmode;
SIGNAL unnamed_net9 : fieldmode;
SIGNAL unnamed_net8 : fieldmode;
SIGNAL unnamed_net7 : fieldmode;
SIGNAL unnamed_net6 : fieldmode;
SIGNAL unnamed_net5 : fieldmode;
SIGNAL unnamed_net4 : fieldmode;
SIGNAL unnamed_net3 : fieldmode;
SIGNAL unnamed_net2 : fieldmode;
SIGNAL unnamed_net1 : fieldmode;
SIGNAL w : fieldmode;
BEGIN
-- Architecture statement part
W_beta : Displace
GENERIC MAP (
alpha => beta);
PORT MAP (
VacIn => unnamed_net6,
Out1 => unnamed_net11);
BS2 : Beamsplitter
GENERIC MAP (
theta => theta);
PORT MAP (
In1 => unnamed_net11,
In2 => unnamed_net3,
Out1 => unnamed_net10,
Out2 => unnamed_net8);
BS1 : Beamsplitter
PORT MAP (
In1 => unnamed_net4,
In2 => unnamed_net5,
Out1 => unnamed_net7,
Out2 => w);
P : Phase
GENERIC MAP (
phi => phi);
PORT MAP (
In1 => unnamed_net10,
Out1 => unnamed_net9);
K : KerrCavity
GENERIC MAP (
Delta => Delta,
chi => chi,
kappa_1 => kappa,
kappa_2 => kappa);
PORT MAP (
In1 => w,
Out1 => unnamed_net1,
In2 => unnamed_net2,
Out2 => unnamed_net3);
-- Signal assignment part
unnamed_net6 <= VIn1;
unnamed_net2 <= VIn2;
unnamed_net5 <= B;
unnamed_net4 <= A;
NAND_AB <= unnamed_net9;
OUT2 <= unnamed_net8;
UOut2 <= unnamed_net1;
UOut1 <= unnamed_net7;
END netlist;
A Pseudo-NAND-Latch¶
This circuit consists of two subcomponents that each act almost (i.e., for all relevant input conditions) like a NAND logic gate in a symmetric feedback conditions. As is known from electrical circuits this arrangement allows the fabrication of a bi-stable system with memory or state from two systems that have a one-to-one input output behavior. See also [Mabuchi11]
--pseudo-NAND latch with explicit parameter dependence
entity PseudoNANDLatch is
generic (Delta, chi, kappa, phi, theta : real;
beta : complex);
port (NS, W1, kerr2_extra, NR, W2, kerr1_extra : in fieldmode;
BS1_1_out, kerr1_out2, OUT2_2, BS1_2_out, kerr2_out2, OUT2_1 : out fieldmode);
end PseudoNANDLatch;
architecture latch_netlist of PseudoNANDLatch is
component PseudoNAND
generic (Delta, chi, kappa, phi, theta : real;
beta : complex);
port (A, B, W_in, kerr_in2 : in fieldmode;
uo1, kerr_out1, NAND_AB, OUT2 : out fieldmode);
end component;
signal FB12, FB21 : fieldmode; -- feedback signals
begin
NAND2 : PseudoNAND
generic map (
Delta => Delta, chi => chi, kappa => kappa, phi => phi, theta => theta, beta => beta);
port map (
A => NR, B => FB12, W_in => W2, kerr_in2 => kerr2_extra,
uo1 => BS1_2_out, kerr_out1 => kerr2_out2, NAND_AB => FB21, OUT2 => OUT2_2);
NAND1 : PseudoNAND
generic map (
Delta => Delta, chi => chi, kappa => kappa, phi => phi, theta => theta, beta => beta);
port map (
A => NS, B => FB21, W_in => W1, kerr_in2 => kerr1_extra,
uo1 => BS1_1_out, kerr_out1 => kerr1_out2, NAND_AB => FB12, OUT2 => OUT2_1);
end latch_netlist;
Parsing QHDL¶
Given a QHDL-file my_circuit.qhdl
which contains an entity named MyEntity
(Note again the CamelCaseConvention for entity names!), we have two options for the final python circuit model file:
We can compile it to an output in the local directory. To do this run in the shell:
$QNET/bin/parse_qhdl.py -f my_circuit.qhdl -lWe can compile it and install it within the module
qnet.circuit_components
. To do this run in the shell:$QNET/bin/parse_qhdl.py -f my_circuit.qhdl -L
In either case the output file will be named based on a CamelCase to lower_case_with_underscore convention with a _cc
suffix to the name.
I.e., for the above example MyEntity
will become my_entity_cc.py
.
In the case of entity names with multiple subsequent capital letters such as PseudoNAND
the convention is to only add underlines before the first and the last of the capitalized group,
i.e. the output would be written to pseudo_nand_cc.py
.
Symbolic Analysis and Simulation¶
Symbolic Analysis of the Pseudo NAND gate and the Pseudo NAND SR-Latch¶
Pseudo NAND gate¶
In[1]:
from qnet.algebra.circuit_algebra import *
In[2]:
from qnet.circuit_components import pseudo_nand_cc as nand
# real parameters
kappa = symbols('kappa', positive = True)
Delta, chi, phi, theta = symbols('Delta, chi, phi, theta', real = True)
# complex parameters
A, B, beta = symbols('A, B, beta')
N = nand.PseudoNAND('N', kappa=kappa, Delta=Delta, chi=chi, phi=phi, theta=theta, beta=beta)
N
Out[2]:
Circuit Analysis of Pseudo NAND gate¶
In[3]:
N.creduce()
Out[3]:
In[4]:
# yields a single block
N.show()
# decompose into sub components
N.creduce().show()


SLH model¶
In[5]:
NSLH = N.coherent_input(A, B, 0, 0).toSLH()
NSLH
Out[5]:
Heisenberg equation of motion of the mode operator \(a\)¶
In[6]:
s = N.space
a = Destroy(s)
a
Out[6]:
In[7]:
NSLH.symbolic_heisenberg_eom(a).expand().simplify_scalar()
Out[7]:
Super operator algebra: The system’s liouvillian and a re-derivation of the eom for \(a\) via the super-operator adjoint of the liouvillian.¶
In[8]:
LLN = NSLH.symbolic_liouvillian().expand().simplify_scalar()
LLN
Out[8]:
In[9]:
(LLN.superadjoint() * a).expand().simplify_scalar()
Out[9]:
A full Pseudo-NAND SR-Latch¶
In[10]:
N1 = nand.PseudoNAND('N_1', kappa=kappa, Delta=Delta, chi=chi, phi=phi, theta=theta, beta=beta)
N2 = nand.PseudoNAND('N_2', kappa=kappa, Delta=Delta, chi=chi, phi=phi, theta=theta, beta=beta)
# NAND gates in mutual feedback configuration
NL = (N1 + N2).feedback(2, 4).feedback(5, 0).coherent_input(A, 0, 0, B, 0, 0)
NL
Out[10]:
The circuit algebra simplification rules have already eliminated one of the two feedback operations in favor or a series product.
In[11]:
NL.show()
NL.creduce().show()
NL.creduce().creduce().show()



SLH model¶
In[12]:
NLSLH = NL.toSLH().expand().simplify_scalar()
NLSLH
Out[12]:
Heisenberg equations of motion for the mode operators¶
In[13]:
NL.space
Out[13]:
In[14]:
s1, s2 = NL.space.operands
a1 = Destroy(s1)
a2 = Destroy(s2)
In[15]:
da1dt = NLSLH.symbolic_heisenberg_eom(a1).expand().simplify_scalar()
da1dt
Out[15]:
In[16]:
da2dt = NLSLH.symbolic_heisenberg_eom(a2).expand().simplify_scalar()
da2dt
Out[16]:
Show Exchange-Symmetry of the Pseudo NAND latch Liouvillian super operator¶
Simultaneously exchanging the degrees of freedom and the coherent input amplitudes leaves the liouvillian unchanged.
In[17]:
C = symbols('C')
LLNL = NLSLH.symbolic_liouvillian().expand().simplify_scalar()
LLNL
Out[17]:
In[18]:
C = symbols('C')
(LLNL.substitute({A:C}).substitute({B:A}).substitute({C:B}) - LLNL.substitute({s1:s2,s2:s1}).expand().simplify_scalar()).expand().simplify_scalar()
Out[18]:
Numerical Analysis via QuTiP¶
Input-Output Logic of the Pseudo-NAND Gate¶
In[19]:
NSLH.space
Out[19]:
In[20]:
NSLH.space.dimension = 75
Numerical parameters taken from
Mabuchi, H. (2011). Nonlinear interferometry approach to photonic sequential logic. Appl. Phys. Lett. 99, 153103 (2011)
In[21]:
# numerical values for simulation
alpha = 22.6274 # logical 'one' amplitude
numerical_vals = {
beta: -34.289-11.909j, # bias input for pseudo-nands
kappa: 25., # Kerr-Cavity mirror couplings
Delta: 50., # Kerr-Cavity Detuning
chi : -50./60., # Kerr-Non-Linear coupling coefficient
theta: 0.891, # pseudo-nand beamsplitter mixing angle
phi: 2.546, # pseudo-nand corrective phase
}
In[22]:
NSLHN = NSLH.substitute(numerical_vals)
NSLHN
Out[22]:
In[23]:
input_configs = [
(0,0),
(1, 0),
(0, 1),
(1, 1)
]
In[24]:
Lout = NSLHN.L[2,0]
Loutqt = Lout.to_qutip()
times = arange(0, 1., 0.01)
psi0 = qutip.basis(N.space.dimension, 0)
datasets = {}
for ic in input_configs:
H, Ls = NSLHN.substitute({A: ic[0]*alpha, B: ic[1]*alpha}).HL_to_qutip()
data = qutip.mcsolve(H, psi0, times, Ls, [Loutqt], ntraj = 1)
datasets[ic] = data.expect[0]
100.0% (1/1) Est. time remaining: 00:00:00:00
100.0% (1/1) Est. time remaining: 00:00:00:00
100.0% (1/1) Est. time remaining: 00:00:00:00
100.0% (1/1) Est. time remaining: 00:00:00:00
In[25]:
figure(figsize=(10, 8))
for ic in input_configs:
plot(times, real(datasets[ic])/alpha, '-', label = str(ic) + ", real")
plot(times, imag(datasets[ic])/alpha, '--', label = str(ic) + ", imag")
legend()
xlabel('Time $t$', size = 20)
ylabel(r'$\langle L_out \rangle$ in logic level units', size = 20)
title('Pseudo NAND logic, stochastically simulated time \n dependent output amplitudes for different inputs.', size = 20)
Out[25]:
<matplotlib.text.Text at 0x1100b7dd0>

Pseudo NAND latch memory effect¶
In[26]:
NLSLH.space
Out[26]:
In[27]:
s1, s2 = NLSLH.space.operands
s1.dimension = 75
s2.dimension = 75
NLSLH.space.dimension
Out[27]:
5625
In[28]:
NLSLHN = NLSLH.substitute(numerical_vals)
NLSLHN
Out[28]:
In[29]:
input_configs = {
"SET": (1, 0),
"RESET": (0, 1),
"HOLD": (1, 1)
}
models = {k: NLSLHN.substitute({A:v[0]*alpha, B:v[1]*alpha}).HL_to_qutip() for k, v in input_configs.items()}
In[30]:
a1, a2 = Destroy(s1), Destroy(s2)
observables = [a1.dag()*a1, a2.dag()*a2]
observables_qt = [o.to_qutip(full_space = NLSLH.space) for o in observables]
In[31]:
def model_sequence_single_trajectory(models, durations, initial_state, dt):
"""
Solve a sequence of constant QuTiP open system models (H_i, [L_1_i, L_2_i, ...])
via Quantum Monte-Carlo. Each model is valid for a duration deltaT_i and the initial state for
is given by the previous model's final state.
The function returns an array with the times and an array with the states at each time.
:param models: Sequence of models given as tuples: (H_j, [L1j,L2j,...])
:type models: Sequence of tuples
:param durations: Sequence of times
:type durations: Sequence of float
:param initial_state: Overall initial state
:type initial_state: qutip.Qobj
:param dt: Sampling interval
:type dt: float
:return: times, states
:rtype: tuple((numpy.ndarray, numpy.ndarray)
"""
totalT = 0
totalTimes = array([])
totalStates = array([])
current_state = initial_state
for j, (model, deltaT) in enumerate(zip(models, durations)):
print "Solving step {}/{} of model sequence".format(j + 1, len(models))
HQobj, LQObjs = model
times = arange(0, deltaT, dt)
data = qutip.mcsolve(HQobj, current_state, times, LQObjs, [], ntraj = 1, options = qutip.Odeoptions(gui = False))
# concatenate states
totalStates = np.hstack((totalStates,data.states.flatten()))
current_state = data.states.flatten()[-1]
# concatenate times
totalTimes = np.hstack((totalTimes, times + totalT))
totalT += times[-1]
return totalTimes, totalStates
In[32]:
durations = [.5, 1., .5, 1.]
model_sequence = [models[v] for v in ['SET', 'HOLD', 'RESET', 'HOLD']]
initial_state = qutip.tensor(qutip.basis(s1.dimension, 0), qutip.basis(s2.dimension, 0))
In[33]:
times, data = model_sequence_single_trajectory(model_sequence, durations, initial_state, 5e-3)
Solving step 1/4 of model sequence
100.0% (1/1) Est. time remaining: 00:00:00:00
Solving step 2/4 of model sequence
100.0% (1/1) Est. time remaining: 00:00:00:00
Solving step 3/4 of model sequence
100.0% (1/1) Est. time remaining: 00:00:00:00
Solving step 4/4 of model sequence
100.0% (1/1) Est. time remaining: 00:00:00:00
In[34]:
datan1 = qutip.expect(observables_qt[0], data)
datan2 = qutip.expect(observables_qt[1], data)
In[36]:
figsize(10,6)
plot(times, datan1)
plot(times, datan2)
for t in cumsum(durations):
axvline(t, color = "r")
xlabel("Time $t$", size = 20)
ylabel("Intra-cavity Photon Numbers", size = 20)
legend((r"$\langle n_1 \rangle :math:`", r"`\langle n_2 \rangle $"), loc = 'lower right')
title("SET - HOLD - RESET - HOLD sequence for $\overline{SR}$-latch", size = 20)
Out[36]:
<matplotlib.text.Text at 0x1121d8990>

References¶
[GoughJames08] | Gough & James (2008). Quantum Feedback Networks: Hamiltonian Formulation. Communications in Mathematical Physics, 287(3), 1109-1132. doi:10.1007/s00220-008-0698-8 |
[GoughJames09] | 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 |
[QHDL] | Tezak, N., Niederberger, A., Pavlichin, D. S., Sarma, G., & Mabuchi, H. (2012). Specification of photonic circuits using quantum hardware description language. Philosophical transactions A, 370(1979), 5270–90. doi:10.1098/rsta.2011.0526 |
[Mabuchi11] | Mabuchi, H. (2011). Nonlinear interferometry approach to photonic sequential logic. Appl. Phys. Lett. 99, 153103 (2011), doi:10.1063/1.3650250 |
API¶
qnet package¶
The qnet
package exposes all of QNET’s functionality for easy
interactive or programmative use.
Specifically, the subpackages for the following parts of QNET are directly available:
- Symbolic quantum and circuit algebra as
qnet.algebra
- Printers for symbolic symbolic expressions as
qnet.printing
- A library of circuit components as
qnet.cc
(as a shorthand for thecircuit_components
subpackage)- Conversion utilities to Sympy and Numpy as
qnet.convert
- Parsing utilities for the QHDL language, as
qnet.qhdl
- Miscellaneous additional tools, as
qnet.misc
For interactive usage, the package should be initialized as follows:
>>> import qnet
>>> qnet.init_printing()
Note that most subpackages in turn expose their functionality through a “flat” API. That is, instead of
from qnet.algebra.operator_algebra import LocalOperator
from qnet.circuit_components.displace_cc import Displace
the two objects may be more succintly imported from a higher level namespace as
import qnet # required for qnet.cc to work
from qnet.algebra import LocalOperator
from qnet.cc import Displace
In an interactive context (and only there!), a star import such as
from qnet.algebra import *
may be useful.
The flat API is defined via the __all__ attribute of each subpackage (see each package’s documentation).
Internally, the flat API (or star imports) must never be used.
Subpackages:
qnet.algebra package¶
Submodules:
qnet.algebra.abstract_algebra module¶
- The abstract algebra package provides a basic interface
- for defining custom Algebras.
See The Abstract Algebra module for design details and usage.
Summary¶
Exceptions:
AlgebraError |
Base class for all errors concerning the mathematical definitions and rules of an algebra. |
AlgebraException |
Base class for all errors concerning the mathematical definitions and rules of an algebra. |
CannotSimplify |
Raised when an expression cannot be further simplified |
WrongSignatureError |
Raised when an operation is instantiated with operands of the wrong signature. |
Classes:
Expression |
Abstract class for QNET Expressions. |
Operation |
Base class for all “operations”, i.e. |
Functions:
all_symbols |
Return all all_symbols featured within an expression. |
assoc |
Associatively expand out nested arguments of the flat class. |
cache_attr |
A method decorator that caches the result of a method in an attribute, intended for e.g. |
check_idempotent_create |
Check that an expression is ‘idempotent’ |
extra_binary_rules |
Context manager that temporarily adds the given rules to cls (to be processed by match_replace_binary. |
extra_rules |
Context manager that temporarily adds the given rules to cls (to be processed by match_replace. |
filter_neutral |
Remove occurrences of a neutral element from the argument/operand list, if that list has at least two elements. |
idem |
Remove duplicate arguments and order them via the cls’s order_key key object/function. |
match_replace |
Match and replace a full operand specification to a function that provides a replacement for the whole expression or raises a CannotSimplify exception. |
match_replace_binary |
Similar to func:match_replace, but for arbitrary length operations, such that each two pairs of subsequent operands are matched pairwise. |
no_instance_caching |
Temporarily disable the caching of instances through |
no_rules |
Context manager that temporarily disables all rules (processed by match_replace or match_replace_binary) for the given cls. |
orderby |
Re-order arguments via the class’s order_key key object/function. |
set_union |
Similar to sum() , but for sets. |
simplify |
Recursively re-instantiate the expression, while applying all of the |
substitute |
Substitute symbols or (sub-)expressions with the given replacements and |
temporary_instance_cache |
Use a temporary cache for instances obtained from the create method of the given cls. |
__all__
: AlgebraError
, AlgebraException
, CannotSimplify
, Expression
, Operation
, SCALAR_TYPES
, WrongSignatureError
, all_symbols
, extra_binary_rules
, extra_rules
, no_instance_caching
, no_rules
, set_union
, simplify
, substitute
, temporary_instance_cache
Reference¶
-
exception
qnet.algebra.abstract_algebra.
AlgebraException
[source]¶ Bases:
Exception
Base class for all errors concerning the mathematical definitions and rules of an algebra.
-
exception
qnet.algebra.abstract_algebra.
AlgebraError
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraException
Base class for all errors concerning the mathematical definitions and rules of an algebra.
-
exception
qnet.algebra.abstract_algebra.
CannotSimplify
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraException
Raised when an expression cannot be further simplified
-
exception
qnet.algebra.abstract_algebra.
WrongSignatureError
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraError
Raised when an operation is instantiated with operands of the wrong signature.
-
qnet.algebra.abstract_algebra.
cache_attr
(attr)[source]¶ A method decorator that caches the result of a method in an attribute, intended for e.g. __str__
>>> class MyClass(): ... def __init__(self): ... self._str = None ... ... @cache_attr('_str') ... def __str__(self): ... return "MyClass" >>> a = MyClass() >>> a._str # None >>> str(a) 'MyClass' >>> a._str 'MyClass'
-
class
qnet.algebra.abstract_algebra.
Expression
(*args, **kwargs)[source]¶ Bases:
object
Abstract class for QNET Expressions. All algebraic objects are either scalars (numbers or Sympy expressions) or instances of Expression.
Expressions should generally be instantiated using the create class method, which takes into account the algebraic properties of the Expression and and applies simplifications. It also uses memoization to cache all known (sub-)expression. This is possible because expressions are intended to be immutable. Any changes to an expression should be made through e.g.
substitute()
, which returns a new modified expression.Every expression has a well-defined list of positional and keyword arguments that uniquely determine the expression and that may be accessed through the args and kwargs property. That is,
expr.__class__(*expr.args, **expr.kwargs)
will return and object identical to expr.
Class Attributes: instance_caching (bool) – Flag to indicate whether the create class method should cache the instantiation of instances -
instance_caching
= True¶
-
classmethod
create
(*args, **kwargs)[source]¶ Instead of directly instantiating, it is recommended to use create, which applies simplifications to the args and keyword arguments according to the _simplifications class attribute, and returns an appropriate object (which may or may not be an instance of the original class)
-
args
¶ The tuple of positional arguments for the instantiation of the Expression
-
kwargs
¶ The dictionary of keyword-only arguments for the instantiation of the Expression
-
minimal_kwargs
¶ A “minimal” dictionary of keyword-only arguments, i.e. a subsect of kwargs that may exclude default options
-
substitute
(var_map)[source]¶ Substitute all_symbols for other expressions.
Parameters: var_map (dict) – Dictionary with entries of the form {expr: substitution}
-
simplify
(rules=None)[source]¶ Recursively re-instantiate the expression, while applying all of the given rules to all encountered (sub-) expressions
-
-
qnet.algebra.abstract_algebra.
check_idempotent_create
(expr)[source]¶ Check that an expression is ‘idempotent’
-
qnet.algebra.abstract_algebra.
substitute
(expr, var_map)[source]¶ Substitute symbols or (sub-)expressions with the given replacements and re-evalute the result
Parameters: - expr – The expression in which to perform the substitution
- var_map (dict) – The substitution dictionary.
-
qnet.algebra.abstract_algebra.
simplify
(expr, rules=None)[source]¶ Recursively re-instantiate the expression, while applying all of the given rules to all encountered (sub-) expressions
Parameters: - expr – Any Expression or scalar object
- rules (list) – A list of tuples
(pattern, replacement)
where rule is an instance ofPattern
) and replacement is a callable. The pattern will be matched against any expression that is encountered during the re-instantiation. If the pattern matches, then the (sub-)expression is replaced by the result of calling replacement while passing any wildcards from pattern as keyword arguments. If replacement raises CannotSimplify, it will be ignored
Note
Instead of or in addition to passing rules, simplify can often be combined with e.g. extra_rules / extra_binary_rules context managers. If a simplification can be handled through these context managers, this is usually more efficient than an equivalent rule. However, both really are complemetary: the rules defined in the context managers are applied before instantation (hence these these patterns are instantiated through pattern_head). In contrast, the patterns defined in rules are applied against instantiated expressions.
-
qnet.algebra.abstract_algebra.
set_union
(*sets)[source]¶ Similar to
sum()
, but for sets. Generate the union of an arbitrary number of set arguments.
-
qnet.algebra.abstract_algebra.
all_symbols
(expr)[source]¶ Return all all_symbols featured within an expression.
-
class
qnet.algebra.abstract_algebra.
Operation
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.abstract_algebra.Expression
Base class for all “operations”, i.e. Expressions that act algebraically on other expressions (their “operands”).
Operations differ from more general Expressions by the convention that the arguments of the Operator are exactly the operands (which must be members of the algebra!) Any other parameters (non-operands) that may be required must be given as keyword-arguments.
-
operands
¶ Tuple of operands of the operation
-
args
¶ Alias for operands
-
-
qnet.algebra.abstract_algebra.
assoc
(cls, ops, kwargs)[source]¶ Associatively expand out nested arguments of the flat class. E.g.:
>>> class Plus(Operation): ... _simplifications = [assoc, ] >>> Plus.create(1,Plus(2,3)) Plus(1, 2, 3)
-
qnet.algebra.abstract_algebra.
idem
(cls, ops, kwargs)[source]¶ Remove duplicate arguments and order them via the cls’s order_key key object/function. E.g.:
>>> class Set(Operation): ... order_key = lambda val: val ... _simplifications = [idem, ] >>> Set.create(1,2,3,1,3) Set(1, 2, 3)
-
qnet.algebra.abstract_algebra.
orderby
(cls, ops, kwargs)[source]¶ Re-order arguments via the class’s
order_key
key object/function. Use this for commutative operations: E.g.:>>> class Times(Operation): ... order_key = lambda val: val ... _simplifications = [orderby, ] >>> Times.create(2,1) Times(1, 2)
-
qnet.algebra.abstract_algebra.
filter_neutral
(cls, ops, kwargs)[source]¶ Remove occurrences of a neutral element from the argument/operand list, if that list has at least two elements. To use this, one must also specify a neutral element, which can be anything that allows for an equality check with each argument. E.g.:
>>> class X(Operation): ... neutral_element = 1 ... _simplifications = [filter_neutral, ] >>> X.create(2,1,3,1) X(2, 3)
-
qnet.algebra.abstract_algebra.
match_replace
(cls, ops, kwargs)[source]¶ Match and replace a full operand specification to a function that provides a replacement for the whole expression or raises a
CannotSimplify
exception. E.g.First define an operation:
>>> class Invert(Operation): ... _rules = [] ... _simplifications = [match_replace, ]
Then some _rules:
>>> A = wc("A") >>> A_float = wc("A", head=float) >>> Invert_A = pattern(Invert, A) >>> Invert._rules += [ ... (pattern_head(Invert_A), lambda A: A), ... (pattern_head(A_float), lambda A: 1./A), ... ]
Check rule application:
>>> print(srepr(Invert.create("hallo"))) # matches no rule Invert('hallo') >>> Invert.create(Invert("hallo")) # matches first rule 'hallo' >>> Invert.create(.2) # matches second rule 5.0
A pattern can also have the same wildcard appear twice:
>>> class X(Operation): ... _rules = [ ... (pattern_head(A, A), lambda A: A), ... ] ... _simplifications = [match_replace, ] >>> X.create(1,2) X(1, 2) >>> X.create(1,1) 1
-
qnet.algebra.abstract_algebra.
match_replace_binary
(cls, ops, kwargs)[source]¶ Similar to func:match_replace, but for arbitrary length operations, such that each two pairs of subsequent operands are matched pairwise.
>>> A = wc("A") >>> class FilterDupes(Operation): ... _binary_rules = [(pattern_head(A,A), lambda A: A), ] ... _simplifications = [match_replace_binary, assoc] ... neutral_element = 0 >>> FilterDupes.create(1,2,3,4) # No duplicates FilterDupes(1, 2, 3, 4) >>> FilterDupes.create(1,2,2,3,4) # Some duplicates FilterDupes(1, 2, 3, 4)
Note that this only works for subsequent duplicate entries:
>>> FilterDupes.create(1,2,3,2,4) # No *subsequent* duplicates FilterDupes(1, 2, 3, 2, 4)
Any operation that uses binary reduction must be associative and define a neutral element. The binary rules must be compatible with associativity, i.e. there is no specific order in which the rules are applied to pairs of operands.
-
qnet.algebra.abstract_algebra.
no_instance_caching
()[source]¶ Temporarily disable the caching of instances through Expression.create
-
qnet.algebra.abstract_algebra.
temporary_instance_cache
(cls)[source]¶ Use a temporary cache for instances obtained from the create method of the given cls. That is, no cached instances from outside of the managed context will be used within the managed context, and vice versa
-
qnet.algebra.abstract_algebra.
extra_rules
(cls, rules)[source]¶ Context manager that temporarily adds the given rules to cls (to be processed by match_replace. Implies temporary_instance_cache.
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 The Circuit Algebra module.
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:
FB |
Wrapper for :py:class:Feedback: but with additional default values. |
P_sigma |
Create a channel permutation circuit for the given index image values. |
check_cdims |
Check that all operands (ops) have equal channel dimension. |
cid |
Return the circuit identity for n channels. |
circuit_identity |
Return the circuit identity for n channels. |
connect |
Connect a list of components according to a list of connections. |
eval_adiabatic_limit |
Compute the limiting SLH model for the adiabatic approximation. |
extract_signal |
Create a permutation that maps the k-th (zero-based) element to the last element, while preserving the relative order of all other elements. |
extract_signal_circuit |
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. |
getABCD |
Return the A, B, C, D and (a, c) matrices that linearize an SLH model about a coherent displacement amplitude a0. |
get_common_block_structure |
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. |
map_signals |
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. |
map_signals_circuit |
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. |
move_drive_to_H |
For the given slh model, move inhomogeneities in the Lindblad operators (resulting from the presence of a coherent drive, see Displace ) to the Hamiltonian. |
pad_with_identity |
Pad a circuit by ‘inserting’ an n-channel identity circuit at index k. |
prepare_adiabatic_limit |
Prepare the adiabatic elimination procedure for an SLH object with |
try_adiabatic_elimination |
Attempt to automatically carry out the adiabatic elimination procedure on slh with scaling parameter k. |
__all__
: ABCD
, CIdentity
, CPermutation
, CannotConvertToABCD
, CannotConvertToSLH
, CannotEliminateAutomatically
, CannotVisualize
, Circuit
, CircuitSymbol
, CircuitZero
, Concatenation
, FB
, Feedback
, IncompatibleBlockStructures
, P_sigma
, SLH
, SeriesInverse
, SeriesProduct
, WrongCDimError
, cid
, cid_1
, circuit_identity
, connect
, eval_adiabatic_limit
, extract_signal
, extract_signal_circuit
, getABCD
, get_common_block_structure
, map_signals
, map_signals_circuit
, move_drive_to_H
, pad_with_identity
, prepare_adiabatic_limit
, try_adiabatic_elimination
Module data:
-
qnet.algebra.circuit_algebra.
cid_1
¶
Reference¶
-
exception
qnet.algebra.circuit_algebra.
CannotConvertToSLH
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraException
Is raised when a circuit algebra object cannot be converted to a concrete SLH object.
-
exception
qnet.algebra.circuit_algebra.
CannotConvertToABCD
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraException
Is raised when a circuit algebra object cannot be converted to a concrete ABCD object.
-
exception
qnet.algebra.circuit_algebra.
CannotVisualize
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraException
Is raised when a circuit algebra object cannot be visually represented.
-
exception
qnet.algebra.circuit_algebra.
WrongCDimError
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraError
Is raised when two object are tried to joined together in series but have different channel dimensions.
-
exception
qnet.algebra.circuit_algebra.
IncompatibleBlockStructures
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraError
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]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraError
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 Raises: 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)Returns: A tuple of subblocks that the circuit consists of. Raises: 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 portin_port
.Parameters:
-
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. Return (str): 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 Returns: The circuit including the coherent inputs. Return type: Circuit Raise: WrongCDimError
-
space
¶ Hilbert space of the circuit
-
-
class
qnet.algebra.circuit_algebra.
SLH
(S, L, H)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Expression
SLH class to encapsulate an open system model that is parametrized as described in [2] , [3]
SLH(S, L, H)
Attributes: - 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
Parameters: - S – Value for the S attribute.
- L – Value for the L attribute
- H – Value for the H attribute
-
args
¶
-
Ls
¶ Lindblad operators (entries of the L vector), as a list
-
cdim
¶
-
space
¶ Total Hilbert space
-
series_with_slh
(other)[source]¶ Evaluate the series product with another :py:class:
SLH
object.Parameters: other (SLH) – An upstream SLH circuit. Returns: The combines system. Return type: SLH
-
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_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 Returns: The RHS of the master equation. Return type: 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: Returns: The RHS of the Heisenberg equations of motion of X.
Return type:
-
class
qnet.algebra.circuit_algebra.
ABCD
(A, B, C, D, w, space)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Expression
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
- A (Matrix) – Coupling matrix: internal to internal, scalar valued elements,
-
class
qnet.algebra.circuit_algebra.
CircuitSymbol
(name, cdim)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Expression
Circuit Symbol object, parametrized by an identifier (name) and channel dimension.
-
name
¶
-
args
¶
-
cdim
¶ Dimension of circuit
-
space
¶ FullSpace (Circuit Symbols are not restricted to a particular Hilbert space)
-
-
class
qnet.algebra.circuit_algebra.
CPermutation
(permutation)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Expression
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. -
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) Return type: Circuit
-
space
¶ TrivialSpace
-
-
class
qnet.algebra.circuit_algebra.
SeriesProduct
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Operation
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. -
cdim
¶
-
space
¶ Hilbert space of the series product (product space of all operators)
-
-
class
qnet.algebra.circuit_algebra.
Concatenation
(*operands)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Operation
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¶
-
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]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Operation
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: -
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]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Operation
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
-
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 Returns: n-channel identity circuit Return type: Circuit
-
qnet.algebra.circuit_algebra.
cid
(n)¶ Return the circuit identity for n channels.
Parameters: n (int) – The channel dimension Returns: n-channel identity circuit Return type: 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: Returns: The circuit with applied feedback operation.
Return type:
-
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:
-
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: Returns: Permutation image tuple
Return type:
-
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: Returns: Permutation circuit
Return type:
-
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
-
qnet.algebra.circuit_algebra.
pad_with_identity
(circuit, k, n)[source]¶ 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) >>> print(ascii(pad_with_identity(A+B, 1, 2))) 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: Returns: An extended circuit that passes through the channels k, k+1, ..., k+n-1
Return type:
-
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.
-
qnet.algebra.circuit_algebra.
prepare_adiabatic_limit
(slh, k=None)[source]¶ 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.
Returns: The objects Y, A, B, F, G, N necessary to compute the limiting system.
Return type:
-
qnet.algebra.circuit_algebra.
eval_adiabatic_limit
(YABFGN, Ytilde, P0)[source]¶ 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.
Returns: Limiting SLH model
Return type:
-
qnet.algebra.circuit_algebra.
try_adiabatic_elimination
(slh, k=None, fock_trunc=6, sub_P0=True)[source]¶ 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))
wherec1
andc2
are elements of components (or the index of the element in components, andport1
andport2
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
qnet.algebra.hilbert_space_algebra module¶
This module defines some simple classes to describe simple and composite/tensor (i.e., multiple degree of freedom) Hilbert spaces of quantum systems.
For more details see Hilbert Space Algebra.
Summary¶
Exceptions:
BasisNotSetError |
Raised if the basis or a Hilbert space dimension is requested but is not |
Classes:
HilbertSpace |
Basic Hilbert space class from which concrete classes are derived. |
LocalSpace |
A local Hilbert space, i.e., for a single degree of freedom. |
ProductSpace |
Tensor product space class for an arbitrary number of LocalSpace factors. |
Functions:
convert_to_spaces |
For all operands that are merely of type str or int, substitute LocalSpace objects with corresponding labels: For a string, just itself, for an int, a string version of that int. |
empty_trivial |
A ProductSpace of zero Hilbert spaces should yield the TrivialSpace |
__all__
: BasisNotSetError
, FullSpace
, HilbertSpace
, LocalSpace
, ProductSpace
, TrivialSpace
Module data:
Reference¶
-
exception
qnet.algebra.hilbert_space_algebra.
BasisNotSetError
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraError
Raised if the basis or a Hilbert space dimension is requested but is not available
-
qnet.algebra.hilbert_space_algebra.
convert_to_spaces
(cls, ops, kwargs)[source]¶ For all operands that are merely of type str or int, substitute LocalSpace objects with corresponding labels: For a string, just itself, for an int, a string version of that int.
-
qnet.algebra.hilbert_space_algebra.
empty_trivial
(cls, ops, kwargs)[source]¶ A ProductSpace of zero Hilbert spaces should yield the TrivialSpace
-
class
qnet.algebra.hilbert_space_algebra.
HilbertSpace
[source]¶ Bases:
object
Basic Hilbert space class from which concrete classes are derived.
-
tensor
(*others)[source]¶ Tensor product between Hilbert spaces
Parameters: others (HilbertSpace) – Other Hilbert space(s) Returns: Tensor product space. Return type: HilbertSpace
-
local_factors
¶ Return tuple of LocalSpace objects that tensored together yield this Hilbert space.
-
isdisjoint
(other)[source]¶ Check whether two Hilbert spaces are disjoint (do not have any common local factors). Note that FullSpace is not disjoint with any other Hilbert space, while TrivialSpace is disjoint with any other HilbertSpace (even itself)
-
is_tensor_factor_of
(other)[source]¶ Test if a space is included within a larger tensor product space. Also
True
ifself == other
.Parameters: other (HilbertSpace) – Other Hilbert space Return type: bool
-
is_strict_tensor_factor_of
(other)[source]¶ Test if a space is included within a larger tensor product space. Not
True
ifself == other
.
-
dimension
¶ The full dimension of the Hilbert space (or None) if the dimension is not known
-
get_dimension
(raise_basis_not_set_error=True)[source]¶ Return the dimension property, but if raise_basis_not_set_error is True, raise a BasisNotSetError if no basis is set, instead of returning None
-
basis
¶ Basis of the the Hilbert space, or None if no basis is set
-
get_basis
(raise_basis_not_set_error=True)[source]¶ Return the basis property, but if raise_basis_not_set_error is True, raise a BasisNotSetError if no basis is set, instead of returning None
-
-
class
qnet.algebra.hilbert_space_algebra.
LocalSpace
(label, *, basis=None, dimension=None, order_index=None)[source]¶ Bases:
qnet.algebra.hilbert_space_algebra.HilbertSpace
,qnet.algebra.abstract_algebra.Expression
A local Hilbert space, i.e., for a single degree of freedom.
Parameters: - label (str) – label (subscript) of the Hilbert space
- basis (tuple or None) – Set an explicit basis for the Hilbert space (tuple of labels for the basis states)
- dimension (int or None) – Specify the dimension \(n\) of the Hilbert space. This implies a basis numbered from 0 to \(n-1\).
- order_index (int or None) – An optional key that determines the preferred order of Hilbert spaces. This also changes the order of e.g. sums or products of Operators. Hilbert spaces will be ordered from left to right be increasing order_index; Hilbert spaces without an explicit order_index are sorted by their label
-
args
¶
-
label
¶ Label of the Hilbert space
-
basis
¶
-
dimension
¶
-
kwargs
¶
-
minimal_kwargs
¶
-
local_factors
¶
-
class
qnet.algebra.hilbert_space_algebra.
ProductSpace
(*local_spaces)[source]¶ Bases:
qnet.algebra.hilbert_space_algebra.HilbertSpace
,qnet.algebra.abstract_algebra.Operation
Tensor product space class for an arbitrary number of LocalSpace factors.
>>> hs1 = LocalSpace('1', basis=(0,1)) >>> hs2 = LocalSpace('2', basis=(0,1)) >>> hs = hs1 * hs2 >>> hs.basis ('0,0', '0,1', '1,0', '1,1')
-
signature
= ((<class 'qnet.algebra.hilbert_space_algebra.HilbertSpace'>, '*'), {})¶
-
neutral_element
= TrivialSpace¶
-
basis
¶ Basis of the ProductSpace, from the bases of the operands
-
dimension
¶
-
local_factors
¶ The LocalSpace instances that make up the product
-
qnet.algebra.matrix_algebra module¶
Matrices of Operators
Summary¶
Exceptions:
NonSquareMatrix |
Classes:
Matrix |
Matrix with Operator (or scalar-) valued elements. |
Functions:
Im |
The imaginary part of a number or operator. |
ImAdjoint |
The imaginary part of an OperatorMatrix, i.e. |
ImMatrix |
|
Re |
The real part of a number or operator. |
ReAdjoint |
The real part of an OperatorMatrix, i.e. |
ReMatrix |
|
block_matrix |
Generate the operator matrix with quadrants |
diagm |
Generalizes the diagonal matrix creation capabilities of numpy.diag to OperatorMatrix objects. |
hstackm |
Generalizes numpy.hstack to OperatorMatrix objects. |
identity_matrix |
Generate the N-dimensional identity matrix. |
permutation_matrix |
Return an orthogonal permutation matrix |
vstackm |
Generalizes numpy.vstack to OperatorMatrix objects. |
zerosm |
Generalizes numpy.zeros to Matrix objects. |
__all__
: ImAdjoint
, ImMatrix
, Matrix
, NonSquareMatrix
, ReAdjoint
, ReMatrix
, block_matrix
, diagm
, hstackm
, identity_matrix
, permutation_matrix
, vstackm
, zerosm
Reference¶
-
class
qnet.algebra.matrix_algebra.
Matrix
(m)[source]¶ Bases:
qnet.algebra.abstract_algebra.Expression
Matrix with Operator (or scalar-) valued elements.
-
matrix
= None¶
-
shape
¶ The shape of the matrix
(nrows, ncols)
-
block_structure
¶ For square matrices this gives the block (-diagonal) structure of the matrix as a tuple of integers that sum up to the full dimension.
Type: tuple
-
args
¶
-
is_zero
¶ Are all elements of the matrix zero?
-
conjugate
()[source]¶ The element-wise conjugate matrix, i.e., if an element is an operator this means the adjoint operator, but no transposition of matrix elements takes place.
-
T
¶ Transpose matrix
-
adjoint
()[source]¶ Return the adjoint operator matrix, i.e. transpose and the Hermitian adjoint operators of all elements.
-
dag
()¶ Return the adjoint operator matrix, i.e. transpose and the Hermitian adjoint operators of all elements.
-
H
¶ Return the adjoint operator matrix, i.e. transpose and the Hermitian adjoint operators of all elements.
-
element_wise
(method)[source]¶ Apply a method to each matrix element and return the result in a new operator matrix of the same shape. :param method: A method taking a single argument. :type method: FunctionType :return: Operator matrix with results of method applied element-wise. :rtype: Matrix
-
series_expand
(param, about, order)[source]¶ Expand the matrix expression as a truncated power series in a scalar parameter.
Parameters: - param (sympy.core.symbol.Symbol) – Expansion parameter.
- about (Any one of Operator.scalar_types) – Point about which to expand.
- order (int >= 0) – Maximum order of expansion.
Returns: tuple of length (order+1), where the entries are the expansion coefficients.
Return type: tuple of Operator
-
expand
()[source]¶ Expand each matrix element distributively. :return: Expanded matrix. :rtype: Matrix
-
space
¶ Combined Hilbert space of all matrix elements.
-
-
qnet.algebra.matrix_algebra.
hstackm
(matrices)[source]¶ Generalizes numpy.hstack to OperatorMatrix objects.
-
qnet.algebra.matrix_algebra.
vstackm
(matrices)[source]¶ Generalizes numpy.vstack to OperatorMatrix objects.
-
qnet.algebra.matrix_algebra.
diagm
(v, k=0)[source]¶ Generalizes the diagonal matrix creation capabilities of numpy.diag to OperatorMatrix objects.
-
qnet.algebra.matrix_algebra.
block_matrix
(A, B, C, D)[source]¶ Generate the operator matrix with quadrants
\[\begin{split}\begin{pmatrix} A B \\ C D \end{pmatrix}\end{split}\]Parameters: Returns: The combined block matrix [[A, B], [C, D]].
Type: OperatorMatrix
-
qnet.algebra.matrix_algebra.
identity_matrix
(N)[source]¶ Generate the N-dimensional identity matrix.
Parameters: N (int) – Dimension Returns: Identity matrix in N dimensions Return type: Matrix
-
qnet.algebra.matrix_algebra.
zerosm
(shape, *args, **kwargs)[source]¶ Generalizes
numpy.zeros
toMatrix
objects.
-
qnet.algebra.matrix_algebra.
permutation_matrix
(permutation)[source]¶ Return an orthogonal permutation matrix \(M_\sigma\) for a permutation \(\sigma\) defined by the image tuple \((\sigma(1), \sigma(2),\dots \sigma(n))\), such that
\[M_\sigma \vec{e}_i = \vec{e}_{\sigma(i)}\]where \(\vec{e}_k\) is the k-th standard basis vector. This definition ensures a composition law:
\[M_{\sigma \cdot \tau} = M_\sigma M_\tau.\]The column form of \(M_\sigma\) is thus given by
\[M = (\vec{e}_{\sigma(1)}, \vec{e}_{\sigma(2)}, \dots \vec{e}_{\sigma(n)}).\]Parameters: permutation (tuple) – A permutation image tuple (zero-based indices!)
-
qnet.algebra.matrix_algebra.
Im
(op)[source]¶ The imaginary part of a number or operator. Acting on OperatorMatrices, it produces the element-wise imaginary parts.
Parameters: op (Operator or Matrix or any of Operator.scalar_types) – Anything that has a conjugate method. Returns: The imaginary part of the operand. Return type: Same as type of op.
-
qnet.algebra.matrix_algebra.
Re
(op)[source]¶ The real part of a number or operator. Acting on OperatorMatrices, it produces the element-wise real parts.
Parameters: op (Operator or Matrix or any of Operator.scalar_types) – Anything that has a conjugate method. Returns: The real part of the operand. Return type: Same as type of op.
qnet.algebra.operator_algebra module¶
This module features classes and functions to define and manipulate symbolic Operator expressions. For more details see The Operator Algebra module.
For a list of all properties and methods of an operator object, see the
documentation for the basic Operator
class.
Summary¶
Classes:
Adjoint |
The symbolic Adjoint of an operator. |
Create |
Create(hs=space) yields a bosonic creation operator acting on a |
Destroy |
Destroy(hs=space) yields a bosonic annihilation operator acting on a |
Displace |
Unitary coherent displacement operator |
Jminus |
Jminus(space) yields the \(J_-\) lowering ladder operator of a general |
Jplus |
Jplus(space) yields the \(J_+\) raising ladder operator of a general |
Jz |
Jz(space) yields the \(z\) component of a general spin operator acting |
LocalOperator |
Base class for all kinds of operators that act locally, i.e. |
LocalSigma |
A local level flip operator operator acting on a particular local space/degree of freedom. |
NullSpaceProjector |
Returns a projection operator \(\mathcal{P}_{{\rm Ker} X}\) that |
Operator |
The basic operator class, which fixes the abstract interface of operator objects and where possible also defines the default behavior under operations. |
OperatorOperation |
Base class for Operations acting only on Operator arguments, for when the Hilbert space of the operation result is the product space of the operands. |
OperatorPlus |
A sum of Operators |
OperatorPlusMinusCC |
An operator plus or minus its complex conjugate |
OperatorSymbol |
Symbolic operator, parametrized by an identifier string and an associated Hilbert space. |
OperatorTimes |
A product of Operators that serves both as a product within a Hilbert space as well as a tensor product. |
OperatorTrace |
Take the (partial) trace of an operator \(X\) over the degrees of |
Phase |
The unitary Phase operator acting on a particular local space/degree of |
PseudoInverse |
The symbolic pseudo-inverse \(X^+\) of an operator \(X\). |
ScalarTimesOperator |
Multiply an operator by a scalar coefficient. |
SingleOperatorOperation |
Base class for Operations that act on a single Operator |
Squeeze |
A unitary Squeezing operator acting on a particular local space/degree |
Functions:
Jmjmcoeff |
|
Jpjmcoeff |
|
Jzjmcoeff |
|
LocalProjector |
|
X |
Pauli-type X-operator |
Y |
Pauli-type Y-operator |
Z |
Pauli-type Z-operator |
adjoint |
Return the adjoint of an obj. |
create_operator_pm_cc |
Return a list of rules that can be used in an |
decompose_space |
Simplifies OperatorTrace expressions over tensor-product spaces by turning it into iterated partial traces. |
delegate_to_method |
Create a simplification rule that delegates the instantiation to the |
expand_operator_pm_cc |
Return a list of rules that can be used in simplify to expand |
factor_coeff |
Factor out coefficients of all factors. |
factor_for_trace |
Given a local space ls to take the partial trace over and an operator, factor the trace such that operators acting on disjoint degrees of freedom are pulled out of the trace. |
get_coeffs |
Create a dictionary with all Operator terms of the expression (understood as a sum) as keys and their coefficients as values. |
implied_local_space |
Return a simplification that converts the positional argument |
scalar_free_symbols |
Return all free symbols from any symbolic operand |
simplify_scalar |
Simplify all occurences of scalar expressions in s |
space |
Gives the associated HilbertSpace with an object. |
__all__
: Adjoint
, Create
, Destroy
, Displace
, II
, IdentityOperator
, Jminus
, Jmjmcoeff
, Jpjmcoeff
, Jplus
, Jz
, Jzjmcoeff
, LocalOperator
, LocalProjector
, LocalSigma
, NullSpaceProjector
, Operator
, OperatorOperation
, OperatorPlus
, OperatorPlusMinusCC
, OperatorSymbol
, OperatorTimes
, OperatorTrace
, Phase
, PseudoInverse
, ScalarTimesOperator
, SingleOperatorOperation
, Squeeze
, X
, Y
, Z
, ZeroOperator
, adjoint
, create_operator_pm_cc
, decompose_space
, expand_operator_pm_cc
, factor_coeff
, factor_for_trace
, get_coeffs
, scalar_free_symbols
, simplify_scalar
, space
Module data:
-
qnet.algebra.operator_algebra.
II
¶
Reference¶
-
qnet.algebra.operator_algebra.
implied_local_space
(*, arg_index=None, keys=None)[source]¶ Return a simplification that converts the positional argument arg_index from (str, int) to LocalSpace, as well as any keyword argument with one of the given keys
-
qnet.algebra.operator_algebra.
delegate_to_method
(mtd)[source]¶ Create a simplification rule that delegates the instantiation to the method mtd of the operand (if defined)
-
class
qnet.algebra.operator_algebra.
Operator
[source]¶ Bases:
object
The basic operator class, which fixes the abstract interface of operator objects and where possible also defines the default behavior under operations. Any operator contains an associated HilbertSpace object, on which it is taken to act non-trivially.
-
space
¶ The HilbertSpace on which the operator acts non-trivially
-
conjugate
()¶ The Hermitian adjoint of the operator.
-
dag
()¶ The Hermitian adjoint of the operator.
-
pseudo_inverse
()[source]¶ The pseudo-Inverse of the Operator, i.e., it inverts the operator on the orthogonal complement of its nullspace
-
expand
()[source]¶ Expand out distributively all products of sums. Note that this does not expand out sums of scalar coefficients.
Returns: A fully expanded sum of operators. Return type: Operator
-
simplify_scalar
()[source]¶ Simplify all scalar coefficients within the Operator expression.
Returns: The simplified expression. Return type: Operator
-
diff
(sym, n=1, expand_simplify=True)[source]¶ Differentiate by scalar parameter sym.
Parameters: Return (Operator): The n-th derivative.
-
series_expand
(param, about, order)[source]¶ Expand the operator expression as a truncated power series in a scalar parameter.
Parameters: - param (sympy.core.symbol.Symbol) – Expansion parameter.
- about (Any one of SCALAR_TYPES) – Point about which to expand.
- order (int >= 0) – Maximum order of expansion.
Returns: tuple of length (order+1), where the entries are the expansion coefficients.
Return type: tuple of Operator
-
-
class
qnet.algebra.operator_algebra.
LocalOperator
(*args, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Expression
Base class for all kinds of operators that act locally, i.e. only on a single degree of freedom.
-
space
¶
-
args
¶
-
kwargs
¶
-
minimal_kwargs
¶
-
identifier
¶ The name / identifying symbol of the operator
-
-
class
qnet.algebra.operator_algebra.
OperatorOperation
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
Base class for Operations acting only on Operator arguments, for when the Hilbert space of the operation result is the product space of the operands.
-
space
¶
-
-
class
qnet.algebra.operator_algebra.
SingleOperatorOperation
(op, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
Base class for Operations that act on a single Operator
-
space
¶
-
operand
¶
-
-
class
qnet.algebra.operator_algebra.
OperatorSymbol
(identifier, *, hs)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Expression
Symbolic operator, parametrized by an identifier string and an associated Hilbert space.
Parameters: - identifier (str) – Symbol identifier
- hs (HilbertSpace) – Associated Hilbert space (can be a ProductSpace)
-
args
¶
-
kwargs
¶
-
space
¶
-
class
qnet.algebra.operator_algebra.
Create
(*args, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
Create(hs=space)
yields a bosonic creation operator acting on a particular local space/degree of freedom. Its adjoint is:>>> print(ascii(Create(hs=1).adjoint())) a^(1)
and it obeys the bosonic commutation relation:
>>> Destroy(hs=1) * Create(hs=1) - Create(hs=1) * Destroy(hs=1) IdentityOperator >>> Destroy(hs=1) * Create(hs=2) - Create(hs=2) * Destroy(hs=1) ZeroOperator
Parameters: space (LocalSpace or str) – Associated local Hilbert space.
-
class
qnet.algebra.operator_algebra.
Destroy
(*args, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
Destroy(hs=space)
yields a bosonic annihilation operator acting on a particular local space/degree of freedom. Its adjoint is:>>> print(ascii(Destroy(hs=1).adjoint())) a^(1)H
and it obeys the bosonic commutation relation:
>>> Destroy(hs=1) * Create(hs=1) - Create(hs=1) * Destroy(hs=1) IdentityOperator >>> Destroy(hs=1) * Create(hs=2) - Create(hs=2) * Destroy(hs=1) ZeroOperator
Parameters: space (LocalSpace or str) – Associated local Hilbert space.
-
class
qnet.algebra.operator_algebra.
Jz
(*args, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
Jz(space)
yields the \(z\) component of a general spin operator acting on a particular local space/degree of freedom with well defined spin quantum number \(J\). It is Hermitian:>>> print(ascii(Jz(hs=1).adjoint())) J_z^(1)
Jz
,Jplus
andJminus
satisfy the angular momentum commutator algebra:>>> print(ascii((Jz(hs=1) * Jplus(hs=1) - ... Jplus(hs=1)*Jz(hs=1)).expand())) J_+^(1) >>> print(ascii((Jz(hs=1) * Jminus(hs=1) - ... Jminus(hs=1)*Jz(hs=1)).expand())) -J_-^(1) >>> print(ascii((Jplus(hs=1) * Jminus(hs=1) ... - Jminus(hs=1)*Jplus(hs=1)).expand())) 2 * J_z^(1)
where
Jplus = Jx + i * Jy
,Jminux= Jx - i * Jy
.
-
class
qnet.algebra.operator_algebra.
Jplus
(*args, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
Jplus(space)
yields the \(J_+\) raising ladder operator of a general spin operator acting on a particular local space/degree of freedom with well defined spin quantum number \(J\). It’s adjoint is the lowering operator:>>> print(ascii(Jplus(hs=1).adjoint())) J_-^(1)
Jz
,Jplus
andJminus
satisfy that angular momentum commutator algebra:>>> print(ascii((Jz(hs=1) * Jplus(hs=1) - ... Jplus(hs=1)*Jz(hs=1)).expand())) J_+^(1) >>> print(ascii((Jz(hs=1) * Jminus(hs=1) - ... Jminus(hs=1)*Jz(hs=1)).expand())) -J_-^(1) >>> print(ascii((Jplus(hs=1) * Jminus(hs=1) - ... Jminus(hs=1)*Jplus(hs=1)).expand())) 2 * J_z^(1)
where
Jplus = Jx + i * Jy
,Jminux= Jx - i * Jy
.
-
class
qnet.algebra.operator_algebra.
Jminus
(*args, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
Jminus(space)
yields the \(J_-\) lowering ladder operator of a general spin operator acting on a particular local space/degree of freedom with well defined spin quantum number \(J\). It’s adjoint is the raising operator:>>> print(ascii(Jminus(hs=1).adjoint())) J_+^(1)
Jz
,Jplus
andJminus
satisfy that angular momentum commutator algebra:>>> print(ascii((Jz(hs=1) * Jplus(hs=1) - ... Jplus(hs=1)*Jz(hs=1)).expand())) J_+^(1) >>> print(ascii((Jz(hs=1) * Jminus(hs=1) - ... Jminus(hs=1)*Jz(hs=1)).expand())) -J_-^(1) >>> print(ascii((Jplus(hs=1) * Jminus(hs=1) - ... Jminus(hs=1)*Jplus(hs=1)).expand())) 2 * J_z^(1)
where
Jplus = Jx + i * Jy
,Jminux= Jx - i * Jy
.
-
class
qnet.algebra.operator_algebra.
Phase
(phi, *, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
The unitary Phase operator acting on a particular local space/degree of freedom:
\[P_{\rm s}(\phi):= \exp\left(i \phi a_{\rm s}^\dagger a_{\rm s}\right)\]where \(a_{\rm s}\) is the annihilation operator acting on the local space s.
Parameters: - hs (LocalSpace or str) – Associated local Hilbert space.
- phi (Any from SCALAR_TYPES) – Displacement amplitude.
-
args
¶
-
class
qnet.algebra.operator_algebra.
Displace
(alpha, *, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
Unitary coherent displacement operator
\[D_{\rm s}(\alpha) := \exp\left({\alpha a_{\rm s}^\dagger - \alpha^* a_{\rm s}}\right)\]where \(a_{\rm s}\) is the annihilation operator acting on the local space \(s\).
Parameters: - space (LocalSpace or str) – Associated local Hilbert space.
- alpha (Any from SCALAR_TYPES) – Displacement amplitude.
-
args
¶
-
class
qnet.algebra.operator_algebra.
Squeeze
(eta, *, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
A unitary Squeezing operator acting on a particular local space/degree of freedom:
\[S_{\rm s}(\eta) := \exp {\left( \frac{\eta}{2} {a_{\rm s}^\dagger}^2 - \frac{\eta^*}{2} {a_{\rm s}}^2 \right)}\]where \(a_{\rm s}\) is the annihilation operator acting on the local space \(s\).
Parameters: - space (LocalSpace or str) – Associated local Hilbert space.
- eta (Any from SCALAR_TYPES) – Squeeze parameter.
-
args
¶
-
class
qnet.algebra.operator_algebra.
LocalSigma
(j, k, *, hs, identifier=None)[source]¶ Bases:
qnet.algebra.operator_algebra.LocalOperator
A local level flip operator operator acting on a particular local space/degree of freedom.
\[\sigma_{jk}^{\rm s} := \left| j\right\rangle_{\rm s} \left \langle k \right |_{\rm s}\]Parameters: -
args
¶
-
-
class
qnet.algebra.operator_algebra.
OperatorPlus
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.OperatorOperation
A sum of Operators
Parameters: operands (list) – Operator summands -
neutral_element
= ZeroOperator¶
-
order_key
¶ alias of
FullCommutativeHSOrder
-
-
class
qnet.algebra.operator_algebra.
OperatorTimes
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.OperatorOperation
A product of Operators that serves both as a product within a Hilbert space as well as a tensor product.
Parameters: operands (list) – Operator factors -
neutral_element
= IdentityOperator¶
-
order_key
¶ alias of
DisjunctCommutativeHSOrder
-
-
class
qnet.algebra.operator_algebra.
ScalarTimesOperator
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
Multiply an operator by a scalar coefficient.
Parameters: - coefficient (Any of SCALAR_TYPES) – Scalar coefficient.
- term (Operator) – The operator that is multiplied.
-
static
has_minus_prefactor
(c)[source]¶ For a scalar object c, determine whether it is prepended by a “-” sign.
-
space
¶
-
coeff
¶
-
term
¶
-
class
qnet.algebra.operator_algebra.
OperatorTrace
(op, *, over_space)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
Take the (partial) trace of an operator \(X\) over the degrees of freedom given by a Hilbert hs \(\mathcal{H}\):
\[{\rm Tr}_{\mathcal{H}} X\]Use as:
OperatorTrace(X, over_space=hs)
Parameters: - over_space (HilbertSpace) – The degrees of freedom to trace over
- op (Operator) – The operator to take the trace of.
-
kwargs
¶
-
operand
¶
-
space
¶
-
class
qnet.algebra.operator_algebra.
Adjoint
(op, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.SingleOperatorOperation
The symbolic Adjoint of an operator.
Adjoint(op)
Parameters: op (Operator) – The operator to take the adjoint of.
-
class
qnet.algebra.operator_algebra.
OperatorPlusMinusCC
(op, *, sign=1)[source]¶ Bases:
qnet.algebra.operator_algebra.SingleOperatorOperation
An operator plus or minus its complex conjugate
-
kwargs
¶
-
minimal_kwargs
¶
-
-
class
qnet.algebra.operator_algebra.
PseudoInverse
(op, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.SingleOperatorOperation
The symbolic pseudo-inverse \(X^+\) of an operator \(X\). It is defined via the relationship
\[\begin{split}X X^+ X = X \\ X^+ X X^+ = X^+ \\ (X^+ X)^\dagger = X^+ X \\ (X X^+)^\dagger = X X^+\end{split}\]Parameters: X (Operator) – The operator to take the adjoint of.
-
class
qnet.algebra.operator_algebra.
NullSpaceProjector
(op, **kwargs)[source]¶ Bases:
qnet.algebra.operator_algebra.SingleOperatorOperation
Returns a projection operator \(\mathcal{P}_{{\rm Ker} X}\) that projects onto the nullspace of its operand
\[\begin{split}X \mathcal{P}_{{\rm Ker} X} = 0 \Leftrightarrow X (1 - \mathcal{P}_{{\rm Ker} X}) = X\\ \mathcal{P}_{{\rm Ker} X}^\dagger = \mathcal{P}_{{\rm Ker} X} = \mathcal{P}_{{\rm Ker} X}^2\end{split}\]Parameters: X (Operator) – Operator argument
-
qnet.algebra.operator_algebra.
X
(local_space, states=('h', 'g'))[source]¶ Pauli-type X-operator
Parameters: - local_space (LocalSpace) – Associated Hilbert space.
- states (tuple with two elements of type int or str) – The qubit state labels for the basis states \(\left\{|0\rangle, |1\rangle \right\}\), where \(Z|0\rangle = +|0\rangle\), default =
('h', 'g')
.
Returns: Local X-operator.
Return type:
-
qnet.algebra.operator_algebra.
Y
(local_space, states=('h', 'g'))[source]¶ Pauli-type Y-operator
Parameters: - local_space (LocalSpace) – Associated Hilbert space.
- states (tuple with two elements of type int or str) – The qubit state labels for the basis states \(\left\{|0\rangle, |1\rangle \right\}\), where \(Z|0\rangle = +|0\rangle\), default =
('h', 'g')
.
Returns: Local Y-operator.
Return type:
-
qnet.algebra.operator_algebra.
Z
(local_space, states=('h', 'g'))[source]¶ Pauli-type Z-operator
Parameters: - local_space (LocalSpace) – Associated Hilbert space.
- states (tuple with two elements of type int or str) – The qubit state labels for the basis states \(\left\{|0\rangle, |1\rangle \right\}\), where \(Z|0\rangle = +|0\rangle\), default =
('h', 'g')
.
Returns: Local Z-operator.
Return type:
-
qnet.algebra.operator_algebra.
factor_for_trace
(ls, op)[source]¶ Given a local space ls to take the partial trace over and an operator, factor the trace such that operators acting on disjoint degrees of freedom are pulled out of the trace. If the operator acts trivially on ls the trace yields only a pre-factor equal to the dimension of ls. If there are LocalSigma operators among a product, the trace’s cyclical property is used to move to sandwich the full product by
LocalSigma
operators:\[{\rm Tr} A \sigma_{jk} B = {\rm Tr} \sigma_{jk} B A \sigma_{jj}\]Parameters: - ls (HilbertSpace) – Degree of Freedom to trace over
- op (Operator) – Operator to take the trace of
Returns: The (partial) trace over the operator’s spc-degrees of freedom
Return type:
-
qnet.algebra.operator_algebra.
decompose_space
(H, A)[source]¶ Simplifies OperatorTrace expressions over tensor-product spaces by turning it into iterated partial traces.
Parameters: H (ProductSpace) – The full space. Returns: Iterative partial trace expression Return type: Operator
-
qnet.algebra.operator_algebra.
get_coeffs
(expr, expand=False, epsilon=0.0)[source]¶ Create a dictionary with all Operator terms of the expression (understood as a sum) as keys and their coefficients as values.
The returned object is a defaultdict that return 0. if a term/key doesn’t exist. :param expr: The operator expression to get all coefficients from. :param expand: Whether to expand the expression distributively. :param epsilon: If non-zero, drop all Operators with coefficients that have absolute value less than epsilon. :return: A dictionary of {op1: coeff1, op2: coeff2, ...} :rtype: dict
-
qnet.algebra.operator_algebra.
space
(obj)[source]¶ Gives the associated HilbertSpace with an object. Also works for SCALAR_TYPES
-
qnet.algebra.operator_algebra.
simplify_scalar
(s)[source]¶ Simplify all occurences of scalar expressions in s
Parameters: s (Expression or SympyBasic) – The expression to simplify. Returns: The simplified version. Return type: Expression or SympyBasic
-
qnet.algebra.operator_algebra.
scalar_free_symbols
(*operands)[source]¶ Return all free symbols from any symbolic operand
-
qnet.algebra.operator_algebra.
factor_coeff
(cls, ops, kwargs)[source]¶ Factor out coefficients of all factors.
-
qnet.algebra.operator_algebra.
create_operator_pm_cc
()[source]¶ Return a list of rules that can be used in an
extra_binary_rules()
context forOperatorPlus
in order to combine suitable terms into aOperatorPlusMinusCC
instance:>>> A = OperatorSymbol('A', hs=1) >>> sum = A + A.dag() >>> from qnet.algebra.abstract_algebra import extra_binary_rules >>> with extra_binary_rules(OperatorPlus, create_operator_pm_cc()): ... sum2 = sum.simplify() >>> print(ascii(sum2)) A^(1) + c.c.
The inverse is done through
expand_operator_pm_cc()
:>>> print(ascii(sum2.simplify(rules=expand_operator_pm_cc()))) A^(1) + A^(1)H
qnet.algebra.ordering module¶
The ordering package implements the default canonical ordering for sums and products of operators, states, and superoperators.
To the extent that commutativity rules allow this, the ordering defined here groups objects of the same Hilbert space together, and orders these groups in the same order that the Hilbert spaces occur in a ProductSpace (lexicographically/by order_index/by complexity). Objects within the same Hilbert space (again, assuming they commute) are ordered by the KeyTuple value that expr_order_key returns for each object. Note that expr_order_key defers to the object’s _order_key property, if available. This property should be defined for all QNET Expressions, generally ordering objects according to their type, then their label (if any), then their pre-factor then any other properties.
We assume that quantum operations have either full commutativity (sums, or products of states), or commutativity of objects only in different Hilbert spaces (e.g. products of operators). The former is handled by FullCommutativeHSOrder, the latter by DisjunctCommutativeHSOrder. Theses classes serve as the order_key for sums and products (e.g. OperatorPlus and similar classes)
A user may implement a custom ordering by subclassing (or replacing) FullCommutativeHSOrder and/or DisjunctCommutativeHSOrder, and assigning their replacements to all the desired algebraic classes.
Summary¶
Classes:
DisjunctCommutativeHSOrder |
Auxiliary class that generates the correct pseudo-order relation for operator products. |
FullCommutativeHSOrder |
Auxiliary class that generates the correct pseudo-order relation for operator products. |
KeyTuple |
A tuple that allows for ordering, facilitating the default ordering of Operations. |
Functions:
expr_order_key |
A default order key for arbitrary expressions |
Reference¶
-
class
qnet.algebra.ordering.
KeyTuple
[source]¶ Bases:
tuple
A tuple that allows for ordering, facilitating the default ordering of Operations. It differs from a normal tuple in that it falls back to string comparison if any elements are not directly comparable
-
class
qnet.algebra.ordering.
DisjunctCommutativeHSOrder
(op, space_order=None, op_order=None)[source]¶ Bases:
object
Auxiliary class that generates the correct pseudo-order relation for operator products. Only operators acting on disjoint Hilbert spaces are commuted to reflect the order the local factors have in the total Hilbert space. I.e.,
sorted(factors, key=DisjunctCommutativeHSOrder)
achieves this ordering.
-
class
qnet.algebra.ordering.
FullCommutativeHSOrder
(op, space_order=None, op_order=None)[source]¶ Bases:
object
Auxiliary class that generates the correct pseudo-order relation for operator products. Only operators acting on disjoint Hilbert spaces are commuted to reflect the order the local factors have in the total Hilbert space. I.e.,
sorted(factors, key=FullCommutativeHSOrder)
achieves this ordering.
qnet.algebra.pattern_matching module¶
Patterns may be constructed by either instantiating a Pattern
instance
directly, or (preferred) by calling the pattern()
, pattern_head()
,
or wc()
helper routines.
The pattern may then be matched against an expression using
match_pattern()
. The result of a match is a MatchDict
object,
which evaluates to True or False in a boolean context to indicate the success
or failure of the match (or alternatively, through the success attribute).
The MatchDict
object also maps any wildcard names to the expression
that the corresponding wildcard Pattern matches.
Summary¶
Classes:
MatchDict |
Dictionary of wildcard names to expressions. |
Pattern |
Pattern for matching an expression |
ProtoExpr |
Object representing an un-instantiated Expression that may matched by a |
Functions:
match_pattern |
Recursively match expr with the given expr_or_pattern, which is either a direct expression (equal to expr for a successful match), or an instance of Pattern. |
pattern |
‘Flat’ constructor for the Pattern class, where positional and keyword |
pattern_head |
Helper function to create a Pattern object specfically matching a ProtoExpr. |
wc |
Helper function to create a Pattern object with an emphasis on wildcard |
__all__
: MatchDict
, Pattern
, match_pattern
, pattern
, pattern_head
, wc
Reference¶
-
class
qnet.algebra.pattern_matching.
MatchDict
(*args)[source]¶ Bases:
collections.OrderedDict
Dictionary of wildcard names to expressions. Once the value for a key is set, attempting to set it again with a different value raises a KeyError. The attribute merge_lists may be set do modify this behavior for values that are lists: If it is set to a value different from zero two lists that are set via the same key are merged. If merge_lists is negative, the new values are appended to the existing values; if it is positive, the new values are prepended
In a boolean context, a MatchDict always evaluates as True (even if empty, unlike a normal dictionary), unless the success attribute is explicitly set to False (which a failed Pattern matching should do)
Attributes: - success (bool) – Value of the MatchDict object in a boolean context:
bool(match) == match.success
- reason (str) – If success is False, string explaining why the match failed
- merge_lists (int) – Code that indicates how to combine multiple values that are lists
- success (bool) – Value of the MatchDict object in a boolean context:
-
class
qnet.algebra.pattern_matching.
Pattern
(head=None, args=None, kwargs=None, *, mode=1, wc_name=None, conditions=None)[source]¶ Bases:
object
Pattern for matching an expression
Parameters: - head (type or None) – The type (or tuple of types) of the expression that can be matched. If None, any type of Expression matches
- args (list or None) – List or tuple of positional arguments of the matched Expression (cf. Expression.args). Each element is an expression (to be matched exactly) or another Pattern instance (matched recursively). If None, no arguments are checked
- kwargs (dict or None) – Dictionary of keyword arguments of the expression (cf. Expression.kwargs). As for args, each value is an expression or Pattern instance.
- mode (int) – If the pattern is used to match the arguments of an expression, code to indicate how many arguments the Pattern can consume: Pattern.single, Pattern.one_or_more, Pattern.zero_or_more
- wc_name (str or None) – If pattern matches an expression, key in the resulting MatchDict for the expression. If None, the match will not be recorded in the result
- conditions (list of callables, or None) – If not None, a list of callables that take expr and return a boolean value. If the return value os False, the pattern is determined not to match expr.
Note
For (sub-)patterns that occur nested in the args attribute of another pattern, only the first or last sub-pattern may have a mode other than Pattern.single. This also implies that only one of the args may have a mode other than Pattern.single. This restrictions ensures that patterns can be matched without backtracking, thus guaranteeing numerical efficiency.
Example
Consider the following nested circuit expression:
>>> from qnet.algebra.circuit_algebra import * >>> C1 = CircuitSymbol('C1', 3) >>> C2 = CircuitSymbol('C2', 3) >>> C3 = CircuitSymbol('C3', 3) >>> C4 = CircuitSymbol('C4', 3) >>> perm1 = CPermutation((2, 1, 0)) >>> perm2 = CPermutation((0, 2, 1)) >>> concat_expr = Concatenation( ... (C1 << C2 << perm1), ... (C3 << C4 << perm2))
We may match this with the following pattern:
>>> conditions = [lambda c: c.cdim == 3, ... lambda c: c.name[0] == 'C'] >>> A__Circuit = wc("A__", head=CircuitSymbol, ... conditions=conditions) >>> C__Circuit = wc("C__", head=CircuitSymbol, ... conditions=conditions) >>> B_CPermutation = wc("B", head=CPermutation) >>> D_CPermutation = wc("D", head=CPermutation) >>> pattern_concat = pattern( ... Concatenation, ... pattern(SeriesProduct, A__Circuit, B_CPermutation), ... pattern(SeriesProduct, C__Circuit, D_CPermutation)) >>> m = pattern_concat.match(concat_expr)
The match returns the following dictionary:
>>> result = {'A': [C1, C2], 'B': perm1, 'C': [C3, C4], 'D': perm2} >>> assert m == result
-
single
= 1¶
-
one_or_more
= 2¶
-
zero_or_more
= 3¶
-
extended_arg_patterns
()[source]¶ Return an iterator over patterns for positional arguments to be matched. This yields the elements of
args
, extended by their mode value
-
match
(expr) → qnet.algebra.pattern_matching.MatchDict[source]¶ Match the given expression (recursively) and return a MatchDict instance that maps any wildcard names to the expressions that the corresponding wildcard pattern matches. For (sub-)pattern that have a mode attribute other than Pattern.single, the wildcard name is mapped to a list of all matched expression.
If the match is successful, the resulting MatchDict instance will evalute to True in a boolean context. If the match is not successful, it will evaluate as False, and the reason for failure is stored in the reason attribute of the MatchDict object.
-
qnet.algebra.pattern_matching.
pattern
(head, *args, mode=1, wc_name=None, conditions=None, **kwargs) → qnet.algebra.pattern_matching.Pattern[source]¶ ‘Flat’ constructor for the Pattern class, where positional and keyword arguments are mapped into args and kwargs, respectively. Useful for defining rules that match an instantiated Expression with specific arguments
-
qnet.algebra.pattern_matching.
pattern_head
(*args, conditions=None, wc_name=None, **kwargs) → qnet.algebra.pattern_matching.Pattern[source]¶ Helper function to create a Pattern object specfically matching a ProtoExpr. The patterns used associated with _rules and _binary_rules of an Expression subclass must be instantiated through this routine. The function does not allow to set a wildcard name (wc_name must not be given / be None)
-
qnet.algebra.pattern_matching.
wc
(name_mode='_', head=None, args=None, kwargs=None, *, conditions=None) → qnet.algebra.pattern_matching.Pattern[source]¶ Helper function to create a Pattern object with an emphasis on wildcard patterns if we don’t care about the arguments of the matched expressions (otherwise, use
pattern()
)Parameters: The name_mode argument uses trailing underscored to indicate the mode:
A
->Pattern(wc_name="A", mode=Pattern.single, ...)
A_
->Pattern(wc_name="A", mode=Pattern.single, ...)
B__
->Pattern(wc_name="B", mode=Pattern.one_or_more, ...)
B___
->Pattern(wc_name="C", mode=Pattern.zero_or_more, ...)
-
class
qnet.algebra.pattern_matching.
ProtoExpr
(args, kwargs)[source]¶ Bases:
object
Object representing an un-instantiated Expression that may matched by a Pattern created via
pattern_head()
Parameters:
qnet.algebra.permutations module¶
Summary¶
Exceptions:
BadPermutationError |
Can be raised to signal that a permutation does not pass the :py:func:check_permutation test. |
Functions:
block_perm_and_perms_within_blocks |
Decompose a permutation into a block permutation and into permutations acting within each block. |
check_permutation |
Verify that a tuple of permutation image points (sigma(1), sigma(2), ..., sigma(n)) is a valid permutation, i.e. |
compose_permutations |
Find the composite permutation |
concatenate_permutations |
Concatenate two permutations: |
full_block_perm |
Extend a permutation of blocks to a permutation for the internal signals of all blocks. |
invert_permutation |
Compute the image tuple of the inverse permutation. |
permutation_from_block_permutations |
Reverse operation to permutation_to_block_permutations() |
permutation_from_disjoint_cycles |
Reconstruct a permutation image tuple from a list of disjoint cycles |
permutation_to_block_permutations |
If possible, decompose a permutation into a sequence of permutations each acting on individual ranges of the full range of indices. |
permutation_to_disjoint_cycles |
Any permutation sigma can be represented as a product of cycles. |
permute |
Apply a permutation sigma({j}) to an arbitrary sequence. |
Reference¶
-
exception
qnet.algebra.permutations.
BadPermutationError
[source]¶ Bases:
ValueError
Can be raised to signal that a permutation does not pass the :py:func:check_permutation test.
-
qnet.algebra.permutations.
check_permutation
(permutation)[source]¶ Verify that a tuple of permutation image points
(sigma(1), sigma(2), ..., sigma(n))
is a valid permutation, i.e. each number from 0 and n-1 occurs exactly once. I.e. the following set-equality must hold:{sigma(1), sigma(2), ..., sigma(n)} == {0, 1, 2, ... n-1}
Parameters: permutation (tuple) – Tuple of permutation image points Return type: bool
-
qnet.algebra.permutations.
invert_permutation
(permutation)[source]¶ Compute the image tuple of the inverse permutation.
Parameters: permutation – A valid (cf. :py:func:check_permutation) permutation. Returns: The inverse permutation tuple Return type: tuple
-
qnet.algebra.permutations.
permutation_to_disjoint_cycles
(permutation)[source]¶ Any permutation sigma can be represented as a product of cycles. A cycle (c_1, .. c_n) is a closed sequence of indices such that
sigma(c_1) == c_2, sigma(c_2) == sigma^2(c_1)== c_3, ..., sigma(c_(n-1)) == c_n, sigma(c_n) == c_1Any single length-n cycle admits n equivalent representations in correspondence with which element one defines as c_1.
(0,1,2) == (1,2,0) == (2,0,1)A decomposition into disjoint cycles can be made unique, by requiring that the cycles are sorted by their smallest element, which is also the left-most element of each cycle. Note that permutations generated by disjoint cycles commute. E.g.,
(1, 0, 3, 2) == ((1,0),(3,2)) –> ((0,1),(2,3)) normal formParameters: permutation (tuple) – A valid permutation image tuple Returns: A list of disjoint cycles, that when comb Return type: list Raise: BadPermutationError
-
qnet.algebra.permutations.
permutation_from_disjoint_cycles
(cycles, offset=0)[source]¶ Reconstruct a permutation image tuple from a list of disjoint cycles :param cycles: sequence of disjoint cycles :type cycles: list or tuple :param offset: Offset to subtract from the resulting permutation image points :type offset: int :return: permutation image tuple :rtype: tuple
-
qnet.algebra.permutations.
permutation_to_block_permutations
(permutation)[source]¶ If possible, decompose a permutation into a sequence of permutations each acting on individual ranges of the full range of indices. E.g.
(1,2,0,3,5,4) --> (1,2,0) [+] (0,2,1)
Parameters: permutation (tuple) – A valid permutation image tuple s = (s_0,...s_n)
withn > 0
Returns: A list of permutation tuples [t = (t_0,...,t_n1), u = (u_0,...,u_n2),..., z = (z_0,...,z_nm)]
such thats = t [+] u [+] ... [+] z
Return type: list of tuples Raise: ValueError
-
qnet.algebra.permutations.
permutation_from_block_permutations
(permutations)[source]¶ Reverse operation to
permutation_to_block_permutations()
Compute the concatenation of permutations(1,2,0) [+] (0,2,1) --> (1,2,0,3,5,4)
Parameters: permutations (list of tuples) – A list of permutation tuples [t = (t_0,...,t_n1), u = (u_0,...,u_n2),..., z = (z_0,...,z_nm)]
Returns: permutation image tuple s = t [+] u [+] ... [+] z
Return type: tuple
-
qnet.algebra.permutations.
compose_permutations
(alpha, beta)[source]¶ Find the composite permutation
\[\begin{split}\sigma := \alpha \cdot \beta \\ \Leftrightarrow \sigma(j) = \alpha\left(\beta(j)\right) \\\end{split}\]Parameters: - a – first permutation image tuple
- beta (tuple) – second permutation image tuple
Returns: permutation image tuple of the composition.
Return type:
-
qnet.algebra.permutations.
concatenate_permutations
(a, b)[source]¶ - Concatenate two permutations:
- s = a [+] b
Parameters: Returns: permutation image tuple of the concatenation.
Return type:
-
qnet.algebra.permutations.
permute
(sequence, permutation)[source]¶ Apply a permutation sigma({j}) to an arbitrary sequence.
Parameters: - sequence – Any finite length sequence
[l_1,l_2,...l_n]
. If it is a list, tuple or str, the return type will be the same. - permutation (tuple) – permutation image tuple
Returns: The permuted sequence
[l_sigma(1), l_sigma(2), ..., l_sigma(n)]
Raise: BadPermutationError or ValueError
- sequence – Any finite length sequence
-
qnet.algebra.permutations.
full_block_perm
(block_permutation, block_structure)[source]¶ Extend a permutation of blocks to a permutation for the internal signals of all blocks. E.g., say we have two blocks of sizes (‘block structure’)
(2, 3)
, then a block permutation that switches the blocks would be given by the image tuple(1,0)
. However, to get a permutation of all 2+3 = 5 channels that realizes that block permutation we would need(2, 3, 4, 0, 1)
Parameters: Returns: A single permutation for all channels of all blocks.
Return type:
-
qnet.algebra.permutations.
block_perm_and_perms_within_blocks
(permutation, block_structure)[source]¶ Decompose a permutation into a block permutation and into permutations acting within each block.
Parameters: Returns: (block_permutation, permutations_within_blocks)
Whereblock_permutations
is an image tuple for a permutation of the block indices andpermutations_within_blocks
is a list of image tuples for the permutations of the channels within each blockReturn type:
qnet.algebra.singleton module¶
Constant algebraic objects are best implemented as singletons (i.e., they only exist as a single object). This module provides the means to declare singletons:
- The
Singleton
metaclass ensures that every class based on it produces the same object every time it is instantiated - The
singleton_object()
class decorator returns a singleton class definition with the actual singleton object
Singletons in QNET should use both of these.
Summary¶
Classes:
Singleton |
Metaclass for singletons. |
Functions:
singleton_object |
Class decorator that transforms (and replaces) a class definition (which must have a Singleton metaclass) with the actual singleton object. |
__all__
: Singleton
, singleton_object
Reference¶
-
qnet.algebra.singleton.
singleton_object
(cls)[source]¶ Class decorator that transforms (and replaces) a class definition (which must have a Singleton metaclass) with the actual singleton object. Ensures that the resulting object can still be “instantiated” (i.e., called), returning the same object. Also ensures the object can be pickled, is hashable, and has the correct string representation (the name of the singleton)
-
class
qnet.algebra.singleton.
Singleton
[source]¶ Bases:
abc.ABCMeta
Metaclass for singletons. Any instantiation of a Singleton class yields the exact same object, e.g.:
>>> class MyClass(metaclass=Singleton): ... pass >>> a = MyClass() >>> b = MyClass() >>> a is b True
qnet.algebra.state_algebra module¶
This module implements a basic Hilbert space state algebra.
Summary¶
Exceptions:
OverlappingSpaces |
|
SpaceTooLargeError |
|
UnequalSpaces |
Classes:
BasisKet |
Local basis state, labeled by an integer or a string. |
Bra |
The associated dual/adjoint state for any Ket object k is given by Bra(k) . |
BraKet |
The symbolic inner product between two states, represented as Bra and |
CoherentStateKet |
Local coherent state, labeled by a scalar amplitude. |
Ket |
Basic Ket algebra class to represent Hilbert Space states |
KetBra |
A symbolic operator formed by the outer product of two states |
KetPlus |
A sum of Ket states. |
KetSymbol |
Ket symbol class, parametrized by an identifier string and an associated Hilbert space. |
LocalKet |
A state that lives on a single local Hilbert space. |
OperatorTimesKet |
Multiply an operator by an operator |
ScalarTimesKet |
Multiply a Ket by a scalar coefficient. |
TensorKet |
A tensor product of kets each belonging to different degrees of freedom. |
Functions:
act_locally |
|
act_locally_times_tensor |
|
check_kets_same_space |
Check that all operands are from the same Hilbert space. |
check_op_ket_space |
Check that all operands are from the same Hilbert space. |
tensor_decompose_kets |
__all__
: BasisKet
, Bra
, BraKet
, CoherentStateKet
, Ket
, KetBra
, KetPlus
, KetSymbol
, LocalKet
, OperatorTimesKet
, OverlappingSpaces
, ScalarTimesKet
, SpaceTooLargeError
, TensorKet
, TrivialKet
, UnequalSpaces
, ZeroKet
Module data:
Reference¶
-
qnet.algebra.state_algebra.
check_kets_same_space
(cls, ops, kwargs)[source]¶ Check that all operands are from the same Hilbert space.
-
qnet.algebra.state_algebra.
check_op_ket_space
(cls, ops, kwargs)[source]¶ Check that all operands are from the same Hilbert space.
-
class
qnet.algebra.state_algebra.
Ket
[source]¶ Bases:
object
Basic Ket algebra class to represent Hilbert Space states
-
space
¶ The associated HilbertSpace
-
dag
¶ The adjoint of a Ket state, i.e., the corresponding Bra.
-
-
class
qnet.algebra.state_algebra.
KetSymbol
(label, *, hs)[source]¶ Bases:
qnet.algebra.state_algebra.Ket
,qnet.algebra.abstract_algebra.Expression
Ket symbol class, parametrized by an identifier string and an associated Hilbert space.
Parameters: - label (str) – Symbol identifier
- hs (HilbertSpace) – Associated Hilbert space.
-
args
¶
-
kwargs
¶
-
space
¶
-
label
¶
-
class
qnet.algebra.state_algebra.
LocalKet
(label, *, hs)[source]¶ Bases:
qnet.algebra.state_algebra.KetSymbol
A state that lives on a single local Hilbert space. This does not include operations, even if these operations only involve states acting on the same local space
-
class
qnet.algebra.state_algebra.
BasisKet
(label, *, hs)[source]¶ Bases:
qnet.algebra.state_algebra.LocalKet
Local basis state, labeled by an integer or a string. Basis kets are orthornormal
Parameters: - hs (LocalSpace) – The local Hilbert space degree of freedom.
- or int) label ((str) – The basis state label.
-
class
qnet.algebra.state_algebra.
CoherentStateKet
(ampl, *, hs)[source]¶ Bases:
qnet.algebra.state_algebra.LocalKet
Local coherent state, labeled by a scalar amplitude.
Parameters: - hs (LocalSpace) – The local Hilbert space degree of freedom.
- amp (SCALAR_TYPES) – The coherent displacement amplitude.
-
ampl
¶
-
args
¶
-
kwargs
¶
-
class
qnet.algebra.state_algebra.
KetPlus
(*operands)[source]¶ Bases:
qnet.algebra.state_algebra.Ket
,qnet.algebra.abstract_algebra.Operation
A sum of Ket states.
Instantiate as:
KetPlus(*summands)
Parameters: summands (Ket) – State summands. -
neutral_element
= ZeroKet¶
-
order_key
¶ alias of
FullCommutativeHSOrder
-
space
¶
-
-
class
qnet.algebra.state_algebra.
TensorKet
(*operands)[source]¶ Bases:
qnet.algebra.state_algebra.Ket
,qnet.algebra.abstract_algebra.Operation
A tensor product of kets each belonging to different degrees of freedom. Instantiate as:
TensorKet(*factors)
Parameters: factors (Ket) – Ket factors. -
neutral_element
= TrivialKet¶
-
order_key
¶ alias of
FullCommutativeHSOrder
-
factor_for_space
(space)[source]¶ Factor into a Ket defined on the given space and a Ket on the remaining Hilbert space
-
space
¶
-
label
¶ Combined label of the product state if the state is a simple product of LocalKets, raise AttributeError otherwise
-
-
class
qnet.algebra.state_algebra.
ScalarTimesKet
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.state_algebra.Ket
,qnet.algebra.abstract_algebra.Operation
Multiply a Ket by a scalar coefficient.
- Instantiate as::
- ScalarTimesKet(coefficient, term)
Parameters: - coefficient (SCALAR_TYPES) – Scalar coefficient.
- term (Ket) – The ket that is multiplied.
-
space
¶
-
coeff
¶
-
term
¶
-
class
qnet.algebra.state_algebra.
OperatorTimesKet
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.state_algebra.Ket
,qnet.algebra.abstract_algebra.Operation
Multiply an operator by an operator
Instantiate as:
OperatorTimesKet(op, ket)
Parameters: -
space
¶
-
operator
¶
-
ket
¶
-
-
class
qnet.algebra.state_algebra.
Bra
(ket)[source]¶ Bases:
qnet.algebra.abstract_algebra.Operation
The associated dual/adjoint state for any
Ket
objectk
is given byBra(k)
.Parameters: k (Ket) – The state to represent as Bra. -
space
¶
-
label
¶
-
-
class
qnet.algebra.state_algebra.
BraKet
(bra, ket)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
The symbolic inner product between two states, represented as Bra and Ket
In math notation this corresponds to:
\[\langle b | k \rangle\]which we define to be linear in the state \(k\) and anti-linear in \(b\).
Parameters: -
ket
¶
-
bra
¶
-
space
¶
-
-
class
qnet.algebra.state_algebra.
KetBra
(ket, bra)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
A symbolic operator formed by the outer product of two states
Parameters: -
ket
¶
-
bra
¶
-
space
¶
-
qnet.algebra.super_operator_algebra module¶
The specification of a quantum mechanics symbolic super-operator algebra. See The Super-Operator Algebra module for more details.
Summary¶
Exceptions:
BadLiouvillianError |
Raise when a Liouvillian is not of standard Lindblad form. |
CannotSymbolicallyDiagonalize |
Classes:
SPost |
Linear post-multiplication operator. |
SPre |
Linear pre-multiplication operator. |
ScalarTimesSuperOperator |
Multiply an operator by a scalar coefficient: |
SuperAdjoint |
The symbolic SuperAdjoint of a super-operator. |
SuperCommutativeHSOrder |
Ordering class that acts like DisjunctCommutativeHSOrder, but also |
SuperOperator |
The super-operator abstract base class. |
SuperOperatorOperation |
Base class for Operations acting only on SuperOperator arguments. |
SuperOperatorPlus |
A sum of super-operators. |
SuperOperatorSymbol |
Super-operator symbol class, parametrized by an identifier string and an associated Hilbert space. |
SuperOperatorTimes |
A product of super-operators that denotes order of application of |
SuperOperatorTimesOperator |
Application of a super-operator to an operator (result is an Operator). |
Functions:
anti_commutator |
If B != None , return the anti-commutator \(\{A,B\}\), otherwise return the super-operator \(\{A,\cdot\}\). |
commutator |
If B != None , return the commutator \([A,B]\), otherwise return the super-operator \([A,\cdot]\). |
lindblad |
Return SPre(C) * SPost(C.adjoint()) - (1/2) * santi_commutator(C.adjoint()*C) . |
liouvillian |
Return the Liouvillian super-operator associated with a Hamilton operator H and a set of collapse-operators Ls = [L1, L2, ...] . |
liouvillian_normal_form |
Return a Hamilton operator H and a minimal list of collapse operators Ls that generate the liouvillian L . |
__all__
: BadLiouvillianError
, CannotSymbolicallyDiagonalize
, IdentitySuperOperator
, SPost
, SPre
, ScalarTimesSuperOperator
, SuperAdjoint
, SuperCommutativeHSOrder
, SuperOperator
, SuperOperatorOperation
, SuperOperatorPlus
, SuperOperatorSymbol
, SuperOperatorTimes
, SuperOperatorTimesOperator
, ZeroSuperOperator
, anti_commutator
, commutator
, lindblad
, liouvillian
, liouvillian_normal_form
Module data:
Reference¶
-
exception
qnet.algebra.super_operator_algebra.
BadLiouvillianError
[source]¶ Bases:
qnet.algebra.abstract_algebra.AlgebraError
Raise when a Liouvillian is not of standard Lindblad form.
-
class
qnet.algebra.super_operator_algebra.
SuperOperator
[source]¶ Bases:
object
The super-operator abstract base class.
Any super-operator contains an associated HilbertSpace object, on which it is taken to act non-trivially.
-
space
¶ The Hilbert space associated with the operator on which it acts non-trivially
-
superadjoint
()[source]¶ The super-operator adjoint (w.r.t to the
Tr
operation). SeeSuperAdjoint
documentation.Returns: The super-adjoint of the super-operator. Return type: SuperOperator
-
expand
()[source]¶ Expand out distributively all products of sums. Note that this does not expand out sums of scalar coefficients.
Returns: A fully expanded sum of superoperators. Return type: SuperOperator
-
-
class
qnet.algebra.super_operator_algebra.
SuperOperatorOperation
(*operands)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperator
,qnet.algebra.abstract_algebra.Operation
Base class for Operations acting only on SuperOperator arguments.
-
space
¶
-
-
class
qnet.algebra.super_operator_algebra.
SuperOperatorSymbol
(label, *, hs)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperator
,qnet.algebra.abstract_algebra.Expression
Super-operator symbol class, parametrized by an identifier string and an associated Hilbert space.
Instantiate as:
SuperOperatorSymbol(name, hs)
Parameters: - label (str) – Symbol identifier
- hs (HilbertSpace) – Associated Hilbert space.
-
label
¶
-
args
¶
-
kwargs
¶
-
space
¶
-
class
qnet.algebra.super_operator_algebra.
SuperOperatorPlus
(*operands)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperatorOperation
A sum of super-operators.
Instantiate as:
OperatorPlus(*summands)
Parameters: summands (SuperOperator) – super-operator summands. -
neutral_element
= ZeroSuperOperator¶
-
order_key
¶ alias of
FullCommutativeHSOrder
-
-
class
qnet.algebra.super_operator_algebra.
SuperCommutativeHSOrder
(op, space_order=None, op_order=None)[source]¶ Bases:
qnet.algebra.ordering.DisjunctCommutativeHSOrder
Ordering class that acts like DisjunctCommutativeHSOrder, but also commutes any SPost and SPre
-
class
qnet.algebra.super_operator_algebra.
SuperOperatorTimes
(*operands)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperatorOperation
A product of super-operators that denotes order of application of super-operators (right to left):
SuperOperatorTimes(*factors)
Parameters: factors (SuperOperator) – Super-operator factors. -
neutral_element
= IdentitySuperOperator¶
-
order_key
¶ alias of
SuperCommutativeHSOrder
-
-
class
qnet.algebra.super_operator_algebra.
ScalarTimesSuperOperator
(*operands, **kwargs)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperator
,qnet.algebra.abstract_algebra.Operation
Multiply an operator by a scalar coefficient:
ScalarTimesSuperOperator(coeff, term)
Parameters: - coeff (SCALAR_TYPES) – Scalar coefficient.
- term (SuperOperator) – The super-operator that is multiplied.
-
space
¶
-
coeff
¶ The scalar coefficient.
-
term
¶ The super-operator term.
-
class
qnet.algebra.super_operator_algebra.
SuperAdjoint
(operand)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperatorOperation
The symbolic SuperAdjoint of a super-operator.
The math notation for this is typically
\[{\rm SuperAdjoint}(\mathcal{L}) =: \mathcal{L}^*\]and for any super operator \(\mathcal{L}\), its super-adjoint \(\mathcal{L}^*\) satisfies for any pair of operators \(M,N\):
\[{\rm Tr}[M (\mathcal{L}N)] = Tr[(\mathcal{L}^*M) N]\]Parameters: L (SuperOperator) – The super-operator to take the adjoint of. -
operand
¶
-
-
class
qnet.algebra.super_operator_algebra.
SPre
(op)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperator
,qnet.algebra.abstract_algebra.Operation
Linear pre-multiplication operator.
Acting
SPre(A)
on an operatorB
just yields the productA * B
-
space
¶
-
-
class
qnet.algebra.super_operator_algebra.
SPost
(op)[source]¶ Bases:
qnet.algebra.super_operator_algebra.SuperOperator
,qnet.algebra.abstract_algebra.Operation
Linear post-multiplication operator.
Acting
SPost(A)
on an operatorB
just yields the reversed productB * A
.-
space
¶
-
-
class
qnet.algebra.super_operator_algebra.
SuperOperatorTimesOperator
(sop, op)[source]¶ Bases:
qnet.algebra.operator_algebra.Operator
,qnet.algebra.abstract_algebra.Operation
Application of a super-operator to an operator (result is an Operator).
Parameters: - sop (SuperOperator) – The super-operator to apply.
- op (Operator) – The operator it is applied to.
-
space
¶
-
sop
¶
-
op
¶
-
qnet.algebra.super_operator_algebra.
commutator
(A, B=None)[source]¶ If
B != None
, return the commutator \([A,B]\), otherwise return the super-operator \([A,\cdot]\). The super-operator \([A,\cdot]\) maps any other operatorB
to the commutator \([A, B] = A B - B A\).Parameters: Returns: The linear superoperator \([A,\cdot]\)
Return type:
-
qnet.algebra.super_operator_algebra.
anti_commutator
(A, B=None)[source]¶ If
B != None
, return the anti-commutator \(\{A,B\}\), otherwise return the super-operator \(\{A,\cdot\}\). The super-operator \(\{A,\cdot\}\) maps any other operatorB
to the anti-commutator \(\{A, B\} = A B + B A\).Parameters: Returns: The linear superoperator \([A,\cdot]\)
Return type:
-
qnet.algebra.super_operator_algebra.
lindblad
(C)[source]¶ Return
SPre(C) * SPost(C.adjoint()) - (1/2) * santi_commutator(C.adjoint()*C)
. These are the super-operators \(\mathcal{D}[C]\) that form the collapse terms of a Master-Equation. Applied to an operator \(X\) they yield\[\mathcal{D}[C] X = C X C^\dagger - {1\over 2} (C^\dagger C X + X C^\dagger C)\]Parameters: C (Operator) – The associated collapse operator Returns: The Lindblad collapse generator. Return type: SuperOperator
-
qnet.algebra.super_operator_algebra.
liouvillian
(H, Ls=[])[source]¶ Return the Liouvillian super-operator associated with a Hamilton operator
H
and a set of collapse-operatorsLs = [L1, L2, ...]
.The Liouvillian \(\mathcal{L}\) generates the Markovian-dynamics of a system via the Master equation:
\[\dot{\rho} = \mathcal{L}\rho = -i[H,\rho] + \sum_{j=1}^n \mathcal{D}[L_j] \rho\]Parameters: Returns: The Liouvillian super-operator.
Return type:
-
qnet.algebra.super_operator_algebra.
liouvillian_normal_form
(L, symbolic=False)[source]¶ Return a Hamilton operator
H
and a minimal list of collapse operatorsLs
that generate the liouvillianL
.A Liouvillian defined by a hermitian Hamilton operator \(H\) and a vector of collapse operators \(\mathbf{L} = (L_1, L_2, \dots L_n)^T\) is invariant under the following two operations:
\[\begin{split}\left(H, \mathbf{L}\right) & \mapsto \left(H + {1\over 2i}\left(\mathbf{w}^\dagger \mathbf{L} - \mathbf{L}^\dagger \mathbf{w}\right), \mathbf{L} + \mathbf{w} \right) \\ \left(H, \mathbf{L}\right) & \mapsto \left(H, \mathbf{U}\mathbf{L}\right)\\\end{split}\]where \(\mathbf{w}\) is just a vector of complex numbers and \(\mathbf{U}\) is a complex unitary matrix. It turns out that for quantum optical circuit models the set of collapse operators is often linearly dependent. This routine tries to find a representation of the Liouvillian in terms of a Hamilton operator
H
with as few non-zero collapse operatorsLs
as possible. Consider the following example, which results from a two-port linear cavity with a coherent input into the first port:>>> kappa_1, kappa_2 = symbols('kappa_1, kappa_2', positive = True) >>> Delta = symbols('Delta', real = True) >>> alpha = symbols('alpha') >>> H = (Delta * Create(hs=1) * Destroy(hs=1) + ... (sqrt(kappa_1) / (2 * I)) * ... (alpha * Create(hs=1) - alpha.conjugate() * Destroy(hs=1))) >>> Ls = [sqrt(kappa_1) * Destroy(hs=1) + alpha, ... sqrt(kappa_2) * Destroy(hs=1)] >>> LL = liouvillian(H, Ls) >>> Hnf, Lsnf = liouvillian_normal_form(LL) >>> print(ascii(Hnf)) -I*alpha*sqrt(kappa_1) * a^(1)H + I*sqrt(kappa_1)*conjugate(alpha) * a^(1) + Delta * a^(1)H * a^(1) >>> len(Lsnf) 1 >>> print(ascii(Lsnf[0])) sqrt(kappa_1 + kappa_2) * a^(1)
In terms of the ensemble dynamics this final system is equivalent. Note that this function will only work for proper Liouvillians.
Parameters: L (SuperOperator) – The Liouvillian Returns: (H, Ls)
Return type: tuple Raises: BadLiouvillianError
__all__
: ABCD
, Adjoint
, AlgebraError
, AlgebraException
, BadLiouvillianError
, BasisKet
, BasisNotSetError
, Bra
, BraKet
, CIdentity
, CPermutation
, CannotConvertToABCD
, CannotConvertToSLH
, CannotEliminateAutomatically
, CannotSimplify
, CannotSymbolicallyDiagonalize
, CannotVisualize
, Circuit
, CircuitSymbol
, CircuitZero
, CoherentStateKet
, Concatenation
, Create
, Destroy
, Displace
, Expression
, FB
, Feedback
, FullSpace
, HilbertSpace
, II
, IdentityOperator
, IdentitySuperOperator
, ImAdjoint
, ImMatrix
, IncompatibleBlockStructures
, Jminus
, Jmjmcoeff
, Jpjmcoeff
, Jplus
, Jz
, Jzjmcoeff
, Ket
, KetBra
, KetPlus
, KetSymbol
, LocalKet
, LocalOperator
, LocalProjector
, LocalSigma
, LocalSpace
, MatchDict
, Matrix
, NonSquareMatrix
, NullSpaceProjector
, Operation
, Operator
, OperatorOperation
, OperatorPlus
, OperatorPlusMinusCC
, OperatorSymbol
, OperatorTimes
, OperatorTimesKet
, OperatorTrace
, OverlappingSpaces
, P_sigma
, Pattern
, Phase
, ProductSpace
, PseudoInverse
, ReAdjoint
, ReMatrix
, SCALAR_TYPES
, SLH
, SPost
, SPre
, ScalarTimesKet
, ScalarTimesOperator
, ScalarTimesSuperOperator
, SeriesInverse
, SeriesProduct
, SingleOperatorOperation
, SpaceTooLargeError
, Squeeze
, SuperAdjoint
, SuperCommutativeHSOrder
, SuperOperator
, SuperOperatorOperation
, SuperOperatorPlus
, SuperOperatorSymbol
, SuperOperatorTimes
, SuperOperatorTimesOperator
, TensorKet
, TrivialKet
, TrivialSpace
, UnequalSpaces
, WrongCDimError
, WrongSignatureError
, X
, Y
, Z
, ZeroKet
, ZeroOperator
, ZeroSuperOperator
, adjoint
, all_symbols
, anti_commutator
, block_matrix
, cid
, cid_1
, circuit_identity
, commutator
, connect
, create_operator_pm_cc
, decompose_space
, diagm
, eval_adiabatic_limit
, expand_operator_pm_cc
, extra_binary_rules
, extra_rules
, extract_signal
, extract_signal_circuit
, factor_coeff
, factor_for_trace
, getABCD
, get_coeffs
, get_common_block_structure
, hstackm
, identity_matrix
, lindblad
, liouvillian
, liouvillian_normal_form
, map_signals
, map_signals_circuit
, match_pattern
, move_drive_to_H
, no_instance_caching
, no_rules
, pad_with_identity
, pattern
, pattern_head
, permutation_matrix
, prepare_adiabatic_limit
, scalar_free_symbols
, set_union
, simplify
, simplify_scalar
, space
, substitute
, temporary_instance_cache
, try_adiabatic_elimination
, vstackm
, wc
, zerosm
qnet.circuit_components package¶
This module contains all defined primitive circuit component definitions as well as the compiled circuit definitions
that are automatically created via the $QNET/bin/parse_qhdl.py
script.
For some examples on how to create your own circuit definition file, check out the source code to
The module qnet.circuit_components.component
features some base classes for component definitions and the module qnet.circuit_components.library
features some utility functions to help manage the circuit component definitions.
Submodules:
qnet.circuit_components.and_cc module¶
And component
Reference¶
-
class
qnet.circuit_components.and_cc.
And
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
-
CDIM
= 4¶
-
Delta
= 50.0¶
-
chi
= -0.26¶
-
kappa_1
= 20.0¶
-
kappa_2
= 20.0¶
-
kappa_3
= 10.0¶
-
theta
= 0.6435¶
-
phi
= -1.39¶
-
phip
= 2.65¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1']¶
-
B1
¶
-
B2
¶
-
C
¶
-
Phase1
¶
-
Phase2
¶
-
space
¶
-
qnet.circuit_components.beamsplitter_cc module¶
Component definition file for a infinite bandwidth beamsplitter with
variable mixing angle. See Beamsplitter
Reference¶
-
class
qnet.circuit_components.beamsplitter_cc.
Beamsplitter
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
Infinite bandwidth beamsplitter model. It is a pure scattering component, i.e. it’s internal dynamics are not modeled explicitly. The single real parameter theta is the mixing angle for the two signals. Note that there is an asymmetry in the effect on the two input signals due to the minus sign appearing in the scattering matrix
\[\begin{split}S = \begin{pmatrix} \cos{\theta} & -\sin{\theta} \\ \sin{\theta} & \cos{\theta} \end{pmatrix}\end{split}\]To achieve a more general beamsplitter combine this component with one or more
qnet.circuit_components.Phase
components.Instantiate as:
Beamsplitter("B", theta = pi/4)
-
CDIM
= 2¶
-
theta
= pi/4¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1', 'Out2']¶
-
qnet.circuit_components.component module¶
We distinguish between two independent properties of Components:
1) They may be ‘creducible’, i.e. they can be expressed as a circuit expression of sub components.
- They may be ‘primitive’, i.e. they cannot be specified via QHDL
We write ‘creducible’ instead of ‘reducible’ in order to distinguish the meaning from the definition of Gough and James, who define reducible circuits as all circuits that can be decomposed into a concatenation of parts. Creducibility is more general than reducibility since we allow for an expansion into any sort of non-trivial algebraic expression, but in reverse, all reducible circuits are creducible.
Examples of creducible but primitive Components are: KerrCavity, Relay, ...
non-creducible & primitive: Beamsplitter, Phase, Displace
creducible & non-primitive: Any parsed QHDL circuit
non-creducible & non-primitive: None.
Summary¶
Classes:
Component |
Base class for all circuit components, both primitive components such as beamsplitters and cavity models and also composite circuit models that are built up from these. |
SubComponent |
Class for the subcomponents of a reducible (but primitive) Component. |
__all__
: Component
, SubComponent
Reference¶
-
class
qnet.circuit_components.component.
Component
(name, **kwargs)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Expression
Base class for all circuit components, both primitive components such as beamsplitters and cavity models and also composite circuit models that are built up from these. Via the creduce() method, an object can be decomposed into its parts.
-
CDIM
= 0¶
-
PORTSIN
= []¶
-
PORTSOUT
= []¶
-
name
¶
-
args
¶
-
kwargs
¶
-
cdim
¶
-
space
¶
-
-
class
qnet.circuit_components.component.
SubComponent
(parent_component, sub_index)[source]¶ Bases:
qnet.algebra.circuit_algebra.Circuit
,qnet.algebra.abstract_algebra.Expression
Class for the subcomponents of a reducible (but primitive) Component.
-
parent_component
= None¶
-
sub_index
= 0¶
-
PORTSIN
¶ Names of ingoing ports.
-
PORTSOUT
¶ Names of outgoing ports.
-
cdim
¶ Numbers of channels
-
name
¶
-
args
¶
-
space
¶
-
qnet.circuit_components.delay_cc module¶
Component definition file for a pseudo-delay model that works over a limited
bandwidth. See documentation of Delay
.
qnet.circuit_components.displace_cc module¶
Component definition file for a coherent field displacement component.
See documentation of Displace
.
Summary¶
Classes:
Displace |
Coherent displacement of the input field (usually vacuum) by a complex amplitude \(\alpha\). |
__all__
: Displace
Reference¶
-
class
qnet.circuit_components.displace_cc.
Displace
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
Coherent displacement of the input field (usually vacuum) by a complex amplitude \(\alpha\). This component serves as the model of an ideal laser source without internal non-classical internal dynamics.
-
CDIM
= 1¶
-
alpha
= alpha¶
-
PORTSIN
= ['VacIn']¶
-
PORTSOUT
= ['Out1']¶
-
qnet.circuit_components.double_sided_jaynes_cummings_cc module¶
Component definition file for a two mirror CQED Jaynes-Cummings cavity model.
See documentation of DoubleSidedJaynesCummings
.
Summary¶
Classes:
CavityPort |
Sub component model for port coupling the internal mode of a DoubleSidedJaynesCummings model to the external field. |
DecayChannel |
Sub component model for the port coupling the internal two-level atom to the vacuum of the transverse free-field modes, inducing spontaneous emission/decay. |
DoubleSidedJaynesCummings |
Typical CQED Jaynes-Cummings model with a two laser input/output channels with coupling coefficients \(\kappa_1\) and \(\kappa_2\), respectively, and a single atomic decay channel with rate \(\gamma\). |
__all__
: DoubleSidedJaynesCummings
Reference¶
-
class
qnet.circuit_components.double_sided_jaynes_cummings_cc.
DoubleSidedJaynesCummings
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
Typical CQED Jaynes-Cummings model with a two laser input/output channels with coupling coefficients \(\kappa_1\) and \(\kappa_2\), respectively, and a single atomic decay channel with rate \(\gamma\). The full model is given by:
\[\begin{split}S & = \mathbf{1}_3 \\ L & = \begin{pmatrix} \sqrt{\kappa_1}a \\ \sqrt{\kappa_1}a \\ \sqrt{\gamma} \sigma_- \end{pmatrix} \\ H & = \Delta_f a^\dagger a + \Delta_a \sigma_+ \sigma_- + ig\left(\sigma_+ a - \sigma_- a^\dagger \right)\end{split}\]As the model is reducible, sub component models for the mode and the atomic decay channel are given by
CavityPort
andDecayChannel
, respectively.-
CDIM
= 3¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
gamma
= gamma¶
-
g
= g¶
-
Delta_a
= Delta_a¶
-
Delta_f
= Delta_f¶
-
FOCK_DIM
= 20¶
-
PORTSIN
= ['In1', 'In2', 'VacIn']¶
-
PORTSOUT
= ['Out1', 'Out2', 'UOut']¶
-
sub_blockstructure
= (1, 1, 1)¶
-
fock_space
¶ The cavity mode’s Hilbert space.
Type: qnet.algebra.hilbert_space_algebra.LocalSpace
-
tls_space
¶ The two-level-atom’s Hilbert space.
Type: qnet.algebra.hilbert_space_algebra.LocalSpace
-
space
¶
-
-
class
qnet.circuit_components.double_sided_jaynes_cummings_cc.
CavityPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for port coupling the internal mode of a
DoubleSidedJaynesCummings
model to the external field. The Hamiltonian is included with this first port.
-
class
qnet.circuit_components.double_sided_jaynes_cummings_cc.
DecayChannel
(cavity)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the port coupling the internal two-level atom to the vacuum of the transverse free-field modes, inducing spontaneous emission/decay.
qnet.circuit_components.double_sided_opo_cc module¶
Component definition file for a degenerate OPO model with two signal beam ports.
See documentation of DoubleSidedOPO
.
Summary¶
Classes:
DoubleSidedOPO |
This model describes a degenerate OPO with two signal beam ports in the sub-threshold regime. |
OPOPort |
Sub component model for the individual ports of a DoubleSidedOPO . |
__all__
: DoubleSidedOPO
Reference¶
-
class
qnet.circuit_components.double_sided_opo_cc.
DoubleSidedOPO
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a degenerate OPO with two signal beam ports in the sub-threshold regime. I.e., the pump is modeled as a classical amplitude.
The model’s SLH parameters are given by
\[\begin{split}S & = \mathbf{1}_2 \\ L & = \begin{pmatrix} \sqrt{\kappa_1} a \\ \sqrt{\kappa_2} a \end{pmatrix} \\ H &= \Delta a^\dagger a + {i\over 2} \left( \alpha {a^\dagger}^2 - \alpha^* a^2\right)\end{split}\]This particular component definition explicitly captures the reducibility of a trivial scattering matrix. I.e., it can be reduced into separate
OPOPort
models for each port.Note that this model’s validity breaks down even in open-loop configuration when
\[|\alpha| > {\kappa_1 + \kappa_2 \over 2}\]which is just the threshold condition. In a feedback configuration the threshold condition is generally changed.
-
CDIM
= 2¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
alpha
= alpha¶
-
Delta
= Delta¶
-
FOCK_DIM
= 25¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1', 'Out2']¶
-
sub_blockstructure
= (1, 1)¶
-
space
¶
-
-
class
qnet.circuit_components.double_sided_opo_cc.
OPOPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the individual ports of a
DoubleSidedOPO
. The Hamiltonian is included with the first port.
qnet.circuit_components.inverting_fanout_cc module¶
Reference¶
-
class
qnet.circuit_components.inverting_fanout_cc.
InvertingFanout
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
-
CDIM
= 5¶
-
Delta
= 50.0¶
-
chi
= -0.14¶
-
kappa_1
= 20.0¶
-
kappa_2
= 20.0¶
-
kappa_3
= 10.0¶
-
theta
= 0.473¶
-
phi
= -1.45¶
-
phip
= -0.49¶
-
alpha
= -130.0¶
-
PORTSIN
= ['In1']¶
-
PORTSOUT
= ['Out1', 'Out2']¶
-
B1
¶
-
B2
¶
-
B3
¶
-
C
¶
-
Phase1
¶
-
Phase2
¶
-
W
¶
-
space
¶
-
qnet.circuit_components.kerr_cavity_cc module¶
Component definition file for a Kerr-nonlinear cavity model with two ports.
See documentation of KerrCavity
.
Summary¶
Classes:
KerrCavity |
This model describes a Kerr cavity model with two ports. |
KerrPort |
Sub component model for the individual ports of a KerrCavity . |
__all__
: KerrCavity
Reference¶
-
class
qnet.circuit_components.kerr_cavity_cc.
KerrCavity
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a Kerr cavity model with two ports.
The model’s SLH parameters are given by
\[\begin{split}S & = \mathbf{1}_2 \\ L & = \begin{pmatrix} \sqrt{\kappa_1} a \\ \sqrt{\kappa_2} a \end{pmatrix} \\ H &= \Delta a^\dagger a + \chi {a^\dagger}^2 a^2\end{split}\]This particular component definition explicitly captures the reducibility of a trivial scattering matrix. I.e., it can be reduced into separate
KerrPort
models for each port.-
CDIM
= 2¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1', 'Out2']¶
-
sub_blockstructure
= (1, 1)¶
-
Delta
= Delta¶
-
chi
= chi¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
FOCK_DIM
= 75¶
-
space
¶
-
port1
¶
-
port2
¶
-
-
class
qnet.circuit_components.kerr_cavity_cc.
KerrPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the individual ports of a
KerrCavity
. The Hamiltonian is included with the first port.
qnet.circuit_components.latch_cc module¶
Reference¶
-
class
qnet.circuit_components.latch_cc.
Latch
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
-
CDIM
= 8¶
-
Delta
= 50.0¶
-
chi
= -0.205¶
-
kappa_1
= 20.0¶
-
kappa_2
= 20.0¶
-
kappa_3
= 10.0¶
-
theta
= 0.891¶
-
thetap
= 0.593¶
-
phi
= 2.72¶
-
phip
= 0.14¶
-
beta
= (-79.838356622-35.806239846j)¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1']¶
-
B11
¶
-
B12
¶
-
B21
¶
-
B22
¶
-
B3
¶
-
C1
¶
-
C2
¶
-
Phase1
¶
-
Phase2
¶
-
Phase3
¶
-
W1
¶
-
W2
¶
-
space
¶
-
qnet.circuit_components.library module¶
This module features some helper functions for automatically creating and managing a library of circuit component definition files.
Summary¶
Functions:
camelcase_to_underscore |
Convert a camelcase entity name into an appropriate underscore name to import its corresponding module |
getCDIM |
Get the channel dimension of a referenced subcomponent |
make_namespace_string |
Make a namespace string by combining a namespace string with a new name. |
write_component |
Write a new entity definition to a python module file. |
Reference¶
-
qnet.circuit_components.library.
make_namespace_string
(namespace, sub_name)[source]¶ Make a namespace string by combining a namespace string with a new name.
Parameters: Returns: The combined namespace
Return type:
-
qnet.circuit_components.library.
camelcase_to_underscore
(st)¶ Convert a camelcase entity name into an appropriate underscore name to import its corresponding module
-
qnet.circuit_components.library.
getCDIM
(component_name)[source]¶ Get the channel dimension of a referenced subcomponent
Parameters: component_name (str) – The entity name of the component Returns: The channel dimension of the component. Return type: int
-
qnet.circuit_components.library.
write_component
(entity, architectures, local=False)[source]¶ Write a new entity definition to a python module file.
Parameters: - entity (
qnet.qhdl.qhdl.Entity
) – The entity object - architectures (dict) – A dictionary of architectures
dict(name = architecture)
associated with the entity. - local (bool) – Whether or not to store the created module in the current/local directory or install it in :py:module:
qnet.circuit_components
, default =False
Returns: The filename of the new module.
Return type: - entity (
qnet.circuit_components.linear_cavity_cc module¶
Component definition file for a simple linear cavity model with two ports.
See documentation of LinearCavity
.
Summary¶
Classes:
CavityPort |
Sub component model for the individual ports of a LinearCavity . |
LinearCavity |
This model describes a cavity model with two ports. |
__all__
: LinearCavity
Reference¶
-
class
qnet.circuit_components.linear_cavity_cc.
LinearCavity
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a cavity model with two ports.
The model’s SLH parameters are given by
\[\begin{split}S & = \mathbf{1}_2 \\ L & = \begin{pmatrix} \sqrt{\kappa_1} a \\ \sqrt{\kappa_2} a \end{pmatrix} \\ H &= \Delta a^\dagger a\end{split}\]This particular component definition explicitly captures the reducibility of a trivial scattering matrix. I.e., it can be reduced into separate
CavityPort
models for each port.-
CDIM
= 2¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1', 'Out2']¶
-
sub_blockstructure
= (1, 1)¶
-
Delta
= Delta¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
FOCK_DIM
= 75¶
-
space
¶
-
port1
¶
-
port2
¶
-
-
class
qnet.circuit_components.linear_cavity_cc.
CavityPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the individual ports of a
LinearCavity
. The Hamiltonian is included with the first port.
qnet.circuit_components.mach_zehnder_cc module¶
qnet.circuit_components.phase_cc module¶
Component definition file for a coherent field Phasement component.
See documentation of Phase
.
qnet.circuit_components.pseudo_nand_cc module¶
Reference¶
-
class
qnet.circuit_components.pseudo_nand_cc.
PseudoNAND
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
-
CDIM
= 4¶
-
Delta
= Delta¶
-
chi
= chi¶
-
kappa
= kappa¶
-
phi
= phi¶
-
theta
= theta¶
-
beta
= beta¶
-
PORTSIN
= ['A', 'B', 'VIn1', 'VIn2']¶
-
PORTSOUT
= ['UOut1', 'UOut2', 'NAND_AB', 'OUT2']¶
-
BS1
¶
-
BS2
¶
-
K
¶
-
P
¶
-
W_beta
¶
-
space
¶
-
qnet.circuit_components.pseudo_nand_latch_cc module¶
Reference¶
-
class
qnet.circuit_components.pseudo_nand_latch_cc.
PseudoNANDLatch
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
-
CDIM
= 6¶
-
PORTSIN
= ['NS', 'W1', 'kerr2_extra', 'NR', 'W2', 'kerr1_extra']¶
-
PORTSOUT
= ['BS1_1_out', 'kerr1_out2', 'OUT2_2', 'BS1_2_out', 'kerr2_out2', 'OUT2_1']¶
-
NAND1
¶
-
NAND2
¶
-
space
¶
-
qnet.circuit_components.relay_cc module¶
Component definition file for an all-optical Relay model.
See documentation of Relay
.
Summary¶
Classes:
Relay |
This is the Relay model as used in our group’s QEC papers [1],[#qec2]_. |
RelayControl |
Second subcomponent of a Relay model. |
RelayOut |
First subcomponent of a Relay model. |
__all__
: Relay
Reference¶
-
class
qnet.circuit_components.relay_cc.
Relay
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This is the Relay model as used in our group’s QEC papers [1],[#qec2]_. The
SET
andRESET
inputs control whether thePOW
input is routed through theOUT
or theNOUT
output port.Since the scattering matrix is of block diagonal form (2x2,2x2) we provide sub component models for the individual subsystems
RelayOut
andRelayControl
.[1] (1, 2) http://pra.aps.org/abstract/PRA/v80/i4/e045802 [2] http://prl.aps.org/abstract/PRL/v105/i4/e040502 -
CDIM
= 4¶
-
PORTSIN
= ['POW', 'VIn', 'SET', 'RESET']¶
-
PORTSOUT
= ['NOUT', 'OUT', 'UOut1', 'UOut2']¶
-
sub_blockstructure
= (2, 2)¶
-
space
¶
-
-
class
qnet.circuit_components.relay_cc.
RelayOut
(relay)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
First subcomponent of a
Relay
model.
-
class
qnet.circuit_components.relay_cc.
RelayControl
(relay)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Second subcomponent of a
Relay
model.
qnet.circuit_components.relay_double_probe_cc module¶
Component definition file for an all-optical Relay model.
See documentation of Relay
.
Summary¶
Classes:
RelayControl |
Second subcomponent of a Relay model. |
RelayDoubleProbe |
This is the Relay model as used in our group’s QEC papers [1],[#qec2]_. |
RelayOut |
First subcomponent of a Relay model. |
__all__
: RelayDoubleProbe
Reference¶
-
class
qnet.circuit_components.relay_double_probe_cc.
RelayDoubleProbe
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This is the Relay model as used in our group’s QEC papers [1],[#qec2]_. The
SET
andRESET
inputs control whether thePOW
input is routed through theOUT
or theNOUT
output port.Since the scattering matrix is of block diagonal form (2x2,2x2) we provide sub component models for the individual subsystems
RelayOut
andRelayControl
.[1] (1, 2) http://pra.aps.org/abstract/PRA/v80/i4/e045802 [2] http://prl.aps.org/abstract/PRL/v105/i4/e040502 -
CDIM
= 6¶
-
PORTSIN
= ['POW1', 'VIn1', 'POW2', 'VIn2', 'SET', 'RESET']¶
-
PORTSOUT
= ['NOUT1', 'OUT1', 'NOUT2', 'OUT2', 'UOut1', 'UOut2']¶
-
sub_blockstructure
= (2, 2, 2)¶
-
space
¶
-
-
class
qnet.circuit_components.relay_double_probe_cc.
RelayOut
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
First subcomponent of a
Relay
model.
-
class
qnet.circuit_components.relay_double_probe_cc.
RelayControl
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Second subcomponent of a
Relay
model.
qnet.circuit_components.single_sided_jaynes_cummings_cc module¶
Component definition file for a single mirror CQED Jaynes-Cummings cavity model.
See documentation of SingleSidedJaynesCummings
.
Summary¶
Classes:
CavityPort |
Sub component model for port coupling the internal mode of a SingleSidedJaynesCummings model to the external field. |
DecayChannel |
Sub component model for the port coupling the internal two-level atom to the vacuum of the transverse free-field modes, inducing spontaneous emission/decay. |
SingleSidedJaynesCummings |
Typical CQED Jaynes-Cummings model with a single laser input/output channel with coupling coefficient \(\kappa\) and a single atomic decay channel with rate \(\gamma\). |
__all__
: SingleSidedJaynesCummings
Reference¶
-
class
qnet.circuit_components.single_sided_jaynes_cummings_cc.
SingleSidedJaynesCummings
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
Typical CQED Jaynes-Cummings model with a single laser input/output channel with coupling coefficient \(\kappa\) and a single atomic decay channel with rate \(\gamma\). The full model is given by:
\[\begin{split}S & = \mathbf{1}_2 \\ L & = \begin{pmatrix} \sqrt{\kappa}a \\ \sqrt{\gamma} \sigma_- \end{pmatrix} \\ H & = \Delta_f a^\dagger a + \Delta_a \sigma_+ \sigma_- + ig\left(\sigma_+ a - \sigma_- a^\dagger \right)\end{split}\]As the model is reducible, sub component models for the mode and the atomic decay channel are given by
CavityPort
andDecayChannel
, respectively.-
CDIM
= 2¶
-
kappa
= kappa¶
-
gamma
= gamma¶
-
g
= g¶
-
Delta_a
= Delta_a¶
-
Delta_f
= Delta_f¶
-
FOCK_DIM
= 20¶
-
PORTSIN
= ['In1', 'VacIn']¶
-
PORTSOUT
= ['Out1', 'UOut']¶
-
sub_blockstructure
= (1, 1)¶
-
fock_space
¶ The cavity mode’s Hilbert space.
Type: qnet.algebra.hilbert_space_algebra.LocalSpace
-
tls_space
¶ The two-level-atom’s Hilbert space.
Type: qnet.algebra.hilbert_space_algebra.LocalSpace
-
-
class
qnet.circuit_components.single_sided_jaynes_cummings_cc.
CavityPort
(cavity)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for port coupling the internal mode of a
SingleSidedJaynesCummings
model to the external field. The Hamiltonian is included with this first port.
-
class
qnet.circuit_components.single_sided_jaynes_cummings_cc.
DecayChannel
(cavity)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the port coupling the internal two-level atom to the vacuum of the transverse free-field modes, inducing spontaneous emission/decay.
qnet.circuit_components.single_sided_opo_cc module¶
Component definition file for a degenerate OPO model with a single port for the signal beam.
See documentation of SingleSidedOPO
.
Summary¶
Classes:
SingleSidedOPO |
This model describes a degenerate OPO with a single port for the signal mode in the sub-threshold regime: i.e., the pump is modeled as a classical amplitude. |
__all__
: SingleSidedOPO
Reference¶
-
class
qnet.circuit_components.single_sided_opo_cc.
SingleSidedOPO
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a degenerate OPO with a single port for the signal mode in the sub-threshold regime: i.e., the pump is modeled as a classical amplitude.
The model’s SLH parameters are given by
\[\begin{split}S & = (1) \\ L & = \begin{pmatrix} \sqrt{\kappa} a \end{pmatrix} \\ H &= \Delta a^\dagger a + {i\over 2} \left( \alpha {a^\dagger}^2 - \alpha^* a^2\right)\end{split}\]-
CDIM
= 1¶
-
kappa
= kappa¶
-
alpha
= alpha¶
-
Delta
= Delta¶
-
FOCK_DIM
= 25¶
-
PORTSIN
= ['In1']¶
-
PORTSOUT
= ['Out1']¶
-
space
¶
-
qnet.circuit_components.three_port_kerr_cavity_cc module¶
Component definition file for a Kerr-nonlinear cavity model with two ports.
See documentation of ThreePortKerrCavity
.
Summary¶
Classes:
KerrPort |
Sub component model for the individual ports of a ThreePortKerrCavity . |
ThreePortKerrCavity |
This model describes a Kerr cavity model with three ports. |
__all__
: ThreePortKerrCavity
Reference¶
-
class
qnet.circuit_components.three_port_kerr_cavity_cc.
ThreePortKerrCavity
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a Kerr cavity model with three ports.
The model’s SLH parameters are given by
\[\begin{split}S & = \mathbf{1}_3 \\ L & = \begin{pmatrix} \sqrt{\kappa_1} a \\ \sqrt{\kappa_2} a \\ \sqrt{\kappa_3} a\end{pmatrix} \\ H &= \Delta a^\dagger a + \chi {a^\dagger}^2 a^2\end{split}\]This particular component definition explicitly captures the reducibility of a trivial scattering matrix. I.e., it can be reduced into separate
KerrPort
models for each port.-
CDIM
= 3¶
-
PORTSIN
= ['In1', 'In2', 'In3']¶
-
PORTSOUT
= ['Out1', 'Out2', 'Out3']¶
-
sub_blockstructure
= (1, 1, 1)¶
-
Delta
= Delta¶
-
chi
= chi¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
kappa_3
= kappa_3¶
-
FOCK_DIM
= 75¶
-
space
¶
-
port1
¶
-
port2
¶
-
port3
¶
-
-
class
qnet.circuit_components.three_port_kerr_cavity_cc.
KerrPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the individual ports of a
ThreePortKerrCavity
. The Hamiltonian is included with the first port.
qnet.circuit_components.three_port_opo_cc module¶
Component definition file for a degenerate OPO model with three signal beam ports.
See documentation of ThreePortOPO
.
Summary¶
Classes:
OPOPort |
Sub component model for the individual ports of a ThreePortOPO . |
ThreePortOPO |
This model describes a degenerate OPO with three signal beam ports in the sub-threshold regime. |
__all__
: ThreePortOPO
Reference¶
-
class
qnet.circuit_components.three_port_opo_cc.
ThreePortOPO
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a degenerate OPO with three signal beam ports in the sub-threshold regime. I.e., the pump is modeled as a classical amplitude.
The model’s SLH parameters are given by
\[\begin{split}S & = \identity_3 \\ L & = \begin{pmatrix} \sqrt{\kappa_1} a \\ \sqrt{\kappa_2} a \\ \sqrt{\kappa_3} a \end{pmatrix} \\ H &= \Delta a^\dagger a + {i\over 2} \left( \alpha {a^\dagger}^2 - \alpha^* a^2\right)\end{split}\]This particular component definition explicitly captures the reducibility of a trivial scattering matrix. I.e., it can be reduced into separate
OPOPort
models for each port.Note that this model’s validity breaks down even in open-loop configuration when
\[|\alpha| > {\kappa_1 + \kappa_2 + \kappa_3\over 2}\]which is just the threshold condition. In a feedback configuration the threshold condition is generally changed.
-
CDIM
= 3¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
kappa_3
= kappa_2¶
-
alpha
= alpha¶
-
Delta
= Delta¶
-
FOCK_DIM
= 25¶
-
PORTSIN
= ['In1', 'In2', 'In3']¶
-
PORTSOUT
= ['Out1', 'Out2', 'In3']¶
-
sub_blockstructure
= (1, 1, 1)¶
-
space
¶
-
-
class
qnet.circuit_components.three_port_opo_cc.
OPOPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the individual ports of a
ThreePortOPO
. The Hamiltonian is included with the first port.
qnet.circuit_components.two_port_kerr_cavity_cc module¶
Component definition file for a Kerr-nonlinear cavity model with two ports.
See documentation of TwoPortKerrCavity
.
Summary¶
Classes:
KerrPort |
Sub component model for the individual ports of a TwoPortKerrCavity . |
TwoPortKerrCavity |
This model describes a Kerr cavity model with two ports. |
__all__
: TwoPortKerrCavity
Reference¶
-
class
qnet.circuit_components.two_port_kerr_cavity_cc.
TwoPortKerrCavity
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This model describes a Kerr cavity model with two ports.
The model’s SLH parameters are given by
\[\begin{split}S & = \mathbf{1}_2 \\ L & = \begin{pmatrix} \sqrt{\kappa_1} a \\ \sqrt{\kappa_2} \end{pmatrix} \\ H &= \Delta a^\dagger a + \chi {a^\dagger}^2 a^2\end{split}\]This particular component definition explicitly captures the reducibility of a trivial scattering matrix. I.e., it can be reduced into separate
KerrPort
models for each port.-
CDIM
= 2¶
-
PORTSIN
= ['In1', 'In2']¶
-
PORTSOUT
= ['Out1', 'Out2']¶
-
sub_blockstructure
= (1, 1, 1)¶
-
Delta
= Delta¶
-
chi
= chi¶
-
kappa_1
= kappa_1¶
-
kappa_2
= kappa_2¶
-
FOCK_DIM
= 75¶
-
space
¶
-
port1
¶
-
port2
¶
-
-
class
qnet.circuit_components.two_port_kerr_cavity_cc.
KerrPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Sub component model for the individual ports of a
TwoPortKerrCavity
. The Hamiltonian is included with the first port.
qnet.circuit_components.z_probe_cavity_cc module¶
Component definition file for the Z-probe cavity model from the Mabuchi-Lab Coherent Feedback Quantum Error Correction papers.
See documentation of ZProbeCavity
.
Summary¶
Classes:
FeedbackPort |
Feedback beam port for the Z-Probe cavity model. |
LossPort |
Spontaneous decay from the far detuned excited r level. |
ProbePort |
Probe beam port for the Z-Probe cavity model. |
ZProbeCavity |
This is the Z-probe cavity model as used in our group’s QEC papers [#qec1,#qec2]_ , which has three (dressed) internal states: r, g, h. |
__all__
: ZProbeCavity
Reference¶
-
class
qnet.circuit_components.z_probe_cavity_cc.
ZProbeCavity
(name, **kwargs)[source]¶ Bases:
qnet.circuit_components.component.Component
This is the Z-probe cavity model as used in our group’s QEC papers [#qec1,#qec2]_ , which has three (dressed) internal states: r, g, h. The qubit is encoded in g,h, while r is used to drive transitions. The first channel is the probe-signal, while the second and third channels are the two independent feedback beams.
Since the scattering matrix is diagonal we provide sub component models for the individual subsystems: One
ProbePort
and twoFeedbackPort
instances..-
CDIM
= 5¶
-
gamma
= gamma¶
-
gamma_p
= gamma_p¶
-
Delta
= Delta¶
-
PORTSIN
= ['PIn', 'FIn1', 'FIn2']¶
-
PORTSOUT
= ['POut']¶
-
sub_blockstructure
= (1, 1, 1, 1, 1)¶
-
space
¶
-
-
class
qnet.circuit_components.z_probe_cavity_cc.
ProbePort
(cavity)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Probe beam port for the Z-Probe cavity model.
-
class
qnet.circuit_components.z_probe_cavity_cc.
FeedbackPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Feedback beam port for the Z-Probe cavity model.
-
class
qnet.circuit_components.z_probe_cavity_cc.
LossPort
(parent_component, sub_index)[source]¶ Bases:
qnet.circuit_components.component.SubComponent
Spontaneous decay from the far detuned excited r level.
__all__
: And
, Beamsplitter
, Component
, Delay
, Displace
, DoubleSidedJaynesCummings
, DoubleSidedOPO
, InvertingFanout
, KerrCavity
, Latch
, LinearCavity
, MachZehnder
, OpenLossy
, Phase
, PseudoNAND
, PseudoNANDLatch
, Relay
, RelayDoubleProbe
, SingleSidedJaynesCummings
, SingleSidedOPO
, SubComponent
, ThreePortKerrCavity
, ThreePortOPO
, TwoPortKerrCavity
, ZProbeCavity
qnet.convert package¶
Submodules:
qnet.convert.to_qutip module¶
Conversion of QNET expressions to qutip objects.
Summary¶
Functions:
SLH_to_qutip |
Generate and return QuTiP representation matrices for the Hamiltonian and the collapse operators. |
convert_to_qutip |
Convert a QNET expression to a qutip object |
__all__
: SLH_to_qutip
, convert_to_qutip
Reference¶
-
qnet.convert.to_qutip.
convert_to_qutip
(expr, full_space=None, mapping=None)[source]¶ Convert a QNET expression to a qutip object
Parameters: - expr – a QNET expression
- full_space (HilbertSpace) – The
Hilbert space in which expr is defined. If not given,
expr.space
is used. The Hilbert space must have a well-defined basis. - mapping (dict) – A mapping of any (sub-)expression to either a quip.Qobj directly, or to a callable that will convert the expression into a qutip.Qobj. Useful for e.g. supplying objects for symbols
Raises: ValueError
– if expr is not in full_space, or if expr cannot be converted.
-
qnet.convert.to_qutip.
SLH_to_qutip
(slh, full_space=None, time_symbol=None, convert_as='pyfunc')[source]¶ Generate and return QuTiP representation matrices for the Hamiltonian and the collapse operators. Any inhomogeneities in the Lindblad operators (resulting from coherent drives) will be moved into the Hamiltonian, cf.
move_drive_to_H()
.Parameters: - slh (SLH) – The SLH object from which to generate the qutip data
- full_space (HilbertSpace or None) – The Hilbert space in which to represent the operators. If None, the space of shl will be used
- time_symbol (
sympy.Symbol
or None) – The symbol (if any) expressing time dependence (usually ‘t’) - convert_as (str) – How to express time dependencies to qutip. Must be ‘pyfunc’ or ‘str’
Returns: tuple
(H, [L1, L2, ...])
as numerical qutip.Qobj representations, whereH
and eachL
may be a nested list to express time dependence, e.g.H = [H0, [H1, eps_t]]
, whereH0
andH1
are of type qutip.Qobj, andeps_t
is either a string (convert_as='str'
) or a function (convert_as='pyfunc'
)Raises: AlgebraError
– If the Hilbert space (slh.space or full_space) is invalid for numerical conversion
qnet.convert.to_sympy_matrix module¶
Conversion of QNET expressions to sympy matrices. For small Hilbert spaces, this facilitates some analytic treatments, such as decomposition into a basis.
Summary¶
Functions:
SympyCreate |
Creation operator for a Hilbert space of dimension n, as an instance |
basis_state |
n x 1 sympy.Matrix representing the i‘th eigenstate of an |
convert_to_sympy_matrix |
Convert a QNET expression to an explicit n x n instance of sympy.Matrix, where n is the dimension of full_space. |
__all__
: convert_to_sympy_matrix
Reference¶
-
qnet.convert.to_sympy_matrix.
basis_state
(i, n)[source]¶ n x 1
sympy.Matrix representing the i‘th eigenstate of an n-dimensional Hilbert space (i >= 0)
-
qnet.convert.to_sympy_matrix.
SympyCreate
(n)[source]¶ Creation operator for a Hilbert space of dimension n, as an instance of sympy.Matrix
-
qnet.convert.to_sympy_matrix.
convert_to_sympy_matrix
(expr, full_space=None)[source]¶ Convert a QNET expression to an explicit
n x n
instance of sympy.Matrix, wheren
is the dimension of full_space. The entries of the matrix may contain symbols.Parameters: - expr – a QNET expression
- full_space (qnet.algebra.hilbert_space_algebra.HilbertSpace) – The
Hilbert space in which expr is defined. If not given,
expr.space
is used. The Hilbert space must have a well-defined basis.
Raises: qnet.algebra.hilbert_space_algebra.BasisNotSetError
– if full_space does not have a defined basisValueError
– if expr is not in full_space, or if expr cannot be converted.
__all__
: SLH_to_qutip
, convert_to_qutip
, convert_to_sympy_matrix
qnet.misc package¶
Submodules:
qnet.misc.circuit_visualization module¶
Summary¶
Functions:
draw_circuit |
Generate a graphic representation of circuit and store them in a file. |
draw_circuit_canvas |
Generate a PyX graphical representation of a circuit expression object. |
__all__
: draw_circuit
, draw_circuit_canvas
Reference¶
-
qnet.misc.circuit_visualization.
draw_circuit_canvas
(circuit, hunit=4, vunit=-1.0, rhmargin=0.1, rvmargin=0.2, rpermutation_length=0.4, draw_boxes=True, permutation_arrows=False)[source]¶ Generate a PyX graphical representation of a circuit expression object.
Parameters: - circuit (ca.Circuit) – The circuit expression
- hunit (float) – The horizontal length unit, default =
HUNIT
- vunit (float) – The vertical length unit, default =
VUNIT
- rhmargin (float) – relative horizontal margin, default =
RHMARGIN
- rvmargin (float) – relative vertical margin, default =
RVMARGIN
- rpermutation_length (float) – the relative length of a permutation circuit, default =
RPLENGTH
- draw_boxes (bool) – Whether to draw indicator boxes to denote subexpressions (Concatenation, SeriesProduct, etc.), default =
True
- permutation_arrows (bool) – Whether to draw arrows within the permutation visualization, default =
False
Returns: A PyX canvas object that can be further manipulated or printed to an output image.
Return type: pyx.canvas.canvas
-
qnet.misc.circuit_visualization.
draw_circuit
(circuit, filename, direction='lr', hunit=4, vunit=-1.0, rhmargin=0.1, rvmargin=0.2, rpermutation_length=0.4, draw_boxes=True, permutation_arrows=False)[source]¶ Generate a graphic representation of circuit and store them in a file. The graphics format is determined from the file extension.
Parameters: - circuit (ca.Circuit) – The circuit expression
- filename (str) – A filepath to store the output image under. The file name suffix determines the output graphics format
- direction – The horizontal direction of laying out series products. One of
'lr'
and'rl'
. This option overrides a negative value forhunit
, default ='lr'
- hunit (float) – The horizontal length unit, default =
HUNIT
- vunit (float) – The vertical length unit, default =
VUNIT
- rhmargin (float) – relative horizontal margin, default =
RHMARGIN
- rvmargin (float) – relative vertical margin, default =
RVMARGIN
- rpermutation_length (float) – the relative length of a permutation circuit, default =
RPLENGTH
- draw_boxes (bool) – Whether to draw indicator boxes to denote subexpressions (Concatenation, SeriesProduct, etc.), default =
True
- permutation_arrows (bool) – Whether to draw arrows within the permutation visualization, default =
False
Returns: True
if printing was successful,False
if not.Return type:
qnet.misc.euler_mayurama module¶
Reference¶
-
qnet.misc.euler_mayurama.
euler_mayurama_complex
(f, g, x0, m, h, steps_per_sample, n_samples, include_initial=False)[source]¶ Evaluate the Ito-SDE
\[dx = f(x,t)dt + g(x,t)dA_t\]using an Euler-Mayurama scheme with fixed stepsize \(h\).
Parameters: - f – function for drift term
- g – function for diffusion term
- x0 – initial value
- m – number of complex noises
- steps_per_sample – The number of $h$-sized steps between samples
- n_samples – the total number of integration steps
- include_initial – whether or not to include the initial value (and time) in the output.
Returns: a tuple
(times, xs, dAs)
, wheretimes
is an array of times at which x is evaluated,xs
is \(x\) at different times, anddAs
are the noise increments for the time interval \([t, t+h)\)
qnet.misc.kerr_model_matrices module¶
Summary¶
Functions:
T_a_qp |
Basis transfer matrix, [[a],[a.conjugate()]] = T_a_qp.dot(qp) , |
T_qp_a |
Basis transfer matrix, qp = T_qp_a.dot([[a],[a.conjugate()]]) |
model_matrices |
Return the matrices necessary to carry out a semi-classical simulation of the SLH system driven by some dynamic inputs. |
model_matrices_complex |
Same as model_matrices() but tries to convert all output to purely |
model_matrices_symbolic |
Same as model_matrices() but converts all output to Matrix objects. |
prepare_sde |
Compute the SDE functions f, g and (optionally) the Jacobian of f (see euler_mayurama docs) for the model matrices. |
substitute_into_symbolic_model_matrices |
|
wrap_Jqp |
Wrap the jacobian of a complex ode function f(a,t) as f(qp, t) , |
wrap_fqp |
Wrap a complex ode function f(a,t) as f(qp, t) where |
Reference¶
-
qnet.misc.kerr_model_matrices.
model_matrices
(slh, dynamic_input_ports, apply_kerr_diagonal_correction=True, epsilon=0.0, return_eoms=False)[source]¶ Return the matrices necessary to carry out a semi-classical simulation of the SLH system driven by some dynamic inputs.
Parameters: - slh – SLH object
- dynamic_input_ports (dict) – Mapping of port index to
input_name_str
- apply_kerr_diagonal_correction (bool) – whether there should be an effective detuning of 2 chi for every kerr-cavity.
- epsilon (float) – for non-zero epsilon (and a numerical coefficient slh) remove expressions with coefficents smaller than epsilon.
- return_eoms (bool) – Whether to also return the symbolic e.o.m.’s as well as the output processes.
Returns: A tuple
(A, B, C, D, A_kerr, B_input, D_input, u_c, U_c[, eoms, dA'])
A
: coupling of modes to each otherB
: coupling of external input fields to modesC
: coupling of internal modes to outputD
: coupling of external input fields to output fieldsA_kerr
: kerr-type coupling between modesB_input
: coupling of dynamic inputs to modesD_input
: coupling of dynamic inputs to external output fieldsu_c
: constant coherent input driving to modesU_c
: constant coherent input contribution to output fieldeoms
: symbolic QSDEs for the internal modes (if return_eoms is True, None otherwise)dA
: symbolic expression for the output fields (if return_eoms is True, None otherwise)
The overall SDE is then:
\begin{align} da_t/dt &= (A a_t + (A_{kerr} (a_t \odot a_t^*)) \odot a_t + u_c + B_{input} u_t) + B dA_t/dt \\ dA'_t/dt &= (C * a_t + U_c + D_{input} u_t) + D dA_t/dt \end{align}where \(\odot\) denotes the element-wise product of two vectors. It is assumed that all degrees of freedom are cavities with their only non-linearity being of the Kerr-type, i.e. either self coupling \(H_{kerr} = a^*a^* a a\) or cross-coupling \(H_{kerr} = a^*a b^*b\).
-
qnet.misc.kerr_model_matrices.
model_matrices_complex
(*args, **kwargs)[source]¶ Same as
model_matrices()
but tries to convert all output to purely numerical matrices
-
qnet.misc.kerr_model_matrices.
model_matrices_symbolic
(*args, **kwargs)[source]¶ Same as
model_matrices()
but converts all output toMatrix
objects.
-
qnet.misc.kerr_model_matrices.
substitute_into_symbolic_model_matrices
(model_matrices, params)[source]¶
-
qnet.misc.kerr_model_matrices.
prepare_sde
(numeric_model_matrices, input_fn, return_jac=False)[source]¶ Compute the SDE functions f, g and (optionally) the Jacobian of f (see euler_mayurama docs) for the model matrices.
Returns: f, g[, Jf]
The overall SDE is:
\begin{align} da_t/dt &= (A a_t + (A_{kerr} (a_t \odot a_t^*) \odot a_t + u_c + B_{input} u_t) + B dA_t/dt \\ dA'_t/dt &= (C a_t + U_c + D_{input} u_t) + D dA_t/dt \end{align}
-
qnet.misc.kerr_model_matrices.
wrap_fqp
(f)[source]¶ Wrap a complex ode function
f(a,t)
asf(qp, t)
whereqp = [a1r, a1i, a2r, a2i,...]
-
qnet.misc.kerr_model_matrices.
T_qp_a
(n)[source]¶ Basis transfer matrix,
qp = T_qp_a.dot([[a],[a.conjugate()]])
qnet.misc.parse_circuit_strings module¶
Parse strings into Circuit expressions. See documentation for parse_circuit_strings()
Summary¶
Exceptions:
ParseCircuitStringError |
Raised when an error is encountered while parsing a circuit expression string. |
Functions:
parse_circuit_strings |
Parse strings for symbolic Circuit expressions into actual expression objects. |
Reference¶
-
qnet.misc.parse_circuit_strings.
parse_circuit_strings
(circuit_string)[source]¶ Parse strings for symbolic Circuit expressions into actual expression objects.
Parameters: circuit_string – A string containing one or more circuit expressions in the special syntax described below. Returns: A list of all parsed expressions if there are more than one, otherwise just the single result. Return type: list or ca.Circuit Examples
A circuit symbol can be instantiated via:
>>> print(srepr(parse_circuit_strings('name(3)'))) CircuitSymbol('name', 3)
A concatenation can be instantiated by using the infix ‘+’ operator
>>> print(srepr(parse_circuit_strings('a(3) + b(5)'))) Concatenation(CircuitSymbol('a', 3), CircuitSymbol('b', 5))
A series product can be instantiated by using the infix ‘<<’ operator
>>> print(srepr(parse_circuit_strings('a(3) << b(3)'))) SeriesProduct(CircuitSymbol('a', 3), CircuitSymbol('b', 3))
Circuit identity objects for
n
channels can be instantiated viacid(n)
:>>> print(srepr(parse_circuit_strings('(a(3) + cid(1)) << b(4)'))) SeriesProduct(Concatenation(CircuitSymbol('a', 3), CIdentity), CircuitSymbol('b', 4))
Feedback operations are specified as
>>> print(srepr(parse_circuit_strings('[a(5)]_(1->2)'))) Feedback(CircuitSymbol('a', 5), out_port=1, in_port=2)
Permutation objects are specified as
>>> print(srepr(parse_circuit_strings('P_sigma(1,2,3,0)'))) CPermutation((1, 2, 3, 0))
-
exception
qnet.misc.parse_circuit_strings.
ParseCircuitStringError
[source]¶ Bases:
qnet.misc.parser.ParsingError
Raised when an error is encountered while parsing a circuit expression string.
qnet.misc.parser module¶
Generic Parser class.
Summary¶
Exceptions:
ParsingError |
Raised for parsing error. |
Classes:
Parser |
Base class for a lexer/parser that has the _rules defined as methods |
Reference¶
-
exception
qnet.misc.parser.
ParsingError
[source]¶ Bases:
SyntaxError
Raised for parsing error.
qnet.misc.parser__CircuitExpressionParser_parsetab module¶
qnet.misc.qsd_codegen module¶
Summary¶
Exceptions:
QSDCodeGenError |
Exception raised for missing data in a QSDCodeGen instance |
Classes:
QSDCCodePrinter |
A printer for converting SymPy expressions to C++ code, while taking |
QSDCodeGen |
Class that allows to generate a QSD program for QNET expressions, and |
QSDOperator |
Encapsulation of a QSD (symbolic) Operator, containing all information required to instantiate that operator and to use it in C++ code expressions. |
Functions:
compilation_worker |
Worker to perform compilation, suitable e.g. |
expand_cmd |
Return a copy of the array cmd, where for each element of the cmd |
find_kets |
Given a Ket instance, return the set of LocalKet instances contained in it. |
local_ops |
Given a symbolic expression, extract the set of “atomic” operators (instances of Operator ) occurring in that expression. |
qsd_run_worker |
Worker to perform run of a previously compiled program (see compilation_worker() ), suitable e.g. |
sanitize_name |
Return a sanitized name, where all letters that occur as keys in |
Reference¶
-
class
qnet.misc.qsd_codegen.
QSDCCodePrinter
(settings={})[source]¶ Bases:
sympy.printing.ccode.CCodePrinter
A printer for converting SymPy expressions to C++ code, while taking into account pre-defined variable names for symbols
-
qnet.misc.qsd_codegen.
local_ops
(expr)[source]¶ Given a symbolic expression, extract the set of “atomic” operators (instances of
Operator
) occurring in that expression. The set is “atomic” in the sense that the operators are not algebraic combinations of other operators.
-
qnet.misc.qsd_codegen.
find_kets
(expr, cls=<class 'qnet.algebra.state_algebra.LocalKet'>)[source]¶ Given a
Ket
instance, return the set ofLocalKet
instances contained in it.
-
class
qnet.misc.qsd_codegen.
QSDOperator
(qsd_type, name, instantiator)[source]¶ Bases:
object
Encapsulation of a QSD (symbolic) Operator, containing all information required to instantiate that operator and to use it in C++ code expressions.
All arguments set the corresponding properties.
Examples
>>> A0 = QSDOperator('AnnihilationOperator', 'A0', '(0)') >>> Ad0 = QSDOperator('Operator', 'Ad0', '= A0.hc()')
-
known_types
= ['AnnihilationOperator', 'FieldTransitionOperator', 'IdentityOperator', 'Operator']¶
-
qsd_type
¶ QSD object type, i.e., name of the C++ class. See
known_types
class attribute for allowed type names
-
name
¶ The name of the operator object. Must be a valid C++ variable name.
-
instantiator
¶ String that instantiates the operator object. This must either be the constructor arguments of the operator’s QSD class, or a C++ expression (starting with an equal sign) that initializes the object
-
instantiation
¶ Complete line of C++ code that instantiates the operator
Example
>>> A0 = QSDOperator('AnnihilationOperator', 'A0', '(0)') >>> print(A0.instantiation) AnnihilationOperator A0(0);
-
__iter__
()[source]¶ Split
QSDOperator
into a tuple.Example
>>> A0 = QSDOperator('AnnihilationOperator', 'A0', '(0)') >>> qsd_type, name, instantiator = A0
-
-
exception
qnet.misc.qsd_codegen.
QSDCodeGenError
[source]¶ Bases:
Exception
Exception raised for missing data in a
QSDCodeGen
instance
-
class
qnet.misc.qsd_codegen.
QSDCodeGen
(circuit, num_vals=None, time_symbol=None)[source]¶ Bases:
object
Class that allows to generate a QSD program for QNET expressions, and to run the program to (accumulative) collect expectation values for observables
Parameters: - circuit (
SLH
) – The circuit to be simulated via QSD. - num_vals (dict of
Symbol
to float)) – Numeric value for any symbol occurring in the circuit, or any operator/state that may be added later on. - time_symbol (None or
Symbol
) – symbol to denote the time dependence in the Hamiltonian (usually t). If None, the Hamiltonian is time-independent.
Attributes: - circuit (
SLH
) – see circuit parameter - time_symbol (None or
Symbol
) – see time_symbol parameter - syms (set of
Symbol
) – The set of symbols used either in the circuit, any of the observables, or the initial state, excluding time_symbol - num_vals (dict of
Symbol
to float)) – Map of symbols to numeric value. Must specify a value for any symbol in syms. - traj_data (
TrajectoryData
) – The accumulated trajectory data. Every time therun()
, respectively therun_delayed()
method is called, the resulting trajectory data is incorporated. Thus, by repeatedly callingrun()
(followed byrun_delayed()
ifdelay=True
), an arbitrary number of trajectories may be accumulated in traj_data.
-
known_steppers
= ['Order4Step', 'AdaptiveStep', 'AdaptiveJump', 'AdaptiveOrthoJump']¶
-
observable_names
¶ Iterator of all defined observable names (str)
-
compile_cmd
¶ Command to be used for compilation (after
compile()
method has been called). Environment variables and ‘~’ are not expanded
-
get_observable
(name)[source]¶ Return the observable for the given name (instance of
Operator
), according to the mapping defined byadd_observable()
-
add_observable
(op, name=None)[source]¶ Register an operator as an observable, together with a name that will be used in the header of the table of expectation values, and on which the name of the QSD output files will be based.
Parameters: - op (
Operator
) – Observable (does not need to be Hermitian) - name (str or
None
) – Name of of the operator, to be used in the header of the output table. IfNone
,str(op)
is used.
Raises: ValueError
– if name is invalid or too long, or no unique filename can be generated from name- op (
-
set_moving_basis
(move_dofs, delta=0.0001, width=2, move_eps=0.0001)[source]¶ Activate the use of the moving basis, see Section 6 of the QSD Paper.
Parameters: - move_dofs (int) – degrees of freedom for which to use a moving basis (the first ‘move_dofs’ freedoms are re-centered, and their cutoffs adjusted.)
- delta (float) – probability threshold for the cutoff adjustment
- width (int) – size of the “pad” for the cutoff
- move_eps (float) – numerical accuracy with which to make the shift.
Cf.
shiftAccuracy
in QSDState::recenter
method
Raises: ValueError
– if move_dofs is invalidQSDCodeGenError
– if requesting a moving basis for a degree of freedom for which any operator is defined that cannot be applied in the moving basis
-
set_trajectories
(psi_initial, stepper, dt, nt_plot_step, n_plot_steps, n_trajectories, traj_save=10)[source]¶ Set the parameters that control the trajectories from which a plot of expectation values for the registered observables will be generated.
Parameters: - psi_initial (
Ket
) – The initial state - stepper (str) – Name of the QSD stepper that should handle
propagation of a single time step. See
known_steppers
for allowed values - dt (float) – The duration for a single propagation step. Note that
the plot of expectation values will generally be on a coarser
grid, as controlled by the
set_plotting
routine - nt_plot_step (int) – Number of propagation steps per plot step. That is, expectation values of the observables will be written out every nt_plot_step propagation steps
- n_plot_steps (int) – Number of plot steps. The total number of
propagation steps for each trajectory will be
nt_plot_step * n_plot_steps
, and duration T of the entire trajectory will bedt * nt_plot_step * n_plot_steps
- n_trajectories (int) – The number of trajectories over which to average for getting the expectation values of the observables
- traj_save (int) – Number of trajectories to propagate before writing
the averaged expectation values of all observables to file.
This ensures that if the program is terminated before the
calculation of
n_trajectories
is complete, the lost data is at most that of the lasttraj_save
trajectories is lost. A value of 0 indicates that the values are to be written out only after completing all trajectories.
- psi_initial (
-
compile
(qsd_lib, qsd_headers, executable='qsd_run', path='.', compiler='g++', compile_options='-O2', delay=False, keep_cc=False, remote_apply=None)[source]¶ Compile into an executable
Parameters: - qsd_lib (str) – full path to the file
libqsd.a
containing the statically compiled QSD library. May reference environment variables the home directory (‘~’) - qsd_headers (str) – path to the folder containing the QSD header files. May reference environment variables the home directory (‘~’)
- executable (str) – name of executable to which the QSD program should be compiled. Must consist only of letters, numbers, dashes, and underscores only
- path (str) – The path to the folder where executable will be generated. May reference environment variables the home directory (‘~’)
- compiler (str) – compiler executable
- compile_options (str) – options to pass to the compiler
- delay (bool) – Deprecated, must be False
- keep_cc (bool) – If True, keep the C++ code from which the executable was compiled. It will have the same name as the executable, with an added ‘.cc’ file extension.
- remote_apply (callable or None) – If not None,
remote_apply(compilation_worker, kwargs)
must callcompilation_worker()
on any remote node. Typically, this might point to the apply method of anipyparallel
View instance. The remote_apply argument should only be given ifrun_delayed()
will be called with an argument map that will push the calculation of a trajectory to a remote node.
Raises: ValueError
– if executable name or qsd_lib are invalidsubprocess.CalledProcessError
– if compilation fails
- qsd_lib (str) – full path to the file
-
run
(seed=None, workdir=None, keep=False, delay=False)[source]¶ Run the QSD program. The
compile()
method must have been called before run. Ifcompile()
was called withdelay=True
, compile at this point and run the resulting program. Otherwise, just run the existing program from the earlier compilation. The resulting directory data is returned, and in addition the traj_data attribute is updated to include the new trajectories (in addition to any previous trajectories)The run method may be called repeatedly to accumulate trajectories.
Parameters: - seed (int) – Random number generator seed (unsigned integer), will be passed to the executable as the only argument.
- workdir (str or None) – The directory in which to (temporarily) create the output files. If None, a temporary directory will be used. Otherwise, the workdir must exist. Environment variables and ‘~’ will be expanded.
- keep (bool) – If True, keep QSD output files inside workdir.
- delay (bool) – If True, schedule the run to be performed at a later
point in time, when the
run_delayed()
routine is called.
Returns: Averaged data obtained from the newly simulated trajectories only. None if delay=True.
Return type: Raises: QSDCodeGenError
– ifcompile()
was not calledOSError
– if creating/removing files/folders failssubprocess.CalledProcessError
– if delayed compilation fails or executable returns with non-zero exit codeValueError
– if seed is not unique
Note
The only way to run multiple trajectories in parallel is by giving
delay=True
. After preparing an arbitrary number of trajectories by repeated calls torun()
. Thenrun_delayed()
must be called with a map argument that supports parallel execution.
-
run_delayed
(map=<class 'map'>, n_procs_extend=1, _run_worker=None)[source]¶ Execute all scheduled runs (see delay option in
run()
method), possibly in parallel.Parameters: - map (callable) –
map(qsd_run_worker, list_of_kwargs)
must be equivalent to[qsd_run_worker(kwargs) for kwargs in list_of_kwargs]
. Defaults to the builtin map routine, which will process the scheduled runs serially. - n_procs_extend (int) – Number of local processes to use when averaging over trajectories.
Raises: TypeError
– If map does not return a list ofTrajectoryData
instances.Note
Parallel execution is achieved by passing an appropriate map routine. For example,
map=multiprocessing.Pool(5).map
would use a local thread pool of 5 workers. Another alternative would be the map method of anipyparallel
View. If (and only if) the View connects remote IPython engines,compile()
must have been called with an appropriate remote_apply argument that compiled the QSD program on all of the remote engines.- map (callable) –
- circuit (
-
qnet.misc.qsd_codegen.
expand_cmd
(cmd)[source]¶ Return a copy of the array cmd, where for each element of the cmd array, environment variables and ‘~’ are expanded
-
qnet.misc.qsd_codegen.
compilation_worker
(kwargs, _runner=None)[source]¶ Worker to perform compilation, suitable e.g. for being run on an IPython cluster. All arguments are in the kwargs dictionary.
Keys: - executable (str) – Name of the executable to be created. Nothing will be expanded.
- path (str) – Path where the executable should be created, as absolute path or relative to the current working directory. Environment variables and ‘~’ will be expanded.
- cc_code (str) – Multiline string that contains the entire C++ program to be compiled
- keep_cc (bool) – Keep C++ file after compilation? It will have the
same name as the executable, with an added
.cc
file extension. - cmd (list of str) – Command line arguments (see args in
subprocess.check_output). In each argument, environment
variables are expanded, and ‘~’ is
expanded to
$HOME
. It must meet the following requirements:- the compiler (first argument) must be in the
$PATH
- Invocation of the command must compile a C++ file with the name executable.cc in the current working directory to exectuable, also in the current working directoy. It must not take into account path. This is because the working directory for the subprocess handling the command invocation will be set to path. Thus, that is where the executable will be created.
- the compiler (first argument) must be in the
Returns: Absolute path of the compiled executable
Raises: subprocess.CalledProcessError
– if compilation failsOSError
– if creating/removing files/folder fails
-
qnet.misc.qsd_codegen.
qsd_run_worker
(kwargs, _runner=None)[source]¶ Worker to perform run of a previously compiled program (see
compilation_worker()
), suitable e.g. for being run on an IPython cluster. All arguments are in the kwargs dictionary.Keys: - executable (str) – Name of the executable to be run. Nothing will be
expanded. This should generally be only the name of the
executable, but it can also be a path relative to
kwargs['path']
, or a (fully expanded) absolute path, in which casekwargs['path']
is ignored. - path (str) – Path where the executable can be found, as absolute path or relative to the current working directory. Environment variables and ‘~’ will be expanded.
- seed (int) – Seed (unsigned int) to be passed as argument to the executable
- operators (dict or OrderedDict of str to str)) – Mapping of operator name
to filename, see operators parameter of
from_qsd_data()
- workdir (str or None) – The working directory in which to execute the executable (relative to the current working directory). The output files defined in operators will be created in this folder. If None, a temporary directory will be used. If workdir does not exist yet, it will be created.
- keep (bool) – If True, keep the QSD output files. If False, remove the output files as well as any parent folders that may have been created alongside with workdir
Raises: FileNotFoundError
– if executable does not exist in pathReturns: Expectation values and variances of the observables, from the newly simulated trajectories only (instance of
TrajectoryData
)- executable (str) – Name of the executable to be run. Nothing will be
expanded. This should generally be only the name of the
executable, but it can also be a path relative to
-
qnet.misc.qsd_codegen.
sanitize_name
(name, allowed_letters, replacements)[source]¶ Return a sanitized name, where all letters that occur as keys in replacements are replaced by their corresponding values, and any letters that do not match allowed_letters are dropped
Parameters: - name (str) – string to be sanitized
- allowed_letters (regex) – compiled regular expression that any allowed letter must match
- replacement (dict of str to str) – dictionary of mappings
Returns: sanitized name
Return type: Example:
>>> sanitize_filename = partial(sanitize_name, ... allowed_letters=re.compile(r'[.a-zA-Z0-9_-]'), ... replacements={'^':'_', '+':'_', '*':'_', ' ':'_'}) >>> sanitize_filename.__doc__ = "Sanitize name to be used as a filename" >>> sanitize_filename('\chi^{(1)}_1') 'chi_1_1'
qnet.misc.testing_tools module¶
Collection of routines needed for testing. This includes proto-fixtures, i.e. routines that should be imported and then turned into a fixture with the pytest.fixture decorator.
See <https://pytest.org/latest/fixture.html>
Summary¶
Functions:
datadir |
Proto-fixture responsible for searching a folder with the same name of test module and, if available, moving all contents to a temporary directory so tests can use them freely. |
fake_traj |
Return a new trajectory that has the same data as traj_template, but a different ID and seed. |
qsd_traj |
Return a proto-fixture that returns a TrajectoryData instance based on all the *.out file in the given folder (relative to the test datadir), and with the given seed. |
Reference¶
-
qnet.misc.testing_tools.
datadir
(tmpdir, request)[source]¶ Proto-fixture responsible for searching a folder with the same name of test module and, if available, moving all contents to a temporary directory so tests can use them freely.
In any test, import the datadir routine and turn it into a fixture:
>>> import pytest >>> import qnet.misc.testing_tools >>> datadir = pytest.fixture(qnet.misc.testing_tools.datadir)
-
qnet.misc.testing_tools.
qsd_traj
(datadir, folder, seed)[source]¶ Return a proto-fixture that returns a
TrajectoryData
instance based on all the*.out
file in the given folder (relative to the test datadir), and with the given seed.The returned function should be turned into a fixture:
>>> import pytest >>> import qnet.misc.testing_tools >>> from qnet.misc.testing_tools import qsd_traj >>> datadir = pytest.fixture(qnet.misc.testing_tools.datadir) >>> traj1 = pytest.fixture(qsd_traj(datadir, 'traj1', 102121))
qnet.misc.trajectory_data module¶
Summary¶
Exceptions:
TrajectoryParserError |
Exception raised if a TrajectoryData file is malformed |
Classes:
TrajectoryData |
Tabular data of expectation values for one or more trajectories. |
Reference¶
-
exception
qnet.misc.trajectory_data.
TrajectoryParserError
[source]¶ Bases:
Exception
Exception raised if a
TrajectoryData
file is malformed
-
class
qnet.misc.trajectory_data.
TrajectoryData
(ID, dt, seed, n_trajectories, data)[source]¶ Bases:
object
Tabular data of expectation values for one or more trajectories. Multiple TrajectoryData objects can be combined with the
extend()
method, in order to accumulate averages over an arbitrary number o trajectories. As much as possible, it is checked that all trajectories are statistically independent. A record is kept to ensure exact reproducibility.Parameters: - ID (str) – A unique, RFC 4122 compliant identifier (as generated by
new_id()
) - dt (float) – Time step between data points (>0)
- seed (int) – The random number generator seed on which the data is based
- n_trajectories (int) – The number of trajectories from which the data is averaged (It is assumed that the random number generator was seeded with the given seed, and then the given number of trajectories were calculated sequentially)
- data (dict of str to tuple of arrays) – dictionary (preferably
OrderedDict) of expectation value data. The value of
data[operator_name]
must be a tuple of four numpy arrays (real part of expectation value, imaginary part of expectation value, real part of standard deviation, imaginary part of standard deviation). The operator names must contain only ASCII characters and must be shorter thancol_width - 10
.
Raises: ValueError
– if ID is not RFC 4122 compliant, dt is an invalid or non-positive float, or data does not follow the correct structure.Attributes: - ID (str) – A unique ID for the current state of the TrajectoryData
(read-only). See
ID
property. - table (OrderedDict of str to numpy array) – A table that contains four
column for every known operator (real/imaginary part of the
expectation value, real/imaginary part of the variance). Note that
the table attribute can easily be converted to a
pandas.DataFrame
(DataFrame(data=traj.table)
). The table attribute should be considered read-only. - dt (float) – Time step between data points
- nt (int) – Number of time steps / data points
- operators (list of str) – An iterator of the operator names. The column names in the table attribute derive from these. Assuming “X” is one of the operator names, there will be four keys in table: “Re[<X>]”, “Im[<X>]”, “Re[var(X)]”, “Im[var(X)]”
- record (OrderedDic of str to tuple of int, int, list) – A copy of the
complete record of how the averaged expectation values for all
operators were obtained. See discussion of the
record
property. - col_width (int) – width of the data columns when writing out data.
Defaults to 25 (allowing to full double precision). Note that
operator names may be at most of length
col_width-10
-
col_width
= 25¶
-
classmethod
read
(filename)[source]¶ Read in TrajectoryData from the given filename. The file must be in the format generated by the write method.
Raises: TrajectoryParserError
– if the file has an incorrect format
-
classmethod
from_qsd_data
(operators, seed, workdir='.')[source]¶ Instantiate from one or more QSD output files specified as values of the dictionary operators
Each QSD output file must have the following structure:
- The first line must start with the string “Number_of_Trajectories”, followed by an integer (separated by whitespace)
- All following lines must contain five floating point numbers (time, real/imaginary part of expectation value, and real/imaginary part of variance), separated by whitespace.
All QSD output files must contain the same number of lines, specify the same number of trajectories, and use the same time grid values (first column). It is the user’s responsibility to ensure that all out output files were indeed generated in a single QSD run using the specified initial seed for the random number generator.
Parameters: - operators (dict of str to str) – dictionary (preferably OrderedDict) of operator name to filename. The filenames are relative to the workdir. Each filename must contain data in the format described above
- seed (int) – The seed to the random number generator that was used to produce the data file
- workdir (str) – directory to which the filenames in operators are relative to
Raises: ValueError
– if any of the data files do not have the correct format or are inconsistentNote
Remember that is is vitally important that all quantum trajectories that go into an average are statistically independent. The
TrajectoryData
class tries as much as possible to ensure this, by refusing to combine identical IDs, or trajectories originating from the same seed. To this end, in thefrom_qsd_data()
method, the ID of the instantiated object will depend uniquely on the collective data read from the QSD output files.
-
classmethod
new_id
(name=None)[source]¶ Generate a new unique identifier, as a string. The identifier will be RFC 4122 compliant. If name is None, the resulting ID will be random. Otherwise, name must be a string that the ID will depend on. That is, calling new_id repeatedly with the same name will result in identical IDs.
-
ID
¶ A unique RFC 4122 compliant identifier. The identifier changes whenever the class data is modified (via the
extend()
method). Two instances of TrajectoryData with the same ID are assumed to be identical
-
record
¶ A copy of the full trajectory record, i.e., a history of calls to the
extend()
method. Its purpose is to ensure that the data is completely reproducible. This entails storing the seed to the random number generator for all sets of trajectories.The record is an OrderedDict that maps the original ID of any TrajectoryData instance combined via
extend()
to a tuple(seed, n_trajectories, ops)
, whereseed
is the seed to the random number generator that was used to calculate a specific set of trajectories (sequentially),n_trajectories
are the number of trajectories in that dataset, andops
is a list of operator names for which expectation values were calculated. This may be the complete list of operators in the operators attribute, or a subset of those operators (Not all trajectories have to include data for all operators).For example, let’s assume we have a
QSDCodeGen
instance to set up for a QSD propagation. Two observables ‘X1’, ‘X2’, have been added to be written to file ‘X1.out’, and ‘X2.out’. Theset_trajectories()
method has been called withn_trajectories=10
, after which a call torun()
with argumentseed=SEED1
, performed a sequential propagation of 10 trajectories, with the averaged expectation values written to the output files.This data may now be read into a new TrajectoryData instance
traj
via thefrom_qsd_data()
class method (with seed=SEED1). The newly created instance (with, let’s say,ID='8d102e4b-...'
) will have one entry in its record:'8d102e4b-...': (SEED1, 10, ['X1', 'X2'])
Now, let’s say we add a new observable ‘A2’ (output file ‘A2.out’) for the
QSDCodeGen
instance (in addition to the existing observables X1, X2), and call therun()
method again, with a new seedSEED2
. We then updatetraj
with a call such as:traj.extend(TrajectoryData.from_qsd_data( {'X1':'X1.out', 'X2':'X2.out', 'A2':'A2.out'}, SEED2)
The record will now have an additional entry, e.g.:
'd9831647-...': (SEED2, 10, ['X1', 'X2', 'A2'])
traj.table
will contain the averaged expectation values (average over 20 trajectories for ‘X1’, ‘X2’, and 10 trajectories for ‘A2’). The record tells use that to reproduce this table, 10 sequential trajectories starting fromSEED1
must be performed for X1, X2, followed by another 10 trajectories for X1, X2, A2 starting fromSEED2
.
-
operators
¶ Iterator over all operators
-
record_IDs
¶ Set of all IDs in the record
-
dt
¶ Time step between data points
-
nt
¶ Number of time steps / data points
-
shape
¶ Tuple
(n_row, n_cols)
for the data in self.table. The time grid is included in the column count
-
record_seeds
¶ Set of all random number generator seeds in the record
-
tgrid
¶ Time grid, as numpy array
-
to_str
(show_rows=-1)[source]¶ Generate full string representation of the TrajectoryData
Parameters: show_rows (int) – If given > 0, maximum number of data rows to show. If there are more rows, they will be indicated by an ellipsis ( ...
)Raises: ValueError
– if any operator name is too long to generate a label that fits in the limit given by thecol_width
class attribute
-
write
(filename)[source]¶ Write data to a text file. The TrajectoryData may later be restored by the read class method from the same file
-
extend
(*others, **kwargs)[source]¶ Extend data with data from one or more other TrajectoryData instances, averaging the expectation values. Equivalently to
traj1.extend(traj2)
, the syntaxtraj1 += traj2
may be used.Raises: ValueError
– if data in self and and any element of others are incompatibleTypeError
– if any others are not an instance of TrajectoryData
- ID (str) – A unique, RFC 4122 compliant identifier (as generated by
qnet.printing package¶
Printing system for QNET Expressions and related objects
Submodules:
qnet.printing.ascii module¶
qnet.printing.base module¶
Provides the base class for Printers
Reference¶
-
class
qnet.printing.base.
Printer
[source]¶ Bases:
object
Base class for Printers (and default ASCII printer)
Attributes: - head_repr_fmt (str) – The format for representing expressions in the
form
head(arg1, arg2, ..., key1=val1, key2=val2, ...)
. Uses formatting keys head (expr.__class__.__name__
), args (rendered representation ofexpr.args
), and kwargs (rendered representation ofexpr.kwargs
). Used byrender_head_repr()
- identity_sym (str) – Representation of the identity operator
- circuit_identify_fmt (str) – Format for the identity in a Circuit, parametrized by the number of channels, given as the formatting key cdim.
- dagger_sym (str) – Symbol representing a dagger
- daggered_sym (str) – Superscript version of dagger_sym
- permutation_sym (str) – The identifier of a Circuit permutation
- pseudo_daggered_sym (str) – Superscript representing a pseudo-dagger
- pal_left (str) – The symbol/string for a left parenthesis
- par_right (str) – The symbol/string for a right parenthesis
- brak_left (str) – The symbol/string for a left square bracket
- brak_right (str) – The symbol/string for a right square bracket
- arg_sep (str) – The string that should be used to separate rendered arguments in a list (usually a comma)
- scalar_product_sym (str) – Symbol to indicate a product between two scalars
- tensor_sym (str) – Symbol to indicate a tensor product
- inner_product_sym (str) – Symbol to indicate an inner product
- op_product_sym (str) – Symbol to indicate a product between two operators in the the same Hilbert space
- circuit_series (str) – Infix symbol for a series product of two circuits
- circuit_concat_sym (str) – Infix symbol for a concatenation of two circuits
- circuit_inverse_fmt (str) – Format for rendering the series-inverse of a circuit element. Receives a formatting key operand of the rendered operand circuit element
- circuit_fb_fmt (str) – Format for rendering a feedback circuit element. Receives the formatting keys operand, output, and input that are the rendered operand circuit element, the index of the ouput port (as a string), and the index of the input port to which the feedback connects (also as a string)
- op_trace_fmt (str) – Format for rendering a trace. Receives the formatting keys operand (the object being traced) and space (the rendered label of the Hilbert space that is being traced over)
- null_space_proj_sym (str) – The identifier for a nullspace projector
- hilbert_space_fmt (str) – Format for rendering a
HilbertSpace
object. Receives the formatting key label with the rendered label of the Hilbert space - matrix_left_sym (str) – The symbol that marks the beginning of a matrix,
for rendering a
Matrix
instance - matrix_right_sym (str) – The symbol that marks the end of a matrix
- matrix_row_left_sym (str) – Symbol that marks beginning of row in matrix
- matrix_row_right_sym (str) – Symbol that marks end of row in matrix
- matrix_col_sep_sym (str) – Symbol that separates the values in different columns of a matrix
- matrix_row_sep_sym (str) – Symbol that separates the rows of a matrix
- bra_fmt (str) – Format for rendering a
Bra
instance. Receives the formatting keys label (the rendered label of the state) and space (the rendered label of the Hilbert space) - ket_fmt (str) – Format for rendering a
Ket
instance. Receives the formatting keys label and space - ketbra_fmt (str) – Format for rendering a
KetBra
instance. Receives the formatting keys label_i, label_j, and space, for the rendered label of the “left” and “right” state, and the Hilbert space - braket_fmt (str) – Format for rendering a
BraKet
instance. Receives the formatting keys label_i, label_j, and space. - cc_string (str) – String to indicate the complex conjugate (in a sum)
-
head_repr_fmt
= '{head}({args}{kwargs})'¶
-
identity_sym
= '1'¶
-
circuit_identity_fmt
= 'cid({cdim})'¶
-
zero_sym
= '0'¶
-
dagger_sym
= 'H'¶
-
daggered_sym
= '^H'¶
-
permutation_sym
= 'Perm'¶
-
pseudo_daggered_sym
= '^+'¶
-
par_left
= '('¶
-
par_right
= ')'¶
-
brak_left
= '['¶
-
brak_right
= ']'¶
-
arg_sep
= ', '¶
-
scalar_product_sym
= '*'¶
-
tensor_sym
= '*'¶
-
inner_product_sym
= '*'¶
-
op_product_sym
= '*'¶
-
circuit_series_sym
= '<<'¶
-
circuit_concat_sym
= '+'¶
-
circuit_inverse_fmt
= '[{operand}]^{{-1}}'¶
-
circuit_fb_fmt
= '[{operand}]_{{{output}->{input}}}'¶
-
op_trace_fmt
= 'tr_({space})[{operand}]'¶
-
null_space_proj_sym
= 'P_Ker'¶
-
hilbert_space_fmt
= 'H_{label}'¶
-
matrix_left_sym
= '['¶
-
matrix_right_sym
= ']'¶
-
matrix_row_left_sym
= '['¶
-
matrix_row_right_sym
= ']'¶
-
matrix_col_sep_sym
= ', '¶
-
matrix_row_sep_sym
= ', '¶
-
bra_fmt
= '<{label}|_({space})'¶
-
ket_fmt
= '|{label}>_({space})'¶
-
ketbra_fmt
= '|{label_i}><{label_j}|_({space})'¶
-
braket_fmt
= '<{label_i}|{label_j}>_({space})'¶
-
cc_string
= 'c.c.'¶
-
op_hs_super_sub
= 1¶
-
classmethod
render
(expr: typing.Any, adjoint=False) → str[source]¶ Render an expression (or the adjoint of the expression)
-
classmethod
register
(expr, rendered)[source]¶ Register a fixed rendered string for the given expr in an internal registry. As a result, any call to
render()
for expr will immediately return rendered
-
classmethod
update_registry
(mapping)[source]¶ Call
register(key, val)
for every key-value pair in the mapping dictionary
-
classmethod
del_registered_expr
(expr)[source]¶ Remove the registered expr from the registry (cf.
register_expr()
)
-
classmethod
render_head_repr
(expr: typing.Any, sub_render=None, key_sub_render=None) → str[source]¶ Render a textual representation of expr using
head_repr_fmt
. Positional and keyword arguments are recursively rendered using sub_render, which defaults to cls.render by default. If desired, a different renderer may be used for keyword arguments by giving key_sub_rendererRaises: AttributeError
– if expr is not an instance ofExpression
, or more specifically, if expr does not have args and kwargs (respectively minimal_kwargs) properties
-
classmethod
render_op
(identifier: str, hs=None, dagger=False, args=None, superop=False) → str[source]¶ Render an operator
Parameters: - identifier (str) – Name of the operator (unrendered string)
- hs (HilbertSpace) – Hilbert space instance of the operator
- dagger (bool) – Whether or not to render the operator with a dagger
- args (list) – List of arguments for the operator (list of expressions). These will be rendered through the render method and appended to the rendered operator in parentheses
- superop (bool) – Flag to indicate whether the operator is a superoperator
-
classmethod
render_string
(ascii_str: str) → str[source]¶ Render an unrendered (ascii) string, resolving e.g. greek letters and sub-/superscripts
-
classmethod
render_sum
(operands, plus_sym='+', minus_sym='-', padding=' ', adjoint=False)[source]¶ Render a sum
-
classmethod
render_product
(operands, prod_sym, sum_classes, minus_sym='-', padding=' ', adjoint=False, dynamic_prod_sym=None)[source]¶ Render a product
- head_repr_fmt (str) – The format for representing expressions in the
form
qnet.printing.srepr module¶
Provides printers for a full-structured representation
Summary¶
Classes:
IndentedSReprPrinter |
Printer for rendering an expression in such a way that the resulting |
Functions:
srepr |
Render the given expression into a string that can be evaluated in an appropriate context to re-instantiate an identical expression. |
Module data:
Reference¶
-
class
qnet.printing.srepr.
IndentedSReprPrinter
(indent=0)[source]¶ Bases:
qnet.printing.base.Printer
Printer for rendering an expression in such a way that the resulting string can be evaluated in an appropriate context to re-instantiate an identical object, using nested indentation (implementing
srepr(expr, indented=True)
-
render_head_repr
(expr: typing.Any, sub_render=None, key_sub_render=None) → str[source]¶ Render a multiline textual representation of expr
Raises: AttributeError
– if expr is not an instance ofExpression
, or more specifically, if expr does not have args and kwargs (respectively minimal_kwargs) properties
-
-
qnet.printing.srepr.
srepr
(expr, indented=False)[source]¶ Render the given expression into a string that can be evaluated in an appropriate context to re-instantiate an identical expression. If indented is False (default), the resulting string is a single line. Otherwise, the result is a multiline string, and each positional and keyword argument of each Expression is on a separate line, recursively indented to produce a tree-like output.
See also
qnet.printing.tree_str produces an output similar to srepr with
indented=True
. Unlike srepr, however, tree_str uses line drawings for the tree, shows arguments directly on the same line as the expression they belong to, and cannot be evaluated.
qnet.printing.tex module¶
Routines for rendering expressions to LaTeX
qnet.printing.tree module¶
Tree printer for Expressions
Summary¶
Functions:
shorten_renderer |
Return a modified that returns the representation of expr, or ‘...’ if |
tree |
Print a tree representation of the structure of expr |
tree_str |
Give the output of tree as a multiline string, using line drawings to |
Module data:
Reference¶
-
qnet.printing.tree.
shorten_renderer
(renderer, max_len)[source]¶ Return a modified that returns the representation of expr, or ‘...’ if that representation is longer than max_len
-
qnet.printing.tree.
tree
(expr, attr='operands', padding='', to_str=<bound method HeadStrPrinter.render of <class 'qnet.printing.tree.HeadStrPrinter'>>, exclude_type=None, depth=None, unicode=True, _last=False, _root=True, _level=0, _print=True)[source]¶ Print a tree representation of the structure of expr
Parameters: - expr (Expression) – expression to render
- attr (str) – The attribute from which to get the children of expr
- padding (str) – Whitespace by which the entire tree is idented
- to_str (callable) – Renderer for expr
- exclude_type (type) – Type (or list of types) which should never be expanded recursively
- depth (int or None) – Maximum depth of the tree to be printed
- unicode (bool) – If True, use unicode line-drawing symbols for the tree. If False, use an ASCII approximation
See also
tree_str()
return the result as a string, instead of printing it
-
qnet.printing.tree.
tree_str
(expr, **kwargs)[source]¶ Give the output of tree as a multiline string, using line drawings to visualize the hierarchy of expressions (similar to the
tree
unix command line program for showing directory trees)See also
qnet.printing.srepr()
withindented=True
produces a similar tree-like rendering of the given expression that can be re-evaluated to the original expression.
qnet.printing.unicode module¶
Routines for rendering expressions to Unicode
Summary¶
Functions:
unicode |
Return a unicode representation of the given expr |
unicode_sub_super |
Try to render a subscript string in unicode, fall back on ascii if this |
Module data:
Summary¶
Functions:
configure_printing |
context manager for temporarily changing the printing paremters. This |
init_printing |
Initialize printing |
__all__
: ascii
, configure_printing
, init_printing
, srepr
, tex
, tree
, unicode
Reference¶
-
qnet.printing.
init_printing
(use_unicode=True, str_printer=None, repr_printer=None, cached_rendering=True, implicit_tensor=False, _init_sympy=True)[source]¶ Initialize printing
- Initialize sympy printing with the given use_unicode (i.e. call sympy.init_printing)
- Set the printers for textual representations (
str
andrepr
) of Expressions - Configure whether ascii, unicode, and tex representations should be cached. If caching is enabled, the representations are rendered only once. This means that any configuration of the corresponding printers must be made before generating the representation for the first time.
Parameters: - use_unicode (bool) – If True, use unicode symbols. If False, restrict to ascii. Besides initializing sympy printing, this only determins the default str and repr printer. Thus, if str_printer and repr_printer are given, use_unicode has almost no effect.
- str_printer (Printer, str, or None) – The printer to be used for
str(expr)
. Must be an instance ofPrinter
or one of the strings ‘ascii’, ‘unicode’, ‘unicode’, ‘latex’, or ‘srepr’, corresponding to AsciiPrinter, UnicodePrinter, LaTeXPrinter, and SReprPrinter respectively. If not given, either AsciiPrinter or UnicodePrinter is set, depending on use_unicode. - repr_printer (Printer, str, or None) – Like str_printer, but for
repr(expr)
. This is also what is displayed in an interactive Python session - cached_rendering (bool) – Flag whether the results of
ascii(expr)
,unicode(expr)
, andtex(expr)
should be cached - implicit_tensor (bool) – If True, don’t use tensor product symbols in the standard tex representation
Notes
- This routine does not set custom printers for rendering ascii, unicode, and tex. To use a non-default printer, you must assign directly to the corresponding class attributes of Expression.
- str and repr representations are never directly cached (but the printers they delegate to may use caching)
qnet.qhdl package¶
Submodules:
qnet.qhdl.parser_QHDLParser_parsetab module¶
qnet.qhdl.qhdl module¶
This module contains the code to convert a circuit specified in QHDL into a Gough-James circuit expression.
The other module in this package qhdl_parser
implements an actual parser for the qhdl source text, while this file then
converts structured netlist information into a circuit expression.
For more details on the QHDL syntax, see The QHDL Syntax.
Summary¶
Exceptions:
QHDLError |
Classes:
Architecture |
|
BasicInterface |
|
Component |
|
Entity |
|
QHDLObject |
Functions:
dict_keys_sorted_by_val |
|
gtype_compatible |
|
my_debug |
Reference¶
-
class
qnet.qhdl.qhdl.
BasicInterface
(identifier, generics, ports)[source]¶ Bases:
qnet.qhdl.qhdl.QHDLObject
-
cid
= 0¶
-
in_port_identifiers
= []¶
-
out_port_identifiers
= []¶
-
inout_port_identifiers
= []¶
-
port_identifiers
¶ The port_identifiers property.
-
generic_identifiers
¶ The generic_identifiers property.
-
gids
¶ The generic_identifiers property.
-
-
class
qnet.qhdl.qhdl.
Architecture
(identifier, entity, components, signals, assignments, global_assignments={})[source]¶ Bases:
qnet.qhdl.qhdl.QHDLObject
-
signals
= []¶
-
lossy_signals
= []¶
-
global_inout
= {}¶
-
global_out
= {}¶
-
global_in
= {}¶
-
inout_to_signal
= {}¶
-
out_to_signal
= {}¶
-
in_to_signal
= {}¶
-
signal_to_global_in
= {}¶
-
signal_to_global_out
= {}¶
-
qnet.qhdl.qhdl_parser module¶
The PLY-based QHDLParser class.
Reference¶
-
class
qnet.qhdl.qhdl_parser.
QHDLParser
(**kw)[source]¶ Bases:
qnet.misc.parser.Parser
-
reserved
= {'entity': 'ENTITY', 'generic': 'GENERIC', 'int': 'INT', 'port': 'PORT', 'fieldmode': 'FIELDMODE', 'end': 'END', 'in': 'IN', 'out': 'OUT', 'lossy_fieldmode': 'LOSSY_FIELDMODE', 'map': 'MAP', 'is': 'IS', 'complex': 'COMPLEX', 'of': 'OF', 'signal': 'SIGNAL', 'component': 'COMPONENT', 'begin': 'BEGIN', 'architecture': 'ARCHITECTURE', 'real': 'REAL', 'inout': 'INOUT'}¶
-
tokens
= ['ENTITY', 'GENERIC', 'INT', 'PORT', 'FIELDMODE', 'END', 'IN', 'OUT', 'LOSSY_FIELDMODE', 'MAP', 'IS', 'COMPLEX', 'OF', 'SIGNAL', 'COMPONENT', 'BEGIN', 'ARCHITECTURE', 'REAL', 'INOUT', 'ID', 'ICONST', 'FCONST', 'ASSIGN', 'FEEDRIGHT', 'FEEDLEFT', 'LPAREN', 'RPAREN', 'COMMA', 'SEMI', 'COLON']¶
-
t_ignore
= ' \t\x0c'¶
-
t_ASSIGN
= ':='¶
-
t_FEEDRIGHT
= '=>'¶
-
t_FEEDLEFT
= '<='¶
-
t_LPAREN
= '\\('¶
-
t_RPAREN
= '\\)'¶
-
t_COMMA
= ','¶
-
t_SEMI
= ';'¶
-
t_COLON
= ':'¶
-
t_ICONST
= '-?\\d+'¶
-
t_FCONST
= '-?((\\d+)(\\.\\d+)(e(\\+|-)?(\\d+))? | (\\d+)e(\\+|-)?(\\d+))'¶
-
start
= 'top_level_list'¶
-
p_entity_declaration
(p)[source]¶ entity_declaration : ENTITY ID IS generic_clause port_clause END opt_entity opt_id SEMI
-
p_generic_statement
(p)[source]¶ generic_statement : GENERIC LPAREN generic_list opt_semi RPAREN SEMI
-
p_with_io_port_list
(p)[source]¶ - with_io_port_list : io_port_entry_group SEMI non_io_port_list
- io_port_entry_group
-
p_non_io_port_list
(p)[source]¶ - non_io_port_list : non_io_port_entry_group SEMI non_io_port_list
- non_io_port_entry_group
-
p_non_io_port_entry_group
(p)[source]¶ non_io_port_entry_group : id_list COLON signal_direction signal_type
-
p_architecture_declaration
(p)[source]¶ architecture_declaration : ARCHITECTURE ID OF ID IS architecture_head BEGIN instance_mapping_assignment_list feedleft_assignment_list END opt_arch opt_id SEMI
-
p_component_declaration_list
(p)[source]¶ - component_declaration_list : component_declaration_list component_declaration
- component_declaration
-
p_component_declaration
(p)[source]¶ component_declaration : COMPONENT ID generic_clause port_clause END COMPONENT opt_id SEMI
-
p_instance_mapping_assignment_list
(p)[source]¶ - instance_mapping_assignment_list : instance_mapping_assignment_list instance_mapping_assignment
- instance_mapping_assignment
-
p_instance_mapping_assignment
(p)[source]¶ instance_mapping_assignment : ID COLON ID generic_map port_map
-
p_generic_map
(p)[source]¶ - generic_map : GENERIC MAP LPAREN feedright_generic_assignment_list RPAREN SEMI
- empty
-
p_feedright_generic_assignment_list
(p)[source]¶ - feedright_generic_assignment_list : feedright_generic_assignment_list COMMA feedright_generic_assignment
- feedright_generic_assignment
-
p_feedright_generic_assignment
(p)[source]¶ - feedright_generic_assignment : ID FEEDRIGHT id_or_value
- id_or_value
-
p_feedright_port_assignment_list
(p)[source]¶ - feedright_port_assignment_list : feedright_port_assignment_list COMMA feedright_port_assignment
- feedright_port_assignment
-
__all__
: init_printing