遗传编程Stackoverflow错误

时间:2012-03-29 19:03:23

标签: java recursion

当我用更深的树调用它时,我的代码似乎做了无限的递归。 我试图在没有递归的情况下做到这一点,这很难做,因为我需要操纵树本身,无论如何这里是m代码。感谢

问题在于printPostOrder方法,它到达叶子节点并来回打印叶子节点及其父节点,直到堆栈溢出

我宁愿发布我的完整代码,这样你就能得到我想做的事情。

节点插入就像这样

import java.util.*;

public class IPG {

    class Node {

        private int arity;
        private String label;
        private int value;
        private Node[] children;
        protected int visit = 0;
        protected boolean isVisited = false;

        public Node(int arity, String label) {
            this.arity = arity;
            this.label = label;
            this.children = new Node[3];
        }

        public Node(Node another) {
            this.label = another.label;
            this.arity = another.arity;
        }

        @Override
        public String toString() {
            return label;
        }

        String getLabel() {
            return label;
        }

        void insertChild(int pos, Node n) {
            if (pos < arity) {
                children[pos] = n;
            }
        }

        Node getChildAt(int i) {
            return children[i];
        }

        void setValue(int value) {
            this.value = value;
        }

        int getArity() {
            return arity;
        }

        void replace(Node another) {
            this.arity = another.arity;
            this.children = another.children;
            this.label = another.label;
        }

    }

    private Node[] functions = { new Node(2, "AND"), new Node(2, "OR"),
            new Node(1, "NOT"), new Node(3, "IF") };

    private Node[] terminals = { new Node(0, "A0"), new Node(0, "D1"),
            new Node(0, "D0"), new Node(0, "A1"), new Node(0, "D2"),
            new Node(0, "D3"), new Node(0, "A2"), new Node(0, "D4"),
            new Node(0, "D5"), new Node(0, "D6"), new Node(0, "D7") };

    private Random random = new Random();

    private int multiplexerType = 3;

    public Node getTerminal() {
        return terminals[random.nextInt(multiplexerType)];
    }

    public Node getFunction() {

        return functions[random.nextInt(3)];
    }

    public Node getAnyNode() {
        return random.nextInt(2) == 1 ? getFunction() : getTerminal();
    }

    public Node generateGrow(int depth) {
        Node root;

        if (depth > 1)
            root = getAnyNode();

        else
            root = getTerminal();

        for (int i = 0; i < root.getArity(); i++)
            root.insertChild(i, generateGrow(depth - 1));

        return root;
    }

    public Node generateFull(int depth) {
        Node root;

        if (depth > 1)
            root = getFunction();

        else
            root = getTerminal();

        for (int i = 0; i < root.getArity(); i++)
            root.insertChild(i, generateFull(depth - 1));

        return root;
    }

    public void printPostOrder() {
        Node root = generateFull(3);
        printPostOrder(root);
    }

    private void printPostOrder(Node n) {
        if (n == null) {
            return;
        } else {
            System.out.println(n + " ");

            printPostOrder(n.children[0]);
            printPostOrder(n.children[1]);
            printPostOrder(n.children[2]);
        }
    }

    public static void main(String[] args) {
        new IPG().printPostOrder();
    }
}

2 个答案:

答案 0 :(得分:1)

图表有可能是循环的。仅仅因为您使用预先创建的节点并随机选择它们。节点越深,一个节点插入一次以上的概率就越高。在这种情况下,你有你的周期,JVM抱怨SSO。

问题的根源是functions数组(terminals没问题,因为终端节点没有任何子节点。)

删除该数组并为每个节点创建 new 函数对象。

答案 1 :(得分:0)

问题在于,当您生成functions数组时,您只创建每种类型的一个节点,然后getFunction()重新使用这些相同的节点。例如,如果您插入“AND”节点并且其子节点也是“AND”节点,则会创建一个循环,因为它们实际上是同一个对象。

这是一个简单的修复,您只需要确保每次调用getFunction()创建一个新节点,例如:

private String [] functionNames = {"AND", "OR", "NOT", "IF"};
private int [] functionArities = {2,2,1,3};

public Node getFunction() {
    int index = random.nextInt(3); // If you want to use "IF" nodes too this
                                   // needs to be nextInt(4)
    return new Node(functionArities[index],functionNodes[index]);
}