Raw File
Program.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Tamaki_Tree_Decomp.Data_Structures;
using Tamaki_Tree_Decomp.Safe_Separators;
using static Tamaki_Tree_Decomp.Data_Structures.BlockSieve;
using static Tamaki_Tree_Decomp.Data_Structures.BlockSieve.InnerNode;

namespace Tamaki_Tree_Decomp
{
    public class Program
    {
#pragma warning disable CS0414
        static readonly string test_t0 = "..\\..\\Test Data\\tamaki test instances\\empty.gr";                 //
        static readonly string test_t1 = "..\\..\\Test Data\\tamaki test instances\\single-vertex.gr";         // 1
        static readonly string test_t2 = "..\\..\\Test Data\\tamaki test instances\\two-vertices.gr";          // 1 2
        static readonly string test_t3 = "..\\..\\Test Data\\tamaki test instances\\single-edge.gr";           // 1-2
        static readonly string test_t4 = "..\\..\\Test Data\\tamaki test instances\\wedge.gr";                 // 1-2-3
        static readonly string test_t5 = "..\\..\\Test Data\\tamaki test instances\\four_in_a_line.gr";        // 1-2-3-4
        static readonly string test_t6 = "..\\..\\Test Data\\tamaki test instances\\gr-only.gr";               // 1-2-3-4-5
        static readonly string test_t7 = "..\\..\\Test Data\\tamaki test instances\\p-num-vertices-larger.gr"; // 1-2-3-4-5 6

        // -------------------------------------

        static readonly string test_a0 = "..\\..\\Test Data\\test1.gr";
        static readonly string test_a1 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\fuzix_clock_settime_clock_settime.gr";

        static readonly string test_a2 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\fuzix_devio_bfind.gr";
        static readonly string td_o_a2 = "..\\..\\Test Data\\test decomps\\fuzix_devio_bfind.td";

        static readonly string test_a3 = "..\\..\\Test Data\\test2.gr";
        static readonly string test_a4 = "..\\..\\Test Data\\test3.gr";
        static readonly string test_a5 = "..\\..\\Test Data\\small_cycle.gr";
        static readonly string test_a6 = "..\\..\\Test Data\\double_cycle.gr";
        static readonly string test_a7 = "..\\..\\Test Data\\double_cycle_bridge.gr";
        static readonly string test_a8 = "..\\..\\Test Data\\cycle_cycle.gr";
        static readonly string test_a9 = "..\\..\\Test Data\\cycle_line.gr";
        static readonly string test_tr0 = "..\\..\\Test Data\\tree.gr";

        static readonly string test_ss0 = "..\\..\\Test Data\\cliques_4_3_4.gr";


        static readonly string test_s0 = "..\\..\\Test Data\\s0_fuzix_clock_settime_clock_settime.gr";
        static readonly string test_s1 = "..\\..\\Test Data\\s1_fuzix_clock_settime_clock_settime.gr";
        static readonly string test_s2 = "..\\..\\Test Data\\s3_fuzix_clock_settime_clock_settime.gr";

        static readonly string test_e0 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\fuzix_filesys_getinode.gr";
        static readonly string test_e1 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\fuzix_devf_fd_transfer.gr";
        static readonly string test_e2 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\BalancedTree_3,5.gr";
        static readonly string test_e3 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\contiki_ifft_ifft.gr";
        static readonly string test_e4 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\easy\\contiki_powertrace_powertrace_print.gr";

        static readonly string test_m0 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\medium\\DesarguesGraph.gr";
        static readonly string test_m1 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\medium\\FlowerSnark.gr";
        static readonly string test_m2 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\medium\\GeneralizedPetersenGraph_10_4.gr";
        static readonly string test_m3 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\medium\\HoffmanGraph.gr";
        static readonly string test_m4 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\medium\\NauruGraph.gr";

        static readonly string test_h0 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\hard\\ClebschGraph.gr";
        static readonly string test_h1 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\hard\\contiki_dhcpc_handle_dhcp.gr";
        static readonly string test_h2 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\hard\\DoubleStarSnark.gr";
        static readonly string test_h3 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\hard\\fuzix_vfscanf_vfscanf.gr";
        static readonly string test_h4 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\hard\\McGeeGraph.gr";

