```
pip install strawberryfields
```

    Requirement already satisfied: strawberryfields in /usr/local/lib/python3.6/dist-packages (0.14.0)
    Requirement already satisfied: urllib3>=1.25.3 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (1.25.9)
    Requirement already satisfied: appdirs in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (1.4.4)
    Requirement already satisfied: networkx>=2.0 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (2.4)
    Requirement already satisfied: scipy>=1.0.0 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (1.4.1)
    Requirement already satisfied: numba in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (0.48.0)
    Requirement already satisfied: toml in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (0.10.1)
    Requirement already satisfied: python-dateutil>=2.8.0 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (2.8.1)
    Requirement already satisfied: sympy>=1.5 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (1.6.1)
    Requirement already satisfied: quantum-blackbird>=0.2.3 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (0.2.4)
    Requirement already satisfied: requests>=2.22.0 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (2.23.0)
    Requirement already satisfied: numpy>=1.17.4 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (1.18.5)
    Requirement already satisfied: thewalrus>=0.12 in /usr/local/lib/python3.6/dist-packages (from strawberryfields) (0.12.0)
    Requirement already satisfied: decorator>=4.3.0 in /usr/local/lib/python3.6/dist-packages (from networkx>=2.0->strawberryfields) (4.4.2)
    Requirement already satisfied: llvmlite<0.32.0,>=0.31.0dev0 in /usr/local/lib/python3.6/dist-packages (from numba->strawberryfields) (0.31.0)
    Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from numba->strawberryfields) (49.1.0)
    Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.8.0->strawberryfields) (1.12.0)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.6/dist-packages (from sympy>=1.5->strawberryfields) (1.1.0)
    Requirement already satisfied: antlr4-python3-runtime==4.7.2 in /usr/local/lib/python3.6/dist-packages (from quantum-blackbird>=0.2.3->strawberryfields) (4.7.2)
    Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests>=2.22.0->strawberryfields) (2.10)
    Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests>=2.22.0->strawberryfields) (2020.6.20)
    Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests>=2.22.0->strawberryfields) (3.0.4)
    Requirement already satisfied: dask[delayed] in /usr/local/lib/python3.6/dist-packages (from thewalrus>=0.12->strawberryfields) (2.12.0)
    Requirement already satisfied: toolz>=0.7.3; extra == "delayed" in /usr/local/lib/python3.6/dist-packages (from dask[delayed]->thewalrus>=0.12->strawberryfields) (0.10.0)
    Requirement already satisfied: cloudpickle>=0.2.1; extra == "delayed" in /usr/local/lib/python3.6/dist-packages (from dask[delayed]->thewalrus>=0.12->strawberryfields) (1.3.0)

```
import strawberryfields as sf
from strawberryfields.apps import  data, plot, sample
import numpy as np
```

