Circuit

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

Class to represent any circuit composed of one or multiple components

Parameters
  • m (Optional[int]) – The number of port of the circuit, if omitted the parameter U should be defined

  • U – Unitary matrix defining the circuit

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

  • use_polarization – defines if the circuit should be used with Polarized states. This value is automatically induced when a component working on polarization is added to the circuit

property U

get the numeric unitary matrix, circuit has to be defined

__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=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 circuit

  • merge (Optional[bool]) – if the component is a complex circuit,

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)

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

Parameters
  • U (MatrixN) – the matrix to decompose

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

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

  • 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.

  • inverse_v (bool) – inverse the decomposition vertically

  • inverse_h (bool) – inverse the decomposition horizontally

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

  • shape (Literal[‘triangle’]) – triangle

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

  • 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

Returns

a circuit

property defined

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)

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 (Literal[‘triangle’, ‘rectangle’]) – 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 [Fldzhyan et al., 2020].

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

Return type

ACircuit

Returns

a circuit

See [Fldzhyan et al., 2020], [Clements et al., 2016] and [Reck et al., 1994]

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

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

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

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

Return type

Optional[Match]

Returns

ncomponents()

Return number of actual components in the circuit

property requires_polarization: bool

Does the circuit require polarization?

Return type

bool

Returns

is True if the circuit has a polarization component

shape(_, canvas, compact=False)

Implement in subclasses to render the circuit on canvas

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