File: vitmatrix.hh

package info (click to toggle)
augustus 3.2.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 289,676 kB
  • sloc: cpp: 48,711; perl: 13,339; ansic: 1,251; makefile: 859; sh: 58
file content (781 lines) | stat: -rw-r--r-- 22,283 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
/***********************************************************************
 * file:    vitmatrix.hh
 * licence: Artistic Licence, see file LICENCE.TXT or
 *          http://www.opensource.org/licenses/artistic-license.php
 * descr.:  data structures used inside the viterbi matrix
 * author:  Oliver Keller (keller@cs.uni-goettingen.de)
 *
 **********************************************************************/

#ifndef _VITMATRIX_HH
#define _VITMATRIX_HH

// project includes
#include "types.hh"  // for ProjectError

// standard C/C++ includes
#include <vector>
#include <map>
#include <list>
#include <limits>
#include <climits>

using namespace std;


// constants for Viterbi*Types
#define VIT_MIN_CAPACITY 7
#define MAX_LINKCOUNT 300
#define SUBSTATEVALUE_BITS (8*sizeof(short))
	
struct SubstateId {
    explicit SubstateId(signed char s=-1, short v=0) : slot(s), value(v) {}

    bool operator< (const SubstateId& other) const {
	return 
	    slot < other.slot || (slot == other.slot &&
				  value < other.value);
    }
    bool operator== (const SubstateId& other) const {
	return slot == other.slot && value == other.value;
    }
    bool operator> (const SubstateId& other) const {
	return (other < *this);
    }
    bool operator!= (const SubstateId& other) const {
	return !operator==(other);
    }
    bool operator<= (const SubstateId& other) const {
	return !operator>(other);
    }

    bool undef() {
	return slot==-1 && value==0;
    }
    
    

    int fullId() const {
	// implements a monotonous mapping
	// with SubstateId() -> 0
	return ((slot+1) << SUBSTATEVALUE_BITS) + value;
    }
    void set(int fromId) {
	// reverse mapping int->SubstateId()
	value = fromId;
	slot = ((fromId-value) >> SUBSTATEVALUE_BITS) -1;
    }
    static SubstateId min(int slot) {
	return SubstateId(slot, numeric_limits<short>::min());
    }
    static SubstateId max(int slot) {
	return SubstateId(slot, numeric_limits<short>::max());
    }

    signed char slot;
    short value;
};

#ifdef DEBUG
inline string itoa(SubstateId d) {
    return "(" + itoa(d.slot) + "/" + itoa(d.value) + ")";
}
#endif

typedef map<SubstateId, SubstateId> SubstateIdMap;

#ifdef DEBUG
#define MEMUSEDBLCOUNT 10
struct GenericDataType {
    GenericDataType() {
	for (int i=0; i<MEMUSEDBLCOUNT; i++)
	    vals[i]=0;
    }
    void operator+=(const GenericDataType& other) {
	for (int i=0; i<MEMUSEDBLCOUNT; i++)
	    vals[i]+=other.vals[i];
    }
    double& operator[] (int i) { return vals[i]; }
    double vals[MEMUSEDBLCOUNT];
};
#endif

// exceptions thrown by Viterbi
struct NoSubmapFoundError : public ProjectError {
    NoSubmapFoundError() : 
	ProjectError("Internal error: ViterbiSubmapType has no map!") {}
};
struct SubmapEmptyError : public ProjectError {
    SubmapEmptyError() : 
	ProjectError("Internal error: ViterbiSubmapType is empty!") {}
};


/*
 * AlgorithmVariant: 
 * this type is used to determine the variant implemented in the
 * viterbiForwardAndSampling methods
 *
 */
enum AlgorithmVariant { doViterbiOnly, doViterbiAndForward, doSampling, doBacktracking };
/* any changes made to the order above needs to be reflected in the following 
   functions */
inline bool doViterbi(AlgorithmVariant algovar) {
    return algovar <= doViterbiAndForward;
}
inline bool needForwardTable(AlgorithmVariant algovar) {
    return algovar == doViterbiAndForward || algovar == doSampling;
}
inline AlgorithmVariant doViterbi(bool needForwardTable) {
    return needForwardTable ? doViterbiAndForward : doViterbiOnly;
}