```
from strawberryfields.apps import data, sample

samples = data.Planted()

A = samples.adj
n_mean = samples.n_mean
more_samples = sample.sample(A, n_mean, n_samples=5)
print(more_samples)
```

    [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

```
import networkx as nx

samples = data.Planted()
g = nx.Graph(samples.adj)
samples = sample.postselect(samples, 16, 30)
samples = sample.to_subgraphs(samples, g)
plot.graph(g, samples[7])

```

<meta charset="utf-8" />

```
from strawberryfields.apps import clique

c = clique.shrink(samples[2],g)
plot.graph(g,c)
```

<meta charset="utf-8" />

```
c = clique.grow(c,g)
plot.graph(g,c)
```

<meta charset="utf-8" />

```
c = clique.swap(c,g)
plot.graph(g, c)
```

<meta charset="utf-8" />

```
shrunk_cliques = [clique.shrink(s, g) for s in samples]
search_cliques = [clique.search(s, g, 10) for s in shrunk_cliques]
cliques_plus_lengths = [(len(s), s) for s in shrunk_cliques]
cliques_plus_lengths = sorted(cliques_plus_lengths, reverse=True)
print(cliques_plus_lengths[0])

```

    (8, [21, 22, 24, 25, 26, 27, 28, 29])

```
samples = data.TaceAs()

g = nx.Graph(samples.adj)
samples = sample.postselect(samples, 8,8)
samples = sample.to_subgraphs(samples, g)

cliques = [clique.shrink(s, g) for s in samples]
cliques = [clique.search(s, g, 10) for s in cliques]

print(max(len(c) for c in cliques))
```

    8

```
from strawberryfields.apps import data, sample, vibronic

f = data.Formic()

params_0 = vibronic.gbs_params(f.w, f.wp, f.Ud, f.delta, T=0)
params_300 = vibronic.gbs_params(f.w, f.wp, f.Ud, f.delta, T=300)

samples_0 = sample.vibronic(*params_0, n_samples=10)
samples_300 = sample.vibronic(*params_300, n_samples=10)

energies_0 = vibronic.energies(samples_0, f.w, f.wp)
energies_300 = vibronic.energies(samples_300, f.w, f.wp)

```

```

```


```python
!pip install qiskit==0.16.1
```

    Requirement already satisfied: qiskit==0.16.1 in /usr/local/lib/python3.7/dist-packages (0.16.1)
    Requirement already satisfied: qiskit-aer==0.4.1 in /usr/local/lib/python3.7/dist-packages (from qiskit==0.16.1) (0.4.1)
    Requirement already satisfied: qiskit-ibmq-provider==0.5.0 in /usr/local/lib/python3.7/dist-packages (from qiskit==0.16.1) (0.5.0)
    Requirement already satisfied: qiskit-aqua==0.6.4 in /usr/local/lib/python3.7/dist-packages (from qiskit==0.16.1) (0.6.4)
    Requirement already satisfied: qiskit-ignis==0.2.0 in /usr/local/lib/python3.7/dist-packages (from qiskit==0.16.1) (0.2.0)
    Requirement already satisfied: qiskit-terra==0.12.0 in /usr/local/lib/python3.7/dist-packages (from qiskit==0.16.1) (0.12.0)
    Requirement already satisfied: scipy>=1.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-aer==0.4.1->qiskit==0.16.1) (1.4.1)
    Requirement already satisfied: pybind11>=2.4 in /usr/local/lib/python3.7/dist-packages (from qiskit-aer==0.4.1->qiskit==0.16.1) (2.6.2)
    Requirement already satisfied: numpy>=1.16.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-aer==0.4.1->qiskit==0.16.1) (1.19.5)
    Requirement already satisfied: cython>=0.27.1 in /usr/local/lib/python3.7/dist-packages (from qiskit-aer==0.4.1->qiskit==0.16.1) (0.29.22)
    Requirement already satisfied: requests>=2.19 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (2.23.0)
    Requirement already satisfied: arrow>=0.15.5 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (1.0.3)
    Requirement already satisfied: requests-ntlm>=1.1.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (1.1.0)
    Requirement already satisfied: websockets<8,>=7 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (7.0)
    Requirement already satisfied: nest-asyncio!=1.1.0,>=1.0.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (1.5.1)
    Requirement already satisfied: fastdtw in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (0.3.4)
    Requirement already satisfied: dlx in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (1.0.4)
    Requirement already satisfied: docplex in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (2.20.204)
    Requirement already satisfied: scikit-learn>=0.20.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (0.22.2.post1)
    Requirement already satisfied: pyscf; sys_platform == "linux" or (python_version < "3.8" and sys_platform != "win32") in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (1.7.6.post1)
    Requirement already satisfied: psutil>=5 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (5.4.8)
    Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (2.5.1)
    Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (2.6.0)
    Requirement already satisfied: cvxopt; python_version < "3.8" or sys_platform != "win32" in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (1.2.6)
    Requirement already satisfied: sympy>=1.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (1.7.1)
    Requirement already satisfied: h5py in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (2.10.0)
    Requirement already satisfied: quandl in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (3.6.1)
    Requirement already satisfied: setuptools>=40.1.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.6.4->qiskit==0.16.1) (56.0.0)
    Requirement already satisfied: marshmallow-polyfield<6,>=5.7 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.12.0->qiskit==0.16.1) (5.10)
    Requirement already satisfied: ply>=3.10 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.12.0->qiskit==0.16.1) (3.11)
    Requirement already satisfied: marshmallow<4,>=3 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.12.0->qiskit==0.16.1) (3.11.1)
    Requirement already satisfied: dill>=0.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.12.0->qiskit==0.16.1) (0.3.3)
    Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (2.10)
    Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (2020.12.5)
    Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (3.0.4)
    Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (1.24.3)
    Requirement already satisfied: python-dateutil>=2.7.0 in /usr/local/lib/python3.7/dist-packages (from arrow>=0.15.5->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (2.8.1)
    Requirement already satisfied: typing-extensions; python_version < "3.8" in /usr/local/lib/python3.7/dist-packages (from arrow>=0.15.5->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (3.7.4.3)
    Requirement already satisfied: ntlm-auth>=1.0.2 in /usr/local/lib/python3.7/dist-packages (from requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (1.5.0)
    Requirement already satisfied: cryptography>=1.3 in /usr/local/lib/python3.7/dist-packages (from requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (3.4.7)
    Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from docplex->qiskit-aqua==0.6.4->qiskit==0.16.1) (1.15.0)
    Requirement already satisfied: joblib>=0.11 in /usr/local/lib/python3.7/dist-packages (from scikit-learn>=0.20.0->qiskit-aqua==0.6.4->qiskit==0.16.1) (1.0.1)
    Requirement already satisfied: decorator<5,>=4.3 in /usr/local/lib/python3.7/dist-packages (from networkx>=2.2->qiskit-aqua==0.6.4->qiskit==0.16.1) (4.4.2)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy>=1.3->qiskit-aqua==0.6.4->qiskit==0.16.1) (1.2.1)
    Requirement already satisfied: inflection>=0.3.1 in /usr/local/lib/python3.7/dist-packages (from quandl->qiskit-aqua==0.6.4->qiskit==0.16.1) (0.5.1)
    Requirement already satisfied: more-itertools in /usr/local/lib/python3.7/dist-packages (from quandl->qiskit-aqua==0.6.4->qiskit==0.16.1) (8.7.0)
    Requirement already satisfied: pandas>=0.14 in /usr/local/lib/python3.7/dist-packages (from quandl->qiskit-aqua==0.6.4->qiskit==0.16.1) (1.1.5)
    Requirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.7/dist-packages (from cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (1.14.5)
    Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.14->quandl->qiskit-aqua==0.6.4->qiskit==0.16.1) (2018.9)
    Requirement already satisfied: pycparser in /usr/local/lib/python3.7/dist-packages (from cffi>=1.12->cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.5.0->qiskit==0.16.1) (2.20)

# Task One : Fuandamentals of Qunatum Computation

## Basic Arithmatic Operations & Complex Numbers

```python
5+9
```

    14

```python
12*4
```

    48

Complex numbers are always of the form

\begin{align}
\alpha = a + bi
\end{align}

```python
1j * 1j
```

    (-1+0j)

```python
z = 3 + 4j
w = 1 - 2j
```

```python
import numpy as np
```

```python
print('z=', z)
print('Real(z)=', np.real(z))
print('Imag(z)=', np.imag(z))
```

    z= (3+4j)
    Real(z)= 3.0
    Imag(z)= 4.0

```python
z+w
```

    (4+2j)

```python
z-w
```

    (2+6j)

```python
z/w
```

    (-1+2j)

## Complex conjugate

```python
z
```

    (3+4j)

```python
np.conj(z)
```

    (3-4j)

## Norms/Absolute Values

\begin{align} ||z|| &= \sqrt{zz^*} = \sqrt{|z|^2},\\ ||w|| &= \sqrt{ww^*} = \sqrt{|w|^2}, \end{align}

```python
print('||z||=', np.abs(z))
```

    ||z||= 5.0

```python
print('||w||=', np.abs(w))
```

    ||w||= 2.23606797749979

## Row Vectors, Column Vectors, and Bra-Ket Notation

\begin{align} \text{Column Vector:} \ \begin{pmatrix}
a_1 \\ a_2 \\ \vdots \\ a_n
\end{pmatrix}
\quad \quad \text{Row Vector:} \ \begin{pmatrix}
a_1, & a_2, & \cdots, & a_n
\end{pmatrix} \end{align}

```python
# Create a vector as a row
row_vector = np.array([2-1j, 7j, -3])

# Create a vector as a column
column_vector = np.array([[2+1j],
                          [-5],
                          [2j]])
```

```python
row_vector
```

    array([ 2.-1.j,  0.+7.j, -3.+0.j])

Row vectors in quantum mechanics are also called **bra-vectors**, and are denoted as follows:

\begin{align} \langle A| = \begin{pmatrix}
a_1, & a_2, \cdots, & a_n
\end{pmatrix} \end{align}

Column vectors are also called **ket-vectors** in quantum mechanics denoted as follows:

\begin{align} |B\rangle = \begin{pmatrix}
b_1 \\ b_2 \\ \vdots \\ b_n
\end{pmatrix} \end{align}

In general, if we have a column vector, i.e. a ket-vector:

\begin{align} |A\rangle = \begin{pmatrix}
a_1 \\ a_2 \\ \vdots \\ a_n
\end{pmatrix} \end{align}

the corresponding bra-vector:

\begin{align} \langle A| = \begin{pmatrix}
a_1^*, & a_2^*, & \cdots, & a_n^*
\end{pmatrix} \end{align}

```python
ket_A = np.array([[2-1j],
                  [5]])
ket_B = np.array([[7],
                  [-3j]])
```

```python
print(ket_A + ket_B)
```

    [[9.-1.j]
     [5.-3.j]]

## Inner Product

\begin{align} \langle A| = \begin{pmatrix}
a_1, & a_2, & \cdots, & a_n
\end{pmatrix}, \quad \quad
|B\rangle = \begin{pmatrix}
b_1 \\ b_2 \\ \vdots \\ b_n
\end{pmatrix} \end{align}

Taking the inner product of $\langle A|$ and $|B\rangle$ gives the following:

\begin{align} \langle A| B \rangle &= \begin{pmatrix}
a_1, & a_2, & \cdots, & a_n
\end{pmatrix}
\begin{pmatrix}
b_1 \\ b_2 \\ \vdots \\ b_n
\end{pmatrix}\\
&=
a_1b_1 + a_2b_2 + \cdots + a_nb_n\\
&= \sum_{i=1}^n a_ib_i
\end{align}

```python
# Define the 4x1 matrix version of a column vector (instead of using the np.array() version):
A = np.matrix([[1-1j],
               [3],
               [2j],
               [5+1j]])
A
```

    matrix([[1.-1.j],
            [3.+0.j],
            [0.+2.j],
            [5.+1.j]])

```python
# Define B as a 1x4 matrix
B = np.matrix([[-3j, 2+2j, -6j, -7]])

B
```

    matrix([[-0.-3.j,  2.+2.j, -0.-6.j, -7.+0.j]])

```python
# Compute <B|A>
np.dot(B,A)
```

    matrix([[-20.-4.j]])

## Matrices

\begin{align}
M = \begin{pmatrix}
2-i & -3 \\
-5i & 2
\end{pmatrix}
\end{align}

```python
M = np.array([[2-1j, -3],
              [-5j, 2]])

print(M)
```

    [[ 2.-1.j -3.+0.j]
     [-0.-5.j  2.+0.j]]

```python
M = np.matrix([[2-1j, -3],
               [-5j, 2]])

print(M)
```

    [[ 2.-1.j -3.+0.j]
     [-0.-5.j  2.+0.j]]

Hermitian conjugates are given by taking the conjugate transpose of the matrix

```python
print(M.H)
```

    [[ 2.+1.j -0.+5.j]
     [-3.-0.j  2.-0.j]]

## Tensor Products of Matrices

\begin{align}
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix} \otimes
\begin{pmatrix}
x & y \\
z & w
\end{pmatrix} =
\begin{pmatrix}
a \begin{pmatrix}
x & y \\
z & w
\end{pmatrix} & b \begin{pmatrix}
x & y \\
z & w
\end{pmatrix} \\
c \begin{pmatrix}
x & y \\
z & w
\end{pmatrix} & d \begin{pmatrix}
x & y \\
z & w
\end{pmatrix}
\end{pmatrix} =
\begin{pmatrix}
ax & ay & bx & by \\
az & aw & bz & bw \\
cx & cy & dx & dy \\
cz & cw & dz & dw
\end{pmatrix}
\end{align}

```python
A = np.matrix([[1j+8 , 2j-6], []])

```

    /usr/local/lib/python3.7/dist-packages/numpy/matrixlib/defmatrix.py:145: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
      arr = N.array(data, dtype=dtype, copy=copy)

# Task Two: Qubits, Bloch Sphere and Basis States

```python
import qiskit
qiskit.__qiskit_version__
```

    {'qiskit': '0.16.1',
     'qiskit-aer': '0.4.1',
     'qiskit-aqua': '0.6.4',
     'qiskit-ibmq-provider': '0.5.0',
     'qiskit-ignis': '0.2.0',
     'qiskit-terra': '0.12.0'}

\begin{align}
|\psi \rangle = \begin{pmatrix}
\alpha \\ \beta
\end{pmatrix}, \quad \text{where } \sqrt{\langle \psi | \psi \rangle} = 1.
\end{align}

Think of Qubit as an Electron:

\begin{align}
\text{spin-up}: \ |0\rangle &= \begin{pmatrix} 1\\0 \end{pmatrix} \\
\text{spin-down}: \ |1\rangle & = \begin{pmatrix} 0\\1 \end{pmatrix}
\end{align}

```python
import numpy as np
from qiskit import *
from qiskit.visualization import plot_bloch_vector
%matplotlib inline
```

Another representation is via Bloch Sphere:

```python
plot_bloch_vector([0,0,1], title="Spin-Up")
```

## Spin + / - :

\begin{align}
\text{spin +}: \ |+\rangle &= \begin{pmatrix} 1/\sqrt{2} \\ 1/\sqrt{2} \end{pmatrix} = \frac{1}{\sqrt{2}} \left(|0\rangle + |1\rangle\right) \\
\text{spin -}: \ |-\rangle & = \begin{pmatrix} 1/\sqrt{2} \\ -1/\sqrt{2} \end{pmatrix} = \frac{1}{\sqrt{2}} \left(|0\rangle - |1\rangle\right)
\end{align}

```python
plot_bloch_vector([1,0,0], title="spin-plus")
```

## Basis States

\begin{align}
 |0\rangle &= \begin{pmatrix} 1\\0 \end{pmatrix} \\
 |1\rangle & = \begin{pmatrix} 0\\1 \end{pmatrix}
\end{align}
Preapring other states from Basis States:
\begin{align}
|00 \rangle &= |0\rangle \otimes |0\rangle = \begin{pmatrix} 1\\0 \end{pmatrix} \otimes \begin{pmatrix} 1\\0 \end{pmatrix} = \begin{pmatrix} 1\\0\\0\\0 \end{pmatrix} \\
|01 \rangle &= |0\rangle \otimes |1\rangle = \begin{pmatrix} 1\\0 \end{pmatrix} \otimes \begin{pmatrix} 0\\1 \end{pmatrix} = \begin{pmatrix} 0\\1\\0\\0 \end{pmatrix} \\
|10 \rangle &= |1\rangle \otimes |0\rangle = \begin{pmatrix} 0\\1 \end{pmatrix} \otimes \begin{pmatrix} 1\\0 \end{pmatrix} = \begin{pmatrix} 0\\0\\1\\0 \end{pmatrix} \\
|11 \rangle &= |1\rangle \otimes |1\rangle = \begin{pmatrix} 0\\1 \end{pmatrix} \otimes \begin{pmatrix} 0\\1 \end{pmatrix} = \begin{pmatrix} 0\\0\\0\\1 \end{pmatrix}
\end{align}

```python
qubit1_state = np.matrix([[1],[0]])
qubit2_state = np.matrix([[0],[1]])

two_qubit_state =np.kron(qubit1_state, qubit2_state)
```

```python

```

# Task Three: Qunatum Gates and Circuits

```python
from qiskit import *
from qiskit.visualization import plot_bloch_multivector
```

## Pauli Matrices

\begin{align}
I = \begin{pmatrix} 1&0 \\ 0&1 \end{pmatrix}, \quad
X = \begin{pmatrix} 0&1 \\ 1&0 \end{pmatrix}, \quad
Y = \begin{pmatrix} 0&i \\ -i&0 \end{pmatrix}, \quad
Z = \begin{pmatrix} 1&0 \\ 0&-1 \end{pmatrix} \quad
\end{align}

## X-gate

The X-gate is represented by the Pauli-X matrix:

$$ X = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} = |0\rangle\langle1| + |1\rangle\langle0| $$

