МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ "ЛЬВІВСЬКА ПОЛІТЕХНІКА"
Інститут КНІТ
Кафедра ПЗ
ЗВІТ
До лабораторної роботи № 4
На тему: “Послідовний метод компонування за зв’язністю”
З дисципліни: “Комбінаторні методи та алгоритми”
Лектор:
проф. кафедри ПЗ
Базилевич Р.П.
Львів – 2013
Тема роботи: Послідовний метод компонування за зв’язністю
Мета роботи: Дослідження алгоритму послідовного методу компонування за зв’язністю.
Теоретичні відомості
Завданням даної лабораторної роботи є процес розбиття елементів графу на вузли за допомогою ілюстративної програми та тестування конкретних випадків з її допомогою. Як приклад, для порівняльної характеристики використати стандартну тестову задачу Штейнберга, а також графи з різною кількістю елементів для дослідження характеристик методу. В ході дослідження процесу розбиття на вузли елементів графу зробити висновки відносно обчислювальної складності та точності методу.
Розглянемо загальну схему методу й особливості його конкретної реалізації на ЕОМ.
Нехай задана схема множина елементів E={e1, ... , en} і матриця суміжності, яка описує зв’язки між цими елементами. Визначемо послідовний процес призначення елементів eiE (i=1, ..., n) у вузли Tr(r=1, 2, ..., ), на кожному кроці якого вибирається один із нерозподілених елементів і приписується черговому вузлу.
Вузол вважається завершеним, якщо число елементів у вузлі дорівнює заданому числу k або призначення любого з нерозподілених елементів призводить до утворення такого числа зовнішніх зв'язків вузла, що перевищує гранично припустиме значення v.
Після завершення чергового вузла аналогічна процедура повторюється для наступного вузла, причому кандидатами для призначення є елементи, не включені в попередні вузли. Процес закінчується, коли всі елементи з множини Е розподілені.
Зауважимо, що елемент е0, що відповідає набору зовнішніх виводів схеми, рахується розподіленим у вузол T0.
Тактика призначення елементів складається в наступному.
n°1. На черговому кроці процесу виділяються ті з ще нерозподілених елементів, включення кожного з яких у даний вузол не порушує обмежень по числу елементів і виводів вузла.
n°2. Елементом, який включений у вузол на черговому кроці, є той із вибраних у n°1 елементів, що має найбільше число зв'язків з елементами, уже поміщеними у вузол (максимальна кон’юнкція). При кількох таких елементах включається той з них, що має мінімальну диз'юнкцію з елементами вузла.
Код програми
namespace poslid
{
public partial class Form1 : Form
{
public struct pointS
{
public int x;
public int y;
public int color;
public bool used;
}
pointS[] points = new pointS[1];
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
int val = (int)numericUpDown1.Value;
dataGridView1.Columns.Clear();
for (int i = 0; i < val; i++) {
//col
dataGridView1.Columns.Add('x' + (i + 1).ToString(), 'x' + (i + 1).ToString());
dataGridView1.Columns[dataGridView1.Columns.Count - 1].Width = 25;
//row
dataGridView1.Rows.Add(1);
dataGridView1.Rows[dataGridView1.Rows.Count - 1].HeaderCell.Value = 'x' + (i + 1).ToString();
dataGridView1.RowHeadersWidth = 50;
}
Random r = new Random();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
double n =r.NextDouble() * 10 - r.NextDouble() * 10;
if (n < 0) n = 0;
if (i == j) n = 0;
if (i > j)
n = Double.Parse(dataGridView1.Rows[j].Cells[i].Value.ToString());
dataGridView1.Rows[i].Cells[j].Value = (int)(n);
}
points = new pointS[val];
for (int i = 0; i < val; i++) {
points[i].x = r.Next(pictureBox1.Width);
points[i].y = r.Next(pictureBox1.Height);
}
}
private void button1_Click(object sender, EventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
g.Clear(SystemColors.Control);
for (int i = 0; i < points.Length; i++)
{
g.FillEllipse(Brushes.Black, new Rectangle(points[i].x, points[i].y, 4, 4));
g.DrawString((i + 1).ToString(), SystemFonts.DefaultFont, Brushes.Black, new Point(points[i].x+2, points[i].y+2));
}
}
private void button2_Click(object sender, EventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
g.Clear(SystemColors.Control);
for (int i = 0; i < points.Length; i++)
{
g.FillEllipse(Brushes.Black, new Rectangle(points[i].x, points[i].y, 4, 4));
g.DrawString((i + 1).ToString(), SystemFonts.DefaultFont, Brushes.Black, new Point(points[i].x + 2, points[i].y + 2));
}
for (int i = 0; i < dataGridView1.Rows.Count; i++)
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
if (i > j)
continue;
int pointFrom = i;
int pointTo = j;
if (int.Parse(dataGridView1.Rows[i].Cells[j].Value.ToString()) > 0)
g.DrawLine(Pens.Gray, new Point(points[pointFrom].x, points[pointFrom].y), new Point(points[pointTo].x, points[pointTo].y));
}
}
private void numericUpDown2_ValueChanged(object sender, EventArgs e)
{
int val = (int)numericUpDown2.Value;
dataGridView2.Columns.Clear();
for (int i = 0; i < val; i++)
{
//col
dataGridView2.Columns.Add('G' + (i + 1).ToString(), 'G' + (i + 1).ToString());
dataGridView2.Columns[dataGridView2.Columns.Count - 1].Width = 30;
}
dataGridView2.Rows.Add(1);
dataGridView2.RowHeadersVisible = false;
Random r = new Random();
for (int j = 0; j < dataGridView2.Columns.Count; j++)
{
int sum = 0;
for (int k = 0; k < j; k++)
sum += int.Parse(dataGridView2.Rows[0].Cells[k].Value.ToString());
int n = r.Next(Math.Min(points.Length / 2 + 1, points.Length - sum + 1));
if (n == 0 && points.Length - sum > 0)
n += 1;
if (j == dataGridView2.Columns.Count - 1)
n = points.Length - sum;
dataGridView2.Rows[0].Cells[j].Value = n;
}
}
private int getStep(int vert)
{
int step = 0;
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
if (points[i].used) continue;
step += int.Parse(dataGridView1.Rows[vert].Cells[i].Value.ToString());
}
return step;
}
private int getMaxStep()
{
int maxStepPoint = -1;
for (int i = 0; i < points.Length; i++)
{
if (points[i].used) continue;
if (maxStepPoint == -1)
maxStepPoint = i;
else if (getStep(maxStepPoint) < getStep(i))
maxStepPoint = i;
}
return maxStepPoint;
}
private int getReberFromNotSelected(int vert, List<int> l)
{
int sumR = 0;
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
if (points[i].used) continue;
if (l.IndexOf(i) >= 0) continue; //it is in List
sumR += int.Parse(dataGridView1.Rows[vert].Cells[i].Value.ToString());
}
return sumR;
}
private int getReberFromSelected(int vert, List<int> l)
{
int sumR = 0;
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
//if (points[i].used) continue;
if (l.IndexOf(i) < 0) continue; //it is not in List
sumR += int.Parse(dataGridView1.Rows[vert].Cells[i].Value.ToString());
}
return sumR;
}
private void button3_Click(object sender, EventArgs e)
{
Random r = new Random();
List<int>[] G = new List<int>[dataGridView2.Columns.Count];
for (int curBlock = 0; curBlock < dataGridView2.Columns.Count; curBlock++)
{
int curBlockSize = int.Parse(dataGridView2.Rows[0].Cells[curBlock].Value.ToString());
List<int> H = new List<int>();
int m_s = getMaxStep();
H.Add(m_s);
points[m_s].used = true;
while (H.Count < curBlockSize)
{
int new_m_s = -1;
for (int i = 0; i < points.Length; i++)
{
if(points[i].used)
continue;
if (new_m_s == -1)
new_m_s = i;
else if (getReberFromNotSelected(i, H) - getReberFromSelected(i, H) < getReberFromNotSelected(new_m_s, H) - getReberFromSelected(new_m_s, H))
{
new_m_s = i;
}
}
points[new_m_s].used = true;
H.Add(new_m_s);
}
G[curBlock] = new List<int>();
G[curBlock].AddRange(H);
}
String s = "";
for (int curBlock = 0; curBlock < dataGridView2.Columns.Count; curBlock++)
{
s += (curBlock + 1).ToString() + ": ";
for (int i = 0; i < G[curBlock].Count; i++)
{
s += (G[curBlock][i]+1)+" ";
}
s += "\n";
}
MessageBox.Show(s);
for (int i = 0; i < points.Length; i++)
{
points[i].used = false;
points[i].color = 0;
}
}
}
Результат виконання
Рис. 1 Розбиття графів
Висновок
На даній лабораторній роботі я розробив програму на мові C# для вирішення задачі компонування електричних схем за зв’язністю. Результати були задовільні, тому певні аспекти алгоритму були виведені у спрощеному варіанті. При необхідності програму можна доробити для більшої наочності та розфарбувати граф відповідно до групування.