Skip to content

Commit

Permalink
Merge branch 'main' into update-readme
Browse files Browse the repository at this point in the history
  • Loading branch information
gcattan authored Nov 10, 2023
2 parents 208e5bd + f158e10 commit 5cb30bd
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 87 deletions.
3 changes: 3 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ sphinx:
python:
install:
- requirements: doc/requirements.txt
# Install our python package before building the docs
- method: pip
path: .
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ RUN apt-get -y install build-essential

RUN pip install urllib3==1.26.12
RUN pip install "numpy<1.24"
RUN pip install qiskit-terra==0.25.2.1
RUN pip install qiskit-terra==0.45.0
RUN python setup.py develop
RUN pip install .[docs]
RUN pip install .[tests]
Expand All @@ -24,10 +24,10 @@ RUN mkdir /root/mne_data
RUN mkdir /home/mne_data

## Workaround for firestore
RUN pip install protobuf==4.24.4
RUN pip install protobuf==4.25.0
RUN pip install google_cloud_firestore==2.13.1
### Missing __init__ file in protobuf
RUN touch /usr/local/lib/python3.9/site-packages/protobuf-4.24.4-py3.9.egg/google/__init__.py
RUN touch /usr/local/lib/python3.9/site-packages/protobuf-4.25.0-py3.9-linux-x86_64.egg/google/__init__.py
## google.cloud.location is never used in these files, and is missing in path.
RUN sed -i 's/from google.cloud.location import locations_pb2//g' '/usr/local/lib/python3.9/site-packages/google_cloud_firestore-2.13.1-py3.9.egg/google/cloud/firestore_v1/services/firestore/client.py'
RUN sed -i 's/from google.cloud.location import locations_pb2//g' '/usr/local/lib/python3.9/site-packages/google_cloud_firestore-2.13.1-py3.9.egg/google/cloud/firestore_v1/services/firestore/transports/base.py'
Expand Down
12 changes: 6 additions & 6 deletions doc/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
numpy<1.24
numpy<1.27
sphinx-gallery
sphinx-bootstrap_theme
numpydoc
cython
mne[data]>=0.24
seaborn
seaborn>=0.12.1
scikit-learn
joblib
pandas
cvxpy==1.3.2
cvxpy==1.4.1
qiskit_machine_learning==0.6.1
qiskit-ibm-provider==0.7.0
qiskit-ibm-provider==0.7.2
qiskit-optimization==0.5.0
qiskit-aer==0.12.2
qiskit-aer==0.13.0
scipy==1.11.3
moabb>=0.4.6
moabb>=1.0.0
pyriemann==0.5
docplex>=2.21.207
firebase_admin==6.2.0
4 changes: 4 additions & 0 deletions ecosystem.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"dependencies_files": ["requirements.txt"],
"extra_dependencies": ["pytest", "seaborn", "flake8", "mne", "pooch"]
}
58 changes: 32 additions & 26 deletions pyriemann_qiskit/classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,34 @@
in several modes quantum/classical and simulated/real
quantum computer.
"""
import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.svm import SVC
from qiskit_ibm_provider import IBMProvider, least_busy
from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit.utils.quantum_instance import logger
from qiskit_machine_learning.algorithms import QSVC, VQC, PegasosQSVC
from qiskit_machine_learning.kernels.quantum_kernel import QuantumKernel
from datetime import datetime
import logging
from .utils.hyper_params_factory import gen_zz_feature_map, gen_two_local, get_spsa
from .utils import get_provider, get_devices, get_simulator
import numpy as np

from pyriemann.classification import MDM
from pyriemann_qiskit.datasets import get_feature_dimension
from pyriemann_qiskit.utils import (
ClassicalOptimizer,
NaiveQAOAOptimizer,
set_global_optimizer,
)
from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit.utils.quantum_instance import logger
from qiskit_ibm_provider import IBMProvider, least_busy
from qiskit_machine_learning.algorithms import QSVC, VQC, PegasosQSVC
from qiskit_machine_learning.kernels.quantum_kernel import QuantumKernel
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.svm import SVC

from .utils.hyper_params_factory import gen_zz_feature_map, gen_two_local, get_spsa
from .utils import get_provider, get_devices, get_simulator

logger.level = logging.INFO


class QuanticClassifierBase(BaseEstimator, ClassifierMixin):

"""Quantum classification.
"""Quantum classifier
This class implements a scikit-learn wrapper around Qiskit library [1]_.
It provides a mean to run classification tasks on a local and
Expand All @@ -49,12 +51,12 @@ class QuanticClassifierBase(BaseEstimator, ClassifierMixin):
(depending on q_account_token value),
- If false, will perform classical computing instead.
q_account_token : string (default:None)
If quantum==True and q_account_token provided,
If `quantum` is True and `q_account_token` provided,
the classification task will be running on a IBM quantum backend.
If `load_account` is provided, the classifier will use the previous
token saved with `IBMProvider.save_account()`.
verbose : bool (default:True)
If true will output all intermediate results and logs.
If true, will output all intermediate results and logs.
shots : int (default:1024)
Number of repetitions of each circuit, for sampling.
gen_feature_map : Callable[int, QuantumCircuit | FeatureMap] \
Expand All @@ -76,6 +78,7 @@ class QuanticClassifierBase(BaseEstimator, ClassifierMixin):
--------
QuanticSVM
QuanticVQC
QuanticMDM
References
----------
Expand Down Expand Up @@ -234,9 +237,10 @@ def _predict(self, X):

class QuanticSVM(QuanticClassifierBase):

"""Quantum-enhanced SVM classification.
"""Quantum-enhanced SVM classifier
This class implements SVC [1]_ on a quantum machine [2]_.
This class implements a support-vector machine (SVM) classifier [1]_,
called SVC, on a quantum machine [2]_.
Note that if `quantum` parameter is set to `False`
then a classical SVC will be perfomed instead.
Expand Down Expand Up @@ -270,12 +274,12 @@ class QuanticSVM(QuanticClassifierBase):
(depending on q_account_token value),
- If false, will perform classical computing instead.
q_account_token : string (default:None)
If quantum==True and q_account_token provided,
If `quantum` is True and `q_account_token` provided,
the classification task will be running on a IBM quantum backend.
If `load_account` is provided, the classifier will use the previous
token saved with `IBMProvider.save_account()`.
verbose : bool (default:True)
If true will output all intermediate results and logs.
If true, will output all intermediate results and logs.
shots : int (default:1024)
Number of repetitions of each circuit, for sampling.
gen_feature_map : Callable[int, QuantumCircuit | FeatureMap] \
Expand Down Expand Up @@ -401,8 +405,9 @@ def predict(self, X):

class QuanticVQC(QuanticClassifierBase):

"""Variational Quantum Classifier
"""Variational quantum classifier
This class implements a variational quantum classifier (VQC).
Note that there is no classical version of this algorithm.
This will always run on a quantum computer (simulated or not).
Expand All @@ -419,12 +424,12 @@ class QuanticVQC(QuanticClassifierBase):
(depending on q_account_token value).
- If false, will perform classical computing instead.
q_account_token : string (default:None)
If quantum==True and q_account_token provided,
If `quantum` is True and `q_account_token` provided,
the classification task will be running on a IBM quantum backend.
If `load_account` is provided, the classifier will use the previous
token saved with `IBMProvider.save_account()`.
verbose : bool (default:True)
If true will output all intermediate results and logs
If true, will output all intermediate results and logs
shots : int (default:1024)
Number of repetitions of each circuit, for sampling
gen_feature_map : Callable[int, QuantumCircuit | FeatureMap] \
Expand Down Expand Up @@ -552,11 +557,11 @@ def parameter_count(self):

class QuanticMDM(QuanticClassifierBase):

"""Quantum-enhanced MDM
"""Quantum-enhanced MDM classifier
This class is a convex implementation of the MDM [1]_,
that can runs with quantum optimization.
Only log-euclidian distance between trial and class prototypes is supported
This class is a convex implementation of the Minimum Distance to Mean (MDM)
[1]_, which can run with quantum optimization.
Only log-Euclidean distance between trial and class prototypes is supported
at the moment, but any type of metric can be used for centroid estimation.
Notes
Expand All @@ -577,16 +582,17 @@ class QuanticMDM(QuanticClassifierBase):
distance in order to keep the good sensitivity for the classification.
quantum : bool (default: True)
Only applies if `metric` contains a convex distance or mean.
- If true will run on local or remote backend
(depending on q_account_token value),
- If false, will perform classical computing instead.
q_account_token : string (default:None)
If quantum==True and q_account_token provided,
If `quantum` is True and `q_account_token` provided,
the classification task will be running on a IBM quantum backend.
If `load_account` is provided, the classifier will use the previous
token saved with `IBMProvider.save_account()`.
verbose : bool (default:True)
If true will output all intermediate results and logs.
If true, will output all intermediate results and logs.
shots : int (default:1024)
Number of repetitions of each circuit, for sampling.
gen_feature_map : Callable[int, QuantumCircuit | FeatureMap] \
Expand Down
26 changes: 9 additions & 17 deletions pyriemann_qiskit/datasets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@


def get_mne_sample(n_trials=10, include_auditory=False):
"""Return sample data from the mne dataset.
"""Return sample data from the MNE dataset.
```
``
In this experiment, checkerboard patterns were presented to the subject
into the left and right visual field, interspersed by tones to the
left or right ear. The interval between the stimuli was 750 ms.
Occasionally a smiley face was presented at the center of the visual field.
The subject was asked to press a key with the right index finger
as soon as possible after the appearance of the face.
``` [1]_
`` [1]_
The samples returned by this method are epochs of duration 1s.
Only visual left and right trials are selected.
Expand All @@ -35,8 +35,7 @@ def get_mne_sample(n_trials=10, include_auditory=False):
Number of trials to return.
If -1, then all trials are returned.
include_auditory : boolean (default:False)
If True, it returns also the auditory stimulation
in the MNE dataset.
If True, it returns also the auditory stimulation in the MNE dataset.
Returns
-------
Expand Down Expand Up @@ -236,19 +235,12 @@ class MockDataset:
Attributes
----------
code_ : str
The code of the dataset.
The code of the dataset is also the string representation
The code of the dataset, which is also the string representation
of the dataset.
data_ : Dict
A dictionnary representing the dataset. Ex:
```
{
subject1: (samples1, labels1),
subject2: (samples2, labels2),
...
}
```
subjects_ : List[int]
data_ : dict
A dictionnary representing the dataset, e.g.:
``{subject1: (samples1, labels1), subject2: (samples2, labels2), ...}``
subjects_ : list[int]
The subjects of the dataset.
Notes
Expand Down
13 changes: 7 additions & 6 deletions pyriemann_qiskit/pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def _log(self, trace):
print("[" + self.code + "] ", trace)

def fit(self, X, y):
"""Train the riemann quantum classifier.
"""Train the Riemannian quantum classifier.
Parameters
----------
Expand All @@ -70,6 +70,7 @@ def fit(self, X, y):

def score(self, X, y):
"""Return the accuracy.
You might want to use a different metric by using sklearn
cross_val_score
Expand Down Expand Up @@ -139,7 +140,7 @@ def transform(self, X):

