from qiskit.circuit.library import TwoLocal, ZZFeatureMap
from qiskit_algorithms.optimizers import COBYLA
from qiskit_algorithms.utils import algorithm_globals
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import MinMaxScaler
from qiskit_machine_learning.algorithms import VQC
from qiskit.circuit.library import ZZFeatureMap
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split


seed = 1376
algorithm_globals.random_seed = seed

cancerData = load_breast_cancer()

print(cancerData.DESCR)


import pandas as pd
import seaborn as sns
from sklearn.decomposition import PCA
from sklearn.svm import SVC

features = cancerData.data
labels = cancerData.target

features = MinMaxScaler().fit_transform(features)


num_features = features.shape[1]

feature_map = ZZFeatureMap(feature_dimension=num_features, reps=1)
feature_map.decompose().draw(style="clifford")

from qiskit.circuit.library import RealAmplitudes
from qiskit.primitives import Sampler
from IPython.display import clear_output

ansatz = RealAmplitudes(num_qubits=num_features, reps=3)
optimizer = COBYLA(maxiter=100)
sampler = Sampler()


objective_func_vals = []
plt.rcParams["figure.figsize"] = (12, 6)



def callback_graph(weights, obj_func_eval):
    clear_output(wait=True)
    objective_func_vals.append(obj_func_eval)
    plt.title("Objective function value against iteration")
    plt.xlabel("Iteration")
    plt.ylabel("Objective function value")
    plt.plot(range(len(objective_func_vals)), objective_func_vals)
    plt.show()

df = pd.DataFrame(cancerData.data, columns=cancerData.feature_names)
df["class"] = pd.Series(cancerData.target)

sns.pairplot(df, hue="class", palette="tab10")

import time
from qiskit_machine_learning.algorithms.classifiers import VQC

algorithm_globals.random_seed = 12
train_features, test_features, train_labels, test_labels = train_test_split(
    features, labels, train_size=0.8, random_state=algorithm_globals.random_seed
)



svc = SVC()
_ = svc.fit(train_features, train_labels)  # suppress printing the return value

train_score_c4 = svc.score(train_features, train_labels)
test_score_c4 = svc.score(test_features, test_labels)

print(f"Classical SVC on the training dataset: {train_score_c4:.2f}")
print(f"Classical SVC on the test dataset:     {test_score_c4:.2f}")

vqc = VQC(
    sampler=sampler,
    feature_map=feature_map,
    ansatz=ansatz,
    optimizer=optimizer,
    callback=callback_graph,
)

# clear objective value history

objective_func_vals = []

start = time.time()
vqc.fit(train_features, train_labels)
train_score_q4 = vqc.score(train_features, train_labels)
test_score_q4 = vqc.score(test_features, test_labels)
print(f"Quantum VQC on the training dataset: {train_score_q4:.2f}")
print(f"Quantum VQC on the test dataset:     {test_score_q4:.2f}")