Example #1
0
 private void CreateUsesChannel(VariableInformation vi, int useCount, VariableToChannelInformation vtci, IList <IStatement> stmts)
 {
     vtci.usageChannel      = ChannelInfo.UseChannel(vi);
     vtci.usageChannel.decl = vi.DeriveArrayVariable(stmts, context, vi.Name + "_uses", Builder.LiteralExpr(useCount), Builder.VarDecl("_ind", typeof(int)), useLiteralIndices: true);
     context.InputAttributes.CopyObjectAttributesTo <InitialiseTo>(vi.declaration, context.OutputAttributes, vtci.usageChannel.decl);
     context.OutputAttributes.Set(vtci.usageChannel.decl, vtci.usageChannel);
     context.OutputAttributes.Set(vtci.usageChannel.decl, new DescriptionAttribute("uses of '" + vi.Name + "'"));
 }
Example #2
0
        /// <summary>
        /// Modify the argument of Infer to be the marginal channel variable i.e. Infer(a) transforms to Infer(a_marginal).
        /// </summary>
        /// <param name="imie"></param>
        /// <returns></returns>
        protected IExpression ConvertInfer(IMethodInvokeExpression imie)
        {
            IVariableReferenceExpression ivre = imie.Arguments[0] as IVariableReferenceExpression;

            if (ivre == null)
            {
                //Error("Argument to Infer() must be a variable reference, was " + imie.Arguments[0] + ".");
                return(imie);
            }
            // Find expression for the marginal of interest
            IVariableDeclaration         ivd  = ivre.Variable.Resolve();
            VariableToChannelInformation vtci = context.InputAttributes.Get <VariableToChannelInformation>(ivd);

            if (vtci == null)
            {
                return(imie);              // The argument is constant
            }
            ExpressionEvaluator  eval      = new ExpressionEvaluator();
            QueryType            query     = (QueryType)eval.Evaluate(imie.Arguments[2]);
            IVariableDeclaration inferDecl = null;

            if (query == QueryTypes.Marginal)
            {
                inferDecl = vtci.marginalChannel.decl;
            }
            else if (query == QueryTypes.Samples)
            {
                inferDecl = vtci.samplesChannel.decl;
            }
            else if (query == QueryTypes.Conditionals)
            {
                inferDecl = vtci.conditionalsChannel.decl;
            }
            else
            {
                return(imie); // Error("Unrecognized query '"+query+"'");
            }
            IMethodInvokeExpression mie = Builder.MethodInvkExpr();

            mie.Method = imie.Method;
            mie.Arguments.Add(Builder.VarRefExpr(inferDecl));
            for (int i = 1; i < imie.Arguments.Count; i++)
            {
                mie.Arguments.Add(imie.Arguments[i]);
            }
            // move the IsInferred attribute to the inferred channel
            context.OutputAttributes.Remove <IsInferred>(ivd);
            if (!context.OutputAttributes.Has <IsInferred>(inferDecl))
            {
                context.OutputAttributes.Set(inferDecl, new IsInferred());
                context.OutputAttributes.Add(inferDecl, new QueryTypeCompilerAttribute(query));
            }
            return(mie);
        }
Example #3
0
        private void CreateMarginalChannel(VariableInformation vi, VariableToChannelInformation vtc, IList <IStatement> stmts)
        {
            IVariableDeclaration marginalDecl = vi.DeriveIndexedVariable(stmts, context, vi.Name + "_marginal");

            vtc.marginalChannel      = ChannelInfo.MarginalChannel(vi);
            vtc.marginalChannel.decl = marginalDecl;
            context.InputAttributes.CopyObjectAttributesTo <InitialiseTo>(vi.declaration, context.OutputAttributes, vtc.marginalChannel.decl);
            context.OutputAttributes.Set(vtc.marginalChannel.decl, vtc.marginalChannel);
            context.OutputAttributes.Set(vtc.marginalChannel.decl, new DescriptionAttribute("marginal of '" + vi.Name + "'"));
            VariableInformation marginalInformation = VariableInformation.GetVariableInformation(context, marginalDecl);

            marginalInformation.IsStochastic = true;
        }
