Пример #1
0
 def test_register_by_name(self):
     i_set = InstructionSet()
     i_set.register_by_name(".*_mult")
     print(i_set)
     assert len(i_set) == 2
     assert set([i.name
                 for i in i_set.values()]) == {"int_mult", "float_mult"}
Пример #2
0
    def __init__(self,
                 n_inputs: int,
                 instruction_set: Union[InstructionSet, str],
                 literals: Sequence[Any],
                 erc_generators: Sequence[Callable],
                 distribution: DiscreteProbDistrib = "proportional"):
        self.n_inputs = n_inputs
        self.erc_generators = erc_generators

        self.instruction_set = instruction_set
        if self.instruction_set == "core":
            self.instruction_set = InstructionSet(register_core=True)
        self.type_library = self.instruction_set.type_library
        self.literals = [
            lit if isinstance(lit, Literal) else infer_literal(
                lit, self.type_library) for lit in literals
        ]

        if distribution == "proportional":
            self.distribution = (DiscreteProbDistrib().add(
                GeneTypes.INPUT, self.n_inputs).add(
                    GeneTypes.INSTRUCTION, len(self.instruction_set)).add(
                        GeneTypes.CLOSE,
                        sum([
                            i.code_blocks
                            for i in self.instruction_set.values()
                        ])).add(GeneTypes.LITERAL,
                                len(literals)).add(GeneTypes.ERC,
                                                   len(erc_generators)))
        else:
            self.distribution = distribution
Пример #3
0
    def __init__(self,
                 instruction_set: Union[InstructionSet, str] = "core",
                 reset_on_run: bool = True):
        self.reset_on_run = reset_on_run
        # If no instruction set given, create one and register all instructions.
        if instruction_set == "core":
            self.instruction_set = InstructionSet(register_core=True)
        else:
            self.instruction_set = instruction_set

        self.type_library = self.instruction_set.type_library

        # Initialize the PushState and status
        self.state: PushState = None
        self.status: PushInterpreterStatus = None
        self._validate()
Пример #4
0
def run_ga_on_odd_test(parallelism):
    X = np.arange(-10, 10).reshape(-1, 1)
    y = [[bool(x[0] % 2)] for x in X]

    instruction_set = (InstructionSet().register_core_by_stack(
        {"int"}, exclude_stacks={"str", "exec", "code"}))

    spawner = GeneSpawner(n_inputs=1,
                          instruction_set=instruction_set,
                          literals=[],
                          erc_generators=[
                              partial(random.randint, 0, 10),
                          ])

    est = PushEstimator(spawner=spawner,
                        population_size=30,
                        max_generations=3,
                        simplification_steps=10,
                        parallelism=parallelism)
    est.fit(X, y)

    assert isinstance(est.solution, Individual)
    assert len(est.solution.program.code) > 0

    path = "tmp.push"
    solution = est.solution.copy(deep=True)
    est.save(path)
    est.load(path)
    assert solution == est.solution
    os.remove(path)
Пример #5
0
    def __init__(self,
                 instruction_set: Union[InstructionSet, str] = "core",
                 config: PushInterpreterConfig = None,
                 verbosity_config: VerbosityConfig = "default"):
        # If no instruction set given, create one and register all instructions.
        if instruction_set == "core":
            self.instruction_set = InstructionSet(register_core=True)
        else:
            self.instruction_set = instruction_set

        self.type_library = self.instruction_set.type_library

        if config is None:
            self.config = PushInterpreterConfig()
        else:
            self.config = config

        if verbosity_config == "default":
            self.verbosity_config = DEFAULT_VERBOSITY_LEVELS[0]
        else:
            self.verbosity_config = verbosity_config

        # Initialize the PushState and status
        self._validate()
        self.reset()
Пример #6
0
    def __init__(self,
                 instruction_set: Union[InstructionSet, str] = "core",
                 config: PushInterpreterConfig = None):
        # If no instruction set given, create one and register all instructions.
        if instruction_set == "core":
            self.instruction_set = InstructionSet(register_all=True)
        else:
            self.instruction_set = instruction_set
        self._supported_types = self.instruction_set.supported_types()

        if config is None:
            self.config = PushInterpreterConfig()
        else:
            self.config = config

        # Initialize the PushState and status
        self.reset()
Пример #7
0
 def test_unregister(self, instr_set):
     i_set = InstructionSet()
     i_set.register(instr_set["int_add"])
     i_set.register(instr_set["int_sub"])
     i_set.unregister("int_add")
     assert len(i_set) == 1
     assert list(i_set.values())[0].name == "int_sub"
