def test_eval_tree(self):
        # create terminal nodes
        term_node = Node(NodeType.CONSTANT, value=100.0)
        input_node = Node(NodeType.INPUT, name="x")

        # create function nodes
        mul_func = Node(
            NodeType.FUNCTION,
            name="MUL",
            arity=2,
            branches=[input_node, term_node]
        )

        rad_func = Node(
            NodeType.FUNCTION,
            name="RAD",
            arity=1,
            branches=[mul_func]
        )

        sin_func = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[rad_func]
        )

        # create tree
        tree = Tree()
        tree.root = sin_func
        tree.update()

        # evaluate tree
        score, output = evaluator.eval_tree(tree, self.functions, self.config)
        self.assertEquals(round(score, 7), 0.5000001)
Exemple #2
0
    def test_eval_tree(self):
        # create terminal nodes
        term_node = Node(NodeType.CONSTANT, value=100.0)
        input_node = Node(NodeType.INPUT, name="x")

        # create function nodes
        mul_func = Node(NodeType.FUNCTION,
                        name="MUL",
                        arity=2,
                        branches=[input_node, term_node])

        rad_func = Node(NodeType.FUNCTION,
                        name="RAD",
                        arity=1,
                        branches=[mul_func])

        sin_func = Node(NodeType.FUNCTION,
                        name="SIN",
                        arity=1,
                        branches=[rad_func])

        # create tree
        tree = Tree()
        tree.root = sin_func
        tree.update()

        # evaluate tree
        score, output = evaluator.eval_tree(tree, self.functions, self.config)
        self.assertEquals(round(score, 7), 0.5000001)
Exemple #3
0
    def test_generate_eq_function(self):
        # create terminal nodes
        term_node = Node(NodeType.CONSTANT, value=100.0)
        input_node = Node(NodeType.INPUT, name="x")

        # create function nodes
        mul_func = Node(NodeType.FUNCTION,
                        name="MUL",
                        arity=2,
                        branches=[input_node, term_node])

        rad_func = Node(NodeType.FUNCTION,
                        name="RAD",
                        arity=1,
                        branches=[mul_func])

        sin_func = Node(NodeType.FUNCTION,
                        name="SIN",
                        arity=1,
                        branches=[rad_func])

        # create tree
        tree = Tree()
        tree.root = sin_func
        tree.update()

        # generate equation function
        eq_func = evaluator.generate_eq_function(tree, self.functions,
                                                 self.config)

        # assert
        self.assertIsNotNone(eq_func)
        self.assertEquals(round(eq_func(1), 4), 0.9848)
    def test_generate_eq_function_multivars(self):
        # create terminal nodes
        term_node = Node(NodeType.INPUT, name="var2")
        input_node = Node(NodeType.INPUT, name="var1")

        # create function nodes
        div_func = Node(
            NodeType.FUNCTION,
            name="DIV",
            arity=2,
            branches=[input_node, term_node]
        )

        # create tree
        tree = Tree()
        tree.root = div_func
        tree.update()

        # generate equation function
        config = {
            "input_variables": [
                {
                    "type": "INPUT",
                    "name": "var1"
                },
                {
                    "type": "INPUT",
                    "name": "var2"
                }
            ],

            "functions": {
                "ADD": "+",
                "SUB": "-",
                "MUL": "*",
                "DIV": "/",
                "POW": "**",
                "SIN": "math.sin",
                "COS": "math.cos",
                "RAD": "math.radians",
                "LN": "math.ln",
                "LOG": "math.log"
            }
        }
        eq_func = evaluator.generate_eq_function(tree, self.functions, config)

        # assert
        self.assertIsNotNone(eq_func)
        self.assertEquals(eq_func(1.0, 2.0), 0.5)
Exemple #5
0
    def test_edit_tree_inputs_and_terminals(self):
        # TEST INPUTS AND TERMINALS
        term_node_1 = Node(NodeType.CONSTANT, value=2.0)
        term_node_2 = Node(NodeType.INPUT, name="x")
        func_node = Node(NodeType.FUNCTION,
                         name="ADD",
                         arity=2,
                         branches=[term_node_1, term_node_2])

        print "BEFORE:", func_node
        tree = Tree()
        tree.root = func_node
        tree.depth = 3
        editor.edit_tree(tree, tree.root, self.functions)
        print "AFTER:", func_node
        print
Exemple #6
0
    def generate_tree_from_dict(self, tree_dict):
        tree = Tree()
        stack = []

        tree.tree_id = tree_dict["id"]
        for node_dict in tree_dict["program"]:
            node_type = node_dict["type"]
            node = None

            if node_type == NodeType.INPUT:
                node = Node(
                    NodeType.INPUT,
                    name=node_dict.get("name", None)
                )

                tree.program.append(node)
                stack.append(node)

            elif node_type == NodeType.CONSTANT:
                node = Node(
                    NodeType.CONSTANT,
                    name=node_dict.get("name", None),
                    value=node_dict.get("value", None)
                )

                tree.program.append(node)
                stack.append(node)

            elif node_type == NodeType.FUNCTION:
                value_nodes = []
                for i in xrange(node_dict["arity"]):
                    value_nodes.append(stack.pop())

                node = Node(
                    NodeType.FUNCTION,
                    name=node_dict["name"],
                    arity=node_dict["arity"],
                    branches=value_nodes
                )

                tree.program.append(node)
                stack.append(node)

                if node_dict.get("root", False):
                    tree.root = node

        return tree
Exemple #7
0
    def test_replace_node(self):
        # setup
        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[node_x, node_y])

        # build tree
        tree = Tree()
        tree.root = add_func
        tree.update_program()

        # replace input node
        new_node = Node(NodeType.INPUT, name="z")
        before_replace = list(tree.program)
        tree.replace_node(node_x, new_node)
        after_replace = list(tree.program)

        # assert
        self.assertTrue(before_replace == before_replace)
        self.assertTrue(after_replace == after_replace)
        self.assertFalse(before_replace == after_replace)
        self.assertTrue(add_func.branches[0] is new_node)
Exemple #8
0
    def test_edit_tree_inputs_and_terminals(self):
        # TEST INPUTS AND TERMINALS
        term_node_1 = Node(NodeType.CONSTANT, value=2.0)
        term_node_2 = Node(NodeType.INPUT, name="x")
        func_node = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[term_node_1, term_node_2]
        )

        print "BEFORE:", func_node
        tree = Tree()
        tree.root = func_node
        tree.depth = 3
        editor.edit_tree(tree, tree.root, self.functions)
        print "AFTER:", func_node
        print
Exemple #9
0
    def test_edit_tree_zero_only(self):
        # TEST CONTAINS ZERO
        term_node_1 = Node(NodeType.CONSTANT, value=0.0)
        term_node_2 = Node(NodeType.CONSTANT, value=1.0)
        func_node = Node(NodeType.FUNCTION,
                         name="ADD",
                         arity=2,
                         branches=[term_node_1, term_node_2])

        print "BEFORE:", func_node
        tree = Tree()
        tree.root = func_node
        tree.depth = 3
        editor.edit_tree(tree, tree.root, self.functions)
        print "AFTER:", func_node
        print

        self.assertEquals(func_node.value, 1.0)
