• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // difference.h
2 
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Copyright 2005-2010 Google, Inc.
16 // Author: riley@google.com (Michael Riley)
17 //
18 // \file
19 // Class to compute the difference between two FSAs
20 
21 #ifndef FST_LIB_DIFFERENCE_H__
22 #define FST_LIB_DIFFERENCE_H__
23 
24 #include <vector>
25 using std::vector;
26 #include <algorithm>
27 
28 #include <fst/cache.h>
29 #include <fst/compose.h>
30 #include <fst/complement.h>
31 
32 
33 namespace fst {
34 
35 template <class A,
36           class M = Matcher<Fst<A> >,
37           class F = SequenceComposeFilter<M>,
38           class T = GenericComposeStateTable<A, typename F::FilterState> >
39 struct DifferenceFstOptions : public ComposeFstOptions<A, M, F, T> {
40   explicit DifferenceFstOptions(const CacheOptions &opts,
41                                 M *mat1 = 0, M *mat2 = 0,
42                                 F *filt = 0, T *sttable= 0)
43       : ComposeFstOptions<A, M, F, T>(mat1, mat2, filt, sttable) { }
44 
DifferenceFstOptionsDifferenceFstOptions45   DifferenceFstOptions() {}
46 };
47 
48 // Computes the difference between two FSAs. This version is a delayed
49 // Fst. Only strings that are in the first automaton but not in second
50 // are retained in the result.
51 //
52 // The first argument must be an acceptor; the second argument must be
53 // an unweighted, epsilon-free, deterministic acceptor. One of the
54 // arguments must be label-sorted.
55 //
56 // Complexity: same as ComposeFst.
57 //
58 // Caveats: same as ComposeFst.
59 template <class A>
60 class DifferenceFst : public ComposeFst<A> {
61  public:
62   using ImplToFst< ComposeFstImplBase<A> >::SetImpl;
63   using ImplToFst< ComposeFstImplBase<A> >::GetImpl;
64 
65   using ComposeFst<A>::CreateBase1;
66 
67   typedef A Arc;
68   typedef typename A::Weight Weight;
69   typedef typename A::StateId StateId;
70 
71   // A - B = A ^ B'.
72   DifferenceFst(const Fst<A> &fst1, const Fst<A> &fst2,
73                 const CacheOptions &opts = CacheOptions()) {
74     typedef RhoMatcher< Matcher<Fst<A> > > R;
75 
76     ComplementFst<A> cfst(fst2);
77     ComposeFstOptions<A, R> copts(CacheOptions(),
78                                   new R(fst1, MATCH_NONE),
79                                   new R(cfst, MATCH_INPUT,
80                                         ComplementFst<A>::kRhoLabel));
81     SetImpl(CreateBase1(fst1, cfst, copts));
82 
83     if (!fst1.Properties(kAcceptor, true)) {
84       FSTERROR() << "DifferenceFst: 1st argument not an acceptor";
85       GetImpl()->SetProperties(kError, kError);
86     }
87  }
88 
89   template <class M, class F, class T>
DifferenceFst(const Fst<A> & fst1,const Fst<A> & fst2,const DifferenceFstOptions<A,M,F,T> & opts)90   DifferenceFst(const Fst<A> &fst1, const Fst<A> &fst2,
91                 const DifferenceFstOptions<A, M, F, T> &opts) {
92     typedef RhoMatcher<M> R;
93 
94     ComplementFst<A> cfst(fst2);
95     ComposeFstOptions<A, R> copts(opts);
96     copts.matcher1 = new R(fst1, MATCH_NONE, kNoLabel, MATCHER_REWRITE_ALWAYS,
97                            opts.matcher1);
98     copts.matcher2 = new R(cfst, MATCH_INPUT, ComplementFst<A>::kRhoLabel,
99                            MATCHER_REWRITE_ALWAYS, opts.matcher2);
100 
101     SetImpl(CreateBase1(fst1, cfst, copts));
102 
103     if (!fst1.Properties(kAcceptor, true)) {
104       FSTERROR() << "DifferenceFst: 1st argument not an acceptor";
105       GetImpl()->SetProperties(kError, kError);
106     }
107   }
108 
109   // See Fst<>::Copy() for doc.
110   DifferenceFst(const DifferenceFst<A> &fst, bool safe = false)
111       : ComposeFst<A>(fst, safe) {}
112 
113   // Get a copy of this DifferenceFst. See Fst<>::Copy() for further doc.
114   virtual DifferenceFst<A> *Copy(bool safe = false) const {
115     return new DifferenceFst<A>(*this, safe);
116   }
117 };
118 
119 
120 // Specialization for DifferenceFst.
121 template <class A>
122 class StateIterator< DifferenceFst<A> >
123     : public StateIterator< ComposeFst<A> > {
124  public:
StateIterator(const DifferenceFst<A> & fst)125   explicit StateIterator(const DifferenceFst<A> &fst)
126       : StateIterator< ComposeFst<A> >(fst) {}
127 };
128 
129 
130 // Specialization for DifferenceFst.
131 template <class A>
132 class ArcIterator< DifferenceFst<A> >
133     : public ArcIterator< ComposeFst<A> > {
134  public:
135   typedef typename A::StateId StateId;
136 
ArcIterator(const DifferenceFst<A> & fst,StateId s)137   ArcIterator(const DifferenceFst<A> &fst, StateId s)
138       : ArcIterator< ComposeFst<A> >(fst, s) {}
139 };
140 
141 // Useful alias when using StdArc.
142 typedef DifferenceFst<StdArc> StdDifferenceFst;
143 
144 
145 typedef ComposeOptions DifferenceOptions;
146 
147 
148 // Computes the difference between two FSAs. This version is writes
149 // the difference to an output MutableFst. Only strings that are in
150 // the first automaton but not in second are retained in the result.
151 //
152 // The first argument must be an acceptor; the second argument must be
153 // an unweighted, epsilon-free, deterministic acceptor.  One of the
154 // arguments must be label-sorted.
155 //
156 // Complexity: same as Compose.
157 //
158 // Caveats: same as Compose.
159 template<class Arc>
160 void Difference(const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,
161              MutableFst<Arc> *ofst,
162              const DifferenceOptions &opts = DifferenceOptions()) {
163   typedef Matcher< Fst<Arc> > M;
164 
165   if (opts.filter_type == AUTO_FILTER) {
166     CacheOptions nopts;
167     nopts.gc_limit = 0;  // Cache only the last state for fastest copy.
168     *ofst = DifferenceFst<Arc>(ifst1, ifst2, nopts);
169   } else if (opts.filter_type == SEQUENCE_FILTER) {
170     DifferenceFstOptions<Arc> dopts;
171     dopts.gc_limit = 0;  // Cache only the last state for fastest copy.
172     *ofst = DifferenceFst<Arc>(ifst1, ifst2, dopts);
173   } else if (opts.filter_type == ALT_SEQUENCE_FILTER) {
174     DifferenceFstOptions<Arc, M, AltSequenceComposeFilter<M> > dopts;
175     dopts.gc_limit = 0;  // Cache only the last state for fastest copy.
176     *ofst = DifferenceFst<Arc>(ifst1, ifst2, dopts);
177   } else if (opts.filter_type == MATCH_FILTER) {
178     DifferenceFstOptions<Arc, M, MatchComposeFilter<M> > dopts;
179     dopts.gc_limit = 0;  // Cache only the last state for fastest copy.
180     *ofst = DifferenceFst<Arc>(ifst1, ifst2, dopts);
181   }
182 
183   if (opts.connect)
184     Connect(ofst);
185 }
186 
187 }  // namespace fst
188 
189 #endif  // FST_LIB_DIFFERENCE_H__
190