private void VaildateSubstrateNodes(List<SubstrateNodeSet> nodeSetList)
{
// Baseline validation tests. There should be at least two nodesets (input and output sets), and each of those must have at least one node.
if(nodeSetList.Count < 2) {
throw new ArgumentException("Substrate requires a minimum of two NodeSets - one each for input and output nodes.");
}
// Input nodes.
if(nodeSetList[0].NodeList.Count == 0) {
throw new ArgumentException("Substrate input nodeset must have at least one node.");
}
if(nodeSetList[1].NodeList.Count == 0) {
throw new ArgumentException("Substrate output nodeset must have at least one node.");
}
// Check for duplicate IDs or ID zero (reserved for bias node).
Dictionary<uint,object> idDict = new Dictionary<uint,object>();
foreach(SubstrateNodeSet nodeSet in nodeSetList)
{
foreach(SubstrateNode node in nodeSet.NodeList)
{
if(0u == node._id) {
throw new ArgumentException("Substrate node with invalid ID of 0 (reserved for bias node).");
}
if(idDict.ContainsKey(node._id)) {
throw new ArgumentException(string.Format("Substrate node with duplicate ID of [{0}]", node._id));
}
idDict.Add(node._id, null);
}
}
// Check ID ordering.
// Input node IDs should be contiguous and ordered sequentially after the bias node with ID 0.
SubstrateNodeSet inputNodeSet = nodeSetList[0];
int count = inputNodeSet.NodeList.Count;
int expectedId = 1;
for(int i=0; i<count; i++, expectedId++)
{
if(inputNodeSet.NodeList[i]._id != expectedId) {
throw new ArgumentException(string.Format("Substrate input node with unexpected ID of [{0}]. Ids should be contiguous and starting from 1.", inputNodeSet.NodeList[i]._id));
}
}
// Output node IDs should be contiguous and ordered sequentially after the last input ID.
SubstrateNodeSet outputNodeSet = nodeSetList[1];
count = outputNodeSet.NodeList.Count;
for(int i=0; i<count; i++, expectedId++)
{
if(outputNodeSet.NodeList[i]._id != expectedId) {
throw new ArgumentException(string.Format("Substrate output node with unexpected ID of [{0}].", outputNodeSet.NodeList[i]._id));
}
}
// Hidden node IDs don't have to be contiguous but must have IDs greater than all of the input and output IDs.
int setCount = nodeSetList.Count;
for(int i=2; i<setCount; i++)
{
SubstrateNodeSet hiddenNodeSet = nodeSetList[i];
foreach(SubstrateNode node in hiddenNodeSet.NodeList)
{
if(node._id < expectedId) {
throw new ArgumentException(string.Format("Substrate hidden node with unexpected ID of [{0}] (must be greater than the last output node ID [{1}].",
hiddenNodeSet.NodeList[i]._id, expectedId-1));
}
}
}
}