sf.Program

class Program(num_subsystems, name=None)[source]

Bases: object

Represents a photonic quantum circuit.

The program class provides a context manager for:

  • accessing the quantum register associated with the program, and

  • appending Operations to the program.

Within the context, operations are appended to the program using the syntax

ops.GateName(arg1, arg2, ...) | (q[i], q[j], ...)

where ops.GateName is a valid quantum operation, and q is a list of the programs quantum modes. All operations are appended to the program in the order they are listed within the context.

In addition, some ‘meta-operations’ (such as New() and Del) are provided to modify the programs quantum register itself by adding and deleting subsystems.

Note

Two programs can be run successively on the same engine if and only if the number of registers at the end of the first program matches the number of modes at the beginning of the second program.

This can be enforced by constructing the second program as an explicit successor of the first, in which case the registers are directly copied over.

When a Program is run or it obtains a successor, it is locked and no more operations can be appended to it.

Example:

import strawberryfields as sf
from strawberryfields import ops

# 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
Parameters
  • num_subsystems (int, Program) – Initial number of modes (subsystems) in the quantum register. Alternatively, another Program instance from which to inherit the register state.

  • name (str) – program name (optional)

context

Syntactic sugar for defining a Program using the with statement.

num_subsystems

Return the current number of valid quantum modes.

register

Return a tuple of all the currently valid quantum modes.

context

Syntactic sugar for defining a Program using the with statement.

The Program object itself acts as the context manager.

num_subsystems

Return the current number of valid quantum modes.

Returns

number of currently valid register subsystems

Return type

int

register

Return a tuple of all the currently valid quantum modes.

Returns

valid subsystem references

Return type

tuple[RegRef]

append(op, reg)

Append a command to the program.

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(target, **kwargs)

Compile the program targeting the given circuit specification.

draw_circuit([tex_dir, write_to_file])

Draw the circuit using the Qcircuit \(\LaTeX\) package.

lock()

Finalize the program.

optimize()

Simplify and optimize the program.

params(*args)

Create and access free circuit parameters.

print([print_fn])

Print the program contents using Blackbird syntax.

append(op, reg)[source]

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]

bind_params(binding)[source]

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)[source]

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(target, **kwargs)[source]

Compile the program targeting the given circuit specification.

Validates the program against the given target, making sure all the Operations used are accepted by the target specification.

Additionally, depending on the target, the compilation may modify the quantum circuit into an equivalent circuit, e.g., by decomposing certain gates into sequences of simpler gates, or optimizing the gate ordering using commutation rules.

Example:

The gbs compile target will compile a circuit consisting of Gaussian operations and Fock measurements into canonical Gaussian boson sampling form.

>>> prog2 = prog.compile('gbs')
Parameters

target (str, CircuitSpecs) – short name of the target circuit specification, or the specification object itself

Keyword Arguments
  • optimize (bool) – If True, try to optimize the program by merging and canceling gates. The default is False.

  • warn_connected (bool) – If True, the user is warned if the quantum circuit is not weakly connected. The default is True.

Returns

compiled program

Return type

Program

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

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

Dgate, Xgate, Zgate, Sgate, Rgate, Pgate, Vgate, Kgate, Fouriergate

Two mode gates

BSgate, S2gate, CXgate, CZgate, CKgate

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()[source]

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()[source]

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.

See optimize_circuit().

Returns

optimized copy of the program

Return type

Program

params(*args)[source]

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>)[source]

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