|
@@ -3,12 +3,127 @@
|
|
|
|
|
|
namespace Yuuna.Contracts.Optimization
|
|
|
{
|
|
|
+ using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.Immutable;
|
|
|
+ using System.Diagnostics.CodeAnalysis;
|
|
|
+ using System.Linq;
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
using Yuuna.Contracts.Patterns;
|
|
|
using Yuuna.Contracts.Plugins;
|
|
|
+ using Yuuna.Contracts.Semantics;
|
|
|
+
|
|
|
+ public abstract class Plan
|
|
|
+ {
|
|
|
+ public Plan()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void FindBest(IEnumerable<PluginBase> plugins, IImmutableList<string> feed)
|
|
|
+ {
|
|
|
+ var list = ImmutableArray.CreateBuilder<Match>();
|
|
|
+ foreach (var plugin in plugins)
|
|
|
+ {
|
|
|
+ foreach (var p in plugin.Patterns.ToImmutable())
|
|
|
+ {
|
|
|
+ var score = this.CalculatePatternMatch(p, feed);
|
|
|
+ if (score.HasValue)
|
|
|
+ list.Add(score.Value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var e = this.E(list.ToImmutable());
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void E(IImmutableList<Match> matches)
|
|
|
+ {
|
|
|
+ var sta = new SortedList<Match, int>();
|
|
|
+ foreach (var j in matches)
|
|
|
+ {
|
|
|
+ if (!sta.ContainsKey(j))
|
|
|
+ sta.Add(j, 1);
|
|
|
+ else
|
|
|
+ sta[j]++;
|
|
|
+ }
|
|
|
+
|
|
|
+ var tuple = new List<Tuple<Match, double>>();
|
|
|
+ foreach (var s in sta)
|
|
|
+ {
|
|
|
+ var x = (s.Value) / (double)-(matches.Count * s.Key.SequentialMatches.Count);
|
|
|
+ var y = Math.Tanh(Math.Pow(Math.E, x));
|
|
|
+ tuple.Add(Tuple.Create(s.Key, y));
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var s in tuple.OrderByDescending(x => x.Item2))
|
|
|
+ {
|
|
|
+ Console.WriteLine(s);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 評估 <paramref name="pattern"/> 與 <paramref name="feed"/> 的符合程度並給予一個分數,並返回一個 <see cref="Match"/> 物件。
|
|
|
+ /// 若回傳 <see langword="null"/> 則此規則將不列入計算。
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="pattern"></param>
|
|
|
+ /// <param name="feed"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ protected virtual Match? CalculatePatternMatch(IPattern pattern, IImmutableList<string> feed)
|
|
|
+ {
|
|
|
+ var matches = ImmutableArray.CreateBuilder<ISynonym>();
|
|
|
+
|
|
|
+ using (var iterator = pattern.ToImmutable().GetEnumerator())
|
|
|
+ {
|
|
|
+ iterator.MoveNext();
|
|
|
+ foreach (var word in feed)
|
|
|
+ {
|
|
|
+ if (iterator.Current.TryGetSynonym(word, out var s))
|
|
|
+ {
|
|
|
+ matches.Add(s);
|
|
|
+ if (!iterator.MoveNext())
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new Match(pattern, matches.ToImmutable());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public struct Match : IEquatable<Match>
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 比較的文法。
|
|
|
+ /// </summary>
|
|
|
+ public IPattern Pattern { get; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 表示缺少的群組物件清單。
|
|
|
+ /// </summary>
|
|
|
+ public IImmutableList<IGroup> Missing { get; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// </summary>
|
|
|
+ public IImmutableList<ISynonym> SequentialMatches { get; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ ///
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="pattern">比對的目標</param>
|
|
|
+ /// <param name="matches">從頭逐一比對後符合的項目</param>
|
|
|
+ public Match(IPattern pattern, IImmutableList<ISynonym> matches)
|
|
|
+ {
|
|
|
+ this.Pattern = pattern;
|
|
|
+ this.SequentialMatches = matches;
|
|
|
+ this.Missing = pattern.ToImmutable().Except(matches.Select(x => x.Owner)).ToImmutableArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool Equals(Match other)
|
|
|
+ {
|
|
|
+ return this.Pattern.Equals(other.Pattern);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
public abstract class StrategyBase
|
|
|
{
|
|
@@ -20,6 +135,13 @@ namespace Yuuna.Contracts.Optimization
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 評估 <paramref name="plugin"/> 中最佳的
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="plugin"></param>
|
|
|
+ /// <param name="words"></param>
|
|
|
+ /// <param name="set"></param>
|
|
|
+ /// <returns></returns>
|
|
|
internal IImmutableList<IScore> Assess(PluginBase plugin, IImmutableList<string> words, IPatternSet set)
|
|
|
{
|
|
|
var scores = new List<IScore>();
|
|
@@ -32,16 +154,18 @@ namespace Yuuna.Contracts.Optimization
|
|
|
}
|
|
|
scores.Sort(this.Comparer);
|
|
|
|
|
|
+
|
|
|
+
|
|
|
return scores.ToImmutableArray();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 評估
|
|
|
+ /// 評估 <paramref name="pattern"/> 與 <paramref name="words"/> 的符合程度,並返回評估後的分數物件
|
|
|
/// </summary>
|
|
|
/// <param name="words"></param>
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
- private IScore Evaluate(PluginBase plugin, IImmutableList<string> words, IPattern pattern)
|
|
|
- {
|
|
|
+ private IScore Evaluate(IImmutableList<string> words, IPattern pattern)
|
|
|
+ {
|
|
|
var matches = ImmutableArray.CreateBuilder<IPair>();
|
|
|
|
|
|
using (var iterator = pattern.ToImmutable().GetEnumerator())
|
|
@@ -58,7 +182,7 @@ namespace Yuuna.Contracts.Optimization
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return new Score(plugin, matches.ToImmutable(), pattern);
|
|
|
+ return new Score(matches.ToImmutable(), pattern);
|
|
|
}
|
|
|
}
|
|
|
}
|