source: tags/arb_5.2/PROBE_SET/ps_detect_weak_differences.cxx

Last change on this file was 5782, checked in by westram, 15 years ago
  • fixed spelling of 'occurrence'
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.2 KB
Line 
1#include "ps_database.hxx"
2#include "ps_bitmap.hxx"
3#include "ps_tools.hxx"
4
5#include <cstdio>
6#include <cstdlib>
7#include <cstring>
8#include <climits>
9
10#include <sys/times.h>
11
12// common globals
13SpeciesID          __MAX_ID;
14SpeciesID          __MIN_ID;
15PS_BitMap_Fast    *__MAP;
16// globals for PS_detect_weak_differences
17IDVector          *__PATH;
18IDVector          *__INVERSE_PATH;
19unsigned long int  __COUNT_SET_OPS  = 0;
20unsigned long int  __COUNT_SET_OPS2 = 0;
21char              *__NODES_LEFT;
22// globals for PS_print_and_evaluate_map
23IDSet             *__PATHSET;
24IDID2IDSetMap     *__PAIR2PATH;
25SpeciesID          __ONEMATCH_MIN_ID;
26SpeciesID          __ONEMATCH_MAX_ID;
27
28void PS_print_path() {
29    printf( "__PATH %3zu :",__PATH->size() );
30    int c = 1;
31    for (IDVectorCIter i = __PATH->begin(); i != __PATH->end(); ++i,++c) {
32        if (c % 20 == 0) printf( "\n" );
33        printf( " %3i", *i );
34    }
35    printf( "\n" );
36}
37
38void PS_print_inverse_path() {
39    printf( "__INVERSE_PATH %3zu :",__INVERSE_PATH->size() );
40    int c = 1;
41    for (IDVectorCIter i = __INVERSE_PATH->begin(); i != __INVERSE_PATH->end(); ++i,++c) {
42        if (c % 20 == 0) printf( "\n" );
43        printf( " %3i", *i );
44    }
45    printf( "\n" );
46}
47
48
49void PS_detect_weak_differences_stepdown( const PS_NodePtr _ps_node,
50                                          const SpeciesID  _parent_ID,
51                                          const long       _depth ) {
52    //  Recursively walk through tree and make a bool-matrix of SpeciesID's
53    //  where true means that the 2 species can be distinguished by a probe.
54    //
55    //  The first occurrence of a pair of distinguishable IDs is stored as (smaller_ID,bigger_ID).
56    //  The following occurrence of this pair are stored as (bigger_ID,smaller_ID).
57    //  (this allows us to find pairs of SpeciesIDs that can be distinguished by exactly one probe)
58
59    SpeciesID id = _ps_node->getNum();
60    if (_depth < 60) {
61        printf( "%s", __NODES_LEFT );
62        for (int i = 0; i < 60; ++i) printf( "\b" );
63        fflush( stdout );
64    }
65    //
66    // append IDs to paths
67    //
68    __PATH->push_back( id );                                                                    // append id to path
69    for (SpeciesID i = (_parent_ID < __MIN_ID) ? __MIN_ID : _parent_ID+1; i < id; ++i) {        // append parent_id+1 .. id-1 to inverse path
70        //printf( "%i ",i );
71        __INVERSE_PATH->push_back( i );
72    }
73
74    //
75    // set values in the maps if node has probes
76    //
77    if (_ps_node->hasProbes()) {
78        if (_ps_node->hasPositiveProbes() && _ps_node->hasInverseProbes()) {
79//            PS_print_path();
80//            PS_print_inverse_path();
81            unsigned long int set_ops = 2*__PATH->size()*(__MAX_ID-id-1+__INVERSE_PATH->size());
82            if (ULONG_MAX - __COUNT_SET_OPS < set_ops) {
83                set_ops = set_ops - (ULONG_MAX - __COUNT_SET_OPS);
84                __COUNT_SET_OPS = 0;
85                ++__COUNT_SET_OPS2;
86            }
87            __COUNT_SET_OPS = __COUNT_SET_OPS + set_ops;
88
89            SpeciesID inverse_path_ID;
90            // path loop
91            for (IDVectorCIter it_path = __PATH->begin();
92                 it_path != __PATH->end();
93                 ++it_path) {
94                SpeciesID path_ID = *it_path;
95                // inverse path loop (explicit)
96                for (IDVectorCIter it_inverse_path = __INVERSE_PATH->begin();
97                     it_inverse_path != __INVERSE_PATH->end();
98                     ++it_inverse_path ) {
99                    inverse_path_ID = *it_inverse_path;
100
101                    __MAP->setTrue( path_ID, inverse_path_ID );
102                    __MAP->setTrue( inverse_path_ID, path_ID );
103                }
104
105                // inverse path loop (implicit)
106                for (inverse_path_ID = id+1; inverse_path_ID < __MAX_ID; ++inverse_path_ID) { // skip to id ABOVE current node id
107                    __MAP->setTrue( path_ID, inverse_path_ID );
108                    __MAP->setTrue( inverse_path_ID, path_ID );
109                }
110            }
111        } else {
112//            PS_print_path();
113//            PS_print_inverse_path();
114            unsigned long int set_ops = __PATH->size()*(__MAX_ID-id-1+__INVERSE_PATH->size());
115            if (ULONG_MAX - __COUNT_SET_OPS < set_ops) {
116                set_ops = set_ops - (ULONG_MAX - __COUNT_SET_OPS);
117                __COUNT_SET_OPS = 0;
118                ++__COUNT_SET_OPS2;
119            }
120            __COUNT_SET_OPS = __COUNT_SET_OPS + set_ops;
121
122            SpeciesID inverse_path_ID;
123            SpeciesID smaller_ID;
124            SpeciesID bigger_ID;
125            // path loop
126            for (IDVectorCIter it_path = __PATH->begin();
127                 it_path != __PATH->end();
128                 ++it_path) {
129                SpeciesID path_ID = *it_path;
130                // inverse path loop (explicit)
131                for (IDVectorCIter it_inverse_path = __INVERSE_PATH->begin();
132                     it_inverse_path != __INVERSE_PATH->end();
133                     ++it_inverse_path ) {
134                    inverse_path_ID = *it_inverse_path;
135                    smaller_ID = (path_ID < inverse_path_ID) ? path_ID : inverse_path_ID;
136                    bigger_ID  = (path_ID > inverse_path_ID) ? path_ID : inverse_path_ID;
137
138                    if (__MAP->get( smaller_ID, bigger_ID )) {
139                        __MAP->setTrue( bigger_ID, smaller_ID );
140                    } else {
141                        __MAP->setTrue( smaller_ID, bigger_ID );
142                    }
143                }
144
145                // inverse path loop (implicit)
146                for (inverse_path_ID = id+1; inverse_path_ID < __MAX_ID; ++inverse_path_ID) { // skip to id ABOVE current node id
147                    smaller_ID = (path_ID < inverse_path_ID) ? path_ID : inverse_path_ID;
148                    bigger_ID  = (path_ID > inverse_path_ID) ? path_ID : inverse_path_ID;
149
150                    if (__MAP->get( smaller_ID, bigger_ID )) {
151                        __MAP->setTrue( bigger_ID, smaller_ID );
152                    } else {
153                        __MAP->setTrue( smaller_ID, bigger_ID );
154                    }
155                }
156            }
157        }
158    }
159    //
160    // step down the children
161    //
162    int c = _ps_node->countChildren()-1;
163    for ( PS_NodeMapConstIterator i = _ps_node->getChildrenBegin();
164          i != _ps_node->getChildrenEnd();
165          ++i,--c ) {
166        if (_depth < 60) {
167            if (c < 10) {
168                __NODES_LEFT[ _depth ] = '0'+c;
169            } else {
170                __NODES_LEFT[ _depth ] = '+';
171            }
172        }
173        PS_detect_weak_differences_stepdown( i->second, id, _depth+1 );
174    }
175    if (_depth < 60) __NODES_LEFT[ _depth ] = ' ';
176
177    //
178    // remove IDs from paths
179    //
180    __PATH->pop_back();
181    while ((__INVERSE_PATH->back() > _parent_ID) && (!__INVERSE_PATH->empty())) {
182        __INVERSE_PATH->pop_back();
183    }
184}
185
186void PS_detect_weak_differences( const PS_NodePtr _root_node ) {
187    //
188    // make bitmap
189    //
190    __PATH         = new IDVector;
191    __INVERSE_PATH = new IDVector;
192
193    int c = 0;
194    struct tms before;
195    times( &before );
196    struct tms before_first_level_node;
197    for (PS_NodeMapConstIterator i = _root_node->getChildrenBegin(); i != _root_node->getChildrenEnd(); ++i,++c ) {
198        if (_root_node->countChildren()-c-1 < 10) {
199            __NODES_LEFT[0] = '0'+_root_node->countChildren()-c-1;
200        } else {
201            __NODES_LEFT[0] = '+';
202        }
203        if ((c < 50) || (c % 100 == 0)) {
204            times( &before_first_level_node );
205            printf( "PS_detect_weak_differences_stepdown( %i ) : %i. of %zu  ", i->first, c+1, _root_node->countChildren() ); fflush( stdout );
206        }
207        PS_detect_weak_differences_stepdown( i->second, -1, 1 );
208        if ((c < 50) || (c % 100 == 0)) {
209            PS_print_time_diff( &before_first_level_node, "this node ", "  " );
210            PS_print_time_diff( &before, "total ", "\n" );
211        }
212    }
213    printf( "%lu * %lu + %lu set operations performed\n", __COUNT_SET_OPS2, ULONG_MAX, __COUNT_SET_OPS ); fflush( stdout );
214
215    delete __PATH;
216    delete __INVERSE_PATH;
217}
218
219typedef map<ID2IDPair,PS_NodePtr>    IDID2NodeMap;
220typedef IDID2NodeMap::iterator       IDID2NodeMapIter;
221typedef IDID2NodeMap::const_iterator IDID2NodeMapCIter;
222
223void PS_find_probes_for_pairs( const PS_NodePtr _ps_node, ID2IDSet &_pairs ) {
224    SpeciesID id         = _ps_node->getNum();
225    bool      has_probes = _ps_node->hasProbes();
226
227    //
228    // append ID to path
229    //
230    __PATHSET->insert( id );
231
232    //
233    // dont look at path until ID is greater than lowest ID in the set of ID-pairs
234    //
235    if ((id >= __ONEMATCH_MIN_ID) && has_probes) {
236        for (ID2IDSetCIter pair=_pairs.begin(); pair != _pairs.end(); ++pair) {
237            // look for pair-IDs in the path
238            bool found_first  = __PATHSET->find( pair->first  ) != __PATHSET->end();
239            bool found_second = __PATHSET->find( pair->second ) != __PATHSET->end();
240            if (found_first ^ found_second) { // ^ is XOR
241                printf( "found path for (%i,%i) at %p ", pair->first, pair->second,&(*_ps_node) );
242                _ps_node->printOnlyMe();
243                (*__PAIR2PATH)[ *pair ] = *__PATHSET;   // store path
244                _pairs.erase( pair );                   // remove found pair
245                // scan pairs for new min,max IDs
246                if ((pair->first == __ONEMATCH_MIN_ID) || (pair->second == __ONEMATCH_MAX_ID)) {
247                    __ONEMATCH_MIN_ID = __MAX_ID;
248                    __ONEMATCH_MAX_ID = -1;
249                    for (ID2IDSetCIter p=_pairs.begin(); p != _pairs.end(); ++p) {
250                        if (p->first  < __ONEMATCH_MIN_ID) __ONEMATCH_MIN_ID = p->first;
251                        if (p->second > __ONEMATCH_MAX_ID) __ONEMATCH_MAX_ID = p->second;
252                    }
253                    printf( " new MIN,MAX (%d,%d)", __ONEMATCH_MIN_ID, __ONEMATCH_MAX_ID );
254                }
255                printf( "\n" );
256            }
257        }
258    }
259       
260    //
261    // step down the children unless all paths are found
262    // if either ID is lower than highest ID in the set of ID-pairs
263    // or the node has no probes
264    //
265    if ((id < __ONEMATCH_MAX_ID) || (! has_probes)) {
266        for (PS_NodeMapConstIterator i = _ps_node->getChildrenBegin();
267             (i != _ps_node->getChildrenEnd()) && (!_pairs.empty());
268             ++i) {
269            PS_find_probes_for_pairs( i->second, _pairs );
270        }
271    }
272
273    //
274    // remove ID from path
275    //
276    __PATHSET->erase( id );
277}
278
279void PS_print_and_evaluate_map( const PS_NodePtr _root_node, const char *_result_filename ) {
280    //
281    // print and evaluate bitmap
282    //
283    printf( "\n\n----------------- bitmap ---------------\n\n" );
284    SpeciesID smaller_id;
285    SpeciesID bigger_id;
286    ID2IDSet  noMatch;
287    ID2IDSet  oneMatch;
288    bool      bit1;
289    bool      bit2;
290    __ONEMATCH_MIN_ID = __MAX_ID;
291    __ONEMATCH_MAX_ID = __MIN_ID;
292    for (SpeciesID id1 = __MIN_ID; id1 <= __MAX_ID; ++id1) {
293//         printf( "[%6i] ",id1 );
294        for (SpeciesID id2 = __MIN_ID; id2 <= id1; ++id2) {
295            smaller_id = (id1 < id2) ? id1 : id2;
296            bigger_id  = (id1 < id2) ? id2 : id1;
297            bit1       = __MAP->get( smaller_id, bigger_id );
298            bit2       = __MAP->get( bigger_id, smaller_id );
299            if (bit1 && bit2) {
300//                 printf( "2" );
301            } else if (bit1) {
302//                 printf( "1" );
303                oneMatch.insert( ID2IDPair(smaller_id,bigger_id) );
304                if (smaller_id < __ONEMATCH_MIN_ID) __ONEMATCH_MIN_ID = smaller_id;
305                if (bigger_id  > __ONEMATCH_MAX_ID) __ONEMATCH_MAX_ID = bigger_id;
306            } else {
307//                 printf( "0" );
308                if (id1 != id2) noMatch.insert( ID2IDPair(smaller_id,bigger_id) ); // there are no probes to distinguish a species from itself .. obviously
309            }
310        }
311//         printf( "\n" );
312    }
313    printf( "(enter to continue)\n" );
314//    getchar();
315
316    printf( "\n\n----------------- no matches ---------------\n\n" );
317    if (!_result_filename) {
318        for (ID2IDSetCIter i = noMatch.begin(); i != noMatch.end(); ++i) {
319            printf( "%6i %6i\n", i->first, i->second );
320        }
321    }
322    printf( "%zu no matches\n(enter to continue)\n", noMatch.size() );
323//    getchar();
324
325    printf( "\n\n----------------- one match ---------------\n\n" );
326    if (!_result_filename) {
327        for (ID2IDSetCIter i = oneMatch.begin(); i != oneMatch.end(); ++i) {
328            printf( "%6i %6i\n", i->first, i->second );
329        }
330    }
331    printf( "%zu one matches\n(enter to continue)\n", oneMatch.size() );
332//    getchar();
333    //
334    // find paths for pairs
335    //
336    __PATHSET   = new IDSet;
337    __PAIR2PATH = new IDID2IDSetMap;
338    int c = 0;
339    for (PS_NodeMapConstIterator i = _root_node->getChildrenBegin();
340         (i != _root_node->getChildrenEnd()) && (!oneMatch.empty());
341         ++i,++c ) {
342        if ((c < 50) || (c % 100 == 0)) printf( "PS_find_probes_for_pairs( %i ) : %i of %zu\n", i->first, c+1, _root_node->countChildren() );
343        PS_find_probes_for_pairs( i->second, oneMatch );
344    }
345    //
346    // print paths
347    //
348    for (IDID2IDSetMapCIter i = __PAIR2PATH->begin();
349         i != __PAIR2PATH->end();
350         ++i) {
351        printf( "\nPair (%i,%i) Setsize (%zu)", i->first.first, i->first.second, i->second.size() );
352        PS_NodePtr current_node = _root_node;
353        long c2 = 0;
354        for (IDSetCIter path_id=i->second.begin();
355             path_id !=i->second.end();
356             ++path_id,++c2) {
357            current_node = current_node->getChild( *path_id ).second;
358            if (c2 % 10 == 0) printf( "\n" );
359            printf( "%6i%s ", *path_id, (current_node->hasProbes()) ? ((current_node->hasInverseProbes()) ? "*" : "+") : "-" );
360        }
361        printf( "\nFinal Node : %p ", &(*current_node) );
362        current_node->printOnlyMe();
363        printf( "\n" );
364    }
365    printf( "\n%zu paths\n", __PAIR2PATH->size() );
366    //
367    // oups
368    //
369    if (!oneMatch.empty()) {
370        printf( "did not find a path for these :\n" );
371        for (ID2IDSetCIter i = oneMatch.begin(); i != oneMatch.end(); ++i) {
372            printf( "%6i %6i\n", i->first, i->second );
373        }
374    }
375    //
376    // make preset map
377    //
378    PS_BitMap_Counted *preset = new PS_BitMap_Counted( false, __MAX_ID+1 );
379    // set bits for no matches
380    for (ID2IDSetCIter pair=noMatch.begin(); pair != noMatch.end(); ++pair) {
381        preset->setTrue( pair->second, pair->first );
382    }
383    // iterate over paths
384    for (IDID2IDSetMapCIter i = __PAIR2PATH->begin();
385         i != __PAIR2PATH->end();
386         ++i) {
387        // iterate over all IDs except path
388        IDSetCIter path_iter    = i->second.begin();
389        SpeciesID  next_path_id = *path_iter;
390        for (SpeciesID id = __MIN_ID; id <= __MAX_ID; ++id) {
391            if (id == next_path_id) {   // if i run into a ID in path
392                ++path_iter;            // advance to next path ID
393                next_path_id = (path_iter == i->second.end()) ? -1 : *path_iter;
394                continue;               // skip this ID
395            }
396            // iterate over path IDs
397            for (IDSetCIter path_id = i->second.begin(); path_id != i->second.end(); ++path_id) {
398                if (id == *path_id) continue;   // obviously a probe cant differ a species from itself
399                if (id > *path_id) {
400                    preset->setTrue( id,*path_id );
401                } else {
402                    preset->setTrue( *path_id,id );
403                }
404            }
405        }
406    }
407    preset->recalcCounters();
408    if (!_result_filename) preset->print();
409    //
410    // save results
411    //
412    if (_result_filename) {
413        PS_FileBuffer *result_file = new PS_FileBuffer( _result_filename, PS_FileBuffer::WRITEONLY );
414        // no matches
415        printf( "saving no matches to %s...\n", _result_filename );
416        result_file->put_long( noMatch.size() );
417        for (ID2IDSetCIter i = noMatch.begin(); i != noMatch.end(); ++i) {
418            result_file->put_int( i->first );
419            result_file->put_int( i->second );
420        }
421        // one matches
422        printf( "saving one matches to %s...\n", _result_filename );
423        result_file->put_long( __PAIR2PATH->size() );
424        for (IDID2IDSetMapCIter i = __PAIR2PATH->begin(); i != __PAIR2PATH->end(); ++i) {
425            result_file->put_int( i->first.first );
426            result_file->put_int( i->first.second );
427            result_file->put_long( i->second.size() );
428            for (IDSetCIter path_id=i->second.begin(); path_id !=i->second.end(); ++path_id) {
429                result_file->put_int( *path_id );
430            }
431        }
432        // preset bitmap
433        printf( "saving preset bitmap to %s...\n", _result_filename );
434        preset->save( result_file );
435        delete result_file;
436    }
437    delete preset;
438    delete __PATHSET;
439    delete __PAIR2PATH;
440}
441
442//  ====================================================
443//  ====================================================
444
445int main( int argc,  char *argv[] ) {
446
447   // open probe-set-database
448    if (argc < 2) {
449        printf( "Missing argument\n Usage %s <database name> [[-]bitmap filename] [+result filename]\n ", argv[0] );
450        printf( "if bitmap filename begins with '-' it is loaded, else its created\n " );
451        printf( "result filename MUST be preceded by '+'\n" );
452        exit( 1 );
453    }
454
455    const char *input_DB_name   = argv[1];
456    const char *bitmap_filename = 0;
457    const char *result_filename = 0;
458
459    if (argc > 2) {
460        if (argv[2][0] == '+') {
461            result_filename = argv[2]+1;
462        } else {
463            bitmap_filename = argv[2];
464        }
465    }
466    if (argc > 3) {
467        if (argv[3][0] == '+') {
468            result_filename = argv[3]+1;
469        } else {
470            bitmap_filename = argv[3];
471        }
472    }
473   
474    struct tms before;
475    times( &before );
476    printf( "Opening probe-set-database '%s'..\n", input_DB_name );
477    PS_Database *db = new PS_Database( input_DB_name, PS_Database::READONLY );
478    db->load();
479    __MAX_ID = db->getMaxID();
480    __MIN_ID = db->getMinID();
481    PS_print_time_diff( &before, "(enter to continue)  " );
482//    getchar();
483
484    __MAP = new PS_BitMap_Fast( false, __MAX_ID+1 );
485    if (!bitmap_filename || (bitmap_filename[0] != '-')) {
486        printf( "detecting..\n" ); fflush( stdout );
487        __NODES_LEFT = (char*)malloc( 61 );
488        memset( __NODES_LEFT, ' ', 60 );
489        __NODES_LEFT[ 60 ] = '\x00';
490        PS_detect_weak_differences( db->getRootNode() );
491        free( __NODES_LEFT );
492        if (bitmap_filename) {
493            printf( "saving bitmap to file %s\n", bitmap_filename );
494            PS_FileBuffer *mapfile = new PS_FileBuffer( bitmap_filename, PS_FileBuffer::WRITEONLY );
495            __MAP->save( mapfile );
496            delete mapfile;
497        }
498    } else if (bitmap_filename) {
499        printf( "loading bitmap from file %s\n",bitmap_filename+1 );
500        PS_FileBuffer *mapfile = new PS_FileBuffer( bitmap_filename+1, PS_FileBuffer::READONLY );
501        __MAP->load( mapfile );
502        delete mapfile;
503    }
504    printf( "(enter to continue)\n" );
505//    getchar();
506
507    times( &before );
508    PS_print_and_evaluate_map( db->getRootNode(), result_filename );
509    PS_print_time_diff( &before, "(enter to continue)  " );
510//    getchar();
511    delete __MAP;
512   
513    printf( "removing database from memory\n" );
514    delete db;
515    printf( "(enter to continue)\n" );
516//    getchar();
517
518    return 0;
519}
Note: See TracBrowser for help on using the repository browser.