Exemple #1
0
        // Tests whether a vertex is simplicial
        public bool TestSimplicial(FVertex v)
        {
#if !DFS_SIMPLICIALRULE
            return(false);
#else
            // Signal edges: we remember which edges are currently missing to hopefully speed the check up
            if (v.SignalA != null && v.SignalB != null && IsVertex(v.SignalA) && IsEdge(v, v.SignalA) && IsEdge(v, v.SignalB) && IsVertex(v.SignalB) && !IsEdge(v.SignalA, v.SignalB))
            {
                return(false);
            }

            for (int i = 0; i < v.Degree; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (!IsEdge(v.AdjList[i], v.AdjList[j]))
                    {
                        v.SignalA = baseVertices[v.AdjList[i]];
                        v.SignalB = baseVertices[v.AdjList[j]];
                        return(false);
                    }
                }
            }

            return(true);
#endif
        }
Exemple #2
0
        // Undoes the elimination (or contraction) of a vertex
        public void Uneliminate()
        {
            FVertex restoreVertex = baseVertices[undoStack.Pop().a];

            foreach (int u in restoreVertex.Adj)
            {
                AddAdj(baseVertices[u], restoreVertex);
            }

            currentVertices[vertexCount] = currentVertices[restoreVertex.ListLocation];
            currentVertices[restoreVertex.ListLocation].ListLocation = vertexCount;
            currentVertices[restoreVertex.ListLocation] = restoreVertex;
            vertexPresent[restoreVertex.Id]             = true;
            vertexCount++;

            while (undoStack.Count > 0)
            {
                UndoInfo ui = undoStack.Peek();
                if (ui.b < 0)
                {
                    break;
                }
                undoStack.Pop();
                RemoveEdge(ui.a, ui.b);
            }
        }
Exemple #3
0
        public FastGraph(Graph G)
        {
            Vertex[] temp = G.vertices.Keys.ToArray();

            vertexCount   = temp.Length;
            vertexPresent = new BitArray(vertexCount);
            baseVertices  = new FVertex[vertexCount]; currentVertices = new FVertex[vertexCount];
            adjMatrix     = new int[vertexCount, vertexCount];
            layerData     = new DFSData[vertexCount];
            rep           = new FVertex[vertexCount]; rank = new int[vertexCount];
            degreeLists   = new List <int> [vertexCount];
            //commonNeighbors = new int[vertexCount, vertexCount];

            for (int i = 0; i < vertexCount; i++)
            {
                baseVertices[i]    = new FVertex(i, i, vertexCount, temp[i]);
                currentVertices[i] = baseVertices[i];
                vertexPresent[i]   = true;
                layerData[i]       = new DFSData(vertexCount);
                degreeLists[i]     = new List <int>();
            }

            foreach (Edge e in G.edges)
            {
                AddEdge(Array.IndexOf(temp, e.a), Array.IndexOf(temp, e.b));
            }
        }
Exemple #4
0
 // Find with path compression
 FVertex Find(FVertex cur)
 {
     if (rep[cur.Id] != cur)
     {
         rep[cur.Id] = Find(rep[cur.Id]);
     }
     return(rep[cur.Id]);
 }
Exemple #5
0
        // Remove b from a's adj list
        public void RemoveAdj(FVertex a, FVertex b)
        {
            a.AdjVector[b.Id] = false;
            a.Degree--;
            a.AdjList[adjMatrix[a.Id, b.Id]]     = a.AdjList[a.Degree];
            adjMatrix[a.Id, a.AdjList[a.Degree]] = adjMatrix[a.Id, b.Id];

            //foreach (int c in b.Adj)
            //commonNeighbors[a.Id, c]--;
        }
Exemple #6
0
        // Add b to a's adj list
        public void AddAdj(FVertex a, FVertex b)
        {
            a.AdjVector[b.Id]     = true;
            a.AdjList[a.Degree]   = b.Id;
            adjMatrix[a.Id, b.Id] = a.Degree;
            a.Degree++;

            //foreach (int c in b.Adj)
            //commonNeighbors[a.Id, c]++;
        }
Exemple #7
0
        // Adds an edge between a and b, returns true if the edge was added, false if the edge already existed
        public bool AddEdge(FVertex a, FVertex b)
        {
            if (IsEdge(a, b))
            {
                return(false);
            }

            AddAdj(a, b);
            AddAdj(b, a);

            return(true);
        }
