Circuit

class perceval.components.linear_circuit.Circuit(m, name=None)

Class to represent any circuit composed of one or multiple components

Parameters:
  • m (int) – The number of port of the circuit

  • name (Optional[str]) – Name of the circuit

property U

get the symbolic unitary matrix

__floordiv__(component)

Build a new circuit by adding component to the current circuit

>>> c = a // b   # equivalent to: `Circuit(n) // self // component`
Parameters:

component (Union[ACircuit, Tuple[int, ACircuit]]) – the component to add, or a tuple (first_port, component)

Return type:

Circuit

__ifloordiv__(component)

Shortcut for .add

>>> c //= b       # equivalent to: `c.add((0:b.n),b)`
>>> c //= (i, b)  # equivalent to: `c.add((i:i+b.n), b)`
Parameters:

component (Union[ACircuit, Tuple[int, ACircuit]]) – the component to add, or a tuple (first_port, component)

Return type:

Circuit

add(port_range, component, merge=False, x_grid=None)

Add a component in a circuit

Parameters:
  • port_range (Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]]) – the port range as a tuple of consecutive ports, or the initial port where to add the component

  • component (ACircuit) – the component to add, must be a linear component or circuit

  • merge (bool) – when the component is a complex circuit, if True, flatten the added circuit. Otherwise keep the nested structure (default False)

X_grid:

if not None, the component is aligned based on this x_grid value according to the following rule: - any other component with the same x_grid will be vertically aligned - components with lower x_grids will be on the left

Return type:

Circuit

Returns:

the circuit itself, allowing to add multiple components in a same line

Raise:

AssertionError if parameters are not valid

barrier()

Add a barrier to a circuit

The barrier is a visual marker to break down a circuit into sections. Behind the scenes, it is implemented as a Barrier unitary operating on all modes.

At the moment, the barrier behaves exactly like a component with a unitary equal to identity.

compute_unitary(use_symbolic=False, assign=None, use_polarization=None)

Compute the unitary matrix corresponding to the circuit

Parameters:
  • assign (Optional[dict]) –

  • use_symbolic (bool) –

  • use_polarization (Optional[bool]) –

Return type:

Matrix

Returns:

static decomposition(U, component, phase_shifter_fn=None, shape=InterferometerShape.TRIANGLE, permutation=None, inverse_v=False, inverse_h=False, constraints=None, merge=True, precision=1e-06, max_try=10, allow_error=False, ignore_identity_block=True)

Decompose a given unitary matrix U into a circuit with a specified component type

Parameters:
  • U (MatrixN) – the matrix to decompose

  • component (ACircuit) – a circuit, to solve any decomposition must have up to 2 independent parameters

  • phase_shifter_fn (Optional[Callable[[int], ACircuit]]) – a function generating a phase_shifter circuit. If None, residual phase will be ignored

  • shape (Union[str, InterferometerShape]) – shape of the decomposition (triangle is natively supported in Perceval)

  • permutation (Optional[Type[ACircuit]]) – if provided, type of permutation operator to avoid unnecessary operators

  • inverse_v (bool) – inverse the decomposition vertically

  • inverse_h (bool) – inverse the decomposition horizontally

  • constraints – constraints to apply on both parameters, it is a list of individual constraints. Each constraint should have the numbers of free parameters of the system.

  • merge (bool) – don’t use sub-circuits

  • precision (float) – for intermediate values - norm below precision are considered 0. If not - use global_params

  • max_try (int) – number of times to try the decomposition

  • allow_error (bool) – allow decomposition error - when the actual solution is not locally reachable

  • ignore_identity_block (bool) – If true, do not insert a component when it’s not needed (component is an identity) Otherwise, insert a component everytime (default True).

Returns:

a circuit

property defined: bool

check if all parameters of the circuit are fully defined

definition()

Gives mathematical definition of the circuit

Only defined for elementary circuits

Return type:

Matrix

depths()

Return depth of the circuit for each mode

describe(map_param_kid=None)

Describe a circuit

Parameters:

map_param_kid – internal parameter

Return type:

str

Returns:

a string describing the circuit that be re-used to define the circuit

find_subnodes(pos)

find the subnodes of a given component (Udef for pos==None)

Parameters:

pos (int) – the position of the current node

Return type:

List[int]

Returns:

get_parameters(all_params=False)

Return the parameters of the circuit

Parameters:

all_params (bool) – if False, only returns the variable parameters

Return type:

List[Parameter]

Returns:

the list of parameters

getitem(idx, only_parameterized=False)

Direct access to components of the circuit :type idx: Tuple[int, int] :param idx: index of the component as (row, col) :type only_parameterized: bool :param only_parameterized: if True, only count components with parameters :rtype: ACircuit :return: the component

group_components_by_xgrid()

Group the components according to their x_grid to facilitate rendering

Grouping rule is simple: components without x_grid are singleton, components with similar x_grid are grouped together at the position of the first one, moving of the components force recursively parents components to move This reordering works if x_grid values are consistent which is guaranteed by construction

identify(unitary_matrix, phases, precision=None, max_try=10, allow_error=False)

Identify an instance of the current circuit (should be parameterized) such as \(Q.C=U.P\) where \(Q\) and \(P\) are single-mode phase shifts (resp. \([q1, q2, ..., qn]\), and \([p1, p2, ...,pn]\)). This is solved through \(n^2\) equations: \(q_i * C_{i,j}(x,y, ...) = UP_{i,j} * p_j\)

Parameters:
  • unitary_matrix – the matrix to identify

  • phases – phase shift parameters

  • max_try – the resolution is using parameter search starting on a random points, it might fail, this parameter sets the maximal number of times to try

Return type:

None

is_composite()

Returns True if the component is itself composed of subcomponents

match(pattern, pos=None, pattern_pos=0, browse=False, match=None, actual_pos=None, actual_pattern_pos=None, reverse=False)

match a sub-circuit at a given position

Parameters:
  • match (Optional[Match]) – the partial match

  • browse (bool) – true if we want to search the pattern at any location in the current circuit, if true, pos should be None

  • pattern (ACircuit) – the pattern to search for

  • pos (Optional[int]) – the start position in the current circuit

  • pattern_pos (int) – the start position in the pattern

  • actual_pos (Optional[int]) – unused, parameter only used by parent class

  • actual_pattern_pos (Optional[int]) – unused, parameter only used by parent class

  • reverse (bool) – true if we want to search the pattern from the end of the circuit to pos (or the 0 if browse)

Return type:

Optional[Match]

Returns:

property name: str

Returns component name

ncomponents()

Return number of actual components in the circuit

property requires_polarization: bool

Does the circuit require polarization?

Returns:

is True if the circuit has a polarization component

transfer_from(source, force=False)

Transfer parameters of a circuit to the current one

Parameters:
  • source (ACircuit) – the circuit to transfer the parameters from. The shape of the circuit to transfer from should be a subset of the current circuit.

  • force (bool) – force changing fixed parameter if necessary