Exemple #10
0
    def test_generate_eq_function_multivars(self):
        # create terminal nodes
        term_node = Node(NodeType.INPUT, name="var2")
        input_node = Node(NodeType.INPUT, name="var1")

        # create function nodes
        div_func = Node(NodeType.FUNCTION,
                        name="DIV",
                        arity=2,
                        branches=[input_node, term_node])

        # create tree
        tree = Tree()
        tree.root = div_func
        tree.update()

        # generate equation function
        config = {
            "input_variables": [{
                "type": "INPUT",
                "name": "var1"
            }, {
                "type": "INPUT",
                "name": "var2"
            }],
            "functions": {
                "ADD": "+",
                "SUB": "-",
                "MUL": "*",
                "DIV": "/",
                "POW": "**",
                "SIN": "math.sin",
                "COS": "math.cos",
                "RAD": "math.radians",
                "LN": "math.ln",
                "LOG": "math.log"
            }
        }
        eq_func = evaluator.generate_eq_function(tree, self.functions, config)

        # assert
        self.assertIsNotNone(eq_func)
        self.assertEquals(eq_func(1.0, 2.0), 0.5)
    def test_generate_eq_function(self):
        # create terminal nodes
        term_node = Node(NodeType.CONSTANT, value=100.0)
        input_node = Node(NodeType.INPUT, name="x")

        # create function nodes
        mul_func = Node(
            NodeType.FUNCTION,
            name="MUL",
            arity=2,
            branches=[input_node, term_node]
        )

        rad_func = Node(
            NodeType.FUNCTION,
            name="RAD",
            arity=1,
            branches=[mul_func]
        )

        sin_func = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[rad_func]
        )

        # create tree
        tree = Tree()
        tree.root = sin_func
        tree.update()

        # generate equation function
        eq_func = evaluator.generate_eq_function(
            tree,
            self.functions,
            self.config
        )

        # assert
        self.assertIsNotNone(eq_func)
        self.assertEquals(round(eq_func(1), 4), 0.9848)
Exemple #12
0
    def test_edit_tree_terminals_only(self):
        # TEST TERMINALS ONLY
        term_node_1 = Node(NodeType.CONSTANT, value=2.0)
        term_node_2 = Node(NodeType.CONSTANT, value=1.0)
        func_node = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[term_node_1, term_node_2]
        )

        print "BEFORE:", func_node
        tree = Tree()
        tree.root = func_node
        tree.depth = 3
        editor.edit_tree(tree, tree.root, self.functions)
        print "AFTER:", func_node
        print

        self.assertEquals(func_node.value, 3.0)
Exemple #13
0
    def test_edit_tree_prune(self):
        # TEST PRUNE
        term_node_1 = Node(NodeType.CONSTANT, value=0.0)
        term_node_2 = Node(NodeType.INPUT, name="x")
        func_node = Node(NodeType.FUNCTION,
                         name="MUL",
                         arity=2,
                         branches=[term_node_1, term_node_2])

        print "BEFORE:", func_node
        tree = Tree()
        tree.root = func_node
        tree.depth = 3
        editor.edit_tree(tree, tree.root, self.functions)
        print "AFTER:", func_node
        print

        self.assertEquals(func_node.node_type, NodeType.CONSTANT)
        self.assertIsNone(func_node.name)
        self.assertEquals(func_node.value, 0)
Exemple #14
0
    def full_method(self):
        # initialize tree
        tree = Tree()
        tree.size = 1
        tree.depth = self.max_depth
        tree.root = self.generate_func_node()
        tree.tree_type = self.gen_config.get("tree_type", None)

        # build tree via full method
        self.full_method_build_tree(tree, tree.root, 0)
        tree.update()

        return tree
Exemple #15
0
    def test_replace_node(self):
        # setup
        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[node_x, node_y]
        )

        # build tree
        tree = Tree()
        tree.root = add_func
        tree.update_program()

        # replace input node
        new_node = Node(NodeType.INPUT, name="z")
        before_replace = list(tree.program)
        tree.replace_node(node_x, new_node)
        after_replace = list(tree.program)

        # assert
        self.assertTrue(before_replace == before_replace)
        self.assertTrue(after_replace == after_replace)
        self.assertFalse(before_replace == after_replace)
        self.assertTrue(add_func.branches[0] is new_node)
Exemple #16
0
    def test_edit_tree_prune(self):
        # TEST PRUNE
        term_node_1 = Node(NodeType.CONSTANT, value=0.0)
        term_node_2 = Node(NodeType.INPUT, name="x")
        func_node = Node(
            NodeType.FUNCTION,
            name="MUL",
            arity=2,
            branches=[term_node_1, term_node_2]
        )

        print "BEFORE:", func_node
        tree = Tree()
        tree.root = func_node
        tree.depth = 3
        editor.edit_tree(tree, tree.root, self.functions)
        print "AFTER:", func_node
        print

        self.assertEquals(func_node.node_type, NodeType.CONSTANT)
        self.assertIsNone(func_node.name)
        self.assertEquals(func_node.value, 0)
Exemple #17
0
    def setUp(self):
        self.config = {
            "max_population": 10,

            "tree_generation": {
                "method": "FULL_METHOD",
                "initial_max_depth": 4
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "INPUT", "name": "x"},
                {"type": "INPUT", "name": "y"},
                {"type": "INPUT", "name": "z"}
            ],

            "input_variables": [
                {"name": "x"},
                {"name": "y"},
                {"name": "z"}
            ]
        }

        self.t_parser = TreeParser()
        self.tree = Tree()

        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        node_z = Node(NodeType.INPUT, name="z")

        self.tree.input_nodes.append(node_x)
        self.tree.input_nodes.append(node_y)
        self.tree.input_nodes.append(node_z)
class TreeCrossoverTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "tree_generation": {
                "initial_max_depth": 4
            },
            "crossover": {
                "method": "POINT_CROSSOVER",
                "probability": 1.0
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "name": "ADD",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "SUB",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "MUL",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "DIV",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "COS",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "SIN",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "RAD",
                "arity": 1
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "CONSTANT",
                "value": 2.0
            }, {
                "type": "CONSTANT",
                "value": 2.0
            }, {
                "type": "CONSTANT",
                "value": 3.0
            }, {
                "type": "CONSTANT",
                "value": 4.0
            }, {
                "type": "CONSTANT",
                "value": 5.0
            }, {
                "type": "CONSTANT",
                "value": 6.0
            }, {
                "type": "CONSTANT",
                "value": 7.0
            }, {
                "type": "CONSTANT",
                "value": 8.0
            }, {
                "type": "CONSTANT",
                "value": 9.0
            }, {
                "type": "CONSTANT",
                "value": 10.0
            }],
            "input_variables": [{
                "type": "INPUT",
                "name": "x"
            }]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.crossover = TreeCrossover(self.config)
        self.parser = TreeParser()

        # create nodes
        left_node_1 = Node(NodeType.INPUT, name="x")
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)
        node = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(NodeType.FUNCTION,
                          name="ADD",
                          arity=2,
                          branches=[left_node_1, right_node_1])

        sin_func_1 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[node])

        cos_func_2 = Node(NodeType.FUNCTION,
                          name="COS",
                          arity=1,
                          branches=[left_node_2])
        sin_func_2 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[right_node_2])

        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[cos_func_1, sin_func_1])

        sub_func = Node(NodeType.FUNCTION,
                        name="SUB",
                        arity=2,
                        branches=[sin_func_2, cos_func_2])

        # create tree_1
        self.tree_1 = Tree()
        self.tree_1.root = add_func
        self.tree_1.update()

        print self.tree_1

        # create tree_2
        self.tree_2 = Tree()
        self.tree_2.root = sub_func
        self.tree_2.update()

    def tearDown(self):
        del self.config
        del self.generator
        del self.parser

    def build_tree_str(self, tree):
        tree_str = ""

        for node in tree.program:
            if hasattr(node, "name") and node.name is not None:
                tree_str += "node:{0} addr:{1}\n".format(node.name, id(node))
            else:
                tree_str += "node:{0} addr:{1}\n".format(node.value, id(node))

        return tree_str

    def tree_equals(self, tree_1_str, tree_2_str):
        if tree_1_str == tree_2_str:
            return True
        else:
            return False

    def test_point_crossover(self):
        # record before crossover
        tree_1_before = self.build_tree_str(self.tree_1)
        tree_2_before = self.build_tree_str(self.tree_2)

        # point crossover
        self.crossover.point_crossover(self.tree_1, self.tree_2)

        # record after crossover
        tree_1_after = self.build_tree_str(self.tree_1)
        tree_2_after = self.build_tree_str(self.tree_2)

        print("Before Crossover")
        print("\nTree 1")
        print(tree_1_before)
        print("\nTree 2")
        print(tree_2_before)

        print("\nAfter Crossover")
        print("\nTree 1")
        print(tree_1_after)
        print("\nTree 2")
        print(tree_2_after)

        # asserts
        self.assertTrue(self.tree_equals(tree_1_before, tree_1_before))
        self.assertTrue(self.tree_equals(tree_2_before, tree_2_before))
        self.assertTrue(self.tree_equals(tree_1_after, tree_1_after))
        self.assertTrue(self.tree_equals(tree_2_after, tree_2_after))

        self.assertFalse(self.tree_equals(tree_1_before, tree_1_after))
        self.assertFalse(self.tree_equals(tree_2_before, tree_2_after))

    def test_common_region_point_crossover(self):
        # record before crossover
        tree_1_before = self.build_tree_str(self.tree_1)
        tree_2_before = self.build_tree_str(self.tree_2)

        # point crossover
        self.crossover.common_region_point_crossover(self.tree_1, self.tree_2)

        # record after crossover
        tree_1_after = self.build_tree_str(self.tree_1)
        tree_2_after = self.build_tree_str(self.tree_2)

        print("Before Crossover")
        print("\nTree 1")
        print(tree_1_before)
        print("\nTree 2")
        print(tree_2_before)

        print("\nAfter Crossover")
        print("\nTree 1")
        print(tree_1_after)
        print("\nTree 2")
        print(tree_2_after)

    def test_crossover(self):
        # record before crossover
        tree_1_before = self.build_tree_str(self.tree_1)
        tree_2_before = self.build_tree_str(self.tree_2)

        # point crossover
        self.crossover.crossover(self.tree_1, self.tree_2)

        # record after crossover
        tree_1_after = self.build_tree_str(self.tree_1)
        tree_2_after = self.build_tree_str(self.tree_2)

        print("Before Crossover")
        print("\nTree 1!")
        print(tree_1_before)
        print("\nTree 2!")
        print(tree_2_before)

        print("\nAfter Crossover")
        print("\nTree 1!")
        print(tree_1_after)
        print("\nTree 2!")
        print(tree_2_after)

        # asserts
        self.assertTrue(self.tree_equals(tree_1_before, tree_1_before))
        self.assertTrue(self.tree_equals(tree_2_before, tree_2_before))
        self.assertTrue(self.tree_equals(tree_1_after, tree_1_after))
        self.assertTrue(self.tree_equals(tree_2_after, tree_2_after))

        self.assertFalse(self.tree_equals(tree_1_before, tree_1_after))
        self.assertFalse(self.tree_equals(tree_2_before, tree_2_after))
    def setUp(self):
        self.config = {
            "tree_generation": {
                "initial_max_depth": 4
            },
            "crossover": {
                "method": "POINT_CROSSOVER",
                "probability": 1.0
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "name": "ADD",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "SUB",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "MUL",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "DIV",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "COS",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "SIN",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "RAD",
                "arity": 1
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "CONSTANT",
                "value": 2.0
            }, {
                "type": "CONSTANT",
                "value": 2.0
            }, {
                "type": "CONSTANT",
                "value": 3.0
            }, {
                "type": "CONSTANT",
                "value": 4.0
            }, {
                "type": "CONSTANT",
                "value": 5.0
            }, {
                "type": "CONSTANT",
                "value": 6.0
            }, {
                "type": "CONSTANT",
                "value": 7.0
            }, {
                "type": "CONSTANT",
                "value": 8.0
            }, {
                "type": "CONSTANT",
                "value": 9.0
            }, {
                "type": "CONSTANT",
                "value": 10.0
            }],
            "input_variables": [{
                "type": "INPUT",
                "name": "x"
            }]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.crossover = TreeCrossover(self.config)
        self.parser = TreeParser()

        # create nodes
        left_node_1 = Node(NodeType.INPUT, name="x")
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)
        node = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(NodeType.FUNCTION,
                          name="ADD",
                          arity=2,
                          branches=[left_node_1, right_node_1])

        sin_func_1 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[node])

        cos_func_2 = Node(NodeType.FUNCTION,
                          name="COS",
                          arity=1,
                          branches=[left_node_2])
        sin_func_2 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[right_node_2])

        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[cos_func_1, sin_func_1])

        sub_func = Node(NodeType.FUNCTION,
                        name="SUB",
                        arity=2,
                        branches=[sin_func_2, cos_func_2])

        # create tree_1
        self.tree_1 = Tree()
        self.tree_1.root = add_func
        self.tree_1.update()

        print self.tree_1

        # create tree_2
        self.tree_2 = Tree()
        self.tree_2.root = sub_func
        self.tree_2.update()
Exemple #20
0
    def setUp(self):
        self.config = {
            "max_population":
            10,
            "tree_generation": {
                "method": "FULL_METHOD",
                "initial_max_depth": 4
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "name": "ADD",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "SUB",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "MUL",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "DIV",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "COS",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "SIN",
                "arity": 1
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "INPUT",
                "name": "x"
            }, {
                "type": "INPUT",
                "name": "y"
            }, {
                "type": "INPUT",
                "name": "z"
            }],
            "input_variables": [{
                "name": "x"
            }, {
                "name": "y"
            }, {
                "name": "z"
            }]
        }

        self.t_parser = TreeParser()
        self.tree = Tree()

        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        node_z = Node(NodeType.INPUT, name="z")

        self.tree.input_nodes.append(node_x)
        self.tree.input_nodes.append(node_y)
        self.tree.input_nodes.append(node_z)