Example #4
0
        /// <summary>
        /// When array creations are assigned to stochastic arrays, this creates corresponding arrays for the marginal and uses channels.
        /// </summary>
        /// <param name="iace"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayCreate(IArrayCreateExpression iace)
        {
            IAssignExpression iae = context.FindAncestor <IAssignExpression>();

            if (iae == null)
            {
                return(iace);
            }
            if (iae.Expression != iace)
            {
                return(iace);
            }
            IVariableDeclaration         ivd  = Recognizer.GetVariableDeclaration(iae.Target);
            VariableToChannelInformation vtci = context.InputAttributes.Get <VariableToChannelInformation>(ivd);

            if (vtci == null)
            {
                return(iace);              // not a stochastic variable
            }
            // Check if this is the last level of indexing
            bool lastLevel = (!(iace.Type is IArrayType));

            if ((lastLevel) && (vtci.usesEqualDefsStatements != null))
            {
                if (vtci.IsUsesEqualDefsStatementInserted)
                {
                    //Error("Duplicate array allocation.");
                }
                else
                {
                    // Insert the UsesEqualDef statement after the array is fully allocated.
                    // Note the array elements will not have been defined yet.
                    LoopContext    lc  = context.InputAttributes.Get <LoopContext>(ivd);
                    RefLoopContext rlc = lc.GetReferenceLoopContext(context);
                    // IMPORTANT TODO: add this statement at the right level!
                    IStatement ist = context.FindAncestor <IStatement>();
                    if (rlc.loops.Count > 0)
                    {
                        ist = rlc.loops[0];
                    }
                    int        ancIndex         = context.GetAncestorIndex(ist);
                    Containers containers       = context.InputAttributes.Get <Containers>(ivd);
                    Containers containersNeeded = containers.GetContainersNotInContext(context, ancIndex);
                    vtci.usesEqualDefsStatements = Containers.WrapWithContainers(vtci.usesEqualDefsStatements, containersNeeded.outputs);
                    context.AddStatementsAfter(ist, vtci.usesEqualDefsStatements);
                    vtci.IsUsesEqualDefsStatementInserted = true;
                }
            }
            return(iace);
        }
Example #5
0
        private void CreateSamplesChannel(VariableInformation vi, VariableToChannelInformation vtci, IList <IStatement> stmts)
        {
            vtci.samplesChannel      = ChannelInfo.MarginalChannel(vi);
            vtci.samplesChannel.decl = vi.DeriveIndexedVariable(stmts, context, vi.Name + "_samples");
            context.OutputAttributes.Remove <InitialiseTo>(vtci.samplesChannel.decl);
            context.OutputAttributes.Set(vtci.samplesChannel.decl, vtci.samplesChannel);
            context.OutputAttributes.Set(vtci.samplesChannel.decl, new DescriptionAttribute("samples of '" + vi.Name + "'"));
            Type                domainType  = vi.VariableType.DotNetType;
            Type                samplesType = typeof(List <>).MakeGenericType(domainType);
            IExpression         samples_mpe = Builder.NewObject(samplesType);
            VariableInformation samples_vi  = VariableInformation.GetVariableInformation(context, vtci.samplesChannel.decl);

            samples_vi.marginalPrototypeExpression = samples_mpe;
        }
Example #6
0
        private object AddMarginalStatements(IExpression expr)
        {
            object decl = Recognizer.GetDeclaration(expr);

            if (!context.InputAttributes.Has <VariableToChannelInformation>(decl))
            {
                VariableInformation vi = VariableInformation.GetVariableInformation(context, decl);
                vi.DefineAllIndexVars(context);
                IList <IStatement> stmts = Builder.StmtCollection();

                VariableToChannelInformation vtci = new VariableToChannelInformation();
                vtci.shareAllUses = true;
                Context.InputAttributes.Set(decl, vtci);

                CreateMarginalChannel(vi, vtci, stmts);
                IExpression marginalExpr = Builder.VarRefExpr(vtci.marginalChannel.decl);
                Type[]      genArgs      = new Type[] { expr.GetExpressionType() };
                IExpression countExpr    = Builder.LiteralExpr(0);
                IExpression variableFactorExpr;
                if (algorithm is GibbsSampling && ((GibbsSampling)algorithm).UseSideChannels)
                {
                    CreateSamplesChannel(vi, vtci, stmts);
                    CreateConditionalsChannel(vi, vtci, stmts);

                    IExpression burnInExpr       = Builder.LiteralExpr(0);
                    IExpression thinExpr         = Builder.LiteralExpr(1);
                    IExpression samplesExpr      = Builder.VarRefExpr(vtci.samplesChannel.decl);
                    IExpression conditionalsExpr = Builder.VarRefExpr(vtci.conditionalsChannel.decl);
                    Delegate    d = new FuncOut3 <PlaceHolder, int, int, int, PlaceHolder, PlaceHolder, PlaceHolder, PlaceHolder[]>(Clone.ReplicateWithMarginalGibbs);
                    variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, expr, countExpr, burnInExpr, thinExpr, marginalExpr, samplesExpr, conditionalsExpr);
                }
                else
                {
                    vtci.samplesChannel      = vtci.marginalChannel;
                    vtci.conditionalsChannel = vtci.marginalChannel;

                    Delegate d = new FuncOut <PlaceHolder, int, PlaceHolder, PlaceHolder[]>(Clone.ReplicateWithMarginal);
                    variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, expr, countExpr, marginalExpr);
                }
                CreateUsesChannel(vi, 0, vtci, stmts);
                IExpression usesExpr = Builder.VarRefExpr(vtci.usageChannel.decl);
                vtci.usageChannel = null;
                stmts.Add(Builder.AssignStmt(usesExpr, variableFactorExpr));
                context.OutputAttributes.Set(variableFactorExpr, new IsVariableFactor());

                context.AddStatementsBeforeCurrent(stmts);
            }
            return(decl);
        }
