## 3 VirtFogSim: A View of the Simulated Formal Models
### Dynamic Performance Tracking Function  
The numerical outputs of the _FogTracker_ function are three matrices that store the time behaviors of: (i) the consumed total energy \(\mathcal{E}_{TOT}\) (Joule); (ii) the corresponding consumed network energy \(\mathcal{E}_{NET}\) (Joule); and (iii) the _lambda_ multiplier (Joule), for values of the iteration index going from one to the given _iteration_number_. The goal of _FogTracker_ is to test the convergence rate to the steady-state and the steady-state stability of the primal-dual iterations performed by the \(RAP\_p\) function when abrupt changes of the maximum allowed WiFi and Cellular up/down bandwidths and task allocation vectors simultaneously happen. For this purpose, at the time indexes:  
1. \(\text{round}\left((1/5)\times iteration\_number\right)+1\);
2. \(\text{round}\left((2/5)\times iteration\_number\right)+1\);
3. \(\text{round}\left((3/5)\times iteration\_number\right)+1\);
4. \(\text{round}\left((4/5)\times iteration\_number\right)+1\),  
the initial values of the global variables: \(R_{U}^{MAX}\), \(R_{D}^{MAX}\), \(B_{U}^{MAX}\), \(B_{D}^{MAX}\) undergo abrupt changes. These changes are obtained by multiplying them by the (non-negative) input factors: \(jump_{WiFi}^{1}\), \(jump_{CELL}^{1}\), \(jump_{WiFi}^{2}\) and \(jump_{CELL}^{2}\). These jump coefficients are declared as global variables and set by the user. At the same time, the task allocation vector passes from \(\vec{x}_{1}\) to \(\vec{x}_{2}\) and, then, from \(\vec{x}_{2}\) to \(\vec{x}_{3}\). Finally, it comes back to \(\vec{x}_{1}\). The resulting time behaviors of the total energies, network energies, and lambda multiplier values over the time window: \([1,\,iteration\_number]\) are plotted under the three user-specified values of \(a_{MAX}\), which are stored by the \((1\times 3)\) global input vector \(\vec{a}_{MAX-FT}\). In so doing, the FogTracker function tests the convergence rate of the \(RAP\_p\) function when the task allocation vector undergoes abrupt changes. The actual feasibility of the task allocation vectors: \(\vec{x}_{1}\), \(\vec{x}_{2}\), and \(\vec{x}_{3}\) is explicitly checked in the body of the _FogTracker_ function. If at least one of these feasibility checks fails, the _FogTracker_ function generates a suitable error message and, then, halts. In detail, the _FogTracker_ function performs the following nine steps:  
1. it begins to run the \(RAP\_p\) function over the time interval: \([1,\text{round}\left((1/5)\times iteration\_number\right)]\), under the original settings of: \(R_{U}^{MAX}\), \(R_{D}^{MAX}\), \(B_{U}^{MAX}\), \(B_{D}^{MAX}\) dictated by the main program _VirtFogSim_ and the first input task allocation vector \(\vec{x}_{1}\);
2. at the end of the iteration number: \(\text{round}\left((1/5)\times iteration\_number\right)\), the WiFi maximum bandwidths: \(R_{U}^{MAX}\) and \(R_{D}^{MAX}\) are multiplied by the (non-negative) scaling factor: \(jump_{WiFi}^{1}\), while the maximum cellular bandwidths: \(B_{U}^{MAX}\) and \(B_{D}^{MAX}\) are multiplied by the corresponding (possibly, coincident) scaling factor: \(jump_{CELL}^{1}\). Furthermore, the task allocation vector is changed into \(\vec{x}_{2}\). In so doing, both the maximum available bandwidths and the task allocation vector undergo abrupt (typically, user mobility induced) variations;
3. the \(RAP\_p\) function runs over the time-interval: \([\text{round}\left(\,(1/5)\times iteration\_number\right)+1,\text{round}\left( \,(2/5)\times iteration\_number\right)]\) under the setting of Step 2. Its initial vector is the last returned vector of the \(RAP\_p\) at the previous iteration: \(\text{round}\left((1/5)\times iteration\_number\right)\);
4. at the end of iteration number: \(\text{round}\left((2/5)\times iteration\_number\right)\), all four maximum bandwidths: \(R_{U}^{MAX}\), \(R_{D}^{MAX}\), \(B_{U}^{MAX}\), and \(B_{D}^{MAX}\) are restored to their original values.