```python
pip install cirq
```

    Requirement already satisfied: cirq in /usr/local/lib/python3.7/dist-packages (0.13.1)
    Requirement already satisfied: cirq-web==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-core==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-google==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-aqt==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-ionq==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-pasqal==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-rigetti==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: requests~=2.18 in /usr/local/lib/python3.7/dist-packages (from cirq-aqt==0.13.1->cirq) (2.23.0)
    Requirement already satisfied: numpy~=1.16 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.21.5)
    Requirement already satisfied: matplotlib~=3.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (3.2.2)
    Requirement already satisfied: duet~=0.2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (0.2.3)
    Requirement already satisfied: sortedcontainers~=2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (2.4.0)
    Requirement already satisfied: scipy in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.7.3)
    Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (3.10.0.2)
    Requirement already satisfied: tqdm in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (4.62.3)
    Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.7.1)
    Requirement already satisfied: networkx~=2.4 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (2.6.3)
    Requirement already satisfied: pandas in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.3.5)
    Requirement already satisfied: google-api-core[grpc]<2.0.0dev,>=1.14.0 in /usr/local/lib/python3.7/dist-packages (from cirq-google==0.13.1->cirq) (1.26.3)
    Requirement already satisfied: protobuf>=3.13.0 in /usr/local/lib/python3.7/dist-packages (from cirq-google==0.13.1->cirq) (3.17.3)
    Requirement already satisfied: pyjwt~=1.7.1 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.7.1)
    Requirement already satisfied: rfc3339~=6.2 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (6.2)
    Requirement already satisfied: h11~=0.9.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.9.0)
    Requirement already satisfied: httpcore~=0.11.1 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.11.1)
    Requirement already satisfied: qcs-api-client~=0.8.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.8.0)
    Requirement already satisfied: certifi~=2021.5.30 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (2021.5.30)
    Requirement already satisfied: iso8601~=0.1.14 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.1.16)
    Requirement already satisfied: toml~=0.10.2 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.10.2)
    Requirement already satisfied: httpx~=0.15.5 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.15.5)
    Requirement already satisfied: pydantic~=1.8.2 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.8.2)
    Requirement already satisfied: pyquil~=3.0.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (3.0.1)
    Requirement already satisfied: idna~=2.10 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (2.10)
    Requirement already satisfied: six~=1.16.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.16.0)
    Requirement already satisfied: retrying~=1.3.3 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.3.3)
    Requirement already satisfied: attrs~=20.3.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (20.3.0)
    Requirement already satisfied: python-dateutil~=2.8.1 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (2.8.2)
    Requirement already satisfied: sniffio~=1.2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.2.0)
    Requirement already satisfied: rfc3986~=1.5.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.5.0)
    Requirement already satisfied: google-auth<2.0dev,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (1.35.0)
    Requirement already satisfied: googleapis-common-protos<2.0dev,>=1.6.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (1.54.0)
    Requirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (2018.9)
    Requirement already satisfied: setuptools>=40.3.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (57.4.0)
    Requirement already satisfied: packaging>=14.3 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (21.3)
    Requirement already satisfied: grpcio<2.0dev,>=1.29.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (1.43.0)
    Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (0.2.8)
    Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (4.8)
    Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (4.2.4)
    Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.13.1->cirq) (0.11.0)
    Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.13.1->cirq) (1.3.2)
    Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.13.1->cirq) (3.0.7)
    Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /usr/local/lib/python3.7/dist-packages (from pyasn1-modules>=0.2.1->google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (0.4.8)
    Requirement already satisfied: rpcq<4.0.0,>=3.6.0 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (3.9.2)
    Requirement already satisfied: lark<0.12.0,>=0.11.1 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.11.3)
    Requirement already satisfied: importlib-metadata<4.0.0,>=3.7.3 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (3.10.1)
    Requirement already satisfied: retry<0.10.0,>=0.9.2 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.9.2)
    Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata<4.0.0,>=3.7.3->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (3.7.0)
    Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->cirq-aqt==0.13.1->cirq) (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.18->cirq-aqt==0.13.1->cirq) (1.24.3)
    Requirement already satisfied: py<2.0.0,>=1.4.26 in /usr/local/lib/python3.7/dist-packages (from retry<0.10.0,>=0.9.2->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (1.11.0)
    Requirement already satisfied: decorator>=3.4.2 in /usr/local/lib/python3.7/dist-packages (from retry<0.10.0,>=0.9.2->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (4.4.2)
    Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (22.3.0)
    Requirement already satisfied: python-rapidjson in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (1.5)
    Requirement already satisfied: msgpack<1.0,>=0.6 in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.6.2)
    Requirement already satisfied: ruamel.yaml in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.17.21)
    Requirement already satisfied: ruamel.yaml.clib>=0.2.6 in /usr/local/lib/python3.7/dist-packages (from ruamel.yaml->rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.2.6)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy->cirq-core==0.13.1->cirq) (1.2.1)

```python
#importing required libraries
import cirq
import numpy as np
import scipy as sp
import random
import time
```

```python
# Custom function used to respresent a a set of bits in string format
def bitstring(bits):
    return ''.join(str(int(b)) for b in bits)
```

```python
def bnv_circuit(qubits):

  # Generating secret number that needs to be encoded by the oracle
  a=[random.randint(0, 1) for _ in range(qubits)]
  # Generating the random bit in the function  f(x) = ax+b
  b = random.randint(0, 1)

  # initializing the circuit in Cirq
  c = cirq.Circuit()

  # Defining number of qubits in the circuit
  lines=cirq.LineQubit.range(qubits+1)

  # Segregating input and output qubits
  input_qubits=lines[:qubits]
  output_qubit = lines[-1]

  # Applying H gate for superposition
  c.append([cirq.X(output_qubit),cirq.H(output_qubit),cirq.H.on_each(*input_qubits)])

  # defining the orale function of the circuit
  def oracle(a,b,c):
    #Initalizing CNOT gates for qubits that hold value |1>
    if b:
      c.append(cirq.X(output_qubit))
    for i,encoded in zip(input_qubits, a):
      if (encoded):
        c.append(cirq.CNOT(i,output_qubit))

  oracle(a,b,c)

  # Measuring the result in H basis
  c.append([cirq.H.on_each(*input_qubits), cirq.measure(*input_qubits, key='result')])

  # Displaying oracle function for cross verification
  print(
    'Secret function:\nf(x) = a·<{}> + {} (mod 2)'.format(
        ', '.join(str(e) for e in a), b
    ))

  return c

```

