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 circuitname (
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:
- __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:
- 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 componentcomponent (
ACircuit
) – the component to add, must be a linear component or circuitmerge (
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:
- 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:
- 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 decomposecomponent (
ACircuit
) – a circuit, to solve any decomposition must have up to 2 independent parametersphase_shifter_fn (
Optional
[Callable
[[int
],ACircuit
]]) – a function generating a phase_shifter circuit. If None, residual phase will be ignoredshape (
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 operatorsinverse_v (
bool
) – inverse the decomposition verticallyinverse_h (
bool
) – inverse the decomposition horizontallyconstraints – 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-circuitsprecision (
float
) – for intermediate values - norm below precision are considered 0. If not - use global_paramsmax_try (
int
) – number of times to try the decompositionallow_error (
bool
) – allow decomposition error - when the actual solution is not locally reachableignore_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:
- 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 matchbrowse (
bool
) – true if we want to search the pattern at any location in the current circuit, if true, pos should be Nonepattern (
ACircuit
) – the pattern to search forpos (
Optional
[int
]) – the start position in the current circuitpattern_pos (
int
) – the start position in the patternactual_pos (
Optional
[int
]) – unused, parameter only used by parent classactual_pattern_pos (
Optional
[int
]) – unused, parameter only used by parent classreverse (
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