# Path: wallace/predictive_models/sklearn_model.py
# class SklearnModel(PredictiveModel):
#     def get_dependent_variable_data(self, dataset):
#         return dataset.get_filtered_column(self.dependent_variable)
# 
#     def get_independent_variable_data(self, dataset):
#         filtered_matrix = dataset.get_filtered_matrix(self.independent_variables)
#         filtered_data_types = dataset.get_filtered_data_types(self.independent_variables)
#         categorical_features, category_value_mapping, num_category_values = self.get_categorical_features(filtered_data_types)
# 
#         variable_encoder = CategoricalVariableEncoder()
#         filtered_matrix = variable_encoder.convert_categorical_variables(filtered_matrix, categorical_features, category_value_mapping)
# 
#         encoder = preprocessing.OneHotEncoder(categorical_features=categorical_features, n_values=num_category_values)
#         data_result = encoder.fit_transform(filtered_matrix)
# 
#         # Take care of sparse and non-sparse matrices. If we have any categorical
#         # variables, then it is likely we will get back a sparse matrix and will
#         # need to convert it into an array.
#         try:
#             return data_result.toarray()
#         except AttributeError:
#             return data_result
# 
#     def get_categorical_features(self, filtered_data_types):
#         categorical_features = []
#         category_value_mapping = {}
#         num_category_values = []
#         for i in xrange(len(filtered_data_types)):
#             data_type = filtered_data_types[i]
#             if data_type.is_equal("string") or data_type.is_equal("boolean"):
#                 categorical_features.append(i)
#                 category_value_mapping[i] = CategoricalVariableEncoder.create_value_map(data_type.categories)
#                 num_category_values.append(len(category_value_mapping[i]))
#         return categorical_features, category_value_mapping, num_category_values
# 
# class TrainedSklearnModel(TrainedPredictiveModel):
#     def __init__(self, predictive_model, fitted_regression):
#         TrainedPredictiveModel.__init__(self, predictive_model)
#         self.fitted_regression = fitted_regression
# 
#     def predict(self, dataset):
#         independent_data = self.predictive_model.get_independent_variable_data(dataset)
#         return self.fitted_regression.predict(independent_data)
# 
# Path: wallace/parameters.py
# class ParametersGeneralValidityCheck(ParametersValidityCheck):
#     def __init__(self, parameters=None):
#         if parameters == None:
#             self.parameters = {}
#         else:
#             self.parameters = parameters
# 
#     def set_range_parameter(self, parameter_name, lower_bound, upper_bound):
#         self.parameters[parameter_name] = RangeParameter(lower_bound, upper_bound)
# 
#     def set_integer_range_parameter(self, parameter_name, lower_bound, upper_bound):
#         self.parameters[parameter_name] = IntegerRangeParameter(lower_bound, upper_bound)
# 
#     def set_category_parameter(self, parameter_name, categories, weights=None):
#         self.parameters[parameter_name] = CategoryParameter(categories, weights)
# 
#     def set_parameter(self, parameter_name, parameter):
#         if isinstance(parameter, BasicParameter):
#             self.parameters[parameter_name] = parameter
#         else:
#             raise TypeError("Parameters must be subclasses of BasicParameter.")
# 
#     def list_parameter_names(self):
#         return self.parameters.keys()
# 
#     def get_parameter_type(self, parameter_name):
#         self._check_parameter_existence(parameter_name)
#         return self.parameters[parameter_name].__class__.__name__
# 
#     def check_validity(self, parameter_name, value):
#         self._check_parameter_existence(parameter_name)
#         return self.parameters[parameter_name].check_validity(value)
# 
#     def merge(self, validity_check):
#         self.parameters.update(validity_check.parameters)
# 
#     def get_valid_value(self, parameter_name):
#         self._check_parameter_existence(parameter_name)
#         return self.parameters[parameter_name].get_valid_value()
# 
#     def _check_parameter_existence(self, parameter_name):
#         if parameter_name not in self.parameters:
#             raise ValueError("Parameter '%s' does not have a validity check defined." % parameter_name)


from sklearn import linear_model
from wallace.predictive_models.sklearn_model import SklearnModel, TrainedSklearnModel
from wallace.parameters import ParametersGeneralValidityCheck

class BayesianRidgeRegression(SklearnModel):
    def train(self, dataset):
        model = linear_model.BayesianRidge(
                n_iter=self.get_number_iterations(),
                alpha_1=self.get_alpha_1(),
                alpha_2=self.get_alpha_2(),
                lambda_1=self.get_lambda_1(),
                lambda_2=self.get_lambda_2()
                )
        independent_data = self.get_independent_variable_data(dataset)
        dependent_data = self.get_dependent_variable_data(dataset)
        trained_regression = model.fit(independent_data, dependent_data)

        return TrainedSklearnModel(self, trained_regression)

    @classmethod
    def validity_check(klass):
        validity_check = ParametersGeneralValidityCheck()
        validity_check.set_range_parameter("bayesian_ridge_regression.alpha_1", 0.0, 0.001)
        validity_check.set_range_parameter("bayesian_ridge_regression.alpha_2", 0.0, 0.001)
        validity_check.set_range_parameter("bayesian_ridge_regression.lambda_1", 0.0, 0.001)
        validity_check.set_range_parameter("bayesian_ridge_regression.lambda_2", 0.0, 0.001)
        validity_check.set_integer_range_parameter("bayesian_ridge_regression.number_iterations", 10, 1000)
        return validity_check

    def get_alpha_1(self):
        return self.parameter_set.get("bayesian_ridge_regression.alpha_1")

    def get_alpha_2(self):

