# 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 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)

Return type:

Circuit

Returns:

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

Raise:

AssertionError if parameters are not valid

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='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 (str) – 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:

static generic_interferometer(m, fun_gen, shape='rectangle', depth=None, phase_shifter_fun_gen=None, phase_at_output=False)

Generate a generic interferometer with generic elements and optional phase_shifter layer

Parameters:
• m (int) – number of modes

• fun_gen (Callable[[int], ACircuit]) – generator function for the building components, index is an integer allowing to generate named parameters - for instance: fun_gen=lambda idx: phys.BS()//(0, phys.PS(pcvl.P("phi_%d"%idx)))

• shape (str) – rectangle or triangle

• depth (Optional[int]) – if None, maximal depth is $$m-1$$ for rectangular shape, $$m$$ for triangular shape. Can be used with $$2*m$$ to reproduce .

• phase_shifter_fun_gen (Optional[Callable[[int], ACircuit]]) – a function generating a phase_shifter circuit.

• phase_at_output (bool) – if True creates a layer of phase shifters at the output of the generated interferometer else creates it in the input (default: False)

Return type:

Circuit

Returns:

a circuit

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

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:

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