[英]Efficient method for finding unique neighbors of nodes in an undirected graph without using Matlab built-in functions
I have an undirected graph of N nodes and L links, whose structure is typically described by its adjacency matrix A with N rows and N columns.我有一个N个节点和L个链接的无向图,其结构通常由其具有N行和N列的邻接矩阵A描述。 In this adjacency matrix, the value '1' denotes a link between two nodes and, conversely, '0' denotes no links.
在这个邻接矩阵中,值“1”表示两个节点之间的链接,相反,“0”表示没有链接。
I work in Matlab and want to avoid all the sophistications provided by the built-in graph()
functions such as N = neighbors(G, NODEID)
where G
is G = graph(adjm);
我在 Matlab 工作,并希望避免内置
graph()
函数提供的所有复杂性,例如N = neighbors(G, NODEID)
其中G
是G = graph(adjm);
and adjm
the adjacency matrix.并
adjm
邻接矩阵。
In this graph, I need to identify which unique nodes (neighbors) are connected to one or several starting nodes, labelled idx
.在此图中,我需要确定哪些唯一节点(邻居)连接到一个或多个起始节点,标记为
idx
。 I'm currently using the following line of code:我目前正在使用以下代码行:
fidx = unique(ceil(find(adjm(idx,:)) / numel(idx)));
where fidx
contains the neighbors (connected nodes) of a set of idx
starting nodes.其中
fidx
包含一组idx
起始节点的邻居(连接节点)。 This operation is repeated a large number of times for different nodes and after some profiling, I found that the instruction find(adjm(idx,:))
is really hindering the overall runtime.这个操作对不同的节点重复了很多次,经过一些分析,我发现指令
find(adjm(idx,:))
确实阻碍了整体运行时间。 My first attempt was to try to avoid find()
.我的第一次尝试是尽量避免
find()
。 For example using:例如使用:
A = adjm(idx,:);
A = A(:) == 1;
V = 1:size(A,1);
idx = unique(ceil(V(A) / numel(idx)));
However, this still remains too slow for my application.但是,对于我的应用程序来说,这仍然太慢了。
What are you suggestions to reduce the runtime associated with this specific section of code?您有什么建议可以减少与此特定代码部分相关的运行时间?
Here is a minimal example:这是一个最小的例子:
%Minimal example:
f = @() get_neighb();
timeit(f)
function get_neighb()
%generate a graph with a large number of nodes N, in order to have
%computations times large enough:
N = 2e4; %number of nodes
G = round( rand(N) / 1.5 );
G = triu(G) + triu(G,1)';
adjm = G - diag(diag(G));
%for visualisation purposes:
%plot(graph(adjm));
s = size(adjm,1);
%list of some nodes to search for (randomly chosen):
n_nodes_test = 2000; %number of couples to test
%In this minimal example, we focus on searching for the neighbors of each couple (2-tuple) of
%nodes only. But 'snodes' can be single nodes or n-tuples, i.e. containing more
%than 2 nodes
snodes = [ round(linspace(1, s/2, n_nodes_test)); round(linspace(s/2, s, n_nodes_test))]';
%This section is the critical one:
for i=1:n_nodes_test
idx = snodes(i,:); %assign current couple of starting nodes to 'idx'.
%fidx = unique(ceil(find(adjm(idx,:)) / numel(idx)));
%can be replaced by the following:
A = adjm(idx,:);
A = A(:) == 1;
V = 1:size(A,1);
idxf = unique(ceil(V(A) / numel(idx)));
%which is similar to (using Matlab built-in 'graph' functions):
% G = graph(adjm);
% T = unique([neighbors(G, snodes(1,1)); neighbors(G, snodes(1,2))]);
% here idxf' == T
end
end
You can use any
, so the code will be reduced to:您可以使用
any
,因此代码将简化为:
idxf = find(any(adjm(idx, :)));
Explanation:解释:
Assume that you have two logical row vectors A
and B
and you want to find a vector C
that contains 1
where any of elements of A
or B
are 1
.假设您有两个逻辑行向量
A
和B
并且您想要找到一个向量C
,其中包含1
,其中A
或B
的任何元素都是1
。 In other words we want to find the unique indices of A
or B
where they that contain 1
.换句话说,我们想要找到包含
1
的A
或B
的唯一索引。 We simply can use logical OR
operator:我们可以简单地使用逻辑
OR
运算符:
C = A | B;
Equivalently you can use any
function to compute C
:等效地,您可以使用
any
function 来计算C
:
C = any([A;B]);
When we use idx = find(C)
the indices will be unique and there is no need to use the unique
function.当我们使用
idx = find(C)
时,索引将是唯一的,不需要使用unique
function。
A second solution第二种解决方案
idxf = find(idx * adjm);
Here we can use vector by matrix multiplication idx * adjm
that is equivalent to sum(adjm(idx, :))
.在这里,我们可以使用矩阵乘法
idx * adjm
的向量,相当于sum(adjm(idx, :))
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.