/*
         * The method Skolemize performs best-effort skolemization of the input expression expr.
         * If polarity == Polarity.Negative, a quantifier F embedded in expr is skolemized
         * provided it can be proved that F is a forall quantifier in the NNF version of expr.
         * If polarity == Polarity.Positive, a quantifier F embedded in expr is skolemized
         * provided it can be proved that F is an exists quantifier in the NNF version of expr.
         *
         * Factorization is performed on the resulting expression.
         */
        public static VCExpr Skolemize(QuantifierInstantiationEngine qiEngine, Polarity polarity, VCExpr vcExpr)
        {
            var skolemizer     = new Skolemizer(qiEngine, polarity, vcExpr);
            var skolemizedExpr = skolemizer.Mutate(vcExpr, true);

            return(Factorizer.Factorize(qiEngine, QuantifierCollector.Flip(polarity), skolemizedExpr));
        }
        private void InstantiateQuantifierAtInstance(VCExprQuantifier quantifierExpr, List <VCExpr> instance)
        {
            var quantifierInstantiationInfo = this.quantifierInstantiationInfo[quantifierExpr];

            if (quantifierInstantiationInfo.instances.ContainsKey(instance))
            {
                return;
            }
            var subst = new VCExprSubstitution(
                Enumerable.Range(0, quantifierExpr.BoundVars.Count).ToDictionary(
                    x => quantifierExpr.BoundVars[x],
                    x => instance[x]), new Dictionary <TypeVariable, Type>());
            var substituter   = new SubstitutingVCExprVisitor(vcExprGen);
            var instantiation = substituter.Mutate(quantifierExpr.Body, subst);

            quantifierInstantiationInfo.instances[new List <VCExpr>(instance)] =
                Skolemizer.Skolemize(this, quantifierExpr.Quan == Quantifier.ALL ? Polarity.Positive : Polarity.Negative,
                                     instantiation);
        }
        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)));
        }