arc-map.h revision 3da1eb108d36da35333b2d655202791af854996b
1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// arc-map.h
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: riley@google.com (Michael Riley)
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Class to map over/transform arcs e.g., change semirings or
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// implement project/invert. Consider using when operation does
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// not change the number of arcs (except possibly superfinal arcs).
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_ARC_MAP_H__
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_ARC_MAP_H__
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
263da1eb108d36da35333b2d655202791af854996bPrzemyslaw Szczepaniak#include <tr1/unordered_map>
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::tr1::unordered_map;
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::tr1::unordered_multimap;
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <string>
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <utility>
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::pair; using std::make_pair;
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/cache.h>
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/mutable-fst.h>
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// This determines how final weights are mapped.
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonenum MapFinalAction {
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // A final weight is mapped into a final weight. An error
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // is raised if this is not possible.
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MAP_NO_SUPERFINAL,
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // A final weight is mapped to an arc to the superfinal state
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // when the result cannot be represented as a final weight.
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // The superfinal state will be added only if it is needed.
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MAP_ALLOW_SUPERFINAL,
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // A final weight is mapped to an arc to the superfinal state
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // unless the result can be represented as a final weight of weight
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Zero(). The superfinal state is always added (if the input is
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // not the empty Fst).
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MAP_REQUIRE_SUPERFINAL
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// This determines how symbol tables are mapped.
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonenum MapSymbolsAction {
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Symbols should be cleared in the result by the map.
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MAP_CLEAR_SYMBOLS,
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Symbols should be copied from the input FST by the map.
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MAP_COPY_SYMBOLS,
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Symbols should not be modified in the result by the map itself.
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // (They may set by the mapper).
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MAP_NOOP_SYMBOLS
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// ArcMapper Interface - class determinies how arcs and final weights
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// are mapped. Useful for implementing operations that do not change
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// the number of arcs (expect possibly superfinal arcs).
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// class ArcMapper {
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  public:
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef A FromArc;
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef B ToArc;
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Maps an arc type A to arc type B.
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   B operator()(const A &arc);
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Specifies final action the mapper requires (see above).
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // The mapper will be passed final weights as arcs of the
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // form A(0, 0, weight, kNoStateId).
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   MapFinalAction FinalAction() const;
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Specifies input symbol table action the mapper requires (see above).
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   MapSymbolsAction InputSymbolsAction() const;
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Specifies output symbol table action the mapper requires (see above).
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   MapSymbolsAction OutputSymbolsAction() const;
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // This specifies the known properties of an Fst mapped by this
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // mapper. It takes as argument the input Fst's known properties.
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   uint64 Properties(uint64 props) const;
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// };
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The ArcMap functions and classes below will use the FinalAction()
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// method of the mapper to determine how to treat final weights,
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// e.g. whether to add a superfinal state. They will use the Properties()
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// method to set the result Fst properties.
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// We include a various map versions below. One dimension of
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// variation is whether the mapping mutates its input, writes to a
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// new result Fst, or is an on-the-fly Fst. Another dimension is how
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// we pass the mapper. We allow passing the mapper by pointer
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// for cases that we need to change the state of the user's mapper.
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// This is the case with the encode mapper, which is reused during
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// decoding. We also include map versions that pass the mapper
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// by value or const reference when this suffices.
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Maps an arc type A using a mapper function object C, passed
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// by pointer.  This version modifies its Fst input.
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class A, class C>
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid ArcMap(MutableFst<A> *fst, C* mapper) {
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::StateId StateId;
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight Weight;
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (mapper->InputSymbolsAction() == MAP_CLEAR_SYMBOLS)
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    fst->SetInputSymbols(0);
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (mapper->OutputSymbolsAction() == MAP_CLEAR_SYMBOLS)
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    fst->SetOutputSymbols(0);
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (fst->Start() == kNoStateId)
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return;
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 props = fst->Properties(kFstProperties, false);
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction final_action = mapper->FinalAction();
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId superfinal = kNoStateId;
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (final_action == MAP_REQUIRE_SUPERFINAL) {
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    superfinal = fst->AddState();
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    fst->SetFinal(superfinal, Weight::One());
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (StateId s = 0; s < fst->NumStates(); ++s) {
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (MutableArcIterator< MutableFst<A> > aiter(fst, s);
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson         !aiter.Done(); aiter.Next()) {
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      const A &arc = aiter.Value();
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      aiter.SetValue((*mapper)(arc));
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    switch (final_action) {
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_NO_SUPERFINAL:
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      default: {
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId));
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          FSTERROR() << "ArcMap: non-zero arc labels for superfinal arc";
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          fst->SetProperties(kError, kError);
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        fst->SetFinal(s, final_arc.weight);
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_ALLOW_SUPERFINAL: {
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (s != superfinal) {
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId));
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            // Add a superfinal state if not already done.
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            if (superfinal == kNoStateId) {
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              superfinal = fst->AddState();
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              fst->SetFinal(superfinal, Weight::One());
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            }
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            final_arc.nextstate = superfinal;
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            fst->AddArc(s, final_arc);
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            fst->SetFinal(s, Weight::Zero());
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          } else {
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            fst->SetFinal(s, final_arc.weight);
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_REQUIRE_SUPERFINAL: {
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (s != superfinal) {
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId));
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              final_arc.weight != Weight::Zero())
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            fst->AddArc(s, A(final_arc.ilabel, final_arc.olabel,
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                             final_arc.weight, superfinal));
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            fst->SetFinal(s, Weight::Zero());
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  fst->SetProperties(mapper->Properties(props), kFstProperties);
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Maps an arc type A using a mapper function object C, passed
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// by value.  This version modifies its Fst input.
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class A, class C>
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid ArcMap(MutableFst<A> *fst, C mapper) {
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMap(fst, &mapper);
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Maps an arc type A to an arc type B using mapper function
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// object C, passed by pointer. This version writes the mapped
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// input Fst to an output MutableFst.
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class A, class B, class C>
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid ArcMap(const Fst<A> &ifst, MutableFst<B> *ofst, C* mapper) {
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::StateId StateId;
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight Weight;
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ofst->DeleteStates();
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (mapper->InputSymbolsAction() == MAP_COPY_SYMBOLS)
207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->SetInputSymbols(ifst.InputSymbols());
208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (mapper->InputSymbolsAction() == MAP_CLEAR_SYMBOLS)
209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->SetInputSymbols(0);
210f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (mapper->OutputSymbolsAction() == MAP_COPY_SYMBOLS)
212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->SetOutputSymbols(ifst.OutputSymbols());
213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (mapper->OutputSymbolsAction() == MAP_CLEAR_SYMBOLS)
214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->SetOutputSymbols(0);
215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 iprops = ifst.Properties(kCopyProperties, false);
217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (ifst.Start() == kNoStateId) {
219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (iprops & kError) ofst->SetProperties(kError, kError);
220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return;
221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction final_action = mapper->FinalAction();
224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (ifst.Properties(kExpanded, false)) {
225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->ReserveStates(CountStates(ifst) +
226f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        final_action == MAP_NO_SUPERFINAL ? 0 : 1);
227f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
228f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
229f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Add all states.
230f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (StateIterator< Fst<A> > siter(ifst); !siter.Done(); siter.Next())
231f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->AddState();
232f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
233f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId superfinal = kNoStateId;
234f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (final_action == MAP_REQUIRE_SUPERFINAL) {
235f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    superfinal = ofst->AddState();
236f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->SetFinal(superfinal, B::Weight::One());
237f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
238f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (StateIterator< Fst<A> > siter(ifst); !siter.Done(); siter.Next()) {
239f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    StateId s = siter.Value();
240f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s == ifst.Start())
241f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      ofst->SetStart(s);
242f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
243f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ofst->ReserveArcs(s, ifst.NumArcs(s));
244f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (ArcIterator< Fst<A> > aiter(ifst, s); !aiter.Done(); aiter.Next())
245f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      ofst->AddArc(s, (*mapper)(aiter.Value()));
246f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
247f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    switch (final_action) {
248f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_NO_SUPERFINAL:
249f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      default: {
250f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId));
251f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
252f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          FSTERROR() << "ArcMap: non-zero arc labels for superfinal arc";
253f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->SetProperties(kError, kError);
254f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
255f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ofst->SetFinal(s, final_arc.weight);
256f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
257f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
258f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_ALLOW_SUPERFINAL: {
259f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId));
260f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
261f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            // Add a superfinal state if not already done.
262f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (superfinal == kNoStateId) {
263f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            superfinal = ofst->AddState();
264f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            ofst->SetFinal(superfinal, B::Weight::One());
265f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
266f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          final_arc.nextstate = superfinal;
267f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->AddArc(s, final_arc);
268f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->SetFinal(s, B::Weight::Zero());
269f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        } else {
270f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->SetFinal(s, final_arc.weight);
271f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
272f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
273f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
274f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_REQUIRE_SUPERFINAL: {
275f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId));
276f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
277f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            final_arc.weight != B::Weight::Zero())
278f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->AddArc(s, B(final_arc.ilabel, final_arc.olabel,
279f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                            final_arc.weight, superfinal));
280f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ofst->SetFinal(s, B::Weight::Zero());
281f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
282f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
283f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
284f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
285f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 oprops = ofst->Properties(kFstProperties, false);
286f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ofst->SetProperties(mapper->Properties(iprops) | oprops, kFstProperties);
287f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
288f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
289f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Maps an arc type A to an arc type B using mapper function
290f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// object C, passed by value. This version writes the mapped input
291f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Fst to an output MutableFst.
292f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class A, class B, class C>
293f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid ArcMap(const Fst<A> &ifst, MutableFst<B> *ofst, C mapper) {
294f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMap(ifst, ofst, &mapper);
295f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
296f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
297f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
298f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct ArcMapFstOptions : public CacheOptions {
299f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // ArcMapFst default caching behaviour is to do no caching. Most
300f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // mappers are cheap and therefore we save memory by not doing
301f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // caching.
302f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFstOptions() : CacheOptions(true, 0) {}
303f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFstOptions(const CacheOptions& opts) : CacheOptions(opts) {}
304f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
305f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
306f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
307f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B, class C> class ArcMapFst;
308f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
309f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Implementation of delayed ArcMapFst.
310f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B, class C>
311f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass ArcMapFstImpl : public CacheImpl<B> {
312f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
313f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FstImpl<B>::SetType;
314f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FstImpl<B>::SetProperties;
315f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FstImpl<B>::SetInputSymbols;
316f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FstImpl<B>::SetOutputSymbols;
317f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
318f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using VectorFstBaseImpl<typename CacheImpl<B>::State>::NumStates;
319f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
320f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::PushArc;
321f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::HasArcs;
322f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::HasFinal;
323f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::HasStart;
324f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::SetArcs;
325f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::SetFinal;
326f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using CacheImpl<B>::SetStart;
327f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
328f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  friend class StateIterator< ArcMapFst<A, B, C> >;
329f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
330f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef B Arc;
331f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename B::Weight Weight;
332f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename B::StateId StateId;
333f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
334f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFstImpl(const Fst<A> &fst, const C &mapper,
335f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                 const ArcMapFstOptions& opts)
336f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : CacheImpl<B>(opts),
337f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        fst_(fst.Copy()),
338f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        mapper_(new C(mapper)),
339f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        own_mapper_(true),
340f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        superfinal_(kNoStateId),
341f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        nstates_(0) {
342f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Init();
343f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
344f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
345f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFstImpl(const Fst<A> &fst, C *mapper,
346f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                 const ArcMapFstOptions& opts)
347f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : CacheImpl<B>(opts),
348f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        fst_(fst.Copy()),
349f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        mapper_(mapper),
350f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        own_mapper_(false),
351f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        superfinal_(kNoStateId),
352f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        nstates_(0) {
353f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Init();
354f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
355f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
356f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFstImpl(const ArcMapFstImpl<A, B, C> &impl)
357f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : CacheImpl<B>(impl),
358f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        fst_(impl.fst_->Copy(true)),
359f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        mapper_(new C(*impl.mapper_)),
360f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        own_mapper_(true),
361f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        superfinal_(kNoStateId),
362f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        nstates_(0) {
363f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Init();
364f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
365f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
366f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ~ArcMapFstImpl() {
367f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    delete fst_;
368f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (own_mapper_) delete mapper_;
369f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
370f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
371f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId Start() {
372f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasStart())
373f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetStart(FindOState(fst_->Start()));
374f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return CacheImpl<B>::Start();
375f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
376f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
377f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Weight Final(StateId s) {
378f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasFinal(s)) {
379f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      switch (final_action_) {
380f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case MAP_NO_SUPERFINAL:
381f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        default: {
382f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
383f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                        kNoStateId));
384f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
385f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            FSTERROR() << "ArcMapFst: non-zero arc labels for superfinal arc";
386f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            SetProperties(kError, kError);
387f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
388f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          SetFinal(s, final_arc.weight);
389f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
390f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
391f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case MAP_ALLOW_SUPERFINAL: {
392f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (s == superfinal_) {
393f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            SetFinal(s, Weight::One());
394f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          } else {
395f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
396f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                          kNoStateId));
397f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            if (final_arc.ilabel == 0 && final_arc.olabel == 0)
398f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              SetFinal(s, final_arc.weight);
399f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            else
400f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              SetFinal(s, Weight::Zero());
401f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
402f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
403f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
404f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case MAP_REQUIRE_SUPERFINAL: {
405f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          SetFinal(s, s == superfinal_ ? Weight::One() : Weight::Zero());
406f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
407f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
408f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
409f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
410f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return CacheImpl<B>::Final(s);
411f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
412f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
413f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t NumArcs(StateId s) {
414f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasArcs(s))
415f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Expand(s);
416f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return CacheImpl<B>::NumArcs(s);
417f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
418f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
419f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t NumInputEpsilons(StateId s) {
420f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasArcs(s))
421f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Expand(s);
422f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return CacheImpl<B>::NumInputEpsilons(s);
423f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
424f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
425f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t NumOutputEpsilons(StateId s) {
426f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasArcs(s))
427f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Expand(s);
428f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return CacheImpl<B>::NumOutputEpsilons(s);
429f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
430f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
431f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties() const { return Properties(kFstProperties); }
432f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
433f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Set error if found; return FST impl properties.
434f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 mask) const {
435f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if ((mask & kError) && (fst_->Properties(kError, false) ||
436f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                            (mapper_->Properties(0) & kError)))
437f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetProperties(kError, kError);
438f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return FstImpl<Arc>::Properties(mask);
439f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
440f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
441f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void InitArcIterator(StateId s, ArcIteratorData<B> *data) {
442f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasArcs(s))
443f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Expand(s);
444f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    CacheImpl<B>::InitArcIterator(s, data);
445f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
446f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
447f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Expand(StateId s) {
448f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Add exiting arcs.
449f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s == superfinal_) { SetArcs(s); return; }
450f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
451f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (ArcIterator< Fst<A> > aiter(*fst_, FindIState(s));
452f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson         !aiter.Done(); aiter.Next()) {
453f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      A aarc(aiter.Value());
454f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      aarc.nextstate = FindOState(aarc.nextstate);
455f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      const B& barc = (*mapper_)(aarc);
456f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      PushArc(s, barc);
457f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
458f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
459f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Check for superfinal arcs.
460f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!HasFinal(s) || Final(s) == Weight::Zero())
461f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      switch (final_action_) {
462f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case MAP_NO_SUPERFINAL:
463f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        default:
464f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
465f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case MAP_ALLOW_SUPERFINAL: {
466f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
467f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                        kNoStateId));
468f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
469f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            if (superfinal_ == kNoStateId)
470f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              superfinal_ = nstates_++;
471f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            final_arc.nextstate = superfinal_;
472f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            PushArc(s, final_arc);
473f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
474f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
475f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
476f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MAP_REQUIRE_SUPERFINAL: {
477f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
478f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      kNoStateId));
479f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
480f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            final_arc.weight != B::Weight::Zero())
481f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          PushArc(s, B(final_arc.ilabel, final_arc.olabel,
482f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                      final_arc.weight, superfinal_));
483f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
484f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
485f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
486f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SetArcs(s);
487f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
488f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
489f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
490f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Init() {
491f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SetType("map");
492f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
493f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (mapper_->InputSymbolsAction() == MAP_COPY_SYMBOLS)
494f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetInputSymbols(fst_->InputSymbols());
495f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (mapper_->InputSymbolsAction() == MAP_CLEAR_SYMBOLS)
496f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetInputSymbols(0);
497f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
498f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (mapper_->OutputSymbolsAction() == MAP_COPY_SYMBOLS)
499f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetOutputSymbols(fst_->OutputSymbols());
500f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (mapper_->OutputSymbolsAction() == MAP_CLEAR_SYMBOLS)
501f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetOutputSymbols(0);
502f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
503f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (fst_->Start() == kNoStateId) {
504f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      final_action_ = MAP_NO_SUPERFINAL;
505f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetProperties(kNullProperties);
506f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
507f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      final_action_ = mapper_->FinalAction();
508f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      uint64 props = fst_->Properties(kCopyProperties, false);
509f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      SetProperties(mapper_->Properties(props));
510f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (final_action_ == MAP_REQUIRE_SUPERFINAL)
511f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        superfinal_ = 0;
512f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
513f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
514f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
515f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Maps from output state to input state.
516f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId FindIState(StateId s) {
517f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (superfinal_ == kNoStateId || s < superfinal_)
518f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return s;
519f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
520f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return s - 1;
521f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
522f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
523f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Maps from input state to output state.
524f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId FindOState(StateId is) {
525f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    StateId os;
526f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (superfinal_ == kNoStateId || is < superfinal_)
527f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      os = is;
528f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
529f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      os = is + 1;
530f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
531f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (os >= nstates_)
532f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      nstates_ = os + 1;
533f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
534f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return os;
535f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
536f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
537f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
538f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Fst<A> *fst_;
539f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  C*   mapper_;
540f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool own_mapper_;
541f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction final_action_;
542f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
543f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId superfinal_;
544f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId nstates_;
545f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
546f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const ArcMapFstImpl<A, B, C> &);  // disallow
547f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
548f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
549f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
550f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Maps an arc type A to an arc type B using Mapper function object
551f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// C. This version is a delayed Fst.
552f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B, class C>
553f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass ArcMapFst : public ImplToFst< ArcMapFstImpl<A, B, C> > {
554f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
555f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  friend class ArcIterator< ArcMapFst<A, B, C> >;
556f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  friend class StateIterator< ArcMapFst<A, B, C> >;
557f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
558f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef B Arc;
559f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename B::Weight Weight;
560f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename B::StateId StateId;
561f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef CacheState<B> State;
562f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef ArcMapFstImpl<A, B, C> Impl;
563f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
564f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFst(const Fst<A> &fst, const C &mapper, const ArcMapFstOptions& opts)
565f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : ImplToFst<Impl>(new Impl(fst, mapper, opts)) {}
566f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
567f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFst(const Fst<A> &fst, C* mapper, const ArcMapFstOptions& opts)
568f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : ImplToFst<Impl>(new Impl(fst, mapper, opts)) {}
569f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
570f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFst(const Fst<A> &fst, const C &mapper)
571f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : ImplToFst<Impl>(new Impl(fst, mapper, ArcMapFstOptions())) {}
572f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
573f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFst(const Fst<A> &fst, C* mapper)
574f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : ImplToFst<Impl>(new Impl(fst, mapper, ArcMapFstOptions())) {}
575f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
576f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // See Fst<>::Copy() for doc.
577f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcMapFst(const ArcMapFst<A, B, C> &fst, bool safe = false)
578f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    : ImplToFst<Impl>(fst, safe) {}
579f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
580f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Get a copy of this ArcMapFst. See Fst<>::Copy() for further doc.
581f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual ArcMapFst<A, B, C> *Copy(bool safe = false) const {
582f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new ArcMapFst<A, B, C>(*this, safe);
583f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
584f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
585f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual inline void InitStateIterator(StateIteratorData<B> *data) const;
586f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
587f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void InitArcIterator(StateId s, ArcIteratorData<B> *data) const {
588f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    GetImpl()->InitArcIterator(s, data);
589f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
590f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
591f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
592f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Makes visible to friends.
593f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Impl *GetImpl() const { return ImplToFst<Impl>::GetImpl(); }
594f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
595f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const ArcMapFst<A, B, C> &fst);  // disallow
596f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
597f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
598f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
599f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Specialization for ArcMapFst.
600f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class A, class B, class C>
601f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass StateIterator< ArcMapFst<A, B, C> > : public StateIteratorBase<B> {
602f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
603f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename B::StateId StateId;
604f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
605f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  explicit StateIterator(const ArcMapFst<A, B, C> &fst)
606f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : impl_(fst.GetImpl()), siter_(*impl_->fst_), s_(0),
607f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        superfinal_(impl_->final_action_ == MAP_REQUIRE_SUPERFINAL)
608f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  { CheckSuperfinal(); }
609f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
610f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const { return siter_.Done() && !superfinal_; }
611f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
612f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId Value() const { return s_; }
613f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
614f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() {
615f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ++s_;
616f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!siter_.Done()) {
617f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      siter_.Next();
618f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      CheckSuperfinal();
619f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
620f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (superfinal_)
621f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      superfinal_ = false;
622f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
623f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
624f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Reset() {
625f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    s_ = 0;
626f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    siter_.Reset();
627f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    superfinal_ = impl_->final_action_ == MAP_REQUIRE_SUPERFINAL;
628f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    CheckSuperfinal();
629f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
630f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
631f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
632f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // This allows base-class virtual access to non-virtual derived-
633f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // class members of the same name. It makes the derived class more
634f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // efficient to use but unsafe to further derive.
635f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done_() const { return Done(); }
636f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId Value_() const { return Value(); }
637f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next_() { Next(); }
638f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Reset_() { Reset(); }
639f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
640f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void CheckSuperfinal() {
641f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (impl_->final_action_ != MAP_ALLOW_SUPERFINAL || superfinal_)
642f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return;
643f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!siter_.Done()) {
644f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      B final_arc = (*impl_->mapper_)(A(0, 0, impl_->fst_->Final(s_),
645f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                           kNoStateId));
646f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (final_arc.ilabel != 0 || final_arc.olabel != 0)
647f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        superfinal_ = true;
648f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
649f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
650f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
651f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const ArcMapFstImpl<A, B, C> *impl_;
652f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateIterator< Fst<A> > siter_;
653f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId s_;
654f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool superfinal_;    // true if there is a superfinal state and not done
655f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
656f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  DISALLOW_COPY_AND_ASSIGN(StateIterator);
657f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
658f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
659f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
660f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Specialization for ArcMapFst.
661f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B, class C>
662f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass ArcIterator< ArcMapFst<A, B, C> >
663f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    : public CacheArcIterator< ArcMapFst<A, B, C> > {
664f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
665f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::StateId StateId;
666f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
667f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcIterator(const ArcMapFst<A, B, C> &fst, StateId s)
668f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : CacheArcIterator< ArcMapFst<A, B, C> >(fst.GetImpl(), s) {
669f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!fst.GetImpl()->HasArcs(s))
670f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      fst.GetImpl()->Expand(s);
671f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
672f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
673f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
674f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  DISALLOW_COPY_AND_ASSIGN(ArcIterator);
675f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
676f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
677f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B, class C> inline
678f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid ArcMapFst<A, B, C>::InitStateIterator(StateIteratorData<B> *data)
679f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const {
680f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  data->base = new StateIterator< ArcMapFst<A, B, C> >(*this);
681f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
682f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
683f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
684f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
685f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Utility Mappers
686f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
687f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
688f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper that returns its input.
689f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A>
690f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct IdentityArcMapper {
691f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
692f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
693f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
694f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const A &arc) const { return arc; }
695f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
696f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
697f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
698f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
699f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
700f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
701f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
702f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const { return props; }
703f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
704f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
705f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
706f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper that returns its input with final states redirected to
707f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// a single super-final state.
708f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A>
709f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct SuperFinalMapper {
710f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
711f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
712f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
713f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const A &arc) const { return arc; }
714f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
715f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_REQUIRE_SUPERFINAL; }
716f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
717f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
718f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
719f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
720f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
721f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
722f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return props & kAddSuperFinalProperties;
723f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
724f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
725f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
726f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
727f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper that leaves labels and nextstate unchanged and constructs a new weight
728f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// from the underlying value of the arc weight.  Requires that there is a
729f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WeightConvert class specialization that converts the weights.
730f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B>
731f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass WeightConvertMapper {
732f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
733f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
734f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef B ToArc;
735f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename FromArc::Weight FromWeight;
736f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename ToArc::Weight ToWeight;
737f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
738f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ToArc operator()(const FromArc &arc) const {
739f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return ToArc(arc.ilabel, arc.olabel,
740f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                 convert_weight_(arc.weight), arc.nextstate);
741f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
742f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
743f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
744f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
745f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
746f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
747f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
748f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
749f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const { return props; }
750f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
751f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
752f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  WeightConvert<FromWeight, ToWeight> convert_weight_;
753f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
754f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
755f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Non-precision-changing weight conversions.
756f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Consider using more efficient Cast (fst.h) instead.
757f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef WeightConvertMapper<StdArc, LogArc> StdToLogMapper;
758f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef WeightConvertMapper<LogArc, StdArc> LogToStdMapper;
759f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
760f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Precision-changing weight conversions.
761f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef WeightConvertMapper<StdArc, Log64Arc> StdToLog64Mapper;
762f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef WeightConvertMapper<LogArc, Log64Arc> LogToLog64Mapper;
763f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef WeightConvertMapper<Log64Arc, StdArc> Log64ToStdMapper;
764f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef WeightConvertMapper<Log64Arc, LogArc> Log64ToLogMapper;
765f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
766f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper from A to GallicArc<A>.
767f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, StringType S = STRING_LEFT>
768f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct ToGallicMapper {
769f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
770f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef GallicArc<A, S> ToArc;
771f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
772f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef StringWeight<typename A::Label, S> SW;
773f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight AW;
774f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename GallicArc<A, S>::Weight GW;
775f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
776f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ToArc operator()(const A &arc) const {
777f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // 'Super-final' arc.
778f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.nextstate == kNoStateId && arc.weight != AW::Zero())
779f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return ToArc(0, 0, GW(SW::One(), arc.weight), kNoStateId);
780f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // 'Super-non-final' arc.
781f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (arc.nextstate == kNoStateId)
782f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return ToArc(0, 0, GW(SW::Zero(), arc.weight), kNoStateId);
783f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Epsilon label.
784f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (arc.olabel == 0)
785f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return ToArc(arc.ilabel, arc.ilabel,
786f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                   GW(SW::One(), arc.weight), arc.nextstate);
787f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Regular label.
788f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
789f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return ToArc(arc.ilabel, arc.ilabel,
790f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                   GW(SW(arc.olabel), arc.weight), arc.nextstate);
791f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
792f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
793f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
794f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
795f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
796f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
797f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_CLEAR_SYMBOLS;}
798f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
799f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
800f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return ProjectProperties(props, true) & kWeightInvariantProperties;
801f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
802f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
803f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
804f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
805f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper from GallicArc<A> to A.
806f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, StringType S = STRING_LEFT>
807f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct FromGallicMapper {
808f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef GallicArc<A, S> FromArc;
809f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
810f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
811f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Label Label;
812f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef StringWeight<Label, S> SW;
813f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight AW;
814f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename GallicArc<A, S>::Weight GW;
815f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
816f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  FromGallicMapper(Label superfinal_label = 0)
817f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : superfinal_label_(superfinal_label), error_(false) {}
818f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
819f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const FromArc &arc) const {
820f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // 'Super-non-final' arc.
821f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.nextstate == kNoStateId && arc.weight == GW::Zero())
822f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return A(arc.ilabel, 0, AW::Zero(), kNoStateId);
823f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
824f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SW w1 = arc.weight.Value1();
825f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    AW w2 = arc.weight.Value2();
826f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    StringWeightIterator<Label, S> iter1(w1);
827f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
828f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Label l = w1.Size() == 1 ? iter1.Value() : 0;
829f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
830f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (l == kStringInfinity || l == kStringBad ||
831f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        arc.ilabel != arc.olabel || w1.Size() > 1) {
832f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "FromGallicMapper: unrepesentable weight";
833f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
834f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
835f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
836f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.ilabel == 0 && l != 0 && arc.nextstate == kNoStateId)
837f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return A(superfinal_label_, l, w2, arc.nextstate);
838f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
839f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return A(arc.ilabel, l, w2, arc.nextstate);
840f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
841f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
842f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_ALLOW_SUPERFINAL; }
843f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
844f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
845f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
846f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_CLEAR_SYMBOLS;}
847f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
848f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 inprops) const {
849f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 outprops = inprops & kOLabelInvariantProperties &
850f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        kWeightInvariantProperties & kAddSuperFinalProperties;
851f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (error_)
852f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      outprops |= kError;
853f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops;
854f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
855f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
856f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
857f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label superfinal_label_;
858f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  mutable bool error_;
859f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
860f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
861f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
862f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper from GallicArc<A> to A.
863f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, StringType S = STRING_LEFT>
864f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct GallicToNewSymbolsMapper {
865f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef GallicArc<A, S> FromArc;
866f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
867f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
868f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::StateId StateId;
869f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Label Label;
870f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef StringWeight<Label, S> SW;
871f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight AW;
872f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename GallicArc<A, S>::Weight GW;
873f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
874f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  GallicToNewSymbolsMapper(MutableFst<ToArc> *fst)
875f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : fst_(fst), lmax_(0), osymbols_(fst->OutputSymbols()),
876f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        isymbols_(0), error_(false) {
877f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    fst_->DeleteStates();
878f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    state_ = fst_->AddState();
879f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    fst_->SetStart(state_);
880f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    fst_->SetFinal(state_, AW::One());
881f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (osymbols_) {
882f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      string name = osymbols_->Name() + "_from_gallic";
883f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      fst_->SetInputSymbols(new SymbolTable(name));
884f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      isymbols_ = fst_->MutableInputSymbols();
885f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      isymbols_->AddSymbol(osymbols_->Find((int64) 0), 0);
886f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
887f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      fst_->SetInputSymbols(0);
888f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
889f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
890f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
891f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const FromArc &arc) {
892f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // 'Super-non-final' arc.
893f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.nextstate == kNoStateId && arc.weight == GW::Zero())
894f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return A(arc.ilabel, 0, AW::Zero(), kNoStateId);
895f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
896f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SW w1 = arc.weight.Value1();
897f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    AW w2 = arc.weight.Value2();
898f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Label l;
899f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
900f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (w1.Size() == 0) {
901f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      l = 0;
902f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
903f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      typename Map::iterator miter = map_.find(w1);
904f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (miter != map_.end()) {
905f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        l = (*miter).second;
906f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else {
907f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        l = ++lmax_;
908f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        map_.insert(pair<const SW, Label>(w1, l));
909f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        StringWeightIterator<Label, S> iter1(w1);
910f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        StateId n;
911f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        string s;
912f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        for(size_t i = 0, p = state_;
913f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            i < w1.Size();
914f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            ++i, iter1.Next(), p = n) {
915f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          n = i == w1.Size() - 1 ? state_ : fst_->AddState();
916f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          fst_->AddArc(p, ToArc(i ? 0 : l, iter1.Value(), AW::One(), n));
917f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (isymbols_) {
918f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            if (i) s = s + "_";
919f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            s = s + osymbols_->Find(iter1.Value());
920f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
921f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
922f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (isymbols_)
923f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          isymbols_->AddSymbol(s, l);
924f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
925f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
926f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
927f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (l == kStringInfinity || l == kStringBad || arc.ilabel != arc.olabel) {
928f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "GallicToNewSymbolMapper: unrepesentable weight";
929f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
930f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
931f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
932f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return A(arc.ilabel, l, w2, arc.nextstate);
933f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
934f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
935f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_ALLOW_SUPERFINAL; }
936f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
937f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
938f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
939f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_CLEAR_SYMBOLS; }
940f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
941f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 inprops) const {
942f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 outprops = inprops & kOLabelInvariantProperties &
943f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        kWeightInvariantProperties & kAddSuperFinalProperties;
944f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (error_)
945f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      outprops |= kError;
946f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops;
947f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
948f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
949f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
950f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  class StringKey {
951f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson   public:
952f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size_t operator()(const SW &x) const {
953f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return x.Hash();
954f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
955f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  };
956f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
957f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef unordered_map<SW, Label, StringKey> Map;
958f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
959f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MutableFst<ToArc> *fst_;
960f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Map map_;
961f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label lmax_;
962f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId state_;
963f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const SymbolTable *osymbols_;
964f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SymbolTable *isymbols_;
965f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  mutable bool error_;
966f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
967f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  DISALLOW_COPY_AND_ASSIGN(GallicToNewSymbolsMapper);
968f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
969f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
970f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
971f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper to add a constant to all weights.
972f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A>
973f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct PlusMapper {
974f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
975f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
976f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight Weight;
977f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
978f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  explicit PlusMapper(Weight w) : weight_(w) {}
979f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
980f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const A &arc) const {
981f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.weight == Weight::Zero())
982f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return arc;
983f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Weight w = Plus(arc.weight, weight_);
984f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return A(arc.ilabel, arc.olabel, w, arc.nextstate);
985f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
986f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
987f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
988f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
989f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
990f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
991f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
992f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
993f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
994f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return props & kWeightInvariantProperties;
995f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
996f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
997f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
998f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
999f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1000f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1001f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Weight weight_;
1002f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1003f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1004f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1005f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper to (right) multiply a constant to all weights.
1006f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A>
1007f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct TimesMapper {
1008f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
1009f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
1010f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight Weight;
1011f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1012f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  explicit TimesMapper(Weight w) : weight_(w) {}
1013f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1014f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const A &arc) const {
1015f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.weight == Weight::Zero())
1016f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return arc;
1017f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Weight w = Times(arc.weight, weight_);
1018f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return A(arc.ilabel, arc.olabel, w, arc.nextstate);
1019f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1020f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1021f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
1022f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1023f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
1024f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1025f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
1026f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1027f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
1028f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return props & kWeightInvariantProperties;
1029f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1030f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1031f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
1032f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Weight weight_;
1033f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1034f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1035f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1036f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper to reciprocate all non-Zero() weights.
1037f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A>
1038f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct InvertWeightMapper {
1039f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
1040f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A ToArc;
1041f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight Weight;
1042f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1043f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  A operator()(const A &arc) const {
1044f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (arc.weight == Weight::Zero())
1045f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return arc;
1046f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Weight w = Divide(Weight::One(), arc.weight);
1047f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return A(arc.ilabel, arc.olabel, w, arc.nextstate);
1048f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1049f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1050f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
1051f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1052f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
1053f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1054f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
1055f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1056f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
1057f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return props & kWeightInvariantProperties;
1058f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1059f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1060f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1061f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1062f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper to map all non-Zero() weights to One().
1063f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B = A>
1064f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct RmWeightMapper {
1065f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
1066f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef B ToArc;
1067f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename FromArc::Weight FromWeight;
1068f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename ToArc::Weight ToWeight;
1069f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1070f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  B operator()(const A &arc) const {
1071f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ToWeight w = arc.weight != FromWeight::Zero() ?
1072f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                   ToWeight::One() : ToWeight::Zero();
1073f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return B(arc.ilabel, arc.olabel, w, arc.nextstate);
1074f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1075f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1076f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
1077f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1078f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
1079f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1080f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
1081f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1082f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
1083f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return (props & kWeightInvariantProperties) | kUnweighted;
1084f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1085f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1086f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1087f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1088f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper to quantize all weights.
1089f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B = A>
1090f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct QuantizeMapper {
1091f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
1092f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef B ToArc;
1093f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename FromArc::Weight FromWeight;
1094f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename ToArc::Weight ToWeight;
1095f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1096f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  QuantizeMapper() : delta_(kDelta) {}
1097f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1098f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  explicit QuantizeMapper(float d) : delta_(d) {}
1099f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  B operator()(const A &arc) const {
1101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ToWeight w = arc.weight.Quantize(delta_);
1102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return B(arc.ilabel, arc.olabel, w, arc.nextstate);
1103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
1106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
1108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
1110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const {
1112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return props & kWeightInvariantProperties;
1113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
1116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  float delta_;
1117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Mapper from A to B under the assumption:
1121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//    B::Weight = A::Weight::ReverseWeight
1122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//    B::Label == A::Label
1123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//    B::StateId == A::StateId
1124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The weight is reversed, while the label and nextstate preserved
1125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// in the mapping.
1126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A, class B>
1127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct ReverseWeightMapper {
1128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A FromArc;
1129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef B ToArc;
1130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  B operator()(const A &arc) const {
1132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return B(arc.ilabel, arc.olabel, arc.weight.Reverse(), arc.nextstate);
1133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
1136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
1138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;}
1140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const { return props; }
1142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
1145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_ARC_MAP_H__
1147