Exemple #21
0
class TreeTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "max_population":
            10,
            "tree_generation": {
                "method": "FULL_METHOD",
                "initial_max_depth": 4
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "name": "ADD",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "SUB",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "MUL",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "DIV",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "COS",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "SIN",
                "arity": 1
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "INPUT",
                "name": "x"
            }, {
                "type": "INPUT",
                "name": "y"
            }, {
                "type": "INPUT",
                "name": "z"
            }],
            "input_variables": [{
                "name": "x"
            }, {
                "name": "y"
            }, {
                "name": "z"
            }]
        }

        self.t_parser = TreeParser()
        self.tree = Tree()

        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        node_z = Node(NodeType.INPUT, name="z")

        self.tree.input_nodes.append(node_x)
        self.tree.input_nodes.append(node_y)
        self.tree.input_nodes.append(node_z)

    def test_valid(self):
        # assert valid
        res = self.tree.valid(self.config["input_variables"])
        self.assertTrue(res)

        # assert fail valid
        self.tree.input_nodes.pop()
        res = self.tree.valid(self.config["input_variables"])
        self.assertFalse(res)

    def test_get_linked_node(self):
        # setup
        del self.tree.input_nodes[:]
        left_node = Node(NodeType.INPUT, name="x")
        right_node = Node(NodeType.INPUT, name="y")
        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[left_node, right_node])
        self.tree.root = add_func
        self.tree.program = self.t_parser.post_order_traverse(self.tree.root)

        # pass test
        linked_node = self.tree.get_linked_node(left_node)
        self.assertTrue(linked_node is add_func)
        linked_node = self.tree.get_linked_node(right_node)
        self.assertTrue(linked_node is add_func)

        # fail test
        random_node = Node(NodeType.INPUT, name="z")
        linked_node = self.tree.get_linked_node(random_node)
        self.assertFalse(linked_node is add_func)

    def test_replace_node(self):
        # setup
        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[node_x, node_y])

        # build tree
        tree = Tree()
        tree.root = add_func
        tree.update_program()

        # replace input node
        new_node = Node(NodeType.INPUT, name="z")
        before_replace = list(tree.program)
        tree.replace_node(node_x, new_node)
        after_replace = list(tree.program)

        # assert
        self.assertTrue(before_replace == before_replace)
        self.assertTrue(after_replace == after_replace)
        self.assertFalse(before_replace == after_replace)
        self.assertTrue(add_func.branches[0] is new_node)

    def test_equal(self):
        # create nodes
        left_node_1 = Node(NodeType.CONSTANT, value=1.0)
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(NodeType.FUNCTION,
                          name="COS",
                          arity=1,
                          branches=[left_node_1])
        sin_func_1 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[right_node_1])

        cos_func_2 = Node(NodeType.FUNCTION,
                          name="COS",
                          arity=1,
                          branches=[left_node_2])
        sin_func_2 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[right_node_2])

        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[cos_func_1, sin_func_1])

        sub_func = Node(NodeType.FUNCTION,
                        name="SUB",
                        arity=2,
                        branches=[sin_func_2, cos_func_2])

        # create tree_1
        tree_1 = Tree()
        tree_1.root = add_func
        tree_1.update()

        # create tree_2
        tree_2 = Tree()
        tree_2.root = sub_func
        tree_2.update()

        self.assertTrue(tree_1.equals(tree_1))
        self.assertFalse(tree_1.equals(tree_2))
        self.assertTrue(tree_2.equals(tree_2))
        self.assertFalse(tree_2.equals(tree_1))

    def test_str(self):
        # setup
        del self.tree.input_nodes[:]
        left_node = Node(NodeType.INPUT, name="x")
        right_node = Node(NodeType.INPUT, name="y")
        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[left_node, right_node])
        self.tree.root = add_func
        self.tree.program = self.t_parser.post_order_traverse(self.tree.root)

        # assert
        self.assertEquals(str(self.tree), "(x ADD y)")
Exemple #22
0
    def setUp(self):
        random.seed(10)

        self.config = {
            "max_population": 10,

            "tree_generation": {
                "method": "FULL_METHOD",
                "initial_max_depth": 4
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "INPUT", "name": "x"},
                {"type": "INPUT", "name": "y"},
                {"type": "INPUT", "name": "z"}
            ],

            "input_variables": [
                {"name": "x"},
                {"name": "y"},
                {"name": "z"}
            ]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)
        self.parser = TreeParser()

        # create nodes
        left_node = Node(NodeType.CONSTANT, value=1.0)
        right_node = Node(NodeType.CONSTANT, value=2.0)

        cos_func = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node]
        )
        sin_func = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func, sin_func]
        )

        # create tree
        self.tree = Tree()
        self.tree.root = add_func
        self.tree.update_program()
        self.tree.update_func_nodes()
        self.tree.update_term_nodes()
Exemple #23
0
class TreeParserTests(unittest.TestCase):
    def setUp(self):
        random.seed(10)

        self.config = {
            "max_population": 10,

            "tree_generation": {
                "method": "FULL_METHOD",
                "initial_max_depth": 4
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "INPUT", "name": "x"},
                {"type": "INPUT", "name": "y"},
                {"type": "INPUT", "name": "z"}
            ],

            "input_variables": [
                {"name": "x"},
                {"name": "y"},
                {"name": "z"}
            ]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)
        self.parser = TreeParser()

        # create nodes
        left_node = Node(NodeType.CONSTANT, value=1.0)
        right_node = Node(NodeType.CONSTANT, value=2.0)

        cos_func = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node]
        )
        sin_func = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func, sin_func]
        )

        # create tree
        self.tree = Tree()
        self.tree.root = add_func
        self.tree.update_program()
        self.tree.update_func_nodes()
        self.tree.update_term_nodes()

    def tearDown(self):
        del self.config
        del self.generator
        del self.parser

    def test_parse_tree(self):
        # self.parser.print_tree(tree.root)
        program = self.parser.parse_tree(self.tree, self.tree.root)
        for i in program:
            if i.name is not None:
                print i.name
            else:
                print i.value

        self.assertEquals(self.tree.size, 5)
        self.assertEquals(self.tree.depth, 2)

        self.assertEquals(len(self.tree.func_nodes), 2)
        self.assertEquals(len(self.tree.term_nodes), 2)
        self.assertEquals(len(self.tree.input_nodes), 0)

    def test_parse_equation(self):
        # self.parser.print_tree(tree.root)
        equation = self.parser.parse_equation(self.tree.root)
        self.assertEquals(equation, "((COS(1.0)) ADD (SIN(2.0)))")

    def test_tree_to_dict(self):
        solution = {
            'program': [
                {'type': 'CONSTANT', 'value': 1.0},
                {'arity': 1, 'type': 'FUNCTION', 'name': 'COS'},
                {'type': 'CONSTANT', 'value': 2.0},
                {'arity': 1, 'type': 'FUNCTION', 'name': 'SIN'},
                {'arity': 2, 'type': 'FUNCTION', 'root': True, 'name': 'ADD'}
            ]
        }
        results = self.parser.tree_to_dict(self.tree, self.tree.root)
        self.assertEquals(results["program"], solution["program"])
