3

I'm creating a project similar to this which was created by Karl Sims. Based on the paper that Sims published, I understood that in order to create a "brain" for the creature I need to create a sort of neural network, which in this case is a directed node graph. I won't go into detail about the way the entire network works.

I need to creature neurons, which are nodes that receive some input values and produce one other value based on their functions. They can be pointed to, and point to one or more other nodes. Each neuron also has a function it uses to produce its value. The first step in creating the network is to instantiate neurons without pointers, then give each neuron a function, and then point the pointers of the neurons to its inputs (other nodes in the network). My problem is I can't link the function chosen with the number of parameters required.

For example, let's say that neurons can have these 3 functions:

    public float Sum2(float a, float b)
    {
        return a + b;
    }

    public float Mul3(float a, float b, float c)
    {
        return a * b * c;
    }

    public float Threshold(float a){
        if(a > 0.5)
            return a;
        return 0;
    }

Somewhere in the code, I need to have a class similar to this:

    class NeuronData{
        FunctionIdendifier func; // An object that points to one of the functions Sum2, Mul3, or Threshold. Through it I can reach the original method easily. 
        int numOfInputs;
    }


I thought of creating a dictionary where the keys are functions and the values are the parameters amounts, but that seems too complex, and also has room for human error.

Thanks in advance :)

Koby 27
  • 1,049
  • 1
  • 8
  • 17

2 Answers2

0

How about array as input. But it always expects float data type.

float SumN(float[] args)
{
    return args.Sum();
}

float MulN(float[] args)
{
    return args.Aggregate((s, x) => s * x);
}

float Threshold(float[] args)
{
    if (args.Length != 1)
    {
        throw new InvalidOperationException();
    }
    float value = args[0];
    return value > 0.5 ? value : 0f;
}

class NeuronData
{
    Func<float[], float> func;

    public NeuronData(Func<float[], float> func)
    {
        this.func = func;
    }
}
Posix
  • 300
  • 3
  • 14
  • Have a look at [Viewing Type Information](https://learn.microsoft.com/en-US/dotnet/framework/reflection-and-codedom/viewing-type-information) especially [ParameterInfo Class](https://learn.microsoft.com/en-us/dotnet/api/system.reflection.parameterinfo?view=netframework-4.8) – H.G. Sandhagen Feb 28 '20 at 10:08
0

I used an approach similar to @Posix, I'll post the code for the complete solution. Here 10 neurons are created and get assigned a random function out of a dictionary that includes a function as a key and the parameter amount as a value.

    class Program
    {
        static void Main(string[] args)
        {
            for(int i = 0; i < 10; i++)
            {
                Neuron n = new Neuron();                
            }

        }
    }

The function manager:

    public delegate float NeuralFunction (params float[] inputs);
    public class FunctionManager
    {
        private static Random rand = new Random();
        private static FunctionManager singleton = new FunctionManager();

        private Dictionary<NeuralFunction,int> functionDict;

        private FunctionManager() {
            functionDict = new Dictionary<NeuralFunction, int>();

            functionDict.Add(Thresh, 1);
            functionDict.Add(Sum2, 2);
            functionDict.Add(Mul3, 3);
        }

        public static FunctionManager Singleton { get { return singleton; } }


        public float Sum2(params float[] inputs)
        {
            // 2 Inputs
            if (inputs.Length != 2)
                throw new InvalidOperationException();
            float n1 = inputs[0];
            float n2 = inputs[1];
            return n1 + n2;
        }

        public float Mul3(params float[] inputs)
        {
            // 3 Inputs
            if (inputs.Length != 3)
                throw new InvalidOperationException();
            float n1 = inputs[0];
            float n2 = inputs[1];
            float n3 = inputs[2];
            return n1 * n2 * n3;
        }

        public float Thresh(params float[] inputs)
        {
            // 1 Inputs
            if (inputs.Length != 1)
                throw new InvalidOperationException();
            float n1 = inputs[0];
            if (n1 > 0.5)
                return n1;
            return 0;
        }

        public KeyValuePair<NeuralFunction, int> GetRandomFunction()
        {                        
            List<NeuralFunction> keys = Enumerable.ToList(functionDict.Keys);            
            NeuralFunction function = keys[rand.Next(0, keys.Count)];
            return new KeyValuePair<NeuralFunction, int>(function, functionDict[function]);

        }
    }    

The neuron class:

class Neuron
    {
        NeuralFunction function;
        int paramAmount;

        public Neuron()
        {
            KeyValuePair<NeuralFunction, int> keyVal = FunctionManager.Singleton.GetRandomFunction();
            function = keyVal.Key;
            paramAmount = keyVal.Value;
            MethodInfo method = function.Method;
            Console.WriteLine("-- Method: " + method.Name + "Has " + paramAmount + " Parameters");
        }
    }
Koby 27
  • 1,049
  • 1
  • 8
  • 17