# build your code here
answer1 = [1]

# run this cell to submit your answer

# import the grader for the exercise 1 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex1

# expected result type: List
grade_badge5_ex1(answer1)

# build your code here
answer2 = [2]

# run this cell to submit your answer

# import the grader for the exercise 2 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex2

# expected result type: List
grade_badge5_ex2(answer2)

# build your code here
answer3 = [4]

# run this cell to submit your answer

# import the grader for the exercise 3 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex3

# expected result type: List
grade_badge5_ex3(answer3)

# build your code here
answer4 = [4]

# run this cell to submit your answer

# import the grader for the exercise 4 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex4

# expected result type: List
grade_badge5_ex4(answer4)

# build your code here
answer5 = [3]

# run this cell to submit your answer

# import the grader for the exercise 5 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex5

# expected result type: List
grade_badge5_ex5(answer5)

# build your code here
answer6 = [1]

# run this cell to submit your answer

# import the grader for the exercise 6 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex6

# expected result type: List
grade_badge5_ex6(answer6)

# build your code here
answer7 = [1]

# run this cell to submit your answer

# import the grader for the exercise 7 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex7

# expected result type: List
grade_badge5_ex7(answer7)

# build your code here
answer8 = [2]

# run this cell to submit your answer

# import the grader for the exercise 8 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex8

# expected result type: List
grade_badge5_ex8(answer8)

# build your code here
answer9 = [1]

# run this cell to submit your answer

# import the grader for the exercise 9 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex9

# expected result type: List
grade_badge5_ex9(answer9)

# build your code here
answer10 = [3]

# run this cell to submit your answer

# import the grader for the exercise 10 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex10

# expected result type: List
grade_badge5_ex10(answer10)

# build your code here
answer11 = [1]

# run this cell to submit your answer

# import the grader for the exercise 11 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex11

# expected result type: List
grade_badge5_ex11(answer11)

# build your code here
answer12 = [4]

# run this cell to submit your answer

# import the grader for the exercise 12 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex12

# expected result type: List
grade_badge5_ex12(answer12)

# import the NumPy library with 'np' alias 
import numpy as np

# import the Quantum Support Vector Classifier (QSVC) from
# the Qiskit's Machine Learning - Algorithms module
from qiskit_machine_learning.algorithms import QSVC


# define the features X of the initial training dataset 
x_train = np.array([
       [1.25663706, 5.02654825, 3.76991118],
       [3.76991118, 0.        , 0.62831853],
       [4.08407045, 3.76991118, 1.88495559],
       [0.62831853, 2.82743339, 2.51327412],
       [0.9424778 , 5.96902604, 5.02654825],
       [5.02654825, 2.51327412, 0.31415927],
       [5.34070751, 0.62831853, 3.45575192],
       [0.31415927, 3.45575192, 3.76991118],
       [1.25663706, 4.39822972, 5.96902604],
       [3.76991118, 1.25663706, 2.82743339],
       [3.14159265, 5.34070751, 1.88495559],
       [3.45575192, 0.31415927, 1.57079633],
       [1.57079633, 0.        , 5.96902604],
       [4.08407045, 3.14159265, 0.        ],
       [1.57079633, 4.39822972, 0.9424778 ],
       [0.        , 1.57079633, 0.31415927],
       [5.02654825, 2.82743339, 4.71238898],
       [2.51327412, 0.62831853, 0.62831853],
       [3.14159265, 5.34070751, 1.88495559],
       [5.65486678, 4.71238898, 4.08407045],
       [0.        , 2.19911486, 3.45575192],
       [0.62831853, 0.31415927, 3.45575192],
       [5.65486678, 2.51327412, 5.65486678],
       [2.19911486, 0.62831853, 5.02654825],
       [5.34070751, 3.45575192, 4.39822972],
       [4.08407045, 2.51327412, 4.08407045],
       [0.62831853, 5.65486678, 4.08407045],
       [5.96902604, 4.39822972, 0.62831853],
       [5.96902604, 4.39822972, 5.96902604],
       [0.        , 5.96902604, 4.08407045]
])

# define the labels Y of the initial training dataset
y_train = np.array([ 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
                     0, 0, 1, 0, 1, 1, 1, 1, 0, 0,
                     1, 1, 1, 0, 0, 0, 0, 1, 1, 0 ])


# compute the size of metric to
# split the initial training dataset into
# a final training set and a final test set,
# where 80% of the data will be used for training,
# and 20% of the data will be used for testing
train_size = int( 0.8 * len(x_train) )


# split the initial training dataset
# into a final training set,
# for the data features X
x_train_split = x_train[:train_size]

# split the initial training dataset
# into a final training set,
# for the data labels Y
y_train_split = y_train[:train_size]


# split the initial training dataset
# into a final testing set,
# for the data features X
x_test = x_train[train_size:]

# split the initial training dataset
# into a final testing set,
# for the data labels Y
y_test = y_train[train_size:]


####### build your code below #########

# import the Z Feature Map from
# the Qiskit's Circuit Library module
from qiskit.circuit.library import ZFeatureMap

# import the Sampler from
# the Qiskit's Primitives module
from qiskit.primitives import Sampler

# import the Compute-Uncompute method from
# the Qiskit's Algorithms - State Fidelities module
from qiskit.algorithms.state_fidelities import ComputeUncompute

# import the Fidelity Quantum Kernel from
# the Qiskit's Machine Learning - Kernels module
from qiskit_machine_learning.kernels import FidelityQuantumKernel


# compute the number of features X of
# the samples present in the final training set
num_features = x_train_split.shape[1]

# define the number of repetitions of
# the quantum circuits for the Z Feature Map
num_repetitions = 1


