# Problem with defining CPT from 2 random variables

• ### 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

### 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
• 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
• 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
• 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