Skip to content

Commit

Permalink
Refactorize test_classification.py (#19)
Browse files Browse the repository at this point in the history
* refactorize method test_init

* introduce BinFVT

* Refactor all FVT tests

* Factorize FVT and splitclasses test together

* fix pipeline error?

Co-authored-by: gcattan <gregoire.cattan@ibm.com>
  • Loading branch information
gcattan and gcattan authored Jan 13, 2022
1 parent f1fe17e commit 8cd5a42
Showing 1 changed file with 98 additions and 85 deletions.
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)

0 comments on commit 8cd5a42

Please sign in to comment.