Effect a gate has on a qubit:

$$ X|0\rangle = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} = |1\rangle$$

```python
# Let's do an X-gate on a |0> qubit
qc = QuantumCircuit(1)
qc.x(0)
qc.draw('mpl')
```

```python
# Let's see the result
backend = Aer.get_backend('statevector_simulator')
out = execute(qc,backend).result().get_statevector()
plot_bloch_multivector(out)
```

## Z & Y-Gate

$$ Y = \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix} \quad\quad\quad\quad Z = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} $$

$$ Y = -i|0\rangle\langle1| + i|1\rangle\langle0| \quad\quad Z = |0\rangle\langle0| - |1\rangle\langle1| $$

```python
qc.y(0) # Do Y-gate on qubit 0
qc.z(0) # Do Z-gate on qubit 0
qc.draw('mpl')
```

## Hadamard Gate

$$ H = \tfrac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} $$

We can see that this performs the transformations below:

$$ H|0\rangle = |+\rangle $$

$$ H|1\rangle = |-\rangle $$

```python
qc = QuantumCircuit(3)
# Apply H-gate to each qubit:
for qubit in range(3):
    qc.h(qubit)
# See the circuit:
qc.draw('mpl')
```

## Identity Gate

$$
I = \begin{bmatrix} 1 & 0 \\ 0 & 1\end{bmatrix}
$$