Пример #8
0
    def test_register_core_by_stack_with_exclude(self, core_type_lib):
        foo = common.instructions(core_type_lib)
        print([i for i in foo
               if i.name == "exec_dup_times"][0].required_stacks())

        i_set = InstructionSet(register_core=False)
        i_set.register_core_by_stack({"int"},
                                     exclude_stacks={"str", "exec", "code"})
        for i in i_set.values():
            if len(i.required_stacks()) > 0:
                print(i.name, i.required_stacks())
                assert i.name not in {
                    "exec_pop", "exec_dup", "exec_dup_times", "exec_swap",
                    "exec_rot", "exec_flush", "exec_stack_depth", "exec_yank",
                    "exec_yank_dup", "exec_shove", "exec_shove_dup"
                }
                assert "int" in i.required_stacks()
                assert "exec" not in i.required_stacks()
Пример #9
0
def simple_test_spawner():
    instruction_set = InstructionSet().register_core_by_stack({"int"}, exclude_stacks={"str", "exec", "code"})
    spawner = GeneSpawner(
        n_inputs=1,
        instruction_set=instruction_set,
        literals=[],
        erc_generators=[
            partial(random.randint, 0, 10),
        ]
    )
    return spawner
Пример #10
0
 def test_unregister(self, atoms):
     i_set = InstructionSet()
     i_set.register(atoms["add"])
     i_set.register(atoms["sub"])
     i_set.unregister("int_add")
     assert len(i_set) == 1
     assert list(i_set.values())[0].name == "int_sub"
Пример #11
0
    def __init__(self,
                 instruction_set: InstructionSet,
                 literals: Sequence[Union[Literal, Any]],
                 erc_generators: Sequence[Callable],
                 distribution: DiscreteProbDistrib = "proportional"):
        self.instruction_set = instruction_set
        self.type_library = instruction_set.type_library
        self.literals = [lit if isinstance(lit, Literal) else infer_literal(lit, self.type_library) for lit in literals]
        self.erc_generators = erc_generators

        if distribution == "proportional":
            self.distribution = (
                DiscreteProbDistrib()
                .add("instruction", len(instruction_set))
                .add("close", sum([i.code_blocks for i in instruction_set.values()]))
                .add("literal", len(literals))
                .add("erc", len(erc_generators))
            )
        else:
            self.distribution = distribution
Пример #12
0
    def __init__(self,
                 instruction_set: InstructionSet,
                 literals: Sequence[Union[Literal, Any]],
                 erc_generators: Sequence[Callable],
                 distribution: DiscreteProbDistrib = "proportional"):
        self.instruction_set = instruction_set
        self.literals = [
            lit if isinstance(lit, Literal) else Literal(lit)
            for lit in literals
        ]
        self.erc_generators = erc_generators

        if distribution == "proportional":
            self.distribution = (DiscreteProbDistrib().add(
                "instruction", len(instruction_set)).add(
                    "close",
                    sum([i.code_blocks for i in instruction_set.values()
                         ])).add("literal",
                                 len(literals)).add("erc",
                                                    len(erc_generators)))
        else:
            self.distribution = distribution
Пример #13
0
def test_ga_on_odd():
    X = np.arange(-10, 10).reshape(-1, 1)
    y = [[bool(x[0] % 2)] for x in X]

    instruction_set = (InstructionSet().register_by_type(
        ["int"], exclude=["str", "exec",
                          "code"]).register_n_inputs(X.shape[1]))

    spawner = GeneSpawner(instruction_set=instruction_set,
                          literals=[],
                          erc_generators=[
                              lambda: random.randint(0, 10),
                          ])

    est = PushEstimator(spawner=spawner,
                        population_size=20,
                        max_generations=10,
                        simplification_steps=100)
    est.fit(X, y)

    assert isinstance(est._result.program, CodeBlock)
    assert len(est._result.program) > 0
Пример #14
0
 def test_register_core(self, all_core_instructions):
     i_set = InstructionSet().register_core()
     assert set(i_set.values()) == all_core_instructions
Пример #15
0
 def test_register_core_by_stack(self):
     i_set = InstructionSet()
     i_set.register_core_by_stack({"int"})
     for i in i_set.values():
         if len(i.required_stacks()) > 0:
             assert "int" in i.required_stacks()
Пример #16
0
 def test_register_list(self, instr_set):
     i_set = InstructionSet()
     i_set.register_list([instr_set["int_add"], instr_set["int_sub"]])
     assert len(i_set) == 2
Пример #17
0
import sys

from pyshgp.gp.estimators import PushEstimator
from pyshgp.gp.genome import GeneSpawner
from pyshgp.gp.selection import Lexicase
from pyshgp.push.instruction_set import InstructionSet


def target_function(x: float) -> (float, float):
    return (max(0.0, x), max(0.1 * x, x))


X = np.arange(-1.0, 1.0, 0.15).reshape([-1, 1])
y = np.array([target_function(x[0]) for x in X])

instruction_set = (InstructionSet().register_by_type(
    ["float", "bool"]).register_n_inputs(X.shape[1]))

