# Entanglers

The Classiq entangler tools include three functions designed for creating entangled state vectors. All entanglers construct graph states [1] , according to specific types of graphs, when applied to the all-zero ($$\ket{0}...\ket{0}$$) state vector. A graph state $$\ket{G}$$ corresponding to graph G = (V,E) is defined as

$\ket{G} = \prod_{(a,b) \in E} CZ_{(a,b)} \ket{+}^{\bigotimes V}.$

The graph state is prepared by first applying Hadamard gates to all qubits in the graph, which correspond to the nodes in V, and then applying CZ gates to qubit pairs, which correspond to the edges in E. Note that the CZ operations commute, and therefore the order in which they are applied does not affect the output state of the circuit.

The entanglement is measured by the Schmidt rank width [2] of the state created by the selected entangler, which is defined via sequences of partitions according to a subcubic tree T, where each leaf of T corresponds to a qubit in $$\ket{G}$$. Specifically, the Schmidt rank width of an n-qubit state is defined as

$\chi_{wd} = \min_{T} \max_{e\in T} \chi_{e}$

where $$\chi_{e}$$ is the log of the Schmidt number of the partition defined by removing an internal edge e∈T, the maximum is taken over all internal edges in T, and the minimum is taken over all subcubic trees with n leaves. Since it is defined via a subcubic tree structure, the Schmidt rank width of n-qubit graph state is bounded from above by $$\lceil n/3 \rceil$$. The Schmidt rank width of $$\ket{G}$$ is equal to a width parameter of G – the rank-width $$( rwd(G) )$$ of G [2,3] .

The entanglers included in the function library are the hypercube entangler, the two-dimensional entangler, and the grid entangler.

## Hypercube Entangler¶

Function: HypercubeEntangler

Parameter:

• qubit_count (int)

### Syntax¶

Example 1

{
"logic_flow": [{
"function": "HypercubeEntangler",
"function_params": {"qubit_count": 8}
}]
}

from classiq import Model
from classiq.builtin_functions import HypercubeEntangler

hypercube = HypercubeEntangler(qubit_count=8)
model = Model()
model.HypercubeEntangler(hypercube)

circuit = model.synthesize()


Output circuit:

### Description¶

The HypercubeEntangler function creates a circuit for constructing a graph state $$\ket{G}$$ whose underlying graph is a d dimensional hypercube G = Qd, where d is the largest possible dimension for the selected number of qubits set by the parameter qubit_count, connected to the remainder of the qubits.

The d-dimensional hypercube Qd is a graph whose vertices are d-dimensional vectors with binary coordinates (i1,…,id) where il={0,1}. The edges in Qd connect vectors that differ in exactly one coordinate. A circuit constructing $$\ket{G=Q_{d}}$$ includes CZ gates between qubits according to their binary representation. For example, qubit 0 whose binary representation is (0, …,0) is connected by CZ gates to qubits 1, 2, 4, … , 2d-1 whose binary representations are (0,…0,1), (0,…,1,0), … ,(1,0,...,0).

An n-qubit graph state whose underlying graph is Qd ($$n=2^{d}$$) is a highly entangled state, whose Schmidt rank width is asymptotically close to the maximal possible.

Specifically, the rank width of $$Q_{d}$$, which is equal to the Schmidt rank width of $$\ket{Q_{d}}$$, is bounded by

$\Omega \left( \frac{n}{(\log n)^{3/2}} \right) = rwd(Q_{d}) = O \left( \frac{n}{(\log n )^{1/2}} \right).$

For n qubits where n= 2d, the function creates a circuit, that, when applied to the |0⟩(⨂n) state, outputs a graph state in the form of d dimensional hypercube Qd.

For qubit_count of 23 = 8 qubits, as in example 1, the circuit generated by the function creates the three-dimensional cube Q3.

For $$2^{d} < n < 2^{d+1}$$, the HypercubeEntangler outputs a circuit connecting each qubit to all its neighbors in a form of an incomplete $$2^{d+1}$$ dimensional hypercube.

For 11 qubits, the circuit constructs a three-dimensional cube connected to the three additional qubits, as follows:

Example 2

{
"logic_flow": [{
"function": "HypercubeEntangler",
"function_params": {"qubit_count": 11}
}]
}

from classiq import Model
from classiq.builtin_functions import HypercubeEntangler

hypercube = HypercubeEntangler(qubit_count=11)
model = Model()
model.HypercubeEntangler(hypercube)

circuit = model.synthesize()


Output circuit:

## Two-dimensional Entangler¶

Function: TwoDimensionalEntangler.

Parameters:

• qubit_count (int)
• schmidt_rank (int)

### Syntax¶

Example 1

{
"logic_flow": [{
"function": "TwoDimensionalEntangler",
"function_params": {"qubit_count": 6, "schmidt_rank": 2}
}]
}

from classiq import Model
from classiq.builtin_functions import TwoDimensionalEntangler

two_D_grid = TwoDimensionalEntangler(qubit_count=6, schmidt_rank=2)
model = Model()
model.TwoDimensionalEntangler(two_D_grid)

circuit = model.synthesize()


Output circuit:

### Description¶

The two-dimensional entangler function creates a circuit for constructing a graph state $$\ket{G}$$ whose underlying graph is a two-dimensional rectangular $$d_{1} \times d_{2}$$ grid where $$d_{1} > d_{2}$$.