Exemple #8
0
        // Attempts to remove the edge between a and b, returns true if the edge was removed, false if the edge does not exist
        public bool RemoveEdge(FVertex a, FVertex b)
        {
            if (!IsEdge(a, b))
            {
                return(false);
            }

            RemoveAdj(a, b);
            RemoveAdj(b, a);

            return(true);
        }
Exemple #9
0
        // Remove vertex and incident edges
        public void RemoveVertex(FVertex a)
        {
            foreach (int u in a.Adj)
            {
                RemoveAdj(baseVertices[u], a);
            }

            vertexCount--;
            currentVertices[a.ListLocation]           = currentVertices[vertexCount];
            currentVertices[vertexCount].ListLocation = a.ListLocation;
            vertexPresent[a.Id] = false;

            undoStack.Push(new UndoInfo(a.Id, -1));
        }
Exemple #10
0
        // Eliminate a vertex
        public void EliminateVertex(FVertex a)
        {
            foreach (int u in a.Adj)
            {
                foreach (int v in a.Adj)
                {
                    if (u < v && AddEdge(u, v))
                    {
                        undoStack.Push(new UndoInfo(u, v));
                    }
                }
            }

            RemoveVertex(a);
        }
Exemple #11
0
 // Union by rank
 void Union(FVertex x, FVertex y)
 {
     x = Find(x); y = Find(y);
     if (rank[x.Id] < rank[y.Id])
     {
         rep[x.Id] = y;
     }
     else
     {
         rep[y.Id] = x;
         if (rank[x.Id] == rank[y.Id])
         {
             rank[x.Id]++;
         }
     }
 }
