/*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; }
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; }