1
1
mirror of https://github.com/github/semantic.git synced 2024-12-26 08:25:19 +03:00

Parameterize SES by the cost function.

This commit is contained in:
Rob Rix 2015-10-14 18:51:18 -04:00
parent 230394bde2
commit 7c099bac6f
2 changed files with 2 additions and 15 deletions

View File

@ -94,7 +94,7 @@ public enum Algorithm<Term: TermType, B> {
return f(Dictionary(elements: deleted + inserted + patched)).evaluate(equals, recur: recur) return f(Dictionary(elements: deleted + inserted + patched)).evaluate(equals, recur: recur)
case let .Roll(.ByIndex(a, b, f)): case let .Roll(.ByIndex(a, b, f)):
return f(SES(a, b, recur: recur)).evaluate(equals, recur: recur) return f(SES(a, b, cost: cost, recur: recur)).evaluate(equals, recur: recur)
} }
} }
} }

View File

@ -1,25 +1,12 @@
/// Computes the SES (shortest edit script), i.e. the shortest sequence of diffs (`Free<A, Patch<Term>>`) for two arrays of `Term`s which would suffice to transform `a` into `b`. /// Computes the SES (shortest edit script), i.e. the shortest sequence of diffs (`Free<A, Patch<Term>>`) for two arrays of `Term`s which would suffice to transform `a` into `b`.
/// ///
/// This is computed w.r.t. an `equals` function, which computes the equality of leaf nodes within terms, and a `recur` function, which produces diffs representing matched-up terms. /// This is computed w.r.t. an `equals` function, which computes the equality of leaf nodes within terms, and a `recur` function, which produces diffs representing matched-up terms.
public func SES<Term, A>(a: [Term], _ b: [Term], recur: (Term, Term) -> Free<A, Patch<Term>>?) -> [Free<A, Patch<Term>>] { public func SES<Term, A>(a: [Term], _ b: [Term], cost: Free<A, Patch<Term>> -> Int, recur: (Term, Term) -> Free<A, Patch<Term>>?) -> [Free<A, Patch<Term>>] {
typealias Diff = Free<A, Patch<Term>> typealias Diff = Free<A, Patch<Term>>
if a.isEmpty { return b.map { Diff.Pure(Patch.Insert($0)) } } if a.isEmpty { return b.map { Diff.Pure(Patch.Insert($0)) } }
if b.isEmpty { return a.map { Diff.Pure(Patch.Delete($0)) } } if b.isEmpty { return a.map { Diff.Pure(Patch.Delete($0)) } }
func cost(diff: Diff) -> Int {
return diff.map(const(1)).iterate { syntax in
switch syntax {
case .Leaf:
return 0
case let .Indexed(costs):
return costs.reduce(0, combine: +)
case let .Keyed(costs):
return costs.values.reduce(0, combine: +)
}
}
}
func cons(diff: Diff, rest: Memo<Stream<(Diff, Int)>>) -> Stream<(Diff, Int)> { func cons(diff: Diff, rest: Memo<Stream<(Diff, Int)>>) -> Stream<(Diff, Int)> {
return .Cons((diff, cost(diff) + costOfStream(rest)), rest) return .Cons((diff, cost(diff) + costOfStream(rest)), rest)
} }