Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactorize test_classification.py #19

Merged
merged 5 commits into from
Jan 13, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 98 additions & 85 deletions tests/test_classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,109 +22,122 @@ def test_vqc_classical_should_return_value_error():
QuanticVQC(quantum=False)


def test_qsvm_init():
def test_qsvm_init_quantum_wrong_token():
with pytest.raises(Exception):
q = QuanticSVM(quantum=True, q_account_token="INVALID")
q._init_quantum()


@pytest.mark.parametrize('quantum', [False, True])
def test_qsvm_init(quantum):
"""Test init of quantum classifiers"""
# if "classical" computation enable,
# no provider and backend should be defined
q = QuanticSVM(quantum=False)
q._init_quantum()
assert not q.quantum
assert not hasattr(q, "backend")
assert not hasattr(q, "provider")
# if "quantum" computation enabled, but no accountToken are provided,
# then "quantum" simulation will be enabled
# i.e., no remote quantum provider will be defined
q = QuanticSVM(quantum=True)

q = QuanticSVM(quantum=quantum)
q._init_quantum()
assert q.quantum
assert hasattr(q, "_backend")
assert q.quantum == quantum
assert hasattr(q, "_backend") == quantum

# A provider is only assigned when running on a real quantum backend
assert not hasattr(q, "_provider")
# if "quantum" computation enabled, and accountToken is provided,
# then real quantum backend is used
# this should raise a error as uncorrect API Token is passed
try:
q = QuanticSVM(labelsquantum=True, qAccountToken="Test")
assert False # Should never reach this line
except Exception:
pass


def test_qsvm_splitclasses(get_dataset):
class BinaryTest:
def prepare(self, n_samples, n_features, quantum_instance, random):
self.n_classes = 2
self.n_samples = n_samples
self.n_features = n_features
self.quantum_instance = quantum_instance
self.random = random
self.class_len = n_samples // self.n_classes

def test(self, get_dataset):
# there is no __init__ method with pytest
n_samples, n_features, quantum_instance, random = self.get_params()
self.prepare(n_samples, n_features, quantum_instance, random)
self.samples, self.labels = get_dataset(self.n_samples,
self.n_features,
self.n_classes,
self.random)
self.additional_steps()
self.check()

def get_params(self):
raise NotImplementedError

def additional_steps(self):
raise NotImplementedError

def check(self):
raise NotImplementedError


class TestQSVMSplitClasses(BinaryTest):
"""Test _split_classes method of quantum classifiers"""
q = QuanticSVM(quantum=False)
def get_params(self):
quantum_instance = QuanticSVM(quantum=False)
return 100, 9, quantum_instance, True

def additional_steps(self):
# As fit method is not called here, classes_ is not set.
# so we need to provide the classes ourselves.
self.quantum_instance.classes_ = range(0, self.n_classes)
self.x_class1, \
self.x_class0 = self.quantum_instance._split_classes(self.samples,
self.labels)

n_samples, n_features, n_classes = 100, 9, 2
samples, labels = get_dataset(n_samples, n_features, n_classes)
def check(self):
assert np.shape(self.x_class1) == (self.class_len, self.n_features)
assert np.shape(self.x_class0) == (self.class_len, self.n_features)

# As fit method is not called here, classes_ is not set.
# so we need to provide the classes ourselves.
q.classes_ = range(0, n_classes)

x_class1, x_class0 = q._split_classes(samples, labels)
class_len = n_samples // n_classes # balanced set
assert np.shape(x_class1) == (class_len, n_features)
assert np.shape(x_class0) == (class_len, n_features)
class BinaryFVT(BinaryTest):
def additional_steps(self):
self.quantum_instance.fit(self.samples, self.labels)
self.prediction = self.quantum_instance.predict(self.samples)


def test_quantic_fvt_Classical(get_dataset):
class TestClassicalSVM(BinaryFVT):
""" Perform standard SVC test
(canary test to assess pipeline correctness)
"""
# When quantum=False, it should use
# classical SVC implementation from SKlearn
q = QuanticSVM(quantum=False, verbose=False)
# We need to have different values for first and second classes
# in our samples or vector machine will not converge
n_samples, n_features, n_classes = 100, 9, 2
class_len = n_samples // n_classes # balanced set
samples, labels = get_dataset(n_samples, n_features, n_classes,
random=False)

q.fit(samples, labels)
# This will autodefine testing sets
prediction = q.predict(samples)
# In this case, using SVM, predicting accuracy should be 100%
assert prediction[:class_len].all() == q.classes_[0]
assert prediction[class_len:].all() == q.classes_[1]


def test_quantic_svm_fvt_simulated_quantum(get_dataset):
def get_params(self):
quantum_instance = QuanticSVM(quantum=False, verbose=False)
return 100, 9, quantum_instance, False

def check(self):
assert self.prediction[:self.class_len].all() == \
self.quantum_instance.classes_[0]
assert self.prediction[self.class_len:].all() == \
self.quantum_instance.classes_[1]


class TestQuanticSVM(BinaryFVT):
"""Perform SVC on a simulated quantum computer.
This test can also be run on a real computer by providing a qAccountToken
To do so, you need to use your own token, by registering on:
https://quantum-computing.ibm.com/
Note that the "real quantum version" of this test may also take some time.
"""
# We will use a quantum simulator on the local machine
q = QuanticSVM(quantum=True, verbose=False)
# We need to have different values for target and non-target in our samples
# or vector machine will not converge
# To achieve testing in a reasonnable amount of time,
# we will lower the size of the feature and the number of trials
n_samples, n_features, n_classes = 10, 4, 2
class_len = n_samples // n_classes # balanced set
samples, labels = get_dataset(n_samples, n_features, n_classes,
random=False)

q.fit(samples, labels)
prediction = q.predict(samples)
# In this case, using SVM, predicting accuracy should be 100%
assert prediction[:class_len].all() == q.classes_[0]
assert prediction[class_len:].all() == q.classes_[1]


def test_quantic_vqc_fvt_simulated_quantum(get_dataset):
def get_params(self):
quantum_instance = QuanticSVM(quantum=True, verbose=False)
return 10, 4, quantum_instance, False

def check(self):
assert self.prediction[:self.class_len].all() == \
self.quantum_instance.classes_[0]
assert self.prediction[self.class_len:].all() == \
self.quantum_instance.classes_[1]


class TestQuanticVQC(BinaryFVT):
"""Perform VQC on a simulated quantum computer"""
# We will use a quantum simulator on the local machine
# quantum parameter for VQC is always true
q = QuanticVQC(verbose=False)
# To achieve testing in a reasonnable amount of time,
# we will lower the size of the feature and the number of trials
n_samples, n_features, n_classes = 4, 4, 2
samples, labels = get_dataset(n_samples, n_features, n_classes)

q.fit(samples, labels)
prediction = q.predict(samples)
# Considering the inputs, this probably make no sense to test accuracy.
# Instead, we could consider this test as a canary test
assert len(prediction) == len(labels)
def get_params(self):
quantum_instance = QuanticVQC(verbose=False)
# To achieve testing in a reasonnable amount of time,
# we will lower the size of the feature and the number of trials
return 4, 4, quantum_instance, True

def check(self):
# Considering the inputs, this probably make no sense to test accuracy.
# Instead, we could consider this test as a canary test
assert len(self.prediction) == len(self.labels)