1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LATINIME_TYPING_TRAVERSAL_H 18 #define LATINIME_TYPING_TRAVERSAL_H 19 20 #include <cstdint> 21 22 #include "defines.h" 23 #include "suggest/core/dicnode/dic_node.h" 24 #include "suggest/core/dicnode/dic_node_vector.h" 25 #include "suggest/core/layout/proximity_info_state.h" 26 #include "suggest/core/layout/proximity_info_utils.h" 27 #include "suggest/core/policy/traversal.h" 28 #include "suggest/core/session/dic_traverse_session.h" 29 #include "suggest/policyimpl/typing/scoring_params.h" 30 #include "utils/char_utils.h" 31 32 namespace latinime { 33 class TypingTraversal : public Traversal { 34 public: 35 static const TypingTraversal *getInstance() { return &sInstance; } 36 37 AK_FORCE_INLINE int getMaxPointerCount() const { 38 return MAX_POINTER_COUNT; 39 } 40 41 AK_FORCE_INLINE bool allowsErrorCorrections(const DicNode *const dicNode) const { 42 return dicNode->getNormalizedSpatialDistance() 43 < ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT; 44 } 45 46 AK_FORCE_INLINE bool isOmission(const DicTraverseSession *const traverseSession, 47 const DicNode *const dicNode, const DicNode *const childDicNode, 48 const bool allowsErrorCorrections) const { 49 if (!CORRECT_OMISSION) { 50 return false; 51 } 52 // Note: Always consider intentional omissions (like apostrophes) since they are common. 53 const bool canConsiderOmission = 54 allowsErrorCorrections || childDicNode->canBeIntentionalOmission(); 55 if (!canConsiderOmission) { 56 return false; 57 } 58 const int inputSize = traverseSession->getInputSize(); 59 // TODO: Don't refer to isCompletion? 60 if (dicNode->isCompletion(inputSize)) { 61 return false; 62 } 63 if (dicNode->canBeIntentionalOmission()) { 64 return true; 65 } 66 const int point0Index = dicNode->getInputIndex(0); 67 const int currentBaseLowerCodePoint = 68 CharUtils::toBaseLowerCase(childDicNode->getNodeCodePoint()); 69 const int typedBaseLowerCodePoint = 70 CharUtils::toBaseLowerCase(traverseSession->getProximityInfoState(0) 71 ->getPrimaryCodePointAt(point0Index)); 72 return (currentBaseLowerCodePoint != typedBaseLowerCodePoint); 73 } 74 75 AK_FORCE_INLINE bool isSpaceSubstitutionTerminal( 76 const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const { 77 if (!CORRECT_NEW_WORD_SPACE_SUBSTITUTION) { 78 return false; 79 } 80 if (!canDoLookAheadCorrection(traverseSession, dicNode)) { 81 return false; 82 } 83 const int point0Index = dicNode->getInputIndex(0); 84 return dicNode->isTerminalDicNode() 85 && traverseSession->getProximityInfoState(0)-> 86 hasSpaceProximity(point0Index); 87 } 88 89 AK_FORCE_INLINE bool isSpaceOmissionTerminal( 90 const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const { 91 if (!CORRECT_NEW_WORD_SPACE_OMISSION) { 92 return false; 93 } 94 const int inputSize = traverseSession->getInputSize(); 95 // TODO: Don't refer to isCompletion? 96 if (dicNode->isCompletion(inputSize)) { 97 return false; 98 } 99 if (!dicNode->isTerminalDicNode()) { 100 return false; 101 } 102 const int16_t pointIndex = dicNode->getInputIndex(0); 103 return pointIndex <= inputSize && !dicNode->isTotalInputSizeExceedingLimit() 104 && !dicNode->shouldBeFilteredBySafetyNetForBigram(); 105 } 106 107 AK_FORCE_INLINE bool shouldDepthLevelCache( 108 const DicTraverseSession *const traverseSession) const { 109 const int inputSize = traverseSession->getInputSize(); 110 return traverseSession->isCacheBorderForTyping(inputSize); 111 } 112 113 AK_FORCE_INLINE bool shouldNodeLevelCache( 114 const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const { 115 return false; 116 } 117 118 AK_FORCE_INLINE bool canDoLookAheadCorrection( 119 const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const { 120 const int inputSize = traverseSession->getInputSize(); 121 return dicNode->canDoLookAheadCorrection(inputSize); 122 } 123 124 AK_FORCE_INLINE ProximityType getProximityType( 125 const DicTraverseSession *const traverseSession, const DicNode *const dicNode, 126 const DicNode *const childDicNode) const { 127 return traverseSession->getProximityInfoState(0)->getProximityType( 128 dicNode->getInputIndex(0), childDicNode->getNodeCodePoint(), 129 true /* checkProximityChars */); 130 } 131 132 AK_FORCE_INLINE bool needsToTraverseAllUserInput() const { 133 return true; 134 } 135 136 AK_FORCE_INLINE float getMaxSpatialDistance() const { 137 return ScoringParams::MAX_SPATIAL_DISTANCE; 138 } 139 140 AK_FORCE_INLINE int getDefaultExpandDicNodeSize() const { 141 return DicNodeVector::DEFAULT_NODES_SIZE_FOR_OPTIMIZATION; 142 } 143 144 AK_FORCE_INLINE int getMaxCacheSize(const int inputSize) const { 145 return (inputSize <= 1) ? ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT 146 : ScoringParams::MAX_CACHE_DIC_NODE_SIZE; 147 } 148 149 AK_FORCE_INLINE int getTerminalCacheSize() const { 150 return MAX_RESULTS; 151 } 152 153 AK_FORCE_INLINE bool isPossibleOmissionChildNode( 154 const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode, 155 const DicNode *const dicNode) const { 156 const ProximityType proximityType = 157 getProximityType(traverseSession, parentDicNode, dicNode); 158 if (!ProximityInfoUtils::isMatchOrProximityChar(proximityType)) { 159 return false; 160 } 161 return true; 162 } 163 164 AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode) const { 165 const int probability = dicNode->getProbability(); 166 if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) { 167 return false; 168 } 169 const bool shortCappedWord = dicNode->getNodeCodePointCount() 170 < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && dicNode->isFirstCharUppercase(); 171 return !shortCappedWord 172 || probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED; 173 } 174 175 private: 176 DISALLOW_COPY_AND_ASSIGN(TypingTraversal); 177 static const bool CORRECT_OMISSION; 178 static const bool CORRECT_NEW_WORD_SPACE_SUBSTITUTION; 179 static const bool CORRECT_NEW_WORD_SPACE_OMISSION; 180 static const TypingTraversal sInstance; 181 182 TypingTraversal() {} 183 ~TypingTraversal() {} 184 }; 185 } // namespace latinime 186 #endif // LATINIME_TYPING_TRAVERSAL_H 187