spawner = GeneSpawner(instruction_set=instruction_set,
                      literals=[0.1, 0.0],
                      erc_generators=[
                          lambda: random.randint(0, 10),
                      ])

ep_lex_sel = Lexicase(epsilon=True)

est = PushEstimator(population_size=500,
                    max_generations=50,
                    spawner=spawner,
                    selector=ep_lex_sel,
                    verbose=2)
Пример #18
0
X_train_synthetic = [mirror_vectors() for _ in range(10)] + \
                    [equal_vectors() for _ in range(10)] + \
                    [random_vectors() for _ in range(10)]

X_train = X_train_edge + X_train_synthetic
y_train = [[target_function(x[0], x[1])] for x in X_train]


X_test = [mirror_vectors() for _ in range(100)] + \
         [equal_vectors() for _ in range(100)] + \
         [random_vectors() for _ in range(100)]
y_test = [[target_function(x[0], x[1])] for x in X_test]

spawner = GeneSpawner(
    n_inputs=2,
    instruction_set=InstructionSet().register_core_by_stack(
        {"int", "bool", "vector_int", "exec"}),
    literals=[" ", "\n"],
    erc_generators=[
        lambda: random.random() < 0.5,
    ],
)

if __name__ == "__main__":
    est = PushEstimator(search="GA",
                        population_size=500,
                        max_generations=150,
                        spawner=spawner,
                        simplification_steps=100,
                        verbose=2)

    start = time.time()
def check_unary_fn_translation(program_name: str):
    interpreter = PushInterpreter(InstructionSet(register_core=True))
    check_translation(program_name, interpreter)
Пример #20
0
def simple_gene_spawner(atoms):
    i_set = InstructionSet()
    i_set.register_list([atoms["add"], atoms["sub"], atoms["if"]])
    l_set = [5, 1.2, True]
    return GeneSpawner(i_set, l_set, [random.random])
Пример #21
0
    PushTypeLibrary(register_core=False)
    .register(PushFloat)
    .create_and_register("point", (Point, ), coercion_func=to_point)
)


# An instruction set which will register all core instructions that can be supported
# using only exec, code, stdout, float, and point types.
#
# For example, the instruction int_from_float will NOT be registered because
# our type library does not define a type that would support the "int" stack.
#
# Our two custom instructions as well as the input instructions are also defined.
instruction_set = (
    InstructionSet(type_library=type_library, register_core=True)
    .register(point_distance_insrt)
    .register(point_from_floats_instr)
)

print(instruction_set.keys())

spawner = GeneSpawner(
    n_inputs=2,
    instruction_set=instruction_set,
    literals=[2.0],
    erc_generators=[]
)


# Our estimator with a custom interpreter defined.
est = PushEstimator(
Пример #22
0
 def test_register_list(self, atoms):
     i_set = InstructionSet()
     i_set.register_list([atoms["add"], atoms["sub"]])
     assert len(i_set) == 2
Пример #23
0
def simple_gene_spawner(instr_set):
    i_set = InstructionSet()
    i_set.register_list([instr_set["int_add"], instr_set["int_sub"], instr_set["exec_if"]])
    l_set = [5, 1.2, True]
    return GeneSpawner(1, i_set, l_set, [random.random])
Пример #24
0
def instr_set():
    return InstructionSet(register_core=True)
Пример #25
0
def point_instr_set(point_type_library, point_instructions):
    return (
        InstructionSet(type_library=point_type_library, register_core=True)
        .register_list(point_instructions)
    )
Пример #26
0
        return Rectangle(float(value[0]), float(value[1]))


type_library = (PushTypeLibrary(
    register_core=False).register(PushFloat).register(RectangleType()))
"""
Next we define out instruction set using the type library and the two instructions we created.
Our two custom instructions as well as the input instructions are  defined.
The instruction set will register all core instructions that can be supported 
    using only exec, code, float, and rectangle types because the only core PushType we registered was "PushInt"
For example, the instruction int_from_float will NOT be registered because
    our type library does not define a type that would support the "int" stack.
"""

instruction_set = (InstructionSet(
    type_library=type_library,
    register_core=True).register(rectangle_areas_instruction).register(
        rectangle_from_floats_instruction))

print("Stacks: ", instruction_set.required_stacks())
print("Types: ", type_library.supported_stacks())
print("Instruction Set: ", instruction_set.keys())
print()
"""
Next we have to declare our "GeneSpawner."
We pass to it our instruction_set.
n_inputs=2 because we would like the genome to possibly include 2 input instructions.
literals=[2.0] because it will detect that 2.0 is a float, 
    and the spawner will pull floats when spawning genes and genomes.

"""
Пример #27
0
"""The goal of the Odd problem is to evolve a program that will produce a True if
the input integer is odd, and a False if its even.
"""
import logging
import numpy as np
import random
import sys
from pyshgp.gp.estimators import PushEstimator
from pyshgp.gp.genome import GeneSpawner
from pyshgp.push.instruction_set import InstructionSet

X = np.arange(-10, 10).reshape(-1, 1)
y = [[bool(x % 2)] for x in X]

instruction_set = (InstructionSet(register_all=True).register_n_inputs(
    X.shape[1]))

spawner = GeneSpawner(instruction_set=instruction_set,
                      literals=[],
                      erc_generators=[lambda: random.randint(0, 10)])

est = PushEstimator(spawner=spawner,
                    population_size=500,
                    max_generations=200,
                    verbose=2)

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format="%(asctime)s %(levelname)s %(message)s",
                        stream=sys.stdout)
    est.fit(X, y)
