// Author: Orlys // Github: https://github.com/Orlys namespace Yuuna.Contracts.Optimization { using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Yuuna.Contracts.Patterns; using Yuuna.Contracts.Modules; using Yuuna.Contracts.Semantics; using System.Linq; public enum Status { /// /// 無有效解。 /// Invalid, /// /// 最佳解。表示與模式(Pattern)完全符合。 /// Optimal, /// /// 近似解。表示缺少一個群組(Group)。 /// Closest, /// /// 命題。表示具有兩個近似解()。 /// Proposition, /// /// 悖論。表示具有多個最佳解(),這實際上屬於模組設計上的問題。 /// Paradox, /// /// 沒有已安裝的模組。 /// NoModuleInstalled = -1, } public class Alternative { public Status Status { get; } public IImmutableList Matches { get; } public Alternative(IImmutableList 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 { public DefaultStrategy() { } public Alternative FindBest(IEnumerable patternSetCollection, IImmutableList feed) { var list = ImmutableArray.CreateBuilder(); foreach (var pattern in patternSetCollection) { foreach (var p in pattern.ToImmutable()) { var match = this.CountPatternMatch(p, feed); list.Add(match); } } var e = this.SelectBestMatch(list.ToImmutable()); return e; } /// /// /// /// /// protected virtual Alternative SelectBestMatch(IImmutableList matches) { //if(matches is null || matches.Count == 0) // return //沒有安裝任何模組 var sta = new SortedList>(); foreach (var match in matches) { var key = match.SequentialMatches.Count; if (!sta.ContainsKey(key)) { sta.Add(key, new List { match }); } else { sta[key].Add(match); } } var weight = double.MinValue; var bestSelect = default(List); 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>(); //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)); //} //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.Pattern.Count))); // if (y > hold) // { // hold = y; // bestSelect = s.Key; // } //} //if (bestSelect.SequentialMatches.Count == 0) // return null; //return bestSelect; } /// /// 評估 的符合程度並返回一個 物件。 /// /// /// /// protected virtual Match CountPatternMatch(IPattern pattern, IImmutableList feed) { var matches = ImmutableArray.CreateBuilder(); 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()); } } }