Example #7
0
        private void CreateConditionalsChannel(VariableInformation vi, VariableToChannelInformation vtci, IList <IStatement> stmts)
        {
            vtci.conditionalsChannel      = ChannelInfo.MarginalChannel(vi);
            vtci.conditionalsChannel.decl = vi.DeriveIndexedVariable(stmts, context, vi.Name + "_conditionals");
            context.OutputAttributes.Remove <InitialiseTo>(vtci.conditionalsChannel.decl);
            context.OutputAttributes.Set(vtci.conditionalsChannel.decl, vtci.conditionalsChannel);
            context.OutputAttributes.Set(vtci.conditionalsChannel.decl, new DescriptionAttribute("conditionals of '" + vi.Name + "'"));
            Type marginalType = MessageTransform.GetDistributionType(vi.varType, vi.InnermostElementType,
                                                                     vi.marginalPrototypeExpression.GetExpressionType(), true);
            Type                conditionalsType = typeof(List <>).MakeGenericType(marginalType);
            IExpression         conditionals_mpe = Builder.NewObject(conditionalsType);
            VariableInformation conditionals_vi  = VariableInformation.GetVariableInformation(context, vtci.conditionalsChannel.decl);

            conditionals_vi.marginalPrototypeExpression = conditionals_mpe;
        }
        private int GetUseNumber(IVariableDeclaration ivd, VariableToChannelInformation vtci)
        {
            var        info = analysis.usageInfo[ivd];
            IStatement st   = context.FindAncestorNotSelf <IStatement>();
            int        useNumber;

            if (info.useNumberOfStatement.TryGetValue(st, out Queue <int> queue))
            {
                useNumber = queue.Dequeue();
            }
            else
            {
                useNumber = vtci.useCount++;
            }
            return(useNumber);
        }
        private VariableToChannelInformation DeclareUsesArray(IList <IStatement> stmts, IVariableDeclaration ivd, VariableInformation vi, int useCount, int usageDepth)
        {
            // Create AnyIndex expressions up to usageDepth
            List <IList <IExpression> > prefixSizes = new List <IList <IExpression> >();
            List <IList <IExpression> > prefixVars  = new List <IList <IExpression> >();

            vi.DefineAllIndexVars(context);
            for (int d = 0; d < usageDepth; d++)
            {
                IList <IExpression> sizeBracket = Builder.ExprCollection();
                IList <IExpression> varBracket  = Builder.ExprCollection();
                for (int i = 0; i < vi.sizes[d].Length; i++)
                {
                    sizeBracket.Add(Builder.StaticMethod(new Func <int>(GateAnalysisTransform.AnyIndex)));
                    varBracket.Add(Builder.VarRefExpr(vi.indexVars[d][i]));
                }
                prefixSizes.Add(sizeBracket);
                prefixVars.Add(varBracket);
            }
            string prefix = vi.Name;

            if (prefix.EndsWith("_use"))
            {
                prefix = prefix.Substring(0, prefix.Length - 4);
            }
            string arrayName = VariableInformation.GenerateName(context, prefix + "_uses");
            IVariableDeclaration usesDecl = vi.DeriveArrayVariable(stmts, context, arrayName, Builder.LiteralExpr(useCount), Builder.VarDecl("_ind", typeof(int)),
                                                                   prefixSizes, prefixVars, useLiteralIndices: true);

            context.OutputAttributes.Remove <ChannelInfo>(usesDecl);
            context.OutputAttributes.Add(usesDecl, new DescriptionAttribute($"uses of '{vi.Name}'"));
            ChannelInfo ci = ChannelInfo.UseChannel(vi);

            ci.decl = usesDecl;
            context.OutputAttributes.Set(usesDecl, ci);
            VariableToChannelInformation vtci = new VariableToChannelInformation();

            vtci.usesDecl       = usesDecl;
            vtci.usageDepth     = usageDepth;
            usesOfVariable[ivd] = vtci;
            return(vtci);
        }
