Answered by:
How to track down "System.NullReferenceException"?

Question
-
I've built a fairly large belief network (Printer Nightmare example from David Barber Bayesian Reasoning and Machine Learning book). Multiple random variables, their parameter and associated prior variables are defined and used in a graph. I used the Sprinkler demo from samples as a guidance and for the structure for the code.
When running the inference, the Infer.NET compiler stumbles upon the first "Engine.Infer<Beta>(probFuse)" statement. The error message is not very informative, nor is the call trace. For example, I cannot see RV names in the error message which could help me to pin down the null reference object. I tried to do debugging and check if any of RVs is null but everything appears to be fine (I am sure something is not defined properly somewhere).
Is there a way to track down what exactly is null reference? What are the best techniques?
The code is on Github: https://github.com/usptact/PrinterNightmare/blob/master/PrinterNightmare.cs
Thanks
- Edited by usptact Wednesday, November 1, 2017 8:12 AM
Wednesday, November 1, 2017 8:09 AM
Answers
-
Thanks for the stack trace, that told me where the bug is. You have found a bug in Infer.NET. It will be fixed in the next version. Meanwhile, you can work around by using the following code:
public static VariableArray<bool> AddChildFromThreeParents(VariableArray<bool> parent1, VariableArray<bool> parent2, VariableArray<bool> parent3, VariableArray<VariableArray<VariableArray<double>, double[][]>, double[][][]> cpt) { var n = parent1.Range; var child = Variable.Array<bool>(n); using (Variable.ForEach(n)) { var parent2n = parent2[n] & Variable.Bernoulli(1.0); using (Variable.If(parent1[n])) { using (Variable.If(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][0][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][0][1]); } using (Variable.IfNot(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][1][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][1][1]); } } using (Variable.IfNot(parent1[n])) { using (Variable.If(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][0][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][0][1]); } using (Variable.IfNot(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][1][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][1][1]); } } } return child; }
- Marked as answer by usptact Wednesday, November 1, 2017 7:44 PM
Wednesday, November 1, 2017 7:14 PMOwner -
Infer.NET version 2.7 is now out and fixes this problem.
- Marked as answer by usptact Monday, April 2, 2018 3:47 PM
Sunday, April 1, 2018 2:51 PMOwner
All replies
-
The best technique is to enable debugging in the generated code, described at Debugging inference.Wednesday, November 1, 2017 2:39 PMOwner
-
Thanks. The problem is that there is no generated code. Apparently, something fails pretty early and the GeneratedSources folder is never created and populated.
For the record, I set these fields in the engine:
engine.Compiler.GenerateInMemory = false; engine.Compiler.WriteSourceFiles = true; engine.Compiler.IncludeDebugInformation = true;
- Edited by usptact Wednesday, November 1, 2017 4:14 PM
Wednesday, November 1, 2017 4:13 PM -
The complete error message:
Exception thrown: 'System.NullReferenceException' in Infer.Compiler.dll An unhandled exception of type 'System.NullReferenceException' occurred in Infer.Compiler.dll Object reference not set to an instance of an object.
Wednesday, November 1, 2017 5:08 PM -
I think I have identified the problem. The "AddChildFromThreeParents" function builds a VariablArray<bool> and has 3 levels of branching.
public static VariableArray<bool> AddChildFromThreeParents(VariableArray<bool> parent1, VariableArray<bool> parent2, VariableArray<bool> parent3, VariableArray<VariableArray<VariableArray<double>, double[][]>, double[][][]> cpt) { var n = parent1.Range; var child = Variable.Array<bool>(n); using (Variable.ForEach(n)) { using (Variable.If(parent1[n])) { using (Variable.If(parent2[n])) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][0][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][0][1]); } using (Variable.IfNot(parent2[n])) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][1][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][1][1]); } } using (Variable.IfNot(parent1[n])) { using (Variable.If(parent2[n])) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][0][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][0][1]); } using (Variable.IfNot(parent2[n])) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][1][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][1][1]); } } } return child; }
The other two functions for adding a child from one and two parents respectively work well (inference runs). There is something bad with branching at 3 levels...
Wednesday, November 1, 2017 5:47 PM -
You should get a more complete error message (with stack trace) if you compile with Debugging enabled.Wednesday, November 1, 2017 5:59 PMOwner
-
Unfortunately, this is the stack trace that I am able to get. I don't see variable names that could help me to find the problem.
Compiling model...System.NullReferenceException: Object reference not set to an instance of an object. at MicrosoftResearch.Infer.CompilerAttributes.Containers.ContainerGetHashCode (IStatement st) in c:\Builds\2\infernet\External\src\infernet\Compiler\Infer\Com pilerAttributes\Containers.cs:line 319 at MicrosoftResearch.Infer.CompilerAttributes.Containers.ContainerComparer.Ge tHashCode(IStatement st) in c:\Builds\2\infernet\External\src\infernet\Compiler\ Infer\CompilerAttributes\Containers.cs:line 333 at MicrosoftResearch.Infer.Utils.Hash.GetHashCodeAsSet[T](IEnumerable`1 set, IEqualityComparer`1 comparer) in c:\Builds\2\infernet\External\src\infernet\Runt ime\Core\Utils\Hash.cs:line 125 at MicrosoftResearch.Infer.CompilerAttributes.Containers.GetHashCode() in c:\ Builds\2\infernet\External\src\infernet\Compiler\Infer\CompilerAttributes\Contai ners.cs:line 231 at System.Collections.Generic.ObjectEqualityComparer`1.GetHashCode(T obj) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boo lean add) at MicrosoftResearch.Infer.Collections.Set`1.Add(T item) in c:\Builds\2\infer net\External\src\infernet\Runtime\Core\Collections\Set.cs:line 120 at MicrosoftResearch.Transforms.AttributeRegistry`2.Set(TObject obj, TAttribu te attr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramewo rk\AttributeRegistry.cs:line 219 at #h.#ln.#Db(IExpression #j) in c:\Builds\2\infernet\External\src\infernet\C ompiler\Infer\Transforms\ReplicationTransform.cs:line 392 at #h.#ln.ConvertArrayIndexer(IArrayIndexerExpression #T) in c:\Builds\2\infe rnet\External\src\infernet\Compiler\Infer\Transforms\ReplicationTransform.cs:lin e 100 at MicrosoftResearch.Transforms.CopyTransform.DoConvertExpression(IExpression expr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework \CopyTransform.cs:line 616 at MicrosoftResearch.Transforms.CopyTransform.ConvertExpression(IExpression e xpr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\C opyTransform.cs:line 602 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertCollection(IList` 1 exprColl) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFram ework\ShallowCopyTransform.cs:line 417 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertMethodInvoke(IMet hodInvokeExpression imie) in c:\Builds\2\infernet\External\src\infernet\Compiler \TransformFramework\ShallowCopyTransform.cs:line 435 at MicrosoftResearch.Transforms.CopyTransform.DoConvertExpression(IExpression expr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework \CopyTransform.cs:line 610 at MicrosoftResearch.Transforms.CopyTransform.ConvertExpression(IExpression e xpr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\C opyTransform.cs:line 602 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertAssign(IAssignExp ression iae) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFra mework\ShallowCopyTransform.cs:line 401 at MicrosoftResearch.Transforms.CopyTransform.DoConvertExpression(IExpression expr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework \CopyTransform.cs:line 609 at MicrosoftResearch.Transforms.CopyTransform.ConvertExpression(IExpression e xpr) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\C opyTransform.cs:line 602 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertExpressionStateme nt(IExpressionStatement ies) in c:\Builds\2\infernet\External\src\infernet\Compi ler\TransformFramework\ShallowCopyTransform.cs:line 102 at MicrosoftResearch.Transforms.CopyTransform.DoConvertStatement(IStatement i st) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Co pyTransform.cs:line 464 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatement(IStatement ist ) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Copy Transform.cs:line 446 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatements(IList`1 outpu ts, IList`1 inputs) in c:\Builds\2\infernet\External\src\infernet\Compiler\Trans formFramework\CopyTransform.cs:line 396 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertBlockAlreadyOpen( IBlockStatement inputBlock) in c:\Builds\2\infernet\External\src\infernet\Compil er\TransformFramework\ShallowCopyTransform.cs:line 74 at MicrosoftResearch.Transforms.CopyTransform.ConvertBlock(IBlockStatement in putBlock) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramew ork\CopyTransform.cs:line 346 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertCondition(ICondit ionStatement ics) in c:\Builds\2\infernet\External\src\infernet\Compiler\Transfo rmFramework\ShallowCopyTransform.cs:line 91 at MicrosoftResearch.Transforms.CopyTransform.DoConvertStatement(IStatement i st) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Co pyTransform.cs:line 472 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatement(IStatement ist ) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Copy Transform.cs:line 446 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatements(IList`1 outpu ts, IList`1 inputs) in c:\Builds\2\infernet\External\src\infernet\Compiler\Trans formFramework\CopyTransform.cs:line 396 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertBlockAlreadyOpen( IBlockStatement inputBlock) in c:\Builds\2\infernet\External\src\infernet\Compil er\TransformFramework\ShallowCopyTransform.cs:line 74 at MicrosoftResearch.Transforms.CopyTransform.ConvertBlock(IBlockStatement in putBlock) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramew ork\CopyTransform.cs:line 346 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertCondition(ICondit ionStatement ics) in c:\Builds\2\infernet\External\src\infernet\Compiler\Transfo rmFramework\ShallowCopyTransform.cs:line 91 at MicrosoftResearch.Transforms.CopyTransform.DoConvertStatement(IStatement i st) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Co pyTransform.cs:line 472 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatement(IStatement ist ) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Copy Transform.cs:line 446 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatements(IList`1 outpu ts, IList`1 inputs) in c:\Builds\2\infernet\External\src\infernet\Compiler\Trans formFramework\CopyTransform.cs:line 396 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertBlockAlreadyOpen( IBlockStatement inputBlock) in c:\Builds\2\infernet\External\src\infernet\Compil er\TransformFramework\ShallowCopyTransform.cs:line 74 at MicrosoftResearch.Transforms.CopyTransform.ConvertBlock(IBlockStatement in putBlock) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramew ork\CopyTransform.cs:line 346 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertFor(IForStatement ifs) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\ ShallowCopyTransform.cs:line 116 at #h.#ln.ConvertFor(IForStatement #V) in c:\Builds\2\infernet\External\src\i nfernet\Compiler\Infer\Transforms\ReplicationTransform.cs:line 45 at MicrosoftResearch.Transforms.CopyTransform.DoConvertStatement(IStatement i st) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Co pyTransform.cs:line 476 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatement(IStatement ist ) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Copy Transform.cs:line 446 at MicrosoftResearch.Transforms.CopyTransform.ConvertStatements(IList`1 outpu ts, IList`1 inputs) in c:\Builds\2\infernet\External\src\infernet\Compiler\Trans formFramework\CopyTransform.cs:line 396 at MicrosoftResearch.Transforms.CopyTransform.DoConvertMethodBody(IList`1 out puts, IList`1 inputs) in c:\Builds\2\infernet\External\src\infernet\Compiler\Tra nsformFramework\CopyTransform.cs:line 321 at MicrosoftResearch.Transforms.CopyTransform.DoConvertMethod(IMethodDeclarat ion md, IMethodDeclaration imd) in c:\Builds\2\infernet\External\src\infernet\Co mpiler\TransformFramework\CopyTransform.cs:line 305 at MicrosoftResearch.Transforms.ShallowCopyTransform.DoConvertMethod(IMethodD eclaration md, IMethodDeclaration imd) in c:\Builds\2\infernet\External\src\infe rnet\Compiler\TransformFramework\ShallowCopyTransform.cs:line 53 at MicrosoftResearch.Transforms.CopyTransform.ConvertMethod(IMethodDeclaratio n imd) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework \CopyTransform.cs:line 156 at MicrosoftResearch.Transforms.CopyTransform.ConvertMethods(ITypeDeclaration td, ITypeDeclaration itd) in c:\Builds\2\infernet\External\src\infernet\Compile r\TransformFramework\CopyTransform.cs:line 137 at MicrosoftResearch.Transforms.CopyTransform.ConvertType(ITypeDeclaration it d) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\Cop yTransform.cs:line 64 at MicrosoftResearch.Transforms.ShallowCopyTransform.ConvertType(ITypeDeclara tion itd) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramew ork\ShallowCopyTransform.cs:line 20 at MicrosoftResearch.Transforms.CopyTransform.Transform(ITypeDeclaration itd) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFramework\CopyT ransform.cs:line 46 at MicrosoftResearch.Transforms.CodeTransformer.TransformToDeclaration(ITypeD eclaration typeDecl) in c:\Builds\2\infernet\External\src\infernet\Compiler\Tran sformFramework\CodeTransformer.cs:line 55 at MicrosoftResearch.Transforms.TransformerChain.TransformToDeclaration(IType Declaration itd, AttributeRegistry`2 inputAttributes, Boolean trackTransform, Bo olean showProgress, List`1& warnings, Boolean catchExceptions, Boolean treatWarn ingsAsErrors) in c:\Builds\2\infernet\External\src\infernet\Compiler\TransformFr amework\TransformerChain.cs:line 63 at MicrosoftResearch.Infer.ModelCompiler.GetTransformedDeclaration(ITypeDecla ration itd, MethodBase method, AttributeRegistry`2 inputAttributes) in c:\Builds \2\infernet\External\src\infernet\Compiler\Infer\ModelCompiler.cs:line 704 at MicrosoftResearch.Infer.ModelCompiler.CompileWithoutParams(ITypeDeclaratio n itd, MethodBase method, AttributeRegistry`2 inputAttributes) in c:\Builds\2\in fernet\External\src\infernet\Compiler\Infer\ModelCompiler.cs:line 757 at MicrosoftResearch.Infer.InferenceEngine.Compile() in c:\Builds\2\infernet\ External\src\infernet\Compiler\Infer\InferenceEngine.cs:line 223 at MicrosoftResearch.Infer.InferenceEngine.BuildAndCompile(Boolean inferOnlyS pecifiedVars, IEnumerable`1 vars) in c:\Builds\2\infernet\External\src\infernet\ Compiler\Infer\InferenceEngine.cs:line 637 at MicrosoftResearch.Infer.InferenceEngine.GetCompiledInferenceAlgorithm(Bool ean inferOnlySpecifiedVars, IVariable var) in c:\Builds\2\infernet\External\src\ infernet\Compiler\Infer\InferenceEngine.cs:line 598 at MicrosoftResearch.Infer.InferenceEngine.Infer[TReturn](IVariable var) in c :\Builds\2\infernet\External\src\infernet\Compiler\Infer\InferenceEngine.cs:line 272 at PrinterNightmare.LearnParameters(Boolean[] fuse, Boolean[] drum, Boolean[] toner, Boolean[] paper, Boolean[] roller, Boolean[] burning, Boolean[] quality, Boolean[] wrinkled, Boolean[] multPages, Boolean[] paperJam) in C:\Users\vladis lavsd\Documents\Visual Studio 2017\Projects\PrinterNightmare\PrinterNightmare.cs :line 191 at PrinterNightmare.Main() in C:\Users\vladislavsd\Documents\Visual Studio 20 17\Projects\PrinterNightmare\PrinterNightmare.cs:line 313
Wednesday, November 1, 2017 6:10 PM -
Thanks for the stack trace, that told me where the bug is. You have found a bug in Infer.NET. It will be fixed in the next version. Meanwhile, you can work around by using the following code:
public static VariableArray<bool> AddChildFromThreeParents(VariableArray<bool> parent1, VariableArray<bool> parent2, VariableArray<bool> parent3, VariableArray<VariableArray<VariableArray<double>, double[][]>, double[][][]> cpt) { var n = parent1.Range; var child = Variable.Array<bool>(n); using (Variable.ForEach(n)) { var parent2n = parent2[n] & Variable.Bernoulli(1.0); using (Variable.If(parent1[n])) { using (Variable.If(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][0][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][0][1]); } using (Variable.IfNot(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][1][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[0][1][1]); } } using (Variable.IfNot(parent1[n])) { using (Variable.If(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][0][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][0][1]); } using (Variable.IfNot(parent2n)) { using (Variable.If(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][1][0]); using (Variable.IfNot(parent3[n])) child[n] = Variable.Bernoulli(cpt[1][1][1]); } } } return child; }
- Marked as answer by usptact Wednesday, November 1, 2017 7:44 PM
Wednesday, November 1, 2017 7:14 PMOwner -
Thank you very much, Tom! I was tinkering with this function and noticed that the error appeared whenever the 3rd branching with Variable.If() / Variable.IfNot() was created.
Your workaround works!
Is the new release coming any time soon, if I may ask? Will it be more like bug fixing or there will be some breaking changes? Just curious what is in store.
Wednesday, November 1, 2017 7:47 PM -
The upcoming changes are listed at release change history.Wednesday, November 1, 2017 9:30 PMOwner
-
Infer.NET version 2.7 is now out and fixes this problem.
- Marked as answer by usptact Monday, April 2, 2018 3:47 PM
Sunday, April 1, 2018 2:51 PMOwner -
This is great news! I am very excited!
Tom, thank you for the great work on the framework and for the support in the forum here! Thank you a lot!
Monday, April 2, 2018 3:48 PM