示例#1
0
    def __init__(self):
        self.tree_id = None
        self.score = None
        self.tree_type = None

        self.root = None
        self.depth = 0
        self.size = 0

        self.program = []
        self.func_nodes = []
        self.term_nodes = []
        self.input_nodes = []

        self.parser = TreeParser()
示例#2
0
    def setUp(self):
        self.config = {
            "max_population": 10,

            "tree_generation": {
                "tree_type": "SYMBOLIC_REGRESSION",
                "method": "RAMPED_HALF_AND_HALF_METHOD",
                "initial_max_depth": 3
            },

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

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "INPUT", "name": "x"},
                {"type": "INPUT", "name": "y"},
                {
                    "type": "RANDOM_CONSTANT",
                    "data_range": {
                        "upper_bound": 10.0,
                        "lower_bound": -10.0,
                        "decimal_places": 1
                    }
                }
            ],

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

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)
        self.parser = TreeParser()
示例#3
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)
示例#4
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()
示例#5
0
class Tree(object):
    def __init__(self):
        self.tree_id = None
        self.score = None
        self.tree_type = None

        self.root = None
        self.depth = 0
        self.size = 0

        self.program = []
        self.func_nodes = []
        self.term_nodes = []
        self.input_nodes = []

        self.parser = TreeParser()

    def valid(self, config_input_nodes):
        # convert config input nodes from dict to list of Nodes
        check_list = []
        for node in config_input_nodes:
            check_list.append(node["name"])

        # convert tree input nodes
        tree_input_nodes = []
        for node in self.input_nodes:
            tree_input_nodes.append(node.name)

        result = set(check_list) - set(tree_input_nodes)
        if len(list(result)) == 0:
            return True
        else:
            return False

    def get_linked_node(self, target_node):
        try:
            index = self.program.index(target_node) + 1

            for node in self.program[index:]:
                if node.has_value_node(target_node) is not False:
                    return node
        except ValueError:
            return None

    def replace_node(self, target_node, replace_with, override_update=False):
        linked_node = self.get_linked_node(target_node)
        branch_index = linked_node.has_value_node(target_node)
        linked_node.branches[branch_index] = replace_with

        if override_update is False:
            self.update()

    def equals(self, tree):
        if len(self.program) != len(tree.program):
            return False

        index = 0
        for node in self.program:
            equals = node.equals(tree.program[index])
            if equals is False:
                return False
            index += 1

        return True

    def update_program(self):
        del self.program[:]
        self.program = self.parser.post_order_traverse(self.root)

    def update_func_nodes(self):
        del self.func_nodes[:]
        for node in self.program:
            if node.is_function():
                if node is not self.root:
                    self.func_nodes.append(node)

    def update_term_nodes(self):
        del self.term_nodes[:]
        for node in self.program:
            if node.is_terminal():
                self.term_nodes.append(node)

    def update_input_nodes(self):
        del self.input_nodes[:]
        for node in self.program:
            if node.is_input():
                self.input_nodes.append(node)

    def update_tree_info(self):
        self.size = len(self.program)
        self.branches = len(self.term_nodes) + len(self.input_nodes)

    def update(self):
        self.program = self.parser.parse_tree(self, self.root)

    def __str__(self):
        if self.tree_type == "CLASSIFICATION_TREE":
            return self.parser.parse_classification_tree(self.root)
        else:
            return self.parser.parse_equation(self.root)

    def to_dict(self):
        self_dict = {
            "id": id(self),
            "score": self.score,

            "size": self.size,
            "depth": self.depth,

            "func_nodes_len": len(self.func_nodes),
            "term_nodes_len": len(self.term_nodes),
            "input_nodes_len": len(self.input_nodes),

            "func_nodes": [str(node) for node in self.func_nodes],
            "term_nodes": [str(node) for node in self.term_nodes],
            "input_nodes": [str(node) for node in self.input_nodes],

            "program": str(self)
        }
        return self_dict
