/// <summary>
                    /// Here we actually add constraints to our state.
                    /// </summary>
                    private Domain ConstrainLessThan(Expression var, Expression bound, Domain domain)
                    {
                        // First, skip unary coercions on var and bound
                        SkipConversionDecoder skipper = new SkipConversionDecoder();

                        var   = this.context.Decode <Unit, Expression, SkipConversionDecoder>(var, skipper, Unit.Value);
                        bound = this.context.Decode <Unit, Expression, SkipConversionDecoder>(bound, skipper, Unit.Value);

                        Variable left  = this.context.Unrefine(var);
                        Variable right = this.context.Unrefine(bound);
                        // add the bound to the set of bounds known
                        SetDomain <Variable> currentBounds =
                            (domain.Value.Contains(left)) ? domain.Value[left] : SetDomain <Variable> .TopValue;

                        return(new Domain(domain.Value.Add(left, currentBounds.Add(right))));
                    }
                /// <summary>
                /// Here's where the actual work is. We get passed a list of pairs (source,targets) representing
                /// the assignments t = source for each t in targets.
                ///
                /// For our domain, we thus add new mappings for all targets by looking up the bounds of the source and map the source bounds to new target bounds.
                /// </summary>
                public Domain ParallelAssign(Pair <Label, Label> edge, IFunctionalMap <Variable, FList <Variable> > sourceTargetMap, Domain state)
                {
                    EnvironmentDomain <Variable, SetDomain <Variable> > originalState = state.Value;
                    EnvironmentDomain <Variable, SetDomain <Variable> > newState      = originalState;

                    foreach (Variable source in sourceTargetMap.Keys)
                    {
                        FList <Variable> targets = sourceTargetMap[source];

                        // 1) for each target in this assignment, assign it the same bounds as source.
                        // 2) since we also have to map the source bounds, we assign it actually the union of all targets of all bounds of the source.
                        SetDomain <Variable> targetBounds = SetDomain <Variable> .TopValue;
                        if (originalState.Contains(source))
                        {
                            SetDomain <Variable> originalBounds = originalState[source];
                            foreach (Variable origBound in originalBounds.Elements)
                            {
                                FList <Variable> targetBoundNames = sourceTargetMap[origBound];
                                while (targetBoundNames != null)
                                {
                                    targetBounds     = targetBounds.Add(targetBoundNames.Head);
                                    targetBoundNames = targetBoundNames.Tail;
                                }
                            }
                        }
                        if (targetBounds.IsTop)
                        {
                            // have no bounds, so havoc all targets
                            while (targets != null)
                            {
                                newState = newState.Remove(targets.Head);
                                targets  = targets.Tail;
                            }
                        }
                        else
                        {
                            while (targets != null)
                            {
                                newState = newState.Add(targets.Head, targetBounds);
                                targets  = targets.Tail;
                            }
                        }
                    }
                    return(new Domain(newState));
                }