# 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

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

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 = Q_{d}, 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 Q_{d} is a graph whose vertices are d-dimensional vectors
with binary coordinates (i_{1},…,i_{d}) where i_{l}={0,1}.
The edges in Q_{d} 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, … , 2^{d-1}
whose binary representations are (0,…0,1), (0,…,1,0), … ,(1,0,...,0).

An n-qubit graph state whose underlying graph is Q_{d} (\(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

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

For `qubit_count`

of 2^{3} = 8 qubits, as in example 1, the circuit generated by the
function creates the three-dimensional cube Q_{3}.

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:

`qubit_count`

= \(d_{1} \times d_{2} \times ...\times d_{n}\) and`schmidt_rank`

= \(d_{1} \times d_{2} \times...\times d_{n-1}\), where- \((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).