Answered by:
shared variables in IronPython
Question

Hi,
I've been running into problems when trying to use shared variables in IronPython; I'm sure I'm making a silly mistake but I can't quite figure it out. Any pointers are very much appreciated.
When I try to define a shared variable with:
shareTest = SharedVariable[float].Random(Dirichlet.Symmetric(2,1.))
I get the error
TypeError: The type arguments for method 'Random' cannot be inferred from the usage. Try specifying the type arguments explicitly.
If I then specify the type by
shareTest = SharedVariable[float].Random[float](Dirichlet.Symmetric(2,1.))
I get the error
ValueError: GenericArguments[0], "System.Double" for "MicrosoftResearch.Infer.Models.ISharedVariableArray`2[MicrosoftResearch.Infer.Models.VariableArray`1[System.Double],System.Double[][]] Random[DistributionArrayType](MicrosoftResearch.Infer.Models.VariableArray`1[System.Double], MicrosoftResearch.Infer.Models.Range, DistributionArrayType, Boolean)"
Same error if I replace the second float with Dirichlet and/or omit the first [float]. If I understand the error correctly, it seems to think that I'm defining a shared variable array rather than a scalar variable?
Thank you for your help,
flo
Wednesday, May 9, 2012 8:35 AM
Answers

We have spent some time looking at this now, and don't have a good solution. IronPython will try to find the best overload at runtime, but it seems that in this case it is confused between the various overloads of Random (there are 4 of them) and is chosing the wrong one.
IronPython provides an Overloads method (documentation is limited right now, but see http://stackoverflow.com/questions/3907886/ironpythonoverloadresolutionongenerictypes for example) which is designed to allow you to specify the overload explicitly, so we would expect
mean = SharedVariable[float].Random[Gaussian].Overloads[Gaussian, bool](priorMean, True)
to work; however, unfortunately, this also gives the same error, so we're not sure what to recommend. You might be able to find better advice on an IronPython forum  if you do, please repost here with any insights.
In the meantime however, the following ugly hack works:
def GetMySharedVariableMethod() :
svtype = clr.GetClrType(SharedVariable[float])
methods = svtype.GetMethods(System.Reflection.BindingFlags.StaticSystem.Reflection.BindingFlags.Public)
for i in range(0, methods.Length):
method = methods[i]
if method.Name == "Random"and method.IsGenericMethod:
typeArguments = method.GetGenericArguments()
if typeArguments.Length == 1 and typeArguments[0].Name == "DistributionType":
return method.MakeGenericMethod(clr.GetClrType(Gaussian))
Then call as:myMethod = GetMySharedVariableMethod()
mySharedVariable = myMethod.Invoke(None, System.Array[object]([priorMean, True])) Marked as answer by fl0m0 Thursday, May 10, 2012 5:58 PM
Thursday, May 10, 2012 3:44 PMOwner
All replies

Dirichlet is a distribution over Vectors so you need to use SharedVariable[Vector].Thursday, May 10, 2012 11:02 AMOwner

Thank you very much for your answer, Tom.
Unfortunately that doesn't work either. I also tried to use a Gaussian prior which also gave the same errors. So basically when I try to reproduce the IronPython equivalent of the C# code (from the Infer.NET Documentation)
Gaussian priorMean = Gaussian.FromMeanAndVariance(0, 100);
SharedVariable<double> mean = SharedVariable<double>.Random(priorMean);In form of
priorMean = Gaussian.FromMeanAndVariance(0, 100)
mean = SharedVariable[float].Random(priorMean)
I get the same errors as described above. Any ideas?
Thanks!
Thursday, May 10, 2012 2:13 PM 
We have spent some time looking at this now, and don't have a good solution. IronPython will try to find the best overload at runtime, but it seems that in this case it is confused between the various overloads of Random (there are 4 of them) and is chosing the wrong one.
IronPython provides an Overloads method (documentation is limited right now, but see http://stackoverflow.com/questions/3907886/ironpythonoverloadresolutionongenerictypes for example) which is designed to allow you to specify the overload explicitly, so we would expect
mean = SharedVariable[float].Random[Gaussian].Overloads[Gaussian, bool](priorMean, True)
to work; however, unfortunately, this also gives the same error, so we're not sure what to recommend. You might be able to find better advice on an IronPython forum  if you do, please repost here with any insights.
In the meantime however, the following ugly hack works:
def GetMySharedVariableMethod() :
svtype = clr.GetClrType(SharedVariable[float])
methods = svtype.GetMethods(System.Reflection.BindingFlags.StaticSystem.Reflection.BindingFlags.Public)
for i in range(0, methods.Length):
method = methods[i]
if method.Name == "Random"and method.IsGenericMethod:
typeArguments = method.GetGenericArguments()
if typeArguments.Length == 1 and typeArguments[0].Name == "DistributionType":
return method.MakeGenericMethod(clr.GetClrType(Gaussian))
Then call as:myMethod = GetMySharedVariableMethod()
mySharedVariable = myMethod.Invoke(None, System.Array[object]([priorMean, True])) Marked as answer by fl0m0 Thursday, May 10, 2012 5:58 PM
Thursday, May 10, 2012 3:44 PMOwner 
Thank you very much, John, that is really helpful.
I'll have a look if I find an alternative solution for the Overloads problem, and until then will use the hack you came up with. Thanks again for that and your very quick reply!
Best wishes,
flo
Thursday, May 10, 2012 6:00 PM