/// <summary>
        /// Generates up to n solutions of the given variability model.
        /// Note that this method could also generate less than n solutions if the variability model does not contain sufficient solutions.
        /// Moreover, in the case that <code>n &lt; 0</code>, all solutions are generated.
        /// </summary>
        /// <param name="vm">The <see cref="VariabilityModel"/> to obtain solutions for.</param>
        /// <param name="n">The number of solutions to obtain.</param>
        /// <returns>A list of configurations, in which a configuration is a list of SELECTED binary options.</returns>
        public List <List <BinaryOption> > GenerateUpToNFast(VariabilityModel vm, int n)
        {
            // Use the random seed to produce new random seeds
            Random random = new Random(Convert.ToInt32(z3RandomSeed));

            List <BoolExpr> variables;
            Dictionary <BoolExpr, BinaryOption> termToOption;
            Dictionary <BinaryOption, BoolExpr> optionToTerm;
            Tuple <Context, BoolExpr>           z3Tuple = Z3Solver.GetInitializedBooleanSolverSystem(out variables, out optionToTerm, out termToOption, vm, this.henard, random.Next());
            Context         z3Context              = z3Tuple.Item1;
            BoolExpr        z3Constraints          = z3Tuple.Item2;
            List <BoolExpr> excludedConfigurations = new List <BoolExpr>();
            List <BoolExpr> constraints            = Z3Solver.lastConstraints;

            List <List <BinaryOption> > configurations = new List <List <BinaryOption> >();

            Microsoft.Z3.Solver s = z3Context.MkSolver();

            // TODO: The following line works for z3Solver version >= 4.6.0
            //solver.Set (RANDOM_SEED, z3RandomSeed);
            Params solverParameter = z3Context.MkParams();

            if (henard)
            {
                solverParameter.Add(RANDOM_SEED, NextUInt(random));
            }
            else
            {
                solverParameter.Add(RANDOM_SEED, z3RandomSeed);
            }
            s.Parameters = solverParameter;

            s.Assert(z3Constraints);
            s.Push();

            Model model = null;

            while (s.Check() == Status.SATISFIABLE && (configurations.Count < n || n < 0))
            {
                model = s.Model;

                List <BinaryOption> config = RetrieveConfiguration(variables, model, termToOption);

                configurations.Add(config);

                if (henard)
                {
                    BoolExpr newConstraint = Z3Solver.NegateExpr(z3Context, Z3Solver.ConvertConfiguration(z3Context, config, optionToTerm, vm));

                    excludedConfigurations.Add(newConstraint);

                    Dictionary <BoolExpr, BinaryOption> oldTermToOption = termToOption;

                    // Now, initialize a new one for the next configuration
                    z3Tuple       = Z3Solver.GetInitializedBooleanSolverSystem(out variables, out optionToTerm, out termToOption, vm, this.henard, random.Next());
                    z3Context     = z3Tuple.Item1;
                    z3Constraints = z3Tuple.Item2;

                    s = z3Context.MkSolver();

                    //s.Set (RANDOM_SEED, NextUInt (random));
                    solverParameter = z3Context.MkParams();

                    solverParameter.Add(RANDOM_SEED, NextUInt(random));
                    s.Parameters = solverParameter;

                    constraints = Z3Solver.lastConstraints;

                    excludedConfigurations = Z3Solver.ConvertConstraintsToNewContext(oldTermToOption, optionToTerm, excludedConfigurations, z3Context);

                    constraints.AddRange(excludedConfigurations);

                    s.Assert(z3Context.MkAnd(Z3Solver.Shuffle(constraints, new Random(random.Next()))));

                    s.Push();
                }
                else
                {
                    s.Add(Z3Solver.NegateExpr(z3Context, Z3Solver.ConvertConfiguration(z3Context, config, optionToTerm, vm)));
                }
            }

            return(configurations);
        }