public static Dictionary <Function, HashSet <List <VCExpr> > > CollectInstances(QuantifierInstantiationEngine qiEngine, VCExpr vcExpr)
        {
            var lambdaInstanceCollector = new LambdaInstanceCollector(qiEngine);

            lambdaInstanceCollector.Traverse(vcExpr, true);
            var lambdaFunctionToInstances =
                lambdaInstanceCollector.lambdaFunctions.ToDictionary(
                    x => x, x => new HashSet <List <VCExpr> >(new ListComparer <VCExpr>()));

            foreach (var instance in lambdaInstanceCollector.instances)
            {
                var function = (instance.Op as VCExprBoogieFunctionOp).Func;
                lambdaFunctionToInstances[function].Add(instance.UniformArguments.ToList());
            }
            return(lambdaFunctionToInstances);
        }
        private VCExpr Execute(Implementation impl, VCExpr vcExpr)
        {
            impl.Blocks.ForEach(block => block.Cmds.OfType <PredicateCmd>().Iter(predicateCmd =>
            {
                AddDictionary(FindInstantiationSources(predicateCmd, "add_to_pool", exprTranslator), labelToInstances);
            }));
            vcExpr            = Skolemizer.Skolemize(this, Polarity.Negative, vcExpr);
            lambdaToInstances = LambdaInstanceCollector.CollectInstances(this, vcExpr);
            while (labelToInstances.Count > 0)
            {
                var currLabelToInstances = labelToInstances;
                labelToInstances = new Dictionary <string, HashSet <VCExpr> >();
                AddDictionary(currLabelToInstances, accLabelToInstances);

                var currLambdaToInstances = lambdaToInstances;
                lambdaToInstances = new Dictionary <Function, HashSet <List <VCExpr> > >();
                AddDictionary(currLambdaToInstances, accLambdaToInstances);

                var visitedQuantifierBindings = new HashSet <VCExprVar>();
                while (visitedQuantifierBindings.Count < quantifierBinding.Count)
                {
                    foreach (var v in quantifierBinding.Keys)
                    {
                        if (visitedQuantifierBindings.Contains(v))
                        {
                            continue;
                        }
                        visitedQuantifierBindings.Add(v);
                        var quantifierExpr = quantifierBinding[v];
                        var quantifierInfo = quantifierInstantiationInfo[quantifierExpr];
                        if (quantifierInfo.relevantLabels.Overlaps(currLabelToInstances.Keys))
                        {
                            InstantiateQuantifier(quantifierExpr);
                        }
                    }
                }

                var visitedLambdaFunctions = new HashSet <Function>();
                while (visitedLambdaFunctions.Count < lambdaDefinition.Count)
                {
                    foreach (var lambdaFunction in lambdaDefinition.Keys)
                    {
                        if (visitedLambdaFunctions.Contains(lambdaFunction))
                        {
                            continue;
                        }
                        visitedLambdaFunctions.Add(lambdaFunction);
                        var quantifierExpr = lambdaDefinition[lambdaFunction];
                        var quantifierInfo = quantifierInstantiationInfo[quantifierExpr];
                        if (quantifierInfo.relevantLabels.Overlaps(currLabelToInstances.Keys) ||
                            currLambdaToInstances[lambdaFunction].Count > 0)
                        {
                            InstantiateLambdaDefinition(lambdaFunction);
                        }
                    }
                }
            }

            var lambdaAxioms = vcExprGen.NAry(VCExpressionGenerator.AndOp, lambdaDefinition.Values
                                              .SelectMany(quantifierExpr =>
                                                          quantifierInstantiationInfo[quantifierExpr].instances.Values.ToList()).ToList());

            return(vcExprGen.Implies(lambdaAxioms, LetConvert(vcExpr)));
        }