コード例 #1
0
        public Dictionary <int, int> ColourGraph(Graph graph)
        {
            stopwatch.Restart();
            var dummySolution = new Solution()
            {
                colourCount = int.MaxValue,
            };
            var initialSolution = new Solution()
            {
                colourCount = 0,
                colourLayer = new Stack <List <int> >()
            };

            graph = graph.CloneNeighboursSorted(v => graph.VerticesKVPs[v].Length);

            // var solution = Recurse(graph, initialSolution, dummySolution, ref leftSteps, alphaRatio).vertexToColour;
            var dictionary = new Dictionary <int, int>();
            //var misCount = 0;
            //var largestMIS = 0;
            //foreach (var mis in EnumerateMIS(graph))
            //{
            //    misCount += 1;
            //    if (mis.vertices.Count > largestMIS)
            //        largestMIS = mis.vertices.Count;
            //}
            //System.Console.WriteLine($"MIS count: {misCount}, largest: {largestMIS}");
            var ignoredVertices    = new bool[graph.VerticesKVPs.Length];
            var primaryGraph       = new GraphFast(graph);
            var complementaryGraph = new GraphFast(graph);
            var bestSolution       = Recurse(graph.VerticesKVPs.Length, primaryGraph, complementaryGraph, initialSolution, dummySolution);
            var layerColour        = 0;

            foreach (var layer in bestSolution.colourLayer)
            {
                foreach (var vertex in layer)
                {
                    dictionary.Add(vertex, layerColour);
                }
                layerColour += 1;
            }
            stopwatch.Stop();
            return(dictionary);
        }
コード例 #2
0
        //public IEnumerable<List<int>> EnumerateMIS(Graph graph)
        //{
        //    var primaryGraph = new GraphFast(graph);
        //    var complementaryGraph = new GraphFast(graph);
        //    var ignoredVertex = new bool[graph.VerticesKVPs.Length];
        //    var verticesAlreadyInMIS = new List<int>();
        //    foreach (var mis in FindMIS(primaryGraph, complementaryGraph, verticesAlreadyInMIS, ignoredVertex, 0))
        //    {
        //        yield return mis.vertices;
        //    }
        //}

        private Solution Recurse(int n, GraphFast primaryGraph, GraphFast complementaryGraph, Solution currentSolution, Solution bestSolution, int latestMisSize = int.MaxValue, int lastMisId = int.MaxValue)
        {
            if (complementaryGraph.vertexCount == 0)
            {
                if (currentSolution.colourCount < bestSolution.colourCount)
                {
                    bestSolution = currentSolution.DeepClone();
                    NewBestSolutionFound?.Invoke(null, new PerformanceReport()
                    {
                        minimalNumberOfColoursUsed = bestSolution.colourCount,
                        elapsedProcessorTime       = stopwatch.Elapsed
                    });
                }
            }
            else if (currentSolution.colourCount + 1 < bestSolution.colourCount) // could improve this bound by finding a clique
            {
                // get MIS get and complimentary graph
                // compute subsolution
                var verticesAlreadyInMIS = new List <int>();
                currentSolution.colourCount += 1;
                var ignoredVertex = new bool[n];
                FindMIS(primaryGraph, complementaryGraph, verticesAlreadyInMIS, ignoredVertex, 0, mis =>
                {
                    // optionally check for cliques to delete
                    if (mis.vertices.Count < latestMisSize || (mis.vertices.Count == latestMisSize && mis.vertices[0] > lastMisId))// pre-optimization
                    {
                        currentSolution.colourLayer.Push(mis.vertices);
                        bestSolution = Recurse(n, complementaryGraph, complementaryGraph.DeepIrreversibleClone(), currentSolution, bestSolution, mis.vertices.Count, mis.vertices[0]);
                        currentSolution.colourLayer.Pop();
                    }
                    // need to fix the enumerator to ensure breakability
                    return(currentSolution.colourCount < bestSolution.colourCount);
                });
                currentSolution.colourCount -= 1;
            }
            return(bestSolution);
        }
コード例 #3
0
        // ignoredVertexCount might turn out to be useless
        private bool FindMIS(
            GraphFast graph,
            GraphFast complementaryGraph,
            List <int> verticesAlreadyInMIS,
            bool[] ignoredVertex,
            int ignoredVertexCount,
            Func <MisResult, bool> consumeAndDecideToContinue)
        {
            var continueExecution = true;

            // add detailed parameters
            if (graph.vertexCount == 0)
            {
                // ignored vertices can only be removed by nonignored so the following if is unnecessary
                // if (ignoredVertexCount == 0)
                continueExecution = consumeAndDecideToContinue(new MisResult()
                {
                    graphWithoutMIS = complementaryGraph,
                    vertices        = verticesAlreadyInMIS
                });
            }
            else
            {
                // choose a vertex v
                var chosenVertex = -1;

                var vertexScore = int.MinValue;
                for (int i = 0; i < graph.vertexCount; i++)
                {
                    var tmpVertex = graph.vertices[i];
                    if (!ignoredVertex[tmpVertex])
                    {
                        var tmpVertexScore = graph.neighbourCount[tmpVertex];
                        if (tmpVertexScore > vertexScore)
                        {
                            chosenVertex = tmpVertex;
                            vertexScore  = tmpVertexScore;
                        }
                    }
                }

                if (chosenVertex != -1)
                {
                    // ADD VERTEX V TO MIS
                    // remove the vertex and all its neighbours
                    var neighbours     = graph.neighbours[chosenVertex];
                    var neighbourCount = graph.neighbourCount[chosenVertex];

                    graph.RemoveVertex(chosenVertex);
                    var newIgnoredVertexCount = ignoredVertexCount;
                    for (int i = 0; i < neighbourCount; i++)
                    {
                        var neighbour = neighbours[i];
                        if (ignoredVertex[neighbour])
                        {
                            newIgnoredVertexCount -= 1;
                        }
                        graph.RemoveVertex(neighbour);
                    }

                    // construct complementary graph
                    complementaryGraph.RemoveVertex(chosenVertex);
                    verticesAlreadyInMIS.Add(chosenVertex);
                    continueExecution = FindMIS(graph, complementaryGraph, verticesAlreadyInMIS, ignoredVertex, newIgnoredVertexCount, consumeAndDecideToContinue);
                    verticesAlreadyInMIS.RemoveAt(verticesAlreadyInMIS.Count - 1);
                    complementaryGraph.RestoreDeletedVertex();

                    // restore

                    for (int i = 0; i < neighbourCount; i++)
                    {
                        graph.RestoreDeletedVertex();
                    }
                    graph.RestoreDeletedVertex();

                    // DO NOT ADD VERTEX V TO MIS
                    // TODO: add warnings to his neighbours, add notion that the chosen vertex needs to be "covered" by someone!
                    // each vertex has a satifiability list
                    // there is a variable representing vertices left to satisfy
                    // each vertex has a counter that (when >0) triggers satisfiability stuff
                    // TODO make extra checks here and there is it possible to satisfy an ignored vertex, if not STOP
                    if (continueExecution && graph.neighbourCount[chosenVertex] > 0)
                    {
                        ignoredVertex[chosenVertex] = true;
                        continueExecution           = FindMIS(graph, complementaryGraph, verticesAlreadyInMIS, ignoredVertex, ignoredVertexCount + 1, consumeAndDecideToContinue);
                        ignoredVertex[chosenVertex] = false;
                    }
                }
            }
            return(continueExecution);
        }