Пример #28
0
class PushInterpreter:
    """An interpreter capable of running Push programs.

    Parameters
    ----------
    instruction_set : Union[InstructionSet, str], optional
        The InstructionSet to use for executing programs. Default is "core"
        which instansiates an InstructionSet using all the core instructions.
    config : PushInterpreterConfig, optional
        A PushInterpreterConfig specifying limits and early termination
        conditions. Default is None, which creates a config will all default
        values.
    verbosity_config : VerbosityConfig, optional
        A VerbosityConfig controling what is logged during the execution
        of the program. Default is no verbosity.

    Attributes
    ----------
    instruction_set : InstructionSet
        The InstructionSet to use for executing programs.
    config : PushInterpreterConfig
        A PushInterpreterConfig specifying limits and early termination
        conditions.
    verbosity_config : VerbosityConfig, optional
        A VerbosityConfig controling what is logged during the execution
        of the program. Default is no verbosity.
    state : PushState
        The current PushState. Contains one stack for each PushType utilized
        mentioned by the instructions in the instruction set.
    status : PushInterpreterStatus
        A string denoting if the Interpreter has enountered a situation
        where non-standard termination was required.

    """

    def __init__(self,
                 instruction_set: Union[InstructionSet, str] = "core",
                 config: PushInterpreterConfig = None,
                 verbosity_config: VerbosityConfig = "default"):
        # If no instruction set given, create one and register all instructions.
        if instruction_set == "core":
            self.instruction_set = InstructionSet(register_core=True)
        else:
            self.instruction_set = instruction_set

        self.type_library = self.instruction_set.type_library

        if config is None:
            self.config = PushInterpreterConfig()
        else:
            self.config = config

        if verbosity_config == "default":
            self.verbosity_config = DEFAULT_VERBOSITY_LEVELS[0]
        else:
            self.verbosity_config = verbosity_config

        # Initialize the PushState and status
        self._validate()
        self.reset()

    def _validate(self):
        library_type_names = set(self.type_library.keys())
        required_stacks = self.instruction_set.required_stacks() - {"stdout", "exec", "untyped"}
        if not required_stacks <= library_type_names:
            raise ValueError(
                "PushInterpreter instruction_set and type_library are incompatible. {iset} vs {tlib}. Diff: {d}".format(
                    iset=required_stacks,
                    tlib=library_type_names,
                    d=required_stacks - library_type_names,
                ))

    def reset(self):
        """Reset the interpreter status and PushState."""
        self.state = PushState(self.type_library)
        self.status = PushInterpreterStatus.normal
        self._verbose_trace = self.verbosity_config.program_trace
        self._log_fn_for_trace = log_function(self._verbose_trace)

    def _log_trace(self, msg=None, log_state=False):
        if msg is not None:
            self._log_fn_for_trace(msg)
        if log_state:
            self.state.pretty_print(self._log_fn_for_trace)

    def _evaluate_instruction(self, instruction: Union[Instruction, JitInstructionRef]):
        self.state = instruction.evaluate(self.state, self.config)

    def untyped_to_typed(self):
        """Infers PushType of items on state's untyped queue and pushes to corresponding stacks."""
        while len(self.state.untyped) > 0:
            el = self.state.untyped.popleft()
            push_type = self.type_library.push_type_of(el, error_on_not_found=True)
            self.state[push_type.name].push(el)

    def evaluate_atom(self, atom: Atom):
        """Evaluate an Atom.

        Parameters
        ----------
        atom : Atom
            The Atom (Literal, Instruction, JitInstructionRef, or CodeBlock) to
            evaluate against the current PushState.

        """
        try:
            if isinstance(atom, Instruction):
                self._evaluate_instruction(atom)
            elif isinstance(atom, JitInstructionRef):
                self._evaluate_instruction(self.instruction_set[atom.name])
            elif isinstance(atom, CodeBlock):
                for a in atom[::-1]:
                    self.state["exec"].push(a)
            elif isinstance(atom, Literal):
                self.state[atom.push_type.name].push(atom.value)
            elif isinstance(atom, Closer):
                raise PushError("Closers should not be in push programs. Only genomes.")
            else:
                raise PushError("Cannont evaluate {t}, require a subclass of Atom".format(t=type(atom)))
            self.untyped_to_typed()
        except Exception as e:
            err_type = type(e).__name__
            err_msg = str(e)
            raise PushError(
                "{t} raised while evaluating {atom}. Origional mesage: \"{m}\"".format(
                    t=err_type,
                    atom=atom,
                    m=err_msg
                ))

    def run(self,
            program: CodeBlock,
            inputs: Sequence,
            output_types: Sequence[str]):
        """Run a Push program given some inputs and desired output PushTypes.

        The general flow of this method is:
            1. Create a new push state
            2. Load the program and inputs.
            3. If the exec stack is empty, return the outputs.
            4. Else, pop the exec stack and process the atom.
            5. Return to step 3.

        Parameters
        ----------
        program
            Program to run.
        inputs
            A sequence of values to use as inputs to the push program.
        output_types
            A secence of values that denote the Pushtypes of the expected
            outputs of the push program.

        Returns
        -------
        Sequence
            A sequence of values pulled from the final push state. May contain
            pyshgp.utils.Token.no_stack_item if needed stacks are empty.

        """
        if self.config.reset_on_run:
            self.reset()

        # Setup
        self.state.load_program(program)
        self.state.load_inputs(inputs)
        stop_time = time.time() + self.config.runtime_limit
        steps = 0

        if self._verbose_trace >= self.verbosity_config.log_level:
            self._log_trace("Initial State:", True)

        # Iterate atom evaluation until entire program is evaluated.
        while len(self.state["exec"]) > 0:
            # Stopping conditions
            if steps > self.config.atom_limit:
                self.status = PushInterpreterStatus.atom_limit_exceeded
                break
            if time.time() > stop_time:
                self.status = PushInterpreterStatus.runtime_limit_exceeded
                break

            # Next atom in the program to evaluate.
            next_atom = self.state["exec"].pop()

            if self._verbose_trace >= self.verbosity_config.log_level:
                self._log_trace("Current Atom: " + str(next_atom))

            # Evaluate atom.
            old_size = len(self.state)
            self.evaluate_atom(next_atom)
            if len(self.state) > old_size + self.config.growth_cap:
                self.status = PushInterpreterStatus.growth_cap_exceeded
                break

            if self._verbose_trace >= self.verbosity_config.log_level:
                self._log_trace("Current State:", True)
            steps += 1

        if self._verbose_trace >= self.verbosity_config.log_level:
            self._log_trace("Finished program evaluation.")

        return self.state.observe_stacks(output_types)