        static readonly string test_r0 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\GNP_20_10_1.gr";
        static readonly string test_r1 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\GNP_20_20_0.gr";
        static readonly string test_r2 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\GNP_20_30_0.gr";
        static readonly string test_r3 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\GNP_20_40_0.gr";
        static readonly string test_r4 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\RKT_20_40_10_0.gr";
        static readonly string test_r5 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\RKT_20_40_10_1.gr";
        static readonly string test_r6 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\RKT_20_50_10_0.gr";
        static readonly string test_r7 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\RKT_20_50_10_1.gr";
        static readonly string test_r8 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\RKT_20_70_10_0.gr";
        static readonly string test_r9 = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\random\\RKT_20_80_10_1.gr";

        static readonly string test_n0 = "..\\..\\Test Data\\normalised_0.gr";
        static readonly string test_n1 = "..\\..\\Test Data\\normalised_1.gr";

#pragma warning restore CS0414

        static int workerThreads = 1;
        static int timePerInstance = 2000000;
        static int startingInstance = 100;

        static void Main(string[] args)
        {
            // used for naming files when something needs to be written onto disk
            date_time_string = DateTime.Now.ToString();
            date_time_string = date_time_string.Replace('.', '-').Replace(':', '-');

            //string filepath = null;
            string filepath = test_m4;
            //string filepath = PACE2017(1);
            //string filepath = "..\\..\\Test Data\\graphs_MC2020\\clique_graphs\\track1_034.gr";
            //string filepath = "..\\..\\Test Data\\graphs_MC2020\\bipartite_graphs\\track1_014.gr";
            //string filepath = Console.ReadLine();

            
            if (args.Length > 0)
            {
                filepath = args[0];
            }            

            //string directory = "..\\..\\Test Data\\graphs_MC2020\\bipartite_graphs";
            //string directory = "..\\..\\Test Data\\graphs_MC2020\\clique_graphs";
            //string directory = "..\\..\\Test Data\\graphs_MC2020";
            //string directory = "..\\..\\Test Data\\pace16-tw-instances-20160307\\tw-exact\\hard\\";
            string directory = "..\\..\\Test Data\\ex-instances-PACE2017-public\\";
            int directoryStartIndex = 0;
            int directoryEndIndex = 200;

            BitSet.plusOneInString = false;
            Graph.dumpSubgraphs = false;   // dumps graphs only in DEBUG mode!
            //SafeSeparator.separate = false;
            //GraphReduction.reduce = false;
            Treewidth.completeHeuristically = true;
            Treewidth.heuristicCompletionFrequency = 20;
            Treewidth.heuristicInletMax = 1f;
            Treewidth.heuristicInletMin = 0f;
            Treewidth.maxTestsPerGraphAndK = 20;
            Treewidth.heuristic = Heuristics.Heuristic.min_degree;

            Treewidth.moreThan2ComponentsOptimization = true;
            PTD.testIfAddingOneVertexToBagFormsPMC = false;
            ImmutableGraph.cachePMC = false;
            LowerBound.calculateLowerBound = true;
            Treewidth.testOutletIsCliqueMinor = false;

            
            //Run(filepath, true);
            Run(filepath, false, false);
            //RunAll_Parallel(directory);
            //RunAll_Sequential(directory, directoryStartIndex, directoryEndIndex);
            //EvaluateParameterImpact<bool>(directory, ref Treewidth.testOutletIsCliqueMinor, false, true, directoryStartIndex, directoryEndIndex);

            //Treewidth.PrintStats_kMinus(12);
            //Console.WriteLine("total time for lower bound calculation: {0}", LowerBound.stopWatch.Elapsed);
            //Console.WriteLine("articulation point stopwatch: {0}, only neighbor stopwatch: {1}", PTD.articulationPointCandidatesStopwatch.Elapsed, PTD.onlyNeighborStopwatch.Elapsed);
            //Console.Read();
        }

