# sf.TDMProgram¶

class TDMProgram(N, name=None)[source]

Bases: strawberryfields.program.Program

Represents a photonic quantum circuit in the time domain encoding.

The TDMProgram class provides a context manager for easily defining a single time-bin of the time domain algorithm. As with the standard Program, Strawberry Fields operations are appended to the time domain program using the Python-embedded Blackbird syntax.

Once created, time domain programs can be executed on Strawberry Fields’ suite of built-in simulators in an efficient manner, or submitted to be executed on compatible hardware.

Parameters
• N (int or Sequence[int]) – If an integer, the number of concurrent (or ‘alive’) modes in each time bin. Alternatively, a sequence of integers may be provided, corresponding to the number of concurrent modes in the possibly multiple bands in the circuit.

• name (str) – the program name (optional)

Example

Below, we create a time domain program with 2 concurrent modes:

>>> import strawberryfields as sf
>>> from strawberryfields import ops
>>> prog = sf.TDMProgram(N=2)


Once created, we can construct the program using the prog.context() context manager.

>>> with prog.context([1, 2], [3, 4]) as (p, q):
...     ops.Sgate(0.7, 0) | q[1]
...     ops.BSgate(p[0]) | (q[0], q[1])
...     ops.MeasureHomodyne(p[1]) | q[0]


Printing out this program:

>>> prog.print()
Sgate(0.7, 0) | (q[1])
BSgate({p0}, 0) | (q[0], q[1])
MeasureHomodyne({p1}) | (q[0])


Note that p0 and p1 are symbolic gate parameters; to access the numeric values, we must use the prog.parameters attribute:

>>> prog.parameters
{'p0': [1, 2], 'p1': [3, 4]}


When we simulate a time-domain program, it is first unrolled by the engine; unrolling involves explicitly repeating the single time-bin sequence constructed above, and shifting the simulated registers. This ‘unrolling’ procedure is performed automatically by the engine, however, we can visualize the unrolled program by calling the unroll() method.

>>> prog.unroll(shots=3).print()
Sgate(0.7, 0) | (q[1])
BSgate(1, 0) | (q[0], q[1])
MeasureHomodyne(3) | (q[0])
Sgate(0.7, 0) | (q[0])
BSgate(2, 0) | (q[1], q[0])
MeasureHomodyne(4) | (q[1])
Sgate(0.7, 0) | (q[1])
BSgate(1, 0) | (q[0], q[1])
MeasureHomodyne(3) | (q[0])
Sgate(0.7, 0) | (q[0])
BSgate(2, 0) | (q[1], q[0])
MeasureHomodyne(4) | (q[1])
Sgate(0.7, 0) | (q[1])
BSgate(1, 0) | (q[0], q[1])
MeasureHomodyne(3) | (q[0])
Sgate(0.7, 0) | (q[0])
BSgate(2, 0) | (q[1], q[0])
MeasureHomodyne(4) | (q[1])


Note the ‘shifting’ of the measured registers — this optimization allows for time domain algorithms to be simulated in memory much more efficiently:

>>> eng = sf.Engine("gaussian")
>>> results = eng.run(prog, shots=3)


The engine automatically takes this mode shifting into account; returned samples will always be transformed to match the modes specified during construction:

>>> print(results.all_samples)
{0: [array([1.26208025]), array([1.53910032]), array([-1.29648336]),
array([0.75743215]), array([-0.17850101]), array([-1.44751996])]}


Note that, unlike the standard Program, the TDM context manager has both required and essential arguments:

• Positional arguments are used to pass sequences of gate arguments to apply per time-bin. Within the context, these are accessible via the p context variable; p[i] corresponds to the i-th positional arguments.

All positional arguments corresponding to sequences of gate arguments must be the same length. This length determines how many time-bins are present in the TDM program.

If the p variable is not used, the gate argument is assumed to be constant across all time-bins.

• shift="default" (str or int): Defines how the qumode register is shifted at the end of each time bin. If set to "default", the qumode register is shifted such that each measured qumode reappears as a fresh mode at the beginning of the subsequent time bin. This is equivalent to a measured qumode being removed from the representation (by measurement) and a new one being added (by a light source). If set to an integer value, the register will shift by a step size of this integer at the end of each time bin.

 compile_info The device specification and the compiler that was used during compilation. num_subsystems Return the current number of valid quantum modes. parameters Return the parameters of the TDMProgram as a dictionary with the parameter name as keys, and the parameter lists as values register Return a tuple of all the currently valid quantum modes. target The target specification the program has been compiled against.
compile_info

The device specification and the compiler that was used during compilation.

If the program has not been compiled, this will return None.

Returns

device specification and the short name of the Compiler that was used if compiled, otherwise None

Return type

tuple or None

num_subsystems

Return the current number of valid quantum modes.

Returns

number of currently valid register subsystems

Return type

int

parameters

Return the parameters of the TDMProgram as a dictionary with the parameter name as keys, and the parameter lists as values

register

Return a tuple of all the currently valid quantum modes.

Returns

valid subsystem references

Return type

tuple[RegRef]

target

The target specification the program has been compiled against.

If the program has not been compiled, this will return None.

Returns

the short name of the target Compiler template if compiled, otherwise None

