Skip to content

Commit be16e48

Browse files
authored
Merge pull request #54 from Gromwud/main
Cumulitive update
2 parents b618927 + 1bc2f2b commit be16e48

13 files changed

Lines changed: 75 additions & 58 deletions

File tree

epde/operators/common/coeff_calculation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ 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-
objective.weights_final_evald = True
8685
objective.weights_final = weights
86+
objective.weights_final_evald = True
8787

8888
def use_default_tags(self):
8989
self._tags = {'coefficient calculation', 'gene level', 'no suboperators', 'inplace'}

epde/operators/common/fitness.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import epde.globals as global_var
2020
from sklearn.linear_model import LinearRegression
2121
from scipy.optimize import minimize
22+
from epde.supplementary import minmax_normalize
2223

2324
LOSS_NAN_VAL = 1e7
2425

@@ -129,10 +130,13 @@ def apply(self, objective: Equation, arguments: dict, force_out_of_place: bool =
129130
else:
130131
discr_feats = np.dot(features, objective.weights_final[:-1][objective.weights_internal != 0])
131132
discr_feats = discr_feats + objective.weights_final[-1]
133+
# discr = minmax_normalize(discr_feats.reshape(*data_shape)) - minmax_normalize(target.reshape(*data_shape))
134+
# discr = discr.flatten()
132135
discr = discr_feats - target
133136

134-
discr = np.multiply(discr, self.g_fun_vals) / np.std(target)
135-
rl_error = np.sqrt(np.mean(discr ** 2))
137+
discr = np.multiply(discr, self.g_fun_vals)
138+
# rl_error = np.mean(discr ** 2)
139+
rl_error = np.sum(np.abs(discr)) / np.sum(np.abs(target)) * 100
136140

137141
if not (self.params['penalty_coeff'] > 0. and self.params['penalty_coeff'] < 1.):
138142
raise ValueError('Incorrect penalty coefficient set, value shall be in (0, 1).')

epde/operators/common/right_part_selection.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ def apply(self, objective : Equation, arguments : dict):
4949
objective.reset_state(True)
5050

5151
while not (objective.simplified and objective.is_correct_right_part):
52-
objective.is_correct_right_part = False
52+
objective.reset_state(True)
5353
min_fitness = np.inf
5454
weights_internal = np.zeros_like(objective.structure)
55+
objective.weights_internal_evald = False
5556
min_idx = 0
5657
if not any(term.contains_variable(objective.main_var_to_explain) and term.contains_deriv(objective.main_var_to_explain) for term in objective.structure):
5758
objective.restore_property(mandatory_family=objective.main_var_to_explain, deriv=True)
@@ -69,12 +70,14 @@ def apply(self, objective : Equation, arguments : dict):
6970
pass
7071

7172
objective.weights_internal = weights_internal
73+
objective.weights_internal_evald = True
7274
objective.target_idx = min_idx
7375
self.simplify_equation(objective)
7476
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):
7577
objective.is_correct_right_part = True
7678
else:
7779
objective.right_part_selected = True
80+
objective.reset_state(False)
7881

7982
def simplify_equation(self, objective: Equation):
8083
# Get nonzero terms

epde/operators/common/sparsity.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@ def apply(self, objective : Equation, arguments : dict):
6666
positive=False, precompute=False, random_state=None,
6767
selection='random', tol=0.0001, warm_start=False)
6868
# estimator = STLSQ(threshold=objective.metaparameters[('sparsity', objective.main_var_to_explain)]['value'],
69-
# copy_X=True, unbias=True, max_iter=1000, alpha=0.05)
69+
# copy_X=True, unbias=True, max_iter=20, alpha=1e-5, ridge_kw={"tol": 1e-10})
7070
_, target, features = objective.evaluate(normalize = True, return_val = False)
7171
self.g_fun_vals = global_var.grid_cache.g_func.reshape(-1)
7272

7373
estimator.fit(features, target, sample_weight = self.g_fun_vals)
7474
objective.weights_internal = estimator.coef_
75+
# objective.weights_internal = estimator.coef_[0]
76+
objective.weights_internal_evald = True
7577

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