$$ I = XX $$

```python
qc = QuantumCircuit(1)
#qc.i(0)
qc.draw('mpl')
```

 ** Other Gates: S-gate , T-gate, U-gate

## Multiple Qubits, Entanglement

## Multiple Qubits

The state of two qubits :

$$ |psi\rangle = a_{00}|00\rangle + a_{01}|01\rangle + a_{10}|10\rangle + a_{11}|11\rangle = \begin{bmatrix} a_{00} \\ a_{01} \\ a_{10} \\ a_{11} \end{bmatrix} $$

```python
from qiskit import *
```

```python
qc = QuantumCircuit(3)

for qubit in range(3):
    qc.h(qubit)

qc.draw('mpl')
```

Each qubit is in the state $|+\rangle$, so we should see the vector:

$$
|{+++}\rangle = \frac{1}{\sqrt{8}}\begin{bmatrix} 1 \\ 1 \\ 1 \\ 1 \\
                              1 \\ 1 \\ 1 \\ 1 \\
              \end{bmatrix}
$$

```python
backend = Aer.get_backend('statevector_simulator')
final_state= execute(qc, backend).result().get_statevector()
print(final_state)
```

    [0.35355339+0.j 0.35355339+0.j 0.35355339+0.j 0.35355339+0.j
     0.35355339+0.j 0.35355339+0.j 0.35355339+0.j 0.35355339+0.j]

