diff --git a/force_bdss/mco/base_mco_communicator.py b/force_bdss/mco/base_mco_communicator.py index 308903166cdebdbf8dcee705ff4089fb626e3639..eeb3ee5b9268920ef23d3f3036447fecf16cceb8 100644 --- a/force_bdss/mco/base_mco_communicator.py +++ b/force_bdss/mco/base_mco_communicator.py @@ -1,8 +1,30 @@ import abc -import six +from traits.api import ABCHasStrictTraits, Instance + +from .base_mco_model import BaseMCOModel +from ..bdss_application import BDSSApplication +from .i_multi_criteria_optimizer_bundle import IMultiCriteriaOptimizerBundle + + +class BaseMCOCommunicator(ABCHasStrictTraits): + """Communicator class that defines how the MCO communicates + with the evaluator program that does the actual heavylifting of the + calculation. + + The model assumes that the MCO spawns a process to perform the evaluation, + and passes data to this process that define the parameters for the + evaluation. Once completed, the evaluation will return a set of results, + that we interpret as KPIs. These KPIs are encoded in some form, which is + again specified by the MCO. + """ + #: A reference to the bundle + bundle = Instance(IMultiCriteriaOptimizerBundle) + #: A reference to the application + application = Instance(BDSSApplication) + #: A reference to the model class + model = Instance(BaseMCOModel) -class BaseMCOCommunicator(six.with_metaclass(abc.ABCMeta)): def __init__(self, bundle, application, model): self.bundle = bundle self.application = application @@ -10,8 +32,30 @@ class BaseMCOCommunicator(six.with_metaclass(abc.ABCMeta)): @abc.abstractmethod def receive_from_mco(self): - pass + """ + Receives the parameters from the MCO. + The conversion is specific to the format of the communication + between the MCO and its evaluator program. + + Must return a single DataSourceParameters object, containing + the parameters as passed by the MCO. + + Returns + ------- + DataSourceParameters + An instance of the DataSourceParameters with the appropriate + information filled in. + """ @abc.abstractmethod - def send_to_mco(self): - pass + def send_to_mco(self, kpi_results): + """Send the KPI results from the evaluation to the MCO + Must be reimplemented to perform the conversion between the + two formats. This is of course dependent on the specifics of the + MCO and how it interacts with the external evaluator program. + + Parameters + ---------- + kpi_results: List(KPICalculatorResult) + A list of KPI calculator results, one per each KPI calculator. + """ diff --git a/force_bdss/mco/tests/test_base_mco_communicator.py b/force_bdss/mco/tests/test_base_mco_communicator.py new file mode 100644 index 0000000000000000000000000000000000000000..26f7ea05df6a396c00c2c1e88b497370c8eec1da --- /dev/null +++ b/force_bdss/mco/tests/test_base_mco_communicator.py @@ -0,0 +1,33 @@ +import unittest + +from force_bdss.mco.base_mco_communicator import BaseMCOCommunicator +from force_bdss.mco.base_mco_model import BaseMCOModel +from force_bdss.mco.i_multi_criteria_optimizer_bundle import \ + IMultiCriteriaOptimizerBundle + +try: + import mock +except ImportError: + from unittest import mock + +from force_bdss.bdss_application import BDSSApplication + + +class DummyMCOCommunicator(BaseMCOCommunicator): + def receive_from_mco(self): + pass + + def send_to_mco(self, kpi_results): + pass + + +class TestBaseMCOCommunicator(unittest.TestCase): + def test_initialization(self): + bundle = mock.Mock(spec=IMultiCriteriaOptimizerBundle) + application = mock.Mock(spec=BDSSApplication) + model = mock.Mock(spec=BaseMCOModel) + mcocomm = DummyMCOCommunicator(bundle, application, model) + + self.assertEqual(mcocomm.bundle, bundle) + self.assertEqual(mcocomm.application, application) + self.assertEqual(mcocomm.model, model) diff --git a/force_bdss/mco/tests/test_base_multi_criteria_optimizer.py b/force_bdss/mco/tests/test_base_multi_criteria_optimizer.py index cab26edf81e35a21d5f0fd73d0669f2dea69a0d9..72eb30e33a2c6ad026de38d0f56b83a4d615cf95 100644 --- a/force_bdss/mco/tests/test_base_multi_criteria_optimizer.py +++ b/force_bdss/mco/tests/test_base_multi_criteria_optimizer.py @@ -19,7 +19,7 @@ class DummyMCO(BaseMultiCriteriaOptimizer): pass -class TestBaseKPICalculator(unittest.TestCase): +class TestBaseMultiCriteriaOptimizer(unittest.TestCase): def test_initialization(self): bundle = mock.Mock(spec=IMultiCriteriaOptimizerBundle) application = mock.Mock(spec=BDSSApplication) diff --git a/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py b/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py index de89488eb3ae413fb83236c2582618e43535a40f..55f3e13ff6b57f928f43acf7d000c8fc7484bbb4 100644 --- a/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py +++ b/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py @@ -16,11 +16,11 @@ class DummyMCOBundle(BaseMultiCriteriaOptimizerBundle): def create_model(self, model_data=None): pass - def create_communicator(self, model_data): + def create_communicator(self, application, model): pass -class TestBaseDataSourceBundle(unittest.TestCase): +class TestBaseMCOBundle(unittest.TestCase): def test_initialization(self): bundle = DummyMCOBundle() self.assertEqual(bundle.id, 'foo')