static public void Test()
        {
            RangeCollection aRangeCollection = RangeCollection.GetInstance();

            aRangeCollection.Add(0);
            SpecialFunctions.CheckCondition("0-0" == aRangeCollection.ToString());
            aRangeCollection.Add(1);
            SpecialFunctions.CheckCondition("0-1" == aRangeCollection.ToString());
            aRangeCollection.Add(4);
            SpecialFunctions.CheckCondition("0-1,4-4" == aRangeCollection.ToString());
            aRangeCollection.Add(5);
            SpecialFunctions.CheckCondition("0-1,4-5" == aRangeCollection.ToString());
            aRangeCollection.Add(7);
            SpecialFunctions.CheckCondition("0-1,4-5,7-7" == aRangeCollection.ToString());
            aRangeCollection.Add(2);
            SpecialFunctions.CheckCondition("0-2,4-5,7-7" == aRangeCollection.ToString());
            aRangeCollection.Add(3);
            SpecialFunctions.CheckCondition("0-5,7-7" == aRangeCollection.ToString());
            aRangeCollection.Add(6);
            SpecialFunctions.CheckCondition("0-7" == aRangeCollection.ToString());
            aRangeCollection.Add(-10);
            SpecialFunctions.CheckCondition("-10--10,0-7" == aRangeCollection.ToString());
            aRangeCollection.Add(-5);
            SpecialFunctions.CheckCondition("-10--10,-5--5,0-7" == aRangeCollection.ToString());

            aRangeCollection = RangeCollection.Parse("1-5,7-12,13-14");

            Console.WriteLine(aRangeCollection);
            Console.WriteLine(aRangeCollection.Contains(3));
            Console.WriteLine(aRangeCollection.Contains(12));
            Console.WriteLine(aRangeCollection.Contains(13));
            Console.WriteLine(aRangeCollection.Contains(6));

            aRangeCollection = RangeCollection.Parse("-10--5,-1-14");

            Console.WriteLine(aRangeCollection);
            Console.WriteLine(aRangeCollection.Contains(-12));
            Console.WriteLine(aRangeCollection.Contains(-10));
            Console.WriteLine(aRangeCollection.Contains(-7));
            Console.WriteLine(aRangeCollection.Contains(-5));
            Console.WriteLine(aRangeCollection.Contains(-4));
            Console.WriteLine(aRangeCollection.Contains(0));
            Console.WriteLine(aRangeCollection.Contains(1));
            Console.WriteLine(aRangeCollection.Contains(-2));

            Console.WriteLine("Count: " + aRangeCollection.Count());
            Console.WriteLine("Count -5 to 2: " + aRangeCollection.Count(-5, 2));

            RangeCollectionCollection rcc = RangeCollectionCollection.GetInstance(aRangeCollection);

            Console.WriteLine(rcc);
            Console.WriteLine(rcc.GetContainingRangeCollection(-12));
            Console.WriteLine(rcc.GetContainingRangeCollection(-10));
            Console.WriteLine(rcc.GetContainingRangeCollection(-5));
            Console.WriteLine(rcc.GetContainingRangeCollection(3));
            Console.WriteLine(rcc.GetContainingRangeCollection(15));
        }
        public void Run(
            ModelScorer modelScorer,
            PhyloTree phyloTree,
            string predictorSparseFileName,
            string targetSparseFileName,
            string leafDistributionName,
            string nullDataGeneratorName,
            KeepTest <Dictionary <string, string> > keepTest,
            RangeCollection skipRowIndexRangeCollectionOrNull,
            string shortName,
            string outputDirectoryName,
            RangeCollection pieceIndexRangeCollection, int pieceCount,
            RangeCollection nullIndexRangeCollection,
            string optimizerName)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            Directory.CreateDirectory(outputDirectoryName);


            string outputFileName = string.Format(@"{0}\{1}.{2}.{3}.{4}.{5}.{6}{7}.txt",
                                                  outputDirectoryName, shortName,
                                                  leafDistributionName, nullDataGeneratorName,
                                                  nullIndexRangeCollection,
                                                  pieceCount,
                                                  pieceIndexRangeCollection,
                                                  skipRowIndexRangeCollectionOrNull == null ? "" : ".Skip" + skipRowIndexRangeCollectionOrNull.Count().ToString()
                                                  );

            #region from PhyloTree refactor
            //Dictionary<string, Dictionary<string, bool>> predictorVariableToCaseIdToRealNonMissingValue = LoadSparseFileInMemory<bool>(predictorSparseFileName);
            //IEnumerable<Pair<string, Dictionary<string, T>>> targetNameAndCaseIdToNonMissingValueEnumeration = LoadSparseFileEnumeration<T>(targetSparseFileName);

            //NullDataCollection nullDataGenerator =
            //    NullDataCollection.GetInstance(this, modelTester, nullIndexRangeCollection, predictorVariableToCaseIdToRealNonMissingValue);

            //UniversalWorkList<T> workList = UniversalWorkList<T>.GetInstance(
            //    predictorVariableToCaseIdToRealNonMissingValue,
            //    targetNameAndCaseIdToNonMissingValueEnumeration,
            //    nullDataGenerator, nullIndexRangeCollection, keepTest);
            #endregion
            bool speedOverMemory = true;

            IEnumerable <Pair <string, Dictionary <string, SufficientStatistics> > >
            predictorNameAndCaseIdToNonMissingValueEnumeration = CreateNameAndCaseIdToNonMissingValueEnumeration(predictorSparseFileName, speedOverMemory);
            IEnumerable <Pair <string, Dictionary <string, SufficientStatistics> > >
            targetNameAndCaseIdToNonMissingValueEnumeration = CreateNameAndCaseIdToNonMissingValueEnumeration(targetSparseFileName, speedOverMemory);

            NullDataCollection nullDataGenerator =
                CreateNullDataGenerator(nullDataGeneratorName, modelScorer, phyloTree, nullIndexRangeCollection,
                                        predictorNameAndCaseIdToNonMissingValueEnumeration, targetNameAndCaseIdToNonMissingValueEnumeration);

            UniversalWorkList workList = UniversalWorkList.GetInstance(
                predictorNameAndCaseIdToNonMissingValueEnumeration,
                targetNameAndCaseIdToNonMissingValueEnumeration,
                nullDataGenerator, nullIndexRangeCollection, keepTest);

            int workListCount = SpecialFunctions.Count(workList.List());

            int effectiveWorkListCount;
            if (skipRowIndexRangeCollectionOrNull == null)
            {
                effectiveWorkListCount = workListCount;
            }
            else
            {
                effectiveWorkListCount = 0;
                for (int iRowIndex = 0; iRowIndex < workListCount; iRowIndex++)
                {
                    if (!skipRowIndexRangeCollectionOrNull.Contains(iRowIndex))
                    {
                        effectiveWorkListCount++;
                    }
                }
            }
            Console.WriteLine("{0} Total rows. Skipping {1} of them.", workListCount, workListCount - effectiveWorkListCount);

            using (TextWriter textWriter = File.CreateText(outputFileName))
            {
                textWriter.WriteLine(Header);
                int rowIndex          = -1;
                int effectiveRowIndex = -1;

                foreach (RowData rowAndTargetData in workList.List())
                {
                    //!!!make all these parameters and the calculation a class
                    ++rowIndex;
                    Debug.Assert(rowIndex < workListCount); // real assert

                    if (skipRowIndexRangeCollectionOrNull == null || !skipRowIndexRangeCollectionOrNull.Contains(rowIndex))
                    {
                        ++effectiveRowIndex;

                        int workIndex = ExtractWorkIndex(effectiveRowIndex, pieceCount, effectiveWorkListCount);

                        if (pieceIndexRangeCollection.Contains(workIndex))
                        {
                            Debug.WriteLine("WorkItemIndex " + rowIndex.ToString());
                            string reportLine;
                            try
                            {
                                reportLine =
                                    CreateReportLine(modelScorer, phyloTree, rowAndTargetData, workList, rowIndex, workListCount, workIndex);
                            }
                            catch (OutOfMemoryException)
                            {
                                Console.WriteLine("OUT OF MEMORY!! Clearing cache and trying to recover where we left off.");
                                modelScorer.ClearCache();
                                reportLine =
                                    CreateReportLine(modelScorer, phyloTree, rowAndTargetData, workList, rowIndex, workListCount, workIndex);
                            }

                            textWriter.WriteLine(reportLine);
                            textWriter.Flush();
                        }
                    }
                }
            }
            stopwatch.Stop();
            Console.WriteLine("Running time: " + stopwatch.Elapsed);
        }