```python
qc = QuantumCircuit(2)

qc.x(0)
qc.h(1)

qc.draw('mpl')
```

$$
X|q_1\rangle \otimes H|q_0\rangle = (X\otimes H)|q_1 q_0\rangle
$$

The operation looks like this:

$$
X\otimes H = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \otimes \tfrac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} = \frac{1}{\sqrt{2}}
\begin{bmatrix} 0 & 0 & 1 & 1 \\
                0 & 0 & 1 & -1 \\
                1 & 1 & 0 & 0 \\
                1 & -1 & 0 & 0 \\
\end{bmatrix}
$$

Which we can then apply to our 4D statevector $|q_1 q_0\rangle$. You will often see the clearer notation:

$$
X\otimes H =
\begin{bmatrix} 0 & H \\
               H & 0\\
\end{bmatrix}
$$

## C-Not Gate

```python
qc = QuantumCircuit(2)

qc.cx(0, 1)

qc.draw('mpl')

```

Classical truth table of C-Not gate:

| Input (t,c) | Output (t,c) |
|:-----------:|:------------:|
| 00          | 00           |
| 01          | 11           |
| 10          | 10           |
| 11          | 01           |

## Entanglement

```python
qc = QuantumCircuit(2)
# Apply H-gate to the first:
qc.h(0)
qc.draw('mpl')
```

```python
# Let's see the result:
backend = Aer.get_backend('statevector_simulator')
final_state = execute(qc,backend).result().get_statevector()
print(final_state)
```

    [0.70710678+0.j 0.70710678+0.j 0.        +0.j 0.        +0.j]

Quantum System Sate is:

$$
|0{+}\rangle = \tfrac{1}{\sqrt{2}}(|00\rangle + |01\rangle)
$$

```python
qc = QuantumCircuit(2)
# Apply H-gate to the first:
qc.h(0)
# Apply a CNOT:
qc.cx(0,1)
qc.draw('mpl')
```

```python
# Let's see the result:
backend = Aer.get_backend('statevector_simulator')
final_state = execute(qc,backend).result().get_statevector()
print(final_state)
```

    [0.70710678+0.j 0.        +0.j 0.        +0.j 0.70710678+0.j]

We see we have this final state (Bell State):

$$
\text{CNOT}|0{+}\rangle = \tfrac{1}{\sqrt{2}}(|00\rangle + |11\rangle)
$$

Other Bell States:

## Bernstein-Vazirani Algorithm

A black-box function $f$, which takes as input a string of bits ($x$), and returns either $0$ or $1$, that is:

$$f(\{x_0,x_1,x_2,...\}) \rightarrow 0 \textrm{ or } 1 \textrm{ where } x_n \textrm{ is }0 \textrm{ or } 1  $$

The function is guaranteed to return the bitwise product of the input with some string, $s$.

In other words, given an input $x$, $f(x) = s \cdot x \, \text{(mod 2)} =\ x_0 * s_0+x_1*s_1+x_2*s_2+...\ $ mod 2

# Classical-solution:

|Input(x)|
|:-----:|
|100...0|
|010...0|
|001...0|
|000...1|

Where each query reveals a different bit of $s$ (the bit $s_i$)

# The quantum Bernstein-Vazirani Oracle:

1. Initialise the inputs qubits to the $|0\rangle^{\otimes n}$ state, and output qubit to $|{-}\rangle$.
2. Apply Hadamard gates to the input register
3. Query the oracle
4. Apply Hadamard gates to the input register
5. Measure

## Example Two Qubits:

 The register of two qubits is initialized to zero:

$$\lvert \psi_0 \rangle = \lvert 0 0 \rangle$$

 Apply a Hadamard gate to both qubits:

$$\lvert \psi_1 \rangle = \frac{1}{2} \left( \lvert 0 0 \rangle + \lvert 0 1 \rangle + \lvert 1 0 \rangle + \lvert 1 1 \rangle \right) $$

 For the string $s=11$, the quantum oracle performs the operation:
$$
|x \rangle \xrightarrow{f_s} (-1)^{x\cdot 11} |x \rangle.
$$

$$\lvert \psi_2 \rangle = \frac{1}{2} \left( (-1)^{00\cdot 11}|00\rangle + (-1)^{01\cdot 11}|01\rangle + (-1)^{10\cdot 11}|10\rangle + (-1)^{11\cdot 11}|11\rangle \right)$$

$$\lvert \psi_2 \rangle = \frac{1}{2} \left( \lvert 0 0 \rangle - \lvert 0 1 \rangle - \lvert 1 0 \rangle + \lvert 1 1 \rangle \right)$$

 Apply a Hadamard gate to both qubits:

$$\lvert \psi_3 \rangle = \lvert 1 1 \rangle$$

 Measure to find the secret string $s=11$

