mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 11:32:59 +00:00
fuzzy
This commit is contained in:
parent
a645946a18
commit
584cd458de
@ -6,8 +6,17 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Fuzzy\FuzzyRule.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Processing\" />
|
||||
<Folder Include="Signals\Modulation\" />
|
||||
<Folder Include="Optimization\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Fuzzy\FuzzyRule.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
44
Esiur.Analysis/Fuzzy/ContinuousSet.cs
Normal file
44
Esiur.Analysis/Fuzzy/ContinuousSet.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public class ContinuousSet : INumericalSet<double>
|
||||
{
|
||||
public MembershipFunction Function { get; set; }
|
||||
|
||||
public double AlphaCut { get; set; } = double.MinValue;
|
||||
|
||||
|
||||
|
||||
public INumericalSet<double> Intersection(INumericalSet<double> with)
|
||||
{
|
||||
return new OperationSet(Operation.Intersection, this, with);
|
||||
}
|
||||
|
||||
public INumericalSet<double> Union(INumericalSet<double> with)
|
||||
{
|
||||
return new OperationSet(Operation.Union, this, with);
|
||||
}
|
||||
|
||||
public ContinuousSet(MembershipFunction function)
|
||||
{
|
||||
this.Function = function;
|
||||
}
|
||||
|
||||
public double this[double input]
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
var results = Function(input);
|
||||
|
||||
return results < AlphaCut ? 0 : results;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
67
Esiur.Analysis/Fuzzy/DiscreteSet.cs
Normal file
67
Esiur.Analysis/Fuzzy/DiscreteSet.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public class DiscreteSet : INumericalSet<double>, IEnumerable<KeyValuePair<double, double>>
|
||||
{
|
||||
Dictionary<double, double> vector = new Dictionary<double, double>();
|
||||
|
||||
public double this[double index]
|
||||
{
|
||||
get => vector.ContainsKey(index) ? vector[index] : 0;
|
||||
set
|
||||
{
|
||||
if (vector.ContainsKey(index))
|
||||
vector[index] = value;
|
||||
else
|
||||
vector.Add(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public double AlphaCut { get; set; }
|
||||
|
||||
|
||||
|
||||
public INumericalSet<double> Intersection(INumericalSet<double> with)
|
||||
{
|
||||
return new OperationSet(Operation.Intersection, new INumericalSet<double>[] { this, with });
|
||||
}
|
||||
|
||||
public INumericalSet<double> Union(INumericalSet<double> with)
|
||||
{
|
||||
return new OperationSet(Operation.Union, new INumericalSet<double>[] { this, with });
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return vector.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<double, double>> IEnumerable<KeyValuePair<double, double>>.GetEnumerator()
|
||||
{
|
||||
return vector.GetEnumerator();
|
||||
}
|
||||
|
||||
public KeyValuePair<double, double>[] Maximas
|
||||
{
|
||||
get {
|
||||
var max = vector.Values.Max();
|
||||
return vector.Where(x => x.Value == max).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValuePair<double, double>[] Minimas
|
||||
{
|
||||
get
|
||||
{
|
||||
var min = vector.Values.Min();
|
||||
return vector.Where(x => x.Value == min).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
12
Esiur.Analysis/Fuzzy/FuzzyElement.cs
Normal file
12
Esiur.Analysis/Fuzzy/FuzzyElement.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public class FuzzyElement
|
||||
{
|
||||
public double Degree { get; set; }
|
||||
public double Value { get; set; }
|
||||
}
|
||||
}
|
45
Esiur.Analysis/Fuzzy/FuzzyExtensions.cs
Normal file
45
Esiur.Analysis/Fuzzy/FuzzyExtensions.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public static class FuzzyExtensions
|
||||
{
|
||||
|
||||
public static double Or(this double value, double orValue) => value > orValue ? value : orValue;
|
||||
public static double And(this double value, double orValue) => value < orValue ? value : orValue;
|
||||
|
||||
public static double Is(this double value, INumericalSet<double> set) => set[value];
|
||||
|
||||
// Mamdani
|
||||
public static ContinuousSet Then(this double value, ContinuousSet set)
|
||||
=> new ContinuousSet(set.Function) { AlphaCut = value };// set.AlphaCut < value ? set.AlphaCut : value };
|
||||
|
||||
// TKS
|
||||
public static double Then(this double value, double constant)
|
||||
=> value * constant;
|
||||
|
||||
|
||||
public static INumericalSet<double> FuzzyUnion(this INumericalSet<double>[] sets)
|
||||
{
|
||||
return new OperationSet(Operation.Union, sets);
|
||||
}
|
||||
|
||||
public static INumericalSet<double> FuzzyIntersection(this INumericalSet<double> sets)
|
||||
{
|
||||
return new OperationSet(Operation.Intersection, sets);
|
||||
|
||||
}
|
||||
|
||||
public static DiscreteSet ToDiscrete(this INumericalSet<double> set, double from, double to, double step)
|
||||
{
|
||||
var rt = new DiscreteSet();
|
||||
for (var x = from; x <= to; x += step)
|
||||
rt[x] = set[x];
|
||||
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
}
|
28
Esiur.Analysis/Fuzzy/FuzzyRule.cs
Normal file
28
Esiur.Analysis/Fuzzy/FuzzyRule.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public class FuzzyRule
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public FuzzySet InputSet { get; set; }
|
||||
public FuzzySet OutputSet { get; set; }
|
||||
|
||||
public FuzzyRule(string name, FuzzySet input, FuzzySet output)
|
||||
{
|
||||
Name = name;
|
||||
InputSet = input;
|
||||
OutputSet = output;
|
||||
}
|
||||
|
||||
public FuzzySet Evaluate(double input)
|
||||
{
|
||||
var val = InputSet[input];
|
||||
var results = new FuzzySet(OutputSet.Function) { AlphaCut = OutputSet.AlphaCut < val ? OutputSet.AlphaCut : val };
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
12
Esiur.Analysis/Fuzzy/IFuzzyEvaluator.cs
Normal file
12
Esiur.Analysis/Fuzzy/IFuzzyEvaluator.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public interface IFuzzyEvaluator
|
||||
{
|
||||
|
||||
public double[] Evaluate(double[] crispValues);
|
||||
}
|
||||
}
|
16
Esiur.Analysis/Fuzzy/INumericalSet.cs
Normal file
16
Esiur.Analysis/Fuzzy/INumericalSet.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public interface INumericalSet<T>
|
||||
{
|
||||
public T this[T index] { get; }
|
||||
public double AlphaCut { get; set; }
|
||||
|
||||
public INumericalSet<T> Intersection(INumericalSet<T> with);
|
||||
public INumericalSet<T> Union(INumericalSet<T> with);
|
||||
|
||||
}
|
||||
}
|
14
Esiur.Analysis/Fuzzy/IVectorSet.cs
Normal file
14
Esiur.Analysis/Fuzzy/IVectorSet.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
internal interface IVectorSet: IEnumerable<double>
|
||||
{
|
||||
public double this[double index]
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
30
Esiur.Analysis/Fuzzy/MamdaniDefuzzifier.cs
Normal file
30
Esiur.Analysis/Fuzzy/MamdaniDefuzzifier.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public enum MamdaniDefuzzifierMethod
|
||||
{
|
||||
CenterOfGravity,
|
||||
FirstMaxima,
|
||||
LastMaxima,
|
||||
Bisector,
|
||||
MeanOfMaxima,
|
||||
}
|
||||
public class MamdaniDefuzzifier
|
||||
{
|
||||
|
||||
public static double Evaluate(INumericalSet<double>[] sets, MamdaniDefuzzifierMethod method, double from, double to, double step)
|
||||
{
|
||||
|
||||
var union = sets.FuzzyUnion();
|
||||
var output = union.ToDiscrete(from, to, step);
|
||||
var max = output.Maximas;
|
||||
return max[0].Key;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
43
Esiur.Analysis/Fuzzy/MembershipFunction.cs
Normal file
43
Esiur.Analysis/Fuzzy/MembershipFunction.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public delegate double MembershipFunction(double value);
|
||||
|
||||
public static class MembershipFunctions
|
||||
{
|
||||
public static MembershipFunction Triangular(double start, double peak, double end)
|
||||
{
|
||||
return new MembershipFunction(x =>
|
||||
{
|
||||
if (x < start || x > end) return 0;
|
||||
if (x < peak) return (x - start) / (peak - start);
|
||||
if (x > peak) return (end - x) / (end - peak);
|
||||
return 1; // x = peak
|
||||
});
|
||||
}
|
||||
|
||||
public static MembershipFunction Descending(double peak, double end)
|
||||
{
|
||||
return new MembershipFunction(x =>
|
||||
{
|
||||
if (x <= peak) return 1;
|
||||
if (x > peak && x < end) return (end - x) / (end - peak);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
public static MembershipFunction Ascending(double start, double peak)
|
||||
{
|
||||
return new MembershipFunction(x =>
|
||||
{
|
||||
if (x >= peak) return 1;
|
||||
if (x < peak && x > start) return (x - start) / (peak - start);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
61
Esiur.Analysis/Fuzzy/OperationSet.cs
Normal file
61
Esiur.Analysis/Fuzzy/OperationSet.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Fuzzy
|
||||
{
|
||||
public enum Operation
|
||||
{
|
||||
Intersection,
|
||||
Union
|
||||
}
|
||||
|
||||
public class OperationSet : INumericalSet<double>
|
||||
{
|
||||
|
||||
public Operation Operation { get; set; }
|
||||
|
||||
public INumericalSet<double>[] Sets { get; internal set; }
|
||||
|
||||
public double AlphaCut { get; set; }
|
||||
|
||||
public double this[double index]
|
||||
{
|
||||
get
|
||||
{
|
||||
double x = 0;
|
||||
if (Operation == Operation.Union)
|
||||
x = Sets.Max(x => x[index]);
|
||||
else if (Operation == Operation.Intersection)
|
||||
x = Sets.Min(x => x[index]);
|
||||
|
||||
// Alpha might be changed for this instance
|
||||
return x < AlphaCut ? 0 : x;
|
||||
}
|
||||
}
|
||||
|
||||
public OperationSet(Operation operation, params INumericalSet<double>[] sets)
|
||||
{
|
||||
Sets = sets;
|
||||
|
||||
if (operation == Operation.Intersection)
|
||||
AlphaCut = sets.Min(x => x.AlphaCut);
|
||||
else if (Operation == Operation.Union)
|
||||
AlphaCut = sets.Max(x => x.AlphaCut);
|
||||
|
||||
Operation = operation;
|
||||
}
|
||||
|
||||
public INumericalSet<double> Intersection(INumericalSet<double> with)
|
||||
{
|
||||
return new OperationSet(Operation.Intersection, new INumericalSet<double>[] { this, with });
|
||||
}
|
||||
|
||||
public INumericalSet<double> Union(INumericalSet<double> with)
|
||||
{
|
||||
return new OperationSet(Operation.Union, new INumericalSet<double>[] { this, with });
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ namespace Esiur.Analysis.Statistics
|
||||
|
||||
public static double Correlation(this double[] x, double[] y)
|
||||
{
|
||||
return x.Covariance(y) / (x.StdDiv() * y.StdDiv());
|
||||
return Covariance(x, y) / (StdDiv(x) * StdDiv(y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
87
Esiur.Analysis/Units/Frequency.cs
Normal file
87
Esiur.Analysis/Units/Frequency.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Analysis.Units
|
||||
{
|
||||
public enum FrequencyKind
|
||||
{
|
||||
Hertz,
|
||||
Kilohertz,
|
||||
Megahertz,
|
||||
Gigahertz,
|
||||
Terahertz
|
||||
}
|
||||
|
||||
public struct Frequency : IComparable
|
||||
{
|
||||
public double Value;
|
||||
|
||||
|
||||
public Frequency(double value, FrequencyKind kind = FrequencyKind.Hertz)
|
||||
{
|
||||
if (kind == FrequencyKind.Kilohertz)
|
||||
Value = value * 1000;
|
||||
else if (kind == FrequencyKind.Megahertz)
|
||||
Value = value * 1000000;
|
||||
else if (kind == FrequencyKind.Gigahertz)
|
||||
Value = value * 1000000000;
|
||||
else if (kind == FrequencyKind.Terahertz)
|
||||
Value = value * 1000000000000;
|
||||
else
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static implicit operator Frequency(double d) => new Frequency(d);
|
||||
public static implicit operator double(Frequency d) => d.Value;
|
||||
|
||||
//public static explicit operator PowerUnit(double d) => new PowerUnit(d, PowerUnitKind.Watt);
|
||||
//public static explicit operator double(PowerUnit d) => d.Value;
|
||||
|
||||
//public static PowerUnit operator +(PowerUnit a) => a;
|
||||
//public static PowerUnit operator -(PowerUnit a) => new PowerUnit(-a.num, a.den);
|
||||
|
||||
public static Frequency operator +(Frequency a, Frequency b)
|
||||
=> new Frequency(a.Value + b.Value);
|
||||
|
||||
public static Frequency operator -(Frequency a, Frequency b)
|
||||
=> new Frequency(a.Value - b.Value);
|
||||
|
||||
public static Frequency operator *(Frequency a, Frequency b)
|
||||
=> new Frequency(a.Value * b.Value);
|
||||
|
||||
public static Frequency operator /(Frequency a, Frequency b)
|
||||
{
|
||||
if (b.Value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return new Frequency(a.Value / b.Value);
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Value >= 1e12)
|
||||
return (Value / 1e12).ToString("F") + " Terahertz";
|
||||
else if (Value >= 1e9)
|
||||
return (Value / 1e9).ToString("F") + " Gigahertz";
|
||||
else if (Value >= 1e6)
|
||||
return (Value / 1e6).ToString("F") + " Megahertz";
|
||||
else if (Value >= 1e3)
|
||||
return (Value * 1e3).ToString("F") + " Kilohertz";
|
||||
else
|
||||
return Value.ToString("F") + " Hertz";
|
||||
}
|
||||
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj is Frequency p)
|
||||
return Value.CompareTo(p.Value);
|
||||
else
|
||||
return Value.CompareTo(obj);
|
||||
}
|
||||
}
|
||||
}
|
@ -47,6 +47,7 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Esiur.Analysis.Signals;
|
||||
using Esiur.Analysis.Units;
|
||||
using Esiur.Analysis.Fuzzy;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
@ -55,8 +56,6 @@ namespace Test
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
|
||||
|
||||
//var outage = Capacity.ComputeOutage(20000000, new Capacity.CSI[]
|
||||
//{
|
||||
// new Capacity.CSI(PowerUnit.FromDb(20), 0.1),
|
||||
@ -74,6 +73,34 @@ namespace Test
|
||||
new Capacity.CSI(PowerUnit.FromDb(0), 0.2),
|
||||
});
|
||||
|
||||
|
||||
var low = new ContinuousSet(MembershipFunctions.Descending(20, 40));
|
||||
var mid = new ContinuousSet(MembershipFunctions.Triangular(20, 40, 60));
|
||||
var high = new ContinuousSet(MembershipFunctions.Ascending(40, 60));
|
||||
|
||||
var bad = new ContinuousSet(MembershipFunctions.Descending(0, 30));
|
||||
var ok = new ContinuousSet(MembershipFunctions.Triangular(20, 50, 80));
|
||||
var excelent = new ContinuousSet(MembershipFunctions.Ascending(70, 100));
|
||||
|
||||
var small = new ContinuousSet(MembershipFunctions.Descending(100, 200));
|
||||
var avg = new ContinuousSet(MembershipFunctions.Triangular(150, 200, 250));
|
||||
var big = new ContinuousSet(MembershipFunctions.Ascending(200, 300));
|
||||
|
||||
//var speedIsLowThenSmall = new FuzzyRule("Low=>Small", low, small);
|
||||
|
||||
double temp = 34;
|
||||
double rating = 70;
|
||||
|
||||
var v = MamdaniDefuzzifier.Evaluate(new INumericalSet<double>[]
|
||||
{
|
||||
temp.Is(low).Or(rating.Is(bad)).Then(small),
|
||||
temp.Is(mid).Or(rating.Is(ok)).Then(avg),
|
||||
temp.Is(high).Or(rating.Is(excelent)).Then(big),
|
||||
}, MamdaniDefuzzifierMethod.FirstMaxima, 0, 600, 1);
|
||||
|
||||
|
||||
Console.WriteLine(v);
|
||||
|
||||
// Create stores to keep objects.
|
||||
var system = await Warehouse.Put("sys", new MemoryStore());
|
||||
var server = await Warehouse.Put("sys/server", new DistributedServer());
|
||||
@ -111,7 +138,7 @@ namespace Test
|
||||
sender.Send("Hello");
|
||||
});
|
||||
|
||||
var ok = await Warehouse.Open();
|
||||
await Warehouse.Open();
|
||||
|
||||
// Start testing
|
||||
TestClient(service);
|
||||
|
Loading…
x
Reference in New Issue
Block a user