## This Jupyter notebook is available at https://github.com/dkp-quantum/Tutorials

## Further Information

#### * Qiskit: https://qiskit.org

#### * Qiskit GitHub: https://github.com/Qiskit

## What is Qiskit?

* Quantum Information Science Kit

* Open-source SDK for working with quantum computers at the level of pulses, circuits and algorithms

* Founded by IBM Research in 2017 to allow software development for their cloud quantum computing service known as IBM Q Experience.

* The primary version of Qiskit uses the Python programming language. It is used to create quantum programs based on the OpenQASM (Open Quantum Assembly Language) representation of quantum instructions.

## What can we do with Qiskit?

* Access to circuits
* Access to a library of quantum algorithms
* Access to quantum hardware
* Access to optimization against noise

## IBM Quantum Experience Backend

* 9 real quantum devices with number of qubits 1, 5, and 16.
* 32-qubit simulator

## Main simulator backends

1. __QASM Simulator__: It emulates execution of a quantum circuits on a real device and returns __measurement counts__. It includes highly configurable noise models and can even be loaded with automatically generated approximate noise models based on the calibration parameters of actual hardware devices.

    * What is __QASM__? QASM = Quantum Assembly Language (see https://arxiv.org/abs/1707.03429 for more detail)

2. __Statevector Simulator__: It simulates the ideal execution of a quantum circuit and returns __the final quantum state vector__ of the device at the end of simulation.

3. __Unitary Simulator__: It allows simulation of the final unitary matrix implemented by an ideal quantum circuit. This only works if all the elements in the circuit are unitary operations.

## How to start

1. Start Online: https://quantum-computing.ibm.com

## How to start

2. Start Locally

* Qiskit is tested and supported on the following 64-bit systems:

    * Ubuntu 16.04 or later
    * macOS 10.12.6 or later
    * Windows 7 or later

* To install Qiskit locally, you will need Python 3.5+.

* IBM recommends using a virtual environment with Anaconda, a cross-platform Python distribution for scientific computing: https://www.anaconda.com/products/individual

## Let's start on Mac

## Let's start on Windows

## Let's start on Windows

## Let's start on Windows

```python
%matplotlib inline
# Importing standard Qiskit libraries and configuring account
from qiskit import *
from qiskit.visualization import *
import numpy as np
```

```python
# Create a quantum register with 2 qubits
q = QuantumRegister(2,'q')
# Form a quantum circuit
# Note that the circuit name is optional
qc = QuantumCircuit(q,name="first_qc")
# Display the quantum circuit
qc.draw()
```

q_0: |0>

q_1: |0>

## Qiskit quantum operations summary:
###  https://qiskit.org/documentation/tutorials/circuits/3_summary_of_quantum_operations.html

```python
# Add a Hadamard gate on qubit 0, putting this in superposition.
qc.h(0)
# Add a CX (CNOT) gate on control qubit 0
# and target qubit 1 to create an entangled state.
qc.cx(0, 1)
qc.draw()
```

        ┌───┐
q_0: |0>┤ H ├──■──
        └───┘┌─┴─┐
q_1: |0>─────┤ X ├
             └───┘

```python
# Create a classical register with 2 bits
c = ClassicalRegister(2,'c')

meas = QuantumCircuit(q,c,name="first_m")
meas.barrier(q)
meas.measure(q, c)

meas.draw()
```

         ░ ┌─┐
q_0: |0>─░─┤M├───
         ░ └╥┘┌─┐
q_1: |0>─░──╫─┤M├
         ░  ║ └╥┘
 c_0: 0 ════╩══╬═
               ║
 c_1: 0 ═══════╩═

```python
# Quantum circuits can be added with + operations
# Add two pre-defined circuits
qc_all=qc+meas
qc_all.draw()
```

        ┌───┐      ░ ┌─┐
q_0: |0>┤ H ├──■───░─┤M├───
        └───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: |0>─────┤ X ├─░──╫─┤M├
             └───┘ ░  ║ └╥┘
 c_0: 0 ══════════════╩══╬═
                         ║
 c_1: 0 ═════════════════╩═

```python
# Draw the quantum circuit in a different (slightly better) format
qc_all.draw(output='mpl')
```

```python
# Create the quantum circuit with the measurement in one go.
qc_all = QuantumCircuit(q,c,name="2q_all")
qc_all.h(0)
qc_all.cx(0,1)
qc_all.barrier()
qc_all.measure(0,0)
qc_all.measure(1,1)
qc_all.draw(output='mpl')
```

```python
# Use Aer's qasm_simulator
backend_q = Aer.get_backend('qasm_simulator')

# Execute the circuit on the qasm simulator.
job_sim1 = execute(qc_all, backend_q, shots=4096)
```

```python
job_sim1.status()
```

    <JobStatus.DONE: 'job has successfully run'>

```python
# Grab the results from the job.
result_sim1 = job_sim1.result()
result_sim1
```

    namespace(backend_name='qasm_simulator',
              backend_version='0.3.2',
              qobj_id='944ac6fa-832c-4ecd-a579-f14eb1b1be04',
              job_id='7d81d747-8230-4474-b9d5-f73191109997',
              success=True,
              results=[namespace(shots=4096,
                                 success=True,
                                 data=namespace(counts=namespace(0x0=1995,
                                                                 0x3=2101)),
                                 meas_level=2,
                                 header=namespace(memory_slots=2,
                                                  clbit_labels=[['c', 0],
                                                                ['c', 1]],
                                                  name='circuit2',
                                                  qubit_labels=[['q', 0],
                                                                ['q', 1]],
                                                  n_qubits=2,
                                                  qreg_sizes=[['q', 2]],
                                                  creg_sizes=[['c', 2]]),
                                 status='DONE',
                                 time_taken=0.010838524,
                                 seed_simulator=4177817008,
                                 metadata={'measure_sampling': True,
                                           'method': 'stabilizer',
                                           'parallel_shots': 1,
                                           'parallel_state_update': 8})],
              date=datetime.datetime(2020, 8, 5, 11, 22, 8, 660150),
              header=namespace(backend_name='qasm_simulator',
                               backend_version='0.3.2'),
              status='COMPLETED',
              time_taken=0.028506040573120117,
              metadata={'max_memory_mb': 4096,
                        'omp_enabled': True,
                        'parallel_experiments': 1,
                        'time_taken': 0.011715323000000001})

```python
result_sim1.get_counts(qc_all)
```

    {'00': 1995, '11': 2101}

```python
plot_histogram(result_sim1.get_counts(qc_all))
```

```python
# Use Aer's statevector_simulator
backend_sv = Aer.get_backend('statevector_simulator')

# Execute the circuit on the statevector simulator.
# It is important to note that the measurement has been excluded
job_sim2 = execute(qc, backend_sv)
```

```python
# Grab the results from the job.
result_sim2 = job_sim2.result()
# Output the entire result
result_sim2
```

    namespace(backend_name='statevector_simulator',
              backend_version='0.3.2',
              qobj_id='1861012f-18e1-4186-80eb-848ae00b8cad',
              job_id='2e6f72fa-2de1-4166-8414-d03ce5c6ec02',
              success=True,
              results=[namespace(shots=1,
                                 success=True,
                                 data=namespace(statevector=[(0.7071067811865476+0j),
                                                             0j,
                                                             0j,
                                                             (0.7071067811865475+0j)]),
                                 meas_level=2,
                                 header=namespace(memory_slots=0,
                                                  clbit_labels=[],
                                                  name='first_qc',
                                                  qubit_labels=[['q', 0],
                                                                ['q', 1]],
                                                  n_qubits=2,
                                                  qreg_sizes=[['q', 2]],
                                                  creg_sizes=[]),
                                 status='DONE',
                                 time_taken=0.000285063,
                                 seed_simulator=1215084373,
                                 metadata={'parallel_shots': 1,
                                           'parallel_state_update': 8})],
              date=datetime.datetime(2020, 8, 5, 11, 28, 16, 708104),
              header=namespace(backend_name='statevector_simulator',
                               backend_version='0.3.2'),
              status='COMPLETED',
              time_taken=0.006955862045288086,
              metadata={'max_memory_mb': 4096,
                        'omp_enabled': True,
                        'parallel_experiments': 1,
                        'time_taken': 0.002053295})

```python
# See output state as a vector
outputstate = result_sim2.get_statevector(qc, decimals=5)
print(outputstate)

# Visualize density matrix
plot_state_city(outputstate)
```

```python
# Create the quantum circuit with the measurement in one go.
qc_3 = QuantumCircuit(3,3,name="qc_bloch")
qc_3.x(1)
qc_3.h(2)
qc_3.barrier()
qc_3.draw(output='mpl')
```

```python
# Execute the circuit on the statevector simulator.
# It is important to note that the measurement has been excluded
job_sim_bloch = execute(qc_3, backend_sv)

# Grab the results from the job.
result_sim_bloch = job_sim_bloch.result()

# See output state as a vector
output_bloch = result_sim_bloch.get_statevector(qc_3, decimals=5)

# Draw on the Bloch sphere
plot_bloch_multivector(output_bloch)
```

```python
# Use Aer's unitary_simulator
backend_u = Aer.get_backend('unitary_simulator')

# Execute the circuit on the unitary simulator.
job_usim = execute(qc, backend_u)

# Grab the results from the job.
result_usim = job_usim.result()
result_usim
```

    namespace(backend_name='unitary_simulator',
              backend_version='0.3.2',
              qobj_id='5518d9ba-fed3-4b4c-a9aa-a92c72010b39',
              job_id='e3d1367f-6943-4fa0-a8ef-25156827f137',
              success=True,
              results=[namespace(shots=1,
                                 success=True,
                                 data=namespace(unitary=[[(0.7071067811865476+0j),
                                                          (0.7071067811865475+0j),
                                                          0j,
                                                          0j],
                                                         [0j,
                                                          0j,
                                                          (0.7071067811865475+0j),
                                                          (-0.7071067811865476+0j)],
                                                         [0j,
                                                          0j,
                                                          (0.7071067811865476+0j),
                                                          (0.7071067811865475+0j)],
                                                         [(0.7071067811865475+0j),
                                                          (-0.7071067811865476+0j),
                                                          0j,
                                                          0j]]),
                                 meas_level=2,
                                 status='DONE',
                                 header=namespace(qreg_sizes=[['q', 2]],
                                                  creg_sizes=[],
                                                  n_qubits=2,
                                                  name='first_qc',
                                                  qubit_labels=[['q', 0],
                                                                ['q', 1]],
                                                  memory_slots=0,
                                                  clbit_labels=[]),
                                 seed_simulator=2335392040,
                                 time_taken=9.462500000000001e-05,
                                 metadata={'parallel_shots': 1,
                                           'parallel_state_update': 8})],
              status='COMPLETED',
              header=namespace(backend_version='0.3.2',
                               backend_name='unitary_simulator'),
              date=datetime.datetime(2020, 8, 3, 15, 36, 22, 517107),
              time_taken=0.002722024917602539,
              metadata={'max_memory_mb': 4096,
                        'omp_enabled': True,
                        'parallel_experiments': 1,
                        'time_taken': 0.00021459200000000002})

```python
# Output the unitary matrix
unitary = result_usim.get_unitary(qc)
print('%s\n' % unitary)
```

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

## Exercise 1:
## Design a quantum circuit to create the following 2-qubit entangled state: $\frac{|01\rangle+|10\rangle}{\sqrt{2}}$.
## Check the answer with the QASM simulation and by plotting the histogram of the measurement statistics.

```python
# Create the quantum circuit with the measurement in one go.
qc_ex1 = QuantumCircuit(q,c,name="ex1")
```

```python
# Put the first qubit in equal superposition
qc_ex1.h(0)
```

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

```python
# Rest of the circuit
qc_ex1.x(1)
qc_ex1.cx(0,1)
qc_ex1.barrier()
qc_ex1.measure(0,0)
qc_ex1.measure(1,1)
qc_ex1.draw(output='mpl')
```

```python
# Execute the circuit on the qasm simulator.
job_ex1 = execute(qc_ex1, backend_q, shots=4096)
```

```python
job_ex1.status()
```

    <JobStatus.DONE: 'job has successfully run'>

```python
# Grab the results from the job.
result_ex1 = job_ex1.result()
result_ex1.get_counts(qc_ex1)
```

    {'10': 2117, '01': 1979}

```python
plot_histogram(result_ex1.get_counts(qc_ex1))
```

```python
# Or get the histogram in one go
plot_histogram(job_ex1.result().get_counts(qc_ex1))
```

## Exercise 2:
## Design a quantum circuit that creates a 3-qubit entangled state: $\alpha|000\rangle+\beta|111\rangle$,
## such that $|\alpha|^2 = 0.25$, and $|\beta|^2 = 0.75$.
## Check the answer with the QASM simulation and by plotting the histogram of the measurement statistics.

### Hint:
$R_y(\theta) = \begin{bmatrix} \cos(\theta/2) & -\sin(\theta/2)\\ \sin(\theta/2) & \cos(\theta/2)\end{bmatrix}$ can be implemented by the qiskit code: `qc.ry(theta,q)`

```python
# Create a quantum register with 3 qubits
q3 = QuantumRegister(3,'q')
# Create a classical register with 3 qubits
c3 = ClassicalRegister(3,'c')

# Create the quantum circuit with the measurement in one go.
qc_ex2 = QuantumCircuit(q3,c3,name="ex1")

qc_ex2.ry(2*np.pi/3,0)
qc_ex2.cx(0,1)
qc_ex2.cx(1,2)
qc_ex2.barrier()
qc_ex2.measure(q3,c3)
qc_ex2.draw(output='mpl')
```

```python
# Execute the circuit on the qasm simulator.
job_ex2 = execute(qc_ex2, backend_q, shots=4096)

# Grab the results from the job.
result_ex2 = job_ex2.result()
plot_histogram(result_ex2.get_counts(qc_ex2))
```

## 3-qubit gate example: Toffoli gate

```python
# Create a quantum register with 3 qubits
q3 = QuantumRegister(3,'q')
# Create a classical register with 3 qubits
c3 = ClassicalRegister(3,'c')

# Create the quantum circuit without a Toffoli gate
qc_toff = QuantumCircuit(q3,c3,name="ex1")

qc_toff.ry(2*np.pi/3,0)
qc_toff.h(1)
qc_toff.h(2)
qc_toff.barrier()
qc_toff.measure(q3,c3)
qc_toff.draw(output='mpl')
```

```python
# Execute the circuit on the qasm simulator.
job_toff = execute(qc_toff, backend_q, shots=4096)

# Grab the results from the job.
result_toff = job_toff.result()
plot_histogram(result_toff.get_counts(qc_toff))
```

```python
# Now, add a Toffoli gate
qc_toff = QuantumCircuit(q3,c3,name="ex1")

qc_toff.ry(2*np.pi/3,0)
qc_toff.h(1)
qc_toff.h(2)
qc_toff.ccx(1,2,0)
qc_toff.barrier()
qc_toff.measure(q3,c3)
qc_toff.draw(output='mpl')
```

```python
# Execute the circuit on the qasm simulator.
job_toff = execute(qc_toff, backend_q, shots=4096)

# Grab the results from the job.
result_toff = job_toff.result()
plot_histogram(result_toff.get_counts(qc_toff))
```

## Native single-qubit gates of IBM Q devices

One way to write a general form of a single qubit unitary:

$$
U(\theta,\phi,\lambda)=\begin{bmatrix}
 \cos(\theta/2) & -e^{i\lambda}\sin(\theta/2) \\
e^{i\phi}\sin(\theta/2) & e^{i(\lambda+\phi)}\cos(\theta/2)
\end{bmatrix}
$$
***
Native single qubit gates:
* `u3`=$U(\theta,\phi,\lambda)$
* `u2`=$U(\pi/2,\phi,\lambda)$
* `u1`=$U(0,0,\lambda)$

Native two qubit gate:
* controlled-NOT

### But why such form? $\rightarrow$ This is related to gate implementations on real devices

### Note that $$
U(\theta,\phi,\lambda)=\begin{bmatrix}
 \cos(\theta/2) & -e^{i\lambda}\sin(\theta/2) \\
e^{i\phi}\sin(\theta/2) & e^{i(\lambda+\phi)}\cos(\theta/2)
\end{bmatrix}
$$
### can be written as:
### \begin{align}
U(\theta,\phi,\lambda)&=R_z(\phi)R_y(\theta)R_z(\lambda)\\
&=R_z(\phi)R_x(-\pi/2)R_z(\theta)R_x(\pi/2)R_z(\lambda)
\end{align}

### In RF/MW based quantum control, $R_z$ is given for free, and $R_x(\pm\pi/2)$ can be calibrated with high precision.

## Running Quantum Circuits on IBM Q

### Need IBM Token for running an experiment on a IBM cloud quantum computer:  https://quantum-computing.ibm.com

```python
IBMQ.disable_account()
provider = IBMQ.enable_account('IBM_TOKEN')
```

```python
# provider = IBMQ.get_provider(hub='ibm-q-research')
```

```python
provider.backends()
```

    [<IBMQSimulator('ibmq_qasm_simulator') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmqx2') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_16_melbourne') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_vigo') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_ourense') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_valencia') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_london') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_burlington') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_essex') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_armonk') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>,
     <IBMQBackend('ibmq_rome') from IBMQ(hub='ibm-q-research', group='Daniel-Park', project='main')>]

