qnet_qsd package

Top-level package for QNET-QSD.

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 into account pre-defined variable names for symbols
QSDCodeGen Class that allows to generate a QSD program for QNET expressions, and to run the program to (accumulative) collect expectation values for observables
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 array, environment variables and ‘~’ are expanded
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 replacements are replaced by their corresponding values, and any letters that do not match allowed_letters are dropped

Reference

class qnet_qsd.QSDCCodePrinter(settings={})[source]

Bases: sympy.printing.ccode.C89CodePrinter

A printer for converting SymPy expressions to C++ code, while taking into account pre-defined variable names for symbols

qnet_qsd.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_qsd.find_kets(expr, cls=<class 'qnet.algebra.state_algebra.LocalKet'>)[source]

Given a Ket instance, return the set of LocalKet instances contained in it.

class qnet_qsd.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
__str__()[source]

The string representation of an operator is simply its name

Example

>>> A0 = QSDOperator('AnnihilationOperator', 'A0', '(0)')
>>> assert(str(A0) == str(A0.name))
exception qnet_qsd.QSDCodeGenError[source]

Bases: Exception

Exception raised for missing data in a QSDCodeGen instance

class qnet_qsd.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.TrajectoryData) – The accumulated trajectory data. Every time the run(), respectively the run_delayed() method is called, the resulting trajectory data is incorporated. Thus, by repeatedly calling run() (followed by run_delayed() if delay=True), an arbitrary number of trajectories may be accumulated in traj_data.
known_steppers = ['Order4Step', 'AdaptiveStep', 'AdaptiveJump', 'AdaptiveOrthoJump']
observables

Iterator over all defined observables (instances of Operator)

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 by add_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. If None, str(op) is used.
Raises:

ValueError – if name is invalid or too long, or no unique filename can be generated from name

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 QSD State::recenter method
Raises:
  • ValueError – if move_dofs is invalid
  • QSDCodeGenError – 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 be dt * 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 last traj_save trajectories is lost. A value of 0 indicates that the values are to be written out only after completing all trajectories.
generate_code()[source]

Return C++ program that corresponds to the circuit as a multiline string

write(outfile)[source]

Write C++ program that corresponds to the circuit

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 call compilation_worker() on any remote node. Typically, this might point to the apply method of an ipyparallel View instance. The remote_apply argument should only be given if run_delayed() will be called with an argument map that will push the calculation of a trajectory to a remote node.
Raises:
run(seed=None, workdir=None, keep=False, delay=False)[source]

Run the QSD program. The compile() method must have been called before run. If compile() was called with delay=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:

trajectorydata.TrajectoryData

Raises:

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 to run(). Then run_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 of TrajectoryData 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 an ipyparallel 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.

qnet_qsd.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_qsd.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.
Returns:

Absolute path of the compiled executable

Raises:
qnet_qsd.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 case kwargs['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 path

Returns:

Expectation values and variances of the observables, from the newly simulated trajectories only (instance of TrajectoryData)

qnet_qsd.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:

str

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'