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);
					}
				}
			}
		}
	}
}
Пример #2
0
 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);
				}
			}
		}
	}
}
Пример #4
0
 void Thread::join()
 {
     if (isJoinable())
         m_thread.join();
 }