locked
Problem with defining CPT from 2 random variables RRS feed

  • Question

  • Hi, I have problem with this line of code:

    // TTC probability table conditioned on Speed and Distance
                CPTTTCPrior = Variable.Array(Variable.Array<Dirichlet>(S), D).Named("CPTTTCPrior");
                CPTTTC = Variable.Array(Variable.Array<Vector>(S), D).Named("CPTTTC");
                CPTTTC[S][D] = Variable<Vector>.Random(CPTTTCPrior[S][D]);
                CPTTTC.SetValueRange(T);

    and the error message is : VariableArray<VariableArray<Vector>, Vector[][]> CPTTTC cannot be indexed by S. Perhaps you omitted S as an argument to the constructor?

    The full code as follow:

    class TTC
        {
            //Primary random variable
            public VariableArray<int> Speed;
            public VariableArray<int> Distance;
            public VariableArray<int> TimeToCollision;
            public Variable<int> NumberOfExamples;

            // Random variables representing the parameters of the distributions
            // of the primary random variables. For child variables, these are
            // in the form of conditional probability tables (CPTs)
            public Variable<Vector> ProbSpeed;
            public Variable<Vector> ProbDistance;
            public VariableArray<VariableArray<Vector>, Vector[][]> CPTTTC;

            // Prior distributions for the probability and CPT variables.
            // The prior distributions are formulated as Infer.NET variables
            // so that they can be set at runtime without recompiling the model
            public Variable<Dirichlet> ProbSpeedPrior;
            public Variable<Dirichlet> ProbDistancePrior;
            public VariableArray<VariableArray<Dirichlet>, Dirichlet[][]> CPTTTCPrior;        

            public InferenceEngine Engine = new InferenceEngine();

            public TTC()
            {
                // Set up the ranges
                NumberOfExamples = Variable.New<int>().Named("NofE");
                Range N = new Range(NumberOfExamples).Named("N");

                // Although all the variables in this example have just 2 states (true/false),
                // the example is formulated in a way that shows how to extend to multiple states
                Range S = new Range(2).Named("S");
                Range D = new Range(2).Named("D");
                Range T = new Range(2).Named("T");

                // Define the priors and the parameters
                ProbSpeedPrior = Variable.New<Dirichlet>().Named("ProbSpeedPrior");
                ProbSpeed = Variable<Vector>.Random(ProbSpeedPrior).Named("ProbSpeed");
                ProbSpeed.SetValueRange(S);

                ProbDistancePrior = Variable.New<Dirichlet>().Named("ProbDistancePrior");
                ProbDistance = Variable<Vector>.Random(ProbDistancePrior).Named("ProbDistance");
                ProbDistance.SetValueRange(D);

                // TTC probability table conditioned on Speed and Distance
                CPTTTCPrior = Variable.Array(Variable.Array<Dirichlet>(S), D).Named("CPTTTCPrior");
                CPTTTC = Variable.Array(Variable.Array<Vector>(S), D).Named("CPTTTC");
                CPTTTC[S][D] = Variable<Vector>.Random(CPTTTCPrior[S][D]);
                CPTTTC.SetValueRange(T);

                // Define the primary variables
                Speed = Variable.Array<int>(N).Named("Speed");
                Speed[N] = Variable.Discrete(ProbSpeed).ForEach(N);
                Distance = Variable.Array<int>(N).Named("Distance");
                Distance[N] = Variable.Discrete(ProbDistance).ForEach(N);
                TimeToCollision = AddChildFromTwoParents(Speed, Distance, CPTTTC).Named("TimeToCollision");
            }

            public double ProbTMTC(
                 int? speed,
                 int? distance,
                 Dirichlet probSpeedPrior,
                 Dirichlet probDistancePrior,
                 Dirichlet[][] cptTTCPrior)
            {
                NumberOfExamples.ObservedValue = 1;
                if (speed.HasValue)
                    Speed.ObservedValue = new int[] { speed.Value };
                else
                    Speed.ClearObservedValue();

                if (distance.HasValue)
                    Distance.ObservedValue = new int[] { distance.Value };
                else
                    Distance.ClearObservedValue();

                TimeToCollision.ClearObservedValue();

                ProbSpeedPrior.ObservedValue = probSpeedPrior;
                CPTTTCPrior.ObservedValue = cptTTCPrior;

                // Inference
                var ttcPosterior = Engine.Infer<Discrete[]>(TimeToCollision);
                // In this example, index 0 is true and index 1 is false
                return ttcPosterior[0].GetProbs()[0];
            }

            public double ProbTMTCT(
                int? speed,
                int? distance,
                Vector probSpeed,
                Vector probDistance,
                Vector[][] cptTTC)
            {
                var probSpeedPrior = Dirichlet.PointMass(probSpeed);
                var probDistancePrior = Dirichlet.PointMass(probDistance);
                var cptTTCPrior = cptTTC.Select(va => va.Select(v => Dirichlet.PointMass(v)).ToArray()).ToArray(); ;           
                return ProbTMTC(speed, distance, probSpeedPrior, probDistancePrior, cptTTCPrior);
            }

            public static VariableArray<int> AddChildFromOneParent(
                VariableArray<int> parent,
                VariableArray<Vector> cpt)
            {
                var n = parent.Range;
                var child = Variable.Array<int>(n);
                using (Variable.ForEach(n))
                using (Variable.Switch(parent[n]))
                    child[n] = Variable.Discrete(cpt[parent[n]]);
                return child;
            }

            public static VariableArray<int> AddChildFromTwoParents(
                VariableArray<int> parent1,
                VariableArray<int> parent2,
                VariableArray<VariableArray<Vector>, Vector[][]> cpt)
            {
                var n = parent1.Range;
                var child = Variable.Array<int>(n);
                using (Variable.ForEach(n))
                using (Variable.Switch(parent1[n]))
                using (Variable.Switch(parent2[n]))
                    child[n] = Variable.Discrete(cpt[parent1[n]][parent2[n]]);
                return child;
            }
        }


    Wednesday, January 31, 2018 4:12 AM

