Skip to content

Commit ad928a1

Browse files
committed
Term updates.
1 parent c4b6a9b commit ad928a1

File tree

8 files changed

+307
-302
lines changed

8 files changed

+307
-302
lines changed

Sources/Megrez/0_Megrez.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ public enum Megrez {}
88
// 天權星引擎(Megrez Compositor)特色:
99
// - 原生 Swift 實作,擁有完備的 Swift 5.3 ~ 5.9 支援、也可以用作任何 Swift 6 專案的相依套件(需使用者自行處理對跨執行緒安全性的需求)。
1010
// - API 以陣列的形式處理輸入的 key。而且,在獲取候選字詞內容的時候,也可以徹底篩除橫跨游標的詞。
11-
// - 爬軌算法(Walking Algorithm)採用 Dijkstra 的算法,且經過效能最佳化處理、擁有比 DAG-Relax 算法更優的效能。
11+
// - 組句算法(Assembling Algorithm)採用 Dijkstra 的算法,且經過效能最佳化處理、擁有比 DAG-Relax 算法更優的效能。
1212

1313
// 術語:
1414

1515
// Grid: 節軌
16-
// Walk: 爬軌
16+
// Assemble: 組句
1717
// Node: 節點
18-
// SpanLength: 節幅
19-
// Span: 幅位
18+
// SegLength: 節幅
19+
// Segment: 幅節

Sources/Megrez/1_Compositor.swift

Lines changed: 96 additions & 91 deletions
Large diffs are not rendered by default.
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
// This code is released under the SPDX-License-Identifier: `LGPL-3.0-or-later`.
44

