locked
3d jagged array problem RRS feed

  • Question

  • Hi,

    I have two questions regarding to defining a jagged array with depth 3. I used the code in this post for making an array of array of arrays:

    https://social.microsoft.com/Forums/en-US/d5db1bbc-b209-438b-a155-e0bfa5c756d7/creating-array-of-array-of-array-of-variables-migrated-from-communityresearchmicrosoftcom?forum=infer.net

    But I get this error for the same code: 

    Error    1    The best overloaded method match for 'MicrosoftResearch.Infer.Models.Variable.Array<bool>(MicrosoftResearch.Infer.Models.Range, MicrosoftResearch.Infer.Models.Range)' has some invalid arguments   

    Error    2    Argument 1: cannot convert from 'MicrosoftResearch.Infer.Models.VariableArray<MicrosoftResearch.Infer.Models.VariableArray<bool>,bool[][]>' to 'MicrosoftResearch.Infer.Models.Range'   

    Can anyone let me know how can I resolve this?

    My second question is:

    When I have a 3d jagged array like above, and I have another 2d jagged array with exactly the same structure as two internal (middle and internal) arrays as a 3d jagged array, how can I write the same loop over these two different structures. For example I mean:

    // assuming variables are called jag2d and jag3d
    using (Variable.ForEach(outer3)) {
       using (Variable.ForEach(middle3)) {
          using (Variable.ForEach(inner3)) {
             jag3d[outer3][middle3][outer3] = Variable.Discrete(jag2d[outer2][inner2]);  
            }
          }
       }

    Here I know that middle3 and inner3 iterate over the same structure as outer2 and middle2, but I cant make a clone or some other thing to show it. I don't understand how is it possible to define it. Your help is appreciated :)

    * This is because I need a matrix, in which each element comes from a mixture of gaussians.

    Thursday, October 9, 2014 11:32 PM

Answers

  • You can use the same ranges as follows:

    var mixtureMeans = Variable.Array(Variable.Array(Variable.Array<double>(k), wRange), nodeRange);

    • Marked as answer by Capli19 Wednesday, October 15, 2014 3:16 PM
    Wednesday, October 15, 2014 2:12 PM
    Owner

