# Mixing continous and integer variables • ### Question

• Hi,

As part of my effort learning how to use Infer.Net for solving an interesting problem, I am struggling with a part of my model, which involves both continous and integer variables. The part that causes me trouble has the following form:

cpObservations[range] = distances[range] + 0.2 * n+ Variable.GaussianFromMeanAndVariance(0, 0.02);

where cpObservations (observed) and distances are Gaussian variables, and n is supposed to be a fixed integer, whose value is to be estimated by the model data.

I don't know how to properly represent and implement n. I have played around with a custom factor implementing a rounding operation on a gaussian variable, but I have had no real success so far. Either my approach is wrong or my knowledge about how to implement the exact factor messages is insufficient.

Any ideas how to proceed? I would be happy for any feedback

Thank you

Henrik Kjær Nielsen

Sunday, March 18, 2012 7:09 PM

### Answers

• Apologies for the delay in replying - it's been a busy week.

Would this do what you want?

John

```		static void Main(string[] args)
{
// The model
var nMults = Variable.New<int>();
var nRange = new Range(nMults);

var n = Variable.DiscreteUniform(nRange);
var multiplier = Variable.Array<double>(nRange);

var nData = Variable.New<int>();
var range = new Range(nData);

var distances = Variable.Array<double>(range);
distances[range] = Variable.GaussianFromMeanAndPrecision(0, 1).ForEach(range);
var cpObservations = Variable.Array<double>(range);

using (Variable.Switch(n))
{
var mult = multiplier[n];
cpObservations[range] = distances[range] * mult + Variable.GaussianFromMeanAndVariance(0, 0.02);
}

// The data
var observedData = new double[] { 0.5, 0.6, 0.7 };
int numMults = 6;
var mults = Enumerable.Range(1, numMults).Select(i => (double)i).ToArray();

nMults.ObservedValue = numMults;
multiplier.ObservedValue = mults;
nData.ObservedValue = observedData.Length;
cpObservations.ObservedValue = observedData;

var engine = new InferenceEngine();
Console.WriteLine(engine.Infer(n));
Console.WriteLine(engine.Infer(distances));

}```

Friday, March 30, 2012 5:21 PM

### All replies

• Apologies for the delay in replying - it's been a busy week.

Would this do what you want?

John

```		static void Main(string[] args)
{
// The model
var nMults = Variable.New<int>();
var nRange = new Range(nMults);

var n = Variable.DiscreteUniform(nRange);
var multiplier = Variable.Array<double>(nRange);

var nData = Variable.New<int>();
var range = new Range(nData);

var distances = Variable.Array<double>(range);
distances[range] = Variable.GaussianFromMeanAndPrecision(0, 1).ForEach(range);
var cpObservations = Variable.Array<double>(range);

using (Variable.Switch(n))
{
var mult = multiplier[n];
cpObservations[range] = distances[range] * mult + Variable.GaussianFromMeanAndVariance(0, 0.02);
}

// The data
var observedData = new double[] { 0.5, 0.6, 0.7 };
int numMults = 6;
var mults = Enumerable.Range(1, numMults).Select(i => (double)i).ToArray();

nMults.ObservedValue = numMults;
multiplier.ObservedValue = mults;
nData.ObservedValue = observedData.Length;
cpObservations.ObservedValue = observedData;

var engine = new InferenceEngine();
Console.WriteLine(engine.Infer(n));
Console.WriteLine(engine.Infer(distances));

}```

Friday, March 30, 2012 5:21 PM
• Hi John,

Thank you for your feedback. This was exactly what I needed...

As a side note, I have a few comments regarding Infer.NET based on my rather limited experience so far. Maybe my comments are not all relevant or already taken care of:

1. When working with indexes in relation to ranges and vectors, I sometimes run into type issues like: "Argument type 'Microsoft.Infer.Models.Variable<int>' is not assignable to parameter type 'int'". Is there no way to cast a 'Microsoft.Infer.Models.Variable<int>' to an 'int' ?

2. A part of my model had the following construction:

```using (ForEachBlock ddBlock = Variable.ForEach(ddRange))
{
ddAmbiguities[ddRange] = sdAmbiguities[ddBlock.Index + 1] - sdAmbiguities[ddBlock.Index];
}```

This however causes a compiler error: "Variable 'sdAmbiguities_use' appears twice in the same function call. This will lead to inaccurate inference."
But the two sdAmbiguities are different variables, and there should be nothing wrong in the above statement. However, the following slightly arkward reformulation seems to do the trick:

```using (ForEachBlock ddBlock = Variable.ForEach(ddRange))
{
ddAmbiguities[ddRange] = (sdAmbiguities[ddBlock.Index + 1] - 0) - (sdAmbiguities[ddBlock.Index] - 0);
}```

Maybe this could be fixed in a later release.

3. May I suggest that the model source code generated by Infer.NET simply adds the "partial" keyword in the class declaration (as in: public partial class Model_EP : IGeneratedAlgorithm). This would allow for having various helper functions (data set handling, custom functions etc) in a separate file and use these with the pre-compiled model code without having to merge source code after each re-compilation of the model.

Best regards

Henrik Kjær Nielsen

Sunday, April 1, 2012 11:18 AM
• 1. It doesn't make sense to cast a Variable<int> into an int, since the Variable may be random.  If the Variable is constant or observed, you can get its ObservedValue.  For Ranges, there is a special property SizeAsInt that reads the ObservedValue property of its size variable.

2. This is a bug.  Thanks for finding it.

3. Good suggestion.  I'll look into it.

Wednesday, April 4, 2012 4:53 PM
• Infer.NET 2.5 has fixed the above bug, and the generated code now has the "partial" keyword as you suggested.

Thursday, October 4, 2012 10:17 AM