Beispiel #1
0
def random_cable(layout):
    import random
    cables_info = read_cablelist()
    Cable_List = []

    for number in number_turbines_per_cable:

        for cable in cables_info:

            if rated_current * number <= cable[1]:
                Cable_List.append([number, cable[2] + 365.0])
                break

    layout = [[item[0] + 1, item[1], item[2]] for item in layout]
    layout.insert(0, [0, central_platform[0][0], central_platform[0][1]])

    quantity = range(1, len(layout))

    routes = []
    for route in range(len(layout) / number_turbines_per_cable[0]):
        routes.append([])
        first_turbine = random.choice(quantity)
        routes[-1].append([0, first_turbine])
        quantity.pop(quantity.index(first_turbine))

        for turbine in range(
                min(number_turbines_per_cable[0] - 1, len(quantity))):

            random_number = random.choice(quantity)
            routes[-1].append([routes[-1][-1][1], random_number])
            quantity.pop(quantity.index(random_number))

    routes_dict = {1: routes}

    # print routes_dict
    total_distance = 0.0
    for i in range(len(routes)):
        summation = 0.0
        for j in range(len(routes[i])):

            distance_one = sqrt((layout[routes[i][j][0]][1] -
                                 layout[routes[i][j][1]][1])**2.0 +
                                (layout[routes[i][j][0]][2] -
                                 layout[routes[i][j][1]][2])**2.0)
            # print distance_one, layout[routes[i][j][0]], layout[routes[i][j][1]]
            summation += distance_one
        total_distance += summation
    cable_length = total_distance
    total_cost = cable_length * Cable_List[0][1]

    return total_cost, routes_dict, cable_length
Beispiel #2
0
def radial_cable(layout):

    cables_info = read_cablelist()
    Cable_List = []
    for number in number_turbines_per_cable:
        for cable in cables_info:
            if rated_current * number <= cable[1]:
                Cable_List.append([number, cable[2] + 365.0])
                break

    total_distance = 0.0
    for i in range(len(layout)):
        distance_one = sqrt((central_platform[0][0] - layout[i][1])**2.0 +
                            (central_platform[0][1] - layout[i][2])**2.0)
        total_distance += distance_one
    cable_length = total_distance
    total_cost = cable_length * Cable_List[0][1]

    routes = []
    for turbine in layout:
        routes.append([[0, turbine[0] + 1]])
    routes_dict = {1: routes}

    return total_cost, routes_dict, cable_length
def infield_efficiency(topology, wt_list, powers):

    from copy import deepcopy
    from farm_description import number_turbines_per_cable, read_cablelist
    from turbine_description import rated_power, rated_current

    cables_info = read_cablelist()
    Cable_area = []
    for number in number_turbines_per_cable:
        for cable in cables_info:
            if rated_current * number <= cable[1]:
                Cable_area.append([number, cable[0] / 1000000.0])
                break
    # print Cable_area

    def current_turbine(tree, coord):
        line2 = deepcopy(tree)

        def find_next(number, branch, outl):
            next_turbine = number
            for item in branch:
                if number == item[0]:
                    outl.append(item[1])
                    branch.remove(item)
                    next_turbine = item[1]
                elif number == item[1]:
                    outl.append(item[0])
                    branch.remove(item)
                    next_turbine = item[0]
            return next_turbine, branch, outl

        def find_ends(branch2):
            branch = deepcopy(branch2)
            all_elements = [item[i] for i in range(2) for item in branch]
            values = list(set(all_elements))
            values.remove(0)
            out_list = []
            for value in values:
                if all_elements.count(value) == 1:
                    out_list.append([value])
                    for i in range(100):
                        value, branch, out_list[-1] = find_next(value, branch, out_list[-1])
            return out_list

        tree_branches = find_ends(line2)

        def sort_branches(routes):
            def length(a):
                return len(a)
            routes.sort(key=length)
            if routes[-1][-1] != 0:
                for item in routes:
                    if item[-1] == 0:
                        routes.append(routes.pop(routes.index(item)))
            return routes

        sort_branches(tree_branches)

        all_elements = [item[i] for item in tree_branches for i in range(len(item))]

        def remove_dup(seq):
            seen = set()
            seen_add = seen.add
            return [x for x in seq if not (x in seen or seen_add(x))]

        def distance(t1, t2):
            return ((t1[1] - t2[1]) ** 2.0 + (t1[2] - t2[2]) ** 2.0) ** 0.5

        a = list(reversed(remove_dup(reversed(all_elements))))
        # print a
        counter = {n: [1, 0.0] for n in a}

        for n in a:
            for m in a:
                if [n, m] in line2 or [m, n] in line2:
                    if [n, m] in line2:
                        line2.remove([n, m])
                        counter[m][0] += counter[n][0]
                        counter[n][1] = distance(coord[n - 1], coord[m - 1])
                    if [m, n] in line2:
                        line2.remove([m, n])
                        counter[m][0] += counter[n][0]
                        counter[n][1] = distance(coord[n - 1], coord[m - 1])
                        # TODO solve distances of individual cables per number of turbines connected.

        return counter

    all_lines = topology[1]

    max_counter = [[0.0, []] for _ in range(100)]

    for line in all_lines:
        amount = current_turbine(line, wt_list)
        for i in range(10):
            for key in amount:
                if amount[key][0] == i + 1 and key != 0:
                    max_counter[i][0] += amount[key][1]
                    max_counter[i][1].append(key)
    # Provides the length of cables that carry the current
    #  of that number of turbines, and their ID. Index one is for one turbine, etc.

    current_squared_cables = [0.00 for _ in range(len(max_counter))]
    for i in range(len(max_counter)):
        for turbine in max_counter[i][1]:
            current_squared_cables[i] += (i + 1) ** 2.0 * (rated_current * powers[turbine - 1] / rated_power) ** 2.0
            #  Assumed linear current with power.

    losses = []  # Expresed in W.
    for i in range(len(max_counter)):
        losses.append(max_counter[i][0] * 1.74e-8 / Cable_area[0][1] * current_squared_cables[i] * 3.0)  # Three times the loss of each cable (* 3.0)

    # print sum(powers)  # Expressed in W originally.
    # print sum(losses)
    efficiency = 1.0 - sum(losses) / (sum(powers) * 1000.0)
    # print efficiency
    return efficiency
