Построение потокового графа
Министерство образования и науки РФ
Федеральное государственное бюджетное
образовательное учреждение высшего профессионального образования «Ивановский государственный энергетический университет имени В.И. Ленина»
Кафедра программного обеспечения компьютерных систем
Контрольная работа
по дисциплине «Тестирование ПО»
Выполнил: студент
группы 5-80к
Сошко О.А.
Проверил: к.т.н., доцент
Зубков В.П.
Иваново, 2017
Часть 1. Разработка приложения
Задание
Разработать программу построения матрицы смежности, инцидентности и списка ребер для произвольного графа.
2. Описание предметной области
В предметной области построения графа, основной сущностью будет сам граф - совокупность непустого множества вершин и наборов пар вершин (связей между вершинами), в свою очередь граф состоит из такой сущности, как вершина и связей – рёбер.
Для вершин существенны следующие признаки (атрибуты):
· Координата по Х;
· Координата по У.
Связь – ребро, можно выделить тоже как сущность с атрибутами:
· Вершина 1;
· Вершина 2;
Исходный код
Класс Form1.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace SystAnalys_lr1
{
public partial class Form1 : Form
{
DrawGraph G;
List<Vertex> V;
List<Edge> E;
int[,] AMatrix; //матрица смежности
int[,] IMatrix; //матрица инцидентности
int selected1; //выбранные вершины, для соединения линиями
int selected2;
public Form1()
{
InitializeComponent();
V = new List<Vertex>();
G = new DrawGraph(sheet.Width, sheet.Height); //Инициализация рабочей поверхности
E = new List<Edge>();
sheet.Image = G.GetBitmap();
}
//кнопка - рисовать вершину
private void drawVertexButton_Click(object sender, EventArgs e)
{
drawVertexButton.Enabled = false;
drawEdgeButton.Enabled = true;
deleteButton.Enabled = true;
G.clearSheet();
G.drawALLGraph(V, E);
sheet.Image = G.GetBitmap();
}
//кнопка - рисовать ребро
private void drawEdgeButton_Click(object sender, EventArgs e)
{
drawEdgeButton.Enabled = false;
drawVertexButton.Enabled = true;
deleteButton.Enabled = true;
G.clearSheet();
G.drawALLGraph(V, E);
sheet.Image = G.GetBitmap();
selected1 = -1;
selected2 = -1;
}
//кнопка - удалить элемент
private void deleteButton_Click(object sender, EventArgs e)
{
deleteButton.Enabled = false;
drawVertexButton.Enabled = true;
drawEdgeButton.Enabled = true;
G.clearSheet();
G.drawALLGraph(V, E);
sheet.Image = G.GetBitmap();
}
//кнопка - удалить граф
private void deleteALLButton_Click(object sender, EventArgs e)
{
drawVertexButton.Enabled = true;
drawEdgeButton.Enabled = true;
deleteButton.Enabled = true;
const string message = "Вы действительно хотите полностью удалить граф?";
const string caption = "Удаление";
var MBSave = MessageBox.Show(message, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (MBSave == DialogResult.Yes)
{
V.Clear();
E.Clear();
G.clearSheet();
sheet.Image = G.GetBitmap();
}
}
//кнопка - матрица смежности
private void buttonAdj_Click(object sender, EventArgs e)
{
createAdjAndOut();
}
//кнопка - матрица инцидентности
private void buttonInc_Click(object sender, EventArgs e)
{
createIncAndOut();
}
private void sheet_MouseClick(object sender, MouseEventArgs e)
{
//нажата кнопка "рисовать вершину"
if (drawVertexButton.Enabled == false)
{
V.Add(new Vertex(e.X, e.Y));
G.drawVertex(e.X, e.Y, V.Count.ToString());
sheet.Image = G.GetBitmap();
}
//нажата кнопка "рисовать ребро"
if (drawEdgeButton.Enabled == false)
{
if (e.Button == MouseButtons.Left)
{
for (int i = 0; i < V.Count; i++)
{
if (Math.Pow((V[i].x - e.X), 2) + Math.Pow((V[i].y - e.Y), 2) <= G.R * G.R)
{
if (selected1 == -1)
{
G.drawSelectedVertex(V[i].x, V[i].y);
selected1 = i;
sheet.Image = G.GetBitmap();
break;
}
if (selected2 == -1)
{
G.drawSelectedVertex(V[i].x, V[i].y);
selected2 = i;
E.Add(new Edge(selected1, selected2));
G.drawEdge(V[selected1], V[selected2], E[E.Count - 1], E.Count - 1);
selected1 = -1;
selected2 = -1;
sheet.Image = G.GetBitmap();
break;
}
}
}
}
if (e.Button == MouseButtons.Right)
{
if ((selected1 != -1) &&
(Math.Pow((V[selected1].x - e.X), 2) + Math.Pow((V[selected1].y - e.Y), 2) <= G.R * G.R))
{
G.drawVertex(V[selected1].x, V[selected1].y, (selected1 + 1).ToString());
selected1 = -1;
sheet.Image = G.GetBitmap();
}
}
}
//нажата кнопка "удалить элемент"
if (deleteButton.Enabled == false)
{
bool flag = false; //удалили ли что-нибудь по ЭТОМУ клику
//ищем, возможно была нажата вершина
for (int i = 0; i < V.Count; i++)
{
if (Math.Pow((V[i].x - e.X), 2) + Math.Pow((V[i].y - e.Y), 2) <= G.R * G.R)
{
for (int j = 0; j < E.Count; j++)
{
if ((E[j].v1 == i) || (E[j].v2 == i))
{
E.RemoveAt(j);
j--;
}
else
{
if (E[j].v1 > i) E[j].v1--;
if (E[j].v2 > i) E[j].v2--;
}
}
V.RemoveAt(i);
flag = true;
break;
}
}
//ищем, возможно было нажато ребро
if (!flag)
{
for (int i = 0; i < E.Count; i++)
{
if (E[i].v1 == E[i].v2) //если это петля
{
if ((Math.Pow((V[E[i].v1].x - G.R - e.X), 2) + Math.Pow((V[E[i].v1].y - G.R - e.Y), 2) <= ((G.R + 2) * (G.R + 2))) &&
(Math.Pow((V[E[i].v1].x - G.R - e.X), 2) + Math.Pow((V[E[i].v1].y - G.R - e.Y), 2) >= ((G.R - 2) * (G.R - 2))))
{
E.RemoveAt(i);
flag = true;
break;
}
}
else //не петля
{
if (((e.X - V[E[i].v1].x) * (V[E[i].v2].y - V[E[i].v1].y) / (V[E[i].v2].x - V[E[i].v1].x) + V[E[i].v1].y) <= (e.Y + 4) &&
((e.X - V[E[i].v1].x) * (V[E[i].v2].y - V[E[i].v1].y) / (V[E[i].v2].x - V[E[i].v1].x) + V[E[i].v1].y) >= (e.Y - 4))
{
if ((V[E[i].v1].x <= V[E[i].v2].x && V[E[i].v1].x <= e.X && e.X <= V[E[i].v2].x) ||
(V[E[i].v1].x >= V[E[i].v2].x && V[E[i].v1].x >= e.X && e.X >= V[E[i].v2].x))
{
E.RemoveAt(i);
flag = true;
break;
}
}
}
}
}
//если что-то было удалено, то обновляем граф на экране
if (flag)
{
G.clearSheet();
G.drawALLGraph(V, E);
sheet.Image = G.GetBitmap();
}
}
}
//создание матрицы смежности и вывод в листбокс
private void createAdjAndOut()
{
AMatrix = new int[V.Count, V.Count];
G.fillAdjacencyMatrix(V.Count, E, AMatrix);
listBoxMatrix.Items.Clear();
string sOut = " ";
for (int i = 0; i < V.Count; i++)
sOut += (i + 1) + " ";
listBoxMatrix.Items.Add(sOut);
for (int i = 0; i < V.Count; i++)
{
sOut = (i + 1) + " | ";
for (int j = 0; j < V.Count; j++)
sOut += AMatrix[i, j] + " ";
listBoxMatrix.Items.Add(sOut);
}
}
//создание матрицы инцидентности и вывод в листбокс
private void createIncAndOut()
{
if (E.Count > 0)
{
IMatrix = new int[V.Count, E.Count];
G.fillIncidenceMatrix(V.Count, E, IMatrix);
listBoxMatrix.Items.Clear();
string sOut = " ";
for (int i = 0; i < E.Count; i++)
sOut += (char)('a' + i) + " ";
listBoxMatrix.Items.Add(sOut);
for (int i = 0; i < V.Count; i++)
{
sOut = (i + 1) + " | ";
for (int j = 0; j < E.Count; j++)
sOut += IMatrix[i, j] + " ";
listBoxMatrix.Items.Add(sOut);
}
}
else
listBoxMatrix.Items.Clear();
}
//вывод списка рёбер
private void chainButton_Click(object sender, EventArgs e)
{
listBoxMatrix.Items.Clear();
for (int i=0; i<E.Count;i++)
{
listBoxMatrix.Items.Add((i+1)+". "+"[" + (E[i].v1+1) + "," + (E[i].v2+1) + "]");
}
}
}
} Класс CodeFile.cs
using System.Collections.Generic;
using System.Drawing;
namespace SystAnalys_lr1
{
class Vertex
{
public int x, y;
public Vertex(int x, int y)
{
this.x = x;
this.y = y;
}
}
class Edge
{
public int v1, v2;
public Edge(int v1, int v2)
{
this.v1 = v1;
this.v2 = v2;
}
}
class DrawGraph
{
Bitmap bitmap;
Pen blackPen;
Pen redPen;
Pen darkGoldPen;
Graphics gr;
Font fo;
Brush br;
PointF point; //точка с координатами х и у
public int R = 20; //радиус окружности вершины
public DrawGraph(int width, int height)
{
bitmap = new Bitmap(width, height);
gr = Graphics.FromImage(bitmap);
clearSheet();
blackPen = new Pen(Color.Black);
blackPen.Width = 2;
redPen = new Pen(Color.Red);
redPen.Width = 2;
darkGoldPen = new Pen(Color.DarkGoldenrod);
darkGoldPen.Width = 2;
fo = new Font("Arial", 15);
br = Brushes.Black;
}
public Bitmap GetBitmap()
{
return bitmap;
}
public void clearSheet()
{
gr.Clear(Color.White);
}
public void drawVertex(int x, int y, string number)
{
gr.FillEllipse(Brushes.White, (x - R), (y - R), 2 * R, 2 * R);
gr.DrawEllipse(blackPen, (x - R), (y - R), 2 * R, 2 * R);
point = new PointF(x - 9, y - 9);
gr.DrawString(number, fo, br, point);
}
public void drawSelectedVertex(int x, int y)
{
gr.DrawEllipse(redPen, (x - R), (y - R), 2 * R, 2 * R);
}
public void drawEdge(Vertex V1, Vertex V2, Edge E, int numberE)
{
if (E.v1 == E.v2)
{
gr.DrawArc(darkGoldPen, (V1.x - 2 * R), (V1.y - 2 * R), 2 * R, 2 * R, 90, 270);
point = new PointF(V1.x - (int)(2.75 * R), V1.y - (int)(2.75 * R));
gr.DrawString(((char)('a' + numberE)).ToString(), fo, br, point);
drawVertex(V1.x, V1.y, (E.v1 + 1).ToString());
}
else
{
gr.DrawLine(darkGoldPen, V1.x, V1.y, V2.x, V2.y);
point = new PointF((V1.x + V2.x) / 2, (V1.y + V2.y) / 2);
gr.DrawString(((char)('a' + numberE)).ToString(), fo, br, point);
drawVertex(V1.x, V1.y, (E.v1 + 1).ToString());
drawVertex(V2.x, V2.y, (E.v2 + 1).ToString());
}
}
public void drawALLGraph(List<Vertex> V, List<Edge> E)
{
//рисуем ребра
for (int i = 0; i < E.Count; i++)
{
if (E[i].v1 == E[i].v2)
{
gr.DrawArc(darkGoldPen, (V[E[i].v1].x - 2 * R), (V[E[i].v1].y - 2 * R), 2 * R, 2 * R, 90, 270);
point = new PointF(V[E[i].v1].x - (int)(2.75 * R), V[E[i].v1].y - (int)(2.75 * R));
gr.DrawString(((char)('a' + i)).ToString(), fo, br, point);
}
else
{
gr.DrawLine(darkGoldPen, V[E[i].v1].x, V[E[i].v1].y, V[E[i].v2].x, V[E[i].v2].y);
point = new PointF((V[E[i].v1].x + V[E[i].v2].x) / 2, (V[E[i].v1].y + V[E[i].v2].y) / 2);
gr.DrawString(((char)('a' + i)).ToString(), fo, br, point);
}
}
//рисуем вершины
for (int i = 0; i < V.Count; i++)
{
drawVertex(V[i].x, V[i].y, (i + 1).ToString());
}
}
//заполняет матрицу смежности
public void fillAdjacencyMatrix(int numberV, List<Edge> E, int[,] matrix)
{
for (int i = 0; i < numberV; i++)
for (int j = 0; j < numberV; j++)
matrix[i, j] = 0;
for (int i = 0; i < E.Count; i++)
{
matrix[E[i].v1, E[i].v2] = 1;
matrix[E[i].v2, E[i].v1] = 1;
}
}
//заполняет матрицу инцидентности
public void fillIncidenceMatrix(int numberV, List<Edge> E, int[,] matrix)
{
for (int i = 0; i < numberV; i++)
for (int j = 0; j < E.Count; j++)
matrix[i, j] = 0;
for (int i = 0; i < E.Count; i++)
{
matrix[E[i].v1, i] = 1;
matrix[E[i].v2, i] = -1;
}
}
}
}
Спецификация
Написать программу построения матрицы смежности, инцидентности и списка рёбер для произвольного графа на языке C#. При написании использовать платформу WindowsForm.
Входные данные вводятся вручную на графическом поле интерфейса с помощью таких встроенных инструментов, как «вершина» и «ребро».
Результат построения графа отображается на графическом поле интерфейса, а матрицы смежности, инцидентности и список рёбер выводится в listBox.
Программа должна выполняться на операционных системах семейства Windows версии Seven и выше. При ошибках пользовательского ввода или внутренних ошибках программа должна осуществлять вывод соответствующего сообщения.
Ограничения
· Максимальное число вершин графа не должно превышать 10. (CountVertex < 11)
· Направление рёбер задаётся от первой вершины ко второй, данную тенденцию можно проследить при выводе списка рёбер.
· Формат вывода матрицы смежности:
… | |||
… | |||
· Формат матрицы инцидентности:
A | … | N | |
… | |||
-1 |
· Формат вывода списка рёбер:
1. [1,2]
2. ….
· Название рёбер обозначается латинскими буквами;
· Номера вершин обозначаются натуральными цифрами.
Классы эквивалентности
№ | Входное или выходное событие | Классы эквивалентности | |
Допустимые | Недопустимые | ||
Ввод вершин | Вершины имеют вид окружности с номером N | N<1 | |
N – натуральное число | N>10 | ||
S<11 | N – не цифра | ||
Контроль кол-ва вершин | 1<=S<=10 | S<1 | |
S>10 | |||
Вывод данных | Матрица инцидентности размером MxN(M-число вершин; N-число рёбер) | Матрица инцидентности размером NxM | |
Матрица смежности размеро MxM(M-число вершин) | Элементы матрицы отличаются от 1,0,-1. | ||
Элементы матрицы 1,0,-1 |
Часть 2. Модульное тестирование. Тестирование методом «белого ящика».
Модуль drawALLGraph
Программный код модуля приведен в листинге 1.
1. | public void drawALLGraph(List<Vertex> V, List<Edge> E) | |
2. | { | |
3. | for (int i = 0; i < E.Count; i++) | |
4. | { | |
5. | if (E[i].v1 == E[i].v2) | |
6. | { | |
7. | gr.DrawArc(darkGoldPen, (V[E[i].v1].x - 2 * R), (V[E[i].v1].y - 2 * R), 2 * R, 2 * R, 90, 270); | |
8. | point = new PointF(V[E[i].v1].x - (int)(2.75 * R), V[E[i].v1].y - (int)(2.75 * R)); | |
9. | gr.DrawString(((char)('a' + i)).ToString(), fo, br, point); | |
10. | } | |
11. | Else | |
12. | { | |
13. | gr.DrawLine(darkGoldPen, V[E[i].v1].x, V[E[i].v1].y, V[E[i].v2].x, V[E[i].v2].y); | |
14. | point = new PointF((V[E[i].v1].x + V[E[i].v2].x) / 2, (V[E[i].v1].y + V[E[i].v2].y) / 2); | |
15. | gr.DrawString(((char)('a' + i)).ToString(), fo, br, point); | |
16. | } | |
17. | } | |
18. | for (int i = 0; i < V.Count; i++) | |
19. | { | |
20. | drawVertex(V[i].x, V[i].y, (i + 1).ToString()); | |
21. | } | |
22. | } |
Построение потокового графа
Потоковый граф рассматриваемого модуля с указанием регионов и выделенными предикатными узлами приведен ниже.
Управляющий граф не содержит сложных условий, следовательно потоковый граф такойже как и управляющий.