Connectivity graph of a combinational circuit - graph

I am reading the book called, "VLSI Physical Design: From Graph Partitioning to Timing Closure" by Andrew B. Kahng, Jens Lienig, Igor L. Markov, and Jin Hu.
In that book, there is a picture of a combinational circuit like shown in Fig 1.
For the combinational circuit in Fig 1, the authors show the connectivity graph as shown in Fig 2 below.
My question is, there is no connectivity directly between gates x and y. In that case, why does the graph show two edges between gates (or nodes) x and y ?
Thanks for your help.

While there is no direct connectivity between x and y (such as x feeding y), the net N1 connects three nodes: a, x, and y. So, as all three are electrically equivalent, you must preserve the connections for the relationship among all three nodes. Therefore, for N1, you need an edge between a and x, an edge between a and y, and an edge between x and y. Similarly for N2, as it connects b, x, and y, you need an edge between every pin pair among b, x, and y.
In the general case, if you have a multi-pin net, a net that connects multiple nodes, then you will need to have an edge between every pin pair:
"A p-pin net is represented by (p choose 2) total connections between its nodes"
-- connectivity graph definition on p.28.
As an aside, you can see that this is a tedious process and the number of edges can quickly grow in this model. If you use a hyperedge and hypergraph model, however, then you only need one hyperedge to represent N1 and one hyperedge to represent N2 (versus the three regular edges).
I do also want to point out that this connectivity definition is very general, and in some cases, the edges between x and y can be removed. For instance, if you are performing timing propagation (e.g., arrival time) on N1, then you only need a directed edge between a and x and a directed edge between a and y.
I hope this helps.

Related

Subgraph in LightGraphs - Julia

Say that I have a big network with 10^4 nodes. And then I want to analyse the neighbourhood associated with a random node, say node 10. I can see which are the nodes connected to that node by looking at the 10th row entries of the adjacency matrix, and then I can repeat this if I want to look at the neighbours of those neighbours (second shell) and so on and so forth.
Is there an efficient way to do this - or even an inefficient but better than writing the whole thing from the scratch-? The actual network that I have is a Random Regular Graph and I am interested on the tree-like local structure for large networks.
If I understand your use case, there is a good way of doing this: the egonet function. You give it a graph, a starting vertex, and number of hops, and it will return an induced subgraph of the graph starting at the vertex and going out that number of hops. Here's the docstring:
egonet(g, v, d, distmx=weights(g))
Return the subgraph of g induced by the neighbors of v up to distance d, using weights (optionally) provided by distmx. This is equivalent to
induced_subgraph(g, neighborhood(g, v, d, dir=dir))[1].
Optional Arguments
––––––––––––––––––––
• dir=:out: if g is directed, this argument specifies the edge direction
with respect to v (i.e. :in or :out).
Edited to add: if all you need are the vertex indices, then neighborhood() is what you want:
neighborhood(g, v, d, distmx=weights(g))
Return a vector of each vertex in g at a geodesic distance less than or equal to d, where distances may be specified by distmx.
Optional Arguments
––––––––––––––––––––
• dir=:out: If g is directed, this argument specifies the edge direction
with respect to v of the edges to be considered. Possible values: :in or :out.

Maximum number of directed graph

Given set of N points, what is the maximum number of directed graphs can be created ? I'm having trouble with isomorphic problem.
Edit (1): Only directed simple, non-loop vertex graph, doesn't required to be connected
Edit (2): Any point in this set is treated equally to each other, so the main problem here is to calculate and subtract the number of isomorphic graphs created from different sets of edges.
Number of unlabeled directed graphs with n vertices is here (OEIS A000273)
1, 1, 3, 16, 218, 9608, 1540944, 882033440, 1793359192848
There is no closed formula, approximated value is number of labeled graphs divided by number of vertex permutations:
2^(n*(n-1)) / n!
There are n-1 possible edges for each node, so a total of n(n-1) edges.
Each possible graph will either contain a particular edge, or it won't.
So the number of possible graphs is 2^(n(n-1)).
EDIT: This only applies under the assumption there are no loops and each edge is unique.
Looping is basically coming back to the same node again so I'm considering double-headed arrows are not allowed. Now, if there are n nodes available so graphs you make without loops can have n-1 edges. Now, let m be the number of homeomorphic graphs you can make out of n nodes. Let si is number of symmetries present in ith graph of those m homeomorphic graphs. These symmetries I'm talking about are the likes of we study in group theory for geometric figures. Now, we know all edge can have 2 states i.e. left head and right head.
So the total number of distinct directed graphs can be given as:
Note: If these symmetries were not present then it would have been simply m*2(n-1)
(Edit 1) Also, this valid for connected graph with n nodes. If you want to include graphs that don't need to be connected then you'll have to modify a few things in this equation or add few things like the number of smaller partitions of this n noded graph you can form and apply this formula in each of those combinations.
Permutation&Combination, Group Theory, Symmetries, Partitions, Overall it's messy so this was the only simple way I could put it.

