locked
Accessing to VariableArray<double> elements (Migrated from community.research.microsoft.com) RRS feed

  • Question

  • amin posted on 08-04-2010 1:16 PM

    Hi all,

    I defined  in c# :

    Range X_Range = new Range(X_No).Named("X_Range");

    Range Z_Range = new Range(Z_No).Named("Z_Range");

    VariableArray<double> Var_X = Variable.Array<double>(X_Range).Named("Var_X");

    VariableArray<double> Var_Z = Variable.Array<double>(Z_Range);

    and X_No> Z_No
    I want to select some random elements ,that are not sequential, from Var_X and add them together and assign that some to one specific Var_Z element.
    I used this code: 
    Variable<int> index_X = Variable.New<int>();
    Variable<int> index_Z = Variable.New<int>();
    for (int i = 0; i < InpurOfFunction; i++) // InpurOfFunction is No. of Var_X that add together and creat Var_Z 
                {
                    for (int j = 0; j < Z_No; j++)
                    {
                        index_X.ObservedValue = Index[ j ][ i ];// Index is a 2D random selection index  
                        index_Z.ObservedValue = j;
                         Var_Z[index_Z]= Var_Z[index_Z] + Var_X[index_X];
                    }                           
                }

    I see this error :

    Property or indexer 'MicrosoftResearch.Infer.Models.VariableArray<MicrosoftResearch.Infer.Models.Variable<double>,double[]>.this[MicrosoftResearch.Infer.Models.Variable<int>]' cannot be assigned to -- it is read only

    what should I do for writable access to Var_Z elements? 

    Friday, June 3, 2011 5:57 PM