```python
from qiskit.tools.monitor import backend_overview, backend_monitor, job_monitor
from qiskit.tools.visualization import plot_gate_map, plot_error_map
```

```python
# Retrieve IBM Quantum device information
backend_overview()
```

    ibmq_rome                    ibmq_armonk                  ibmq_essex
    ---------                    -----------                  ----------
    Num. Qubits:  5              Num. Qubits:  1              Num. Qubits:  5
    Pending Jobs: 6              Pending Jobs: 2              Pending Jobs: 70
    Least busy:   False          Least busy:   False          Least busy:   False
    Operational:  True           Operational:  True           Operational:  True
    Avg. T1:      77.2           Avg. T1:      149.4          Avg. T1:      104.2
    Avg. T2:      109.1          Avg. T2:      225.6          Avg. T2:      143.5

    ibmq_burlington              ibmq_london                  ibmq_valencia
    ---------------              -----------                  -------------
    Num. Qubits:  5              Num. Qubits:  5              Num. Qubits:  5
    Pending Jobs: 7              Pending Jobs: 7              Pending Jobs: 6
    Least busy:   False          Least busy:   False          Least busy:   False
    Operational:  True           Operational:  True           Operational:  True
    Avg. T1:      80.5           Avg. T1:      60.5           Avg. T1:      98.0
    Avg. T2:      75.7           Avg. T2:      68.1           Avg. T2:      65.1

    ibmq_ourense                 ibmq_vigo                    ibmq_16_melbourne
    ------------                 ---------                    -----------------
    Num. Qubits:  5              Num. Qubits:  5              Num. Qubits:  15
    Pending Jobs: 1              Pending Jobs: 7              Pending Jobs: 8
    Least busy:   True           Least busy:   False          Least busy:   False
    Operational:  True           Operational:  True           Operational:  True
    Avg. T1:      106.2          Avg. T1:      95.5           Avg. T1:      53.2
    Avg. T2:      64.7           Avg. T2:      63.0           Avg. T2:      56.6

    ibmqx2
    ------
    Num. Qubits:  5
    Pending Jobs: 13
    Least busy:   False
    Operational:  True
    Avg. T1:      64.1
    Avg. T2:      40.6

