Chaitin-Briggs Algorithm explanation - algorithm

I googled it but I haven't found some good material about this topic.
Where can I find more information about Chaitin-Briggs graph-coloring algorithm? Or can somebody explain how it works?

The key insight to Chaitin’s algorithm is called the degree < R rule which is as follows.
Given a graph G which contains a node N with degree less than R, G is R-colorable iff the graph G’, where G’ is G with node N removed, is R-colorable. The proof is obvious in one direction: if a graph G can be colored with R colors then the graph G’ can be created without changing the coloring. In the other direction supposed we have an R-coloring of G’. Since N has a degree of less than R there must be at least one color that is not in use for a node adjacent to N. We can color N with this color.
The algorithm is as follows:
While G cannot be R-colored
While graph G has a node N with degree less than R
Remove N and its associated edges from G and push N on a stack S
End While
If the entire graph has been removed then the graph is R-colorable
While stack S contains a node N
Add N to graph G and assign it a color from the R colors
End While
Else graph G cannot be colored with R colors
Simplify the graph G by choosing an object to spill and remove its node N from G
(spill nodes are chosen based on object’s number of definitions and references)
End While
The complexity of the Chaitin-Briggs algorithm is O(n2) because of the problem of spilling. A graph G will only fail to be R-colorable if at some point the reduced graph G’ only has nodes of degree R or greater. When a graph is easily R-colorable the cost of a single iteration is O(n) because we make two trips through the graph and either remove or add one node each time. But spilling brings in additional complexity because we may need to spill an arbitrary number of nodes before G becomes R-colorable. For every node we spill we make another trip through the linear algorithm
You can also go through this Register allocation algorithm

Related

Specific Graph and need to more Creative solution

Directed Graph (|V|=a, |E|=b) is given.
each vertexes has specific weight. we want for each vertex (1..a) find a vertex with maximum weight that can be reachable from that vertex.
Update 1: one nice answer is prepare by #Paul in O(b + a log a). but I
search for O(a + b) algorithms, if any?
Is there any different efficient or fastest any other ways for doing it?
Yes, it's possible to modify Tarjan's SCC algorithm to solve this problem in linear time.
Tarjan's algorithm uses two node fields to drive its SCC finding logic: index, which represents the order in which the algorithm discovers the nodes; and lowlink, the minimum index reachable by a sequence of tree arcs followed by a back arc. As part of the same depth-first traversal, we can compute another field, maxweight, which has one of two meanings:
For a node not yet included in a finished SCC, it represents the maximum weight reachable by a sequence of tree arcs, optionally followed by a cross arc to another SCC and then any subsequent path.
For nodes in a finished SCC, it represents the maximum weight reachable.
The logic for computing maxweight is as follows. If we discover an arc from v to a new node w, then vw is a tree arc, so we compute w.maxweight recursively and update v.maxweight = max(v.maxweight, w.maxweight). If w is on the stack, then we do nothing, because vw is a back arc and not included in the definition of maxweight. Otherwise, vw is a cross arc, and we do the same update that we would have done for a tree arc, just without the recursive call.
When Tarjan's algorithm identifies an SCC, it's because it has a node r with r.lowlink == r.index. Since r is the depth-first search root of this SCC, its value of maxweight is correct for the whole SCC. Instead of recording each node in the SCC, we simply update its maxweight to r.maxweight.
Sort all nodes by weight in decreasing order and create the graph g' with all edges in E reversed (i.e. if there's an edge a -> b in g, there's an edge b -> a in g'). In this graph you can now propagate the maximum-value by simple DFS. Do this iteratively for all nodes and terminate when a maximum-weight has already been assigned.
As pseudocode:
dfs_assign_weight_reachable(node, weight):
if node.max_weight_reachable >= weight:
return
node.max_weight_reachable = weight
for n = neighbor of node:
dfs_assign_weight_reachable(n, weight)
g' = g with all edges reversed
nodes = nodes from g' sorted descendingly by weight
assign max_weight_reachable = -inf to each node in nodes
for node in nodes:
dfs_assign_weight_reachable(node, node.weight)
UPDATE:
The tight bound is O(b + a log a). a log a is caused by the sorting step. And each edge gets visited once during the reversal step and once during the assigning maximum weights, giving the second term in the max-expression.
Acknowledgement:
I'd like to thank #SerialLazer for the time invested in a discussion about the time-complexity of the above algorithm and helping me figure out the correct bound.

Optimal edge coloring in bipartite graphs

