from multiprocessing import cpu_count

import numpy as np

from linora.param_search._HyperParameters import HyperParametersRandom, HyperParametersGrid

__xgboost_version__ = '1.4.0'
__lightgbm_version__ = '3.3.0'
n_jobs = int(np.ceil(cpu_count()*0.9))

def model_hp(model, method):
    if method=='random':
        hp = HyperParametersRandom()
    elif method=='grid':
        hp = HyperParametersGrid()
    else:
        raise ValueError('`method` value error.')
    if model=='XGBClassifier' and method=='random':
        hp.Float('learning_rate', 0.01, 0.1)
        hp.Int('n_estimators', 100, 850)
        hp.Choice('max_depth', [3, 4, 5, 6, 7])
        hp.Choice('min_child_weight', [1, 2, 3, 4, 5, 6, 7])
        hp.Choice('max_delta_step', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        hp.Choice('reg_alpha', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('reg_lambda', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('subsample', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bytree', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bylevel', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bynode', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('gamma', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('random_state', [27])
        hp.Choice('booster', ['gbtree'])
        hp.Choice('importance_type', ["gain", "weight", "cover", "total_gain", "total_cover"])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['binary:logistic'])
        hp.Choice('tree_method', ['auto', 'exact', 'approx', 'hist'])
        hp.Choice('gpu_id', [-1])
    elif model=='XGBRegressor' and method=='random':
        hp.Float('learning_rate', 0.01, 0.1)
        hp.Int('n_estimators', 100, 850)
        hp.Choice('max_depth', [3, 4, 5, 6, 7])
        hp.Choice('min_child_weight', [1, 2, 3, 4, 5, 6, 7])
        hp.Choice('max_delta_step', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        hp.Choice('reg_alpha', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('reg_lambda', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('subsample', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bytree', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bylevel', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bynode', [0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
        hp.Choice('gamma', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('scale_pos_weight', [1])
        hp.Choice('random_state', [27])
        hp.Choice('booster', ['gbtree'])
        hp.Choice('importance_type', ["gain", "weight", "cover", "total_gain", "total_cover"])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['reg:squarederror'])
        hp.Choice('tree_method', ['auto', 'exact', 'approx', 'hist'])
        hp.Choice('gpu_id', [-1])
    elif model=='XGBClassifier' and method=='grid':
        hp.Choice('learning_rate', [0.01, 0.03, 0.05, 0.07, 0.09, 0.1], 0.1, rank=7)
        hp.Choice('n_estimators', list(range(100, 850, 50)), 300, rank=1)
        hp.Choice('max_depth', [3, 4, 5, 6, 7], 5, rank=2)
        hp.Choice('min_child_weight', [1, 2, 3, 4, 5], 1, rank=2)
        hp.Choice('max_delta_step', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0, rank=6)
        hp.Choice('reg_alpha', [0, 0.05, 0.5, 1, 50, 100], 0, rank=5)
        hp.Choice('reg_lambda', [0.05, 0.5, 1, 10, 50, 100], 1, rank=5)
        hp.Choice('subsample', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('colsample_bytree', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('colsample_bylevel', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('colsample_bynode', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('gamma', [0.1, 0.2, 0.3, 0.4, 0.5], 0, rank=3)
        hp.Choice('random_state', [27])
        hp.Choice('booster', ['gbtree'])
        hp.Choice('importance_type', ["gain"])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['binary:logistic'])
        hp.Choice('tree_method', ['hist'])
        hp.Choice('gpu_id', [-1])
    elif model=='XGBRegressor' and method=='grid':
        hp.Choice('learning_rate', [0.01, 0.03, 0.05, 0.07, 0.09, 0.1], 0.1, rank=7)
        hp.Choice('n_estimators', list(range(100, 850, 50)), 300, rank=1)
        hp.Choice('max_depth', [3, 4, 5, 6, 7], 5, rank=2)
        hp.Choice('min_child_weight', [1, 2, 3, 4, 5], 1, rank=2)
        hp.Choice('max_delta_step', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0, rank=6)
        hp.Choice('reg_alpha', [0, 0.05, 0.5, 1, 50, 100], 0, rank=5)
        hp.Choice('reg_lambda', [0.05, 0.5, 1, 10, 50, 100], 1, rank=5)
        hp.Choice('subsample', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('colsample_bytree', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('colsample_bylevel', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('colsample_bynode', [0.6, 0.7, 0.8, 0.9], 0.8, rank=4)
        hp.Choice('gamma', [0.1, 0.2, 0.3, 0.4, 0.5], 0, rank=3)
        hp.Choice('scale_pos_weight', [1])
        hp.Choice('random_state', [27])
        hp.Choice('booster', ['gbtree'])
        hp.Choice('importance_type', ["gain"])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['reg:squarederror'])
        hp.Choice('tree_method', ['hist'])
        hp.Choice('gpu_id', [-1])
    elif model=='LGBMClassifier' and method=='grid':
        hp.Choice('learning_rate', [0.01, 0.03, 0.05, 0.07, 0.09, 0.1], 0.1, rank=5)
        hp.Choice('n_estimators', list(range(100, 850, 50)), 300, rank=1)
        hp.Choice('max_depth', [3, 4, 5, 6, 7], 4, rank=2)
        hp.Dependence('num_leaves', 'max_depth', lambda x:int(np.random.choice(range(int(2**x*0.4), int(2**x*0.6)))), default=15)
        hp.Choice('reg_alpha', [0, 0.05, 0.5, 1, 50, 100], 0, rank=4)
        hp.Choice('reg_lambda', [0.05, 0.5, 1, 10, 50, 100], 1, rank=4)
        hp.Choice('subsample', [0.6, 0.7, 0.8, 0.9], 0.8, rank=3)
        hp.Choice('colsample_bytree', [0.6, 0.7, 0.8, 0.9], 0.8, rank=3)
        hp.Choice('random_state', [27])
        hp.Choice('boosting_type', ['gbdt'])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['binary'])
    elif model=='LGBMClassifier' and method=='random':
        hp.Float('learning_rate', 0.01, 0.1, default=0.1)
        hp.Int('n_estimators', 100, 850, default=200)
        hp.Choice('max_depth', [3, 4, 5, 6, 7], default=4)
        hp.Dependence('num_leaves', 'max_depth', lambda x:int(np.random.choice(range(int(2**x*0.4), int(2**x*0.6)))), default=15)
        hp.Choice('reg_alpha', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('reg_lambda', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('subsample', [0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bytree', [0.7, 0.8, 0.9, 1. ])
        hp.Choice('random_state', [27])
        hp.Choice('boosting_type', ['gbdt'])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['binary'])
    elif model=='LGBMRegressor' and method=='grid':
        hp.Choice('learning_rate', [0.01, 0.03, 0.05, 0.07, 0.09, 0.1], 0.1, rank=5)
        hp.Choice('n_estimators', list(range(100, 850, 50)), 300, rank=1)
        hp.Choice('max_depth', [3, 4, 5, 6, 7], 4, rank=2)
        hp.Dependence('num_leaves', 'max_depth', lambda x:int(np.random.choice(range(int(2**x*0.4), int(2**x*0.6)))), default=15)
        hp.Choice('reg_alpha', [0, 0.05, 0.5, 1, 50, 100], 0, rank=4)
        hp.Choice('reg_lambda', [0.05, 0.5, 1, 10, 50, 100], 1, rank=4)
        hp.Choice('subsample', [0.6, 0.7, 0.8, 0.9], 0.8, rank=3)
        hp.Choice('colsample_bytree', [0.6, 0.7, 0.8, 0.9], 0.8, rank=3)
        hp.Choice('random_state', [27])
        hp.Choice('boosting_type', ['gbdt'])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['regression'])
    elif model=='LGBMRegressor' and method=='random':
        hp.Float('learning_rate', 0.01, 0.1, default=0.1)
        hp.Int('n_estimators', 100, 850, default=200)
        hp.Choice('max_depth', [3, 4, 5, 6, 7], default=4)
        hp.Dependence('num_leaves', 'max_depth', lambda x:int(np.random.choice(range(int(2**x*0.4), int(2**x*0.6)))), default=15)
        hp.Choice('reg_alpha', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('reg_lambda', np.concatenate([np.linspace(0, 1, 101), np.linspace(2, 100, 99)]).round(2))
        hp.Choice('subsample', [0.7, 0.8, 0.9, 1. ])
        hp.Choice('colsample_bytree', [0.7, 0.8, 0.9, 1. ])
        hp.Choice('random_state', [27])
        hp.Choice('boosting_type', ['gbdt'])
        hp.Choice('verbosity', [0])
        hp.Choice('n_jobs', [n_jobs])
        hp.Choice('objective', ['regression'])
    return hp