Constraints

The microgp.constraints.Constraints class contains the set of macros and sections of which an individual is composed, the microgp.properties.Properties and the function that will evaluate the individuals (microgp.contraints.Constraints._evaluator).

Section

A section can be of several types:

Section class schema
class microgp.constraints.Section(name: str, instances: Optional[Tuple[int, int]] = None, label_format=None)

Base structural unit. A section can be composed by one or more macros, a set or a list of other subsections. See microgp.constraints.make_section.

How a section is built

microgp.constraints.make_section

To build a section the following method is used:

constraints.make_section(name: str = None, instances: Optional[Tuple[int, int]] = None, size: Tuple[int, int] = None, label_format: str = None) → microgp.constraints.Section

Builds a section from a human-readable description.

Parameters:
  • section_definition – macro, list of macros or set of macros that will be translated into MacroPool / SubsectionsSequence / SubsectionsAlternative
  • name (str) – Name of the section to build
  • instances (tuple(int,int)) – (None or (int >=0, int >0)) How many times the section can appear inside an individual
  • size (tuple(int,int) – ((int >=0, int >0)) number of macro that the section can contain
  • label_format (str) – define how to translate a node into string
Returns:

The section just built

Examples:

  • Create a section of name word_sec containing a macro (word_macro), it will appear once inside the individual

    >>> word_section = ugp4.make_section(word_macro, size=(1, 1), name='word_sec')
    
  • Create a section of name sec_jmp that contains 1 to 4 macros (jmp1), it will appear once inside the individual

    >>> sec_jmp = ugp4.make_section(jmp1, size=(1, 4), name='sec_jmp')
    
  • Create a section with a default unique name that contains 2 to 5 macros chosen in {add, sub} and it can appear 0 to 10 times inside the individual

    >>> generic_math = ugp4.make_section({add, sub}, size=(2, 5), instances=(0, 10))
    
  • Build the main section with 3 sections, the second one is a SubsectionsSequence that contains 3 sections:

    >>> library['main'] = [
    >>>     'Prologue...'
    >>>     [{sec2a, sec2b}, sec_jmp, '; this is a comment'],
    >>>     'Epilogue...'
    >>> ]
    

The main section is contained inside the RootSection.

RootSection

class microgp.constraints.RootSection

The ROOT section of an individual. Each individual have one and only one root section.

MacroPool

class microgp.constraints.MacroPool(macro_pool: Collection[microgp.macro.Macro] = None, name: str = None, size: Tuple[int, int] = (1, 1), **kwargs)

A pool of macros.

SubsectionsAlternative

class microgp.constraints.SubsectionsAlternative(name: str, sub_sections: Sequence[microgp.constraints.Section] = None, **kwargs)

A list of alternative (sub)sections. This type of section contains a sequence of sections.

SubsectionsSequence

class microgp.constraints.SubsectionsSequence(sub_sections: Sequence[microgp.constraints.Section] = None, name: str = None, **kwargs)

A sequence of subsections. This class contains a tuple of sub sections

Properties

Properties are boxes that can contain values and checkers that run tests on the values. The testers can return True or False. Values in Properties can be customized, for instance a value can be the number of macros in a certain section and can be set a checker on it that checks that this values doesn’t exceed a certain threshold.

Builders can be:

  • custom_builders: customizable by the user;
  • default_builders: builders provided with MicroGP package.

Another distinction:

  • base_builders: I can set a certain value;
  • cumulative_builders: I can set a value and it can be added up recursively going through the frame tree.

This checkers are called by microgp.individual.check_individual_validity

microgp.properties

class microgp.properties.Properties

Updates a dictionary of values and runs checks against them.

Properties are used to check if a frame (ie. the portion of the individual implementing a given section) is valid. First, all functions registered as values builders are called, then all functions registered as check are evaluated; if all succeeded, then True is turned.

Values are divided in custom and base. User’s builders build custom ones. Values can be retrieved through property values that merge the two, alternatively they can be retrieved through properties base_values and custom_values.

Values builders are functions returning a dictionary of values {‘value_name’: value} that is added to the current value-bag. Values cannot be shadowed.

Checks are called when the value bag is complete and get getting all values as parameters, i.e. check(**values)

Examples: create two cumulative (custom) builders and add a checker that test that two sections have the same number of nodes

>>> sec2a.properties.add_cumulative_builder(lambda num_nodes, **v: {'sec2a': num_nodes})
>>> sec2b.properties.add_cumulative_builder(lambda **v: {'sec2b': v['num_nodes']})
>>> library.global_properties.add_check(lambda sec2a, sec2b, **v: sec2a == sec2b)
base_values

Read-only dictionary of base values

cumulative_values

Read-only dictionary of custom values

run_checks()

Runs all checks against current values; returns True if all succeed.

update_values(cumulative_values: Optional[dict] = None, **kwargs)

Runs properties builders and collect the results into values dictionary.

values

Read-only dictionary of all values (both custom and base)

Default builders

microgp.default_builders

microgp.default_builders.default_base_builder(individual: Individual, frame: microgp.common_data_structures.Frame, **kwargs) → Dict[str, Any]

Get base stats of the frame

microgp.default_builders.default_cumulative_builder(individual: Individual, frame: microgp.common_data_structures.Frame, **kwargs) → Dict[str, Any]

Get base cumulative stats of the frame