class QuantumClassifierWithDefaultRiemannianPipeline(BasePipeline):

"""Default pipeline with Riemann Geometry and a quantum classifier.
"""Default pipeline with Riemannian geometry and a quantum classifier.
Projects the data into the tangent space of the Riemannian manifold
and applies quantum classification.
Expand Down Expand Up @@ -310,12 +311,12 @@ class QuantumMDMWithRiemannianPipeline(BasePipeline):
(depending on q_account_token value),
- If false, will perform classical computing instead.
q_account_token : string (default:None)
If quantum==True and q_account_token provided,
If `quantum` is True and `q_account_token` provided,
the classification task will be running on a IBM quantum backend.
If `load_account` is provided, the classifier will use the previous
token saved with `IBMProvider.save_account()`.
verbose : bool (default:True)
If true will output all intermediate results and logs.
If true, will output all intermediate results and logs.
shots : int (default:1024)
Number of repetitions of each circuit, for sampling.
gen_feature_map : Callable[int, QuantumCircuit | FeatureMap] \
Expand Down Expand Up @@ -405,12 +406,12 @@ class QuantumMDMVotingClassifier(BasePipeline):
(depending on q_account_token value),
- If false, will perform classical computing instead.
q_account_token : string (default:None)
If quantum==True and q_account_token provided,
If `quantum` is True and `q_account_token` provided,
the classification task will be running on a IBM quantum backend.
If `load_account` is provided, the classifier will use the previous
token saved with `IBMProvider.save_account()`.
verbose : bool (default:True)
If true will output all intermediate results and logs.
If true, will output all intermediate results and logs.
shots : int (default:1024)
Number of repetitions of each circuit, for sampling.
gen_feature_map : Callable[int, QuantumCircuit | FeatureMap] \
Expand Down
Loading

0 comments on commit 5cb30bd

Please sign in to comment.