Exemple #24
0
class TreeTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "max_population": 10,

            "tree_generation": {
                "method": "FULL_METHOD",
                "initial_max_depth": 4
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "INPUT", "name": "x"},
                {"type": "INPUT", "name": "y"},
                {"type": "INPUT", "name": "z"}
            ],

            "input_variables": [
                {"name": "x"},
                {"name": "y"},
                {"name": "z"}
            ]
        }

        self.t_parser = TreeParser()
        self.tree = Tree()

        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        node_z = Node(NodeType.INPUT, name="z")

        self.tree.input_nodes.append(node_x)
        self.tree.input_nodes.append(node_y)
        self.tree.input_nodes.append(node_z)

    def test_valid(self):
        # assert valid
        res = self.tree.valid(self.config["input_variables"])
        self.assertTrue(res)

        # assert fail valid
        self.tree.input_nodes.pop()
        res = self.tree.valid(self.config["input_variables"])
        self.assertFalse(res)

    def test_get_linked_node(self):
        # setup
        del self.tree.input_nodes[:]
        left_node = Node(NodeType.INPUT, name="x")
        right_node = Node(NodeType.INPUT, name="y")
        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[left_node, right_node]
        )
        self.tree.root = add_func
        self.tree.program = self.t_parser.post_order_traverse(self.tree.root)

        # pass test
        linked_node = self.tree.get_linked_node(left_node)
        self.assertTrue(linked_node is add_func)
        linked_node = self.tree.get_linked_node(right_node)
        self.assertTrue(linked_node is add_func)

        # fail test
        random_node = Node(NodeType.INPUT, name="z")
        linked_node = self.tree.get_linked_node(random_node)
        self.assertFalse(linked_node is add_func)

    def test_replace_node(self):
        # setup
        node_x = Node(NodeType.INPUT, name="x")
        node_y = Node(NodeType.INPUT, name="y")
        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[node_x, node_y]
        )

        # build tree
        tree = Tree()
        tree.root = add_func
        tree.update_program()

        # replace input node
        new_node = Node(NodeType.INPUT, name="z")
        before_replace = list(tree.program)
        tree.replace_node(node_x, new_node)
        after_replace = list(tree.program)

        # assert
        self.assertTrue(before_replace == before_replace)
        self.assertTrue(after_replace == after_replace)
        self.assertFalse(before_replace == after_replace)
        self.assertTrue(add_func.branches[0] is new_node)

    def test_equal(self):
        # create nodes
        left_node_1 = Node(NodeType.CONSTANT, value=1.0)
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node_1]
        )
        sin_func_1 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node_1]
        )

        cos_func_2 = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node_2]
        )
        sin_func_2 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node_2]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func_1, sin_func_1]
        )

        sub_func = Node(
            NodeType.FUNCTION,
            name="SUB",
            arity=2,
            branches=[sin_func_2, cos_func_2]
        )

        # create tree_1
        tree_1 = Tree()
        tree_1.root = add_func
        tree_1.update()

        # create tree_2
        tree_2 = Tree()
        tree_2.root = sub_func
        tree_2.update()

        self.assertTrue(tree_1.equals(tree_1))
        self.assertFalse(tree_1.equals(tree_2))
        self.assertTrue(tree_2.equals(tree_2))
        self.assertFalse(tree_2.equals(tree_1))

    def test_str(self):
        # setup
        del self.tree.input_nodes[:]
        left_node = Node(NodeType.INPUT, name="x")
        right_node = Node(NodeType.INPUT, name="y")
        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[left_node, right_node]
        )
        self.tree.root = add_func
        self.tree.program = self.t_parser.post_order_traverse(self.tree.root)

        # assert
        self.assertEquals(str(self.tree), "(x ADD y)")
Exemple #25
0
    def test_equal(self):
        # create nodes
        left_node_1 = Node(NodeType.CONSTANT, value=1.0)
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node_1]
        )
        sin_func_1 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node_1]
        )

        cos_func_2 = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node_2]
        )
        sin_func_2 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node_2]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func_1, sin_func_1]
        )

        sub_func = Node(
            NodeType.FUNCTION,
            name="SUB",
            arity=2,
            branches=[sin_func_2, cos_func_2]
        )

        # create tree_1
        tree_1 = Tree()
        tree_1.root = add_func
        tree_1.update()

        # create tree_2
        tree_2 = Tree()
        tree_2.root = sub_func
        tree_2.update()

        self.assertTrue(tree_1.equals(tree_1))
        self.assertFalse(tree_1.equals(tree_2))
        self.assertTrue(tree_2.equals(tree_2))
        self.assertFalse(tree_2.equals(tree_1))
class TreeMutatorTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "tree_generation": {
                "method": "GROW_METHOD",
                "initial_max_depth": 4
            },
            "mutation": {
                "methods": [
                    "POINT_MUTATION", "HOIST_MUTATION", "SUBTREE_MUTATION",
                    "SHRINK_MUTATION", "EXPAND_MUTATION"
                ],
                "probability":
                1.0
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "name": "ADD",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "SUB",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "MUL",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "DIV",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "COS",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "SIN",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "RAD",
                "arity": 1
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "CONSTANT",
                "value": 2.0
            }, {
                "type": "INPUT",
                "name": "x"
            }],
            "input_variables": [{
                "type": "INPUT",
                "name": "x"
            }]
        }
        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.parser = TreeParser()
        self.mutation = TreeMutation(self.config)

        # create nodes
        left_node = Node(NodeType.CONSTANT, value=1.0)
        right_node = Node(NodeType.INPUT, name="x")

        cos_func = Node(NodeType.FUNCTION,
                        name="COS",
                        arity=1,
                        branches=[left_node])

        sin_func = Node(NodeType.FUNCTION,
                        name="SIN",
                        arity=1,
                        branches=[right_node])

        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[cos_func, sin_func])

        # create tree
        self.tree = Tree()
        self.tree.root = add_func
        self.tree.update_program()
        self.tree.update_func_nodes()
        self.tree.update_term_nodes()

    def tearDown(self):
        del self.config
        del self.generator
        del self.parser

    def build_tree_str(self, tree):
        tree_str = ""

        for node in tree.program:
            if hasattr(node, "name") and node.name is not None:
                tree_str += "node:{0} addr:{1}\n".format(node.name, id(node))
            else:
                tree_str += "node:{0} addr:{1}\n".format(node.value, id(node))

        return tree_str

    def tree_equals(self, tree_1_str, tree_2_str):
        if tree_1_str == tree_2_str:
            return True
        else:
            return False

    def mutated(self, tree, mutation_func, mutation_index=None):
        tree_before = self.build_tree_str(self.tree)
        mutation_func(tree, mutation_index)
        tree_after = self.build_tree_str(self.tree)

        print("Before Mutation")
        print(tree_before)

        print("\nAfter Mutation")
        print(tree_after)

        self.assertTrue(self.tree_equals(tree_before, tree_before))
        self.assertTrue(self.tree_equals(tree_after, tree_after))
        self.assertFalse(self.tree_equals(tree_before, tree_after))

    def test_mutate_new_node_details(self):
        # MUTATE NEW FUNCTION NODE DETAILS
        for i in range(100):
            func_node = Node(NodeType.FUNCTION,
                             name="ADD",
                             arity=2,
                             branches=[])
            node_details = self.mutation.mutate_new_node_details(func_node)
            self.assertNotEquals(node_details["name"], func_node.name)
            self.assertEquals(node_details["arity"], func_node.arity)
            self.assertEquals(node_details["type"], func_node.node_type)

        # MUTATE NEW TERMINAL NODE DETAILS
        for i in range(100):
            term_node = Node(NodeType.CONSTANT, value=1.0)
            node_details = self.mutation.mutate_new_node_details(term_node)
            if node_details["type"] == NodeType.CONSTANT:
                self.assertNotEqual(node_details["value"], term_node.value)

            elif node_details["type"] == NodeType.INPUT:
                self.assertNotEqual(node_details["name"], term_node.name)

        # MUTATE NEW CLASS FUNCTION NODE DETAILS
        self.config["function_nodes"] = [{
            "type": "CLASS_FUNCTION",
            "name": "GREATER_THAN",
            "arity": 2,
            "data_range": {
                "lower_bound": 0.0,
                "upper_bound": 10.0,
                "decimal_places": 0,
            }
        }, {
            "type": "CLASS_FUNCTION",
            "name": "LESS_THAN",
            "arity": 2,
            "data_range": {
                "lower_bound": 0.0,
                "upper_bound": 10.0,
                "decimal_places": 0,
            }
        }, {
            "type": "CLASS_FUNCTION",
            "name": "EQUALS",
            "arity": 2,
            "decimal_precision": 2
        }]
        mutation = TreeMutation(self.config)

        for i in range(100):
            class_func_node = Node(NodeType.CLASS_FUNCTION,
                                   name="GREATER_THAN",
                                   arity=2)
            node_details = mutation.mutate_new_node_details(class_func_node)
            self.assertNotEquals(node_details["name"], class_func_node.name)
            self.assertEquals(node_details["arity"], class_func_node.arity)
            self.assertEquals(node_details["type"], class_func_node.node_type)

    def test_point_mutation(self):
        print "---------- POINT MUATION! ----------"
        self.mutated(self.tree, self.mutation.point_mutation)

    def test_hoist_mutation(self):
        print "---------- HOIST MUATION! ----------"
        self.mutated(self.tree, self.mutation.hoist_mutation, 3)

    def test_SUBTREE_MUTATION(self):
        print "---------- SUBTREE MUATION! ----------"
        self.mutated(self.tree, self.mutation.subtree_mutation, 3)

    def test_shrink_mutation(self):
        print "---------- SHRINK MUATION! ----------"
        self.mutated(self.tree, self.mutation.shrink_mutation, 3)

    def test_expansion_mutation(self):
        print "---------- EXPANSION MUATION! ----------"
        self.mutated(self.tree, self.mutation.expansion_mutation, 3)

    def test_mutate(self):
        print "MUTATE!"
        tree_before = self.build_tree_str(self.tree)
        self.mutation.mutate(self.tree)
        tree_after = self.build_tree_str(self.tree)

        print "----->", self.mutation.method
        print("Before Mutation")
        print(tree_before)

        print("\nAfter Mutation")
        print(tree_after)

        self.assertTrue(self.tree_equals(tree_before, tree_before))
        self.assertTrue(self.tree_equals(tree_after, tree_after))
        self.assertFalse(self.tree_equals(tree_before, tree_after))
Exemple #27
0
    def test_equal(self):
        # create nodes
        left_node_1 = Node(NodeType.CONSTANT, value=1.0)
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(NodeType.FUNCTION,
                          name="COS",
                          arity=1,
                          branches=[left_node_1])
        sin_func_1 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[right_node_1])

        cos_func_2 = Node(NodeType.FUNCTION,
                          name="COS",
                          arity=1,
                          branches=[left_node_2])
        sin_func_2 = Node(NodeType.FUNCTION,
                          name="SIN",
                          arity=1,
                          branches=[right_node_2])

        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[cos_func_1, sin_func_1])

        sub_func = Node(NodeType.FUNCTION,
                        name="SUB",
                        arity=2,
                        branches=[sin_func_2, cos_func_2])

        # create tree_1
        tree_1 = Tree()
        tree_1.root = add_func
        tree_1.update()

        # create tree_2
        tree_2 = Tree()
        tree_2.root = sub_func
        tree_2.update()

        self.assertTrue(tree_1.equals(tree_1))
        self.assertFalse(tree_1.equals(tree_2))
        self.assertTrue(tree_2.equals(tree_2))
        self.assertFalse(tree_2.equals(tree_1))
Exemple #28
0
    def setUp(self):
        self.config = {
            "tree_generation": {
                "initial_max_depth": 4
            },

            "crossover": {
                "method": "POINT_CROSSOVER",
                "probability": 1.0
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1},
                {"type": "FUNCTION", "name": "RAD", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "CONSTANT", "value": 2.0},
                {"type": "CONSTANT", "value": 2.0},
                {"type": "CONSTANT", "value": 3.0},
                {"type": "CONSTANT", "value": 4.0},
                {"type": "CONSTANT", "value": 5.0},
                {"type": "CONSTANT", "value": 6.0},
                {"type": "CONSTANT", "value": 7.0},
                {"type": "CONSTANT", "value": 8.0},
                {"type": "CONSTANT", "value": 9.0},
                {"type": "CONSTANT", "value": 10.0}
            ],

            "input_variables": [
                {"type": "INPUT", "name": "x"}
            ]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.crossover = TreeCrossover(self.config)
        self.parser = TreeParser()

        # create nodes
        left_node_1 = Node(NodeType.INPUT, name="x")
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)
        node = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[left_node_1, right_node_1]
        )

        sin_func_1 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[node]
        )

        cos_func_2 = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node_2]
        )
        sin_func_2 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node_2]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func_1, sin_func_1]
        )

        sub_func = Node(
            NodeType.FUNCTION,
            name="SUB",
            arity=2,
            branches=[sin_func_2, cos_func_2]
        )

        # create tree_1
        self.tree_1 = Tree()
        self.tree_1.root = add_func
        self.tree_1.update()

        print self.tree_1

        # create tree_2
        self.tree_2 = Tree()
        self.tree_2.root = sub_func
        self.tree_2.update()
