Пример #1
0
        }/**/

        // увеличиваем состояние нейрона и запускаем разряды
        // не делать async Task! так как в этом случае мы тупо встанем в зависон
        public int IncState(int state, NCoords coords)
        {
            //return Task.Run(() =>
            //{
            // счетчики потоков надо ставить в самой функции SpikeAsync так как разряды, затухания, повторения все в ней
            //Interlocked.Increment(ref NNet.Threads);

            var newState = Interlocked.Add(ref _state, state);

            // в этом месте значение _state может увеличится другим потоком, но нам как бы пофиг. либо этот либо тот процесс получат в newState значение выше порога и запустят разряд
            //Net.LogInformation(321, "Neuron IncState {coords} + {state} = {newstate}", coords, state, _state);

            if (_checkState() && _isStarted == 0)
            {
                Net.LogInformation(321, "Neuron IncState {coords} activated!!!!!", coords);

                // просто метим как активный
                IsActive = 1;

                // надо где то прописать что появился активный нейрон (пофигу елси 1 нейрон засунем в очередь несколько раз на том конце разберемся)
                Net.Queue.Enqueue(new QueueNeuron {
                    Neuron = this, Coords = coords
                });
            }

            //Interlocked.Decrement(ref NNet.Threads);
            //});
            return(newState);
        }
Пример #2
0
        public int MaxZ; // { get; set; }

        public bool Test(NCoords coords)
        {
            if (
                MinX <= coords.X && coords.X <= MaxX &&
                MinY <= coords.Y && coords.Y <= MaxY &&
                MinZ <= coords.Z && coords.Z <= MaxZ
                )
            {
                return(true);
            }
            return(false);
        }
Пример #3
0
        // тупой вариант расчета новых состояний (нарушает закон сохранения - сеть быстро "взрывается")
        private void _evalNewStates()
        {
            // пропускаем ток
            var s = 0; // суммируем скока заряда ушло (если нейрон с положительным зарядом то тут всегда будет >0, так как связи всегда положительные. и наоборот)

            foreach (var o in Output)
            {
                var coord = new NCoords(o.Neuron, Net.LenX, Net.LenY, Net.LenZ);
                var state = (int)(_state * o.WeightSum);
                s += state;
                Net.Neurons[coord.Z][coord.Y][coord.X].IncState(state, coord);
            }

            // уменьшаем свое состояние
            _decreaseState(s);
        }
Пример #4
0
        // вариант с распределением существующего заряда равномерно в зависимости от веса
        private void _evalNewStates2()
        {
            var s = _state; // _state может меняться в процессе

            // если выход всего 1, то результат (state0+state1) / 2 для обоих состояний (оно выравнивается всегда)
            #region one output
            if (Output.Count == 1)
            {
                var o     = Output[0];
                var coord = new NCoords(o.Neuron, Net.LenX, Net.LenY, Net.LenZ);
                var n     = Net.Neurons[coord.Z][coord.Y][coord.X];
                var ts    = n.State;
                if (s > 0)
                {
                    if (ts > 0)      // + => +
                    {
                        if (s <= ts) // заряд активного нейрона меньше целевого, тут ничего не должно происходить (возможно уменьшение веса связи???)
                        {
                            return;
                        }
                        //var ns = (s + ts) / 2;
                        //_state -= s - (s + ts) / 2 => _state -= (s-ts)/2
                        Interlocked.Add(ref _state, -(s - ts) / 2);
                        n.IncState((s - ts) / 2, coord);
                    }
                    else        // + => -
                    {
                    }
                }
                else
                {
                }
                return;
            }
            #endregion

            // если выходов больше, то
            foreach (var o in Output)
            {
            }
        }
