<commit_before># -*- coding: utf-8 -*-

from typing import Union, Tuple, Optional, Callable
from json import encoder, dumps
from textwrap import indent
from copy import deepcopy
from logging import DEBUG

from sklearn.ensemble.weight_boosting import AdaBoostClassifier \
    as AdaBoostClassifierClass
from sklearn.tree import DecisionTreeClassifier

from sklearn_porter.estimator.EstimatorApiABC import EstimatorApiABC
from sklearn_porter.estimator.EstimatorBase import EstimatorBase
from sklearn_porter.enums import Method, Language, Template
from sklearn_porter.exceptions import NotSupportedYetError, \
    NotFittedEstimatorError
from sklearn_porter.utils import get_logger


L = get_logger(__name__)


class AdaBoostClassifier(EstimatorBase, EstimatorApiABC):
    """Extract model data and port an AdaBoostClassifier classifier."""

    DEFAULT_LANGUAGE = Language.JAVA
    DEFAULT_METHOD = Method.PREDICT
    DEFAULT_TEMPLATE = Template.COMBINED

    SUPPORT = {
        Language.C: {Method.PREDICT: {Template.COMBINED, }},
        Language.JAVA: {Method.PREDICT: {Template.COMBINED, Template.EXPORTED}},
        Language.JS: {Method.PREDICT: {Template.COMBINED, Template.EXPORTED}},
    }

    estimator = None  # type: AdaBoostClassifierClass

    def __init__(self, estimator: AdaBoostClassifierClass):
        super().__init__(estimator)
        L.info('Create specific estimator `%s`.', self.estimator_name)
        est = self.estimator  # alias

        # Check the used algorithm type:
        if est.algorithm != 'SAMME.R':
            msg = 'The used algorithm `{}` is not supported yet.'
            msg = msg.format(est.algorithm)
            raise NotSupportedYetError(msg)

        # Check type of base estimators:
        if not isinstance(est.base_estimator, DecisionTreeClassifier):
            msg = 'The used base estimator `{}` is not supported yet.'
            msg = msg.format(est.base_estimator.__class__.__qualname__)
            raise NotSupportedYetError(msg)

        # Check number of base estimators:
        if not estimator.n_estimators > 0:
            raise NotFittedEstimatorError(self.estimator_name)

        # Ignore estimators with zero weight:
        estimators = []
        for idx in range(est.n_estimators):
            if est.estimator_weights_[idx] > 0:
                estimators.append(est.estimators_[idx])
        n_estimators = len(estimators)

        self.meta_info = dict(
            n_classes=est.n_classes_,
            n_features=est.estimators_[0].n_features_,
            n_estimators=n_estimators,
        )
        L.info('Meta info (keys): {}'.format(
            self.meta_info.keys()))<commit_msg>feature/oop-api-refactoring: Fix base estimator validation<commit_after># -*- coding: utf-8 -*-

from typing import Union, Tuple, Optional, Callable
from json import encoder, dumps
from textwrap import indent
from copy import deepcopy
from logging import DEBUG

from sklearn.ensemble.weight_boosting import AdaBoostClassifier \
    as AdaBoostClassifierClass
from sklearn.tree import DecisionTreeClassifier

from sklearn_porter.estimator.EstimatorApiABC import EstimatorApiABC
from sklearn_porter.estimator.EstimatorBase import EstimatorBase
from sklearn_porter.enums import Method, Language, Template
from sklearn_porter.exceptions import NotSupportedYetError, \
    NotFittedEstimatorError
from sklearn_porter.utils import get_logger


L = get_logger(__name__)


class AdaBoostClassifier(EstimatorBase, EstimatorApiABC):
    """Extract model data and port an AdaBoostClassifier classifier."""

    DEFAULT_LANGUAGE = Language.JAVA
    DEFAULT_METHOD = Method.PREDICT
    DEFAULT_TEMPLATE = Template.COMBINED

    SUPPORT = {
        Language.C: {Method.PREDICT: {Template.COMBINED, }},
        Language.JAVA: {Method.PREDICT: {Template.COMBINED, Template.EXPORTED}},
        Language.JS: {Method.PREDICT: {Template.COMBINED, Template.EXPORTED}},
    }

    estimator = None  # type: AdaBoostClassifierClass

    def __init__(self, estimator: AdaBoostClassifierClass):
        super().__init__(estimator)
        L.info('Create specific estimator `%s`.', self.estimator_name)
        est = self.estimator  # alias

        # Check the used algorithm type:
        if est.algorithm != 'SAMME.R':
            msg = 'The used algorithm `{}` is not supported yet.'
            msg = msg.format(est.algorithm)
            raise NotSupportedYetError(msg)

        # Check type of base estimators:
        if not isinstance(est.base_estimator_, DecisionTreeClassifier):
            msg = 'The used base estimator `{}` is not supported yet.'
            msg = msg.format(est.base_estimator.__class__.__qualname__)
            raise NotSupportedYetError(msg)

        # Check number of base estimators:
        if not estimator.n_estimators > 0:
            raise NotFittedEstimatorError(self.estimator_name)

        # Ignore estimators with zero weight:
        estimators = []
        for idx in range(est.n_estimators):
            if est.estimator_weights_[idx] > 0:
                estimators.append(est.estimators_[idx])
        n_estimators = len(estimators)

        self.meta_info = dict(
            n_classes=est.n_classes_,
            n_features=est.estimators_[0].n_features_,
            n_estimators=n_estimators,
        )
        L.info('Meta info (keys): {}'.format(
            self.meta_info.keys()))
{'fraction_non_alphanumeric': 0.08509847640282422, 'fraction_numerical': 0.0014864362690449647, 'mean_word_length': 3.1028963414634148, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6812446', 'n_tokens_mistral': 1649, 'n_tokens_neox': 1549, 'n_words': 377}