/*This implements the MC21 perfect matching*/
match_size_t FindPerfectMatch(Match_t *M,SparseGraph *G){
	unsigned int match_size=0;
	assert(G && M);
	node_t n = G->order;
	node_t *colind=G->colind;colind--;
	node_t *rowptr=G->rowptr;rowptr--;
	node_t *m = M->m;m--;
	BitArray_t *col_marker = CreateBitArray(n);
	BitArray_t *matched_row = CreateBitArray(n);
	node_t *p = (node_t *) malloc(sizeof(node_t)*n);p--;
	node_t *m_inv = (node_t *) malloc(sizeof(node_t)*n);m_inv--;
	node_t i,j,k,i1,jend;node_t m_inv_prev;char aug_extend=0;

	match_size=0;
	for(i=1;i<=n;i++){
		m_inv[i]=0;
	}
	for(j=1;j<=n;j++){
		if(m[j]){
			m_inv[m[j]]=j;
			match_size++;
		}
	}
	for(i=1;i<=n;i++){
		/*Augmenting path at any unmatched node*/
		if(m_inv[i]){
			continue;
		}
		i1 = i; p[i1]=0; jend=0;
		ResetAllBits(col_marker);
		while(i1 && !jend){
			for(k=0;k<(rowptr[i1+1]-rowptr[i1]);k++){
				j = colind[rowptr[i1]+k];
				if(!m[j]){
					jend=j;
					break;
				}
			}
			if(jend){
				/*Found an unmatched node*/
				break;
			}
			aug_extend=0;
			for(k=0;k<(rowptr[i1+1]-rowptr[i1]) && !jend;k++){
				j = colind[rowptr[i1]+k];
				if(!CheckBit(col_marker,j) && m[j]){
					p[m[j]]=i1;
					m_inv[m[j]]=j;
					SetBit(col_marker,j);
					i1 = m[j];
					aug_extend = 1;
					break;
				}
			}
			if(!aug_extend){
				/*Unable to find a unmarked matched node*/
				i1 = p[i1];
			}
		}
		if(i1){
			/*Augmenting path is found so augment*/
			j = jend; 
			printf("Augmenting the path {");
			while(i1){
				m_inv_prev = m_inv[i1];
				m[j] = i1; m_inv[i1] = j;
				printf("(%u,%u)",i1,j);
				j = m_inv_prev;
				i1 = p[i1];
			}
			printf("}\n");
			match_size++;
			printf("Match Size: %u\n",match_size);
		}else{
			/*the matching is maximum*/
			break;
		}
	}
	FreeBitArray(col_marker); FreeBitArray(matched_row);
	free(++m_inv); free(++p);
	printf("Done freeing\n");
	return match_size;
}
Exemple #2
0
WaMMHashReturn UpdateOneMemoryBlock(WaMMhashState *pState, const BitSequence *pData, long lBitsInBlock, const int rounds)
{
	WaMMHashReturn retVal = WaMM_FAIL;
	BitArray *pBitArrayIncomingData = NULL;

	/* a negative bit length is an error */
	if (0 > lBitsInBlock)
	{
		retVal = WaMM_ERORR_NEGATVELEN_BITARRAY;
	}
	else if (0 < lBitsInBlock)
	{
		if (NULL != pState)
		{
			if (IsHashLengthSupported(pState->hashbitlen))
			{
				if (NULL != pData)
				{
					// retVal = InitWaMMVector(pState->InputVector);
					retVal = InitWaMMVector(pState->InputVector);
					if (WaMM_SUCCESS == retVal)
					{
						/* convert incoming bit sequence into a BitArray struct */
						pBitArrayIncomingData = BitArrayFromBitSequence(lBitsInBlock, pData);
						if (NULL != pBitArrayIncomingData)
						{
							/* Add the BitArray of the incoming bits to pUnprocessedBitArray */
							retVal = ConcatenateBitArray(pState->pUnprocessedBitArray, pBitArrayIncomingData);
							if (WaMM_SUCCESS == retVal)
							{
								/* while full vectors of data exist within the incoming data
								 * transfer the full vectors to the and hash them
								 */
								while ((WaMM_VectorLength_Bits <= pState->pUnprocessedBitArray->lNumBits) &&
										(WaMM_SUCCESS == retVal))
								{
									retVal = PopWholeVectorFromBitArray( pState->pUnprocessedBitArray, pState->InputVector);
									if (WaMM_SUCCESS == retVal)
									{
										retVal = WaMMRoundFunction(pState, rounds);
										pState->BitsProcessed += WaMM_VectorLength_Bits;
									}
								}
							}
							FreeBitArray(pBitArrayIncomingData);
						}
						else
						{
							retVal = WaMM_ERORR_MALLOC_BITARRAY;
						}
					}
				}
				else
				{
					retVal = WaMM_ERORR_NULL_HASHDATA_POINTER;
				}
			}
			else
			{
				retVal = WaMM_BAD_HASHLENGTH;
			}
		}
		else
		{
			retVal = WaMM_ERORR_NULL_STATE_POINTER;
		}
	}
	else
	{
		/* Processing Zero Incoming bits is a NULL operation.  the state matrix is unchanged. */
		retVal = WaMM_SUCCESS;
	}

	return retVal;
}
size_t WeightedMatching(RowStarts *rowptr,ColIndices *colind,ValueType *C,
ValueType *C1,ValueType *dist,ValueType *u,ValueType *v,Indices *p,
Indices *m_inv,Indices *m, Indices n,CompareFunction cmpFunc){

	size_t i,j,i1,jend,k,m_inv_prev;
	size_t match_size=0;
	ValueType curr_shortest_path = (ValueType)0;
	ValueType curr_aug_path = GetMaxTypeValue<ValueType>(); 
	ValueType dist1; Indices itrace;
	BitArray_t *col_marker = CreateBitArray(n);
	BitArray_t *heap_marker = CreateBitArray(n);
	C--;m--;C1--;dist--;u--;v--;p--;m_inv--;
	rowptr--;colind--;
#if BINARY_HEAP
	Heap *bin_heap = NewBinaryHeap(cmpFunc,n,GetDistKeyID);  
	ValueType *dist_ptr = NULL;
#endif
	assert(C1 && dist && u && v && p);
	ComputeInitialExtremeMatch<ValueType,Indices>(u,v,C1,C,m,m_inv,colind,rowptr,n,dist);
	match_size=0;
	for(i=1;i<=n;i++){
		if(m_inv[i]){
			match_size++;
			continue;
		}
		/*
		 *Aim is to find a value for jend such that the path
		 *from i-->jend is the shortest
		 */
		i1 = i; p[i1] = 0; jend=0; itrace=i;
		ResetAllBits(col_marker);
		ResetAllBits(heap_marker);
#if BINARY_HEAP
		bin_heap->n = 0;
		dist_base = (unsigned long)&(dist[1]);
#endif
		curr_shortest_path=(ValueType)0;
		curr_aug_path=GetMaxTypeValue<ValueType>();
		while(1){
			for(k=rowptr[i1];k<rowptr[i1+1];k++){
				j = colind[k];
				if(CheckBit(col_marker,j)){
					continue;
				}
				dist1 = curr_shortest_path + C1[k];
				/*Prune any dist1's > curr_aug_path, since
				 *all the costs>0 
				 */
				if(*((long long int *)&dist1) < *((long long int *)&curr_aug_path)){
					if(!m[j]){
						/*we need itrace because, the last i1 which
						 *we explore may not actually give the shortest 
						 *augmenting path.*/
						jend = j; itrace = i1;
						curr_aug_path = dist1;
					}else if(*((long long int *)&dist1) < *((long long int *)&(dist[j]))){ 
						/*Update the dist*/
						dist[j] = dist1; p[m[j]] = i1;
#if SIMPLE_HEAP
						SetBit(heap_marker,j);
#elif BINARY_HEAP
						if(CheckBit(heap_marker,j)){
							DecreaseKey(bin_heap,j);
						}else{
							InsertHeap(bin_heap,&(dist[j]));
							SetBit(heap_marker,j);
						}
#endif
					}
				}
			}
			if(*((long long int *)&curr_aug_path) <= *((long long int *)&curr_shortest_path)){ 
				break;
			}
			/*We now have a heap of matched cols, so pick the min*/
#ifdef SIMPLE_HEAP
			j = SimplePickMin(heap_marker,dist,n);
			if(j){
				curr_shortest_path = dist[j]; 
				UnsetBit(heap_marker,j); 
#elif BINARY_HEAP
			dist_ptr = (ValueType *) HeapDelete(bin_heap);
			if(dist_ptr){
				assert((unsigned long)dist_ptr >= (unsigned long)&dist[1]);
				j = ((((unsigned long)dist_ptr -
					(unsigned long)&dist[1]))/sizeof(double))+1;
				assert(j>=1 && j<=n);
				curr_shortest_path = dist[j]; 
				UnsetBit(heap_marker,j); 
#endif
				SetBit(col_marker,j);
				i1 = m[j];
			}else{
				break;
			}
		}
		if(jend){ /*We found a shortest augmenting path*/
			j=jend;
			node_t itrace_prev;
			//printf("Shortest augmenting Path {");
			while(itrace){
				m_inv_prev = m_inv[itrace];
				m[j] = itrace; m_inv[itrace]=j;
				//printf("(%u,%u)",itrace,j);
				j=m_inv_prev;
				itrace_prev = itrace;
				itrace = p[itrace];
				if(itrace){
				//	printf("(%u,%u)",itrace_prev,m_inv_prev);
				}
			}
			match_size++;
			//printf("}\n");
			/*Update the cost with new match m*/
			for(j=1;j<=n;j++){
				if(CheckBit(col_marker,j)){
					u[j] = (u[j]+dist[j])-curr_aug_path;
					/*Reset the dist values*/
				}
			}
			for(i1=1;i1<=n;i1++){
				if(!m_inv[i1]) continue;
				j = m_inv[i1];
				for(k=rowptr[i1];k<rowptr[i1+1];k++){
					if(colind[k] == j){
						v[i1] = C[k] - u[j];
					}
				}
			}
			/*Update the cost*/
			for(i1=1;i1<=n;i1++){
				for(k=rowptr[i1];k<rowptr[i1+1];k++){
					j = colind[k];
					C1[k] = C[k]-(u[j]+v[i1]);
				}
				/*The index should be j rather than i1 but just 
				 *avoiding another loop*/
				dist[i1] = GetMaxTypeValue<double>();
			}
		}
	}
	FreeBitArray(col_marker);
	FreeBitArray(heap_marker);
#ifdef BINARY_HEAP	
	FreeHeap(bin_heap);
#endif

	return match_size;
}
/*O(n) time picking the maximum from the heap_marker */
node_t SimplePickMin(BitArray_t *bit_heap,double *dist,node_t n){
	node_t min_j=0;node_t j; 
	double curr_min = MAX_DOUBLE_VALUE; 
	for(j=1;j<=n;j++){
		if(CheckBit(bit_heap,j) && dist[j] < curr_min){
			min_j = j;
			curr_min = dist[j];
		}
	}
	return min_j;
}
size_t WeightedMatching(RowStarts rowptr,ColIndices colind,ValueTypePtr C,
ValueTypePtr dist,ValueTypePtr u,ValueTypePtr v,Indices *p,
Indices *m_inv,Indices *m, Indices n,CompareFunction cmpFunc){
	typedef typename std::iterator_traits<ValueTypePtr>::value_type ValueType;
	Indices i,j,i1,jend,k,m_inv_prev;
	Indices match_size=0; Indices k0,j0;
	ValueType curr_shortest_path = (ValueType)0;
	ValueType curr_aug_path = GetMaxTypeValue<ValueType>(curr_aug_path); 
	ValueType dist1; Indices itrace;
	/*Cost of the edges in the match if
	 *$(i,j) \in M$ then $clabel[i] = C[i][j]$*/
	Indices *clabel = new Indices[n];
	Indices *aug_label = new Indices[n];
	Indices *update_stack = new Indices[n];
	Indices update_stack_index;
	/*Save The Operations on the Heap.*/
	Indices save_heap_index;
	Indices *save_heap_op = new Indices[n];
#ifdef TURN_ON_SAVE_HEAP
	double close_factor = (double)1.0 + (double)1.0e-16;
#endif
	/*Force the write back to memory to avoid floating point issues*/
	ValueType force_mem_write[3];
#ifndef NO_LOCAL_PROFILING
	CreateProfilingClocks();
#endif

	/*Core Profiling Clock*/
	Clock *core_clk = CreateClock();
#ifdef USE_BIT_ARRAY
	BitArray_t *col_marker = CreateBitArray(n);
	BitArray_t *heap_marker = CreateBitArray(n);
#else
	Indices *col_marker = new Indices[n];
	unsigned int *heap_marker = NULL;
	col_marker--;
	for(i=1;i<=n;i++){ /*Do we need Initialization?*/
		col_marker[i] = (Indices)0;
	}
#endif
#if BINARY_HEAP
	Heap *bin_heap = NewBinaryHeap(cmpFunc,n,GetDistKeyID);  
	ValueType *dist_ptr = NULL;
	heap_marker = bin_heap->keyMap;
#endif
	/*Algorithm Uses 1-Indexing to be consistent*/
	C--;m--;dist--;u--;v--;p--;m_inv--;
	rowptr--;colind--;clabel--;save_heap_op--;
	update_stack--;aug_label--;
	assert(dist && u && v && p);
	ComputeInitialExtremeMatch<ValueType,Indices>(u,v,clabel,C,m,m_inv,colind,
		rowptr,n,dist);
	match_size=0; 

	StartClock(core_clk);

	for(i=1;i<=n;i++){
		if(m_inv[i]){
			match_size++;
			continue;
		}
		/*
		 *Aim is to find a value for jend such that the path
		 *from i-->jend is the shortest
		 */
		i1 = i; p[i1] = 0; jend=0; itrace=i;
#ifdef USE_BIT_ARRAY
		ResetAllBits(col_marker);
		ResetAllBits(heap_marker);
#endif

#if BINARY_HEAP
		bin_heap->n = 0;
		dist_base = (unsigned long)&(dist[1]);
#endif
		curr_shortest_path=(ValueType)0;
		curr_aug_path=GetMaxTypeValue<ValueType>(curr_aug_path);
		save_heap_index = (Indices)0;
		update_stack_index = (Indices)0;
		while(1){
			for(k=rowptr[i1]+1;k<(rowptr[i1+1]+1);k++){ 
				j = colind[k]+1; 
#ifdef USE_BIT_ARRAY
				if(CheckBit(col_marker,j)){
#else
				if(col_marker[j]==i){
#endif
					continue;
				}
				force_mem_write[k%3] = C[k]-(v[i1]+u[j]);
				dist1 = curr_shortest_path + force_mem_write[k%3];
				/*Prune any dist1's > curr_aug_path, since
				 *all the costs>0 
				 */
				if(dist1 < curr_aug_path){
					if(!m[j]){
						/*we need itrace because, the last i1 which
						 *we explore may not actually give the shortest 
						 *augmenting path.*/
						jend = j; itrace = i1;
						curr_aug_path = dist1;
						aug_label[j] = k;
					}else if(dist1 < dist[j]){ 
						/*Update the dist*/
						dist[j] = dist1; p[m[j]] = i1;
						aug_label[j] = k;
#if SIMPLE_HEAP

#ifdef USE_BIT_ARRAY
						SetBit(heap_marker,j);
#else
						heap_marker[j] = i;
#endif

#elif BINARY_HEAP /*SIMPLE_HEAP*/

#ifdef USE_BIT_ARRAY
						if(CheckBit(heap_marker,j)){
#else
						if(heap_marker[j]){
#endif
#ifndef NO_LOCAL_PROFILING
							StartClock(hupdate_clk);
#endif
							/*Call the decrease Key Operation*/
							DecreaseKey(bin_heap,j);

#ifndef NO_LOCAL_PROFILING
							StopClock(hupdate_clk);
							hupdate_ticks += GetClockTicks(hupdate_clk);
#endif
						}
#ifdef TURN_ON_SAVE_HEAP 
						else if(curr_shortest_path &&  
							dist[j] <= (curr_shortest_path)*(close_factor)){
							/*If dist[j] is close to root push it in
							 *save_heap_op*/
							 assert(save_heap_index < n);
							 save_heap_op[++save_heap_index] = j;
						}
#endif					
						else{
#ifndef NO_LOCAL_PROFILING
							StartClock(hins_clk);
#endif
							InsertHeap(bin_heap,&(dist[j]));
#ifndef NO_LOCAL_PROFILING
							StopClock(hins_clk);
							hins_ticks += GetClockTicks(hins_clk);
#endif
#ifdef USE_BIT_ARRAY
							SetBit(heap_marker,j);
#endif
						}
#endif /*SIMPLE_HEAP*/
					}
				}
			}
			if(curr_aug_path <= curr_shortest_path){ 
				break;
			}
			/*We now have a heap of matched cols, so pick the min*/
#ifdef SIMPLE_HEAP
			j = SimplePickMin(heap_marker,dist,n);
			if(j){
				curr_shortest_path = dist[j]; 
				UnsetBit(heap_marker,j); 
#elif BINARY_HEAP


#ifndef NO_LOCAL_PROFILING
			StartClock(hdel_clk);
#endif
			if(save_heap_index){
				j = save_heap_op[save_heap_index];
				save_heap_index--;
				curr_shortest_path = dist[j]; 
#ifdef USE_BIT_ARRAY
				SetBit(col_marker,j);
#else
				col_marker[j] = (Indices)i;
				update_stack[++update_stack_index]=j;
#endif /*#ifdef USE_BIT_ARRAY*/

				i1 = m[j];
			}else if(dist_ptr = (ValueType *) HeapDelete(bin_heap)) {
#ifndef NO_LOCAL_PROFILING
				StopClock(hdel_clk);
				hdel_ticks += GetClockTicks(hdel_clk);
#endif
				assert((unsigned long)dist_ptr >= (unsigned long)&dist[1]);
				j = ((((unsigned long)dist_ptr -
					(unsigned long)&dist[1]))/sizeof(ValueType))+1;
				assert(j>=1 && j<=n);
				curr_shortest_path = dist[j]; 
				heap_marker[j] = 0; /*Setting the keyMap in Heap to 0*/
#endif /*#ifdef SIMPLE_HEAP */


#ifdef USE_BIT_ARRAY
				SetBit(col_marker,j);
				update_stack[++update_stack_index]=j;
#else
				col_marker[j] = (Indices)i;
				update_stack[++update_stack_index]=j;
#endif /*#ifdef USE_BIT_ARRAY*/

				i1 = m[j];
			}else{
				break;
			}
		}
		/*We found a shortest augmenting path*/
		if(jend){ 
			unsigned long **harray = bin_heap->heapArray;
#ifndef NO_LOCAL_PROFILING
			StartClock(dual_clk);
#endif
			/*NOTE1: We need a very fast way to update
			 *the dual variables and also reset the dist[]
			 *we avoid linear scan where ever we can to update
			 *these dual variables*/
			while(update_stack_index){ /*Update u[j]: while*/
				j=update_stack[update_stack_index--];
				u[j] = (u[j]+dist[j])-curr_aug_path;
				if(m[j]){ /*See NOTE1*/
					i1 = m[j];
					v[i1] = C[clabel[i1]] - u[j];
				}
				dist[j] = MAX_DOUBLE_VALUE;
				if(bin_heap->n){
					dist_ptr = (double *)harray[bin_heap->n];
					j = ((((unsigned long)dist_ptr -
						(unsigned long)&dist[1]))/sizeof(ValueType))+1;
					heap_marker[j] = 0;
					*((double *)harray[bin_heap->n]) = MAX_DOUBLE_VALUE;
					bin_heap->n -= 1 ;
				}
			} /*Update u[j]: while*/
			
			/*Uncomment if you need to print augmenting path*/
			/*node_t itrace_prev;*/
			/*printf("Shortest augmenting Path {");*/

			j=jend;
			while(itrace){
				m_inv_prev = m_inv[itrace];
				m[j] = itrace; m_inv[itrace]=j;
				/*See NOTE1(above)*/
				clabel[itrace] = aug_label[j];
				v[itrace] = C[clabel[itrace]] - u[j];
				/*printf("(%u,%u)",itrace,j);*/
				j=m_inv_prev;
				/*itrace_prev = itrace;*/
				itrace = p[itrace];
				/*
				if(itrace){
					printf("(%u,%u)",itrace_prev,m_inv_prev);
				}*/
			}
			/*printf("}\n");*/
			/*There may some dist[] still in the heap*/
			while(bin_heap->n){
				dist_ptr = (double *)harray[bin_heap->n];
				j = ((((unsigned long)dist_ptr -
					(unsigned long)&dist[1]))/sizeof(ValueType))+1;
				heap_marker[j] = 0;
				*((double *)harray[bin_heap->n]) = MAX_DOUBLE_VALUE;
				bin_heap->n -= 1;
			}
			match_size++;
			/*End Dual Update*/
#ifndef NO_LOCAL_PROFILING
			StopClock(dual_clk);
			dual_ticks += GetClockTicks(dual_clk);
#endif
		} /*if(jend) : Found Augmeting Path*/
	} /*for(i=1;i<=n;i++): Main Outer Loop*/

	StopClock(core_clk);
	WeightedMatchTicks = GetClockTicks(core_clk);

#ifndef NO_LOCAL_PROFILING
	printf("Profile Summary\n");
	printf("HINS=(%d) HDEL=(%d) HUPDATE=(%d)\n",(int)hins_ticks,(int)hdel_ticks,
		(int)hupdate_ticks);
	printf("DUAL=(%d) \n",(int)dual_ticks);
#endif

#ifdef USE_BIT_ARRAY
	FreeBitArray(col_marker);
	FreeBitArray(heap_marker);
#else
	col_marker++;
	delete col_marker; 
#endif

#ifdef SIMPLE_HEAP
	heap_marker++;
	delete heap_marker;
#endif

	aug_label++;
	delete aug_label;
	save_heap_op++;
	delete save_heap_op;
	clabel++;
	delete clabel;
#ifdef BINARY_HEAP	
	FreeHeap(bin_heap);
#endif
	return match_size;
}
/*O(n) time picking the maximum from the heap_marker */
node_t SimplePickMin(BitArray_t *bit_heap,double *dist,node_t n){
	node_t min_j=0;node_t j; 
	double curr_min = HUGE_VAL; 
	for(j=1;j<=n;j++){
		if(CheckBit(bit_heap,j) && dist[j] < curr_min){
			min_j = j;
			curr_min = dist[j];
		}
	}
	return min_j;
}
#ifdef BINARY_HEAP 
inline keyid_t GetDistKeyID(void *dist_ptr){ assert((unsigned long)dist_ptr >= dist_base);
	return (((((unsigned long)dist_ptr-dist_base))/sizeof(double))+1);
}
#endif

BitArray_t* CreateBitArray(unsigned int size){
	div_t d = div(size,SIZE_OF_BYTE_IN_BITS);
	BitArray_t *bits = (BitArray_t *)malloc(sizeof(BitArray_t)*1);
	assert(bits);
	bits->size = (d.rem > 0)?(d.quot+1):d.quot;
	bits->ba = (char *)malloc(sizeof(char)*(bits->size));
	assert(bits->ba);
	memset(bits->ba,'\0',bits->size);
	return bits;
}