Пример #1
0
    // Randomize a new BT using given defined subtrees and definitions.
    protected Genome RandomGenome()
    {
        N_Root root         = new N_Root();
        Genome randomGenome = new Genome();

        // First, randomize starting composition.
        N_CompositionNode firstComp = RandomComp();

        N_CompositionNode currentComp = firstComp;
        bool nestled = false;

        // Generate random subtrees
        for (int i = 0; i < genomeSubtrees; i++)
        {
            // Calculate random chance for adding a new composition as well
            // as ending it.
            float randomChance = UnityEngine.Random.Range(0.0f, 1.0f);
            if (randomChance < additionalCompChance && !nestled)
            {
                nestled = true;
                N_CompositionNode subComp = RandomComp();

                // Attach new composition and add a subtree to it.
                currentComp.AddLast(subComp);
                currentComp = subComp;
            }
            else if (randomChance < (additionalCompChance + 0.2f) && nestled)
            {
                nestled     = false;
                currentComp = firstComp;
            }

            // Lastly, add a random subtree to the current composition as
            // well as to the list of subtree roots.
            Node subTree = RandomSubtree();
            randomGenome.SubRoots.Add(subTree);
            currentComp.AddLast(subTree);
        }

        root.Child            = firstComp;
        randomGenome.RootNode = root;

        return(randomGenome);
    }
