public void ParallelSchedulerTest2()
        {
            ParallelScheduler ps = new ParallelScheduler();

            ps.FillIdleSlots = true;
            int depth = 10;

            int[][] variablesUsedByNode = Util.ArrayInit(2 * depth + 1, i =>
            {
                if (i < depth)
                {
                    return(new int[] { 0 });
                }
                else if (i < 2 * depth)
                {
                    return(new int[] { i - depth });
                }
                else
                {
                    return(Util.ArrayInit(depth, j => j));
                }
            });
            ps.CreateGraph(variablesUsedByNode);
            var schedule = ps.GetScheduleWithBarriers(2);

            ParallelScheduler.WriteSchedule(schedule);
            var perThread = ps.ConvertToSchedulePerThread(schedule, 2);

            Assert.True(perThread[1][0].Length == 0);
            Assert.True(perThread[0][2].Length == 0);
        }
        public void ParallelSchedulerEmptySequenceTest()
        {
            ParallelScheduler ps    = new ParallelScheduler();
            var variablesUsedByNode = new[] { new int[] { } };

            ps.CreateGraph(variablesUsedByNode);
        }
        private int[][][] parallelScheduleTest(int numThreads, int nodeCount, out IReadOnlyList <Gaussian> xMarginal, out Gaussian shiftMarginal, out IReadOnlyList <int[]> variablesUsedByNode)
        {
            int maxParentCount = 1;

            variablesUsedByNode = GenerateVariablesUsedByNode(nodeCount, maxParentCount);
            ParallelScheduler ps = new ParallelScheduler();

            ps.CreateGraph(variablesUsedByNode);
            var schedule = ps.GetScheduleWithBarriers(numThreads);

            ParallelScheduler.WriteSchedule(schedule, true);
            var schedulePerThread = ps.ConvertToSchedulePerThread(schedule, numThreads);

            var   nodeCountVar = Variable.Observed(nodeCount).Named("nodeCount");
            Range node         = new Range(nodeCountVar).Named("node");

            node.AddAttribute(new Sequential()
            {
                BackwardPass = true
            });
            var x = Variable.Array <double>(node).Named("x");

            x[node] = Variable.GaussianFromMeanAndPrecision(0, 1).ForEach(node);
            var   parentCount = Variable.Observed(variablesUsedByNode.Select(a => a.Length).ToArray(), node).Named("parentCount");
            Range parent      = new Range(parentCount[node]).Named("parent");
            var   indices     = Variable.Observed(variablesUsedByNode.ToArray(), node, parent).Named("indices");
            var   shift       = Variable.GaussianFromMeanAndPrecision(0, 1).Named("shift");

            shift.AddAttribute(new PointEstimate());
            using (Variable.ForEach(node))
            {
                var subArray = Variable.Subarray(x, indices[node]).Named("subArray");
                using (Variable.If(parentCount[node] == 1))
                {
                    Variable.ConstrainEqualRandom(subArray[0], Gaussian.FromMeanAndVariance(0, 1));
                }
                using (Variable.If(parentCount[node] == 2))
                {
                    Variable.ConstrainEqual(subArray[0], subArray[1] + 1);
                }
                Variable.ConstrainEqualRandom(shift, new Gaussian(1, 2));
            }

            InferenceEngine engine = new InferenceEngine();

            engine.NumberOfIterations   = 2;
            engine.OptimiseForVariables = new IVariable[] { x, shift };
            var xExpected = engine.Infer(x);
            //Console.WriteLine(xExpected);
            var shiftExpected = engine.Infer(shift);

            var   threadCount      = Variable.Observed(0).Named("threadCount");
            Range thread           = new Range(threadCount).Named("thread");
            var   blockCount       = Variable.Observed(0).Named("blockCount");
            Range gameBlock        = new Range(blockCount).Named("block");
            var   gameCountInBlock = Variable.Observed(default(int[][]), thread, gameBlock).Named("GameCountInBlock");
            Range gameInBlock      = new Range(gameCountInBlock[thread][gameBlock]).Named("gameInBlock");
            var   gamesInBlock     = Variable.Observed(default(int[][][]), thread, gameBlock, gameInBlock).Named("GamesInBlock");

            node.AddAttribute(new ParallelSchedule(gamesInBlock));

            threadCount.ObservedValue      = schedulePerThread.Length;
            blockCount.ObservedValue       = (schedulePerThread.Length == 0) ? 0 : schedulePerThread[0].Length;
            gameCountInBlock.ObservedValue = Util.ArrayInit(schedulePerThread.Length, t =>
                                                            Util.ArrayInit(schedulePerThread[t].Length, b => schedulePerThread[t][b].Length));
            gamesInBlock.ObservedValue = schedulePerThread;

            var xActual = engine.Infer <IReadOnlyList <Gaussian> >(x);

            //Debug.WriteLine(xActual);
            Assert.True(xExpected.Equals(xActual));
            var shiftActual = engine.Infer <Gaussian>(shift);

            Assert.True(shiftExpected.Equals(shiftActual));

            xMarginal     = xActual;
            shiftMarginal = shiftActual;
            return(schedulePerThread);
        }