Пример #29
0
    ["^_^ " * 5],
]
y_train_edge = [target_function(x[0]) for x in X_train_edge]

X_train_synthetic = [[synthetic_input()] for _ in range(70)]
y_train_synthetic = [target_function(x[0]) for x in X_train_synthetic]

X_train = X_train_edge + X_train_synthetic
y_train = y_train_edge + y_train_synthetic

X_test = [[synthetic_input()] for _ in range(100)]
y_test = [target_function(x[0]) for x in X_test]

# Spawner

instruction_set = (InstructionSet().register_by_type(
    ["int", "bool", "string", "char", "exec", "stdout"]).register_n_inputs(1))

spawner = GeneSpawner(
    instruction_set=instruction_set,
    literals=[Char(" "), Char("\n")],
    erc_generators=[lambda: Char(choice(_possible_chars)), synthetic_input],
)

# Estimator

est = PushEstimator(search="GA",
                    population_size=1000,
                    max_generations=100,
                    spawner=spawner,
                    last_str_from_stdout=True,
                    verbose=2)
Пример #30
0
class PushInterpreter:
    """An interpreter capable of running Push programs.

    Parameters
    ----------
    instruction_set : Union[InstructionSet, str], optional
        The ``InstructionSet`` to use for executing programs. Default is "core"
        which instantiates an ``InstructionSet`` using all the core instructions.

    Attributes
    ----------
    instruction_set : InstructionSet
        The ``InstructionSet`` to use for executing programs.
    state : PushState
        The current ``PushState``. Contains one stack for each ``PushType``
        mentioned by the instructions in the instruction set.
    status : PushInterpreterStatus
        A string denoting if the interpreter has encountered a situation
        where non-standard termination was required.

    """
    def __init__(self,
                 instruction_set: Union[InstructionSet, str] = "core",
                 reset_on_run: bool = True):
        self.reset_on_run = reset_on_run
        # If no instruction set given, create one and register all instructions.
        if instruction_set == "core":
            self.instruction_set = InstructionSet(register_core=True)
        else:
            self.instruction_set = instruction_set

        self.type_library = self.instruction_set.type_library

        # Initialize the PushState and status
        self.state: PushState = None
        self.status: PushInterpreterStatus = None
        self._validate()

    def _validate(self):
        library_type_names = set(self.type_library.keys())
        required_stacks = self.instruction_set.required_stacks() - {
            "stdout", "exec", "untyped"
        }
        if not required_stacks <= library_type_names:
            raise ValueError(
                "PushInterpreter instruction_set and type_library are incompatible. {iset} vs {tlib}. Diff: {d}"
                .format(
                    iset=required_stacks,
                    tlib=library_type_names,
                    d=required_stacks - library_type_names,
                ))

    def _evaluate_instruction(self, instruction: Instruction,
                              config: PushConfig):
        self.state = instruction.evaluate(self.state, config)

    def untyped_to_typed(self):
        """Infer ``PushType`` of items on state's untyped queue and push to corresponding stacks."""
        while len(self.state.untyped) > 0:
            el = self.state.untyped.popleft()
            push_type = self.type_library.push_type_of(el,
                                                       error_on_not_found=True)
            self.state[push_type.name].push(el)

    @tap
    def evaluate_atom(self, atom: Atom, config: PushConfig):
        """Evaluate an ``Atom``.

        Parameters
        ----------
        atom : Atom
            The Atom (``Literal``, ``InstructionMeta``, ``Input``, or ``CodeBlock``) to
            evaluate against the current ``PushState``.
        config : PushConfig
            The configuration of the Push program being run.

        """
        try:
            if isinstance(atom, InstructionMeta):
                self._evaluate_instruction(self.instruction_set[atom.name],
                                           config)
            elif isinstance(atom, Input):
                input_value = self.state.inputs[atom.input_index]
                self.state.untyped.append(input_value)
            elif isinstance(atom, CodeBlock):
                for a in atom[::-1]:
                    self.state["exec"].push(a)
            elif isinstance(atom, Literal):
                self.state[atom.push_type.name].push(atom.value)
            elif isinstance(atom, Closer):
                raise PushError(
                    "Closers should not be in push programs. Only genomes.")
            else:
                raise PushError(
                    "Cannot evaluate {t}, require a subclass of Atom".format(
                        t=type(atom)))
            self.untyped_to_typed()
        except Exception as e:
            err_type = type(e).__name__
            err_msg = str(e)
            raise PushError(
                "{t} raised while evaluating {atom}. Original message: \"{m}\""
                .format(t=err_type, atom=atom, m=err_msg))

    @tap
    def run(self,
            program: Program,
            inputs: list,
            print_trace: bool = False) -> list:
        """Run a Push ``Program`` given some inputs and desired output ``PushTypes``.

        The general flow of this method is:
            1. Create a new push state
            2. Load the program and inputs.
            3. If the exec stack is empty, return the outputs.
            4. Else, pop the exec stack and process the atom.
            5. Return to step 3.

        Parameters
        ----------
        program : Program
            Program to run.
        inputs : list
            A sequence of values to use as inputs to the push program.
        print_trace : bool
            If True, each step of program execution will be summarized in stdout.

        Returns
        -------
        Sequence
            A sequence of values pulled from the final push state. May contain
            pyshgp.utils.Token.no_stack_item if output stacks are empty.

        """
        push_config = program.signature.push_config

        if self.reset_on_run or self.state is None:
            self.state = PushState(self.type_library, push_config)
            self.status = PushInterpreterStatus.normal

        # Setup
        self.state.load_code(program.code)
        self.state.load_inputs(inputs)
        stop_time = time.time() + push_config.runtime_limit
        steps = 0

        if print_trace:
            print("Initial State:")
            self.state.pretty_print()

        # Iterate atom evaluation until entire program is evaluated.
        while len(self.state["exec"]) > 0:
            # Stopping conditions
            if steps > push_config.step_limit:
                self.status = PushInterpreterStatus.step_limit_exceeded
                break
            if time.time() > stop_time:
                self.status = PushInterpreterStatus.runtime_limit_exceeded
                break

            # Next atom in the program to evaluate.
            next_atom = self.state["exec"].pop()

            if print_trace:
                start = time.time()
                print("\nCurrent Atom: " + str(next_atom))

            # Evaluate atom.
            old_size = self.state.size()
            self.evaluate_atom(next_atom, push_config)
            if self.state.size() > old_size + push_config.growth_cap:
                self.status = PushInterpreterStatus.growth_cap_exceeded
                break

            if print_trace:
                duration = time.time() - start
                print("Current State (step {step}):".format(step=steps))
                self.state.pretty_print()
                print("Step duration:", duration)
            steps += 1

        if print_trace:
            print("Finished program evaluation.")

        return self.state.observe_stacks(program.signature.output_stacks)