Пример #2
0
    public static List <Node> RetrieveNodesOfType(N_Root tree, Type nodeType)
    {
        Queue <Node> itQ   = new Queue <Node>();
        List <Node>  found = new List <Node>();

        itQ.Enqueue(tree.Child);

        // Do a breadth-first search to retrieve all nodes of the given type.
        while (itQ.Count > 0)
        {
            Node current = itQ.Dequeue();
            // If the current node ís the same as the search type
            // or a subclass of it, add it to found.
            if (current.GetType().IsSubclassOf(nodeType) ||
                current.GetType() == nodeType)
            {
                found.Add(current);
            }

            // If node is a composition or decorator, enqueue its child(ren).
            if (current.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            {
                N_CompositionNode comp = current as N_CompositionNode;
                foreach (Node n in comp.GetChildren())
                {
                    itQ.Enqueue(n);
                }
            }
            else if (current.GetType().IsSubclassOf(typeof(N_Decorator)))
            {
                N_Decorator dec = current as N_Decorator;
                itQ.Enqueue(dec.Child);
            }
        }

        // Lastly, return the found children.
        return(found);
    }
Пример #3
0
    // Return a list of all nodes that act as roots for a randomized subtree.
    public static List <Node> RetrieveSubtreeNodes(N_Root tree)
    {
        Queue <Node> itQ   = new Queue <Node>();
        List <Node>  found = new List <Node>();

        itQ.Enqueue(tree.Child);

        while (itQ.Count > 0)
        {
            Node current = itQ.Dequeue();

            // If current node is flagged as subtree, add it to found
            if (current.IsSubtree)
            {
                found.Add(current);
            }

            // If node is a composition or decorator, enqueue its child(ren).
            if (current.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            {
                N_CompositionNode comp = current as N_CompositionNode;
                foreach (Node n in comp.GetChildren())
                {
                    itQ.Enqueue(n);
                }
            }
            else if (current.GetType().IsSubclassOf(typeof(N_Decorator)))
            {
                N_Decorator dec = current as N_Decorator;
                itQ.Enqueue(dec.Child);
            }
        }

        // Return all nodes found with the subtree flag
        return(found);
    }
Пример #4
0
    // Assign random mutations to the given tree.
    protected void Mutate(N_Root child)
    {
        // First, check if there'll be any mutation at all.
        float random = UnityEngine.Random.Range(0.0f, 1.0f);

        if (random < mutationRate)
        {
            List <Node> thresholds = TreeOperations.RetrieveNodesOfType(child, typeof(N_Threshold));
            List <Node> probNodes  = TreeOperations.RetrieveNodesOfType(child, typeof(N_ProbabilitySelector));

            // Randomise between whether to change thresholds or probabilities
            random = UnityEngine.Random.Range(0.0f, 1.0f);
            // If no probnode exists, change condition if there are any instead
            if ((random <= 0.25f && thresholds.Count > 0))
            {
                //Debug.Log("Changing threshold!");
                // Get random index within range of list
                int         index  = UnityEngine.Random.Range(0, thresholds.Count);
                N_Threshold thresh = thresholds[index] as N_Threshold;

                // Mutate threshold by random offset
                int offset = UnityEngine.Random.Range(minThresholdOffset, maxTresholdOffset);
                thresh.SetThreshold(thresh.Threshold + offset);
            }
            else if (random > 0.25f && random <= 0.5f && probNodes.Count > 0) // Adjust relative probabilities on a probability selector.
            {
                //Debug.Log("Changing prob!");
                // Get random index within range of list
                int index = UnityEngine.Random.Range(0, probNodes.Count);
                N_ProbabilitySelector probSelect = probNodes[index] as N_ProbabilitySelector;

                // Check so that the probablitySelector has any children.
                if (probSelect.GetChildren().Count <= 0)
                {
                    return;
                }

                // Calculate total probability and retrieve a relative offset based on it.
                float totalProb = 0.0f;
                foreach (Node n in probSelect.GetChildren())
                {
                    totalProb += probSelect.GetProbabilityWeight(n);
                }
                float offset = totalProb * (relativeProbabilityMutation / 100.0f);
                // Also, get a random sign to decide whether to substract or add offset
                // and a random index for which child to be changed.
                float randomSign       = Mathf.Sign(UnityEngine.Random.Range(-1.0f, 1.0f));
                int   randomChildIndex = UnityEngine.Random.Range(0, probSelect.GetChildren().Count);

                // Finally, offset the given childs probability by the random amount.
                probSelect.OffsetProbabilityWeight(probSelect.GetChildren()[randomChildIndex]
                                                   , offset * randomSign);
            }
            else if (random > 0.5f && random <= 0.75f) // Change subtree
            {
                //Debug.Log("Changing subtree!");
                List <Node>       subtrees    = TreeOperations.RetrieveSubtreeNodes(child);
                int               randomIndex = UnityEngine.Random.Range(0, subtrees.Count);
                Node              subtree     = subtrees[randomIndex];
                N_CompositionNode parentComp  = subtree.Parent as N_CompositionNode;

                // Get a random subtree index and replace its position in the tree with
                // a new randomized subtree instead.
                parentComp.ReplaceChild(subtree, RandomSubtree());
            }
            else if (random > 0.75f) // Change composition
            {
                //Debug.Log("Changing composition!");
                List <Node>       comps       = TreeOperations.RetrieveNodesOfType(child, typeof(N_CompositionNode));
                int               randomIndex = UnityEngine.Random.Range(0, comps.Count);
                N_CompositionNode replaceComp = comps[randomIndex] as N_CompositionNode;

                // If parent is null, this comp is the initial comp.
                if (replaceComp.Parent != null)
                {
                    Node        compParent = replaceComp.Parent;
                    List <Node> children   = replaceComp.GetChildren();

                    // Attach old comps children to the new one.
                    N_CompositionNode newComp = RandomComp();
                    // Make sure to keep structure of subtrees
                    if (replaceComp.IsSubtree)
                    {
                        newComp.IsSubtree = true;
                    }

                    foreach (Node c in children)
                    {
                        c.Parent = newComp;
                        newComp.AddLast(c);
                    }

                    // Reattach parent to the new comp
                    if (compParent.GetType().IsSubclassOf(typeof(N_CompositionNode)))
                    {
                        N_CompositionNode compParent_comp = compParent as N_CompositionNode;
                        compParent_comp.ReplaceChild(replaceComp, newComp);
                    }
                    else if (compParent.GetType().IsSubclassOf(typeof(N_Decorator)))
                    {
                        N_Decorator compParent_dec = compParent as N_Decorator;
                        compParent_dec.Child = newComp;
                    }
                }
            }
        }
    }
Пример #5
0
    // Combine parents and create two new children based on them
    protected void Combine(out Genome child0, out Genome child1, Genome parent0, Genome parent1)
    {
        Node subtree0, subtree1 = null;
        // First, check if there'll be any combination/crossover.
        float random = UnityEngine.Random.Range(0.0f, 1.0f);

        if (random < combinationRate)
        {
            List <Node> subtrees0 = TreeOperations.RetrieveSubtreeNodes(parent0.RootNode);
            List <Node> subtrees1 = TreeOperations.RetrieveSubtreeNodes(parent1.RootNode);

            // Select to random subtrees...
            int randomIndex = UnityEngine.Random.Range(0, subtrees0.Count);
            subtree0    = subtrees0[randomIndex];
            randomIndex = UnityEngine.Random.Range(0, subtrees1.Count);
            subtree1    = subtrees1[randomIndex];

            // Swap subtrees between 0 and 1.
            if (subtree0.Parent.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            {
                N_CompositionNode comp0 = subtree0.Parent as N_CompositionNode;
                comp0.ReplaceChild(subtree0, StaticMethods.DeepCopy <Node>(subtree1));
            }

            // Swap subtrees between 1 and 0.
            if (subtree1.Parent.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            {
                N_CompositionNode comp1 = subtree1.Parent as N_CompositionNode;
                comp1.ReplaceChild(subtree1, StaticMethods.DeepCopy <Node>(subtree0));
            }

            #region Old Combination
            //// Get initial comp of parent 0
            //N_CompositionNode comp0 = parent0.RootNode.Child as N_CompositionNode;
            //// Fetch a random subtree from the parent's subtrees
            //int randomIndex = UnityEngine.Random.Range(0, comp0.GetChildren().Count);
            //subtree0 = comp0.GetChildren()[randomIndex];

            //// Get initial comp of parent 1
            //N_CompositionNode comp1 = parent1.RootNode.Child as N_CompositionNode;
            //// Fetch a random subtree from the parent's subtrees
            //randomIndex = UnityEngine.Random.Range(0, comp1.GetChildren().Count);
            //subtree1 = comp1.GetChildren()[randomIndex];

            //// Swap subtrees between 0 and 1.
            //if (subtree0.Parent.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            //{
            //    comp0.ReplaceChild(subtree0, StaticMethods.DeepCopy<Node>(subtree1));
            //}

            //// Swap subtrees between 1 and 0.
            //if (subtree1.Parent.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            //{
            //    comp1.ReplaceChild(subtree1, StaticMethods.DeepCopy<Node>(subtree0));
            //}
            #endregion
        }

        // Regardless of combination, assign the children to be the parents. (combined or not)
        child0 = parent0;
        child1 = parent1;
    }