The function constructs a circuit for a grid with $$d_{2}$$ equal to the schmidt_rank provided that a sufficiently large qubit_count is specified. Namely, for qubit_count = $$N$$, schmidt_rank = $$K$$, if $$\lfloor N/K \rfloor ≥ K$$ then a $$\lfloor N/K \rfloor$$ by $$K$$ grid is constructed. Otherwise, a circuit for a rectangular grid is constructed, where the smaller dimension is $$d_{2} =\lfloor \sqrt N \rfloor$$ if possible, and $$d_{2} =\lfloor \sqrt N \rfloor-1$$ if not.

Example 2

For qubit_count = 9 and schmidt_rank = 2, a circuit is constructed for a 2x4 grid.

{
"logic_flow": [{
"function": "TwoDimensionalEntangler",
"function_params": {"qubit_count": 9, "schmidt_rank": 2}
}]
}

from classiq import Model
from classiq.builtin_functions import TwoDimensionalEntangler

two_D_grid = TwoDimensionalEntangler(qubit_count=9, schmidt_rank=2)
model = Model()
model.TwoDimensionalEntangler(two_D_grid)

circuit = model.synthesize()


Output circuit:

Example 3

For qubit_count = 17 and schmidt_rank = 5, a circuit is constructed for a 3x5 grid.

{
"logic_flow": [{
"function": "TwoDimensionalEntangler",
"function_params": {"qubit_count": 17, "schmidt_rank": 5}
}]
}

from classiq import Model
from classiq.builtin_functions import TwoDimensionalEntangler

two_D_grid = TwoDimensionalEntangler(qubit_count=17, schmidt_rank=5)
model = Model()
model.TwoDimensionalEntangler(two_D_grid)

circuit = model.synthesize()


Output circuit:

## Grid Entangler¶

Function: GridEntangler

Parameters:

• qubit_count (int)
• schmidt_rank (int)
• grid_randomization Optional (bool)

### Syntax¶

Example 1

{
"logic_flow": [{
"function": "GridEntangler",
"function_params": {"qubit_count": 16, "schmidt_rank": 4}
}]
}

from classiq import Model
from classiq.builtin_functions import GridEntangler

grid = GridEntangler(qubit_count=16, schmidt_rank=4)
model = Model()
model.GridEntangler(grid)

circuit = model.synthesize()


Output circuit:

### Description¶

The grid entangler function creates a circuit for constructing a graph state whose underlying graph is a multidimensional $$d_{1} \times d_{2}\times ... \times d_{n}$$ grid, where $$d_{1} \leq d_{2} \leq ...\leq d_{n}$$. The grid entangler function attempts to construct a grid whose dimensions obey these conditions:

1. qubit_count = $$d_{1} \times d_{2} \times ...\times d_{n}$$ and
2. schmidt_rank = $$d_{1} \times d_{2} \times...\times d_{n-1}$$, where
3. $$(d_{1}-1) + ...+ (d_{n-1}-1) < d_{n}-1$$.

If the conditions cannot be met, then a grid is constructed with qubit_count < $$d_{1} \times d_{2}\times...\times d_{n}$$, and $${d_{1} \times...\times d_{n-1}}$$ as close as possible to, and smaller than, the schmidt_rank.

The optional grid_randomization parameter triggers a randomization of the grid structure. By default, grid_randomization = True. If grid_randomization = False, the selected (default) grid structure has a maximal number of dimensions (n) and minimal $$d_{1},..., d_{n-1}$$ dimensions (and therefore maximal $$d_{n}$$). For grid_randomization = True, the grid structure is selected randomly out of all grids with the same products $$d_{1} \times ...\times d_{n}$$ and $$d_{1} \times ...\times d_{n-1}$$ as in the default grid, which obeys condition 3.

For qubit_count = 12 and schmidt_rank = 4, the generated circuit constructs a 2x2x4 grid as in example 1.

Example 2

For qubit_count = 25, schmidt_rank = 4, and grid_randomisation = false, the generated circuit constructs a 2x2x6 grid (note that one qubit remains unconnected to the grid).

{
"logic_flow": [
{
"function": "GridEntangler",
"function_params": {
"qubit_count": 25,
"schmidt_rank": 4,
"grid_randomization": false
}
}
]
}

from classiq import Model
from classiq.builtin_functions import GridEntangler

grid = GridEntangler(qubit_count=25, schmidt_rank=4, grid_randomization=False)
model = Model()
model.GridEntangler(grid)

circuit = model.synthesize()


Output circuit:

Example 3

For qubit_count = 25 and schmidt_rank = 4 (grid_randomization is by default true), one may obtain either the circuit of the previous example, or the following output circuit constructing a 4x6 grid.

{
"logic_flow": [
{
"function": "GridEntangler",
"function_params": {
"qubit_count": 25,
"schmidt_rank": 4
}
}
]
}

from classiq import Model
from classiq.builtin_functions import GridEntangler

grid = GridEntangler(qubit_count=25, schmidt_rank=4)
model = Model()
model.GridEntangler(grid)

circuit = model.synthesize()


One of the possible output circuits:

## References¶

[1] M. Hein, W. Dur, J. Eisert, R. Raussendorf, M. Van den Nest, H. J. Briegel, "Entanglement in Graph States and its Applications", Phys. Rev. A, 63320645, (2006), arXiv:quant-ph/0602096 (2006).

[2] M. Van den Nest, W. Dur, G. Vidal, H. J. Briegel, "Classical simulation versus universality in measurement-based quantum computation", Phys. Rev. A 75, 012337 (2007).

[3] S.-I. Oum, "Rank-width: Algorithmic and structural results", Lect. Notes Comput. Sci. 3787, 49 (2005).