```python
c= bnv_circuit(6)
```

    Secret function:
    f(x) = a·<1, 0, 0, 0, 0, 1> + 0 (mod 2)

```python
c
```

0: ───H───────@───H───────M('result')───
              │           │
1: ───H───H───┼───────────M─────────────
              │           │
2: ───H───H───┼───────────M─────────────
              │           │
3: ───H───H───┼───────────M─────────────
              │           │
4: ───H───H───┼───────────M─────────────
              │           │
5: ───H───────┼───@───H───M─────────────
              │   │
6: ───X───H───X───X─────────────────────

```python
# Function defined to run simulation of the ciruit above &
# To determine the most common bitstring that is determined by the circuit after performing a couple of simulations of the circuit.
def run_simulation(c,run_count):
  simulator = cirq.Simulator()
  result = simulator.run(c, repetitions=run_count)
  frequencies = result.histogram(key='result', fold_func=bitstring)
  print(f'Sampled results:\n{frequencies}')

  # Check if we actually found the secret value.
  most_common_bitstring = frequencies.most_common(1)[0][0]

```

```python
# Running the algorithm by altering the circuit for varied values of n, where n represents number of qubits &
# Capturing time taken for the algorithm to run for each value of n
l=[]
for i in range(2,20):
  st=time.time()
  c=bnv_circuit(i)
  print(c)
  run_simulation(c,1024)
  end=time.time()
  l.append(end-st)

```

    Secret function:
    f(x) = a·<0, 1> + 1 (mod 2)
    0: ───H───H───────────────M('result')───
                              │
    1: ───H───────────@───H───M─────────────
                      │
    2: ───X───H───X───X─────────────────────
    Sampled results:
    Counter({'01': 1024})
    Secret function:
    f(x) = a·<0, 0, 1> + 1 (mod 2)
    0: ───H───H───────────────M('result')───
                              │
    1: ───H───H───────────────M─────────────
                              │
    2: ───H───────────@───H───M─────────────
                      │
    3: ───X───H───X───X─────────────────────
    Sampled results:
    Counter({'001': 1024})
    Secret function:
    f(x) = a·<1, 1, 1, 0> + 0 (mod 2)
    0: ───H───────@───H───────────M('result')───
                  │               │
    1: ───H───────┼───@───H───────M─────────────
                  │   │           │
    2: ───H───────┼───┼───@───H───M─────────────
                  │   │   │       │
    3: ───H───H───┼───┼───┼───────M─────────────
                  │   │   │
    4: ───X───H───X───X───X─────────────────────
    Sampled results:
    Counter({'1110': 1024})
    Secret function:
    f(x) = a·<1, 1, 0, 0, 1> + 0 (mod 2)
    0: ───H───────@───H───────────M('result')───
                  │               │
    1: ───H───────┼───@───H───────M─────────────
                  │   │           │
    2: ───H───H───┼───┼───────────M─────────────
                  │   │           │
    3: ───H───H───┼───┼───────────M─────────────
                  │   │           │
    4: ───H───────┼───┼───@───H───M─────────────
                  │   │   │
    5: ───X───H───X───X───X─────────────────────
    Sampled results:
    Counter({'11001': 1024})
    Secret function:
    f(x) = a·<1, 0, 1, 0, 0, 1> + 1 (mod 2)
    0: ───H───────────@───H───────────M('result')───
                      │               │
    1: ───H───H───────┼───────────────M─────────────
                      │               │
    2: ───H───────────┼───@───H───────M─────────────
                      │   │           │
    3: ───H───H───────┼───┼───────────M─────────────
                      │   │           │
    4: ───H───H───────┼───┼───────────M─────────────
                      │   │           │
    5: ───H───────────┼───┼───@───H───M─────────────
                      │   │   │
    6: ───X───H───X───X───X───X─────────────────────
    Sampled results:
    Counter({'101001': 1024})
    Secret function:
    f(x) = a·<0, 1, 0, 0, 0, 0, 1> + 1 (mod 2)
    0: ───H───H───────────────────M('result')───
                                  │
    1: ───H───────────@───H───────M─────────────
                      │           │
    2: ───H───H───────┼───────────M─────────────
                      │           │
    3: ───H───H───────┼───────────M─────────────
                      │           │
    4: ───H───H───────┼───────────M─────────────
                      │           │
    5: ───H───H───────┼───────────M─────────────
                      │           │
    6: ───H───────────┼───@───H───M─────────────
                      │   │
    7: ───X───H───X───X───X─────────────────────
    Sampled results:
    Counter({'0100001': 1024})
    Secret function:
    f(x) = a·<1, 1, 1, 0, 1, 0, 1, 1> + 1 (mod 2)
    0: ───H───────────@───H───────────────────────M('result')───
                      │                           │
    1: ───H───────────┼───@───H───────────────────M─────────────
                      │   │                       │
    2: ───H───────────┼───┼───@───H───────────────M─────────────
                      │   │   │                   │
    3: ───H───H───────┼───┼───┼───────────────────M─────────────
                      │   │   │                   │
    4: ───H───────────┼───┼───┼───@───H───────────M─────────────
                      │   │   │   │               │
    5: ───H───H───────┼───┼───┼───┼───────────────M─────────────
                      │   │   │   │               │
    6: ───H───────────┼───┼───┼───┼───@───H───────M─────────────
                      │   │   │   │   │           │
    7: ───H───────────┼───┼───┼───┼───┼───@───H───M─────────────
                      │   │   │   │   │   │
    8: ───X───H───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'11101011': 1024})
    Secret function:
    f(x) = a·<0, 0, 1, 0, 0, 0, 1, 0, 0> + 1 (mod 2)
    0: ───H───H───────────────────M('result')───
                                  │
    1: ───H───H───────────────────M─────────────
                                  │
    2: ───H───────────@───H───────M─────────────
                      │           │
    3: ───H───H───────┼───────────M─────────────
                      │           │
    4: ───H───H───────┼───────────M─────────────
                      │           │
    5: ───H───H───────┼───────────M─────────────
                      │           │
    6: ───H───────────┼───@───H───M─────────────
                      │   │       │
    7: ───H───H───────┼───┼───────M─────────────
                      │   │       │
    8: ───H───H───────┼───┼───────M─────────────
                      │   │
    9: ───X───H───X───X───X─────────────────────
    Sampled results:
    Counter({'001000100': 1024})
    Secret function:
    f(x) = a·<1, 1, 0, 1, 1, 1, 1, 0, 0, 0> + 1 (mod 2)
    0: ────H───────────@───H───────────────────────M('result')───
                       │                           │
    1: ────H───────────┼───@───H───────────────────M─────────────
                       │   │                       │
    2: ────H───H───────┼───┼───────────────────────M─────────────
                       │   │                       │
    3: ────H───────────┼───┼───@───H───────────────M─────────────
                       │   │   │                   │
    4: ────H───────────┼───┼───┼───@───H───────────M─────────────
                       │   │   │   │               │
    5: ────H───────────┼───┼───┼───┼───@───H───────M─────────────
                       │   │   │   │   │           │
    6: ────H───────────┼───┼───┼───┼───┼───@───H───M─────────────
                       │   │   │   │   │   │       │
    7: ────H───H───────┼───┼───┼───┼───┼───┼───────M─────────────
                       │   │   │   │   │   │       │
    8: ────H───H───────┼───┼───┼───┼───┼───┼───────M─────────────
                       │   │   │   │   │   │       │
    9: ────H───H───────┼───┼───┼───┼───┼───┼───────M─────────────
                       │   │   │   │   │   │
    10: ───X───H───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'1101111000': 1024})
    Secret function:
    f(x) = a·<0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0> + 0 (mod 2)
    0: ────H───H───────────────────M('result')───
                                   │
    1: ────H───H───────────────────M─────────────
                                   │
    2: ────H───H───────────────────M─────────────
                                   │
    3: ────H───H───────────────────M─────────────
                                   │
    4: ────H───H───────────────────M─────────────
                                   │
    5: ────H───────@───H───────────M─────────────
                   │               │
    6: ────H───H───┼───────────────M─────────────
                   │               │
    7: ────H───H───┼───────────────M─────────────
                   │               │
    8: ────H───────┼───@───H───────M─────────────
                   │   │           │
    9: ────H───────┼───┼───@───H───M─────────────
                   │   │   │       │
    10: ───H───H───┼───┼───┼───────M─────────────
                   │   │   │
    11: ───X───H───X───X───X─────────────────────
    Sampled results:
    Counter({'00000100110': 1024})
    Secret function:
    f(x) = a·<1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0> + 0 (mod 2)
    0: ────H───────@───H───────────────────────────M('result')───
                   │                               │
    1: ────H───────┼───@───H───────────────────────M─────────────
                   │   │                           │
    2: ────H───────┼───┼───@───H───────────────────M─────────────
                   │   │   │                       │
    3: ────H───────┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │                   │
    4: ────H───H───┼───┼───┼───┼───────────────────M─────────────
                   │   │   │   │                   │
    5: ────H───H───┼───┼───┼───┼───────────────────M─────────────
                   │   │   │   │                   │
    6: ────H───────┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │               │
    7: ────H───H───┼───┼───┼───┼───┼───────────────M─────────────
                   │   │   │   │   │               │
    8: ────H───H───┼───┼───┼───┼───┼───────────────M─────────────
                   │   │   │   │   │               │
    9: ────H───────┼───┼───┼───┼───┼───@───H───────M─────────────
                   │   │   │   │   │   │           │
    10: ───H───────┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │       │
    11: ───H───H───┼───┼───┼───┼───┼───┼───┼───────M─────────────
                   │   │   │   │   │   │   │
    12: ───X───H───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'111100100110': 1024})
    Secret function:
    f(x) = a·<1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1> + 1 (mod 2)
    0: ────H───────────@───H───────────────────────────M('result')───
                       │                               │
    1: ────H───H───────┼───────────────────────────────M─────────────
                       │                               │
    2: ────H───H───────┼───────────────────────────────M─────────────
                       │                               │
    3: ────H───H───────┼───────────────────────────────M─────────────
                       │                               │
    4: ────H───────────┼───@───H───────────────────────M─────────────
                       │   │                           │
    5: ────H───────────┼───┼───@───H───────────────────M─────────────
                       │   │   │                       │
    6: ────H───────────┼───┼───┼───@───H───────────────M─────────────
                       │   │   │   │                   │
    7: ────H───────────┼───┼───┼───┼───@───H───────────M─────────────
                       │   │   │   │   │               │
    8: ────H───H───────┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │               │
    9: ────H───────────┼───┼───┼───┼───┼───@───H───────M─────────────
                       │   │   │   │   │   │           │
    10: ───H───H───────┼───┼───┼───┼───┼───┼───────────M─────────────
                       │   │   │   │   │   │           │
    11: ───H───H───────┼───┼───┼───┼───┼───┼───────────M─────────────
                       │   │   │   │   │   │           │
    12: ───H───────────┼───┼───┼───┼───┼───┼───@───H───M─────────────
                       │   │   │   │   │   │   │
    13: ───X───H───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'1000111101001': 1024})
    Secret function:
    f(x) = a·<0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1> + 1 (mod 2)
    0: ────H───H───────────────────────────────────────────M('result')───
                                                           │
    1: ────H───────────@───H───────────────────────────────M─────────────
                       │                                   │
    2: ────H───────────┼───@───H───────────────────────────M─────────────
                       │   │                               │
    3: ────H───────────┼───┼───@───H───────────────────────M─────────────
                       │   │   │                           │
    4: ────H───H───────┼───┼───┼───────────────────────────M─────────────
                       │   │   │                           │
    5: ────H───────────┼───┼───┼───@───H───────────────────M─────────────
                       │   │   │   │                       │
    6: ────H───────────┼───┼───┼───┼───@───H───────────────M─────────────
                       │   │   │   │   │                   │
    7: ────H───────────┼───┼───┼───┼───┼───@───H───────────M─────────────
                       │   │   │   │   │   │               │
    8: ────H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    9: ────H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    10: ───H───────────┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                       │   │   │   │   │   │   │           │
    11: ───H───H───────┼───┼───┼───┼───┼───┼───┼───────────M─────────────
                       │   │   │   │   │   │   │           │
    12: ───H───H───────┼───┼───┼───┼───┼───┼───┼───────────M─────────────
                       │   │   │   │   │   │   │           │
    13: ───H───────────┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                       │   │   │   │   │   │   │   │
    14: ───X───H───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'01110111001001': 1024})
    Secret function:
    f(x) = a·<0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0> + 1 (mod 2)
    0: ────H───H───────────────────────────────────────────────────M('result')───
                                                                   │
    1: ────H───────────@───H───────────────────────────────────────M─────────────
                       │                                           │
    2: ────H───H───────┼───────────────────────────────────────────M─────────────
                       │                                           │
    3: ────H───────────┼───@───H───────────────────────────────────M─────────────
                       │   │                                       │
    4: ────H───────────┼───┼───@───H───────────────────────────────M─────────────
                       │   │   │                                   │
    5: ────H───────────┼───┼───┼───@───H───────────────────────────M─────────────
                       │   │   │   │                               │
    6: ────H───────────┼───┼───┼───┼───@───H───────────────────────M─────────────
                       │   │   │   │   │                           │
    7: ────H───────────┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                       │   │   │   │   │   │                       │
    8: ────H───────────┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                       │   │   │   │   │   │   │                   │
    9: ────H───H───────┼───┼───┼───┼───┼───┼───┼───────────────────M─────────────
                       │   │   │   │   │   │   │                   │
    10: ───H───────────┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                       │   │   │   │   │   │   │   │               │
    11: ───H───H───────┼───┼───┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │   │   │               │
    12: ───H───────────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                       │   │   │   │   │   │   │   │   │           │
    13: ───H───────────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                       │   │   │   │   │   │   │   │   │   │       │
    14: ───H───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───────M─────────────
                       │   │   │   │   │   │   │   │   │   │
    15: ───X───H───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'010111111010110': 1024})
    Secret function:
    f(x) = a·<1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0> + 0 (mod 2)
    0: ────H───────@───H───────────────────────────────────────────M('result')───
                   │                                               │
    1: ────H───────┼───@───H───────────────────────────────────────M─────────────
                   │   │                                           │
    2: ────H───H───┼───┼───────────────────────────────────────────M─────────────
                   │   │                                           │
    3: ────H───H───┼───┼───────────────────────────────────────────M─────────────
                   │   │                                           │
    4: ────H───────┼───┼───@───H───────────────────────────────────M─────────────
                   │   │   │                                       │
    5: ────H───H───┼───┼───┼───────────────────────────────────────M─────────────
                   │   │   │                                       │
    6: ────H───────┼───┼───┼───@───H───────────────────────────────M─────────────
                   │   │   │   │                                   │
    7: ────H───H───┼───┼───┼───┼───────────────────────────────────M─────────────
                   │   │   │   │                                   │
    8: ────H───────┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │                               │
    9: ────H───────┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │                           │
    10: ───H───────┼───┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                   │   │   │   │   │   │   │                       │
    11: ───H───────┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │                   │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │               │
    13: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │           │
    14: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │       │
    15: ───H───H───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │
    16: ───X───H───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'1100101011111110': 1024})
    Secret function:
    f(x) = a·<1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0> + 1 (mod 2)
    0: ────H───────────@───H───────────────────────────────M('result')───
                       │                                   │
    1: ────H───H───────┼───────────────────────────────────M─────────────
                       │                                   │
    2: ────H───H───────┼───────────────────────────────────M─────────────
                       │                                   │
    3: ────H───────────┼───@───H───────────────────────────M─────────────
                       │   │                               │
    4: ────H───H───────┼───┼───────────────────────────────M─────────────
                       │   │                               │
    5: ────H───────────┼───┼───@───H───────────────────────M─────────────
                       │   │   │                           │
    6: ────H───────────┼───┼───┼───@───H───────────────────M─────────────
                       │   │   │   │                       │
    7: ────H───────────┼───┼───┼───┼───@───H───────────────M─────────────
                       │   │   │   │   │                   │
    8: ────H───────────┼───┼───┼───┼───┼───@───H───────────M─────────────
                       │   │   │   │   │   │               │
    9: ────H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    10: ───H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    11: ───H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    12: ───H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    13: ───H───H───────┼───┼───┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │   │   │               │
    14: ───H───────────┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                       │   │   │   │   │   │   │           │
    15: ───H───────────┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                       │   │   │   │   │   │   │   │       │
    16: ───H───H───────┼───┼───┼───┼───┼───┼───┼───┼───────M─────────────
                       │   │   │   │   │   │   │   │
    17: ───X───H───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'10010111100000110': 1024})
    Secret function:
    f(x) = a·<0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0> + 0 (mod 2)
    0: ────H───H───────────────────────────────────────────────────────M('result')───
                                                                       │
    1: ────H───────@───H───────────────────────────────────────────────M─────────────
                   │                                                   │
    2: ────H───────┼───@───H───────────────────────────────────────────M─────────────
                   │   │                                               │
    3: ────H───H───┼───┼───────────────────────────────────────────────M─────────────
                   │   │                                               │
    4: ────H───────┼───┼───@───H───────────────────────────────────────M─────────────
                   │   │   │                                           │
    5: ────H───────┼───┼───┼───@───H───────────────────────────────────M─────────────
                   │   │   │   │                                       │
    6: ────H───────┼───┼───┼───┼───@───H───────────────────────────────M─────────────
                   │   │   │   │   │                                   │
    7: ────H───────┼───┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │   │                               │
    8: ────H───H───┼───┼───┼───┼───┼───┼───────────────────────────────M─────────────
                   │   │   │   │   │   │                               │
    9: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │   │                           │
    10: ───H───────┼───┼───┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │                       │
    11: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │                   │
    12: ───H───H───┼───┼───┼───┼───┼───┼───┼───┼───┼───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                   │
    13: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │               │
    14: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │           │
    15: ───H───H───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │           │
    16: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │       │
    17: ───H───H───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │
    18: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'011011110111011010': 1024})
    Secret function:
    f(x) = a·<0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0> + 1 (mod 2)
    0: ────H───H───────────────────────────────────M('result')───
                                                   │
    1: ────H───H───────────────────────────────────M─────────────
                                                   │
    2: ────H───────────@───H───────────────────────M─────────────
                       │                           │
    3: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    4: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    5: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    6: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    7: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    8: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    9: ────H───H───────┼───────────────────────────M─────────────
                       │                           │
    10: ───H───────────┼───@───H───────────────────M─────────────
                       │   │                       │
    11: ───H───────────┼───┼───@───H───────────────M─────────────
                       │   │   │                   │
    12: ───H───H───────┼───┼───┼───────────────────M─────────────
                       │   │   │                   │
    13: ───H───H───────┼───┼───┼───────────────────M─────────────
                       │   │   │                   │
    14: ───H───────────┼───┼───┼───@───H───────────M─────────────
                       │   │   │   │               │
    15: ───H───H───────┼───┼───┼───┼───────────────M─────────────
                       │   │   │   │               │
    16: ───H───────────┼───┼───┼───┼───@───H───────M─────────────
                       │   │   │   │   │           │
    17: ───H───────────┼───┼───┼───┼───┼───@───H───M─────────────
                       │   │   │   │   │   │       │
    18: ───H───H───────┼───┼───┼───┼───┼───┼───────M─────────────
                       │   │   │   │   │   │
    19: ───X───H───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'0010000000110010110': 1024})

