Skip to content

Commit 502e886

Browse files
authored
Merge pull request #51 from Gromwud/main
Cumulitive update
2 parents d3c3d6d + ac75bc8 commit 502e886

17 files changed

Lines changed: 239 additions & 241 deletions

File tree

epde/operators/common/coeff_calculation.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,6 @@ def apply(self, objective : Equation, arguments : dict = None):
8282
if weight_idx in nonzero_features_indexes:
8383
weights[weight_idx] = valueable_weights[nonzero_features_indexes.index(weight_idx)]
8484
weights[-1] = valueable_weights[-1]
85-
# nonzero_terms_mask = np.array([False if np.isclose(weight, 0) else True for weight in weights])
86-
# weights = np.array([item if keep else 0 for item, keep in zip(weights, nonzero_terms_mask)])
87-
# objective.weights_internal = np.array([item if keep else 0 for item, keep in zip(objective.weights_internal, nonzero_terms_mask[:-1])])
8885
objective.weights_final_evald = True
8986
objective.weights_final = weights
9087

epde/operators/common/fitness.py

Lines changed: 100 additions & 119 deletions
Large diffs are not rendered by default.

epde/operators/common/right_part_selection.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ def apply(self, objective : Equation, arguments : dict):
6060
if not (objective.structure[target_idx].contains_variable(objective.main_var_to_explain) and objective.structure[target_idx].contains_deriv(objective.main_var_to_explain)):
6161
continue
6262
objective.target_idx = target_idx
63-
fitness = self.suboperators['fitness_calculation'].apply(objective,
64-
arguments = subop_args['fitness_calculation'],
65-
force_out_of_place = True)
63+
fitness = self.suboperators['fitness_calculation'].apply(objective, arguments = subop_args['fitness_calculation'], force_out_of_place = True)
6664
if fitness < min_fitness:
6765
min_fitness = fitness
6866
min_idx = target_idx
@@ -72,14 +70,10 @@ def apply(self, objective : Equation, arguments : dict):
7270

7371
objective.weights_internal = weights_internal
7472
objective.target_idx = min_idx
75-
# self.suboperators['fitness_calculation'].apply(objective, arguments = subop_args['fitness_calculation'])
76-
# if not np.isclose(objective.fitness_value, max_fitness) and global_var.verbose.show_warnings:
77-
# warnings.warn('Reevaluation of fitness function for equation has obtained different result. Not an error, if ANN DE solver is used.')
7873
self.simplify_equation(objective)
7974
if objective.structure[objective.target_idx].contains_variable(objective.main_var_to_explain) and objective.structure[objective.target_idx].contains_deriv(objective.main_var_to_explain):
8075
objective.is_correct_right_part = True
8176
else:
82-
objective.reset_explaining_term(objective.target_idx)
8377
objective.right_part_selected = True
8478

8579
def simplify_equation(self, objective: Equation):
@@ -88,18 +82,18 @@ def simplify_equation(self, objective: Equation):
8882
nonrs_terms = [term for i, term in enumerate(objective.structure) if i != objective.target_idx]
8983
nonzero_terms = [item for item, keep in zip(nonrs_terms, nonzero_terms_mask) if keep]
9084
nonzero_terms.append(objective.structure[objective.target_idx])
91-
nonzero_terms_labels = [[term.cache_label[0]] if not isinstance(term.cache_label[0], tuple) else list(next(zip(*term.cache_label))) for term in nonzero_terms]
9285

86+
equation_terms = objective.described_variables
9387
# If amount nonzero terms is more than one -- get their intersection
94-
if len(nonzero_terms) > 1:
95-
common_factor = np.array(list(set.intersection(*map(set, nonzero_terms_labels)))).flatten()
88+
if len(equation_terms) > 1:
89+
common_factor = list(frozenset.intersection(*equation_terms))
9690
common_dim = []
9791
if len(common_factor) > 0:
9892
# Find if this intersection in the same dimension (i.e. trigonometry functions) + it's minimal order
9993
min_order = np.inf
10094
for term in nonzero_terms:
10195
for factor in term.structure:
102-
if factor.cache_label[0] == common_factor[0]:
96+
if factor.cache_label[0] == common_factor[0][0]:
10397
if len(factor.params) > 1:
10498
common_dim.append(factor.params[-1])
10599
if factor.cache_label[1][0] < min_order:
@@ -110,7 +104,7 @@ def simplify_equation(self, objective: Equation):
110104
temp = deepcopy(term)
111105
factors_simplified = []
112106
for factor in term.structure:
113-
if factor.cache_label[0] == common_factor[0]:
107+
if factor.cache_label[0] == common_factor[0][0]:
114108
for i, value in enumerate(factor.params_description):
115109
if factor.params_description[i]["name"] == "power":
116110
factor.params[i] -= min_order

