# polycirc.permutation

Basic permutations and maps which do not rely on operations

polycirc.permutation.identity(n: int)

`identity(n) : n → n` is the circuit which returns its inputs unchanged

polycirc.permutation.twist(m: int, n: int)

`twist(a, b) : a + b → b + a` swaps the first `a` inputs with the remaining `b` inputs.

polycirc.permutation.interleave(n: int)

`interleave(n) : n + n → 2n` is the circuit taking two `n`-dimensional inputs and interleaving their values.

```>>> from polycirc.ast import diagram_to_function
>>> f = diagram_to_function(interleave(2))
>>> f(1, 2, 1, 2)
[1, 1, 2, 2]
```
polycirc.permutation.cointerleave(n: int)

`cointerleave(n) : 2n → n` is the inverse of `interleave(n)`

```>>> from polycirc.ast import diagram_to_function
>>> f = diagram_to_function(cointerleave(2))
>>> f(1, 1, 2, 2)
[1, 2, 1, 2]
```
polycirc.permutation.block_interleave(num_blocks: int, block_size: int)

`block_interleave(num_blocks, block_size)` is like `interleave`, each `n`-dimensional input vector is thought of having elements of size `m`.

```>>> from polycirc.ast import diagram_to_function
>>> f = diagram_to_function(interleave(2))
>>> g = diagram_to_function(block_interleave(num_blocks=2, block_size=1))
>>> f(1, 1, 2, 2) == g(1, 1, 2, 2)
True
```
polycirc.permutation.transpose(n: int, m: int)

Given an `n×m`-dimensional input thought of as a 2D array, transpose it to get a `m×n`-dimensional output