```python
# Let's get two quantum devices as an example
backend_qx2 = provider.get_backend('ibmqx2')
backend_vigo = provider.get_backend('ibmq_vigo')
```

```python
backend_monitor(backend_qx2)
```

    ibmqx2
    ======
    Configuration
    -------------
        n_qubits: 5
        operational: True
        status_msg: active
        pending_jobs: 13
        backend_version: 2.1.0
        basis_gates: ['id', 'u1', 'u2', 'u3', 'cx']
        local: False
        simulator: False
        sample_name: sparrow
        memory: True
        credits_required: True
        meas_map: [[0, 1, 2, 3, 4]]
        max_shots: 8192
        n_registers: 1
        coupling_map: [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1], [2, 3], [2, 4], [3, 2], [3, 4], [4, 2], [4, 3]]
        description: 5 qubit device
        backend_name: ibmqx2
        quantum_volume: 8
        conditional: False
        open_pulse: False
        allow_q_object: True
        url: None
        max_experiments: 75
        allow_object_storage: True
        online_date: 2017-01-24T05:00:00+00:00

    Qubits [Name / Freq / T1 / T2 / U1 err / U2 err / U3 err / Readout err]
    -----------------------------------------------------------------------
        Q0 / 5.2829 GHz / 73.79798 µs / 27.86901 µs / 0.0 / 0.00133 / 0.00266 / 0.0495
        Q1 / 5.24766 GHz / 61.62679 µs / 27.59343 µs / 0.0 / 0.00122 / 0.00243 / 0.023
        Q2 / 5.03384 GHz / 54.81727 µs / 62.96767 µs / 0.0 / 0.0009 / 0.0018 / 0.02
        Q3 / 5.29225 GHz / 59.02961 µs / 41.38983 µs / 0.0 / 0.00053 / 0.00107 / 0.014
        Q4 / 5.07847 GHz / 71.2559 µs / 43.16323 µs / 0.0 / 0.00051 / 0.00102 / 0.026

    Multi-Qubit Gates [Name / Type / Gate Error]
    --------------------------------------------
        cx0_1 / cx / 0.0194
        cx0_2 / cx / 0.01643
        cx1_0 / cx / 0.0194
        cx1_2 / cx / 0.02873
        cx2_0 / cx / 0.01643
        cx2_1 / cx / 0.02873
        cx2_3 / cx / 0.01804
        cx2_4 / cx / 0.01461
        cx3_2 / cx / 0.01804
        cx3_4 / cx / 0.01251
        cx4_2 / cx / 0.01461
        cx4_3 / cx / 0.01251

