RefInstanceListNode *AllocateRefInstanceListNode() { RefInstanceListNode *refInstanceListNode = malloc(sizeof(RefInstanceListNode)); refInstanceListNode->instanceList = AllocateInstanceList(); refInstanceListNode->refGraph = NULL; refInstanceListNode->next = NULL; return refInstanceListNode; }
InstanceList *CollectRecursiveInstances(Instance **instanceMap, ULONG numInstances) { InstanceList *recInstances; ULONG i, j; recInstances = AllocateInstanceList(); for (i = 0; i < numInstances; i++) if (instanceMap[i] != NULL) { InstanceListInsert(instanceMap[i], recInstances, FALSE); for (j = i + 1; j < numInstances; j++) if (instanceMap[j] == instanceMap[i]) instanceMap[j] = NULL; instanceMap[i] = NULL; } return recInstances; }
InstanceList *ExtendInstancesByEdge(InstanceList *instanceList, Graph *g1, Edge *edge1, Graph *g2, Parameters *parameters) { InstanceList *newInstanceList; InstanceListNode *instanceListNode; Instance *instance; Instance *newInstance; ULONG v2; ULONG e2; Edge *edge2; Vertex *vertex2; newInstanceList = AllocateInstanceList(); // extend each instance instanceListNode = instanceList->head; while (instanceListNode != NULL) { instance = instanceListNode->instance; MarkInstanceEdges(instance, g2, TRUE); // consider extending from each vertex in instance for (v2 = 0; v2 < instance->numVertices; v2++) { vertex2 = & g2->vertices[instance->vertices[v2]]; for (e2 = 0; e2 < vertex2->numEdges; e2++) { edge2 = & g2->edges[vertex2->edges[e2]]; if ((! edge2->used) && (EdgesMatch(g1, edge1, g2, edge2, parameters))) { // add new instance to list newInstance = CreateExtendedInstance(instance, instance->vertices[v2], vertex2->edges[e2], g2); InstanceListInsert(newInstance, newInstanceList, TRUE); } } } MarkInstanceEdges(instance, g2, FALSE); instanceListNode = instanceListNode->next; } FreeInstanceList(instanceList); return newInstanceList; }
InstanceList *FilterInstances(Graph *subGraph, InstanceList *instanceList, Graph *graph, Parameters *parameters) { InstanceListNode *instanceListNode; Instance *instance; InstanceList *newInstanceList; Graph *instanceGraph; double thresholdLimit; double matchCost; newInstanceList = AllocateInstanceList(); if (instanceList != NULL) { instanceListNode = instanceList->head; while (instanceListNode != NULL) { if (instanceListNode->instance != NULL) { instance = instanceListNode->instance; if (parameters->allowInstanceOverlap || (! InstanceListOverlap(instance, newInstanceList))) { thresholdLimit = parameters->threshold * (instance->numVertices + instance->numEdges); instanceGraph = InstanceToGraph(instance, graph); if (GraphMatch(subGraph, instanceGraph, parameters->labelList, thresholdLimit, & matchCost, NULL)) { if (matchCost < instance->minMatchCost) instance->minMatchCost = matchCost; InstanceListInsert(instance, newInstanceList, FALSE); } FreeGraph(instanceGraph); } } instanceListNode = instanceListNode->next; } } FreeInstanceList(instanceList); return newInstanceList; }
InstanceList *FindSingleVertexInstances(Graph *graph, Vertex *vertex, Parameters *parameters) { ULONG v; InstanceList *instanceList; Instance *instance; instanceList = AllocateInstanceList(); for (v = 0; v < graph->numVertices; v++) { if (graph->vertices[v].label == vertex->label) { // ***** do inexact label matches here? (instance->minMatchCost too) instance = AllocateInstance(1, 0); instance->vertices[0] = v; instance->minMatchCost = 0.0; InstanceListInsert(instance, instanceList, FALSE); } } return instanceList; }
InstanceList *ExtendInstances(InstanceList *instanceList, Graph *graph) { InstanceList *newInstanceList; InstanceListNode *instanceListNode; Instance *instance; Instance *newInstance; ULONG v; ULONG e; Vertex *vertex; Edge *edge; newInstanceList = AllocateInstanceList(); instanceListNode = instanceList->head; while (instanceListNode != NULL) { instance = instanceListNode->instance; MarkInstanceEdges(instance, graph, TRUE); for (v = 0; v < instance->numVertices; v++) { vertex = & graph->vertices[instance->vertices[v]]; for (e = 0; e < vertex->numEdges; e++) { edge = & graph->edges[vertex->edges[e]]; if (! edge->used) { // add new instance to list newInstance = CreateExtendedInstance(instance, instance->vertices[v], vertex->edges[e], graph); InstanceListInsert(newInstance, newInstanceList, TRUE); } } } MarkInstanceEdges(instance, graph, FALSE); instanceListNode = instanceListNode->next; } return newInstanceList; }
SubList *GetInitialSubs(Parameters *parameters) { SubList *initialSubs; ULONG i, j; ULONG vertexLabelIndex; ULONG numInitialSubs; Graph *g; Substructure *sub; Instance *instance; // parameters used Graph *posGraph = parameters->posGraph; Graph *negGraph = parameters->negGraph; LabelList *labelList = parameters->labelList; ULONG outputLevel = parameters->outputLevel; ULONG currentIncrement = 0; ULONG startVertexIndex; if (parameters->incremental) { currentIncrement = GetCurrentIncrementNum(parameters); // Index for first vertex in increment // Begin with the index for the first vertex in this increment and // move up through all remaining vertices. Relies on the fact that // each new increment is placed on the end of the vertex array and that // we are only interested in the current (last) increment startVertexIndex = GetStartVertexIndex(currentIncrement, parameters, POS); if (parameters->outputLevel > 2) printf("Start vertex index = %lu\n", startVertexIndex); } else startVertexIndex = 0; // reset labels' used flag for (i = 0; i < labelList->numLabels; i++) labelList->labels[i].used = FALSE; numInitialSubs = 0; initialSubs = AllocateSubList(); for (i = startVertexIndex; i < posGraph->numVertices; i++) { posGraph->vertices[i].TimesAddedToInstanceList = 0; vertexLabelIndex = posGraph->vertices[i].label; if (labelList->labels[vertexLabelIndex].used == FALSE) { labelList->labels[vertexLabelIndex].used = TRUE; // create one-vertex substructure definition g = AllocateGraph(1, 0); g->vertices[0].label = vertexLabelIndex; g->vertices[0].numEdges = 0; g->vertices[0].edges = NULL; g->vertices[0].TimesAddedToInstanceList = 0; // allocate substructure sub = AllocateSub(); sub->definition = g; sub->instances = AllocateInstanceList(); // collect instances in positive graph j = posGraph->numVertices; do { j--; if (posGraph->vertices[j].label == vertexLabelIndex) { // ***** do inexact label matches here? (instance->minMatchCost // ***** too) instance = AllocateInstance(1, 0); instance->vertices[0] = j; instance->mapping[0].v1 = 0; instance->mapping[0].v2 = j; instance->minMatchCost = 0.0; InstanceListInsert(instance, sub->instances, FALSE); sub->numInstances++; } } while (j > i); // only keep substructure if more than one positive instance if (sub->numInstances > 1) { if (negGraph != NULL) { // collect instances in negative graph sub->negInstances = AllocateInstanceList(); j = negGraph->numVertices; if (parameters->incremental) startVertexIndex = GetStartVertexIndex(currentIncrement, parameters, POS); else startVertexIndex = 0; do { j--; if (negGraph->vertices[j].label == vertexLabelIndex) { // ***** do inexact label matches here? // ***** (instance->minMatchCost too) instance = AllocateInstance(1, 0); instance->vertices[0] = j; instance->mapping[0].v1 = 0; instance->mapping[0].v2 = j; instance->minMatchCost = 0.0; InstanceListInsert(instance, sub->negInstances, FALSE); sub->numNegInstances++; } // We need to try all negative graph labels } while (j > startVertexIndex); } EvaluateSub(sub, parameters); // add to initialSubs SubListInsert(sub, initialSubs, 0, FALSE, labelList); numInitialSubs++; } else { // prune single-instance substructure FreeSub(sub); } } } if (outputLevel > 1) printf("%lu initial substructures\n", numInitialSubs); return initialSubs; }
//--------------------------------------------------------------------------- // // NAME: AddNegInstancesToSub // // INPUTS: (Substructure *sub) - substructure to collect instances // (Instance *subInstance) - instance of substructure // (InstanceList *instanceList) - instances to collect from in // negative graph // (Parameters *parameters) // // RETURN: (void) // // PURPOSE: Add instance from instanceList to sub's negative // instances if the instance matches sub's definition. If // allowInstanceOverlap=FALSE, then instances added only if they do // not overlap with existing instances. //--------------------------------------------------------------------------- void AddNegInstancesToSub(Substructure *sub, Instance *subInstance, InstanceList *instanceList, Parameters *parameters) { InstanceListNode *instanceListNode; Instance *instance; Graph *instanceGraph; double thresholdLimit; double matchCost; // parameters used Graph *negGraph = parameters->negGraph; LabelList *labelList = parameters->labelList; BOOLEAN allowInstanceOverlap = parameters->allowInstanceOverlap; double threshold = parameters->threshold; // collect negative instances of substructure if (instanceList != NULL) { sub->negInstances = AllocateInstanceList(); instanceListNode = instanceList->head; while (instanceListNode != NULL) { if (instanceListNode->instance != NULL) { instance = instanceListNode->instance; if (allowInstanceOverlap || (! InstanceListOverlap(instance, sub->negInstances))) { thresholdLimit = threshold * (instance->numVertices + instance->numEdges); instanceGraph = InstanceToGraph(instance, negGraph); // // First, if the threshold is 0.0, see if we can match on // just the new edge that was added. // if (threshold == 0.0) { // If instance has already been added to another substructure's // list of instances, we can skip it if (!instance->used) { if (NewEdgeMatch (sub->definition, subInstance, instanceGraph, instance, parameters, thresholdLimit, & matchCost)) { if (matchCost < instance->minMatchCost) instance->minMatchCost = matchCost; instance->used = TRUE; InstanceListInsert(instance, sub->negInstances, FALSE); sub->numNegInstances++; } } } else { if (GraphMatch(sub->definition, instanceGraph, labelList, thresholdLimit, & matchCost, NULL)) { if (matchCost < instance->minMatchCost) instance->minMatchCost = matchCost; InstanceListInsert(instance, sub->negInstances, FALSE); sub->numNegInstances++; } } FreeGraph(instanceGraph); } } instanceListNode = instanceListNode->next; } } }
//--------------------------------------------------------------------------- // // NAME: AddPosInstancesToSub // // INPUTS: (Substructure *sub) - substructure to collect instances // (Instance *subInstance) - instance of substructure // (InstanceList *instanceList) - instances to collect from in // positive graph // (Parameters *parameters) // (ULONG index) - index of substructure into instance list // // RETURN: (void) // // PURPOSE: Add instance from instanceList to sub's positive // instances if the instance matches sub's definition. If // allowInstanceOverlap=FALSE, then instances added only if they do // not overlap with existing instances. //--------------------------------------------------------------------------- void AddPosInstancesToSub(Substructure *sub, Instance *subInstance, InstanceList *instanceList, Parameters *parameters, ULONG index) { InstanceListNode *instanceListNode; Instance *instance; Graph *instanceGraph; double thresholdLimit; double matchCost; ULONG counter = 0; // parameters used Graph *posGraph = parameters->posGraph; LabelList *labelList = parameters->labelList; BOOLEAN allowInstanceOverlap = parameters->allowInstanceOverlap; double threshold = parameters->threshold; // collect positive instances of substructure if (instanceList != NULL) { sub->instances = AllocateInstanceList(); // // Go ahead an insert the subInstance onto the list of instances for the // substructure, as it is obviously an instance. // subInstance->used = TRUE; InstanceListInsert(subInstance, sub->instances, FALSE); sub->numInstances++; instanceListNode = instanceList->head; while (instanceListNode != NULL) { if (instanceListNode->instance != NULL) { instance = instanceListNode->instance; if (allowInstanceOverlap || (! InstanceListOverlap(instance, sub->instances))) { thresholdLimit = threshold * (instance->numVertices + instance->numEdges); instanceGraph = InstanceToGraph(instance, posGraph); // // First, if the threshold is 0.0, see if we can match on // just the new edge that was added. // if (threshold == 0.0) { // // To avoid processing duplicates, skip all entries // before this instance (because they have been checked // before in a previous call), and skip itself (because // there is no point in comparing it to itself). // // Also, skip processing this instance if it is already // matched with another substructure. // if ((counter > index) && (!instance->used)) { if (NewEdgeMatch (sub->definition, subInstance, instanceGraph, instance, parameters, thresholdLimit, & matchCost)) { if (matchCost < instance->minMatchCost) instance->minMatchCost = matchCost; instance->used = TRUE; InstanceListInsert(instance, sub->instances, FALSE); sub->numInstances++; } } } else { if (GraphMatch(sub->definition, instanceGraph, labelList, thresholdLimit, & matchCost, NULL)) { if (matchCost < instance->minMatchCost) instance->minMatchCost = matchCost; InstanceListInsert(instance, sub->instances, FALSE); sub->numInstances++; } } FreeGraph(instanceGraph); } counter++; } instanceListNode = instanceListNode->next; } } }