Example #10
0
        /// <summary>
        /// Converts an array indexed expression.
        /// </summary>
        /// <param name="iaie"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            IExpression expr = base.ConvertArrayIndexer(iaie);

            // Check if this is the top level indexer
            if (Recognizer.IsBeingIndexed(context))
            {
                return(expr);
            }
            IExpression target;
            List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out target);

            if (!(target is IVariableReferenceExpression))
            {
                return(expr);
            }
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target);

            if (ivd == null)
            {
                return(expr);
            }
            VariableToChannelInformation vtci = Context.InputAttributes.Get <VariableToChannelInformation>(ivd);

            if (vtci == null)
            {
                return(expr);
            }
            if (vtci.usageChannel == null)
            {
                return(expr);
            }
            bool isDef = Recognizer.IsBeingMutated(context, expr);

            if (isDef)
            {
                return(expr);
            }
            return(vtci.usageChannel.ReplaceWithUsesChannel(expr, Builder.LiteralExpr(vtci.shareAllUses ? 0 : vtci.useCount++)));
        }
Example #11
0
        /// <summary>
        /// Converts a variable reference.
        /// </summary>
        /// <param name="ivre"></param>
        /// <returns></returns>
        protected override IExpression ConvertVariableRefExpr(IVariableReferenceExpression ivre)
        {
            IVariableDeclaration         ivd  = ivre.Variable.Resolve();
            VariableToChannelInformation vtci = Context.InputAttributes.Get <VariableToChannelInformation>(ivd);

            // If deterministic variable do nothing.
            if (vtci == null || vtci.usageChannel == null)
            {
                return(ivre);
            }
            else if (Recognizer.IsBeingIndexed(context))
            {
                return(ivre);
            }
            else if (Recognizer.IsBeingMutated(context, ivre))
            {
                return(ivre);
            }
            else
            {
                return(vtci.usageChannel.ReplaceWithUsesChannel(ivre, Builder.LiteralExpr(vtci.shareAllUses ? 0 : vtci.useCount++)));
            }
        }
