public static void crossover(GeneticTree current, GeneticTree other)
        {
            List <string> currentIndices  = current._nodeIndices.Where(x => x.Length != 1).ToList();
            List <string> otherIndices    = other._nodeIndices.Where(x => x.Length != 1).ToList();
            int           currentIndexAux = Rng.Rnd.Next(currentIndices.Count);
            int           otherIndexAux   = Rng.Rnd.Next(otherIndices.Count);
            string        currentIndex    = currentIndices[currentIndexAux];
            string        otherIndex      = otherIndices[otherIndexAux];

            GeneticNode iterCurrent = current._root;
            GeneticNode iterOther   = other._root;

            for (int i = 1; i < currentIndex.Length; i++)
            {
                int index = GeneticTree._TREE_NODES_CHAR_TO_INT[currentIndex[i]];
                iterCurrent = iterCurrent._children._children[index];
            }

            for (int i = 1; i < otherIndex.Length; i++)
            {
                int index = GeneticTree._TREE_NODES_CHAR_TO_INT[otherIndex[i]];
                iterOther = iterOther._children._children[index];
            }

            current.attachNode(iterOther, currentIndex);
            other.attachNode(iterCurrent, otherIndex);

            current.recalculateIndices();
            other.recalculateIndices();
        }
        public void calculatePositions()
        {
            int         correct = 0;
            GeneticTree _tree   = _population[0];
            Task        t       = new Task(() =>
            {
                StreamReader sr = new StreamReader("./test/testpos");
                string line;
                char[] fenDelim = { ';' };
                while ((line = sr.ReadLine()) != null)
                {
                    string[] FENs = line.Split(fenDelim);
                    string first  = FENs[0].Split(null)[0];
                    string second = FENs[1].Split(null)[0];

                    Process p             = new Process();
                    p.StartInfo.FileName  = "bestmove.exe";
                    p.StartInfo.Arguments = $"{_evalDepth} \"{FENs[0]}\" \"{_tree._rpn}\"";
                    p.StartInfo.RedirectStandardOutput = true;
                    p.StartInfo.CreateNoWindow         = true;
                    p.StartInfo.UseShellExecute        = false;
                    p.Start();
                    string FEN = p.StandardOutput.ReadToEnd().Trim();
                    if (FEN.Split(null)[0].CompareTo(second) == 0)
                    {
                        correct++;
                    }
                }
            });

            t.Start();
            Task.WaitAll(new Task[] { t });
            _statistics._positionsSolved.Add(correct);
        }
        public void beginCrossover()
        {
            _successfulCrossover = new List <TreePair>();
            _toMutate            = new List <GeneticTree>();
            foreach (var item in _toCrossover)
            {
                if (Rng.Rnd.NextDouble() < _crossoverRate)
                {
                    GeneticTree t1 = GeneticTree.deepCopy(item._first);
                    GeneticTree t2 = GeneticTree.deepCopy(item._second);
                    crossover(t1, t2);

                    _successfulCrossover.Add(new TreePair(GeneticTree.deepCopy(t1), GeneticTree.deepCopy(t2)));
                    _swapParents(t1, t2, item._first._id, item._second._id);

                    _toMutate.Add(t1);
                    _toMutate.Add(t2);
                }
                else
                {
                    _toMutate.Add(item._first);
                    _toMutate.Add(item._second);
                }
            }
        }
        private void _swapParents(GeneticTree first, GeneticTree second, ulong firstParentId, ulong secondParentId)
        {
            ulong randomSalt = Rng.randomSparseBits();

            first._id             = (firstParentId & _RIGHT_PARENT_MASK) | (secondParentId & _LEFT_PARENT_MASK) ^ randomSalt;
            second._id            = (secondParentId & _RIGHT_PARENT_MASK) | (firstParentId & _LEFT_PARENT_MASK) ^ randomSalt;
            first._firstParentId  = second._firstParentId = firstParentId;
            first._secondParentId = second._secondParentId = secondParentId;
        }
        public static void mutateOpportunistic(GeneticTree current)
        {
            NodeStatistics       stats         = current.allNodesStats(current._root, 0, "", 0);
            List <NodeStatsPair> opportunities = new List <NodeStatsPair>();

            foreach (var item in current._nodeStatsDictionary)
            {
                //Debug.WriteLine("Node " + item.Key + " /// Operator variance: " + item.Value._opVariance + " Variable variance: " + item.Value._varVariance + " Avg depth: " + item.Value._avgDepth + " Avg branching: " + item.Value._avgBranching);
                opportunities.Add(new NodeStatsPair(item.Key, item.Value._avgBranching + item.Value._avgDepth + item.Value._opVariance + item.Value._varVariance));
            }

            float max = opportunities.Max(x => x._mutationValue);

            foreach (var item in opportunities)
            {
                item._mutationValue = max - item._mutationValue + 1; // make less branchy, depthy and variant more likely to be mutated
            }
            opportunities = opportunities.OrderByDescending(x => x._mutationValue).ToList();


            float[] wSum = new float[opportunities.Count];

            wSum[0] = opportunities[0]._mutationValue;
            for (int i = 1; i < wSum.Length; i++)
            {
                wSum[i] = opportunities[i]._mutationValue + wSum[i - 1];
            }

            float sumF = opportunities.Sum(x => x._mutationValue);

            double centil = Rng.Rnd.NextDouble() * sumF;

            int index = 0;

            for (int i = 0; i < opportunities.Count && centil < wSum[i]; i++)
            {
                index = i;
            }

            string currentIndex = opportunities[index]._node;

            int         newDepth = (int)current._maxDepth - currentIndex.Length + 1;
            GeneticTree added    = new GeneticTree((uint)newDepth, current._maxBranching);

            GeneticNode tmp = current._root;

            for (int i = 1; i < currentIndex.Length; i++) // traversing to find proper index
            {
                index = GeneticTree._TREE_NODES_CHAR_TO_INT[currentIndex[i]];
                tmp   = tmp._children._children[index];
            }

            current.attachNode(added._root, currentIndex);

            current.recalculateIndices();
        }
        public static void mutateSwap(GeneticTree current)
        {
            List <string> currentIndices  = current._nodeIndices.Where(x => x.Length != 1).ToList();
            int           currentIndexAux = Rng.Rnd.Next(currentIndices.Count);
            string        currentIndex    = currentIndices[currentIndexAux];

            List <string> otherIndices = current._nodeIndices.
                                         Where(x => x.Length != 1).ToList();

            List <string> shorter = otherIndices.Where(x => x.Length <= currentIndex.Length).Where(x => currentIndex.Substring(0, x.Length).CompareTo(x) != 0).ToList();
            List <string> longer  = otherIndices.Where(x => x.Length > currentIndex.Length).Where(x => x.Substring(0, currentIndex.Length).CompareTo(currentIndex) != 0).ToList();


            otherIndices = shorter.Union(longer).ToList();
            if (otherIndices == null || otherIndices.Count == 0)
            {
                return;
            }

            int    otherIndexAux = Rng.Rnd.Next(otherIndices.Count);
            string otherIndex    = otherIndices[otherIndexAux];


            GeneticNode tmp  = current._root;
            GeneticNode tmp2 = current._root;

            for (int i = 1; i < currentIndex.Length; i++)
            {
                int index = GeneticTree._TREE_NODES_CHAR_TO_INT[currentIndex[i]];
                tmp = tmp._children._children[index];
            }

            for (int i = 1; i < otherIndex.Length; i++)
            {
                int index = GeneticTree._TREE_NODES_CHAR_TO_INT[otherIndex[i]];
                tmp2 = tmp2._children._children[index];
            }

            current.attachNode(tmp2, currentIndex);
            current.attachNode(tmp, otherIndex);

            current.recalculateIndices();
        }
 public void beginMutation()
 {
     _successfulMutation = new List <GeneticTree>();
     foreach (var item in _toMutate)
     {
         item.setColor(item._nodesColor);
         item.allNodesStats(item._root, 0, "", 0);
         if (Rng.Rnd.NextDouble() < _mutationRate)
         {
             GeneticTree copy = GeneticTree.deepCopy(item);
             mutateOpportunistic(copy);
             _successfulMutation.Add(copy);
         }
         else
         {
             _newPopulation.Add(item);
         }
     }
 }
        public static void mutateReplace(GeneticTree current)
        {
            List <string> currentIndices  = current._nodeIndices.Where(x => x.Length != 1).ToList();
            int           currentIndexAux = Rng.Rnd.Next(currentIndices.Count);
            string        currentIndex    = currentIndices[currentIndexAux];

            int         newDepth = (int)current._maxDepth - currentIndex.Length + 1;
            GeneticTree added    = new GeneticTree((uint)newDepth, current._maxBranching);

            GeneticNode tmp = current._root;

            for (int i = 1; i < currentIndex.Length; i++) // traversing to find proper index
            {
                int index = GeneticTree._TREE_NODES_CHAR_TO_INT[currentIndex[i]];
                tmp = tmp._children._children[index];
            }

            current.attachNode(added._root, currentIndex);

            current.recalculateIndices();
        }
        public static GeneticTree deepCopy(GeneticTree other)
        {
            GeneticTree res = new GeneticTree(other._maxDepth, other._maxBranching);

            res._nodesColor  = other._nodesColor;
            res._id          = other._id;
            res._nodeIndices = new List <string>(other._nodeIndices);
            switch (other._root)
            {
            case OperatorNode on:
                res._root = OperatorNode.deepCopy((OperatorNode)other._root);
                break;

            case VariableNode vn:
                res._root = VariableNode.deepCopy((VariableNode)other._root);
                break;

            case ConstNode cn:
                res._root = ConstNode.deepCopy((ConstNode)other._root);
                break;

            case MultipleNode mn:
                res._root = MultipleNode.deepCopy((MultipleNode)other._root);
                break;

            default:
                break;
            }
            res.getRPN();
            res._nodeStatsDictionary = other._nodeStatsDictionary;
            res._firstParentId       = other._firstParentId;
            res._secondParentId      = other._secondParentId;

            //res.setColor(other._nodesColor.r, other._nodesColor.g, other._nodesColor.b);
            return(res);
        }
        public void beginSelection()
        {
            _newPopulation = new List <GeneticTree>();
            _toCrossover   = new List <TreePair>();
            int elitismPassNumber = (int)(_populationSize * _elitismPercentage);

            if (elitismPassNumber % 2 != 0)
            {
                elitismPassNumber++;
            }
            for (int i = 0; i < elitismPassNumber; i++)
            {
                _newPopulation.Add(GeneticTree.deepCopy(_population[i]));
            }
            switch (_selectionType)
            {
            case GpSelectionType.RANK:

                int[]  weights    = Enumerable.Range(1, (int)_populationSize).Reverse().ToArray();
                int[]  weightsRev = weights.Reverse().ToArray();
                uint[] weightSum  = new uint[_populationSize];
                weightSum[0] = _populationSize;
                for (uint i = 1; i < weightSum.Length; i++)
                {
                    weightSum[i] = _populationSize - i + weightSum[i - 1];
                }
                int sum = ((1 + (int)_populationSize)) * (int)_populationSize / 2;

                for (int i = 0; i < _populationSize - elitismPassNumber; i += 2)
                {
                    int         centil   = Rng.Rnd.Next(0, sum);
                    int         resIndex = weightsRev.First(x => weightSum[x - 1] > centil) - 1;
                    GeneticTree first    = _population[resIndex];
                    centil   = Rng.Rnd.Next(0, sum);
                    resIndex = weightsRev.First(x => weightSum[x - 1] > centil) - 1;
                    GeneticTree second = _population[resIndex];

                    _toCrossover.Add(new TreePair(GeneticTree.deepCopy(first), GeneticTree.deepCopy(second)));
                }
                break;

            case GpSelectionType.ROULETTE:

                weights    = Enumerable.Range(0, (int)_populationSize).ToArray();
                weightsRev = weights.Reverse().ToArray();
                float[] wSum = new float[(int)_populationSize];
                wSum[0] = _fitnesses[0];
                for (int i = 1; i < wSum.Length; i++)
                {
                    wSum[i] = _fitnesses[i] + wSum[i - 1];
                }
                float sumF = _fitnesses.Sum();

                for (int i = 0; i < _populationSize - elitismPassNumber; i += 2)
                {
                    double      centil   = Rng.Rnd.NextDouble() * sumF;
                    int         resIndex = weights.First(x => wSum[x] > centil);
                    GeneticTree first    = _population[resIndex];
                    centil   = Rng.Rnd.NextDouble() * sumF;
                    resIndex = weights.First(x => wSum[x] > centil);
                    GeneticTree second = _population[resIndex];

                    _toCrossover.Add(new TreePair(GeneticTree.deepCopy(first), GeneticTree.deepCopy(second)));
                }
                break;

            case GpSelectionType.TOURNAMENT:

                weights = Enumerable.Range(0, (int)_populationSize).ToArray();
                var shuffled = weights.OrderBy(x => Guid.NewGuid());

                for (int i = 0; i < _populationSize - elitismPassNumber; i += 2)
                {
                    var slice       = shuffled.Take((int)_tournamentSelectionSize);
                    var firstRandom = _population[slice.OrderByDescending(x => _fitnesses[x]).First()];
                    shuffled = weights.OrderBy(x => Guid.NewGuid());

                    slice = shuffled.Take((int)_tournamentSelectionSize);
                    var secondRandom = _population[slice.OrderByDescending(x => _fitnesses[x]).First()];
                    shuffled = weights.OrderBy(x => Guid.NewGuid());

                    _toCrossover.Add(new TreePair(GeneticTree.deepCopy(firstRandom), GeneticTree.deepCopy(secondRandom)));
                }
                break;
            }
        }
 public TreePair(GeneticTree first, GeneticTree second)
 {
     _first  = first;
     _second = second;
 }