void TurboIsoBoostedMQO::resuriveSearch(int matchingOrderIndex) { if (recursiveCallsNo++ >= GlobalConstant::G_enoughRecursiveCalls) { (*numberOfEmbeddings)[queryGraph->graphId] = -1; needReturn = true; return; } if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } if (matchingOrderIndex == jointNodeMatchingOrder.size()) { #ifdef DEBUG cout << "Find a Embedding for query " << queryGraph->graphId << "{"; for (int i = 0; i < queryGraph->getNumberOfVertexes(); i++) { cout << embedding[i] << " "; } cout << " } " << endl; #endif (*numberOfEmbeddings)[queryGraph->graphId] ++; // already reached to the last node. a full embedding was found if (needSaveCache) { ComboLinkedLists::addEmbeddingToCache(resultCaches, queryGraph, embedding); } } else { JointGraphNode & jointNode = jointGraph->jointNodes[jointNodeMatchingOrder[matchingOrderIndex].jointNodeId]; if (jointNode.parentId != -1) { /* * the next joint node represents a parent graph, we enumerate the candaite and for each candidate, we try to go to next iteration */ AdjacenceListsGRAPH * parentGraph = NULL; if (jointNode.parentId < queryGraphVector->size()) { parentGraph = &(*queryGraphVector)[jointNode.parentId]; } else { parentGraph = &(*newlyGeneratedGraphVector)[jointNode.parentId - queryGraphVector->size()]; } /* * enumerate the embeddings from the cache */ CacheRetrieval * cacheRetrieval = new CacheRetrieval(dataGraph, resultCaches); std::vector<std::vector<CacheEmbeddingNode *>> candidates; cacheRetrieval->retrieveEmbeddingCandidate(queryGraph, parentGraph, &jointNode, &jointNodeMatchingOrder[matchingOrderIndex], embedding, &inverseEmbedding, &candidates); for (std::vector<std::vector<CacheEmbeddingNode *>>::iterator candidateIter = candidates.begin(); candidateIter != candidates.end(); candidateIter++) { if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } map<int, int> updatedQueryVertexMap; for (int comboNodeId = 0; comboNodeId < parentGraph->getComboGraph()->size(); comboNodeId++) { if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } // each combo node corresponding to cache embedding node which contains multiple matched data vertices ComboNODE & comboNode = (*(parentGraph->getComboGraph()))[comboNodeId]; for (int comboVertexIter = 0; comboVertexIter < comboNode.queryVertices.size(); comboVertexIter++) { int dataVertexId = (*candidateIter)[comboNodeId]->comboMappingVertices[comboVertexIter]; int queryVertexId = jointNode.mapping[comboNode.queryVertices[comboVertexIter]]; if (embedding[queryVertexId] == -1) { updateState(queryVertexId, dataVertexId); updatedQueryVertexMap.insert(std::pair<int, int>(queryVertexId, dataVertexId)); } } } // next iteration resuriveSearch(matchingOrderIndex + 1); // recover the last for (map<int, int>::iterator updatedVIter = updatedQueryVertexMap.begin(); updatedVIter != updatedQueryVertexMap.end(); updatedVIter++) { restoreState(updatedVIter->first, updatedVIter->second); } } delete cacheRetrieval; } else { /* * the next node represents a stand alone query vertex. * stand alone query vertex cannot be matched before. so no need to ensure multi-map consistency */ AdjacenceListsGRAPH::Vertex * queryVertex = queryGraph->getVertexAddressByVertexId(jointNode.mapping[0]); JointGraphNode & parentJointNode = jointGraph->jointNodes[jointNodeMatchingOrder[matchingOrderIndex - 1].jointNodeId]; AdjacenceListsGRAPH::Vertex * parentMap = NULL; if (parentJointNode.parentId == -1) { // its parent is a stand alone vertex, we just get the mapped datavertex of its parent parentMap = dataGraph->getVertexAddressByVertexId(embedding[parentJointNode.mapping[0]]); } else { // its parent is a parent graph, we get a already mapped data vertex of a query vertex which is connected to this vertex for (size_t queryVertexIndex = 0; queryVertexIndex <= queryGraph->getNumberOfVertexes(); queryVertexIndex++) { if (embedding[queryVertexIndex] != -1 && queryGraph->edge(queryVertex->id, queryVertexIndex)) { parentMap = dataGraph->getVertexAddressByVertexId(embedding[queryVertexIndex]); break; } } } /* * we get is parent joint node, as its parent node has already been matched. we can use exploration to get the candidates */ std::map<int, std::vector<int>>::iterator exploreCandidates = parentMap->labelVertexList.find(queryVertex->label); if (exploreCandidates == parentMap->labelVertexList.end()) { // no candidate found return; } else { for (vector<int>::iterator candidateIter = exploreCandidates->second.begin(); candidateIter != exploreCandidates->second.end(); candidateIter++) { if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } if (degreeFilter(queryVertex->id, *candidateIter) && isJoinable(queryVertex->id, *candidateIter)) { updateState(queryVertex->id, *candidateIter); resuriveSearch(matchingOrderIndex + 1); restoreState(queryVertex->id, *candidateIter); } } } } } }
void Thread::detach() { if (isJoinable()) m_thread.detach(); }
void TurboIsoMQO::resuriveSearch(int matchingOrderIndex) { if (recursiveCallsNo++ >= GlobalConstant::G_enoughRecursiveCalls) { (*numberOfEmbeddings)[queryGraph->graphId] = -1; needReturn = true; return; } if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } if (matchingOrderIndex == jointNodeMatchingOrder.size()) { #ifdef DEBUG cout << "Find a Embedding for query " << queryGraph->graphId << "{"; for (int i = 0; i < queryGraph->getNumberOfVertexes(); i++) { cout << embedding[i] << " "; } cout << " } " << endl; #endif (*numberOfEmbeddings)[queryGraph->graphId] ++; // already reached to the last node. a full embedding was found if (needSaveCache) { ComboLinkedLists::addEmbeddingToCache(resultCaches, queryGraph, embedding); } } else { JointGraphNode & jointNode = jointGraph->jointNodes[jointNodeMatchingOrder[matchingOrderIndex].jointNodeId]; if (jointNode.parentId != -1) { /* * the next joint node represents a parent graph, we enumerate the candaite and for each candidate, we try to go to next iteration */ AdjacenceListsGRAPH * parentGraph = NULL; if (jointNode.parentId < queryGraphVector->size()) { parentGraph = &(*queryGraphVector)[jointNode.parentId]; } else { parentGraph = &(*newlyGeneratedGraphVector)[jointNode.parentId - queryGraphVector->size()]; } /* * enumerate the embeddings from the cache */ CacheRetrieval * cacheRetrieval = new CacheRetrieval(dataGraph, resultCaches); std::vector<std::vector<CacheEmbeddingNode *>> candidates; cacheRetrieval->retrieveEmbeddingCandidate(queryGraph, parentGraph, &jointNode, &jointNodeMatchingOrder[matchingOrderIndex], embedding, &inverseEmbedding, &candidates); cout << "Candidate Size: " << candidates.size() << endl; /* * will be updated query vertex */ vector<int> updatingQueryVertex; for (int comboNodeId = 0; comboNodeId < parentGraph->getComboGraph()->size(); comboNodeId++) { ComboNODE & comboNode = (*(parentGraph->getComboGraph()))[comboNodeId]; for (int comboVertexIter = 0; comboVertexIter < comboNode.queryVertices.size(); comboVertexIter++) { int queryVertexId = jointNode.mapping[comboNode.queryVertices[comboVertexIter]]; if (embedding[queryVertexId] == -1) { updatingQueryVertex.push_back(queryVertexId); } } } for (std::vector<std::vector<CacheEmbeddingNode *>>::iterator candidateIter = candidates.begin(); candidateIter != candidates.end(); candidateIter++) { if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } for (int comboNodeId = 0; comboNodeId < parentGraph->getComboGraph()->size(); comboNodeId++) { // each combo node corresponding to cache embedding node which contains multiple matched data vertices ComboNODE & comboNode = (*(parentGraph->getComboGraph()))[comboNodeId]; for (int comboVertexIter = 0; comboVertexIter < comboNode.queryVertices.size(); comboVertexIter++) { int dataVertexId = (*candidateIter)[comboNodeId]->comboMappingVertices[comboVertexIter]; int queryVertexId = jointNode.mapping[comboNode.queryVertices[comboVertexIter]]; if (embedding[queryVertexId] == -1) { updateState(queryVertexId, dataVertexId); } } } // next iteration resuriveSearch(matchingOrderIndex + 1); // recover the last for (vector<int>::iterator updatedVIter = updatingQueryVertex.begin(); updatedVIter != updatingQueryVertex.end(); updatedVIter++) { restoreState(*updatedVIter); } } delete cacheRetrieval; } else { /* * the next node represents a stand alone query vertex. * stand alone query vertex cannot be matched before. so no need to ensure multi-map consistency */ AdjacenceListsGRAPH::Vertex * queryVertex = queryGraph->getVertexAddressByVertexId(jointNode.mapping[0]); std::vector<int> * candidates = NULL; if (matchingOrderIndex == 0) { // the starting vertex cannot use exploration std::map<int, std::vector<int>>::iterator candidateIter = dataGraph->getLabelVertexList()->find(queryVertex->label); if (candidateIter == dataGraph->getLabelVertexList()->end()) { return; } candidates = &candidateIter->second; } else { /* * the following vertex use candidate exploration from its mapped parents. * we explore a connected, already mapped query vertex which generate minimum number of candidates. */ int minCandidateSize = INT_MAX; for (size_t queryVertexIndex = 0; queryVertexIndex <= queryGraph->getNumberOfVertexes(); queryVertexIndex++) { if (embedding[queryVertexIndex] != -1 && queryGraph->edge(queryVertex->id, queryVertexIndex)) { AdjacenceListsGRAPH::Vertex * alreadyMappedDataVer = dataGraph->getVertexAddressByVertexId(embedding[queryVertexIndex]); std::map<int, std::vector<int>>::iterator candidateIter = alreadyMappedDataVer->labelVertexList.find(queryVertex->label); if (candidateIter == alreadyMappedDataVer->labelVertexList.end()) { return; } else { if (candidateIter->second.size() < minCandidateSize) { minCandidateSize = candidateIter->second.size(); candidates = &candidateIter->second; } } } } } /* * for each of the candidates, we further iterate */ for (vector<int>::iterator candidateIter = candidates->begin(); candidateIter != candidates->end(); candidateIter++) { if (needReturn || (*numberOfEmbeddings)[queryGraph->graphId] >= GlobalConstant::G_SUFFICIENT_NUMBER_EMBEDDINGS) { needReturn = true; return; } if (degreeFilter(queryVertex->id, *candidateIter) && isJoinable(queryVertex->id, *candidateIter)) { updateState(queryVertex->id, *candidateIter); resuriveSearch(matchingOrderIndex + 1); restoreState(queryVertex->id); } } } } }
void Thread::join() { if (isJoinable()) m_thread.join(); }