/// <summary> /// Compares this instance with a specified adjacency matrix. /// </summary> /// <param name="matrix">The specified adjacency matrix that this instantce is to be compared with.</param> /// <returns> /// Returns NULL if the two adjaceny matrices are identical. /// If the two adjacency matrices are different, return a List<int> containing the indexes of different vertices. /// </returns> public List <int> CompareTo(AdjacencyMatrix matrix) { bool isEqual = true; List <int> differentVertices = new List <int>(); if (matrix == null) { isEqual = false; for (int v = 0; v < GetSize(); v++) { if (this.IsVertexExisting(v)) { if (!differentVertices.Contains(v)) { differentVertices.Add(v); } } } differentVertices.Sort(); return(differentVertices); } for (int v = 0; v < GetSize(); v++) { if (this.IsVertexExisting(v) != matrix.IsVertexExisting(v)) { isEqual = false; if (!differentVertices.Contains(v)) { differentVertices.Add(v); } } } for (int row = 0; row < GetSize(); row++) { for (int col = 0; col < GetSize(); col++) { if (!this.GetEdge(row, col).Equals(matrix.GetEdge(row, col))) { isEqual = false; if (!differentVertices.Contains(row)) { differentVertices.Add(row); } } } } if (isEqual) { return(null); } else { differentVertices.Sort(); return(differentVertices); } }
private void PanelGraph_Paint(object sender, PaintEventArgs e) { Dictionary <bool, Color> colorFocusEdge = new Dictionary <bool, Color> { { true, Color.Red }, { false, Color.Black } }; using (Graphics g = e.Graphics) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; foreach (DijkstraVertexLabel v1 in vertices) { foreach (DijkstraVertexLabel v2 in vertices) { int vStart = v1.GetNumberIndex(); int vFinish = v2.GetNumberIndex(); if (mapMatrix.ContainsEdge(vStart, vFinish)) { int shiftX = Convert.ToInt32(Math.Round(Math.Min(v2.Width / 2, Math.Abs(v2.Height / 2 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y + 1e-10))))); int shiftY = Convert.ToInt32(Math.Round(Math.Min(v2.Height / 2, Math.Abs(v2.Width / 2 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / (v2.GetCentreLocation().X - v1.GetCentreLocation().X + 1e-10))))); int directionX = v2.GetCentreLocation().X > v1.GetCentreLocation().X ? 1 : -1; int directionY = v2.GetCentreLocation().Y > v1.GetCentreLocation().Y ? 1 : -1; if (!mapMatrix.ContainsEdge(vFinish, vStart)) { g.DrawLine(new Pen(colorFocusEdge[edgeFocused[vStart, vFinish]], 5), v1.GetCentreLocation(), v2.GetCentreLocation()); Point point1 = new Point ( v2.GetCentreLocation().X - directionX * shiftX, v2.GetCentreLocation().Y - directionY * shiftY ); Point pointBase = new Point ( Convert.ToInt32(Math.Round(point1.X - 40 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(point1.Y - 40 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))) ); Point point2 = new Point ( Convert.ToInt32(Math.Round(pointBase.X + 7.5 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(pointBase.Y - 7.5 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))) ); Point point3 = new Point ( Convert.ToInt32(Math.Round(pointBase.X - 7.5 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(pointBase.Y + 7.5 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))) ); Point[] arrow = { point1, point2, point3 }; g.FillPolygon(new SolidBrush(colorFocusEdge[edgeFocused[vStart, vFinish]]), arrow); } else if (mapMatrix.GetEdge(vStart, vFinish) != mapMatrix.GetEdge(vFinish, vStart)) { if (vFinish > vStart) { Point point1 = new Point ( v1.GetCentreLocation().X + directionX * shiftX, v1.GetCentreLocation().Y + directionY * shiftY ); Point point2 = new Point ( v2.GetCentreLocation().X - directionX * shiftX, v2.GetCentreLocation().Y - directionY * shiftY ); Point midPoint = new Point ( (v1.GetCentreLocation().X + v2.GetCentreLocation().X) / 2, (v1.GetCentreLocation().Y + v2.GetCentreLocation().Y) / 2 ); Point point3 = new Point ( Convert.ToInt32(Math.Round(midPoint.X + 42 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(midPoint.Y - 42 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))) ); Point point4 = new Point ( Convert.ToInt32(Math.Round(midPoint.X - 42 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(midPoint.Y + 42 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))) ); Point point5 = new Point ( Convert.ToInt32(Math.Round(point2.X - 40 * (point2.X - point3.X) / Math.Sqrt((point2.X - point3.X) * (point2.X - point3.X) + (point2.Y - point3.Y) * (point2.Y - point3.Y)))), Convert.ToInt32(Math.Round(point2.Y - 40 * (point2.Y - point3.Y) / Math.Sqrt((point2.X - point3.X) * (point2.X - point3.X) + (point2.Y - point3.Y) * (point2.Y - point3.Y)))) ); Point point6Reflect = new Point ( Convert.ToInt32(Math.Round(point2.X - 40 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(point2.Y - 40 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))) ); Point point6 = new Point ( Convert.ToInt32(Math.Round(point5.X + 11 * (point5.X - point6Reflect.X) / Math.Sqrt((point5.X - point6Reflect.X) * (point5.X - point6Reflect.X) + (point5.Y - point6Reflect.Y) * (point5.Y - point6Reflect.Y)))), Convert.ToInt32(Math.Round(point5.Y + 11 * (point5.Y - point6Reflect.Y) / Math.Sqrt((point5.X - point6Reflect.X) * (point5.X - point6Reflect.X) + (point5.Y - point6Reflect.Y) * (point5.Y - point6Reflect.Y)))) ); Point point7 = new Point ( Convert.ToInt32(Math.Round(point1.X - 40 * (point1.X - point4.X) / Math.Sqrt((point1.X - point4.X) * (point1.X - point4.X) + (point1.Y - point4.Y) * (point1.Y - point4.Y)))), Convert.ToInt32(Math.Round(point1.Y - 40 * (point1.Y - point4.Y) / Math.Sqrt((point1.X - point4.X) * (point1.X - point4.X) + (point1.Y - point4.Y) * (point1.Y - point4.Y)))) ); Point point8Reflect = new Point ( Convert.ToInt32(Math.Round(point1.X + 40 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(point1.Y + 40 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))) ); Point point8 = new Point ( Convert.ToInt32(Math.Round(point7.X + 11 * (point7.X - point8Reflect.X) / Math.Sqrt((point7.X - point8Reflect.X) * (point7.X - point8Reflect.X) + (point7.Y - point8Reflect.Y) * (point7.Y - point8Reflect.Y)))), Convert.ToInt32(Math.Round(point7.Y + 11 * (point7.Y - point8Reflect.Y) / Math.Sqrt((point7.X - point8Reflect.X) * (point7.X - point8Reflect.X) + (point7.Y - point8Reflect.Y) * (point7.Y - point8Reflect.Y)))) ); Point[] curve1 = { point1, point3, point2 }; Point[] curve2 = { point2, point4, point1 }; g.DrawCurve(new Pen(colorFocusEdge[edgeFocused[vStart, vFinish]], 5), curve1); g.DrawCurve(new Pen(colorFocusEdge[edgeFocused[vFinish, vStart]], 5), curve2); Point[] arrow1 = { point2, point5, point6 }; Point[] arrow2 = { point1, point7, point8 }; g.FillPolygon(new SolidBrush(colorFocusEdge[edgeFocused[vStart, vFinish]]), arrow1); g.FillPolygon(new SolidBrush(colorFocusEdge[edgeFocused[vFinish, vStart]]), arrow2); } } else { if (vFinish > vStart) { g.DrawLine(new Pen(colorFocusEdge[edgeFocused[vStart, vFinish]], 5), v1.GetCentreLocation(), v2.GetCentreLocation()); } } } } } } }
/// <summary> /// Show the tag window of the vertex, and all its adjacenct edge information. /// </summary> private void FormVertexTag_Load(object sender, EventArgs e) { for (int finishingVertex = 0; finishingVertex < mapMatrix.GetSize(); finishingVertex++) { int startingVertex = mapMatrix.GetVertexIndex((sender as FormVertexTag).Text.Trim("Vertex ".ToCharArray())); if (mapMatrix.IsVertexExisting(finishingVertex) && finishingVertex != startingVertex) { (sender as FormVertexTag).AddVertexTagControl(finishingVertex); if (mapMatrix.ContainsEdge(startingVertex, finishingVertex)) { (sender as FormVertexTag).edgeControls[(sender as FormVertexTag).edgeControls.Count - 1].GetCheckBoxContainsEdge().Checked = true; (sender as FormVertexTag).edgeControls[(sender as FormVertexTag).edgeControls.Count - 1].GetTextBoxWeight().Text = mapMatrix.GetEdge(startingVertex, finishingVertex).ToString(); } } } }
// Graph/Tree Traversal (Group A) is implemented here. private void ButtonNext_Click(object sender, EventArgs e) { if (buttonNext.Text == "Close") { this.Close(); } else { // Step 1 operation if (currentStep == 1) { // Highlight current step label1.ForeColor = Color.Red; labelStep1.ForeColor = Color.Red; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; // Show the headers of the list of all edges labelList.Visible = true; labelEdgeLeft.Visible = true; labelWeightLeft.Visible = true; labelEdgeRight.Visible = true; labelWeightRight.Visible = true; // Initialise and sort the list of all edges int edgeCount = 0; for (int v1 = 0; v1 < mapMatrix.GetSize() - 1; v1++) { for (int v2 = v1 + 1; v2 < mapMatrix.GetSize(); v2++) { if (mapMatrix.ContainsEdge(v1, v2)) { edgeCount++; edgeList.Add(new Edge { vStart = v1, vFinish = v2, weight = mapMatrix.GetEdge(v1, v2) }); } } } edgeCount /= 2; QuickSort(edgeList, 0, edgeList.Count - 1); // Show the list of all edges Point[] originalLocations = new Point[2]; originalLocations[0] = new Point(24, 332); originalLocations[1] = new Point(originalLocations[0].X + 228, originalLocations[0].Y); for (int i = 0; i < edgeList.Count; i++) { Point location = new Point(originalLocations[i / edgeCount].X, originalLocations[i / edgeCount].Y + 44 * (i % edgeCount)); labelEdges.Add(new Label() { AutoSize = true, Font = new Font("Microsoft YaHei", 12F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134))), Location = location, MinimumSize = new Size(100, 44), Name = "labelEdge" + i.ToString(), Size = new Size(100, 44), Text = Convert.ToChar(edgeList[i].vStart + 'A').ToString() + Convert.ToChar(edgeList[i].vFinish + 'A').ToString(), TextAlign = ContentAlignment.TopCenter }); labelEdges[i].Click += new EventHandler(LabelEdge_Click); labelWeights.Add(new Label() { AutoSize = true, Font = new Font("Microsoft YaHei", 12F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134))), Location = new Point(location.X + 100, location.Y), MinimumSize = new Size(100, 44), Name = "labelWeight" + i.ToString(), Size = new Size(100, 44), Text = edgeList[i].weight.ToString(), TextAlign = ContentAlignment.TopCenter }); labelWeights[i].Click += new EventHandler(LabelEdge_Click); labelEdgeUsed.Add(new Label() { AutoSize = true, Font = new Font("Microsoft YaHei", 12F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134))), Location = new Point(location.X + 200, location.Y), MinimumSize = new Size(0, 22), Name = "labelEdgeUsed" + i.ToString(), Size = new Size(22, 22), Text = "×", TextAlign = ContentAlignment.TopCenter, Visible = false }); this.Controls.Add(labelEdges[i]); this.Controls.Add(labelWeights[i]); this.Controls.Add(labelEdgeUsed[i]); } currentEdgeIndex = 0; currentWeight = edgeList[0].weight; currentStep = 2; } // Step 2 operations else if (currentStep == 2) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = Color.Red; labelStep2.ForeColor = Color.Red; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; foreach (Label label in labelEdges) { label.ForeColor = SystemColors.ControlText; } foreach (Label label in labelWeights) { label.ForeColor = SystemColors.ControlText; } labelEdges[currentEdgeIndex].ForeColor = Color.Red; labelWeights[currentEdgeIndex].ForeColor = Color.Red; // Initialise text explanation label labelInformation.Text = ""; labelInformation.Visible = true; // Perform Kruskal's algorithm if (Find(edgeList[currentEdgeIndex].vStart).GetLeader() == Find(edgeList[currentEdgeIndex].vFinish).GetLeader()) // Reject edges forming a cycle { labelInformation.Text = "Adding edge " + labelEdges[currentEdgeIndex].Text + " will form a cycle, therefore edge " + labelEdges[currentEdgeIndex].Text + " should not be chosen."; labelEdgeUsed[currentEdgeIndex].Text = "×"; labelEdgeUsed[currentEdgeIndex].ForeColor = Color.Red; labelEdgeUsed[currentEdgeIndex].Visible = true; labelEdges[currentEdgeIndex].Font = new Font("Microsoft YaHei", 12F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Strikeout))), System.Drawing.GraphicsUnit.Point, ((byte)(134))); labelWeights[currentEdgeIndex].Font = new Font("Microsoft YaHei", 12F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Strikeout))), System.Drawing.GraphicsUnit.Point, ((byte)(134))); do { currentEdgeIndex++; } while (labelEdgeUsed[currentEdgeIndex].Visible); currentWeight = edgeList[currentEdgeIndex].weight; currentStep = 2; } else { int i = currentEdgeIndex + 1; List <Edge> tempEdgeList = new List <Edge> { edgeList[currentEdgeIndex] }; while (edgeList[i].weight == currentWeight && !labelEdgeUsed[i].Visible) { if (Find(edgeList[i].vStart).GetLeader() != Find(edgeList[i].vFinish).GetLeader()) // Highlight feasible candidate edges { labelEdges[i].ForeColor = Color.Red; labelWeights[i].ForeColor = Color.Red; tempEdgeList.Add(edgeList[i]); } else // Reject edges forming a cycle { labelInformation.Text += "Adding edge " + labelEdges[i].Text + " will form a cycle, therefore edge " + labelEdges[i].Text + " should not be chosen.\n"; labelEdgeUsed[i].Text = "×"; labelEdgeUsed[i].ForeColor = Color.Red; labelEdgeUsed[i].Visible = true; labelEdges[i].Font = new Font("Microsoft YaHei", 12F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Strikeout))), System.Drawing.GraphicsUnit.Point, ((byte)(134))); labelWeights[i].Font = new Font("Microsoft YaHei", 12F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Strikeout))), System.Drawing.GraphicsUnit.Point, ((byte)(134))); } i++; } if (tempEdgeList.Count >= 2) // More than two candidate edges - user operation required { labelInformation.Text += "Edges "; foreach (Edge edge in tempEdgeList) { labelInformation.Text += Convert.ToChar(edge.vStart + 'A').ToString() + Convert.ToChar(edge.vFinish + 'A').ToString() + ", "; } labelInformation.Text = labelInformation.Text.TrimEnd(", ".ToCharArray()); labelInformation.Text += " have the same weight. Please pick one of your choice.\n" + "Please click on the edge in the list (NOT on the graph)."; currentStep = 2; buttonNext.Enabled = false; } else // One candidate edge only { labelInformation.Text += "Edge " + labelEdges[currentEdgeIndex].Text + " has been added to the Minimum Spanning Tree."; labelEdgeUsed[currentEdgeIndex].Text = "√"; labelEdgeUsed[currentEdgeIndex].ForeColor = Color.Green; labelEdgeUsed[currentEdgeIndex].Visible = true; EdgeFocusOn(edgeList[currentEdgeIndex].vStart, edgeList[currentEdgeIndex].vFinish); exampleGraph.LabelFocusOn(edgeList[currentEdgeIndex].vStart, edgeList[currentEdgeIndex].vFinish); treeEdgeCount++; weightMST += currentWeight; Union(Find(edgeList[currentEdgeIndex].vStart).GetLeader(), Find(edgeList[currentEdgeIndex].vFinish).GetLeader()); currentEdgeIndex = i; while (labelEdgeUsed[currentEdgeIndex].Visible) { currentEdgeIndex++; } currentWeight = edgeList[currentEdgeIndex].weight; currentStep = 3; } } } // Step 3 operation else // if (currentStep == 3) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = Color.Red; labelStep3.ForeColor = Color.Red; foreach (Label label in labelEdges) { label.ForeColor = SystemColors.ControlText; } foreach (Label label in labelWeights) { label.ForeColor = SystemColors.ControlText; } // Initialise text explanation label labelInformation.Text = ""; labelInformation.Visible = true; // Check if the algorithm is finished if (treeEdgeCount < mapMatrix.Count() - 1) { labelInformation.Text = "We have not yet formed a Minimum Spanning Tree, so go back to STEP 2."; currentStep = 2; } else { labelInformation.Text = "Now we have picked " + (mapMatrix.Count() - 1).ToString() + " edges and has formed a Minimum Spanning Tree.\nTherefore Kruskal's algorithm has finished."; for (int i = 0; i < edgeList.Count; i++) { if (labelEdgeUsed[i].Text == "√") { labelTotalWeight.Text += labelWeights[i].Text + " + "; } } labelTotalWeight.Text = labelTotalWeight.Text.TrimEnd(" + ".ToCharArray()); labelTotalWeight.Text += " = " + weightMST.ToString(); labelTotalWeight.Visible = true; buttonNext.Text = "Close"; } } } }
// Graph/Tree Traversal (Group A) is implemented here. private void ButtonNext_Click(object sender, EventArgs e) { if (buttonNext.Text == "Close") { this.Close(); } else { labelInformation.Visible = true; // Step 1 operation if (currentStep == 1) { // Highlight current step label1.ForeColor = Color.Red; labelStep1.ForeColor = Color.Red; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; // Initialise Prim's algorithm for (int i = 0; i < mapMatrix.GetSize(); i++) { if (mapMatrix.IsVertexExisting(i)) { remainingVertices.Add(i); } } labelInformation.Text = "Please pick a vertex of your choice:\nPlease click on the vertex of the graph."; buttonNext.Enabled = false; } // Step 2 operation else if (currentStep == 2) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = Color.Red; labelStep2.ForeColor = Color.Red; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; // Find minimum value of edge weight and candidate edges double min = Double.MaxValue; List <int[]> candidateEdges = new List <int[]>(); foreach (int i in visitedVertices) { foreach (int j in remainingVertices) { if (mapMatrix.ContainsEdge(i, j) && mapMatrix.GetEdge(i, j) < min) // Find minimum value of edge weight { min = mapMatrix.GetEdge(i, j); } } } foreach (int i in visitedVertices) { foreach (int j in remainingVertices) { if (mapMatrix.ContainsEdge(i, j) && mapMatrix.GetEdge(i, j) == min) // Find candidate edges { candidateEdges.Add(new int[2] { i, j }); } } } // More than two candidate edges - User operation required if (candidateEdges.Count >= 2) { // Show explanation labelInformation.Text = "Edges "; foreach (int[] edge in candidateEdges) { labelInformation.Text += Convert.ToChar(edge[0] + 'A').ToString() + Convert.ToChar(edge[1] + 'A').ToString() + ", "; } labelInformation.Text = labelInformation.Text.TrimEnd(", ".ToCharArray()); labelInformation.Text += " have the same weight (" + min.ToString() + "). Please pick one of your choice:\n" + "Please click on the vertex or the weight."; // Highlight candidate edges for (int i = 0; i < candidateEdges.Count; i++) { int v1 = Math.Min(candidateEdges[i][0], candidateEdges[i][1]); int v2 = Math.Max(candidateEdges[i][0], candidateEdges[i][1]); string labelName = "label" + Convert.ToChar(v1 + 'A').ToString() + Convert.ToChar(v2 + 'A').ToString(); foreach (Label label in exampleGraph.labelWeights) { if (label.Name == labelName) { label.ForeColor = Color.Red; break; } } foreach (Vertex vertex in vertices) { if (vertex.GetNumberIndex() == candidateEdges[i][1]) { vertex.labelName.ForeColor = Color.Red; break; } } } currentStep = 2; buttonNext.Enabled = false; } // Only one candidate edge avaliable - No user operation needed else { // Show explanation int[] newEdge = new int[2] { candidateEdges[0][0], candidateEdges[0][1] }; labelInformation.Text = "Edge " + Convert.ToChar(candidateEdges[0][0] + 'A').ToString() + Convert.ToChar(candidateEdges[0][1] + 'A').ToString() + " has the minimum weight joining a vertex already included to a vertex not already included (" + min.ToString() + ")," + " therefore it has been added to the Minimum Spanning Tree."; // Update Prim's algorithm foreach (Vertex vertex in vertices) { if (vertex.GetNumberIndex() == newEdge[1]) { weightMST += min; labelTotalWeight.Text += min.ToString() + " + "; visitedVertices.Add(newEdge[1]); remainingVertices.Remove(newEdge[1]); EdgeFocusOn(newEdge[0], newEdge[1]); exampleGraph.LabelFocusOn(newEdge[0], newEdge[1]); currentStep = 3; break; } } } } // Step 3 operation else // if (currentStep == 3) { // Highlight current steps label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = Color.Red; labelStep3.ForeColor = Color.Red; // Check if Prim's algorithm has finished if (remainingVertices.Any()) { labelInformation.Text = "We have not yet formed a Minimum Spanning Tree, so go back to STEP 2."; currentStep = 2; } else { labelInformation.Text = "Now we have picked " + (mapMatrix.Count() - 1).ToString() + " edges and has formed a Minimum Spanning Tree.\nTherefore Prim's algorithm has finished."; labelTotalWeight.Text = labelTotalWeight.Text.TrimEnd(" + ".ToCharArray()); labelTotalWeight.Text += " = " + weightMST.ToString(); labelTotalWeight.Visible = true; buttonNext.Text = "Close"; } } } }
public FormPrimOnMatrix(int accountID, string username, string accountName, string accountType, int example) { InitializeComponent(); // Show account name on the account menu. this.accountMenu.accountID = accountID; this.accountMenu.username = username; this.accountMenu.labelAccountName.Text = accountName; this.accountMenu.accountType = accountType; this.example = example; // Select the correct example graph to perform the demonstration. if (example == 1) { exampleGraph = new MinimumSpanningTreeExample1(this.panelGraph); } else { exampleGraph = new MinimumSpanningTreeExample2(this.panelGraph); } // Initialise the example graph. vertices = exampleGraph.GetVertices(); mapMatrix = exampleGraph.GetMatrix(); // Initialise the table for the example graph. for (int i = 0; i <= mapMatrix.Count(); i++) { DataGridViewColumn newColumn = new DataGridViewColumn { CellTemplate = new DataGridViewTextBoxCell(), SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable, Width = 60 }; if (i == 0) { newColumn.Width = 41; } dataGridViewGraph.Columns.Add(newColumn); } int count = 1; for (int i = 0; i < mapMatrix.GetSize(); i++) { if (mapMatrix.IsVertexExisting(i)) { dataGridViewGraph.Columns[count].HeaderText = Convert.ToChar('A' + i).ToString(); dataGridViewGraph.Columns[count].Name = "Column" + dataGridViewGraph.Columns[count].HeaderText; count++; } } count = 0; this.dataGridViewGraph.RowCount = mapMatrix.Count(); for (int i = 0; i < mapMatrix.GetSize(); i++) { if (mapMatrix.IsVertexExisting(i)) { this.dataGridViewGraph[0, count++].Value = (Convert.ToChar('A' + i)).ToString(); } } for (int col = 1; col <= mapMatrix.Count(); col++) { for (int row = 0; row < mapMatrix.Count(); row++) { int vStartIndex = mapMatrix.GetVertexIndex(dataGridViewGraph.Columns[col].HeaderText); int vFinishIndex = mapMatrix.GetVertexIndex(this.dataGridViewGraph[0, row].Value.ToString()); if (mapMatrix.ContainsEdge(vStartIndex, vFinishIndex)) { this.dataGridViewGraph[col, row].Value = mapMatrix.GetEdge(vStartIndex, vFinishIndex); } else { this.dataGridViewGraph[col, row].Value = "-"; } } } }
// Graph/Tree Traversal (Group A) is implemented here. private void ButtonNext_Click(object sender, EventArgs e) { if (buttonNext.Text == "Close") { this.Close(); } else { labelInformation.Visible = true; double min; // Step 1 operation if (currentStep == 1) { // Highlight current step label1.ForeColor = Color.Red; labelStep1.ForeColor = Color.Red; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; label4.ForeColor = SystemColors.ControlText; labelStep4.ForeColor = SystemColors.ControlText; label5.ForeColor = SystemColors.ControlText; labelStep5.ForeColor = SystemColors.ControlText; // Initialise Prim's algorithm for (int i = 0; i < mapMatrix.GetSize(); i++) { if (mapMatrix.IsVertexExisting(i)) { remainingVertices.Add(i); } } labelInformation.Text = "Please pick a vertex of your choice:\nPlease click on the headers of the tableau."; buttonNext.Enabled = false; } // Step 2 operation else if (currentStep == 2) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = Color.Red; labelStep2.ForeColor = Color.Red; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; label4.ForeColor = SystemColors.ControlText; labelStep4.ForeColor = SystemColors.ControlText; label5.ForeColor = SystemColors.ControlText; labelStep5.ForeColor = SystemColors.ControlText; // Find minimum value of edge weight and candidate edges min = double.MaxValue; candidateEdges.Clear(); foreach (int i in visitedVertices) { foreach (int j in remainingVertices) { if (mapMatrix.ContainsEdge(i, j) && mapMatrix.GetEdge(i, j) < min) // Find minimum value of edge weight { min = mapMatrix.GetEdge(i, j); } } } foreach (int i in visitedVertices) { foreach (int j in remainingVertices) { if (mapMatrix.ContainsEdge(i, j) && mapMatrix.GetEdge(i, j) == min) // Find candidate edges { candidateEdges.Add(new int[2] { i, j }); } } } // Show candidate edges on the table for (int i = 0; i < candidateEdges.Count; i++) { char v1 = Convert.ToChar(candidateEdges[i][0] + 'A'); char v2 = Convert.ToChar(candidateEdges[i][1] + 'A'); for (int col = 1; col < dataGridViewGraph.ColumnCount; col++) { if (dataGridViewGraph.Columns[col].HeaderText[0] == v1) { for (int row = 0; row < dataGridViewGraph.RowCount; row++) { if (dataGridViewGraph[0, row].Value.ToString() == v2.ToString()) { dataGridViewGraph[col, row].Style.ForeColor = Color.Red; dataGridViewGraph[col, row].Style.SelectionForeColor = Color.Red; } } } } } // More than two candidate edges - User operation required if (candidateEdges.Count >= 2) { labelInformation.Text = "Edges "; foreach (int[] edge in candidateEdges) { labelInformation.Text += Convert.ToChar(edge[0] + 'A').ToString() + Convert.ToChar(edge[1] + 'A').ToString() + ", "; } labelInformation.Text = labelInformation.Text.TrimEnd(", ".ToCharArray()); labelInformation.Text += " have the same weight (" + min.ToString() + "). Please pick one of your choice:\n" + "Please click on the weights in the tableau."; currentStep = 2; buttonNext.Enabled = false; } // Only one candidate edge avaliable - No user operation needed else if (candidateEdges.Count == 1) { newEdge = new int[2] { candidateEdges[0][0], candidateEdges[0][1] }; labelInformation.Text = "Edge " + Convert.ToChar(candidateEdges[0][0] + 'A').ToString() + Convert.ToChar(candidateEdges[0][1] + 'A').ToString() + " has the minimum weight from the uncircled entries in the marked column(s) (" + min.ToString() + ")," + " therefore it has been chosen."; currentStep = 3; } // No candidate edge found - Algorithm about to finish else { labelInformation.Text = ""; currentStep = 3; } } // Step 3 operation else if (currentStep == 3) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = Color.Red; labelStep3.ForeColor = Color.Red; label4.ForeColor = SystemColors.ControlText; labelStep4.ForeColor = SystemColors.ControlText; label5.ForeColor = SystemColors.ControlText; labelStep5.ForeColor = SystemColors.ControlText; // Check if Prim's algorithm has finished if (candidateEdges.Count == 0) { labelInformation.Text = "There is no available entry to be chosen, and therefore Prim's algorithm has finished.\n" + "We have found a Minimum Spanning Tree."; labelTotalWeight.Text = labelTotalWeight.Text.TrimEnd(" + ".ToCharArray()); labelTotalWeight.Text += " = " + weightMST.ToString(); labelTotalWeight.Visible = true; buttonNext.Text = "Close"; } else { labelInformation.Text += "\nNow that we have found an entry, we should go to STEP 4."; currentStep = 4; } } // Step 4 operation else if (currentStep == 4) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; label4.ForeColor = Color.Red; labelStep4.ForeColor = Color.Red; label5.ForeColor = SystemColors.ControlText; labelStep5.ForeColor = SystemColors.ControlText; // Update Prim's algorithm and show demonstration labelInformation.Text = ""; weightMST += mapMatrix.GetEdge(newEdge[0], newEdge[1]); labelTotalWeight.Text += mapMatrix.GetEdge(newEdge[0], newEdge[1]).ToString() + " + "; visitedVertices.Add(newEdge[1]); remainingVertices.Remove(newEdge[1]); EdgeFocusOn(newEdge[0], newEdge[1]); exampleGraph.LabelFocusOn(newEdge[0], newEdge[1]); char v1 = Convert.ToChar(newEdge[0] + 'A'); char v2 = Convert.ToChar(newEdge[1] + 'A'); for (int col = 1; col < dataGridViewGraph.ColumnCount; col++) { for (int row = 0; row < dataGridViewGraph.RowCount; row++) { if (dataGridViewGraph.Columns[col].HeaderText[0] == v1 && dataGridViewGraph[0, row].Value.ToString() == v2.ToString()) { dataGridViewGraph.Columns[row + 1].HeaderCell.Style.ForeColor = Color.Red; dataGridViewGraph.Columns[row + 1].HeaderCell.Style.SelectionForeColor = Color.Red; dataGridViewGraph.Columns[row + 1].HeaderCell.Value = dataGridViewGraph.Columns[row + 1].HeaderCell.Value.ToString() + " " + visitedVertices.Count.ToString(); dataGridViewGraph[col, row].Style.Font = boldFont; dataGridViewGraph[col, row].Style.ForeColor = Color.Red; dataGridViewGraph[col, row].Style.SelectionForeColor = Color.Red; } else if (dataGridViewGraph[col, row].Style.Font != boldFont) { dataGridViewGraph[col, row].Style.ForeColor = SystemColors.ControlText; dataGridViewGraph[col, row].Style.SelectionForeColor = SystemColors.ControlText; if (visitedVertices.Contains(Convert.ToInt32(Convert.ToChar(dataGridViewGraph[0, row].Value) - 'A'))) { dataGridViewGraph[col, row].Style.Font = strikeoutFont; } } } } currentStep = 5; } // Step 5 operation else // if (currentStep == 5) { // Highlight current step label1.ForeColor = SystemColors.ControlText; labelStep1.ForeColor = SystemColors.ControlText; label2.ForeColor = SystemColors.ControlText; labelStep2.ForeColor = SystemColors.ControlText; label3.ForeColor = SystemColors.ControlText; labelStep3.ForeColor = SystemColors.ControlText; label4.ForeColor = SystemColors.ControlText; labelStep4.ForeColor = SystemColors.ControlText; label5.ForeColor = Color.Red; labelStep5.ForeColor = Color.Red; // Refresh and go to Step 2 labelInformation.Text = ""; currentStep = 2; } } }
/// <summary> /// Shows the edge weight on the label. /// </summary> public void DrawLabelWeights() { for (int v1 = 0; v1 < mapMatrix.GetSize(); v1++) { for (int v2 = 0; v2 < mapMatrix.GetSize(); v2++) { labelWeights[v1, v2].Enabled = mapMatrix.ContainsEdge(v1, v2); labelWeights[v1, v2].Visible = mapMatrix.ContainsEdge(v1, v2); } } foreach (DijkstraVertexLabel v1 in vertices) { foreach (DijkstraVertexLabel v2 in vertices) { int vStart = v1.GetNumberIndex(); int vFinish = v2.GetNumberIndex(); if (mapMatrix.ContainsEdge(vStart, vFinish)) { if (mapMatrix.ContainsEdge(vFinish, vStart) && mapMatrix.GetEdge(vStart, vFinish) != mapMatrix.GetEdge(vFinish, vStart)) { if (vFinish > vStart) { Point midPoint = new Point ( (v1.GetCentreLocation().X + v2.GetCentreLocation().X) / 2, (v1.GetCentreLocation().Y + v2.GetCentreLocation().Y) / 2 ); Point pointForward = new Point ( Convert.ToInt32(Math.Round(midPoint.X + 42 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(midPoint.Y - 42 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))) ); Point pointBackward = new Point ( Convert.ToInt32(Math.Round(midPoint.X - 42 * (v2.GetCentreLocation().Y - v1.GetCentreLocation().Y) / v1.GetDistance(v2))), Convert.ToInt32(Math.Round(midPoint.Y + 42 * (v2.GetCentreLocation().X - v1.GetCentreLocation().X) / v1.GetDistance(v2))) ); labelWeights[vStart, vFinish].Location = new Point ( pointForward.X - labelWeights[vStart, vFinish].Width, pointForward.Y - labelWeights[vStart, vFinish].Height ); labelWeights[vStart, vFinish].Text = mapMatrix.GetEdge(vStart, vFinish).ToString(); labelWeights[vFinish, vStart].Location = new Point ( pointBackward.X - labelWeights[vFinish, vStart].Width, pointBackward.Y - labelWeights[vFinish, vStart].Height ); labelWeights[vFinish, vStart].Text = mapMatrix.GetEdge(vFinish, vStart).ToString(); } } else if (labelWeights[vStart, vFinish].Enabled) { Point midPoint = new Point ( (v1.GetCentreLocation().X + v2.GetCentreLocation().X) / 2, (v1.GetCentreLocation().Y + v2.GetCentreLocation().Y) / 2 ); labelWeights[vStart, vFinish].Location = new Point ( midPoint.X - labelWeights[vStart, vFinish].Width, midPoint.Y - labelWeights[vStart, vFinish].Height ); labelWeights[vStart, vFinish].Text = mapMatrix.GetEdge(vStart, vFinish).ToString(); labelWeights[vFinish, vStart].Enabled = false; labelWeights[vFinish, vStart].Visible = false; } } } } }