Exemple #12
0
        // Tests whether a vertex is almost simplicial
        public bool TestAlmostSimplicial(FVertex v, int upper)
        {
#if !DFS_ALMOSTSIMPLICIALRULE
            return(false);
#else
            if (v.Degree >= upper)
            {
                return(false);
            }

            int sa = v.SignalA.Id, sb = v.SignalB.Id;

            for (int i = 0; i < v.Degree; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (!IsEdge(v.AdjList[i], v.AdjList[j]))
                    {
                        if ((i == sa && j == sb) || (j == sa && i == sb))
                        {
                            continue;
                        }
                        else if (i == sa || j == sa)
                        {
                            sb = sa;
                        }
                        else if (i == sb || j == sb)
                        {
                            sa = sb;
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
#endif
        }
Exemple #13
0
        public List <int> DFS(int upper, FVertex prev)
        {
            // Keep track of current elimination order
            if (prev != null)
            {
                currentOrder.RemoveRange(baseVertices.Length - vertexCount - 1, currentOrder.Count - (baseVertices.Length - vertexCount - 1));
                currentOrder.Add(prev);
            }

            // Apply DVS pruning rule
            currentLayer.DVS.Clear();
            if (!ComputeDVS(true))
            {
                return(null);
            }
            ComputeDVS(false);

            // Use MMW or not
#if DFS_MMW
            int lb = MMW(upper);
#elif DFS_MMW_LIMITED
            int lb = baseVertices.Length - vertexCount < 7 ? MMW(upper) : 0;
#else
            int lb = 0;
#endif

            Program.TotalExpanded++; // Statistics
            //if (Program.TotalExpanded % 100000 == 1) Console.WriteLine(Program.TotalExpanded / 1000 + ",000 " + upper + " " + baseVertices.Length + " " + lb + " " + vertexCount + " " + currentLayer.DVS.Count());

            // Inreasible?
            if (lb > upper)
            {
                return(null);
            }

            // Are we done because any order will work from this point?
            if (vertexCount <= upper)
            {
                return(Vertices.Select(v => v.Id).ToList());
            }

            // Try to find the highest-degree (almost)-simplicial vertex
            FVertex simplicialVertex = null;
            foreach (FVertex v in Vertices)
            {
                if ((simplicialVertex == null || v.Degree > simplicialVertex.Degree) && (TestSimplicial(v) || TestAlmostSimplicial(v, upper)))
                {
                    simplicialVertex = v;
                    if (v.Degree >= upper)
                    {
                        return(null);
                    }
                }
            }

            // We found a simplicial vertex
            if (simplicialVertex != null)
            {
                // Pruned due to nogoods
                if (currentLayer.nogoods.Contains(simplicialVertex))
                {
                    return(null);
                }

                // A nogood vertex becomes good if we eliminate a vertex adjacent to it
                List <FVertex> newnogoods = nextLayer.nogoods;
                newnogoods.Clear();
                foreach (FVertex u in currentLayer.nogoods)
                {
                    if (!IsEdge(u, simplicialVertex))
                    {
                        newnogoods.Add(u);
                    }
                }

                // Eliminate and go deeper
                EliminateVertex(simplicialVertex);
                EdgeAddition(upper);
                List <int> result = DFS(upper, simplicialVertex);
                Uneliminate();

                // Feasible
                if (result != null)
                {
                    result.Add(simplicialVertex.Id);
                    return(result);
                }

                // Not feasible
                return(null);
            }

            // Branching!
            foreach (FVertex v in Vertices)
            {
                // Check nogoods, and we never need to eliminate two adjacent vertices subsequently (note that we can not apply this latter rule to prune simplicial vertices)
                if (currentLayer.nogoods.Contains(v) || (prev != null && IsEdge(prev, v)))
                {
                    continue;
                }

                if (v.Degree < upper)
                {
                    // A nogood vertex becomes good if we eliminate a vertex adjacent to it
                    List <FVertex> newnogoods = nextLayer.nogoods;
                    newnogoods.Clear();
                    foreach (FVertex u in currentLayer.nogoods)
                    {
                        if (!IsEdge(u, v))
                        {
                            newnogoods.Add(u);
                        }
                    }

                    // Eliminate and go deeper
                    EliminateVertex(v);
                    EdgeAddition(upper);
                    List <int> result = DFS(upper, v);
                    Uneliminate();

                    // Found a solution
                    if (result != null)
                    {
                        result.Add(v.Id);
                        return(result);
                    }

                    // In next layers, do not eliminate v before eliminating a neighbor of v
                    currentLayer.nogoods.Add(v);
                }
            }

            // We didn't manage to find a solution in this branch
            return(null);
        }
Exemple #14
0
        // Computes the minor-min-width LB heuristic
        public int MMW(int upper)
        {
            int oldCount = vertexCount;

            foreach (FVertex v in Vertices)
            {
                degreeLists[v.Degree].Add(v.Id);
            }
            int min = 0;

            int lb = upper;

            while (vertexCount > 0)
            {
                // We won't be able to find a better bound this way (max degree = upper - 1)
                if (vertexCount <= lb)
                {
                    break;
                }

                // We use a priority queue implemented by having a list for each priority, to find the smallest vertex more quickly
                // Idea due to Dow and Korf
                FVertex minDegree = null;
                while (true)
                {
                    while (degreeLists[min].Count == 0)
                    {
                        min++;
                    }
                    minDegree = baseVertices[degreeLists[min][degreeLists[min].Count - 1]];
                    degreeLists[min].RemoveAt(degreeLists[min].Count - 1);
                    if (minDegree.Degree == min && IsVertex(minDegree))
                    {
                        break;
                    }
                }

                lb = Math.Max(lb, minDegree.Degree + 1);

                // We already found a good enough bound
                if (lb > upper)
                {
                    break;
                }

                // Find neighbor with least number of common edges
                FVertex minNb      = null;
                int     mintersect = int.MaxValue;
                foreach (int v in minDegree.Adj)
                {
                    int mytersect = CommonNB(minDegree, baseVertices[v]);

                    if (mytersect < mintersect || (mytersect == mintersect && baseVertices[v].Degree > minNb.Degree))
                    {
                        mintersect = mytersect;
                        minNb      = baseVertices[v];
                    }
                }

                // We are going to contract minDegree into minNb
                foreach (int u in minDegree.Adj)
                {
                    if (u == minNb.Id)
                    {
                        continue;
                    }

                    if (AddEdge(u, minNb.Id))
                    {
                        undoStack.Push(new UndoInfo(u, minNb.Id));
                    }
                    else
                    {
                        degreeLists[baseVertices[u].Degree - 1].Add(u);
                        min = Math.Min(min, baseVertices[u].Degree - 1);
                    }
                }

                RemoveVertex(minDegree);
                degreeLists[minNb.Degree].Add(minNb.Id);
                min = Math.Min(min, minNb.Degree);
            }

            // Restore the damage
            while (vertexCount < oldCount)
            {
                Uneliminate();
            }

            while (min < vertexCount)
            {
                degreeLists[min++].Clear();
            }

            return(lb);
        }
Exemple #15
0
 // Tests whether a given vertex is currently in the graph
 public bool IsVertex(FVertex v)
 {
     return(IsVertex(v.Id));
 }
Exemple #16
0
 public bool IsEdge(FVertex a, FVertex b)
 {
     return(IsEdge(a.Id, b.Id));
 }
Exemple #17
0
 public int CommonNB(FVertex a, FVertex b)
 {
     return(a.AdjVector.XORCount(b.AdjVector));
 }