import random
import NSGA2 as ns

def objective_function(function1,function2,x):
    # 定义优化的目标函数，此处以一个简单的二维函数为例
    return function1(x),function2(x)

#todo 按照非支配解个数来动态修改生成位置范围
def generate_neighbor(pos,iter,iter_max):
    # 在当前解的邻域内随机生成新解
    new_pos=[]
    pos_range=[0,1000]
    for loc in pos:
        k=[]
        for i in range(0,len(loc)-1):
            # x = loc[i] + random.uniform(-20 + 10 * iter / iter_max, 20 -10 * iter / iter_max)
            # x = loc[i] + random.uniform(-10, 10)
            if iter<10:
                x=loc[i] + random.uniform(-40+10*iter/iter_max, 40-10*iter/iter_max)
            elif iter>=10 and iter<20:
                x = loc[i] + random.uniform(-30 + 10 * iter / iter_max, 30 - 10 * iter / iter_max)
            elif iter>=20 and iter<30:
                x = loc[i] + random.uniform(-20 + 10 * iter / iter_max, 20 -10 * iter / iter_max)
            else:
                x = loc[i] + random.uniform(-10 + 5 * iter / iter_max, 10 - 5 * iter / iter_max)
            if x>pos_range[1]:
                x=pos_range[1]
            if x<pos_range[0]:
                x=pos_range[0]
            k.append(x)
        k.append(loc[2])
        new_pos.append(k)

    return new_pos

def generate_neighbor2(pos,rank,rank_max,iter_,iter_max):
    # 在当前解的邻域内随机生成新解
    new_pos=[]
    pos_range=[0,1000]
    for loc in pos:
        k=[]
        for i in range(0,len(loc)-1):
            r1=-10-20 * (rank+1) / rank_max+10*iter_/iter_max
            r2=10+ 20 * (rank+1) / rank_max-10*iter_/iter_max
            x = loc[i] + random.uniform(r1,r2)

            if x>pos_range[1]:
                x=pos_range[1]
            if x<pos_range[0]:
                x=pos_range[0]
            k.append(x)
        k.append(loc[2])
        new_pos.append(k)

    return new_pos

#todo：根据当前解的等级调整领域范围生成领域解
def generate_neighbor3(pos,rank,rank_max):
    new_pos=[]
    pos_range=[0,1000]
    for loc in pos:
        k=[]
        for i in range(0,len(loc)-1):
            if rank_max>10:
                r1=-50-20 * (rank+1) / rank_max
                r2=50+ 20 * (rank+1) / rank_max
                x = loc[i] + random.uniform(r1,r2)
            elif rank_max<=10 and rank_max>5:
                r1 = -20 - 20 * (rank + 1) / rank_max
                r2 = 20 + 10 * (rank + 1) / rank_max
                x = loc[i] + random.uniform(r1, r2)
            else:
                r1 = -20 - 10 * (rank + 1) / rank_max
                r2 = 20 + 10 * (rank + 1) / rank_max
                x = loc[i] + random.uniform(r1, r2)
            if x>pos_range[1]:
                x=pos_range[1]
            if x<pos_range[0]:
                x=pos_range[0]
            k.append(x)
        k.append(loc[2])
        new_pos.append(k)

    return new_pos
def get_best(neighbors,neighbors_p,users):
    function1_values, function2_values, _ = ns.get_function_values(len(neighbors), neighbors,
                                                                   neighbors_p, users)
    non_dominated_sorted_solution, rank = ns.fast_non_dominated_sort(function1_values[:], function2_values[:])
    best=non_dominated_sorted_solution[0][0]
    return neighbors[best]

def tabu_search(pos,users,max_iter,iter,iterMax,rank,rank_max):
    individual=pos
    current_solution = pos  # 初始解
    best_solution = current_solution  # 记录最优解
    best=[]
    tabu_list = []  # 禁忌表，避免重复搜索
    tabu_tenure = 4  # 禁忌期限，即禁忌解在禁忌表中停留的迭代次数

    for i in range(max_iter):
        # neighbors = [generate_neighbor2(current_solution,rank,rank_max,iter,iterMax) for _ in range(10)]  # 随机生成10个邻域解
        neighbors = [generate_neighbor(current_solution, iter,iterMax) for _ in range(10)]
        # neighbors = [generate_neighbor3(current_solution, rank, rank_max) for _ in range(10)]
        neighbors_p=[]#根据领域解生成的功率分配
        for j in range(len(neighbors)):
            neighbors_p.append(ns.init_p(neighbors[j],users))
        # 在邻域解中选择一个非禁忌的最优解,找到支配等级最高的解，

        candidate = get_best(neighbors,neighbors_p,users)
        while candidate in tabu_list:
            neighbors.remove(candidate)
            candidate = get_best(neighbors,neighbors_p,users)

        # 更新当前解和最优解
        current_solution = candidate
        compare_group=[candidate,individual]
        compare_group_p=[]
        for i in range(len(compare_group)):
            compare_group_p.append(ns.init_p(compare_group[i],users))
        function1_values, function2_values, _ = ns.get_function_values(len(compare_group), compare_group,
                                                                       compare_group_p, users)
        non_dominated_sorted_solution, rank = ns.fast_non_dominated_sort(function1_values[:], function2_values[:])
        # crowding_distance_values = []
        # for i in range(0, len(non_dominated_sorted_solution)):
        #     crowding_distance_values.append(
        #         ns.crowding_distance(function1_values[:], function2_values[:], non_dominated_sorted_solution[i][:]))

        if rank[0]<rank[1]:
            best_solution = candidate
            return best_solution

        tabu_list.append(candidate)  # 将当前解加入禁忌表
        if len(tabu_list) > tabu_tenure:  # 维护禁忌表的长度不超过禁忌期限
            tabu_list.pop(0)

    return best_solution

pos=[[313.99873528 ,416.45594562, 100.        ],
 [842.85965065 ,611.07755542, 100.        ],
 [810.63437665 ,371.17088506 ,100.        ]]

# print(generate_neighbor(pos))