# Essentials
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Classical Machine Learning
from sklearn.svm import SVC
from sklearn.datasets import make_blobs, make_circles
from sklearn.cluster import SpectralClustering
from sklearn.metrics import normalized_mutual_info_score, accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# Quantum Machine Learning
from qiskit import BasicAer
from qiskit.circuit.library import ZZFeatureMap, ZFeatureMap, PauliFeatureMap
from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit_machine_learning.algorithms import QSVC
from qiskit_machine_learning.kernels import QuantumKernel

dataset = pd.read_csv(r'iris_data\iris.data')
features_all= dataset.iloc[:, :4].values
features_sepal= dataset.iloc[:, :2].values
features_petal= dataset.iloc[:, 2:4].values
label   = dataset.iloc[:, 4].values

for i in range(len(label)):
    if label[i] == 'Iris-setosa':
        label[i] = 0
    elif label[i] == 'Iris-versicolor':
        label[i] = 1
    elif label[i] == 'Iris-virginica':
        label[i] = 2

label = label.astype(str).astype(int)        

X_train, X_test, y_train, y_test = train_test_split(features_all, label, test_size=0.25, random_state=12)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Normalize
mms = MinMaxScaler((-1, 1))
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test)

clf = SVC(kernel="linear", random_state=2)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print("Accuracy is", accuracy_score(y_test, y_pred))

X_train, X_test, y_train, y_test = train_test_split(features_sepal, label, test_size=0.25, random_state=12)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Normalize
mms = MinMaxScaler((-1, 1))
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test)

clf = SVC(kernel="rbf", random_state=2)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print("Accuracy is", accuracy_score(y_test, y_pred))

X_train, X_test, y_train, y_test = train_test_split(features_petal, label, test_size=0.25, random_state=12)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Normalize
mms = MinMaxScaler((-1, 1))
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test)

clf = SVC(kernel="linear", random_state=2)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print("Accuracy is", accuracy_score(y_test, y_pred))

feature_map = ZZFeatureMap(feature_dimension=2, reps=2, entanglement='linear')
backend = QuantumInstance(BasicAer.get_backend('qasm_simulator'), shots=8000)
kernel = QuantumKernel(feature_map=feature_map, quantum_instance=backend)

X_train, X_test, y_train, y_test = train_test_split(features_all, label, test_size=0.25, random_state=12)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Normalize
mms = MinMaxScaler((-1, 1))
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test)

clf = SVC(kernel=kernel.evaluate)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print("Accuracy is", accuracy_score(y_test, y_pred))

X_train, X_test, y_train, y_test = train_test_split(features_sepal, label, test_size=0.25, random_state=12)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Normalize
mms = MinMaxScaler((-1, 1))
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test)

clf = SVC(kernel="rbf", random_state=2)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print("Accuracy is", accuracy_score(y_test, y_pred))

X_train, X_test, y_train, y_test = train_test_split(features_petal, label, test_size=0.25, random_state=12)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Normalize
mms = MinMaxScaler((-1, 1))
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test)

clf = SVC(kernel="linear", random_state=2)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print("Accuracy is", accuracy_score(y_test, y_pred))

