void AddEdgeToInstance(ULONG edgeIndex, Edge *edge, Instance *instance2) { Instance *instance1; // convert edge to instance if (edge->vertex1 == edge->vertex2) { // self-edge instance1 = AllocateInstance(1, 1); instance1->vertices[0] = edge->vertex1; } else { instance1 = AllocateInstance(2, 1); if (edge->vertex1 < edge->vertex2) { instance1->vertices[0] = edge->vertex1; instance1->vertices[1] = edge->vertex2; } else { instance1->vertices[0] = edge->vertex2; instance1->vertices[1] = edge->vertex1; } } instance1->edges[0] = edgeIndex; AddInstanceToInstance(instance1, instance2); FreeInstance(instance1); }
Instance *CreateGraphRefInstance(Instance *instance1, ReferenceGraph *refGraph) { int i; Instance *instance2 = AllocateInstance(instance1->numVertices, instance1->numEdges); for(i=0;i<instance1->numVertices;i++) { // assign the vertices to the full graph instance2->vertices[i] = refGraph->vertices[instance1->vertices[i]].map; } // reorder indices based on the vertices in the full graph SortIndices(instance2->vertices, 0, instance2->numVertices-1); for(i=0;i<instance1->numEdges;i++) { // assign the vertices to the full graph instance2->edges[i] = refGraph->edges[instance1->edges[i]].map; } // reorder indices based on the vertices in the full graph SortIndices(instance2->edges, 0, instance2->numEdges-1); return instance2; }
Instance *CopyInstance(Instance *instance) { Instance *newInstance; ULONG i; newInstance = AllocateInstance(instance->numVertices, instance->numEdges); for (i = 0; i < instance->numVertices; i++) newInstance->vertices[i] = instance->vertices[i]; for (i = 0; i < instance->numEdges; i++) newInstance->edges[i] = instance->edges[i]; return newInstance; }
void AddRecursiveInstancePair(ULONG i1, ULONG i2, Instance *instance1, Instance *instance2, ULONG edgeIndex, Edge *edge, ULONG numInstances, Instance **instanceMap) { Instance *tmpInstance = NULL; ULONG i; if ((instanceMap[i1] == instance1) && (instanceMap[i2] == instance2)) { // instances not yet linked to a new recursive instance tmpInstance = AllocateInstance(0, 0); AddInstanceToInstance(instance1, tmpInstance); AddInstanceToInstance(instance2, tmpInstance); AddEdgeToInstance(edgeIndex, edge, tmpInstance); instanceMap[i1] = tmpInstance; instanceMap[i2] = tmpInstance; } else if (instanceMap[i1] == instance1) { // instance1 to be linked to new instance at instanceMap[i2] AddInstanceToInstance(instance1, instanceMap[i2]); AddEdgeToInstance(edgeIndex, edge, instanceMap[i2]); instanceMap[i1] = instanceMap[i2]; } else if (instanceMap[i2] == instance2) { // instance2 to be linked to new instance at instanceMap[i1] AddInstanceToInstance(instance2, instanceMap[i1]); AddEdgeToInstance(edgeIndex, edge, instanceMap[i1]); instanceMap[i2] = instanceMap[i1]; } else if (instanceMap[i1] != instanceMap[i2]) { // both instances already belong to new different recursive instances AddInstanceToInstance(instanceMap[i2], instanceMap[i1]); AddEdgeToInstance(edgeIndex, edge, instanceMap[i1]); tmpInstance = instanceMap[i2]; for (i = 0; i < numInstances; i++) if (instanceMap[i] == tmpInstance) instanceMap[i] = instanceMap[i1]; FreeInstance(tmpInstance); } else { // both instances already in same new recursive instance AddEdgeToInstance(edgeIndex, edge, instanceMap[i1]); } }
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; }
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; }
Instance *CreateExtendedInstance(Instance *instance, ULONG v, ULONG e, Graph *graph) { Instance *newInstance; ULONG v2; BOOLEAN found = FALSE; ULONG i; // get edge's other vertex if (graph->edges[e].vertex1 == v) v2 = graph->edges[e].vertex2; else v2 = graph->edges[e].vertex1; // check if edge's other vertex is already in instance for (i = 0; ((i < instance->numVertices) && (! found)); i++) if (instance->vertices[i] == v2) found = TRUE; // allocate memory for new instance if (! found) newInstance = AllocateInstance(instance->numVertices + 1, instance->numEdges + 1); else newInstance = AllocateInstance(instance->numVertices, instance->numEdges + 1); // save pointer to what the instance was before this // extension (to be used as the "parent mapping") newInstance->parentInstance = instance; // set vertices and mappings of new instance for (i = 0; i < instance->numVertices; i++) { // copy vertices newInstance->vertices[i] = instance->vertices[i]; // copy mapping newInstance->mapping[i].v1 = instance->mapping[i].v1; newInstance->mapping[i].v2 = instance->mapping[i].v2; // set indices to indicate indices to source and target vertices if (newInstance->mapping[i].v2 == graph->edges[e].vertex2) newInstance->mappingIndex2 = i; if (newInstance->mapping[i].v2 == graph->edges[e].vertex1) newInstance->mappingIndex1 = i; } newInstance->newVertex = VERTEX_UNMAPPED; if (! found) { i = instance->numVertices; while ((i > 0) && (v2 < newInstance->vertices[i-1])) { newInstance->vertices[i] = newInstance->vertices[i-1]; newInstance->mapping[i].v1 = i; newInstance->mapping[i].v2 = newInstance->mapping[i-1].v2; // if indices moved, move mapping indices if (newInstance->mapping[i].v2 == graph->edges[e].vertex2) newInstance->mappingIndex2 = i; if (newInstance->mapping[i].v2 == graph->edges[e].vertex1) newInstance->mappingIndex1 = i; i--; } newInstance->vertices[i] = v2; newInstance->newVertex = i; newInstance->mapping[i].v1 = i; newInstance->mapping[i].v2 = v2; // Since this is a new vertex, need to update the index if (newInstance->mapping[i].v2 == graph->edges[e].vertex2) newInstance->mappingIndex2 = i; if (newInstance->mapping[i].v2 == graph->edges[e].vertex1) newInstance->mappingIndex1 = i; } // set edges of new instance, kept in increasing order for (i = 0; i < instance->numEdges; i++) newInstance->edges[i] = instance->edges[i]; i = instance->numEdges; while ((i > 0) && (e < newInstance->edges[i-1])) { newInstance->edges[i] = newInstance->edges[i-1]; i--; } newInstance->edges[i] = e; newInstance->newEdge = i; return newInstance; }