TKey
をIDictionary<TKey, TValue>
引数として返す拡張メソッドを実装しています。TValue
がの場合、メソッドは最大値のdouble
を返す可能性があります。TKey
それ以外の場合は、ランダムに を返しますTKey
。
public static TKey Sample<TKey>(this IDictionary<TKey, double> probabilityTable, Random r)
{
probabilityTable.Normalize();
var roll = r.NextDouble();
var temp = 0.0;
foreach (var key in probabilityTable.Keys)
{
temp += probabilityTable[key];
if (roll <= temp)
return key;
}
return default(TKey);
}
public static TKey Sample<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Random r)
{
return dictionary.Skip(r.Next(dictionary.Count)).FirstOrDefault().Key;
}
public static IDictionary<TKey, double> Normalize<TKey>(this IDictionary<TKey, double> probabilityTable)
{
if (probabilityTable.Any(x => x.Value < 0))
throw new ArgumentOutOfRangeException("probabilityTable", "Probability is expected to be positive.");
var sum = probabilityTable.Sum(x => x.Value);
if (Math.Abs(sum - 1) > 1e-8)
return probabilityTable.ToDictionary(x => x.Key, x => x.Value / sum);
if (Math.Abs(sum) < 1e-8)
return probabilityTable.ToDictionary(x => x.Key, x => 1.0 / probabilityTable.Count);
return probabilityTable;
}
問題は、Sample<TKey, TValue>
常に of でも呼び出されることdouble
ですTValue
。TValue
where句でexclude double型を指定できる方法はありますか? すなわちwhere TValue: !double
拡張機能を呼び出すコードは次のとおりです。
var r = new Random();
var pt = new Dictionary<char, double> {{'A', 0.1}, {'B', 0.2}, {'C', 0.7}};
var ct = new Dictionary<char, char> {{'A', 'D'}, {'B','E'}, {'C', 'F'}};
Console.WriteLine(pt.Sample(r)); // expected to return 'C' mostly but uniformly returns key
Console.WriteLine(ct.Sample(r));