```python
from qiskit import *
%matplotlib inline
from qiskit.tools.visualization import plot_histogram
```

```python
secret_num = '101001'
```

```python
circuit = QuantumCircuit(6+1,6)
circuit.h([0,1,2,3,4,5])

circuit.x(6)
circuit.h(6)

circuit.barrier()

circuit.cx(5,6)
circuit.cx(3,6)
circuit.cx(0,6)

circuit.barrier()
circuit.h([0,1,2,3,4,5])

circuit.measure([0,1,2,3,4,5],[0,1,2,3,4,5])
```

    <qiskit.circuit.instructionset.InstructionSet at 0x7f3bde001ad0>

```python
circuit.draw(output= 'mpl')
```

```python
simulator = Aer.get_backend('qasm_simulator')
result = execute(circuit, backend= simulator, shots = 1).result()
counts= result.get_counts()
print(counts)
```

    {'101001': 1}

```python

```


# Calculations of supercurrents in a proximitized semiconducting 3D nanowire
The simulations in this notebook generate data that is used for the plotting of the theoretical figures of the paper.

Some simulations are expensive and take ~20hrs on 300 cores. Therefore we often cut up the simulation in parts using the `funcs.run_simulation` function with the `N` argument. The resulting (partial) data is saved in `pandas.DataFrame`s.

To view the resulting data (after joining the parts with `funcs.combine_dfs`, see example just below) see [paper-figures.ipynb](paper-figures.ipynb) for the figures from the paper or [explore-data.ipynb](explore-data.ipynb) to interactively explore the data using sliders.

### Example: joining the data files
```python
# If the simulation is run with:
funcs.run_simulation(lview, func, vals, parameters=dict(**params, **syst_pars),
                     fname_i='tmp/1d_alpha_vs_B_x_{}.hdf', N=20000, overwrite=True)
# You can join the resulting files with:
df = funcs.combine_dfs('tmp/1d_alpha_vs_B_x_*.hdf', 'data/1d_alpha_vs_B_x.hdf')
```

# The Python conda environment that is used
* We used the following Python environment. See [README.md](README.md) for installation instructions.
```yaml
name: python3
channels:
  - conda-forge
dependencies:
  - python=3.6
  - kwant=1.3
  - holoviews=1.8.1
  - xarray=0.9.6
  - pandas=0.20.3
  - pytables=3.4.2
  - toolz=0.8.2
  - hpc05  # This is only needed if you use a PBS cluster with headnode, as on the TU Delft network
```

## Notes
* See [example-toy-models.ipynb](example-toy-models.ipynb) for simpler examples.
* Read the comments!

```python
# Connect the ipyparallel.Client
try:
    # If this can be imported, it assumes you have access to a PBS cluster
    # with a headnode where you started a cluster
    import hpc05
    client = hpc05.Client(profile='pbs', timeout=60)
    print("Connected to hpc05")
except ImportError:
    # Otherwise start an ipyparallel ipcluster locally
    from ipyparallel import Client
    client = Client()
    print("Connected to local engines")
```

```python
dview = client[:]
dview.use_dill()
lview = client.load_balanced_view()
print('Connected to {} engines.'.format(len(dview)))
```

```python
# Make sure this folder is in your $PYTHONPATH of the ipengines
# or set the correct location in the next line (run after all engines are connected)
%px import sys, os; sys.path.append(os.path.expanduser('~/Work/nanowire_current/'))
```

    UsageError: Line magic function `%px` not found.

# Imports

```python
# Related third party imports
import holoviews as hv
import kwant
import numpy as np
import pandas as pd

# Local imports
import funcs

%matplotlib inline
hv.notebook_extension()
```

<link rel="stylesheet" href="https://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">

# Creating some wires as example

```python
import sympy
```

```python
sympy.__version__
```

    '1.2'

```python
# Create system with infinite leads
syst_pars = dict(a=8, angle=0, site_disorder=False, holes=True, L=200, L_sc=80,
                 phi=135, r1=50, r2=70, shape='circle', with_leads=True,
                 with_shell=True, with_vlead=True)

syst, hopping = funcs.make_3d_wire(**syst_pars)
kwant.plot(syst);
```

```python
# Create system without leads and bigger SC regions
syst_pars['L_sc'] = 40
syst_pars['L'] = 40
syst, hopping = funcs.make_3d_wire(**syst_pars)
kwant.plot(syst, site_size=0, hop_lw=0.1);
```

```python
# Create system without leads
syst_pars['with_leads'] = False
syst, hopping = funcs.make_3d_wire(**syst_pars)
kwant.plot(syst);
```

# Mean free path calculation
See [mean-free-path.ipynb](mean-free-path.ipynb) for the data processing.

```python
syst_pars = dict(a=8, angle=0, site_disorder=True, holes=False, L_sc=8,
                 phi=135, r1=50, r2=70, shape='circle', with_leads=True,
                 with_shell=False, with_vlead=False)

params = dict(alpha=20, B_x=0, B_y=0, B_z=0, Delta=0, g=50,
              orbital=True, V='lambda x: 0', **funcs.constants.__dict__)

Ls = np.arange(80, 2000, 80)
salts = np.arange(0, 10)
disorders = [0, 10, 20, 30, 40, 50, 55, 60, 65, 70, 75, 80, 90, 100, 110]
mus = np.arange(10, 31)

vals = funcs.named_product(salt=salts, disorder=disorders, L=Ls, mu=mus)
print(len(vals))

def func(val, syst_pars=syst_pars, params=params):
    import kwant, funcs

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    # Remove the parameters from `params` that belong in `syst_pars`.
    for x in ['L']:
        syst_pars[x] = params.pop(x)

    syst, hopping = funcs.make_3d_wire(**syst_pars)
    smatrix = kwant.smatrix(syst, params=params)

    # Return a combined dictionary with the results and input.
    return dict(transmission=smatrix.transmission(0, 1),
                num_propagating=smatrix.num_propagating(0),
                **val)

fname = 'data/mean_free_path.hdf'
funcs.run_simulation(lview, func, vals, dict(**params, **syst_pars), fname, overwrite=True)
```