```python
plot_error_map(backend_qx2)
```

```python
backend_monitor(backend_vigo)
```

    ibmq_vigo
    =========
    Configuration
    -------------
        n_qubits: 5
        operational: True
        status_msg: active
        pending_jobs: 7
        backend_version: 1.0.3
        basis_gates: ['id', 'u1', 'u2', 'u3', 'cx']
        local: False
        simulator: False
        sample_name: Giraffe
        memory: True
        credits_required: True
        meas_map: [[0, 1, 2, 3, 4]]
        max_shots: 8192
        n_registers: 1
        coupling_map: [[0, 1], [1, 0], [1, 2], [1, 3], [2, 1], [3, 1], [3, 4], [4, 3]]
        description: 5 qubit device Vigo
        backend_name: ibmq_vigo
        quantum_volume: 16
        conditional: False
        open_pulse: False
        allow_q_object: True
        url: None
        max_experiments: 75
        allow_object_storage: True
        online_date: 2019-07-03T04:00:00+00:00

    Qubits [Name / Freq / T1 / T2 / U1 err / U2 err / U3 err / Readout err]
    -----------------------------------------------------------------------
        Q0 / 4.79649 GHz / 122.04295 µs / 13.28137 µs / 0.0 / 0.00035 / 0.0007 / 0.008
        Q1 / 4.94014 GHz / 64.04633 µs / 78.91768 µs / 0.0 / 0.0005 / 0.001 / 0.013
        Q2 / 4.83352 GHz / 85.55076 µs / 103.29922 µs / 0.0 / 0.00038 / 0.00076 / 0.011
        Q3 / 4.80797 GHz / 64.45464 µs / 65.45159 µs / 0.0 / 0.00061 / 0.00123 / 0.026
        Q4 / 4.74967 GHz / 141.21974 µs / 54.21269 µs / 0.0 / 0.00054 / 0.00107 / 0.022

    Multi-Qubit Gates [Name / Type / Gate Error]
    --------------------------------------------
        cx0_1 / cx / 0.00953
        cx1_0 / cx / 0.00953
        cx1_2 / cx / 0.00934
        cx1_3 / cx / 0.01271
        cx2_1 / cx / 0.00934
        cx3_1 / cx / 0.01271
        cx3_4 / cx / 0.00726
        cx4_3 / cx / 0.00726

