Substructure *MakeRecursiveSub(Substructure *sub, ULONG edgeLabel, Parameters *parameters) { Substructure *recursiveSub; // parameters used Graph *posGraph = parameters->posGraph; Graph *negGraph = parameters->negGraph; recursiveSub = AllocateSub(); recursiveSub->definition = CopyGraph(sub->definition); recursiveSub->recursive = TRUE; recursiveSub->recursiveEdgeLabel = edgeLabel; recursiveSub->instances = GetRecursiveInstances(posGraph, sub->instances, sub->numInstances, edgeLabel); recursiveSub->numInstances = CountInstances(recursiveSub->instances); if (negGraph != NULL) { recursiveSub->negInstances = GetRecursiveInstances(negGraph, sub->negInstances, sub->numNegInstances, edgeLabel); recursiveSub->numNegInstances = CountInstances(recursiveSub->negInstances); } EvaluateSub(recursiveSub, parameters); return recursiveSub; }
SubList *DiscoverSubs(Parameters *parameters) { SubList *parentSubList; SubList *childSubList; SubList *extendedSubList; SubList *discoveredSubList; SubListNode *parentSubListNode; SubListNode *extendedSubListNode; Substructure *parentSub; Substructure *extendedSub; Substructure *recursiveSub = NULL; // parameters used ULONG limit = parameters->limit; ULONG numBestSubs = parameters->numBestSubs; ULONG beamWidth = parameters->beamWidth; BOOLEAN valueBased = parameters->valueBased; LabelList *labelList = parameters->labelList; BOOLEAN prune = parameters->prune; ULONG maxVertices = parameters->maxVertices; ULONG minVertices = parameters->minVertices; ULONG outputLevel = parameters->outputLevel; BOOLEAN recursion = parameters->recursion; ULONG evalMethod = parameters->evalMethod; // get initial one-vertex substructures parentSubList = GetInitialSubs(parameters); discoveredSubList = AllocateSubList(); while ((limit > 0) && (parentSubList->head != NULL)) { parentSubListNode = parentSubList->head; childSubList = AllocateSubList(); // extend each substructure in parent list while (parentSubListNode != NULL) { parentSub = parentSubListNode->sub; parentSubListNode->sub = NULL; if (outputLevel > 4) { parameters->outputLevel = 1; // turn off instance printing printf("\nConsidering "); PrintSub(parentSub, parameters); printf("\n"); parameters->outputLevel = outputLevel; } if ((((parentSub->numInstances > 1) && (evalMethod != EVAL_SETCOVER)) || (parentSub->numNegInstances > 0)) && (limit > 0)) { limit--; if (outputLevel > 3) printf("%lu substructures left to be considered\n", limit); fflush(stdout); extendedSubList = ExtendSub(parentSub, parameters); extendedSubListNode = extendedSubList->head; while (extendedSubListNode != NULL) { extendedSub = extendedSubListNode->sub; extendedSubListNode->sub = NULL; if (extendedSub->definition->numVertices <= maxVertices) { // evaluate each extension and add to child list EvaluateSub(extendedSub, parameters); if (prune && (extendedSub->value < parentSub->value)) { FreeSub(extendedSub); } else { SubListInsert(extendedSub, childSubList, beamWidth, valueBased, labelList); } } else { FreeSub(extendedSub); } extendedSubListNode = extendedSubListNode->next; } FreeSubList(extendedSubList); } // add parent substructure to final discovered list if (parentSub->definition->numVertices >= minVertices) { if (! SinglePreviousSub(parentSub, parameters)) { // consider recursive substructure, if requested if (recursion) recursiveSub = RecursifySub(parentSub, parameters); if (outputLevel > 3) PrintNewBestSub(parentSub, discoveredSubList, parameters); SubListInsert(parentSub, discoveredSubList, numBestSubs, FALSE, labelList); if (recursion && (recursiveSub != NULL)) { if (outputLevel > 4) { parameters->outputLevel = 1; // turn off instance printing printf("\nConsidering Recursive "); PrintSub(recursiveSub, parameters); printf ("\n"); parameters->outputLevel = outputLevel; } if (outputLevel > 3) PrintNewBestSub(recursiveSub, discoveredSubList, parameters); SubListInsert(recursiveSub, discoveredSubList, numBestSubs, FALSE, labelList); } } } else { FreeSub (parentSub); } parentSubListNode = parentSubListNode->next; } FreeSubList(parentSubList); parentSubList = childSubList; } if ((limit > 0) && (outputLevel > 2)) printf ("\nSubstructure queue empty.\n"); // try to insert any remaining subs in parent list on to discovered list parentSubListNode = parentSubList->head; while (parentSubListNode != NULL) { parentSub = parentSubListNode->sub; parentSubListNode->sub = NULL; if (parentSub->definition->numVertices >= minVertices) { if (! SinglePreviousSub(parentSub, parameters)) { if (outputLevel > 3) PrintNewBestSub(parentSub, discoveredSubList, parameters); SubListInsert(parentSub, discoveredSubList, numBestSubs, FALSE, labelList); } } else { FreeSub(parentSub); } parentSubListNode = parentSubListNode->next; } FreeSubList(parentSubList); return discoveredSubList; }
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; }