Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed scipy dependency #304

Merged
merged 3 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ per-file-ignores =
NiaPy/tests/*:B007,D100,D101,D102,D107,D208,D211,D413,E117,E302,E701,E704,F841,S110,W191,W293,D204,RST210,E101,D204,D205,D206,E741
NiaPy/algorithms/*:B305,B007,D100,D101,D102,D107,D204,D206,D413,E101,E117,E126,E302,E305,E701,E704,E711,E741,F812,RST201,RST203,RST204,RST210,RST301,W191
NiaPy/task/*:E701
NiaPy/util/*:W191,E117,E305,E302,E704,E701,RST203,D204,E306
NiaPy/util/*:W191,E117,E305,E302,E704,E701,RST203,D204,E306,D100
NiaPy/benchmarks/*:W191,E117,E305,E302,E704,E701,RST203,D204,E306,D206,D208

22 changes: 6 additions & 16 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ Before creating bug reports, please check existing issues list as you might find

### Suggesting Enhancements
- Open new issue
- Write in details what enhancement whould you like to see in the future
- Write in details what enhancement would you like to see in the future
- If you have technical knowledge, propose solution on how to implement enhancement

### Pull requests

If you are not so familiar with Git or/and GitHub, we suggest you take a look at our [beginner's guide](.github/beginners_guide.md).

- Fill in the [reqired template](.github/pull_request_template.md)
- Fill in the [required template](.github/pull_request_template.md)
- Document new code
- Make sure all the code goes through Flake8 without problems (run ```make check``` command)
- Make sure PR builds goes through
Expand All @@ -43,11 +43,10 @@ List of NiaPy's dependencies:

| Package | Version | Platform |
| ---------- |:-------:|:--------:|
| click | Any | All |
| numpy | 1.17.0 | All |
| scipy | 1.0.0 | All |
| xlsxwriter | 1.0.2 | All |
| matplotlib | Any | All |
| matplotlib | 2.2.4 | All |
| pandas | 0.24.2 | All |
| openpyxl | 3.0.3 | All |


List of development dependencies:
Expand All @@ -65,20 +64,11 @@ List of development dependencies:
|freezegun | Any | Any |
|coverage-space | Any | Any |
|docutils | Any | Any |
|pygments | Any | Any |
|Pygments | Any | Any |
|wheel | Any | Any |
|pyinstaller | Any | Any |
|twine | Any | Any |
|sniffer | Any | Any |
|macfsevents | Any | darwin |
|enum34 | Any | Any |
|singledispatch | Any | Any |
|backports.functools-lru-cache | Any | Any |
|configparser | Any | Any |
|sphinx | Any | Any |
|sphinx-rtd-theme | Any | Any |
|funcsigs | Any | Any |
|futures | Any | Any |
|autopep8 | Any | Any |
|sphinx-autobuild | Any | Any |

Expand Down
3 changes: 0 additions & 3 deletions NiaPy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

"""Python micro framework for building nature-inspired algorithms."""

from __future__ import print_function


from NiaPy import util, algorithms, benchmarks, task
from NiaPy.runner import Runner

Expand Down
5 changes: 2 additions & 3 deletions NiaPy/algorithms/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

from numpy import random as rand, inf, ndarray, asarray, array_equal, argmin, apply_along_axis

from NiaPy.util import FesException, GenException, TimeException, RefException
from NiaPy.util.utility import objects2array
from NiaPy.util import FesException, GenException, TimeException, RefException, objects_to_array

logging.basicConfig()
logger = logging.getLogger('NiaPy.util.utility')
Expand Down Expand Up @@ -53,7 +52,7 @@ def defaultIndividualInit(task, NP, rnd=rand, itype=None, **kwargs):
1. Initialized individuals.
2. Initialized individuals function/fitness values.
"""
pop = objects2array([itype(task=task, rnd=rnd, e=True) for _ in range(NP)])
pop = objects_to_array([itype(task=task, rnd=rnd, e=True) for _ in range(NP)])
return pop, asarray([x.f for x in pop])

class Algorithm:
Expand Down
10 changes: 5 additions & 5 deletions NiaPy/algorithms/basic/ca.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from numpy import exp, random as rand, asarray

from NiaPy.algorithms.algorithm import Algorithm, Individual
from NiaPy.util.utility import objects2array
from NiaPy.util import objects_to_array

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down Expand Up @@ -239,7 +239,7 @@ def initPop(self, task, NP, rnd, itype, **kwargs):
1. Initialize population of camels.
2. Initialized populations function/fitness values.
"""
caravan = objects2array([itype(E_init=self.E_init, S_init=self.S_init, task=task, rnd=rnd, e=True) for _ in range(NP)])
caravan = objects_to_array([itype(E_init=self.E_init, S_init=self.S_init, task=task, rnd=rnd, e=True) for _ in range(NP)])
return caravan, asarray([c.f for c in caravan])

def walk(self, c, cb, task):
Expand Down Expand Up @@ -324,9 +324,9 @@ def runIteration(self, task, caravan, fcaravan, cb, fcb, **dparams):
4. New global best fitness/objective value
5. Additional arguments
"""
ncaravan = objects2array([self.walk(c, cb, task) for c in caravan])
ncaravan = objects2array([self.oasis(c, self.rand(), self.alpha) for c in ncaravan])
ncaravan = objects2array([self.lifeCycle(c, self.mu, task) for c in ncaravan])
ncaravan = objects_to_array([self.walk(c, cb, task) for c in caravan])
ncaravan = objects_to_array([self.oasis(c, self.rand(), self.alpha) for c in ncaravan])
ncaravan = objects_to_array([self.lifeCycle(c, self.mu, task) for c in ncaravan])
fncaravan = asarray([c.f for c in ncaravan])
cb, fcb = self.getBest(ncaravan, fncaravan, cb, fcb)
return ncaravan, fncaravan, cb, fcb, {}
Expand Down
2 changes: 1 addition & 1 deletion NiaPy/algorithms/basic/cro.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# encoding=utf8
import logging
from scipy.spatial.distance import euclidean
from numpy import apply_along_axis, argsort, where, random as rand, asarray, delete, sqrt, sum, unique, append
from NiaPy.algorithms.algorithm import Algorithm
from NiaPy.util import euclidean

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down
4 changes: 2 additions & 2 deletions NiaPy/algorithms/basic/cs.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# encoding=utf8
import logging
from numpy import apply_along_axis, argsort
from scipy.stats import levy
from NiaPy.algorithms.algorithm import Algorithm
from NiaPy.util import levy_flight

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down Expand Up @@ -154,7 +154,7 @@ def runIteration(self, task, pop, fpop, xb, fxb, pa_v, **dparams):
* pa_v (float): TODO
"""
i = self.randint(self.NP)
Nn = task.repair(pop[i] + self.alpha * levy.rvs(size=[task.D], random_state=self.Rand), rnd=self.Rand)
Nn = task.repair(pop[i] + levy_flight(self.alpha, size=task.D, rng=self.Rand), rnd=self.Rand)
Nn_f = task.eval(Nn)
j = self.randint(self.NP)
while i == j: j = self.randint(self.NP)
Expand Down
17 changes: 8 additions & 9 deletions NiaPy/algorithms/basic/de.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import math

from numpy import random as rand, argmin, argmax, mean, cos, asarray, append, sin, isfinite
from scipy.spatial.distance import euclidean

from NiaPy.algorithms.algorithm import Algorithm, Individual, defaultIndividualInit
from NiaPy.util.utility import objects2array
from NiaPy.util import objects_to_array, euclidean

__all__ = ['DifferentialEvolution', 'DynNpDifferentialEvolution', 'AgingNpDifferentialEvolution', 'CrowdingDifferentialEvolution', 'MultiStrategyDifferentialEvolution', 'DynNpMultiStrategyDifferentialEvolution', 'AgingNpMultiMutationDifferentialEvolution', 'AgingIndividual', 'CrossRand1', 'CrossBest2', 'CrossBest1', 'CrossBest2', 'CrossCurr2Rand1', 'CrossCurr2Best1', 'multiMutations']

Expand Down Expand Up @@ -317,7 +316,7 @@ def evolve(self, pop, xb, task, **kwargs):
Returns:
numpy.ndarray: New evolved populations.
"""
return objects2array([self.itype(x=self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand), task=task, rnd=self.Rand, e=True) for i in range(len(pop))])
return objects_to_array([self.itype(x=self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand), task=task, rnd=self.Rand, e=True) for i in range(len(pop))])

def selection(self, pop, npop, xb, fxb, task, **kwargs):
r"""Operator for selection.
Expand All @@ -336,7 +335,7 @@ def selection(self, pop, npop, xb, fxb, task, **kwargs):
2. New global best solution.
3. New global best solutions fitness/objective value.
"""
arr = objects2array([e if e.f < pop[i].f else pop[i] for i, e in enumerate(npop)])
arr = objects_to_array([e if e.f < pop[i].f else pop[i] for i, e in enumerate(npop)])
xb, fxb = self.getBest(arr, asarray([e.f for e in arr]), xb, fxb)
return arr, xb, fxb

Expand Down Expand Up @@ -545,7 +544,7 @@ def postSelection(self, pop, task, xb, fxb, **kwargs):
"""
Gr = task.nFES // (self.pmax * len(pop)) + self.rp
nNP = len(pop) // 2
if (task.Iters + 1) == Gr and len(pop) > 3: pop = objects2array([pop[i] if pop[i].f < pop[i + nNP].f else pop[i + nNP] for i in range(nNP)])
if (task.Iters + 1) == Gr and len(pop) > 3: pop = objects_to_array([pop[i] if pop[i].f < pop[i + nNP].f else pop[i + nNP] for i in range(nNP)])
return pop, xb, fxb

def proportional(Lt_min, Lt_max, mu, x_f, avg, **args):
Expand Down Expand Up @@ -743,7 +742,7 @@ def aging(self, task, pop):
x.age += 1
Lt = round(self.age(Lt_min=self.Lt_min, Lt_max=self.Lt_max, mu=self.mu, x_f=x.f, avg=avg, x_gw=x_w.f, x_gb=x_b.f))
if x.age <= Lt: npop.append(x)
if len(npop) == 0: npop = objects2array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(self.NP)])
if len(npop) == 0: npop = objects_to_array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(self.NP)])
return npop

def popIncrement(self, pop, task):
Expand All @@ -757,7 +756,7 @@ def popIncrement(self, pop, task):
numpy.ndarray[Individual]: Increased population.
"""
deltapop = int(round(max(1, self.NP * self.deltaPopE((task.Iters + 1)))))
return objects2array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(deltapop)])
return objects_to_array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(deltapop)])

def popDecrement(self, pop, task):
r"""Decrement population.
Expand All @@ -776,7 +775,7 @@ def popDecrement(self, pop, task):
for i, e in enumerate(pop):
if i not in ni: npop.append(e)
elif self.rand() >= self.omega: npop.append(e)
return objects2array(npop)
return objects_to_array(npop)

def selection(self, pop, npop, xb, fxb, task, **kwargs):
r"""Select operator for individuals with aging.
Expand Down Expand Up @@ -929,7 +928,7 @@ def evolve(self, pop, xb, task, **kwargs):
Returns:
numpy.ndarray: New population of individuals.
"""
return objects2array([self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand, task, self.itype, self.strategies) for i in range(len(pop))])
return objects_to_array([self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand, task, self.itype, self.strategies) for i in range(len(pop))])

class DynNpMultiStrategyDifferentialEvolution(MultiStrategyDifferentialEvolution, DynNpDifferentialEvolution):
r"""Implementation of Dynamic population size Differential evolution algorithm with dynamic population size that is defined by the quality of population.
Expand Down
14 changes: 7 additions & 7 deletions NiaPy/algorithms/basic/es.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from numpy.linalg import norm, cholesky as chol, eig, solve, lstsq

from NiaPy.algorithms.algorithm import Algorithm, Individual, defaultIndividualInit
from NiaPy.util.utility import objects2array
from NiaPy.util import objects_to_array

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down Expand Up @@ -175,7 +175,7 @@ def runIteration(self, task, c, fpop, xb, fxb, ki, **dparams):
* ki (int): Number of successful rho update.
"""
if (task.Iters + 1) % self.k == 0: c.rho, ki = self.updateRho(c.rho, ki), 0
cn = objects2array([task.repair(self.mutate(c.x, c.rho), self.Rand) for _i in range(self.mu)])
cn = objects_to_array([task.repair(self.mutate(c.x, c.rho), self.Rand) for _i in range(self.mu)])
cn_f = asarray([task.eval(cn[i]) for i in range(len(cn))])
ib = argmin(cn_f)
if cn_f[ib] < c.f:
Expand Down Expand Up @@ -384,9 +384,9 @@ def runIteration(self, task, c, fpop, xb, fxb, ki, **dparams):
* ki (int): Number of successful mutations.
"""
if (task.Iters + 1) % self.k == 0: _, ki = self.updateRho(c, ki), 0
cn = objects2array([IndividualES(x=self.mutateRand(c, task), task=task, rnd=self.Rand) for _ in range(self.lam)])
cn = objects_to_array([IndividualES(x=self.mutateRand(c, task), task=task, rnd=self.Rand) for _ in range(self.lam)])
cn = append(cn, c)
cn = objects2array([cn[i] for i in argsort([i.f for i in cn])[:self.mu]])
cn = objects_to_array([cn[i] for i in argsort([i.f for i in cn])[:self.mu]])
ki += self.changeCount(c, cn)
fcn = asarray([x.f for x in cn])
xb, fxb = self.getBest(cn, fcn, xb, fxb)
Expand Down Expand Up @@ -441,10 +441,10 @@ def newPop(self, pop):
numpy.ndarray: New population.
"""
pop_s = argsort([i.f for i in pop])
if self.mu < self.lam: return objects2array([pop[i] for i in pop_s[:self.mu]])
if self.mu < self.lam: return objects_to_array([pop[i] for i in pop_s[:self.mu]])
npop = list()
for i in range(int(ceil(float(self.mu) / self.lam))): npop.extend(pop[:self.lam if (self.mu - i * self.lam) >= self.lam else self.mu - i * self.lam])
return objects2array(npop)
return objects_to_array(npop)

def initPopulation(self, task):
r"""Initialize starting population.
Expand Down Expand Up @@ -483,7 +483,7 @@ def runIteration(self, task, c, fpop, xb, fxb, **dparams):
4. New global best solutions fitness/objective value.
5. Additional arguments.
"""
cn = objects2array([IndividualES(x=self.mutateRand(c, task), task=task, rand=self.Rand) for _ in range(self.lam)])
cn = objects_to_array([IndividualES(x=self.mutateRand(c, task), task=task, rand=self.Rand) for _ in range(self.lam)])
c = self.newPop(cn)
fc = asarray([x.f for x in c])
xb, fxb = self.getBest(c, fc, xb, fxb)
Expand Down
4 changes: 2 additions & 2 deletions NiaPy/algorithms/basic/foa.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
from numpy import where, apply_along_axis, zeros, append, ndarray, delete, arange, argmin, absolute, int32
from NiaPy.algorithms.algorithm import Algorithm
from NiaPy.util import limit_repair
from NiaPy.util import repair

__all__ = ['ForestOptimizationAlgorithm']

Expand Down Expand Up @@ -131,7 +131,7 @@ def localSeeding(self, task, trees):
perms = self.rand([deltas.shape[0], deltas.shape[1]]).argsort(1)
deltas = deltas[arange(deltas.shape[0])[:, None], perms]
trees += deltas
trees = apply_along_axis(limit_repair, 1, trees, task.Lower, task.Upper)
trees = apply_along_axis(repair.limit, 1, trees, task.Lower, task.Upper)
return trees

def globalSeeding(self, task, candidates, size):
Expand Down
15 changes: 3 additions & 12 deletions NiaPy/algorithms/basic/fpa.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# encoding=utf8
import logging

from scipy.special import gamma as Gamma
from numpy import where, sin, fabs, pi, zeros
from numpy import where, zeros

from NiaPy.algorithms.algorithm import Algorithm
from NiaPy.util import levy_flight

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down Expand Up @@ -105,15 +105,6 @@ def repair(self, x, task):
x[ir] = task.Lower[ir] + x[ir] % task.bRange[ir]
return x

def levy(self, D):
r"""Levy function.

Returns:
float: Next Levy number.
"""
sigma = (Gamma(1 + self.beta) * sin(pi * self.beta / 2) / (Gamma((1 + self.beta) / 2) * self.beta * 2 ** ((self.beta - 1) / 2))) ** (1 / self.beta)
return 0.01 * (self.normal(0, 1, D) * sigma / fabs(self.normal(0, 1, D)) ** (1 / self.beta))

def initPopulation(self, task):
pop, fpop, d = Algorithm.initPopulation(self, task)
d.update({'S': zeros((self.NP, task.D))})
Expand All @@ -139,7 +130,7 @@ def runIteration(self, task, Sol, Sol_f, xb, fxb, S, **dparams):
5. Additional arguments.
"""
for i in range(self.NP):
if self.uniform(0, 1) > self.p: S[i] += self.levy(task.D) * (Sol[i] - xb)
if self.uniform(0, 1) > self.p: S[i] += levy_flight(beta=self.beta, size=task.D, rng=self.Rand) * (Sol[i] - xb)
else:
JK = self.Rand.permutation(self.NP)
S[i] += self.uniform(0, 1) * (Sol[JK[0]] - Sol[JK[1]])
Expand Down
4 changes: 2 additions & 2 deletions NiaPy/algorithms/basic/fss.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# encoding=utf8
from numpy import nan, asarray, zeros, full

from NiaPy.util.utility import objects2array
from NiaPy.util import objects_to_array
from NiaPy.algorithms.algorithm import Algorithm, Individual

class Fish(Individual):
Expand Down Expand Up @@ -170,7 +170,7 @@ def init_school(self, task):
school.append(fish)
curr_weight_school += fish.weight
prev_weight_school = curr_weight_school
return curr_step_individual, curr_step_volitive, curr_weight_school, prev_weight_school, objects2array(school)
return curr_step_individual, curr_step_volitive, curr_weight_school, prev_weight_school, objects_to_array(school)

def max_delta_cost(self, school):
r"""Find maximum delta cost - return 0 if none of the fishes moved.
Expand Down
6 changes: 3 additions & 3 deletions NiaPy/algorithms/basic/fwa.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
from numpy import apply_along_axis, argmin, argmax, sum, sqrt, round, argsort, fabs, asarray, where
from NiaPy.algorithms.algorithm import Algorithm
from NiaPy.util import fullArray
from NiaPy.util import full_array

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down Expand Up @@ -185,7 +185,7 @@ def initAmplitude(self, task):
Returns:
numpy.ndarray[float]: Starting amplitudes.
"""
return fullArray(self.A, task.D)
return full_array(self.A, task.D)

def SparsksNo(self, x_f, xw_f, Ss):
r"""Calculate number of sparks based on function value of individual.
Expand Down Expand Up @@ -446,7 +446,7 @@ def initRanges(self, task):
2. Final amplitude values over dimensions.
3. uAmin.
"""
Ainit, Afinal = fullArray(self.Ainit, task.D), fullArray(self.Afinal, task.D)
Ainit, Afinal = full_array(self.Ainit, task.D), full_array(self.Afinal, task.D)
return Ainit, Afinal, self.uAmin(Ainit, Afinal, task)

def uAmin(self, Ainit, Afinal, task):
Expand Down
2 changes: 1 addition & 1 deletion NiaPy/algorithms/basic/gso.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# encoding=utf8
import logging

from scipy.spatial.distance import euclidean
from numpy import full, apply_along_axis, copy, sum, fmax, pi, where

from NiaPy.algorithms.algorithm import Algorithm
from NiaPy.util import euclidean

logging.basicConfig()
logger = logging.getLogger('NiaPy.algorithms.basic')
Expand Down
Loading