source: branches/profile/PROBE_SET/ps_candidate.hxx

Last change on this file was 10113, checked in by westram, 11 years ago
  • changed dynamic value-initializations into default-initializations
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.7 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ps_candidate.hxx                                  //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Wolfram Foerster in October 2002                     //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#ifndef PS_CANDIDATE_HXX
13#define PS_CANDIDATE_HXX
14
15#ifndef PS_DEFS_HXX
16#include "ps_defs.hxx"
17#endif
18#ifndef PS_BITMAP_HXX
19#include "ps_bitmap.hxx"
20#endif
21
22#ifndef _GLIBCXX_CLIMITS
23#include <climits>
24#endif
25
26using namespace std;
27
28class PS_Candidate;
29typedef PS_Candidate*                           PS_CandidatePtr;
30typedef SmartPtr<PS_Candidate>                  PS_CandidateSPtr;
31
32struct cmp_candidates
33{
34  bool operator()(const PS_CandidateSPtr &c1, const PS_CandidateSPtr &c2) const
35  {
36    return &(*c1) < &(*c2);
37  }
38};
39typedef set<PS_CandidateSPtr, cmp_candidates>    PS_CandidateSet;
40typedef PS_CandidateSet::iterator               PS_CandidateSetIter;
41typedef PS_CandidateSet::const_iterator         PS_CandidateSetCIter;
42typedef PS_CandidateSet::reverse_iterator       PS_CandidateSetRIter;
43typedef PS_CandidateSet::const_reverse_iterator PS_CandidateSetCRIter;
44
45typedef map<unsigned long, PS_CandidateSPtr>     PS_CandidateByGainMap;
46typedef PS_CandidateByGainMap::iterator               PS_CandidateByGainMapIter;
47typedef PS_CandidateByGainMap::const_iterator         PS_CandidateByGainMapCIter;
48typedef PS_CandidateByGainMap::reverse_iterator       PS_CandidateByGainMapRIter;
49typedef PS_CandidateByGainMap::const_reverse_iterator PS_CandidateByGainMapCRIter;
50
51typedef pair<SpeciesID, PS_BitSet::IndexSet>     ID2IndexSetPair;
52typedef set<ID2IndexSetPair>                    ID2IndexSetSet;
53typedef ID2IndexSetSet::iterator                ID2IndexSetSetIter;
54typedef ID2IndexSetSet::const_iterator          ID2IndexSetSetCIter;
55typedef ID2IndexSetSet::reverse_iterator        ID2IndexSetSetRIter;
56typedef ID2IndexSetSet::const_reverse_iterator  ID2IndexSetSetCRIter;
57
58class PS_Candidate : virtual Noncopyable {
59    PS_Candidate();
60    PS_Candidate(const PS_Candidate&);
61    explicit PS_Candidate(float _distance, unsigned long _gain, const PS_NodePtr& _ps_node, IDSet &_path, PS_CandidatePtr _parent) {
62        filling_level = 0.0;
63        depth         = ULONG_MAX;
64        distance      = _distance;
65        gain          = _gain;
66        passes_left   = MAX_PASSES;
67        parent        = _parent;
68        false_IDs     = 0;
69        one_false_IDs = 0;
70        one_false_IDs_matches = 0;
71        map           = 0;
72        node          = _ps_node;
73        path          = _path;
74    }
75
76public:
77    static const unsigned int MAX_PASSES = 3;
78    float                  filling_level;
79    unsigned long          depth;
80    float                  distance;
81    unsigned long          gain;
82    unsigned int           passes_left;
83    PS_Candidate          *parent;
84    unsigned long          false_IDs;
85    ID2IDSet              *one_false_IDs;
86    unsigned long          one_false_IDs_matches;
87    PS_BitMap_Counted     *map;
88    IDSet                  path;
89    PS_NodePtr             node;
90    PS_CandidateByGainMap  children;
91
92    unsigned long initFalseIDs(const SpeciesID  _min_id,
93                                const SpeciesID  _max_id,
94                                      SpeciesID &_min_sets_id,
95                                      SpeciesID &_max_sets_id) {
96        // if i already have the set return its size
97        if (one_false_IDs) {
98            return one_false_IDs->size();
99        }
100        else {
101            one_false_IDs = new ID2IDSet;
102            false_IDs     = 0;
103            PS_BitSet::IndexSet falseIndices;       // temp. set to hold IDs of falses per ID
104            // iterate over _min_id .. _max_id range in map
105            for (SpeciesID id1 = _min_id;
106                  id1 <= _max_id;
107                  ++id1) {
108                if (map->getCountFor(id1) == _max_id+1) continue;   // skip ID if its already filled
109                if (id1 < _min_sets_id) _min_sets_id = id1;
110                if (id1 > _max_sets_id) _max_sets_id = id1;
111                map->getFalseIndicesFor(id1, falseIndices);
112                while ((*(falseIndices.begin()) < id1) &&
113                       !falseIndices.empty()) falseIndices.erase(*falseIndices.begin());
114                if (falseIndices.empty()) continue;
115                if (*falseIndices.begin()  < _min_sets_id) _min_sets_id = *falseIndices.begin();
116                if (*falseIndices.rbegin() > _max_sets_id) _max_sets_id = *falseIndices.rbegin();
117                // store
118                false_IDs += falseIndices.size();
119                if (falseIndices.size() == 1) {
120                    one_false_IDs->insert(ID2IDPair(id1, *falseIndices.begin()));
121                }
122            }
123        }
124        return one_false_IDs->size();
125    }
126
127    unsigned long matchPathOnOneFalseIDs(IDSet &_path) {
128        unsigned long matches = 0;
129        IDSetCIter path_end = _path.end();
130        for (ID2IDSetCIter p = one_false_IDs->begin();
131              p != one_false_IDs->end();
132              ++p) {
133            if (_path.find(p->first) == path_end) {
134                if (_path.find(p->second) != path_end) ++matches;
135            }
136            else {
137                if (_path.find(p->second) == path_end) ++matches;
138            }
139        }
140        return matches;
141    }
142
143    void decreasePasses() {
144        --passes_left;
145    }
146
147    void getParentMap() {
148        if (!parent) return;
149        map = parent->map;      // grab parents version of the map
150        parent->map = 0;        // unbind parent from map
151    }
152
153    bool hasChild(PS_NodePtr _ps_node) const {
154        PS_CandidateByGainMapCIter found = children.end();
155        for (PS_CandidateByGainMapCIter child = children.begin();
156              (child != children.end()) && (found == children.end());
157              ++child) {
158            if (child->second->node == _ps_node) found = child;
159        }
160        return (found != children.end());
161    }
162
163    bool alreadyUsedNode(const PS_NodePtr& _ps_node) const {
164        if (node.isNull()) return false;
165        if (_ps_node == node) {
166            return true;
167        }
168        else {
169            return parent->alreadyUsedNode(_ps_node);
170        }
171    }
172
173    int addChild(unsigned long     _distance,
174                 unsigned long     _gain,
175                 const PS_NodePtr& _node,
176                 IDSet&            _path)
177    {
178        PS_CandidateByGainMapIter found = children.find(_gain);
179        if (found == children.end()) {
180            PS_CandidateSPtr new_child(new PS_Candidate(_distance, _gain, _node, _path, this));
181            children[_gain] = new_child;
182            return 2;
183        }
184        else if (_distance < found->second->distance) {
185            children.erase(_gain);
186            PS_CandidateSPtr new_child(new PS_Candidate(_distance, _gain, _node, _path, this));
187            children[_gain] = new_child;
188            return 1;
189        }
190        return 0;
191    }
192
193    bool updateBestChild(const unsigned long _gain,
194                         const unsigned long _one_false_IDs_matches,
195                         const float         _filling_level,
196                         const PS_NodePtr&   _node,
197                         IDSet&              _path)
198    {
199        if (children.empty()) {
200            // no child yet
201            PS_CandidateSPtr new_child(new PS_Candidate(0, _gain, _node, _path, this));
202            new_child->depth = depth+1;
203            new_child->filling_level = _filling_level;
204            if (_filling_level >= 100.0) new_child->passes_left = 0;
205            children[0] = new_child;
206            one_false_IDs_matches = _one_false_IDs_matches;
207            return true;
208        }
209        // return false if new child matches less 'must matches' than best child so far
210        if (_one_false_IDs_matches < one_false_IDs_matches) return false;
211        // return false if new child matches same 'must matches' but has less total gain
212        if ((_one_false_IDs_matches == one_false_IDs_matches) &&
213            (_gain <= children[0]->gain)) return false;
214
215        children.clear();
216        PS_CandidateSPtr new_child(new PS_Candidate(0, _gain, _node, _path, this));
217        new_child->depth = depth+1;
218        new_child->filling_level = _filling_level;
219        if (_filling_level >= 100.0) new_child->passes_left = 0;
220        children[0] = new_child;
221        one_false_IDs_matches = _one_false_IDs_matches;
222        return true;
223    }
224
225    void reduceChildren(const float _filling_level) {
226        if (children.empty()) return;
227        // prepare
228        unsigned long best_gain   = children.rbegin()->first;
229        unsigned long worst_gain  = children.begin()->first;
230        unsigned long middle_gain = (best_gain + worst_gain) >> 1;
231        PS_CandidateByGainMapIter middle_child = children.find(middle_gain);
232        if (middle_child == children.end()) {
233            middle_child = children.lower_bound(middle_gain);
234            middle_gain  = middle_child->first;
235        }
236        PS_CandidateByGainMapIter to_delete = children.end();
237        // delete unwanted children depending on filling level
238        if (_filling_level < 50.0) {
239            if (children.size() <= 3) return;
240            for (PS_CandidateByGainMapIter c = children.begin();
241                  c != children.end();
242                  ++c) {
243                if (to_delete != children.end()) {
244                    children.erase(to_delete);
245                    to_delete = children.end();
246                }
247                if ((c->first != worst_gain) &&
248                    (c->first != middle_gain) &&
249                    (c->first != best_gain)) {
250                    to_delete = c;
251                }
252            }
253        }
254        else if (_filling_level < 75.0) {
255            if (children.size() <= 2) return;
256            for (PS_CandidateByGainMapIter c = children.begin();
257                  c != children.end();
258                  ++c) {
259                if (to_delete != children.end()) {
260                    children.erase(to_delete);
261                    to_delete = children.end();
262                }
263                if ((c->first != middle_gain) &&
264                    (c->first != best_gain)) {
265                    to_delete = c;
266                }
267            }
268        }
269        else {
270            if (children.size() <= 1) return;
271            for (PS_CandidateByGainMapIter c = children.begin();
272                  c != children.end();
273                  ++c) {
274                if (to_delete != children.end()) {
275                    children.erase(to_delete);
276                    to_delete = children.end();
277                }
278                if (c->first != best_gain) {
279                    to_delete = c;
280                }
281            }
282        }
283        if (to_delete != children.end()) {
284            children.erase(to_delete);
285            to_delete = children.end();
286        }
287    }
288
289    void printProbes(const SpeciesID      _species_count,
290                      const unsigned long _depth = 0,
291                      const bool          _descend = true) const {
292        for (unsigned long i = 0; i < _depth; ++i) {
293            printf("|  ");
294        }
295        printf("\n");
296        if (node.isNull()) {
297            for (unsigned long i = 0; i < _depth; ++i) {
298                printf("|  ");
299            }
300            printf("[%p] depth (%lu) no node\n", this, _depth);
301        }
302        else if (node->countProbes() == 0) {
303            for (unsigned long i = 0; i < _depth; ++i) {
304                printf("|  ");
305            }
306            printf("[%p] depth (%lu)  node (%p)  no probes\n", this, _depth, &(*node));
307        }
308        else {
309            for (PS_ProbeSetCIter probe = node->getProbesBegin();
310                  probe != node->getProbesEnd();
311                  ++probe) {
312                for (unsigned long i = 0; i < _depth; ++i) {
313                    printf("|  ");
314                }
315                printf("[%p] depth (%lu)  node (%p)  matches (%zu)       %u   %u\n",
316                        this,
317                        _depth,
318                        &(*node),
319                        ((*probe)->quality > 0) ? path.size() : _species_count - path.size(),
320                        (*probe)->length,
321                        (*probe)->GC_content);
322            }
323        }
324        fflush(stdout);
325
326        if (_descend) {
327            for (PS_CandidateByGainMapCRIter child = children.rbegin();
328                  child != children.rend();
329                  ++child) {
330                child->second->printProbes(_species_count, _depth+1);
331            }
332        }
333
334    }
335
336    void print (const unsigned long _depth = 0,
337                 const bool          _print_one_false_IDs = false,
338                 const bool          _descend = true) const {
339        for (unsigned long i = 0; i < _depth; ++i) {
340            printf("|  ");
341        }
342        printf("[%p] passes left (%u)  filling level (%.5f)  distance (%6.2f)  gain (%6lu)  depth (%3lu)  path length (%4zu)  ",
343                this,
344                passes_left,
345                filling_level,
346                distance,
347                gain,
348                depth,
349                path.size());
350        if (node.isNull()) {
351            printf("node (undefined)  children (%2zu)  ", children.size());
352        }
353        else {
354            printf("node (%p)  children (%2zu)  ", &(*node), children.size());
355        }
356        printf("(%4lu %4zu)/%lu", one_false_IDs_matches, (one_false_IDs) ? one_false_IDs->size() : 0, false_IDs);
357        if (_print_one_false_IDs) {
358            printf("\n");
359            for (unsigned long i = 0; i < _depth; ++i) {
360                printf("|  ");
361            }
362            printf("            one_false_IDs : ");
363            if (one_false_IDs) {
364                for (ID2IDSetCIter p = one_false_IDs->begin();
365                      p != one_false_IDs->end();
366                      ++p) {
367                    printf("(%i %i)  ", p->first, p->second);
368                }
369            }
370            else {
371                printf("none");
372            }
373        }
374        printf("\n"); fflush(stdout);
375        if (_descend) {
376            for (PS_CandidateByGainMapCRIter child = children.rbegin();
377                  child != children.rend();
378                  ++child) {
379                child->second->print(_depth+1);
380            }
381        }
382    }
383
384    void save(PS_FileBuffer       *_file,
385               const unsigned long  _bits_in_map) {
386        unsigned long count;
387        // gain
388        _file->put_ulong(gain);
389        // passes_left
390        _file->put_uint(passes_left);
391        // false_IDs
392        _file->put_ulong(false_IDs);
393        // one_false_IDs
394        if (one_false_IDs) {
395            count = one_false_IDs->size();
396            _file->put_ulong(count);
397            for (ID2IDSetCIter p = one_false_IDs->begin();
398                  p != one_false_IDs->end();
399                  ++p) {
400                _file->put_int(p->first);
401                _file->put_int(p->second);
402            }
403        }
404        else {
405            _file->put_ulong(0);
406        }
407        // one_false_IDs_matches
408        _file->put_ulong(one_false_IDs_matches);
409        // path
410        count = path.size();
411        _file->put_ulong(count);
412        for (IDSetCIter id = path.begin();
413              id != path.end();
414              ++id) {
415            _file->put_int(*id);
416        }
417        // children
418        count = children.size();
419        _file->put_ulong(count);
420        for (PS_CandidateByGainMapIter child = children.begin();
421              child != children.end();
422              ++child) {
423            child->second->save(_file, _bits_in_map);
424        }
425    }
426
427    void load(PS_FileBuffer       *_file,
428              const unsigned long  _bits_in_map,
429              const PS_NodePtr&    _root_node)
430    {
431        unsigned long count;
432        // gain
433        _file->get_ulong(gain);
434        // passes_left
435        _file->get_uint(passes_left);
436        // false_IDs & filling_level
437        _file->get_ulong(false_IDs);
438        filling_level = (float)(_bits_in_map - false_IDs) / _bits_in_map * 100.0;
439        // one_false_IDs
440        SpeciesID id1;
441        SpeciesID id2;
442        _file->get_ulong(count);
443        one_false_IDs = (count) ? new ID2IDSet : 0;
444        for (; count > 0; --count) {
445            _file->get_int(id1);
446            _file->get_int(id2);
447            one_false_IDs->insert(ID2IDPair(id1, id2));
448        }
449        // one_false_IDs_matches
450        _file->get_ulong(one_false_IDs_matches);
451        // path & node
452        _file->get_ulong(count);
453        if (count) node = _root_node;
454        for (; count > 0; --count) {
455            _file->get_int(id1);
456            path.insert(id1);
457            node = node->getChild(id1).second;
458        }
459        // children
460        _file->get_ulong(count);
461        for (; count > 0; --count) {
462            PS_CandidateSPtr new_child(new PS_Candidate(0.0));
463            new_child->depth  = depth+1;
464            new_child->parent = this;
465            new_child->load(_file, _bits_in_map, _root_node);
466            children[new_child->gain] = new_child;
467        }
468    }
469
470    explicit PS_Candidate(float _distance) {
471        filling_level = 0.0;
472        depth         = 0;
473        distance      = _distance;
474        gain          = 0;
475        passes_left   = 0;
476        parent        = 0;
477        false_IDs     = 0;
478        one_false_IDs = 0;
479        one_false_IDs_matches = 0;
480        map           = 0;
481        node.SetNull();
482    }
483    ~PS_Candidate() {
484        if (map)           delete map;
485        if (one_false_IDs) delete one_false_IDs;
486
487        path.clear();
488        children.clear();
489    }
490};
491
492#else
493#error ps_candidate.hxx included twice
494#endif // PS_CANDIDATE_HXX
Note: See TracBrowser for help on using the repository browser.