/*
 * ViterbiSubmapType:
 * This class stores the probabilites for substates for a single
 * pair (base position, state)
 * 
 * the actual values are the entries of the map, multiplied by a common factor
 */
class ViterbiSubmapType;

struct ViterbiSubmapEntry {
    ViterbiSubmapEntry(const Double& dbl=0, ViterbiSubmapType* pred=0) :
	p(dbl), predMap(pred), succCount(0) {}
    bool operator<(const ViterbiSubmapEntry& other) const {
	return p<other.p;
    }
    bool operator<=(const ViterbiSubmapEntry& other) const {
	return !(other < *this);
    }
    bool operator>=(const ViterbiSubmapEntry& other) const {
	return !operator<(other);
    }
    bool operator>(const ViterbiSubmapEntry& other) const {
	return other < *this;
    }
    void set(const Double& dbl, ViterbiSubmapType* pred) {
	p =dbl;
	predMap = pred;
    }

    Double p;
    ViterbiSubmapType* predMap;
    short succCount;
};

struct ViterbiSubmapBasetype : public map<SubstateId, ViterbiSubmapEntry > {
    ViterbiSubmapBasetype(int ln) : 
	linkcount(ln), 
	predSubstates(0) {}
    ViterbiSubmapBasetype(const ViterbiSubmapBasetype& other, int ln) :
	map<SubstateId,ViterbiSubmapEntry>(other),
	linkcount(ln),
	predSubstates(0) {}
    ~ViterbiSubmapBasetype() {
	delete predSubstates;
    }

    // multiple instances of ViterbiSubmapType can share the same values;
    // this value tells how many of them exist, so ViterbiSubmapType
    // knows when to delete the pointed to 
    int linkcount;

    // this map stores the predecessor substates, if needed
    SubstateIdMap* predSubstates;
}; // ViterbiSubmapBasetype

class ViterbiSubmapType {
    friend class ViterbiColumnType;
    // ``const'' in this class refers not to the contents of the map
    // but just to the pointer (we want to be able to change
    // substates of otherwise ``constant'' Viterbi columns)
 
public:
    // these are aliases for a map iterator
    typedef ViterbiSubmapBasetype::iterator iterator;
    typedef ViterbiSubmapBasetype::const_iterator const_iterator;

    // constructors
    explicit ViterbiSubmapType(signed char st) : 
	factor(1), state(st), theMap(0) {}
    // copy constructor: does not copy the map pointed to but
    // just adds a link to it
    ViterbiSubmapType(const ViterbiSubmapType& other) :
	factor(other.factor), state(other.state)
    {
	link(other);
    }
    // destructor
    ~ViterbiSubmapType() {
	unlink();
    }
    // assignment: the same behaviour as the copy constructor
    void operator= (const ViterbiSubmapType& other) {
	if (&other == this)
	    return;
	factor = other.factor;
	state = other.state;
	unlink();
	link(other);
    }
    // share another submap's map
    void link (const ViterbiSubmapType& other, Double mult) {
	factor = other.factor * mult;
	unlink();
	link(other);
    }
    // remove the map
    void deactivate() {
	unlink();
	theMap=0;
    }
    int getMainState() const {
	return state;
    }


    // the following methods can be used also when the map is NULL
    bool inactive() const {  // is the map NULL?
	return (theMap==0);
    }
    bool empty() const {
     	return inactive() || theMap->empty();
    }
    bool emptypart(int part) {
    	return inactive() || begin(part) == end(part);
    }
    int size() const {
    	return inactive() ? 0 : theMap->size();
    }
    void activate() {
	if (!theMap)
	    theMap = new ViterbiSubmapBasetype(1);
    }
    int linkcount() const {
	return inactive() ? 0 : theMap->linkcount;
    }
    bool is_linked() {
	return theMap && theMap->linkcount > 1;
    }
    // access predecessor substate map
    SubstateIdMap* getPredSubstateMap() const; 
    SubstateId popPredSubstate(SubstateId substate) const;
    void clearEmptySubstateMap() const;

