//Обчислення матриці подібності public void calcResultMatrix(TextBox[][] valueEl, int sizeMatrix, NumericUpDown[] numUpDnArray) { mas = new List<HashSet<string>>();//Копіюю елементи з TextBox[][] в List for (int i = 0; i < sizeMatrix; i++) { mas.Add(new HashSet<string>()); for (int j = 0; j < (int)numUpDnArray[i].Value; j++) { if (valueEl[i][j].Text == "") continue; mas[i].Add(valueEl[i][j].Text); } } for (int i = 0; i < mas.Count; i++)//Видалення пустих рядків { if (mas.ElementAt(i).Count == 0) mas.RemoveAt(i); } //////////////////////////////////////////////////////////////////////////////////////// resultMatrix = new List<List<int>>(); for (int i = 0; i < mas.Count; i++) { resultMatrix.Add(new List<int>()); for (int j = 0; j < mas.Count; j++) { resultMatrix[i].Add(0); } } List<String> list; //List для злиття 2 рядків елементів for (int i = 0; i < mas.Count - 1; i++) { list = new List<String>(); for (int j = 1; j < mas.Count; j++) { if (i == j) continue; list.AddRange(mas[i]);//Копіюю 1 рядок list.AddRange(mas[j]);//Копіюю 2 рядок /* list.Distinct() видаляє елементи, які повторюються, залишаючи перший з них. * (list.Count - list.Distinct().Count()))*2 - дізнаюсь скільки спільних елементів * (list.Count - (list.Count - list.Distinct().Count()) * 2) - дізнаюсь скільки унікальних елементів * countUEl - (list.Count - (list.Count - list.Distinct().Count()) * 2) - від загальної кількості віднімаю унікальні в 2 рядках */ resultMatrix[i][j] = countUEl - (list.Count - (list.Count - list.Distinct().Count()) * 2); resultMatrix[j][i] = countUEl - (list.Count - (list.Count - list.Distinct().Count()) * 2); list.Clear();//Очищаю для наступної пари рядків } } }
//Створює графи на основі уточнених груп private Graph GenerateGraph() { graphs = new List<Graph>();//Лист графів для кожної групи for (int i = 0; i < calc.setElAfterV.Count; i++) { var Graph = new Graph(); HashSet<string> tempSet = new HashSet<string>(); foreach (string k in calc.setElAfterV[i])//Формування вершин { var Vertex = new DataVertex(k); Graph.AddVertex(Vertex); } var vlist = Graph.Vertices.ToList(); for (int j = 0; j < calc.groupsAfterV[i].Count; j++)//Формування ребер { for (int t = 0; t < calc.mas[calc.groupsAfterV[i].ElementAt(j)].Count - 1; t++) { var dataVertex1 = new DataVertex(calc.mas[calc.groupsAfterV[i].ElementAt(j)].ElementAt(t)); var dataVertex2 = new DataVertex(calc.mas[calc.groupsAfterV[i].ElementAt(j)].ElementAt(t + 1)); var Edge = new DataEdge(vlist.Find(x => x.Text == dataVertex1.Text), vlist.Find(x => x.Text == dataVertex2.Text)) { Text = string.Format("{0} -> {1}", vlist.Find(x => x.Text == dataVertex1.Text), vlist.Find(x => x.Text == dataVertex2.Text)) }; //Перевіряю чи є вже таке ребро DataEdge temp = new DataEdge(); if (Graph.TryGetEdge(Edge.Source, Edge.Target, out temp) == false) Graph.AddEdge(Edge); } } graphs.Add(Graph); } totalGraph = new Graph();//Граф для відображення(об'єднує всі графи) for (int i = 0; i < graphs.Count; i++) { totalGraph.AddVertexRange(graphs.ElementAt(i).Vertices.ToList()); totalGraph.AddEdgeRange(graphs.ElementAt(i).Edges.ToList()); } return totalGraph; }
//Пошук в глибину(для 5 умови) private void DFScycleForFifth(int u, int endV, List<DataEdge> E, List<DataVertex> V, int[] color, int unavailableEdge, List<int> cycle, Graph graph) { //если u == endV, то эту вершину перекрашивать не нужно, иначе мы в нее не вернемся, а вернуться необходимо if (u != endV) color[u] = 2; else if (cycle.Count >= 2) { cycle.Reverse(); string s = cycle[0].ToString(); for (int i = 1; i < cycle.Count; i++) s += "-" + cycle[i].ToString(); /////////////////////// List<DataVertex> list = new List<DataVertex>();//Додаю вершину в цикл list.Add(V.ElementAt(cycle[0])); for (int i = 1; i < cycle.Count - 1; i++) list.Add(V.ElementAt(cycle[i])); /////////////////////// bool flag = false; //есть ли палиндром для этого цикла графа в List<string> catalogCycles? for (int i = 0; i < catalogCycles.Count; i++) if (catalogCycles[i].ToString() == s) { flag = true; break; } if (!flag) { cycle.Reverse(); list = new List<DataVertex>(); list.Add(V.ElementAt(cycle[0])); for (int i = 1; i < cycle.Count - 1; i++) list.Add(V.ElementAt(cycle[i])); catalogCycles.Add(list); } return; } for (int w = 0; w < E.Count; w++) { var q = graph.OutEdges(V[V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text)]); if (w == unavailableEdge || (graph.InEdges(V[V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text)]).Count() > 1 || graph.OutEdges(V[V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text)]).Count() > 1) && V.FindIndex(x => x.Text == E[w].Target.Text) != endV) continue; if (color[V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text)] == 1 && V.FindIndex(0, V.Count, x => x.Text == E[w].Source.Text) == u) { List<int> cycleNEW = new List<int>(cycle); cycleNEW.Add(V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text)); DFScycleForFifth(V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text), endV, E, V, color, w, cycleNEW, graph); color[V.FindIndex(0, V.Count, x => x.Text == E[w].Target.Text)] = 1; } } }
//Сортую групи і множини елементів за кількістю елементів(разом щоб співпадали) private void sortV(List<HashSet<int>> groupsAfterV, List<HashSet<string>> setElAfterV) { List<HashSet<int>> temp = new List<HashSet<int>>(); List<HashSet<string>> temp2 = new List<HashSet<string>>(); for (int i = 0; i < groupsAfterV.Count; i++) { for (int j = 0; j < groupsAfterV.Count - 1; j++) { if (setElAfterV.ElementAt(j).Count < setElAfterV.ElementAt(j + 1).Count) { temp.Add(groupsAfterV.ElementAt(j)); groupsAfterV.Insert(j, groupsAfterV.ElementAt(j + 1)); groupsAfterV.RemoveAt(j + 1); groupsAfterV.Insert(j + 1, temp.ElementAt(0)); groupsAfterV.RemoveAt(j + 2); temp.Clear(); temp2.Add(setElAfterV.ElementAt(j)); setElAfterV.Insert(j, setElAfterV.ElementAt(j + 1)); setElAfterV.RemoveAt(j + 1); setElAfterV.Insert(j + 1, temp2.ElementAt(0)); setElAfterV.RemoveAt(j + 2); temp2.Clear(); } } } }
//Групування з знаходженням підмножин public void groupsAfterVerification() { groupsAfterV = new List<HashSet<int>>(); setElAfterV= new List<HashSet<string>>(); groupsAfterV.AddRange(groups); setElAfterV.AddRange(createSet(groups)); sortV(groupsAfterV, setElAfterV);//Сортування груп за кількістю елементів sortWithEqualL(setElAfterV);//Сортування груп з однаковою кількістю елементів за перекриванням найбільшої кількості об'єктів for (int i = 0; i < setElAfterV.Count() - 1; i++)//Йду по найбільших групах { for (int k = i+1; k < groupsAfterV.Count(); k++)//Йду по підгрупах { for (int j = 0; j < groupsAfterV[k].Count; j++)//Йду по елементах в групі { if (setElAfterV[i].IsSupersetOf(mas[groupsAfterV[k].ElementAt(j)]))//Являється підмножиною? { groupsAfterV[i].Add(groupsAfterV[k].ElementAt(j));//Додаю елемент групи в групу надмножину groupsAfterV[k].Remove(groupsAfterV[k].ElementAt(j));//Видаляю елемент з підмножини j--; } } } for (int ind = 0; ind < groupsAfterV.Count; ind++)//Видалення пустих рядків { if (groupsAfterV.ElementAt(ind).Count == 0) groupsAfterV.RemoveAt(ind); } setElAfterV.Clear();//Видалив всі групи setElAfterV.AddRange(createSet(groupsAfterV));//Переукомплектовую групи після уточнення sortWithEqualL(setElAfterV);//Сортування груп з однаковою кількістю елементів за перекриванням найбільшої кількості об'єктів } }
//Розбиття на групи ////////////////До 2 лаби public void createGroups() { groups = new List<HashSet<int>>(); int currentGroup = 0; do//Виконуємо поки всі елементи не розподілили по групам { int[] maxElIndex = maxEl(resultMatrix.Count, resultMatrix); if (maxElIndex == null && containsAllIndex() == false)//Якщо не можемо знайти максимальний елемент, який не входить в групи, але ще залишилися елементи { createLastGroup();//Елементи, що залишилися об'єднуємо в одну групу return; } groups.Add(new HashSet<int>());//Створюю нову групу groups.ElementAt(currentGroup).Add(maxElIndex[0]);//Записую в групу індекси максимального елемента (i) groups.ElementAt(currentGroup).Add(maxElIndex[1]);//(j) createGroupsNext(currentGroup, maxElIndex[0], maxElIndex[1]); currentGroup++; } while (containsAllIndex() == false); }