```python
plot_error_map(backend_vigo)
```

## Let's create a 5-qubit GHZ state, i.e. $ \frac{|00000\rangle + |11111\rangle}{\sqrt{2}}$.

```python
# Create a 5-qubit GHZ state (i.e. (|00000> + |11111>)/sqrt(2))
q5 = QuantumRegister(5,'q')
c5 = ClassicalRegister(5,'c')
ghz5= QuantumCircuit(q5,c5)

ghz5.h(0)
for i in range(1,5):
    ghz5.cx(0,i)

ghz5.barrier()
ghz5.measure(q5,c5)
ghz5.draw(output='mpl')
```

## Now, let's run it on a real IBMQ device.

```python
# Run the 5-qubit GHZ experiment on a 5-qubit device (try vigo)
job_exp1 = execute(ghz5, backend=backend_vigo, shots=4096)
job_monitor(job_exp1)
```

    Job Status: job has successfully run

```python
# Grab experimental results
result_vigo = job_exp1.result()
counts_vigo = result_vigo.get_counts(ghz5)
```

```python
# Let's also try the same experiment on the 14-qubit device.
job_exp2 = execute(ghz5, backend=provider.get_backend('ibmq_16_melbourne'), shots=4096)
job_monitor(job_exp2)
```

    Job Status: job has successfully run

```python
# Grab experimental results
result_mel = job_exp2.result()
counts_mel = result_mel.get_counts(ghz5)
```

```python
# Now, compare to theory by running it on qasm_simulator
job_qasm = execute(ghz5,backend=backend_q)
result_qasm = job_qasm.result()
counts_qasm = result_qasm.get_counts(ghz5)

# Plot both experimental and ideal results
plot_histogram([counts_qasm,counts_vigo,counts_mel],
               color=['black','green','blue'],
               legend=['QASM','Vigo','Melbourne'],figsize = [20,8])
```

## Elementary Quantum Protocols

* Superdense coding
* Quantum teleportation

```python

```


# BÁO CÁO ĐỒ ÁN 01: REGRESSION

__TÊN MÔN HỌC:__ NHẬP MÔN HỌC MÁY

__ĐỀ TÀI:__ CHI PHÍ SỬ DỤNG DỊCH VỤ Y TẾ

__GIẢNG VIÊN:__ NGUYỄN TIẾN HUY

__THỨ TỰ NHÓM:__ 07

__THÀNH VIÊN:__

- 18120184 Nguyễn Nguyên Khang
- 18120189 Trần Đăng Khoa
- 18120264 Nguyễn Duy Vũ
- 18120283 Nguyễn Chiêu Bản
- 18120286 Nguyễn Quốc Bảo

__PHÂN CÔNG:__

Công việc | Thực hiện | Mức độ hoàn thành
------------ | ------------- | ------------
Khám phá dữ liệu cơ bản | Vũ | 100%
Tiền xử lý dữ liệu | Vũ | 100%
Mô hình hóa dữ liệu | Bản, Bảo | 100%
Phân tích dữ liệu tìm Insight| Khang, Khoa | 100%

## Mục Lục

