// 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());
}
}
}