From 6537913b112ad8fc00f91dac737adba3ab4c125d Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Sun, 16 Oct 2022 22:16:00 +0300 Subject: [PATCH] Analysis --- Esiur.Analysis/Esiur.Analysis.csproj | 13 +++ Esiur.Analysis/Signals/Capacity.cs | 69 ++++++++++++ Esiur.Analysis/Signals/DSP.cs | 55 ++++++++++ Esiur.Analysis/Signals/Propagation.cs | 16 +++ Esiur.Analysis/Statistics/Probability.cs | 31 ++++++ .../Statistics/StatisticalFunctions.cs | 44 ++++++++ Esiur.Analysis/Units/BitRate.cs | 81 ++++++++++++++ Esiur.Analysis/Units/PowerUnit.cs | 81 ++++++++++++++ Esiur.sln | 6 + Esiur/Data/IUserType.cs | 2 + Esiur/Data/VarList.cs | 103 ++++++++++++++++++ Esiur/Esiur.csproj | 2 +- Test/Program.cs | 13 +++ Test/Test.csproj | 1 + 14 files changed, 516 insertions(+), 1 deletion(-) create mode 100644 Esiur.Analysis/Esiur.Analysis.csproj create mode 100644 Esiur.Analysis/Signals/Capacity.cs create mode 100644 Esiur.Analysis/Signals/DSP.cs create mode 100644 Esiur.Analysis/Signals/Propagation.cs create mode 100644 Esiur.Analysis/Statistics/Probability.cs create mode 100644 Esiur.Analysis/Statistics/StatisticalFunctions.cs create mode 100644 Esiur.Analysis/Units/BitRate.cs create mode 100644 Esiur.Analysis/Units/PowerUnit.cs create mode 100644 Esiur/Data/VarList.cs diff --git a/Esiur.Analysis/Esiur.Analysis.csproj b/Esiur.Analysis/Esiur.Analysis.csproj new file mode 100644 index 0000000..625bd34 --- /dev/null +++ b/Esiur.Analysis/Esiur.Analysis.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.1 + enable + + + + + + + + diff --git a/Esiur.Analysis/Signals/Capacity.cs b/Esiur.Analysis/Signals/Capacity.cs new file mode 100644 index 0000000..9958a04 --- /dev/null +++ b/Esiur.Analysis/Signals/Capacity.cs @@ -0,0 +1,69 @@ +using Esiur.Analysis.Statistics; +using Esiur.Analysis.Units; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace Esiur.Analysis.Signals +{ + public static class Capacity + { + public struct CSI + { + public double SNR; + public Probability Probability; + + public CSI(double snr, double probability) + { + SNR = snr; + Probability = probability; + } + } + + public struct OutageCapacity + { + public BitRate Capacity; + public double MinSNR; + public Probability Outage; + public double Bandwidth; + + public OutageCapacity(Probability outage, double minSNR, double bandwidth) + { + MinSNR = minSNR; + Outage = outage; + Bandwidth = bandwidth; + Capacity = (1 - Outage) * bandwidth * Math.Log(1 + minSNR, 2); + } + + public override string ToString() => $" {MinSNR.ToString("F")} <{Outage}> => {Capacity}"; + } + + public static double Compute(double bandwidth, double snr) + => bandwidth * Math.Log(1 + snr, 2); + + + public static double ComputeErgodic(double bandwidth, CSI[] receiverCSI) + { + return bandwidth * receiverCSI.Sum(x => Math.Log(1 + x.SNR, 2) * x.Probability); + } + + public static OutageCapacity[] ComputeOutage(double bandwidth, CSI[] receiverCSI) + { + var sorted = receiverCSI.OrderBy(x => x.SNR); + var rt = sorted.Select(x => { + var pOut = receiverCSI.Where(csi => csi.SNR < x.SNR).Sum(x => x.Probability); + return new OutageCapacity() + { + Outage = pOut, + MinSNR = x.SNR, + Capacity = (1 - pOut) * bandwidth * Math.Log(1 + x.SNR, 2) + }; + }); + + return rt.ToArray(); + } + } +} \ No newline at end of file diff --git a/Esiur.Analysis/Signals/DSP.cs b/Esiur.Analysis/Signals/DSP.cs new file mode 100644 index 0000000..ee6fa6a --- /dev/null +++ b/Esiur.Analysis/Signals/DSP.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Esiur.Analysis.Signals +{ + public static class DSP + { + public static double[] ConvolveMany(params double[][] signals) + { + var rt = signals[0]; + + for (var i = 1; i < signals.Length; i++) + rt = rt.Convolve(signals[i]); + + return rt; + } + + public static double[] Convolve(this double[] signal, double[] filter) + { + var length = signal.Length + filter.Length - 1; + var rt = new double[length]; + + //for (var i = 0; i < signal.Length; i++) + // for (var j = 0; j < filter.Length; j++) + // rt[i + j] += signal[i] * filter[j]; + + for (var i = 0; i < length; i++) + { + for (var j = 0; j < signal.Length && i - j >= 0 && i - j < filter.Length; j++) + { + rt[i] = signal[j] * filter[i - j]; + } + } + + return rt; + } + + public static double[] CrossCorrelate(this double[] signal, double[] filter) + { + var length = signal.Length + filter.Length - 1; + var rt = new double[length]; + for (var i = 0; i < length; i++) + { + for (var j = 0; j < signal.Length && j + i < filter.Length; j++) + { + rt[i] = signal[j] * filter[i + j]; + } + } + + return rt; + } + + } +} diff --git a/Esiur.Analysis/Signals/Propagation.cs b/Esiur.Analysis/Signals/Propagation.cs new file mode 100644 index 0000000..1ac2487 --- /dev/null +++ b/Esiur.Analysis/Signals/Propagation.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Esiur.Analysis.Signals +{ + public static class Propagation + { + public static readonly double LightSpeed = 2.99792458e8; + public static double FindReceivedPower(double transmittedPower, double distance, + double transmitterGain, double receiverGain, double pathLoss) + { + throw new NotImplementedException(); + } + } +} diff --git a/Esiur.Analysis/Statistics/Probability.cs b/Esiur.Analysis/Statistics/Probability.cs new file mode 100644 index 0000000..c2ec0c7 --- /dev/null +++ b/Esiur.Analysis/Statistics/Probability.cs @@ -0,0 +1,31 @@ +using Esiur.Analysis.Units; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Esiur.Analysis.Statistics +{ + public struct Probability + { + public double Value; + + public static implicit operator Probability(double v) => new Probability(v); + public static implicit operator double(Probability v) => v.Value; + + public Probability(double value) + { + if (value > 1 || value < 0) + throw new Exception("0 >= Probability <= 1"); + + Value = value; + } + + public double ToPercentage() => Value * 100; + public Probability FromPercentage(double value) => new Probability(value / 100); + + public override string ToString() + { + return (Math.Round(Value * 10000) / 100) + "%"; + } + } +} diff --git a/Esiur.Analysis/Statistics/StatisticalFunctions.cs b/Esiur.Analysis/Statistics/StatisticalFunctions.cs new file mode 100644 index 0000000..f0c5cf8 --- /dev/null +++ b/Esiur.Analysis/Statistics/StatisticalFunctions.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Esiur.Analysis.Statistics +{ + public static class Statistics + { + public static double Mean(this double[] values) => values.Sum() / values.Length; + + public static double Variance(this double[] x) + { + var mean = x.Mean(); + return x.Sum(x => Math.Pow(x - mean, 2)) / x.Length; + } + + + public static double StdDiv(this double[] x) => Math.Sqrt(x.Variance()); + + public static double Covariance(this double[] x, double[] y) + { + var n = x.Length < y.Length ? x.Length : y.Length; + var X = x.Mean(); + var Y = y.Mean(); + + double rt = 0; + + for (var i = 0; i < n; i++) + rt += (x[i] - X) * (y[i] - Y); + + return rt / n; + } + + + public static double RMS(this double[] x) => Math.Sqrt(x.Sum(x => x * x) / x.Length); + + + public static double Correlation(this double[] x, double[] y) + { + return x.Covariance(y) / (x.StdDiv() * y.StdDiv()); + } + } +} diff --git a/Esiur.Analysis/Units/BitRate.cs b/Esiur.Analysis/Units/BitRate.cs new file mode 100644 index 0000000..49de13f --- /dev/null +++ b/Esiur.Analysis/Units/BitRate.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Esiur.Analysis.Units +{ + public enum BitRateKind + { + Bits, + Octets, + Bytes + } + + public struct BitRate : IComparable + { + public double Value; + + + public BitRate(double value, BitRateKind kind = BitRateKind.Bits) + { + if (kind == BitRateKind.Bytes) + Value = value * 8; + else if (kind == BitRateKind.Octets) + Value = value * 7; + else + Value = value; + } + + public static implicit operator BitRate(double d) => new BitRate(d); + public static implicit operator double(BitRate 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 BitRate operator +(BitRate a, BitRate b) + => new BitRate(a.Value + b.Value); + + public static BitRate operator -(BitRate a, BitRate b) + => new BitRate(a.Value - b.Value); + + public static BitRate operator *(BitRate a, BitRate b) + => new BitRate(a.Value * b.Value); + + public static BitRate operator /(BitRate a, BitRate b) + { + if (b.Value == 0) + { + throw new DivideByZeroException(); + } + return new BitRate(a.Value / b.Value); + } + + + public override string ToString() + { + if (Value >= 1e12) + return (Value / 1e12).ToString("F") + " tbps"; + else if (Value >= 1e9) + return (Value / 1e9).ToString("F") + " gbps"; + else if (Value >= 1e6) + return (Value / 1e6).ToString("F") + " mbps"; + else if (Value >= 1e3) + return (Value * 1e3).ToString("F") + " kbps"; + else + return Value.ToString("F") + " bps"; + } + + + public int CompareTo(object obj) + { + if (obj is BitRate p) + return Value.CompareTo(p.Value); + else + return Value.CompareTo(obj); + } + } +} diff --git a/Esiur.Analysis/Units/PowerUnit.cs b/Esiur.Analysis/Units/PowerUnit.cs new file mode 100644 index 0000000..eba59d7 --- /dev/null +++ b/Esiur.Analysis/Units/PowerUnit.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Esiur.Analysis.Units +{ + public enum PowerUnitKind + { + Watt, + Decibel + } + + public struct PowerUnit : IComparable + { + public double Value; + + + public PowerUnit(double value, PowerUnitKind kind = PowerUnitKind.Watt) + { + if (kind == PowerUnitKind.Watt) + Value = value; + else if (kind == PowerUnitKind.Decibel) + Value = FromDb(value); + else + Value = 0; + } + + public static implicit operator PowerUnit(double d) => new PowerUnit(d, PowerUnitKind.Watt); + public static implicit operator double(PowerUnit 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 PowerUnit operator +(PowerUnit a, PowerUnit b) + => new PowerUnit(a.Value + b.Value); + + public static PowerUnit operator -(PowerUnit a, PowerUnit b) + => new PowerUnit(a.Value - b.Value); + + public static PowerUnit operator *(PowerUnit a, PowerUnit b) + => new PowerUnit(a.Value * b.Value); + + public static PowerUnit operator /(PowerUnit a, PowerUnit b) + { + if (b.Value == 0) + { + throw new DivideByZeroException(); + } + return new PowerUnit(a.Value / b.Value); + } + + + public override string ToString() + { + if (Value < 1e-6) + return (Value * 1e9).ToString("F") + "nW"; + else if (Value < 1e-3) + return (Value * 1e6).ToString("F") + "µW"; + else if (Value < 1) + return (Value * 1e3).ToString("F") + "mW"; + else + return Value.ToString("F") + "W"; + } + + public double ToDb() => 10 * Math.Log(10, Value); + public static double FromDb(double value) => Math.Pow(10, value / 10); + + public int CompareTo(object obj) + { + + if (obj is PowerUnit p) + return Value.CompareTo(p.Value); + else + return Value.CompareTo(obj); + } + } +} diff --git a/Esiur.sln b/Esiur.sln index 104e119..b7e0ef6 100644 --- a/Esiur.sln +++ b/Esiur.sln @@ -10,6 +10,8 @@ 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}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -32,6 +34,10 @@ Global {331F82B6-6B90-4533-9718-F7C8090D8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU {331F82B6-6B90-4533-9718-F7C8090D8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU {331F82B6-6B90-4533-9718-F7C8090D8F19}.Release|Any CPU.Build.0 = Release|Any CPU + {8D52DEEA-B7E8-4C93-9B6C-EDB9C2D25211}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Esiur/Data/IUserType.cs b/Esiur/Data/IUserType.cs index 6485b33..7122b40 100644 --- a/Esiur/Data/IUserType.cs +++ b/Esiur/Data/IUserType.cs @@ -7,5 +7,7 @@ public interface IUserType { object Get(); void Set(object value); + + object SetAndGet(object value); } diff --git a/Esiur/Data/VarList.cs b/Esiur/Data/VarList.cs new file mode 100644 index 0000000..7d6eba0 --- /dev/null +++ b/Esiur/Data/VarList.cs @@ -0,0 +1,103 @@ +using Esiur.Core; +using Esiur.Resource; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Esiur.Data +{ + public class VarList : IEnumerable, ICollection, ICollection + { + string propertyName; + IResource resource; + + List list = new List(); + + public VarList(IResource resource, [CallerMemberName] string propertyName = "") + { + this.resource = resource; + this.propertyName = propertyName; + } + + public int Count => list.Count; + + public bool IsReadOnly => false; + + public bool IsSynchronized => true; + + + public object SyncRoot { get; } = new object(); + + public void Add(T item) + { + list.Add(item); + + resource?.Instance?.Modified(propertyName); + } + + public void Clear() + { + list.Clear(); + resource?.Instance?.Modified(propertyName); + } + + public bool Contains(T item) + { + return list.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + lock (SyncRoot) + list.CopyTo(array, arrayIndex); + } + + public void CopyTo(Array array, int index) + { + lock (SyncRoot) + (list as ICollection).CopyTo(array, index); + } + + public IEnumerator GetEnumerator() + { + return list.GetEnumerator(); + } + + public bool Remove(T item) + { + if ( list.Remove(item)) + { + resource?.Instance?.Modified(propertyName); + return true; + } + + return false; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return list.GetEnumerator(); + } + + + public T this[int index] + { + get + { + return list[index]; + } + set + { + //var oldValue = list[index]; + + lock (SyncRoot) + list[index] = value; + + resource?.Instance?.Modified(propertyName); + + } + } + } +} diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj index 9203a94..4b63b3f 100644 --- a/Esiur/Esiur.csproj +++ b/Esiur/Esiur.csproj @@ -6,7 +6,7 @@ Ahmed Kh. Zamil http://www.esiur.com true - 2.3.6 + 2.3.7 https://github.com/esiur/esiur-dotnet Ahmed Kh. Zamil diff --git a/Test/Program.cs b/Test/Program.cs index 5d5ac93..38489bb 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -45,6 +45,8 @@ using System.Collections.Generic; using System.Reflection; using System.Security.Cryptography; using System.Text; +using Esiur.Analysis.Signals; +using Esiur.Analysis.Units; namespace Test { @@ -54,6 +56,17 @@ 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), + }); + // Create stores to keep objects. var system = await Warehouse.Put("sys", new MemoryStore()); var server = await Warehouse.Put("sys/server", new DistributedServer()); diff --git a/Test/Test.csproj b/Test/Test.csproj index 00950c4..d54d448 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -6,6 +6,7 @@ +