Пример #1
0
def test_program_relu_2(interpreter: PushInterpreter):
    prog = load_program("relu_via_if")
    result = interpreter.run(prog, [-5], ["float"])
    assert result == [0.0]

    result = interpreter.run(prog, [5.6], ["float"])
    assert result == [5.6]
Пример #2
0
def test_program_point_dist(point_instr_set):
    interpreter = PushInterpreter(point_instr_set)
    prog = load_program("point_distance", interpreter)
    interpreter.run(prog, [1.0, 3.0, 3.0, 3.0], ["float"])
    assert list(interpreter.state["float"]) == [2.0]

    interpreter.run(prog, [3.0, 2.5, 3.0, -3.0], ["float"])
    assert list(interpreter.state["float"]) == [5.5]
Пример #3
0
def test_program_relu_2():
    interpreter = PushInterpreter(InstructionSet(register_core=True).register_n_inputs(1))
    prog = load_program("relu_via_if", interpreter)
    result = interpreter.run(prog, [-5], ["float"])
    assert result == [0.0]

    result = interpreter.run(prog, [5.6], ["float"])
    assert result == [5.6]
Пример #4
0
def check_program(name: str, inputs: list, outputs: list,
                  sig: ProgramSignature, iset: InstructionSet) -> PushState:
    """Returns the PushState for further validation."""
    interpreter = PushInterpreter(iset)
    prog = get_program(name, sig, interpreter)
    assert interpreter.run(prog, inputs) == outputs
    return interpreter.state
Пример #5
0
class TestPushInterpreterMethods(unittest.TestCase):
    def setUp(self):
        self.i = PushInterpreter()

    def test_reset(self):
        self.i.reset()

    def test_eval_atom_literal(self):
        self.i.eval_atom(5)
        self.assertEqual(self.i.state['_integer'][0], 5)

    def test_eval_atom_list(self):
        self.i.eval_atom([1, 2, 3, 4, 5])
        self.assertEqual(len(self.i.state['_exec']), 5)

    def test_eval_push(self):
        self.i.state['_exec'].push([1, 2, [3, 4], 5])
        self.i.eval_push()
        self.assertEqual(len(self.i.state['_integer']), 5)
        self.assertEqual(len(self.i.state['_exec']), 0)

    def test_run(self):
        outputs = self.i.run([7, 'hello'],
                             inputs=["a", "b", "c"],
                             output_types=['_string'])
        self.assertEqual(outputs, ['hello'])
Пример #6
0
def test_interpreter_constraints(push_config: PushConfig, instr_set: InstructionSet):
    name = "infinite_growth"
    sig = ProgramSignature(arity=0, output_stacks=["int"], push_config=push_config)
    interpreter = PushInterpreter(instr_set)
    cb = load_code(name, interpreter)
    program = Program(code=cb, signature=sig)
    output = interpreter.run(program, [0], print_trace=True)
    assert output[0] == int(push_config.numeric_magnitude_limit)
    assert interpreter.status == PushInterpreterStatus.step_limit_exceeded
Пример #7
0
def error_func(program):
    errors = []
    for x in range(10):
        # Create the push interpreter
        interpreter = PushInterpreter()
        y_hat = interpreter.run(program, [x], ['_integer'])[0]
        # Get output
        if y_hat is None:
            errors.append(1e5)
        else:
            # compare to target output
            y_target = target_function(x)
            # calculate error
            errors.append(abs(y_hat - y_target))
    return errors
Пример #8
0
def test_program_fibonacci(interpreter: PushInterpreter):
    prog = load_program("fibonacci")
    interpreter.run(prog, [5], [])
    assert list(interpreter.state["int"]) == [1, 1, 2, 3, 5]

    interpreter.run(prog, [1], [])
    assert list(interpreter.state["int"]) == [1]

    interpreter.run(prog, [-3], [])
    assert list(interpreter.state["int"]) == []
Пример #9
0
def error_func(program):
    errors = []
    for x in range(10):
        # Create the push interpreter and run program
        interpreter = PushInterpreter()
        y_hat = interpreter.run(program, inputs=[x],
                                output_types=['_integer'])[0]
        # Get output
        if y_hat is not None:
            # compare to target output
            target_int = target_function(x)
            # calculate error
            errors.append((y_hat - target_int)**2)
        else:
            errors.append(1e5)
    return errors
Пример #10
0
def iris_error_func(program):
    error_vec = []
    for i in range(X_train.shape[0]):
        interpreter = PushInterpreter()
        outputs = interpreter.run(program, X_train[i],
                                  ['_float', '_float', '_float'])
        not_none = [x for x in outputs if x is not None]
        if len(not_none) == 0:
            error_vec.append(1000000)
        else:
            y_hat = outputs.index(max(not_none))
            if y_hat == y_train[i]:
                error_vec.append(0)
            else:
                error_vec.append(1)
    return error_vec
