Further Details

Analysing the Best individuals

If we look at the car-evaluation's /run_42/best.json file:

{"features": 21, "phenotype": "~x['safety_med'],x['buying_high'],~x['safety_low'],~x['doors_2'],x['lug_boot_big'],~x['persons_2'],~x['persons_4'],x['maint_low'],~x['buying_med'],x['lug_boot_small'],x['doors_2'],x['buying_high'],x['maint_high'],(~x['safety_high']&x['lug_boot_small']),~x['maint_high'],~x['maint_low'],~x['buying_vhigh'],x['lug_boot_small'],(x['maint_vhigh']&~x['maint_high']),x['safety_med'],~x['persons_more']&(x['persons_4']&x['doors_3'])"}

We are able to see that the transformation has 21 features. It is possible to individually get each feature in a list by doing:

from fedora.core.utilities.lib import get_features

individual = Fedora.get_best("car-evaluation-results/", 42)
features = get_features(individual["phenotype"])

print(features)
["~x['safety_med']", "x['buying_high']", "~x['safety_low']", "~x['doors_2']", "x['lug_boot_big']", "~x['persons_2']", "~x['persons_4']", "x['maint_low']", "~x['buying_med']", "x['lug_boot_small']", "x['doors_2']", "x['buying_high']", "x['maint_high']", "(~x['safety_high']&x['lug_boot_small'])", "~x['maint_high']", "~x['maint_low']", "~x['buying_vhigh']", "x['lug_boot_small']", "(x['maint_vhigh']&~x['maint_high'])", "x['safety_med']", "~x['persons_more']&(x['persons_4']&x['doors_3'])"]

From here, one can extract all kinds of statistics concerning the phenotype of the best individuals.

Building a Custom Operator

Here we will build and use the "MyOpt" operator, showcased in the Representation and Operators section, and the concatLen operator to concat 2 strings and return the final length.

Simply create the MyOpt and concatLen functions and wrap them with the Infix class:

from fedora.sge.utilities.protected_math import Infix

def MyOpt(series: pd.Series):
    return series.apply(lambda x: x.count("i"))

def concatLen(s1: pd.Series, s2: pd.Series):
    return pd.Series(s1 + s2).apply(lambda x: x[::-1])

_MyOpt_ = Infix(MyOpt)
_cclen_ = Infix(concatLen)

One can invoke the functions in the following ways:

This is very useful since it allows for function calls without needing to enumerate the arguments with commas. When evaluating the operators using actual features, we obtain:

Therefore, the operators function as intended.

The next step is to incorporate these operators into the grammar, which might appear as follows:

The final step is to incorporate these operators into the framework.

Ephemeral Constants

We also provide support for ephemeral constantsarrow-up-right via the 'RANDFLOAT' and 'RANDINT' built-in functions. E.g. Supposing there are two types of numerical data — float and int — random noise can be incorporated in the following manner:

Where the values of fnoise and inoise are ephemeral constants.

Tailored Setups

If additional customization of the framework is required, such as incorporating a penalty into the fitness function, implementing early stopping for the evolution process, or logging more generational information, users can create their own class by inheriting from the Fedora class:

This example is available in herearrow-up-right.

Structured Grammatical Evolution

Structured Grammatical Evolution is also available through this package. Here is a symbolic regression example:

Last updated