public void TestFourSequences()
        {
            List <Object> sequence0 = new List <Object>(new Integer[] { 7, 12, 16 });
            List <Object> sequence1 = new List <Object>(new Integer[] { 3, 4, 5 });
            List <Object> sequence2 = new List <Object>(new Integer[] { 3, 3, 4, 5 });
            List <Object> sequence3 = new List <Object>(new Integer[] { 3, 3, 4, 5 });

            List <Pair <List <Object>, Func <Object, Integer> > > list = new List <Pair <List <object>, Func <object, Integer> > >();

            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence0, m_Times1Fnc));
            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence1, m_Times3Fnc));
            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence2, m_Times4Fnc));
            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence3, m_Times5Fnc));

            GroupBy2 <Integer> m = GroupBy2 <Integer> .of(list.ToArray());

            List <Pair <Object, List <List <Object> > > > expectedValues = new List <Pair <Object, List <List <Object> > > >(
                new Pair <Object, List <List <Object> > >[]
            {
                new Pair <Object, List <List <Object> > >(7, new List <List <Object> >(getListOfList(getList(7), getList(m_None), getList(m_None), getList(m_None)))),
                new Pair <Object, List <List <Object> > >(9, new List <List <Object> >(getListOfList(getList(m_None), getList(3), getList(m_None), getList(m_None)))),
                new Pair <Object, List <List <Object> > >(12, new List <List <Object> >(getListOfList(getList(12), getList(4), getList(3, 3), getList(m_None)))),
                new Pair <Object, List <List <Object> > >(15, new List <List <Object> >(getListOfList(getList(m_None), getList(5), getList(m_None), getList(3, 3)))),
                new Pair <Object, List <List <Object> > >(16, new List <List <Object> >(getListOfList(getList(16), getList(m_None), getList(4), getList(m_None)))),
                new Pair <Object, List <List <Object> > >(20, new List <List <Object> >(getListOfList(getList(m_None), getList(m_None), getList(5), getList(4)))),
                new Pair <Object, List <List <Object> > >(25, new List <List <Object> >(getListOfList(getList(m_None), getList(m_None), getList(m_None), getList(5)))),
            });

            assertResults(m, expectedValues);
        }
        public void TestOneSequence()
        {
            List <Object> sequence0 = new List <Object>(new Integer[] { 7, 12, 12, 16 });

            List <Pair <List <Object>, Func <Object, Integer> > > list = new List <Pair <List <object>, Func <object, Integer> > >();

            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence0, m_Times1Fnc));
            GroupBy2 <Integer> m = GroupBy2 <Integer> .of(list.ToArray());

            List <Pair <Object, List <List <Object> > > > expectedValues = new List <Pair <Object, List <List <Object> > > >(
                new Pair <Object, List <List <Object> > >[]
            {
                new Pair <Object, List <List <Object> > >(7, getListOfList(getList(7))),
                new Pair <Object, List <List <Object> > >(12, getListOfList(getList(12, 12))),
                new Pair <Object, List <List <Object> > >(16, getListOfList(getList(16))),
            });

            assertResults(m, expectedValues);
        }
        public void TestTwoSequences2()
        {
            List <Object> sequence0 = new List <Object>(new Object[] { new Integer(9) });
            List <Object> sequence1 = new List <Object>(new Object[] { new Integer(3), new Integer(4) });

            List <Pair <List <Object>, Func <Object, Integer> > > list = new List <Pair <List <object>, Func <object, Integer> > >();

            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence0, m_Times1Fnc));
            list.Add(new Pair <List <Object>, Func <Object, Integer> >(sequence1, m_Times3Fnc));
            GroupBy2 <Integer> group = GroupBy2 <Integer> .of(list.ToArray());

            List <Pair <Object, List <List <Object> > > > expectedValues = new List <Pair <Object, List <List <Object> > > >(
                new Pair <Object, List <List <Object> > >[]
            {
                new Pair <Object, List <List <Object> > >(9, getListOfList(getList(new Integer(9)), getList(3))),
                new Pair <Object, List <List <Object> > >(12, getListOfList(getList(m_None), getList(4))),
            });

            assertResults(group, expectedValues);
        }
        /**
         * Calculate the active cells, using the current active columns and dendrite
         * segments. Grow and reinforce synapses.
         *
         * <pre>
         * Pseudocode:
         *   for each column
         *     if column is active and has active distal dendrite segments
         *       call activatePredictedColumn
         *     if column is active and doesn't have active distal dendrite segments
         *       call burstColumn
         *     if column is inactive and has matching distal dendrite segments
         *       call punishPredictedColumn
         *
         * </pre>
         *
         * @param conn
         * @param activeColumnIndices
         * @param learn
         */

        protected ComputeCycle ActivateCells(Connections conn, int[] activeColumnIndices, bool learn)
        {
            ComputeCycle cycle = new ComputeCycle();

            ColumnData activeColumnData = new ColumnData();

            List <Cell> prevActiveCells = conn.getActiveCells();
            List <Cell> prevWinnerCells = conn.getWinnerCells();

            // The list of active columns.
            List <Column> activeColumns = new List <Column>();

            foreach (var indx in activeColumnIndices.OrderBy(i => i))
            {
                activeColumns.Add(conn.getColumn(indx));
            }

            //Func<Object, Column> segToCol = segment => ((DistalDendrite)segment).getParentCell().getParentColumnIndex();

            Func <Object, Column> segToCol = (segment) =>
            {
                var colIndx   = ((DistalDendrite)segment).GetParentCell().getParentColumnIndex();
                var parentCol = this.connections.getMemory().GetColumn(colIndx);
                return(parentCol);
            };

            Func <object, Column> times1Fnc = x => (Column)x;

            var list = new Pair <List <object>, Func <object, Column> > [3];

            list[0] = new Pair <List <object>, Func <object, Column> >(Array.ConvertAll(activeColumns.ToArray(), item => (object)item).ToList(), times1Fnc);
            list[1] = new Pair <List <object>, Func <object, Column> >(Array.ConvertAll(conn.getActiveSegments().ToArray(), item => (object)item).ToList(), segToCol);
            list[2] = new Pair <List <object>, Func <object, Column> >(Array.ConvertAll(conn.getMatchingSegments().ToArray(), item => (object)item).ToList(), segToCol);

            GroupBy2 <Column> grouper = GroupBy2 <Column> .of(list);

            double permanenceIncrement = conn.HtmConfig.PermanenceIncrement;
            double permanenceDecrement = conn.HtmConfig.PermanenceDecrement;

            //
            // Grouping by columns, which have active and matching segments.
            foreach (var tuple in grouper)
            {
                Console.Write(":");
                activeColumnData = activeColumnData.Set(tuple);

                if (activeColumnData.IsExistAnyActiveCol(cIndexofACTIVE_COLUMNS))
                {
                    // If there are some active segments on the column already...
                    if (activeColumnData.ActiveSegments != null && activeColumnData.ActiveSegments.Count > 0)
                    {
                        Debug.Write(".");

                        List <Cell> cellsOwnersOfActSegs = ActivatePredictedColumn(conn, activeColumnData.ActiveSegments,
                                                                                   activeColumnData.MatchingSegments, prevActiveCells, prevWinnerCells,
                                                                                   permanenceIncrement, permanenceDecrement, learn);

                        foreach (var item in cellsOwnersOfActSegs)
                        {
                            cycle.ActiveCells.Add(item);
                            cycle.WinnerCells.Add(item);
                        }

                        //foreach (var item in cellsOwnersOfActSegs)
                        //{
                        //    cycle.WinnerCells.Add(item);
                        //}
                    }
                    else
                    {
                        Debug.Write("B.");
                        //
                        // If no active segments are detected (start of learning) then all cells are activated
                        // and a random single cell is chosen as a winner.
                        BurstingResult burstingResult = BurstColumn(conn, activeColumnData.Column(), activeColumnData.MatchingSegments,
                                                                    prevActiveCells, prevWinnerCells, permanenceIncrement, permanenceDecrement, conn.getRandom(),
                                                                    learn);

                        //
                        // Here we activate all cells by putting them to list of active cells.
                        foreach (var item in burstingResult.Cells)
                        {
                            cycle.ActiveCells.Add(item);
                        }

                        cycle.WinnerCells.Add((Cell)burstingResult.BestCell);
                    }
                }
                else
                {
                    if (learn)
                    {
                        punishPredictedColumn(conn, activeColumnData.ActiveSegments, activeColumnData.MatchingSegments,
                                              prevActiveCells, prevWinnerCells, conn.getPredictedSegmentDecrement());
                    }
                }
            }


            //int[] arr = new int[cycle.winnerCells.Count];
            //int count = 0;
            //foreach (Cell activeCell in cycle.winnerCells)
            //{
            //    arr[count] = activeCell.Index;
            //    count++;
            //}

            return(cycle);
        }