Merge "Move typing policy to AOSP"

This commit is contained in:
Satoshi Kataoka 2013-04-02 07:54:43 +00:00 committed by Android (Google) Code Review
commit d2a04e1e79
10 changed files with 704 additions and 1 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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