Пример #31
0
 def test_register_core(self, all_core_instrucitons):
     i_set = InstructionSet().register_core()
     assert set(i_set.values()) == all_core_instrucitons
Пример #32
0
 def test_register_core_by_stack(self, core_type_lib):
     i_set = InstructionSet()
     i_set.register_core_by_stack({"int"})
     for i in i_set.values():
         if len(i.required_stacks()) > 0:
             assert "int" in i.required_stacks()
Пример #33
0
y_train = y_train_edge + y_train_synthetic

X_test = [[synthetic_input()] for _ in range(100)]
y_test = [target_function(x[0]) for x in X_test]

# Spawner


def random_char():
    """Return a random character."""
    return Char(choice(_possible_chars))


spawner = GeneSpawner(
    n_inputs=1,
    instruction_set=InstructionSet().register_core_by_stack(
        {"int", "bool", "string", "char", "exec", "stdout"}),
    literals=[" ", "\n"],
    erc_generators=[
        random_char,
    ],
)

if __name__ == "__main__":
    est = PushEstimator(search="GA",
                        population_size=500,
                        max_generations=150,
                        spawner=spawner,
                        simplification_steps=100,
                        last_str_from_stdout=True,
                        parallelism=True,
                        verbose=2)
Пример #34
0
 def test_register(self, instr_set):
     i_set = InstructionSet()
     i_set.register(instr_set["int_add"])
     assert len(i_set) == 1