55
extension Megrez.Compositor {
6-
/// 爬軌函式,會以 Dijkstra 算法更新當前組字器的 walkedNodes
6+
/// 組句函式,會以 Dijkstra 算法更新當前組字器的 assembledNodes
77
///
88
/// 該算法會在圖中尋找具有最高分數的路徑,即最可能的字詞組合。
99
///
1010
/// 該算法所依賴的 HybridPriorityQueue 針對 Sandy Bridge 經過最佳化處理,
1111
/// 使得該算法在 Sandy Bridge CPU 的電腦上比 DAG 算法擁有更優的效能。
1212
///
13-
/// - Returns: 爬軌結果(已選字詞陣列)。
13+
/// - Returns: 組句結果(已選字詞陣列)。
1414
@discardableResult
15-
public func walk() -> [Megrez.Node] {
16-
walkedNodes.removeAll()
17-
guard !spans.isEmpty else { return [] }
15+
public func assemble() -> [Megrez.Node] {
16+
assembledNodes.removeAll()
17+
guard !segments.isEmpty else { return [] }
1818

1919
// 初期化資料結構。
2020
var openSet = HybridPriorityQueue<PrioritizedState>(reversed: true)
@@ -54,7 +54,7 @@ extension Megrez.Compositor {
5454
}
5555

5656
// 處理下一個可能的節點。
57-
for (length, nextNode) in spans[current.position] {
57+
for (length, nextNode) in segments[current.position] {
5858
let nextPos = current.position + length
5959

6060
// 計算新的權重分數。
@@ -102,7 +102,7 @@ extension Megrez.Compositor {
102102
current = state.prev
103103
// 備註:此處不需要手動 ASAN,因為沒有參據循環(Retain Cycle)。
104104
}
105-
walkedNodes = pathNodes.map(\.copy)
105+
assembledNodes = pathNodes.map(\.copy)
106106

107107
// 手動 ASAN:批次清理所有 SearchState 物件以防止記憶體洩漏
108108
// 包括 visited set 中的所有狀態、openSet 中剩餘的狀態,以及 leadingState
@@ -111,7 +111,7 @@ extension Megrez.Compositor {
111111
openSet: &openSet,
112112
leadingState: start
113113
)
114-
return walkedNodes
114+
return assembledNodes
115115
}
116116

117117
/// 部分清理已訪問狀態集合以控制記憶體使用

Sources/Megrez/3_KeyValuePaired.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ extension Megrez.Compositor {
120120
/// - endAt 僅獲取在當前游標位置結束的節點內的候選字。
121121
public enum CandidateFetchFilter { case all, beginAt, endAt }
122122

123-
/// 返回在當前位置的所有候選字詞(以詞音配對的形式)。如果組字器內有幅位、且游標
123+
/// 返回在當前位置的所有候選字詞(以詞音配對的形式)。如果組字器內有幅節、且游標
124124
/// 位於組字器的(文字輸入順序的)最前方(也就是游標位置的數值是最大合規數值)的
125125
/// 話,那麼這裡會對 location 的位置自動減去 1、以免去在呼叫該函式後再處理的麻煩。
126126
/// - Parameter location: 游標位置,必須是顯示的游標位置、不得做任何事先糾偏處理。
@@ -151,8 +151,8 @@ extension Megrez.Compositor {
151151
guard theAnchor.location == location else { return }
152152
case .endAt:
153153
guard theNode.keyArray.last == keyAtCursor else { return }
154-
switch theNode.spanLength {
155-
case 2... where theAnchor.location + theAnchor.node.spanLength - 1 != location: return
154+
switch theNode.segLength {
155+
case 2... where theAnchor.location + theAnchor.node.segLength - 1 != location: return
156156
default: break
157157
}
158158
}
@@ -232,10 +232,10 @@ extension Megrez.Compositor {
232232

233233
guard let overridden = overridden else { return false } // 啥也不覆寫。
234234

235-
(overridden.location ..< min(spans.count, overridden.location + overridden.node.spanLength))
235+
(overridden.location ..< min(segments.count, overridden.location + overridden.node.segLength))
236236
.forEach { i in
237-
/// 咱們還得弱化所有在相同的幅位座標的節點的複寫權重。舉例說之前爬軌的結果是「A BC」
238-
/// 且 A 與 BC 都是被覆寫的結果,然後使用者現在在與 A 相同的幅位座標位置
237+
/// 咱們還得弱化所有在相同的幅節座標的節點的複寫權重。舉例說之前組句的結果是「A BC」
238+
/// 且 A 與 BC 都是被覆寫的結果,然後使用者現在在與 A 相同的幅節座標位置
239239
/// 選了「DEF」,那麼 BC 的覆寫狀態就有必要重設(但 A 不用重設)。
240240
arrOverlappedNodes = fetchOverlappingNodes(at: i)
241241
arrOverlappedNodes.forEach { anchor in
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,32 @@
22
// ====================
33
// This code is released under the SPDX-License-Identifier: `LGPL-3.0-or-later`.
44

5-
// MARK: - Megrez.SpanUnit
5+
// MARK: - Megrez.Segment
66

77
extension Megrez {
8-
/// 幅位乃指一組共享起點的節點。其實是個辭典:[幅位長度: 節點]。
9-
public typealias SpanUnit = [Int: Node]
8+
/// 幅節乃指一組共享起點的節點。其實是個辭典:[幅節長度: 節點]。
9+
public typealias Segment = [Int: Node]
1010
}
1111

12-
extension Megrez.SpanUnit {
13-
/// 幅位乃指一組共享起點的節點。其實是個辭典:[幅位長度: 節點]。
12+
extension Megrez.Segment {
13+
/// 幅節乃指一組共享起點的節點。其實是個辭典:[幅節長度: 節點]。
1414
/// - Remark: 因為 Node 不是 Struct,所以會在 Compositor 被拷貝的時候無法被真實複製。
1515
/// 這樣一來,Compositor 複製品當中的 Node 的變化會被反應到原先的 Compositor 身上。
1616
/// 這在某些情況下會造成意料之外的混亂情況,所以需要引入一個拷貝用的建構子。
17-
public init(SpanUnit target: Megrez.SpanUnit) {
17+
public init(Segment target: Megrez.Segment) {
1818
self.init()
1919
target.forEach { theKey, theValue in
2020
self[theKey] = theValue.copy
2121
}
2222
}
2323

24-
/// 該幅位的硬拷貝
25-
public var hardCopy: Megrez.SpanUnit { .init(SpanUnit: self) }
24+
/// 該幅節的硬拷貝
25+
public var hardCopy: Megrez.Segment { .init(Segment: self) }
2626

2727
// MARK: - Dynamic Variables
2828

29-
/// 該幅位單元內的所有節點當中持有最長幅位的節點長度
30-
/// 該變數受該幅位的自身操作函式而被動更新
29+
/// 該幅節單元內的所有節點當中持有最長幅節的節點長度
30+
/// 該變數受該幅節的自身操作函式而被動更新
3131
public var maxLength: Int { keys.max() ?? 0 }
3232
}
3333

@@ -40,22 +40,22 @@ extension Megrez.Compositor {
4040
public func fetchOverlappingNodes(at givenLocation: Int) -> [(location: Int, node: Megrez.Node)] {
4141
var results = [(location: Int, node: Megrez.Node)]()
4242
let givenLocation = max(0, min(givenLocation, keys.count - 1))
43-
guard spans.indices.contains(givenLocation) else { return results }
43+
guard segments.indices.contains(givenLocation) else { return results }
4444

4545
// 先獲取該位置的所有單字節點。
46-
spans[givenLocation].keys.sorted().forEach { theSpanLength in
47-
guard let node = spans[givenLocation][theSpanLength] else { return }
48-
Self.insertAnchor(spanIndex: givenLocation, node: node, to: &results)
46+
segments[givenLocation].keys.sorted().forEach { theSegLength in
47+
guard let node = segments[givenLocation][theSegLength] else { return }
48+
Self.insertAnchor(segmentIndex: givenLocation, node: node, to: &results)
4949
}
5050

5151
// 再獲取以當前位置結尾或開頭的節點。
52-
let begin: Int = givenLocation - min(givenLocation, maxSpanLength - 1)
52+
let begin: Int = givenLocation - min(givenLocation, maxSegLength - 1)
5353
(begin ..< givenLocation).forEach { theLocation in
54-
let (A, B): (Int, Int) = (givenLocation - theLocation + 1, spans[theLocation].maxLength)
54+
let (A, B): (Int, Int) = (givenLocation - theLocation + 1, segments[theLocation].maxLength)
5555
guard A <= B else { return }
5656
(A ... B).forEach { theLength in
57-
guard let node = spans[theLocation][theLength] else { return }
58-
Self.insertAnchor(spanIndex: theLocation, node: node, to: &results)
57+
guard let node = segments[theLocation][theLength] else { return }
58+
Self.insertAnchor(segmentIndex: theLocation, node: node, to: &results)
5959
}
6060
}
6161

@@ -64,14 +64,14 @@ extension Megrez.Compositor {
6464

6565
/// 要在 fetchOverlappingNodes() 內使用的一個工具函式。
6666
private static func insertAnchor(
67-
spanIndex location: Int, node: Megrez.Node,
67+
segmentIndex location: Int, node: Megrez.Node,
6868
to targetContainer: inout [(location: Int, node: Megrez.Node)]
6969
) {
7070
guard !node.keyArray.joined().isEmpty else { return }
7171
let anchor = (location: location, node: node)
7272
for i in 0 ... targetContainer.count {
7373
guard !targetContainer.isEmpty else { break }
74-
guard targetContainer[i].node.spanLength <= anchor.node.spanLength else { continue }
74+
guard targetContainer[i].node.segLength <= anchor.node.segLength else { continue }
7575
targetContainer.insert(anchor, at: i)
7676
return
7777
}

Sources/Megrez/5_Node.swift

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,28 @@
77
extension Megrez {
88
/// 字詞節點。
99
///
10-
/// 一個節點由這些內容組成:幅位長度、索引鍵、以及一組單元圖。幅位長度就是指這個
10+
/// 一個節點由這些內容組成:幅節長度、索引鍵、以及一組單元圖。幅節長度就是指這個
1111
/// 節點在組字器內橫跨了多少個字長。組字器負責構築自身的節點。對於由多個漢字組成
1212
/// 的詞,組字器會將多個讀音索引鍵合併為一個讀音索引鍵、據此向語言模組請求對應的
1313
/// 單元圖結果陣列。舉例說,如果一個詞有兩個漢字組成的話,那麼讀音也是有兩個、其
14-
/// 索引鍵也是由兩個讀音組成的,那麼這個節點的幅位長度就是 2。
14+
/// 索引鍵也是由兩個讀音組成的,那麼這個節點的幅節長度就是 2。
1515
public class Node: Equatable, Hashable, Codable {
1616
// MARK: Lifecycle
1717

1818
/// 生成一個字詞節點。
1919
///
20-
/// 一個節點由這些內容組成:幅位長度、索引鍵、以及一組單元圖。幅位長度就是指這個
20+
/// 一個節點由這些內容組成:幅節長度、索引鍵、以及一組單元圖。幅節長度就是指這個
2121
/// 節點在組字器內橫跨了多少個字長。組字器負責構築自身的節點。對於由多個漢字組成
2222
/// 的詞,組字器會將多個讀音索引鍵合併為一個讀音索引鍵、據此向語言模組請求對應的
2323
/// 單元圖結果陣列。舉例說,如果一個詞有兩個漢字組成的話,那麼讀音也是有兩個、其
24-
/// 索引鍵也是由兩個讀音組成的,那麼這個節點的幅位長度就是 2。
24+
/// 索引鍵也是由兩個讀音組成的,那麼這個節點的幅節長度就是 2。
2525
/// - Parameters:
2626
/// - keyArray: 給定索引鍵陣列,不得為空。
27-
/// - spanLength: 給定幅位長度,一般情況下與給定索引鍵陣列內的索引鍵數量一致。
27+
/// - segLength: 給定幅節長度,一般情況下與給定索引鍵陣列內的索引鍵數量一致。
2828
/// - unigrams: 給定單元圖陣列,不得為空。
29-
public init(keyArray: [String] = [], spanLength: Int = 0, unigrams: [Megrez.Unigram] = []) {
29+
public init(keyArray: [String] = [], segLength: Int = 0, unigrams: [Megrez.Unigram] = []) {
3030
self.keyArray = keyArray
31-
self.spanLength = max(spanLength, 0)
31+
self.segLength = max(segLength, 0)
3232
self.unigrams = unigrams
3333
self.currentOverrideType = .withNoOverrides
3434
}
@@ -40,7 +40,7 @@ extension Megrez {
4040
public init(node: Node) {
4141
self.overridingScore = node.overridingScore
4242
self.keyArray = node.keyArray
43-
self.spanLength = node.spanLength
43+
self.segLength = node.segLength
4444
self.unigrams = node.unigrams
4545
self.currentOverrideType = node.currentOverrideType
4646
self.currentUnigramIndex = node.currentUnigramIndex
@@ -54,28 +54,28 @@ extension Megrez {
5454
/// 當前狀態下權重最高的單元圖的權重數值。打比方說,如果該節點內的單元圖陣列是
5555
/// [("a", -114), ("b", -514), ("c", -1919)] 的話,指定該覆寫行為則會導致該節
5656
/// 點返回的結果為 ("c", -114)。該覆寫行為多用於諸如使用者半衰記憶模組的建議
57-
/// 行為。被覆寫的這個節點的狀態可能不會再被爬軌行為擅自改回。該覆寫行為無法
58-
/// 防止其它節點被爬軌函式所支配。這種情況下就需要用到 overridingScore。
59-
/// - withHighScore: 將該節點權重覆寫為 overridingScore,使其被爬軌函式所青睞
57+
/// 行為。被覆寫的這個節點的狀態可能不會再被組句行為擅自改回。該覆寫行為無法
58+
/// 防止其它節點被組句函式所支配。這種情況下就需要用到 overridingScore。
59+
/// - withHighScore: 將該節點權重覆寫為 overridingScore,使其被組句函式所青睞
6060
public enum OverrideType: Int, Codable {
6161
case withNoOverrides = 0
6262
case withTopUnigramScore = 1
6363
case withHighScore = 2
6464
}
6565

66-
/// 一個用以覆寫權重的數值。該數值之高足以改變爬軌函式對該節點的讀取結果。這裡用
67-
/// 「0」可能看似足夠了,但仍會使得該節點的覆寫狀態有被爬軌函式忽視的可能。比方說
66+
/// 一個用以覆寫權重的數值。該數值之高足以改變組句函式對該節點的讀取結果。這裡用
67+
/// 「0」可能看似足夠了,但仍會使得該節點的覆寫狀態有被組句函式忽視的可能。比方說
6868
/// 要針對索引鍵「a b c」複寫的資料值為「A B C」,使用大寫資料值來覆寫節點。這時,
69-
/// 如果這個獨立的 c 有一個可以拮抗權重的詞「bc」的話,可能就會導致爬軌函式的算法
70-
/// 找出「A->bc」的爬軌途徑(尤其是當 A 和 B 使用「0」作為複寫數值的情況下)。這樣
71-
/// 一來,「A-B」就不一定始終會是爬軌函式的青睞結果了。所以,這裡一定要用大於 0 的
69+
/// 如果這個獨立的 c 有一個可以拮抗權重的詞「bc」的話,可能就會導致組句函式的算法
70+
/// 找出「A->bc」的組句途徑(尤其是當 A 和 B 使用「0」作為複寫數值的情況下)。這樣
71+
/// 一來,「A-B」就不一定始終會是組句函式的青睞結果了。所以,這裡一定要用大於 0 的
7272
/// 數(比如野獸常數),以讓「c」更容易單獨被選中。
7373
public var overridingScore: Double = 114_514
7474

7575
/// 索引鍵陣列。
7676
public private(set) var keyArray: [String]
77-
/// 幅位長度
78-
public private(set) var spanLength: Int
77+
/// 幅節長度
78+
public private(set) var segLength: Int
7979
/// 單元圖陣列。
8080
public private(set) var unigrams: [Megrez.Unigram]
8181
/// 該節點目前的覆寫狀態種類。
@@ -127,7 +127,7 @@ extension Megrez {
127127
public func hash(into hasher: inout Hasher) {
128128
hasher.combine(overridingScore)
129129
hasher.combine(keyArray)
130-
hasher.combine(spanLength)
130+
hasher.combine(segLength)
131131
hasher.combine(unigrams)
132132
hasher.combine(currentOverrideType)
133133
hasher.combine(currentUnigramIndex)
@@ -211,18 +211,18 @@ extension Array where Element == Megrez.Node {
211211
return (resultA, resultB)
212212
}
213213

214-
/// 返回一個辭典,以座標查索引。允許以游標位置查詢其屬於第幾個幅位座標(從 0 開始算)。
214+
/// 返回一個辭典,以座標查索引。允許以游標位置查詢其屬於第幾個幅節座標(從 0 開始算)。
215215
public var cursorRegionMap: [Int: Int] { nodeBorderPointDictPair.cursorRegionMap }
216216

217-
/// 總讀音單元數量。在絕大多數情況下,可視為總幅位長度
217+
/// 總讀音單元數量。在絕大多數情況下,可視為總幅節長度
218218
public var totalKeyCount: Int { map(\.keyArray.count).reduce(0, +) }
219219

220220
/// 根據給定的游標,返回其前後最近的節點邊界。
221221
/// - Parameter cursor: 給定的游標。
222222
public func contextRange(ofGivenCursor cursor: Int) -> Range<Int> {
223223
guard !isEmpty else { return 0 ..< 0 }
224-
let lastSpanningLength = reversed()[0].keyArray.count
225-
var nilReturn = (totalKeyCount - lastSpanningLength) ..< totalKeyCount
224+
let frontestSegLength = reversed()[0].keyArray.count
225+
var nilReturn = (totalKeyCount - frontestSegLength) ..< totalKeyCount
226226
if cursor >= totalKeyCount { return nilReturn } // 防呆
227227
let cursor = Swift.max(0, cursor) // 防呆
228228
nilReturn = cursor ..< cursor

Tests/MegrezTests/MegrezImplForTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Megrez
88
// MARK: - Megrez Extensions for Test Purposes Only.
99

1010
extension Megrez.Compositor {
11-
/// 返回在當前位置的所有候選字詞(以詞音配對的形式)。如果組字器內有幅位、且游標
11+
/// 返回在當前位置的所有候選字詞(以詞音配對的形式)。如果組字器內有幅節、且游標
1212
/// 位於組字器的(文字輸入順序的)最前方(也就是游標位置的數值是最大合規數值)的
1313
/// 話,那麼這裡會用到 location - 1、以免去在呼叫該函式後再處理的麻煩。
1414
/// - Remark: 該函式已被淘汰,因為有「無法徹底清除 node-crossing 內容」的故障。

0 commit comments

Comments
 (0)