示例#6
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()
示例#7
0
    def setUp(self):
        self.config = {
            "max_population":
            10,
            "tree_generation": {
                "tree_type": "SYMBOLIC_REGRESSION",
                "method": "RAMPED_HALF_AND_HALF_METHOD",
                "initial_max_depth": 3
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "arity": 2,
                "name": "ADD"
            }, {
                "type": "FUNCTION",
                "arity": 2,
                "name": "SUB"
            }, {
                "type": "FUNCTION",
                "arity": 2,
                "name": "MUL"
            }, {
                "type": "FUNCTION",
                "arity": 2,
                "name": "DIV"
            }, {
                "type": "FUNCTION",
                "arity": 1,
                "name": "COS"
            }, {
                "type": "FUNCTION",
                "arity": 1,
                "name": "SIN"
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "INPUT",
                "name": "x"
            }, {
                "type": "INPUT",
                "name": "y"
            }, {
                "type": "RANDOM_CONSTANT",
                "data_range": {
                    "upper_bound": 10.0,
                    "lower_bound": -10.0,
                    "decimal_places": 1
                }
            }],
            "input_variables": [{
                "name": "x"
            }, {
                "name": "y"
            }]
        }

        self.functions = GPFunctionRegistry("SYMBOLIC_REGRESSION")
        self.generator = TreeGenerator(self.config)
        self.parser = TreeParser()
示例#8
0
class TreeGeneratorTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "max_population":
            10,
            "tree_generation": {
                "tree_type": "SYMBOLIC_REGRESSION",
                "method": "RAMPED_HALF_AND_HALF_METHOD",
                "initial_max_depth": 3
            },
            "function_nodes": [{
                "type": "FUNCTION",
                "arity": 2,
                "name": "ADD"
            }, {
                "type": "FUNCTION",
                "arity": 2,
                "name": "SUB"
            }, {
                "type": "FUNCTION",
                "arity": 2,
                "name": "MUL"
            }, {
                "type": "FUNCTION",
                "arity": 2,
                "name": "DIV"
            }, {
                "type": "FUNCTION",
                "arity": 1,
                "name": "COS"
            }, {
                "type": "FUNCTION",
                "arity": 1,
                "name": "SIN"
            }],
            "terminal_nodes": [{
                "type": "CONSTANT",
                "value": 1.0
            }, {
                "type": "INPUT",
                "name": "x"
            }, {
                "type": "INPUT",
                "name": "y"
            }, {
                "type": "RANDOM_CONSTANT",
                "data_range": {
                    "upper_bound": 10.0,
                    "lower_bound": -10.0,
                    "decimal_places": 1
                }
            }],
            "input_variables": [{
                "name": "x"
            }, {
                "name": "y"
            }]
        }

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

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

    def test_generate_func_node(self):
        # SYMBOLIC REGRESSION TREES
        for i in range(100):
            node = self.generator.generate_func_node()
            self.assertEquals(node.node_type, NodeType.FUNCTION)

        # CLASSIFICATION TREES
        self.config["tree_generation"]["tree_type"] = "CLASSIFICATION_TREE"
        self.config["function_nodes"] = [{
            "type": "CLASS_FUNCTION",
            "name": "GREATER_THAN",
            "arity": 2,
            "data_range": {
                "lower_bound": 0.0,
                "upper_bound": 10.0,
                "decimal_places": 1
            }
        }]
        self.config["class_attributes"] = [
            "attrubte_1", "attrubte_2", "attrubte_3"
        ]
        generator = TreeGenerator(self.config)
        for i in range(100):
            node = generator.generate_func_node()
            class_attribute = node.class_attribute
            self.assertEquals(node.node_type, NodeType.CLASS_FUNCTION)
            self.assertTrue(class_attribute in self.config["class_attributes"])

    def test_resolve_random_constant(self):
        upper_bound = 10.0
        lower_bound = -10.0
        decimal_places = 0

        for i in range(100):
            n_details = {
                "type": "RANDOM_CONSTANT",
                "data_range": {
                    "lower_bound": lower_bound,
                    "upper_bound": upper_bound,
                    "decimal_places": decimal_places
                }
            }
            new_n_details = self.generator.resolve_random_constant(n_details)
            node_type = new_n_details["type"]
            node_value = new_n_details["value"]

            self.assertEquals(node_type, "CONSTANT")
            self.assertTrue(upper_bound >= node_value)
            self.assertTrue(lower_bound <= node_value)
            self.assertEquals(node_value, int(node_value))

        upper_bound = 100.0
        lower_bound = -100.0
        decimal_places = 1

        for i in range(100):
            n_details = {
                "type": "RANDOM_CONSTANT",
                "data_range": {
                    "lower_bound": lower_bound,
                    "upper_bound": upper_bound,
                    "decimal_places": decimal_places
                }
            }
            new_n_details = self.generator.resolve_random_constant(n_details)
            node_type = new_n_details["type"]
            node_value = new_n_details["value"]

            self.assertEquals(node_type, "CONSTANT")
            self.assertTrue(upper_bound >= node_value)
            self.assertTrue(lower_bound <= node_value)

            node_value = decimal.Decimal(str(node_value))
            node_decimal_places = abs(node_value.as_tuple().exponent)
            self.assertEquals(decimal_places, node_decimal_places)

    def test_generate_term_node(self):
        for i in range(100):
            node = self.generator.generate_term_node()
            self.assertTrue(node.node_type == NodeType.CONSTANT
                            or NodeType.INPUT)

    def test_full_method(self):
        tests = 1

        for i in xrange(tests):
            tree = self.generator.full_method()

            # asserts
            init_max = self.config["tree_generation"]["initial_max_depth"]
            self.assertEquals(tree.depth, init_max)
            self.assertTrue(tree.size > init_max)

    def test_grow_method(self):
        tests = 1000

        for i in xrange(tests):
            tree = self.generator.grow_method()

            # asserts
            init_max = self.config["tree_generation"]["initial_max_depth"]
            self.assertEquals(tree.depth, init_max)
            self.assertTrue(tree.size > init_max)

    def test_generate_tree_from_dict(self):
        population = self.generator.init()
        tree = population.individuals[0]
        tree_dict = self.parser.tree_to_dict(tree, tree.root)
        tree_generated = self.generator.generate_tree_from_dict(tree_dict)

        program_str = ""
        for i in tree.program:
            if i.name is not None:
                program_str += i.name
            else:
                program_str += str(i.value)

        generated_str = ""
        for i in tree_generated.program:
            if i.name is not None:
                generated_str += i.name
            else:
                generated_str += str(i.value)

        self.assertEquals(program_str, generated_str)

    def test_init(self):
        population = self.generator.init()
        self.assertEquals(len(population.individuals), 10)