epde/operators/common/sparsity.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
from typing import Union, Callable
1010
import numpy as np
11-
from sklearn.linear_model import Lasso
11+
from sklearn.linear_model import Lasso, LassoLars
12+
from pysindy import STLSQ
1213

1314
import epde.globals as global_var
1415
from epde.operators.utils.template import CompoundOperator
@@ -60,15 +61,17 @@ def apply(self, objective : Equation, arguments : dict):
6061
# print(f'Metaparameter: {objective.metaparameters}, objective.metaparameters[("sparsity", objective.main_var_to_explain)]')
6162
self_args, subop_args = self.parse_suboperator_args(arguments = arguments)
6263

63-
estimator = Lasso(alpha = objective.metaparameters[('sparsity', objective.main_var_to_explain)]['value'],
64-
copy_X=True, fit_intercept=True, max_iter=1000,
65-
positive=False, precompute=False, random_state=None,
66-
selection='random', tol=0.0001, warm_start=False)
64+
# estimator = Lasso(alpha = objective.metaparameters[('sparsity', objective.main_var_to_explain)]['value'],
65+
# copy_X=True, fit_intercept=True, max_iter=1000,
66+
# positive=False, precompute=False, random_state=None,
67+
# selection='random', tol=0.0001, warm_start=False)
68+
estimator = STLSQ(threshold=objective.metaparameters[('sparsity', objective.main_var_to_explain)]['value'],
69+
copy_X=True, unbias=True, max_iter=1000, alpha=0.05)
6770
_, target, features = objective.evaluate(normalize = True, return_val = False)
6871
self.g_fun_vals = global_var.grid_cache.g_func.reshape(-1)
6972

7073
estimator.fit(features, target, sample_weight = self.g_fun_vals)
71-
objective.weights_internal = estimator.coef_
74+
objective.weights_internal = estimator.coef_[-1]
7275

7376
def use_default_tags(self):
7477
self._tags = {'sparsity', 'gene level', 'no suboperators', 'inplace'}

epde/operators/multiobjective/moeadd_specific.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,7 @@ def apply(self, objective : Tuple[Union[SoEq, ParetoLevels]], arguments : dict):
190190
most_crowded_domain = crowded_domains[np.argmax(PBIS)]
191191