# create a Z Feature Map for the number of
# features X and number of repetitions defined before,
# to be used for the creation of the Quantum Kernel
feature_map = ZFeatureMap( feature_dimension=num_features, reps=num_repetitions )


# create the Sampler object
# for the Compute-Uncompute method
sampler = Sampler()

# create the Fidelity object object
# with the Sampler object defined before
fidelity = ComputeUncompute( sampler=sampler )

# create the Fidelity Quantum Kernel object
# with the Fidelity and the Z Feature Map defined before
quantum_kernel = FidelityQuantumKernel( fidelity=fidelity, feature_map=feature_map )

# create the Quantum Support Vector Classifier (QSVC)
# with the Fidelity Quantum Kernel defined before
qsvc = QSVC( quantum_kernel=quantum_kernel )


# fit the data features X and data labels Y of
# the final training dataset into the previously
# created Quantum Support Vector Classifier (QSVC)
qsvc.fit( x_train_split, y_train_split )

####### build your code above #########


# evaluate the performance score of
# the quantum learning model of
# the Quantum Support Vector Classifier (QSVC)
# note: you need achieve a score higher
#       than 0.8 to pass the code question
qsvc_score = qsvc.score(x_test, y_test)

# print the performance score of
# the quantum learning model of
# the Quantum Support Vector Classifier (QSVC)
print(f"QSVC classification test score: {qsvc_score} ( { ( round( qsvc_score * 100 , 2 ) ) }% )")

# run this cell to submit your answer

# import the grader for the coding exercise of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_code

# expected result type: QSVC
answer_code = grade_badge5_code(qsvc)

# import the Qiskit Runtime Service
# from the Qiksit's IBM Runtime module
from qiskit_ibm_runtime import QiskitRuntimeService


# create a Qiskit's Runtime Service object,
# using the IBM Quantum channel
service = QiskitRuntimeService( channel="ibm_quantum" )


# compute the number of features X of
# the samples present in the final training set
num_features = x_train_split.shape[1]


# retrieve the least-busy backend
# with a minimum number of two qubits
# (this step can take a while)
real_backend = service.least_busy( min_num_qubits=num_features, simulator=False )

# print the information about the best (i.e., the least-busy)
# backend with a minimum number of two qubits, and an informative
# message about the job submission on this backend
print( "The best backend is " + real_backend.name + "!" )

# import the ZZ Feature Map from
# the Qiskit's Circuit Library module
from qiskit.circuit.library import ZZFeatureMap

# import the Quantum Support Vector Classifier (QSVC) from
# the Qiskit's Machine Learning - Algorithms module
from qiskit_machine_learning.algorithms import QSVC

# import the Session from
# the Qiksit's IBM Runtime module
from qiskit_ibm_runtime import Session

# import the Sampler from
# the Qiskit's Primitives module
from qiskit.primitives import Sampler

# import the Compute-Uncompute method from
# the Qiskit's Algorithms - State Fidelities module
from qiskit.algorithms.state_fidelities import ComputeUncompute

# import the Fidelity Quantum Kernel from
# the Qiskit's Machine Learning - Kernels module
from qiskit_machine_learning.kernels import FidelityQuantumKernel


# compute the number of features X of
# the samples present in the final training set
num_features = x_train_split.shape[1]

# create a ZZ Feature Map for
# the number of features X defined before,
# to be used for the creation of the Quantum Kernel
fm = feature_map = ZZFeatureMap( num_features )


# within the context of a Session configured
# with the Qiskit's Runtime Service object,
# created before, using the IBM Quantum channel,
# and also using the backend defined before 
with Session( service=service, backend=real_backend ) as session:
    
    # create the Sampler object
    # for the Compute-Uncompute method
    sampler = Sampler()
    
    # create the Fidelity object,
    # using the Compute-Uncompute method
    # applied on the Sampler object defined before
    fidelity = ComputeUncompute( sampler )
    
    
    # create the Fidelity Quantum Kernel object
    # with the Fidelity and the ZZ Feature Map defined before
    quantum_kernel = FidelityQuantumKernel( feature_map=fm, fidelity=fidelity )
    
    # create the Quantum Support Vector Classifier (QSVC)
    # with the Fidelity Quantum Kernel defined before
    qsvc = QSVC( quantum_kernel=quantum_kernel )


###### add your answers from above before running the cell #######

# fit the data features X and data labels Y of
# the final training dataset into the previously
# created Quantum Support Vector Classifier (QSVC)
qsvc.fit( x_train_split, y_train_split )

# evaluate the performance score of
# the quantum learning model of
# the Quantum Support Vector Classifier (QSVC)
qsvc_score = qsvc.score(x_test, y_test)

# print the performance score of
# the quantum learning model of
# the Quantum Support Vector Classifier (QSVC)
print(f"QSVC classification test score: {qsvc_score} ( { ( round( qsvc_score * 100 , 2 ) ) }% )")

# build your code here
answer13 = [4]

# run this cell to submit your answer

# import the grader for the exercise 13 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex13

# expected result type: List
grade_badge5_ex13(answer13)

# build your code here
answer14 = [3]

# run this cell to submit your answer

# import the grader for the exercise 14 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex14

# expected result type: List
grade_badge5_ex14(answer14)

# build your code here
answer15 = [2]

# run this cell to submit your answer

# import the grader for the exercise 15 of the lab/badge 5
from qc_grader.challenges.quantum_explorers23 import grade_badge5_ex15

# expected result type: List
grade_badge5_ex15(answer15)

# run this cell to check whether you have passed

# import the grader for the badge 5 of
# the IBM Qiskit's Quantum Explorers 2023-2024
from qc_grader.challenges.quantum_explorers23 import grade_badge5_score

# grade the score of the quiz of the lab for the badge 5
grade_badge5_score("en")