```python
import matplotlib.pyplot as plt

# Plotting the time taken by the algorithm against the number of qubits in the circuit to analyze scalability of the algorithm
plt.scatter(range(2,20),l)
plt.title('Time vs Bits')
plt.xlabel('Qubits')
plt.ylabel('Time (in seconds)')
plt.show()
```

```python

```


```python
# Erasmus+ ICCT project (2018-1-SI01-KA203-047081)

# Toggle cell visibility

from IPython.display import HTML
tag = HTML('''
Toggle cell visibility <a href="javascript:code_toggle()">here</a>.''')
display(tag)

# Hide the code completely

# from IPython.display import HTML
# tag = HTML('''<style>
# div.input {
#     display:none;
# }
# </style>''')
# display(tag)
```

Toggle cell visibility here.

```python
%matplotlib inline
import control
import numpy
import sympy as sym
from IPython.display import display, Markdown
import ipywidgets as widgets
import matplotlib.pyplot as plt

#print a matrix latex-like
def bmatrix(a):
     """Returns a LaTeX bmatrix - by Damir Arbula (ICCT project)

     :a: numpy array
     :returns: LaTeX bmatrix as a string
     """
     if len(a.shape) > 2:
         raise ValueError('bmatrix can at most display two dimensions')
     lines = str(a).replace('[', '').replace(']', '').splitlines()
     rv = [r'\begin{bmatrix}']
     rv += ['  ' + ' & '.join(l.split()) + r'\\' for l in lines]
     rv +=  [r'\end{bmatrix}']
     return '\n'.join(rv)

# Display formatted matrix:
def vmatrix(a):
    if len(a.shape) > 2:
         raise ValueError('bmatrix can at most display two dimensions')
    lines = str(a).replace('[', '').replace(']', '').splitlines()
    rv = [r'\begin{vmatrix}']
    rv += ['  ' + ' & '.join(l.split()) + r'\\' for l in lines]
    rv +=  [r'\end{vmatrix}']
    return '\n'.join(rv)

#matrixWidget is a matrix looking widget built with a VBox of HBox(es) that returns a numPy array as value !
class matrixWidget(widgets.VBox):
    def updateM(self,change):
        for irow in range(0,self.n):
            for icol in range(0,self.m):
                self.M_[irow,icol] = self.children[irow].children[icol].value
                #print(self.M_[irow,icol])
        self.value = self.M_

    def dummychangecallback(self,change):
        pass

    def __init__(self,n,m):
        self.n = n
        self.m = m
        self.M_ = numpy.matrix(numpy.zeros((self.n,self.m)))
        self.value = self.M_
        widgets.VBox.__init__(self,
                             children = [
                                 widgets.HBox(children =
                                              [widgets.FloatText(value=0.0, layout=widgets.Layout(width='90px')) for i in range(m)]
                                             )
                                 for j in range(n)
                             ])

        #fill in widgets and tell interact to call updateM each time a children changes value
        for irow in range(0,self.n):
            for icol in range(0,self.m):
                self.children[irow].children[icol].value = self.M_[irow,icol]
                self.children[irow].children[icol].observe(self.updateM, names='value')
        #value = Unicode('example@example.com', help="The email value.").tag(sync=True)
        self.observe(self.updateM, names='value', type= 'All')

    def setM(self, newM):
        #disable callbacks, change values, and reenable
        self.unobserve(self.updateM, names='value', type= 'All')
        for irow in range(0,self.n):
            for icol in range(0,self.m):
                self.children[irow].children[icol].unobserve(self.updateM, names='value')
        self.M_ = newM
        self.value = self.M_
        for irow in range(0,self.n):
            for icol in range(0,self.m):
                self.children[irow].children[icol].value = self.M_[irow,icol]
        for irow in range(0,self.n):
            for icol in range(0,self.m):
                self.children[irow].children[icol].observe(self.updateM, names='value')
        self.observe(self.updateM, names='value', type= 'All')

                #self.children[irow].children[icol].observe(self.updateM, names='value')

#overlaod class for state space systems that DO NOT remove "useless" states (what "professor" of automatic control would do this?)
class sss(control.StateSpace):
    def __init__(self,*args):
        #call base class init constructor
        control.StateSpace.__init__(self,*args)
    #disable function below in base class
    def _remove_useless_states(self):
        pass
```