192192
if len(last_level_by_domains[most_crowded_domain]) == 1:
193-
worst_solution = locate_pareto_worst(objective[1], self_args['weights'],
194-
self_args['best_obj'], self.params['PBI_penalty'])
193+
worst_solution = last_level_by_domains[most_crowded_domain][0]
195194
else:
196195
PBIS = np.fromiter(map(lambda solution: penalty_based_intersection(solution,
197196
self_args['weights'][most_crowded_domain],
@@ -367,31 +366,34 @@ def apply(self, objective: ParetoLevels, arguments: dict):
367366

368367
while objective.unplaced_candidates:
369368
offspring = objective.unplaced_candidates.pop()
370-
attempt = 1
371-
attempt_limit = self.params['attempt_limit']
369+
attempt = 0
370+
mutation_attempt_limit = self.params['mutation_attempt_limit']
371+
offspring_attempt_limit = self.params['offspring_attempt_limit']
372372
temp_offspring = deepcopy(offspring)
373373
replaced = 0
374374
while True:
375-
temp_offspring = self.suboperators['chromosome_mutation'].apply(objective=temp_offspring,
376-
arguments=subop_args['chromosome_mutation'])
377375
self.suboperators['right_part_selector'].apply(objective=temp_offspring,
378376
arguments=subop_args['right_part_selector'])
379-
self.suboperators['chromosome_fitness'].apply(objective=temp_offspring,
380-
arguments=subop_args['chromosome_fitness'])
381-
382-
if tuple(temp_offspring.obj_fun) not in objective.history:
377+
temp_offspring.reset_state()
378+
system = temp_offspring.described_variables
379+
if system not in objective.history:
380+
self.suboperators['chromosome_fitness'].apply(objective=temp_offspring,
381+
arguments=subop_args['chromosome_fitness'])
383382
self.suboperators['pareto_level_updater'].apply(objective=(temp_offspring, objective),
384383
arguments=subop_args['pareto_level_updater'])
385-
objective.history.add(tuple(temp_offspring.obj_fun))
386-
# print(tuple(temp_offspring.obj_fun))
384+
objective.history.add(system)
385+
print(temp_offspring.obj_fun)
387386
break
388-
elif replaced == attempt_limit:
387+
elif replaced == offspring_attempt_limit:
389388
print("Could not generate unique offspring")
390389
break
391-
elif attempt == attempt_limit:
390+
elif attempt == mutation_attempt_limit:
392391
temp_offspring = deepcopy(offspring)
393392
replaced += 1
394393
attempt = 0
394+
temp_offspring = self.suboperators['chromosome_mutation'].apply(objective=temp_offspring,
395+
arguments=subop_args[
396+
'chromosome_mutation'])
395397
attempt += 1
396398
return objective
397399

@@ -437,15 +439,16 @@ def apply(self, objective : ParetoLevels, arguments : dict):
437439
for idx, candidate in enumerate(objective.unplaced_candidates):
438440
self.suboperators['right_part_selector'].apply(objective = candidate,
439441
arguments = subop_args['right_part_selector'])
440-
self.suboperators['chromosome_fitness'].apply(objective = objective.unplaced_candidates[idx],
441-
arguments = subop_args['chromosome_fitness'])
442-
while tuple(candidate.obj_fun) in objective.history:
442+
system = candidate.described_variables
443+
while system in objective.history:
443444
candidate.create()
444445
self.suboperators['right_part_selector'].apply(objective=candidate,
445446
arguments=subop_args['right_part_selector'])
446-
self.suboperators['chromosome_fitness'].apply(objective=objective.unplaced_candidates[idx],
447-
arguments=subop_args['chromosome_fitness'])
448-
objective.history.add(tuple(candidate.obj_fun))
447+
system = candidate.described_variables
448+
self.suboperators['chromosome_fitness'].apply(objective=candidate,
449+
arguments=subop_args['chromosome_fitness'])
450+
objective.history.add(system)
451+
print(candidate.obj_fun)
449452
objective.initial_placing()
450453

451454
# TODO: consider carefully, where normalizer init shall be held. If here, only the initial values are employed

epde/operators/multiobjective/mutations.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ class EquationMutation(CompoundOperator):
5757
def apply(self, objective : Equation, arguments : dict):
5858
self_args, subop_args = self.parse_suboperator_args(arguments = arguments)
5959

60-
for term_idx in range(objective.n_immutable, len(objective.structure)):
61-
if np.random.uniform(0, 1) <= self.params['r_mutation']:
62-
objective.structure[term_idx] = self.suboperators['mutation'].apply(objective = (term_idx, objective),
63-
arguments = subop_args['mutation'])
64-
# term_idx = np.random.choice(len(objective.structure))
65-
# objective.structure[term_idx] = self.suboperators['mutation'].apply(objective=(term_idx, objective),
66-
# arguments=subop_args['mutation'])
60+
# for term_idx in range(objective.n_immutable, len(objective.structure)):
61+
# if np.random.uniform(0, 1) <= self.params['r_mutation']:
62+
# objective.structure[term_idx] = self.suboperators['mutation'].apply(objective = (term_idx, objective),
63+
# arguments = subop_args['mutation'])
64+
term_idx = np.random.choice(len(objective.structure))
65+
objective.structure[term_idx] = self.suboperators['mutation'].apply(objective=(term_idx, objective),
66+
arguments=subop_args['mutation'])
6767
return objective
6868

6969
def use_default_tags(self):
@@ -76,11 +76,11 @@ class MetaparameterMutation(CompoundOperator):
7676
def apply(self, objective : Union[int, float], arguments : dict):
7777
self_args, subop_args = self.parse_suboperator_args(arguments = arguments)
7878

79-
altered_objective = np.random.normal(objective, scale = self.params['std'])
79+
altered_objective = np.random.normal(objective, objective)
8080
if altered_objective < 0:
8181
altered_objective = - altered_objective
82-
83-
return altered_objective
82+
83+
return np.float64(altered_objective)
8484

8585
def use_default_tags(self):
8686
self._tags = {'mutation', 'gene level', 'no suboperators'}

epde/operators/utils/parameters/default_parameters_multi_objective.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"number_of_neighbors" : 4
1111
},
1212
"ParetoLevelUpdater" : {
13-
"attempt_limit" : 5
13+
"mutation_attempt_limit" : 5,
14+
"offspring_attempt_limit" : 5
1415
},
1516
"InitialParetoLevelSorting" : {
1617

epde/optimizers/moeadd/moeadd.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,25 +175,17 @@ def delete_point(self, point):
175175
None
176176
"""
177177
new_levels = []
178-
deleted = False
178+
population_cleared = []
179+
point_system = point.described_variables
179180
for level in self.levels:
180181
temp = []
181182
for element in level:
182-
if not np.allclose(element.obj_fun, point.obj_fun) or deleted:
183+
if element.described_variables != point_system:
183184
temp.append(element)
184-
else:
185-
deleted = True
185+
population_cleared.append(element)
186186
if not len(temp) == 0:
187187
new_levels.append(temp)
188188

189-
population_cleared = []
190-
deleted = False
191-
for elem in self.population:
192-
if not np.allclose(elem.obj_fun, point.obj_fun) or deleted:
193-
population_cleared.append(elem)
194-
else:
195-
deleted = True
196-
197189
if len(population_cleared) != sum([len(level) for level in new_levels]):
198190
print(len(population_cleared), len(self.population), sum([len(level) for level in new_levels]))
199191
print('initial population', [solution.vals for solution in self.population], len([solution.vals for solution in self.population]), '\n')

epde/structure/main_structures.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ def evaluate(self, structural, grids=None):
215215
self.prev_normalized = normalize
216216
value = super().evaluate(structural)
217217
if normalize:
218-
value = value / np.linalg.norm(value, 2)
218+
value = (value - np.mean(value)) / np.std(value)
219+
# value = value / np.linalg.norm(value, 2)
220+
219221
if np.all([len(factor.params) == 1 for factor in self.structure]) and grids is None:
220222
# Место возможных проблем: сохранение/загрузка нормализованных данных
221223
self.saved[normalize] = global_var.tensor_cache.add(self.cache_label, value, normalized=normalize)
@@ -580,7 +582,7 @@ def shifted_idx(idx):
580582
def reset_state(self, reset_right_part: bool = True):
581583
if reset_right_part:
582584
self.right_part_selected = False
583-
self.weights_internal_evald = False
585+
# self.weights_internal_evald = False
584586
self.weights_final_evald = False
585587
self.fitness_calculated = False
586588
self.stability_calculated = False
@@ -744,17 +746,28 @@ def state(self):
744746

745747
@property
746748
def described_variables(self):
747-
eps = 1e-7
748749
described = set()
749750
for term_idx, term in enumerate(self.structure):
751+
cache_label = set()
750752
if term_idx == self.target_idx:
751-
described.update({factor.family_type for factor in term.structure
752-
if factor.is_deriv and factor.deriv_code != [None]})
753+
for factor in term.structure:
754+
if len(factor.params) == 1:
755+
factor_label = (factor.cache_label[0])
756+
else:
757+
factor_label = (factor.cache_label[0], (factor.cache_label[1][-1]))
758+
cache_label.add(factor_label)
753759
else:
754-
weight_idx = term_idx if term_idx < term_idx else term_idx - 1
755-
if np.abs(self.weights_final[weight_idx]) > eps:
756-
described.update({factor.family_type for factor in term.structure
757-
if factor.is_deriv and factor.deriv_code != [None]})
760+
weight_idx = term_idx if term_idx < self.target_idx else term_idx - 1
761+
if not np.isclose(self.weights_internal[weight_idx], 0):
762+
for factor in term.structure:
763+
if len(factor.params) == 1:
764+
factor_label = (factor.cache_label[0])
765+
else:
766+
factor_label = (factor.cache_label[0], (factor.cache_label[1][-1]))
767+
cache_label.add(factor_label)
768+
if len(cache_label) > 0:
769+
cache_label = frozenset(cache_label)
770+
described.add(cache_label)
758771
described = frozenset(described)
759772
return described
760773

@@ -1110,6 +1123,13 @@ def __iter__(self):
11101123
def fitness_calculated(self):
11111124
return all([equation.fitness_calculated for equation in self.vals])
11121125

1126+
@property
1127+
def described_variables(self):
1128+
equations_caches = set()
1129+
for equation in self.vals:
1130+
equations_caches.add(equation.described_variables)
1131+
return frozenset(equations_caches)
1132+
11131133

11141134
class SoEqIterator(object):
11151135
def __init__(self, system: SoEq):

0 commit comments

Comments
 (0)