出于学习目的,我正在开发一个在现实生活中基本上可以像Quartz Composer或最近的Vuo一样工作的应用程序。我正在基于核心数据框架构建节点图。
基本上我有一个与输入和输出实体有一对多关系的节点实体(一个节点可以有多个输入和多个输出)。Input与Connection实体是一对一的关系,而Output与后者是一对多的关系(一个输入只能有一个连接,而一个输出可以有多个)。
要阅读图表,我使用的是拓扑排序算法(Kahn 的算法),在此处进行了描述。代码如下:
/**
* Get all nodes.
*/
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Node"];
NSMutableArray *nodes = [[[_document managedObjectContext] executeFetchRequest:request error:nil] mutableCopy];
/**
* Reset the nodes 'visited' flag.
*/
[self reset:nodes];
/**
* Get sources: predicate for nodes without input ports or with input ports without connections.
*/
[request setPredicate:[NSPredicate predicateWithFormat:@"inputs == nil OR ALL inputs.connection == nil"]];
NSMutableArray *sources = [[[_document managedObjectContext] executeFetchRequest:request error:nil] mutableCopy];
/**
* Perform a topological sort.
*/
while ([sources count] > 0) {
/**
* While there are sources.
*/
NSManagedObject *node = [sources lastObject];
/**
* Add the node to the tail of the final graph (NSMutableArray).
*/
[_graph addObject:node];
[node setValue:@([_graph count] - 1) forKey:@"kNodeExecutionIndex"];
[sources removeLastObject];
/**
* Outputs.
*/
NSMutableSet *outputs = [node valueForKey:@"outputs"];
for (NSManagedObject *output in outputs) {
/**
* Get output connections.
*/
NSMutableSet *connections = [output valueForKey:@"connections"];
for (NSManagedObject *connection in connections) {
/**
* Set the connection as already visited.
*/
[connection setValue:@(YES) forKey:@"kConnectionVisited"];
NSManagedObject *n = [[connection valueForKey:@"destination"] valueForKey:@"node"];
/**
* Set the 'source' flag to YES by default.
*/
BOOL isNewSource = YES;
/**
* Get connected inputs.
*/
NSMutableSet *inputs = [n valueForKey:@"inputs"];
for (NSManagedObject *input in inputs) {
/**
* Check if one of the input connections was visited.
* If not, then we need to process this connection and
* don't add it to sources for next pass.
*/
if ([[[input valueForKey:@"connection"] valueForKey:@"kConnectionVisited"] isEqualTo:@(NO)]) {
isNewSource = NO;
break;
}
}
if (isNewSource) {
[sources addObject:n];
}
}
}
}
如果可能的话,我试图了解如何(以及在此代码中的位置)我必须计算每个节点(因此对于每个输入)实体的可达性的逻辑。
我的问题是:
- 是否可以计算卡恩算法中节点的可达性?
- 如果合适,在哪里以及如何做,所以我可以理解它为什么起作用?
谢谢你。