diff --git a/Esiur.Analysis.Test/FGraph.Designer.cs b/Esiur.Analysis.Test/FGraph.Designer.cs index a0184dc..4092b59 100644 --- a/Esiur.Analysis.Test/FGraph.Designer.cs +++ b/Esiur.Analysis.Test/FGraph.Designer.cs @@ -28,19 +28,49 @@ /// private void InitializeComponent() { + this.button1 = new System.Windows.Forms.Button(); + this.pbDraw = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pbDraw)).BeginInit(); this.SuspendLayout(); // + // button1 + // + this.button1.Location = new System.Drawing.Point(468, 409); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 0; + this.button1.Text = "Step"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // pbDraw + // + this.pbDraw.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pbDraw.Location = new System.Drawing.Point(36, 40); + this.pbDraw.Name = "pbDraw"; + this.pbDraw.Size = new System.Drawing.Size(639, 345); + this.pbDraw.TabIndex = 1; + this.pbDraw.TabStop = false; + this.pbDraw.Paint += new System.Windows.Forms.PaintEventHandler(this.pbDraw_Paint); + // // FGraph // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(838, 494); + this.ClientSize = new System.Drawing.Size(729, 459); + this.Controls.Add(this.pbDraw); + this.Controls.Add(this.button1); + this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.Name = "FGraph"; this.Text = "FGraph"; + ((System.ComponentModel.ISupportInitialize)(this.pbDraw)).EndInit(); this.ResumeLayout(false); } #endregion + + private Button button1; + private PictureBox pbDraw; } } \ No newline at end of file diff --git a/Esiur.Analysis.Test/FGraph.cs b/Esiur.Analysis.Test/FGraph.cs index fd3b6e6..dce861f 100644 --- a/Esiur.Analysis.Test/FGraph.cs +++ b/Esiur.Analysis.Test/FGraph.cs @@ -1,4 +1,5 @@ -using System; +using Esiur.Analysis.Graph; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -12,9 +13,94 @@ namespace Esiur.Analysis.Test { public partial class FGraph : Form { + DirectedGraph graph; + int step = 0; + public FGraph() { + graph = new DirectedGraph(); + + var n1 = graph.AddNode(1, "1", 80, 120); + var n2 = graph.AddNode(2, "2", 300, 120); + + graph.Link(n1, n2, (decimal)0.5, "1->2"); + graph.Link(n1, n1, (decimal)0.5, "1->1"); + + graph.Link(n2, n1, (decimal)0.2, "2->1"); + graph.Link(n2, n2, (decimal)0.8, "2->2"); + + graph.Build(); + InitializeComponent(); } + + private void button1_Click(object sender, EventArgs e) + { + graph.Step(); + step++; + pbDraw.Refresh(); + + } + + private void pbDraw_Paint(object sender, PaintEventArgs e) + { + + var pen = new Pen(Brushes.Red, 4); + var g = e.Graphics; + + g.FillRectangle(Brushes.White, 0, 0, pbDraw.Width, pbDraw.Height); + + // update label + foreach (var edge in graph.Edges) + { + DrawArcBetweenTwoPoints(g, pen, new PointF(edge.SourceNode.X, edge.SourceNode.Y), + new PointF(edge.DestinationNode.X, edge.DestinationNode.Y), edge.Label + " " + Math.Round( edge.Weight, 4)); + } + + foreach (var node in graph.Nodes) + { + g.FillEllipse(Brushes.LightGreen, node.X - 30, node.Y - 30, 60, 60); + g.DrawString(node.Label, new Font("Arial", 26), Brushes.Blue, node.X - 15, node.Y - 20); + } + + + g.DrawString("Step " + step, new Font("Arial", 26), Brushes.Orange, new PointF(20, pbDraw.Height - 50)); + + g.Flush(); + } + + + public void DrawArcBetweenTwoPoints(Graphics g, Pen pen, PointF a, PointF b, string label) + { + + if (a.X == b.X && a.Y == b.Y) + { + var c = new PointF(a.X, a.Y - 60); + + // draw + g.DrawString(label, new Font("Arial", 14), Brushes.Black, new PointF(c.X, c.Y - 25)); + + g.DrawCurve(pen, new PointF[] { a, new PointF(a.X - 30, a.Y - 30), c, new PointF(a.X + 30, a.Y - 30), a }); + } + else + { + if (b.X > a.X) + { + var c = new PointF(a.X + ((b.X - a.X) / 2), a.Y - 20); + g.DrawCurve(pen, new PointF[] { a, c, b }); + g.DrawString(label, new Font("Arial", 14), Brushes.Black, new PointF( c.X - 30, c.Y - 25)); + + } + else + { + var c = new PointF(b.X + ((a.X - b.X) / 2), b.Y + 20); + g.DrawCurve(pen, new PointF[] { b, c, a }); + g.DrawString(label, new Font("Arial", 14), Brushes.Black, new PointF(c.X - 30, c.Y + 5)); + } + + + } + } + } } diff --git a/Esiur.Analysis.Test/Program.cs b/Esiur.Analysis.Test/Program.cs index db93172..d7f139d 100644 --- a/Esiur.Analysis.Test/Program.cs +++ b/Esiur.Analysis.Test/Program.cs @@ -3,6 +3,7 @@ using System.Net.Sockets; using System.Text; using Esiur.Analysis.Coding; using Esiur.Analysis.DSP; +using Esiur.Analysis.Graph; using Esiur.Analysis.Signals; /* @@ -31,6 +32,7 @@ SOFTWARE. using Esiur.Analysis.Signals.Codes; using Esiur.Data; using Esiur.Resource; +using ScottPlot.Statistics.Interpolation; namespace Esiur.Analysis.Test { @@ -45,6 +47,28 @@ namespace Esiur.Analysis.Test static void Main() { + + var graph = new DirectedGraph(); + + var n1 = graph.AddNode(1, "1", 10, 10); + var n2 = graph.AddNode(2, "2", 20, 10); + + graph.Link(n1, n2, 0.5, "1->2"); + graph.Link(n1, n1, 0.5, "1->1"); + + graph.Link(n2, n1, 0.2, "2->1"); + graph.Link(n2, n2, 0.8, "2->2"); + + + var matrix = new Matrix(new double[,] { { 0.5, 0.5 }, { 0.2, 0.8 } }); + + var m = matrix; + for(var i = 0; i < 3; i++) + { + m = m * m; + Console.WriteLine(m); + } + var msg = Encoding.ASCII.GetBytes("A_DEAD_DAD_CEDED_A_BAD_BABE_A_BEADED_ABACA_BED").Select(x => CodeWord.FromByte(x)).ToArray();// ()); // convert msg to codewords @@ -78,7 +102,7 @@ namespace Esiur.Analysis.Test // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); - Application.Run(new FSoft()); + Application.Run(new FGraph()); } } } \ No newline at end of file diff --git a/Esiur.Analysis/Esiur.Analysis.csproj b/Esiur.Analysis/Esiur.Analysis.csproj index f5b19ec..c1f6baa 100644 --- a/Esiur.Analysis/Esiur.Analysis.csproj +++ b/Esiur.Analysis/Esiur.Analysis.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -20,6 +20,10 @@ + + + + diff --git a/Esiur.Analysis/Graph/DirectedGraph.cs b/Esiur.Analysis/Graph/DirectedGraph.cs index f793edd..ad0a0e2 100644 --- a/Esiur.Analysis/Graph/DirectedGraph.cs +++ b/Esiur.Analysis/Graph/DirectedGraph.cs @@ -1,15 +1,75 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace Esiur.Analysis.Graph { - public class DirectedGraph : IGraph + public class DirectedGraph : IGraph where T:struct { - public Node[] Nodes { get; set; } - public Edge[] Edges { get; set; } + public List> Nodes { get;} = new List>(); + public List> Edges { get; }= new List>(); + public void Link(Node source, Node destination , T weight, string label) + { + var edge = new Edge() { SourceNode = source, DestinationNode = destination, Weight = weight, Label = label }; + Edges.Add(edge); + source.Destinations.Add(edge); + destination.Sources.Add(edge); + + } + public Node AddNode(T value, string label, int x, int y) + { + var n = new Node() { Value = value, Label = label, X = x, Y = y }; + Nodes.Add(n); + return n; + } + + public Matrix TransitionMatrix { get; private set; } + + public Matrix CurrentStep { get; private set; } + + public Edge[,] EdgesMatrix { get; private set; } + + public void Build() + { + // create matrix + var m = new T[Nodes.Count, Nodes.Count]; + var e = new Edge[Nodes.Count, Nodes.Count]; + + for(var i = 0; i < Nodes.Count; i++) + { + for(var j = 0; j < Nodes.Count; j++) + { + var link = Edges.FirstOrDefault(x => x.SourceNode == Nodes[i] && x.DestinationNode == Nodes[j]); + if (link == null) + m[i, j] = default(T); + else + { + m[i, j] = link.Weight; + e[i, j] = link; + } + } + } + + TransitionMatrix = new Matrix(m); + CurrentStep = TransitionMatrix; + EdgesMatrix = e; + } + + public void Step() + { + CurrentStep *= CurrentStep; + // update weights + for(var i = 0; i < CurrentStep.Rows; i++) + for(var j = 0; j < CurrentStep.Columns; j++) + { + if (EdgesMatrix[i, j] != null) + EdgesMatrix[i, j].Weight = CurrentStep[i, j]; + } + + } } } diff --git a/Esiur.Analysis/Graph/Edge.cs b/Esiur.Analysis/Graph/Edge.cs index eefbb7c..a0fc054 100644 --- a/Esiur.Analysis/Graph/Edge.cs +++ b/Esiur.Analysis/Graph/Edge.cs @@ -6,7 +6,11 @@ namespace Esiur.Analysis.Graph { public class Edge { - public T SourceNode { get; set; } - public T DestinationNode { get; set; } + public Node SourceNode { get; set; } + public Node DestinationNode { get; set; } + + public T Weight { get; set; } + + public string Label { get; set; } } } diff --git a/Esiur.Analysis/Graph/TransitionMatrix.cs b/Esiur.Analysis/Graph/Matrix.cs similarity index 53% rename from Esiur.Analysis/Graph/TransitionMatrix.cs rename to Esiur.Analysis/Graph/Matrix.cs index 12bbb82..72f1fc7 100644 --- a/Esiur.Analysis/Graph/TransitionMatrix.cs +++ b/Esiur.Analysis/Graph/Matrix.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; -using System.Reflection.Metadata.Ecma335; -using System.Security.Cryptography.X509Certificates; +using System.Data.Common; using System.Text; namespace Esiur.Analysis.Graph @@ -20,7 +19,34 @@ namespace Esiur.Analysis.Graph this.value = value; } - public static Matrix Multiply(Matrix a, Matrix b) where T:struct + public static Matrix operator *(Matrix a, Matrix b) + => Multiply(a, b); + + public Matrix Pow(int power) + { + var rt = this; + for (var i = 1; i < power; i++) + rt = rt * rt; + return rt; + } + + public override string ToString() + { + var rt = ""; + for (var i = 0; i < Rows; i++) + { + rt += "|"; + + for (var j = 0; j < Columns - 1; j++) + rt += value[i, j] + ","; + + rt += value[i, Columns - 1] + "|"; + } + + return rt; + } + + public static Matrix Multiply(Matrix a, Matrix b) where T : struct { @@ -36,7 +62,9 @@ namespace Esiur.Analysis.Graph { // bColumn for (int k = 0; k < a.Columns; k++) { // aColumn - rt[i, j] += a[i, k] * b[k, j]; + dynamic aValue = a[i, k]; + dynamic bValue = b[k, j]; + rt[i, j] += aValue * bValue;// a[i, k] * b[k, j]; } } } diff --git a/Esiur.Analysis/Graph/Node.cs b/Esiur.Analysis/Graph/Node.cs index 7740e4e..7523ced 100644 --- a/Esiur.Analysis/Graph/Node.cs +++ b/Esiur.Analysis/Graph/Node.cs @@ -10,5 +10,10 @@ namespace Esiur.Analysis.Graph public int X { get; set; } public int Y { get; set; } + + public string Label { get; set; } + public List> Destinations { get; } = new List>(); + public List> Sources { get; } = new List>(); + } }