Пример #11
0
def test_program_fibonacci():
    interpreter = PushInterpreter(InstructionSet(register_core=True).register_n_inputs(1))
    prog = load_program("fibonacci", interpreter)
    interpreter.run(prog, [5], [])
    assert list(interpreter.state["int"]) == [1, 1, 2, 3, 5]

    interpreter.run(prog, [1], [])
    assert list(interpreter.state["int"]) == [1]

    interpreter.run(prog, [-3], [])
    assert list(interpreter.state["int"]) == []
Пример #12
0
def test_program_rswn(interpreter: PushInterpreter):
    prog = load_program("replace_space_with_newline")
    interpreter.run(prog, ["hello world"], [])
    assert list(interpreter.state["int"]) == [10]
    assert interpreter.state.stdout == "hello\nworld"

    interpreter.run(prog, ["nospace"], [])
    assert list(interpreter.state["int"]) == [7]
    assert interpreter.state.stdout == "nospace"

    interpreter.run(prog, ["   "], [])
    assert list(interpreter.state["int"]) == [0]
    assert interpreter.state.stdout == "\n\n\n"
Пример #13
0
def odd_error_func(program, debug=False):
    errors = []
    for i in range(10):
        # Create the push interpreter
        interpreter = PushInterpreter()
        interpreter.state['_integer'].push(i)
        # Run program
        y_hat = interpreter.run(program, [i], ['_boolean'], debug)[0]
        # Get output
        if y_hat is None:
            errors.append(1e5)
        else:
            # compare to target output
            y = bool(i % 2)
            if y_hat == y:
                errors.append(0)
            else:
                errors.append(1)
    return errors
Пример #14
0
def test_program_rswn():
    interpreter = PushInterpreter(InstructionSet(register_core=True).register_n_inputs(1))
    prog = load_program("replace_space_with_newline", interpreter)
    interpreter.run(prog, ["hello world"], [])
    assert list(interpreter.state["int"]) == [10]
    assert interpreter.state.stdout == "hello\nworld"

    interpreter.run(prog, ["nospace"], [])
    assert list(interpreter.state["int"]) == [7]
    assert interpreter.state.stdout == "nospace"

    interpreter.run(prog, ["   "], [])
    assert list(interpreter.state["int"]) == [0]
    assert interpreter.state.stdout == "\n\n\n"
Пример #15
0
def string_error_func(program):
    inputs = [
        "abcde", "", "E", "Hi", "Tom", "leprechaun", "zoomzoomzoom",
        "qwertyuiopasd", "GallopTrotCanter", "Quinona", "_abc"
    ]
    errors = []

    for inpt in inputs:
        # Create the push interpreter
        interpreter = PushInterpreter()
        y_hat = interpreter.run(program, [inpt], ['_string'])[0]
        if y_hat is None:
            errors.append(1e5)
        else:
            # compare to target output
            target_output = inpt[:-2] + inpt[:-2]
            errors.append(
                string_difference(y_hat, target_output) +
                string_char_counts_difference(y_hat, target_output))
    return errors
