From 582bd4ffa1bb40f11e93f28427f4521bf6b23d8e Mon Sep 17 00:00:00 2001
From: dmt <>
Date: Thu, 10 Oct 2019 18:02:32 +0200
Subject: [PATCH] Implement the construction logic for conceptual knowledge
 finding.

---
 cml/domain/construction.py | 112 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 2 deletions(-)

diff --git a/cml/domain/construction.py b/cml/domain/construction.py
index 0f11a2c..b223f01 100644
--- a/cml/domain/construction.py
+++ b/cml/domain/construction.py
@@ -1,9 +1,117 @@
+from functools import partial
 
 
 __all__ = (
-    "Construction"
+    "Constructor",
 )
 
 
+def update_construction(func):
+    def wrapper(self, value):
+        func(self, value)
+        self.construction_type = self.construction_type
+    return wrapper
+
+
 class Constructor:
-    pass
+
+    def __init__(self, ml_models, settings):
+        self.settings = settings
+        self.ml_models = ml_models
+        self._construction = None
+        self._construction_type = "conceptual"
+
+    def construct(self, learnblock):
+        for block in self._construction(learnblock):
+            yield block
+
+    @property
+    def max_target_error(self):
+        return self.settings.max_target_error
+
+    @max_target_error.setter
+    @update_construction
+    def max_target_error(self, value):
+        self.settings.max_target_error = value
+
+    @property
+    def max_model_targets(self):
+        return self.settings.max_model_targets
+
+    @max_model_targets.setter
+    @update_construction
+    def max_model_targets(self, value):
+        self.settings.max_model_targets = value
+
+    @property
+    def min_category_size(self):
+        return self.settings.min_category_size
+
+    @min_category_size.setter
+    @update_construction
+    def min_category_size(self, value):
+        self.settings.min_category_size = value
+
+    @property
+    def max_categories(self):
+        return self.settings.max_categories
+
+    @max_categories.setter
+    def max_categories(self, value):
+        self.settings.max_categories = value
+        self.construction_type = self.construction_type
+
+    @property
+    def construction_type(self):
+        return self._construction_type
+
+    @construction_type.setter
+    def construction_type(self, construct_type):
+        if construct_type == "conceptual":
+            self._construction_type = construct_type
+            self._construction = partial(
+                self._construct_conceptual_knowledge,
+                categorial_complexity=self.settings.max_categories,
+                min_category_size=self.settings.min_category_size,
+            )
+
+        elif construct_type == "procedural":
+            self._construction_type = construct_type
+            self._construction = partial(
+                self._construct_procedural_knowledge,
+                procedural_complexity=self.settings.max_model_targets,
+                max_target_error=self.settings.max_target_error
+            )
+
+        else:
+            # TODO (dmt): Provide proper exception handling.
+            raise Exception("Provide valid construction type.")
+
+    def _construct_conceptual_knowledge(self,
+                                        learnblock,
+                                        categorial_complexity=None,
+                                        min_category_size=None):
+        for ml_model in self.ml_models:
+            for cluster_number in range(2, categorial_complexity):
+                ml_model.cluster = cluster_number
+                trained_model = ml_model.train(learnblock)
+                for cluster, size in trained_model.cluster_sizes.items():
+                    print(cluster, size)
+                    if size < min_category_size:
+                        continue
+                    labels = trained_model.get_labels()
+                    labeld_learnblock = learnblock.set_labels(labels)
+                    yield labeld_learnblock
+
+    def _construct_procedural_knowledge(self,
+                                        learnblock,
+                                        procedural_complexity=None,
+                                        max_target_error=None):
+        for ml_model in self.ml_models:
+            for target_number in range(2, procedural_complexity):
+                ml_model.target_number = target_number
+                trained_model = ml_model.train(learnblock)
+                if trained_model.target_error < max_target_error:
+                    labeld_learnblock = learnblock.set_labels(trained_model)
+                    yield labeld_learnblock
+
-- 
GitLab