# $B_x(I_c)$ combinations of effects and geometries:

```python
syst_pars = dict(a=8, angle=0, site_disorder=False, holes=True, phi=135,
                 r1=50, r2=70, shape='circle', with_shell=True, with_vlead=True)

params = dict(B_y=0, B_z=0, Delta=60, c_tunnel=5/8, V=lambda x: 0, **funcs.constants.__dict__)

Ts = [0.1, 0.5, 1]
orbital_bools = [False, True]
gs = [0, 50]
alphas = [0, 20]
mus = [10, 15, 20, 25, 30]
Ls = [80, 160, 320, 640]
leads = [(True, 8), (False, 400)]
Bs = np.linspace(0, 2, 101)

vals = funcs.named_product(T=Ts, L=Ls, orbital=orbital_bools,
                           g=gs, alpha=alphas, mu=mus, leads=leads, B_x=Bs)

def func(val, syst_pars=syst_pars, params=params):
    import funcs
    val['with_leads'], val['L_sc'] = val['leads']

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    # Remove the parameters from `params` that belong in `syst_pars`.
    for x in ['with_leads', 'L_sc', 'L']:
        syst_pars[x] = params.pop(x)

    syst, hopping = funcs.make_3d_wire(**syst_pars)

    # Return a combined dictionary with the results and input.
    return dict(**funcs.I_c(syst, hopping, params), **val)

fname = "tmp/I_c(B_x)_no_disorder_combinations_of_effects_and_geometries_{}.hdf"
funcs.run_simulation(lview, func, vals, dict(**params, **syst_pars), fname, 2000)

```

# $B_x(I_c)$ with disorder:
* Main paper figure 4
* Supplementary materials figure 8

```python
ONLY_PAPER_COMBINATIONS = False

syst_pars = dict(a=8, angle=0, site_disorder=True, holes=True, L=640,
                 L_sc=8, phi=135, r1=50, r2=70, shape='circle',
                 with_leads=True, with_shell=True, with_vlead=True)

params = dict(B_y=0, B_z=0, Delta=60, c_tunnel=5/8, V='lambda x: 0', T=100e-3, **funcs.constants.__dict__)

Bs = np.linspace(0, 0.5, 201)

if ONLY_PAPER_COMBINATIONS:
    # These are all the combinations of effects that are showed in Fig. 4 of the main paper.
    vals = [[(0, 0, True, 50, 20, 10, B),
             (0, 0, False, 50, 20, 10, B),
             (0, 0, True, 50, 0, 10, B),
             (0, 0, False, 50, 0, 10, B),
             (0, 0, True, 50, 20, 20, B),
             (0, 0, False, 50, 20, 20, B),
             (0, 0, True, 50, 0, 20, B),
             (0, 0, False, 50, 0, 20, B),
             (7, 75, True, 50, 20, 20, B)]
            for B in Bs]
    vals = sum(vals, [])
    names = ['salt', 'disorder', 'orbital', 'g', 'alphas', 'mu', 'B_x']
    vals = [dict(zip(names, val)) for val in vals]

else:
    # Calculate all combinations of effects (which is much slower.)
    vals = funcs.named_product(salt=np.arange(0, 8, 1), disorder=[0, 75],
                               orbital=[False, True], g=[0, 50], alpha=[0, 20],
                               mu=[10, 20], B_x=Bs)

    # Filter out different salts when there is no disorder.
    vals = [val for val in vals if not (val['salt'] > 0 and val['disorder'] == 0)]

print(len(vals))

def func(val, syst_pars=syst_pars, params=params):
    import funcs
    syst, hopping = funcs.make_3d_wire(**syst_pars)

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    # Return a combined dictionary with the results and input.
    return dict(**funcs.I_c(syst, hopping, params), **val)

fname_i = "tmp/I_c(B_x)_mu10,20meV_disorder0,75meV_T0.1K_all_combinations_of_effects_{}.hdf"
funcs.run_simulation(lview, func, vals, dict(**params, **syst_pars), fname_i, 2500)
```

# Rotation of the magnetic field in the $xy$-plane
* Supplementary materials figure 10

```python
syst_pars = dict(a=8, angle=0, site_disorder=True, holes=True, L=160, L_sc=8,
                 phi=135, r1=50, r2=70, shape='circle',
                 with_leads=True, with_shell=True, with_vlead=True)

params = dict(alpha=20, B_z=0, Delta=60, g=50, mu=20, salt=7,
              orbital=True, c_tunnel=5/8, V='lambda x: 0', T=100e-3, **funcs.constants.__dict__)

Bs = np.linspace(0, 2, 101)
thetas = [0, 45, 90]
vals = funcs.named_product(B=Bs, theta=thetas, disorder=[0, 75])

def func(val, syst_pars=syst_pars, params=params):
    import funcs
    import numpy as np
    angle = np.deg2rad(val['theta'])
    val['B_x'] = val['B'] * np.cos(angle).round(15)
    val['B_y'] = val['B'] * np.sin(angle).round(15)

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    syst, hopping = funcs.make_3d_wire(**syst_pars)

    # Return a combined dictionary with the results and input.
    return dict(**funcs.I_c(syst, hopping, params), **val)

fname = 'data/I_c(B_x)_mu20meV_rotation_of_field_in_xy_plane.hdf'
funcs.run_simulation(lview, func, vals, dict(**syst_pars, **params), fname, None, overwrite=True)
```