        public static string date_time_string;
        static Thread[] threads;
        static Timer[] timers;
        static string[] filepaths;
        static string[] currentlyRunning;
        static int started = startingInstance;
        static readonly Object timerCallbackLock = new Object();

        /// <summary>
        /// runs the algorithm for all graphs in the directory (and subdirectories) in "workerThreads" many threads.
        /// </summary>
        /// <param name="directory"></param>
        private static void RunAll_Parallel(string directory)
        {
            filepaths = Directory.GetFiles(directory, "*.gr", SearchOption.AllDirectories);

            threads = new Thread[workerThreads];
            timers = new Timer[workerThreads];
            currentlyRunning = new string[workerThreads];
            started = startingInstance;
            lock (timerCallbackLock)
            {
                for (int i = 0; i < workerThreads && startingInstance + i < filepaths.Length; i++)
                {
                    int copy = i;
                    threads[copy] = new Thread(() =>
                        {
                            currentlyRunning[copy] = filepaths[startingInstance + copy];
                            try
                            {
                                Run(filepaths[startingInstance + copy], false);
                            }
                            catch(OutOfMemoryException)
                            {
                                Console.WriteLine("program ran out of memory while executing algorithm for {0}.", currentlyRunning[copy]);
                            }
                            lock (timerCallbackLock)
                            {
                                threads[copy] = null;
                            }
                            AbortThread(copy);
                        }
                    );
                    threads[copy].Start();
                    timers[copy] = new Timer(new TimerCallback(AbortThread), copy, timePerInstance, Timeout.Infinite);
                    started++;
                }
            }
        }

        /// <summary>
        /// callback to abort a running thread after a timeout and to restart computation on a new graph instance if there are any left.
        /// </summary>
        /// <param name="state">the thread index in the array of threads (and timer index in the array of timers)</param>
        private static void AbortThread(object state)
        {
            int threadIndex = (int)state;
            lock (timerCallbackLock)
            {
                if (threads[threadIndex] != null){
                    threads[threadIndex].Abort();
                    Console.WriteLine("graph {0} timed out", currentlyRunning[threadIndex]);
                }
                if (started < filepaths.Length) {
                    int copy = started;
                    threads[threadIndex] = new Thread(() =>
                        {
                            currentlyRunning[threadIndex] = filepaths[copy];
                            try
                            {
                                Run(filepaths[copy], false);
                            }
                            catch (OutOfMemoryException)
                            {
                                Console.WriteLine("program ran out of memory while executing algorithm for {0}.", currentlyRunning[threadIndex]);
                            }
                            lock (timerCallbackLock)
                            {
                                threads[threadIndex] = null;
                            }
                            AbortThread(state);
                        }
                    );
                    started++;
                    threads[threadIndex].Start();
                    timers[threadIndex].Change(timePerInstance, Timeout.Infinite);
                }
            }
        }

        private static void RunAll_Sequential(string directory, int start=0, int end=int.MaxValue)
        {
            Stopwatch timer = new Stopwatch();
            int counter = -1;
            timer.Start();
            foreach(String filepath in Directory.GetFiles(directory, "*.gr", SearchOption.AllDirectories))
            {
                counter++;
                if (counter < start / 2 || counter > end / 2)
                {
                    continue;
                }
                Run(filepath, false);
            }
            timer.Stop();
            Console.WriteLine("\n-------------------------------------------------------------------------------------\n\ntotal time for directory: " + timer.Elapsed.ToString());
        }