# Path: wallace/predictive_models/sklearn_model.py
# class SklearnModel(PredictiveModel):
#     def get_dependent_variable_data(self, dataset):
#         return dataset.get_filtered_column(self.dependent_variable)
# 
#     def get_independent_variable_data(self, dataset):
#         filtered_matrix = dataset.get_filtered_matrix(self.independent_variables)
#         filtered_data_types = dataset.get_filtered_data_types(self.independent_variables)
#         categorical_features, category_value_mapping, num_category_values = self.get_categorical_features(filtered_data_types)
# 
#         variable_encoder = CategoricalVariableEncoder()
#         filtered_matrix = variable_encoder.convert_categorical_variables(filtered_matrix, categorical_features, category_value_mapping)
# 
#         encoder = preprocessing.OneHotEncoder(categorical_features=categorical_features, n_values=num_category_values)
#         data_result = encoder.fit_transform(filtered_matrix)
# 
#         # Take care of sparse and non-sparse matrices. If we have any categorical
#         # variables, then it is likely we will get back a sparse matrix and will
#         # need to convert it into an array.
#         try:
#             return data_result.toarray()
#         except AttributeError:
#             return data_result
# 
#     def get_categorical_features(self, filtered_data_types):
#         categorical_features = []
#         category_value_mapping = {}
#         num_category_values = []
#         for i in xrange(len(filtered_data_types)):
#             data_type = filtered_data_types[i]
#             if data_type.is_equal("string") or data_type.is_equal("boolean"):
#                 categorical_features.append(i)
#                 category_value_mapping[i] = CategoricalVariableEncoder.create_value_map(data_type.categories)
#                 num_category_values.append(len(category_value_mapping[i]))
#         return categorical_features, category_value_mapping, num_category_values
# 
# class TrainedSklearnModel(TrainedPredictiveModel):
#     def __init__(self, predictive_model, fitted_regression):
#         TrainedPredictiveModel.__init__(self, predictive_model)
#         self.fitted_regression = fitted_regression
# 
#     def predict(self, dataset):
#         independent_data = self.predictive_model.get_independent_variable_data(dataset)
#         return self.fitted_regression.predict(independent_data)
# 
# Path: wallace/parameters.py
# class ParametersGeneralValidityCheck(ParametersValidityCheck):
#     def __init__(self, parameters=None):
#         if parameters == None:
#             self.parameters = {}
#         else:
#             self.parameters = parameters
# 
#     def set_range_parameter(self, parameter_name, lower_bound, upper_bound):
#         self.parameters[parameter_name] = RangeParameter(lower_bound, upper_bound)
# 
#     def set_integer_range_parameter(self, parameter_name, lower_bound, upper_bound):
#         self.parameters[parameter_name] = IntegerRangeParameter(lower_bound, upper_bound)
# 
#     def set_category_parameter(self, parameter_name, categories, weights=None):
#         self.parameters[parameter_name] = CategoryParameter(categories, weights)
# 
#     def set_parameter(self, parameter_name, parameter):
#         if isinstance(parameter, BasicParameter):
#             self.parameters[parameter_name] = parameter
#         else:
#             raise TypeError("Parameters must be subclasses of BasicParameter.")
# 
#     def list_parameter_names(self):
#         return self.parameters.keys()
# 
#     def get_parameter_type(self, parameter_name):
#         self._check_parameter_existence(parameter_name)
#         return self.parameters[parameter_name].__class__.__name__
# 
#     def check_validity(self, parameter_name, value):
#         self._check_parameter_existence(parameter_name)
#         return self.parameters[parameter_name].check_validity(value)
# 
#     def merge(self, validity_check):
#         self.parameters.update(validity_check.parameters)
# 
#     def get_valid_value(self, parameter_name):
#         self._check_parameter_existence(parameter_name)
#         return self.parameters[parameter_name].get_valid_value()
# 
#     def _check_parameter_existence(self, parameter_name):
#         if parameter_name not in self.parameters:
#             raise ValueError("Parameter '%s' does not have a validity check defined." % parameter_name)


# Path: wallace/predictive_models/bayesian_ridge_regression.py
from sklearn import linear_model
from wallace.predictive_models.sklearn_model import SklearnModel, TrainedSklearnModel
from wallace.parameters import ParametersGeneralValidityCheck


class BayesianRidgeRegression(SklearnModel):
    def train(self, dataset):
        model = linear_model.BayesianRidge(
                n_iter=self.get_number_iterations(),
                alpha_1=self.get_alpha_1(),
                alpha_2=self.get_alpha_2(),
                lambda_1=self.get_lambda_1(),
                lambda_2=self.get_lambda_2()
                )
        independent_data = self.get_independent_variable_data(dataset)
        dependent_data = self.get_dependent_variable_data(dataset)
        trained_regression = model.fit(independent_data, dependent_data)

        return TrainedSklearnModel(self, trained_regression)

    @classmethod
    def validity_check(klass):
        validity_check = ParametersGeneralValidityCheck()
        validity_check.set_range_parameter("bayesian_ridge_regression.alpha_1", 0.0, 0.001)
        validity_check.set_range_parameter("bayesian_ridge_regression.alpha_2", 0.0, 0.001)
        validity_check.set_range_parameter("bayesian_ridge_regression.lambda_1", 0.0, 0.001)
        validity_check.set_range_parameter("bayesian_ridge_regression.lambda_2", 0.0, 0.001)
        validity_check.set_integer_range_parameter("bayesian_ridge_regression.number_iterations", 10, 1000)
        return validity_check

    def get_alpha_1(self):
        return self.parameter_set.get("bayesian_ridge_regression.alpha_1")

    def get_alpha_2(self):

        return self.parameter_set.get("bayesian_ridge_regression.alpha_2")