1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. 5 * 6 * The contents of this file are subject to the terms of either the GNU Lesser 7 * General Public License Version 2.1 only ("LGPL") or the Common Development and 8 * Distribution License ("CDDL")(collectively, the "License"). You may not use this 9 * file except in compliance with the License. You can obtain a copy of the CDDL at 10 * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at 11 * http://www.opensource.org/licenses/lgpl-license.php. See the License for the 12 * specific language governing permissions and limitations under the License. When 13 * distributing the software, include this License Header Notice in each file and 14 * include the full text of the License in the License file as well as the 15 * following notice: 16 * 17 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 18 * (CDDL) 19 * For Covered Software in this distribution, this License shall be governed by the 20 * laws of the State of California (excluding conflict-of-law provisions). 21 * Any litigation relating to this License shall be subject to the jurisdiction of 22 * the Federal Courts of the Northern District of California and the state courts 23 * of the State of California, with venue lying in Santa Clara County, California. 24 * 25 * Contributor(s): 26 * 27 * If you wish your version of this file to be governed by only the CDDL or only 28 * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to 29 * include this software in this distribution under the [CDDL or LGPL Version 2.1] 30 * license." If you don't indicate a single choice of license, a recipient has the 31 * option to distribute your version of this file under either the CDDL or the LGPL 32 * Version 2.1, or to extend the choice of license to its licensees as provided 33 * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL 34 * Version 2 license, then the option applies only if the new code is made subject 35 * to such option by the copyright holder. 36 */ 37 38 #ifndef SUNPY_LATTICE_STATES_H 39 #define SUNPY_LATTICE_STATES_H 40 41 #include "portability.h" 42 43 #include "imi_context.h" 44 45 /** 46 * CStateKey represent the history. In real implementation, it's a 47 * node pointer to a state in the language model. But to save the 48 * language model size, the state node in language model do not 49 * thread the back-off pointer. Now, we just use the Word Id for 50 * the node in the language model. Later we should abstract the 51 * StateNode from language model implemetation to replace this 52 * definition. 53 */ 54 typedef CThreadSlm::TState CStateKey; 55 56 /** 57 * A WordKey could represent a word. Define this use the unsigned int 58 * directly. Because in the future, we may adopt word class, such as 59 * Digital Word Class. 60 */ 61 typedef unsigned CWordKey; 62 63 /** 64 * This class is used to record lexicon state (pinyin trie nodes) 65 * just before a bone. From the bone, it could see when arriving 66 * it, how many valid Pinyin Trie Node still could be used to search 67 * more words further, and what bone is its starting bone. 68 */ 69 struct CLexiconState { 70 public: 71 /** 72 * The bone where m_pPYNode starts 73 */ 74 CSkeletonIter m_BoneStart; 75 76 /** 77 * PinYin trie node, from which we could get its corresponding 78 * words (if it contains some), and search further for longer 79 * words. 80 */ 81 const CPinyinTrie::TNode *m_pPYNode; 82 83 /** 84 * If is not a PINYIN state, we should use the m_WordId directly. 85 */ 86 bool m_bPinyin; 87 88 /** 89 * the word id for normal string, like english string, punc, etc. 90 */ 91 unsigned int m_WordId; 92 93 public: 94 CLexiconState(const CLexiconState& b) 95 : m_BoneStart(b.m_BoneStart), m_pPYNode(b.m_pPYNode), 96 m_bPinyin(b.m_bPinyin), m_WordId(b.m_WordId) { } 97 98 CLexiconState(CSkeletonIter boneStart = CSkeletonIter(), 99 const CPinyinTrie::TNode *pynptr = NULL) 100 : m_BoneStart(boneStart), m_pPYNode(pynptr), 101 m_bPinyin(true), m_WordId(0) { } 102 103 CLexiconState(CSkeletonIter boneStart, unsigned int wid) 104 : m_BoneStart(boneStart), m_pPYNode(NULL), 105 m_bPinyin(false), m_WordId(wid) { } 106 }; 107 108 /** 109 * A list of Lexicon State. Every state may from different 110 * starting position. Later, when Fuzzy PinYin are added, 111 * more than one state may comes from one starting bone. 112 */ 113 typedef std::vector<CLexiconState> CLexiconStates; 114 115 116 /** 117 * The basic static unit used in the lattice searching 118 */ 119 struct TLatticeState { 120 public: 121 122 /** 123 * The score from the beginning of the sentence to here 124 * pr(w1)*pr(w2|w1)*... or its log format 125 */ 126 TSentenceScore m_Score; 127 128 /** 129 * The bone right after this lattice node. 130 */ 131 CSkeletonIter m_BoneAfter; 132 133 /** 134 * The history key 135 */ 136 CStateKey m_State; 137 138 /** 139 * prevState --- word ---> thisState 140 * BackTraceNode record the best prevState that make thisState 141 * best score. 142 */ 143 TLatticeState *m_pBackTraceNode; 144 145 /** 146 * BackTraceWordId record the best word's id that make thisState 147 * best score 148 */ 149 CWordKey m_BackTraceWordId; 150 151 /** for debug printing... */ 152 void 153 print(std::string& prefix); 154 155 public: 156 /** 157 * Default constructor 158 */ 159 #ifdef _USE_RAW_PROBABILITY 160 TLatticeState(double score = -1.0, 161 #else 162 TLatticeState(double score = 0.0, 163 #endif 164 CSkeletonIter bone=CSkeletonIter(), 165 TLatticeState* btNodePtr = NULL, 166 CStateKey sk= CStateKey(), 167 CWordKey wk = CWordKey()) 168 : m_Score(score), m_BoneAfter(bone), m_State(sk), 169 m_pBackTraceNode(btNodePtr), m_BackTraceWordId(wk) { } 170 171 }; 172 173 typedef std::vector<TLatticeState> CLatticeStateVec; 174 175 176 /** 177 * All lattice node before a single bone. This class provide beam pruning 178 * while push_back, which means at most the best MAX states are reserved, 179 * ie, weak state will may be discard while new better state are inserted, 180 * and the number MAX is arrived. 181 */ 182 class CLatticeStates { 183 private: 184 static const unsigned beam_width = 32; 185 186 public: 187 /** just use the CLatticeStateVec's iterator */ 188 typedef CLatticeStateVec::iterator iterator; 189 190 /** just use the CLatticeStateVec's iterator */ 191 typedef CLatticeStateVec::const_iterator const_iterator; 192 193 public: 194 void 195 clear(); 196 197 void 198 push_back(const TLatticeState& node); 199 200 //@{ 201 /** return the first iterator of m_Vec. */ 202 size_t 203 size() 204 { return m_Vec.size(); } 205 206 iterator 207 begin() 208 { return m_Vec.begin(); } 209 210 /** return the first iterator of m_Vec. */ 211 const_iterator 212 begin() const 213 { return m_Vec.begin(); } 214 //@} 215 216 217 //@{ 218 /** return the last iterator of m_Vec. */ 219 iterator 220 end() 221 { return m_Vec.end(); } 222 223 /** return the last iterator of m_Vec. */ 224 const_iterator 225 end() const 226 { return m_Vec.end(); } 227 //@} 228 229 230 protected: 231 void 232 bubbleUp(int idxInHeap); 233 234 void 235 ironDown(int idxInHeap); 236 237 protected: 238 std::vector<TLatticeState> m_Vec; 239 std::vector<int> m_VecIdxInHeap; 240 std::map<CStateKey, int> m_Map; 241 std::vector<int> m_Heap; 242 }; 243 244 245 /** 246 * Bone Inner Data is used to construct the search lattice. Logically, 247 * each bone just like the time fram as in the speech recoginition. 248 * Many information when searching arrived right before the bone are needed. 249 * - The Pinyin Trie States start from previous bones, and not terminated 250 * yet. From these states, we could look further to find longer words. 251 * - All Lattice State (which is already after beam-pruning). They are 252 * basic units of the Lattice. 253 * Any other information also needed to help the interaction with user: 254 * - Best word start righ from the bone. A best word in the best 255 * sentence is an edge of the best path. 256 * - Best word type. 257 * -# Whether there is a best word start right before the bone? Best 258 * words are not overlaped and many bones may contains no best word. 259 * -# Whether the best word is user-selected. Some best word is user 260 * selected, and may be really diffirent with what we found according 261 * to Language Model. 262 */ 263 class CBoneInnerData { 264 public: 265 /** values used by m_BWType to reflect the m_BestWord status */ 266 enum { 267 NoBestWordStartHere, /**< best word not start here. m_bestWod invalid.*/ 268 BestWordStartHere, /**< m_BestWord is valid, but not user selected.*/ 269 UserSelectedBestWord /**< m_BestWord is the user selected best word.*/ 270 }; 271 272 /** 273 * The best word start from here. A best word in the best sentence is 274 * an edge of the best path. 275 */ 276 CCandidate m_BestWord; 277 278 /** 279 * m_BWType reflects the m_BestWord status: 280 * -# Is there a best word start here? 281 * -# Whether or not it is user selected? 282 */ 283 int m_BWType; 284 285 /** 286 * Lexicon status list just before this bone. 287 */ 288 CLexiconStates m_LexiconStates; 289 290 /** 291 * Lattice status list just before this bone. 292 */ 293 CLatticeStates m_LatticeNodes; 294 295 public: 296 CBoneInnerData() 297 : m_BestWord(), m_BWType(NoBestWordStartHere), 298 m_LexiconStates(), m_LatticeNodes() { } 299 /** 300 * clear LatticeNodes and LexiconStates, 301 * set the BWType to NoBestWordStartHere. 302 */ 303 void 304 clear() 305 { 306 m_BWType = NoBestWordStartHere; 307 m_LatticeNodes.clear(); 308 m_LexiconStates.clear(); 309 } 310 311 void 312 print(std::string& prefix); 313 }; 314 315 316 #endif 317