Megrez // Weighten nodes with longer span (Megrez v1.0.7).
This commit is contained in:
parent
afa2dd2feb
commit
7db65e6e2c
|
@ -31,21 +31,37 @@ extension Megrez {
|
||||||
mutGrid = grid
|
mutGrid = grid
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reverseWalk(at location: Int, score accumulatedScore: Double = 0.0) -> [NodeAnchor] {
|
public func reverseWalk(at location: Int, score accumulatedScore: Double = 0.0, nodesLimit: Int = 0)
|
||||||
|
-> [NodeAnchor]
|
||||||
|
{
|
||||||
if location == 0 || location > mutGrid.width() {
|
if location == 0 || location > mutGrid.width() {
|
||||||
return [] as [NodeAnchor]
|
return [] as [NodeAnchor]
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths: [[NodeAnchor]] = []
|
var paths: [[NodeAnchor]] = []
|
||||||
let nodes: [NodeAnchor] = mutGrid.nodesEndingAt(location: location)
|
var nodes: [NodeAnchor] = mutGrid.nodesEndingAt(location: location)
|
||||||
|
|
||||||
for n in nodes {
|
nodes.sort {
|
||||||
|
$0.balancedScore > $1.balancedScore // 排序規則已經在 NodeAnchor 內定義了。
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只檢查前 X 個 NodeAnchor 是否有 node。
|
||||||
|
// 這裡有 abs 是為了防止有白癡填負數。
|
||||||
|
var border: Int = nodes.count
|
||||||
|
if nodesLimit > 0 {
|
||||||
|
border = min(nodes.count, abs(nodesLimit))
|
||||||
|
}
|
||||||
|
|
||||||
|
for n in nodes[0..<border] {
|
||||||
var n = n
|
var n = n
|
||||||
if n.node == nil {
|
guard let nNode = n.node else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
n.accumulatedScore = accumulatedScore + n.node!.score()
|
// 利用 Spanning Length 來決定權重。
|
||||||
|
// 這樣一來,例:「再見」比「在」與「見」的權重更高。
|
||||||
|
let weightedScore: Double = (Double(n.spanningLength) - 1) * 2
|
||||||
|
n.accumulatedScore = accumulatedScore + nNode.score() + weightedScore
|
||||||
|
|
||||||
var path: [NodeAnchor] = reverseWalk(
|
var path: [NodeAnchor] = reverseWalk(
|
||||||
at: location - n.spanningLength,
|
at: location - n.spanningLength,
|
||||||
|
@ -54,6 +70,11 @@ extension Megrez {
|
||||||
path.insert(n, at: 0)
|
path.insert(n, at: 0)
|
||||||
|
|
||||||
paths.append(path)
|
paths.append(path)
|
||||||
|
|
||||||
|
// 始終使用固定的候選字
|
||||||
|
if nNode.score() >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !paths.isEmpty {
|
if !paths.isEmpty {
|
||||||
|
|
|
@ -140,16 +140,15 @@ extension Megrez {
|
||||||
|
|
||||||
public func fixNodeSelectedCandidate(location: Int, value: String) -> NodeAnchor {
|
public func fixNodeSelectedCandidate(location: Int, value: String) -> NodeAnchor {
|
||||||
var node = NodeAnchor()
|
var node = NodeAnchor()
|
||||||
let nodes = nodesCrossingOrEndingAt(location: location)
|
for (index, nodeAnchor) in nodesCrossingOrEndingAt(location: location).enumerated() {
|
||||||
for nodeAnchor in nodes {
|
|
||||||
// Reset the candidate-fixed state of every node at the location.
|
// Reset the candidate-fixed state of every node at the location.
|
||||||
let candidates = nodeAnchor.node?.candidates() ?? []
|
let candidates = nodeAnchor.node?.candidates() ?? []
|
||||||
nodeAnchor.node?.resetCandidate()
|
nodesCrossingOrEndingAt(location: location)[index].node?.resetCandidate()
|
||||||
|
|
||||||
for (i, candidate) in candidates.enumerated() {
|
for (i, candidate) in candidates.enumerated() {
|
||||||
if candidate.value == value {
|
if candidate.value == value {
|
||||||
nodeAnchor.node?.selectCandidateAt(index: i)
|
nodesCrossingOrEndingAt(location: location)[index].node?.selectCandidateAt(index: i)
|
||||||
node = nodeAnchor
|
node = nodesCrossingOrEndingAt(location: location)[index]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,18 +157,17 @@ extension Megrez {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func overrideNodeScoreForSelectedCandidate(location: Int, value: String, overridingScore: Double) {
|
public func overrideNodeScoreForSelectedCandidate(location: Int, value: String, overridingScore: Double) {
|
||||||
for nodeAnchor in nodesCrossingOrEndingAt(location: location) {
|
for (index, nodeAnchor) in nodesCrossingOrEndingAt(location: location).enumerated() {
|
||||||
var nodeAnchor = nodeAnchor
|
|
||||||
if let theNode = nodeAnchor.node {
|
if let theNode = nodeAnchor.node {
|
||||||
let candidates = theNode.candidates()
|
let candidates = theNode.candidates()
|
||||||
// Reset the candidate-fixed state of every node at the location.
|
// Reset the candidate-fixed state of every node at the location.
|
||||||
theNode.resetCandidate()
|
nodesCrossingOrEndingAt(location: location)[index].node?.resetCandidate()
|
||||||
nodeAnchor.node = theNode
|
|
||||||
|
|
||||||
for (i, candidate) in candidates.enumerated() {
|
for (i, candidate) in candidates.enumerated() {
|
||||||
if candidate.value == value {
|
if candidate.value == value {
|
||||||
theNode.selectFloatingCandidateAt(index: i, score: overridingScore)
|
nodesCrossingOrEndingAt(location: location)[index].node?.selectFloatingCandidateAt(
|
||||||
nodeAnchor.node = theNode
|
index: i, score: overridingScore
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,5 +32,11 @@ extension Megrez {
|
||||||
public var keyLength: Int {
|
public var keyLength: Int {
|
||||||
node?.key().count ?? 0
|
node?.key().count ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var balancedScore: Double {
|
||||||
|
let weightedScore: Double = (Double(spanningLength) - 1) * 2
|
||||||
|
let nodeScore: Double = node?.score() ?? 0
|
||||||
|
return weightedScore + nodeScore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ extension Megrez {
|
||||||
var mutCandidateFixed: Bool = false
|
var mutCandidateFixed: Bool = false
|
||||||
var mutSelectedUnigramIndex: Int = 0
|
var mutSelectedUnigramIndex: Int = 0
|
||||||
|
|
||||||
|
let kSelectedCandidateScore: Double = 99
|
||||||
|
|
||||||
public init(key: String, unigrams: [Megrez.Unigram], bigrams: [Megrez.Bigram] = []) {
|
public init(key: String, unigrams: [Megrez.Unigram], bigrams: [Megrez.Bigram] = []) {
|
||||||
mutLM = LanguageModel()
|
mutLM = LanguageModel()
|
||||||
|
|
||||||
|
@ -112,7 +114,7 @@ extension Megrez {
|
||||||
public func selectCandidateAt(index: Int = 0, fix: Bool = false) {
|
public func selectCandidateAt(index: Int = 0, fix: Bool = false) {
|
||||||
mutSelectedUnigramIndex = index >= mutUnigrams.count ? 0 : index
|
mutSelectedUnigramIndex = index >= mutUnigrams.count ? 0 : index
|
||||||
mutCandidateFixed = fix
|
mutCandidateFixed = fix
|
||||||
mutScore = 99
|
mutScore = kSelectedCandidateScore
|
||||||
}
|
}
|
||||||
|
|
||||||
public func resetCandidate() {
|
public func resetCandidate() {
|
||||||
|
|
Loading…
Reference in New Issue