Пример #5
0
        public async Task SubscribeClientAsync(HttpContext httpContext)
        {
            //_logger.LogInformation(1113, "NNetServer SubscribeClient start");

            var webSocket = await httpContext.WebSockets.AcceptWebSocketAsync();

            //Socket = socket;
            // Добавляем его в список клиентов
            LockerWS.EnterWriteLock();
            try
            {
                Clients.Add(webSocket);
            }
            finally
            {
                LockerWS.ExitWriteLock();
            }

            while (webSocket.State == WebSocketState.Open)
            {
                //_logger.LogInformation(1113, "NNetServer SubscribeClient begin action");
                try
                {
                    //var token = CancellationToken.None;
                    var buffer   = new ArraySegment <Byte>(new Byte[4096]); // не очень хорошо ограничивать вход 4 кб! расчетные модули могут посылать больше инфы за 1 раз
                    var received = await webSocket.ReceiveAsync(buffer, CancellationToken.None);

                    switch (received.MessageType)
                    {
                    case WebSocketMessageType.Text:
                        var request = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
                        //_logger.LogInformation(1113, "NNetServer SubscribeClient request = {request}", request);
                        var tmp = JsonConvert.DeserializeObject <WSRequest>(request);
                        switch (tmp.Action.ToLower())
                        {
                        // подписка на изменения в сети
                        case "subscribe":
                            if (tmp.ArgsInt.Count < 6)
                            {
                                await SendErrorAsync(webSocket, "Число аргументов ArgsInt должно быть >= 6", tmp.Action); return;
                            }
                            if (tmp.ArgsInt.Count % 6 != 0)
                            {
                                await SendErrorAsync(webSocket, "Число аргументов ArgsInt должно быть кратно 6", tmp.Action); return;
                            }

                            var val = new List <NRange>();
                            for (var i = 0; i < tmp.ArgsInt.Count; i = i + 6)
                            {
                                // обязательно проверить кто раньше первый или второй и это важно
                                // нем пох кто меньше надо найти меньший угол и больший в кубе
                                var min = new NCoords(
                                    Math.Min(tmp.ArgsInt[i + 0], tmp.ArgsInt[i + 3]),
                                    Math.Min(tmp.ArgsInt[i + 1], tmp.ArgsInt[i + 4]),
                                    Math.Min(tmp.ArgsInt[i + 2], tmp.ArgsInt[i + 5]));
                                var max = new NCoords(
                                    Math.Max(tmp.ArgsInt[i + 0], tmp.ArgsInt[i + 3]),
                                    Math.Max(tmp.ArgsInt[i + 1], tmp.ArgsInt[i + 4]),
                                    Math.Max(tmp.ArgsInt[i + 2], tmp.ArgsInt[i + 5]));

                                /*var min = new NCoords(tmp.ArgsInt[i + 0], tmp.ArgsInt[i + 1], tmp.ArgsInt[i + 2]);
                                 * var max = new NCoords(tmp.ArgsInt[i + 3], tmp.ArgsInt[i + 4], tmp.ArgsInt[i + 5]);
                                 * if (max.ToSingle(LenX, LenY) < min.ToSingle(LenX, LenY))
                                 * {
                                 *  var t = min; min = max; max = t;
                                 * }*/
                                val.Add(new NRange()
                                {
                                    MinX = min.X, MinY = min.Y, MinZ = min.Z,
                                    MaxX = max.X, MaxY = max.Y, MaxZ = max.Z
                                });
                            }

                            // доки https://docs.microsoft.com/ru-ru/dotnet/articles/standard/collections/threadsafe/how-to-add-and-remove-items
                            // очень маловероятно что 1 клиент 2 раза сможет вызвать подписку больше 1 раза в одно и то же время!
                            Subscribers.AddOrUpdate(webSocket, val, (key, existingVal) => {
                                // If this delegate is invoked, then the key already exists.
                                // Here we make sure the city really is the same city we already have.
                                // (Support for multiple cities of the same name is left as an exercise for the reader.)
                                existingVal.AddRange(val);

                                return(existingVal);
                            });

                            // сразу отправим полные данные о выбранных нейронах
                            await SendNeuronsAsync(webSocket, val, tmp.Action);

                            break;

                        // полная отписка
                        case "unsubscribe":
                            List <NRange> tmp1;
                            Subscribers.TryRemove(webSocket, out tmp1);

                            await SendMessageAsync(webSocket, "OK", tmp.Action);

                            break;

                        // запрос конфигурации сети
                        case "getnetconfig":
                            await SendConfigAsync(webSocket, tmp.Action);

                            break;

                        case "start":
                            Start();
                            await SendMessageAsync(webSocket, "OK", tmp.Action);

                            break;

                        case "stop":
                            Stop();
                            await SendMessageAsync(webSocket, "OK", tmp.Action);

                            break;

                        case "setinput":
                            if (tmp.ArgsInt.Count != 7)
                            {
                                await SendErrorAsync(webSocket, "Число аргументов ArgsInt должно быть = 7", tmp.Action); return;
                            }

                            var inputs = new Dictionary <NCoords, int>();

                            {
                                var i = 0;
                                // обязательно проверить кто раньше первый или второй и это важно
                                // нам пох кто меньше надо найти меньший угол и больший в кубе
                                var min = new NCoords(
                                    Math.Min(tmp.ArgsInt[i + 0], tmp.ArgsInt[i + 3]),
                                    Math.Min(tmp.ArgsInt[i + 1], tmp.ArgsInt[i + 4]),
                                    Math.Min(tmp.ArgsInt[i + 2], tmp.ArgsInt[i + 5]));
                                var max = new NCoords(
                                    Math.Max(tmp.ArgsInt[i + 0], tmp.ArgsInt[i + 3]),
                                    Math.Max(tmp.ArgsInt[i + 1], tmp.ArgsInt[i + 4]),
                                    Math.Max(tmp.ArgsInt[i + 2], tmp.ArgsInt[i + 5]));

                                for (var z = min.Z; z <= max.Z; z++)
                                {
                                    for (var y = min.Y; y <= max.Y; y++)
                                    {
                                        for (var x = min.X; x <= max.X; x++)
                                        {
                                            inputs[new NCoords(x, y, z)] = tmp.ArgsInt[i + 6];
                                        }
                                    }
                                }
                            }

                            SetInputs(inputs);
                            await SendMessageAsync(webSocket, "OK", tmp.Action);

                            break;
                        }
                        break;
                    }
                }
                catch (Exception e)
                {
                    //Error = e;
                    //_logger.LogInformation(1113, "NNetServer SubscribeClient error {error}.", e.Message);
                    await SendErrorAsync(webSocket, e.Message, null);
                }
                //_logger.LogInformation(1113, "NNetServer SubscribeClient end action");
            }/**/

            //_logger.LogInformation(1113, "NNetServer SubscribeClient before removing");

            LockerWS.EnterWriteLock();
            try
            {
                Clients.Remove(webSocket);
            }
            finally
            {
                LockerWS.ExitWriteLock();
            }
            List <NRange> tmp2;

            Subscribers.TryRemove(webSocket, out tmp2);
            //_logger.LogInformation(1113, "NNetServer SubscribeClient end");
        }