示例#9
0
class TreeGeneratorTests(unittest.TestCase):
    def setUp(self):
        self.config = {
            "max_population": 10,

            "tree_generation": {
                "tree_type": "SYMBOLIC_REGRESSION",
                "method": "RAMPED_HALF_AND_HALF_METHOD",
                "initial_max_depth": 3
            },

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

            "terminal_nodes": [
                {"type": "CONSTANT", "value": 1.0},
                {"type": "INPUT", "name": "x"},
                {"type": "INPUT", "name": "y"},
                {
                    "type": "RANDOM_CONSTANT",
                    "data_range": {
                        "upper_bound": 10.0,
                        "lower_bound": -10.0,
                        "decimal_places": 1
                    }
                }
            ],

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

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

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

    def test_generate_func_node(self):
        # SYMBOLIC REGRESSION TREES
        for i in range(100):
            node = self.generator.generate_func_node()
            self.assertEquals(node.node_type, NodeType.FUNCTION)

        # CLASSIFICATION TREES
        self.config["tree_generation"]["tree_type"] = "CLASSIFICATION_TREE"
        self.config["function_nodes"] = [
            {
                "type": "CLASS_FUNCTION",
                "name": "GREATER_THAN",
                "arity": 2,

                "data_range": {
                    "lower_bound": 0.0,
                    "upper_bound": 10.0,
                    "decimal_places": 1
                }
            }
        ]
        self.config["class_attributes"] = [
            "attrubte_1",
            "attrubte_2",
            "attrubte_3"
        ]
        generator = TreeGenerator(self.config)
        for i in range(100):
            node = generator.generate_func_node()
            class_attribute = node.class_attribute
            self.assertEquals(node.node_type, NodeType.CLASS_FUNCTION)
            self.assertTrue(class_attribute in self.config["class_attributes"])

    def test_resolve_random_constant(self):
        upper_bound = 10.0
        lower_bound = -10.0
        decimal_places = 0

        for i in range(100):
            n_details = {
                "type": "RANDOM_CONSTANT",
                "data_range": {
                    "lower_bound": lower_bound,
                    "upper_bound": upper_bound,
                    "decimal_places": decimal_places
                }
            }
            new_n_details = self.generator.resolve_random_constant(n_details)
            node_type = new_n_details["type"]
            node_value = new_n_details["value"]

            self.assertEquals(node_type, "CONSTANT")
            self.assertTrue(upper_bound >= node_value)
            self.assertTrue(lower_bound <= node_value)
            self.assertEquals(node_value, int(node_value))

        upper_bound = 100.0
        lower_bound = -100.0
        decimal_places = 1

        for i in range(100):
            n_details = {
                "type": "RANDOM_CONSTANT",
                "data_range": {
                    "lower_bound": lower_bound,
                    "upper_bound": upper_bound,
                    "decimal_places": decimal_places
                }
            }
            new_n_details = self.generator.resolve_random_constant(n_details)
            node_type = new_n_details["type"]
            node_value = new_n_details["value"]

            self.assertEquals(node_type, "CONSTANT")
            self.assertTrue(upper_bound >= node_value)
            self.assertTrue(lower_bound <= node_value)

            node_value = decimal.Decimal(str(node_value))
            node_decimal_places = abs(node_value.as_tuple().exponent)
            self.assertEquals(decimal_places, node_decimal_places)

    def test_generate_term_node(self):
        for i in range(100):
            node = self.generator.generate_term_node()
            self.assertTrue(
                node.node_type == NodeType.CONSTANT or NodeType.INPUT
            )

    def test_full_method(self):
        tests = 1

        for i in xrange(tests):
            tree = self.generator.full_method()

            # asserts
            init_max = self.config["tree_generation"]["initial_max_depth"]
            self.assertEquals(tree.depth, init_max)
            self.assertTrue(tree.size > init_max)

    def test_grow_method(self):
        tests = 1000

        for i in xrange(tests):
            tree = self.generator.grow_method()

            # asserts
            init_max = self.config["tree_generation"]["initial_max_depth"]
            self.assertEquals(tree.depth, init_max)
            self.assertTrue(tree.size > init_max)

    def test_generate_tree_from_dict(self):
        population = self.generator.init()
        tree = population.individuals[0]
        tree_dict = self.parser.tree_to_dict(tree, tree.root)
        tree_generated = self.generator.generate_tree_from_dict(tree_dict)

        program_str = ""
        for i in tree.program:
            if i.name is not None:
                program_str += i.name
            else:
                program_str += str(i.value)

        generated_str = ""
        for i in tree_generated.program:
            if i.name is not None:
                generated_str += i.name
            else:
                generated_str += str(i.value)

        self.assertEquals(program_str, generated_str)

    def test_init(self):
        population = self.generator.init()
        self.assertEquals(len(population.individuals), 10)
示例#10
0
    def test_evaluate(self):
        random.seed(10)
        # solution = {
        #     "results":
        #     [
        #         {"score": 15726642.002161335},
        #         {"score": 359.25843589015597},
        #         {"score": 92155571.22132382},
        #         {"score": 26186.46142920347},
        #         {"score": 15649304.847552022},
        #         {"score": 188.86069156360125},
        #         {"score": 23439.33097274221},
        #     ]
        # }

        # setup
        config = {
            "max_population" : 10,
            "max_generation" : 5,

            "tree_generation" : {
                "method" : "GROW_METHOD",
                "initial_max_depth" : 3
            },

            "evaluator": {
                "use_cache" : True
            },

            "selection" : {
                "method" : "TOURNAMENT_SELECTION",
                "tournament_size": 5
            },

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

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

            "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": "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}
            ],


            "data_file" : "tests/data/sine.dat",

            "input_variables" : [{"type": "INPUT", "name": "x"}],
            "response_variables" : [{"name": "y"}]
        }
        parser = TreeParser()
        population = TreeGenerator(config).init()

        # create a dictionary of trees
        data = {"config": config, "individuals": []}
        for individual in population.individuals:
            tree_json = parser.tree_to_dict(individual, individual.root)
            data["individuals"].append(tree_json)

        # make sure population size is equals to number of trees
        population_size = len(population.individuals)
        individuals = len(data["individuals"])
        self.assertEquals(population_size, individuals)

        # evaluating individuals
        data = json.dumps(data)
        host = "localhost"
        port = 8080
        req_type = "POST"
        path = "evaluate"
        response = self.transmit(host, port, req_type, path, data)
        response = json.loads(response)
        print response
示例#11
0
 def __init__(self, config):
     self.config = config
     self.gen_config = config["tree_generation"]
     self.max_depth = self.gen_config.get("initial_max_depth", 0)
     self.parser = TreeParser()
示例#12
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)")
示例#13
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()
示例#14
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"])
示例#15
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)
示例#16
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)")