Skip to content

Metrics

normalized_tree_distance(e_a, e_b)

Normalized edit distance between two trees according to Li, Y., & Chenguang, Z. (2011). A metric normalization of tree edit distance. Frontiers of Computer Science in China, 5, 119-125.

Source code in src/equation_tree/metrics.py
11
12
13
14
15
16
17
18
19
20
def normalized_tree_distance(e_a: EquationTree, e_b: EquationTree):
    """
    Normalized edit distance between two trees according to
    `Li, Y., & Chenguang, Z. (2011). A metric normalization of tree edit distance.
    Frontiers of Computer Science in China, 5, 119-125.`

    """
    if e_a.root is None or e_b.root is None:
        return 1
    return ned(e_a.root, e_b.root)

prediction_distance(e_a, e_b, X)

Mean squared difference between the prediction of two equations on X

Examples:

>>> is_operator = lambda x : x in ['+', '*', '**', '-']
>>> is_variable = lambda x : x in ['x', 'y']
>>> expr_1 = sympify('x + y')
>>> expr_2 = sympify('x')
>>> et_1 = EquationTree.from_sympy(
...     expr_1,
...     operator_test=is_operator,
...     variable_test=is_variable,
... )
>>> et_1.sympy_expr
x_1 + x_2
>>> et_2 = EquationTree.from_sympy(
...     expr_2,
...     operator_test=is_operator,
...     variable_test=is_variable,
... )
>>> et_2.sympy_expr
x_1
>>> prediction_distance(et_1, et_2, {'x_1': [1], 'x_2': [1]})
1.0
>>> prediction_distance(et_1, et_2, {'x_1': [1, 2, 3], 'x_2': [0, 0, 0]})
0.0
>>> prediction_distance(et_1, et_2, {'x_1': [1, 2], 'x_2': [1, 2]})
2.5
Source code in src/equation_tree/metrics.py
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
def prediction_distance(
        e_a: EquationTree, e_b: EquationTree, X: Union[dict, pd.DataFrame]
):
    """
    Mean squared difference between the prediction of two equations on X

    Examples:
        >>> is_operator = lambda x : x in ['+', '*', '**', '-']
        >>> is_variable = lambda x : x in ['x', 'y']
        >>> expr_1 = sympify('x + y')
        >>> expr_2 = sympify('x')
        >>> et_1 = EquationTree.from_sympy(
        ...     expr_1,
        ...     operator_test=is_operator,
        ...     variable_test=is_variable,
        ... )
        >>> et_1.sympy_expr
        x_1 + x_2
        >>> et_2 = EquationTree.from_sympy(
        ...     expr_2,
        ...     operator_test=is_operator,
        ...     variable_test=is_variable,
        ... )
        >>> et_2.sympy_expr
        x_1
        >>> prediction_distance(et_1, et_2, {'x_1': [1], 'x_2': [1]})
        1.0
        >>> prediction_distance(et_1, et_2, {'x_1': [1, 2, 3], 'x_2': [0, 0, 0]})
        0.0
        >>> prediction_distance(et_1, et_2, {'x_1': [1, 2], 'x_2': [1, 2]})
        2.5

    """
    predict_a = e_a.evaluate(X)
    predict_b = e_b.evaluate(X)
    squared_diff = (predict_a - predict_b) ** 2
    return squared_diff.mean()

symbolic_solution_diff(e_a, e_b)

Symbolic solution with difference constant based on La Cava, W. et al (2021). Contemporary symbolic regression methods and their relative performance. Examples: >>> is_operator = lambda x : x in ['+', '', '*', '-'] >>> is_variable = lambda x : x in ['x', 'y'] >>> is_constant = lambda x: is_numeric(x) >>> expr_1 = sympify('x + .1') >>> expr_2 = sympify('x') >>> et_1 = EquationTree.from_sympy( ... expr_1, ... operator_test=is_operator, ... variable_test=is_variable, ... constant_test=is_constant ... ) >>> et_1.sympy_expr x_1 + 0.1 >>> et_2 = EquationTree.from_sympy( ... expr_2, ... operator_test=is_operator, ... variable_test=is_variable, ... ) >>> et_2.sympy_expr x_1 >>> symbolic_solution_diff(et_1, et_2) 0.1

