private ArrayState AssumeCheckOfAnArrayElement(APC pc, Variable var, ArrayState data)
                {
                    Contract.Requires(data != null);
                    Contract.Ensures(Contract.Result <ArrayState>() != null);

                    Pair <BoxedVariable <Variable>, BoxedVariable <Variable> > refined;

                    if (data.CanRefineToArrayLoad(new BoxedVariable <Variable>(var), out refined))
                    {
                        var mySubState = Select(data);
                        ArraySegmentation <
                            FlatAbstractDomainOfBoolsWithRenaming <BoxedVariable <Variable> >, BoxedVariable <Variable>, BoxedExpression> segmentation;

                        Contract.Assume(refined.One != null);
                        Contract.Assume(refined.Two != null);

                        // Do we have a segmentation?
                        foreach (var arr in GetEquals(pc, refined.One, data))
                        {
                            if (mySubState.TryGetValue(arr, out segmentation))
                            {
                                // Is it unmodified?
                                if (data.IsUnmodifiedArrayElementFromEntry(arr, ToBoxedExpression(pc, refined.Two)))
                                {
                                    var norm = ToBoxedExpression(pc, refined.Two).ToNormalizedExpression <Variable>();
                                    if (norm != null && segmentation.TrySetAbstractValue(norm, CHECKED, data.Numerical, out segmentation))
                                    {
                                        mySubState.Update(arr, segmentation);
                                    }
                                    else
                                    {
                                        mySubState.RemoveElement(arr);
                                    }

                                    data = data.UpdatePluginAt(this.Id, mySubState);
                                }
                            }
                        }
                    }

                    return(data);
                }
                protected ArrayState AssumeWithArrayRefinement(APC pc, bool positive, BoxedExpression comparison, ArrayState prevState)
                {
                    Contract.Requires(comparison != null);
                    Contract.Requires(prevState != null);
                    Contract.Ensures(Contract.Result <ArrayState>() != null);

                    // Default NonRelational values
                    var interval          = DisInterval.UnknownInterval;
                    var symbExpression    = SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown;
                    var equalities        = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var disequalities     = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var weakUpperBounds   = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var strictUpperBounds = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var existential       = SetOfConstraints <BoxedVariable <Variable> > .Unknown;

                    Pair <BoxedVariable <Variable>, BoxedVariable <Variable> > refined;
                    Variable left, right;
                    int      k;

                    #region left != right ?
                    if (positive && comparison.IsCheckExp1NotEqExp2(out left, out right))
                    {
                        // refined.One[refined.Two] != right
                        var b = prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined);
                        if (!b)
                        {
                            // left != refined.One[refined.Two]
                            b = prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(right), out refined);

                            // Swap roles
                            var tmp = left;
                            left  = right;
                            right = tmp;
                        }

                        if (b)
                        {
                            // invariant: "left" is the one to refine.

                            // TODO: right now we are ignoring the case when both are arrays

                            interval = prevState.IntervalIfNotNull(left);

                            var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>
                                          (interval, symbExpression, equalities,
                                          new SetOfConstraints <BoxedVariable <Variable> >(new BoxedVariable <Variable>(right)),
                                          weakUpperBounds, strictUpperBounds, existential);

                            var index = ToBoxedExpression(pc, refined.Two).ToNormalizedExpression <Variable>();

                            return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState));
                        }
                    }
                    #endregion

                    #region left != k ?
                    BinaryOperator bop;
                    if (comparison.IsCheckExpOpConst(out bop, out left, out k) &&
                        prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined))
                    {
                        switch (bop)
                        {
                        case BinaryOperator.Ceq:
                        {
                            interval = positive ? DisInterval.For(k) : DisInterval.NotInThisInterval(DisInterval.For(k));
                            break;
                        }

                        case BinaryOperator.Cne_Un:
                        {
                            interval = positive ? DisInterval.NotInThisInterval(DisInterval.For(k)) : DisInterval.For(k);
                            break;
                        }

                        default:
                        {
                            return(prevState);
                        }
                        }

                        var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>
                                      (interval, symbExpression, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential);

                        var index = ToBoxedExpression(pc, refined.Two).Stripped().ToNormalizedExpression <Variable>();

                        return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState));
                    }
                    #endregion

                    #region left == 0
                    if (comparison.TryGetFrameworkVariable(out left) &&
                        prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined))
                    {
                        interval = !positive ? DisInterval.Zero : DisInterval.NotZero;

                        var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>
                                      (interval, symbExpression, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential);

                        var index = ToBoxedExpression(pc, refined.Two).Stripped().ToNormalizedExpression <Variable>();

                        return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState));
                    }
                    #endregion

                    return(prevState);
                }