Пример #35
0
 def test_register(self, atoms):
     i_set = InstructionSet()
     i_set.register(atoms["add"])
     assert len(i_set) == 1
Пример #36
0
from pyshgp.gp.estimators import PushEstimator
from pyshgp.gp.genome import GeneSpawner
from pyshgp.gp.selection import Lexicase
from pyshgp.push.instruction_set import InstructionSet


def target_function(x: float) -> (float, float):
    """Generate a training data point."""
    return max(0.0, x), max(0.1 * x, x)


X = np.arange(-1.0, 1.0, 0.05).reshape([-1, 1])
y = np.array([target_function(x[0]) for x in X])

spawner = GeneSpawner(n_inputs=1,
                      instruction_set=InstructionSet().register_core_by_stack(
                          {"float", "bool"}),
                      literals=[0.1, 0.0],
                      erc_generators=[
                          lambda: random.randint(0, 10),
                      ])

ep_lex_sel = Lexicase(epsilon=True)

if __name__ == "__main__":
    est = PushEstimator(population_size=300,
                        max_generations=50,
                        simplification_steps=500,
                        spawner=spawner,
                        selector=ep_lex_sel,
                        verbose=2)
Пример #37
0

def target_function(s):
    """Generate a training data point."""
    return s[:-2] + s[:-2]


X = np.array([
    "abcde", "", "E", "Hi", "Tom", "leprechaun", "zoomzoomzoom",
    "qwertyuiopasd", "GallopTrotCanter", "Quinona", "_abc"
]).reshape(-1, 1)
y = np.array([[target_function(s[0])] for s in X])

spawner = GeneSpawner(
    n_inputs=1,
    instruction_set=InstructionSet().register_core_by_stack({"str", "int"}),
    literals=[],
    erc_generators=[
        lambda: random.randint(0, 10),
    ]
)