Add iteratively one edge in a graph generated by a k regular game maintaining past connections

I have generated an undirected regular graph with an even number of nodes with the same degree, e.g. k, by using the function k.regular.game of the R package igraph.
Now I need to iteratively add one edge to each node, so that in each iteration the degree remains constant for every node and it is equal to k + i, where i is the number of iterations performed.
In addition, I want connections to be preserved in each iteration, that is: the set of neighbors of agent j for iteration i should be the same of the set of neighbors of agent j for iteration i + 1 except for one connection: e.g., if j is connected to w and y when k = 2, j must be connected to w, y and z when k = 3.
My final goal is to obtain (n-1) graphs, where n is equal to the number of nodes in the regular graph. As a result, I will obtain that the first generated graph has k = 1 and the last generated graph has k = (n-1).
Any suggestion on how to do this?
This is a nice network problem solved with two partial solutions below.
Let's imagine there is a function which would bring a graph g from all degrees being 1 to all degrees being 2. It would have to be a graph with an even number of nodes.
increment.k <- function(g){}
It follows that increment.k will increase the degree of each node by one by adding |V|/2 edges to it - one edge for each two nodes in the graph. From what I understand from your problem specification, any of those edges must not connect agin two nodes that are already connected. This makes increment.k() a puzzle in which a random edge between two nodes might close the possibility for all nodes to reach the new k-value of degrees. What if a graph has k=1 and we start adding edges at random only to arrive at the last edge only to find that the only two nodes still with degree 1 are already connected?!
I cannot intuitively grasp if this allows for the possibility of graphs that cannot be incremented since no combination of random edges allows for the creation of |V|/2 edges between previously unconnected nodes. But I can imagine that such graphs exist.
I've done this example on a graph with 20 nodes (which consequently can have a k between 1 and 19):
g <- k.regular.game(no.of.nodes=20, k=1, directed=F)
What if you were to generate random k.regular.games with a higher k until you found a graph where the edges of your graph is a subset of the edges of the higher-k random graph? It should be spectacularly slow.
The problem, of course, is that you don't want to allow for duplicated arches. If not, the solution would be quite simple:
increase.k.allowing.duplicates <- function(graph){
if(length(V(graph))%%2!=0){
stop("k can only be incremented for graphs with an even number of nodes.")
}
# Add random edges to the graph and allow dual edges just to increase k
graph %>% add_edges(as.numeric(sample(1:length(V(graph)), length(V(graph)))))
}
The above code would solve the problem if double arches were allowed. This would return graphs of ever higher k, and would let k go towards infinity since the number of nodes of the graph don't set any maximum average degree of the graph.
I have come up with this Montecarlo approach below. To increase k by one, a given number of edges is added one by one between nodes, but if the loop runs out of alternatives when placing arches between nodes that are 1) not connected and 2) not already incremented to the higher k/degree, the process of creating a new graph with a higher k starts over. The function has a maximum number of tries start over in maximum.tries.
increase.k <- function(graph, maximum.tries=200){
if(length(V(graph))%%2!=0){
stop("k can only be incremented for graphs with an even number of nodes.")
}
k <- mean(degree(graph))
if(k != round(k) ){
stop("Nodes in graph do not have the same degree")
}
if(k >= length(V(graph))-1 ) {
stop("This graph is complete")
}
# each node has the following available arches before starting the iteration:
#posisble.arches <- lapply(neighbors(graph,1), function(x) setdiff(V(graph), x[2:length(x)]))
# Here we must lay the puzzle. If we run into a one-way street with the edges we add, we'll have to start afresh
original.graph <- graph
for(it in 1:maximum.tries){
# We might need many tries to get the puzzle right by brute-forcing
# For each try we increment in a loop to avoid duplicate links
for(e_ij in 1:(length(V(graph))/2)){
# Note that while(mean(degree(graph)) < k + 1){} is a logical posibility, but less safe
# Add a new edge between two nodes of degree k. i is any such node and j is any such node not already connected to i
i <- sample(as.numeric(V(graph)[degree(graph)==k]), 1)
js <- as.numeric(V(graph)[degree(graph) == k * !V(graph) %in% c(as.numeric(neighbors(graph,i)), i)])
# Abandon this try if no node unconnected to i and with degree == k exists
if(length(js)==0){break}
j <- sample(c(js), 1); if(length(js)==1){j<-js}
graph <- graph %>% add_edges(c(i,j))
}
# Did we lay the puzzle to completion successfully crating a random graph with a higher k?
if(mean(degree(graph)) == k+1){
# Success
print(paste("Succeded at iteration ", it))
break
} else {
# Failure, let's try again
graph <- original.graph
print("Failed")
}
}
(graph)
}
# Compare the two approaches
g1 <- increase.k.allowing.duplicates(g)
g2 <- increase.k(g)
degree(g1) == degree(g2)
l <- layout_with_gem(g2)
par(mfrow=c(1,2))
plot(g1, layout=l, vertex.label="")
plot(g2,layout=l, vertex.label="")
dev.off()
# Note that increase.k() can be run incrementally up untill a complete graph:
is.complete <- function(graph){mean(degree(graph)) >= (length(V(graph))-1)}
while(!is.complete(g)){
print(mean(degree(g)))
g <- increase.k(g)
}
# and that increase.k() cannot increase k in already complete graphs.
g <- increase.k(g)
The above code has solved the problem for some graphs. More iterations are needed to lay the puzzle the larger the graph is. In this example with only 20 nodes, each k-level can be generated from 1-19 relatively quickly. I did manage to get 19 separate networks from k=1 to k=19. But I have managed to get stuck in the loop also, which I take as evidence for the existing network structures of which k cannot be successfully incremented. Particularly since the same starting specification can get stuck sometimes, but manage to arrive at a complete graph on other occasions.
To test the function, I set the maximum.tries to 25 and tried to go from k=1 to 19 100 times. It never worked. The higher the k, the more difficult it is to lay the puzzle and find arches that fit, even though the next-to-last iteration is faster before a collapse. The risk of hitting the cap of 25 increased between the 15th and 18th iteration, and most graphs only made it to k=17.
It is possible to imagine this method being performed backwards starting at a complete graph, removing edges within a Montecarlo process which tries to remove edges to achieve a graph with all degrees at k-1. It should run into similar problems, though.
The code above is really an attempt to brute-force this problem without going into the underlying mathematics of graphs of this type. I am not a mathematician and lack the skills, but maybe the creation of a fail-safe k.increment()-function is a real and unsolved mathematical problem. If any graph-theoreticians come by this post, please enlighten us.

