|
using System.Collections.Generic; |
|
using System; |
|
using Unity.Barracuda; |
|
using Unity.MLAgents.Inference.Utils; |
|
using Unity.MLAgents.Sensors; |
|
|
|
namespace Unity.MLAgents.Inference |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
internal class BiDimensionalOutputGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
|
|
public BiDimensionalOutputGenerator(ITensorAllocator allocator) |
|
{ |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
internal class BatchSizeGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
|
|
public BatchSizeGenerator(ITensorAllocator allocator) |
|
{ |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
tensorProxy.data?.Dispose(); |
|
tensorProxy.data = m_Allocator.Alloc(new TensorShape(1, 1)); |
|
tensorProxy.data[0] = batchSize; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal class SequenceLengthGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
|
|
public SequenceLengthGenerator(ITensorAllocator allocator) |
|
{ |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
tensorProxy.shape = new long[0]; |
|
tensorProxy.data?.Dispose(); |
|
tensorProxy.data = m_Allocator.Alloc(new TensorShape(1, 1)); |
|
tensorProxy.data[0] = 1; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal class RecurrentInputGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
Dictionary<int, List<float>> m_Memories; |
|
|
|
public RecurrentInputGenerator( |
|
ITensorAllocator allocator, |
|
Dictionary<int, List<float>> memories) |
|
{ |
|
m_Allocator = allocator; |
|
m_Memories = memories; |
|
} |
|
|
|
public void Generate( |
|
TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); |
|
|
|
var memorySize = tensorProxy.data.width; |
|
|
|
var agentIndex = 0; |
|
for (var infoIndex = 0; infoIndex < infos.Count; infoIndex++) |
|
{ |
|
var infoSensorPair = infos[infoIndex]; |
|
var info = infoSensorPair.agentInfo; |
|
List<float> memory; |
|
|
|
if (info.done) |
|
{ |
|
m_Memories.Remove(info.episodeId); |
|
} |
|
if (!m_Memories.TryGetValue(info.episodeId, out memory)) |
|
{ |
|
for (var j = 0; j < memorySize; j++) |
|
{ |
|
tensorProxy.data[agentIndex, 0, j, 0] = 0; |
|
} |
|
agentIndex++; |
|
continue; |
|
} |
|
for (var j = 0; j < Math.Min(memorySize, memory.Count); j++) |
|
{ |
|
if (j >= memory.Count) |
|
{ |
|
break; |
|
} |
|
tensorProxy.data[agentIndex, 0, j, 0] = memory[j]; |
|
} |
|
agentIndex++; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal class PreviousActionInputGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
|
|
public PreviousActionInputGenerator(ITensorAllocator allocator) |
|
{ |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); |
|
|
|
var actionSize = tensorProxy.shape[tensorProxy.shape.Length - 1]; |
|
var agentIndex = 0; |
|
for (var infoIndex = 0; infoIndex < infos.Count; infoIndex++) |
|
{ |
|
var infoSensorPair = infos[infoIndex]; |
|
var info = infoSensorPair.agentInfo; |
|
var pastAction = info.storedActions.DiscreteActions; |
|
if (!pastAction.IsEmpty()) |
|
{ |
|
for (var j = 0; j < actionSize; j++) |
|
{ |
|
tensorProxy.data[agentIndex, j] = pastAction[j]; |
|
} |
|
} |
|
|
|
agentIndex++; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal class ActionMaskInputGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
|
|
public ActionMaskInputGenerator(ITensorAllocator allocator) |
|
{ |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); |
|
|
|
var maskSize = tensorProxy.shape[tensorProxy.shape.Length - 1]; |
|
var agentIndex = 0; |
|
for (var infoIndex = 0; infoIndex < infos.Count; infoIndex++) |
|
{ |
|
var infoSensorPair = infos[infoIndex]; |
|
var agentInfo = infoSensorPair.agentInfo; |
|
var maskList = agentInfo.discreteActionMasks; |
|
for (var j = 0; j < maskSize; j++) |
|
{ |
|
var isUnmasked = (maskList != null && maskList[j]) ? 0.0f : 1.0f; |
|
tensorProxy.data[agentIndex, j] = isUnmasked; |
|
} |
|
agentIndex++; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
internal class RandomNormalInputGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly RandomNormal m_RandomNormal; |
|
readonly ITensorAllocator m_Allocator; |
|
|
|
public RandomNormalInputGenerator(int seed, ITensorAllocator allocator) |
|
{ |
|
m_RandomNormal = new RandomNormal(seed); |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); |
|
TensorUtils.FillTensorWithRandomNormal(tensorProxy, m_RandomNormal); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal class ObservationGenerator : TensorGenerator.IGenerator |
|
{ |
|
readonly ITensorAllocator m_Allocator; |
|
List<int> m_SensorIndices = new List<int>(); |
|
ObservationWriter m_ObservationWriter = new ObservationWriter(); |
|
|
|
public ObservationGenerator(ITensorAllocator allocator) |
|
{ |
|
m_Allocator = allocator; |
|
} |
|
|
|
public void AddSensorIndex(int sensorIndex) |
|
{ |
|
m_SensorIndices.Add(sensorIndex); |
|
} |
|
|
|
public void Generate(TensorProxy tensorProxy, int batchSize, IList<AgentInfoSensorsPair> infos) |
|
{ |
|
TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); |
|
var agentIndex = 0; |
|
for (var infoIndex = 0; infoIndex < infos.Count; infoIndex++) |
|
{ |
|
var info = infos[infoIndex]; |
|
if (info.agentInfo.done) |
|
{ |
|
|
|
|
|
|
|
TensorUtils.FillTensorBatch(tensorProxy, agentIndex, 0.0f); |
|
} |
|
else |
|
{ |
|
var tensorOffset = 0; |
|
|
|
for (var sensorIndexIndex = 0; sensorIndexIndex < m_SensorIndices.Count; sensorIndexIndex++) |
|
{ |
|
var sensorIndex = m_SensorIndices[sensorIndexIndex]; |
|
var sensor = info.sensors[sensorIndex]; |
|
m_ObservationWriter.SetTarget(tensorProxy, agentIndex, tensorOffset); |
|
var numWritten = sensor.Write(m_ObservationWriter); |
|
tensorOffset += numWritten; |
|
} |
|
} |
|
agentIndex++; |
|
} |
|
} |
|
} |
|
} |
|
|