private Int32 ConnectCount(Area area1, Area area2) { Int32 connectCount = 0; foreach (Port gateway in area1.Gateways) if (gateway.Router.Area == area2) connectCount++; return connectCount; }
public void DoAlg(int areasCount) { Area area = new Area(); area.Number = network.Areas.Count; foreach (Router router in network.Areas[0].Routers) { area.Routers.Add(router); router.Area = area; } network.Areas[0].Routers.Clear(); network.Areas.Add(area); DoBisection(network.Routers, areasCount); foreach (Channel channel in network.Channels) { if (channel.StartRouter.Area == channel.EndRouter.Area) { channel.Area = channel.StartRouter.Area; channel.Area.Channels.Add(channel); } else { channel.Area = null; } } }
private Int32 ConnectCount(Router router, Area area) { Int32 connectCount = 0; foreach (Port port in router.ConnectedPorts) if (port.Router.Area == area) connectCount++; return connectCount; }
/// <summary> /// Первоначальная инициализация /// </summary> /// <param name="area">Сетевой сегмент</param> public void DoAlg(Area area) { // Сортировка узлов по удалению от корня дерева кратчайших путей area.Routers = area.Routers.OrderBy(r => r.DistancePointer).ToList(); // установки для корня дерева оптимальных путей area.Routers[0].EnterPort = null; // Построение резервных маршрутов for (Int32 i = 1; i < area.Routers.Count; i++) { PaveReserveRouts(area.Routers[i]); } }
/// <summary> /// Динамический перерасчет дерева оптимальных маршрутов /// в сетевом сегменте /// </summary> /// <param name="area">Сетевой сегмент</param> /// <returns></returns> public Boolean Recalculate(Area area) { foreach (Router router in area.Routers) { foreach (Port port in router.ConnectedPorts) { if (port.Router.Area == area && port.Router.DistancePointer > 0) { if (port == router.EnterPort) { port.OppositePort.Distance = Const.INF; port.OppositePort.Route.Clear(); } else { port.OppositePort.Distance = router.DistancePointer + port.Channel.Criterion; port.OppositePort.Route.Clear(); port.OppositePort.Route.AddRange(router.MainRoute); port.OppositePort.Route.Add(port); if (port.OppositePort == port.Router.EnterPort) { Int32 dist = port.Router.ConnectedPorts[0].Distance; foreach (Port p in port.Router.ConnectedPorts) { if (p.Distance < dist) { dist = p.Distance; port.Router.EnterPort = p; } } } } if (port.OppositePort.Distance < port.Router.DistancePointer) { set.Add(new PairRoutes(port.Router.EnterPort.Route, port.OppositePort.Route)); //set.Add(CreateRoute(port.Router.EnterPort.Route)); //set.Add(CreateRoute(port.Route)); port.Router.EnterPort = port.OppositePort; port.Router.DistancePointer = port.Router.EnterPort.Distance; port.Router.MainRoute.Clear(); port.Router.MainRoute.AddRange(port.Router.EnterPort.Route); return false; } port.Router.DistancePointer = port.Router.EnterPort.Distance; port.Router.MainRoute.Clear(); port.Router.MainRoute.AddRange(port.Router.EnterPort.Route); } } } return true; }
// конструктор public Settings(Double q, List<Area> areas, Int32 changesCount, Int32 limit, Area areaPointer, Int32 segCount, Boolean auto, Boolean fullMesh, Boolean autoWeight, Boolean autoPortName) { InitializeComponent(); cbArea.DataSource = areas; txtValue.Text = q.ToString(); txtChangesCount.Text = changesCount.ToString(); txtLimit.Text = limit.ToString(); txtSegmentsCount.Text = segCount.ToString(); rbtnAuto.Checked = auto; ckAutoWeight.Checked = autoWeight; ckFullMesh.Checked = fullMesh; if (areas.Contains(areaPointer) == true) cbArea.SelectedItem = areaPointer; }
/// <summary> /// Динамический перерасчет дерева оптимальных маршрутов /// в сетевом сегменте /// </summary> /// <param name="area">Сетевой сегмент</param> /// <returns></returns> public Boolean Recalculate(Area area) { foreach (Router router in area.Routers) { foreach (Port port in router.ConnectedPorts) { if (port.Router.Area == area && port.Router.DistancePointer > 0) { if (port == router.EnterPort) { port.OppositePort.Distance = Const.INF; } else { port.OppositePort.Distance = router.DistancePointer + port.Channel.Criterion; if (port.OppositePort == port.Router.EnterPort) { Int32 dist = port.Router.EnterPort.Distance; foreach (Port p in port.Router.ConnectedPorts) { if (p.Distance < dist) { dist = p.Distance; port.Router.EnterPort = p; } } } } if (port.OppositePort.Distance < port.Router.DistancePointer) { set.Add(new ChannelsPair(port.Router.EnterPort.Channel, port.Channel)); port.Router.EnterPort = port.OppositePort; port.Router.DistancePointer = port.Router.EnterPort.Distance; return false; } port.Router.DistancePointer = port.Router.EnterPort.Distance; } } } return true; }
private void DoBisection(List<Router> routers, int areasCount) { int diameter = AlgDiameter.DoAlg(routers); Router tmpRouter = null; foreach (Router router in routers) { foreach (Router r in routers) { r.DistancePointer = Const.INF; r.Used = false; } router.DistancePointer = 0; tmpRouter = router; for (int i = 0; i < routers.Count; i++) { foreach (Port port in tmpRouter.ConnectedPorts) { if ((port.Router.DistancePointer > tmpRouter.DistancePointer + 1) && (port.Router.Used == false)) { port.Router.DistancePointer = tmpRouter.DistancePointer + 1; } } tmpRouter.Used = true; int min = Const.INF; foreach (Router r in routers) { if ((r.DistancePointer < min) && (r.Used == false)) { tmpRouter = r; min = r.DistancePointer; } } } if (tmpRouter.DistancePointer == diameter) { break; } } Area area = new Area(); area.Number = network.Areas.Count; network.Areas.Add(area); List<Router> newArea = new List<Router>(); foreach (Router router in routers) { if (router.DistancePointer < diameter / 2 + 1) { newArea.Add(router); } } foreach (Router router in newArea) { router.Area.Routers.Remove(router); network.Areas[network.Areas.Count - 1].Routers.Add(router); router.Area = network.Areas[network.Areas.Count - 1]; } if ((areasCount / 2 > 1) && (network.Areas[network.Areas.Count - 1].Routers.Count > 2) && (network.Areas[network.Areas.Count - 2].Routers.Count > 2)) { DoBisection(network.Areas[network.Areas.Count - 1].Routers, areasCount / 2); DoBisection(network.Areas[network.Areas.Count - 3].Routers, areasCount / 2); } }
// событие: пункт Величиа Связности выбран private void menuOptionsSettings_Click(object sender, EventArgs e) { Settings settings = new Settings(Q, this.CurrentField.Network.Areas, changeCount, limit, areaPointer, SegmentsCount, autoRecalculate, FullMesh, AutoWeight, AutoPortName); if (settings.ShowDialog(this) == DialogResult.OK) { Q = settings.Q; areaPointer = settings.AreaPointer; changeCount = settings.ChangeCount; limit = settings.Limit; SegmentsCount = settings.SegmentsCount; autoRecalculate = settings.Auto; FullMesh = settings.FullMesh; AutoWeight = settings.AutoWeight; AutoPortName = settings.AutoPortName; lblQ.Text = String.Format(" Q: {0:0.##}", Q); } }
public void UpdateGraphics(Area area) { Pen grayPen = new Pen(Color.Gray, 1); Pen areaPen = new Pen(area.SpecChannelColor, 4); foreach (Channel channel in area.Channels) channel.Pen = grayPen; foreach (Router router in area.Routers) { foreach (Port port in router.ConnectedPorts) if (router.DistancePointer - port.Channel.Criterion == port.Router.DistancePointer && port.Router.Area == area) { port.Channel.Pen = areaPen; break; } if (router.DistancePointer == 0) router.Mark = Marks.Dejkstra; } }
public void ResetReserve(Area resetedArea) { foreach (Router router in resetedArea.Routers) { router.Grade = Const.INF; router.Open = true; } }
public void ResetEquipment(Area resetedArea) { // исходные установки узлов связи foreach (Router router in resetedArea.Routers) { router.DistancePointer = Const.INF; router.Mark = Marks.None; router.Used = false; foreach (Port port in router.ConnectedPorts) { port.Distance = Const.INF; port.Route.Clear(); } } // исходные установки каналов связи Pen pen = new Pen(Color.Gray, 1); foreach (Channel channel in resetedArea.Channels) { channel.Pen = pen; channel.Tree = false; } }
public List<Int32> MultiRePairSwitch(Area area, Int32 changesCount, Int32 limit) { List<int> changesSet = new List<int>(); AlgPairSwitch algPairSwitch = new AlgPairSwitch(); StringBuilder message = new StringBuilder(); message.AppendFormat("[date: {0}]\n", DateTime.Now); message.AppendFormat("file: {0}\n", mainForm.ctlTabControl.SelectedTab.Text); message.AppendLine("--- Pair Shifts Algorithm: Recalculate ---"); Stopwatch stopWatch = Stopwatch.StartNew(); Random rnd = new Random(); for (int i = 0; i < changesCount; i++) { area.Channels[rnd.Next(area.Channels.Count - 2)].Criterion = 1 + rnd.Next(limit); while (algPairSwitch.Recalculate(area) == false) { } changesSet.Add(algPairSwitch.Set.Count); algPairSwitch.Set.Clear(); } stopWatch.Stop(); foreach (Channel channel in area.Channels) { channel.ChangeCriterion(mainForm.Criterion); } mainForm.AddPairOperationResult(changesSet, mainForm.ctlTabControl.SelectedTab.Text, area.Number, "Pair Switch", area.Routers.Count); message.AppendFormat("time: {0:00.000} ms\n", (stopWatch.ElapsedTicks * 1000.0) / Stopwatch.Frequency); UpdateField(); message.AppendLine("--- End ---"); message.AppendLine(); mainForm.ConsoleWrite(message.ToString()); return changesSet; }
public void Merge(Area area) { while (area.Routers.Count > 0) AddRouter(area.Routers[0]); }
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); } }
private List<Router> GetUnallocatedRouters(List<Router> routers, Area mainArea) { List<Router> unallocatedRouters = new List<Router>(); foreach (Router router in routers) if (router.Area == mainArea) unallocatedRouters.Add(router); return unallocatedRouters; }
public void ResetChannels(Area resetedArea) { // исходные установки каналов связи Pen pen = new Pen(Color.Gray, 1); foreach (Channel channel in Channels) { channel.Pen = pen; channel.Tree = false; } }
// получение списка вершин, составляющих путь между двумя исходными вершинами private void PaveRoute(Area startArea, Area endArea, int position) { /* Поиск маршрута по алгоритму Дейкстры */ startArea.DistancePointer = 0; Area tmpArea = startArea; while (tmpArea != endArea) { foreach (Port port in tmpArea.Gateways) { if ((port.Router.Area.DistancePointer > (tmpArea.DistancePointer + port.Channel.Criterion)) && (port.Router.Area.Used == false)) { port.Router.Area.DistancePointer = tmpArea.DistancePointer + port.Channel.Criterion; } } tmpArea.Used = true; int min = Const.INF; foreach (Area area in network.Areas) { lab += 1; if ((area.DistancePointer < min) && (area.Used == false)) { min = area.DistancePointer; tmpArea = area; } } } /* Построение найденного маршрута */ tmpArea = endArea; while (tmpArea != startArea) { foreach (Port port in tmpArea.Gateways) { if (port.Router.Area.DistancePointer == tmpArea.DistancePointer - port.Channel.Criterion) { if (port.Router == port.Channel.StartRouter) { routeRouters.Insert(position, port.Channel.EndRouter); routeRouters.Insert(position, port.Channel.StartRouter); } else { routeRouters.Insert(position, port.Channel.StartRouter); routeRouters.Insert(position, port.Channel.EndRouter); } tmpArea = port.Router.Area; routeChannels.Add(port.Channel); break; } } } }