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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 5 18:48:23 2021
@author: mike_ubuntu
"""
import numpy as np
from functools import partial
def generate_partial(obj_function, equation_key):
return partial(obj_function, equation_key=equation_key)
def equation_fitness(system, equation_key):
'''
Evaluate the quality of the system of PDEs, using the individual values of fitness function for equations.
Parameters:
-----------
system - ``epde.structure.main_structures.SoEq`` object
The system, that is to be evaluated.
Returns:
----------
error : float.
The value of the error metric.
'''
# print(f'System, for which we evaluate fitness: {system.text_form}')
# print(f'For equation key {equation_key}, {system.vals[equation_key].fitness_calculated}')
assert system.vals[equation_key].fitness_calculated, 'Trying to call fitness before its evaluation.'
res = system.vals[equation_key].fitness_value
return res
def equation_complexity_by_terms(system, equation_key):
'''
Evaluate the complexity of the system of PDEs, evaluating a number of terms for each equation.
In the evaluation, we consider only terms with non-zero weights, and the target term with the free
coefficient are not included in the final metric due to their ubiquty in the equations.
Parameters:
-----------
system - ``epde.structure.main_structures.SoEq`` object
The system, that is to be evaluated.
Returns:
----------
discrepancy : list of integers.
The values of the error metric: list entry for each of the equations.
'''
return np.count_nonzero(system.vals[equation_key].weights_internal)
def equation_complexity_by_factors(system, equation_key):
'''
Evaluate the complexity of the system of PDEs, evaluating a number of factors in terms for each
equation. In the evaluation, we consider only terms with non-zero weights and target, while
the free coefficient is not included in the final metric. Also, the real-valued factors are
not considered in the result.
Parameters:
-----------
system - ``epde.structure.main_structures.SoEq`` object
The system, that is to be evaluated.
Returns:
----------
discrepancy : list of integers.
The values of the error metric: list entry for each of the equations.
'''
# eq_compl = 0
# for idx, term in enumerate(system.vals[equation_key].structure):
# if idx < system.vals[equation_key].target_idx:
# if not system.vals[equation_key].weights_final[idx] == 0:
# eq_compl += len(term.structure)
# elif idx > system.vals[equation_key].target_idx:
# if not system.vals[equation_key].weights_final[idx-1] == 0:
# eq_compl += len(term.structure)
# else:
# eq_compl += len(term.structure)
# return eq_compl
eq_compl = 0
for idx, term in enumerate(system.vals[equation_key].structure):
if idx < system.vals[equation_key].target_idx:
if not system.vals[equation_key].weights_final[idx] == 0:
eq_compl += complexity_deriv(term.structure)
elif idx > system.vals[equation_key].target_idx:
if not system.vals[equation_key].weights_final[idx-1] == 0:
eq_compl += complexity_deriv(term.structure)
else:
eq_compl += complexity_deriv(term.structure)
return eq_compl
def complexity_deriv(term_list: list):
total = 0
for factor in term_list:
if factor.deriv_code == [None]:
total += 0.5
elif factor.deriv_code is None:
total += 0.5
else:
total += len(factor.deriv_code)
return total*factor.param('power')