    void swapMaps(ViterbiSubmapType&);       // exchange values with another instance
 
    void merge(ViterbiSubmapType&, Double);  // merge two maps and take the maximum entries
    int eraseAllUnneededSubstates() const;   // erase substates with succCount==0

    // the following methods do not check if theMap is non-NULL
    iterator begin() const {
    	return theMap->begin();
    }
    iterator begin(int slot) const {
	return theMap->lower_bound(SubstateId::min(slot));
    }
    iterator end() const {
	return theMap->end();
    }
    iterator end(int slot) const {
	return theMap->upper_bound(SubstateId::max(slot));
    }
    iterator bound(SubstateId substate) const {
     	return theMap->lower_bound(substate);
    }
    iterator bound(signed char slot, short value) const {
    	return theMap->lower_bound(SubstateId(slot,value));
    }
    Double get(SubstateId substate) const {
	const_iterator it = theMap->find(substate);
	return it==end() ? 0 : it->second.p * factor;
    }
    iterator insert(iterator where, pair<SubstateId, ViterbiSubmapEntry> what) const {
	// insert the value as is (without dividing it by factor)
    	return theMap->insert(where, what);
    }
    iterator insert(iterator where, SubstateId substate, const Double& value, 
		    ViterbiSubmapType* pred) const {
	// insert the value as is (without dividing it by factor)
    	return insert(where, make_pair(substate, ViterbiSubmapEntry(value,pred)));
    }
    void push_back(SubstateId substate, const Double& value, ViterbiSubmapType* pred) const {
	// insert at end of map
    	insert(end(), substate, value, pred);
    }
    void erase(iterator start, iterator end) const {
	theMap->erase(start, end);
    }
    void erase(SubstateId substate) const {
	theMap->erase(substate);
    }
    short& succCount(SubstateId substate) {
	return (*theMap)[substate].succCount;
    }
    short& succCount(iterator it) {
	return it->second.succCount;
    }
    const short& succCount(iterator it) const {
#ifdef DEBUG
	if (it == end())
	    throw SubmapEmptyError();
#endif
	return it->second.succCount;
    }
    short& succCount() {
    	return succCount(begin());
    }
    void eraseAndDecCounts(iterator it) const; 
    bool setMax(SubstateId substate, Double value, ViterbiSubmapType* pred) const;
    void cloneMap(ViterbiSubmapType* newPredMap, int maxlinkcount=1);
    void cloneMapIfLinkcountExceeded(ViterbiSubmapType* newPredMap) {
	cloneMap(newPredMap, MAX_LINKCOUNT);
    }
    void getMaxSubstate(SubstateId& substate, Double& value) const;
    int eraseUnneededSubstate(SubstateId substate);
    void registerPredecessors();
    void useMaximum(Double& mainProb);

#ifdef DEBUG
    // functions used for debugging only
    GenericDataType memoryUsage();
    void dieOnZero() const;
    void checkAfterWindow() const;
    SubstateId getPredecessorSubstate(SubstateId substate) const;
    void checkCounts() const;
#endif

    Double factor; // multiply this to the entries of the map to get the actual value

private:
    // common to copy constructor and assignment operator:
    void link(const ViterbiSubmapType& other) {
	theMap = other.theMap;
	if (theMap) theMap->linkcount++;
    }
    // common to destructor and assignment operator
    void unlink() {
	if (theMap && --(theMap->linkcount)==0)
	    delete theMap;
    }

    signed char state;             // the main state
    ViterbiSubmapBasetype* theMap; // the entries (probabilities/factor) for each substate
}; // ViterbiSubmapType
    
// inline definitions of ViterbiSubmapType member functions

// returns the predecessor substate map, creates one if none exists
inline SubstateIdMap* ViterbiSubmapType::getPredSubstateMap() const {
    if (!theMap)
	return 0;
    SubstateIdMap*& result = theMap->predSubstates;
    if (!result)
	result = new SubstateIdMap;
    return result;
}