Beispiel #4
0
    def connect(self, turbine_coordinates):
        self.number_turbines = len(turbine_coordinates)
        self.minx = min([turbine[1] for turbine in turbine_coordinates])
        self.maxx = max([turbine[1] for turbine in turbine_coordinates])
        self.miny = min([turbine[2] for turbine in turbine_coordinates])
        self.maxy = max([turbine[2] for turbine in turbine_coordinates])
        from site_conditions.terrain.terrain_models import depth
        from farm_energy.wake_model_mean_new.wake_1angle import energy_one_angle
        from farm_energy.wake_model_mean_new.wake_1angle_turbulence import max_turbulence_one_angle
        from costs.investment_costs.BOS_cost.cable_cost.Hybrid import draw_cables
        from farm_description import central_platform, read_cablelist, number_turbines_per_cable, cable_installation_cost
        from turbine_description import rated_current
        from site_conditions.wind_conditions.windrose import WeibullWindBins, MeanWind
        from farm_energy.wake_model_mean_new.downstream_effects import JensenEffects as Jensen

        cables_info = read_cablelist()
        cable_list = []
        for number in number_turbines_per_cable:
            for cable in cables_info:
                if rated_current * number <= cable[1]:
                    cable_list.append([number, cable[2] + cable_installation_cost])  # 365 is cable installation cost per linear metre.
                    break
        from turbine_description import cutin_wind_speed, cutout_wind_speed
        if self.print_output:
            print "=== PREPARING WIND CONDITIONS ==="
        self.wind_directions, self.direction_probabilities = self.windrose.adapt_directions()
        if self.inflow_model == MeanWind:
            self.wind_speeds = self.windrose.expected_wind_speeds
            self.freestream_turbulence = [0.11]
            self.wind_speeds_probabilities = [[100.0] for _ in range(len(self.wind_directions))]
        elif self.inflow_model == WeibullWindBins:
            self.windrose.cutin = cutin_wind_speed
            self.windrose.cutout = cutout_wind_speed
            self.wind_speeds, self.wind_speeds_probabilities = self.windrose.speed_probabilities()
            self.freestream_turbulence = [0.11 for _ in range(len(self.wind_speeds[0]))]
        if self.print_output:
            print "=== CALCULATING WATER DEPTH ==="
        self.water_depths = depth(turbine_coordinates, self.depth_model(self.minx, self.maxx, self.miny, self.maxy))
        if self.print_output:
            print str(self.water_depths) + "\n"
        central_platform_coordinates = [[0, central_platform[0][0], central_platform[0][1]]]
        if self.print_output:
            print "=== CALCULATING DEPTH AT CENTRAL PLATFORM ==="
        self.depth_central_platform = \
            depth(central_platform_coordinates, self.depth_model(self.minx, self.maxx, self.miny, self.maxy))[0]
        if self.print_output:
            print str(self.depth_central_platform) + " m\n"
        if self.print_output:
            print "=== OPTIMISING INFIELD CABLE TOPOLOGY (COST)==="
        if self.draw_infield:
            draw_cables(turbine_coordinates, central_platform, cable_list)
        if self.cable_topology_model != "ConstantCable":
            self.cable_topology_costs, self.cable_topology, self.infield_length = self.cable_topology_model(
                turbine_coordinates)
        print self.cable_topology
        if self.cable_topology_model == "ConstantCable":
            self.cable_topology_costs = 9960476.0
            self.infield_length = 15276.0
        if self.print_output:
            print str(self.cable_topology_costs) + " EUR\n" + str(self.infield_length)
        self.max_turbulence_per_turbine = [0.0 for _ in range(len(turbine_coordinates))]
        if self.print_output:
            print "=== CALCULATING ENERGY, TURBULENCE PER WIND DIRECTION ==="
        for i in range(len(self.wind_directions)):
            # print " === Wind direction = " + str(self.wind_directions[i])
            self.aero_energy_one_angle, self.powers_one_angle = energy_one_angle(turbine_coordinates,
                                                                                 self.wind_speeds[i],
                                                                                 self.wind_speeds_probabilities[i],
                                                                                 self.wind_directions[i],
                                                                                 self.freestream_turbulence,
                                                                                 self.wake_mean_model, self.power_model,
                                                                                 self.power_lookup_file,
                                                                                 self.thrust_coefficient_model,
                                                                                 self.thrust_lookup_file,
                                                                                 self.wake_merging_model)
            if self.wake_turbulence_model != "ConstantTurbulence":
                self.turbulences = max_turbulence_one_angle(turbine_coordinates, self.wind_speeds[i],
                                                            self.wind_directions[i], self.freestream_turbulence, Jensen,
                                                            self.thrust_coefficient_model, self.thrust_lookup_file,
                                                            self.wake_turbulence_model)
            if self.cable_topology_model != "ConstantCable":
                self.cable_topology_efficiency = self.cable_efficiency_model(self.cable_topology, turbine_coordinates,
                                                                             self.powers_one_angle)
            self.energy_one_angle_weighted = self.aero_energy_one_angle * self.direction_probabilities[i] / 100.0
            self.array_efficiency = (
                self.aero_energy_one_angle / (float(len(turbine_coordinates)) * max(self.powers_one_angle) * 8760.0))
            self.array_efficiencies_weighted = self.array_efficiency * self.direction_probabilities[i] / 100.0
            self.array_efficiencies.append(self.array_efficiencies_weighted)
            self.energies_per_angle.append(self.energy_one_angle_weighted)
            if self.wake_turbulence_model != "ConstantTurbulence":
                self.turbulences_per_angle.append(self.turbulences)
            if self.cable_topology_model != "ConstantCable":
                self.cable_efficiencies_per_angle.append(self.cable_topology_efficiency)
            if self.wake_turbulence_model != "ConstantTurbulence":
                for j in range(len(turbine_coordinates)):
                    if self.turbulences[j] > self.max_turbulence_per_turbine[j]:
                        self.max_turbulence_per_turbine[j] = self.turbulences[j]
        if self.print_output:
            print " --- Array efficiency---"
        self.array_efficiency = sum(self.array_efficiencies)
        if self.print_output:
            print str(self.array_efficiency * 100.0) + " %\n"
        if self.print_output:
            print " --- Farm annual energy without losses---"
        self.farm_annual_energy = sum(self.energies_per_angle)
        if self.print_output:
            print str(self.farm_annual_energy / 1000000.0) + " MWh\n"
        if self.print_output:
            print " --- Infield cable system efficiency ---"
        if self.cable_topology_model != "ConstantCable":
            self.cable_efficiency = sum(self.cable_efficiencies_per_angle) / len(
                self.cable_efficiencies_per_angle)  # TODO Check if average is the way to go instead of weighted average
        # with probability of direction.
        if self.cable_topology_model == "ConstantCable":
            self.cable_efficiency = 0.99
        if self.print_output:
            print str(self.cable_efficiency * 100.0) + " %\n"
        if self.print_output:
            print " --- Maximum wind turbulence intensity ---"
        if self.wake_turbulence_model != "ConstantTurbulence":
            self.turbulence = self.max_turbulence_per_turbine
        elif self.wake_turbulence_model == "ConstantTurbulence":
            self.turbulence = [0.25 for _ in range(self.number_turbines)]
        if self.print_output:
            print str([self.turbulence[l] * 100.0 for l in range(len(self.turbulence))]) + " %\n"
        # --------- COSTS ----------------------------------------
        if self.print_output:
            print " --- Other investment and decommissioning costs ---"
        self.investment, self.decommissioning_cost = self.more_costs(self.depth_central_platform, self.number_turbines,
                                                                     self.infield_length)
        if self.print_output:
            print "Other investment costs"
        if self.print_output:
            print str(self.investment) + " EUR\n"
        if self.print_output:
            print "Decommissioning costs"
        if self.print_output:
            print str(self.decommissioning_cost) + " EUR\n"
        if self.print_output:
            print " --- Support structure investment costs ---"
        if self.support_design_model != "ConstantSupport":
            self.support_costs = self.support_design_model(self.water_depths, self.turbulence)
        elif self.support_design_model == "ConstantSupport":
            self.support_costs = 72376799.0
        if self.print_output:
            print str(self.support_costs) + " EUR\n"
        if self.print_output:
            print " --- O&M costs---"
        self.om_costs, self.availability = self.OandM_model(self.farm_annual_energy, self.aeroloads, self.hydroloads,
                                                            turbine_coordinates)
        if self.print_output:
            print self.om_costs
        if self.print_output:
            print str(self.om_costs) + " EUR\n"
        if self.print_output:
            print " --- Total energy production ---"
        self.aep = self.aep_model(self.farm_annual_energy, self.availability, self.cable_efficiency)
        if self.print_output:
            print str(self.aep / 1000000.0) + " MWh\n"
        if self.print_output:
            print " --- Total investment costs ---"
        self.total_costs = self.support_costs + self.cable_topology_costs + self.investment
        if self.print_output:
            print str(self.total_costs) + " EUR\n"
        if self.print_output:
            print " --- LPC ---"
        self.finance = self.finance_model(self.investment + self.cable_topology_costs + self.support_costs,
                                          self.om_costs, self.decommissioning_cost, self.aep, 0.95)
        if self.print_output:
            print str(self.finance) + " cents/kWh\n"
        return self.finance