- [I. Phân tích dữ liệu](#I.-Phân-tích-dữ-liệu)
    - [1. Vẽ biểu đồ một biến và nhận xét](#1.-Vẽ-biểu-đồ-một-biến-và-nhận-xét)
    - [2. Vẽ biểu đồ các biến tương quan và nhận xét](#2.-Vẽ-biểu-đồ-các-biến-tương-quan-và-nhận-xét)
    - [3. VIF](#3.-VIF)
    - [4. Insight: Sex có ảnh hưởng đến Smoker?](#4.-Insight:-Sex-có-ảnh-hưởng-đến-Smoker?)
    - [5. Insight: Trung bình của 'age', 'bmi', 'children' giữa người có hút thuốc và người không hút thuốc có bằng nhau](#5.-Insight:-Trung-bình-của-'age',-'bmi',-'children'-giữa-người-có-hút-thuốc-và-người-không-hút-thuốc-có-bằng-nhau)
    - [6. Insight: Sự phụ thuộc của 'charges' vào 'sex', 'smoker', 'age', 'bmi', 'children'](#6.-Insight:-Sự-phụ-thuộc-của-'charges'-vào-'sex',-'smoker',-'age',-'bmi',-'children')
- [II. Thuật toán sử dụng](#II.-Thuật-toán-sử-dụng)
    - [1. Cách thức đánh giá mô hình](#1.-Cách-thức-đánh-giá-mô-hình)
    - [ 2. Thuật toán SVR](#2.-Thuật-toán-SVR)
        - [a. Giới thiệu SVR](#a.-Giới-thiệu-SVR)
        - [b. Sử dụng SVR từ thư viện Scikit-learn](#b.-Sử-dụng-SVR-từ-thư-viện-Scikit-learn)
        - [c. Thử nghiệm tương tự với các kernel khác](#c.-Thử-nghiệm-tương-tự-với-các-kernel-khác)
        - [d. Thử xóa các outlier](#d.-Thử-xóa-các-outlier)
    - [3. Dùng Simple Linear Regression từ thư viện Scikit-learn](#3.-Dùng-Simple-Linear-Regression-từ-thư-viện-Scikit-learn)
        - [Trực quan hóa mô hình](#Trực-quan-hóa-mô-hình)
- [III. Tham khảo](#III.-Tham-khảo)

## I. Phân tích dữ liệu

Thông tin về dataset:

Tên cột | Ý nghĩa
------------ | -------------
Age| Tuổi
Sex| Giới tính
BMI| Chỉ số khối cơ thể
Children| Số lượng trẻ con/người phụ thuộc
Smoker| Tình trạng hút thuốc
Region| Khu vực sinh sống
Charges| Chi phí y tế cá nhân

### 1. Vẽ biểu đồ một biến và nhận xét

```python
Biến charges:
```

Nhận xét: Biến charges có phân bố bị lệch trái, nhiều outlier

```python
Biến age:
```

Nhận xét: Biến age có phân bố chuẩn

```python
Biến bmi:
```

Nhận xét: Biến bmi có phân bố chuẩn, tồn tại outlier

```python
Biến sex:
```

Nhận xét: Tỉ lệ nam nữ bằng nhau

```python
Biến smoker:
```

Nhận xét: Tỉ lệ người không hút thuốc gấp 4 lần người hút thuốc

```python
Biến children:
```

Nhận xét: Tỉ lệ người có càng nhiều con giảm dần

### 2. Vẽ biểu đồ các biến tương quan và nhận xét

Trước tiên, ta tính ma trận tương quan

```python

```

Có thể thấy những thuộc tính như age (yếu), bmi (yếu), smoker (mạnh) có tương quan với thuộc tính charges

```python
Biểu đồ thể hiện sự mất tiền vào chi phí y tế của người có hút thuốc
```

Biểu đồ trên cho ta thấy người hút thuốc thì có chi phí y tế cao hơn, cụ thể :
- hơn 75% người hút thuốc trả chi phí cao hơn hầu hết tất cả người không hút thuốc
- chi phí thấp nhất của người hút thuốc chỉ nhỉnh hơn một chút so với chi phí của 75% người không hút thuốc.
- nếu chi phí dưới 10k, xác suất cao là người đó không hút thuốc
- nếu chi phí trên 20k, xác suất cao là người đó hút thuốc

```python
Phân bố của chi phí y tế theo độ tuổi
```

Nhìn vào biểu đồ trên, ta thấy
- người càng cao tuổi thì số tiền chi cho y tế càng nhiều
- Nếu dưới 35 tuổi và không hút thuốc thì khả năng cao chi phí dưới 6k

```python
Phân bố của chi phí y tế theo bmi
```

- Người hút thuốc và có chỉ số BMI lớn hơn 30 thì chi phí tổi thiểu là khoảng 30k

### 3. VIF

```python
Bảng VIF
```

        feature       VIF
    0       sex  1.966855
    1    smoker  1.254563
    2       age  7.658193
    3       bmi  8.638958
    4  children  1.816248

1 = Không tương quan [1]

Giữa 1 và 5 = Tương quan vừa [1]

Lớn hơn 5 = Tương quan mạnh [1]

Ta thấy các biến `sex`, `smoker`, `children` tương quan vừa với các biến còn lại.

`age` và `bmi` có sự tương quan mạnh với các biến còn lại

Nên thu thập thêm data để giảm sự phụ thuộc giữa các biến

### 4. Insight: Sex có ảnh hưởng đến Smoker?

${H_0}$: sex và smoker độc lập nhau

${H_A}$: sex và smoker phụ thuộc nhau

Đặt:

${A =}$  sex, ${A_1 =}$ `male`, ${A_2}$ = `female`

${B =}$ smoker, ${B_1 =}$ `yes`, ${B_2 =}$ `no`

Ta có:

${H_0}$: ${P(A_i\cap B_j) = P(A_i)P(B_j)}$

${H_A}$: ${P(A_i\cap B_j) \neq P(A_i)P(B_j)}$

Phần dưới sẽ trình bày về mặt toán học lẫn sử dụng thư viện scipy.stats để tính toán

```python
contigency
```

      no
      yes
      Pr(Ai)

      sex

      female
      406
      91
      0.495513

      male
      391
      115
      0.504487

Ta đã tính được ${Pr(A_i)}$ như bảng trên và

${Pr(B_1)}$ = 0.2053838484546361

${Pr(B_2)}$ =  0.7946161515453639

---

Đến đây ta có thể tính:

Giá trị mong đợi ${E}$:

\begin{equation}
\text{Do kỳ vọng A và B độc lập:}\\
E_{ij} = Pr(A_i) \times Pr(B_j) \times N [2]\\
\text{hay}\\
E_{ij} = \frac{\text{(Tổng dòng} \times \text{Tổng cột)}}{\text{Tổng bảng}} [3]   \\
\text{với bảng là bảng contingency}
\end{equation}

Giá trị ${\chi^2}$:

\begin{equation}
\chi^2=\Sigma\frac{(O-E)^2}{E} [2][3]\\
\text{với O là giá trị thực sự và E là giá trị mong đợi}
\end{equation}

Giá trị dof: Degree of freedom

dof cho ${\chi^2}$ độc lập:

\begin{equation}
dof = v = rc - 1 - (r-1) - (c-1) = (r-1)(c-1) [2]\\ = 1
\end{equation}

Chọn mức ý nghĩa:

\begin{equation}
\alpha = 0.05
\end{equation}

Tra bảng Chi Squared với ${\alpha = 0.05, dof = 1}$ ta được critical value ${ = 3.841459}$

Chấp nhận ${H_0}$ nếu
\begin{equation}
\chi^2_v <= 3.841459
\end{equation}

Ta có thể sử dụng `chi2_contingency` của thư viện spicy để tính toán, các giá trị tính được từ thư viện và kết luận là:

p-value là:  0.09827321674727184

chi = 2.733346, critical value = 3.841459

Với mức ý nghĩa 0.05, ta bác bỏ HA và chấp nhận H0.

Kết luận: sex và smoker độc lập.

Ta kiểm tra, không dùng thư viện, được kết quả như sau:

```python

```

    chi_square =  2.997908815661011

      smoker
      sex
      count
      Expected value
      (O_ij - E_ij)^2/E_ij

      0
      no
      male
      391
      402.075773
      0.305099

      1
      yes
      male
      115
      103.924227
      1.180406

      2
      no
      female
      406
      394.924227
      0.310623

      3
      yes
      female
      91
      102.075773
      1.201781

Ta thấy:

\begin{equation}
\chi^2_v = 2.997908815661011 < 3.841459
\end{equation}

Vậy bác bỏ ${H_A}$ với mức ý nghĩa 0.05, chấp nhận ${H_0}$

Kết luận: sex và smoker độc lập

### 5. Insight: Trung bình của 'age', 'bmi', 'children' giữa người có hút thuốc và người không hút thuốc có bằng nhau

Sử dụng z-test ta tính được như sau:

$H_0$: trung bình `age` của người có hút thuốc $=$ trung bình `age` của người không hút thuốc

$H_A$: trung bình `age` của người có hút thuốc $\neq$ trung bình `age` của người không hút thuốc

stat=-1.200, p=0.230

KẾT LUẬN:
Với mức ý nghĩa 0.05, ta chấp nhận Ho, bác bỏ Ha

Trung bình `age` của người có hút thuốc $=$ trung bình `age` của người không hút thuốc

---

$H_0$: trung bình `bmi` của người có hút thuốc $=$ trung bình `bmi` của người không hút thuốc

$H_A$: trung bình `bmi` của người có hút thuốc $\neq$ trung bình `bmi` của người không hút thuốc

stat=-0.047, p=0.962

KẾT LUẬN:
Với mức ý nghĩa 0.05, ta chấp nhận Ho, bác bỏ Ha

Trung bình `bmi` của người có hút thuốc $=$ trung bình `bmi` của người không hút thuốc

---

$H_0$: trung bình `children` của người có hút thuốc $=$ trung bình `children` của người không hút thuốc

$H_A$: trung bình `children` của người có hút thuốc $\neq$ trung bình `children` của người không hút thuốc

stat=0.807, p=0.420

KẾT LUẬN:
Với mức ý nghĩa 0.05, ta chấp nhận Ho, bác bỏ Ha

Trung bình `children` của người có hút thuốc $=$ trung bình `children` của người không hút thuốc

### 6. Insight: Sự phụ thuộc của 'charges' vào 'sex', 'smoker', 'age', 'bmi', 'children'

Ta huấn luyện bằng mô hình OLS Regression:

```python

```

                                OLS Regression Results
    ==============================================================================
    Dep. Variable:                charges   R-squared:                       0.744
    Model:                            OLS   Adj. R-squared:                  0.743
    Method:                 Least Squares   F-statistic:                     580.0
    Date:                Fri, 14 May 2021   Prob (F-statistic):          3.98e-292
    Time:                        20:59:36   Log-Likelihood:                -10164.
    No. Observations:                1003   AIC:                         2.034e+04
    Df Residuals:                     997   BIC:                         2.037e+04
    Df Model:                           5
    Covariance Type:            nonrobust
    ==============================================================================
                     coef    std err          t      P>|t|      [0.025      0.975]
    ------------------------------------------------------------------------------
    const       -1.23e+04   1121.474    -10.968      0.000   -1.45e+04   -1.01e+04
    sex           66.0697    386.570      0.171      0.864    -692.515     824.655
    smoker      2.363e+04    478.849     49.344      0.000    2.27e+04    2.46e+04
    age          260.0358     13.870     18.748      0.000     232.818     287.254
    bmi          327.5600     32.307     10.139      0.000     264.162     390.958
    children     434.8043    160.590      2.708      0.007     119.671     749.938
    ==============================================================================
    Omnibus:                      241.068   Durbin-Watson:                   2.068
    Prob(Omnibus):                  0.000   Jarque-Bera (JB):              592.918
    Skew:                           1.268   Prob(JB):                    1.78e-129
    Kurtosis:                       5.785   Cond. No.                         299.
    ==============================================================================

    Notes:
    [1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

Kết luận:

- Biến `sex` không có ý nghĩa (có thể loại bỏ)
- Biến `smoker` có ý nghĩa đối với mô hình về mặt thống kê (với mức ý nghĩa (***) hay p-value = 0.000)
- Biến `age` có ý nghĩa đối với mô hình về mặt thống kê (với mức ý nghĩa (***) hay p-value = 0.000)
- Biến `bmi` có ý nghĩa đối với mô hình về mặt thống kê (với mức ý nghĩa (***) hay p-value = 0.000)
- Biến `children` không có ý nghĩa (có thể loại bỏ)
- Mô hình có thể giải thích được 74.3% sự thay đổi của biến `charges`
- Mô hình tương đối tốt (p-value = 1.78e-129)

Ta huấn luyện lại mô hình dựa theo kết luận trên

```python

```

                                OLS Regression Results
    ==============================================================================
    Dep. Variable:                charges   R-squared:                       0.742
    Model:                            OLS   Adj. R-squared:                  0.741
    Method:                 Least Squares   F-statistic:                     959.1
    Date:                Fri, 14 May 2021   Prob (F-statistic):          1.63e-293
    Time:                        21:00:36   Log-Likelihood:                -10168.
    No. Observations:                1003   AIC:                         2.034e+04
    Df Residuals:                     999   BIC:                         2.036e+04
    Df Model:                           3
    Covariance Type:            nonrobust
    ==============================================================================
                     coef    std err          t      P>|t|      [0.025      0.975]
    ------------------------------------------------------------------------------
    const      -1.185e+04   1097.537    -10.799      0.000    -1.4e+04   -9698.979
    smoker      2.367e+04    479.257     49.386      0.000    2.27e+04    2.46e+04
    age          262.1450     13.884     18.881      0.000     234.900     289.390
    bmi          326.7252     32.392     10.086      0.000     263.160     390.290
    ==============================================================================
    Omnibus:                      238.957   Durbin-Watson:                   2.060
    Prob(Omnibus):                  0.000   Jarque-Bera (JB):              580.364
    Skew:                           1.263   Prob(JB):                    9.45e-127
    Kurtosis:                       5.741   Cond. No.                         291.
    ==============================================================================

    Notes:
    [1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

```python

```

    Parameters:  const    -11852.720452
    smoker    23668.497446
    age         262.144961
    bmi         326.725200
    dtype: float64

Ta thấy:

- Cứ tăng 1 tuổi thì chi phí y tế cá nhân tăng 262.144961, tăng 1 chỉ số bmi thì tăng 326.725200 chi phí y tế cá nhân
- Riêng với smoker, người có hút thuốc thì có chi phí y tế cá nhân cao hơn người không hút thuốc đến 23668.497446

## II. Thuật toán sử dụng

Trong lab này, nhóm em sử dụng 2 thuật toán chính là Simple linear regression và Support Vector Regression (SVR) (là một dạng mở rộng của Support Vector MachineMachine).

### 1. Cách thức đánh giá mô hình

- Nhóm em sử dụng độ do R-squared để đánh giá mô hình
- Phương pháp lấy mẫu để đánh giá mô hình là K-Fold Cross-Validation với k = 10

### 2. Thuật toán SVR

#### a. Giới thiệu SVR

**Support Vector Machine (SVM)**

SVM là bài toán phân lớp, và đi tìm mặt phân cách sao cho margin tìm được là lớn nhất, đồng nghĩa với việc các điểm dữ liệu an toàn nhất so với mặt phân cách.

**Support Vector Regression (SVR)**

SVR là một biến thể của SVM để dùng cho bài toán hồi quy. SVR tìm cách cực tiểu margin sao cho có thể chứa nhiều điểm dữ liệu nhất có thể.

#### b. Sử dụng SVR từ thư viện Scikit-learn

Trước khi trình bày quy trình, nhóm em thống như quy tắt đặt biến như sau:
- X là một Dataframe đọc từ file train và không bao gồm cột `charges`
- y là Series chứa dữ liệu của cột `charges`
- preds là output sau khi chạy mô hình
- X_test, y_test tương tự như X, y nhưng được đọc từ file test

Để chọn ra mô hình tốt nhất, nhóm tiến hành các bước như sau

#### Bước 1: Tiền xử lí:
- Tiền xử lí X: dùng OrdinalEncoder cho cột `sex` và `smoker`, OnehotEncoder cho `region`, StandardScaler cho các cột có kiểu số
- Tiền xử lý y bằng StandardScaler

Theo các bước tiền xử lí như trên ta được Pipeline như sau:

#### Bước 2:

Chọn tham số cho mô hình SVR với kernel mặc đinh

Với phương pháp lấy mẫu là K-Fold, xem xét độ lỗi trên tập train ta được độ lỗi trung bình đối với từng siêu tham số C và gamma như sau:

Qua đó ta thấy mô hình đạt kết quả tốt nhất trên tập train là 0.828 với C = 10 và gamma = 0.05

#### Bước 3: Huấn luyện mô hình với các siêu tham số vừa tìm được ở trên

Với các siêu tham số trên thì độ chính xác trên tập test khoảng 0.857

#### c. Thử nghiệm tương tự với các kernel khác

Thử nghiệm tương tự với các kernel khác. Kết quả được trình bày cụ thể trong bài làm

#### d. Thử xóa các outlier

Ta thấy nhóm bệnh nhân không hút thuốc có nhiều outlier về chi phí phải trả. Ta thử các outlier này và huấn luyện lại mô hình với các siêu tham số tốt nhất trong các thử nghiệm ở trên. Ta được kết quả như sau:

Ta thấy R-squared trên tập train đã tăng lên khá nhiều, đạt 0.899

Tuy nhiên khi dùng mô hình này để chạy trên tập test thì kết quả chỉ đạt 0.853. Có thể thấy các bệnh nhân này không phải là các trường hợp bất thường. Mà trong thực tế (tập test) vẫn có khá nhiều bệnh nhân giống như vậy - không hút thuốc nhưng chi phí y tế lại cao. Có thể ta cần thêm các thuộc tính khác như thu nhập, môi trường sống có ô nhiễm hay không... mới có thể dự đoán chi phí cho y tế được chính xác hơn

### 3. Dùng Simple Linear Regression từ thư viện Scikit-learn

Tương tự như trên, Pipeline của mô hình là:

Đối với mô hình này ta chỉ đặt độ chính xác R-squared là 0.766

#### Trực quan hóa mô hình

### III. Tham khảo

[1]. [Stephanie - Variance Inflation Factor - Statisticshowto.com](https://www.statisticshowto.com/variance-inflation-factor/)

[2]. https://www3.nd.edu/~rwilliam/stats1/x51.pdf

[3]. https://towardsdatascience.com/gentle-introduction-to-chi-square-test-for-independence-7182a7414a95

[4]. https://scikit-learn.org/0.21/documentation.html

[5]. https://machinelearningmastery.com/how-to-transform-target-variables-for-regression-with-scikit-learn/