Strategy.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Author: Orlys
  2. // Github: https://github.com/Orlys
  3. namespace Yuuna.Contracts.Optimization
  4. {
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Collections.Immutable;
  8. using System.Diagnostics.CodeAnalysis;
  9. using System.Runtime.CompilerServices;
  10. using Yuuna.Contracts.Patterns;
  11. using Yuuna.Contracts.Modules;
  12. using Yuuna.Contracts.Semantics;
  13. using System.Diagnostics;
  14. public class Strategy : IStrategy
  15. {
  16. public Strategy()
  17. {
  18. }
  19. public Alternative FindBest(IEnumerable<IPatternSet> patternSetCollection, IImmutableList<string> feed)
  20. {
  21. var list = ImmutableArray.CreateBuilder<Match>();
  22. foreach (var pattern in patternSetCollection)
  23. {
  24. foreach (var p in pattern.ToImmutable())
  25. {
  26. var match = this.CountPatternMatch(p, feed);
  27. list.Add(match);
  28. }
  29. }
  30. var e = this.SelectBestMatch(list.ToImmutable());
  31. return e;
  32. }
  33. /// <summary>
  34. ///
  35. /// </summary>
  36. /// <param name="matches"></param>
  37. /// <returns></returns>
  38. protected virtual Alternative SelectBestMatch(IImmutableList<Match> matches)
  39. {
  40. //if(matches is null || matches.Count == 0)
  41. // return //沒有安裝任何模組
  42. var sta = new SortedList<int, List<Match>>();
  43. foreach (var match in matches)
  44. {
  45. var key = match.SequentialMatches.Count;
  46. if (!sta.ContainsKey(key))
  47. {
  48. sta.Add(key, new List<Match> { match });
  49. }
  50. else
  51. {
  52. sta[key].Add(match);
  53. }
  54. }
  55. sta.Remove(0); //過濾掉完全沒相符的資料以免影響結果
  56. var weight = double.MinValue;
  57. var bestSelect = default(List<Match>);
  58. foreach (var s in sta)
  59. {
  60. //var y = Math.Tanh(Math.Pow(Math.E, (s.Value.Count) / (double)-(matches.Count * s.Key)));
  61. var y = Quantize(s.Value.Count, matches.Count, s.Key);
  62. Debug.WriteLine((s.Key, y));
  63. if (y > weight)
  64. {
  65. weight = y;
  66. bestSelect = s.Value;
  67. }
  68. }
  69. var a = new Alternative(bestSelect?.ToImmutableArray());
  70. return a;
  71. }
  72. private static double Quantize(int elementCount, int categorizedCount, int matchedCount)
  73. {
  74. return Math.Tanh(Math.Pow(Math.E, (elementCount) / (double)-(categorizedCount * matchedCount)));
  75. }
  76. /// <summary>
  77. /// 評估 <paramref name="pattern"/> 與 <paramref name="feed"/> 的符合程度並返回一個 <see cref="Match"/> 物件。
  78. /// </summary>
  79. /// <param name="pattern"></param>
  80. /// <param name="feed"></param>
  81. /// <returns></returns>
  82. protected virtual Match CountPatternMatch(IPattern pattern, IImmutableList<string> feed)
  83. {
  84. var matches = ImmutableArray.CreateBuilder<ISynonym>();
  85. using (var iterator = pattern.ToImmutable().GetEnumerator())
  86. {
  87. iterator.MoveNext();
  88. foreach (var word in feed)
  89. {
  90. if (iterator.Current.TryGetSynonym(word, out var s))
  91. {
  92. matches.Add(s);
  93. if (!iterator.MoveNext())
  94. break;
  95. }
  96. }
  97. }
  98. return new Match(pattern, matches.ToImmutable());
  99. }
  100. }
  101. }