Source code in src/equation_tree/metrics.py
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
def symbolic_solution_diff(e_a: EquationTree, e_b: EquationTree):
    """
    Symbolic solution with difference constant based on
    `La Cava, W. et al (2021).
    Contemporary symbolic regression methods and their relative performance.`
    Examples:
        >>> is_operator = lambda x : x in ['+', '*', '**', '-']
        >>> is_variable = lambda x : x in ['x', 'y']
        >>> is_constant = lambda x: is_numeric(x)
        >>> expr_1 = sympify('x + .1')
        >>> expr_2 = sympify('x')
        >>> et_1 = EquationTree.from_sympy(
        ...     expr_1,
        ...     operator_test=is_operator,
        ...     variable_test=is_variable,
        ...     constant_test=is_constant
        ... )
        >>> et_1.sympy_expr
        x_1 + 0.1
        >>> et_2 = EquationTree.from_sympy(
        ...     expr_2,
        ...     operator_test=is_operator,
        ...     variable_test=is_variable,
        ... )
        >>> et_2.sympy_expr
        x_1
        >>> symbolic_solution_diff(et_1, et_2)
        0.1
    """
    diff = simplify(e_a.sympy_expr - e_b.sympy_expr)
    if diff.is_constant():
        return float(diff)
    else:
        return np.infty

symbolic_solution_quot(e_a, e_b)

Symbolic solution with quotient constant based on La Cava, W. et al (2021). Contemporary symbolic regression methods and their relative performance. Examples: >>> is_operator = lambda x : x in ['+', '', '', '-'] >>> is_variable = lambda x : x in ['x', 'y'] >>> is_constant = lambda x: is_numeric(x) >>> expr_1 = sympify('x * .1') >>> expr_2 = sympify('x') >>> et_1 = EquationTree.from_sympy( ... expr_1, ... operator_test=is_operator, ... variable_test=is_variable, ... constant_test=is_constant ... ) >>> et_1.sympy_expr 0.1x_1 >>> et_2 = EquationTree.from_sympy( ... expr_2, ... operator_test=is_operator, ... variable_test=is_variable, ... ) >>> et_2.sympy_expr x_1 >>> symbolic_solution_quot(et_1, et_2) 0.1

Source code in src/equation_tree/metrics.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def symbolic_solution_quot(e_a: EquationTree, e_b: EquationTree):
    """
    Symbolic solution with quotient constant based on
    `La Cava, W. et al (2021).
    Contemporary symbolic regression methods and their relative performance.`
    Examples:
        >>> is_operator = lambda x : x in ['+', '*', '**', '-']
        >>> is_variable = lambda x : x in ['x', 'y']
        >>> is_constant = lambda x: is_numeric(x)
        >>> expr_1 = sympify('x * .1')
        >>> expr_2 = sympify('x')
        >>> et_1 = EquationTree.from_sympy(
        ...     expr_1,
        ...     operator_test=is_operator,
        ...     variable_test=is_variable,
        ...     constant_test=is_constant
        ... )
        >>> et_1.sympy_expr
        0.1*x_1
        >>> et_2 = EquationTree.from_sympy(
        ...     expr_2,
        ...     operator_test=is_operator,
        ...     variable_test=is_variable,
        ... )
        >>> et_2.sympy_expr
        x_1
        >>> symbolic_solution_quot(et_1, et_2)
        0.1
    """
    quot_1 = simplify(e_a.sympy_expr / e_b.sympy_expr)
    quot_2 = simplify(e_a.sympy_expr / e_b.sympy_expr)
    if quot_1.is_constant():
        return min(float(quot_1), float(quot_2))
    else:
        return np.infty