Push Types

A PushType is a named collection of Python types which is used to determine if multiple items should be considered the same type during Push program execution. For example, the provided PushType that denotes which values should be considered integers is the PushInt. It is named "int" and has the underlying types of (int, numpy.int64, numpy.int32, numpy.int16, numpy.int8).

Instructions which pull values from the integer stack will expect all elements to be of one of the underlying types.

A PushType can test if a value is an instance of one of the underlying types with the is_instance() method.

import numpy as np
from pyshgp.push.types import PushInt, PushStr

PushInt.is_instance(5)               # True
PushInt.is_instance(np.int64(100))   # True
PushInt.is_instance("Foo")           # False
PushInt.is_instance(np.str_("Bar"))  # False

PushStr.is_instance(5)               # False
PushStr.is_instance(np.int64(100))   # False
PushStr.is_instance("Foo")           # True
PushStr.is_instance(np.str_("Bar"))  # True

The core set of PushTypes include PushInt, PushFloat, PushStr, PushBool, and PushChar. Custom push types can be defined by instantiating new instances of the PushType class.

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def __repr__(self):
      return "Point<{x},{y}>".format(x=self.x, y=self.y)

PushPoint = PushType("point", (Point, ))

Push Type Coercion

The first type listed in the underlying types is considered the canonical type of the PushType. During Push program execution, type conversions will result in instances of the canonical type.

Push types can take an optional argument called a “coercion function.” This function must take a single input of any type and attempt to coerce it into the canonical type. Coercion functions can (and probably should) throw errors if the input value cannot be coerced into the canonical type.

The coercion function is used in the coerce method of the PushType.

def to_point(thing: Any) -> Point:
  return Point(float(thing[0]), float(thing[1]))

PushPoint = PushType("point", (Point, ), coercion_func=to_point)

PushPoint.coerce([5, -1])  # Point<5.0,-1.0>

The constructor of the canonical type is used as the coercion function if no coercion function is provided.

Push Type Libraries

The Push language operates using one stack per defined PushType. All literal values evaluated by the Push interpreter, or produced by a Push instruction, are placed on their corresponding stack for use by other instructions.

A PushTypeLibrary is a collection of PushType objects that is used to produce the correct stacks before program evaluation and validate that the instructions specified in the InstructionSet will supported.

If you want to use a PushGP Estimator or Search Algorithm that synthesizes program which manipulate custom data types (using custom instructions) you will have to provide the system with a InstructionSet which holds a custom``PushTypeLibrary``.

By default, all the core types are registered into a PushTypeLibrary but that can be disable using register_core=False which will result in only the exec and code stacks getting registered.

from pyshgp.push.type_library import PushTypeLibrary

lib = PushTypeLibrary()
lib.supported_stacks()  # {'bool', 'char', 'code', 'exec', 'float', 'int', 'str'}

lib2 = PushTypeLibrary(register_core=False)
lib2.supported_stacks()  # {'code', 'exec'}

User defined PushType objects (such as PushPoint from above) can be registered using the register() and register_list() methods.

lib = PushTypeLibrary()
lib.register(PushPoint) # Returns reference to the library for chaining calls to register.
lib.supported_stacks()  # {'bool', 'char', 'code', 'exec', 'float', 'int', 'point', 'str'}

As a shorthand, you can use the create_and_register method of the PushTypeLibrary to create and new PushType and immediately register it.

lib = (
  PushTypeLibrary(register_core=False)
  .create_and_register("point", (Point, ), coercion_func=to_point)
)
lib.supported_stacks()  # {'code', 'exec', 'point'}