pg.DNA

Accessible via pg.DNA, pg.geno.DNA.

class DNA(value=None, children=None, spec=None, metadata=None, *, allow_partial=False, **kwargs)[source]

Bases: pg.Object

The genome of a symbolic object relative to its search space.

DNA is a hierarchical structure - each DNA node has a value, and a list of child DNA nodes. The root node represents the genome that encodes an entire object relative to its space. The value of a DNA node could be None, an integer, a float number or a string, dependening on its specification (pg.DNASpec). A valid DNA has a form of the following.

Hyper value type (DNASpec type)

Possible values

Child nodes

pg.hyper.ObjectTemplate (pg.geno.Space)

None

(elements > 1)

DNA of child decision points (Choices/Float) in the template.

None (elements == 1 and elements[0]. num_choices > 1)

Children of elements[0]

int (elements == 1 and elements[0]. num_choices ==1)

Children of: elements[0][0]

float (elements == 1 and elements[0] is geno.Float)

Empty

pg.oneof (pg.geno.Choices)

int (candidate index as choice)

Children of Space for the chosen candidate

pg.manyof (:class:`pg.geno.Choices)

None (num_choices > 1

DNA of each chosen candidate

int (num_choices==1)

Children of chosen candidate

pg.floatv (pg.geno.Float )

float

Empty

pg.hyper.CustomHyper (pg.geno.CustomDecisionPoint)

string (serialized

object)

User defined.

DNA can also be represented in a compact form - a tree of numbers/strs, formally defined as:

<dna> := empty | <decision>
<decision>: = <single-decision>
           | <multi-decisions>
           | <conditional-choice>
           | <custom-decision>
<single-decision> := <categorical-decision>
                  | <float-decision>
                  | <custom-decision>
<categorical-decision> := int
<float-decision> := float
<custom-decision> := str
<multiple-decisions> := [<decision>, <decision>, ...]
<conditional-choice> := (<categorical-decision>,
                         <categorical-decision>,
                         ...
                         <decision>)

Thus DNA can be constructed by nested structures of list, tuple and numbers. The numeric value for DNA can be integer (as index of choice) or float (the value itself will used as decoded value).

Examples:

# Empty DNA. This may be generated by an empty template.
DNA()

# A DNA of a nested choice of depth 3.
DNA(0, 0, 0)

# A DNA of three choices at the same level,
# positioned at 0, 1, 2, each choice has value 0.
DNA([0, 0, 0])

# A DNA of two choices (one two-level conditional,
# one non-conditional), position 0 is with choice path: 0 -> [0, 1],
# while [0, 1] means it's a multi-choice, decodable by Sublist or Subset.
# position 1 is a single non-conditional choice: 0.
DNA([(0, [0, 1]), 0])

# A DNA with custom decision point whose encoding
# is defined by the user.
DNA('abc')

Attributes:

decision_ids

Returns decision IDs.

is_leaf

Returns whether the current node is a leaf node.

is_multi_choice_container

Returns True if the children of this DNA are multi-choice subchoices.

is_subchoice

Returns True if current DNA is a subchoice of a multi-choice.

literal_value

Returns the literal value represented by current DNA.

multi_choice_spec

Returns the multi-choice spec for child DNAs.

named_decisions

Returns a dict of name to the named DNA in the sub-tree.

parent_dna

Returns parent DNA.

root

Returns the DNA root.

spec

Returns DNA spec of current DNA.

userdata

Gets user data.

Methods:

format([compact, verbose, root_indent, ...])

Customize format method for DNA for more compact representation.

from_dict(dict_repr, dna_spec[, ...])

Create a DNA from its dictionary representation.

from_fn(dna_spec, generator_fn)

Generate a DNA with user generator function.

from_json(json_value, *[, allow_partial, ...])

Class method that load a DNA from a JSON value.

from_numbers(dna_values, dna_spec)

Create a DNA from a flattened list of dna values.

from_parameters(parameters, dna_spec[, ...])

Create DNA from parameters based on DNASpec.

get(key[, default])

Get an immediate child DNA or DNA in the sub-tree.

iter_dna()

Iterate DNA of the space starting from self.

next_dna()

Get the next DNA in the spec.

parameters([use_literal_values])

Returns parameters for this DNA to emit based on its spec.

parse(json_value[, spec])

Parse DNA from a nested structure of numbers.

set_metadata(key, value[, cloneable])

Set metadata associated with a key.

set_userdata(key, value[, cloneable])

Sets user data associated with a key.

sym_jsonify([compact, type_info])

Convert DNA to JSON object.

to_dict([key_type, value_type, ...])

Returns the dict representation of current DNA.

to_numbers([flatten])

Returns a (maybe) nested structure of numbers as decisions.

use_spec(spec)

Use a DNA spec for this node and children recursively.

property decision_ids: List[KeyPath][source]

Returns decision IDs.

format(compact=False, verbose=True, root_indent=0, *, markdown=False, list_wrap_threshold=80, as_dict=False, **kwargs)[source]

Customize format method for DNA for more compact representation.

classmethod from_dict(dict_repr, dna_spec, use_ints_as_literals=False)[source]

Create a DNA from its dictionary representation.

Return type:

pg.DNA

Parameters:
  • dict_repr – The dictionary representation of the DNA. The keys should be either strings as the decision point ID or DNASpec objects. The values should be either numeric or literal values for the decisions. For inactive decisions, their ID/spec should either be absent from the dictionary, or use None as their values.

  • dna_spec – The DNASpec that applies to the DNA.

  • use_ints_as_literals – If True, when an integer is encountered for a dictinonary value, treat it as the literal value. Otherwise, always treat it as a candidate index.

Returns:

A DNA object.

classmethod from_fn(dna_spec, generator_fn)[source]

Generate a DNA with user generator function.

Return type:

pg.DNA

Parameters:
  • dna_spec – The DNASpec for the DNA.

  • generator_fn

    A callable object with signature:

    (decision_point) -> decision

    The decision_point is a Choices object or a Float object. The returned decision should be:

    • a list of integer or a DNA object for a Choices decision point. When a DNA is returned, it will be used as the DNA for the entire sub-tree, hence generate_fn will not be called on sub-decision points.

    • a float or a DNA object for a Float decision point.

    • a string or a DNA object for a CustomDecisionPoint.

Returns:

A DNA generated from the user function.

classmethod from_json(json_value, *, allow_partial=False, root_path=None)[source]

Class method that load a DNA from a JSON value.

Return type:

pg.DNA

Parameters:
  • json_value – Input JSON value, only JSON dict is acceptable.

  • allow_partial – Whether to allow elements of the list to be partial.

  • root_path – KeyPath of loaded object in its object tree.

Returns:

A DNA object.

classmethod from_numbers(dna_values, dna_spec)[source]

Create a DNA from a flattened list of dna values.

Return type:

pg.DNA

Parameters:
  • dna_values – A list of DNA values.

  • dna_spec – DNASpec that interprets the dna values.

Returns:

A DNA object.

classmethod from_parameters(parameters, dna_spec, use_literal_values=False)[source]

Create DNA from parameters based on DNASpec.

Deprecated: use from_dict instead.

Return type:

pg.DNA

Parameters:
  • parameters – A 1-depth dict of parameter names to parameter values.

  • dna_spec – DNASpec to interpret the parameters.

  • use_literal_values – If True, parameter values are literal values from DNASpec.

Returns:

DNA instance bound with the DNASpec.

Raises:

ValueError – If parameters are not aligned with DNA spec.

get(key, default=None)[source]

Get an immediate child DNA or DNA in the sub-tree.

Return type:

Union[Any, None, pg.DNA, List[Optional[pg.DNA]]]

property is_leaf: bool[source]

Returns whether the current node is a leaf node.

property is_multi_choice_container: bool[source]

Returns True if the children of this DNA are multi-choice subchoices.

property is_subchoice: bool[source]

Returns True if current DNA is a subchoice of a multi-choice.

iter_dna()[source]

Iterate DNA of the space starting from self.

property literal_value: str | int | float | List[str | int | float][source]

Returns the literal value represented by current DNA.

property multi_choice_spec: DecisionPoint | None[source]

Returns the multi-choice spec for child DNAs.

Returns:

If the children of this DNA are decisions of a multi-choice’s subchoices, return the multi-choice spec (pg.geno.Choices). Otherwise returns None.

property named_decisions: Dict[str, DNA | List[DNA]][source]

Returns a dict of name to the named DNA in the sub-tree.

next_dna()[source]

Get the next DNA in the spec.

Return type:

Optional[pg.DNA]

parameters(use_literal_values=False)[source]

Returns parameters for this DNA to emit based on its spec.

Deprecated: use to_dict instead.

Return type:

Dict[str, str]

Parameters:

use_literal_values – If True, use literal values from DNASpec for Choices, otherwise returns ‘{choice}/{num_candidates} ({literal})’. Otherwise returns ‘{choice}/{num_candidates}’.

Returns:

Dict of parameter names to their values mapped from this DNA.

Raises:

RuntimeError – If DNA is not associated with a DNASpec.

property parent_dna: DNA | None[source]

Returns parent DNA.

classmethod parse(json_value, spec=None)[source]

Parse DNA from a nested structure of numbers.

Deprecated: use DNA.__init__ instead.

Return type:

pg.DNA

Parameters:
  • json_value – A nested structure of numbers.

  • spec – DNA spec that will be applied to current DNA tree.

Returns:

an instance of DNA object.

Raises:

ValueError – Bad format for json_value or parsed DNA does not conform to the DNA spec.

property root: DNA[source]

Returns the DNA root.

set_metadata(key, value, cloneable=False)[source]

Set metadata associated with a key.

Metadata associated with the DNA will be persisted and carried over across processes, which is different the userdata. (See set_userdata for more details.)

Return type:

pg.DNA

Parameters:
  • key – Key for the metadata.

  • value – Value for the metadata.

  • cloneable – If True, the key/value will be propagated during clone.

Returns:

Self.

set_userdata(key, value, cloneable=False)[source]

Sets user data associated with a key.

User data associated with the DNA will live only within current process, and is not carried over during serialization/deserialization, which is different from DNA metadata. (See set_metadata for more details.)

Return type:

pg.DNA

Parameters:
  • key – Key of the user data.

  • value – Value of the user data.

  • cloneable – If True, the key/value will be carry over to the cloned DNA.

Returns:

Self.

property spec: DNASpec | None[source]

Returns DNA spec of current DNA.

sym_jsonify(compact=True, type_info=True, **kwargs)[source]

Convert DNA to JSON object.

Return type:

Any

Parameters:
  • compact – Whether use compact form. If compact, the nested number structure in DNA.parse will be used, otherwise members will be rendered out as regular symbolic Object.

  • type_info – If True, type information will be included in output, otherwise type information will not be included. Applicable when compact is set to True.

  • **kwargs – Keyword arguments that will be passed to symbolic.Object if compact is False.

Returns:

JSON representation of DNA.

to_dict(key_type='id', value_type='value', multi_choice_key='subchoice', include_inactive_decisions=False, filter_fn=None)[source]

Returns the dict representation of current DNA.

Return type:

Dict[Union[pg.geno.DecisionPoint, str], Union[None, pg.DNA, float, int, str, List[pg.DNA], List[int], List[str]]]

Parameters:
  • key_type

    Key type in returned dictionary. Acceptable values are:

    • ’id’: Use the ID (canonical location) of each decision point as key. This is the default behavior.

    • ’name_or_id’: Use the name of each decision point as key if it’s present, otherwise use ID as key. When the name of a decision point is presented, it is guaranteed not to clash with other decision points’ names or IDs.

    • ’dna_spec’: Use the DNASpec object of each decision point as key.

  • value_type

    Value type for choices in returned dictionary. Acceptable values are:

    • ’value’: Use the index of the chosen candidate for Choices, and use the float number for Float. This is the default behavior.

    • ’dna’: Use DNA for all decision points.

    • ’choice’: Use ‘{index}/{num_candidates}’ for the chosen candidate for Choices, and the chosen float number for Float.

    • ’literal’: Use the literal value for the chosen candidate for Choices, and the chosen float number for Float. If the literal value for the Choices decision point is not present, fall back to the ‘{index}/{num_candidates}’ format.

    • ’choice_and_literal’: Use ‘{index}/{num_candidates} ({literal})’ for the chosen candidate for Choices and then chosen float number for Float. If the literal value for the Choices decision point is not present, fall back to the ‘{index}/{num_candidates}’ format.

  • multi_choice_key – ‘subchoice’, ‘parent’, or ‘both’. If ‘subchoice’, each subchoice will insert a key into the dict. If ‘parent’, subchoices of a multi-choice will share the parent spec as key, its value will be a list of decisions from the subchoices. If ‘both’, the dict will contain both the keys for subchoices and the key for the parent multi-choice.

  • include_inactive_decisions – If True, inactive decisions from the search space will be added to the dict with value None. Otherwise they will be absent in the dict.

  • filter_fn – Decision point filter. If None, all the decision points will be included in the dict. Otherwise only the decision points that pass the filter (returns True) will be included.

Returns:

A dictionary of requested key type to value type mapped from the DNA.

Raises:
  • ValueError – argument key_type or value_type is not valid.

  • RuntimeError – If DNA is not associated with a DNASpec.

to_numbers(flatten=True)[source]

Returns a (maybe) nested structure of numbers as decisions.

Return type:

Union[List[Union[str, int, float]], Any, int, float, str]

Parameters:

flatten – If True, the hierarchy of the numbers will not be preserved. Decisions will be returned as a flat list in DFS order. Otherwise, a nestable structure of numbers will be returned.

Returns:

A flat list or a hierarchical structure of numbers as the decisions made

for each decision point.

use_spec(spec)[source]

Use a DNA spec for this node and children recursively.

Return type:

pg.DNA

Parameters:

spec – DNA spec.

Returns:

Self.

Raises:

ValueError – current DNA tree does not conform to the DNA spec.

property userdata: AttributeDict[source]

Gets user data.