## Crane load position control

A gantry crane consists of a cart of mass $m_c = 1000$ kg, and a load of mass $m_l$, connected by a rope of length $L$ that can be considered massless. Friction acts on the cart linearly, proportional to cart velocity with coefficient $B_f = 100$ Ns/m; the cart is moved by the force $F$. The angle between the vertical axis and the rope is $\theta$. The dynamic equations of the system, linearized around the steady condition ($\theta=\dot{\theta}=\dot{x}=0$), are (where $g = 9.81$ m/$\text{s}^2$ is gravitational acceleration):

\begin{cases}
    (m_l+m_c)\ddot{x}+m_lL\ddot{\theta}+B_f\dot{x}=F \\
    m_lL^2\ddot{\theta}+m_lL\ddot{x}+m_lLg\theta=0
\end{cases}

We assume $m_l=100$ kg and $L=10$ m as nominal values and we want to design a regulator for the measured load position $y=x+L\sin{\theta} \cong x+L\theta$ according to the following specifications:
- settling time for 5% tolerance band of less than 20 seconds,
- minimal or no overshoot,
- zero or practically zero steady-state error in response to a step-wise change of the desired load position,
- force $F$ must not exceed $\pm1000$ N when the requested position change is 10 meters.

First, we have to write the linearized system's equations in state space form; dividing the second equation by $m_lL$ became
$$
    L\ddot{\theta}+\ddot{x}+g\theta=0 \, .