Beispiel #5
0
    def connect(self, turbine_coordinates):
        self.number_turbines = len(turbine_coordinates)
        # print turbine_coordinates
        self.minx = min([turbine[1] for turbine in turbine_coordinates])
        self.maxx = max([turbine[1] for turbine in turbine_coordinates])
        self.miny = min([turbine[2] for turbine in turbine_coordinates])
        self.maxy = max([turbine[2] for turbine in turbine_coordinates])
        from site_conditions.terrain.terrain_models import depth
        from farm_energy.wake_model_mean_new.wake_1angle import energy_one_angle
        from farm_energy.wake_model_mean_new.wake_1angle_turbulence import max_turbulence_one_angle
        from costs.investment_costs.BOS_cost.cable_cost.Hybrid import draw_cables
        from farm_description import central_platform, read_cablelist, number_turbines_per_cable
        from turbine_description import rated_current
        from site_conditions.wind_conditions.windrose import WeibullWindBins, MeanWind
        from farm_energy.wake_model_mean_new.downstream_effects import JensenEffects as Jensen

        cables_info = read_cablelist()
        cable_list = []

        for number in number_turbines_per_cable:
            for cable in cables_info:
                if rated_current * number <= cable[1]:
                    cable_list.append([number, cable[2] + 365.0])
                    break

        # print cable_list

        from turbine_description import cutin_wind_speed, cutout_wind_speed

        if self.print_output is True: print "=== PREPARING WIND CONDITIONS ==="

        self.wind_directions, self.direction_probabilities = self.windrose.adapt_directions()

        if self.inflow_model == MeanWind:

            self.wind_speeds = self.windrose.expected_wind_speeds
            self.freestream_turbulence = [0.11]
            self.wind_speeds_probabilities = [[100.0] for _ in range(len(self.wind_directions))]

        elif self.inflow_model == WeibullWindBins:
            self.windrose.cutin = cutin_wind_speed
            self.windrose.cutout = cutout_wind_speed
            self.wind_speeds, self.wind_speeds_probabilities = self.windrose.speed_probabilities()
            self.freestream_turbulence = [0.11 for _ in range(len(self.wind_speeds[0]))]

        # if self.print_output is True: print self.wind_speeds, self.wind_speeds_probabilities

        if self.print_output is True: print "=== CALCULATING WATER DEPTH ==="
        self.water_depths = depth(turbine_coordinates, self.depth_model(self.minx, self.maxx, self.miny, self.maxy))
        if self.print_output is True: print str(self.water_depths) + "\n"

        central_platform_coordinates = [[0, central_platform[0][0], central_platform[0][1]]]
        if self.print_output is True: print "=== CALCULATING DEPTH AT CENTRAL PLATFORM ==="
        self.depth_central_platform = depth(central_platform_coordinates, self.depth_model(self.minx, self.maxx, self.miny, self.maxy))[0]
        if self.print_output is True: print str(self.depth_central_platform) + " m\n"

        if self.print_output is True: print "=== OPTIMISING INFIELD CABLE TOPOLOGY (COST)==="
        if self.draw_infield is True: draw_cables(turbine_coordinates, central_platform, cable_list)
        if self.cable_topology_model != "ConstantCable":
            self.cable_topology_costs, self.cable_topology, self.infield_length = self.cable_topology_model(turbine_coordinates)
        if self.cable_topology_model == "ConstantCable":
            self.cable_topology_costs = 9960476.0
            self.infield_length = 15276.0
        # print self.cable_topology
        if self.print_output is True: print str(self.cable_topology_costs) + " EUR\n" + str(self.infield_length)

        self.energies_per_angle = []
        self.turbulences_per_angle = []
        self.cable_efficiencies_per_angle = []
        self.array_efficiencies = []
        # if self.print_output is True: print [sum(self.wind_speeds_probabilities[i]) for i in range(len(self.wind_speeds_probabilities))]

        self.max_turbulence_per_turbine = [0.0 for _ in range(len(turbine_coordinates))]

        if self.print_output is True: print "=== CALCULATING ENERGY, TURBULENCE PER WIND DIRECTION ==="
        for i in range(len(self.wind_directions)):
            # print " === Wind direction = " + str(self.wind_directions[i])
            # if self.print_output is True: print self.wind_speeds_probabilities[i]
            self.aero_energy_one_angle, self.powers_one_angle = energy_one_angle(turbine_coordinates, self.wind_speeds[i], self.wind_speeds_probabilities[i], self.wind_directions[i], self.freestream_turbulence, self.wake_mean_model, self.power_model, self.power_lookup_file, self.thrust_coefficient_model, self.thrust_lookup_file, self.wake_merging_model)

            # if self.print_output is True: print self.aero_energy_one_angle
            # if self.print_output is True: print self.powers_one_angle, max(self.powers_one_angle)
            # if self.print_output is True: print turbine_coordinates, self.wind_speeds[i], self.wind_directions[i], self.freestream_turbulence[0], Jensen, self.thrust_coefficient_model, self.wake_turbulence_model
            if self.wake_turbulence_model != "ConstantTurbulence":
                self.turbulences = max_turbulence_one_angle(turbine_coordinates, self.wind_speeds[i], self.wind_directions[i], self.freestream_turbulence, Jensen, self.thrust_coefficient_model, self.thrust_lookup_file, self.wake_turbulence_model)
            if self.cable_topology_model != "ConstantCable":
                self.cable_topology_efficiency = self.cable_efficiency_model(self.cable_topology, turbine_coordinates, self.powers_one_angle)

            self.energy_one_angle_weighted = self.aero_energy_one_angle * self.direction_probabilities[i] / 100.0
            self.array_efficiency = (self.aero_energy_one_angle / (float(len(turbine_coordinates)) * max(self.powers_one_angle) * 8760.0))
            self.array_efficiencies_weighted = self.array_efficiency * self.direction_probabilities[i] / 100.0

            self.array_efficiencies.append(self.array_efficiencies_weighted)
            self.energies_per_angle.append(self.energy_one_angle_weighted)
            if self.wake_turbulence_model != "ConstantTurbulence":
                self.turbulences_per_angle.append(self.turbulences)
            if self.cable_topology_model != "ConstantCable":
                self.cable_efficiencies_per_angle.append(self.cable_topology_efficiency)

            if self.wake_turbulence_model != "ConstantTurbulence":
                for j in range(len(turbine_coordinates)):
                    if self.turbulences[j] > self.max_turbulence_per_turbine[j]:
                        self.max_turbulence_per_turbine[j] = self.turbulences[j]

        # if self.print_output is True: print self.array_efficiencies
        if self.print_output is True: print " --- Array efficiency---"
        self.array_efficiency = sum(self.array_efficiencies)
        if self.print_output is True: print str(self.array_efficiency * 100.0) + " %\n"

        if self.print_output is True: print " --- Farm annual energy without losses---"
        self.farm_annual_energy = sum(self.energies_per_angle)
        if self.print_output is True: print str(self.farm_annual_energy / 1000000.0) + " MWh\n"

        if self.print_output is True: print " --- Infield cable system efficiency ---"
        if self.cable_topology_model != "ConstantCable":
            self.cable_efficiency = sum(self.cable_efficiencies_per_angle) / len(self.cable_efficiencies_per_angle)  # TODO Check if average is the way to go instead of weighted average with probability of direction.
        if self.cable_topology_model == "ConstantCable":
            self.cable_efficiency = 0.99
        if self.print_output is True: print str(self.cable_efficiency * 100.0) + " %\n"

        if self.print_output is True: print " --- Maximum wind turbulence intensity ---"
        if self.wake_turbulence_model != "ConstantTurbulence":
            self.turbulence = self.max_turbulence_per_turbine
        elif self.wake_turbulence_model == "ConstantTurbulence":
            self.turbulence = [0.25 for _ in range(self.number_turbines)]
        if self.print_output is True: print str([self.turbulence[l] * 100.0 for l in range(len(self.turbulence))]) + " %\n"

        # --------- COSTS ----------------------------------------

        if self.print_output is True: print " --- Other investment and decommissioning costs ---"
        self.investment, self.decommissioning_cost = self.more_costs(self.depth_central_platform, self.number_turbines, self.infield_length)
        if self.print_output is True: print "Other investment costs"
        if self.print_output is True: print str(self.investment) + " EUR\n"
        if self.print_output is True: print "Decommissioning costs"
        if self.print_output is True: print str(self.decommissioning_cost) + " EUR\n"

        if self.print_output is True: print " --- Support structure investment costs ---"
        if self.support_design_model != "ConstantSupport":
            self.support_costs = self.support_design_model(self.water_depths, self.turbulence)
        elif self.support_design_model == "ConstantSupport":
            self.support_costs = 72376799.0
        if self.print_output is True: print str(self.support_costs) + " EUR\n"

        self.aeroloads = 0.0
        self.hydroloads = 0.0

        if self.print_output is True: print " --- O&M costs---"
        self.om_costs, self.availability = self.OandM_model(self.farm_annual_energy, self.aeroloads, self.hydroloads, turbine_coordinates)
        # self.om_costs *= 20.0  # Number of years
        if self.print_output is True: print self.om_costs
        if self.print_output is True: print str(self.om_costs) + " EUR\n"

        if self.print_output is True: print " --- Total energy production ---"
        self.aep = self.aep_model(self.farm_annual_energy, self.availability, self.cable_efficiency)
        if self.print_output is True: print str(self.aep / 1000000.0) + " MWh\n"

        if self.print_output is True: print " --- Total investment costs ---"
        self.total_costs = self.support_costs + self.cable_topology_costs + self.investment
        if self.print_output is True: print str(self.total_costs) + " EUR\n"

        if self.print_output is True: print " --- LCOE ---"
        self.finance = self.finance_model(self.investment + self.cable_topology_costs + self.support_costs, self.om_costs, self.decommissioning_cost, self.aep, 0.95)
        if self.print_output is True: print str(self.finance) + " cents/kWh\n"

        return self.finance
