|
|
@@ -10,8 +10,86 @@ namespace Yuuna.Contracts.Optimization
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
using Yuuna.Contracts.Patterns;
|
|
|
- using Yuuna.Contracts.Plugins;
|
|
|
+ using Yuuna.Contracts.Modules;
|
|
|
using Yuuna.Contracts.Semantics;
|
|
|
+ using System.Linq;
|
|
|
+
|
|
|
+ public enum Status
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 無有效解。
|
|
|
+ /// </summary>
|
|
|
+ Invalid,
|
|
|
+ /// <summary>
|
|
|
+ /// 最佳解。表示與模式(Pattern)完全符合。
|
|
|
+ /// </summary>
|
|
|
+ Optimal,
|
|
|
+ /// <summary>
|
|
|
+ /// 近似解。表示缺少一個群組(Group)。
|
|
|
+ /// </summary>
|
|
|
+ Closest,
|
|
|
+ /// <summary>
|
|
|
+ /// 命題。表示具有兩個近似解(<see cref="Closest"/>)。
|
|
|
+ /// </summary>
|
|
|
+ Proposition,
|
|
|
+ /// <summary>
|
|
|
+ /// 悖論。表示具有多個最佳解(<see cref="Optimal"/>),這實際上屬於模組設計上的問題。
|
|
|
+ /// </summary>
|
|
|
+ Paradox,
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 沒有已安裝的模組。
|
|
|
+ /// </summary>
|
|
|
+ NoModuleInstalled = -1,
|
|
|
+ }
|
|
|
+
|
|
|
+ public class Alternative
|
|
|
+ {
|
|
|
+ public Status Status { get; }
|
|
|
+ public IImmutableList<Match> Matches { get; }
|
|
|
+
|
|
|
+ public Alternative(IImmutableList<Match> matches)
|
|
|
+ {
|
|
|
+ var count = matches?.Count ?? 0;
|
|
|
+ if (count.Equals(1))
|
|
|
+ {
|
|
|
+ var single = matches[0].Missing.Count;
|
|
|
+ if (single.Equals(0))
|
|
|
+ {
|
|
|
+ this.Status = Status.Optimal; // 最佳解
|
|
|
+
|
|
|
+ }
|
|
|
+ else if (single.Equals(1))
|
|
|
+ {
|
|
|
+ this.Status = Status.Closest;// 近似解(缺一組條件,詢問使用者)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (count.Equals(2))
|
|
|
+ {
|
|
|
+ if (matches.All(x => x.Missing.Count == 0))
|
|
|
+ {
|
|
|
+ this.Status = Status.Paradox;// 內部錯誤(多個意圖重複)
|
|
|
+ }
|
|
|
+ else if (matches.All(x => x.Missing.Count == 1))
|
|
|
+ {
|
|
|
+ this.Status = Status.Proposition;// 兩個近似解,詢問使用者(二選一 + 離開情境)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (count.Equals(0))
|
|
|
+ {
|
|
|
+ // 無有效模組
|
|
|
+ this.Status = Status.NoModuleInstalled;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 不採用
|
|
|
+ this.Status = Status.Invalid;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.Matches = matches;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
public class DefaultStrategy : IStrategy
|
|
|
{
|
|
|
@@ -20,16 +98,15 @@ namespace Yuuna.Contracts.Optimization
|
|
|
|
|
|
}
|
|
|
|
|
|
- public Match? FindBest(IEnumerable<PluginBase> plugins, IImmutableList<string> feed)
|
|
|
+ public Alternative FindBest(IEnumerable<ModuleBase> 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 match = this.CountPatternMatch(p, feed);
|
|
|
+ list.Add(match);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -42,17 +119,43 @@ namespace Yuuna.Contracts.Optimization
|
|
|
/// </summary>
|
|
|
/// <param name="matches"></param>
|
|
|
/// <returns></returns>
|
|
|
- protected virtual Match? SelectBestMatch(IImmutableList<Match> matches)
|
|
|
- {
|
|
|
- var sta = new SortedList<Match, int>();
|
|
|
- foreach (var j in matches)
|
|
|
+ protected virtual Alternative SelectBestMatch(IImmutableList<Match> matches)
|
|
|
+ {
|
|
|
+ //if(matches is null || matches.Count == 0)
|
|
|
+ // return //沒有安裝任何模組
|
|
|
+
|
|
|
+ var sta = new SortedList<int, List<Match>>();
|
|
|
+ foreach (var match in matches)
|
|
|
{
|
|
|
- if (!sta.ContainsKey(j))
|
|
|
- sta.Add(j, 1);
|
|
|
+ var key = match.SequentialMatches.Count;
|
|
|
+ if (!sta.ContainsKey(key))
|
|
|
+ {
|
|
|
+ sta.Add(key, new List<Match> { match });
|
|
|
+ }
|
|
|
else
|
|
|
- sta[j]++;
|
|
|
+ {
|
|
|
+ sta[key].Add(match);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ var weight = double.MinValue;
|
|
|
+ var bestSelect = default(List<Match>);
|
|
|
+ foreach (var s in sta)
|
|
|
+ {
|
|
|
+ var y = -( Math.Tanh(Math.Pow(Math.E, (s.Value.Count) / (double)-(matches.Count * s.Key))));
|
|
|
+ if (y > weight)
|
|
|
+ {
|
|
|
+ weight = y;
|
|
|
+ bestSelect = s.Value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return new Alternative(bestSelect?.ToImmutableArray());
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
//var tuple = new List<Tuple<Match, double>>();
|
|
|
//foreach (var s in sta)
|
|
|
//{
|
|
|
@@ -60,33 +163,35 @@ namespace Yuuna.Contracts.Optimization
|
|
|
// var y = Math.Tanh(Math.Pow(Math.E, x));
|
|
|
// tuple.Add(Tuple.Create(s.Key, y));
|
|
|
//}
|
|
|
-
|
|
|
//var bestSelect = tuple.OrderByDescending(x => x.Item2).FirstOrDefault();
|
|
|
-
|
|
|
//return bestSelect?.Item1;
|
|
|
|
|
|
- var hold = double.MinValue;
|
|
|
- var bestSelect = default(Match?);
|
|
|
- foreach (var s in sta)
|
|
|
- {
|
|
|
- var y = Math.Tanh(Math.Pow(Math.E, (s.Value) / (double)-(matches.Count * s.Key.SequentialMatches.Count)));
|
|
|
- if (y >= hold)
|
|
|
- {
|
|
|
- hold = y;
|
|
|
- bestSelect = s.Key;
|
|
|
- }
|
|
|
- }
|
|
|
- return bestSelect;
|
|
|
+
|
|
|
+ //var hold = double.MinValue;
|
|
|
+ //var bestSelect = default(Match);
|
|
|
+ //foreach (var s in sta)
|
|
|
+ //{
|
|
|
+ // var y = Math.Tanh(Math.Pow(Math.E, (s.Value) / (double)-(matches.Count * s.Key.Pattern.Count)));
|
|
|
+ // if (y > hold)
|
|
|
+ // {
|
|
|
+ // hold = y;
|
|
|
+ // bestSelect = s.Key;
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+
|
|
|
+ //if (bestSelect.SequentialMatches.Count == 0)
|
|
|
+ // return null;
|
|
|
+
|
|
|
+ //return bestSelect;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 評估 <paramref name="pattern"/> 與 <paramref name="feed"/> 的符合程度並給予一個分數,並返回一個 <see cref="Match"/> 物件。
|
|
|
- /// 若回傳 <see langword="null"/> 則此規則將不列入計算。
|
|
|
+ /// 評估 <paramref name="pattern"/> 與 <paramref name="feed"/> 的符合程度並返回一個 <see cref="Match"/> 物件。
|
|
|
/// </summary>
|
|
|
/// <param name="pattern"></param>
|
|
|
/// <param name="feed"></param>
|
|
|
/// <returns></returns>
|
|
|
- protected virtual Match? CalculatePatternMatch(IPattern pattern, IImmutableList<string> feed)
|
|
|
+ protected virtual Match CountPatternMatch(IPattern pattern, IImmutableList<string> feed)
|
|
|
{
|
|
|
var matches = ImmutableArray.CreateBuilder<ISynonym>();
|
|
|
|
|
|
@@ -103,6 +208,7 @@ namespace Yuuna.Contracts.Optimization
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
return new Match(pattern, matches.ToImmutable());
|
|
|
}
|
|
|
}
|