The previous post can be found here, be sure to check it out so you
can
follow the process step by step. Since then, another two very significant features of the algorithm have been
implemented and tested: node pair candidate selection and feasibility checks.
As previously described, in the ISO problem we are basically trying to create a mapping such that, every node
from the first graph is matched to a node from the second graph. This searching for “feasible pairs” can be visualized
by a tree, where each node is the candidate pair that we should examine. This can become much clearer if we take a look
at the below figure.
In order to check if the graphs , are isomorphic, we check every candidate pair of nodes and if it is
feasible, we extend the mapping and go deeper into the tree of pairs. If it’s not feasible, we climb up and follow a
different branch, until every node in is mapped to a node . In our example, we start by examining node 0 from G1, with
node 0 of G2. After some checks (details below), we decide that the
nodes 0 and 0 are matching, so we go deeper to map the remaining nodes. The next pair is 1-3, which fails the
feasibility check, so we have to examine a different branch as shown. The new branch is 1-2, which is feasible, so we
continue on using the same logic until all the nodes are mapped.
Although in our example we use a random candidate pair of nodes, in the actual implementation we are able to target
specific pairs that are more likely to be matched, hence boost the performance of the algorithm. The idea is that, in
every step of the algorithm, given a candidate
we compute the candidates
where and are the nodes of and respectively. Now this is a puzzle that does not require a lot of
specific knowledge on graphs or the algorithm itself. Keep up with me, and you will realize it yourself. First, let
be the mapping so far, which includes all the “covered nodes” until this point. There are actually three different
types of nodes that we might encounter.
Node has no neighbors (degree of equals to zero). It would be redundant to test
as candidates for , nodes from that have more than zero neighbors. That said, we eliminate most of the possible
candidates and keep those that have the same degree as (in this case, zero). Pretty easy right?
Node has neighbors, but none of them belong to the mapping. This situation is illustrated in the following figure.
The grey lines indicate that the nodes of (left 1,2) are mapped to the nodes of (right 1,2). They are basically
the mapping. Again, given , we make the observation that candidates of u, should also have no neighbors in the
mapping, and also have the same degree as (as in the figure). Notice how if we add a neighbor to , or if we place
one of its neighbors inside the mapping, there is no point examining the pair for matching.
Node has neighbors and some of them belong to the mapping. This scenario is also depicted in the below figure.
In this case, to obtain the candidates for , we must look into the neighborhoods of nodes from , which map back
to the covered neighbors of . In our example, has one covered neighbor (1), and 1 from maps to 1 from ,
which has as neighbor. Also, for v to be considered as candidate, it should have the same degree as , obviously.
Notice how every node that is not in the neighborhood of 1 (in ) cannot be matched to without breaking the
isomorphism.
Let’s assume that given a node , we obtained its candidate following the process described in the previous section.
At this point, the Feasibility Rules are going to determine whether the mapping should be extended by the pair
or if we should try another candidate. The feasibility of a pair is examined by consistency and
cutting checks.
At, first I am going to present the mathematical expression of the consistency check. It may seem complicated at first,
but it’s going to be made simple by using a visual illustration. Using the notation for the neighborhood of u
in graph , the consistency rule is:
We are going to use the following simple figure to demystify the above equation.
The mapping is depicted as grey lines between the nodes that are already mapped, meaning that 1 maps to A and 2 to B.
What is implied by the equation is that, for two nodes and to pass the consistency check, the neighbors of
that belong in the mapping, should map to neighbors of (and backwards). This could be checked by code as simple
as:
where the final two lines also check the number of edges between node and its neighbor , which should be
the same as those between and its neighbor which maps to. At a very high level, we could describe this
check as a 1-look-ahead check.
We have previously discussed what and represent (see previous post). These sets are used in the
cutting checks as follows: the number of neighbors of that belong to , should be equal to the number of
neighbors of that belong to . Take a moment to observe the below figure.
Once again, node 1 maps to A and 2 to B. The red nodes (4,5,6) are basically and the yellow ones (C,D,E) are .
Notice that in order for to be feasible, should have the same number of neighbors, inside ,
as in . In every other case, the two graphs are not isomorphic, which can be verified visually. For this
example, both nodes have 2 of their neighbors (4,6 and C,E) in and respectively. Careful! If we delete the
edge and connect to , the cutting condition is still satisfied. However, the feasibility is going to fail,
by the consistency checks of the previous section. A simple code to apply the cutting check would be:
where T1out and T2out correspond to and respectively. And yes, we have to check for
those as well, however we skipped them in the above explanation for simplicity.