Merge "Move typing policy to AOSP"
commit
d2a04e1e79
|
@ -31,7 +31,8 @@ LOCAL_C_INCLUDES += \
|
|||
$(LATIN_IME_SRC_FULLPATH_DIR)/suggest \
|
||||
$(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/dicnode \
|
||||
$(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/policy \
|
||||
$(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/session
|
||||
$(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/session \
|
||||
$(LATIN_IME_SRC_FULLPATH_DIR)/suggest/policyimpl/typing
|
||||
|
||||
LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-align \
|
||||
-Wwrite-strings -Wfloat-equal -Wpointer-arith -Winit-self -Wredundant-decls -Wno-system-headers
|
||||
|
@ -69,6 +70,10 @@ LATIN_IME_CORE_SRC_FILES := \
|
|||
suggest/core/dicnode/dic_node_utils.cpp \
|
||||
suggest/core/policy/weighting.cpp \
|
||||
suggest/core/session/dic_traverse_session.cpp \
|
||||
suggest/policyimpl/typing/scoring_params.cpp \
|
||||
suggest/policyimpl/typing/typing_scoring.cpp \
|
||||
suggest/policyimpl/typing/typing_traversal.cpp \
|
||||
suggest/policyimpl/typing/typing_weighting.cpp \
|
||||
suggest/gesture_suggest.cpp \
|
||||
suggest/typing_suggest.cpp
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "scoring_params.h"
|
||||
|
||||
namespace latinime {
|
||||
// TODO: RENAME all
|
||||
const float ScoringParams::MAX_SPATIAL_DISTANCE = 1.0f;
|
||||
const int ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY = 40;
|
||||
const int ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED = 120;
|
||||
const float ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD = 1.0f;
|
||||
const int ScoringParams::MAX_CACHE_DIC_NODE_SIZE = 125;
|
||||
const int ScoringParams::THRESHOLD_SHORT_WORD_LENGTH = 4;
|
||||
|
||||
const float ScoringParams::DISTANCE_WEIGHT_LENGTH = 0.132f;
|
||||
const float ScoringParams::PROXIMITY_COST = 0.086f;
|
||||
const float ScoringParams::FIRST_PROXIMITY_COST = 0.104f;
|
||||
const float ScoringParams::OMISSION_COST = 0.388f;
|
||||
const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.431f;
|
||||
const float ScoringParams::OMISSION_COST_FIRST_CHAR = 0.532f;
|
||||
const float ScoringParams::INSERTION_COST = 0.670f;
|
||||
const float ScoringParams::INSERTION_COST_SAME_CHAR = 0.526f;
|
||||
const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.563f;
|
||||
const float ScoringParams::TRANSPOSITION_COST = 0.494f;
|
||||
const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.239f;
|
||||
const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.380f;
|
||||
const float ScoringParams::SUBSTITUTION_COST = 0.363f;
|
||||
const float ScoringParams::COST_NEW_WORD = 0.054f;
|
||||
const float ScoringParams::COST_NEW_WORD_CAPITALIZED = 0.174f;
|
||||
const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.123f;
|
||||
const float ScoringParams::COST_FIRST_LOOKAHEAD = 0.462f;
|
||||
const float ScoringParams::COST_LOOKAHEAD = 0.092f;
|
||||
const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.126f;
|
||||
const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.056f;
|
||||
const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.136f;
|
||||
const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f;
|
||||
const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f;
|
||||
const float ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT = 0.1f;
|
||||
} // namespace latinime
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LATINIME_SCORING_PARAMS_H
|
||||
#define LATINIME_SCORING_PARAMS_H
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
class ScoringParams {
|
||||
public:
|
||||
// Fixed model parameters
|
||||
static const float MAX_SPATIAL_DISTANCE;
|
||||
static const int THRESHOLD_NEXT_WORD_PROBABILITY;
|
||||
static const int THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
|
||||
static const float AUTOCORRECT_OUTPUT_THRESHOLD;
|
||||
static const int MAX_CACHE_DIC_NODE_SIZE;
|
||||
static const int THRESHOLD_SHORT_WORD_LENGTH;
|
||||
|
||||
// Numerically optimized parameters (currently for tap typing only).
|
||||
// TODO: add ability to modify these constants programmatically.
|
||||
// TODO: explore optimization of gesture parameters.
|
||||
static const float DISTANCE_WEIGHT_LENGTH;
|
||||
static const float PROXIMITY_COST;
|
||||
static const float FIRST_PROXIMITY_COST;
|
||||
static const float OMISSION_COST;
|
||||
static const float OMISSION_COST_SAME_CHAR;
|
||||
static const float OMISSION_COST_FIRST_CHAR;
|
||||
static const float INSERTION_COST;
|
||||
static const float INSERTION_COST_SAME_CHAR;
|
||||
static const float INSERTION_COST_FIRST_CHAR;
|
||||
static const float TRANSPOSITION_COST;
|
||||
static const float SPACE_SUBSTITUTION_COST;
|
||||
static const float ADDITIONAL_PROXIMITY_COST;
|
||||
static const float SUBSTITUTION_COST;
|
||||
static const float COST_NEW_WORD;
|
||||
static const float COST_NEW_WORD_CAPITALIZED;
|
||||
static const float DISTANCE_WEIGHT_LANGUAGE;
|
||||
static const float COST_FIRST_LOOKAHEAD;
|
||||
static const float COST_LOOKAHEAD;
|
||||
static const float HAS_PROXIMITY_TERMINAL_COST;
|
||||
static const float HAS_EDIT_CORRECTION_TERMINAL_COST;
|
||||
static const float HAS_MULTI_WORD_TERMINAL_COST;
|
||||
static const float TYPING_BASE_OUTPUT_SCORE;
|
||||
static const float TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
|
||||
static const float MAX_NORM_DISTANCE_FOR_EDIT;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ScoringParams);
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_SCORING_PARAMS_H
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "typing_scoring.h"
|
||||
|
||||
namespace latinime {
|
||||
const TypingScoring TypingScoring::sInstance;
|
||||
} // namespace latinime
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LATINIME_TYPING_SCORING_H
|
||||
#define LATINIME_TYPING_SCORING_H
|
||||
|
||||
#include "defines.h"
|
||||
#include "scoring.h"
|
||||
#include "scoring_params.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
class DicNode;
|
||||
class DicTraverseSession;
|
||||
|
||||
class TypingScoring : public Scoring {
|
||||
public:
|
||||
static const TypingScoring *getInstance() { return &sInstance; }
|
||||
|
||||
AK_FORCE_INLINE bool getMostProbableString(
|
||||
const DicTraverseSession *const traverseSession, const int terminalSize,
|
||||
const float languageWeight, int *const outputCodePoints, int *const type,
|
||||
int *const freq) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE void safetyNetForMostProbableString(const int terminalSize,
|
||||
const int maxScore, int *const outputCodePoints, int *const frequencies) const {
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE void searchWordWithDoubleLetter(DicNode *terminals,
|
||||
const int terminalSize, int *doubleLetterTerminalIndex,
|
||||
DoubleLetterLevel *doubleLetterLevel) const {
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
|
||||
DicNode *const terminals, const int size) const {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE int calculateFinalScore(const float compoundDistance,
|
||||
const int inputSize, const bool forceCommit) const {
|
||||
const float maxDistance = ScoringParams::DISTANCE_WEIGHT_LANGUAGE
|
||||
+ static_cast<float>(inputSize) * ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
|
||||
return static_cast<int>((ScoringParams::TYPING_BASE_OUTPUT_SCORE
|
||||
- (compoundDistance / maxDistance)
|
||||
+ (forceCommit ? ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD : 0.0f))
|
||||
* SUGGEST_INTERFACE_OUTPUT_SCALE);
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE float getDoubleLetterDemotionDistanceCost(const int terminalIndex,
|
||||
const int doubleLetterTerminalIndex,
|
||||
const DoubleLetterLevel doubleLetterLevel) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool doesAutoCorrectValidWord() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TypingScoring);
|
||||
static const TypingScoring sInstance;
|
||||
|
||||
TypingScoring() {}
|
||||
~TypingScoring() {}
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_TYPING_SCORING_H
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LATINIME_TYPING_SUGGEST_POLICY_H
|
||||
#define LATINIME_TYPING_SUGGEST_POLICY_H
|
||||
|
||||
#include "defines.h"
|
||||
#include "suggest_policy.h"
|
||||
#include "typing_scoring.h"
|
||||
#include "typing_traversal.h"
|
||||
#include "typing_weighting.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
class Scoring;
|
||||
class Traversal;
|
||||
class Weighting;
|
||||
|
||||
class TypingSuggestPolicy : public SuggestPolicy {
|
||||
public:
|
||||
TypingSuggestPolicy() {}
|
||||
virtual ~TypingSuggestPolicy() {}
|
||||
AK_FORCE_INLINE const Traversal *getTraversal() const {
|
||||
return TypingTraversal::getInstance();
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE const Scoring *getScoring() const {
|
||||
return TypingScoring::getInstance();
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE const Weighting *getWeighting() const {
|
||||
return TypingWeighting::getInstance();
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TypingSuggestPolicy);
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_TYPING_SUGGEST_POLICY_H
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "typing_traversal.h"
|
||||
|
||||
namespace latinime {
|
||||
const bool TypingTraversal::CORRECT_OMISSION = true;
|
||||
const bool TypingTraversal::CORRECT_SPACE_SUBSTITUTION = true;
|
||||
const bool TypingTraversal::CORRECT_SPACE_OMISSION = true;
|
||||
const TypingTraversal TypingTraversal::sInstance;
|
||||
} // namespace latinime
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LATINIME_TYPING_TRAVERSAL_H
|
||||
#define LATINIME_TYPING_TRAVERSAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "char_utils.h"
|
||||
#include "defines.h"
|
||||
#include "dic_node.h"
|
||||
#include "dic_node_vector.h"
|
||||
#include "dic_traverse_session.h"
|
||||
#include "proximity_info_state.h"
|
||||
#include "scoring_params.h"
|
||||
#include "traversal.h"
|
||||
|
||||
namespace latinime {
|
||||
class TypingTraversal : public Traversal {
|
||||
public:
|
||||
static const TypingTraversal *getInstance() { return &sInstance; }
|
||||
|
||||
AK_FORCE_INLINE int getMaxPointerCount() const {
|
||||
return MAX_POINTER_COUNT;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool allowsErrorCorrections(const DicNode *const dicNode) const {
|
||||
return dicNode->getNormalizedSpatialDistance()
|
||||
< ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool isOmission(const DicTraverseSession *const traverseSession,
|
||||
const DicNode *const dicNode, const DicNode *const childDicNode) const {
|
||||
if (!CORRECT_OMISSION) {
|
||||
return false;
|
||||
}
|
||||
const int inputSize = traverseSession->getInputSize();
|
||||
// TODO: Don't refer to isCompletion?
|
||||
if (dicNode->isCompletion(inputSize)) {
|
||||
return false;
|
||||
}
|
||||
if (dicNode->canBeIntentionalOmission()) {
|
||||
return true;
|
||||
}
|
||||
const int point0Index = dicNode->getInputIndex(0);
|
||||
const int currentBaseLowerCodePoint =
|
||||
toBaseLowerCase(childDicNode->getNodeCodePoint());
|
||||
const int typedBaseLowerCodePoint =
|
||||
toBaseLowerCase(traverseSession->getProximityInfoState(0)
|
||||
->getPrimaryCodePointAt(point0Index));
|
||||
return (currentBaseLowerCodePoint != typedBaseLowerCodePoint);
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool isSpaceSubstitutionTerminal(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
if (!CORRECT_SPACE_SUBSTITUTION) {
|
||||
return false;
|
||||
}
|
||||
if (!canDoLookAheadCorrection(traverseSession, dicNode)) {
|
||||
return false;
|
||||
}
|
||||
const int point0Index = dicNode->getInputIndex(0);
|
||||
return dicNode->isTerminalWordNode()
|
||||
&& traverseSession->getProximityInfoState(0)->
|
||||
hasSpaceProximity(point0Index);
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool isSpaceOmissionTerminal(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
if (!CORRECT_SPACE_OMISSION) {
|
||||
return false;
|
||||
}
|
||||
const int inputSize = traverseSession->getInputSize();
|
||||
// TODO: Don't refer to isCompletion?
|
||||
if (dicNode->isCompletion(inputSize)) {
|
||||
return false;
|
||||
}
|
||||
if (!dicNode->isTerminalWordNode()) {
|
||||
return false;
|
||||
}
|
||||
const int16_t pointIndex = dicNode->getInputIndex(0);
|
||||
return pointIndex <= inputSize && !dicNode->isTotalInputSizeExceedingLimit()
|
||||
&& !dicNode->shouldBeFilterdBySafetyNetForBigram();
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool shouldDepthLevelCache(
|
||||
const DicTraverseSession *const traverseSession) const {
|
||||
const int inputSize = traverseSession->getInputSize();
|
||||
return traverseSession->isCacheBorderForTyping(inputSize);
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool shouldNodeLevelCache(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool canDoLookAheadCorrection(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
const int inputSize = traverseSession->getInputSize();
|
||||
return dicNode->canDoLookAheadCorrection(inputSize);
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE ProximityType getProximityType(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
|
||||
const DicNode *const childDicNode) const {
|
||||
return traverseSession->getProximityInfoState(0)->getProximityType(
|
||||
dicNode->getInputIndex(0), childDicNode->getNodeCodePoint(),
|
||||
true /* checkProximityChars */);
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool needsToTraverseAllUserInput() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE float getMaxSpatialDistance() const {
|
||||
return ScoringParams::MAX_SPATIAL_DISTANCE;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool allowPartialCommit() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE int getDefaultExpandDicNodeSize() const {
|
||||
return DicNodeVector::DEFAULT_NODES_SIZE_FOR_OPTIMIZATION;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool sameAsTyped(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
return traverseSession->getProximityInfoState(0)->sameAsTyped(
|
||||
dicNode->getOutputWordBuf(), dicNode->getDepth());
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE int getMaxCacheSize() const {
|
||||
return ScoringParams::MAX_CACHE_DIC_NODE_SIZE;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool isPossibleOmissionChildNode(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
|
||||
const DicNode *const dicNode) const {
|
||||
const ProximityType proximityType =
|
||||
getProximityType(traverseSession, parentDicNode, dicNode);
|
||||
if (!DicNodeUtils::isProximityChar(proximityType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode) const {
|
||||
const int probability = dicNode->getProbability();
|
||||
if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) {
|
||||
return false;
|
||||
}
|
||||
const int c = dicNode->getOutputWordBuf()[0];
|
||||
const bool shortCappedWord = dicNode->getDepth()
|
||||
< ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && isAsciiUpper(c);
|
||||
return !shortCappedWord
|
||||
|| probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TypingTraversal);
|
||||
static const bool CORRECT_OMISSION;
|
||||
static const bool CORRECT_SPACE_SUBSTITUTION;
|
||||
static const bool CORRECT_SPACE_OMISSION;
|
||||
static const TypingTraversal sInstance;
|
||||
|
||||
TypingTraversal() {}
|
||||
~TypingTraversal() {}
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_TYPING_TRAVERSAL_H
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "dic_node.h"
|
||||
#include "scoring_params.h"
|
||||
#include "typing_weighting.h"
|
||||
|
||||
namespace latinime {
|
||||
const TypingWeighting TypingWeighting::sInstance;
|
||||
} // namespace latinime
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LATINIME_TYPING_WEIGHTING_H
|
||||
#define LATINIME_TYPING_WEIGHTING_H
|
||||
|
||||
#include "defines.h"
|
||||
#include "dic_node_utils.h"
|
||||
#include "dic_traverse_session.h"
|
||||
#include "weighting.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
class DicNode;
|
||||
struct DicNode_InputStateG;
|
||||
|
||||
class TypingWeighting : public Weighting {
|
||||
public:
|
||||
static const TypingWeighting *getInstance() { return &sInstance; }
|
||||
|
||||
protected:
|
||||
float getTerminalSpatialCost(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
float cost = 0.0f;
|
||||
if (dicNode->hasMultipleWords()) {
|
||||
cost += ScoringParams::HAS_MULTI_WORD_TERMINAL_COST;
|
||||
}
|
||||
if (dicNode->getProximityCorrectionCount() > 0) {
|
||||
cost += ScoringParams::HAS_PROXIMITY_TERMINAL_COST;
|
||||
}
|
||||
if (dicNode->getEditCorrectionCount() > 0) {
|
||||
cost += ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
float getOmissionCost(const DicNode *const parentDicNode, const DicNode *const dicNode) const {
|
||||
bool sameCodePoint = false;
|
||||
bool isFirstLetterOmission = false;
|
||||
float cost = 0.0f;
|
||||
sameCodePoint = dicNode->isSameNodeCodePoint(parentDicNode);
|
||||
// If the traversal omitted the first letter then the dicNode should now be on the second.
|
||||
isFirstLetterOmission = dicNode->getDepth() == 2;
|
||||
if (isFirstLetterOmission) {
|
||||
cost = ScoringParams::OMISSION_COST_FIRST_CHAR;
|
||||
} else {
|
||||
cost = sameCodePoint ? ScoringParams::OMISSION_COST_SAME_CHAR
|
||||
: ScoringParams::OMISSION_COST;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
float getMatchedCost(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
|
||||
DicNode_InputStateG *inputStateG) const {
|
||||
const int pointIndex = dicNode->getInputIndex(0);
|
||||
// Note: min() required since length can be MAX_POINT_TO_KEY_LENGTH for characters not on
|
||||
// the keyboard (like accented letters)
|
||||
const float length = min(ScoringParams::MAX_SPATIAL_DISTANCE,
|
||||
traverseSession->getProximityInfoState(0)->getPointToKeyLength(
|
||||
pointIndex, dicNode->getNodeCodePoint()));
|
||||
const float weightedDistance = length * ScoringParams::DISTANCE_WEIGHT_LENGTH;
|
||||
const bool isFirstChar = pointIndex == 0;
|
||||
const bool isProximity = isProximityDicNode(traverseSession, dicNode);
|
||||
const float cost = isProximity ? (isFirstChar ? ScoringParams::FIRST_PROXIMITY_COST
|
||||
: ScoringParams::PROXIMITY_COST) : 0.0f;
|
||||
return weightedDistance + cost;
|
||||
}
|
||||
|
||||
bool isProximityDicNode(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
|
||||
const int pointIndex = dicNode->getInputIndex(0);
|
||||
const int primaryCodePoint = toBaseLowerCase(
|
||||
traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(pointIndex));
|
||||
const int dicNodeChar = toBaseLowerCase(dicNode->getNodeCodePoint());
|
||||
return primaryCodePoint != dicNodeChar;
|
||||
}
|
||||
|
||||
float getTranspositionCost(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
|
||||
const DicNode *const dicNode) const {
|
||||
const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
|
||||
const int prevCodePoint = parentDicNode->getNodeCodePoint();
|
||||
const float distance1 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
|
||||
parentPointIndex + 1, prevCodePoint);
|
||||
const int codePoint = dicNode->getNodeCodePoint();
|
||||
const float distance2 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
|
||||
parentPointIndex, codePoint);
|
||||
const float distance = distance1 + distance2;
|
||||
const float weightedLengthDistance =
|
||||
distance * ScoringParams::DISTANCE_WEIGHT_LENGTH;
|
||||
return ScoringParams::TRANSPOSITION_COST + weightedLengthDistance;
|
||||
}
|
||||
|
||||
float getInsertionCost(
|
||||
const DicTraverseSession *const traverseSession,
|
||||
const DicNode *const parentDicNode, const DicNode *const dicNode) const {
|
||||
const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
|
||||
const int prevCodePoint =
|
||||
traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(parentPointIndex);
|
||||
|
||||
const int currentCodePoint = dicNode->getNodeCodePoint();
|
||||
const bool sameCodePoint = prevCodePoint == currentCodePoint;
|
||||
const float dist = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
|
||||
parentPointIndex + 1, currentCodePoint);
|
||||
const float weightedDistance = dist * ScoringParams::DISTANCE_WEIGHT_LENGTH;
|
||||
const bool singleChar = dicNode->getDepth() == 1;
|
||||
const float cost = (singleChar ? ScoringParams::INSERTION_COST_FIRST_CHAR : 0.0f)
|
||||
+ (sameCodePoint ? ScoringParams::INSERTION_COST_SAME_CHAR
|
||||
: ScoringParams::INSERTION_COST);
|
||||
return cost + weightedDistance;
|
||||
}
|
||||
|
||||
float getNewWordCost(const DicNode *const dicNode) const {
|
||||
const bool isCapitalized = dicNode->isCapitalized();
|
||||
return isCapitalized ?
|
||||
ScoringParams::COST_NEW_WORD_CAPITALIZED : ScoringParams::COST_NEW_WORD;
|
||||
}
|
||||
|
||||
float getNewWordBigramCost(
|
||||
const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
|
||||
hash_map_compat<int, int16_t> *const bigramCacheMap) const {
|
||||
return DicNodeUtils::getBigramNodeImprobability(traverseSession->getOffsetDict(),
|
||||
dicNode, bigramCacheMap);
|
||||
}
|
||||
|
||||
float getCompletionCost(const DicTraverseSession *const traverseSession,
|
||||
const DicNode *const dicNode) const {
|
||||
// The auto completion starts when the input index is same as the input size
|
||||
const bool firstCompletion = dicNode->getInputIndex(0)
|
||||
== traverseSession->getInputSize();
|
||||
// TODO: Change the cost for the first completion for the gesture?
|
||||
const float cost = firstCompletion ? ScoringParams::COST_FIRST_LOOKAHEAD
|
||||
: ScoringParams::COST_LOOKAHEAD;
|
||||
return cost;
|
||||
}
|
||||
|
||||
float getTerminalLanguageCost(const DicTraverseSession *const traverseSession,
|
||||
const DicNode *const dicNode, const float dicNodeLanguageImprobability) const {
|
||||
const bool hasEditCount = dicNode->getEditCorrectionCount() > 0;
|
||||
const bool isSameLength = dicNode->getDepth() == traverseSession->getInputSize();
|
||||
const bool hasMultipleWords = dicNode->hasMultipleWords();
|
||||
const bool hasProximityErrors = dicNode->getProximityCorrectionCount() > 0;
|
||||
// Gesture input is always assumed to have proximity errors
|
||||
// because the input word shouldn't be treated as perfect
|
||||
const bool isExactMatch = !hasEditCount && !hasMultipleWords
|
||||
&& !hasProximityErrors && isSameLength;
|
||||
|
||||
const float totalPrevWordsLanguageCost = dicNode->getTotalPrevWordsLanguageCost();
|
||||
const float languageImprobability = isExactMatch ? 0.0f : dicNodeLanguageImprobability;
|
||||
const float languageWeight = ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
|
||||
// TODO: Caveat: The following equation should be:
|
||||
// totalPrevWordsLanguageCost + (languageImprobability * languageWeight);
|
||||
return (totalPrevWordsLanguageCost + languageImprobability) * languageWeight;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE bool needsToNormalizeCompoundDistance() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE float getAdditionalProximityCost() const {
|
||||
return ScoringParams::ADDITIONAL_PROXIMITY_COST;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE float getSubstitutionCost() const {
|
||||
return ScoringParams::SUBSTITUTION_COST;
|
||||
}
|
||||
|
||||
AK_FORCE_INLINE float getSpaceSubstitutionCost() const {
|
||||
return ScoringParams::SPACE_SUBSTITUTION_COST;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TypingWeighting);
|
||||
static const TypingWeighting sInstance;
|
||||
|
||||
TypingWeighting() {}
|
||||
~TypingWeighting() {}
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_TYPING_WEIGHTING_H
|
Loading…
Reference in New Issue