$$

Now, defining $x=\begin{bmatrix} x_1 & x_2 & x_3 & x_4 \end{bmatrix}^T = =\begin{bmatrix} \dot{x} & \dot{\theta} & \theta & x \end{bmatrix}^T$ we can write:

$$
M\dot{x}=Gx+HF,
$$

where:

$$
    M = \begin{bmatrix} (m_l+m_c) & m_lL & 0 & 0 \\ 1 & L & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}, \quad
    G = \begin{bmatrix} -B_f & 0 & 0 & 0 \\ 0 & 0 & -g & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \end{bmatrix} \quad \text{and} \quad
    H = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} \, .
$$

Thus, pre-multiplying all with $M^{-1}$ we obtain ($A=M^{-1}G$, $B=M^{-1}H$):

\begin{cases}
    \dot{x} = \begin{bmatrix} -B_f/m_c & 0 & gm_l/m_c & 0 \\ B_f/(Lm_c) & 0 & -g(1/L + m_l/(Lm_c)) & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \end{bmatrix}x +\begin{bmatrix}1/m_c \\ -1/(Lm_c) \\ 0 \\ 0 \end{bmatrix}F \\
    y = \begin{bmatrix} 0 & 0 & L & 1 \end{bmatrix}x
\end{cases}

### Regulator development
#### Controller design

