string SeqOp::digital2Motif(const int index, const int len) { string motif(len, '0'); int quot = index; int order = 0; while(quot!=0) { motif[order] += (quot%4); quot /= 4; order++; } return SeqOp::Digital2Letter(motif); }
// Return a sorted occurrence list // First the occurences are sorted according to the motif m (canonic form) // Then the occurences are sorted according to the motif m' or mp // obtained by removing one node from m. // Then a last sort is done according to the location U (of mp) // mode // a - if "NodeToClass" and "NbrOfClasses" are provided the p-value // is computed // b - if "StoreOcc" is motif occurence positions are stored // c - "motif_filter" if true only this motif is considered // d - "del_class" if true provided an deletion class is applied after the // "motif filter" SEXP sort_m_mp_u( SparseAdjacency &G, int G_N, int k, vector<int*> *occurrences, double *Pi, int *NodeToClass, int NbrOfClasses, int *MotifFilter, int DelClassFilter, double PValue, int &n_prot, bool StoreOcc) { int directed; if(G.getSymmetry()) directed=0 ; else directed=1; // Active Filters bool useMotifFilter=false, useDelClassFilter=false; if( MotifFilter ) { useMotifFilter = true; if( DelClassFilter >= 0 ) useDelClassFilter=true; } // If LambdaU must be computed bool ComputePValue = false; int *Alpha = new int[NbrOfClasses]; // Init Alpha if ( (NodeToClass != 0) && (Pi != 0) && (NbrOfClasses != 0) ) { ComputePValue = true; for( int *it=Alpha, *it_end=&Alpha[NbrOfClasses]; it != it_end; it++) { *it=0; } for( int *it = NodeToClass, *it_end = &NodeToClass[G_N]; it != it_end; it++) { Alpha[*it]++; } } else { NbrOfClasses = 0; } // Instanciate PseudoMixnet PseudoMixnet pmixnet(G_N, NbrOfClasses, Alpha, Pi, directed); SEXP S_M_List; int64_t TotalCount = occurrences -> size(); vector<int*>::const_iterator it = occurrences -> begin(); int *ptr = *it; // Print occurences // cerr << "TotalCount " << TotalCount << endl; // for ( int64_t count=0; count < TotalCount; count++, it++) { // printList( "Occurrence : ", *it, *it + k, " ", true); // } int *mat; int *gamma = new int[k]; // Store 2 references : on canonic form and on an occurence canonic_list_t *canonic_list = new canonic_list_t[TotalCount]; // To Store canonic form int *canonic = new int[TotalCount * k*k]; // To sort canonic form (used by canonic_order function) sort_canonic_nbr_elmnt = k*k; // tmp array to perform permutation int *tempo = new int[k]; // // Compute canonic form and reoder occurrence indexes // for ( int64_t count=0; count < TotalCount; count++, it++) { // Extract motif // The matrix must be transposed (true) for nauty mat = G.getMatrix( *it, k, false ); // Get canonic form // ToDo : Perf call getCanonic once int *cur_canonic = &canonic[k*k * count]; getCanonic( mat , k, directed, cur_canonic, gamma ); delete [] mat; canonic_list[count].canonic = cur_canonic; canonic_list[count].occurrence = *it; // // Print canonic form // printList( "Occurences, canonic ", *it, *it+k, " ", false); // cout << ", " ; // // Permute nodes // int *node=*it; for( int i=0; i < k; i++){ tempo[i] = node[gamma[i]]; } // Permute node in the occurence list for( int i=0; i < k; i++){ node[i] = tempo[i]; } // Print cannonic // printList("", cur_canonic, cur_canonic + k*k, "", true); // Print gamma // printList( " gamma : ", gamma, gamma + k); } // // Sort occurrences according to the canonical form of m // qsort( canonic_list, TotalCount, sizeof(canonic_list_t), canonic_order); // // Print occurrences after the canonic sort and reordering // # if( MSG > 0) cout << " Occurrences after the canonic sort and reordering" << endl; cout << " -------------------------------------------------" << endl; it = occurrences -> begin( ); for ( int64_t count=0; count < TotalCount; count++, it++) { // Print node list ptr = canonic_list[count].occurrence; printList( " ", ptr, ptr + k, false); cout << ", "; // Print cannonic ptr = canonic_list[count].canonic; printList("", ptr, ptr + k*k, "", true); } cout << endl; # endif // // Get refences where start and end a motif( canonic form) // // // Build list of reference (pointer of type : canonic_list_t*) // pointing to the same canonical form of m. // Stored in the MotifEnd, MotifStart (STL) list // vector<canonic_list_t*> MotifEnd, MotifStart; int nbr_motif=0; it = occurrences -> begin( ); canonic_list_t *prev_canonic = &canonic_list[0]; MotifStart.push_back( &canonic_list[ 0 ] ); for ( int64_t count=0; count < TotalCount; count++, it++) { // If the current canonc form is equal to the previous one if( canonic_order( &canonic_list[count], prev_canonic ) ) { // New canonic form prev_canonic = &canonic_list[count]; MotifEnd.push_back( &canonic_list[count] ); MotifStart.push_back( prev_canonic ); nbr_motif = 0; } else{ nbr_motif++; } } MotifEnd.push_back( &canonic_list[ TotalCount ] ); // // For each motif m, the occurence list of m is sorted // by ignoring one node (belonging to the same TC - the // remove index is stored in "remove" field) // vector<canonic_list_t*>::const_iterator ite = MotifEnd.begin(); // unused vector<canonic_list_t*>::const_iterator ite_end = MotifEnd.end(); FindMotif TopoClassesBuider(TCMode, 0); int *ij_index = new int[ 2*k*k+2]; int *Color = new int[k]; int *perm = new int[k]; int *perm_1 = new int[k]; // Init for( int i=0; i < k; i++) { Color[i] = 0; } // Configure the occurence sort sort_occurences_nbr_elmnt = k; SEXP S_M_CanonicList; if ( useMotifFilter ) { PROTECT( S_M_CanonicList = allocVector( VECSXP, 1 )); n_prot++; PROTECT( S_M_List = allocVector( VECSXP, 1 )); n_prot++; } else { PROTECT( S_M_CanonicList= allocVector( VECSXP, MotifStart.size() )); n_prot++; PROTECT( S_M_List= allocVector(VECSXP, MotifStart.size() )); n_prot++; } // Counter of the sorted motif m to manage the SEXP int m_index = 0; // Counter of the deletion class mp to mana the corresponding SEXP int mp_index = 0; for( vector<canonic_list_t*>::const_iterator its = MotifStart.begin(), its_end= MotifStart.end(); its != its_end; its++, ite++ ) { // // Occurences having the same motif // // // Motif filter // if( ! useMotifFilter || isEqualCanonic( (*its) -> canonic, MotifFilter, k) ) { // Print cannonic # if( MSG > 0) ptr = (*its) -> canonic; printList("Motif m=", ptr, ptr + k*k, "", false); cout << ", " << endl; # endif // // Get a SparseAdjacency on the current motif m // ptr = (*its) -> canonic; int pos = 0; for( int i=0 ; i < k*k; i++, ptr++){ if(*ptr) { // row index ij_index[pos+1] = i % k; // col index ij_index[pos] = i / k; pos += 2; } } // End list ij_index[pos] = NOT_INDEX; ij_index[pos+1] = NOT_INDEX; // Buid the SparseAdjacency SparseAdjacency motif( ij_index, k, (directed==0) ); // Get good property to compute TC, // "perm" give the permutation done motif.optimizeConnexity( perm ); // get Topological Classes (TC) vector< int > *CT = TopoClassesBuider.getEquivalentNodes( motif, Color ); size_t nbr_motif_m = *ite - *its; // // motif.print(" motif" ); // cout << "Occurences number of motif m " << nbr_motif_m << endl; // Compute inverse permutation perm_1 for( int i=0; i < k; i++) { perm_1[perm[i]] = i; } // Count the number of m' (mp) int n_mp=0; for( int i=0; i < k; i++) { if( CT[i].size() != 0) { n_mp++; } } // unused SEXP S_Fuse_MP_List; SEXP S_MP_List; if ( useDelClassFilter ) { PROTECT( S_MP_List=allocVector(VECSXP, 1 )); n_prot++; } else { PROTECT( S_MP_List=allocVector(VECSXP, n_mp )); n_prot++; } // // For each Topological Class of m // mp_index = 0; for( int i=0; i < k; i++) { // Deletion class Filter if( ! useDelClassFilter || isInDelClass( DelClassFilter, CT[i], perm_1 ) ) { // Computed for class of deletion double max_t = -1; // Print Topological Class # if( MSG > 0) cout << " Couple (m, m'), DelClass " << i << " : "; for ( vector<int>::iterator it_ct = CT[i].begin(), it_ct_end = CT[i].end(); it_ct != it_ct_end; it_ct++) { cout << *it_ct << ", "; } cout << endl; # endif // Build [m,_mp] occurences list m_mp_list_t *m_mp_list = new m_mp_list_t[ CT[i].size() * nbr_motif_m ]; m_mp_list_t *it_m_mp_end = &m_mp_list[ CT[i].size() * nbr_motif_m ]; canonic_list_t *it_m = *its; for( m_mp_list_t *it_m_mp = m_mp_list; it_m_mp != it_m_mp_end; it_m++) { // Scan all possible node in the same TC // and specify the node index to remove in the occ. // list for ( vector<int>::iterator it_ct = CT[i].begin(), it_ct_end = CT[i].end(); it_ct != it_ct_end; it_ct++) { it_m_mp -> occurrence = (it_m) -> occurrence; it_m_mp -> remove = perm_1[*it_ct]; it_m_mp++; } } // sort occurences with one column removing (same CT) // Sort according to U qsort( m_mp_list , CT[i].size() * nbr_motif_m, sizeof(m_mp_list_t), occurrences_order); // Print after the sort m_mp_list_t *prev = m_mp_list; int remove; // Store temporary the extension // stack pb // int ExtStack[ it_m_mp_end - m_mp_list]; // SEXP S_Exts[it_m_mp_end - m_mp_list]; // SEXP S_U[it_m_mp_end - m_mp_list]; int *ExtStack = new int[ it_m_mp_end - m_mp_list ]; SEXP *S_Exts = new SEXP[ it_m_mp_end - m_mp_list ]; SEXP *S_U = new SEXP[ it_m_mp_end - m_mp_list ]; // Fuse the 4 lists SEXP S_U_Fuse_List=0; size_t ExtStackSize = 0; size_t U_index = 0; SEXP S_Del_List; // Store LambdaU and DeltaU double LambdaU[2]; LambdaU[0] = 0.0; LambdaU[1] = 0.0; double DeltaU, gU; int *occ_tmp = new int[ k-1 ]; // New extension # if( MSG > 0) cout << " Position U" << endl; # endif // Test empty list if( m_mp_list != it_m_mp_end ) { for( m_mp_list_t *it_m_mp = m_mp_list; it_m_mp != it_m_mp_end; it_m_mp++, it_m++ ) { ptr = it_m_mp -> occurrence; remove = it_m_mp -> remove; // New position if( occurrences_order( it_m_mp, prev ) ) { # if( MSG > 0) cout << " Position U" << endl; # endif // To store occurences int *it_occ; // // Store previous U (position) // // Allocate and store previous extension if( StoreOcc ) { // Store deletion class /* Inv int* ct_ptr = AllocateIntSEXP( CT[i].size(), S_Del_List, n_prot); for ( vector<int>::iterator it_ct = CT[i].begin(), it_ct_end = CT[i].end(); it_ct != it_ct_end; it_ct++, ct_ptr++ ) { *ct_ptr = perm_1[ *it_ct ]; } */ AllocateAndStoreInSEXP( ExtStack, ExtStackSize, S_Exts[U_index], n_prot ); // Allocate and store previous 'remove index' // AllocateAndStoreInSEXP( RemStack, ExtStackSize, // S_Remove[U_index], // n_prot ); it_occ = AllocateAndStoreOccurInSEXP( prev->occurrence, k, prev -> remove, S_U[U_index], n_prot ); } else if (ComputePValue) { // Compute LambdaU // Allocate and store previous occurence U // Need to be stored even if StoreOcc == false it_occ = AllocateAndStoreOccurInArray( prev->occurrence, k, prev -> remove, occ_tmp ); // The removed node must be permuted according to the // OptimizeGeometry permutation LambdaU[ 0 ] = pmixnet.computeLambdaU( G, it_occ, k-1, // First Ext ExtStack[0], NodeToClass ); DeltaU = (ExtStackSize - LambdaU[ 0 ]) / LambdaU[ 0 ]; LambdaU[ 1 ] = DeltaU; gU = computegU( LambdaU[ 0 ], DeltaU ); max_t = MAX( max_t, gU ); # if( MSG > 0) cout << " Lambda U, Delta U, gU : " << LambdaU[ 0 ] << " " << DeltaU << " " << gU << " " << endl; # endif } U_index++; ExtStackSize = 0; prev = it_m_mp; } // Print occurrence # if( MSG > 0) ptr = it_m_mp -> occurrence; cout << " "; for( int i_i=0 ; i_i < k; i_i++, ptr++){ if( i_i != remove ) cout << *ptr << ", "; } ptr = it_m_mp -> occurrence; cout << "[" << ptr[remove] << "]"; cout << endl; # endif // Store extension and remove index ExtStack[ExtStackSize ] = ptr[remove]; // RemStack[ExtStackSize ] = remove; ExtStackSize++; } // // Store last U (position) // // To store Occurences int *it_occ; bool store_list=true; if ( StoreOcc ) { // Store deletion class int* ct_ptr = AllocateIntSEXP( CT[i].size(), S_Del_List, n_prot); for ( vector<int>::iterator it_ct = CT[i].begin(), it_ct_end = CT[i].end(); it_ct != it_ct_end; it_ct++, ct_ptr++ ) { *ct_ptr = perm_1[ *it_ct ]; } // Allocate and store previous extension AllocateAndStoreInSEXP( ExtStack, ExtStackSize, S_Exts[U_index], n_prot ); // AllocateAndStoreInSEXP( RemStack, ExtStackSize, // S_Remove[U_index], n_prot ); it_occ = AllocateAndStoreOccurInSEXP( prev->occurrence, k, prev -> remove, S_U[U_index], n_prot ); } else if (ComputePValue) { // Allocate and store previous occurence U // Need to be stored even if StoreOcc == false it_occ = AllocateAndStoreOccurInArray( prev->occurrence, k, prev -> remove, occ_tmp ); // Compute LambdaU LambdaU[ 0 ] = pmixnet.computeLambdaU( G, it_occ, k-1, // First Ext ExtStack[0], NodeToClass ); DeltaU = (ExtStackSize - LambdaU[ 0 ]) / LambdaU[ 0 ]; LambdaU[ 1 ] = DeltaU; gU = computegU( LambdaU[ 0 ], DeltaU ); max_t = MAX( max_t, gU ); # if( MSG > 0) cout << " Lambda U, Delta U, gU : " << LambdaU[ 0 ] << ", " << DeltaU << ", " << gU << ", " << endl; # endif } // Number of occurences (m, m', U) size_t NbrOfOccur = U_index + 1; // Store arrays in (NbrOfOccur) lists // unused SEXP S_RemList; SEXP S_UList, S_ExtList; if (StoreOcc) { PROTECT( S_UList =allocVector(VECSXP, NbrOfOccur )); n_prot++; PROTECT( S_ExtList=allocVector(VECSXP, NbrOfOccur )); n_prot++; // PROTECT( S_RemList=allocVector(VECSXP, NbrOfOccur)); n_prot++; for( size_t i_u = 0; i_u < NbrOfOccur; i_u++) { SET_VECTOR_ELT( S_ExtList, i_u, S_Exts [ i_u ] ); SET_VECTOR_ELT( S_UList, i_u, S_U [ i_u ] ); // SET_VECTOR_ELT( S_RemList, i_u, S_Remove[ i_u ] ); } // Store in the main fields PROTECT( S_U_Fuse_List = allocVector(VECSXP, 3) ); n_prot++; SET_VECTOR_ELT( S_U_Fuse_List, 0, S_Del_List); SET_VECTOR_ELT( S_U_Fuse_List, 1, S_UList ); SET_VECTOR_ELT( S_U_Fuse_List, 2, S_ExtList ); } else if ( ComputePValue) { // Compute E( mp ) - mp submotif // and p-value // // Get a SparseAdjacency on the current mp motif // if ( CT[i].begin() != CT[i].end() ) { // No empty list int *ij_mp_index = new int[ 2*(k-1)*(k-1)+2]; ptr = (*its) -> canonic; int rem = perm_1[ *( CT[i].begin() )]; int pos = 0; for( int u=0 ; u < k*k; u++, ptr++){ if(*ptr) { // row index - discard the removed node int ii = u % k; // col index - discard the removed node int jj = u / k; if ( (ii != rem) && (jj != rem) ) { ij_mp_index[pos+1] = ii - ( ii > rem ); ij_mp_index[pos] = jj - ( jj > rem ); pos += 2; } } } // End list ij_mp_index[pos] = NOT_INDEX; ij_mp_index[pos+1] = NOT_INDEX; SparseAdjacency mp( ij_mp_index, k-1, (directed==0) ); // mp.print("mp :"); // Not optimal : FindNotif can't be used because works // on a connex network NonRedondantPermutation NRPMotif( mp ); SEXP S_PValue; SEXP S_Filter; double esp_mp; double proba = 0.0; esp_mp = pmixnet.computeMean( mp, NRPMotif ); proba = exp( - max_t) * esp_mp; # if( MSG > 0) cout << " max_t, esp_mp, proba : " << max_t << " " << esp_mp << " " << proba << endl; # endif if ( proba <= PValue) { // Store PValue double *p_value = AllocateDoubleSEXP(1, S_PValue, n_prot); *p_value = proba; // allocate filter int *p_filter = AllocateIntSEXP(4, S_Filter, n_prot); for( int *p_=p_filter, *p_end=p_filter+4; p_ != p_end; p_++) { *p_ = 1; } // Store deletion class int* ct_ptr = AllocateIntSEXP( CT[i].size(), S_Del_List, n_prot); for ( vector<int>::iterator it_ct = CT[i].begin(), it_ct_end = CT[i].end(); it_ct != it_ct_end; it_ct++, ct_ptr++ ) { *ct_ptr = perm_1[ *it_ct ]; } PROTECT( S_U_Fuse_List = allocVector(VECSXP, 3) ); n_prot++; SET_VECTOR_ELT( S_U_Fuse_List, 0, S_Del_List); SET_VECTOR_ELT( S_U_Fuse_List, 1, S_Filter); SET_VECTOR_ELT( S_U_Fuse_List, 2, S_PValue); } else { // empty list store_list = false; } delete [] ij_mp_index; } else { // empty list store_list = false; } } // Add an item to MP_List if(store_list) { SET_VECTOR_ELT( S_MP_List, mp_index, S_U_Fuse_List); mp_index++; } } // End new extension : if( m_mp_list != it_m_mp_end ) delete [] m_mp_list; delete [] ExtStack; delete [] S_Exts; delete [] S_U; delete [] occ_tmp; } // DelClassFilter } // For each topologic class (m') if ( mp_index != 0 ) { if( useMotifFilter ) SET_VECTOR_ELT( S_M_List, 0, S_MP_List); else SET_VECTOR_ELT( S_M_List, m_index, S_MP_List); // Store Canonic or Adjacency matrix SEXP S_Canonic; // Transpose canonic int *transp = new int[k*k]; int *can = (*its) -> canonic ; for ( int i=0; i < k; i++){ for ( int j=0; j < k; j++){ // transp[ i + k * j] = can[ j + k * i]; transp[ i + k * j] = can[ i + k * j]; } } AllocateAndStoreInSEXP( transp, k*k, S_Canonic, n_prot ); delete [] transp; // Add to canonic list if (useMotifFilter) { SET_VECTOR_ELT( S_M_CanonicList, 0, S_Canonic ); } else { SET_VECTOR_ELT( S_M_CanonicList, m_index, S_Canonic ); } } delete [] CT; } // Motif Filter if ( mp_index != 0) { m_index++; } } // Motif loop delete [] canonic; delete [] canonic_list; SEXP S_Result = R_NilValue; // Fuse the two fields if ( m_index !=0 ) { PROTECT( S_Result = allocVector(VECSXP, 2 )); n_prot++; SET_VECTOR_ELT( S_Result, 0, S_M_CanonicList ); SET_VECTOR_ELT( S_Result, 1, S_M_List ); } // To avoid warnings LOGMSG(100, std::cout, "NULL message ", "" ); delete [] Alpha; delete [] gamma; delete [] tempo; delete [] ij_index; delete [] Color; delete [] perm; delete [] perm_1; return S_Result; }