DFS trees and DFS forests

I was learning about DfS trees from:
http://rosalind.info/glossary/algo-depth-first-search/
In the "Depth-first search in directed graphs" section if we add a node Z with no edges pointing towards it but only one edge from Z to C, then where would Z appear in the resulting DFS tree?
Would its edge from Z to C be considered a tree edge or a cross edge?
Thanks!
When you build the new DFS tree for the given question it will be obvious:
The current DFS tree for exploration of A to H is the same. Z is not part of it since it is not connected by any Edge to Z. Due to lexicographic order in selecting vertices, it won't be selected before A.
After visiting A to H, Z is not visited and those will be - in lexicographic order - selected for exploration. It will be a new Tree in the DFS forest.
Be aware that in the unidirectional case, this is only a DFS forest when you ignore the non-tree edges as shown in the sample.
The Terminology states that Cross Edges ... lead to a node that has already been completely explored. Z has an Edge to the previously explored C, those it's edge is a Cross Edge.
You should check this answer for yourself.
How the tree (or forest) looks and what type of edge ZC is depends on where the DFS is run from, and what nodes are chosen first. If the DFS visits Z before it visits C, then ZC will be a tree edge as it is the only and Z will be a part of a tree with multiple nodes. If DFS starts at Z, then there will be one tree with Z as the root node. However, if Z is only discovered once C has already been visited, then C must also have been finished (completely explored) because Z cannot be reached by any other nodes. Thus in this case, ZC is a cross edge and Z would be in a tree by itself.

Intersection between two curves

I need to obtain the intersection of two curves. The problem I'm facing can be stated in the following way:
Given two curves C1 and C2, defined by N1 and N2 points connected by straight lines, obtain all the intersections of C1 with C2. Both curves don't intersect themselves.
I tried several approaches, but none seems to work so far. Any guess?
The easiest way is to test all pairs of segments, one from each curve. If that is too slow, try a strip tree. The paper below can be found at the author's web site.
Ballard, D. H. (1981), Strip trees: a hierarchical representation for
curves, Communications of the ACM, v.24 n.5,310-321
Since your curves are comprised of line segments, I would suggest using a spatial tree (e.g. a quadtree) to only check segments that are in proximity to each other. This will reduce the complexity of your algorithm from O(N1 N2) to O(N log N) (where N = N1 + N2), assuming that the number of very close intersections is small.
Other than that, you can find intersections in this way.

Resources