The poles of the system are $0$, $-0.091$ and $-0.0045\pm1.038i$. In order to meet the requirement for settling time, we move the real poles to $-0.28$ and decrease the real part of the imaginary poles by $-0.25$. As a result, the chosen closed-loop poles are: $-0.28$, $-0.28$ and $-0.2545\pm1.038i$. For the zero steady-state error we scale the reference signal with a gain equal to the inverse of the closed-loop system's gain.

#### Design of the observer
To support the state feedback controller we design a full state observer with poles in $-8$.

### How to use this notebook?
Try to change the poles location in order to satisfy the requirements for a reference step input of 15 m.

```python
# Preparatory cell

X0 = numpy.matrix('0.0; 0.0; 0.0; 0.0')
K = numpy.matrix([0,0,0,0])
L = numpy.matrix([[0],[0],[0],[0]])

X0w = matrixWidget(4,1)
X0w.setM(X0)
Kw = matrixWidget(1,4)
Kw.setM(K)
Lw = matrixWidget(4,1)
Lw.setM(L)

eig1c = matrixWidget(1,1)
eig2c = matrixWidget(2,1)
eig3c = matrixWidget(1,1)
eig4c = matrixWidget(2,1)
eig1c.setM(numpy.matrix([-0.28]))
eig2c.setM(numpy.matrix([[-0.2545],[-1.038]]))
eig3c.setM(numpy.matrix([-0.28]))
eig4c.setM(numpy.matrix([[-1.],[-1.]]))

eig1o = matrixWidget(1,1)
eig2o = matrixWidget(2,1)
eig3o = matrixWidget(1,1)
eig4o = matrixWidget(2,1)
eig1o.setM(numpy.matrix([-8.]))
eig2o.setM(numpy.matrix([[-8.1],[0.]]))
eig3o.setM(numpy.matrix([-8.2]))
eig4o.setM(numpy.matrix([[-8.3],[0.]]))
```

```python
# Misc

#create dummy widget
DW = widgets.FloatText(layout=widgets.Layout(width='0px', height='0px'))

#create button widget
START = widgets.Button(
    description='Test',
    disabled=False,
    button_style='', # 'success', 'info', 'warning', 'danger' or ''
    tooltip='Test',
    icon='check'
)

def on_start_button_clicked(b):
    #This is a workaround to have intreactive_output call the callback:
    #   force the value of the dummy widget to change
    if DW.value> 0 :
        DW.value = -1
    else:
        DW.value = 1
    pass
START.on_click(on_start_button_clicked)

# Define type of method
selm = widgets.Dropdown(
    options= ['Set K and L', 'Set the eigenvalues'],
    value= 'Set the eigenvalues',
    description='',
    disabled=False
)

# Define the number of complex eigenvalues
selec = widgets.Dropdown(
    options= ['0 complex eigenvalues', '2 complex eigenvalues', '4 complex eigenvalues'],
    value= '2 complex eigenvalues',
    description='Eig controller:',
    disabled=False
)
seleo = widgets.Dropdown(
    options= ['0 complex eigenvalues', '2 complex eigenvalues'],
    value= '0 complex eigenvalues',
    description='Eig observer:',
    disabled=False
)

#define type of ipout
selu = widgets.Dropdown(
    options=['impulse', 'step', 'sinusoid', 'square wave'],
    value='step',
    description='Type of reference:',
    style = {'description_width': 'initial'},
    disabled=False
)
# Define the values of the input
u = widgets.FloatSlider(
    value=10,
    min=0,
    max=20,
    step=1,
    description='Reference:',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='.1f',
)
period = widgets.FloatSlider(
    value=0.5,
    min=0.001,
    max=10,
    step=0.001,
    description='Period: ',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='.3f',
)

simTime = widgets.FloatText(
    value=30,
    description='',
    disabled=False
)
```