Example #12
0
        /// <summary>
        /// Converts a variable declaration by creating definition, marginal and uses channel variables.
        /// </summary>
        protected override IExpression ConvertVariableDeclExpr(IVariableDeclarationExpression ivde)
        {
            IVariableDeclaration ivd = ivde.Variable;
            VariableInformation  vi  = VariableInformation.GetVariableInformation(context, ivd);

            // If the variable is deterministic, return
            bool isInferred = context.InputAttributes.Has <IsInferred>(ivd);

            if (!vi.IsStochastic)
            {
                return(ivde);
            }
            bool suppressVariableFactor = context.InputAttributes.Has <SuppressVariableFactor>(ivd);
            bool isDerived    = context.InputAttributes.Has <DerivedVariable>(ivd);
            bool isStochastic = vi.IsStochastic;
            int  useCount;

            ChannelAnalysisTransform.UsageInfo info;
            if (!analysis.usageInfo.TryGetValue(ivd, out info))
            {
                useCount = 0;
            }
            else
            {
                useCount = info.NumberOfUsesOld;
            }
            if (!(algorithm is Algorithms.GibbsSampling) && isStochastic && !suppressVariableFactor && (useCount <= 1) && !isInferred && isDerived)
            {
                // this is optional
                suppressVariableFactor = true;
                context.InputAttributes.Set(ivd, new SuppressVariableFactor());
            }
            context.InputAttributes.Remove <LoopContext>(ivd);
            context.InputAttributes.Set(ivd, new LoopContext(context));

            // Create variable-to-channel information for the variable.
            VariableToChannelInformation vtci = new VariableToChannelInformation();

            vtci.shareAllUses = (useCount <= 1);
            Context.InputAttributes.Set(ivd, vtci);

            // Create the definition channel
            vtci.defChannel      = ChannelInfo.DefChannel(vi);
            vtci.defChannel.decl = ivd;
            // Always create a variable factor for a stochastic variable
            if (isInferred || (isStochastic && !suppressVariableFactor))
            {
                vi.DefineAllIndexVars(context);
                IList <IStatement> stmts = Builder.StmtCollection();

                // Create marginal channel
                CreateMarginalChannel(vi, vtci, stmts);
                if (algorithm is GibbsSampling && ((GibbsSampling)algorithm).UseSideChannels)
                {
                    CreateSamplesChannel(vi, vtci, stmts);
                    CreateConditionalsChannel(vi, vtci, stmts);
                }
                else
                {
                    vtci.samplesChannel      = vtci.marginalChannel;
                    vtci.conditionalsChannel = vtci.marginalChannel;
                }
                if (isStochastic)
                {
                    // Create uses channel
                    CreateUsesChannel(vi, useCount, vtci, stmts);
                }

                //setAllGroupRoots(context, ivd, false);

                context.AddStatementsBeforeCurrent(stmts);

                // Append usageDepth indices to def/marginal/use expressions
                IExpression defExpr      = Builder.VarRefExpr(ivd);
                IExpression marginalExpr = Builder.VarRefExpr(vtci.marginalChannel.decl);
                IExpression countExpr    = Builder.LiteralExpr(useCount);

                // Add clone factor tying together all of the channels
                IMethodInvokeExpression variableFactorExpr;
                Type[] genArgs = new Type[] { vi.varType };
                if (algorithm is GibbsSampling && ((GibbsSampling)algorithm).UseSideChannels)
                {
                    GibbsSampling gs               = (GibbsSampling)algorithm;
                    IExpression   burnInExpr       = Builder.LiteralExpr(gs.BurnIn);
                    IExpression   thinExpr         = Builder.LiteralExpr(gs.Thin);
                    IExpression   samplesExpr      = Builder.VarRefExpr(vtci.samplesChannel.decl);
                    IExpression   conditionalsExpr = Builder.VarRefExpr(vtci.conditionalsChannel.decl);
                    if (isDerived)
                    {
                        Delegate d = new FuncOut3 <PlaceHolder, int, int, int, PlaceHolder, PlaceHolder, PlaceHolder, PlaceHolder[]>(Clone.ReplicateWithMarginalGibbs);
                        variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, defExpr, countExpr, burnInExpr, thinExpr, marginalExpr, samplesExpr, conditionalsExpr);
                    }
                    else
                    {
                        Delegate d = new FuncOut3 <PlaceHolder, int, int, int, PlaceHolder, PlaceHolder, PlaceHolder, PlaceHolder[]>(Clone.UsesEqualDefGibbs);
                        variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, defExpr, countExpr, burnInExpr, thinExpr, marginalExpr, samplesExpr, conditionalsExpr);
                    }
                }
                else
                {
                    Delegate d;
                    if (isDerived)
                    {
                        d = new FuncOut <PlaceHolder, int, PlaceHolder, PlaceHolder[]>(Clone.ReplicateWithMarginal <PlaceHolder>);
                    }
                    else
                    {
                        d = new FuncOut <PlaceHolder, int, PlaceHolder, PlaceHolder[]>(Clone.UsesEqualDef <PlaceHolder>);
                    }
                    variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, defExpr, countExpr, marginalExpr);
                }
                if (isDerived)
                {
                    context.OutputAttributes.Set(variableFactorExpr, new DerivedVariable());            // used by Gibbs
                }
                // Mark this as a pseudo-factor
                context.OutputAttributes.Set(variableFactorExpr, new IsVariableFactor());
                if (useCount <= 1)
                {
                    context.OutputAttributes.Set(variableFactorExpr, new DivideMessages(false));
                }
                else
                {
                    context.InputAttributes.CopyObjectAttributesTo <DivideMessages>(ivd, context.OutputAttributes, variableFactorExpr);
                }
                context.InputAttributes.CopyObjectAttributesTo <GivePriorityTo>(ivd, context.OutputAttributes, variableFactorExpr);
                if (vtci.usageChannel != null)
                {
                    IExpression       usageExpr  = Builder.VarRefExpr(vtci.usageChannel.decl);
                    IAssignExpression assignExpr = Builder.AssignExpr(usageExpr, variableFactorExpr);
                    // Copy attributes across from input to output
                    Context.InputAttributes.CopyObjectAttributesTo <Algorithm>(ivd, context.OutputAttributes, assignExpr);
                    context.OutputAttributes.Remove <InitialiseTo>(ivd);
                    if (vi.ArrayDepth == 0)
                    {
                        // Insert the UsesEqualDef statement after the declaration.
                        // Note the variable will not have been defined yet.
                        context.AddStatementAfterCurrent(Builder.ExprStatement(assignExpr));
                    }
                    else
                    {
                        // For an array, the UsesEqualDef statement should be inserted after the array is allocated.
                        // Store the statement for later use by ConvertArrayCreate.
                        context.InputAttributes.Remove <LoopContext>(ivd);
                        context.InputAttributes.Set(ivd, new LoopContext(context));
                        context.InputAttributes.Remove <Containers>(ivd);
                        context.InputAttributes.Set(ivd, new Containers(context));
                        vtci.usesEqualDefsStatements = Builder.StmtCollection();
                        vtci.usesEqualDefsStatements.Add(Builder.ExprStatement(assignExpr));
                    }
                }
            }
            // These must be set after the above or they will be copied to the other channels
            if (isStochastic)
            {
                context.OutputAttributes.Set(ivd, vtci.defChannel);
            }
            if (!context.InputAttributes.Has <DescriptionAttribute>(vtci.defChannel.decl))
            {
                context.OutputAttributes.Set(vtci.defChannel.decl, new DescriptionAttribute("definition of '" + ivd.Name + "'"));
            }
            return(ivde);
        }