All replies

  • I've updated the old thread for the current version of Infer.NET.  I don't understand the second question.  Maybe you can write out in words (or math) how you want to fill in the entries of jag3d.
    Friday, October 10, 2014 12:12 PM
    Owner
  • Thanks Tom.

    My problem is that instead of a single variable coming from a mixture, I have a matrix in which each element come from a mixture of Gaussians. Each element has it's own mixture components defined. 

    If we have a set of nodes, and for each node a set of incoming edges, this would be a matrix of the network.

    This is already a 2d jagged array. But when I want to drive the data from mixtures, I need another dimension for mixture components.

    So it will be a 3d jagged array for mixture precision, mean and also for data.

    I'm using this data further to multiply it by node values defined on range parameters (wRange and nodeRange).

    My problem is that this 2d jagged arrays ranges cannot be defined in compatible with two internal ranges of a 3d jagged array, so that I would be able to use loops over them and multiply them. These ranges are defined separately.

    In my code below I have shown a part of my code (I hope this is not so long and is readable enough):

    	    Range nodeRange = new Range(numberOfNodes).Named("nodeRange");
    
                //creating weight matrix for our network 
    			//ppiIndices shows for each node, which incomming edges exist (so we need a jagged array here, since not all nodes have all edges)
                int[] wsizes = new int[ppiIndices.Length];
                for (int i = 0; i < ppiIndices.Length; i++)
                {
                    wsizes[i] = ppiIndices.ElementAt(i).Length;
                }
                VariableArray<int> wsizesVar = Variable.Constant(wsizes, nodeRange).Named("wsizes");
                Range wRange = new Range(wsizesVar[nodeRange]).Named("wRange");
                var wIndices = Variable.Array(Variable.Array<int>(wRange), nodeRange).Named("wIndices");
                wIndices.ObservedValue = ppiIndices;
    
    			// each element of weight matrix comes from a mixture of two gaussians
    			// so instead of weight variable in the mixture of Gaussians example I need a weight matrix:
                VariableArray<VariableArray<Vector>, Vector[][]> weightMatrix =
                    Variable.Array(Variable.Array<Vector>(wRange), nodeRange).Named("mixtureWeight");
                using (ForEachBlock firstBlock = Variable.ForEach(nodeRange))
                {
                    using (ForEachBlock secondBlock = Variable.ForEach(wRange))
                    {
                        weightMatrix[nodeRange][wRange] = Variable.Dirichlet(mixtureRange, new double[] { 1, 1 }).Named("weights");
                    }
                }
                
    			// mixture on two gaussians -> mixtureRange
    			Range mixtureRange = new Range(2).Named("mixtureRange");                        
    			
                // outerRange = mixtureRange
                VariableArray<int> middleSizes = Variable.Constant(new int[] { nodeRange.SizeAsInt, nodeRange.SizeAsInt }, mixtureRange).Named("nodeRangeSize");
                Range middleNodeRange = new Range(middleSizes[mixtureRange]).Named("middleNodesRange");
                int[][] innerWsizes = new int[nodeRange.SizeAsInt][];
                for (int i = 0; i < innerWsizes.Length; i++)
                {
                    innerWsizes[i] = new int[wsizes.Length];
                    for (int j = 0; j < wsizes.Length; j++) { 
                        innerWsizes[i][j] = wsizes[j];
                    }
                }
                var innerSizes = Variable.Constant(innerWsizes, mixtureRange, middleNodeRange).Named("innerSizes");
                Range innerWRange = new Range(innerSizes[mixtureRange][middleNodeRange]).Named("innerWRange");
                
                var mixtureMeans = Variable.Array(Variable.Array(Variable.Array<double>(innerWRange), middleNodeRange), mixtureRange).Named("mixtureMeans");
                mixtureMeans[mixtureRange][middleNodeRange][innerWRange] =  Variable<double>.Random(mixtureMeanPrior).ForEach(mixtureRange,middleNodeRange,innerWRange);
                
                var mixturePrecs = Variable.Array(Variable.Array(Variable.Array<double>(innerWRange), middleNodeRange), mixtureRange).Named("mixturePrecs");
                mixturePrecs[mixtureRange][middleNodeRange][innerWRange] =  Variable<double>.Random(mixturePrecPrior).ForEach(mixtureRange,middleNodeRange,innerWRange);
                
                // mixture data 
                VariableArray<VariableArray<double>, double[][]>[] mixtureData = new
                    VariableArray<VariableArray<double>, double[][]>[numberOfTimeSteps];
                VariableArray<VariableArray<int>, int[][]>[] z = new VariableArray<VariableArray<int>, int[][]>[numberOfTimeSteps];            
    
    			
    			// The problem arises here!
    			// I think it's a problem since my loop is on wRange and nodeRange 
    			// but mixtureMeans and mixturePrecisions are defined as 3d jagged array 
    			// the internal and middle ranges of these 3d jagged arrays should be the same as the inner and outer ranges on weightMatrix
    			// but it is not . I cant use a clone or something else to relate these 
    			// The error is at the specified line below switch statement:
                for (int i = 0; i < numberOfTimeSteps; i++)
                {
                    mixtureData[i] = Variable.Array(Variable.Array<double>(wRange), nodeRange).Named("mixturePrecs" + i);
                    z[i] = Variable.Array(Variable.Array<int>(wRange), nodeRange).Named("z" + i);
                    using (ForEachBlock firstBlock = Variable.ForEach(nodeRange))
                    {
                        using (ForEachBlock secondBlock = Variable.ForEach(wRange))
                        {                        
                            z[i][nodeRange][wRange] = Variable.Discrete(weightMatrix[nodeRange][wRange]);
                            using (Variable.Switch(z[i][nodeRange][wRange]))
                            {
    							/*!!!!!!!! Error in this section: Array elements cannot have different definition types*/
                                mixtureData[i][nodeRange][wRange] = Variable.GaussianFromMeanAndPrecision(
                                    mixtureMeans[z[i][nodeRange][wRange]][middleNodeRange][innerWRange], mixturePrecs[z[i][nodeRange][wRange]][middleNodeRange][innerWRange]
                                    );
                            }
    
    
                        }
                    }
                }

    Saturday, October 11, 2014 12:14 AM
  • It is still not clear what you want.  Let's try a different approach.  If you were writing ordinary C# code to draw a sample of mixtureData, what would it look like?
    Sunday, October 12, 2014 4:24 PM
    Owner
  • I have a dataset generated from a biological network, for which I want to drive weights. Each weight (Wij) is a mixture of two Gaussian (spike-and-slab) for generating a sparse posterior.

    For each weight, my data is the data from different time points. value of Node i  in time t is related to weighted sum of other nodes - all j s - in time t-1.

    This is how the data is generated. value of node i in time t is equal to the weighted sum of all values of j nodes in time t-1.

    each Wij comes from a mixture of two Gaussians (So I have N (number of nodes) times the number of existing edges weight variables, each coming from a mixture of tow Gaussians - and these mixtures are not dependent on each other). and observed values are related to network node values (not directly the weights themselves).

    So I have a weight matrix in which each element comes from a mixture of Gaussians.

    I'm going to write a small code for what I mean, then I'll post it here.

    Monday, October 13, 2014 8:34 AM
  • Hi again. For completing the description above, I have written a code here shortly. I have more dimensions in my data. But I think if I solve this problem, I can extend the case for my implementation.

    I have a 2d jagged array and a 3d jagged array (inner and middle ranges in 3d jagged array is the same as outer and inner ranges in 2d one. But I cannot relate them - I mean using something like clone for single dimension ranges). I need to use a loop over innerRange and middleRange of the 3djagged array which works also with outer and inner ranges in my 2d jagged array.

    Thanks a lot in advance.

    public void Run()
            {
    
                int numberOfNodes = 8; 
                // there are some candidate edges for each node,
                // we just want to choose between these edges by learning edge weights
                // weights of edges comes from a mixture (spike and slab)
                // if the spike is weighted more, then this edge would be considered in final inferred network
                // if the slab is weighted more, this edge is not considered in final inferred network.
                int[][] potentialEdges = new int[][]{
                    new int[] {1,2,3}, new int[] {0, 2,3,4,5}, new int[]{1,2,4, 5}, new int[]{1,4,5,6}, new int[]{0, 1,3, 5,6,7}, 
                    new int[]{4,6,7} , new int[]{3,4,5,7},  new int[]{4,5,6}
                };
    
                // Define a range for the number of mixture components
                Range k = new Range(2).Named("k");
                Range nodeRange = new Range(numberOfNodes).Named("nodeRange");
    
                // 
                int[] wsizes = new int[potentialEdges.Length];
                for (int i = 0; i < potentialEdges.Length; i++)
                {
                    wsizes[i] = potentialEdges.ElementAt(i).Length;
                }
                VariableArray<int> wsizesVar = Variable.Constant(wsizes, nodeRange).Named("wsizes");
                Range wRange = new Range(wsizesVar[nodeRange]).Named("wRange");
                var wIndices = Variable.Array(Variable.Array<int>(wRange), nodeRange).Named("wIndices");
                wIndices.ObservedValue = potentialEdges;
    
                // implimenting weight variable in Gaussian mixture exapmle, but for a weight matrix.
                // we have a matrix, in which each element is a weight for the corresponding edge
                VariableArray<VariableArray<Vector>, Vector[][]> weightMatrix =
                    Variable.Array(Variable.Array<Vector>(wRange), nodeRange).Named("mixtureWeight");
                using (ForEachBlock firstBlock = Variable.ForEach(nodeRange))
                {
                    using (ForEachBlock secondBlock = Variable.ForEach(wRange))
                    {
                        weightMatrix[nodeRange][wRange] = Variable.Dirichlet(k, new double[] { 1, 1 }).Named("weights");
                    }
                }
    
                // now creating means and precs variables for weightMatrix
                // outerRange = k
                VariableArray<int> middleSizes = Variable.Constant(new int[] { nodeRange.SizeAsInt, nodeRange.SizeAsInt }, k).Named("middleSizes");
                Range middleNodeRange = new Range(middleSizes[k]).Named("middleNodesRange");
                int[][] innerWsizes = new int[nodeRange.SizeAsInt][];
                for (int i = 0; i < innerWsizes.Length; i++)
                {
                    innerWsizes[i] = new int[wsizes.Length];
                    for (int j = 0; j < wsizes.Length; j++)
                    {
                        innerWsizes[i][j] = wsizes[j];
                    }
                }
                var innerSizes = Variable.Constant(innerWsizes, k, middleNodeRange).Named("innerSizes");
                Range innerWRange = new Range(innerSizes[k][middleNodeRange]).Named("innerWRange");
    
                Variable<Gaussian> mixtureMeanPrior = Variable.New<Gaussian>().Named("mixtureMeanPrior");
                Variable<Gaussian> mixturePrecPrior = Variable.New<Gaussian>().Named("mixturePrecisionPrior");
    
                var mixtureMeans = Variable.Array(Variable.Array(Variable.Array<double>(innerWRange), middleNodeRange), k).Named("mixtureMeans");
                mixtureMeans[k][middleNodeRange][innerWRange] = Variable<double>.Random(mixtureMeanPrior).ForEach(k, middleNodeRange, innerWRange);
    
                var mixturePrecs = Variable.Array(Variable.Array(Variable.Array<double>(innerWRange), middleNodeRange), k).Named("mixturePrecs");
                mixturePrecs[k][middleNodeRange][innerWRange] = Variable<double>.Random(mixturePrecPrior).ForEach(k, middleNodeRange, innerWRange);
    
                // defining data : since we need indices t and t-1, it is not possible to use Range for t dimension
                // define t as usual dimension (csharp array, not variableArray)
                //Range timeRange = new Range(300).Named("timeRange");
                int time = 300;
                VariableArray<VariableArray<int>, int[][]>[] z = new VariableArray<VariableArray<int>, int[][]>[time];            
                // if we have t time points, then there would be t-1 data related to weights between every two consequence time point:
                VariableArray<VariableArray<double>,double[][]>[] weightMixtureData = new VariableArray<VariableArray<double>,double[][]>[time-1]; 
                for (int t = 0; t < time-1; t++) {
                    // !!!!!!!!!!!!!!!
                    // here I can't use innerWRange (defined for range over w elements in 3djagged arrays above) and I should use wRange (which is defined to be used in 2d jagged array) instead.
                    // because weightMixtureData[t] is a 2d jagged Array
                    // but the loop can be just over one of them (the inner and middle ranges of the 3djagged array / OR / The outer and inner ranges in 2d jagged array).... 
                    // * my 2d jagged array is: weightMixtureData[t]
                    // the question is how can I relate wRange to innerWRange (I need something like clone() function)
                    weightMixtureData[t] = Variable.Array(Variable.Array<double>(wRange), nodeRange).Named("weightMixtureData" + t);
                    z[t] = Variable.Array(Variable.Array<int>(wRange), nodeRange).Named("z_" + t);
                    z[t][nodeRange][wRange] = Variable.Discrete(weightMatrix[nodeRange][wRange]);
                    using (Variable.ForEach(nodeRange))
                    {
                        using (Variable.ForEach(wRange))
                        {
                            using (Variable.Switch(z[t][nodeRange][wRange]))
                            {
                                // error here: Array elements cannot have different definition types
                                weightMixtureData[t][nodeRange][wRange] = Variable.GaussianFromMeanAndPrecision(
                                    mixtureMeans[z[t][nodeRange][wRange]][middleNodeRange][innerWRange], mixturePrecs[z[t][nodeRange][wRange]][middleNodeRange][innerWRange]
                                    );
                            }
                        }
                    }
                }
    
    
    
                
                // time series variable: an array of VariableArrays (array represents time points, variableArray represent nodes)
                var timeSeriesVariable = new VariableArray<double>[time];
                for (int i = 0; i < time; i++)
                    timeSeriesVariable[i] = Variable<double>.Array(nodeRange).Named("timeSeries_" + i);
                // observed data for this time series
                double[][] timeSeriesDataObservation = GenerateTimeSeriesData(time, numberOfNodes);
    
                for (int t = 1; t < time; t++ ) {
                    using (ForEachBlock firstBlock = Variable.ForEach(nodeRange)) {
                        // find subarray of nodes affecting on current node_i (using wIndices matrix which we had for potentialEdge candidates)
                        VariableArray<double> innerProductArray = Variable.Array<double>(wRange).Named("weightSum_" + t);
                        VariableArray<double> nodeSubarray = Variable.Subarray(timeSeriesVariable[t - 1], wIndices[nodeRange]).Named("nodeSubarray_" + t);
                        innerProductArray[wRange] = (weightMixtureData[t-1][nodeRange][wRange] * nodeSubarray[wRange]).Named("weightSumArray_" + t);
                        Variable<double> weightedSum = Variable.Sum(innerProductArray).Named("weightedSum_" + t);
                        Variable<double> noise = Variable<double>.GaussianFromMeanAndPrecision(0, 1).Named("noise_" + t);
                        timeSeriesVariable[t][nodeRange] = (weightedSum + noise).Named("timeSeries_" + t + "_" + nodeRange);
                    }
                }
    
    
                InferenceEngine ie = new InferenceEngine();
                ie.ShowFactorGraph = true;
                ie.Algorithm = new ExpectationPropagation();
                if (!(ie.Algorithm is VariationalMessagePassing))
                {
                    Console.WriteLine("Dist over pi=" + ie.Infer(weightMatrix));
                    Console.WriteLine("Dist over means=\n" + ie.Infer(mixtureMeans));
                    Console.WriteLine("Dist over precs=\n" + ie.Infer(mixturePrecs));
                }
                else
                    Console.WriteLine("This example is not supported by Variational Message Passing");
    
    
    
            }
    
            public double[][] GenerateTimeSeriesData(int nData, int numberOfNodes)
            {
                double trueM1 = 5;
                double trueM2 = 0;
                double trueP1 = 1;
                double trueP2 = 1;
                Gaussian spikeVG1 = Gaussian.FromMeanAndPrecision(trueM1, trueP1); // spike
                Gaussian slabVG2 = Gaussian.FromMeanAndPrecision(trueM2, trueP2); // slab
    
                // true edges in the network
                // trueEdges[i] lists the incomming edges from other j nodes to i. 
                int[][] trueEdges = new int[][]{
                    new int[] {1}/*example: there is an edge from node 1 to node 0*/, 
                    new int[] {0, 2,3}, new int[]{1}, new int[]{1,4}, new int[]{3, 5,6,7}, 
                    new int[]{4} , new int[]{4},  new int[]{4}
                };
    
                //int numberOfNodes = windices.Length;
                double[][] timeSeriesData = new double[nData][];
                Rand.Restart(12347);
    
                // generate random data for row 0
                var r = new Random();
                timeSeriesData[0] = new double[numberOfNodes];
                for(int i=0; i<numberOfNodes; i++) {
                    timeSeriesData[0][i] = r.NextDouble();
                }
    
                for (int t = 1; t < nData; t++ ) {
                    for (int node_i = 0; node_i < numberOfNodes; node_i++ ) {
                        double weightedSum = 0;
                        for (int node_j = 0; node_j < numberOfNodes; node_j++ ) {
                            double w ;
                            // if there is a true edge from node j to node i, then consider node j in weighted sum 
                            w = contains(node_j, trueEdges[node_i]) ? spikeVG1.Sample() : slabVG2.Sample();
                            weightedSum = weightedSum + w * timeSeriesData[t - 1][node_j];                    
                        }
                        timeSeriesData[t][node_i] = weightedSum;
                    }
                }
    
                return timeSeriesData;
            }

    Monday, October 13, 2014 4:39 PM
  • Write some ordinary C# code that samples weightMixtureData from mixtureMeans and mixturePrecs in the way that you want it to work.
    Monday, October 13, 2014 5:37 PM
    Owner
  • Here's my code for generating sample data.

    the same value for means and precs is used. They may be different. That's why I have defined jagged arrays to store the values.

    public double[][] GenerateTimeSeriesData(int nData, int numberOfNodes)
            {
                //int numberOfWeights = numberOfNodes - 1; // Number of edges for each node
                double[][] spikeMean = new double[numberOfNodes][];
                double[][] slabMean = new double[numberOfNodes][];
                double[][] spikePrec = new double[numberOfNodes][];
                double[][] slabPrec = new double[numberOfNodes][];
    
                Gaussian[][] spikeG = new Gaussian[numberOfNodes][];
                Gaussian[][] slabG = new Gaussian[numberOfNodes][];
    
                double[][] spikeForTrue = new double[numberOfNodes][];
    
                // initialization of spile and slab for each edge
                // later we will sample from spike with a higher probability for trueEdge weights
                // and sample with a higher prob from slap for nonExisting edge weights
                // In practice, these spike and slab distributions can be different for different edge weights
                for (int i = 0; i < numberOfNodes; i++)
                {
                    spikeG[i] = new Gaussian[numberOfNodes];
                    slabG[i] = new Gaussian[numberOfNodes];
                    spikeForTrue[i] = new double[numberOfNodes];
                    spikeMean[i] = new double[numberOfNodes];
                    spikePrec[i] = new double[numberOfNodes];
                    slabMean[i] = new double[numberOfNodes];
                    slabPrec[i] = new double[numberOfNodes];
                    for (int j = 0; j < numberOfNodes; j++)
                    {
                        spikeForTrue[i][j] = 0.9;
                        spikeMean[i][j] = 10;
                        spikePrec[i][j] = 1;
                        slabMean[i][j] = 5;
                        slabPrec[i][j] = 1;
                        spikeG[i][j] = Gaussian.FromMeanAndPrecision(spikeMean[i][j], spikePrec[i][j]); // spike
                        slabG[i][j] = Gaussian.FromMeanAndPrecision(slabMean[i][j], slabPrec[i][j]); // slab
                    }
                }
                
                // true edges in the network
                // trueEdges[i] lists the incomming edges from other j nodes to i. 
                int[][] trueEdges = new int[][]{
                    new int[] {1}/*example: there is an edge from node 1 to node 0*/, 
                    new int[] {0, 2,3}, new int[]{1}, new int[]{1,4}, new int[]{3, 5,6,7}, 
                    new int[]{4} , new int[]{4},  new int[]{4}
                };
    
                //nData : number of time points
                double[][] timeSeriesData = new double[nData][];
                Rand.Restart(12347);
    
                // generate random data for row 0 (this is value of nodes - not w values)
                var r = new Random();
                timeSeriesData[0] = new double[numberOfNodes];
                for (int i = 0; i < numberOfNodes; i++)
                {
                    timeSeriesData[0][i] = r.NextDouble();
                }
    
                // generating the rest of data
                // each nodes value is a weightes sum of node values in time t-1
                // if edge is trueEdge, edge weight is sampled from spike
                // otherwise edgeWeight is sampled from slap
                for (int t = 1; t < nData; t++) // t shows time
                {
                    for (int node_i = 0; node_i < numberOfNodes; node_i++)
                    {
                        double weightedSum = 0;
                        timeSeriesData[t] = new double[numberOfNodes];
                        for (int node_j = 0; node_j < numberOfNodes; node_j++)
                        {
                            double w;
                            Bernoulli trueEdge = new Bernoulli(spikeForTrue[node_i][node_j]);
                            bool tSamp = trueEdge.Sample();
                            if (containsTrueEdges(node_j, trueEdges[node_i]))
                            {                            
                                // if there is a true edge from node j to node i, then give a higher probability to spike                            
                                w = tSamp ? spikeG[node_i][node_j].Sample() : slabG[node_i][node_j].Sample();
                            }
                            else {
                                // if there is a true edge from node j to node i, then give a higher probability to slab                            
                                w = tSamp ? slabG[node_i][node_j].Sample() : spikeG[node_i][node_j].Sample();
                            }
                            weightedSum = weightedSum + w * timeSeriesData[t - 1][node_j];
                        }
                        timeSeriesData[t][node_i] = weightedSum;
                    }
                }
    
                return timeSeriesData;
            }

    Monday, October 13, 2014 11:36 PM
  • The code you sent does not contain any variable named weightMixtureData, nor mixtureMeans or mixturePrecs.
    Tuesday, October 14, 2014 8:26 AM
    Owner
  • Sorry for this inconvenience.

    public double[][] GenerateTimeSeriesData(int nData, int numberOfNodes)
            {
                int k = 2;
    
                // Number of edges for each node
                double[][][] mixtureMeans = new double[k][][];
                double[][][] mixturePrecs = new double[k][][];
                double[][] mixtureWeights = new double[numberOfNodes][];
    
                // the first element of mixtures is a point mass at zero (slab), the second is GaussianFromMeanAndPrec(5,1) (spike)
                double[] trueMeans = new double[] { 0, 5};
                double[] truePrecs = new double[] { 0, 1 };
    
                for (int m = 0; m < k; m++ ) {
                    mixtureMeans[m] = new double[numberOfNodes][];
                    mixturePrecs[m] = new double[numberOfNodes][];
                    for (int i = 0; i < numberOfNodes; i++)
                    {
                        mixtureMeans[m][i] = new double[numberOfNodes];
                        mixturePrecs[m][i] = new double[numberOfNodes];
                        mixtureWeights[i] = new double[numberOfNodes];
                        for (int j = 0; j < numberOfNodes; j++)
                        {
                            mixtureMeans[m][i][j] = trueMeans[m];
                            mixturePrecs[m][i][j] = truePrecs[m]; 
                        }
                    }
                }
    
                double spikeForTrue = 0.9;
    
                // later we will sample from spike with a higher probability for trueEdge weights
                // and sample with a higher prob from slap for nonExisting edge weights
                // In practice, these spike and slab distributions can be different for different edge weights
                
                
                // true edges in the network
                // trueEdges[i] lists the incomming edges from other j nodes to i. 
                int[][] trueEdges = new int[][]{
                    new int[] {1}/*example: there is an edge from node 1 to node 0*/, 
                    new int[] {0, 2,3}, new int[]{1}, new int[]{1,4}, new int[]{3, 5,6,7}, 
                    new int[]{4} , new int[]{4},  new int[]{4}
                };
    
                //nData : number of time points
                double[][] timeSeriesData = new double[nData][];
                Rand.Restart(12347);
    
                // generate random data for row 0 (this is value of nodes - not w values)
                var r = new Random();
                timeSeriesData[0] = new double[numberOfNodes];
                for (int i = 0; i < numberOfNodes; i++)
                {
                    timeSeriesData[0][i] = r.NextDouble();
                }
    
                // generating the rest of data
                // each nodes value is a weightes sum of node values in time t-1
                // if edge is trueEdge, edge weight is sampled from spike
                // otherwise edgeWeight is sampled from slap
                for (int t = 1; t < nData; t++) // t shows time
                {
                    for (int node_i = 0; node_i < numberOfNodes; node_i++)
                    {
                        double weightedSum = 0;
                        timeSeriesData[t] = new double[numberOfNodes];
                        for (int node_j = 0; node_j < numberOfNodes; node_j++)
                        {
                            Bernoulli trueEdge = new Bernoulli(spikeForTrue);
                            bool tSamp = trueEdge.Sample();
                            int select = tSamp ? 1 : 0; // if trueEdge then sample from spike with higher probability, otherwise sample from slab with higher probability
                            if (!containsTrueEdges(node_j, trueEdges[node_i])) select = Math.Abs(1-select); //// select the opposite since it is not a trueEdge (sample from slab with probability 0.9)
                            mixtureWeights[node_i][node_j] = Gaussian.FromMeanAndPrecision(mixtureMeans[select][node_i][node_j], mixturePrecs[select][node_i][node_j]).Sample();
                            weightedSum = weightedSum + mixtureWeights[node_i][node_j] * timeSeriesData[t - 1][node_j];
                        }
                        timeSeriesData[t][node_i] = weightedSum;
                    }
                }
    
                return timeSeriesData;
            }

    Tuesday, October 14, 2014 10:49 AM
  • In your sampler, you have defined mixtureWeights, mixtureMeans, and mixturePrecs over the same ranges.  So just do this in your Infer.NET code.
    Range k = new Range(2).Named("k");
    Range nodeRange = new Range(numberOfNodes).Named("nodeRange");
    Range nodeRange2 = nodeRange.Clone();
    
    var mixtureWeights = Variable.Array(Variable.Array<double>(nodeRange2), nodeRange);
    var mixtureMeans = Variable.Array(Variable.Array(Variable.Array<double>(nodeRange2), nodeRange), k);


    Note you could also make k the last range of mixtureMeans instead of the first.  This would make more sense since the number of components might vary per node, but each component can't have a different number of nodes.
    Tuesday, October 14, 2014 10:58 AM
    Owner
  • my real nodeRange2 is a different range actually (instead of nodeRange2, having all possible destinations nodes for my network edges, I need a wRange over potential edges). I mean, each node has not all possible weights. one node may have 8 potential edges, the other 6 edges, etc. That's why I used a jagged array. instead of node_j in my model inference I have a potentialEdges jagged array, and the range over w is defined using this potentialEdges jagged array (which stores for each node_i, the potential node_j s). So the size of w dimension should come from this jagged array (wsizes below).

    And I need this range over w (weights) in my weightMatrix and also

    In fact in my implementation I have this:

                int[] wsizes = new int[potentialEdges.Length];
                for (int i = 0; i < potentialEdges.Length; i++)
                {
                    wsizes[i] = potentialEdges.ElementAt(i).Length;
                }
                VariableArray<int> wsizesVar = Variable.Constant(wsizes, nodeRange).Named("wsizes");
                Range wRange = new Range(wsizesVar[nodeRange]).Named("wRange");
                var wIndices = Variable.Array(Variable.Array<int>(wRange), nodeRange).Named("wIndices");
                wIndices.ObservedValue = potentialEdges;

                // implimenting weight variable in Gaussian mixture exapmle, but for a weight matrix.
                // we have a matrix, in which each element is a weight for the corresponding edge
                VariableArray<VariableArray<Vector>, Vector[][]> mixtureWeights =
                    Variable.Array(Variable.Array<Vector>(wRange), nodeRange).Named("mixtureWeight");
                using (ForEachBlock firstBlock = Variable.ForEach(nodeRange))
                {
                    using (ForEachBlock secondBlock = Variable.ForEach(wRange))
                    {
                        mixtureWeights[nodeRange][wRange] = Variable.Dirichlet(k, new double[] { 1, 1 }).Named("weights");
                    }
                }

                // now creating means and precs variables for mixtureWeights
                // outerRange = k
                VariableArray<int> middleSizes = Variable.Constant(new int[] { nodeRange.SizeAsInt, nodeRange.SizeAsInt }, k).Named("middleSizes");
                Range middleNodeRange = new Range(middleSizes[k]).Named("middleNodesRange");
                int[][] innerWsizes = new int[nodeRange.SizeAsInt][];
                for (int i = 0; i < innerWsizes.Length; i++)
                {
                    innerWsizes[i] = new int[wsizes.Length];
                    for (int j = 0; j < wsizes.Length; j++)
                    {
                        innerWsizes[i][j] = wsizes[j];
                    }
                }
                var innerSizes = Variable.Constant(innerWsizes, k, middleNodeRange).Named("innerSizes");
                Range innerWRange = new Range(innerSizes[k][middleNodeRange]).Named("innerWRange");

                Variable<Gaussian> mixtureMeanPrior = Variable.New<Gaussian>().Named("mixtureMeanPrior");
                Variable<Gaussian> mixturePrecPrior = Variable.New<Gaussian>().Named("mixturePrecisionPrior");

                var mixtureMeans = Variable.Array(Variable.Array(Variable.Array<double>(innerWRange), middleNodeRange), k).Named("mixtureMeans");
                mixtureMeans[k][middleNodeRange][innerWRange] = Variable<double>.Random(mixtureMeanPrior).ForEach(k, middleNodeRange, innerWRange);

                var mixturePrecs = Variable.Array(Variable.Array(Variable.Array<double>(innerWRange), middleNodeRange), k).Named("mixturePrecs");
                mixturePrecs[k][middleNodeRange][innerWRange] = Variable<double>.Random(mixturePrecPrior).ForEach(k, middleNodeRange, innerWRange);

    The problem is having a loop over wRange and nodeRange on both 2d and 3d jagged array. In 3d jagged array we don't have wRange and nodeRange. Instead we have innerWRange and wRange which are in reality the same but in implementation one related to outer range of a 2d jag and one is the middle range in a 3d jag. And these two have not the same implementation therefore cannot be cloned.

    Range wRange = new Range(wsizesVar[nodeRange]).Named("wRange");

    Range innerWRange = new Range(innerSizes[k][middleNodeRange]).Named("innerWRange");

    Is there any way to do this kind of clone? Thanks.

    Wednesday, October 15, 2014 8:47 AM
  • You can use the same ranges as follows:

    var mixtureMeans = Variable.Array(Variable.Array(Variable.Array<double>(k), wRange), nodeRange);

    • Marked as answer by Capli19 Wednesday, October 15, 2014 3:16 PM
    Wednesday, October 15, 2014 2:12 PM
    Owner