# Tuning the induced gap

```python
syst_pars = dict(a=8, angle=0, site_disorder=False, holes=True,
                 L=80, L_sc=8, phi=135, r1=50, r2=70, shape='circle',
                 with_leads=True, with_shell=True, with_vlead=False)

params = dict(alpha=20, B_x=0, B_y=0, B_z=0, g=50, orbital=True,
              c_tunnel=5/8, V='lambda x: 0', **funcs.constants.__dict__,)

mus = np.linspace(2, 30, 50)
Deltas = np.linspace(0, 100, 50)

vals = funcs.named_product(Delta=Deltas, mu=mus)

def func(val, syst_pars=syst_pars, params=params):
    import funcs
    import numpy as np
    lead = funcs.make_3d_wire(**syst_pars)[0].leads[1]

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    # Create the Hamiltonian `ham` at k=0.
    h0 = lead.cell_hamiltonian(params=params)
    t0 = lead.inter_cell_hopping(params=params)
    ham = h0 + t0 + t0.conj().T

    # Find the energies.
    ev = np.linalg.eigvalsh(ham)

    # Return a combined dictionary with the results and input.
    return dict(E_min=np.abs(ev).min(), **val)

funcs.run_simulation(lview, func, vals, dict(**params, **syst_pars), 'data/gap_tuning.hdf')
```

```python
# Plot the gaps and find the `Delta` that is needed for the required `Delta_induced`.
df = pd.read_hdf('data/gap_tuning.hdf')
Deltas = sorted(df.Delta.unique())
mus = sorted(df.mu.unique())
gap = np.reshape(df.E_min.values, (len(Deltas), len(mus)))
max_gap = np.max(np.min(gap, axis=1))
print("Max gap is {} meV".format(max_gap))
```

```python
hv.Curve((Deltas, gap.min(axis=1)), kdims=[r'$\Delta$'], vdims=[r'$E_{gap}$'],
         label=r"$E_{gap}$ over range of $\Delta$'s")
```

```python
Delta_ind = {delta: hv.Path((mus, evs), kdims=[r'$\mu$', ('E_gap', r'$E_{gap}$')])
      for evs, delta in zip(gap, Deltas)}

hm = hv.HoloMap(Delta_ind, kdims=[r'$\Delta$'])
(hm.select(E_gap=(0.15, 0.40)) * hv.HLine(0.25))
```

## Gate simulation with and without disorder $I_c(B_x, V)$
* Main paper figure 5(b)
* Supplementary materials figure 9

```python
# Plot test
syst_pars = dict(a=8, angle=0, site_disorder=False, holes=True,
                 L=640, L_sc=8, phi=135, r1=50, r2=70, shape='circle',
                 with_leads=True, with_shell=True, with_vlead=True)

syst, hopping = funcs.make_3d_wire(**syst_pars)
gate_fun = funcs.gate(syst, 100, 160)
sites = [gate_fun(pos[0]) for pos in [i.pos for i in syst.sites]]
kwant.plot(syst, site_lw=0, site_color=sites, colorbar=False)
```

```python
syst_pars = dict(a=8, angle=0, site_disorder=True, holes=True,
                 L=640, L_sc=8, phi=135, r1=50, r2=70, shape='circle',
                 with_leads=True, with_shell=True, with_vlead=True)

params = dict(alpha=20, B_y=0, B_z=0, Delta=60, g=50, mu=20, orbital=True,
              c_tunnel=5/8, salt=7, T=100e-3, **funcs.constants.__dict__)

Bs = np.linspace(0, 0.5, 51)
Vs = np.linspace(0, 10, 51)
gate_sizes = [160]
disorders = [0, 75]

vals = funcs.named_product(gate_size=gate_sizes,
                           disorder=disorders, V=Vs, B_x=Bs)

def func(val, syst_pars=syst_pars, params=params):
    import funcs
    syst, hopping = funcs.make_3d_wire(**syst_pars)

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    # Create a potential function for the gate.
    params['V'] = funcs.gate(syst, params['V'], params['gate_size'])

    # Return a combined dictionary with the results and input.
    return dict(**funcs.I_c(syst, hopping, params), **val)

fname = "tmp/I_c(B_x,_V)_gate160nm_mu20meV_disorder0,75meV_T0.1K_{}.hdf"
funcs.run_simulation(lview, func, vals, dict(**params, **syst_pars), fname, 2500)
```

# 1D toymodel $I_c(\alpha, B_x)$
Supplementary materials figure 7

```python
syst_pars = dict(a=10, L=500, L_sc=100)

params = dict(B_y=0, B_z=0, Delta=0.25, g=50, V='lambda x: 0', T=0.1,
              **funcs.constants.__dict__)

alphas = np.linspace(0, 30, 101)
B_xs = np.linspace(0, 1.4, 101)
mus = [0.1, 0.3, 1, 3, 10, 30]

vals = funcs.named_product(alpha=alphas, B_x=B_xs, mu=mus)

def func(val, syst_pars=syst_pars, params=params):
    import funcs
    syst, hopping = funcs.make_1d_wire(**syst_pars)

    # Combine the fixed parameters `params` and the changing
    # parameters `val` to one dict and evaluate the string
    # lambda functions.
    params = funcs.parse_params(dict(**params, **val))

    # Return a combined dictionary with the results and input.
    return dict(**funcs.I_c(syst, hopping, params), **val)

funcs.run_simulation(lview, func, vals, dict(**params, **syst_pars),
                     'tmp/1d_alpha_vs_B_x_{}.hdf', N=20000, overwrite=True)
```

```python

```