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); }
public void Record(EnvironmentTimeStep environmentTimeStep, TuringMachineTimeStep turingTimeStep) { _recordedTimeSteps.Add(new TimeStep(environmentTimeStep, turingTimeStep)); }