Build an association that assigns an index for its connected component to every vertex:
a = Association[Join @@ MapIndexed[Thread[Rule[#1, #2[[1]]]] &, ConnectedComponents[myGraph]]]
Then you can check whether v1
and v2
belong to the same component like this:
a[v1] == a[v2]
To check many at once, you can use Lookup
:
{v1, v2} = Transpose[nodepairs1];
And @@ MapThread[SameQ, {Lookup[a, v1], Lookup[a, v2]}]
{v1, v2} = Transpose[nodepairs2];
And @@ MapThread[SameQ, {Lookup[a, v1], Lookup[a, v2]}]
True
False
Using vectorized integer operations instead of MapThread
can also give you some performance improvement. This is the code:
SameQ[Max[Unitize[Subtract[Lookup[a, v1], Lookup[a, v2]]]], 0]
OP's MemberQ
-method looks quite $O(\text{$\#$vertices} \cdot \text{$\#$nodepairs})$-ish if not $O(\text{$\#$vertices}^2 \cdot \text{$\#$nodepairs})$-ish to me.
The algorithmic complexity of my method should be in the ball park of
$$O(\text{$\#$vertices})$$
for computing the components (and the Association
) and
$$ O(\log(\text{$\#$components}) \cdot \text{$\#$nodepairs})$$
for the lookup.
If your vertex labels are simply the consecutive integers starting from 1, then you can even use a simple packed array as lookup table. The build time is quite a bit faster and the lookup is seems to be two orders of magnitude faster.
Build the lookup table:
lookup =
Normal[
SparseArray[
Join @@
MapIndexed[Thread[Rule[#1, #2[[1]]]] &,
ConnectedComponents[G]]]];
Do the check:
SameQ[Max[Unitize[Subtract[Lookup[a, v1], Lookup[a, v2]]]], 0]
Unfortunately, all these approaches do no allow for short-circuiting. This would require loop constructs like While
in the "hot"part of the code. Since Mathematica is an interpreted language, it is not well-suited for such a task. (Although one might be able to tweak, e.g. NestWhile
to make it work.) However, with the plain array lookup table, we can compile the lookup code:
cf = Compile[{{lookup, _Integer, 1}, {nodepairs, _Integer, 2}},
Block[{bool, i},
bool = True;
i = 0;
While[bool && (i < Length[nodepairs] - 1),
++i;
bool =
bool && (Compile`GetElement[nodepairs, i, 1] ==
Compile`GetElement[nodepairs, i, 2]);
];
bool
],
CompilationTarget -> "C",
RuntimeAttributes -> {Listable},
Parallelization -> True,
RuntimeOptions -> "Speed"
];
You would just call it like this:
cf[lookup, nodepairs]
This would also work (even in parallel), if nodepairs
were a list of lists of node pairs; then cf
would thread over the outer list.