Answers

  • You flipped the ranges.  According to the constructor, CPTTTC should be indexed as CPTTTC[D][S].
    Wednesday, January 31, 2018 11:36 AM
    Owner

All replies

  • You flipped the ranges.  According to the constructor, CPTTTC should be indexed as CPTTTC[D][S].
    Wednesday, January 31, 2018 11:36 AM
    Owner
  • Same error occured
    Wednesday, January 31, 2018 11:49 AM
  • When I change the line

    CPTTTC[S][D] = Variable<Vector>.Random(CPTTTCPrior[S][D]);

    to 

    CPTTTC[D][S] = Variable<Vector>.Random(CPTTTCPrior[S][D]);

    I do not get the same error.  By the way, there is more than one problem with this code, but I will let you work them out.

    Wednesday, January 31, 2018 12:05 PM
    Owner
  • Flipping the range solve the problem, thanks.

    CPTTimeToCollisionPrior = Variable.Array(Variable.Array<Dirichlet>(D),S).Named("CPTTimeToCollisionPrior");            
                CPTTimeToCollision = Variable.Array(Variable.Array<Vector>(D), S).Named("CPTTimeToCollision");
                CPTTimeToCollision[S][D] = Variable<Vector>.Random(CPTTimeToCollisionPrior[S][D]);            
                CPTTimeToCollision.SetValueRange(T);

    By the way, can you give me a clue if I have CPT from three nodes? I was trying to do something like this:

    public VariableArray<VariableArray<VariableArray<Vector>, Vector[][][]>> CPTTimeToCollision;
    public VariableArray<VariableArray<VariableArray<Dirichlet>, Dirichlet[][][]>> CPTTimeToCollisionPrior;   

    CPTTimeToCollisionPrior = Variable.Array(Variable.Array(Variable.Array<Dirichlet>(D), R, S)).Named("CPTTimeToCollisionPrior");
                CPTTimeToCollision = Variable.Array(Variable.Array(Variable.Array<Vector>(D), R, S)).Named("CPTTimeToCollision");
                CPTTimeToCollision[S][D][R] = Variable<Vector>.Random(CPTTimeToCollisionPrior[S][D][R]);            
                CPTTimeToCollision.SetValueRange(T);


    Thursday, February 1, 2018 9:04 AM
  • Try using:

    Variable.Array(Variable.Array(Variable.Array<Dirichlet>(D), R), S)

    and again make sure you index the array in the correct order.

    Thursday, February 1, 2018 11:15 AM
    Owner
  • Thanks man... I did it.. Although it was weird at the first time when I have to declare the vector and dirichlet like this:

    public VariableArray<VariableArray<VariableArray<Vector>, Vector[][]>, Vector[][][]> CPTTimeToCollision;

    public VariableArray<VariableArray<VariableArray<Dirichlet>, Dirichlet[][]>, Dirichlet[][][]> CPTTimeToCollisionPrior;

    to be compatible with

    Variable.Array(Variable.Array(Variable.Array<Dirichlet>(D), R), S)

    best regards

    Friday, February 2, 2018 1:44 AM