Individual

The microgp.individual.Individual object represents a possible solution, the microgp.individual.Individual._graph attribute is a NetworkX MultiDiGraph, the nodes, inside it, are identified by their unique node_id (microgp.node.NodeID object that inherits from int).

Each node contains:

Structure of a node

Individual

microgp.individual

class microgp.individual.Individual(constraints: microgp.constraints.Constraints, graph: networkx.classes.multidigraph.MultiDiGraph = None)

A solution encoded in MicroGP, the unit of selection in the evolutive process. Individuals are directed multigraph (MultiDiGraph in NetworkX), that is, more than one directed edges may connect the same pair of nodes. An individual must be finalized to be printed and copied, once it is finalized (individual._finalized == True) it can’t be modified.

What an Individual contains:

  • node_id (int): is the unique node_id of the individual

  • _constraints (Constraints): is a reference to the constraints used to generate them

  • _graph contains a reference to the nx MultiDiGraph. Inside it, node are identified by their unique node_id (NodeID object) and their data are stored as attributes:

    • macro: a reference to the macro
    • parameters: a dictionary with the actual parameters values
    • frame_path: path of the node in the constraints hierarchy
  • _operator (callable): contains the pointer to the operator with which it was created

  • _parents (Set[Individual] or None): set of parent individuals from which the individual was created. None if it has no parents

  • _age (int): count of how many epochs the individual lived

  • _canonic_phenotype (str): phenotype of the individual. It can be retrieved by printing the individual. It must be finalized

Parameters:
  • constraints – constraints of the individual
  • copy_from – Individual to clone (if specified)

Examples:

  • Create a new individual with its constraints
>>> first_individual = Individual(constraints=constraints)
  • Clone an individual (same graph_manager, same parameter values, different NodeIDs and node_id)
>>> copied_individual = Individual(constraints=first_individual.constraints, copy_from=first_individual)
  • Print the phenotype representation of an individual
>>> print(first_individual)
add_node(parent_node: Optional[microgp.node.NodeID], macro: microgp.macro.Macro, frame_path: Sequence[microgp.common_data_structures.Frame]) → microgp.node.NodeID

Adds a node in the individual and chains it

Parameters:
  • parent_node (NodeID or None) – the previous block in the dump, if
  • the node will be the root of the individual (None) –
  • macro (Macro) – the macro that the node will contain
  • frame_path (Sequence of Frame) – the full frame path to the section containing the node.
Returns:

The NodeID of the node just created

copy_parameters(source_individual: microgp.individual.Individual, node_translation: Dict[microgp.node.NodeID, microgp.node.NodeID], destination_node_id: microgp.node.NodeID)

Create parameters of the given node and copy their values from the original node (=``node_translation.keys()``)

Parameters:
  • source_individual (Individual) – individual that contains the parameter values of the nodes to copy
  • node_translation (Dict[NodeID, NodeID]) – correspondences between source node ids and destination node ids
  • destination_node_id (NodeID) – NodeID of the node to copy
Returns:

Dictionary that contains the parameters of the new copied node

copy_section_node_structure(source_individual: microgp.individual.Individual, source_head: microgp.node.NodeID = None) → Dict[microgp.node.NodeID, microgp.node.NodeID]

Copy the structure of a section from the source_individual to self. Used by the builder of the Individual when copy_from is not None.

Parameters:
  • source_individual (Individual) – Individual from which to copy the section structure
  • source_head (NodeID) – NodeID of the head of the next-chain (section)
Returns:

The correspondences between source `NodeID`s and destination `NodeID`s

draw(*args, edge_color=None, with_labels=True, node_size=700, node_color=None, **kwargs)

Draws the individual. All parameters are passed to nx.draw. If node_color == None then each next-chain will be colored with different colors (max 10 colors).

finalize() → None

Final setup of an individual: manage the pending movable nodes, remove non-visitable nodes from the graph_manager, initialize the frame tree and the properties, set the canonical representation of an individual. :return:

frames(section: microgp.constraints.Section = None, section_name: str = None) → Set[microgp.common_data_structures.Frame]

Get all frames of an individual belonging to a given section

Parameters:
  • section (Section) – limit to frames belonging to the section
  • section_name (str) – limit to frames belonging to the section (name)
Returns:

A set of frames

get_next(node: microgp.node.NodeID) → microgp.node.NodeID

Get the successor of node (ie. the next block in the dump)

Parameters:node (NodeID) – NodeID of the node of which I need the next
Returns:NodeID of the next node, None if it is the last one in the graph_manager
get_predecessors(node: microgp.node.NodeID) → List[microgp.node.NodeID]

Get the list of al predecessors of a given node (following next’s)

Parameters:node (NodeID) – NodeID of the node of which I need the predecessors
Returns:The list of NodeID of preceding nodes, None if there are none
get_unique_frame_name(section: Union[microgp.constraints.Section, str]) → str

Get a name never used in the individual by any other frame

Parameters:section (Section) – section to which the frame refers (Section object or name of the section)
Returns:The unique name of the new frame

Set the value of the parameters of type LocalReference and ExternalReference when the node is movable

randomize_macros() → None

Randomize the values of the parameters inside the macros

remove_node(node_to_delete: microgp.node.NodeID) → None

Delete the node from the graph_manager and connect the edges of the currently connected nodes

Parameters:node_to_delete (NodeID) – Node to delete
run_paranoia_checks() → bool

Checks the internal consistency of a “paranoid” object.

The function should be overridden by the sub-classes to implement the required, specific checks. It always returns True, but throws an exception whenever an inconsistency is detected.

Notez bien: Sanity checks may be computationally intensive, paranoia checks are not supposed to be used in production environments (i.e., when -O is used for compiling). Their typical usage is: assert foo.run_paranoia_checks()

Returns:True (always)
Raise:
AssertionError if some internal data structure is incoherent
set_canonical() → None

Set the canonical representation of an individual (self._canonic_phenotype)

stringify_node(node: microgp.node.NodeID) → str

Generates the string with the node’s current parameters

Parameters:node – NodeID of the node to be converted into string
Returns:The string that describes the macro and its parameters of the selected node
valid

Test whole set of checkers to validate the individual

Returns:True if the individual have passed all the tests, False otherwise

NodesCollection

class microgp.individual.NodesCollection(individual: Individual, nx_graph: networkx.classes.multidigraph.MultiDiGraph)

Collection of nodes of an individual; quite but not completely different from a NetworkX node view.

When used as a dictionary it allows read-only access to NodeViews. E.g.,

>>> for n in ind.node_list;
>>>     print(ind.node_list[n]['foo'])
>>>     ind.node_list[n]['bar'] = 41    # nodes can be modified as a dictionary
>>>     ind.node_list[n].baz += 1       # or as properties

When NodesCollection is used as a function it allows to select nodes using various filters, e.g.,

>>> ind.node_list(section_selector='main', heads_selector=False, data=True)
Parameters:
  • data – When data is None, the return value is a list of microgp.node.NodeID(). When data is True, the return value is dictionary of dictionaries {node_id: {<all node properties>}}. When data is the key of a node property, the return value is a dictionary {node_id: <the specified field>}
  • default – When property selected by data does not exists, the node is included in the result withe the specified value. If default is None, the node is not included in the result.
  • select_section (str or Section) – Only include nodes belonging to the specified section.
  • select_frame (str or Frame) – Only include nodes belonging to the specified frame.
  • select_heads (None or bool) – if specified, return only nodes that are heads of sections (True); or nodes that are internal to sections (False)
Returns:

Either a list or a dictionary, see data

GraphWrapper_DELETED

Graph information getter methods

individual.get_nodes_in_frame(frame: microgp.common_data_structures.Frame, frame_path_limit: int = None) → List[microgp.node.NodeID]

