Module: Agentilda::Linear::Fuzzy
- Defined in:
- lib/agentilda/linear/fuzzy.rb
Overview
How alike two short strings are, on a scale rather than a yes or no.
Counting shared words gives whole numbers, and whole numbers tie. Three folders scoring 2 against the same pull request is not three good answers — it is no answer — but a tie has to be detected to be refused, and with a coarse enough score everything ties.
Jaro-Winkler grades instead, and it is the right measure for these inputs: it is built for short strings, and its prefix bonus is exactly the shape of the errors here — a word and its inflection agree from the front and diverge at the end.
Constant Summary collapse
- AKIN =
Two words count as the same word above this.
Calibrated rather than chosen. The prefix bonus that makes
rounding/round(0.938) work also liftsplaid/plain(0.920) andstate/statement(0.926), which are different words that would wrongly file a pull request. 0.93 is the gap between those two groups. It costscorpus/corpora(0.848), which is rarer than either. 0.93
Class Method Summary collapse
-
.akin?(one, other) ⇒ Boolean
Whether these are the same word, inflections aside.
-
.coverage(wanted, found) ⇒ Float
What fraction of
wantedhas a counterpart infound. -
.matcher ⇒ FuzzyStringMatch::JaroWinklerPure
Deliberately the pure-Ruby implementation.
-
.similarity(one, other) ⇒ Float
0.0 to 1.0.
Class Method Details
.akin?(one, other) ⇒ Boolean
Returns whether these are the same word, inflections aside.
48 |
# File 'lib/agentilda/linear/fuzzy.rb', line 48 def akin?(one, other) = similarity(one, other) >= AKIN |
.coverage(wanted, found) ⇒ Float
What fraction of wanted has a counterpart in found.
Asymmetric on purpose. A folder is named for what it is about, in two or three words; a pull request title is a sentence. Asking how much of the sentence the folder covers would punish every long title, so the question is the other way round: how much of this folder's name did the title actually say?
61 62 63 64 65 |
# File 'lib/agentilda/linear/fuzzy.rb', line 61 def coverage(wanted, found) return 0.0 if wanted.empty? wanted.count { |word| found.any? { |other| akin?(word, other) } }.fdiv(wanted.size) end |
.matcher ⇒ FuzzyStringMatch::JaroWinklerPure
Deliberately the pure-Ruby implementation. The native one needs a C extension that does not build everywhere — it fails on this machine over a jemalloc header — and asking for it prints a compile warning to STDERR on every single load, which would land in the middle of every command's output. An import compares a few hundred short strings; that is nowhere near enough work to be worth a build step.
38 |
# File 'lib/agentilda/linear/fuzzy.rb', line 38 def matcher = @matcher ||= FuzzyStringMatch::JaroWinkler.create(:pure) |
.similarity(one, other) ⇒ Float
Returns 0.0 to 1.0.
43 |
# File 'lib/agentilda/linear/fuzzy.rb', line 43 def similarity(one, other) = matcher.getDistance(one.to_s.downcase, other.to_s.downcase) |