if __name__ == "__main__":
    est = PushEstimator(
        spawner=spawner,
        population_size=300,
        max_generations=30,
        initial_genome_size=(10, 50),
        simplification_steps=500,
        parallelism=False,
        verbose=1
Пример #38
0
import sys

from pyshgp.gp.selection import Lexicase
from pyshgp.gp.estimators import PushEstimator
from pyshgp.gp.genome import GeneSpawner
from pyshgp.push.instruction_set import InstructionSet


def target_function(a, b):
    return (2 * a * b) + (b * b)


X = np.arange(50).reshape(-1, 2)
y = np.array([[target_function(x[0], x[1])] for x in X])

instruction_set = (InstructionSet().register_by_type(
    ["int"], exclude=["str", "exec", "code"]).register_n_inputs(X.shape[1]))

spawner = GeneSpawner(instruction_set=instruction_set,
                      literals=[],
                      erc_generators=[
                          lambda: random.randint(0, 10),
                      ])

ep_lex_sel = Lexicase(epsilon=True)

est = PushEstimator(population_size=200,
                    max_generations=50,
                    spawner=spawner,
                    selector=ep_lex_sel,
                    verbose=2)
Пример #39
0
class PushInterpreter:
    """An interpreter capable of running Push programs.

    Parameters
    ----------
    instruction_set : Union[InstructionSet, str], optional
        The InstructionSet to use for executing programs. Default is "core"
        which instansiates an InstructionSet using all the core instructions.
    config : PushInterpreterConfig, optional
        A PushInterpreterConfig specifying limits and early termination
        conditions. Default is None, which creates a config will all default
        values.

    Attributes
    ----------
    instruction_set : InstructionSet
        The InstructionSet to use for executing programs.
    config : PushInterpreterConfig
        A PushInterpreterConfig specifying limits and early termination
        conditions.
    state : PushState
        The current PushState. Contains one stack for each PushType utilized
        mentioned by the instructions in the instruction set.
    status : PushInterpreterStatus
        A string denoting if the Interpreter has enountered a situation
        where non-standard termination was required.

    """
    def __init__(self,
                 instruction_set: Union[InstructionSet, str] = "core",
                 config: PushInterpreterConfig = None):
        # If no instruction set given, create one and register all instructions.
        if instruction_set == "core":
            self.instruction_set = InstructionSet(register_all=True)
        else:
            self.instruction_set = instruction_set
        self._supported_types = self.instruction_set.supported_types()

        if config is None:
            self.config = PushInterpreterConfig()
        else:
            self.config = config

        # Initialize the PushState and status
        self.reset()

    def reset(self):
        """Reset the interpreter status and PushState."""
        self.state = PushState(self._supported_types)
        self.status = PushInterpreterStatus.normal

    def _evaluate_instruction(self, instruction: Union[Instruction,
                                                       JitInstructionRef]):
        self.state = instruction.evaluate(self.state, self.config)

    def evaluate_atom(self, atom: Atom):
        """Evaluate an Atom.

        Parameters
        ----------
        atom : Atom
            The Atom (Literal, Instruction, JitInstructionRef, or CodeBlock) to
            evaluate against the current PushState.

        """
        try:
            if isinstance(atom, Instruction):
                self._evaluate_instruction(atom)
            elif isinstance(atom, JitInstructionRef):
                self._evaluate_instruction(self.instruction_set[atom.name])
            elif isinstance(atom, CodeBlock):
                for a in atom[::-1]:
                    self.state["exec"].push(a)
            elif isinstance(atom, Literal):
                self.state[atom.push_type.name].push(atom.value)
            elif isinstance(atom, Closer):
                raise PushError(
                    "Closers should not be in push programs. Only genomes.")
            else:
                raise PushError(
                    "Cannont evaluate {t}, require a subclass of Atom".format(
                        t=type(atom)))
        except Exception as e:
            err_type = type(e).__name__
            err_msg = str(e)
            raise PushError(
                "{t} raised while evaluating {atom}. Origional mesage: \"{m}\""
                .format(t=err_type, atom=atom, m=err_msg))

    def run(self,
            program: CodeBlock,
            inputs: Sequence,
            output_types: Sequence[str],
            verbosity_config: VerbosityConfig = None):
        """Run a Push program given some inputs and desired output PushTypes.

        The general flow of this method is:
            1. Create a new push state
            2. Load the program and inputs.
            3. If the exec stack is empty, return the outputs.
            4. Else, pop the exec stack and process the atom.
            5. Return to step 3.

        Parameters
        ----------
        program
            Program to run.
        inputs
            A sequence of values to use as inputs to the push program.
        output_types
            A secence of values that denote the Pushtypes of the expected
            outputs of the push program.
        verbosity_config : VerbosityConfig, optional
            A VerbosityConfig controling what is logged during the execution
            of the program. Default is no verbosity.

        Returns
        -------
        Sequence
            A sequence of values pulled from the final push state. May contain
            pyshgp.utils.Token.no_stack_item if needed stacks are empty.

        """
        if self.config.reset_on_run:
            self.reset()

        self.state.load_program(program)
        self.state.load_inputs(inputs)
        stop_time = time.time() + self.config.runtime_limit
        steps = 0

        if verbosity_config is None:
            verbosity_config = DEFAULT_VERBOSITY_LEVELS[0]
        verbose_trace = verbosity_config.program_trace

        if verbose_trace:
            verbose_trace("Initial State:")
            self.state.pretty_print(verbose_trace)

        while len(self.state["exec"]) > 0:
            if steps > self.config.atom_limit:
                self.status = PushInterpreterStatus.atom_limit_exceeded
                break
            if time.time() > stop_time:
                self.status = PushInterpreterStatus.runtime_limit_exceeded
                break

            next_atom = self.state["exec"].pop()

            if verbose_trace:
                verbose_trace("Current Atom: " + str(next_atom))

            old_size = len(self.state)
            self.evaluate_atom(next_atom)
            if len(self.state) > old_size + self.config.growth_cap:
                self.status = PushInterpreterStatus.growth_cap_exceeded
                break

            if verbose_trace:
                verbose_trace("Current State:")
                self.state.pretty_print(verbose_trace)
            steps += 1

        if verbose_trace:
            verbose_trace("Finished program evaluation.")

        return self.state.observe_stacks(output_types)
Пример #40
0
 def test_register_core_by_name(self, core_type_lib):
     i_set = InstructionSet()
     i_set.register_core_by_name(".*_mult")
     assert len(i_set) == 2
     assert set([i.name for i in i_set.values()]) == {"int_mult", "float_mult"}