Repo // Megrez v2.0.2 update.
This commit is contained in:
parent
d0df22b5d4
commit
e20f95c4b5
|
@ -223,34 +223,6 @@ extension Array where Element == Megrez.Compositor.Node {
|
||||||
}
|
}
|
||||||
return counter
|
return counter
|
||||||
}
|
}
|
||||||
|
|
||||||
public func findNode(at cursor: Int, target outCursorPastNode: inout Int) -> Megrez.Compositor.Node? {
|
|
||||||
guard !isEmpty else { return nil }
|
|
||||||
let cursor = Swift.max(0, Swift.min(cursor, keys.count))
|
|
||||||
|
|
||||||
if cursor == 0, let theFirst = first {
|
|
||||||
outCursorPastNode = theFirst.spanLength
|
|
||||||
return theFirst
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同時應對「游標在右端」與「游標離右端還差一個位置」的情形。
|
|
||||||
if cursor >= keys.count - 1, let theLast = last {
|
|
||||||
outCursorPastNode = keys.count
|
|
||||||
return theLast
|
|
||||||
}
|
|
||||||
|
|
||||||
var accumulated = 0
|
|
||||||
for neta in self {
|
|
||||||
accumulated += neta.spanLength
|
|
||||||
if accumulated > cursor {
|
|
||||||
outCursorPastNode = accumulated
|
|
||||||
return neta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下述情形本不應該出現。
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Private Methods
|
// MARK: - Private Methods
|
||||||
|
|
|
@ -13,7 +13,7 @@ extension Megrez {
|
||||||
/// 簡單的貝氏推論:因為底層的語言模組只會提供單元圖資料。一旦將所有可以組字的單元圖
|
/// 簡單的貝氏推論:因為底層的語言模組只會提供單元圖資料。一旦將所有可以組字的單元圖
|
||||||
/// 作為節點塞到組字器內,就可以用一個簡單的有向無環圖爬軌過程、來利用這些隱性資料值
|
/// 作為節點塞到組字器內,就可以用一個簡單的有向無環圖爬軌過程、來利用這些隱性資料值
|
||||||
/// 算出最大相似估算結果。
|
/// 算出最大相似估算結果。
|
||||||
public class Compositor {
|
public struct Compositor {
|
||||||
/// 就文字輸入方向而言的方向。
|
/// 就文字輸入方向而言的方向。
|
||||||
public enum TypingDirection { case front, rear }
|
public enum TypingDirection { case front, rear }
|
||||||
/// 軌格增減行為。
|
/// 軌格增減行為。
|
||||||
|
@ -51,7 +51,7 @@ extension Megrez {
|
||||||
self.separator = separator
|
self.separator = separator
|
||||||
}
|
}
|
||||||
|
|
||||||
public func clear() {
|
public mutating func clear() {
|
||||||
cursor = 0
|
cursor = 0
|
||||||
keys.removeAll()
|
keys.removeAll()
|
||||||
spans.removeAll()
|
spans.removeAll()
|
||||||
|
@ -62,7 +62,7 @@ extension Megrez {
|
||||||
/// 在游標位置插入給定的索引鍵。
|
/// 在游標位置插入給定的索引鍵。
|
||||||
/// - Parameter key: 要插入的索引鍵。
|
/// - Parameter key: 要插入的索引鍵。
|
||||||
/// - Returns: 該操作是否成功執行。
|
/// - Returns: 該操作是否成功執行。
|
||||||
@discardableResult public func insertKey(_ key: String) -> Bool {
|
@discardableResult public mutating func insertKey(_ key: String) -> Bool {
|
||||||
guard !key.isEmpty, key != separator, langModel.hasUnigramsFor(key: key) else { return false }
|
guard !key.isEmpty, key != separator, langModel.hasUnigramsFor(key: key) else { return false }
|
||||||
keys.insert(key, at: cursor)
|
keys.insert(key, at: cursor)
|
||||||
resizeGrid(at: cursor, do: .expand)
|
resizeGrid(at: cursor, do: .expand)
|
||||||
|
@ -77,7 +77,7 @@ extension Megrez {
|
||||||
/// 如果是朝著與文字輸入方向相反的方向砍的話,游標位置會自動遞減。
|
/// 如果是朝著與文字輸入方向相反的方向砍的話,游標位置會自動遞減。
|
||||||
/// - Parameter direction: 指定方向(相對於文字輸入方向而言)。
|
/// - Parameter direction: 指定方向(相對於文字輸入方向而言)。
|
||||||
/// - Returns: 該操作是否成功執行。
|
/// - Returns: 該操作是否成功執行。
|
||||||
@discardableResult public func dropKey(direction: TypingDirection) -> Bool {
|
@discardableResult public mutating func dropKey(direction: TypingDirection) -> Bool {
|
||||||
let isBackSpace: Bool = direction == .rear ? true : false
|
let isBackSpace: Bool = direction == .rear ? true : false
|
||||||
guard cursor != (isBackSpace ? 0 : keys.count) else { return false }
|
guard cursor != (isBackSpace ? 0 : keys.count) else { return false }
|
||||||
keys.remove(at: cursor - (isBackSpace ? 1 : 0))
|
keys.remove(at: cursor - (isBackSpace ? 1 : 0))
|
||||||
|
@ -90,7 +90,7 @@ extension Megrez {
|
||||||
/// 按幅位來前後移動游標。
|
/// 按幅位來前後移動游標。
|
||||||
/// - Parameter direction: 移動方向。
|
/// - Parameter direction: 移動方向。
|
||||||
/// - Returns: 該操作是否順利完成。
|
/// - Returns: 該操作是否順利完成。
|
||||||
@discardableResult public func jumpCursorBySpan(to direction: TypingDirection) -> Bool {
|
@discardableResult public mutating func jumpCursorBySpan(to direction: TypingDirection) -> Bool {
|
||||||
switch direction {
|
switch direction {
|
||||||
case .front:
|
case .front:
|
||||||
if cursor == width { return false }
|
if cursor == width { return false }
|
||||||
|
@ -158,7 +158,7 @@ extension Megrez.Compositor {
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - location: 給定的幅位座標。
|
/// - location: 給定的幅位座標。
|
||||||
/// - action: 指定是擴張還是縮減一個幅位。
|
/// - action: 指定是擴張還是縮減一個幅位。
|
||||||
func resizeGrid(at location: Int, do action: ResizeBehavior) {
|
mutating func resizeGrid(at location: Int, do action: ResizeBehavior) {
|
||||||
let location = max(min(location, spans.count), 0) // 防呆
|
let location = max(min(location, spans.count), 0) // 防呆
|
||||||
switch action {
|
switch action {
|
||||||
case .expand:
|
case .expand:
|
||||||
|
@ -255,7 +255,7 @@ extension Megrez.Compositor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateCursorJumpingTables(_ walkedNodes: [Node]) {
|
mutating func updateCursorJumpingTables(_ walkedNodes: [Node]) {
|
||||||
var cursorRegionMapDict = [Int: Int]()
|
var cursorRegionMapDict = [Int: Int]()
|
||||||
cursorRegionMapDict[-1] = 0 // 防呆
|
cursorRegionMapDict[-1] = 0 // 防呆
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
|
@ -11,7 +11,7 @@ extension Megrez.Compositor {
|
||||||
/// 對於 `G = (V, E)`,該算法的運行次數為 `O(|V|+|E|)`,其中 `G` 是一個有向無環圖。
|
/// 對於 `G = (V, E)`,該算法的運行次數為 `O(|V|+|E|)`,其中 `G` 是一個有向無環圖。
|
||||||
/// 這意味著,即使軌格很大,也可以用很少的算力就可以爬軌。
|
/// 這意味著,即使軌格很大,也可以用很少的算力就可以爬軌。
|
||||||
/// - Returns: 爬軌結果+該過程是否順利執行。
|
/// - Returns: 爬軌結果+該過程是否順利執行。
|
||||||
@discardableResult public func walk() -> ([Node], Bool) {
|
@discardableResult public mutating func walk() -> ([Node], Bool) {
|
||||||
var result = [Node]()
|
var result = [Node]()
|
||||||
defer {
|
defer {
|
||||||
walkedNodes = result
|
walkedNodes = result
|
||||||
|
|
|
@ -144,13 +144,17 @@ extension Megrez.Compositor {
|
||||||
guard let overridden = overridden else { return false } // 啥也不覆寫。
|
guard let overridden = overridden else { return false } // 啥也不覆寫。
|
||||||
|
|
||||||
for i in overridden.spanIndex..<min(spans.count, overridden.spanIndex + overridden.node.spanLength) {
|
for i in overridden.spanIndex..<min(spans.count, overridden.spanIndex + overridden.node.spanLength) {
|
||||||
/// 咱們還得重設所有在相同的幅位座標的節點。舉例說之前爬軌的結果是「A BC」
|
/// 咱們還得弱化所有在相同的幅位座標的節點的複寫權重。舉例說之前爬軌的結果是「A BC」
|
||||||
/// 且 A 與 BC 都是被覆寫的結果,然後使用者現在在與 A 相同的幅位座標位置
|
/// 且 A 與 BC 都是被覆寫的結果,然後使用者現在在與 A 相同的幅位座標位置
|
||||||
/// 選了「DEF」,那麼 BC 的覆寫狀態就有必要重設(但 A 不用重設)。
|
/// 選了「DEF」,那麼 BC 的覆寫狀態就有必要重設(但 A 不用重設)。
|
||||||
arrOverlappedNodes = fetchOverlappingNodes(at: i)
|
arrOverlappedNodes = fetchOverlappingNodes(at: i)
|
||||||
for anchor in arrOverlappedNodes {
|
for anchor in arrOverlappedNodes {
|
||||||
if anchor.node == overridden.node { continue }
|
if anchor.node == overridden.node { continue }
|
||||||
anchor.node.reset()
|
if !overridden.node.key.contains(anchor.node.key) || !overridden.node.value.contains(anchor.node.value) {
|
||||||
|
anchor.node.reset()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
anchor.node.overridingScore /= 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -17,8 +17,8 @@ extension Megrez.Compositor {
|
||||||
/// [("a", -114), ("b", -514), ("c", -1919)] 的話,指定該覆寫行為則會導致該節
|
/// [("a", -114), ("b", -514), ("c", -1919)] 的話,指定該覆寫行為則會導致該節
|
||||||
/// 點返回的結果為 ("c", -114)。該覆寫行為多用於諸如使用者半衰記憶模組的建議
|
/// 點返回的結果為 ("c", -114)。該覆寫行為多用於諸如使用者半衰記憶模組的建議
|
||||||
/// 行為。被覆寫的這個節點的狀態可能不會再被爬軌行為擅自改回。該覆寫行為無法
|
/// 行為。被覆寫的這個節點的狀態可能不會再被爬軌行為擅自改回。該覆寫行為無法
|
||||||
/// 防止其它節點被爬軌函式所支配。這種情況下就需要用到 kOverridingScore
|
/// 防止其它節點被爬軌函式所支配。這種情況下就需要用到 overridingScore
|
||||||
/// - withHighScore: 將該節點權重覆寫為 kOverridingScore,使其被爬軌函式所青睞。
|
/// - withHighScore: 將該節點權重覆寫為 overridingScore,使其被爬軌函式所青睞。
|
||||||
public enum OverrideType: Int {
|
public enum OverrideType: Int {
|
||||||
case withNoOverrides = 0
|
case withNoOverrides = 0
|
||||||
case withTopUnigramScore = 1
|
case withTopUnigramScore = 1
|
||||||
|
@ -32,7 +32,7 @@ extension Megrez.Compositor {
|
||||||
/// 找出「A->bc」的爬軌途徑(尤其是當 A 和 B 使用「0」作為複寫數值的情況下)。這樣
|
/// 找出「A->bc」的爬軌途徑(尤其是當 A 和 B 使用「0」作為複寫數值的情況下)。這樣
|
||||||
/// 一來,「A-B」就不一定始終會是爬軌函式的青睞結果了。所以,這裡一定要用大於 0 的
|
/// 一來,「A-B」就不一定始終會是爬軌函式的青睞結果了。所以,這裡一定要用大於 0 的
|
||||||
/// 數(比如野獸常數),以讓「c」更容易單獨被選中。
|
/// 數(比如野獸常數),以讓「c」更容易單獨被選中。
|
||||||
public static let kOverridingScore: Double = 114_514
|
public var overridingScore: Double = 114_514
|
||||||
|
|
||||||
private(set) var key: String
|
private(set) var key: String
|
||||||
private(set) var keyArray: [String]
|
private(set) var keyArray: [String]
|
||||||
|
@ -81,7 +81,7 @@ extension Megrez.Compositor {
|
||||||
public var score: Double {
|
public var score: Double {
|
||||||
guard !unigrams.isEmpty else { return 0 }
|
guard !unigrams.isEmpty else { return 0 }
|
||||||
switch overrideType {
|
switch overrideType {
|
||||||
case .withHighScore: return Megrez.Compositor.Node.kOverridingScore
|
case .withHighScore: return overridingScore
|
||||||
case .withTopUnigramScore: return unigrams[0].score
|
case .withTopUnigramScore: return unigrams[0].score
|
||||||
default: return currentUnigram.score
|
default: return currentUnigram.score
|
||||||
}
|
}
|
||||||
|
@ -139,4 +139,45 @@ extension Array where Element == Megrez.Compositor.Node {
|
||||||
|
|
||||||
/// 從一個節點陣列當中取出目前的索引鍵陣列。
|
/// 從一個節點陣列當中取出目前的索引鍵陣列。
|
||||||
public var keys: [String] { map(\.key) }
|
public var keys: [String] { map(\.key) }
|
||||||
|
|
||||||
|
/// 在陣列內以給定游標位置找出對應的節點。
|
||||||
|
/// - Parameters:
|
||||||
|
/// - cursor: 給定游標位置。
|
||||||
|
/// - outCursorPastNode: 找出的節點的前端位置。
|
||||||
|
/// - Returns: 查找結果。
|
||||||
|
public func findNode(at cursor: Int, target outCursorPastNode: inout Int) -> Megrez.Compositor.Node? {
|
||||||
|
guard !isEmpty else { return nil }
|
||||||
|
let cursor = Swift.max(0, Swift.min(cursor, keys.count))
|
||||||
|
|
||||||
|
if cursor == 0, let theFirst = first {
|
||||||
|
outCursorPastNode = theFirst.spanLength
|
||||||
|
return theFirst
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同時應對「游標在右端」與「游標離右端還差一個位置」的情形。
|
||||||
|
if cursor >= keys.count - 1, let theLast = last {
|
||||||
|
outCursorPastNode = keys.count
|
||||||
|
return theLast
|
||||||
|
}
|
||||||
|
|
||||||
|
var accumulated = 0
|
||||||
|
for neta in self {
|
||||||
|
accumulated += neta.spanLength
|
||||||
|
if accumulated > cursor {
|
||||||
|
outCursorPastNode = accumulated
|
||||||
|
return neta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下述情形本不應該出現。
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 在陣列內以給定游標位置找出對應的節點。
|
||||||
|
/// - Parameter cursor: 給定游標位置。
|
||||||
|
/// - Returns: 查找結果。
|
||||||
|
public func findNode(at cursor: Int) -> Megrez.Compositor.Node? {
|
||||||
|
var useless = 0
|
||||||
|
return findNode(at: cursor, target: &useless)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue