Esempio n. 1
0
 public TimeStep(EnvironmentTimeStep environmentTimeStep, TuringMachineTimeStep turingMachineTimeStep)
 {
     EnvironmentTimeStep = environmentTimeStep;
     TuringMachineTimeStep = turingMachineTimeStep;
 }
        /// <summary>
        /// Activate the Turing machine.
        /// Operation order:
        ///	1: Write
        /// 2: Content jump
        /// 3: Shift
        /// 4: Read
        /// </summary>
        /// <param name="fromNN">Turing machine input (NN output)</param>
        /// <returns>Turing machine output (NN input)</returns>
        public double[][] ProcessInput(double[] fromNN)
        {
            Debug.DLogHeader("MINIMAL TURING MACHINE START", true);
            Debug.DLog($"From NN: {Utilities.ToString(fromNN, "f4")}", true);

            // Current timestep will start on 1, since the inital read does not run this method
            _currentTimeStep++;

            if (!_enabled)
            {
                return(_initialRead);
            }

            double[][] result = new double[_heads][];

            double[][] writeKeys = new double[_heads][];
            double[]   interps   = new double[_heads];
            double[]   jumps     = new double[_heads];
            double[][] shifts    = new double[_heads][];

            int[]      writePositions = null;
            double[][] written        = null;
            _didWrite = false;
            _didRead  = false;

            // Attention! Novelty score does not currently support multiple read/write heads.
            // It will overwrite data for previous heads, if more than one.
            if (RecordTimeSteps || NoveltySearch.ScoreNovelty)
            {
                writePositions = new int[_heads];

                if (RecordTimeSteps)
                {
                    written = new double[_heads][];
                }
            }

            int p = 0;

            // First all writes
            for (int i = 0; i < _heads; i++)
            {
                writeKeys[i] = Take(fromNN, p, _m);
                p           += _m;

                interps[i] = fromNN[p];
                p++;

                jumps[i] = fromNN[p];
                p++;

                int s = GetShiftInputs();
                shifts[i] = Take(fromNN, p, s);
                p        += s;

                Debug.DLogHeader($"HEAD {i + 1}", true);
                Debug.DLog($"\nWrite:        \t{Utilities.ToString(writeKeys[i], "f4")}" +
                           $"\nInterpolate:  \t{interps[i].ToString("f4")}" +
                           $"\nContent:      \t{jumps[i].ToString("f4")}" +
                           $"\nShift:        \t{Utilities.ToString(shifts[i], "f4")}", true);

                // 1: Write!
                Write(i, writeKeys[i], interps[i]);

                if (RecordTimeSteps || NoveltySearch.ScoreNovelty)
                {
                    // Save write position for recording
                    writePositions[i] = _headPositions[i];

                    if (RecordTimeSteps)
                    {
                        //Save tape data at write location before head is moved
                        written[i] = GetRead(i);
                    }
                }
            }

            for (int i = 0; i < _heads; i++)
            {
                // 2: Content jump!
                PerformContentJump(i, jumps[i], writeKeys[i]);
            }

            // Shift and read (no interaction)
            for (int i = 0; i < _heads; i++)
            {
                // If the memory has been expanded down below 0, which means the memory has shiftet
                _increasedSizeDown = false;

                // 3: Shift!
                int shift = MoveHead(i, shifts[i]);

                // 4: Read!
                result[i] = GetRead(i); // Show me what you've got! \cite{rickEtAl2014}

                if (RecordTimeSteps || NoveltySearch.ScoreNovelty)
                {
                    // Calculate corrected write position first, since the write happened before a possible downward memory increase
                    int correctedWritePosition = writePositions[i] - _zeroPosition;

                    // The memory has increased in size downward (-1), shifting all memory positions +1
                    if (_increasedSizeDown)
                    {
                        writePositions[i]++;
                        _zeroPosition++;
                    }

                    if (NoveltySearch.ScoreNovelty)
                    {
                        // (-1 because timestep 0 is not scored)
                        int n = _currentTimeStep - 1;
                        switch (NoveltySearch.VectorMode)
                        {
                        case NoveltyVectorMode.WritePattern:

                            // Save the write position as a behavioural trait
                            NoveltySearch.NoveltyVectors[n][0] = correctedWritePosition;

                            break;

                        case NoveltyVectorMode.ReadContent:

                            // Content of the read vector
                            Array.Copy(result[i], NoveltySearch.NoveltyVectors[n], result[i].Length);

                            break;

                        case NoveltyVectorMode.WritePatternAndInterp:

                            // Head position (we use corrected write position to account for downward shifts)
                            NoveltySearch.NoveltyVectors[n][0] = correctedWritePosition;

                            // Write interpolation
                            NoveltySearch.NoveltyVectors[n][1] = interps[i];

                            break;

                        case NoveltyVectorMode.ShiftJumpInterp:

                            NoveltySearch.NoveltyVectors[n][0] = shift;
                            NoveltySearch.NoveltyVectors[n][1] = jumps[i];
                            NoveltySearch.NoveltyVectors[n][2] = interps[i];

                            break;
                        }


                        // Check for non-empty reads, to see if novelty search minimum criteria has been reached
                        for (int j = 0; j < result[i].Length; j++)
                        {
                            if (result[i][j] > .1f)
                            {
                                _didRead = true;
                                break;
                            }
                        }

                        if (NoveltySearch.VectorMode != NoveltyVectorMode.EnvironmentAction)
                        {
                            // If the turing machine neither wrote or read this iteration, we note it for the minimum criteria novelty search
                            if (!_didWrite && !_didRead)
                            {
                                // Store number of redundant iterations in the novelty vector.
                                NoveltySearch.MinimumCriteria[0] += 1;
                            }

                            // Total timesteps to calculate redundancy factor
                            NoveltySearch.MinimumCriteria[1] += 1;
                        }
                    }

                    if (RecordTimeSteps)
                    {
                        int readPosition          = _headPositions[i];
                        int correctedReadPosition = readPosition - _zeroPosition;

                        _prevTimeStep = new TuringMachineTimeStep(writeKeys[i], interps[i], jumps[i], shifts[i], result[i], written[i], writePositions[i], readPosition, _zeroPosition, correctedWritePosition, correctedReadPosition, _tape.Count);
                    }
                }
            }

            Debug.DLog(PrintState(), true);
            Debug.DLog("Sending to NN: " + Utilities.ToString(result, "F4"), true);
            Debug.DLogHeader("MINIMAL TURING MACHINE END", true);

            return(result);
        }
Esempio n. 3
0
 public void Record(EnvironmentTimeStep environmentTimeStep, TuringMachineTimeStep turingTimeStep)
 {
     _recordedTimeSteps.Add(new TimeStep(environmentTimeStep, turingTimeStep));
 }