diff -crB openfst-1.4.1.orig/src/include/fst/lock.h openfst-1.4.1/src/include/fst/lock.h *** openfst-1.4.1.orig/src/include/fst/lock.h 2012-04-25 19:43:47.000000000 -0400 --- openfst-1.4.1/src/include/fst/lock.h 2015-02-28 14:12:29.009385600 -0400 *************** *** 78,85 **** RefCounter() : count_(1) {} int count() const { return count_; } ! int Incr() const { return ++count_; } ! int Decr() const { return --count_; } private: mutable int count_; --- 78,93 ---- RefCounter() : count_(1) {} int count() const { return count_; } ! ! // below lines are modifications of openfst for multi-thrads support, ! // from tools/extras/openfst_gcc41up.patch, applied by tools/Makefile, ! // applicable to gcc 4.1 or above ! // int Incr() const { return ++count_; } ! // int Decr() const { return --count_; } ! ! int Incr() const { return __sync_add_and_fetch(&count_, 1); } ! int Decr() const { return __sync_sub_and_fetch(&count_, 1); } ! // end modifications private: mutable int count_; diff -crB openfst-1.4.1.orig/src/include/fst/minimize.h openfst-1.4.1/src/include/fst/minimize.h *** openfst-1.4.1.orig/src/include/fst/minimize.h 2014-04-29 18:15:17.000000000 -0400 --- openfst-1.4.1/src/include/fst/minimize.h 2015-02-28 14:11:39.270566070 -0400 *************** *** 134,140 **** typedef typename A::Weight Weight; typedef ReverseArc RevA; ! CyclicMinimizer(const ExpandedFst& fst) { Initialize(fst); Compute(fst); } --- 134,147 ---- typedef typename A::Weight Weight; typedef ReverseArc RevA; ! CyclicMinimizer(const ExpandedFst& fst): ! // tell the Partition data-member to expect multiple repeated ! // calls to SplitOn with the same element if we are non-deterministic. ! P_(fst.Properties(kIDeterministic, true) == 0) { ! if(fst.Properties(kIDeterministic, true) == 0) ! CHECK(Weight::Properties() & kIdempotent); // this minimization ! // algorithm for non-deterministic FSTs can only work with idempotent ! // semirings. Initialize(fst); Compute(fst); } *************** *** 315,321 **** typedef typename A::StateId ClassId; typedef typename A::Weight Weight; ! AcyclicMinimizer(const ExpandedFst& fst) { Initialize(fst); Refine(fst); } --- 322,334 ---- typedef typename A::StateId ClassId; typedef typename A::Weight Weight; ! AcyclicMinimizer(const ExpandedFst& fst): ! // tell the Partition data-member to expect multiple repeated ! // calls to SplitOn with the same element if we are non-deterministic. ! partition_(fst.Properties(kIDeterministic, true) == 0) { ! if(fst.Properties(kIDeterministic, true) == 0) ! CHECK(Weight::Properties() & kIdempotent); // minimization for ! // non-deterministic FSTs can only work with idempotent semirings. Initialize(fst); Refine(fst); } *************** *** 531,543 **** void Minimize(MutableFst* fst, MutableFst* sfst = 0, float delta = kDelta) { ! uint64 props = fst->Properties(kAcceptor | kIDeterministic| ! kWeighted | kUnweighted, true); ! if (!(props & kIDeterministic)) { ! FSTERROR() << "FST is not deterministic"; ! fst->SetProperties(kError, kError); ! return; ! } if (!(props & kAcceptor)) { // weighted transducer VectorFst< GallicArc > gfst; --- 544,550 ---- void Minimize(MutableFst* fst, MutableFst* sfst = 0, float delta = kDelta) { ! uint64 props = fst->Properties(kAcceptor | kWeighted | kUnweighted, true); if (!(props & kAcceptor)) { // weighted transducer VectorFst< GallicArc > gfst; diff -crB openfst-1.4.1.orig/src/include/fst/partition.h openfst-1.4.1/src/include/fst/partition.h *** openfst-1.4.1.orig/src/include/fst/partition.h 2014-04-29 18:15:17.000000000 -0400 --- openfst-1.4.1/src/include/fst/partition.h 2015-02-28 14:11:39.271566087 -0400 *************** *** 43,50 **** friend class PartitionIterator; struct Element { ! Element() : value(0), next(0), prev(0) {} ! Element(T v) : value(v), next(0), prev(0) {} T value; Element* next; --- 43,50 ---- friend class PartitionIterator; struct Element { ! Element() : value(0), next(0), prev(0) {} ! Element(T v) : value(v), next(0), prev(0) {} T value; Element* next; *************** *** 52,60 **** }; public: ! Partition() {} ! Partition(T num_states) { Initialize(num_states); } --- 52,62 ---- }; public: ! Partition(bool allow_repeated_split): ! allow_repeated_split_(allow_repeated_split) {} ! Partition(bool allow_repeated_split, T num_states): ! allow_repeated_split_(allow_repeated_split) { Initialize(num_states); } *************** *** 137,152 **** if (class_size_[class_id] == 1) return; // first time class is split ! if (split_size_[class_id] == 0) visited_classes_.push_back(class_id); ! // increment size of split (set of element at head of chain) split_size_[class_id]++; ! // update split point ! if (class_split_[class_id] == 0) ! class_split_[class_id] = classes_[class_id]; ! if (class_split_[class_id] == elements_[element_id]) class_split_[class_id] = elements_[element_id]->next; // move to head of chain in same class --- 139,154 ---- if (class_size_[class_id] == 1) return; // first time class is split ! if (split_size_[class_id] == 0) { visited_classes_.push_back(class_id); ! class_split_[class_id] = classes_[class_id]; ! } // increment size of split (set of element at head of chain) split_size_[class_id]++; ! // update split point ! if (class_split_[class_id] != 0 ! && class_split_[class_id] == elements_[element_id]) class_split_[class_id] = elements_[element_id]->next; // move to head of chain in same class *************** *** 157,165 **** // class indices of the newly created class. Returns the new_class id // or -1 if no new class was created. T SplitRefine(T class_id) { // only split if necessary ! if (class_size_[class_id] == split_size_[class_id]) { ! class_split_[class_id] = 0; split_size_[class_id] = 0; return -1; } else { --- 159,169 ---- // class indices of the newly created class. Returns the new_class id // or -1 if no new class was created. T SplitRefine(T class_id) { + + Element* split_el = class_split_[class_id]; // only split if necessary ! //if (class_size_[class_id] == split_size_[class_id]) { ! if(split_el == NULL) { // we split on everything... split_size_[class_id] = 0; return -1; } else { *************** *** 163,180 **** split_size_[class_id] = 0; return -1; } else { - T new_class = AddClass(); size_t remainder = class_size_[class_id] - split_size_[class_id]; if (remainder < split_size_[class_id]) { // add smaller - Element* split_el = class_split_[class_id]; classes_[new_class] = split_el; - class_size_[class_id] = split_size_[class_id]; - class_size_[new_class] = remainder; split_el->prev->next = 0; split_el->prev = 0; } else { - Element* split_el = class_split_[class_id]; classes_[new_class] = classes_[class_id]; class_size_[class_id] = remainder; class_size_[new_class] = split_size_[class_id]; --- 167,189 ---- split_size_[class_id] = 0; return -1; } else { T new_class = AddClass(); + + if(allow_repeated_split_) { // split_size_ is possibly + // inaccurate, so work it out exactly. + size_t split_count; Element *e; + for(split_count=0,e=classes_[class_id]; + e != split_el; split_count++, e=e->next); + split_size_[class_id] = split_count; + } size_t remainder = class_size_[class_id] - split_size_[class_id]; if (remainder < split_size_[class_id]) { // add smaller classes_[new_class] = split_el; split_el->prev->next = 0; split_el->prev = 0; + class_size_[class_id] = split_size_[class_id]; + class_size_[new_class] = remainder; } else { classes_[new_class] = classes_[class_id]; class_size_[class_id] = remainder; class_size_[new_class] = split_size_[class_id]; *************** *** 245,254 **** --- 254,269 ---- vector class_size_; // size of split for each class + // in the nondeterministic case, split_size_ is actually an upper + // bound on the size of split for each class. vector split_size_; // set of visited classes to be used in split refine vector visited_classes_; + + // true if input fst was deterministic: we can make + // certain assumptions in this case that speed up the algorithm. + bool allow_repeated_split_; };