diff --git a/edwin/__init__.py b/edwin/__init__.py index 2198dce47e2823a7acc97a9cfa97ca34d48fee61..b325f3b6db0997eb03ed3fc50895062d0f59017f 100644 --- a/edwin/__init__.py +++ b/edwin/__init__.py @@ -1,3 +1,3 @@ # 'filled_by_setup.py' -__version__ = 'c6c857252e379ba76e90ff3f5bf58f9efe828ee' -__release__ = 'c6c857252e379ba76e90ff3f5bf58f9efe828ee' +__version__ = '0.0.0' +__release__ = '0.0.0' diff --git a/edwin/c_mst.py b/edwin/c_mst.py index f32405d552d7ef19a9bcf4c44c40eece9dd944f4..23720f81ade3b84ca7898d1dca926b2e1522a656 100644 --- a/edwin/c_mst.py +++ b/edwin/c_mst.py @@ -5,8 +5,8 @@ Created on Thu May 28 08:12:54 2020 @author: juru """ import numpy as np -from intersection_checker import intersection_checker import matplotlib.pyplot as plt +from edwin.intersection_checker import intersection_checker def capacitated_spanning_tree(X=[], Y=[], option=3, UL=100, Inters_const=True, max_it=20000): diff --git a/edwin/c_mst_cables.py b/edwin/c_mst_cables.py index db18de66217cd62b028594572961a2717307701e..a34aa34a7c0701ab267581e68c5eb36a917342bd 100644 --- a/edwin/c_mst_cables.py +++ b/edwin/c_mst_cables.py @@ -8,11 +8,11 @@ Created on Thu Jun 4 08:07:37 2020 import numpy as np import networkx as nx import matplotlib.pyplot as plt -from c_mst import capacitated_spanning_tree import time +from edwin.c_mst import capacitated_spanning_tree -def cmst_cables(X=[], Y=[], T=[], Cables=[], plot=True): +def cmst_cables(X=[], Y=[], T=[], Cables=[], plot=False): """ Assigns cables to the obtained C-MST in previous stage @@ -63,27 +63,31 @@ def cmst_cables(X=[], Y=[], T=[], Cables=[], plot=True): for k in range(T_d.shape[0]): T_d[k, 4] = (T_d[k, 2] / 1000) * Cables[T_d.astype(int)[k, 3], 2] if plot: - plt.figure() - plt.plot(X[1:], Y[1:], 'r+', markersize=10, label='Turbines') - plt.plot(X[0], Y[0], 'ro', markersize=10, label='OSS') - for i in range(len(X)): - plt.text(X[i] + 50, Y[i] + 50, str(i + 1)) - colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'bg', 'gr', 'rc', 'cm'] - for i in range(Cables.shape[0]): - index = T_d[:, 3] == i - if index.any(): - n1xs = X[T_d[index, 0].astype(int) - 1].ravel().T - n2xs = X[T_d[index, 1].astype(int) - 1].ravel().T - n1ys = Y[T_d[index, 0].astype(int) - 1].ravel().T - n2ys = Y[T_d[index, 1].astype(int) - 1].ravel().T - xs = np.vstack([n1xs, n2xs]) - ys = np.vstack([n1ys, n2ys]) - plt.plot(xs, ys, '{}'.format(colors[i])) - plt.plot([], [], '{}'.format(colors[i]), label='Cable: {} mm2'.format(Cables[i, 0])) - plt.legend() + plot_network(X, Y, Cables, T_d) return T_d +def plot_network(X, Y, Cables, T_d): + plt.figure() + plt.plot(X[1:], Y[1:], 'r+', markersize=10, label='Turbines') + plt.plot(X[0], Y[0], 'ro', markersize=10, label='OSS') + for i in range(len(X)): + plt.text(X[i] + 50, Y[i] + 50, str(i + 1)) + colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'bg', 'gr', 'rc', 'cm'] + for i in range(Cables.shape[0]): + index = T_d[:, 3] == i + if index.any(): + n1xs = X[T_d[index, 0].astype(int) - 1].ravel().T + n2xs = X[T_d[index, 1].astype(int) - 1].ravel().T + n1ys = Y[T_d[index, 0].astype(int) - 1].ravel().T + n2ys = Y[T_d[index, 1].astype(int) - 1].ravel().T + xs = np.vstack([n1xs, n2xs]) + ys = np.vstack([n1ys, n2ys]) + plt.plot(xs, ys, '{}'.format(colors[i])) + plt.plot([], [], '{}'.format(colors[i]), label='Cable: {} mm2'.format(Cables[i, 0])) + plt.legend() + + if __name__ == "__main__": t = time.time() X = [387100, 383400, 383400, 383900, 383200, 383200, 383200, 383200, 383200, 383200, 383200, 383200, 383300, 384200, 384200, 384100, 384000, 383800, 383700, 383600, 383500, 383400, 383600, 384600, 385400, 386000, 386100, 386200, 386300, 386500, 386600, 386700, 386800, 386900, 387000, 387100, 387200, 383900, 387400, 387500, 387600, 387800, 387900, 388000, 387600, 386800, 385900, 385000, 384100, 384500, 384800, 385000, 385100, 385200, 385400, 385500, 385700, 385800, 385900, 385900, 385500, 385500, 386000, 386200, 386200, 384500, 386200, 386700, 386700, 386700, 384300, 384400, 384500, 384600, 384300, 384700, 384700, 384700, 385500, 384300, 384300] @@ -102,7 +106,7 @@ if __name__ == "__main__": print("Feasibility: {feasible1}".format(feasible1=feasible)) if feasible: - T_cables = cmst_cables(X, Y, T, Cables) + T_cables = cmst_cables(X, Y, T, Cables, plot=True) print("The total cost of the system is {value:.2f} Euros".format(value=T_cables[:, -1].sum())) elapsed = time.time() - t print("The total time is {timep: .2f} s".format(timep=elapsed)) diff --git a/edwin/collection_system.py b/edwin/collection_system.py index 06a55d257dc533559f64ccb0c9aa73faf6154451..ee309855dcfd0e2c2899f4faf898928dc8c98045 100644 --- a/edwin/collection_system.py +++ b/edwin/collection_system.py @@ -5,8 +5,8 @@ Created on Mon Jun 22 10:59:47 2020 @author: juru """ import numpy as np -from c_mst import capacitated_spanning_tree -from c_mst_cables import cmst_cables +from edwin.c_mst import capacitated_spanning_tree +from edwin.c_mst_cables import cmst_cables def collection_system(X=[], Y=[], option=3, Inters_const=True, max_it=20000, Cables=[], plot=False): diff --git a/edwin/intersection_checker.py b/edwin/intersection_checker.py index c70dc51f1e132fc4cb22ebc4aa7c0571481b53f3..54adefa5ca25016a1ccdba806e1768f54707ef50 100644 --- a/edwin/intersection_checker.py +++ b/edwin/intersection_checker.py @@ -6,7 +6,7 @@ Created on Fri May 29 10:08:54 2020 """ import numpy as np -from two_lines_intersecting import two_lines_intersecting +from edwin.two_lines_intersecting import two_lines_intersecting def intersection_checker(pos_potential_edge, edges_tot, mst_edges, X, Y, Inters_const): diff --git a/edwin/method.py b/edwin/method.py deleted file mode 100644 index e255c05bf364dc3f970e4b0ca2c7705a3f669764..0000000000000000000000000000000000000000 --- a/edwin/method.py +++ /dev/null @@ -1,45 +0,0 @@ -from abc import ABC, abstractmethod - - -class Method(ABC): - def __init__(self, **kwargs): - return - - @abstractmethod - def _design(geometry, financial, electrical, contraints, **settings): - ''' - - Parameters - ---------- - **settings : dict - Configuration of algorithm. - - Returns - ------- - dictionary of connections. - - ''' - - -class HeuristicMethod(Method): - def __init__(self, **kwargs): - Method.__init__(self) - - def _design(self, geometry, financial, electrical, contraints, **settings): - return {'hello from': 'HeuristicMethod'} - - -class MetaHeuristicMethod(Method): - def __init__(self, **kwargs): - Method.__init__(self) - - def _design(self, geometry, financial, electrical, contraints, **settings): - return {'hello from': 'MetaHeuristicMethod'} - - -class GlobalMethod(Method): - def __init__(self, **kwargs): - Method.__init__(self) - - def _design(self, geometry, financial, electrical, contraints, **settings): - return {'hello from': 'GlobalMethod'} diff --git a/edwin/tests/test_wind_farm_network.py b/edwin/tests/test_wind_farm_network.py index d663ed60718a93e92553cad8ce825d327d1b72ad..bc45abd5e6634bf2c4df1fde38556665bbfed16c 100644 --- a/edwin/tests/test_wind_farm_network.py +++ b/edwin/tests/test_wind_farm_network.py @@ -1,22 +1,80 @@ -from edwin.wind_farm_network import WindFarmNetwork -from edwin.method import MetaHeuristicMethod +import numpy as np +from edwin.wind_farm_network import WindFarmNetwork, HeuristicDriver +import numpy.testing as npt -method = MetaHeuristicMethod() -geometry = {'turbine_coordinates': {'x': [1, 1, 1, 2, 2, 2, 3, 3, 3], - 'y': [1, 2, 3, 2, 3, 4, 3, 4, 5], }, - 'sub_station_coordinates': {'x': [2.5], - 'y': [3.5], }} -financial = {} -electrical = {} -constraints = {'crossing': False, - 'tree': False, - 'thermal capacity': False, - 'number of main feeders': False} -settings = {} -wfn = WindFarmNetwork(method=method, geometry=geometry, financial=financial, - electrical=electrical, constraints=constraints) +layout = dict(x=np.array([0., 2000., 4000., 6000., + 8000., 498.65600569, 2498.65600569, 4498.65600569, + 6498.65600569, 8498.65600569, 997.31201137, 2997.31201137, + 4997.31201137, 11336.25662483, 8997.31201137, 1495.96801706, + 3495.96801706, 5495.96801706, 10011.39514341, 11426.89538545, + 1994.62402275, 3994.62402275, 5994.62402275, 7994.62402275, + 10588.90471566]), + y=np.array([0., 0., 0., 0., + 0., 2000., 2000., 2000., + 2000., 2000., 4000., 4000., + 4000., 6877.42528387, 4000., 6000., + 6000., 6000., 3179.76530545, 5953.63051694, + 8000., 8000., 8000., 8000., + 4734.32972738])) +settings = {'option': 3, + 'Inters_const': True, + 'max_it': 20000} +cables = np.array([[500, 3, 100000], [800, 5, 150000], [1000, 10, 250000]]) +wfn = WindFarmNetwork(layout=layout, + driver=HeuristicDriver(**settings), + cables=cables) + +T_ref = np.asarray([[1.00000000e+00, 2.00000000e+00, 2.00000000e+03, 1.00000000e+00, + 3.00000000e+05], + [2.00000000e+00, 3.00000000e+00, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [3.00000000e+00, 4.00000000e+00, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [4.00000000e+00, 5.00000000e+00, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [1.00000000e+00, 6.00000000e+00, 2.06122726e+03, 2.00000000e+00, + 5.15306815e+05], + [6.00000000e+00, 7.00000000e+00, 2.00000000e+03, 2.00000000e+00, + 5.00000000e+05], + [7.00000000e+00, 8.00000000e+00, 2.00000000e+03, 2.00000000e+00, + 5.00000000e+05], + [8.00000000e+00, 9.00000000e+00, 2.00000000e+03, 2.00000000e+00, + 5.00000000e+05], + [9.00000000e+00, 1.00000000e+01, 2.00000000e+03, 2.00000000e+00, + 5.00000000e+05], + [1.00000000e+01, 1.90000000e+01, 1.91839148e+03, 1.00000000e+00, + 2.87758722e+05], + [1.90000000e+01, 1.50000000e+01, 1.30428124e+03, 0.00000000e+00, + 1.30428124e+05], + [1.90000000e+01, 2.50000000e+01, 1.65836903e+03, 0.00000000e+00, + 1.65836903e+05], + [2.50000000e+01, 2.00000000e+01, 1.47950085e+03, 0.00000000e+00, + 1.47950085e+05], + [2.00000000e+01, 1.40000000e+01, 9.28230659e+02, 0.00000000e+00, + 9.28230659e+04], + [1.00000000e+00, 1.10000000e+01, 4.12245452e+03, 2.00000000e+00, + 1.03061363e+06], + [1.10000000e+01, 1.20000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [1.20000000e+01, 1.30000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [1.10000000e+01, 1.60000000e+01, 2.06122726e+03, 2.00000000e+00, + 5.15306815e+05], + [1.60000000e+01, 1.70000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [1.70000000e+01, 1.80000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [1.60000000e+01, 2.10000000e+01, 2.06122726e+03, 1.00000000e+00, + 3.09184089e+05], + [2.10000000e+01, 2.20000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [2.20000000e+01, 2.30000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05], + [2.30000000e+01, 2.40000000e+01, 2.00000000e+03, 0.00000000e+00, + 2.00000000e+05]]) def test_wind_farm_network(): - result_dict = wfn.design(settings) - assert result_dict == {'hello from': 'MetaHeuristicMethod'} + cost, state = wfn.design() + assert 7495208.24825092 == cost + npt.assert_allclose(wfn.T, T_ref) diff --git a/edwin/wind_farm_network.py b/edwin/wind_farm_network.py index 0ee2626c8b0e3a77e1e69c5598565957fb9e5d7e..883fe6a9ea17e0e66bfe648985fb989f8bd745eb 100644 --- a/edwin/wind_farm_network.py +++ b/edwin/wind_farm_network.py @@ -1,48 +1,105 @@ -import matplotlib.pyplot as plt +from abc import ABC, abstractmethod +from edwin.collection_system import collection_system +from edwin.c_mst_cables import plot_network +import pandas as pd +import numpy as np + + +class Driver(ABC): + @abstractmethod + def run(): + ''' + + ''' + + +class HeuristicDriver(Driver): + def __init__(self, option=3, Inters_const=True, max_it=20000): + self.option = option + self.Inters_const = Inters_const + self.max_it = max_it + Driver.__init__(self) + + def run(self): + T, cables_cost = collection_system(self.wfn.x, + self.wfn.y, + self.option, + self.Inters_const, + self.max_it, + self.wfn.cables) + return T, cables_cost class WindFarmNetwork(): - def __init__(self, method, geometry, financial, electrical, constraints): - self.method = method - self.geometry = geometry - self.financial = financial - self.electrical = electrical - self.constraints = constraints - - def design(self, settings): - self.settings = settings - return self.method._design(self.geometry, self.financial, self.electrical, - self.constraints, **settings) + def __init__(self, layout, driver=HeuristicDriver(), cables=[]): + self.layout = layout + for k, v in layout.items(): + setattr(self, k, v) + self.driver = driver + self.cables = cables + self.state = None + self.T = None + self.columns = ['from_node', 'to_node', 'cable_length', 'cable_type', 'cable_cost'] + self.setup() + + def setup(self): + setattr(self.driver, 'wfn', self) + + def design(self): + T, cost = self.driver.run() + state = pd.DataFrame(T, columns=self.columns) + state = state.astype({'from_node': int, + 'to_node': int, + 'cable_type': int}) + self.T = T + self.cost = cost + self.state = state + return cost, state def plot(self): - x = self.geometry['turbine_coordinates']['x'] - y = self.geometry['turbine_coordinates']['y'] - xss = self.geometry['sub_station_coordinates']['x'] - yss = self.geometry['sub_station_coordinates']['y'] - plt.plot(x, y, '.') - plt.plot(xss, yss, 'or', label='Sub station') - plt.legend() + if self.state is not None: + self.design() + plot_network(self.x, self.y, self.cables, self.T) + + +class Constraints(dict): + def __init__(self, **kwargs): + dict.__init__(self, {'crossing': False, + 'tree': False, + 'thermal_capacity': False, + 'number_of_main_feeders': False}) + self.update(kwargs) def main(): if __name__ == '__main__': - from edwin.method import MetaHeuristicMethod - method = MetaHeuristicMethod() - geometry = {'turbine_coordinates': {'x': [1, 1, 1, 2, 2, 2, 3, 3, 3], - 'y': [1, 2, 3, 2, 3, 4, 3, 4, 5], }, - 'sub_station_coordinates': {'x': [2.5], - 'y': [3.5], }} - financial = {} - electrical = {} - constraints = {'crossing': False, - 'tree': False, - 'thermal capacity': False, - 'number of main feeders': False} - settings = {} - wfn = WindFarmNetwork(method=method, geometry=geometry, financial=financial, - electrical=electrical, constraints=constraints) - result_dict = wfn.design(settings) - print(result_dict) + # layout = {'x': [473095,471790,471394,470998,470602,470207,469811,472523,469415,472132,471742,471351,470960,470569,470179,469788,472866,472480,472094,471708,471322,470937,470551,473594,473213,472833,472452,472071,471691,471310,470929], + # 'y': [5992345,5991544,5991899,5992252,5992607,5992960,5993315,5991874,5993668,5992236,5992598,5992960,5993322,5993684,5994047,5994409,5992565,5992935,5993306,5993675,5994045,5994416,5994786,5992885,5993264,5993643,5994021,5994400,5994779,5995156,5995535]} + layout = dict(x=np.array([0., 2000., 4000., 6000., + 8000., 498.65600569, 2498.65600569, 4498.65600569, + 6498.65600569, 8498.65600569, 997.31201137, 2997.31201137, + 4997.31201137, 11336.25662483, 8997.31201137, 1495.96801706, + 3495.96801706, 5495.96801706, 10011.39514341, 11426.89538545, + 1994.62402275, 3994.62402275, 5994.62402275, 7994.62402275, + 10588.90471566]), + y=np.array([0., 0., 0., 0., + 0., 2000., 2000., 2000., + 2000., 2000., 4000., 4000., + 4000., 6877.42528387, 4000., 6000., + 6000., 6000., 3179.76530545, 5953.63051694, + 8000., 8000., 8000., 8000., + 4734.32972738])) + # layout = {'x': [387100, 383400, 383400, 383900, 383200, 383200, 383200, 383200, 383200, 383200, 383200, 383200, 383300, 384200, 384200, 384100, 384000, 383800, 383700, 383600, 383500, 383400, 383600, 384600, 385400, 386000, 386100, 386200, 386300, 386500, 386600, 386700, 386800, 386900, 387000, 387100, 387200, 383900, 387400, 387500, 387600, 387800, 387900, 388000, 387600, 386800, 385900, 385000, 384100, 384500, 384800, 385000, 385100, 385200, 385400, 385500, 385700, 385800, 385900, 385900, 385500, 385500, 386000, 386200, 386200, 384500, 386200, 386700, 386700, 386700, 384300, 384400, 384500, 384600, 384300, 384700, 384700, 384700, 385500, 384300, 384300], + # 'y': [6109500, 6103800, 6104700, 6105500, 6106700, 6107800, 6108600, 6109500, 6110500, 6111500, 6112400, 6113400, 6114000, 6114200, 6115100, 6115900, 6116700, 6118400, 6119200, 6120000, 6120800, 6121800, 6122400, 6122000, 6121700, 6121000, 6120000, 6119100, 6118100, 6117200, 6116200, 6115300, 6114300, 6113400, 6112400, 6111500, 6110700, 6117600, 6108900, 6108100, 6107400, 6106300, 6105200, 6104400, 6103600, 6103600, 6103500, 6103400, 6103400, 6104400, 6120400, 6119500, 6118400, 6117400, 6116500, 6115500, 6114600, 6113500, 6112500, 6111500, 6105400, 6104200, 6110400, 6109400, 6108400, 6121300, 6107500, 6106400, 6105300, 6104400, 6113300, 6112500, 6111600, 6110800, 6110100, 6109200, 6108400, 6107600, 6106500, 6106600, 6105000]} + + settings = {'option': 3, + 'Inters_const': True, + 'max_it': 20000} + cables = np.array([[500, 3, 100000], [800, 5, 150000], [1000, 10, 250000]]) + wfn = WindFarmNetwork(layout=layout, + driver=HeuristicDriver(**settings), + cables=cables) + cost, state = wfn.design() wfn.plot()