private void StartNewSessionAndAdmitCall(CallStartedEvent evt, IMobileTerminal mobileTerminal, IRat rat) { var session = new Session(rat.RatId, evt.Time); mobileTerminal.SetSessionId(session.SessionId); rat.TakeNetworkResources(evt.Call.Service.ComputeRequiredNetworkResources()); session.AddToActiveCalls(evt.Call); var state = mobileTerminal.UpdateMobileTerminalState(session); session.AddToSessionSequence(state); rat.AddSession(session); }
private void RunNonPredictiveAlgorithm(CallStartedEvent evt, IMobileTerminal mobileTerminal) { var rats = HetNet.Instance.Rats .Where(x => x.Services.Contains(evt.Call.Service)) .OrderBy(x => x.Services.Count) .ToList(); foreach (var rat in rats) { if (evt.Call.Service.ComputeRequiredNetworkResources() <= rat.AvailableNetworkResources()) { StartNewSessionAndAdmitCall(evt, mobileTerminal, rat); return; } } HetNet.Instance.BlockedCalls++; }
//First time you run this generate call history public void GenerateCalls(int numberOfCalls) { for (int i = 0; i < numberOfCalls; i++) { var service = Services.PickRandom(); var mobileTerminal = HetNet.Instance.MobileTerminals.PickRandom(); var call = new Call(mobileTerminal.MobileTerminalId, service); var callStartedEvent = new CallStartedEvent( DateTime.Now.AddMinutes(1 + (60 - 1) * random.NextDouble()), call); var callEndedEvent = new CallEndedEvent( call.CallId, call.MobileTerminalId, callStartedEvent.Time.AddMinutes(GenerateCallLifetime(service))); EventQueue.Enqueue(callStartedEvent); EventQueue.Enqueue(callEndedEvent); } ServeEventQueue(false); }
public void AdmitCall(CallStartedEvent evt) { if (evt is null) { throw new VerticalHandoverPredictionException($"{nameof(evt)} is null"); } var mobileTerminal = HetNet.Instance.MobileTerminals .FirstOrDefault(x => x.MobileTerminalId == evt.Call.MobileTerminalId); if (mobileTerminal.State != MobileTerminalState.Idle) { var session = HetNet.Instance.Rats .SelectMany(x => x.OngoingSessions) .FirstOrDefault(x => x.SessionId == mobileTerminal.SessionId); //Check if there is a same class of call active in session var services = session.ActiveCalls.Select(x => x.Service); if (services.Contains(evt.Call.Service)) { //Call already exists in the list of active calls so block event return; } Simulator.NetworkSimulator.Instance.Events.Add(evt); //At this point we can establish that call is generated HetNet.Instance.UpdateGeneratedCalls(evt.Call.Service); var rat = HetNet.Instance.Rats .FirstOrDefault(x => x.RatId == session.RatId); if (rat.CanAdmitNewCallToOngoingSession(session, evt.Call, mobileTerminal)) { rat.CanAdmitNewCallToOngoingSession(session, evt.Call, mobileTerminal); rat.AdmitNewCallToOngoingSession(session, evt.Call, mobileTerminal); return; } //NB if video call cannot be admitted block call immediately cannot be handed over elsewhere if (evt.Call.Service == Service.Video) { HetNet.Instance.BlockedCalls++; return; } HetNet.Instance.Handover(evt.Call, session, mobileTerminal, rat); return; } //If Mobile terminal was idle, do the initial RAT Selection else { //Session already terminated so reject all incoming initial calls if (mobileTerminal.IsActive) { return; } //Mobile Terminal is now active mobileTerminal.SetActive(true); Simulator.NetworkSimulator.Instance.Events.Add(evt); //At this point we can establish that the call is generated HetNet.Instance.UpdateGeneratedCalls(evt.Call.Service); if (Predictive) { //Number of calls to be used for prediction -- use this to compute success rate -- HetNet.Instance.CallsToBePredictedInitialRatSelection++; RunPredictiveAlgorithm(evt, mobileTerminal); } else { RunNonPredictiveAlgorithm(evt, mobileTerminal); } } }
private void RunPredictiveAlgorithm(CallStartedEvent evt, IMobileTerminal mobileTerminal) { //var history = CsvUtils._Instance.Read<CallLogMap,CallLog>($"{Environment.CurrentDirectory}/calllogs.csv").ToList(); var nextState = evt.Call.Service.GetState(); if (HetNet.Instance.CallerHistory.Any()) { var group = HetNet.Instance.CallerHistory .Where(x => x.UserId == mobileTerminal.MobileTerminalId) .Select(x => x.SessionSequence) .Select(x => x.ToList().Select(x => (MobileTerminalState)(int.Parse(x.ToString())))) .Select(x => x.Skip(1).Take(2)) .Where(x => x.StartsWith(new List <MobileTerminalState> { evt.Call.Service.GetState() })) .SelectMany(x => x.Skip(1)) .Where(x => x != MobileTerminalState.Idle) .GroupBy(x => x); //If group is empty it means prediction has failed if (!group.Any()) { HetNet.Instance.FailedPredictions++; } else { //continue to compute frequency table var prediction = default(IGrouping <MobileTerminalState, MobileTerminalState>); var max = 0; //If There are ties it takes the last item in the history : Fix this, what decision is made in that case //group.Dump(); foreach (var grp in group) { if (grp.Count() > max) { prediction = grp; max = prediction.Count(); } //Console.WriteLine( $"next state is {grp.Key}, Frequency: {grp.Count()}"); } nextState = prediction.Key; } } var services = new List <Service> { evt.Call.Service }; foreach (var service in nextState.SupportedServices()) { if (!services.Contains(service)) { services.Add(service); } } var rats = HetNet.Instance.Rats .Where(x => x.Services.ToHashSet().IsSupersetOf(services)) .OrderBy(x => x.Services.Count) .ToList(); //This scheme reserves bandwidth in advance, I considered all the services var requiredNetworkResources = 0; foreach (var service in services) { requiredNetworkResources += service.ComputeRequiredNetworkResources(); } foreach (var rat in rats) { if (requiredNetworkResources <= rat.AvailableNetworkResources()) { StartNewSessionAndAdmitCall(evt, mobileTerminal, rat); if (evt.Call.Service.GetState() != nextState) { //Successful Prediction means 1. predicted state was not idle 2. call ends up being admited as predicted HetNet.Instance.SuccessfulPredictions++; //Log.Information("----- Successful prediction"); } return; } } //All Possible Rats Cannot Admit Call i.e [call in its predicted state] HetNet.Instance.BlockedUsingPredictiveScheme++; //Try just accommodating the incoming call without predicting before blocking it RunNonPredictiveAlgorithm(evt, mobileTerminal); }