Exemple #29
0
class TreeCrossoverTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "tree_generation": {
                "initial_max_depth": 4
            },

            "crossover": {
                "method": "POINT_CROSSOVER",
                "probability": 1.0
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1},
                {"type": "FUNCTION", "name": "RAD", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "CONSTANT", "value": 2.0},
                {"type": "CONSTANT", "value": 2.0},
                {"type": "CONSTANT", "value": 3.0},
                {"type": "CONSTANT", "value": 4.0},
                {"type": "CONSTANT", "value": 5.0},
                {"type": "CONSTANT", "value": 6.0},
                {"type": "CONSTANT", "value": 7.0},
                {"type": "CONSTANT", "value": 8.0},
                {"type": "CONSTANT", "value": 9.0},
                {"type": "CONSTANT", "value": 10.0}
            ],

            "input_variables": [
                {"type": "INPUT", "name": "x"}
            ]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.crossover = TreeCrossover(self.config)
        self.parser = TreeParser()

        # create nodes
        left_node_1 = Node(NodeType.INPUT, name="x")
        right_node_1 = Node(NodeType.CONSTANT, value=2.0)
        node = Node(NodeType.CONSTANT, value=2.0)

        left_node_2 = Node(NodeType.CONSTANT, value=3.0)
        right_node_2 = Node(NodeType.CONSTANT, value=4.0)

        cos_func_1 = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[left_node_1, right_node_1]
        )

        sin_func_1 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[node]
        )

        cos_func_2 = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node_2]
        )
        sin_func_2 = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node_2]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func_1, sin_func_1]
        )

        sub_func = Node(
            NodeType.FUNCTION,
            name="SUB",
            arity=2,
            branches=[sin_func_2, cos_func_2]
        )

        # create tree_1
        self.tree_1 = Tree()
        self.tree_1.root = add_func
        self.tree_1.update()

        print self.tree_1

        # create tree_2
        self.tree_2 = Tree()
        self.tree_2.root = sub_func
        self.tree_2.update()

    def tearDown(self):
        del self.config
        del self.generator
        del self.parser

    def build_tree_str(self, tree):
        tree_str = ""

        for node in tree.program:
            if hasattr(node, "name") and node.name is not None:
                tree_str += "node:{0} addr:{1}\n".format(node.name, id(node))
            else:
                tree_str += "node:{0} addr:{1}\n".format(node.value, id(node))

        return tree_str

    def tree_equals(self, tree_1_str, tree_2_str):
        if tree_1_str == tree_2_str:
            return True
        else:
            return False

    def test_point_crossover(self):
        # record before crossover
        tree_1_before = self.build_tree_str(self.tree_1)
        tree_2_before = self.build_tree_str(self.tree_2)

        # point crossover
        self.crossover.point_crossover(self.tree_1, self.tree_2)

        # record after crossover
        tree_1_after = self.build_tree_str(self.tree_1)
        tree_2_after = self.build_tree_str(self.tree_2)

        print("Before Crossover")
        print("\nTree 1")
        print(tree_1_before)
        print("\nTree 2")
        print(tree_2_before)

        print("\nAfter Crossover")
        print("\nTree 1")
        print(tree_1_after)
        print("\nTree 2")
        print(tree_2_after)

        # asserts
        self.assertTrue(self.tree_equals(tree_1_before, tree_1_before))
        self.assertTrue(self.tree_equals(tree_2_before, tree_2_before))
        self.assertTrue(self.tree_equals(tree_1_after, tree_1_after))
        self.assertTrue(self.tree_equals(tree_2_after, tree_2_after))

        self.assertFalse(self.tree_equals(tree_1_before, tree_1_after))
        self.assertFalse(self.tree_equals(tree_2_before, tree_2_after))

    def test_common_region_point_crossover(self):
        # record before crossover
        tree_1_before = self.build_tree_str(self.tree_1)
        tree_2_before = self.build_tree_str(self.tree_2)

        # point crossover
        self.crossover.common_region_point_crossover(self.tree_1, self.tree_2)

        # record after crossover
        tree_1_after = self.build_tree_str(self.tree_1)
        tree_2_after = self.build_tree_str(self.tree_2)

        print("Before Crossover")
        print("\nTree 1")
        print(tree_1_before)
        print("\nTree 2")
        print(tree_2_before)

        print("\nAfter Crossover")
        print("\nTree 1")
        print(tree_1_after)
        print("\nTree 2")
        print(tree_2_after)

    def test_crossover(self):
        # record before crossover
        tree_1_before = self.build_tree_str(self.tree_1)
        tree_2_before = self.build_tree_str(self.tree_2)

        # point crossover
        self.crossover.crossover(self.tree_1, self.tree_2)

        # record after crossover
        tree_1_after = self.build_tree_str(self.tree_1)
        tree_2_after = self.build_tree_str(self.tree_2)

        print("Before Crossover")
        print("\nTree 1!")
        print(tree_1_before)
        print("\nTree 2!")
        print(tree_2_before)

        print("\nAfter Crossover")
        print("\nTree 1!")
        print(tree_1_after)
        print("\nTree 2!")
        print(tree_2_after)

        # asserts
        self.assertTrue(self.tree_equals(tree_1_before, tree_1_before))
        self.assertTrue(self.tree_equals(tree_2_before, tree_2_before))
        self.assertTrue(self.tree_equals(tree_1_after, tree_1_after))
        self.assertTrue(self.tree_equals(tree_2_after, tree_2_after))

        self.assertFalse(self.tree_equals(tree_1_before, tree_1_after))
        self.assertFalse(self.tree_equals(tree_2_before, tree_2_after))
Exemple #30
0
    def setUp(self):
        self.config = {
            "tree_generation": {
                "method": "GROW_METHOD",
                "initial_max_depth": 4
            },

            "mutation": {
                "methods": [
                    "POINT_MUTATION",
                    "HOIST_MUTATION",
                    "SUBTREE_MUTATION",
                    "SHRINK_MUTATION",
                    "EXPAND_MUTATION"
                ],
                "probability": 1.0
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1},
                {"type": "FUNCTION", "name": "RAD", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "CONSTANT", "value": 2.0},
                {"type": "INPUT", "name": "x"}
            ],

            "input_variables": [
                {"type": "INPUT", "name": "x"}
            ]

        }
        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.parser = TreeParser()
        self.mutation = TreeMutation(self.config)

        # create nodes
        left_node = Node(NodeType.CONSTANT, value=1.0)
        right_node = Node(NodeType.INPUT, name="x")

        cos_func = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node]
        )

        sin_func = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func, sin_func]
        )

        # create tree
        self.tree = Tree()
        self.tree.root = add_func
        self.tree.update_program()
        self.tree.update_func_nodes()
        self.tree.update_term_nodes()
    def setUp(self):
        self.config = {
            "tree_generation": {
                "method": "GROW_METHOD",
                "initial_max_depth": 4
            },
            "mutation": {
                "methods": [
                    "POINT_MUTATION", "HOIST_MUTATION", "SUBTREE_MUTATION",
                    "SHRINK_MUTATION", "EXPAND_MUTATION"
                ],
                "probability":
                1.0
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "name": "ADD",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "SUB",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "MUL",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "DIV",
                "arity": 2
            }, {
                "type": "FUNCTION",
                "name": "COS",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "SIN",
                "arity": 1
            }, {
                "type": "FUNCTION",
                "name": "RAD",
                "arity": 1
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "CONSTANT",
                "value": 2.0
            }, {
                "type": "INPUT",
                "name": "x"
            }],
            "input_variables": [{
                "type": "INPUT",
                "name": "x"
            }]
        }
        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.parser = TreeParser()
        self.mutation = TreeMutation(self.config)

        # create nodes
        left_node = Node(NodeType.CONSTANT, value=1.0)
        right_node = Node(NodeType.INPUT, name="x")

        cos_func = Node(NodeType.FUNCTION,
                        name="COS",
                        arity=1,
                        branches=[left_node])

        sin_func = Node(NodeType.FUNCTION,
                        name="SIN",
                        arity=1,
                        branches=[right_node])

        add_func = Node(NodeType.FUNCTION,
                        name="ADD",
                        arity=2,
                        branches=[cos_func, sin_func])

        # create tree
        self.tree = Tree()
        self.tree.root = add_func
        self.tree.update_program()
        self.tree.update_func_nodes()
        self.tree.update_term_nodes()