def cable_design(WT_List):

    from math import hypot
    from copy import deepcopy
    from heapq import heappush, heappop, heapify
    # from time import time
    from farm_description import central_platform as central_platform_locations, number_turbines_per_cable, read_cablelist

    NT = len(WT_List)
    # List of cable types: [Capacity,Cost] in increasing order (maximum 3 cable types)
    cables_info = read_cablelist()
    Cable_List = []
    for number in number_turbines_per_cable:
        for cable in cables_info:
            if rated_current * number <= cable[1]:
                Cable_List.append([number, cable[2] + 365.0])
                break
    # print Cable_List
    # Cable_List = [[2, 256 + 365], [4, 406 + 365]]
    # Cable_List=[[5,110],[8,180]]
    # Cable_List=[[10,406+365]]
    Crossing_penalty = 0
    Area = []
    # Transmission = [[central_platform_locations[0], [463000, 5918000]],
    #                 [central_platform_locations[1], [463000, 5918000]]]
    Transmission = []

    'Remove and return the lowest priority task. Raise KeyError if empty.'
    REMOVED = '<removed-task>'  # placeholder for a removed task

    # ---------------------------------------Main--------------------------------------------------------------------------------
    def set_cable_topology(NT, WT_List, central_platform_locations,
                           Cable_List):
        Wind_turbines = []
        for WT in WT_List:
            Wind_turbines.append([WT[0] + 1, WT[1], WT[2]])
        # initialize the parameters
        Wind_turbinesi, Costi, Cost0i, Costij, Savingsi, Savingsi_finder, Savingsi2, Savingsi2_finder, distancefromsubstationi, substationi, Routingi, Routing_redi, Routing_greeni, Routesi, Capacityi, Cable_Costi, Crossings_finder = dict(
        ), dict(), dict(), dict(), dict(), dict(), dict(), dict(), dict(
        ), dict(), dict(), dict(), dict(), dict(), dict(), dict(), dict()
        i = 1
        for substation in central_platform_locations:
            Wind_turbinesi[i], Costi[i], distancefromsubstationi[
                i] = initial_values(NT, Wind_turbines, substation)
            substationi[i] = substation
            i += 1
        # splits the Wind_turbines list in the closest substation

        def second(x):
            return x[2]

        for j in range(NT):
            empty = []
            for key, value in list(distancefromsubstationi.items()):
                empty.append(value[j])
            index = empty.index(min(empty, key=second)) + 1
            Wind_turbinesi[index].append(
                [value[j][1], Wind_turbines[j][1], Wind_turbines[j][2]])
        # Wind_turbinesi[1]=[x for x in Wind_turbines if x[0]<=118]
        #        Wind_turbinesi[2]=[x for x in Wind_turbines if x[0]>118]
        for j in range(len(Cable_List)):
            Capacityi[j + 1] = Cable_List[j][0]
            Cable_Costi[j + 1] = Cable_List[j][1]
        # initialize routes and Saving matrix
        for key, value in list(Wind_turbinesi.items()):
            Routesi[key], Routingi[key], Routing_redi[key], Routing_greeni[
                key] = initial_routes(value)
            Cost0i[key], Costij[key] = costi(value, substationi[key])
            Savingsi[key], Savingsi_finder[key], Crossings_finder[
                key] = savingsi(Cost0i[key], Costij[key], value,
                                Cable_Costi[1], substationi[key], Area,
                                Crossing_penalty)
        total_cost = 0.0
        crossings = 0

        for key, value in list(Wind_turbinesi.items()):
            Routesi[key], Routingi[key], Routing_redi[key], Routing_greeni[
                key] = Hybrid(Savingsi[key], Savingsi_finder[key],
                              Wind_turbinesi[key], Routingi[key],
                              substationi[key], Capacityi, Routing_redi[key],
                              Routing_greeni[key])
            Savingsi2[key], Savingsi2_finder[key], Crossings_finder[
                key] = savingsi(Cost0i[key], Costij[key], value,
                                Cable_Costi[1], substationi[key], Area,
                                Crossing_penalty)
            Routesi[key], Routingi[key], Routing_redi[
                key], Routing_greeni[key] = Esau_Williams_Cable_Choice(
                    Savingsi2[key], Savingsi2_finder[key],
                    Crossings_finder[key], Wind_turbinesi[key], Routesi[key],
                    Routingi[key], substationi[key], Capacityi,
                    Routing_redi[key], Routing_greeni[key], Costi[key],
                    Cable_Costi)
            Routesi[key], Routingi[key] = RouteOpt_Hybrid(
                Routingi[key], substationi[key], Costi[key], Capacityi,
                Routesi[key], Wind_turbinesi[key])
            cost, total_length = plotting(substationi[key],
                                          Wind_turbinesi[key], Routingi[key],
                                          Routing_redi[key],
                                          Routing_greeni[key], Cable_Costi)
            total_cost += cost

            for route in Routingi[key]:
                if edge_crossings_area([route[0], route[1]],
                                       Wind_turbinesi[key], substationi[key],
                                       Area)[0] is True:
                    crossings += edge_crossings_area([route[0], route[1]],
                                                     Wind_turbinesi[key],
                                                     substationi[key], Area)[1]

        return total_cost, Routesi, total_length

    def mainroutine(arc, lines, Routing):
        if [arc[0], 0] in Routing:
            index1 = Routing.index([arc[0], 0])
        else:
            for line in lines:
                if arc[0] in line:
                    index1 = Routing.index([line[0], 0])
        Routing.pop(index1)
        Routing.append([arc[0], arc[1]])
        # turbines to be reversed
        for line in lines:
            if arc[0] in line:
                indexline = lines.index(line)
                indexarc = line.index(arc[0])
        indeces = []
        for i in range(0, indexarc):
            turbine = lines[indexline][i]
            for route in Routing:
                if route[1] == turbine and route != [arc[0], arc[1]]:
                    indexroute = Routing.index(route)
                    indeces.append(indexroute)
        for index in indeces:
            Routing[index].reverse()
        Routes = []
        for route in Routing:
            if route[1] == 0:
                Routes.append([[route[1], route[0]]])
        helpRouting = [i for i in Routing if i[1] != 0]
        helpRouting.reverse()
        for path in Routes:
            for pair in path:
                for route in helpRouting:
                    if pair[1] == route[1]:
                        index2 = path.index(pair)
                        index3 = Routes.index(path)
                        Routes[index3].insert(index2 + 1, [route[1], route[0]])
        indeces = []
        for zeygos in helpRouting:
            for path in Routes:
                if [zeygos[1], zeygos[0]] in path:
                    indexzeygos = helpRouting.index(zeygos)
                    indeces.append(indexzeygos)
        for index in indeces:
            helpRouting[index] = []
        temp = [x for x in helpRouting if x != []]
        temp2 = []
        for pair1 in temp:
            counter1 = 1
            counter2 = 1
            for pair2 in temp:
                if pair1[0] in pair2 and pair2 != pair1:
                    counter1 += 1
            if [pair1[0], counter1] not in temp2:
                temp2.append([pair1[0], counter1])
            for pair2 in temp:
                if pair1[1] in pair2 and pair2 != pair1:
                    counter2 += 1
            if [pair1[1], counter2] not in temp2:
                temp2.append([pair1[1], counter2])
        temp3 = []
        for pair1 in temp2:
            for pair2 in temp:
                if pair1[1] == 1 and pair1[0] == pair2[0]:
                    temp3.append(pair2)
                    temp.remove(pair2)

        for pair1 in temp3:
            for pair2 in temp:
                if pair1[1] == pair2[0]:
                    indexpair1 = temp3.index(pair1)
                    temp3.insert(indexpair1 + 1, pair2)
                    temp.remove(pair2)
        temp3 = [x for x in temp if x not in temp3] + temp3
        indeces = []
        if temp3:
            for pair in temp3:
                for route in Routes:
                    for path in route:
                        if pair[0] == path[1]:
                            indexpath = route.index(path)
                            indexroute = Routes.index(route)
                            Routes[indexroute].insert(indexpath + 1, pair)
                            indextemp = temp3.index(pair)
                            indeces.append(indextemp)
            for index in indeces:
                temp3[index] = []
            while temp3:
                indeces = []
                temp3 = [x for x in temp3 if x != []]
                temp3.reverse()
                for pair in temp3:
                    for route in Routes:
                        for path in route:
                            if pair[1] == path[1]:
                                indexpath = route.index(path)
                                indexroute = Routes.index(route)
                                Routes[indexroute].insert(
                                    indexpath + 1, [pair[1], pair[0]])
                                indextemp = temp3.index(pair)
                                indeces.append(indextemp)
                for index in indeces:
                    temp3[index] = []
                if temp3:
                    temp3 = [x for x in temp3 if x != []]
                    indeces = []
                    temp3.reverse()
                    for pair in temp3:
                        for route in Routes:
                            for path in route:
                                if pair[0] == path[1]:
                                    indexpath = route.index(path)
                                    indexroute = Routes.index(route)
                                    Routes[indexroute].insert(
                                        indexpath + 1, pair)
                                    indextemp = temp3.index(pair)
                                    indeces.append(indextemp)
                    for index in indeces:
                        temp3[index] = []
                    temp3 = [x for x in temp3 if x != []]
        return Routing, Routes

    def Hybrid(Savingsi, Savingsi_finder, Wind_turbinesi, Routing,
               central_platform_location, Capacityi, Routing_red,
               Routing_green):
        Paths = []
        for WT in Wind_turbinesi:
            Paths.append([0, WT[0]])
        while True:
            if Savingsi:
                Savingsi, Savingsi_finder, saving = pop_task(
                    Savingsi, Savingsi_finder)
            else:
                break
            if saving is None or saving[0] > 0:
                break
            arc = [saving[1], saving[2]]
            if check_same_path(arc, Paths) is False and any([
                    True for e in [[arc[0], 0]] if e in Routing
            ]) is True and one_neighbor(arc[1], Paths) is False:
                condition4 = dict()
                for key, value in list(Capacityi.items()):
                    condition4[key] = check_capacity(arc, Paths,
                                                     Capacityi[key])
                if condition4[1] is False and edge_crossings(
                        arc, Wind_turbinesi, central_platform_location,
                        Routing) is False and edge_crossings_area(
                            arc, Wind_turbinesi, central_platform_location,
                            Transmission)[0] is False:
                    Routing = []
                    for index1, path in enumerate(Paths):
                        if arc[0] == path[1]:
                            Paths[index1].remove(0)
                            break
                    for index2, path in enumerate(Paths):
                        if arc[1] == path[-1]:
                            break
                    Paths[index2] = Paths[index2] + Paths[index1]
                    Paths[index1] = []
                    Paths = [path for path in Paths if path != []]
                    for i in Paths:
                        for j in range(len(i) - 1):
                            Routing.append([i[j + 1], i[j]])
        Routes = []
        for index, path in enumerate(Paths):
            route = []
            for j in range(len(path) - 1):
                route.append([path[j], path[j + 1]])
            Routes.append(route)
        return Routes, Routing, Routing_red, Routing_green

    def Esau_Williams_Cable_Choice(Savingsi, Savingsi_finder,
                                   Crossingsi_finder, Wind_turbinesi, Routes,
                                   Routing, central_platform_location,
                                   Capacityi, Routing_red, Routing_green,
                                   Costi, Cable_Costi):
        total_update_red = []
        total_update_green = []
        while True:
            if Savingsi:
                Savingsi, Savingsi_finder, saving = pop_task(
                    Savingsi, Savingsi_finder)
            else:
                break
            if saving is None or saving[0] > 0:
                break
            arc = [saving[1], saving[2]]
            lines = turbinesinroute(Routes)
            if check_same_path(arc, lines) is False:
                condcap = dict()
                for key, value in list(Capacityi.items()):
                    condcap[key] = check_capacityEW(arc, lines, Capacityi[key])
                if condcap[1] is False:
                    if edge_crossings_area(
                            arc, Wind_turbinesi, central_platform_location,
                            Transmission)[0] is False and edge_crossings(
                                arc, Wind_turbinesi, central_platform_location,
                                Routing) is False:
                        Routing, Routes = mainroutine(arc, lines, Routing)
                        lines = turbinesinroute(Routes)
                        for indexl, line in enumerate(lines):
                            if arc[0] in line:
                                break
                        for turbine in lines[indexl]:
                            for n in Wind_turbinesi:
                                value = -(
                                    Costi[lines[indexl][0]][0] -
                                    Costi[turbine][n[0]]) * Cable_Costi[1]
                                arc1 = [lines[indexl][0], 0]
                                arc2 = [turbine, n[0]]
                                if turbine != n[0]:
                                    value += Crossing_penalty * (
                                        Crossingsi_finder[(arc2[0], arc2[1])] -
                                        Crossingsi_finder[(arc1[0], arc1[1])])
                                Savingsi, Savingsi_finder = add_task(
                                    Savingsi, Savingsi_finder, (turbine, n[0]),
                                    value)
                        heapify(Savingsi)
                if len(condcap
                       ) > 1 and condcap[1] is True and condcap[2] is False:
                    if edge_crossings_area(
                            arc, Wind_turbinesi, central_platform_location,
                            Transmission)[0] is False and edge_crossings(
                                arc, Wind_turbinesi, central_platform_location,
                                Routing) is False:
                        Routing_temp = deepcopy(Routing)
                        total_update_red_temp = []
                        Routing_temp, Routes_temp = mainroutine(
                            arc, lines, Routing_temp)
                        lines = turbinesinroute(Routes_temp)
                        for indexl, line in enumerate(lines):
                            if arc[0] in line:
                                break
                        update = []
                        for route in Routes_temp:
                            for i in range(0, len(route)):
                                if arc[1] in route[i]:
                                    index = Routes_temp.index(route)
                        elements = len(Routes_temp[index])
                        if elements == 1:
                            index1 = len(
                                Routes_temp[index][0]) - 1 - Capacityi[1]
                            for j in range(0, index1):
                                update.append([
                                    Routes_temp[index][0][j + 1],
                                    Routes_temp[index][0][j]
                                ])
                        connected_turbines = []
                        if elements > 1:
                            for i in range(0, elements):
                                for j in range(
                                        len(Routes_temp[index][elements - 1 -
                                                               i]) - 1, 0, -1):
                                    connected_turbines.append([
                                        Routes_temp[index][elements - 1 -
                                                           i][j - 1],
                                        Routes_temp[index][elements - 1 -
                                                           i][j], 1
                                    ])
                        for pair1 in connected_turbines:
                            for pair2 in connected_turbines:
                                if pair1[0] == pair2[1]:
                                    index = connected_turbines.index(pair2)
                                    connected_turbines[index][
                                        2] = connected_turbines[index][
                                            2] + pair1[2]
                        for pair in connected_turbines:
                            if pair[2] > Capacityi[1]:
                                update.append([pair[1], pair[0]])
                        total_update_red_temp = renew_update(
                            total_update_red, total_update_red_temp,
                            Routes_temp) + update
                        Routing_red_temp = []
                        for route in total_update_red_temp:
                            for z in range(0, len(route) - 1):
                                Routing_red_temp.append(
                                    [route[z], route[z + 1]])
                        new = -(cable_cost(
                            central_platform_location, Wind_turbinesi, Routing,
                            Routing_red, Routing_green, Cable_Costi) -
                                cable_cost(central_platform_location,
                                           Wind_turbinesi, Routing_temp,
                                           Routing_red_temp, Routing_green,
                                           Cable_Costi))
                        arc1 = [lines[indexl][0], 0]
                        new += Crossing_penalty * (
                            Crossingsi_finder[(arc[0], arc[1])] -
                            Crossingsi_finder[(arc1[0], arc1[1])])
                        Savingsi, Savingsi_finder = add_task(
                            Savingsi, Savingsi_finder, (arc[0], arc[1]), new)
                        Savingsi, Savingsi_finder, max_saving = pop_task(
                            Savingsi, Savingsi_finder)
                        if max_saving[0] == new:
                            Routes = Routes_temp
                            Routing = Routing_temp
                            Routing_red = Routing_red_temp
                            total_update_red = total_update_red_temp
                            lines = turbinesinroute(Routes)
                            for line in lines:
                                if arc[0] in line:
                                    indexl = lines.index(line)
                            for turbine in lines[indexl]:
                                for n in Wind_turbinesi:
                                    value = -(
                                        Costi[lines[indexl][0]][0] -
                                        Costi[turbine][n[0]]) * Cable_Costi[1]
                                    arc1 = [lines[indexl][0], 0]
                                    arc2 = [turbine, n[0]]
                                    if turbine != n[0]:
                                        value += Crossing_penalty * (
                                            Crossingsi_finder[
                                                (arc2[0], arc2[1])] -
                                            Crossingsi_finder[
                                                (arc1[0], arc1[1])])
                                    Savingsi, Savingsi_finder = add_task(
                                        Savingsi, Savingsi_finder,
                                        (turbine, n[0]), value)
                            heapify(Savingsi)
                        else:
                            Savingsi, Savingsi_finder = add_task(
                                Savingsi, Savingsi_finder,
                                (max_saving[1], max_saving[2]), max_saving[0])

                if len(condcap) > 2 and condcap[1] is True and condcap[
                        2] is True and condcap[3] is False:
                    if edge_crossings_area(
                            arc, Wind_turbinesi, central_platform_location,
                            Transmission)[0] is False and edge_crossings(
                                arc, Wind_turbinesi, central_platform_location,
                                Routing) is False:
                        Routing_temp = deepcopy(Routing)
                        total_update_red_temp = deepcopy(total_update_red)
                        total_update_green_temp = deepcopy(total_update_green)
                        Routing_temp, Routes_temp = mainroutine(
                            arc, lines, Routing_temp)
                        lines = turbinesinroute(Routes_temp)
                        for indexl, line in enumerate(lines):
                            if arc[0] in line:
                                break
                        update_red = []
                        update_green = []
                        for route in Routes_temp:
                            for i in range(0, len(route)):
                                if arc[1] in route[i]:
                                    index = Routes_temp.index(route)
                        elements = len(Routes_temp[index])
                        if elements == 1:
                            index1 = len(
                                Routes_temp[index][0]) - 1 - Capacityi[1]
                            index2 = len(
                                Routes_temp[index][0]) - 1 - Capacityi[2]
                            for j in range(index2, index1):
                                update_red.append([
                                    Routes_temp[index][0][j + 1],
                                    Routes_temp[index][0][j]
                                ])
                            for j in range(0, index2):
                                update_green.append([
                                    Routes_temp[index][0][j + 1],
                                    Routes_temp[index][0][j]
                                ])
                        connected_turbines = []
                        if elements > 1:
                            for i in range(0, elements):
                                for j in range(
                                        len(Routes_temp[index][elements - 1 -
                                                               i]) - 1, 0, -1):
                                    connected_turbines.append([
                                        Routes_temp[index][elements - 1 -
                                                           i][j - 1],
                                        Routes_temp[index][elements - 1 -
                                                           i][j], 1
                                    ])
                        for pair1 in connected_turbines:
                            for pair2 in connected_turbines:
                                if pair1[0] == pair2[1]:
                                    index = connected_turbines.index(pair2)
                                    connected_turbines[index][
                                        2] = connected_turbines[index][
                                            2] + pair1[2]
                        for pair in connected_turbines:
                            if pair[2] > Capacityi[2]:
                                update_green.append([pair[1], pair[0]])
                            elif Capacityi[1] < pair[2] <= Capacityi[2]:
                                update_red.append([pair[1], pair[0]])

                        for pair in update_red:
                            if pair not in total_update_red_temp:
                                total_update_red_temp.append(pair)
                        total_update_red_temp = [
                            x for x in total_update_red_temp
                            if x in Routing_temp
                        ]

                        for pair in update_green:
                            if pair not in total_update_green_temp:
                                total_update_green_temp.append(pair)
                        total_update_green_temp = [
                            x for x in total_update_green_temp
                            if x in Routing_temp
                        ]

                        total_update_red_temp = [
                            x for x in total_update_red_temp
                            if x not in total_update_green_temp
                        ]

                        Routing_red_temp = []
                        for route in total_update_red_temp:
                            for z in range(0, len(route) - 1):
                                Routing_red_temp.append(
                                    [route[z], route[z + 1]])
                        Routing_green_temp = []
                        for route in total_update_green_temp:
                            for z in range(0, len(route) - 1):
                                Routing_green_temp.append(
                                    [route[z], route[z + 1]])
                        arc1 = [lines[indexl][0], 0]
                        new += Crossing_penalty * (
                            Crossingsi_finder[arc[0], arc[1]] -
                            Crossingsi_finder[arc1[0], arc1[1]])
                        Savingsi, Savingsi_finder = add_task(
                            Savingsi, Savingsi_finder, (arc[0], arc[1]), new)
                        Savingsi, Savingsi_finder, max_saving = pop_task(
                            Savingsi, Savingsi_finder)
                        if max_saving[0] == new:
                            Routes = Routes_temp
                            Routing = Routing_temp
                            Routing_red = Routing_red_temp
                            Routing_green = Routing_green_temp
                            total_update_red = total_update_red_temp
                            total_update_green = total_update_green_temp
                            lines = turbinesinroute(Routes)
                            for line in lines:
                                if arc[0] in line:
                                    indexl = lines.index(line)
                            for turbine in lines[indexl]:
                                for n in Wind_turbinesi:
                                    if turbine != n[0]:
                                        value = -(Costi[lines[indexl][0]][0] -
                                                  Costi[turbine][n[0]]
                                                  ) * Cable_Costi[1]
                                        arc1 = [lines[indexl][0], 0]
                                        arc2 = [turbine, n[0]]
                                        value += Crossing_penalty * (
                                            Crossingsi_finder[arc2[0], arc2[1]]
                                            - Crossingsi_finder[arc1[0],
                                                                arc1[1]])
                                        Savingsi, Savingsi_finder = add_task(
                                            Savingsi, Savingsi_finder,
                                            (turbine, n[0]), value)
                            heapify(Savingsi)
                        else:
                            Savingsi, Savingsi_finder = add_task(
                                Savingsi, Savingsi_finder,
                                (max_saving[1], max_saving[2]), max_saving[0])
        return Routes, Routing, Routing_red, Routing_green

    def RouteOpt_Hybrid(Routing, central_platform_location, Costi, Capacityi,
                        Routes, Wind_turbinesi):
        Paths = []
        temp = []
        for route in Routes:
            cond = False
            for i in range(len(route) - 1, -1, -1):
                for pair in route:
                    if route[i][0] == pair[
                            0] and route[i] != pair and cond is False:
                        cond = True
                        for pair5 in route:
                            if pair[0] == pair5[0]:
                                path = [pair5[0], pair5[1]]
                                for pair6 in route:
                                    if pair6[0] == path[-1]:
                                        path.append(pair6[1])
                                Paths.append(path)
                        temp.append(route)
            if cond is False and len(route) <= Capacityi[1]:
                path = [route[0][0]]
                for pair in route:
                    path.append(pair[1])
                Paths.append(path)
            elif cond is False and len(route) > Capacityi[1]:
                index = len(route) - Capacityi[1]
                path = [route[index][0]]
                for i in range(index, len(route)):
                    path.append(route[i][1])
                Paths.append(path)
        before = []
        after = []

        def first(x):
            return x[0]

        for path in Paths:
            list_code = []
            index = Paths.index(path)
            path.reverse()
            cond = True
            i = 0
            while cond:
                for l in range(1, len(path)):
                    list_code.append([
                        Costi[path[l - 1]][path[l]] - Costi[path[l]][path[0]],
                        path[0], path[l]
                    ])
                s = max(list_code, key=first)
                if s[0] > 0 and edge_crossings(
                    [s[1], s[2]], Wind_turbinesi, central_platform_location,
                        Routing) is False and edge_crossings_area(
                            [s[1], s[2]], Wind_turbinesi,
                            central_platform_location,
                            Transmission)[0] is False:
                    for k in list_code:
                        if k == s:
                            lamd = list_code.index(k)
                            xmm = lamd + 1
                            path1 = path[:xmm]
                            path2 = path[xmm:]
                            path1.reverse()
                            if i == 0:
                                before.append(Paths[index])
                            i = 1
                            path = path1 + path2
                            Paths[index] = path
                            list_code = []
                            cond = True
                else:
                    list_code = []
                    cond = False
                    if i == 1:
                        after.append(Paths[index])

        for path in before:
            for i in range(0, len(path) - 1):
                if [path[i], path[i + 1]] in Routing:
                    Routing.remove([path[i], path[i + 1]])
                elif [path[i + 1], path[i]] in Routing:
                    Routing.remove([path[i + 1], path[i]])
        for path in after:
            for i in range(0, len(path) - 1):
                Routing.append([path[i], path[i + 1]])
        return Routes, Routing

    def renew_update(total_update, total_update_temp, Paths_temp):
        indeces = []
        for indexerase, route in enumerate(total_update):
            for turbine in route:
                if turbine != 0:
                    for pair in total_update_temp:
                        if pair[0] != 0 and pair[1] != 0:
                            same1 = [turbine, pair[0]]
                            same2 = [turbine, pair[1]]
                            if check_same_path(
                                    same1,
                                    Paths_temp) is True or check_same_path(
                                        same2, Paths_temp) is True:
                                if indexerase not in indeces:
                                    indeces.append(indexerase)
        if indeces:
            for i in indeces:
                total_update[i] = []
        for pair in total_update[:]:
            if not pair:
                total_update.remove(pair)
        return total_update

    def initial_values(NT, Wind_turbines, central_platform_location):
        Costi = [[0 for i in range(NT + 1)] for j in range(NT + 1)]
        set_cost_matrix(Costi, Wind_turbines, central_platform_location)
        distancefromsubstationi = []
        for i in range(len(Costi[0]) - 1):
            distancefromsubstationi.append([0, i + 1, Costi[0][i + 1]])
        Wind_turbinesi = []
        return Wind_turbinesi, Costi, distancefromsubstationi

    def initial_routes(Wind_turbinesi):
        Routing_greeni = []
        Routing_redi = []
        Routingi = []
        Routesi = []
        for WT in Wind_turbinesi:
            Routingi.append([WT[0], 0])
            Routesi.append([[0, WT[0]]])
        return Routesi, Routingi, Routing_redi, Routing_greeni

    def check_same_path(arc, Paths):
        same_path = False
        for path in Paths:
            if arc[0] in path and arc[1] in path:
                same_path = True
                break
        return same_path

    # Subroutine 5, check if turbine u has only one neighbor in Routing
    def one_neighbor(turbine, Paths):
        more_than_one = False
        for path in Paths:
            if turbine in path and turbine != path[-1]:
                more_than_one = True
                break
        return more_than_one

    def costi(Wind_turbinesi, central_platform_location):
        Cost0i = []
        Costij = []
        for i in Wind_turbinesi:
            Cost0i.append([
                0, i[0],
                hypot(central_platform_location[0] - i[1],
                      central_platform_location[1] - i[2])
            ])
            for j in Wind_turbinesi:
                if i != j:
                    Costij.append(
                        [i[0], j[0],
                         hypot(i[1] - j[1], i[2] - j[2])])
        return Cost0i, Costij

    def savingsi(Cost0i, Costij, Wind_turbinesi, Cable_Cost1,
                 central_platform_location, Area, Crossing_penalty):
        Savingsi = []
        Savingsi_finder = {}
        Crossingsi_finder = {}
        counter = 0
        for i in list(zip(*Wind_turbinesi))[0]:
            k = Cost0i[counter]
            step = (len(Wind_turbinesi) - 1) * counter
            for j in range(step, step + len(Wind_turbinesi) - 1):
                saving = -(k[2] - Costij[j][2]) * Cable_Cost1
                arc1 = [i, 0]
                arc2 = [i, Costij[j][1]]
                crossings_arc1 = edge_crossings_area(
                    arc1, Wind_turbinesi, central_platform_location, Area)[1]
                crossings_arc2 = edge_crossings_area(
                    arc2, Wind_turbinesi, central_platform_location, Area)[1]
                Crossingsi_finder[(arc1[0], arc1[1])] = crossings_arc1
                Crossingsi_finder[(arc2[0], arc2[1])] = crossings_arc2
                saving += Crossing_penalty * (crossings_arc2 - crossings_arc1)
                if saving < 0:
                    add_task(Savingsi, Savingsi_finder, (i, Costij[j][1]),
                             saving)
            counter += 1
        return Savingsi, Savingsi_finder, Crossingsi_finder

    def add_task(Savings, entry_finder, task, priority):
        """Add a new task or update the priority of an existing task"""
        if task in entry_finder:
            entry_finder = remove_task(entry_finder, task)
        entry = [priority, task[0], task[1]]
        entry_finder[(task[0], task[1])] = entry
        heappush(Savings, entry)
        return Savings, entry_finder

    def remove_task(entry_finder, task):
        entry = entry_finder.pop(task)
        entry[0] = REMOVED
        return entry_finder

    def pop_task(Savings, entry_finder):
        while Savings:
            saving = heappop(Savings)
            if saving[0] is not REMOVED:
                del entry_finder[(saving[1], saving[2])]
                return Savings, entry_finder, saving

    def set_cost_matrix(Cost, Wind_turbines, central_platform_location):
        Cost[0][0] = float('inf')
        for i in Wind_turbines:
            Cost[0][i[0]] = hypot(central_platform_location[0] - i[1],
                                  central_platform_location[1] - i[2])
            Cost[i[0]][0] = hypot(central_platform_location[0] - i[1],
                                  central_platform_location[1] - i[2])
            for j in Wind_turbines:
                if i == j:
                    Cost[i[0]][j[0]] = float('inf')
                else:
                    Cost[i[0]][j[0]] = hypot(i[1] - j[1], i[2] - j[2])

    def turbinesinroute(Routes):
        lines = [[] for _ in range(len(Routes))]
        for route in Routes:
            index = Routes.index(route)
            for pair in route:
                lines[index].append(pair[1])
        return lines

    def check_capacityEW(arc, Paths, Capacity):
        cap_exceeded = False
        turbines_in_branch = 0
        for path in Paths:
            if arc[0] in path or arc[1] in path:
                turbines_in_branch += len(path)
                if turbines_in_branch > Capacity:
                    cap_exceeded = True
                    break
        return cap_exceeded

    def check_capacity(arc, Paths, Capacity):
        cap_exceeded = False
        turbines_in_branch = 0
        for path in Paths:
            if arc[0] in path or arc[1] in path:
                turbines_in_branch += len(path) - 1
                if turbines_in_branch > Capacity:
                    cap_exceeded = True
                    break
        return cap_exceeded

    def edge_crossings(arc, Wind_turbines, central_platform_location, Routing):
        x1, y1 = give_coordinates(arc[0], Wind_turbines,
                                  central_platform_location)
        x2, y2 = give_coordinates(arc[1], Wind_turbines,
                                  central_platform_location)
        intersection = False
        # Left - 0
        # Right - 1
        # Colinear - 2
        for route in Routing:
            if arc[0] not in route:
                x3, y3 = give_coordinates(route[0], Wind_turbines,
                                          central_platform_location)
                x4, y4 = give_coordinates(route[1], Wind_turbines,
                                          central_platform_location)
                counter = 0
                Area = [0, 0, 0, 0]
                Position = [0, 0, 0, 0]
                Area[0] = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)
                Area[1] = (x2 - x1) * (y4 - y1) - (x4 - x1) * (y2 - y1)
                Area[2] = (x4 - x3) * (y1 - y3) - (x1 - x3) * (y4 - y3)
                Area[3] = (x4 - x3) * (y2 - y3) - (x2 - x3) * (y4 - y3)
                for i in range(4):
                    if Area[i] > 0:
                        Position[i] = 0
                    elif Area[i] < 0:
                        Position[i] = 1
                    else:
                        Position[i] = 2
                        counter += 1
                if Position[0] != Position[1] and Position[2] != Position[
                        3] and counter <= 1:
                    intersection = True
                    break
        return intersection

    def edge_crossings_area(arc, Wind_turbines, central_platform_location,
                            Area_cross):
        x1, y1 = give_coordinates(arc[0], Wind_turbines,
                                  central_platform_location)
        x2, y2 = give_coordinates(arc[1], Wind_turbines,
                                  central_platform_location)
        intersection = False
        crossings = 0
        for area in Area_cross:
            counter = 0
            x3, y3 = area[0][0], area[0][1]
            x4, y4 = area[1][0], area[1][1]
            Area = [0, 0, 0, 0]
            Position = [0, 0, 0, 0]
            Area[0] = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)
            Area[1] = (x2 - x1) * (y4 - y1) - (x4 - x1) * (y2 - y1)
            Area[2] = (x4 - x3) * (y1 - y3) - (x1 - x3) * (y4 - y3)
            Area[3] = (x4 - x3) * (y2 - y3) - (x2 - x3) * (y4 - y3)
            for i in range(4):
                if Area[i] > 0:
                    Position[i] = 0
                elif Area[i] < 0:
                    Position[i] = 1
                else:
                    Position[i] = 2
                    counter += 1
            if Position[0] != Position[1] and Position[2] != Position[
                    3] and counter <= 1:
                intersection = True
                crossings += 1
        return intersection, crossings

    # Plotting+Cable_length
    def plotting(central_platform_location1, Wind_turbines1, Routing,
                 Routing_red, Routing_green, Cable_Costi):
        central_platform_location1_1 = [[
            0, central_platform_location1[0], central_platform_location1[1]
        ]]
        Full_List = central_platform_location1_1 + Wind_turbines1
        Routing_blue = [i for i in Routing if i not in Routing_red]
        Routing_blue = [i for i in Routing_blue if i not in Routing_green]
        cable_length1blue = 0
        arcs1 = []
        arcs2 = []
        for i in Routing_blue:
            for j in Full_List:
                if j[0] == i[0]:
                    arcs1.append([j[1], j[2]])
                if j[0] == i[1]:
                    arcs2.append([j[1], j[2]])
        for i in range(len(arcs1)):
            arcs1.insert(2 * i + 1, arcs2[i])
        for j in range(len(arcs1) - len(Routing_blue)):
            cable_length1blue += hypot(arcs1[2 * j][0] - arcs1[2 * j + 1][0],
                                       arcs1[2 * j][1] - arcs1[2 * j + 1][1])
        cable_cost = Cable_Costi[1] * cable_length1blue
        cable_length = cable_length1blue

        if len(Cable_Costi) == 2:
            cable_length1red = 0
            arcs1 = []
            arcs2 = []
            for i in Routing_red:
                for j in Full_List:
                    if j[0] == i[0]:
                        arcs1.append([j[1], j[2]])
                    if j[0] == i[1]:
                        arcs2.append([j[1], j[2]])
            for i in range(len(arcs1)):
                arcs1.insert(2 * i + 1, arcs2[i])
            for j in range(len(arcs1) - len(Routing_red)):
                cable_length1red += hypot(
                    arcs1[2 * j][0] - arcs1[2 * j + 1][0],
                    arcs1[2 * j][1] - arcs1[2 * j + 1][1])
            cable_cost = Cable_Costi[1] * cable_length1blue + Cable_Costi[
                2] * cable_length1red
            cable_length = cable_length1blue + cable_length1red

        if len(Cable_Costi) == 3:

            cable_length1red = 0
            arcs1 = []
            arcs2 = []
            for i in Routing_red:
                for j in Full_List:
                    if j[0] == i[0]:
                        arcs1.append([j[1], j[2]])
                    if j[0] == i[1]:
                        arcs2.append([j[1], j[2]])
            for i in range(len(arcs1)):
                arcs1.insert(2 * i + 1, arcs2[i])
            for j in range(len(arcs1) - len(Routing_red)):
                cable_length1red += hypot(
                    arcs1[2 * j][0] - arcs1[2 * j + 1][0],
                    arcs1[2 * j][1] - arcs1[2 * j + 1][1])

            cable_length1green = 0
            arcs1 = []
            arcs2 = []
            for i in Routing_green:
                for j in Full_List:
                    if j[0] == i[0]:
                        arcs1.append([j[1], j[2]])
                    if j[0] == i[1]:
                        arcs2.append([j[1], j[2]])
            for i in range(len(arcs1)):
                arcs1.insert(2 * i + 1, arcs2[i])
            for j in range(len(arcs1) - len(Routing_green)):
                cable_length1green += hypot(
                    arcs1[2 * j][0] - arcs1[2 * j + 1][0],
                    arcs1[2 * j][1] - arcs1[2 * j + 1][1])
            cable_length = cable_length1blue + cable_length1red + cable_length1green
            cable_cost = Cable_Costi[1] * cable_length1blue + Cable_Costi[
                2] * cable_length1red + Cable_Costi[3] * cable_length1green
        return cable_cost, cable_length

    def cable_cost(central_platform_location, Wind_turbinesi, Routing,
                   Routing_red, Routing_green, Cable_Costi):
        Routing_blue = [i for i in Routing if i not in Routing_red]
        Routing_blue = [i for i in Routing_blue if i not in Routing_green]
        cable_length1blue = 0
        for route in Routing_blue:
            x1, y1 = give_coordinates(route[0], Wind_turbinesi,
                                      central_platform_location)
            x2, y2 = give_coordinates(route[1], Wind_turbinesi,
                                      central_platform_location)
            cable_length1blue += hypot(x2 - x1, y2 - y1)
        cable_cost = Cable_Costi[1] * cable_length1blue

        if len(Cable_Costi) == 2:
            cable_length1red = 0
            for route in Routing_red:
                x1, y1 = give_coordinates(route[0], Wind_turbinesi,
                                          central_platform_location)
                x2, y2 = give_coordinates(route[1], Wind_turbinesi,
                                          central_platform_location)
                cable_length1red += hypot(x2 - x1, y2 - y1)
            cable_cost = Cable_Costi[1] * cable_length1blue + Cable_Costi[
                2] * cable_length1red

        if len(Cable_Costi) == 3:
            cable_length1red = 0
            for route in Routing_red:
                x1, y1 = give_coordinates(route[0], Wind_turbinesi,
                                          central_platform_location)
                x2, y2 = give_coordinates(route[1], Wind_turbinesi,
                                          central_platform_location)
                cable_length1red += hypot(x2 - x1, y2 - y1)
            cable_length1green = 0
            for route in Routing_green:
                x1, y1 = give_coordinates(route[0], Wind_turbinesi,
                                          central_platform_location)
                x2, y2 = give_coordinates(route[1], Wind_turbinesi,
                                          central_platform_location)
                cable_length1green += hypot(x2 - x1, y2 - y1)
            cable_cost = Cable_Costi[1] * cable_length1blue + Cable_Costi[
                2] * cable_length1red + Cable_Costi[3] * (cable_length1green)
        return cable_cost

    # Submethods return x and y coordinates of a turbine if it's ID is known. The OHVS must also be included
    def give_coordinates(turbineID, turbines, central_platform_location):
        if turbineID == 0:
            x = central_platform_location[0]
            y = central_platform_location[1]
        else:
            turbine = turbines[turbineID - 1]
            x = turbine[1]
            y = turbine[2]
        return x, y

    return set_cable_topology(NT, WT_List, central_platform_locations,
                              Cable_List)