Nested switch blocks - newbie question
-
Friday, 10 February 2012 2:16 PMCan one use nested switch blocks that are conditioned on different Variable<int> variables in Infer.Net? When I am trying to do it I am getting the following exception:
An unhandled exception of type 'System.InvalidOperationException' occurred in Infer.Compiler.dll
Additional information: Range 'index0' is already open in a ForEach or Switch block
All Replies
-
Saturday, 11 February 2012 12:22 PM
Yes, you can have nested switch blocks. You are probably getting this error because both variables are using the same ValueRange. If so, you will need to use range cloning as described here.- Marked As Answer by Bayesian learner Saturday, 11 February 2012 10:14 PM
-
Tuesday, 10 April 2012 8:50 PM
I have a very similar question. I get the same error: "Range g2VertexRangeClone is already open in a ForEach or Switch block" on the line //*. I've tried changing the ValueRange like in the example you linked, but that hasn't solved it. What am I missing?
//Constructed above: bool[][] g2AdjacencyMatrixObserved, int[] g1EdgesSourceVerticesObserved, int[] g1EdgesSinkVerticesObserved Range g1VertexRange = new Range(g1.VertexCount).Named("g1VertexRange"); Range g1VertexRangeClone = g1VertexRange.Clone().Named("g1VertexRangeClone"); Range g2VertexRange = new Range(g2.VertexCount).Named("g2VertexRange"); Range g2VertexRangeClone = g2VertexRange.Clone().Named("g2VertexRangeClone"); Range g1EdgeRange = new Range(g1.EdgeCount).Named("g1EdgeRange"); Range g1EdgeRangeClone = g1EdgeRange.Clone().Named("g1EdgeRangeClone"); var g2AdjacencyMatrix = Variable.Array(Variable.Array<bool>(g2VertexRangeClone), g2VertexRange); g2AdjacencyMatrix.ObservedValue = g2AdjacencyMatrixObserved; VariableArray<int> g1EdgesSourceVertices = Variable.Observed(g1EdgeSourceVerticesObserved, g1EdgeRange); g1EdgesSourceVertices.SetValueRange(g1VertexRange); VariableArray<int> g1EdgesSinkVertices = Variable.Observed(g1EdgeSinkVerticesObserved, g1EdgeRangeClone); g1EdgesSinkVertices.SetValueRange(g1VertexRangeClone); VariableArray<int> labels = Variable.Array<int>(g1VertexRange); labels[g1VertexRange] = Variable.DiscreteUniform(g2VertexRange).ForEach(g1VertexRange); VariableArray<bool> areG1EdgesInG2 = Variable.Array<bool>(g1EdgeRange); areG1EdgesInG2[g1EdgeRange] = Variable.Bernoulli(0.99).ForEach(g1EdgeRange); using (Variable.ForEach(g1EdgeRange)) { var l1 = labels[g1EdgesSourceVertices[g1EdgeRange]]; var l2 = labels[g1EdgesSinkVertices[g1EdgeRange]]; l2.SetValueRange(g2VertexRangeClone); using (Variable.Switch(l1)) using (Variable.Switch(l2)) areG1EdgesInG2[g1EdgeRange] = g2AdjacencyMatrix[l1][l2]; //* }
InferenceEngine.Infer(labels);Here is some background into my problem, if it helps. I'm trying to do some graph matching. I have two graphs g1 and g2. My model says each vertex in g1 can be labelled as any vertex in g2. Each edge in g1 has a 99% chance of corresponding to an edge between the labelled vertices in g2. It's not a very good model, but I'd like to get this one working before I enhance it. Thanks for any advice you have.
-
Sunday, 22 April 2012 9:35 AM
When you set the ValueRange of l2, you are actually setting the ValueRange of the entire labels array, which means that l1's ValueRange changes as well. Try changing the definition of l2 to:
var l2 = Variable.Copy(labels[g1EdgesSinkVertices[g1EdgeRange]]);
By the way, you also have two definitions of areG1EdgesInG2. The first one should be deleted.