Пример #6
0
        // создаем выходные связи для нейрона (рандомно)
        private List <NRelation> _createOutputForNeuron(int x, int y, int z)
        {
            if (NEED_STAT_WEIGHT)
            {
                MinWeight = 0;
                MaxWeight = 0;
            }

            var output = new List <NRelation>();
            // по оси Z распределение норм тут не надо замыкать последний слой на первый
            var minZ = z - MAX_DEEP_RELATIONS_Z; if (minZ < 1)
            {
                minZ = 1;
            }
            var maxZ = z + MAX_DEEP_RELATIONS_Z; if (maxZ > LenZ - 1)
            {
                maxZ = LenZ - 1;
            }

            // а вот по икс и игрек хотелось бы замкнуть первые нейроны на последние
            var minY = y - maxDeepRelationsY; /*if (minY < 0) minY = 0;*/ var maxY = y + maxDeepRelationsY; // if (maxY > LenY - 1) maxY = LenY - 1;
            var minX = x - maxDeepRelationsX; /*if (minX < 0) minX = 0;*/ var maxX = x + maxDeepRelationsX; // if (maxX > LenX - 1) maxX = LenX - 1;

            /*if (z==0 && y==1 && x==2)
             *  _logger.LogInformation(2111, "NNet _createOutputForNeuron  {x}-{xx} {y}-{yy} {z}-{zz}", minX, maxX, minY, maxY, minZ, maxZ);
             * /**/
            for (var zz = minZ; zz <= maxZ; zz++) // первый слой входы (входы исключительно на другие слои)
            {
                for (var yy = minY; yy <= maxY; yy++)
                {
                    for (var xx = minX; xx <= maxX; xx++)
                    {
                        // замыкания по оси икс и игрек
                        var yyy = yy; var xxx = xx;
                        if (yy < 0)
                        {
                            yyy = LenY + yy;
                        }
                        if (yy > LenY - 1)
                        {
                            yyy = yy - (LenY);
                        }
                        if (xx < 0)
                        {
                            xxx = LenX + xx;
                        }
                        if (xx > LenX - 1)
                        {
                            xxx = xx - (LenX);
                        }

                        // связь на себя не допускаем, тока косвенная - через другие нейроны
                        if (x == xxx && yyy == y && z == zz)
                        {
                            continue;
                        }

                        var coords = new NCoords(xxx, yyy, zz);
                        var o      = new NRelation()
                        {
                            Neuron = coords.ToSingle(LenX, LenY), Weight = _rand.NextFloat(MIN_INIT_WEIGHT, MAX_INIT_WEIGHT), WeightChange = 0
                        };
                        if (NEED_STAT_WEIGHT)
                        {
                            // здесь не надо юзать WeightSum так как WeightChange==0
                            if (MinWeight > o.Weight)
                            {
                                MinWeight = o.Weight;
                            }
                            if (MaxWeight < o.Weight)
                            {
                                MaxWeight = o.Weight;
                            }
                        }

                        /*if (z == 0 && y == 1 && x == 2)
                         * {
                         *  _logger.LogInformation(1111, "NNet _createOutputForNeuron for ({x}, {y}, {z}) => {n} ({xx}, {yy}, {zz})", x, y, z, (new NCoords(xxx, yyy, zz)).ToSingle(LenX, LenY), xxx, yyy, zz);
                         * }/**/

                        o.SetNeuron(Neurons[zz][yyy][xxx]);

                        output.Add(o);
                    }
                }
            }

            return(output);
        }