public void DoAlgPrim() { StringBuilder message = new StringBuilder(); message.AppendFormat("[date: {0}]\n", DateTime.Now); message.AppendFormat("file: {0}\n", mainForm.ctlTabControl.SelectedTab.Text); message.AppendLine("--- Prim Algorithm ---"); Router root; if (SelectedElements.Count == 1 && (root = SelectedElements[0] as Router) != null) { if (Network.CheckNetwork() == 0) { message.AppendLine("checking: graph checking ... OK"); if (Network.Areas.Count > 1) { message.AppendLine("checking: network is segmented ... YES"); } else { message.AppendLine("checking: network is segmented ... NO"); } Network.ResetEquipment(); Stopwatch stopWatch = Stopwatch.StartNew(); AlgPrim algPrim = new AlgPrim(root, Network); stopWatch.Stop(); root.Mark = Marks.Prim; foreach (Channel channel in Network.Channels) if (channel.Tree == true) channel.Pen = new Pen(Color.Black, 4); message.AppendFormat("root: R{0}\n", root.Number); message.AppendFormat("area: {0}\n", root.Area.Number); message.AppendFormat("time: {0:00.000} ms\n", (stopWatch.ElapsedTicks * 1000.0) / Stopwatch.Frequency); message.AppendFormat("routers count: {0}\n", root.Area.Routers.Count); } else { message.Append("warning: gaph is not closed!\n" + "execution is stopped.\n"); } } else { message.Append("warning: please select one router!\n" + "execution is stopped.\n"); } UpdateField(); message.AppendLine("--- End ---"); message.AppendLine(); mainForm.ConsoleWrite(message.ToString()); }
private void DoAlg(Network net, Router root, Double q) { // 1 этап. Алгоритм Прима AlgPrim algPrim = new AlgPrim(root, net); // 2 этап. Получение первичных сегментов foreach (Router router in net.Routers) { Port port = Deg(router); if (port != null) { Area area = new Area(net.Areas.Count); area.AddRouter(port.Owner); if (port.Router.Area == net.MainArea) area.AddRouter(port.Router); else port.Router.Area.AddRouter(router); net.Areas.Add(area); } } // 3 этап. Получение вторичных сегментов List<Router> unallocatedRouters; while ((unallocatedRouters = GetUnallocatedRouters(net.Routers, net.MainArea)).Count > 0 ) { // список сегментов, к которым могут присоединиться нераспределенные вершины PA List<Area> potentialAreas = new List<Area>(); // список весов ребер, связывающих вершины с их потенциальными сегментами PW List<Int32> potentialWeights = new List<Int32>(); foreach (Router router in unallocatedRouters) { // количество сегментов с одинаковой величиной связей Int32 maxConnectValue = 0; // список сегментов с одинаковой величиной связей ECA List<Area> equalConnectAreas = new List<Area>(); // список весов ребер, соединяющий вершину с соответствующим сегментом List<Int32> channelWeights = new List<Int32>(); foreach (Port port in router.ConnectedPorts) { if (port.Channel.Tree == true && port.Router.Area != net.MainArea && port.Router.Area.Used == false) { Int32 connectCount = ConnectCount(router, port.Router.Area); if (connectCount == maxConnectValue) { // дополнение списка ECA port.Router.Area.Used = true; equalConnectAreas.Add(port.Router.Area); channelWeights.Add(port.Channel.Criterion); } else if (connectCount > maxConnectValue) { // обновление списка ECA foreach (Area area in equalConnectAreas) area.Used = false; port.Router.Area.Used = true; maxConnectValue = connectCount; equalConnectAreas = new List<Area>() { port.Router.Area }; channelWeights = new List<Int32>() { port.Channel.Criterion }; } } } /* выбор оптимального сегмента из соседей вершины */ Area connectedArea = null; // минимальный вес ребра между сегментом и вершиной Int32 minConn = Const.INF; if (equalConnectAreas.Count > 0) { for (Int32 i = 0; i < equalConnectAreas.Count; i++ ) { equalConnectAreas[i].Used = false; if (channelWeights[i] < minConn) { connectedArea = equalConnectAreas[i]; minConn = channelWeights[i]; } } } // добавление сегмента к списку PA potentialAreas.Add(connectedArea); // добавление веса ребра к списку PW potentialWeights.Add(minConn); /* * ЗАМЕЧАНИЕ 1: * индекс добавленного сегмента и веса ребра * совпадает с индексом текущей нераспределенной вершины * ЗАМЕЧАНИЕ 2: * элемент списка PA может быть null */ } /* определение оптимальной пары сегмент - вершина */ Area a = potentialAreas[0]; Router r = unallocatedRouters[0]; Int32 min = potentialWeights[0]; for (Int32 i = 1; i < potentialAreas.Count; i++) if (potentialWeights[i] < min) { min = potentialWeights[i]; a = potentialAreas[i]; r = unallocatedRouters[i]; } /* добавление вершины к сегменту */ a.AddRouter(r); } // 4 этап. Окончательное разбиение // список неоптимальных сегментов ( Q < optQ ) List<Area> suboptimalAreas; while ((suboptimalAreas = GetSuboptimalAreas(net.Areas, q)).Count > 0) { // список сегментов, которые могут быть объединены с неоптимальными сегментами PA List<Area> potentialAreas = new List<Area>(); // список весов ребер, связывающих сегменты PW List<Int32> potentialWeights = new List<Int32>(); foreach (Area area in suboptimalAreas) { // количество сегментов с одинаковой величиной связей Int32 maxConnectValue = 0; // список сегментов с одинаковой величиной связей ECA List<Area> equalConnectAreas = new List<Area>(); // список весов ребер, соединяющих сегменты List<Int32> channelWeights = new List<Int32>(); foreach (Port gateway in area.Gateways) { if (gateway.Channel.Tree == true && gateway.Router.Area.Used == false) { Int32 connectCount = ConnectCount(area, gateway.Router.Area); if (connectCount == maxConnectValue) { // дополнение списка ECA gateway.Router.Area.Used = true; equalConnectAreas.Add(gateway.Router.Area); channelWeights.Add(gateway.Channel.Criterion); } else if (connectCount > maxConnectValue) { // обновление списка ECA foreach (Area ar in equalConnectAreas) ar.Used = false; gateway.Router.Area.Used = true; maxConnectValue = connectCount; equalConnectAreas = new List<Area>() { gateway.Router.Area }; channelWeights = new List<Int32>() { gateway.Channel.Criterion }; } } } /* выбор оптимального сегмента из соседей текущего */ Area connectedArea = null; // минимальный вес ребра между сегментами Int32 minConn = Const.INF; if (equalConnectAreas.Count > 0) { for (Int32 i = 0; i < equalConnectAreas.Count; i++) { equalConnectAreas[i].Used = false; if (channelWeights[i] < minConn) { connectedArea = equalConnectAreas[i]; minConn = channelWeights[i]; } } } // добавление сегмента к списку PA potentialAreas.Add(connectedArea); // добавление веса ребра к списку PW potentialWeights.Add(minConn); /* * ЗАМЕЧАНИЕ 3: * индекс добавленного сегмента и веса ребра * совпадает с индексом текущего неоптимального сегмента * ЗАМЕЧАНИЕ 4: * элемент списка PA может быть null */ } /* определение оптимальной пары сегмент - сегмент */ Area a1 = potentialAreas[0]; Area a2 = suboptimalAreas[0]; Int32 min = potentialWeights[0]; for (Int32 i = 1; i < potentialAreas.Count; i++) if (potentialWeights[i] < min) { min = potentialWeights[i]; a1 = potentialAreas[i]; a2 = suboptimalAreas[i]; } /* объединение сегментов */ a1.Merge(a2); } }