Unity 机器学习代理工具包 (ML-Agents) 是一个开源项目,它使游戏和模拟能够作为训练智能代理的环境。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

240 行
7.5 KiB

using System;
using System.Collections.Generic;
namespace Unity.MLAgents
{
/// <summary>
/// An array-like object that stores up to four elements.
/// This is a value type that does not allocate any additional memory.
/// </summary>
/// <remarks>
/// This does not implement any interfaces such as IList, in order to avoid any accidental boxing allocations.
/// </remarks>
/// <typeparam name="T"></typeparam>
public struct InplaceArray<T> : IEquatable<InplaceArray<T>> where T : struct
{
private const int k_MaxLength = 4;
private readonly int m_Length;
private T m_Elem0;
private T m_Elem1;
private T m_Elem2;
private T m_Elem3;
/// <summary>
/// Create a length-1 array.
/// </summary>
/// <param name="elem0"></param>
public InplaceArray(T elem0)
{
m_Length = 1;
m_Elem0 = elem0;
m_Elem1 = new T();
m_Elem2 = new T();
m_Elem3 = new T();
}
/// <summary>
/// Create a length-2 array.
/// </summary>
/// <param name="elem0"></param>
/// <param name="elem1"></param>
public InplaceArray(T elem0, T elem1)
{
m_Length = 2;
m_Elem0 = elem0;
m_Elem1 = elem1;
m_Elem2 = new T();
m_Elem3 = new T();
}
/// <summary>
/// Create a length-3 array.
/// </summary>
/// <param name="elem0"></param>
/// <param name="elem1"></param>
/// <param name="elem2"></param>
public InplaceArray(T elem0, T elem1, T elem2)
{
m_Length = 3;
m_Elem0 = elem0;
m_Elem1 = elem1;
m_Elem2 = elem2;
m_Elem3 = new T();
}
/// <summary>
/// Create a length-3 array.
/// </summary>
/// <param name="elem0"></param>
/// <param name="elem1"></param>
/// <param name="elem2"></param>
/// <param name="elem3"></param>
public InplaceArray(T elem0, T elem1, T elem2, T elem3)
{
m_Length = 4;
m_Elem0 = elem0;
m_Elem1 = elem1;
m_Elem2 = elem2;
m_Elem3 = elem3;
}
/// <summary>
/// Construct an InplaceArray from an IList (e.g. Array or List).
/// The source must be non-empty and have at most 4 elements.
/// </summary>
/// <param name="elems"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static InplaceArray<T> FromList(IList<T> elems)
{
switch (elems.Count)
{
case 1:
return new InplaceArray<T>(elems[0]);
case 2:
return new InplaceArray<T>(elems[0], elems[1]);
case 3:
return new InplaceArray<T>(elems[0], elems[1], elems[2]);
case 4:
return new InplaceArray<T>(elems[0], elems[1], elems[2], elems[3]);
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// Per-element access.
/// </summary>
/// <param name="index"></param>
/// <exception cref="IndexOutOfRangeException"></exception>
public T this[int index]
{
get
{
if (index >= Length)
{
throw new IndexOutOfRangeException();
}
switch (index)
{
case 0:
return m_Elem0;
case 1:
return m_Elem1;
case 2:
return m_Elem2;
case 3:
return m_Elem3;
default:
throw new IndexOutOfRangeException();
}
}
set
{
if (index >= Length)
{
throw new IndexOutOfRangeException();
}
switch (index)
{
case 0:
m_Elem0 = value;
break;
case 1:
m_Elem1 = value;
break;
case 2:
m_Elem2 = value;
break;
case 3:
m_Elem3 = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
}
/// <summary>
/// The length of the array.
/// </summary>
public int Length
{
get => m_Length;
}
/// <summary>
/// Returns a string representation of the array's elements.
/// </summary>
/// <returns></returns>
/// <exception cref="IndexOutOfRangeException"></exception>
public override string ToString()
{
switch (m_Length)
{
case 1:
return $"[{m_Elem0}]";
case 2:
return $"[{m_Elem0}, {m_Elem1}]";
case 3:
return $"[{m_Elem0}, {m_Elem1}, {m_Elem2}]";
case 4:
return $"[{m_Elem0}, {m_Elem1}, {m_Elem2}, {m_Elem3}]";
default:
throw new IndexOutOfRangeException();
}
}
/// <summary>
/// Check that the arrays have the same length and have all equal values.
/// </summary>
/// <param name="lhs"></param>
/// <param name="rhs"></param>
/// <returns>Whether the arrays are equivalent.</returns>
public static bool operator ==(InplaceArray<T> lhs, InplaceArray<T> rhs)
{
return lhs.Equals(rhs);
}
/// <summary>
/// Check that the arrays are not equivalent.
/// </summary>
/// <param name="lhs"></param>
/// <param name="rhs"></param>
/// <returns>Whether the arrays are not equivalent</returns>
public static bool operator !=(InplaceArray<T> lhs, InplaceArray<T> rhs) => !lhs.Equals(rhs);
/// <summary>
/// Check that the arrays are equivalent.
/// </summary>
/// <param name="other"></param>
/// <returns>Whether the arrays are not equivalent</returns>
public override bool Equals(object other) => other is InplaceArray<T> other1 && this.Equals(other1);
/// <summary>
/// Check that the arrays are equivalent.
/// </summary>
/// <param name="other"></param>
/// <returns>Whether the arrays are not equivalent</returns>
public bool Equals(InplaceArray<T> other)
{
// See https://montemagno.com/optimizing-c-struct-equality-with-iequatable/
var thisTuple = (m_Elem0, m_Elem1, m_Elem2, m_Elem3, Length);
var otherTuple = (other.m_Elem0, other.m_Elem1, other.m_Elem2, other.m_Elem3, other.Length);
return thisTuple.Equals(otherTuple);
}
/// <summary>
/// Get a hashcode for the array.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return (m_Elem0, m_Elem1, m_Elem2, m_Elem3, Length).GetHashCode();
}
}
}