Answers

  • John Guiver replied on 08-05-2010 5:04 AM

    Hi Amin

    You cannot write individual elements of a VariableArray. VariableArray is designed to support plates in a graphical model, where the statistical definition is the same for all elements of the plate. However you can efficiently achieve what you want by using jagged ranges and index arrays as follows (you don't say how Var_X is defined, so I am just setting its prior to a standardised Gaussian):

    class Program
    {
        static void Main(string[] args)
        {
            var xSize = Variable.New<int>();
            var zSize = Variable.New<int>();
            var Z_Range = new Range(zSize);
            var X_Range = new Range(xSize);
            var subXSizes = Variable.Array<int>(Z_Range);
            var subXRange = new Range(subXSizes[Z_Range]);
            var indices = Variable.Array(Variable.Array<int>(subXRange), Z_Range);
            var Var_X = Variable.Array<double>(X_Range);
            var Var_Z = Variable.Array<double>(Z_Range);
            Var_X[X_Range] = Variable.GaussianFromMeanAndPrecision(0,1).ForEach(X_Range);
            using (Variable.ForEach(Z_Range))
            {
                // NOTE: you can use the more efficient SubArray rather than GetItems if indices are guaranteed to be all different
                var sub = Variable.GetItems(Var_X, indices[Z_Range]);
                Var_Z[Z_Range] = Variable.Sum(sub);
            }
            // Data:
            int X_No = 10;
            int Z_No = 3;
            int[][] ind = new int[Z_No][];
            int[] sizes = new int[Z_No];
            for (int i = 0; i < Z_No; i++)
            {
                int numElts = Rand.Int(X_No)+1;
                sizes[i] = numElts;
                ind[i] = new int[numElts];
                for (int j = 0; j < numElts; j++)
                    ind[i][j] = Rand.Int(numElts);
            }
            // Hook up the data
            xSize.ObservedValue = X_No;
            zSize.ObservedValue = Z_No;
            subXSizes.ObservedValue = sizes;
            indices.ObservedValue = ind;
            // Infer
            InferenceEngine engine = new InferenceEngine();
            Gaussian[] ZPost = engine.Infer<Gaussian[]>(Var_Z);
            foreach (Gaussian g in ZPost) Console.WriteLine(g);
        }
    }

    You will need the following namespaces:
    using MicrosoftResearch.Infer;
    using MicrosoftResearch.Infer.Distributions;
    using MicrosoftResearch.Infer.Models;
    using MicrosoftResearch.Infer.Maths;

    John
     

    Friday, June 3, 2011 5:57 PM

All replies

  • DavidKnowles replied on 08-05-2010 4:53 AM

    Hi Amin

    You are on the right track but your approach has a couple of problems. Firstly, when you change index_X.ObservedValue in every iteration this will overwrite the value set in the previous iteration. Secondly, Var_Z[index_Z]= Var_Z[index_Z] + Var_X[index_X] introduces a strange circular dependency. Note that you can do something like x = x + y (without the indexing) but this is implicitly making a new variable x. I think the following code does what you want.

     

    int X_No = 5;

    int Z_No = 3;

    Range X_Range = new Range(X_No).Named("X_Range");

    Range Z_Range = new Range(Z_No).Named("Z_Range");

    int[][] Index = new int[][]{ new int[]{ 0, 1, 3 },

    new int[]{ 1, 2, 4 },

    new int[]{ 2, 3 } };

    int[] sizes = new int[Z_No];

    for (int i = 0; i < Z_No; i++)

    sizes = Index.Length;

    VariableArray<int> sizesVar = Variable.Constant(sizes, Z_Range);

    Range Index_Range = new Range(sizesVar[Z_Range]).Named("Index_Range");

    VariableArray<VariableArray<int>, int[][]> indexVar = Variable.Array(Variable.Array<int>(Index_Range), Z_Range).Named("indexVar");

    indexVar.ObservedValue = Index;

    VariableArray<double> Var_X = Variable.Array<double>(X_Range).Named("Var_X");

    VariableArray<double> Var_Z = Variable.Array<double>(Z_Range);

    Var_X[X_Range] = Variable.GaussianFromMeanAndPrecision(0, 1).ForEach(X_Range);

    Var_Z[Z_Range] = Variable.Sum(Variable.GetItems(Var_X, indexVar[Z_Range]));

    InferenceEngine ie = new InferenceEngine();

    Console.WriteLine(ie.Infer(Var_Z));

    If you find the jagged array construction confusing be sure to look at the documentation here:

    http://research.microsoft.com/en-us/um/cambridge/projects/infernet/docs/jagged%20arrays.aspx

    Friday, June 3, 2011 5:57 PM
  • John Guiver replied on 08-05-2010 5:04 AM

    Hi Amin

    You cannot write individual elements of a VariableArray. VariableArray is designed to support plates in a graphical model, where the statistical definition is the same for all elements of the plate. However you can efficiently achieve what you want by using jagged ranges and index arrays as follows (you don't say how Var_X is defined, so I am just setting its prior to a standardised Gaussian):

    class Program
    {
        static void Main(string[] args)
        {
            var xSize = Variable.New<int>();
            var zSize = Variable.New<int>();
            var Z_Range = new Range(zSize);
            var X_Range = new Range(xSize);
            var subXSizes = Variable.Array<int>(Z_Range);
            var subXRange = new Range(subXSizes[Z_Range]);
            var indices = Variable.Array(Variable.Array<int>(subXRange), Z_Range);
            var Var_X = Variable.Array<double>(X_Range);
            var Var_Z = Variable.Array<double>(Z_Range);
            Var_X[X_Range] = Variable.GaussianFromMeanAndPrecision(0,1).ForEach(X_Range);
            using (Variable.ForEach(Z_Range))
            {
                // NOTE: you can use the more efficient SubArray rather than GetItems if indices are guaranteed to be all different
                var sub = Variable.GetItems(Var_X, indices[Z_Range]);
                Var_Z[Z_Range] = Variable.Sum(sub);
            }
            // Data:
            int X_No = 10;
            int Z_No = 3;
            int[][] ind = new int[Z_No][];
            int[] sizes = new int[Z_No];
            for (int i = 0; i < Z_No; i++)
            {
                int numElts = Rand.Int(X_No)+1;
                sizes[i] = numElts;
                ind[i] = new int[numElts];
                for (int j = 0; j < numElts; j++)
                    ind[i][j] = Rand.Int(numElts);
            }
            // Hook up the data
            xSize.ObservedValue = X_No;
            zSize.ObservedValue = Z_No;
            subXSizes.ObservedValue = sizes;
            indices.ObservedValue = ind;
            // Infer
            InferenceEngine engine = new InferenceEngine();
            Gaussian[] ZPost = engine.Infer<Gaussian[]>(Var_Z);
            foreach (Gaussian g in ZPost) Console.WriteLine(g);
        }
    }

    You will need the following namespaces:
    using MicrosoftResearch.Infer;
    using MicrosoftResearch.Infer.Distributions;
    using MicrosoftResearch.Infer.Models;
    using MicrosoftResearch.Infer.Maths;

    John
     

    Friday, June 3, 2011 5:57 PM