Gets all nodes of an individual inside a given frame

Parameters:
  • individual (Individual) – the individual
  • frame (Frame) – the frame
  • frame_path_limit (int) – how deep is the path for matching (positive: from root, negative: from leaf)
Returns:

A list of of Nodes

individual.get_nodes_in_section(section: microgp.constraints.Section, frame_path_limit: int = None, head: bool = False) → List[microgp.node.NodeID]

Gets all nodes of an individual inside a given frame

If frame_path_limit is set to N with N > 0, only the first N frames are considered for the match. If With N < 0, only the last N frames are considered for the match.

Parameters:
  • individual (Individual) – the individual
  • section (Section) – the section
  • frame_path_limit (int) – limit the frame path
  • head (bool) – returns only the head of the section
Returns:

The list of nodes in the selected section

individual.get_frames(section: microgp.constraints.Section = None, section_name: str = None) → Set[microgp.common_data_structures.Frame]

Gets all frames of an individuals belonging to a given section

Parameters:
  • individual (Individual) – the individual
  • section (Section) – limit to frames belonging to the section
  • section_name (str) – limit to frames belonging to the section (name)
Returns:

A set of frames

individual.get_macro_pool_nodes_count(frames: Set[microgp.common_data_structures.Frame] = None) → Dict[microgp.common_data_structures.Frame, int]

Get a dict containing {Frame: number_of_macros}. Selects only MacroPools

Parameters:
  • frames (Set[Frame]) – set of frames of which I want the number of nodes
  • individual (Frame) – individual from which count the nodes
Returns:

Dictionary containing the amount of nodes (value) for each Frame (key)

Meta private:
individual.check_individual_validity() → bool

Check an individual against its constraints.

Check the validity of all parameters (e.g., range), then the default Properties (e.g., number of macros in sections), and finally all the custom Properties added by the user.

The result is cached, as individuals must be finalized to be checked

Parameters:individual (Individual) – the individual to be checked
Returns:The validity as a boolean value

Macro

microgp.macro

class microgp.macro.Macro(text: str, parameters_type: dict = None)

The blueprint of macro.

A “macro” is a fragment of text with zero or more variable parameters. it is the building block of a solution. A macro is associated with the node in the DAG encoding the individual.

Notes

Attributes are read-only and can only be set when the macro is created. Some parameters are by default available to all macros, the list is in Macro.MAGIC_PARAMETERS

add_parameter(name: str, parameter_type: microgp.parameter.abstract.Parameter) → None

Add parameters to the macro

Parameters:
  • name – name of the parameter
  • parameter_type – type of the parameter
run_paranoia_checks() → bool

Checks the internal consistency of a “paranoid” object.

The function should be overridden by the sub-classes to implement the required, specific checks. It always returns True, but throws an exception whenever an inconsistency is detected.

Notez bien: Sanity checks may be computationally intensive, paranoia checks are not supposed to be used in production environments (i.e., when -O is used for compiling). Their typical usage is: assert foo.run_paranoia_checks()

Returns:True (always)
Raise:
AssertionError if some internal data structure is incoherent

Node

microgp.node

class microgp.node.NodeID(value: Optional[int] = None)

A node in the directed MultiDiGraph describing the individual.

Use n = NodeID() to get a unique node_id.

Use n = NodeID(int) to get a specific node node_id. This is deprecated as it could only be useful during debug.

is_valid(value: Any) → bool

Checks an object against a specification. The function may be used to check a value against a parameter definition, a node against a section definition).

Returns:True if the object is valid, False otherwise

Frame

A Frame is a unique instance of a section, its name is unique and can be generated by the microgp.individual.Individual.get_unique_frame_name method in the following way:

>>> Frame(individual.get_unique_frame_name(section), section)
class microgp.common_data_structures.Frame(name, section)
name

Alias for field number 0

section

Alias for field number 1