我有一些节点和边
nodes = [
{ id: 'n1', propositions: ['p'] },
{ id: 'n2', propositions: ['p'] },
{ id: 'n3', propositions: ['p'] }
];
edges = [
{ source: 'n1', target: 'n2' },
{ source: 'n2', target: 'n1' },
{ source: 'n1', target: 'n3' },
{ source: 'n2', target: 'n3' }
];
如数据中所示,两个节点n1
和n2
相互指向,n1
和n2
都指向{{1} }。
我正在尝试在JavaScript中的http://homepages.cwi.nl/~jve/courses/lai0506/LAI11.pdf#page=25上实现该算法。
据我所知,初始分区只有一个包含所有三个节点n3
,n1
和n2
的块。第二个分区在一个子块中有n3
和n1
,在另一个子块中有n2
。第三个分区与第二个分区相同,因此迭代将停止。正如我所理解的,子块中的所有节点都是冗余的,除了一个,所以我可以删除它们并只保留一个。
我首先通过使用相同的命题对节点进行分组来创建初始分区Pi_0。然后我继续迭代,直到自上一个分区以来没有进行任何更改。
到目前为止我想出的是
n3
但我不知道该怎么做而不是我写/**
* Initial partition
**/
// blocks in initial partition
const partition = {};
// group nodes into blocks based on propositions
nodes.forEach(function (node) {
// use propositions as key
const key = node.propositions.sort().join();
// create block if it does not already exists
if (!partition[key]) {
partition[key] = [];
}
// add node to block
partition[key].push(node);
});
/**
* Iterate until P_{i} = P_{i - 1}
**/
// repeat until Pi_{i} = Pi_{i-1}
while (true) {
// get ready to partition each block in the partition into subblocks
const newPartition = {};
// go through each block in partition
Object.keys(partition).forEach(function (blockName) {
// get block by blockName
const nodesInBlock = partition[blockName];
// go through each node in the block
nodesInBlock.forEach(function (sourceNode) {
// ...
// ...
// create subblock if it doesn't already exists
if (!newPartition[key]) {
newPartition[key] = [];
}
// add node to subblock
newPartition[key].push(sourceNode);
});
}
});
// if nothing changed
if (Object.keys(partition).length === Object.keys(newPartition).length) {
break;
} else {
partition = newPartition;
}
}
}
的片段。
我想我应该得到节点所指向的块的名称(即目标节点的块名称),然后从源节点的块名称和目标节点&创建一个键。 #39; s块名称。我只是不知道如何。从page 27开始,Haskell中描述了实现,但我不了解Haskell,所以它不会帮助我。
我猜分区看起来应该是这样的
...
因为第二个和第三个相等,迭代过程停止。