```python
# Support functions

def eigen_choice(selec,seleo):
    if selec == '0 complex eigenvalues':
        eig1c.children[0].children[0].disabled = False
        eig2c.children[1].children[0].disabled = True
        eig3c.children[0].children[0].disabled = False
        eig4c.children[0].children[0].disabled = False
        eig4c.children[1].children[0].disabled = True
        eigc = 0
    if seleo == '0 complex eigenvalues':
        eig1o.children[0].children[0].disabled = False
        eig2o.children[1].children[0].disabled = True
        eig3o.children[0].children[0].disabled = False
        eig4o.children[0].children[0].disabled = False
        eig4o.children[1].children[0].disabled = True
        eigo = 0
    if selec == '2 complex eigenvalues':
        eig1c.children[0].children[0].disabled = False
        eig2c.children[1].children[0].disabled = False
        eig3c.children[0].children[0].disabled = False
        eig4c.children[0].children[0].disabled = True
        eig4c.children[1].children[0].disabled = True
        eigc = 2
    if seleo == '2 complex eigenvalues':
        eig1o.children[0].children[0].disabled = False
        eig2o.children[1].children[0].disabled = False
        eig3o.children[0].children[0].disabled = False
        eig4o.children[0].children[0].disabled = True
        eig4o.children[1].children[0].disabled = True
        eigo = 2
    if selec == '4 complex eigenvalues':
        eig1c.children[0].children[0].disabled = True
        eig2c.children[1].children[0].disabled = False
        eig3c.children[0].children[0].disabled = True
        eig4c.children[0].children[0].disabled = False
        eig4c.children[1].children[0].disabled = False
        eigc = 4
    if seleo == '4 complex eigenvalues':
        eig1o.children[0].children[0].disabled = True
        eig2o.children[1].children[0].disabled = False
        eig3o.children[0].children[0].disabled = True
        eig4o.children[0].children[0].disabled = False
        eig4o.children[1].children[0].disabled = False
        eigo = 4
    return eigc, eigo

def method_choice(selm):
    if selm == 'Set K and L':
        method = 1
        selec.disabled = True
        seleo.disabled = True
    if selm == 'Set the eigenvalues':
        method = 2
        selec.disabled = False
        seleo.disabled = False
    return method
```

