2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-05-06 11:32:59 +00:00
This commit is contained in:
Ahmed Zamil 2022-10-29 17:53:06 +03:00
parent a645946a18
commit 584cd458de
15 changed files with 499 additions and 4 deletions

View File

@ -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>

View 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;
}
}
}
}

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

View 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; }
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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);
}
}

View 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);
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
});
}
}
}

View 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 });
}
}
}

View File

@ -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));
}
}
}

View 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);
}
}
}

View File

@ -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);