-
Notifications
You must be signed in to change notification settings - Fork 0
/
creator.py
119 lines (104 loc) · 4.41 KB
/
creator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# This file is part of DEAP.
#
# DEAP is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# DEAP is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with DEAP. If not, see <http://www.gnu.org/licenses/>.
"""The :mod:`~deap.creator` module is the heart and soul of DEAP, it allows to
create, at runtime, classes that will fulfill the needs of your evolutionary
algorithms.
"""
import array
import copy
import types
try:
import numpy
NUMPY_PRESENT = True
except ImportError:
NUMPY_PRESENT = False
def _deepcopyArray(self, memo):
"""Overrides the deepcopy from array.array that does not copy
the object's attributes and class type.
"""
cls = self.__class__
copy_ = cls.__new__(cls, self)
memo[id(self)] = copy_
copy_.__dict__.update(copy.deepcopy(self.__dict__, memo))
return copy_
def _deepcopyNumPyArray(self, memo):
"""Overrides the deepcopy from numpy.ndarray that does not copy
the object's attributes.
"""
copy_ = numpy.ndarray.__deepcopy__(self, memo)
copy_.__dict__.update(copy.deepcopy(self.__dict__, memo))
return copy_
@staticmethod
def _newNumPyArray(cls, iterable):
"""Creates a new instance of a numpy.ndarray from a function call"""
return numpy.array(list(iterable)).view(cls)
def _finalizeNumPyArray(self, obj):
# __init__ will reinitialize every member of the subclass.
# this might not be desirable for example in the case of an ES.
self.__init__()
# Instead, e could use the following that will simply deepcopy every
# member that is present in the original class
# This is significantly slower.
#if self.__class__ == obj.__class__:
# self.__dict__.update(copy.deepcopy(obj.__dict__))
def reduceArray(self):
return (self.__class__, (list(self),), self.__dict__)
def create(name, base, **kargs):
"""The function :func:`create` does create a new class named *name*
inheriting from *base* in the :mod:`~deap.creator` module. The new
class can have attributes defined by the subsequent keyword
arguments passed to the function create. If the argument is a class,
the __init__ function is called in the initialization of an instance of
the new object and the returned instance is added as an attribute of the
class' instance. Otherwise, if the argument is not a class, (for
example an :class:`int`), it is added as a "static" attribute of the
class.
"""
dict_inst = {}
dict_cls = {}
for obj_name, obj in kargs.iteritems():
if hasattr(obj, "__call__"):
dict_inst[obj_name] = obj
else:
dict_cls[obj_name] = obj
# A DeprecationWarning is raised when the object inherits from the
# class "object" which leave the option of passing arguments, but
# raise a warning stating that it will eventually stop permitting
# this option. Usually this happens when the base class does not
# override the __init__ method from object.
def initType(self, *args, **kargs):
"""Replace the __init__ function of the new type, in order to
add attributes that were defined with **kargs to the instance.
"""
for obj_name, obj in dict_inst.iteritems():
setattr(self, obj_name, obj())
if base.__init__ is not object.__init__:
base.__init__(self, *args, **kargs)
else:
base.__init__(self)
objtype = type(name, (base,), dict_cls)
if issubclass(base, array.array):
objtype.__deepcopy__ = _deepcopyArray
@staticmethod
def newArray(cls, seq=()):
return super(objtype, cls).__new__(cls, cls.typecode, seq)
objtype.__new__ = newArray
objtype.__reduce__ = reduceArray
elif NUMPY_PRESENT and issubclass(base, numpy.ndarray):
objtype.__deepcopy__ = _deepcopyNumPyArray
objtype.__new__ = _newNumPyArray
objtype.__array_finalize__ = _finalizeNumPyArray
objtype.__init__ = initType
globals()[name] = objtype