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_;
};