inline void ViterbiSubmapType::clearEmptySubstateMap() const {
    if (theMap && theMap->predSubstates &&
	theMap->predSubstates->empty()) {
	delete theMap->predSubstates;
	theMap->predSubstates = 0;
    }
}

inline void ViterbiSubmapType::swapMaps(ViterbiSubmapType& other) {
    ViterbiSubmapBasetype* temp = theMap;
    theMap = other.theMap;
    other.theMap = temp;
}

inline void ViterbiSubmapType::eraseAndDecCounts(iterator it) const {
    ViterbiSubmapType* pred = it->second.predMap;
    if (pred) {
	SubstateId substate = popPredSubstate(it->first);
	pred->succCount(substate)--;
#ifdef DEBUG
	if (pred->succCount(substate) < 0)
	    throw ProjectError("Have negative succCounts");
#endif
    }
    theMap->erase(it);
}

inline bool ViterbiSubmapType::setMax(SubstateId substate, Double value, ViterbiSubmapType* pred)  const {
    ViterbiSubmapEntry& target = (*theMap)[substate];
    if (target.p * factor < value) {
	target.set(value / factor, pred);
	return true;
    }
    return false;
}

inline void ViterbiSubmapType::cloneMap(ViterbiSubmapType* newPredMap, int maxlinkcount) {
#ifdef DEBUG
    if (newPredMap == 0)
	throw ProjectError("SubstateModel::cloneMap: predMap==0!");
#endif
   if (theMap->linkcount > maxlinkcount) {
	theMap->linkcount--;
	theMap = new ViterbiSubmapBasetype(*theMap,1);
	for (iterator it=begin(); it != end(); ++it) {
	    it->second.predMap = newPredMap;
	    it->second.succCount = 0;
	}
    }
}

inline void ViterbiSubmapType::getMaxSubstate(SubstateId& substate, Double& value) const {
    value = 0; substate.set(0);
    if (empty()) 
	return;
    for (iterator it = begin(); it != end(); ++it)
	if (it->second > value) {
	    substate = it->first;
	    value = it->second.p;
	}
    value *= factor;
}


/*
 * ViterbiEntryType:
 * one entry in the viterbi matrix, including the index for the substate map
 *
 */
struct ViterbiEntryType {
    ViterbiEntryType(signed char st, Double v, signed char i=-1) :
	state(st), value(v), substate_idx(i) {}
    signed char state;
    Double value;
    signed char substate_idx;
};


/*
 * ViterbiColumnType:
 * The entries of the Viterbi matrix belonging to the same base position
 * Only nonzero values are actually stored
 *
 */
typedef vector<ViterbiEntryType> ViterbiColumnBasetype;

class ViterbiColumnType : public ViterbiColumnBasetype {
public:
    
    // constructor and destructor
    ViterbiColumnType() : 
	ViterbiColumnBasetype(), 
	subProbs(), idx(0), maxsize(0) {}
    ~ViterbiColumnType()  {
	delete[] idx;
    }

    void reset(int n);     // delete the column and reserve space for n states
    void erase(int state); // erase the value for a particular state (including substates)

    // return a value without autovivification
    Double get(int state) const {
	return has(state) ? elem(state).value : 0;
    }
    Double get(int state, SubstateId substate) const {
	if (substate.undef()) return get(state);
	try {
	    return getSubstates(state).get(substate);
	} catch (NoSubmapFoundError) {
	    return 0;
	}
    }
    // index operator; uses autovivication in non-const contexts
    Double operator[](int state) const { // no autovivification
	return get(state);
    }
    Double& operator[](int state) { // autovivification if needed
	if (has(state))
	    return elem(state).value;
	addState(state);
	return back().value;
    }

    bool has(int state) const {
#ifdef DEBUG
	if (state < 0 || state >= maxsize)
	    throw ProjectError("ViterbiColumnType: state out of range");
#endif	
	return idx[state] >= 0;
    }
    int size() { // number of elements !=0
	return ViterbiColumnBasetype::size();
    }
    int max_capacity() { // this equals statecount
	return maxsize;
    }

