internal List <Term> Similars(Term term, int count = 1) { if (count <= 0) { throw new ArgumentException("Количество возращаемых значений должно быть положительным"); } List <Term> result = new List <Term>(); if (term.rank == 0) { //При нулевом ранге терма (т.е. терм - это буква), confidence считаем исходя из наличия соответствующей буквы в алфавите var word = DB.GetWordBySymbol(term.text); if (word == null) { return(result); } term.id = word.Id; term.confidence = (term.id == 0 ? 0 : 1); term.Identified = true; result.Add(term); } else { Stopwatch sw = new Stopwatch(); sw.Start(); //Если ранг терма больше нуля, то confidence считаем по набору дочерних элементов int[] childs = term .Childs .Distinct(new DAL.TermComparer()) .SelectMany(c => Similars(term: c, count: 1)) .Where(c => c.id != 0) .Select(c => c.id) .ToArray(); sw.Stop(); Debug.WriteLine($"Similars->{term.ToString()}.childs [{childs.Length}]: {sw.Elapsed.TotalSeconds}"); sw.Restart(); //!!! List <Word> parents = DB.GetParents(childs).Distinct().ToList(); sw.Stop(); Debug.WriteLine($"Similars->{term.ToString()}.parents [{parents.Count}]: {sw.Elapsed.TotalSeconds}"); sw.Restart(); //!!! List <Term> context = parents.Select(p => DB.ToTerm(p)).ToList(); sw.Stop(); Debug.WriteLine($"Similars->{term.ToString()}.context [{context.Count}]: {sw.Elapsed.TotalSeconds}"); //Поиск ближайшего родителя, т.е. родителя с максимумом сonfidence sw.Restart(); //!!! context.AsParallel().ForAll(p => p.confidence = Confidence.Compare(term, p)); context.Sort(new Comparison <Term>((t1, t2) => Math.Sign(t2.confidence - t1.confidence))); result = context.Take(count).ToList(); } return(result); }
/// <summary> /// Метрика схожести зависящая от количества совпадающих эелементов вне зависимости от их порядка. /// Итоговое значение делится на длину слова b (отсюда в названии Right), т.о. метрика тем больше, /// чем короче слово b /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> private static float SoftOverlappingRight(DAL.Term a, DAL.Term b) { float count = a.Childs.Sum(c => b.Childs.Max(bc => Confidence.Compare(c, bc))); return(count / b.Count); }
private static float SoftOverlappingLeft(int[] a, int[] b) { float count = a.Sum(c => b.Max(bc => Confidence.Compare(bc, c))); return(count / a.Length); }