Passed
Pull Request — master (#202)
by Grega
01:02
created

NiaPy.algorithms.basic.hs   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 257
Duplicated Lines 6.23 %

Importance

Changes 0
Metric Value
eloc 63
dl 16
loc 257
rs 10
c 0
b 0
f 0
wmc 23

12 Methods

Rating   Name   Duplication   Size   Complexity  
A HarmonySearchV1.algorithmInfo() 0 8 1
A HarmonySearch.improvize() 0 15 4
A HarmonySearch.algorithmInfo() 0 8 1
A HarmonySearch.typeParameters() 16 16 5
A HarmonySearchV1.bw() 0 10 1
A HarmonySearchV1.setParameters() 0 13 1
A HarmonySearch.bw() 0 10 1
A HarmonySearch.adjustment() 0 11 1
A HarmonySearch.initPopulation() 0 16 1
A HarmonySearch.setParameters() 0 16 2
A HarmonySearch.runIteration() 0 23 2
A HarmonySearchV1.typeParameters() 0 17 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
# encoding=utf8
2
# pylint: disable=mixed-indentation, trailing-whitespace, multiple-statements, attribute-defined-outside-init, logging-not-lazy, arguments-differ, line-too-long, unused-argument, bad-continuation
3
import logging
4
5
from numpy import argmax, log, exp, full
6
7
from NiaPy.algorithms.algorithm import Algorithm
8
9
logging.basicConfig()
10
logger = logging.getLogger("NiaPy.algorithms.basic")
11
logger.setLevel("INFO")
12
13
__all__ = ["HarmonySearch", "HarmonySearchV1"]
14
15
16
class HarmonySearch(Algorithm):
17
    r"""Implementation of harmony search algorithm.
18
19
    Algorithm:
20
            Harmony Search Algorithm
21
22
    Date:
23
            2018
24
25
    Authors:
26
            Klemen Berkovič
27
28
    License:
29
            MIT
30
31
    Reference URL:
32
            https://link.springer.com/chapter/10.1007/978-3-642-00185-7_1
33
34
    Reference paper:
35
            Yang, Xin-She. "Harmony search as a metaheuristic algorithm." Music-inspired harmony search algorithm. Springer, Berlin, Heidelberg, 2009. 1-14.
36
37
    Attributes:
38
            Name (List[str]): List of strings representing algorithm names
39
            r_accept (float): Probability of accepting new bandwidth into harmony.
40
            r_pa (float): Probability of accepting random bandwidth into harmony.
41
            b_range (float): Range of bandwidth.
42
43
    See Also:
44
            * :class:`NiaPy.algorithms.algorithm.Algorithm`
45
46
    """
47
48
    Name = ["HarmonySearch", "HS"]
49
50
    @staticmethod
51
    def algorithmInfo():
52
        r"""Get basic information about the algorithm.
53
54
        Returns:
55
                str: Basic information.
56
        """
57
        return r"""Yang, Xin-She. "Harmony search as a metaheuristic algorithm." Music-inspired harmony search algorithm. Springer, Berlin, Heidelberg, 2009. 1-14."""
58
59 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
60
    def typeParameters():
61
        r"""Get dictionary with functions for checking values of parameters.
62
63
        Returns:
64
                Dict[str, Callable]:
65
                        * HMS (Callable[[int], bool])
66
                        * r_accept (Callable[[float], bool])
67
                        * r_pa (Callable[[float], bool])
68
                        * b_range (Callable[[float], bool])
69
        """
70
        return {
71
            "HMS": lambda x: isinstance(x, int) and x > 0,
72
            "r_accept": lambda x: isinstance(x, float) and 0 < x < 1,
73
            "r_pa": lambda x: isinstance(x, float) and 0 < x < 1,
74
            "b_range": lambda x: isinstance(x, (int, float)) and x > 0
75
        }
76
77
    def setParameters(self, HMS=30, r_accept=0.7, r_pa=0.35, b_range=1.42, **ukwargs):
78
        r"""Set the arguments of the algorithm.
79
80
        Arguments:
81
                HMS (Optional[int]): Number of harmony in the memory
82
                r_accept (Optional[float]): Probability of accepting new bandwidth to harmony.
83
                r_pa (Optional[float]): Probability of accepting random bandwidth into harmony.
84
                b_range (Optional[float]): Bandwidth range.
85
86
        See Also:
87
                * :func:`NiaPy.algorithms.algorithm.Algorithm.setParameters`
88
        """
89
        Algorithm.setParameters(self, NP=HMS, **ukwargs)
90
        self.r_accept, self.r_pa, self.b_range = r_accept, r_pa, b_range
91
        if ukwargs:
92
            logger.info("Unused arguments: %s" % (ukwargs))
93
94
    def bw(self, task):
95
        r"""Get bandwidth.
96
97
        Args:
98
                task (Task): Optimization task.
99
100
        Returns:
101
                float: Bandwidth.
102
        """
103
        return self.uniform(-1, 1) * self.b_range
104
105
    def adjustment(self, x, task):
106
        r"""Adjust value based on bandwidth.
107
108
        Args:
109
                x (Union[int, float]): Current position.
110
                task (Task): Optimization task.
111
112
        Returns:
113
                float: New position.
114
        """
115
        return x + self.bw(task)
116
117
    def improvize(self, HM, task):
118
        r"""Create new individual.
119
120
        Args:
121
                HM (numpy.ndarray): Current population.
122
                task (Task): Optimization task.
123
124
        Returns:
125
                numpy.ndarray: New individual.
126
        """
127
        H = full(task.D, .0)
128
        for i in range(task.D):
129
            r, j = self.rand(), self.randint(self.NP)
130
            H[i] = HM[j, i] if r > self.r_accept else self.adjustment(HM[j, i], task) if r > self.r_pa else self.uniform(task.Lower[i], task.Upper[i])
131
        return H
132
133
    def initPopulation(self, task):
134
        r"""Initialize first population.
135
136
        Args:
137
                task (Task): Optimization task.
138
139
        Returns:
140
                Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
141
                        1. New harmony/population.
142
                        2. New population fitness/function values.
143
                        3. Additional parameters.
144
145
        See Also:
146
                * :func:`NiaPy.algorithms.algorithm.Algorithm.initPopulation`
147
        """
148
        return Algorithm.initPopulation(self, task)
149
150
    def runIteration(self, task, HM, HM_f, xb, fxb, **dparams):
151
        r"""Core function of HarmonySearch algorithm.
152
153
        Args:
154
                task (Task): Optimization task.
155
                HM (numpy.ndarray): Current population.
156
                HM_f (numpy.ndarray[float]): Current populations function/fitness values.
157
                xb (numpy.ndarray): Global best individual.
158
                fxb (float): Global best fitness/function value.
159
                **dparams (Dict[str, Any]): Additional arguments.
160
161
        Returns:
162
                Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
163
                        1. New harmony/population.
164
                        2. New populations function/fitness values.
165
                        3. Additional arguments.
166
        """
167
        H = self.improvize(HM, task)
168
        H_f = task.eval(task.repair(H, self.Rand))
169
        iw = argmax(HM_f)
170
        if H_f <= HM_f[iw]:
171
            HM[iw], HM_f[iw] = H, H_f
172
        return HM, HM_f, {}
173
174
175
class HarmonySearchV1(HarmonySearch):
176
    r"""Implementation of harmony search algorithm.
177
178
    Algorithm:
179
            Harmony Search Algorithm
180
181
    Date:
182
            2018
183
184
    Authors:
185
            Klemen Berkovič
186
187
    License:
188
            MIT
189
190
    Reference URL:
191
            https://link.springer.com/chapter/10.1007/978-3-642-00185-7_1
192
193
    Reference paper:
194
            Yang, Xin-She. "Harmony search as a metaheuristic algorithm." Music-inspired harmony search algorithm. Springer, Berlin, Heidelberg, 2009. 1-14.
195
196
    Attributes:
197
            Name (List[str]): List of strings representing algorithm name.
198
            bw_min (float): Minimal bandwidth.
199
            bw_max (float): Maximal bandwidth.
200
201
    See Also:
202
            * :class:`NiaPy.algorithms.basic.hs.HarmonySearch`
203
    """
204
    Name = ["HarmonySearchV1", "HSv1"]
205
206
    @staticmethod
207
    def algorithmInfo():
208
        r"""Get basic information about algorihtm.
209
210
        Returns:
211
                str: Basic information.
212
        """
213
        return r"""Yang, Xin-She. "Harmony search as a metaheuristic algorithm." Music-inspired harmony search algorithm. Springer, Berlin, Heidelberg, 2009. 1-14."""
214
215
    @staticmethod
216
    def typeParameters():
217
        r"""Get dictionary with functions for checking values of parameters.
218
219
        Returns:
220
                Dict[str, Callable]: Function for testing correctness of parameters.
221
222
        See Also:
223
                * :func:`NiaPy.algorithms.basic.HarmonySearch.typeParameters`
224
        """
225
        d = HarmonySearch.typeParameters()
226
        del d["b_range"]
227
        d.update({
228
            "dw_min": lambda x: isinstance(x, (float, int)) and x >= 1,
229
            "dw_max": lambda x: isinstance(x, (float, int)) and x >= 1
230
        })
231
        return d
232
233
    def setParameters(self, bw_min=1, bw_max=2, **kwargs):
234
        r"""Set the parameters of the algorithm.
235
236
        Arguments:
237
                bw_min (Optional[float]): Minimal bandwidth
238
                bw_max (Optional[float]): Maximal bandwidth
239
                kwargs (Dict[str, Any]): Additional arguments.
240
241
        See Also:
242
                * :func:`NiaPy.algorithms.basic.hs.HarmonySearch.setParameters`
243
        """
244
        self.bw_min, self.bw_max = bw_min, bw_max
245
        HarmonySearch.setParameters(self, **kwargs)
246
247
    def bw(self, task):
248
        r"""Get new bandwidth.
249
250
        Args:
251
                task (Task): Optimization task.
252
253
        Returns:
254
                float: New bandwidth.
255
        """
256
        return self.bw_min * exp(log(self.bw_min / self.bw_max) * task.Iters / task.nGEN)
257
258
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
259