    // access substates
    bool hasSubstates(int state) const {
	int idx = getSubstateIdx(state);
	return idx >= 0 && idx < subProbs.size() && !subProbs[idx].inactive();
    }
    const ViterbiSubmapType& getSubstates(int state) const;
    ViterbiSubmapType& getSubstates(int state);
    void getMaxSubstate(int state, SubstateId& substate, Double& value) const;
    ViterbiSubmapType& addSubstates(const ViterbiSubmapType& newmap);

    // calls a member function of class Tp with a parameter of
    // type ViterbiSubmapType for each submap in the column
    template <class Tp, class FncPtr>
    void foreachSubstate(Tp p, FncPtr f) {
	for (int i=0; i<subProbs.size(); i++) 
	    (p->*f)(subProbs[i]);
    }
    void eraseSubstates(int state);  // erase all the substates for a particular state
    int eraseUnneededSubstates();    // calls eraseUnneededSubstates for each submap
    int removeEmptySubmaps();        

#ifdef DEBUG
    // functions used for debugging only
    int substateCount(int state) const {
	try {
	    return getSubstates(state).size();
	} catch (...) {
	    return 0;
	}
    }
    int totalSubstateCount() const {
	int result=0;
	for (int i=0; i<subProbs.size(); i++) result += subProbs[i].size();
	return result;
    }
    map<int,Double> substateCounts() const {
	map<int,Double> result;
	for (int i=0; i<subProbs.size(); i++) 
	    result[subProbs[i].state] = subProbs[i].size();
	return result;
    }
    void testIntegrity() const;
    void checkAfterWindow() const {
	for (int i=0; i < subProbs.size(); i++) 
	    subProbs[i].checkAfterWindow();
    }
    void showSubstateInfo(ostream& strm) const;
    void write(ostream& strm, const vector<string>&);
    void write(const vector<string>&); 

    int getSubmapCapacity() {
	return subProbs.capacity() * sizeof(ViterbiSubmapType);
    }
    GenericDataType getSubstateMemoryUsage();
    void countSubmaps(map<ViterbiSubmapBasetype*,int>& linkcounts);
#endif
    	    
private:
    const ViterbiEntryType& elem(int state) const {
	return ViterbiColumnBasetype::operator[](idx[state]);
    }
    ViterbiEntryType& elem(int state) {
	return ViterbiColumnBasetype::operator[](idx[state]);
    }
    void addState(int state, signed char sub_idx=-1);
    signed char getSubstateIdx(int state) const {
	return has(state) ? elem(state).substate_idx : -1;
    }
    void eraseSubProbs(int subidx);

    vector<ViterbiSubmapType> subProbs; // the substate probabilities
    signed char* idx;                   // for each state, the vector index
                                        // or -1 if entry is zero
    int maxsize;                        // number of states
};  // ViterbiColumnType

// inline definitions of ViterbiColumnType member functions
inline const ViterbiSubmapType& ViterbiColumnType::getSubstates(int state) const {
    int idx = getSubstateIdx(state);
    if (idx >= 0 && idx < subProbs.size()) {
	const ViterbiSubmapType& result = subProbs[idx];
	if (!result.inactive())
	    return result;
    }
    throw NoSubmapFoundError();
}

inline ViterbiSubmapType& ViterbiColumnType::getSubstates(int state) {
    int idx = getSubstateIdx(state);
    if (idx >= 0 && idx < subProbs.size()) {
	ViterbiSubmapType& result = subProbs[idx];
	if (!result.inactive())
	    return result;
    }
    throw NoSubmapFoundError();
}

inline void ViterbiColumnType::getMaxSubstate(int state, SubstateId& substate, Double& value) const {
    Double mainval = get(state);
    try {
	const ViterbiSubmapType& submap = getSubstates(state);
	submap.getMaxSubstate(substate, value);
	if (value > mainval)
	    return;
    } catch (NoSubmapFoundError) {}
    substate.set(0); value = mainval;
}

