1 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 // 14 // Copyright 2005-2010 Google, Inc. 15 // Author: jpr (at) google.com (Jake Ratkiewicz) 16 17 #ifndef FST_SCRIPT_RMEPSILON_H_ 18 #define FST_SCRIPT_RMEPSILON_H_ 19 20 #include <vector> 21 using std::vector; 22 23 #include <fst/script/arg-packs.h> 24 #include <fst/script/fst-class.h> 25 #include <fst/script/weight-class.h> 26 #include <fst/script/shortest-distance.h> // for ShortestDistanceOptions 27 #include <fst/rmepsilon.h> 28 #include <fst/queue.h> 29 30 // the following is necessary, or SWIG complains mightily about 31 // shortestdistanceoptions not being defined before being used as a base. 32 #ifdef SWIG 33 %include "nlp/fst/script/shortest-distance.h" 34 #endif 35 36 37 namespace fst { 38 namespace script { 39 40 // 41 // OPTIONS 42 // 43 44 struct RmEpsilonOptions : public fst::script::ShortestDistanceOptions { 45 bool connect; 46 WeightClass weight_threshold; 47 int64 state_threshold; 48 49 RmEpsilonOptions(QueueType qt = AUTO_QUEUE, float d = kDelta, bool c = true, 50 WeightClass w = fst::script::WeightClass::Zero(), 51 int64 n = kNoStateId) 52 : ShortestDistanceOptions(qt, EPSILON_ARC_FILTER, 53 kNoStateId, d), 54 connect(c), weight_threshold(w), state_threshold(n) { } 55 }; 56 57 58 // 59 // TEMPLATES 60 // 61 62 // this function takes care of transforming a script-land RmEpsilonOptions 63 // into a lib-land RmEpsilonOptions 64 template<class Arc> 65 void RmEpsilonHelper(MutableFst<Arc> *fst, 66 vector<typename Arc::Weight> *distance, 67 const RmEpsilonOptions &opts) { 68 typedef typename Arc::StateId StateId; 69 typedef typename Arc::Weight Weight; 70 71 typename Arc::Weight weight_thresh = 72 *(opts.weight_threshold.GetWeight<Weight>()); 73 74 switch (opts.queue_type) { 75 case AUTO_QUEUE: { 76 AutoQueue<StateId> queue(*fst, distance, EpsilonArcFilter<Arc>()); 77 fst::RmEpsilonOptions<Arc, AutoQueue<StateId> > ropts( 78 &queue, opts.delta, opts.connect, weight_thresh, 79 opts.state_threshold); 80 RmEpsilon(fst, distance, ropts); 81 break; 82 } 83 case FIFO_QUEUE: { 84 FifoQueue<StateId> queue; 85 fst::RmEpsilonOptions<Arc, FifoQueue<StateId> > ropts( 86 &queue, opts.delta, opts.connect, weight_thresh, 87 opts.state_threshold); 88 RmEpsilon(fst, distance, ropts); 89 break; 90 } 91 case LIFO_QUEUE: { 92 LifoQueue<StateId> queue; 93 fst::RmEpsilonOptions<Arc, LifoQueue<StateId> > ropts( 94 &queue, opts.delta, opts.connect, weight_thresh, 95 opts.state_threshold); 96 RmEpsilon(fst, distance, ropts); 97 break; 98 } 99 case SHORTEST_FIRST_QUEUE: { 100 NaturalShortestFirstQueue<StateId, Weight> queue(*distance); 101 fst::RmEpsilonOptions<Arc, NaturalShortestFirstQueue<StateId, 102 Weight> > ropts( 103 &queue, opts.delta, opts.connect, weight_thresh, 104 opts.state_threshold); 105 RmEpsilon(fst, distance, ropts); 106 break; 107 } 108 case STATE_ORDER_QUEUE: { 109 StateOrderQueue<StateId> queue; 110 fst::RmEpsilonOptions<Arc, StateOrderQueue<StateId> > ropts( 111 &queue, opts.delta, opts.connect, weight_thresh, 112 opts.state_threshold); 113 RmEpsilon(fst, distance, ropts); 114 break; 115 } 116 case TOP_ORDER_QUEUE: { 117 TopOrderQueue<StateId> queue(*fst, EpsilonArcFilter<Arc>()); 118 fst::RmEpsilonOptions<Arc, TopOrderQueue<StateId> > ropts( 119 &queue, opts.delta, opts.connect, weight_thresh, 120 opts.state_threshold); 121 RmEpsilon(fst, distance, ropts); 122 break; 123 } 124 default: 125 FSTERROR() << "Unknown or unsupported queue type: " << opts.queue_type; 126 fst->SetProperties(kError, kError); 127 } 128 } 129 130 // 1 131 typedef args::Package<const FstClass &, MutableFstClass *, 132 bool, const RmEpsilonOptions &> RmEpsilonArgs1; 133 134 template<class Arc> 135 void RmEpsilon(RmEpsilonArgs1 *args) { 136 const Fst<Arc> &ifst = *(args->arg1.GetFst<Arc>()); 137 MutableFst<Arc> *ofst = args->arg2->GetMutableFst<Arc>(); 138 vector<typename Arc::Weight> distance; 139 bool reverse = args->arg3; 140 141 if (reverse) { 142 VectorFst<Arc> rfst; 143 Reverse(ifst, &rfst); 144 RmEpsilonHelper(&rfst, &distance, args->arg4); 145 Reverse(rfst, ofst); 146 } else { 147 *ofst = ifst; 148 } 149 RmEpsilonHelper(ofst, &distance, args->arg4); 150 } 151 152 // 2 153 typedef args::Package<MutableFstClass *, bool, 154 const WeightClass, int64, 155 float> RmEpsilonArgs2; 156 157 template<class Arc> 158 void RmEpsilon(RmEpsilonArgs2 *args) { 159 MutableFst<Arc> *fst = args->arg1->GetMutableFst<Arc>(); 160 typename Arc::Weight w = *(args->arg3.GetWeight<typename Arc::Weight>()); 161 162 RmEpsilon(fst, args->arg2, w, args->arg4, args->arg5); 163 } 164 165 // 3 166 typedef args::Package<MutableFstClass *, vector<WeightClass> *, 167 const RmEpsilonOptions &> RmEpsilonArgs3; 168 169 template<class Arc> 170 void RmEpsilon(RmEpsilonArgs3 *args) { 171 MutableFst<Arc> *fst = args->arg1->GetMutableFst<Arc>(); 172 const RmEpsilonOptions &opts = args->arg3; 173 174 vector<typename Arc::Weight> weights; 175 176 RmEpsilonHelper(fst, &weights, opts); 177 178 // Copy the weights back 179 args->arg2->resize(weights.size()); 180 for (unsigned i = 0; i < weights.size(); ++i) { 181 (*args->arg2)[i] = WeightClass(weights[i]); 182 } 183 } 184 185 // 186 // PROTOTYPES 187 // 188 189 // 1 190 void RmEpsilon(const FstClass &ifst, MutableFstClass *ofst, 191 bool reverse = false, 192 const RmEpsilonOptions& opts = 193 fst::script::RmEpsilonOptions()); 194 195 // 2 196 void RmEpsilon(MutableFstClass *arc, bool connect = true, 197 const WeightClass &weight_threshold = 198 fst::script::WeightClass::Zero(), 199 int64 state_threshold = fst::kNoStateId, 200 float delta = fst::kDelta); 201 202 // 3 203 void RmEpsilon(MutableFstClass *fst, vector<WeightClass> *distance, 204 const RmEpsilonOptions &opts); 205 206 207 } // namespace script 208 } // namespace fst 209 210 211 #endif // FST_SCRIPT_RMEPSILON_H_ 212