qubiter.device_specific.ForbiddenCNotExpander module¶
-
class
qubiter.device_specific.ForbiddenCNotExpander.
ForbiddenCNotExpander
(file_prefix, num_qbits, c_to_tars)[source]¶ Bases:
qubiter.EchoingSEO_reader.EchoingSEO_reader
Most chips are not fully connected (not all pairs of qubits are physically connected). Furthermore, even if two qubits are connected, one of them may be disallowed, forbidden, as a target of a CNOT between the 2 qubits. This class is designed to circumvent this chip limitation.
This class is a child of the class EchoingSEO_reader. It is one of several expander classes that replace certain single gates by expansions (sequences) of other gates.
The class reads an English file and outputs a new English file and corresponding Picture file. The new English file echoes every line of the original English file except for those lines which are SIGX with one or more controls.
If this class reads a line which is a SIGX with > 1 controls, it outputs an error message. In such a case, you should use the class CGateExpander first to expand such gates into single qubit rotations and simple CNOTs with a single control.
If this class reads a line which is a SIGX with a single control, it echoes it if such a CNOT is allowed according to the input list ‘c_to_tars’. Otherwise, it replaces the disallowed (a.k.a., forbidden, unphysical, between disconnected qubits) CNOT by a sequence of Hadamards and allowed, elementary CNOTs.
Next we explain the expansion used by this class to replace forbidden CNOTs.
Let us denote a CNot with control a and target b by C(a->b)=C(a, b)
Note that if C(a, b) is forbidden but C(b, a) is allowed, we can express the forbidden one in terms of the allowed one and four Hadamard matrices using the identity (X is the target SIGX and @ is the True control):
X---@
equals:
H H @---X H H
Note that:
X---+---@
equals:
X---@ | | X---@ X---@ | | X---@
equals:
| X---@ X---@ | | X---@ X---@ |
One can generalize the previous identity as follows:
X---+---+---@
equals:
X---+---@ | | | X---@ X---+---@ | | | X---@
equals:
| X---@ | X---@ | | | X---@ | X---@ | | | | X---@ X---@ | | | X---@ | X---@ | | | X---@ | | | X---@
equals (cancel two internal CNots):
| X---@ | X---@ | | | X---@ | | | X---@ | X---@ | X---@ | | | X---@ | | | X---@
One can generalize the previous identity as follows:
X---+---+---+---@
equals:
| | X---@ | | X---@ | | X---@ | | | | X---@ | | | | X---@ | | | | X---@ | | X---@ | | X---@ | | X---@ | | | | X---@ | | | | X---@ | | | | X---@
In general, let’s define a composite V gate (called V because it looks like a V lying on its side) as follows:
V(0->4) = | | | X---@ | | X---@ | | X---@ | | X---@ | | | | X---@ | | | | X---@ | | | | X---@
Above, 0, 1, 2, 3, 4 can be replaced by any other distinct qubits. Also, on can define an analogous V for any number >= 2 of qubits.
If:
C(0->4)= X---+---+---+---@
then we proved above that:
C(0->4)= V(0->4)V(1->4)
In fact, we also proved:
C(0->j)= V(0->j)V(1->j) for j = 2, 3, 4, ...
We like to refer to the last equation as the vv expansion of C(0->j). In this class, we expand a forbidden CNot C(trol->targ) using the last equation with the qubit positions 0, 1, 2, …, j in the last equation mapped in a 1-1 onto fashion to qubit positions along a path of qubits connecting the two qubits trol and targ. The path is found by calling the python networkx function that yields the shortest path between two nodes of an undirected graph G. We let G be the undirected graph that has as edges all pairs of qubits that are coupled according to the input c_to_tars.
Variables: - c_to_tars (dict[int, list[int]]) – a dictionary mapping j in range(num_qbits) to a list, possibly empty, of the physically allowed targets of qubit j, when j is the control of a CNOT.
- graph (networkx.Graph) – A networkx undirected graph derived from c_to_tars by taking all items in get_dir_edges_from_c_to_tars(c_to_tars) as edges.
-
__init__
(file_prefix, num_qbits, c_to_tars)[source]¶ Constructor
Parameters: - file_prefix (str) –
- num_qbits (int) –
- c_to_tars (dict[int, list[int]]) –
-
edge_type
(x, y)[source]¶ Returns 0 if C(x->y) and C(y->x) are both allowed.
Returns 1 if C(x->y) but not C(y->x) are allowed.
Returns -1 if C(y->x) but not C(x->y) are allowed.
Returns error message if neither is allowed.
Parameters: - x (int) –
- y (int) –
Returns: Return type: int
-
get_symbolic_vv_expansion
(trol_pos, targ_pos)[source]¶ This function returns a list called expansion. The items in expansion can be either a tuple (int, int) or a tuple (int, bool). A tuple (c, t): (int, int) signifies a CNot with control c and target t. A tuple (k, keep): (int, bool) signifies a Hadamard matrix at qubit k and whether to keep it or not–not if it cancels another Hadamard. This symbolic expansion is supposed to replace a CNot trol_pos->targ_pos.
Parameters: - trol_pos (int) –
- targ_pos (int) –
Returns: Return type: list[tuple(int, int)|tuple(int, bool)]