epde/operators/multiobjective/moeadd_specific.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,37 +366,42 @@ def apply(self, objective: ParetoLevels, arguments: dict):
366366

367367
while objective.unplaced_candidates:
368368
offspring = objective.unplaced_candidates.pop()
369-
attempt = 1
369+
attempt = 0
370+
replaced = 0
370371
mutation_attempt_limit = self.params['mutation_attempt_limit']
371372
offspring_attempt_limit = self.params['offspring_attempt_limit']
372373
temp_offspring = deepcopy(offspring)
373-
replaced = 0
374+
self.suboperators['sparsity'].apply(objective=temp_offspring,
375+
arguments=subop_args['sparsity'])
374376
while True:
375377
temp_offspring = self.suboperators['chromosome_mutation'].apply(objective=temp_offspring,
376378
arguments=subop_args['chromosome_mutation'])
377379
self.suboperators['right_part_selector'].apply(objective=temp_offspring,
378380
arguments=subop_args['right_part_selector'])
379-
temp_offspring.reset_state()
380381
system = temp_offspring.described_variables
381382
if system not in objective.history:
383+
382384
self.suboperators['chromosome_fitness'].apply(objective=temp_offspring,
383385
arguments=subop_args['chromosome_fitness'])
384386
self.suboperators['pareto_level_updater'].apply(objective=(temp_offspring, objective),
385387
arguments=subop_args['pareto_level_updater'])
386388
objective.history.add(system)
387-
print(temp_offspring.obj_fun)
389+
# print(temp_offspring.obj_fun)
388390
break
389391
elif replaced == offspring_attempt_limit:
390392
print("Could not generate unique offspring")
391393
break
392394
elif attempt == mutation_attempt_limit:
393395
temp_offspring = deepcopy(offspring)
396+
self.suboperators['sparsity'].apply(objective=temp_offspring,
397+
arguments=subop_args['sparsity'])
394398
replaced += 1
395399
attempt = 0
396400
attempt += 1
397401
return objective
398402

