QML (High-Level Interface)
|
|
+-----------------+-----------------+
| | |
QuantumModel QuantumProvider HardwareSpec
| | |
+-------+-------+ +------+------+ Hardware Config
| | | | |
QSVM QNN ... Qiskit Future
Provider Providers
from nedc_qml_tools import QML
import numpy as np
# create training data
#
X_train = np.array([[0,0], [0,1], [1,0], [1,1]])
y_train = np.array([0, 1, 1, 0])
# initialize QML with QSVM and Qiskit
#
qml = QML(
model_name='qsvm',
provider_name='qiskit',
encoder_name='zz',
kernel_name='fidelity',
n_qubits=2,
featuremap_reps=2
)
# train and predict
#
trained_model = qml.fit(X_train, y_train)
predictions = qml.predict(X_train)
>> [0, 1, 1, 0]
error_rate, prections = qml.score(X_train, X_train)
>> 0.00, [0, 1, 1, 0]
- Add constant in nedc_qml_tools_constants.py ENCODER_NAME_NEW = 'new'
2a) Add abstract method in nedc_qml_base_providers_tools.py
@abstractmethod
def get_new_encoder(self):
raise NotImplementedError
2b) Update ENCODER_COMPUTERS dictionary:
ENCODER_COMPUTERS = {
QISKIT: {
ZZ: "get_zz_encoder",
Z: "get_z_encoder",
NEW: "get_new_encoder"
}
}
Follow similar pattern for adding a new kernel, ansatz or optimizer:
Kernel functions (KERNEL_COMPUTERS)
Ansatz circuits (ANSATZ_COMPUTERS)
Optimizers (OPTIM_COMPUTERS)
Hardware backends (HARDWARE_SPECS)
- Implement concrete method in nedc_qml_providers_tools.py
Assuming we are adding a Qiskit encoder/featuremap, so adding the concrete implementation in QiskitProvider class.
def get_new_encoder(self):
"""
method: get_new_encoder
arguments:
none
return:
ZZFeatureMap: Qiskit New circuit
description:
creates a New feature map encoder with specified parameters
"""
if dbgl == ndt.FULL:
print("Creating new encoder")
return NewEncoder()
- Run
make install
cd tests
1) Add a new test for the newly added module in test_nedc_qml_tools.py
2) run_tests.sh
- Add constant in nedc_qml_tools_constants.py MODEL_NAME_NEW = 'new'
2a) Add the new quantum model in nedc_qml_tools.py
class NEW(nbpt.QuantumModel):
"""
Description of the NEW model
"""
def __init__(self):
"""
method: constructor
arguments: none
return: none
description: initializes New
"""
if dbgl == ndt.FULL:
print("%s (line: %s) %s: initializing NEW" %
(__FILE__, ndt.__LINE__, ndt.__NAME__))
# call the constructor of the parent class which is QuantumModel
#
super().__init__()
# end of constructor
#
def __repr__(self) -> str:
"""
method: __repr__
arguments: none
return: str
description: returns string representation of NEW instance
"""
return f"{self.__class__.__name__}(provider={self.provider.__class__.__name__ if self.provider else None})"
def fit(self, X, y=None):
"""
method: fit
arguments:
X: training data features
y: training data labels
return: none
description: trains NEW model
"""
if dbgl == ndt.FULL:
print("%s (line: %s) %s: computing kernel and fitting NEW" %
(__FILE__, ndt.__LINE__, ndt.__NAME__))
# exit gracefully
#
def predict(self, X, y=None):
"""
method: predict
arguments:
X: test data features
y: test data labels
return: predictions
description: predicts labels using NEW
"""
if dbgl == ndt.FULL:
print("%s (line: %s) %s: predicting labels using NEW" %
(__FILE__, ndt.__LINE__, ndt.__NAME__))
# exit gracefully: return the predicted labels
#
return predictions
#
# end of NEW
2b) Register the new model at the bottom of the file Registry.register_model(const.MODEL_NAME_NEW, NEW)
- Run
make install
-
Add constant in nedc_qml_tools_constants.py PROVIDER_NAME_NEW = 'new'
-
Add the new quantum provider class and necessary methods in nedc_qml_providers_tools.py
class NewProvider(QuantumProvider): """ Description """ def __init__(self, params: QMLParams): """ method: __init__ arguments: params (QMLParams): Parameters for quantum machine learning operations. return: none description: Initializes the QiskitProvider object with the given parameters. """ # call the parent class constructor with the given parameters # super().__init__(params=params) self.params = params # end of constructor # def __repr__(self) -> str: """ method: __repr__ arguments: none return: str description: returns string representation of NewProvider instance """ return f"NewProvider(params={self.params})" #-------------------------------------------------------------------------- # # concrete methods listed here : # #-------------------------------------------------------------------------- def get_basic_simulator(self): # exit gracefully: # return a def method2(self): # exit gracefully: # return b -
Update the HARDWARE_SPECS dictionary with proper simulator function name in nedc_qml_base_providers_tools.py. For example:
HARDWARE_SPECS = {,
NewProvider: {const.HARDWARE_NAME_CPU: "get_basic_simulator"}
}
-
Register the new quantum provider at the bottom of nedc_qml_tools.py file Registry.register_provider(const.PROVIDER_NAME_NEW, nqpt.NewProvider)
-
Run
make install
This tool is developed in part with contributions from Dr. Joseph Picone’s laboratory, the Neural Engineering Data Consortium (NEDC):
https://www.linkedin.com/company/neural-engineering-data-consortium/
Additionally, the IMLD Toolkit uses this project to visualize quantum machine learning algorithms, including QNN, QSVM, and QRBM models. IMLD: https://isip.piconepress.com/projects/imld/resources/app/