Пример #16
0
class PushEstimator:
    """Simple estimator that synthesizes Push programs.

    Parameters
    ----------
    spawner : Union[GeneSpawner, str], optional
        The GeneSpawner to use when producing Genomes during initialization and
        variation. Default is all core instructions, no literals, and no ERC Generators.
    search : Union[SearchAlgorithm, str], optional
        The search algorithm, or its abbreviation, to use to when synthesizing
        Push programs.
    selector : Union[Selector, str], optional
        The selector, or name of selector, to use when selecting parents.
        The default is lexicase selection.
    variation_strategy : Union[VariationStrategy, dict, str]
        A VariationStrategy describing a collection of VariationOperators and how
        frequently to use them. If a dict is supplied, keys should be operator
        names and values should be the probability distribution. If a string is
        provided, the VariationOperators with that name will always be used.
        Default is ``"umad""``.
    population_size : int, optional
        The number of individuals hold in the population each generation. Default
        is 300.
    max_generations : int, optional
        The number of generations to run the search algorithm. Default is 100.
    initial_genome_size : Tuple[int, int], optional
        The range of genome sizes to produce during initialization. Default is
        (20, 100)
    simplification_steps : int
        The number of simplification iterations to apply to the best Push program
        produced by the search algorithm. Default 2000.
    interpreter : PushInterpreter, optional
        The PushInterpreter to use when making predictions. Also holds the instruction
        set to use
    parallelism : Union[Int, bool], optional
        Set the number of processes to spawn for use when performing embarrassingly
        parallel tasks. If false, no processes will spawn and compuation will be
        serial. Default is true, which spawns one process per available cpu.
    verbose : int, optional
        Indicates if verbose printing should be used during searching.
        Default is 0. Options are 0, 1, or 2.
    **kwargs
        Arbitrary keyword arguments. Examples of supported arguments are
        `epsilon` (bool or float) when using Lexicase as the selector, and
        `tournament_size` (int) when using tournament selection.

    """
    def __init__(self,
                 spawner: GeneSpawner,
                 search: str = "GA",
                 selector: Union[sl.Selector, str] = "lexicase",
                 variation_strategy: Union[vr.VariationStrategy, dict,
                                           str] = "umad",
                 population_size: int = 300,
                 max_generations: int = 100,
                 initial_genome_size: Tuple[int, int] = (20, 100),
                 simplification_steps: int = 2000,
                 last_str_from_stdout: bool = False,
                 interpreter: PushInterpreter = "default",
                 parallelism: Union[int, bool] = False,
                 push_config: PushConfig = "default",
                 verbose: int = 0,
                 **kwargs):
        self._search_name = search
        self.spawner = spawner
        self.selector = selector
        self.variation_strategy = variation_strategy
        self.population_size = population_size
        self.max_generations = max_generations
        self.initial_genome_size = initial_genome_size
        self.simplification_steps = simplification_steps
        self.last_str_from_stdout = last_str_from_stdout
        self.parallelism = parallelism
        self.verbose = verbose
        self.ext = kwargs
        set_verbosity(self.verbose)

        # Initialize attributes that will be set later.
        self.evaluator = None
        self.signature = None
        self.search = None
        self.solution = None

        if interpreter == "default":
            self.interpreter = PushInterpreter()
        else:
            self.interpreter = interpreter

        if push_config == "default":
            self.push_config = PushConfig()
        else:
            self.push_config = push_config

    def _build_search_algo(self):
        if isinstance(self.variation_strategy, dict):
            var_strat = vr.VariationStrategy()
            for op_name, prob in self.variation_strategy.items():
                var_op = vr.get_variation_operator(op_name)
                var_strat.add(var_op, prob)
            self.variation_strategy = var_strat

        search_config = sr.SearchConfiguration(
            signature=self.signature,
            spawner=self.spawner,
            evaluator=self.evaluator,
            selection=self.selector,
            variation=self.variation_strategy,
            population_size=self.population_size,
            max_generations=self.max_generations,
            initial_genome_size=self.initial_genome_size,
            simplification_steps=self.simplification_steps,
            parallelism=self.parallelism,
            push_config=self.push_config)
        self.search = sr.get_search_algo(self._search_name,
                                         config=search_config,
                                         **self.ext)

    @tap
    def fit(self, X, y):
        """Run the search algorithm to synthesize a push program.

        Parameters
        ----------
        X : pandas dataframe of shape = [n_samples, n_features]
            The training input samples.
        y : list, array-like, or pandas dataframe.
            The target values (class labels in classification, real numbers in
            regression). Shape = [n_samples] or [n_samples, n_outputs]

        """
        # arity is the number of inputs that the program takes.
        X, y, arity, y_types = check_X_y(X, y)
        output_types = [
            self.interpreter.type_library.push_type_for_type(t).name
            for t in y_types
        ]
        if self.last_str_from_stdout:
            ndx = list_rindex(output_types, "str")
            if ndx is not None:
                output_types[ndx] = "stdout"
        self.signature = ProgramSignature(arity=arity,
                                          output_stacks=output_types,
                                          push_config=self.push_config)
        self.evaluator = DatasetEvaluator(X, y, interpreter=self.interpreter)
        self._build_search_algo()
        self.solution = self.search.run()
        self.search.config.tear_down()

    def predict(self, X):
        """Execute the synthesized push program on a dataset.

        Parameters
        ----------
        X : pandas dataframe of shape = [n_samples, n_features]
            The set of cases to predict.

        Returns
        -------
        y_hat : pandas dataframe of shape = [n_samples, n_outputs]

        """
        check_is_fitted(self, "solution")
        return [
            self.interpreter.run(self.solution.program, inputs) for inputs in X
        ]

    def score(self, X, y):
        """Run the search algorithm to synthesize a push program.

        Parameters
        ----------
        X : pandas dataframe of shape = [n_samples, n_features]
            The training input samples.

        y : list, array-like, or pandas dataframe.
            The target values (class labels in classification, real numbers in
            regression). Shape = [n_samples] or [n_samples, n_outputs]

        """
        check_is_fitted(self, "solution")
        X, y, arity, y_types = check_X_y(X, y)
        self.evaluator = DatasetEvaluator(X, y, interpreter=self.interpreter)
        return self.evaluator.evaluate(self.solution.program)

    def save(self, filepath: str):
        """Load the found solution to a JSON file.

        Parameters
        ----------
        filepath
            Filepath to write the serialized search result to.

        """
        check_is_fitted(self, "solution")
        self.solution.save(filepath)

    def load(self, filepath: str):
        """Load a found solution from a JSON file.

        Parameters
        ----------
        filepath
            Filepath to read the serialized search result from.

        """
        self.solution = Individual.load(filepath)