        private static void EvaluateParameterImpact<T>(string directory, ref T parameter, T firstValue, T secondValue, int start = 0, int end = int.MaxValue)
        {
            int counter = -1;
            Stopwatch timer = new Stopwatch();
            Stopwatch timer1 = new Stopwatch();
            Stopwatch timer2 = new Stopwatch();
            TimeSpan totalDifference = new TimeSpan(0);
            TimeSpan highestDifference = new TimeSpan(int.MinValue);
            TimeSpan lowestDifference = new TimeSpan(int.MaxValue);
            float highestRelativeDifference = 0;
            float lowestRelativeDifference = float.MaxValue;

            timer.Start();
            foreach (String filepath in Directory.GetFiles(directory, "*.gr", SearchOption.AllDirectories))
            {
                counter++;
                if (counter < start / 2 || counter > end / 2)
                {
                    continue;
                }

                // run without parameter active
                parameter = firstValue;
                timer1.Restart();
                Run(filepath, false, false);
                timer1.Stop();

                // run with parameter active
                parameter = secondValue;
                timer2.Restart();
                Run(filepath, false, false);
                timer2.Stop();

                // calculate statistics
                TimeSpan difference = timer2.Elapsed - timer1.Elapsed;
                float relativeDifference = (float)timer2.ElapsedMilliseconds / timer1.ElapsedMilliseconds;
                totalDifference += difference;
                if (difference > highestDifference)
                {
                    highestDifference = difference;
                }
                if (difference < lowestDifference)
                {
                    lowestDifference = difference;
                }
                if (timer1.ElapsedMilliseconds > 5000 || timer2.ElapsedMilliseconds > 5000)
                {
                    if (relativeDifference > highestRelativeDifference)
                    {
                        highestRelativeDifference = relativeDifference;
                    }
                    if (relativeDifference < lowestRelativeDifference)
                    {
                        lowestRelativeDifference = relativeDifference;
                    }
                }


                //Console.WriteLine("----------------------------------------------------------------------------------------");
                Console.WriteLine("{0}: difference relative: {1:F2}, difference total: {2}, total time: {3}", filepath.Substring(filepath.Length - 8), relativeDifference, difference, timer1.Elapsed + timer2.Elapsed);
                //Console.WriteLine("----------------------------------------------------------------------------------------");
            }
            timer.Stop();
            Console.WriteLine("\n-------------------------------------------------------------------------------------\n" +
                "\ntotal time for directory: {0}" +
                "\ntotal difference: {1}" +
                "\nhighest difference: {2}" +
                "\nlowest difference: {3}" +
                "\nhighest relative difference above 10s: {4:F2}" +
                "\nlowest relative difference above 10s:  {5:F2}",
                timer.Elapsed, totalDifference, highestDifference, lowestDifference, highestRelativeDifference, lowestRelativeDifference);
        }

        private static int Run(string filepath, bool printTD=true, bool printStats=true)
        {
            Graph g = new Graph(filepath);
                
            Stopwatch stopwatch = new Stopwatch();
            SafeSeparator.size3SeparationStopwatch = new Stopwatch();
            SafeSeparator.size3separators = 0;
            SafeSeparator.cliqueSeparatorStopwatch = new Stopwatch();
            SafeSeparator.cliqueSeparators = 0;
            SafeSeparator.almostCliqueSeparatorStopwatch = new Stopwatch();
            SafeSeparator.almostCliqueSeparators = 0;
            stopwatch.Start();
            int treeWidth = Treewidth.TreeWidth(g, out PTD output, printTD);
            stopwatch.Stop();

            if (printTD)
            {
                output.Print();
            }

            if (printStats)
            {
                Console.WriteLine("Tree decomposition of {0} found in {1} time. Treewidth is {2}.\n" +
                        "Found {3} size 3 separators in {4} total time.\n" +
                        "Found {5} clique Separators in {6} total time.\n" +
                        "Found {7} almost clique separators in {8} total time.\n",
                        filepath, stopwatch.Elapsed, treeWidth, SafeSeparator.size3separators, SafeSeparator.size3SeparationStopwatch.Elapsed,
                        SafeSeparator.cliqueSeparators - SafeSeparator.almostCliqueSeparators, SafeSeparator.cliqueSeparatorStopwatch.Elapsed - SafeSeparator.almostCliqueSeparatorStopwatch.Elapsed,
                        SafeSeparator.almostCliqueSeparators, SafeSeparator.almostCliqueSeparatorStopwatch.Elapsed);
            }
            g = new Graph(filepath);
            output.AssertValidTreeDecomposition(new ImmutableGraph(g));
            return treeWidth;
        }

        private static string PACE2017(int number)
        {
            return String.Format("..\\..\\Test Data\\ex-instances-PACE2017-public\\ex{0:D3}.gr", number);
        }
    }
}
back to top