I've faced with following problem: find the optimal edge coloring in a bipartite graph. I know that greedy coloring algorithm can sometimes not return the optimal number of colors. By 'greedy coloring algorithm' I mean: choose first vertex with the highest degree and color its edges on colors 1...degree, then choose the vertex with degree <= to the previous degree and color every of its incident edge on the first available number (the lowest number which is not used by its neighbour), the choose the next vertex etc.
But I've introduced one modification: the edges of first choosen vertex I color in descending order (degree...1), and edges of the next vertices as previously on 1...degree. This modification resulted in examples which I've come up I've got optimal number of colors. But I'm not pretty sure that it's always a rule. Does somebody know if this version of edge coloring algorithm is optimal, or maybe anyone is able to show any counterexample?
You can take your counterexample for the "naive" greedy algorithm and turn it into a counterexample for your "sophisticated" greedy algorithm. Simply insert dummy nodes with appropriate degree to "absorb" the backwards colorings. One can always fabricate a new node with degree n in an arbitrary part of the graph: simply insert n fresh nodes in the other part and connect them each by a single edge to the desired new node.
Since all nodes that get colored in descending order are freshly inserted, all the nodes in the original counterexample are colored in ascending order, hence get the same colors as they would have in the original "naive" greedy algorithm. Since the optimal coloring has at least as many colors as the degree of the original graph, and the freshly inserted nodes all have smaller degree than the original graph's maximal degree, the new graph does not need any more colors than the original. Therefore the coloring produced by the "sophisticated" algorithm -- which will still have more colors than necessary for the original graph -- is not optimal for the new graph.
For example, take the graph described in the comment below, which has nodes B,C,D on the left and E,F,G,H on the right. It has these edges:
B connects to E, F, and G
C connects to E, F, and G
D connects to G and H
For the moment, I will assume only the first node you touch gets colored in descending order. (For other nodes, it is not even clear what "descending order" might mean -- descending from what maximum? The degree of the node may not be high enough.)
Therefore, we insert a new node A on the left and three nodes I, J, and K on the right; the connectivity is now
A connects to I, J, and K
B connects to E, F, and G
C connects to E, F, and G
D connects to G and H
The sophisticated greedy algorithm will therefore color AI-3, AJ-2, AK-1, then proceed as the naive greedy algorithm on the remaining nodes.

Weighted graph and all pairs path

Am trying to solve a question at this link:
https://www.chegg.com/homework-help/questions-and-answers/consider-weighted-directed-graph-g-n-vertices-e-edges-weights-integers-suppose-g-contains--q12054851
(this is not a homework question)
Consider a weighted directed graph G with n vertices and e edges, and the weights are integers. Suppose that G contains no negative cycles, and for every pair of vertices u and v in G, the distance from u to v falls in the range [-2d, 2d] for some positive integer d. We are going to fix a particular edge (x,y) in G, and consider what happens to the distances in G as we change the weight associated with that edge (and leave all other edge weights fixed).
Design an algorithm that takes G as input, as well as a specified edge (x,y) in G. The output of the algorithm should be an integral range of values that the weight of this edge (x,y) could take such that all of the distances in G would remain the same. Note that this range will be non-empty, as it must include the original weight of the edge (x,y). Also note that infinity may occur as an endpoint of your range (i.e. the range may not be finite). For this, you may return “∞” as an endpoint. The running time of your algorithm must be polynomial in n,e, and d (so your running time should not have any of these parameters appearing as exponents). Prove why the algorithm is correct.
I have been thinking on the following lines:
Since distances are in a range, weights should also be in a range. One option is we run Djkstra's multiple times. How do we optimize this?
Yes, you can run Dijkstra n times. Alternatively you can run Floyd-Warshall, which is designed for these problems. Overall, they have similar complexity bounds.

Consensus on multiple graphs

Let G = (V,E) be a Directed Acyclic Graph (DAG). V is the set of vertexes, while E is the set of edges.
Now, suppose that G is corrupted by some annotators in a crowd, according to the crowdsourcing paradigm:
Some of them may decide to remove some edge e belonging to E
Some of them may decide to add an edge e which was not existing
The result of the work of an annotator i is a graph whose set of vertexes V is the same as the original one and whose set of edges Ei may differ from the original one. If n is the number of annotators, we come up with n different graphs, having the same set of vertexes V, but a different set of edges E. Let G1 = (V,E1), ..., Gn = (V,En) be the set of graphs.
I would like to know whether there is a way of merging these graphs, so as to find a consensus on the presence/absence of each possible edge e between two vertexes v1,v2 in V. The purpose of this operation is the one of fusing the opinion of each annotator about the construction of the set of edges E in the graph G. The final graph has to be a DAG.
Let...
U be the distinct union of all Ei sets plus the original set E
T be some arbitrary threshold value
H(x) be some heuristic function
F be the final consensus set of edges
Pseudocode:
for each Edge e in U
if H(e) >= T then F.Add(e)
The question is then of course how to define your heuristic function. A naive approach would be set based voting. Count the number of E sets containing the edge, and if enough people agree that it's in the graph, include it. This is a simple and efficient function to implement. Some weaknesses of this heuristic are its inability to detect and compensate for bad annotators or small crowd sizes.
For each edge count the number of graphs that contains it. If it is greater than some threshold, assume it was an original edge.
You may face some problems if some of the actions are biased. That is, each user does not randomly choose a particular edge to act upon.

