eckity.genetic_encodings.ga.vector_individual
This module implements the vector class.
1""" 2This module implements the vector class. 3""" 4from abc import abstractmethod 5from random import randint 6 7from eckity.individual import Individual 8 9 10class Vector(Individual): 11 """ 12 A Vector individual representation for Genetic Algorithms operations. 13 It is represented by a list of values (integers, floats, etc.) 14 15 Parameters 16 ---------- 17 fitness : Fitness 18 Fitness handler class, responsible of keeping the fitness value of the individual. 19 20 length : int 21 Vector length - the number of cells in the vector. 22 23 bounds : list of tuples 24 Min/Max values for each vector cell (if of length n), or the minimum and maximum (if of length 1). 25 """ 26 27 def __init__(self, 28 fitness, 29 bounds, 30 length, 31 vector=None): 32 super().__init__(fitness) 33 34 if (type(bounds) == tuple and len(bounds) != 2) \ 35 or (type(bounds) == list and len(bounds) != length): 36 raise ValueError(f'Bounds must be either a tuple of size 2 or a list of {length} tuples') 37 38 self.bounds = bounds 39 self.length = length 40 41 if vector is None: 42 self.vector = [] 43 44 else: 45 if not isinstance(vector, list): 46 raise ValueError(f'Expected vector argument in Vector constructor to be a list, got {type(vector)}') 47 if len(vector) != length: 48 raise ValueError(f'Expected vector argument in Vector constructor to be of length {length}, got {len(vector)}') 49 self.vector = vector 50 51 def size(self): 52 """ 53 Compute size of vector. 54 55 Returns 56 ------- 57 int 58 vector size (= number of cells). 59 """ 60 return len(self.vector) 61 62 def get_bounds(self): 63 """ 64 Get vector bounds 65 66 Returns 67 ------- 68 tuple of (Number, Number) 69 vector bounds. 70 """ 71 return self.bounds 72 73 def check_if_in_bounds(self): 74 """ 75 Check if all vector cells are in bounds 76 77 Returns 78 ------- 79 bool 80 True if all vector cells are in bounds, False otherwise 81 """ 82 for i in range(self.size()): 83 if len(self.bounds) == 2: 84 if (self.vector[i] < self.bounds[0]) or (self.vector[i] > self.bounds[1]): 85 return False 86 else: 87 if (self.vector[i] < self.bounds[i][0]) or (self.vector[i] > self.bounds[i][1]): 88 return False 89 return True 90 91 def add_cell(self, cell): 92 """ 93 Add a new cell to the vector (and increase its size by 1) 94 95 Returns 96 ------- 97 None 98 """ 99 self.vector.append(cell) 100 self.length += 1 101 102 def empty_vector(self): 103 """ 104 Convert the vector to an empty vector 105 106 Returns 107 ------- 108 None 109 """ 110 self.vector = [] 111 self.length = 0 112 113 def set_vector(self, vector): 114 """ 115 Set genome to the given vector genome 116 117 Parameters 118 ------- 119 vector: list 120 `other` vector genome 121 122 Returns 123 ------- 124 None 125 """ 126 self.vector = vector 127 self.length = len(vector) 128 129 def get_vector(self): 130 """ 131 Return self vector genome 132 133 Returns 134 ------- 135 list 136 vector genome 137 """ 138 return self.vector 139 140 def random_vector_part(self): 141 """ 142 Get a random part of the vector 143 144 Returns 145 ------- 146 list 147 sub-vector genome 148 """ 149 # todo add tests to make sure this logic works 150 rnd_i = randint(0, self.size() - 1) 151 end_i = randint(rnd_i, self.size() - 1) 152 return self.vector[rnd_i:end_i + 1] 153 154 def replace_vector_part_random(self, inserted_part): 155 """ 156 Replace a given vector part in a random position 157 158 Parameters 159 ------- 160 inserted_part: list 161 new vector part to be inserted 162 163 Returns 164 ------- 165 list 166 previous vector part of this vector genome 167 """ 168 index = randint(0, self.size() - len(inserted_part)) # select a random index 169 end_i = index + len(inserted_part) 170 replaced_part = self.vector[index:end_i] 171 self.vector = self.vector[:index] + inserted_part + self.vector[end_i:] 172 return replaced_part 173 174 def replace_vector_part(self, inserted_part, start_index): 175 """ 176 Replace a given vector part in a given position 177 178 Parameters 179 ------- 180 inserted_part: list 181 new vector part to be inserted 182 183 start_index: int 184 starting position to insert the new vector part from 185 186 Returns 187 ------- 188 list 189 previous vector part of this vector genome 190 """ 191 end_i = start_index + len(inserted_part) 192 replaced_part = self.vector[start_index:end_i] 193 self.vector = self.vector[:start_index] + inserted_part + self.vector[end_i:] 194 return replaced_part 195 196 def get_vector_part(self, index, end_i): 197 """ 198 Return vector part from `index` to `end_i` 199 200 Parameters 201 ------- 202 index: int 203 starting index 204 205 end_i: int 206 end index 207 208 Returns 209 ------- 210 list 211 sub-vector genome 212 """ 213 return self.vector[index:end_i] 214 215 def cell_value(self, index): 216 """ 217 Get vector cell value in a given index 218 219 Parameters 220 ------- 221 index: int 222 cell index 223 224 Returns 225 ------- 226 object 227 vector cell value 228 """ 229 return self.vector[index] 230 231 def set_cell_value(self, index, value): 232 """ 233 Set vector cell value in a given index 234 235 Parameters 236 ------- 237 index: int 238 cell index 239 240 value: object 241 new cell value 242 243 Returns 244 ------- 245 None 246 """ 247 self.vector[index] = value 248 249 @abstractmethod 250 def get_random_number_in_bounds(self, index): 251 """ 252 Returns a random value in vector bounds 253 254 Parameters 255 ------- 256 index: int 257 cell index 258 259 Returns 260 ------- 261 object 262 vector cell value 263 """ 264 raise NotImplementedError("get_random_number is an abstract method in vector individual") 265 266 def execute(self, *args, **kwargs): 267 """ 268 Execute the vector. 269 Input is a numpy array or keyword arguments (but not both). 270 271 Parameters 272 ---------- 273 args : arguments 274 A numpy array, this is mostly relevant to GP representation. 275 276 kwargs : keyword arguments 277 Input to program, this is mostly relevant to GP representation. 278 279 Returns 280 ------- 281 object 282 Vector (genome) of this individual. 283 """ 284 return self.get_vector() 285 286 def show(self): 287 """ 288 Print out a simple textual representation of the vector. 289 290 Returns 291 ------- 292 None. 293 """ 294 print(self.vector) 295 296# end class Vector
11class Vector(Individual): 12 """ 13 A Vector individual representation for Genetic Algorithms operations. 14 It is represented by a list of values (integers, floats, etc.) 15 16 Parameters 17 ---------- 18 fitness : Fitness 19 Fitness handler class, responsible of keeping the fitness value of the individual. 20 21 length : int 22 Vector length - the number of cells in the vector. 23 24 bounds : list of tuples 25 Min/Max values for each vector cell (if of length n), or the minimum and maximum (if of length 1). 26 """ 27 28 def __init__(self, 29 fitness, 30 bounds, 31 length, 32 vector=None): 33 super().__init__(fitness) 34 35 if (type(bounds) == tuple and len(bounds) != 2) \ 36 or (type(bounds) == list and len(bounds) != length): 37 raise ValueError(f'Bounds must be either a tuple of size 2 or a list of {length} tuples') 38 39 self.bounds = bounds 40 self.length = length 41 42 if vector is None: 43 self.vector = [] 44 45 else: 46 if not isinstance(vector, list): 47 raise ValueError(f'Expected vector argument in Vector constructor to be a list, got {type(vector)}') 48 if len(vector) != length: 49 raise ValueError(f'Expected vector argument in Vector constructor to be of length {length}, got {len(vector)}') 50 self.vector = vector 51 52 def size(self): 53 """ 54 Compute size of vector. 55 56 Returns 57 ------- 58 int 59 vector size (= number of cells). 60 """ 61 return len(self.vector) 62 63 def get_bounds(self): 64 """ 65 Get vector bounds 66 67 Returns 68 ------- 69 tuple of (Number, Number) 70 vector bounds. 71 """ 72 return self.bounds 73 74 def check_if_in_bounds(self): 75 """ 76 Check if all vector cells are in bounds 77 78 Returns 79 ------- 80 bool 81 True if all vector cells are in bounds, False otherwise 82 """ 83 for i in range(self.size()): 84 if len(self.bounds) == 2: 85 if (self.vector[i] < self.bounds[0]) or (self.vector[i] > self.bounds[1]): 86 return False 87 else: 88 if (self.vector[i] < self.bounds[i][0]) or (self.vector[i] > self.bounds[i][1]): 89 return False 90 return True 91 92 def add_cell(self, cell): 93 """ 94 Add a new cell to the vector (and increase its size by 1) 95 96 Returns 97 ------- 98 None 99 """ 100 self.vector.append(cell) 101 self.length += 1 102 103 def empty_vector(self): 104 """ 105 Convert the vector to an empty vector 106 107 Returns 108 ------- 109 None 110 """ 111 self.vector = [] 112 self.length = 0 113 114 def set_vector(self, vector): 115 """ 116 Set genome to the given vector genome 117 118 Parameters 119 ------- 120 vector: list 121 `other` vector genome 122 123 Returns 124 ------- 125 None 126 """ 127 self.vector = vector 128 self.length = len(vector) 129 130 def get_vector(self): 131 """ 132 Return self vector genome 133 134 Returns 135 ------- 136 list 137 vector genome 138 """ 139 return self.vector 140 141 def random_vector_part(self): 142 """ 143 Get a random part of the vector 144 145 Returns 146 ------- 147 list 148 sub-vector genome 149 """ 150 # todo add tests to make sure this logic works 151 rnd_i = randint(0, self.size() - 1) 152 end_i = randint(rnd_i, self.size() - 1) 153 return self.vector[rnd_i:end_i + 1] 154 155 def replace_vector_part_random(self, inserted_part): 156 """ 157 Replace a given vector part in a random position 158 159 Parameters 160 ------- 161 inserted_part: list 162 new vector part to be inserted 163 164 Returns 165 ------- 166 list 167 previous vector part of this vector genome 168 """ 169 index = randint(0, self.size() - len(inserted_part)) # select a random index 170 end_i = index + len(inserted_part) 171 replaced_part = self.vector[index:end_i] 172 self.vector = self.vector[:index] + inserted_part + self.vector[end_i:] 173 return replaced_part 174 175 def replace_vector_part(self, inserted_part, start_index): 176 """ 177 Replace a given vector part in a given position 178 179 Parameters 180 ------- 181 inserted_part: list 182 new vector part to be inserted 183 184 start_index: int 185 starting position to insert the new vector part from 186 187 Returns 188 ------- 189 list 190 previous vector part of this vector genome 191 """ 192 end_i = start_index + len(inserted_part) 193 replaced_part = self.vector[start_index:end_i] 194 self.vector = self.vector[:start_index] + inserted_part + self.vector[end_i:] 195 return replaced_part 196 197 def get_vector_part(self, index, end_i): 198 """ 199 Return vector part from `index` to `end_i` 200 201 Parameters 202 ------- 203 index: int 204 starting index 205 206 end_i: int 207 end index 208 209 Returns 210 ------- 211 list 212 sub-vector genome 213 """ 214 return self.vector[index:end_i] 215 216 def cell_value(self, index): 217 """ 218 Get vector cell value in a given index 219 220 Parameters 221 ------- 222 index: int 223 cell index 224 225 Returns 226 ------- 227 object 228 vector cell value 229 """ 230 return self.vector[index] 231 232 def set_cell_value(self, index, value): 233 """ 234 Set vector cell value in a given index 235 236 Parameters 237 ------- 238 index: int 239 cell index 240 241 value: object 242 new cell value 243 244 Returns 245 ------- 246 None 247 """ 248 self.vector[index] = value 249 250 @abstractmethod 251 def get_random_number_in_bounds(self, index): 252 """ 253 Returns a random value in vector bounds 254 255 Parameters 256 ------- 257 index: int 258 cell index 259 260 Returns 261 ------- 262 object 263 vector cell value 264 """ 265 raise NotImplementedError("get_random_number is an abstract method in vector individual") 266 267 def execute(self, *args, **kwargs): 268 """ 269 Execute the vector. 270 Input is a numpy array or keyword arguments (but not both). 271 272 Parameters 273 ---------- 274 args : arguments 275 A numpy array, this is mostly relevant to GP representation. 276 277 kwargs : keyword arguments 278 Input to program, this is mostly relevant to GP representation. 279 280 Returns 281 ------- 282 object 283 Vector (genome) of this individual. 284 """ 285 return self.get_vector() 286 287 def show(self): 288 """ 289 Print out a simple textual representation of the vector. 290 291 Returns 292 ------- 293 None. 294 """ 295 print(self.vector)
A Vector individual representation for Genetic Algorithms operations. It is represented by a list of values (integers, floats, etc.)
Parameters
- fitness (Fitness): Fitness handler class, responsible of keeping the fitness value of the individual.
- length (int): Vector length - the number of cells in the vector.
- bounds (list of tuples): Min/Max values for each vector cell (if of length n), or the minimum and maximum (if of length 1).
28 def __init__(self, 29 fitness, 30 bounds, 31 length, 32 vector=None): 33 super().__init__(fitness) 34 35 if (type(bounds) == tuple and len(bounds) != 2) \ 36 or (type(bounds) == list and len(bounds) != length): 37 raise ValueError(f'Bounds must be either a tuple of size 2 or a list of {length} tuples') 38 39 self.bounds = bounds 40 self.length = length 41 42 if vector is None: 43 self.vector = [] 44 45 else: 46 if not isinstance(vector, list): 47 raise ValueError(f'Expected vector argument in Vector constructor to be a list, got {type(vector)}') 48 if len(vector) != length: 49 raise ValueError(f'Expected vector argument in Vector constructor to be of length {length}, got {len(vector)}') 50 self.vector = vector
52 def size(self): 53 """ 54 Compute size of vector. 55 56 Returns 57 ------- 58 int 59 vector size (= number of cells). 60 """ 61 return len(self.vector)
Compute size of vector.
Returns
- int: vector size (= number of cells).
63 def get_bounds(self): 64 """ 65 Get vector bounds 66 67 Returns 68 ------- 69 tuple of (Number, Number) 70 vector bounds. 71 """ 72 return self.bounds
Get vector bounds
Returns
- tuple of (Number, Number): vector bounds.
74 def check_if_in_bounds(self): 75 """ 76 Check if all vector cells are in bounds 77 78 Returns 79 ------- 80 bool 81 True if all vector cells are in bounds, False otherwise 82 """ 83 for i in range(self.size()): 84 if len(self.bounds) == 2: 85 if (self.vector[i] < self.bounds[0]) or (self.vector[i] > self.bounds[1]): 86 return False 87 else: 88 if (self.vector[i] < self.bounds[i][0]) or (self.vector[i] > self.bounds[i][1]): 89 return False 90 return True
Check if all vector cells are in bounds
Returns
- bool: True if all vector cells are in bounds, False otherwise
92 def add_cell(self, cell): 93 """ 94 Add a new cell to the vector (and increase its size by 1) 95 96 Returns 97 ------- 98 None 99 """ 100 self.vector.append(cell) 101 self.length += 1
Add a new cell to the vector (and increase its size by 1)
Returns
- None
103 def empty_vector(self): 104 """ 105 Convert the vector to an empty vector 106 107 Returns 108 ------- 109 None 110 """ 111 self.vector = [] 112 self.length = 0
Convert the vector to an empty vector
Returns
- None
114 def set_vector(self, vector): 115 """ 116 Set genome to the given vector genome 117 118 Parameters 119 ------- 120 vector: list 121 `other` vector genome 122 123 Returns 124 ------- 125 None 126 """ 127 self.vector = vector 128 self.length = len(vector)
Set genome to the given vector genome
Parameters
- vector (list):
other
vector genome
Returns
- None
130 def get_vector(self): 131 """ 132 Return self vector genome 133 134 Returns 135 ------- 136 list 137 vector genome 138 """ 139 return self.vector
Return self vector genome
Returns
- list: vector genome
141 def random_vector_part(self): 142 """ 143 Get a random part of the vector 144 145 Returns 146 ------- 147 list 148 sub-vector genome 149 """ 150 # todo add tests to make sure this logic works 151 rnd_i = randint(0, self.size() - 1) 152 end_i = randint(rnd_i, self.size() - 1) 153 return self.vector[rnd_i:end_i + 1]
Get a random part of the vector
Returns
- list: sub-vector genome
155 def replace_vector_part_random(self, inserted_part): 156 """ 157 Replace a given vector part in a random position 158 159 Parameters 160 ------- 161 inserted_part: list 162 new vector part to be inserted 163 164 Returns 165 ------- 166 list 167 previous vector part of this vector genome 168 """ 169 index = randint(0, self.size() - len(inserted_part)) # select a random index 170 end_i = index + len(inserted_part) 171 replaced_part = self.vector[index:end_i] 172 self.vector = self.vector[:index] + inserted_part + self.vector[end_i:] 173 return replaced_part
Replace a given vector part in a random position
Parameters
- inserted_part (list): new vector part to be inserted
Returns
- list: previous vector part of this vector genome
175 def replace_vector_part(self, inserted_part, start_index): 176 """ 177 Replace a given vector part in a given position 178 179 Parameters 180 ------- 181 inserted_part: list 182 new vector part to be inserted 183 184 start_index: int 185 starting position to insert the new vector part from 186 187 Returns 188 ------- 189 list 190 previous vector part of this vector genome 191 """ 192 end_i = start_index + len(inserted_part) 193 replaced_part = self.vector[start_index:end_i] 194 self.vector = self.vector[:start_index] + inserted_part + self.vector[end_i:] 195 return replaced_part
Replace a given vector part in a given position
Parameters
- inserted_part (list): new vector part to be inserted
- start_index (int): starting position to insert the new vector part from
Returns
- list: previous vector part of this vector genome
197 def get_vector_part(self, index, end_i): 198 """ 199 Return vector part from `index` to `end_i` 200 201 Parameters 202 ------- 203 index: int 204 starting index 205 206 end_i: int 207 end index 208 209 Returns 210 ------- 211 list 212 sub-vector genome 213 """ 214 return self.vector[index:end_i]
Return vector part from index
to end_i
Parameters
- index (int): starting index
- end_i (int): end index
Returns
- list: sub-vector genome
216 def cell_value(self, index): 217 """ 218 Get vector cell value in a given index 219 220 Parameters 221 ------- 222 index: int 223 cell index 224 225 Returns 226 ------- 227 object 228 vector cell value 229 """ 230 return self.vector[index]
Get vector cell value in a given index
Parameters
- index (int): cell index
Returns
- object: vector cell value
232 def set_cell_value(self, index, value): 233 """ 234 Set vector cell value in a given index 235 236 Parameters 237 ------- 238 index: int 239 cell index 240 241 value: object 242 new cell value 243 244 Returns 245 ------- 246 None 247 """ 248 self.vector[index] = value
Set vector cell value in a given index
Parameters
- index (int): cell index
- value (object): new cell value
Returns
- None
250 @abstractmethod 251 def get_random_number_in_bounds(self, index): 252 """ 253 Returns a random value in vector bounds 254 255 Parameters 256 ------- 257 index: int 258 cell index 259 260 Returns 261 ------- 262 object 263 vector cell value 264 """ 265 raise NotImplementedError("get_random_number is an abstract method in vector individual")
Returns a random value in vector bounds
Parameters
- index (int): cell index
Returns
- object: vector cell value
267 def execute(self, *args, **kwargs): 268 """ 269 Execute the vector. 270 Input is a numpy array or keyword arguments (but not both). 271 272 Parameters 273 ---------- 274 args : arguments 275 A numpy array, this is mostly relevant to GP representation. 276 277 kwargs : keyword arguments 278 Input to program, this is mostly relevant to GP representation. 279 280 Returns 281 ------- 282 object 283 Vector (genome) of this individual. 284 """ 285 return self.get_vector()
Execute the vector. Input is a numpy array or keyword arguments (but not both).
Parameters
- args (arguments): A numpy array, this is mostly relevant to GP representation.
- kwargs (keyword arguments): Input to program, this is mostly relevant to GP representation.
Returns
- object: Vector (genome) of this individual.