diff --git a/Esiur.Analysis.Test/Esiur.Analysis.Test.csproj b/Esiur.Analysis.Test/Esiur.Analysis.Test.csproj
new file mode 100644
index 0000000..f11fa12
--- /dev/null
+++ b/Esiur.Analysis.Test/Esiur.Analysis.Test.csproj
@@ -0,0 +1,19 @@
+
+
+
+ WinExe
+ net6.0-windows
+ enable
+ true
+ enable
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Esiur.Analysis.Test/FMain.Designer.cs b/Esiur.Analysis.Test/FMain.Designer.cs
new file mode 100644
index 0000000..77a7cb0
--- /dev/null
+++ b/Esiur.Analysis.Test/FMain.Designer.cs
@@ -0,0 +1,72 @@
+namespace Esiur.Analysis.Test
+{
+ partial class FMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.formsPlot1 = new ScottPlot.FormsPlot();
+ this.button1 = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // formsPlot1
+ //
+ this.formsPlot1.Location = new System.Drawing.Point(57, 47);
+ this.formsPlot1.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4);
+ this.formsPlot1.Name = "formsPlot1";
+ this.formsPlot1.Size = new System.Drawing.Size(1006, 576);
+ this.formsPlot1.TabIndex = 0;
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(12, 316);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(85, 31);
+ this.button1.TabIndex = 1;
+ this.button1.Text = "button1";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // FMain
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1175, 658);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.formsPlot1);
+ this.Name = "FMain";
+ this.Text = "PID Controller with Fuzzy";
+ this.Load += new System.EventHandler(this.FMain_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private ScottPlot.FormsPlot formsPlot1;
+ private Button button1;
+ }
+}
\ No newline at end of file
diff --git a/Esiur.Analysis.Test/FMain.cs b/Esiur.Analysis.Test/FMain.cs
new file mode 100644
index 0000000..12752ad
--- /dev/null
+++ b/Esiur.Analysis.Test/FMain.cs
@@ -0,0 +1,345 @@
+using Esiur.Analysis.DSP;
+using Esiur.Analysis.Fuzzy;
+using Esiur.Analysis.Optimization;
+using Esiur.Analysis.Signals;
+using Esiur.Analysis.Units;
+using Microsoft.VisualBasic.Logging;
+using ScottPlot;
+using ScottPlot.Drawing.Colormaps;
+using System.Security.Cryptography;
+using Esiur.Analysis.Statistics;
+using System.Diagnostics;
+
+namespace Esiur.Analysis.Test
+{
+ public partial class FMain : Form
+ {
+ public FMain()
+ {
+ InitializeComponent();
+
+ //var outage = Capacity.ComputeOutage(20000000, new Capacity.CSI[]
+ //{
+ // new Capacity.CSI(PowerUnit.FromDb(20), 0.1),
+ // new Capacity.CSI(PowerUnit.FromDb(15), 0.15),
+ // new Capacity.CSI(PowerUnit.FromDb(10), 0.25),
+ // new Capacity.CSI(PowerUnit.FromDb(5), 0.25),
+ // new Capacity.CSI(PowerUnit.FromDb(0), 0.15),
+ // new Capacity.CSI(PowerUnit.FromDb(-5), 0.1),
+ //});
+ var outage = Capacity.ComputeOutage(1, new Capacity.CSI[]
+ {
+ new Capacity.CSI(PowerUnit.FromDb(30), 0.2),
+ new Capacity.CSI(PowerUnit.FromDb(20), 0.3),
+ new Capacity.CSI(PowerUnit.FromDb(10), 0.3),
+ 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(100, 200, 300));
+ var big = new ContinuousSet(MembershipFunctions.Ascending(200, 300));
+
+ //var speedIsLowThenSmall = new FuzzyRule("Low=>Small", low, small);
+
+ double rating = 80;
+
+ for (double temp = 60; temp < 100; temp++)
+ {
+ var v = MamdaniDefuzzifier.Evaluate(new INumericalSet[]
+ {
+ temp.Is(low).And(rating.Is(bad)).Then(small),
+ temp.Is(mid).And(rating.Is(ok)).Then(avg),
+ temp.Is(high).And(rating.Is(excelent)).Then(big),
+ }, MamdaniDefuzzifierMethod.CenterOfGravity, 100, 300, 1);
+
+ }
+
+ }
+
+ private void FMain_Load(object sender, EventArgs e)
+ {
+
+ var lowErr = new ContinuousSet(MembershipFunctions.Descending(-5, 4.5));
+ var midErr = new ContinuousSet(MembershipFunctions.Triangular(-4, 6.5, 16.5));
+ var highErr = new ContinuousSet(MembershipFunctions.Ascending(8, 18));
+
+ var lowAccErr = new ContinuousSet(MembershipFunctions.Descending(0, 0.02));
+ var midAccErr = new ContinuousSet(MembershipFunctions.Triangular(0.02, 0.04, 0.06));
+ var highAccErr = new ContinuousSet(MembershipFunctions.Ascending(0.04, 0.06));
+
+ var small = new ContinuousSet(MembershipFunctions.Descending(0.1, 0.5));
+ var avg = new ContinuousSet(MembershipFunctions.Triangular(0.1, 0.5, 1.1));
+ var big = new ContinuousSet(MembershipFunctions.Ascending(-10, 1.1));
+
+
+ var x = Enumerable.Range(0, 1000).Select(x => x * 0.01).ToArray();
+
+
+ var step = Enumerable.Repeat(1, 1000).Select(x => (double)x).ToArray();
+ step[0] = 0;
+
+ var motor = new TransferFunction(new double[] { 1, 2 }, new double[] { 1, 1, 2 }, 0.01);
+ var motorPID = new TransferFunction(new double[] { 1, 2 }, new double[] { 1, 1, 2 }, 0.01);
+ var motorFuzzyPID = new TransferFunction(new double[] { 1, 2 }, new double[] { 1, 1, 2 }, 0.01);
+
+ //double Kp = 2, Ki = 0.4, Kd = 0.4;
+
+ double Ki = -1.9181372, Kp = 18.625, Kd = 0.38281253;
+
+
+ var pid = new TransferFunction(new double[] { Kd, Kp, Ki }, new double[] { 1, 1 }, 0.01);
+ var fuzzyPID = new TransferFunction(new double[] { Kd, Kp, Ki }, new double[] { 1, 1 }, 0.01);
+
+
+ var sysOut = new double[step.Length];
+ var sysOutFuzzyPID = new double[step.Length];
+ var sysOutPID = new double[step.Length];
+
+ var pidOut = new double[step.Length];
+ var pidOutFuzzy = new double[step.Length];
+ var errorOutPID = new double[step.Length];
+
+ var errOut = new double[step.Length];
+ var errAccOut = new double[step.Length];
+
+ //var errorAccOut = new double[step.Length];
+
+ var errorOutFuzzy = new double[step.Length];
+ var errorOutAccFuzzy = new double[step.Length];
+
+ for (var i = 0; i < step.Length; i++)
+ {
+ sysOut[i] = motor.Evaluate(step[i]);
+ errOut[i] = step[i] - sysOut[i];
+ errAccOut[i] = errOut[i] - (i == 0 ? 0 : errOut[i - 1]);
+
+ sysOutPID[i] = motorPID.Evaluate(step[i] + (i == 0 ? 0 : pidOut[i - 1]));
+ sysOutFuzzyPID[i] = motorFuzzyPID.Evaluate(step[i] + (i == 0 ? 0 : pidOutFuzzy[i - 1]));
+
+
+ errorOutPID[i] = (step[i] - sysOutPID[i]);
+ errorOutFuzzy[i] = (step[i] - sysOutFuzzyPID[i]);
+ errorOutAccFuzzy[i] = (errorOutFuzzy[i] - (i == 0 ? 0 : errorOutFuzzy[i - 1]));
+
+ pidOut[i] = pid.Evaluate(errorOutPID[i]);
+ pidOutFuzzy[i] = fuzzyPID.Evaluate(errorOutFuzzy[i]);
+
+
+ var k = MamdaniDefuzzifier.Evaluate(new INumericalSet[]
+ {
+ errorOutFuzzy[i].Is(lowErr).And(errorOutAccFuzzy[i].Is(lowAccErr)).Then(small),
+ errorOutFuzzy[i].Is(lowErr).And(errorOutAccFuzzy[i].Is(midAccErr)).Then(small),
+ errorOutFuzzy[i].Is(lowErr).And(errorOutAccFuzzy[i].Is(highAccErr)).Then(avg),
+ errorOutFuzzy[i].Is(midErr).And(errorOutAccFuzzy[i].Is(lowAccErr)).Then(small),
+ errorOutFuzzy[i].Is(midErr).And(errorOutAccFuzzy[i].Is(midAccErr)).Then(avg),
+ errorOutFuzzy[i].Is(midErr).And(errorOutAccFuzzy[i].Is(highAccErr)).Then(big),
+ errorOutFuzzy[i].Is(highAccErr).And(errorOutAccFuzzy[i].Is(lowAccErr)).Then(avg),
+ errorOutFuzzy[i].Is(highAccErr).And(errorOutAccFuzzy[i].Is(midAccErr)).Then(big),
+ errorOutFuzzy[i].Is(highAccErr).And(errorOutAccFuzzy[i].Is(highAccErr)).Then(big),
+ }, MamdaniDefuzzifierMethod.CenterOfGravity, 0, 1, 0.05);
+
+ fuzzyPID.InputCoefficients[1] = k;
+ fuzzyPID.InputCoefficients[1] = k;
+ fuzzyPID.InputCoefficients[1] = k;
+ }
+
+ Debug.WriteLine($"Error Values Min: {errOut.Min()} Max: {errOut.Max()} ");
+ Debug.WriteLine($"Error Acc Values Min: {errAccOut.Min()} Max: {errAccOut.Max()} ");
+
+ formsPlot1.Plot.AddScatter(x, sysOut, Color.Red);
+ formsPlot1.Plot.AddScatter(x, sysOutPID, Color.Blue);
+ formsPlot1.Plot.AddScatter(x, sysOutFuzzyPID, Color.Green);
+
+ formsPlot1.Refresh();
+
+ }
+
+
+ struct KK
+ {
+ public float Ki;
+ public float Kp;
+ public float Kd;
+
+ public override string ToString()
+ {
+ return $"Ki {Ki} Kp {Kp} Kd {Kd}";
+ }
+ }
+
+ struct FuzzyChromosome
+ {
+ public sbyte KiInputErrPosition;
+ public sbyte KiInputErrScale;
+
+ public sbyte KiInputErrAccPosition;
+ public sbyte KiInputErrAccScale;
+
+ public sbyte KiOutputPosition;
+ public sbyte KiOutputScale;
+ }
+
+ private double CalculateFuzzyPIDStepError(FuzzyChromosome config, double errStart, double errEnd)
+ {
+ var errPos = config.KiInputErrPosition * 0.1;
+ var errScale = config.KiInputErrPosition * 0.1;
+
+ var lowErr = new ContinuousSet(MembershipFunctions.Descending(config.KiInputErrPosition * 0.1, config.kiLowStart * 0.1 + Math.Abs(config.kiLowEnd * 0.1)));
+ var midErr = new ContinuousSet(MembershipFunctions.Triangular(config.KiInputErrPosition * 0.1, config.kiMidStart * 0.1 + Math.Abs(config.kiMidMid * 0.1), config.kiMidStart * 0.1 + Math.Abs(config.kiMidMid * 0.1) + Math.Abs(config.kiMidEnd * 0.1)));
+ var highErr = new ContinuousSet(MembershipFunctions.Ascending(config.KiInputErrPosition * 0.1, config.kiHiStart * 0.1 + Math.Abs(config.kiHiEnd * 0.1)));
+
+ var lowAccErr = new ContinuousSet(MembershipFunctions.Descending(config.KiInputErrAccPosition * 0.1, Math.Abs(config.kiLowAccStart * 0.1) + Math.Abs(config.kiLowAccEnd * 0.1)));
+ var midAccErr = new ContinuousSet(MembershipFunctions.Triangular(config.KiInputErrAccPosition * 0.1, Math.Abs(config.kiMidAccStart * 0.1) + Math.Abs(config.kiMidAccMid * 0.1), config.kiMidAccStart * 0.1 + Math.Abs(config.kiMidAccMid * 0.1) + Math.Abs(config.kiMidAccEnd * 0.1)));
+ var highAccErr = new ContinuousSet(MembershipFunctions.Ascending(config.KiInputErrAccPosition * 0.1, config.kiHiAccStart * 0.1 + Math.Abs(config.kiHiAccEnd * 0.1)));
+
+ var small = new ContinuousSet(MembershipFunctions.Descending(config.kiSmallStart * 0.1, config.kiSmallStart * 0.1 + Math.Abs(config.kiSmallEnd * 0.1)));
+ var avg = new ContinuousSet(MembershipFunctions.Triangular(config.kiAvgStart * 0.1, config.kiAvgStart * 0.1 + Math.Abs(config.kiAvgMid * 0.1), config.kiAvgStart * 0.1 + Math.Abs(config.kiAvgMid * 0.1) + Math.Abs(config.kiAvgEnd * 0.1)));
+ var big = new ContinuousSet(MembershipFunctions.Ascending(config.kiBigStart * 0.1, config.kiBigStart * 0.1 + Math.Abs(config.kiBigEnd * 0.1)));
+
+ double Ki = -1.9181372, Kp = 18.625, Kd = 0.38281253;
+
+ var step = Enumerable.Repeat(1, 1000).Select(x => (double)x).ToArray();
+ step[0] = 0;
+
+ var motor = new TransferFunction(new double[] { 1, 2 }, new double[] { 1, 1, 2 }, 0.01);
+ var fuzzyPID = new TransferFunction(new double[] { Kd, Kp, Ki }, new double[] { 1, 1 }, 0.01);
+
+ var sysOutFuzzyPID = new double[step.Length];
+
+ var pidOut = new double[step.Length];
+ var pidOutFuzzy = new double[step.Length];
+
+ var errorOutFuzzy = new double[step.Length];
+ var errorOutAccFuzzy = new double[step.Length];
+
+ for (var i = 0; i < step.Length; i++)
+ {
+ sysOutFuzzyPID[i] = motor.Evaluate(step[i] + (i == 0 ? 0 : pidOutFuzzy[i - 1]));
+
+
+ errorOutFuzzy[i] = (step[i] - sysOutFuzzyPID[i]);
+ errorOutAccFuzzy[i] = (errorOutFuzzy[i] - (i == 0 ? 0 : errorOutFuzzy[i - 1]));
+
+ pidOutFuzzy[i] = fuzzyPID.Evaluate(errorOutFuzzy[i]);
+
+
+ var k = MamdaniDefuzzifier.Evaluate(new INumericalSet[]
+ {
+ errorOutFuzzy[i].Is(lowErr).And(errorOutAccFuzzy[i].Is(lowAccErr)).Then(small),
+ errorOutFuzzy[i].Is(lowErr).And(errorOutAccFuzzy[i].Is(midAccErr)).Then(small),
+ errorOutFuzzy[i].Is(lowErr).And(errorOutAccFuzzy[i].Is(highAccErr)).Then(avg),
+ errorOutFuzzy[i].Is(midErr).And(errorOutAccFuzzy[i].Is(lowAccErr)).Then(small),
+ errorOutFuzzy[i].Is(midErr).And(errorOutAccFuzzy[i].Is(midAccErr)).Then(avg),
+ errorOutFuzzy[i].Is(midErr).And(errorOutAccFuzzy[i].Is(highAccErr)).Then(big),
+ errorOutFuzzy[i].Is(highAccErr).And(errorOutAccFuzzy[i].Is(lowAccErr)).Then(avg),
+ errorOutFuzzy[i].Is(highAccErr).And(errorOutAccFuzzy[i].Is(midAccErr)).Then(big),
+ errorOutFuzzy[i].Is(highAccErr).And(errorOutAccFuzzy[i].Is(highAccErr)).Then(big),
+ }, MamdaniDefuzzifierMethod.CenterOfGravity, -100, 100, 0.5);
+
+ fuzzyPID.InputCoefficients[1] = k;
+ //fuzzyPID.InputCoefficients[1] = k;
+ //fuzzyPID.InputCoefficients[1] = k;
+ }
+
+ return errorOutFuzzy.RMS();
+
+ }
+
+ private double CalculatePIDStepError(double Kd, double Kp, double Ki)
+ {
+ var step = Enumerable.Repeat(1, 1000).Select(x => (double)x).ToArray();
+ step[0] = 0;
+
+ var motor = new TransferFunction(new double[] { 1, 2 }, new double[] { 1, 1, 2 }, 0.01);
+
+ var sysOutPID = new double[step.Length];
+
+ var pidOut = new double[step.Length];
+ var errorOutPID = new double[step.Length];
+ var pid = new TransferFunction(new double[] { Kd, Kp, Ki }, new double[] { 1, 1 }, 0.01);
+
+ for (var i = 0; i < step.Length; i++)
+ {
+ sysOutPID[i] = motor.Evaluate(step[i] + (i == 0 ? 0 : pidOut[i - 1]));
+
+ if (double.IsInfinity(sysOutPID[i]))
+ Console.WriteLine();
+
+ errorOutPID[i] = (step[i] - sysOutPID[i]);
+
+ if (double.IsNaN(errorOutPID[i]))
+ Console.WriteLine();
+
+ pidOut[i] = pid.Evaluate(errorOutPID[i]);
+
+ if (double.IsInfinity(pidOut[i]))
+ Console.WriteLine();
+
+ }
+
+ return errorOutPID.RMS();
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+
+ //var gen = new Genetic(100, k =>
+ //{
+ // if (float.IsNaN(k.Ki) || float.IsNaN(k.Kp) || float.IsNaN(k.Kd))
+ // return (double.MaxValue);
+
+
+ // var r = CalculatePIDStepError(k.Kd, k.Kp, k.Ki);
+ // if (double.IsNaN(r))
+ // Console.WriteLine();
+ // return r;
+ //});
+
+ var gen = new Genetic(100, k =>
+ {
+ if (float.IsNaN(k.kiAvgEnd)
+ || float.IsNaN(k.kiAvgMid)
+ || float.IsNaN(k.kiAvgStart)
+ || float.IsNaN(k.kiBigEnd)
+ || float.IsNaN(k.kiBigStart)
+ || float.IsNaN(k.kiHiAccEnd)
+ || float.IsNaN(k.kiHiAccStart)
+ || float.IsNaN(k.kiHiEnd)
+ || float.IsNaN(k.kiHiStart)
+ || float.IsNaN(k.kiLowAccEnd)
+ || float.IsNaN(k.kiLowAccStart)
+ || float.IsNaN(k.kiLowEnd)
+ || float.IsNaN(k.kiLowStart)
+ || float.IsNaN(k.kiMidAccEnd)
+ || float.IsNaN(k.kiMidAccMid)
+ || float.IsNaN(k.kiMidAccStart)
+ || float.IsNaN(k.kiMidEnd)
+ || float.IsNaN(k.kiMidMid)
+ || float.IsNaN(k.kiMidStart)
+ || float.IsNaN(k.kiSmallEnd)
+ || float.IsNaN(k.kiSmallStart))
+ return (double.MaxValue);
+
+
+ var r = CalculateFuzzyPIDStepError(k);
+ if (double.IsNaN(r))
+ Console.WriteLine();
+ return r;
+ });
+
+
+ var ev = gen.Evaluate(1000);
+
+ Console.WriteLine(ev);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Esiur.Analysis.Test/FMain.resx b/Esiur.Analysis.Test/FMain.resx
new file mode 100644
index 0000000..f298a7b
--- /dev/null
+++ b/Esiur.Analysis.Test/FMain.resx
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Esiur.Analysis.Test/Program.cs b/Esiur.Analysis.Test/Program.cs
new file mode 100644
index 0000000..959e116
--- /dev/null
+++ b/Esiur.Analysis.Test/Program.cs
@@ -0,0 +1,17 @@
+namespace Esiur.Analysis.Test
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new FMain());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Esiur.Analysis/Signals/DSP.cs b/Esiur.Analysis/DSP/Functions.cs
similarity index 84%
rename from Esiur.Analysis/Signals/DSP.cs
rename to Esiur.Analysis/DSP/Functions.cs
index ee6fa6a..8ec331c 100644
--- a/Esiur.Analysis/Signals/DSP.cs
+++ b/Esiur.Analysis/DSP/Functions.cs
@@ -2,9 +2,9 @@
using System.Collections.Generic;
using System.Text;
-namespace Esiur.Analysis.Signals
+namespace Esiur.Analysis.DSP
{
- public static class DSP
+ public static class Functions
{
public static double[] ConvolveMany(params double[][] signals)
{
@@ -27,9 +27,11 @@ namespace Esiur.Analysis.Signals
for (var i = 0; i < length; i++)
{
- for (var j = 0; j < signal.Length && i - j >= 0 && i - j < filter.Length; j++)
+
+ for (var j = 0; j < signal.Length; j++)
{
- rt[i] = signal[j] * filter[i - j];
+ if (i - j >= 0 && i - j < filter.Length)
+ rt[i] += signal[j] * filter[i - j];
}
}
diff --git a/Esiur.Analysis/DSP/TransferFunction.cs b/Esiur.Analysis/DSP/TransferFunction.cs
new file mode 100644
index 0000000..6781a09
--- /dev/null
+++ b/Esiur.Analysis/DSP/TransferFunction.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.WebSockets;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml.Schema;
+
+namespace Esiur.Analysis.DSP
+{
+ public class TransferFunction
+ {
+
+ public double Step { get; set; }
+
+ double[] inputs;
+ double[] outputs;
+
+ public double[] InputCoefficients { get; set; }
+ public double[] OutputCoefficients { get; set; }
+
+ public TransferFunction(double[] numerator, double[] denominator, double step = 0.01)
+ {
+ inputs = new double[numerator.Length];
+ outputs = new double[denominator.Length];
+
+ InputCoefficients = numerator.Reverse().ToArray();
+ OutputCoefficients = denominator.Reverse().ToArray();
+
+ Step = step;
+ }
+
+ public double Evaluate(double value)
+ {
+ var xs = new double[inputs.Length];
+ xs[0] = value;// * InputCoefficients.Last();
+
+
+ // diffrentiate
+ for(var i = 1; i < xs.Length; i++)
+ xs[i] = (xs[i - 1] - inputs[i - 1]) / Step;
+
+ var ys = new double[outputs.Length];
+
+ // integrate
+ for (var i = outputs.Length - 2; i >= 0; i--)
+ {
+ var iy = outputs[i] + (Step * outputs[i + 1]);
+ if (double.IsNaN(iy) || double.IsInfinity(iy))
+ ys[i] = outputs[i];
+ else
+ ys[i] = iy;
+ }
+
+ var v = xs.Zip(InputCoefficients, (x, c) => x * c).Sum() - ys.Zip(OutputCoefficients, (y, c) => y * c).Sum();
+
+ if (double.IsNaN(v) || double.IsInfinity(v))
+ ys[ys.Length - 1] = outputs[ys.Length - 1];
+ else
+ ys[ys.Length - 1] = v;
+
+ inputs = xs;
+ outputs = ys;
+
+ return ys[0];
+ }
+
+ public double[] Evaluate(double[] value)
+ {
+ return value.Select(x => Evaluate(x)).ToArray();
+ }
+ }
+}
diff --git a/Esiur.Analysis/Esiur.Analysis.csproj b/Esiur.Analysis/Esiur.Analysis.csproj
index 1700991..31b8f90 100644
--- a/Esiur.Analysis/Esiur.Analysis.csproj
+++ b/Esiur.Analysis/Esiur.Analysis.csproj
@@ -3,6 +3,7 @@
netstandard2.1
enable
+ True
@@ -12,11 +13,14 @@
-
+
+
+
+
diff --git a/Esiur.Analysis/Optimization/Genetic.cs b/Esiur.Analysis/Optimization/Genetic.cs
new file mode 100644
index 0000000..b1610b8
--- /dev/null
+++ b/Esiur.Analysis/Optimization/Genetic.cs
@@ -0,0 +1,135 @@
+using Esiur.Data;
+using Esiur.Resource;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+
+namespace Esiur.Analysis.Optimization
+{
+ public class Genetic where T : unmanaged
+ {
+
+ Random rand = new Random();
+
+ public static unsafe byte[] Encode(in T value)
+ {
+ byte[] result = new byte[sizeof(T)];
+ fixed (byte* dst = result)
+ *(T*)dst = value;
+ return result;
+ }
+
+ public static unsafe T Decode(byte[] data)
+ {
+ fixed (byte* src = data)
+ return *(T*)src;
+ }
+
+ public List Population = new List();
+
+ public int PopulationSize { get; set; }
+ private int DataSize { get; set; }
+
+ public Func FitnessFunction { get; set; }
+
+ public unsafe Genetic(int populationSize, Func fitnessFunction)
+ {
+ FitnessFunction = fitnessFunction;
+ PopulationSize = populationSize;
+ DataSize = sizeof(T);
+ }
+
+ void GeneratePopultation()
+ {
+ for (var i = 0; i < PopulationSize; i++)
+ {
+ byte[] buffer = new byte[DataSize];
+ rand.NextBytes(buffer);
+ var record = Decode(buffer);
+ Population.Add(record);
+ }
+ }
+
+
+ KeyValuePair[] GetFitness()
+ {
+ var rt = new List>();
+
+ foreach (var record in Population)
+ rt.Add(new KeyValuePair( record, FitnessFunction(record)));
+
+ return rt.ToArray();
+ }
+
+ T Mate(T parent1, T parent2)
+ {
+ var dp1 = Encode(parent1);
+ var dp2 = Encode(parent2);
+
+ var dc = new byte[dp1.Length];
+
+
+ for (var i = 0; i < dc.Length; i++)
+ {
+ var prop = rand.NextDouble();
+ if (prop < 0.45)
+ dc[i] = dp1[i];
+ else if (prop < 0.9)
+ dc[i] = dp2[i];
+ else
+ dc[i] = (byte)rand.Next(0, 255);
+ }
+
+ return Decode(dc);
+
+ }
+
+ public T Evaluate(int maxIterations)
+ {
+ GeneratePopultation();
+
+ var generation = 0;
+
+ T best;
+
+ do
+ {
+ var ordered = GetFitness().OrderBy(x => x.Value).ToArray();
+
+ best = ordered[0].Key;
+
+ if (ordered[0].Value == 0)
+ break;
+
+ // Elitism selection ( 10% of fittest population )
+
+ var eliteCount = (int)(ordered.Length * 0.1);
+ var neededCount = (int)(ordered.Length * 0.9);
+
+ var newGeneration = ordered.Select(x => x.Key).Take(eliteCount).ToList();
+
+ for (var i = 0; i < neededCount; i++)
+ {
+ var p1 = Population[rand.Next(0, PopulationSize / 2)];
+ var p2 = Population[rand.Next(0, PopulationSize / 2)];
+
+ var offspring = Mate(p1, p2);
+ newGeneration.Add(offspring);
+ }
+
+ Population = newGeneration;
+
+ Debug.WriteLine($"Gen {generation} Fittest: {ordered.First().Value} {ordered.First().Key.ToString()} ");
+ } while (generation++ < maxIterations);
+
+ Debug.WriteLine($"Gen {generation} Best: {best.ToString()} ");
+
+ return best;
+ }
+
+ }
+}
diff --git a/Esiur.Analysis/Statistics/StatisticalFunctions.cs b/Esiur.Analysis/Statistics/StatisticalFunctions.cs
index 00744d2..40e490f 100644
--- a/Esiur.Analysis/Statistics/StatisticalFunctions.cs
+++ b/Esiur.Analysis/Statistics/StatisticalFunctions.cs
@@ -33,7 +33,13 @@ namespace Esiur.Analysis.Statistics
}
- public static double RMS(this double[] x) => Math.Sqrt(x.Sum(x => x * x) / x.Length);
+ public static double RMS(this double[] x)
+ {
+ var r = Math.Sqrt(x.Sum(x => x * x) / x.Length);
+ if (double.IsNaN(r))
+ Console.WriteLine();
+ return r;
+ }
public static double Correlation(this double[] x, double[] y)
diff --git a/Esiur.sln b/Esiur.sln
index b7e0ef6..3594207 100644
--- a/Esiur.sln
+++ b/Esiur.sln
@@ -10,7 +10,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur.Stores.EntityCore", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{331F82B6-6B90-4533-9718-F7C8090D8F19}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Analysis", "Esiur.Analysis\Esiur.Analysis.csproj", "{8D52DEEA-B7E8-4C93-9B6C-EDB9C2D25211}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur.Analysis", "Esiur.Analysis\Esiur.Analysis.csproj", "{8D52DEEA-B7E8-4C93-9B6C-EDB9C2D25211}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Analysis.Test", "Esiur.Analysis.Test\Esiur.Analysis.Test.csproj", "{72115ABD-BD54-4E88-8DB6-B2A953F57F0A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -38,6 +40,10 @@ Global
{8D52DEEA-B7E8-4C93-9B6C-EDB9C2D25211}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D52DEEA-B7E8-4C93-9B6C-EDB9C2D25211}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D52DEEA-B7E8-4C93-9B6C-EDB9C2D25211}.Release|Any CPU.Build.0 = Release|Any CPU
+ {72115ABD-BD54-4E88-8DB6-B2A953F57F0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {72115ABD-BD54-4E88-8DB6-B2A953F57F0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {72115ABD-BD54-4E88-8DB6-B2A953F57F0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {72115ABD-BD54-4E88-8DB6-B2A953F57F0A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Test/Program.cs b/Test/Program.cs
index b4343d3..f9c956f 100644
--- a/Test/Program.cs
+++ b/Test/Program.cs
@@ -56,53 +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),
- // new Capacity.CSI(PowerUnit.FromDb(15), 0.15),
- // new Capacity.CSI(PowerUnit.FromDb(10), 0.25),
- // new Capacity.CSI(PowerUnit.FromDb(5), 0.25),
- // new Capacity.CSI(PowerUnit.FromDb(0), 0.15),
- // new Capacity.CSI(PowerUnit.FromDb(-5), 0.1),
- //});
- var outage = Capacity.ComputeOutage(1, new Capacity.CSI[]
- {
- new Capacity.CSI(PowerUnit.FromDb(30), 0.2),
- new Capacity.CSI(PowerUnit.FromDb(20), 0.3),
- new Capacity.CSI(PowerUnit.FromDb(10), 0.3),
- 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(100, 200, 300));
- var big = new ContinuousSet(MembershipFunctions.Ascending(200, 300));
-
- //var speedIsLowThenSmall = new FuzzyRule("Low=>Small", low, small);
-
- double rating = 80;
-
- for (double temp = 60; temp < 100; temp++)
- {
- var v = MamdaniDefuzzifier.Evaluate(new INumericalSet[]
- {
- temp.Is(low).And(rating.Is(bad)).Then(small),
- temp.Is(mid).And(rating.Is(ok)).Then(avg),
- temp.Is(high).And(rating.Is(excelent)).Then(big),
- }, MamdaniDefuzzifierMethod.CenterOfGravity, 100, 300, 1);
-
-
- Console.WriteLine(temp + " " + v);
- }
-
// Create stores to keep objects.
var system = await Warehouse.Put("sys", new MemoryStore());
var server = await Warehouse.Put("sys/server", new DistributedServer());