Example #13
0
        /// <summary>
        /// Converts a variable declaration by creating definition, marginal and uses channel variables.
        /// </summary>
        protected override IExpression ConvertVariableDeclExpr(IVariableDeclarationExpression ivde)
        {
            IVariableDeclaration ivd = ivde.Variable;
            VariableInformation  vi  = VariableInformation.GetVariableInformation(context, ivd);

            // If the variable is deterministic, return
            if (!vi.IsStochastic)
            {
                ProcessConstant(ivd);
                context.OutputAttributes.Set(ivd, new DescriptionAttribute("The constant '" + ivd.Name + "'"));
                return(ivde);
            }
            bool suppressVariableFactor = context.InputAttributes.Has <SuppressVariableFactor>(ivd);
            bool isDerived  = context.InputAttributes.Has <DerivedVariable>(ivd);
            bool isConstant = false;
            bool isInferred = context.InputAttributes.Has <IsInferred>(ivd);
            int  useCount;

            ChannelAnalysisTransform.UsageInfo info;
            if (!analysis.usageInfo.TryGetValue(ivd, out info))
            {
                useCount = 0;
            }
            else
            {
                useCount = info.NumberOfUsesOld;
            }
            if (!(algorithm is Algorithms.GibbsSampling) && !isConstant && !suppressVariableFactor && (useCount == 1) && !isInferred && isDerived)
            {
                // this is optional
                suppressVariableFactor = true;
                context.InputAttributes.Set(ivd, new SuppressVariableFactor());
            }
            context.InputAttributes.Remove <LoopContext>(ivd);
            context.InputAttributes.Set(ivd, new LoopContext(context));

            // Create variable-to-channel information for the variable.
            VariableToChannelInformation vtc = new VariableToChannelInformation();

            vtc.shareAllUses = (useCount == 1);
            Context.InputAttributes.Set(ivd, vtc);

            // Ensure the marginal prototype is set.
            MarginalPrototype mpa = Context.InputAttributes.Get <MarginalPrototype>(ivd);

            try
            {
                vi.SetMarginalPrototypeFromAttribute(mpa);
            }
            catch (ArgumentException ex)
            {
                Error(ex.Message);
            }

            // Create the definition channel
            vtc.defChannel      = ChannelInfo.DefChannel(vi);
            vtc.defChannel.decl = ivd;
            // Always create a variable factor for a stochastic variable
            if (!isConstant && !suppressVariableFactor)
            {
                vi.DefineAllIndexVars(context);
                IList <IStatement> stmts = Builder.StmtCollection();

                // Create marginal channel
                vtc.marginalChannel      = ChannelInfo.MarginalChannel(vi);
                vtc.marginalChannel.decl = vi.DeriveIndexedVariable(stmts, context, vi.Name + "_marginal");
                context.InputAttributes.CopyObjectAttributesTo <InitialiseTo>(vi.declaration, context.OutputAttributes, vtc.marginalChannel.decl);
                context.OutputAttributes.Set(vtc.marginalChannel.decl, vtc.marginalChannel);
                context.OutputAttributes.Set(vtc.marginalChannel.decl, new DescriptionAttribute("marginal of '" + ivd.Name + "'"));
                SetMarginalPrototype(vtc.marginalChannel.decl);
                if (algorithm is GibbsSampling && ((GibbsSampling)algorithm).UseSideChannels)
                {
                    Type marginalType = MessageTransform.GetDistributionType(vi.varType, vi.InnermostElementType,
                                                                             vi.marginalPrototypeExpression.GetExpressionType(), true);
                    Type domainType = ivd.VariableType.DotNetType;

                    vtc.samplesChannel      = ChannelInfo.MarginalChannel(vi);
                    vtc.samplesChannel.decl = vi.DeriveIndexedVariable(stmts, context, vi.Name + "_samples");
                    context.OutputAttributes.Remove <InitialiseTo>(vtc.samplesChannel.decl);
                    context.OutputAttributes.Set(vtc.samplesChannel.decl, vtc.samplesChannel);
                    context.OutputAttributes.Set(vtc.samplesChannel.decl, new DescriptionAttribute("samples of '" + ivd.Name + "'"));
                    Type                samplesType = typeof(List <>).MakeGenericType(domainType);
                    IExpression         samples_mpe = Builder.NewObject(samplesType);
                    VariableInformation samples_vi  = VariableInformation.GetVariableInformation(context, vtc.samplesChannel.decl);
                    samples_vi.marginalPrototypeExpression = samples_mpe;

                    vtc.conditionalsChannel      = ChannelInfo.MarginalChannel(vi);
                    vtc.conditionalsChannel.decl = vi.DeriveIndexedVariable(stmts, context, vi.Name + "_conditionals");
                    context.OutputAttributes.Remove <InitialiseTo>(vtc.conditionalsChannel.decl);
                    context.OutputAttributes.Set(vtc.conditionalsChannel.decl, vtc.conditionalsChannel);
                    context.OutputAttributes.Set(vtc.conditionalsChannel.decl, new DescriptionAttribute("conditionals of '" + ivd.Name + "'"));
                    Type                conditionalsType = typeof(List <>).MakeGenericType(marginalType);
                    IExpression         conditionals_mpe = Builder.NewObject(conditionalsType);
                    VariableInformation conditionals_vi  = VariableInformation.GetVariableInformation(context, vtc.conditionalsChannel.decl);
                    conditionals_vi.marginalPrototypeExpression = conditionals_mpe;
                }
                else
                {
                    vtc.samplesChannel      = vtc.marginalChannel;
                    vtc.conditionalsChannel = vtc.marginalChannel;
                }

                // Create uses channel
                vtc.usageChannel      = ChannelInfo.UseChannel(vi);
                vtc.usageChannel.decl = vi.DeriveArrayVariable(stmts, context, vi.Name + "_uses", Builder.LiteralExpr(useCount), Builder.VarDecl("_ind", typeof(int)), useLiteralIndices: true);
                context.InputAttributes.CopyObjectAttributesTo <InitialiseTo>(vi.declaration, context.OutputAttributes, vtc.usageChannel.decl);
                context.OutputAttributes.Set(vtc.usageChannel.decl, vtc.usageChannel);
                context.OutputAttributes.Set(vtc.usageChannel.decl, new DescriptionAttribute("uses of '" + ivd.Name + "'"));
                SetMarginalPrototype(vtc.usageChannel.decl);

                //setAllGroupRoots(context, ivd, false);

                context.AddStatementsBeforeCurrent(stmts);

                // Append usageDepth indices to def/marginal/use expressions
                IExpression defExpr      = Builder.VarRefExpr(ivd);
                IExpression marginalExpr = Builder.VarRefExpr(vtc.marginalChannel.decl);
                IExpression usageExpr    = Builder.VarRefExpr(vtc.usageChannel.decl);
                IExpression countExpr    = Builder.LiteralExpr(useCount);

                // Add clone factor tying together all of the channels
                IMethodInvokeExpression usesEqualDefExpression;
                Type[] genArgs = new Type[] { vi.varType };
                if (algorithm is GibbsSampling && ((GibbsSampling)algorithm).UseSideChannels)
                {
                    GibbsSampling gs               = (GibbsSampling)algorithm;
                    IExpression   burnInExpr       = Builder.LiteralExpr(gs.BurnIn);
                    IExpression   thinExpr         = Builder.LiteralExpr(gs.Thin);
                    IExpression   samplesExpr      = Builder.VarRefExpr(vtc.samplesChannel.decl);
                    IExpression   conditionalsExpr = Builder.VarRefExpr(vtc.conditionalsChannel.decl);
                    if (isDerived)
                    {
                        Delegate d = new FuncOut3 <PlaceHolder, int, int, int, PlaceHolder, PlaceHolder, PlaceHolder, PlaceHolder[]>(Factor.ReplicateWithMarginalGibbs);
                        usesEqualDefExpression = Builder.StaticGenericMethod(d, genArgs, defExpr, countExpr, burnInExpr, thinExpr, marginalExpr, samplesExpr, conditionalsExpr);
                    }
                    else
                    {
                        Delegate d = new FuncOut3 <PlaceHolder, int, int, int, PlaceHolder, PlaceHolder, PlaceHolder, PlaceHolder[]>(Factor.UsesEqualDefGibbs);
                        usesEqualDefExpression = Builder.StaticGenericMethod(d, genArgs, defExpr, countExpr, burnInExpr, thinExpr, marginalExpr, samplesExpr, conditionalsExpr);
                    }
                }
                else
                {
                    Delegate d;
                    if (isDerived)
                    {
                        d = new FuncOut <PlaceHolder, int, PlaceHolder, PlaceHolder[]>(Factor.ReplicateWithMarginal <PlaceHolder>);
                    }
                    else
                    {
                        d = new FuncOut <PlaceHolder, int, PlaceHolder, PlaceHolder[]>(Factor.UsesEqualDef <PlaceHolder>);
                    }
                    usesEqualDefExpression = Builder.StaticGenericMethod(d, genArgs, defExpr, countExpr, marginalExpr);
                }
                if (isDerived)
                {
                    context.OutputAttributes.Set(usesEqualDefExpression, new DerivedVariable());            // used by Gibbs
                }
                // Mark this as a pseudo-factor
                context.OutputAttributes.Set(usesEqualDefExpression, new IsVariableFactor());
                if (useCount == 1)
                {
                    context.OutputAttributes.Set(usesEqualDefExpression, new DivideMessages(false));
                }
                else
                {
                    context.InputAttributes.CopyObjectAttributesTo <DivideMessages>(ivd, context.OutputAttributes, usesEqualDefExpression);
                }
                context.InputAttributes.CopyObjectAttributesTo <GivePriorityTo>(ivd, context.OutputAttributes, usesEqualDefExpression);
                IAssignExpression assignExpr = Builder.AssignExpr(usageExpr, usesEqualDefExpression);

                // Copy attributes across from input to output
                Context.InputAttributes.CopyObjectAttributesTo <Algorithm>(ivd, context.OutputAttributes, assignExpr);
                context.OutputAttributes.Remove <InitialiseTo>(ivd);
                if (vi.ArrayDepth == 0)
                {
                    // Insert the UsesEqualDef statement after the declaration.
                    // Note the variable will not have been defined yet.
                    context.AddStatementAfterCurrent(Builder.ExprStatement(assignExpr));
                }
                else
                {
                    // For an array, the UsesEqualDef statement should be inserted after the array is allocated.
                    // Store the statement for later use by ConvertArrayCreate.
                    context.InputAttributes.Remove <LoopContext>(ivd);
                    context.InputAttributes.Set(ivd, new LoopContext(context));
                    context.InputAttributes.Remove <Containers>(ivd);
                    context.InputAttributes.Set(ivd, new Containers(context));
                    vtc.usesEqualDefsStatements = Builder.StmtCollection();
                    vtc.usesEqualDefsStatements.Add(Builder.ExprStatement(assignExpr));
                }
            }
            // These must be set after the above or they will be copied to the other channels
            context.OutputAttributes.Set(ivd, vtc.defChannel);
            context.OutputAttributes.Set(vtc.defChannel.decl, new DescriptionAttribute("definition of '" + ivd.Name + "'"));
            return(ivde);
        }