pg.hyper.ObjectTemplate

Accessible via pg.hyper.ObjectTemplate, pg.hyper.Template.

class ObjectTemplate(value, compute_derived=False, where=None)[source]

Bases: pg.hyper.HyperValue, pg.Formattable

Object template that encodes and decodes symbolic values.

An object template can be created from a hyper value, which is a symbolic object with some parts placeheld by hyper primitives. For example:

x = A(a=0,
  b=pg.oneof(['foo', 'bar']),
  c=pg.manyof(2, [1, 2, 3, 4, 5, 6]),
  d=pg.floatv(0.1, 0.5),
  e=pg.oneof([
    {
        'f': pg.oneof([True, False]),
    }
    {
        'g': pg.manyof(2, [B(), C(), D()], distinct=False),
        'h': pg.manyof(2, [0, 1, 2], sorted=True),
    }
  ])
})
t = pg.template(x)

In this example, the root template have 4 children hyper primitives associated with keys ‘b’, ‘c’, ‘d’ and ‘e’, while the hyper primitive ‘e’ have 3 children associated with keys ‘f’, ‘g’ and ‘h’, creating a conditional search space.

Thus the DNA shape is determined by the definition of template, described by geno.DNASpec. In this case, the DNA spec of this template looks like:

pg.geno.space([
    pg.geno.oneof([            # Spec for 'b'.
        pg.geno.constant(),    # A constant template for 'foo'.
        pg.geno.constant(),    # A constant template for 'bar'.
    ]),
    pg.geno.manyof([           # Spec for 'c'.
        pg.geno.constant(),    # A constant template for 1.
        pg.geno.constant(),    # A constant template for 2.
        pg.geno.constant(),    # A constant template for 3.
        pg.geno.constant(),    # A constant template for 4.
        pg.geno.constant(),    # A constant template for 5.
        pg.geno.constant(),    # A constant template for 6.
    ]),
    pg.geno.floatv(0.1, 0.5),  # Spec for 'd'.
    pg.geno.oneof([            # Spec for 'e'.
        pg.geno.space([
            pg.geno.oneof([          # Spec for 'f'.
                pg.geno.constant(),  # A constant template for True.
                pg.geno.constant(),  # A constant template for False.
            ])
        ]),
        pg.geno.space([
            pg.geno.manyof(2, [         # Spec for 'g'.
                pg.geno.constant(),     # A constant template for B().
                pg.geno.constant(),     # A constant template for C().
                pg.geno.constant(),     # A constant template for D().
            ], distinct=False)    # choices of the same value can
                                  # be selected multiple times.
            pg.geno.manyof(2, [         # Spec for 'h'.
                pg.geno.constant(),     # A constant template for 0.
                pg.geno.constant(),     # A constant template for 1.
                pg.geno.constant(),     # A constant template for 2.
            ], sorted=True)       # acceptable choices needs to be sorted,
                                  # which enables using choices as set (of
                                  # possibly repeated values).
        ])
    ])
It may generate DNA as the following:

DNA([0, [0, 2], 0.1, (0, 0)])

A template can also work only on a subset of hyper primitives from the input value through the where function. This is useful to partition a search space into parts for separate optimization.

For example:

t = pg.hyper.ObjectTemplate(
  A(a=pg.oneof([1, 2]), b=pg.oneof([3, 4])),
  where=lambda e: e.root_path == 'a')
assert t.dna_spec() == pg.geno.space([
    pg.geno.oneof(location='a', candidates=[
        pg.geno.constant(),   # For a=1
        pg.geno.constant(),   # For a=2
    ], literal_values=['(0/2) 1', '(1/2) 2'])
])
assert t.decode(pg.DNA(0)) == A(a=1, b=pg.oneof([3, 4]))

Methods:

custom_apply(path, value_spec, allow_partial)

Validate candidates during value_spec binding time.

dna_spec([location])

Return DNA spec (geno.Space) from this template.

encode(value)

Encode a value into a DNA.

format([compact, verbose, root_indent])

Format this object.

try_encode(value)

Try to encode a value without raise Exception.

Attributes:

hyper_primitives

Returns hyper primitives in tuple (relative path, hyper primitive).

is_constant

Returns whether current template is constant value.

root_path

Returns root path.

value

Returns templated value.

custom_apply(path, value_spec, allow_partial, child_transform=None)[source]

Validate candidates during value_spec binding time.

Return type:

Tuple[bool, pg.hyper.ObjectTemplate]

dna_spec(location=None)[source]

Return DNA spec (geno.Space) from this template.

Return type:

pg.geno.Space

encode(value)[source]

Encode a value into a DNA.

Example:

# DNA of a constant template:
template = pg.hyper.ObjectTemplate({'a': 0})
assert template.encode({'a': 0}) == pg.DNA(None)
# Raises: Unmatched value between template and input.
template.encode({'a': 1})

# DNA of a template containing only one pg.oneof.
template = pg.hyper.ObjectTemplate({'a': pg.oneof([1, 2])})
assert template.encode({'a': 1}) == pg.DNA(0)

# DNA of a template containing only one pg.oneof.
template = pg.hyper.ObjectTemplate({'a': pg.floatv(0.1, 1.0)})
assert template.encode({'a': 0.5}) == pg.DNA(0.5)
Return type:

pg.DNA

Parameters:

value – Value to encode.

Returns:

Encoded DNA.

Raises:

ValueError if value cannot be encoded by this template.

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

Format this object.

Return type:

str

property hyper_primitives: List[Tuple[str, HyperValue]][source]

Returns hyper primitives in tuple (relative path, hyper primitive).

property is_constant: bool[source]

Returns whether current template is constant value.

property root_path: KeyPath[source]

Returns root path.

try_encode(value)[source]

Try to encode a value without raise Exception.

Return type:

Tuple[bool, pg.DNA]

property value: Any[source]

Returns templated value.