minimum connected subgraph containing a given set of nodes

I have an unweighted, connected graph. I want to find a connected subgraph that definitely includes a certain set of nodes, and as few extras as possible. How could this be accomplished?
Just in case, I'll restate the question using more precise language. Let G(V,E) be an unweighted, undirected, connected graph. Let N be some subset of V. What's the best way to find the smallest connected subgraph G'(V',E') of G(V,E) such that N is a subset of V'?
Approximations are fine.
This is exactly the well-known NP-hard Steiner Tree problem. Without more details on what your instances look like, it's hard to give advice on an appropriate algorithm.
I can't think of an efficient algorithm to find the optimal solution, but assuming that your input graph is dense, the following might work well enough:
Convert your input graph G(V, E) to a weighted graph G'(N, D), where N is the subset of vertices you want to cover and D is distances (path lengths) between corresponding vertices in the original graph. This will "collapse" all vertices you don't need into edges.
Compute the minimum spanning tree for G'.
"Expand" the minimum spanning tree by the following procedure: for every edge d in the minimum spanning tree, take the corresponding path in graph G and add all vertices (including endpoints) on the path to the result set V' and all edges in the path to the result set E'.
This algorithm is easy to trip up to give suboptimal solutions. Example case: equilateral triangle where there are vertices at the corners, in midpoints of sides and in the middle of the triangle, and edges along the sides and from the corners to the middle of the triangle. To cover the corners it's enough to pick the single middle point of the triangle, but this algorithm might choose the sides. Nonetheless, if the graph is dense, it should work OK.
The easiest solutions will be the following:
a) based on mst:
- initially, all nodes of V are in V'
- build a minimum spanning tree of the graph G(V,E) - call it T.
- loop: for every leaf v in T that is not in N, delete v from V'.
- repeat loop until all leaves in T are in N.
b) another solution is the following - based on shortest paths tree.
- pick any node in N, call it v, let v be a root of a tree T = {v}.
- remove v from N.
loop:
1) select the shortest path from any node in T and any node in N. the shortest path p: {v, ... , u} where v is in T and u is in N.
2) every node in p is added to V'.
3) every node in p and in N is deleted from N.
--- repeat loop until N is empty.
At the beginning of the algorithm: compute all shortest paths in G using any known efficient algorithm.
Personally, I used this algorithm in one of my papers, but it is more suitable for distributed enviroments.
Let N be the set of nodes that we need to interconnect. We want to build a minimum connected dominating set of the graph G, and we want to give priority for nodes in N.
We give each node u a unique identifier id(u). We let w(u) = 0 if u is in N, otherwise w(1).
We create pair (w(u), id(u)) for each node u.
each node u builds a multiset relay node. That is, a set M(u) of 1-hop neigbhors such that each 2-hop neighbor is a neighbor to at least one node in M(u). [the minimum M(u), the better is the solution].
u is in V' if and only if:
u has the smallest pair (w(u), id(u)) among all its neighbors.
or u is selected in the M(v), where v is a 1-hop neighbor of u with the smallest (w(u),id(u)).
-- the trick when you execute this algorithm in a centralized manner is to be efficient in computing 2-hop neighbors. The best I could get from O(n^3) is to O(n^2.37) by matrix multiplication.
-- I really wish to know what is the approximation ration of this last solution.
I like this reference for heuristics of steiner tree:
The Steiner tree problem, Hwang Frank ; Richards Dana 1955- Winter Pawel 1952
You could try to do the following:
Creating a minimal vertex-cover for the desired nodes N.
Collapse these, possibly unconnected, sub-graphs into "large" nodes. That is, for each sub-graph, remove it from the graph, and replace it with a new node. Call this set of nodes N'.
Do a minimal vertex-cover of the nodes in N'.
"Unpack" the nodes in N'.
Not sure whether or not it gives you an approximation within some specific bound or so. You could perhaps even trick the algorithm to make some really stupid decisions.
As already pointed out, this is the Steiner tree problem in graphs. However, an important detail is that all edges should have weight 1. Because |V'| = |E'| + 1 for any Steiner tree (V',E'), this achieves exactly what you want.
For solving it, I would suggest the following Steiner tree solver (to be transparent: I am one of the developers):
https://scipjack.zib.de/
For graphs with a few thousand edges, you will usually get an optimal solution in less than 0.1 seconds.

Resources