```python
ml = 100
mc = 1000
L  = 10
g  = 9.81
Bf = 100

A = numpy.matrix([[-Bf/mc,0,g*ml/mc,0],
                  [Bf/(L*mc), 0, -g*(1/L + ml/(L*mc)), 0],
                  [0, 1, 0, 0],
                  [1, 0, 0, 0]])
B = numpy.matrix([[1/mc],[-1/(L*mc)],[0],[0]])
C = numpy.matrix([[0,0,L,1]])

def main_callback2(X0w, K, L, eig1c, eig2c, eig3c, eig4c, eig1o, eig2o, eig3o, eig4o, u, period, selm, selec, seleo, selu, simTime, DW):
    eigc, eigo = eigen_choice(selec,seleo)
    method = method_choice(selm)

    if method == 1:
        solc = numpy.linalg.eig(A-B*K)
        solo = numpy.linalg.eig(A-L*C)
    if method == 2:
        try:
            if eigc == 0:
                K = control.acker(A, B, [eig1c[0,0], eig2c[0,0], eig3c[0,0], eig4c[0,0]])
                Kw.setM(K)
            if eigc == 2:
                K = control.acker(A, B, [eig3c[0,0],
                                          eig1c[0,0],
                                          numpy.complex(eig2c[0,0], eig2c[1,0]),
                                          numpy.complex(eig2c[0,0],-eig2c[1,0])])
                Kw.setM(K)
            if eigc == 4:
                K = control.acker(A, B, [numpy.complex(eig4c[0,0], eig4c[1,0]),
                                          numpy.complex(eig4c[0,0],-eig4c[1,0]),
                                          numpy.complex(eig2c[0,0], eig2c[1,0]),
                                          numpy.complex(eig2c[0,0],-eig2c[1,0])])
                Kw.setM(K)
            if eigo == 0:
                L = control.place(A.T, C.T, [eig1o[0,0], eig2o[0,0], eig3o[0,0], eig4o[0,0]]).T
                Lw.setM(L)
            if eigo == 2:
                L = control.place(A.T, C.T, [eig3o[0,0],
                                             eig1o[0,0],
                                             numpy.complex(eig2o[0,0], eig2o[1,0]),
                                             numpy.complex(eig2o[0,0],-eig2o[1,0])]).T
                Lw.setM(L)
            if eigo == 4:
                L = control.place(A.T, C.T, [numpy.complex(eig4o[0,0], eig4o[1,0]),
                                          numpy.complex(eig4o[0,0],-eig4o[1,0]),
                                          numpy.complex(eig2o[0,0], eig2o[1,0]),
                                          numpy.complex(eig2o[0,0],-eig2o[1,0])]).T
                Lw.setM(L)
        except:
            print("ERROR: at least one of the requested pole is repeated more than rank(B) times, try to change the poles")
            return

    sys = sss(A,B,numpy.vstack((C,[0,0,0,0])),[[0],[1]])
    syse = sss(A-L*C,numpy.hstack((B,L)),numpy.eye(4),numpy.zeros((4,2)))
    sysc = sss(0,[0,0,0,0],0,-K)
    sys_append = control.append(sys,syse,sysc)
    # To avoid strange behaviours
    try:
        sys_CL = control.connect(sys_append,
                                 [[1,7],[2,2],[3,1],[4,3],[5,4],[6,5],[7,6]],
                                 [1],
                                 [1,2])
    except:
        sys_CL = control.connect(sys_append,
                                 [[1,7],[2,2],[3,1],[4,3],[5,4],[6,5],[7,6]],
                                 [1],
                                 [1,2])

    X0w1 = numpy.zeros((8,1))
    X0w1[4,0] = X0w[0,0]
    X0w1[5,0] = X0w[1,0]
    X0w1[6,0] = X0w[2,0]
    X0w1[7,0] = X0w[3,0]
    if simTime != 0:
        T = numpy.linspace(0, simTime, 10000)
    else:
        T = numpy.linspace(0, 1, 10000)
    #t1, y1 = step(sys_CL[0,0],[0,10000])
    u1 = u
    try:
        DCgain = control.dcgain(sys_CL[0,0])
        u = u/DCgain
    except:
        print("Error in the calculation of the dcgain of the closed loop controlled system. The feedforward gain is setted to 1.")
        DCgain = 1

    if selu == 'impulse': #selu
        U = [0 for t in range(0,len(T))]
        U[0] = u
        U1 = [0 for t in range(0,len(T))]
        U1[0] = u1
        T, yout, xout = control.forced_response(sys_CL,T,U,X0w1)
    if selu == 'step':
        U = [u for t in range(0,len(T))]
        U1 = [u1 for t in range(0,len(T))]
        T, yout, xout = control.forced_response(sys_CL,T,U,X0w1)
    if selu == 'sinusoid':
        U = u*numpy.sin(2*numpy.pi/period*T)
        U1 = u1*numpy.sin(2*numpy.pi/period*T)
        T, yout, xout = control.forced_response(sys_CL,T,U,X0w1)
    if selu == 'square wave':
        U = u*numpy.sign(numpy.sin(2*numpy.pi/period*T))
        U1 = u1*numpy.sign(numpy.sin(2*numpy.pi/period*T))
        T, yout, xout = control.forced_response(sys_CL,T,U,X0w1)

    try:
        step_info_dict = control.step_info(sys_CL[0,0],SettlingTimeThreshold=0.05,T=T)
        print('Step info: \n\tRise time =',step_info_dict['RiseTime'],'\n\tSettling time (5%) =',step_info_dict['SettlingTime'],'\n\tOvershoot (%)=',step_info_dict['Overshoot'])
        print('Max u value (% of 1000N)=', max(abs(yout[1]))/(1000)*100)
    except:
        print("Error in the calculation of step info.")
    print("Closed loop system's gain =",DCgain)

    fig = plt.figure(num='Simulation1', figsize=(14,12))

    fig.add_subplot(221)
    plt.title('Output response')
    plt.ylabel('Output')
    plt.plot(T,yout[0],T,U1,'r--')
    plt.xlabel('$t$ [s]')
    plt.axvline(x=0,color='black',linewidth=0.8)
    plt.axhline(y=0,color='black',linewidth=0.8)
    plt.legend(['$y$','Reference'])
    plt.grid()

    fig.add_subplot(222)
    plt.title('Input')
    plt.ylabel('$u$')
    plt.plot(T,yout[1])
    plt.plot(T,[1000 for i in range(len(T))],'r--')
    plt.plot(T,[-1000 for i in range(len(T))],'r--')
    plt.xlabel('$t$ [s]')
    plt.axvline(x=0,color='black',linewidth=0.8)
    plt.axhline(y=0,color='black',linewidth=0.8)
    plt.grid()

    fig.add_subplot(223)
    plt.title('States response')
    plt.ylabel('States')
    plt.plot(T,xout[0],
             T,xout[1],
             T,xout[2],
             T,xout[3])
    plt.xlabel('$t$ [s]')
    plt.axvline(x=0,color='black',linewidth=0.8)
    plt.axhline(y=0,color='black',linewidth=0.8)
    plt.legend(['$x_{1}$','$x_{2}$','$x_{3}$','$x_{4}$'])
    plt.grid()

    fig.add_subplot(224)
    plt.title('Estimation errors')
    plt.ylabel('Errors')
    plt.plot(T,xout[4]-xout[0])
    plt.plot(T,xout[5]-xout[1])
    plt.plot(T,xout[6]-xout[2])
    plt.plot(T,xout[7]-xout[3])
    plt.axvline(x=0,color='black',linewidth=0.8)
    plt.axhline(y=0,color='black',linewidth=0.8)
    plt.xlabel('$t$ [s]')
    plt.legend(['$e_{1}$','$e_{2}$','$e_{3}$','$e_{4}$'])
    plt.grid()
    #plt.tight_layout()

alltogether2 = widgets.VBox([widgets.HBox([selm,
                                          selec,
                                          seleo,
                                          selu]),
                            widgets.Label(' ',border=3),
                            widgets.HBox([widgets.HBox([widgets.Label('K:',border=3), Kw,
                                                        widgets.Label('Eigenvalues:',border=3),
                                                        widgets.HBox([eig1c,
                                                                      eig2c,
                                                                      eig3c,
                                                                      eig4c])])]),
                            widgets.Label(' ',border=3),
                            widgets.HBox([widgets.VBox([widgets.HBox([widgets.Label('L:',border=3), Lw, widgets.Label(' ',border=3),
                                          widgets.Label(' ',border=3),
                                          widgets.Label('Eigenvalues:',border=3),
                                          eig1o,
                                          eig2o,
                                          eig3o,
                                          eig4o,
                                          widgets.Label(' ',border=3),
                                          widgets.Label(' ',border=3),
                                          widgets.Label('X0 est.:',border=3), X0w]),
                                          widgets.Label(' ',border=3),
                                                       widgets.HBox([
                                          widgets.VBox([widgets.Label('Simulation time (s):',border=3)]),
                                          widgets.VBox([simTime])])]),
                                          widgets.Label(' ',border=3)]),
                            widgets.Label(' ',border=3),
                            widgets.HBox([u,
                                          period,
                                          START])])
out2 = widgets.interactive_output(main_callback2, {'X0w':X0w, 'K':Kw, 'L':Lw,
                                                   'eig1c':eig1c, 'eig2c':eig2c, 'eig3c':eig3c, 'eig4c':eig4c,
                                                   'eig1o':eig1o, 'eig2o':eig2o, 'eig3o':eig3o, 'eig4o':eig4o,
                                                   'u':u, 'period':period, 'selm':selm, 'selec':selec, 'seleo':seleo, 'selu':selu, 'simTime':simTime, 'DW':DW})
out2.layout.height = '860px'
display(out2, alltogether2)
```

    Output(layout=Layout(height='860px'))

    VBox(children=(HBox(children=(Dropdown(index=1, options=('Set K and L', 'Set the eigenvalues'), value='Set the…

```python

```