forgetting_curve_utils.cpp revision 70566266be1781100c673addca5af1960a0eedf8
1fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi/*
2fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * Copyright (C) 2013, The Android Open Source Project
3fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi *
4fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License");
5fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * you may not use this file except in compliance with the License.
6fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * You may obtain a copy of the License at
7fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi *
8fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi *     http://www.apache.org/licenses/LICENSE-2.0
9fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi *
10fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software
11fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS,
12fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * See the License for the specific language governing permissions and
14fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi * limitations under the License.
15fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi */
16fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
172fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
182fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
197c4dcf1e918c2b9251e7aa907d991a3ab8764bafKeisuke Kuroyanagi#include <cmath>
20c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi#include <stdlib.h>
21c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi
2257816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi#include "suggest/policyimpl/dictionary/header/header_policy.h"
23fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
242fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "utils/time_keeper.h"
25fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
26fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanaginamespace latinime {
27fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
2813d5dc914aae5cb6bf6ef06aa05643514a40318cKeisuke Kuroyanagiconst int ForgettingCurveUtils::MAX_UNIGRAM_COUNT = 12000;
2913d5dc914aae5cb6bf6ef06aa05643514a40318cKeisuke Kuroyanagiconst int ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC = 10000;
3013d5dc914aae5cb6bf6ef06aa05643514a40318cKeisuke Kuroyanagiconst int ForgettingCurveUtils::MAX_BIGRAM_COUNT = 12000;
3113d5dc914aae5cb6bf6ef06aa05643514a40318cKeisuke Kuroyanagiconst int ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC = 10000;
32fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
3313d5dc914aae5cb6bf6ef06aa05643514a40318cKeisuke Kuroyanagiconst int ForgettingCurveUtils::MAX_COMPUTED_PROBABILITY = 127;
3467c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagiconst int ForgettingCurveUtils::DECAY_INTERVAL_SECONDS = 2 * 60 * 60;
35fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
362fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaconst int ForgettingCurveUtils::MAX_LEVEL = 3;
372fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaconst int ForgettingCurveUtils::MIN_VALID_LEVEL = 1;
382fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaconst int ForgettingCurveUtils::TIME_STEP_DURATION_IN_SECONDS = 6 * 60 * 60;
392fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaconst int ForgettingCurveUtils::MAX_ELAPSED_TIME_STEP_COUNT = 15;
402fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaconst int ForgettingCurveUtils::DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD = 14;
4167c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi
422fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaconst ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityTable;
437c4dcf1e918c2b9251e7aa907d991a3ab8764bafKeisuke Kuroyanagi
4405113c1847e5c41aab3176eb015aabc2acdc0a51Keisuke Kuroyanagi// TODO: Revise the logic to decide the initial probability depending on the given probability.
452fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ const HistoricalInfo ForgettingCurveUtils::createUpdatedHistoricalInfo(
462fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const HistoricalInfo *const originalHistoricalInfo,
4757816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        const int newProbability, const int timestamp, const HeaderPolicy *const headerPolicy) {
482fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (newProbability != NOT_A_PROBABILITY && originalHistoricalInfo->getLevel() == 0) {
492fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return HistoricalInfo(timestamp, MIN_VALID_LEVEL /* level */, 0 /* count */);
502fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    } else if (!originalHistoricalInfo->isValid()) {
512fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        // Initial information.
522fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return HistoricalInfo(timestamp, 0 /* level */, 1 /* count */);
53fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi    } else {
542fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const int updatedCount = originalHistoricalInfo->getCount() + 1;
5557816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        if (updatedCount >= headerPolicy->getForgettingCurveOccurrencesToLevelUp()) {
562fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            // The count exceeds the max value the level can be incremented.
572fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            if (originalHistoricalInfo->getLevel() >= MAX_LEVEL) {
582fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                // The level is already max.
592fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel(),
602fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                        originalHistoricalInfo->getCount());
612fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            } else {
622fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                // Level up.
632fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel() + 1,
642fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                        0 /* count */);
652fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            }
662fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        } else {
672fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel(), updatedCount);
682fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        }
69fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi    }
70fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi}
71fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
722fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ int ForgettingCurveUtils::decodeProbability(
7357816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        const HistoricalInfo *const historicalInfo, const HeaderPolicy *const headerPolicy) {
742fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimeStamp());
7557816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi    return sProbabilityTable.getProbability(
7657816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi            headerPolicy->getForgettingCurveProbabilityValuesTableId(), historicalInfo->getLevel(),
772fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            min(max(elapsedTimeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT));
782fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
792fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
802fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ int ForgettingCurveUtils::getProbability(const int unigramProbability,
812fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const int bigramProbability) {
822fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (unigramProbability == NOT_A_PROBABILITY) {
832fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return NOT_A_PROBABILITY;
842fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    } else if (bigramProbability == NOT_A_PROBABILITY) {
852fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return min(backoff(unigramProbability), MAX_COMPUTED_PROBABILITY);
86fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi    } else {
872fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return min(max(unigramProbability, bigramProbability), MAX_COMPUTED_PROBABILITY);
88fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi    }
89fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi}
90fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
912fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ bool ForgettingCurveUtils::needsToKeep(const HistoricalInfo *const historicalInfo) {
922fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    return historicalInfo->getLevel() > 0
932fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            || getElapsedTimeStepCount(historicalInfo->getTimeStamp())
942fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                    < DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD;
95fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi}
96fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
972fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ const HistoricalInfo ForgettingCurveUtils::createHistoricalInfoToSave(
9857816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        const HistoricalInfo *const originalHistoricalInfo,
9957816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        const HeaderPolicy *const headerPolicy) {
1002fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (originalHistoricalInfo->getTimeStamp() == NOT_A_TIMESTAMP) {
1012fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return HistoricalInfo();
10267c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    }
1032fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int elapsedTimeStep = getElapsedTimeStepCount(originalHistoricalInfo->getTimeStamp());
1042fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (elapsedTimeStep <= MAX_ELAPSED_TIME_STEP_COUNT) {
1052fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        // No need to update historical info.
1062fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return *originalHistoricalInfo;
1072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
1082fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    // Level down.
1092fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int maxLevelDownAmonut = elapsedTimeStep / (MAX_ELAPSED_TIME_STEP_COUNT + 1);
1102fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int levelDownAmount = (maxLevelDownAmonut >= originalHistoricalInfo->getLevel()) ?
1112fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            originalHistoricalInfo->getLevel() : maxLevelDownAmonut;
1122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int adjustedTimestamp = originalHistoricalInfo->getTimeStamp() +
1132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            levelDownAmount * (MAX_ELAPSED_TIME_STEP_COUNT + 1) * TIME_STEP_DURATION_IN_SECONDS;
1142fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    return HistoricalInfo(adjustedTimestamp,
1152fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            originalHistoricalInfo->getLevel() - levelDownAmount, 0 /* count */);
11667c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi}
11767c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi
11867c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi/* static */ bool ForgettingCurveUtils::needsToDecay(const bool mindsBlockByDecay,
11957816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        const int unigramCount, const int bigramCount, const HeaderPolicy *const headerPolicy) {
12067c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    if (unigramCount >= ForgettingCurveUtils::MAX_UNIGRAM_COUNT) {
12167c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        // Unigram count exceeds the limit.
12267c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        return true;
12367c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    } else if (bigramCount >= ForgettingCurveUtils::MAX_BIGRAM_COUNT) {
12467c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        // Bigram count exceeds the limit.
12567c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        return true;
12667c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    }
12767c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    if (mindsBlockByDecay) {
12867c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        return false;
12967c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    }
1302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (headerPolicy->getLastDecayedTime() + DECAY_INTERVAL_SECONDS
1312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            < TimeKeeper::peekCurrentTime()) {
13267c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        // Time to decay.
13367c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi        return true;
134c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi    }
13567c855ea6f882190d73df9d3fae0b56929fd6888Keisuke Kuroyanagi    return false;
136fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi}
137fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
138c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi// See comments in ProbabilityUtils::backoff().
139c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi/* static */ int ForgettingCurveUtils::backoff(const int unigramProbability) {
140c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi    if (unigramProbability == NOT_A_PROBABILITY) {
141c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi        return NOT_A_PROBABILITY;
142c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi    } else {
143c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi        return max(unigramProbability - 8, 0);
144c76bbceedc804d1f2988cbf032b530a107a7d561Keisuke Kuroyanagi    }
145fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi}
146fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi
1472fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ int ForgettingCurveUtils::getElapsedTimeStepCount(const int timestamp) {
1482fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    return (TimeKeeper::peekCurrentTime() - timestamp) / TIME_STEP_DURATION_IN_SECONDS;
1492fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
1502fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
15170566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::PROBABILITY_TABLE_COUNT = 4;
15270566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::WEAK_PROBABILITY_TABLE_ID = 0;
15370566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::MODEST_PROBABILITY_TABLE_ID = 1;
15470566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::STRONG_PROBABILITY_TABLE_ID = 2;
15570566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_PROBABILITY_TABLE_ID = 3;
15670566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::MODEST_BASE_PROBABILITY = 32;
15770566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::STRONG_BASE_PROBABILITY = 35;
15870566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagiconst int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_BASE_PROBABILITY = 40;
15970566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi
16057816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi
16157816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke KuroyanagiForgettingCurveUtils::ProbabilityTable::ProbabilityTable() : mTables() {
16257816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi    mTables.resize(PROBABILITY_TABLE_COUNT);
16357816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi    for (int tableId = 0; tableId < PROBABILITY_TABLE_COUNT; ++tableId) {
16457816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        mTables[tableId].resize(MAX_LEVEL + 1);
16557816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi        for (int level = 0; level <= MAX_LEVEL; ++level) {
16657816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi            mTables[tableId][level].resize(MAX_ELAPSED_TIME_STEP_COUNT + 1);
16770566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi            const float initialProbability = getBaseProbabilityForLevel(tableId, level);
16870566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi            const float endProbability = getBaseProbabilityForLevel(tableId, level - 1);
16957816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi            for (int timeStepCount = 0; timeStepCount <= MAX_ELAPSED_TIME_STEP_COUNT;
17057816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                    ++timeStepCount) {
17157816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                if (level == 0) {
17257816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                    mTables[tableId][level][timeStepCount] = NOT_A_PROBABILITY;
17357816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                    continue;
17457816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                }
17557816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                const int elapsedTime = timeStepCount * TIME_STEP_DURATION_IN_SECONDS;
17657816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                const float probability = initialProbability
17770566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi                        * powf(initialProbability / endProbability,
17870566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi                                -1.0f * static_cast<float>(elapsedTime)
17970566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi                                        / static_cast<float>(TIME_STEP_DURATION_IN_SECONDS
18070566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi                                                * (MAX_ELAPSED_TIME_STEP_COUNT + 1)));
18157816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                mTables[tableId][level][timeStepCount] =
18257816c7a8bac1a47913da7a503ece2b5dd7cc0fcKeisuke Kuroyanagi                        min(max(static_cast<int>(probability), 1), MAX_COMPUTED_PROBABILITY);
1832fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            }
1842fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        }
1857c4dcf1e918c2b9251e7aa907d991a3ab8764bafKeisuke Kuroyanagi    }
1867c4dcf1e918c2b9251e7aa907d991a3ab8764bafKeisuke Kuroyanagi}
1877c4dcf1e918c2b9251e7aa907d991a3ab8764bafKeisuke Kuroyanagi
18870566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi/* static */ int ForgettingCurveUtils::ProbabilityTable::getBaseProbabilityForLevel(
18970566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        const int tableId, const int level) {
19070566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi    if (tableId == WEAK_PROBABILITY_TABLE_ID) {
19170566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        // Max probability is 127.
19270566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        return static_cast<float>(MAX_COMPUTED_PROBABILITY / (1 << (MAX_LEVEL - level)));
19370566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi    } else if (tableId == MODEST_PROBABILITY_TABLE_ID) {
19470566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        // Max probability is 128.
19570566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        return static_cast<float>(MODEST_BASE_PROBABILITY * (level + 1));
19670566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi    } else if (tableId == STRONG_PROBABILITY_TABLE_ID) {
19770566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        // Max probability is 140.
19870566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        return static_cast<float>(STRONG_BASE_PROBABILITY * (level + 1));
19970566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi    } else if (tableId == AGGRESSIVE_PROBABILITY_TABLE_ID) {
20070566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        // Max probability is 160.
20170566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        return static_cast<float>(AGGRESSIVE_BASE_PROBABILITY * (level + 1));
20270566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi    } else {
20370566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi        return NOT_A_PROBABILITY;
20470566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi    }
20570566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi}
20670566266be1781100c673addca5af1960a0eedf8Keisuke Kuroyanagi
207fd02b2d6ee55d4aee7faab89a7a2b72764eafc47Keisuke Kuroyanagi} // namespace latinime
208