public SimpleFacetedSearch(IndexReader reader, string[] groupByFields)
        {
            this._Reader = reader;

            List<FieldValuesBitSets> fieldValuesBitSets = new List<FieldValuesBitSets>();

            //STEP 1
            //f1 = A, B
            //f2 = I, J
            //f3 = 1, 2, 3
            int maxFacets = 1;
            List<List<string>> inputToCP = new List<List<string>>();
            foreach (string field in groupByFields)
            {
                FieldValuesBitSets f = new FieldValuesBitSets(reader, field);
                maxFacets *= f.FieldValueBitSetPair.Count;
                if (maxFacets > MAX_FACETS) throw new Exception("Facet count exceeded " + MAX_FACETS);
                fieldValuesBitSets.Add(f);
                inputToCP.Add(f.FieldValueBitSetPair.Keys.ToList());
            }

            //STEP 2
            // comb1: A I 1
            // comb2: A I 2 etc.
            var cp = inputToCP.CartesianProduct();

            //SETP 3
            //create a single BitSet for each combination
            //BitSet1: A AND I AND 1
            //BitSet2: A AND I AND 2 etc.
            //and remove impossible comb's (for ex, B J 3) from list.
            Parallel.ForEach(cp, combinations =>
            {
                OpenBitSetDISI bitSet = new OpenBitSetDISI(_Reader.MaxDoc());
                bitSet.Set(0, bitSet.Size());

                List<string> comb = combinations.ToList();

                for (int j = 0; j < comb.Count; j++)
                {
                    bitSet.And(fieldValuesBitSets[j].FieldValueBitSetPair[comb[j]]);
                }

                //STEP 3
                if (bitSet.Cardinality() > 0)
                {
                    lock(_Groups)
                        _Groups.Add(new KeyValuePair<List<string>, OpenBitSetDISI>(comb, bitSet));
                }
            });

            //Now _Groups has 7 rows (as <List<string>, BitSet> pairs) 
        }
        private void btnCombinatorialTheory_Click(object sender, EventArgs e)
        {
            //List<string> _list = new List<string>() { "a", "b", "c", "d" };
            //List<List<string>> _answer = _list.CombinationsWithoutRepetition(3);

            //List<test1> _list = new List<test1>() { new test1() { propertyA = null, propertyB = 1 }, new test1() { propertyA = null, propertyB = 2 }, new test1() { propertyA = null, propertyB = 3 } };
            //List<List<test1>> _answer = _list.PermutationsWithoutRepetition();
            //List<List<test1>> _answer = _list.CombinationsWithoutRepetition(2);
            //_answer.First()[0].propertyA  = 18;

            /*
            List<string> _source = new List<string>() { "1", "2" };
            List<string> _other = new List<string>() { "a", "b" };
            List<List<string>> _answer = _source.CartesianProduct(_other);
            */

            /*
            List<string> _source = new List<string>() { "1", "2" };
            List<List<string>> _other = new List<List<string>>() { new List<string>() { "a", "b" }, new List<string>() { "c", "d" } };
            List<List<string>> _answer = _source.CartesianProduct(_other);
            */

            List<string> _other = new List<string>() { "1", "2" };
            List<List<string>> _source = new List<List<string>>() { new List<string>() { "a", "b" }, new List<string>() { "c", "d" } };
            List<List<string>> _answer = _source.CartesianProduct(_other);

        }
        public SparseFacetedSearcher(IndexReader reader, params string[] groupByFields)
        {
            this.reader = reader;

            var fieldValuesBitSets = new List<FieldValuesDocIDs>();

            //STEP 1
            //f1 = A, B
            //f2 = I, J
            //f3 = 1, 2, 3
            int maxFacets = 1;
            var inputToCP = new List<List<string>>();
            foreach (string field in groupByFields)
            {
                var f = new FieldValuesDocIDs(reader, field);
                maxFacets *= f.FieldValueDocIDsPair.Count;
                if (maxFacets > MAX_FACETS) throw new Exception("Facet count exceeded " + MAX_FACETS);
                fieldValuesBitSets.Add(f);
                inputToCP.Add(f.FieldValueDocIDsPair.Keys.ToList());
            }

            //STEP 2
            // comb1: A I 1
            // comb2: A I 2 etc.
            var cp = inputToCP.CartesianProduct();

            //SETP 3
            //create a single BitSet for each combination
            //BitSet1: A AND I AND 1
            //BitSet2: A AND I AND 2 etc.
            //and remove impossible comb's (for ex, B J 3) from list.
            Parallel.ForEach(cp, combinations =>
            {
                var comb = combinations.ToList();

                var bitSet = fieldValuesBitSets[0].FieldValueDocIDsPair[comb[0]];
                for (int j = 1; j < comb.Count; j++)
                    bitSet = bitSet.WalkingIntersect(fieldValuesBitSets[j].FieldValueDocIDsPair[comb[j]]).ToList();

                //STEP 3
                if (bitSet.Any())
                {
                    lock (groups)
                        groups.Add(Tuple.Create(new FacetName(comb), bitSet));
                }
            });

            //Now groups has 7 rows (as <List<string>, BitSet> pairs)
        }