Return type

str or None

 append(op, reg) Append a command to the program. apply_op(cmd, q, t) Apply a particular operation on register q at timestep t assert_number_of_modes(device) Check that the number of modes in the program is valid for the given device. bind_params(binding) Binds the free parameters of the program to the given values. can_follow(prev) Check whether this program can follow the given program. compile(*[, device, compiler]) Compile the time-domain program given a Strawberry Fields photonic hardware device specification. context(*args[, shift]) Syntactic sugar for defining a Program using the with statement. draw_circuit([tex_dir, write_to_file]) Draw the circuit using the Qcircuit $$\LaTeX$$ package. Finalize the program. Simplify and optimize the program. params(*args) Create and access free circuit parameters. print([print_fn]) Print the program contents using Blackbird syntax. Represent the program in a compressed way without rolling the for loops unroll(shots) Construct program with the register shift
append(op, reg)

Append a command to the program.

Parameters
• op (Operation) – quantum operation

• reg (list[int, RegRef]) – register subsystem(s) to apply it to

Returns

subsystem list as RegRefs

Return type

list[RegRef]

apply_op(cmd, q, t)[source]

Apply a particular operation on register q at timestep t

assert_number_of_modes(device)[source]

Check that the number of modes in the program is valid for the given device.

bind_params(binding)

Binds the free parameters of the program to the given values.

Parameters

binding (dict[Union[str, FreeParameter], Any]) – mapping from parameter names (or the parameters themselves) to parameter values

Raises

ParameterError – tried to bind an unknown parameter

can_follow(prev)

Check whether this program can follow the given program.

This requires that the final RegRef state of the first program matches the initial RegRef state of the second program, i.e., they have the same number number of RegRefs, all with identical indices and activity states.

Parameters

prev (Program) – preceding program fragment

Returns

True if the Program can follow prev

Return type

bool

compile(*, device=None, compiler=None)[source]

Compile the time-domain program given a Strawberry Fields photonic hardware device specification.

Currently, the compilation is simply a check that the program matches the device.

Parameters
• device (DeviceSpec) – device specification object to use for program compilation

• compiler (str, Compiler) – Compiler name or compile strategy to use. If a device is specified, this overrides the compile strategy specified by the hardware DeviceSpec. If no compiler is passed, the default “TD2” compiler is used. Currently, the only other allowed compiler is “gaussian”.

Returns

compiled program

Return type

Program

context(*args, shift='default')[source]

Syntactic sugar for defining a Program using the with statement.

The Program object itself acts as the context manager.

draw_circuit(tex_dir='./circuit_tex', write_to_file=True)

Draw the circuit using the Qcircuit $$\LaTeX$$ package.

This will generate the LaTeX code required to draw the quantum circuit diagram corresponding to the Program.

The drawing of the following Xanadu supported operations are currently supported:

Gate type

Supported gates

Single mode gates

Two mode gates

Note

Measurement operations MeasureHomodyne, MeasureHeterodyne, and MeasureFock are not currently supported.

Parameters
• tex_dir (str) – relative directory for latex document output

• write_to_file (bool) – if False, no output file is created

Returns

filename of the written tex document and the written tex content

Return type

list[str]

lock()

Finalize the program.

When a Program is locked, no more Commands can be appended to it. The locking happens when the program is run, compiled, or a successor Program is constructed, in order to ensure that the RegRef state of the Program does not change anymore.

optimize()

Simplify and optimize the program.

The simplifications are based on the algebraic properties of the gates, e.g., combining two consecutive gates of the same gate family.

Returns a copy of the program, sharing RegRefs with the original.

Returns

optimized copy of the program

Return type

Program

params(*args)

Create and access free circuit parameters.

Returns the named free parameters. If a parameter does not exist yet, it is created and returned.

Parameters

*args (tuple[str]) – name(s) of the free parameters to access

Returns

requested parameter(s)

Return type

FreeParameter, list[FreeParameter]

print(print_fn=<built-in function print>)

Print the program contents using Blackbird syntax.

Example:

# create a 3 mode quantum program
prog = sf.Program(3)

with prog.context as q:
ops.Sgate(0.54) | q[0]
ops.Sgate(0.54) | q[1]
ops.Sgate(0.54) | q[2]
ops.BSgate(0.43, 0.1) | (q[0], q[2])
ops.BSgate(0.43, 0.1) | (q[1], q[2])
ops.MeasureFock() | q

>>> prog.print()
Sgate(0.54, 0) | (q[0])
Sgate(0.54, 0) | (q[1])
Sgate(0.54, 0) | (q[2])
BSgate(0.43, 0.1) | (q[0], q[2])
BSgate(0.43, 0.1) | (q[1], q[2])
MeasureFock | (q[0], q[1], q[2])

Parameters

print_fn (function) – optional custom function to use for string printing

roll()[source]

Represent the program in a compressed way without rolling the for loops

unroll(shots)[source]

Construct program with the register shift

Constructs the unrolled single-shot program, storing it in self.unrolled_circuit when run for the first time, and returns the unrolled program including shots.

Parameters

shots (int) – the number of times the circuit should be repeated

Returns

unrolled program (including shots)

Return type

Program