inline int ViterbiColumnType::eraseUnneededSubstates() {
    int result = 0;
    for (int i=0; i<subProbs.size(); i++) 
	result += subProbs[i].eraseAllUnneededSubstates();
    return result;
}

inline int ViterbiColumnType::removeEmptySubmaps() {
    int result = 0;
    for (int i=0; i<subProbs.size(); i++)
	if (subProbs[i].empty() && !subProbs[i].inactive()) {
	    subProbs[i].deactivate();
	    result++;
	}
    return result;
}

inline void ViterbiColumnType::eraseSubProbs(int subidx) {
    if (subidx >= 0) {
	// overwrite entry at position subidx
	// with the (previously) last entry
	if (subidx < subProbs.size()-1) {
	    elem(subProbs.back().state).substate_idx = subidx;
	    subProbs[subidx] = subProbs.back();
	}
	// delete last entry in vector
	subProbs.pop_back();
    }
}


/*
 * ViterbiMatrixType:
 * An array of Viterbi columns
 */
class ViterbiMatrixType {
public:
    ViterbiMatrixType () : data(0), count(0) {}
    ~ViterbiMatrixType() {
	delete[] data;
    }
    void assign(int colcount, int colsize) {
	count = colcount;
	delete[] data;
	data = new ViterbiColumnType[count];
	for (int i=0; i<count; i++) {
	    data[i].reset(colsize);
	}
    }
    ViterbiColumnType& operator[] (int i) {
	return data[i];
    }
    const ViterbiColumnType& operator[] (int i) const {
	return data[i];
    }
    int size() const {
	return count;
    }

#ifdef DEBUG
    // functions used for debugging only
    double load() {
	double result=0;
	for (int i=0; i<count; i++) 
	    result += data[i].capacity();
	return result / count;
    }
    double load(int i) {
	return data[i].capacity();
    }
    double used_load() {
	double result=0;
	for (int i=0; i<count; i++) 
	    result += data[i].size();
	return result / count;
    }
    void write(ostream& strm, const vector<string>& stateNames = vector<string>()) {
	for (int i=0; i<count; i++) 
	    data[i].write(strm, stateNames);
    }
    int compare(istream&, const vector<string>& stateNames = vector<string>());
    void showSubstateMemoryUsage(int from = 0, int to = -1);
#endif
		
private:
    ViterbiColumnType* data;
    int count;
}; // ViterbiMatrixType


/*
 * Options lists are used for sampling; items also in backtracking
 */
class OptionListItem {
public:
    OptionListItem(){reset();};
    OptionListItem(int st, int bs, Double p){
	state = st;
	base = predEnd = bs;
	probability = p;
    }
    OptionListItem(int st, int bs, int pe, Double p){
	state = st;
	base = bs;
	predEnd = pe;
	probability = p;
    }
    void reset(){state = TYPE_UNKNOWN; base = predEnd = -INT_MAX;}
    void resetPredEnd() {predEnd = -INT_MAX;}
    int state;
    int base;
    int predEnd; // base at which predecessor state ends, usually identical to base unless states (genes) overlap
    Double probability;
};

inline bool operator< (const OptionListItem& first, const OptionListItem& second) {
    // the largest probability comes first
    return (first.probability > second.probability);
}

class OptionsList{
public:
    OptionsList(){
	cumprob = 0.0;
    }
    ~OptionsList(){
	while (!options.empty())
	    options.pop_front();
    }
    void add(int state, int base, Double probability, int predEnd = -INT_MAX) {
	options.push_back(OptionListItem(state, base, 
					 (predEnd == -INT_MAX)? base : predEnd,
					 probability));
	cumprob += probability;
    }
    void prepareSampling() {
	options.sort();
    }
    int size(){
	return options.size();
    }
    void print(ostream& out) {
	out << "options: " << cumprob << " | "; 
	for (list<OptionListItem>::iterator it = options.begin(); it != options.end(); ++it){
	    out << it->state << " " << it->base << " " << (it->probability/cumprob) << ", ";
	}
	out << endl;
    }
    OptionListItem sample();

private:
    list<OptionListItem> options;
    Double cumprob;
};


#endif    // _VITMATRIX_HH