399403
def get_pareto_levels_updater(right_part_selector : CompoundOperator, chromosome_fitness : CompoundOperator,
404+
sparsity : CompoundOperator,
400405
mutation : CompoundOperator = None, constrained : bool = False,
401406
mutation_params : dict = {}, pl_updater_params : dict = {},
402407
combiner_params : dict = {}):
@@ -409,6 +414,7 @@ def get_pareto_levels_updater(right_part_selector : CompoundOperator, chromosome
409414
pl_updater = get_basic_populator_updater(pl_updater_params)
410415
updater.set_suboperators(operators = {'chromosome_mutation' : mutation,
411416
'pareto_level_updater' : pl_updater,
417+
'sparsity' : sparsity,
412418
'right_part_selector' : right_part_selector,
413419
'chromosome_fitness' : chromosome_fitness})
414420
return updater

epde/operators/multiobjective/mutations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ def apply(self, objective : Equation, arguments : dict):
6666
nonrs_terms_idx = [i for i, term in enumerate(objective.structure) if i != objective.target_idx]
6767
nonzero_terms_idx = [item for item, keep in zip(nonrs_terms_idx, nonzero_terms_mask) if keep]
6868
nonzero_terms_idx.append(objective.target_idx)
69-
# term_idx = np.random.choice(nonzero_terms_idx)
7069
if len(nonzero_terms_idx) > 0:
7170
term_idx = np.random.choice(nonzero_terms_idx)
7271
else:
7372
term_idx = objective.target_idx
73+
# term_idx = np.random.choice(range(len(objective.structure)))
7474
objective.structure[term_idx] = self.suboperators['mutation'].apply(objective=(term_idx, objective),
7575
arguments=subop_args['mutation'])
7676
return objective

epde/optimizers/moeadd/moeadd.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -335,24 +335,25 @@ def __init__(self, population_instruct, weights_num, pop_size, solution_params,
335335

336336
for solution_idx in range(pop_size - psize):
337337
solution_gen_idx = 0
338-
while True:
339-
if type(solution_params) == type(None): solution_params = {}
340-
temp_solution = pop_constructor.create(**solution_params)
341-
temp_solution.set_domain(psize + solution_idx)
342-
if not np.any([temp_solution == solution for solution in population]):
343-
population.append(temp_solution)
344-
print(f'New solution accepted, confirmed {len(population)}/{pop_size} solutions.')
345-
break
346-
if solution_gen_idx == soluton_creation_attempts['softmax'] and global_var.verbose.show_warnings:
347-
print('solutions tried:', solution_gen_idx)
348-
warnings.warn('Too many failed attempts to create unique solutions for multiobjective optimization.\
349-
Change solution parameters to allow more diversity.')
350-
if solution_gen_idx == soluton_creation_attempts['hardmax']:
351-
population.append(temp_solution)
352-
print(f'New solution accepted, despite being a dublicate of another solution.\
353-
Confirmed {len(population)}/{pop_size} solutions.')
354-
break
355-
solution_gen_idx += 1
338+
# while True:
339+
if type(solution_params) == type(None): solution_params = {}
340+
temp_solution = pop_constructor.create(**solution_params)
341+
temp_solution.set_domain(psize + solution_idx)
342+
population.append(temp_solution)
343+
# if temp_solution.described_variables not np.any([temp_solution == solution for solution in population]):
344+
# population.append(temp_solution)
345+
# print(f'New solution accepted, confirmed {len(population)}/{pop_size} solutions.')
346+
# break
347+
# if solution_gen_idx == soluton_creation_attempts['softmax'] and global_var.verbose.show_warnings:
348+
# print('solutions tried:', solution_gen_idx)
349+
# warnings.warn('Too many failed attempts to create unique solutions for multiobjective optimization.\
350+
# Change solution parameters to allow more diversity.')
351+
# if solution_gen_idx == soluton_creation_attempts['hardmax']:
352+
# population.append(temp_solution)
353+
# print(f'New solution accepted, despite being a dublicate of another solution.\
354+
# Confirmed {len(population)}/{pop_size} solutions.')
355+
# break
356+
solution_gen_idx += 1
356357
self.pareto_levels = ParetoLevels(population, sorting_method = nds_method, update_method = ndl_update) # initial_sort = False
357358
else:
358359
if not isinstance(passed_population, ParetoLevels):

epde/optimizers/moeadd/strategy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ def use_baseline(self, use_solver: bool = False, use_pic: bool = True, variation
7474
fitness = map_operator_between_levels(fitness, 'gene level', 'chromosome level',
7575
objective_condition=fitness_cond)
7676

77-
78-
77+
sparsity_c = map_operator_between_levels(sparsity, 'gene level', 'chromosome level')
7978

8079
rps_cond = lambda x: any([not elem_eq.right_part_selected for elem_eq in x.vals])
8180
sys_rps = map_operator_between_levels(right_part_selector, 'gene level', 'chromosome level',
@@ -85,6 +84,7 @@ def use_baseline(self, use_solver: bool = False, use_pic: bool = True, variation
8584
initial_sorter = get_initial_sorter(right_part_selector = sys_rps, chromosome_fitness = fitness,
8685
sorter_params = sorter_params)
8786
population_updater = get_pareto_levels_updater(right_part_selector = sys_rps, chromosome_fitness = fitness,
87+
sparsity=sparsity_c,
8888
constrained = False, mutation_params = mutation_params,
8989
pl_updater_params = pareto_updater_params,
9090
combiner_params = pareto_combiner_params)

epde/structure/main_structures.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,15 @@ def evaluate(self, structural, grids=None):
215215
self.prev_normalized = normalize
216216
value = super().evaluate(structural)
217217
if normalize:
218-
value = (value - np.mean(value)) / np.std(value)
218+
# value = (value - np.mean(value)) / np.std(value)
219219
# value = value / np.linalg.norm(value, 2)
220+
value = minmax_normalize(value)
220221

222+
# value = np.ones_like(value)
223+
# for factor in self.structure:
224+
# factor_value = factor.evaluate()
225+
# factor_value_normalized = minmax_normalize(factor_value)
226+
# value *= factor_value_normalized
221227
if np.all([len(factor.params) == 1 for factor in self.structure]) and grids is None:
222228
# Место возможных проблем: сохранение/загрузка нормализованных данных
223229
self.saved[normalize] = global_var.tensor_cache.add(self.cache_label, value, normalized=normalize)
@@ -582,14 +588,21 @@ def shifted_idx(idx):
582588
def reset_state(self, reset_right_part: bool = True):
583589
if reset_right_part:
584590
self.right_part_selected = False
591+
self.is_correct_right_part = False
592+
self.simplified = False
593+
self.weights_internal_evald = False
594+
self.weights_internal = None
585595
# self.weights_internal_evald = False
596+
# self.weights_internal = None
586597
self.weights_final_evald = False
598+
self.weights_final = None
587599
self.fitness_calculated = False
600+
self.fitness_value = None
588601
self.stability_calculated = False
602+
self.coefficients_stability = None
589603
self.aic_calculated = False
590-
self.simplified = False
591604
self.solver_form_defined = False
592-
self.is_correct_right_part = False
605+
593606

594607
@HistoryExtender('\n -> was copied by deepcopy(self)', 'n')
595608
def __deepcopy__(self, memo=None):
@@ -687,8 +700,8 @@ def weights_internal(self):
687700
@weights_internal.setter
688701
def weights_internal(self, weights):
689702
self._weights_internal = weights
690-
self.weights_internal_evald = True
691-
self.weights_final_evald = False
703+
# self.weights_internal_evald = True
704+
# self.weights_final_evald = False
692705

693706
@property
694707
def weights_final(self):
@@ -701,7 +714,7 @@ def weights_final(self):
701714
@weights_final.setter
702715
def weights_final(self, weights):
703716
self._weights_final = weights
704-
self.weights_final_evald = True
717+
# self.weights_final_evald = True
705718

706719
@property
707720
def text_form(self):

epde/supplementary.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from epde.solver.data import Domain
2121
from epde.solver.models import Fourier_embedding, mat_model
22+
from epde.preprocessing.smoothers import NN
2223

2324

2425
class BasicDeriv(ABC):
@@ -39,7 +40,7 @@ def take_derivative(self, u: Union[torch.nn.Sequential, torch.Tensor], args: tor
3940
args.requires_grad = True
4041
if axes == [None,]:
4142
return u(args)[..., component].reshape(-1, 1)
42-
if isinstance(u, torch.nn.Sequential):
43+
if isinstance(u, NN) or isinstance(u, torch.nn.Sequential):
4344
comp_sum = u(args)[..., component].sum(dim = 0)
4445
elif isinstance(u, torch.Tensor):
4546
raise TypeError('Autograd shall have torch.nn.Sequential as its inputs.')
@@ -346,22 +347,9 @@ def minmax_normalize(matrix):
346347
if np.ndim(matrix) == 0:
347348
raise ValueError('Incorrect input to the normalization: the data has 0 dimensions')
348349
elif np.ndim(matrix) == 1:
349-
return matrix
350+
return 2 * (matrix - matrix.min()) / (matrix.max() - matrix.min()) - 1
350351
else:
351-
domain_min = np.min(matrix)
352-
domain_max = np.max(matrix)
353-
domain_mean = np.mean(matrix)
354-
if domain_max != domain_min:
355-
matrix = (matrix - domain_mean - domain_min) / (domain_max - domain_min)
356-
# for i in np.arange(matrix.shape[0]):
357-
# row_min = np.min(matrix[i])
358-
# row_max = np.max(matrix[i])
359-
#
360-
# # Only normalize if the row has variation
361-
# if domain_max != domain_min:
362-
# matrix[i] = (matrix[i] - domain_mean - domain_min) / (domain_max - domain_min)
363-
# else:
364-
# # If all values are the same, set to 0.5 or keep original (0.5 is midpoint)
365-
# matrix[i] = 0.5
352+
for i in np.arange(matrix.shape[0]):
353+
matrix[i] = 2 * (matrix[i] - matrix[i].min()) / (matrix[i].max() - matrix[i].min()) - 1
366354

367355
return matrix

0 commit comments

Comments
 (0)