Exemple #32
0
class TreeMutatorTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "tree_generation": {
                "method": "GROW_METHOD",
                "initial_max_depth": 4
            },

            "mutation": {
                "methods": [
                    "POINT_MUTATION",
                    "HOIST_MUTATION",
                    "SUBTREE_MUTATION",
                    "SHRINK_MUTATION",
                    "EXPAND_MUTATION"
                ],
                "probability": 1.0
            },

            "function_nodes": [
                {"type": "FUNCTION", "name": "ADD", "arity": 2},
                {"type": "FUNCTION", "name": "SUB", "arity": 2},
                {"type": "FUNCTION", "name": "MUL", "arity": 2},
                {"type": "FUNCTION", "name": "DIV", "arity": 2},
                {"type": "FUNCTION", "name": "COS", "arity": 1},
                {"type": "FUNCTION", "name": "SIN", "arity": 1},
                {"type": "FUNCTION", "name": "RAD", "arity": 1}
            ],

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "CONSTANT", "value": 2.0},
                {"type": "INPUT", "name": "x"}
            ],

            "input_variables": [
                {"type": "INPUT", "name": "x"}
            ]

        }
        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)

        self.parser = TreeParser()
        self.mutation = TreeMutation(self.config)

        # create nodes
        left_node = Node(NodeType.CONSTANT, value=1.0)
        right_node = Node(NodeType.INPUT, name="x")

        cos_func = Node(
            NodeType.FUNCTION,
            name="COS",
            arity=1,
            branches=[left_node]
        )

        sin_func = Node(
            NodeType.FUNCTION,
            name="SIN",
            arity=1,
            branches=[right_node]
        )

        add_func = Node(
            NodeType.FUNCTION,
            name="ADD",
            arity=2,
            branches=[cos_func, sin_func]
        )

        # create tree
        self.tree = Tree()
        self.tree.root = add_func
        self.tree.update_program()
        self.tree.update_func_nodes()
        self.tree.update_term_nodes()

    def tearDown(self):
        del self.config
        del self.generator
        del self.parser

    def build_tree_str(self, tree):
        tree_str = ""

        for node in tree.program:
            if hasattr(node, "name") and node.name is not None:
                tree_str += "node:{0} addr:{1}\n".format(node.name, id(node))
            else:
                tree_str += "node:{0} addr:{1}\n".format(node.value, id(node))

        return tree_str

    def tree_equals(self, tree_1_str, tree_2_str):
        if tree_1_str == tree_2_str:
            return True
        else:
            return False

    def mutated(self, tree, mutation_func, mutation_index=None):
        tree_before = self.build_tree_str(self.tree)
        mutation_func(tree, mutation_index)
        tree_after = self.build_tree_str(self.tree)

        print("Before Mutation")
        print(tree_before)

        print("\nAfter Mutation")
        print(tree_after)

        self.assertTrue(self.tree_equals(tree_before, tree_before))
        self.assertTrue(self.tree_equals(tree_after, tree_after))
        self.assertFalse(self.tree_equals(tree_before, tree_after))

    def test_mutate_new_node_details(self):
        # MUTATE NEW FUNCTION NODE DETAILS
        for i in range(100):
            func_node = Node(
                NodeType.FUNCTION,
                name="ADD",
                arity=2,
                branches=[]
            )
            node_details = self.mutation.mutate_new_node_details(func_node)
            self.assertNotEquals(node_details["name"], func_node.name)
            self.assertEquals(node_details["arity"], func_node.arity)
            self.assertEquals(node_details["type"], func_node.node_type)

        # MUTATE NEW TERMINAL NODE DETAILS
        for i in range(100):
            term_node = Node(
                NodeType.CONSTANT,
                value=1.0
            )
            node_details = self.mutation.mutate_new_node_details(term_node)
            if node_details["type"] == NodeType.CONSTANT:
                self.assertNotEqual(node_details["value"], term_node.value)

            elif node_details["type"] == NodeType.INPUT:
                self.assertNotEqual(node_details["name"], term_node.name)

        # MUTATE NEW CLASS FUNCTION NODE DETAILS
        self.config["function_nodes"] = [
            {
                "type": "CLASS_FUNCTION",
                "name": "GREATER_THAN",
                "arity": 2,

                "data_range": {
                    "lower_bound": 0.0,
                    "upper_bound": 10.0,
                    "decimal_places": 0,
                }
            },
            {
                "type": "CLASS_FUNCTION",
                "name": "LESS_THAN",
                "arity": 2,

                "data_range": {
                    "lower_bound": 0.0,
                    "upper_bound": 10.0,
                    "decimal_places": 0,
                }
            },
            {
                "type": "CLASS_FUNCTION",
                "name": "EQUALS",
                "arity": 2,
                "decimal_precision": 2
            }
        ]
        mutation = TreeMutation(self.config)

        for i in range(100):
            class_func_node = Node(
                NodeType.CLASS_FUNCTION,
                name="GREATER_THAN",
                arity=2
            )
            node_details = mutation.mutate_new_node_details(class_func_node)
            self.assertNotEquals(node_details["name"], class_func_node.name)
            self.assertEquals(node_details["arity"], class_func_node.arity)
            self.assertEquals(node_details["type"], class_func_node.node_type)

    def test_point_mutation(self):
        print "---------- POINT MUATION! ----------"
        self.mutated(self.tree, self.mutation.point_mutation)

    def test_hoist_mutation(self):
        print "---------- HOIST MUATION! ----------"
        self.mutated(self.tree, self.mutation.hoist_mutation, 3)

    def test_SUBTREE_MUTATION(self):
        print "---------- SUBTREE MUATION! ----------"
        self.mutated(self.tree, self.mutation.subtree_mutation, 3)

    def test_shrink_mutation(self):
        print "---------- SHRINK MUATION! ----------"
        self.mutated(self.tree, self.mutation.shrink_mutation, 3)

    def test_expansion_mutation(self):
        print "---------- EXPANSION MUATION! ----------"
        self.mutated(self.tree, self.mutation.expansion_mutation, 3)

    def test_mutate(self):
        print "MUTATE!"
        tree_before = self.build_tree_str(self.tree)
        self.mutation.mutate(self.tree)
        tree_after = self.build_tree_str(self.tree)

        print "----->", self.mutation.method
        print("Before Mutation")
        print(tree_before)

        print("\nAfter Mutation")
        print(tree_after)

        self.assertTrue(self.tree_equals(tree_before, tree_before))
        self.assertTrue(self.tree_equals(tree_after, tree_after))
        self.assertFalse(self.tree_equals(tree_before, tree_after))