├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── .idea ├── .gitignore ├── NFVdeep.iml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── modules.xml └── vcs.xml ├── LICENSE ├── README.md ├── data ├── Cogentco.graphml ├── abilene--D-B-M-N-C-A-N-N.gml ├── abilene.gpickle ├── cogentco.gpickle ├── debug_overlay.gpickle ├── debug_requests_1.json ├── debug_requests_2.json ├── graphtest.gpickle ├── reward_test_overlay.gpickle ├── simple_graph.gpickle └── test.gpickle ├── environment.yml ├── evaluation.py ├── figures ├── dynamic.svg ├── dynamic_static.svg └── latency.svg ├── graph_generator.py ├── nfvdeep ├── agent │ ├── baselines.py │ └── logging.py ├── environment │ ├── arrival.py │ ├── env.py │ ├── network.py │ └── sfv.py ├── spaces │ ├── A2C_space.json │ └── PPO_space.json └── tuning.py ├── requirements.txt ├── results ├── abilene │ ├── dynamic │ │ └── default │ │ │ ├── default_ppo.csv │ │ │ ├── firstfit.csv │ │ │ ├── monitor.csv │ │ │ ├── requests.json │ │ │ └── tune.csv │ └── static │ │ ├── default │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── requests.json │ │ └── tune.csv │ │ ├── latency_experiments │ │ ├── medium │ │ │ ├── default_ppo.csv │ │ │ ├── firstfit.csv │ │ │ ├── requests.json │ │ │ └── tune.csv │ │ ├── relaxed │ │ │ ├── default_ppo.csv │ │ │ ├── firstfit.csv │ │ │ ├── requests.json │ │ │ └── tune.csv │ │ └── tight │ │ │ ├── default_ppo.csv │ │ │ ├── firstfit.csv │ │ │ ├── requests.json │ │ │ └── tune.csv │ │ └── load_experiments │ │ ├── high_load │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── requests.json │ │ └── tune.csv │ │ ├── low_load │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── requests.json │ │ └── tune.csv │ │ └── medium_load │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── requests.json │ │ └── tune.csv └── abilene_v2 │ ├── dynamic │ └── default │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── random.csv │ │ ├── requests.json │ │ └── tune.csv │ └── static │ ├── default │ ├── default_ppo.csv │ ├── firstfit.csv │ ├── random.csv │ ├── requests.json │ └── tune.csv │ ├── latency_experiments │ ├── medium │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── random.csv │ │ ├── requests.json │ │ └── tune.csv │ ├── relaxed │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── random.csv │ │ ├── requests.json │ │ └── tune.csv │ └── tight │ │ ├── default_ppo.csv │ │ ├── firstfit.csv │ │ ├── random.csv │ │ ├── requests.json │ │ └── tune.csv │ └── load_experiments │ ├── high_load │ ├── default_ppo.csv │ ├── firstfit.csv │ ├── random.csv │ ├── requests.json │ └── tune.csv │ ├── low_load │ ├── default_ppo.csv │ ├── firstfit.csv │ ├── random.csv │ ├── requests.json │ └── tune.csv │ └── medium_load │ ├── default_ppo.csv │ ├── firstfit.csv │ ├── random.csv │ ├── requests.json │ └── tune.csv ├── script.py ├── tests ├── network_requirements.txt └── test_env.py └── tune.py /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python application 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | container: 17 | image: continuumio/miniconda3:latest 18 | 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Set up Python 3.8 23 | uses: actions/setup-python@v2 24 | with: 25 | python-version: 3.8 26 | - name: Install dependencies 27 | run: | 28 | conda update --all 29 | conda install -c conda-forge --file tests/network_requirements.txt 30 | conda install flake8 pytest 31 | - name: Lint with flake 32 | run: | 33 | # stop the build if there are Python syntax errors or undefined names 34 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 35 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 36 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 37 | - name: Test with pytest 38 | run: | 39 | export PYTHONPATH=nfvdeep 40 | pytest 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.vscode 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | pip-wheel-metadata/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # pipenv 89 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 92 | # install all needed dependencies. 93 | #Pipfile.lock 94 | 95 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 96 | __pypackages__/ 97 | 98 | # Celery stuff 99 | celerybeat-schedule 100 | celerybeat.pid 101 | 102 | # SageMath parsed files 103 | *.sage.py 104 | 105 | # Environments 106 | .env 107 | .venv 108 | env/ 109 | venv/ 110 | ENV/ 111 | env.bak/ 112 | venv.bak/ 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | /site 123 | 124 | # mypy 125 | .mypy_cache/ 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre/ 131 | 132 | # ignore agent logs of Tensorboard 133 | .logs/ 134 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/NFVdeep.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 CN-UPB 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![GitHub CI](https://github.com/CN-UPB/NFVdeep/workflows/Python%20application/badge.svg) 2 | 3 | # NFVdeep 4 | Deep Reinforcement Learning for Online Orchestration of Service Function Chains 5 | 6 | *Disclaimer:* This is an unofficial implementation, trying to reproduce the deep reinforcement learning approach described in the [NFVdeep paper by Xiao et al.](https://dl.acm.org/doi/abs/10.1145/3326285.3329056) as part of a graduate student project. 7 | While the implemented agent did learn over time, we were not able to reproduce the same results stated in the paper. 8 | 9 | **Advisor**: [Stefan Schneider](https://github.com/stefanbschneider) 10 | 11 | **Developers**: [Nils Rudminat](https://github.com/NilsLuca), [Stefan Werner](https://github.com/stwerner97) 12 | 13 | ## Setup 14 | Assuming an Anaconda (version 4.8.4) distribution has already been installed on an Ubuntu 18.04 machine, the environment can simply be cloned via `conda env create -f environment.yml`. Depending on your system's setup, the installation of additional packages for ``RayTune`` and the applied `Tensorflow` version might be necessary. 15 | 16 | ## Experiments 17 | The `script.py` file serves as an interface to running either baseline or DRL agents on the NFVdeep environment with their default parameterization, i.e. whithout employing hyperparamter optimization. Here, you can specify the overlay topology and the network's resources, as well as properties of the arrival process. For instance, we may train an stable-baseline's `PPO` DRL agent on the `abilene` network with incoming requests arising from a Poisson process by executing: 18 | ```console 19 | python script.py 20 | --agent PPO 21 | --overlay /abilene.gpickle 22 | --requests /requests.json 23 | --output 24 | --logs 25 | ``` 26 | 27 | ## Hyperparameter Optimization 28 | We employ distributed (single node) Bayesian Optimization with ``BoTorch`` and ``RayTune`` in order to faciliate scalable hyperparameter optimization for our Reinforcement Learning agent. Specifically, we first specify a parameter search space from whom agent configurations are first sampled and subsequently evaluated. Here, ``tune.py `` provides an interface to access our implementation's tuned DRL agents. Note, however, that absolute paths must be used, for instance by executing: 29 | ```console 30 | python tune.py 31 | --agent PPO 32 | --overlay /abilene.gpickle 33 | --requests /requests.json 34 | --output 35 | --logs 36 | ``` 37 | 38 | # Results 39 | Our evaluation is primarily based on generating arrival times with respect to a Poisson process (exponential arrival and service times) and is only loosely based on the evaluation proposed in the original NFVdeep paper. The load of individual SFCs and VNFs is uniformly sampled within their bounds specified in the respective `requests.json` files. All results simulate the SFC embedding problem on the real-world Abline network topology. 40 | ## Sampled Input Traffic 41 | First, we train and evaluate under randomly sampled input traffic traces and compare among PPO also its tuned variant against two heuristic baselines, i.e. against the random placement policy and a greedy first fit ('FirstFit') heuristic. 42 |

43 | drawing 44 |

45 | 46 | Evidently, neither DRL agent matches the greedy baseline's performance in terms of the cumulated episode reward. However, both DRL agents improve upon random placement decisions and in few cases also accomplish competitive results. 47 | 48 | ## Static Input Traffic 49 | The exogenous input process has a significant influence on an episode's trajectory independent from the respective agent's placement decisions. Therefore, training with episodes subject to randomly generated input traffic might cause high variance in the reward signal and ultimately prohibit effective policy improvement. Therefore, we replay input traffic in our experiments with 'static' input. 50 |

51 | drawing 52 |

53 | 54 | In comparison to the previous evaluation setup, the ``(tuned) PPO`` policy manages to close the reward gap to the ``FirstFit`` baseline significantly even though the greedy heuristic ultimately remains superior. 55 | 56 | 57 | ## Latency Constraints 58 | Lastly, we demonstrate that NFVdeep is not provided with effective means to learn concepts related to latency. Specifically, the agent is not provided with information that specifies its last placement decision and cannot determine an informed decision that minimizes latency. Hence, we compare the performance in two related scenarios where only the maximum latency constraints for SFCs vary. 59 |

60 | drawing 61 |

62 | While the ``FirstFit`` baseline accomplishes similar performance in both scenarios (the imposed maximum latency does not pose significant constraints on the placements), we find that the DRL agent's performance deteriorates which is consistent with the prior hypothesis. 63 | -------------------------------------------------------------------------------- /data/abilene--D-B-M-N-C-A-N-N.gml: -------------------------------------------------------------------------------- 1 | Creator "sndlib.ext.generators.gml.ProblemGmlGenerator" 2 | Version "1.0" 3 | 4 | graph [ 5 | label "abilene--D-B-M-N-C-A-N-N" 6 | name "abilene--D-B-M-N-C-A-N-N" 7 | directed 1 8 | 9 | node [ 10 | id 0 11 | label "ATLAM5" 12 | 13 | LabelGraphics [ 14 | fontSize 13 15 | ] 16 | 17 | graphics [ 18 | x 1845.72 19 | y 894.37 20 | h 20 21 | w 60 22 | fill "#cccccc" 23 | outline "#000000" 24 | type "ellipse" 25 | ] 26 | ] 27 | 28 | node [ 29 | id 1 30 | label "ATLAng" 31 | 32 | LabelGraphics [ 33 | fontSize 13 34 | ] 35 | 36 | graphics [ 37 | x 1791.36 38 | y 850.27 39 | h 20 40 | w 60 41 | fill "#cccccc" 42 | outline "#000000" 43 | type "ellipse" 44 | ] 45 | ] 46 | 47 | node [ 48 | id 2 49 | label "CHINng" 50 | 51 | LabelGraphics [ 52 | fontSize 13 53 | ] 54 | 55 | graphics [ 56 | x 1688.33 57 | y 395.53 58 | h 20 59 | w 60 60 | fill "#cccccc" 61 | outline "#000000" 62 | type "ellipse" 63 | ] 64 | ] 65 | 66 | node [ 67 | id 3 68 | label "DNVRng" 69 | 70 | LabelGraphics [ 71 | fontSize 13 72 | ] 73 | 74 | graphics [ 75 | x 842.14 76 | y 465.72 77 | h 20 78 | w 60 79 | fill "#cccccc" 80 | outline "#000000" 81 | type "ellipse" 82 | ] 83 | ] 84 | 85 | node [ 86 | id 4 87 | label "HSTNng" 88 | 89 | LabelGraphics [ 90 | fontSize 13 91 | ] 92 | 93 | graphics [ 94 | x 1303.73 95 | y 1122.31 96 | h 20 97 | w 60 98 | fill "#cccccc" 99 | outline "#000000" 100 | type "ellipse" 101 | ] 102 | ] 103 | 104 | node [ 105 | id 5 106 | label "IPLSng" 107 | 108 | LabelGraphics [ 109 | fontSize 13 110 | ] 111 | 112 | graphics [ 113 | x 1759.26 114 | y 527.56 115 | h 20 116 | w 60 117 | fill "#cccccc" 118 | outline "#000000" 119 | type "ellipse" 120 | ] 121 | ] 122 | 123 | node [ 124 | id 6 125 | label "KSCYng" 126 | 127 | LabelGraphics [ 128 | fontSize 13 129 | ] 130 | 131 | graphics [ 132 | x 1251.19 133 | y 579.13 134 | h 20 135 | w 60 136 | fill "#cccccc" 137 | outline "#000000" 138 | type "ellipse" 139 | ] 140 | ] 141 | 142 | node [ 143 | id 7 144 | label "LOSAng" 145 | 146 | LabelGraphics [ 147 | fontSize 13 148 | ] 149 | 150 | graphics [ 151 | x 197.15 152 | y 876.78 153 | h 20 154 | w 60 155 | fill "#cccccc" 156 | outline "#000000" 157 | type "ellipse" 158 | ] 159 | ] 160 | 161 | node [ 162 | id 8 163 | label "NYCMng" 164 | 165 | LabelGraphics [ 166 | fontSize 13 167 | ] 168 | 169 | graphics [ 170 | x 2352.79 171 | y 463.58 172 | h 20 173 | w 60 174 | fill "#cccccc" 175 | outline "#000000" 176 | type "ellipse" 177 | ] 178 | ] 179 | 180 | node [ 181 | id 9 182 | label "SNVAng" 183 | 184 | LabelGraphics [ 185 | fontSize 13 186 | ] 187 | 188 | graphics [ 189 | x 13.36 190 | y 676.72 191 | h 20 192 | w 60 193 | fill "#cccccc" 194 | outline "#000000" 195 | type "ellipse" 196 | ] 197 | ] 198 | 199 | node [ 200 | id 10 201 | label "STTLng" 202 | 203 | LabelGraphics [ 204 | fontSize 13 205 | ] 206 | 207 | graphics [ 208 | x 0.0 209 | y 0.0 210 | h 20 211 | w 60 212 | fill "#cccccc" 213 | outline "#000000" 214 | type "ellipse" 215 | ] 216 | ] 217 | 218 | node [ 219 | id 11 220 | label "WASHng" 221 | 222 | LabelGraphics [ 223 | fontSize 13 224 | ] 225 | 226 | graphics [ 227 | x 2203.82 228 | y 583.16 229 | h 20 230 | w 60 231 | fill "#cccccc" 232 | outline "#000000" 233 | type "ellipse" 234 | ] 235 | ] 236 | 237 | edge [ 238 | id 0 239 | source 1 240 | target 0 241 | 242 | graphics [ 243 | fill "#000000" 244 | width 1 245 | style "standard" 246 | sourceArrow "standard" 247 | targetArrow "standard" 248 | ] 249 | ] 250 | 251 | edge [ 252 | id 1 253 | source 4 254 | target 1 255 | 256 | graphics [ 257 | fill "#000000" 258 | width 1 259 | style "standard" 260 | sourceArrow "standard" 261 | targetArrow "standard" 262 | ] 263 | ] 264 | 265 | edge [ 266 | id 2 267 | source 5 268 | target 1 269 | 270 | graphics [ 271 | fill "#000000" 272 | width 1 273 | style "standard" 274 | sourceArrow "standard" 275 | targetArrow "standard" 276 | ] 277 | ] 278 | 279 | edge [ 280 | id 3 281 | source 11 282 | target 1 283 | 284 | graphics [ 285 | fill "#000000" 286 | width 1 287 | style "standard" 288 | sourceArrow "standard" 289 | targetArrow "standard" 290 | ] 291 | ] 292 | 293 | edge [ 294 | id 4 295 | source 5 296 | target 2 297 | 298 | graphics [ 299 | fill "#000000" 300 | width 1 301 | style "standard" 302 | sourceArrow "standard" 303 | targetArrow "standard" 304 | ] 305 | ] 306 | 307 | edge [ 308 | id 5 309 | source 8 310 | target 2 311 | 312 | graphics [ 313 | fill "#000000" 314 | width 1 315 | style "standard" 316 | sourceArrow "standard" 317 | targetArrow "standard" 318 | ] 319 | ] 320 | 321 | edge [ 322 | id 6 323 | source 6 324 | target 3 325 | 326 | graphics [ 327 | fill "#000000" 328 | width 1 329 | style "standard" 330 | sourceArrow "standard" 331 | targetArrow "standard" 332 | ] 333 | ] 334 | 335 | edge [ 336 | id 7 337 | source 9 338 | target 3 339 | 340 | graphics [ 341 | fill "#000000" 342 | width 1 343 | style "standard" 344 | sourceArrow "standard" 345 | targetArrow "standard" 346 | ] 347 | ] 348 | 349 | edge [ 350 | id 8 351 | source 10 352 | target 3 353 | 354 | graphics [ 355 | fill "#000000" 356 | width 1 357 | style "standard" 358 | sourceArrow "standard" 359 | targetArrow "standard" 360 | ] 361 | ] 362 | 363 | edge [ 364 | id 9 365 | source 6 366 | target 4 367 | 368 | graphics [ 369 | fill "#000000" 370 | width 1 371 | style "standard" 372 | sourceArrow "standard" 373 | targetArrow "standard" 374 | ] 375 | ] 376 | 377 | edge [ 378 | id 10 379 | source 7 380 | target 4 381 | 382 | graphics [ 383 | fill "#000000" 384 | width 1 385 | style "standard" 386 | sourceArrow "standard" 387 | targetArrow "standard" 388 | ] 389 | ] 390 | 391 | edge [ 392 | id 11 393 | source 6 394 | target 5 395 | 396 | graphics [ 397 | fill "#000000" 398 | width 1 399 | style "standard" 400 | sourceArrow "standard" 401 | targetArrow "standard" 402 | ] 403 | ] 404 | 405 | edge [ 406 | id 12 407 | source 9 408 | target 7 409 | 410 | graphics [ 411 | fill "#000000" 412 | width 1 413 | style "standard" 414 | sourceArrow "standard" 415 | targetArrow "standard" 416 | ] 417 | ] 418 | 419 | edge [ 420 | id 13 421 | source 11 422 | target 8 423 | 424 | graphics [ 425 | fill "#000000" 426 | width 1 427 | style "standard" 428 | sourceArrow "standard" 429 | targetArrow "standard" 430 | ] 431 | ] 432 | 433 | edge [ 434 | id 14 435 | source 10 436 | target 9 437 | 438 | graphics [ 439 | fill "#000000" 440 | width 1 441 | style "standard" 442 | sourceArrow "standard" 443 | targetArrow "standard" 444 | ] 445 | ] 446 | ] 447 | -------------------------------------------------------------------------------- /data/abilene.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/abilene.gpickle -------------------------------------------------------------------------------- /data/cogentco.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/cogentco.gpickle -------------------------------------------------------------------------------- /data/debug_overlay.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/debug_overlay.gpickle -------------------------------------------------------------------------------- /data/debug_requests_1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "arrival_time": 1, 4 | "ttl": 10, 5 | "arrival_rate": 1, 6 | "bandwidth_demand": 1.0, 7 | "max_response_latency": 5.0, 8 | "vnfs": [ 9 | { 10 | "cpu_demand": 5, 11 | "memory_demand": 20.0 12 | }, 13 | { 14 | "cpu_demand": 3, 15 | "memory_demand": 10.0 16 | }, 17 | { 18 | "cpu_demand": 10, 19 | "memory_demand": 10.0 20 | } 21 | ], 22 | "processing_delays": [1,0,1] 23 | }, 24 | { 25 | "arrival_time": 3, 26 | "ttl": 5, 27 | "arrival_rate": 1, 28 | "bandwidth_demand": 1.0, 29 | "max_response_latency": 10.0, 30 | "vnfs": [ 31 | { 32 | "cpu_demand": 15, 33 | "memory_demand": 10.0 34 | } 35 | ] 36 | }, 37 | { 38 | "arrival_time": 3, 39 | "ttl": 5, 40 | "arrival_rate": 1, 41 | "bandwidth_demand": 1.0, 42 | "max_response_latency": 10.0, 43 | "vnfs": [ 44 | { 45 | "cpu_demand": 10, 46 | "memory_demand": 20.0 47 | }, 48 | { 49 | "cpu_demand": 15, 50 | "memory_demand": 10.0 51 | } 52 | ] 53 | } 54 | ] -------------------------------------------------------------------------------- /data/debug_requests_2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "arrival_time": 1, 4 | "ttl": 10, 5 | "arrival_rate": 1, 6 | "bandwidth_demand": 1.0, 7 | "max_response_latency": 5.0, 8 | "vnfs": [ 9 | { 10 | "cpu_demand": 5, 11 | "memory_demand": 20.0 12 | }, 13 | { 14 | "cpu_demand": 3, 15 | "memory_demand": 10.0 16 | }, 17 | { 18 | "cpu_demand": 15, 19 | "memory_demand": 10.0 20 | } 21 | ] 22 | }, 23 | { 24 | "arrival_time": 3, 25 | "ttl": 5, 26 | "arrival_rate": 1, 27 | "bandwidth_demand": 1.0, 28 | "max_response_latency": 10.0, 29 | "vnfs": [ 30 | { 31 | "cpu_demand": 15, 32 | "memory_demand": 10.0 33 | } 34 | ] 35 | }, 36 | { 37 | "arrival_time": 3, 38 | "ttl": 5, 39 | "arrival_rate": 1, 40 | "bandwidth_demand": 1.0, 41 | "max_response_latency": 10.0, 42 | "vnfs": [ 43 | { 44 | "cpu_demand": 10, 45 | "memory_demand": 20.0 46 | }, 47 | { 48 | "cpu_demand": 15, 49 | "memory_demand": 10.0 50 | } 51 | ] 52 | } 53 | ] -------------------------------------------------------------------------------- /data/graphtest.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/graphtest.gpickle -------------------------------------------------------------------------------- /data/reward_test_overlay.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/reward_test_overlay.gpickle -------------------------------------------------------------------------------- /data/simple_graph.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/simple_graph.gpickle -------------------------------------------------------------------------------- /data/test.gpickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phongvu0403/Edge_Cloud_Computing/e0585473cf83a7806475dd20d668b8c5fff28ba6/data/test.gpickle -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: ray 2 | channels: 3 | - defaults 4 | dependencies: 5 | - _libgcc_mutex=0.1=main 6 | - _tflow_select=2.3.0=mkl 7 | - astunparse=1.6.3=py_0 8 | - autopep8=1.5.4=py_0 9 | - blas=1.0=mkl 10 | - blinker=1.4=py38_0 11 | - brotlipy=0.7.0=py38h7b6447c_1000 12 | - c-ares=1.15.0=h7b6447c_1001 13 | - ca-certificates=2020.7.22=0 14 | - cachetools=4.1.1=py_0 15 | - certifi=2020.6.20=py38_0 16 | - cffi=1.14.2=py38he30daa8_0 17 | - chardet=3.0.4=py38_1003 18 | - click=7.1.2=py_0 19 | - cryptography=3.0=py38h1ba5d50_0 20 | - gast=0.3.3=py_0 21 | - google-auth=1.20.1=py_0 22 | - google-auth-oauthlib=0.4.1=py_2 23 | - google-pasta=0.2.0=py_0 24 | - grpcio=1.31.0=py38hf8bcb03_0 25 | - h5py=2.10.0=py38hd6299e0_1 26 | - hdf5=1.10.6=hb1b8bf9_0 27 | - idna=2.10=py_0 28 | - importlib-metadata=1.7.0=py38_0 29 | - intel-openmp=2020.2=254 30 | - keras-preprocessing=1.1.0=py_1 31 | - ld_impl_linux-64=2.33.1=h53a641e_7 32 | - libedit=3.1.20191231=h14c3975_1 33 | - libffi=3.3=he6710b0_2 34 | - libgcc-ng=9.1.0=hdf63c60_0 35 | - libgfortran-ng=7.3.0=hdf63c60_0 36 | - libprotobuf=3.12.4=hd408876_0 37 | - libstdcxx-ng=9.1.0=hdf63c60_0 38 | - markdown=3.2.2=py38_0 39 | - mkl=2020.2=256 40 | - mkl-service=2.3.0=py38he904b0f_0 41 | - mkl_fft=1.1.0=py38h23d657b_0 42 | - mkl_random=1.1.1=py38h0573a6f_0 43 | - ncurses=6.2=he6710b0_1 44 | - numpy=1.19.1=py38hbc911f0_0 45 | - numpy-base=1.19.1=py38hfa32c7d_0 46 | - oauthlib=3.1.0=py_0 47 | - openssl=1.1.1g=h7b6447c_0 48 | - opt_einsum=3.1.0=py_0 49 | - pip=20.2.2=py38_0 50 | - pyasn1=0.4.8=py_0 51 | - pycodestyle=2.6.0=py_0 52 | - pycparser=2.20=py_2 53 | - pyjwt=1.7.1=py38_0 54 | - pyopenssl=19.1.0=py_1 55 | - pysocks=1.7.1=py38_0 56 | - python=3.8.5=hcff3b4d_0 57 | - readline=8.0=h7b6447c_0 58 | - requests=2.24.0=py_0 59 | - requests-oauthlib=1.3.0=py_0 60 | - rsa=4.6=py_0 61 | - scipy=1.5.2=py38h0b6359f_0 62 | - setuptools=49.6.0=py38_0 63 | - six=1.15.0=py_0 64 | - sqlite=3.33.0=h62c20be_0 65 | - tensorflow=2.2.0=mkl_py38h6d3daf0_0 66 | - tensorflow-base=2.2.0=mkl_py38h5059a2d_0 67 | - tensorflow-estimator=2.2.0=pyh208ff02_0 68 | - termcolor=1.1.0=py38_1 69 | - tk=8.6.10=hbc83047_0 70 | - toml=0.10.1=py_0 71 | - urllib3=1.25.10=py_0 72 | - werkzeug=1.0.1=py_0 73 | - wheel=0.35.1=py_0 74 | - wrapt=1.12.1=py38h7b6447c_1 75 | - xz=5.2.5=h7b6447c_0 76 | - zipp=3.1.0=py_0 77 | - zlib=1.2.11=h7b6447c_3 78 | - pip: 79 | - absl-py==0.10.0 80 | - aiohttp==3.6.2 81 | - aioredis==1.3.1 82 | - async-timeout==3.0.1 83 | - attrs==20.1.0 84 | - ax-platform==0.1.14 85 | - beautifulsoup4==4.9.1 86 | - blessings==1.7 87 | - botorch==0.3.0 88 | - cloudpickle==1.6.0 89 | - colorama==0.4.3 90 | - colorful==0.5.4 91 | - cycler==0.10.0 92 | - decorator==4.4.2 93 | - dill==0.3.2 94 | - filelock==3.0.12 95 | - future==0.18.2 96 | - google==3.0.0 97 | - google-api-core==1.22.1 98 | - googleapis-common-protos==1.52.0 99 | - gpustat==0.6.0 100 | - gpytorch==1.1.1 101 | - gym==0.17.2 102 | - hiredis==1.1.0 103 | - jinja2==2.11.2 104 | - joblib==0.16.0 105 | - jsonschema==3.2.0 106 | - kiwisolver==1.2.0 107 | - markupsafe==1.1.1 108 | - matplotlib==3.3.1 109 | - mdutils==1.2.2 110 | - msgpack==1.0.0 111 | - multidict==4.7.6 112 | - networkx==2.5 113 | - nvidia-ml-py3==7.352.0 114 | - opencensus==0.7.10 115 | - opencensus-context==0.1.1 116 | - pandas==1.1.1 117 | - pillow==7.2.0 118 | - plotly==4.9.0 119 | - prometheus-client==0.8.0 120 | - protobuf==3.13.0 121 | - psutil==5.7.2 122 | - py-spy==0.3.3 123 | - pyasn1-modules==0.2.8 124 | - pyglet==1.5.0 125 | - pyparsing==2.4.7 126 | - pyrsistent==0.16.0 127 | - python-dateutil==2.8.1 128 | - pytz==2020.1 129 | - pyyaml==5.3.1 130 | - ray==0.8.7 131 | - redis==3.4.1 132 | - retrying==1.3.3 133 | - scikit-learn==0.23.2 134 | - seaborn==0.11.0 135 | - soupsieve==2.0.1 136 | - stable-baselines3==0.8.0 137 | - tabulate==0.8.7 138 | - tensorboard==2.3.0 139 | - tensorboard-plugin-wit==1.7.0 140 | - tensorboardx==2.1 141 | - threadpoolctl==2.1.0 142 | - torch==1.6.0 143 | - yarl==1.5.1 144 | prefix: /home/aicon/anaconda3/envs/ray 145 | -------------------------------------------------------------------------------- /evaluation.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import argparse 4 | import json 5 | import pandas as pd 6 | import seaborn as sns 7 | import matplotlib 8 | import matplotlib.pyplot as plt 9 | import matplotlib.gridspec as gridspec 10 | from pathlib import Path 11 | from stable_baselines3.common.evaluation import evaluate_policy 12 | 13 | 14 | def evaluate_final_policy(n_eval_episodes, agent, env): 15 | """ Evaluates the final policy of an agent for the specified experiment. 16 | Args: 17 | n_eval_episodes (int): number of evaluation episodes 18 | agent: The trained agent 19 | env: The environment the agent acts in 20 | """ 21 | 22 | episode_results = dict() 23 | for episode_num in range(n_eval_episodes): 24 | episode = dict() 25 | 26 | rew, _ = evaluate_policy( 27 | agent, env, n_eval_episodes=1, return_episode_rewards=True) 28 | 29 | episode['reward'] = rew[0] 30 | episode['acceptance_rate'] = env.num_accepted / \ 31 | (env.num_accepted + env.num_rejected) 32 | 33 | for key in env.resource_utilization: 34 | episode['mean_{}'.format(key)] = env.resource_utilization[key] 35 | 36 | episode['mean_operating_servers'] = env.operating_servers / \ 37 | env.episode_length 38 | 39 | episode_results[episode_num] = episode 40 | 41 | return episode_results 42 | 43 | 44 | def safe_experiment(results, args): 45 | """ Safes one experiment together with its metainformation into a csv file.""" 46 | 47 | if not os.path.exists(args['output']): 48 | os.makedirs(args['output']) 49 | 50 | # safe environemt & hyperparameters used to generate the results 51 | with open(Path(args['output']) / 'args.json', 'a') as file: 52 | file.write(json.dumps(args)) 53 | file.write("\n") 54 | 55 | # safe agent's performances in csv format 56 | data = {(args['agent'], i, j): results[i][j] for i in results.keys() 57 | for j in results[i].keys()} 58 | data = pd.DataFrame.from_dict(data, orient='index') 59 | data.index.names = ['agent', 'trial', 'episode'] 60 | 61 | results_path = Path(args['output']) / 'results.csv' 62 | 63 | if not os.path.exists(results_path): 64 | data.to_csv(results_path) 65 | 66 | else: 67 | data.to_csv(results_path, mode='a', header=False) 68 | 69 | 70 | if __name__ == '__main__': 71 | parser = argparse.ArgumentParser() 72 | 73 | parser.add_argument('--results', type=str) 74 | parser.add_argument('--output', type=str) 75 | 76 | args = parser.parse_args() 77 | 78 | index_mapping = {'agent': 'Agent', 'trial': 'Trial', 'episode': 'Episode'} 79 | 80 | measure_mapping = {'reward': 'Reward', 'acceptance_rate': 'Acceptance Rate', 81 | 'mean_cpu_utilization': 'CPU Utilization', 82 | 'mean_memory_utilization': 'Memory Utilization', 83 | 'mean_bandwidth_utilization': 'Bandwidth Utilization', 84 | 'mean_operating_servers': 'Operating Servers'} 85 | 86 | results = pd.DataFrame() 87 | for table in ['firstfit.csv', 'default_ppo.csv', 'tune.csv']: 88 | table = pd.read_csv(Path(args.results) / table) 89 | results = pd.concat((results, table)) 90 | 91 | results = results.rename(columns={**index_mapping, **measure_mapping}) 92 | results = results.replace('FirstFit_3', 'FirstFit') 93 | results = results.groupby(['Agent', 'Trial']).mean() 94 | results = results.reset_index() 95 | 96 | sns.set_style("whitegrid") 97 | for measure in measure_mapping.values(): 98 | fig, ax = plt.subplots(figsize=(10,6)) 99 | sns.boxplot(x='Agent', y=measure, data=results, ax=ax) 100 | sns.despine() 101 | fig.savefig(Path(args.output) / f'{measure}.svg') 102 | 103 | -------------------------------------------------------------------------------- /graph_generator.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | from geopy.distance import geodesic 3 | import random 4 | import numpy as np 5 | import argparse 6 | 7 | 8 | # def generate_graph(file): 9 | # G = nx.Graph() 10 | # G.add_node(0, cpu=3, memory=10.0, bandwidth=1000.0) 11 | # G.add_node(1, cpu=3, memory=25.0, bandwidth=1000.0) 12 | # G.add_node(2, cpu=10, memory=50.0, bandwidth=1000.0) 13 | # G.add_node(3, cpu=1, memory=10.0, bandwidth=1000.0) 14 | # G.add_node(4, cpu=3, memory=30.0, bandwidth=1000.0) 15 | # G.add_edge(0, 2, latency=50.0) 16 | # G.add_edge(1, 2, latency=50.0) 17 | # G.add_edge(2, 3, latency=50.0) 18 | # G.add_edge(2, 4, latency=50.0) 19 | 20 | # nx.write_gpickle(G, file) 21 | def generate_fatTree_graph(k, file): 22 | G = nx.Graph() 23 | servers = int(pow(k, 3) / 4) 24 | edge_sw = int(k * (k / 2)) 25 | agg_sw = int(k * (k / 2)) 26 | core_sw = int(pow(k / 2, 2)) 27 | gw = 1 28 | edge_devices = 300 29 | sv_idx_range = range(0, servers) 30 | last_sv_idx = sv_idx_range[-1] 31 | edge_idx_range = range(last_sv_idx + 1, last_sv_idx + 1 + edge_sw) 32 | last_edge_idx = edge_idx_range[-1] 33 | agg_idx_range = range(last_edge_idx + 1, last_edge_idx +1 +agg_sw) 34 | last_agg_idx = agg_idx_range[-1] 35 | core_idx_range = range(last_agg_idx + 1, last_agg_idx + 1 + core_sw) 36 | last_core_idx = core_idx_range[-1] 37 | gw_idx = last_core_idx + 1 38 | edge_dev_idx_range = range(gw_idx + 1, gw_idx + 1 + edge_devices) 39 | last_edge_dev_idx = edge_dev_idx_range[-1] 40 | # generate nodes 41 | for i in range(0, last_edge_dev_idx + 1): 42 | G.add_node(i, cpu=100, memory=100.0, bandwidth=1000.0) 43 | 44 | # add link between host and edge sw 45 | sv_cluster = -1 46 | for i in sv_idx_range: 47 | if i % int(k / 2) == 0: 48 | sv_cluster += 1 49 | 50 | G.add_edge(i, edge_idx_range[0] + sv_cluster, latency=50.0) 51 | 52 | # add link between edge sw and agg sw 53 | pod = -int(k / 2) 54 | for i in edge_idx_range: 55 | if i % int(k / 2) == 0: 56 | pod += int(k / 2) 57 | for j in range(0, int(k / 2)): 58 | G.add_edge(i, agg_idx_range[0] + j + pod, latency=50.0) 59 | 60 | # add link between agg sw and core sw 61 | for i in agg_idx_range: 62 | for j in range(int(k / 2) - 1): 63 | if i % int(k / 2) == j: 64 | for m in range(core_idx_range[j * int(k / 2)], core_idx_range[(j + 1) * int(k / 2)]): 65 | G.add_edge(i, m, latency=50.0) 66 | 67 | if i % int(k / 2) == (int(k / 2) - 1): 68 | for m in range(core_idx_range[(int(k / 2) - 1) * int(k / 2)], core_idx_range[-1] + 1): 69 | G.add_edge(i, m, latency=50.0) 70 | 71 | # add link between core sw and gw 72 | for i in core_idx_range: 73 | G.add_edge(i, gw_idx, latency=50.0) 74 | 75 | # add link between gw and edge devices 76 | for i in edge_dev_idx_range: 77 | G.add_edge(i, gw_idx, latency=50.0) 78 | 79 | nx.write_gpickle(G, file) 80 | 81 | def gml_reader(seed, cpu, memory, bandwidth, inputfile, outputfile): 82 | SPEED_OF_LIGHT = 299792458 # meter per second 83 | PROPAGATION_FACTOR = 0.77 # https://en.wikipedia.org/wiki/Propagation_delay 84 | 85 | random.seed(seed) 86 | 87 | file = inputfile 88 | if not file.endswith(".gml"): 89 | raise ValueError("{} is not a GraphML file".format(file)) 90 | network = nx.read_gml(file) 91 | 92 | # TODO assume undirected graph?? 93 | newnetwork = nx.Graph() 94 | mapping = dict() 95 | 96 | for num, node in enumerate(network.nodes()): 97 | mapping[node] = num 98 | newnetwork.add_node(num, cpu=random.randint( 99 | *cpu), memory=float(random.uniform(*memory)), bandwidth=float(random.uniform(*bandwidth))) 100 | 101 | for e in network.edges(): 102 | n1 = network.nodes(data=True)[e[0]] 103 | n2 = network.nodes(data=True)[e[1]] 104 | n1_coord = np.array((n1['graphics'].get("x"), n1['graphics'].get("y"))) 105 | n2_coord = np.array((n2['graphics'].get("x"), n2['graphics'].get("y"))) 106 | 107 | distance = np.linalg.norm(n1_coord-n2_coord) 108 | distance = distance/0.00062137 # miles->meter 109 | delay = (distance / SPEED_OF_LIGHT * 1000) * \ 110 | PROPAGATION_FACTOR # in milliseconds 111 | 112 | newnetwork.add_edge(mapping[e[0]], mapping[e[1]], latency=float(delay)) 113 | 114 | nx.write_gpickle(newnetwork, outputfile) 115 | 116 | 117 | def graphml_reader(seed, cpu, memory, bandwidth, inputfile, outputfile): 118 | SPEED_OF_LIGHT = 299792458 # meter per second 119 | PROPAGATION_FACTOR = 0.77 # https://en.wikipedia.org/wiki/Propagation_delay 120 | 121 | random.seed(seed) 122 | # setting ranged for random values of the nodes 123 | 124 | file = inputfile 125 | if not file.endswith(".graphml"): 126 | raise ValueError("{} is not a GraphML file".format(file)) 127 | network = nx.read_graphml(file, node_type=int) 128 | 129 | # TODO assume undirected graph?? 130 | newnetwork = nx.Graph() 131 | mapping = dict() 132 | 133 | for num, node in enumerate(network.nodes()): 134 | mapping[node] = num 135 | newnetwork.add_node(num, cpu=random.randint( 136 | *cpu), memory=float(random.uniform(*memory)), bandwidth=float(random.uniform(*bandwidth))) 137 | 138 | for e in network.edges(): 139 | n1 = network.nodes(data=True)[e[0]] 140 | n2 = network.nodes(data=True)[e[1]] 141 | n1_lat, n1_long = n1.get("Latitude"), n1.get("Longitude") 142 | n2_lat, n2_long = n2.get("Latitude"), n2.get("Longitude") 143 | distance = geodesic((n1_lat, n1_long), 144 | (n2_lat, n2_long)).meters # in meters 145 | delay = (distance / SPEED_OF_LIGHT * 1000) * \ 146 | PROPAGATION_FACTOR # in milliseconds 147 | newnetwork.add_edge(mapping[e[0]], mapping[e[1]], latency=float(delay)) 148 | 149 | nx.write_gpickle(newnetwork, outputfile) 150 | 151 | 152 | if __name__ == "__main__": 153 | parser = argparse.ArgumentParser() 154 | parser.add_argument('--seed', type=int, nargs='?', 155 | default=0) 156 | parser.add_argument('--k', type=int, nargs='?', 157 | default=10) 158 | parser.add_argument('--inputfile', type=str, nargs='?', 159 | const=1) 160 | parser.add_argument('--outputfile', type=str, nargs='?', 161 | const=1, default=r'./data/network.gpickle') 162 | args = parser.parse_args() 163 | cpu = (1, 500) 164 | memory = (1, 64) 165 | bandwidth = (1, 1000) 166 | 167 | if args.inputfile.endswith(".graphml"): 168 | graphml_reader(args.seed, cpu, memory, bandwidth, args.inputfile, args.outputfile) 169 | if args.inputfile.endswith(".gml"): 170 | gml_reader(args.seed, cpu, memory, bandwidth, args.inputfile, args.outputfile) 171 | else: 172 | generate_fatTree_graph(args.k, args.outputfile) 173 | -------------------------------------------------------------------------------- /nfvdeep/agent/baselines.py: -------------------------------------------------------------------------------- 1 | import time 2 | import random 3 | import torch as th 4 | import numpy as np 5 | import networkx as nx 6 | import random 7 | from stable_baselines3.common.policies import BasePolicy 8 | from stable_baselines3.common.base_class import BaseAlgorithm 9 | from stable_baselines3.common import logger 10 | from stable_baselines3.common.utils import safe_mean 11 | 12 | 13 | class BaselineHeuristic(BaseAlgorithm): 14 | """Agent wrapper for implementing heuristic baselines that adhere to the StableBaselines interface""" 15 | 16 | def __init__(self, **kwargs): 17 | # set steps similar to PPO implementation 18 | self.n_steps = 2048 19 | 20 | # initialize BaseAlgorithm 21 | kwargs['learning_rate'] = 0.0 22 | kwargs['policy_base'] = None 23 | super(BaselineHeuristic, self).__init__(**kwargs) 24 | self._setup_model() 25 | 26 | def train(self): 27 | # baseline heuristics do not require training 28 | pass 29 | 30 | def predict(self, observation, state=None, mask=None, deterministic=False,): 31 | scalar_tensor = self.policy._predict( 32 | observation, **{'deterministic': deterministic}) 33 | return scalar_tensor.item(), None 34 | 35 | def _setup_model(self): 36 | """Setup heuristic baseline policy with modified constructor""" 37 | self._setup_lr_schedule() 38 | self.policy = self.policy_class(self.env, 39 | self.observation_space, 40 | self.action_space, 41 | self.lr_schedule, 42 | **self.policy_kwargs) 43 | 44 | def collect_rollouts(self, env, callback, n_rollout_steps): 45 | """Rollout baseline policy to environment and collect performance in monitor wrapper""" 46 | n_steps = 0 47 | callback.on_rollout_start() 48 | while n_steps < n_rollout_steps: 49 | action = self.policy._predict(self._last_obs) 50 | action = np.asarray([action]) 51 | 52 | new_obs, rewards, dones, infos = env.step(action) 53 | 54 | if callback.on_step() is False: 55 | return False 56 | 57 | # update internal information buffer after each interaction 58 | self._update_info_buffer(infos) 59 | n_steps += 1 60 | self.num_timesteps += 1 61 | self._last_obs = new_obs 62 | 63 | return True 64 | 65 | def learn(self, total_timesteps, 66 | callback=None, 67 | log_interval=1, 68 | tb_log_name="run", 69 | eval_env=None, 70 | eval_freq=-1, 71 | n_eval_episodes=5, 72 | eval_log_path=None, 73 | reset_num_timesteps=True, 74 | ): 75 | 76 | iteration = 0 77 | total_timesteps, callback = self._setup_learn( 78 | total_timesteps, eval_env, callback, eval_freq, n_eval_episodes, eval_log_path, reset_num_timesteps, tb_log_name 79 | ) 80 | 81 | callback.on_training_start(locals(), globals()) 82 | 83 | while self.num_timesteps < total_timesteps: 84 | continue_training = self.collect_rollouts( 85 | self.env, callback, n_rollout_steps=self.n_steps) 86 | 87 | if continue_training is False: 88 | break 89 | 90 | iteration += 1 91 | self._update_current_progress_remaining( 92 | self.num_timesteps, total_timesteps) 93 | 94 | # Display training infos 95 | if log_interval is not None and iteration % log_interval == 0: 96 | fps = int(self.num_timesteps / (time.time() - self.start_time)) 97 | logger.record("time/iterations", iteration, 98 | exclude="tensorboard") 99 | if len(self.ep_info_buffer) > 0 and len(self.ep_info_buffer[0]) > 0: 100 | logger.record( 101 | "rollout/ep_rew_mean", safe_mean([ep_info["r"] for ep_info in self.ep_info_buffer])) 102 | logger.record( 103 | "rollout/ep_len_mean", safe_mean([ep_info["l"] for ep_info in self.ep_info_buffer])) 104 | logger.record("time/fps", fps) 105 | logger.record("time/time_elapsed", int(time.time() - 106 | self.start_time), exclude="tensorboard") 107 | logger.record("time/total_timesteps", 108 | self.num_timesteps, exclude="tensorboard") 109 | logger.dump(step=self.num_timesteps) 110 | 111 | self.train() 112 | 113 | callback.on_training_end() 114 | 115 | return self 116 | 117 | 118 | class BaselinePolicy(BasePolicy): 119 | """Stem for implementing baseline policies that adhere to the StableBaseline3 interface""" 120 | 121 | def __init__(self, env, observation_space, action_space, lr_schedule, device="auto", **kwargs): 122 | super(BaselinePolicy, self).__init__( 123 | observation_space, 124 | action_space, 125 | device, 126 | **kwargs 127 | ) 128 | # set internal NFVdeep environment assuming solely one execution environment (no parallel training) 129 | assert(env.num_envs == 1), 'Heuristic must be trained sequentially' 130 | self.env = next(iter(env.envs)).env 131 | 132 | def forward(self, obs, deterministic=False): 133 | pass 134 | 135 | 136 | class RandomPolicy(BaselinePolicy): 137 | def _predict(self, observation: th.Tensor, **kwargs): 138 | # randomly sample action from the action space 139 | return th.scalar_tensor(self.env.action_space.sample(), dtype=th.int16) 140 | 141 | 142 | class FirstFitPolicy(BaselinePolicy): 143 | """Agent that takes as action the first fitting node""" 144 | 145 | def _predict(self, state, **kwargs): 146 | """Chooses the first fitting node as the action.""" 147 | current_sfc = self.env.request_batch[self.env.sfc_idx] 148 | current_vnf = current_sfc.vnfs[self.env.vnf_idx] 149 | 150 | for node in range(self.env.vnf_backtrack.num_nodes): 151 | if self.env.vnf_backtrack.check_vnf_resources(current_vnf, current_sfc.bandwidth_demand, node): 152 | return th.scalar_tensor(node, dtype=th.int16) 153 | 154 | return self.env.vnf_backtrack.num_nodes 155 | 156 | 157 | class FirstFitPolicy2(FirstFitPolicy): 158 | """Agent that takes as action the first fitting node, but rejects sfc that 159 | have high costs compared to the revenue.""" 160 | 161 | def _predict(self, state, factor=1, **kwargs): 162 | current_sfc = self.env.request_batch[self.env.sfc_idx] 163 | current_vnf = current_sfc.vnfs[self.env.vnf_idx] 164 | positive_reward = current_sfc.bandwidth_demand 165 | costs = self.env.vnf_backtrack.costs 166 | negative_reward = sum([vnf[0]*costs['cpu']+vnf[1]*costs['memory'] 167 | for vnf in current_sfc.vnfs]) 168 | 169 | if positive_reward < factor*negative_reward: 170 | # reject embedding of VNF 171 | return th.scalar_tensor(self.env.vnf_backtrack.num_nodes, dtype=th.int16) 172 | 173 | return super()._predict(state, **kwargs) 174 | 175 | 176 | class FirstFitPolicy3(BaselinePolicy): 177 | """Agent that takes as action the first fitting node which is 178 | close to the previous embedded node in the SFC.""" 179 | 180 | def _predict(self, state, **kwargs): 181 | current_sfc = self.env.request_batch[self.env.sfc_idx] 182 | current_vnf = current_sfc.vnfs[self.env.vnf_idx] 183 | 184 | if self.env.vnf_idx == 0: 185 | # source = random.randint(0, self.env.vnf_backtrack.num_nodes-1) 186 | source = random.randint(376, 675) 187 | last_node = None 188 | 189 | elif self.env.vnf_idx == 3: 190 | source = random.randint(0, 250) 191 | last_node = source 192 | 193 | else: 194 | source = self.env.vnf_backtrack.sfc_embedding[current_sfc][self.env.vnf_idx-1] 195 | last_node = source 196 | 197 | path_length = nx.shortest_path_length( 198 | self.env.vnf_backtrack.overlay, source=source, weight='latency') 199 | sorted_nodes = [node for node, _ in sorted( 200 | path_length.items(), key=lambda item: item[1])] 201 | sorted_nodes_allow = [] 202 | sorted_nodes_allow.append(sorted_nodes[0]) 203 | for node in sorted_nodes: 204 | if node in range(0, 250): 205 | sorted_nodes_allow.append(node) 206 | 207 | for node in sorted_nodes_allow: 208 | if self.env.vnf_backtrack.check_vnf_resources(current_vnf, current_sfc.bandwidth_demand, node): 209 | if not node == last_node: 210 | # check if the bandwidth constraint holds 211 | remaining_bandwidth = self.env.vnf_backtrack.calculate_resources()[ 212 | node]['bandwidth'] 213 | if remaining_bandwidth - current_sfc.bandwidth_demand < 0: 214 | continue 215 | return th.scalar_tensor(node, dtype=th.int16) 216 | 217 | return th.scalar_tensor(self.env.vnf_backtrack.num_nodes, dtype=th.int16) 218 | 219 | 220 | class FirstFitPolicy4(FirstFitPolicy3): 221 | """Agent that takes as action the first fitting node which is close to the previous embedded 222 | node , but rejects sfc that have high costs compared to the revenue.""" 223 | 224 | def _predict(self, state, factor=1, **kwargs): 225 | current_sfc = self.env.request_batch[self.env.sfc_idx] 226 | positive_reward = current_sfc.bandwidth_demand 227 | costs = self.env.vnf_backtrack.costs 228 | negative_reward = sum([vnf[0]*costs['cpu']+vnf[1]*costs['memory'] 229 | for vnf in current_sfc.vnfs]) 230 | 231 | if positive_reward < factor*negative_reward: 232 | return th.scalar_tensor(self.env.vnf_backtrack.num_nodes, dtype=th.int16) 233 | 234 | return super()._predict(state, **kwargs) 235 | -------------------------------------------------------------------------------- /nfvdeep/agent/logging.py: -------------------------------------------------------------------------------- 1 | from stable_baselines3.common.monitor import Monitor 2 | from stable_baselines3.common.callbacks import BaseCallback 3 | 4 | 5 | class MetricLoggingCallback(BaseCallback): 6 | """Custom callback that logs the agent's performance to TensorBoard.""" 7 | 8 | def __init__(self, verbose=0): 9 | super(MetricLoggingCallback, self).__init__(verbose) 10 | 11 | def _on_step(self): 12 | """Logs step information of custom NFVDeep environment to TensorBoard""" 13 | # get monitor object and log network metrics to TensorBoard 14 | monitor: NFVDeepMonitor = self.training_env.envs[0] 15 | num_requests = max(monitor.num_accepted + monitor.num_rejected, 1) 16 | self.logger.record('acceptance_ratio', 17 | monitor.num_accepted / num_requests) 18 | self.logger.record('rejection_ratio', 19 | monitor.num_rejected / num_requests) 20 | 21 | # log mean episode costs per unique resource type 22 | for key in monitor.resource_costs: 23 | self.logger.record('mean_{}'.format( 24 | key), monitor.resource_costs[key] / monitor.episode_length) 25 | 26 | # log total mean costs for the respective episode 27 | self.logger.record('mean_total_costs', sum( 28 | monitor.resource_costs.values()) / monitor.episode_length) 29 | 30 | # log the mean amount of occupied resources per resource type 31 | for key in monitor.resource_utilization: 32 | self.logger.record('mean_{}'.format( 33 | key), monitor.resource_utilization[key]) 34 | 35 | # log the mean number of operating servers per step in an episode 36 | self.logger.record('mean_operating_servers', 37 | monitor.operating_servers / monitor.episode_length) 38 | 39 | 40 | class NFVDeepMonitor(Monitor): 41 | """Custom monitor tracking additional metrics that ensures compatability with StableBaselines.""" 42 | 43 | def reset(self, **kwargs): 44 | """Augments the environment's monitor with network related metrics.""" 45 | self.num_accepted = 0 46 | self.num_rejected = 0 47 | self.episode_length = 1 48 | self.resource_costs = {'cpu_cost': 0, 49 | 'memory_cost': 0, 50 | 'bandwidth_cost': 0} 51 | 52 | self.resource_utilization = {'cpu_utilization': 0, 53 | 'memory_utilization': 0, 54 | 'bandwidth_utilization': 0} 55 | 56 | self.operating_servers = 0 57 | 58 | return super().reset(**kwargs) 59 | 60 | def step(self, action): 61 | """Extract the environment's information to the monitor.""" 62 | observation, reward, done, info = super( 63 | NFVDeepMonitor, self).step(action) 64 | 65 | # add sfc related information to the monitor 66 | self.num_accepted += info['accepted'] 67 | self.num_rejected += info['rejected'] 68 | 69 | # add resource cost related information to the monitor 70 | for key in self.resource_costs: 71 | self.resource_costs[key] += info[key] 72 | 73 | # log moving average for resource utilization 74 | for key in self.resource_utilization: 75 | prev = self.resource_utilization[key] 76 | self.resource_utilization[key] = ( 77 | (self.episode_length - 1) / self.episode_length) * prev 78 | self.resource_utilization[key] += (1 / 79 | self.episode_length) * info[key] 80 | 81 | # add number of operating_servers servers to the monitor 82 | self.operating_servers += info['operating_servers'] 83 | self.episode_length += 1 84 | 85 | return observation, reward, done, info 86 | -------------------------------------------------------------------------------- /nfvdeep/environment/arrival.py: -------------------------------------------------------------------------------- 1 | import json 2 | import heapq 3 | import logging 4 | import random 5 | import numpy as np 6 | from abc import abstractmethod 7 | from collections.abc import Generator 8 | from nfvdeep.environment.sfv import ServiceFunctionChain 9 | 10 | 11 | class ArrivalProcess(Generator): 12 | """Abstract class that implements the request generation. Inheriting classes implement the parameterization of to be generated SFCs.""" 13 | 14 | def __init__(self, **kwargs): 15 | self.timeslot = 1 16 | 17 | # generate requests according to abstract method `generate_requests` 18 | self.requests = self.generate_requests() 19 | 20 | # order arriving SFCs according to their arrival time 21 | self.requests = [((sfc.arrival_time, num), sfc) 22 | for num, sfc in enumerate(self.requests)] 23 | heapq.heapify(self.requests) 24 | 25 | def send(self, arg): 26 | """Implements the generator interface. Generates a list of arriving SFC requests for the 27 | respective timeslot starting from timeslot one. 28 | """ 29 | req = [] 30 | 31 | if len(self.requests) <= 0: 32 | self.throw() 33 | 34 | # add SFCs to the batch until the next SFC has an arrival time that exceeds the internal timestep 35 | while len(self.requests) > 0 and self.requests[0][1].arrival_time <= self.timeslot: 36 | _, sfc = heapq.heappop(self.requests) 37 | req.append(sfc) 38 | 39 | # increment internal timeslot 40 | self.timeslot += 1 41 | return req 42 | 43 | def throw(self, type=None, value=None, traceback=None): 44 | """Raises an Error iff all SFCs were already generated.""" 45 | raise StopIteration 46 | 47 | @staticmethod 48 | def factory(config): 49 | """Factory method to allow for an easier generation of different arrival processes.""" 50 | 51 | if 'type' not in config: 52 | arrival = JSONArrivalProcess(config) 53 | 54 | arrival_type = config['type'] 55 | params = {key: value for key, value in config.items() if key != 'type'} 56 | 57 | # set a seed solely if the episodes should be static, i.e. should always get the same requests for each episode 58 | if not params['static']: 59 | params['seed'] = None 60 | 61 | if arrival_type == 'poisson_arrival_uniform_load': 62 | arrival = PoissonArrivalUniformLoad(**params) 63 | 64 | else: 65 | raise ValueError('Unknown arrival process') 66 | 67 | return arrival 68 | 69 | @abstractmethod 70 | def generate_requests(self): 71 | """Abstract method that must generate a list of SFCs to be emitted.""" 72 | raise NotImplementedError('Must be overwritten by an inheriting class') 73 | 74 | 75 | class JSONArrivalProcess(ArrivalProcess): 76 | def __init__(self, request_path): 77 | """Instantiate an arrival process that generates SFC requests at their respective arrival timeslot from a specified JSON file.""" 78 | assert (isinstance(request_path, str)) 79 | assert (request_path.endswith('.json')) 80 | self.request_path = request_path 81 | super().__init__() 82 | 83 | def generate_requests(self): 84 | """Generates SFC objects according to their paramterization as given by a JSON file.""" 85 | # load SFCs from specified JSON file 86 | with open(self.request_path, 'rb') as file: 87 | requests = json.load(file) 88 | 89 | def parse_vnfs(vnfs): return [tuple(vnf.values()) for vnf in vnfs] 90 | 91 | # create SFC objects with parameters specified in the JSON file 92 | req = [] 93 | for sfc in requests: 94 | vnfs = parse_vnfs(sfc.pop('vnfs')) 95 | sfc = ServiceFunctionChain(vnfs=vnfs, **sfc) 96 | 97 | req.append(sfc) 98 | 99 | return req 100 | 101 | 102 | class StochasticProcess(ArrivalProcess): 103 | def __init__(self, num_requests, load_generator): 104 | self.num_requests = num_requests 105 | self.load_generator = load_generator 106 | 107 | super().__init__() 108 | 109 | def generate_requests(self): 110 | load_gen = self.load_generator.next_sfc_load() 111 | arrival_gen = self.next_arrival() 112 | 113 | req = [] 114 | while len(req) < self.num_requests: 115 | arrival_time, ttl = next(arrival_gen) 116 | sfc_params = next(load_gen) 117 | sfc = ServiceFunctionChain( 118 | arrival_time=arrival_time, ttl=ttl, **sfc_params) 119 | req.append(sfc) 120 | 121 | return req 122 | 123 | 124 | class PoissonArrivalUniformLoad(StochasticProcess): 125 | def __init__(self, num_timeslots, num_requests, service_rate, num_vnfs, sfc_length, bandwidth, max_response_latency, 126 | cpus, memory, vnf_delays, seed=None, **kwargs): 127 | if not seed is None: 128 | random.seed(seed) 129 | 130 | # generate random parameters for episode 131 | self.num_requests = random.randint(*num_requests) 132 | self.num_timeslots = random.randint(*num_timeslots) 133 | 134 | # derive parametrisation of arrival- & service-time distribution 135 | self.mean_arrival_rate = self.num_requests / self.num_timeslots 136 | self.mean_service_rate = random.randint(*service_rate) 137 | 138 | # generate SFC & VNF parameters uniformly at random within their bounds 139 | load_generator = UniformLoadGenerator( 140 | sfc_length, num_vnfs, max_response_latency, bandwidth, cpus, memory, vnf_delays) 141 | 142 | super().__init__(self.num_requests, load_generator) 143 | 144 | def next_arrival(self): 145 | # interarrival times conform to an exponential distribution with the rate parameter `mean_service_rate` 146 | arrival_times = [random.expovariate( 147 | self.mean_arrival_rate) for _ in range(self.num_requests)] 148 | arrival_times = np.ceil(np.cumsum(arrival_times)) 149 | arrival_times = arrival_times.astype(int) 150 | 151 | # service times conform to an exponential distribution with the rate parameter `1 / mean_service_rate` 152 | service_times = [random.expovariate( 153 | 1 / self.mean_service_rate) for _ in range(len(arrival_times))] 154 | service_times = np.floor(service_times) 155 | service_times = service_times.astype(int) 156 | 157 | for arrival_time, service_time in zip(arrival_times, service_times): 158 | yield arrival_time, service_time 159 | 160 | 161 | class UniformLoadGenerator: 162 | def __init__(self, sfc_length, num_vnfs, max_response_latency, bandwidth, cpus, memory, vnf_delays): 163 | # SFC object generation parameters 164 | self.sfc_length = sfc_length 165 | self.num_vnfs = num_vnfs 166 | self.bandwidth = bandwidth 167 | self.max_response_latency = max_response_latency 168 | 169 | # VNF object generation parameters 170 | self.cpus = cpus 171 | self.memory = memory 172 | self.vnf_delays = vnf_delays 173 | 174 | def next_sfc_load(self): 175 | # generate requests demands for `num_vnfs` distinct types of VNFs 176 | vnf_types = [(random.randint(*self.cpus), random.uniform(*self.memory)) 177 | for _ in range(self.num_vnfs)] 178 | delays = [random.uniform( 179 | *self.vnf_delays) for _ in range(self.num_vnfs)] 180 | 181 | # create SFC objects with uniform loads 182 | while True: 183 | sfc_params = {} 184 | 185 | # randomly choose VNFs that compose the SFC 186 | num_sfc_vnfs = random.randint(*self.sfc_length) 187 | # vnfs_idx = [random.randint(0, len(vnf_types) - 1) 188 | # for _ in range(num_sfc_vnfs)] 189 | vnfs_idx = [0, 1, 2, 3] 190 | 191 | # generate all VNFs comprised in the SFC 192 | sfc_params['vnfs'] = [vnf_types[idx] for idx in vnfs_idx] 193 | sfc_params['processing_delays'] = [delays[idx] for idx in vnfs_idx] 194 | sfc_params['max_response_latency'] = random.uniform( 195 | *self.max_response_latency) 196 | sfc_params['bandwidth_demand'] = random.uniform(*self.bandwidth) 197 | 198 | yield sfc_params 199 | -------------------------------------------------------------------------------- /nfvdeep/environment/env.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import gym 3 | import json 4 | import numpy as np 5 | from gym import spaces 6 | from pathlib import Path 7 | from copy import deepcopy 8 | from nfvdeep.environment.network import Network 9 | from nfvdeep.environment.arrival import ArrivalProcess 10 | from tabulate import tabulate 11 | from nfvdeep.environment.sfv import ServiceFunctionChain 12 | import random 13 | 14 | 15 | class Env(gym.Env): 16 | def __init__(self, overlay_path, arrival_config): 17 | """A new Gym environment. This environment represents the environment of NFVdeep. 18 | 19 | Args: 20 | overlay_path: A connection to the network where the agent will act 21 | arrival_config: Dictionary that specifies the properties of the requests.""" 22 | 23 | self.overlay_path = overlay_path 24 | self.arrival_config = arrival_config 25 | 26 | # define action and statespace 27 | _, properties = Network.check_overlay(self.overlay_path) 28 | num_nodes = properties['num_nodes'] 29 | num_node_resources = properties['num_node_resources'] 30 | 31 | # action `num_nodes` refers to volutarily rejecting the VNF embedding 32 | self.action_space = spaces.Discrete(num_nodes + 1) 33 | 34 | obs_dim = num_nodes * num_node_resources + num_node_resources + 3 35 | self.observation_space = spaces.Box( 36 | low=0.0, high=1.0, shape=(obs_dim,), dtype=np.float16) 37 | 38 | self.reward = 0 39 | 40 | def step(self, action): 41 | """Process the action of the agent. 42 | 43 | Args: 44 | action(int): The action is the number of the server where the current VNF will be embedded to. 45 | Action `|nodes|` refers to voluntarily rejecting an embedding of the VNF. 46 | """ 47 | 48 | assert(not self.done), 'Episode was already finished, but step() was called' 49 | 50 | info = {'accepted': False, 'rejected': False} 51 | logging.debug('(SFC, VNF): {} -> Node: ({})'.format( 52 | (self.sfc_idx, self.vnf_idx), action)) 53 | 54 | # get the, to be processed, VNF for the current SFC 55 | sfc = self.request_batch[self.sfc_idx] 56 | vnf = sfc.vnfs[self.vnf_idx] 57 | 58 | if self.vnf_idx == 0: 59 | if action not in range(376, 676): 60 | action = random.randint(376, 675) 61 | 62 | elif self.vnf_idx == 3: 63 | if action not in range(0, 250): 64 | action = random.randint(0, 249) 65 | 66 | else: 67 | if action in range(250, 376): 68 | action = random.randint(376, 675) 69 | ''' 70 | Embed the VNF to the network. An embedding is invalid if either the VNF embedding or there do 71 | not remain sufficient resources to embed further VNFs of the current SFC / the SFC 72 | will not satisfy its constraints (e.g. TTL constraint). 73 | ''' 74 | is_valid_sfc = self.vnf_backtrack.embed_vnf(sfc, vnf, action) 75 | logging.debug('VNF embedding of {} to `vnf_backtrack` network on node: {} was {}.'.format( 76 | self.vnf_idx, action, is_valid_sfc)) 77 | 78 | if is_valid_sfc: 79 | # check whether a valid SFC embedding remains possible after embedding the VNF, i.e. 80 | # if sufficient resources remain and the SFC constraints (e.g. latency) can still be satisfied 81 | is_valid_sfc = self.vnf_backtrack.check_embeddable( 82 | sfc, vnf_offset=self.vnf_idx + 1) 83 | 84 | logging.debug('SFC embedding (remains): {}.'.format( 85 | 'possible' if is_valid_sfc else 'impossible')) 86 | 87 | ''' 88 | Process the determined action. Backtrack to the latest network state if the action was invalid or progress 89 | its state after a successful SFC embedding. 90 | ''' 91 | # determine whether the, to be processed, VNF is the last VNF of the current SFC 92 | is_last_of_sfc = self.vnf_idx >= len(sfc.vnfs) - 1 93 | 94 | # accept `vnf_backtrack` if the embedding (VNF and SFC) was valid and the SFC embedding is completed 95 | if is_valid_sfc and is_last_of_sfc: 96 | self.network = deepcopy(self.vnf_backtrack) 97 | self.sfc_idx, self.vnf_idx = (self.sfc_idx + 1, 0) 98 | # update info regarding successful embedding 99 | info['accepted'] = True 100 | 101 | logging.debug( 102 | 'Updating network state to `vnf_backtrack` after completing SFC: {}'.format(self.sfc_idx)) 103 | 104 | # invoke the agent for the next VNF of the current SFC 105 | elif is_valid_sfc and not is_last_of_sfc: 106 | self.sfc_idx, self.vnf_idx = (self.sfc_idx, self.vnf_idx + 1) 107 | 108 | # backtrack to the latest network state if the (VNF or SFC) embedding was invalid 109 | elif not is_valid_sfc: 110 | self.vnf_backtrack = deepcopy(self.network) 111 | 112 | # update info regarding unsuccessful embedding 113 | info['rejected'] = True 114 | 115 | self.sfc_idx, self.vnf_idx = (self.sfc_idx + 1, 0) 116 | 117 | logging.debug( 118 | 'Backtracking `vnf_backtrack` to the latest network state') 119 | 120 | logging.debug('SFC, VNF indices set to: {}, {}'.format( 121 | self.sfc_idx, self.vnf_idx)) 122 | 123 | ''' 124 | Progress time such that the agent will only be invoked to embed SFC that are embeddable, i.e. for whom 125 | a valid sequence of VNF embeddings exist. 126 | ''' 127 | # progress to next SFC within the request batch that can be embedded succsessfully 128 | # , i.e. progress within the intra timeslot 129 | batch_completed = self.progress_intra_timeslot() 130 | 131 | # determine the agent's reward before progressing time 132 | self.reward = self.compute_reward( 133 | sfc, is_last_of_sfc, is_valid_sfc, batch_completed) 134 | logging.debug( 135 | 'Environment will attribute reward: {}'.format(self.reward)) 136 | 137 | # progress inter timeslots until a `request_batch` with embeddable SFCs arrives 138 | if batch_completed: 139 | while True: 140 | self.done = self.progress_inter_timeslots() 141 | # progress to a SFC in the novel `request_batch` that is embeddable 142 | # if non exists continue to progress inter timeslots 143 | 144 | batch_completed = self.progress_intra_timeslot() 145 | if not batch_completed or self.done: 146 | break 147 | 148 | # log the occupied resources and operation costs, log the number of operating nodes 149 | resource_utilization = self.vnf_backtrack.calculate_resource_utilization() 150 | resource_costs = self.vnf_backtrack.calculate_resource_costs() 151 | info.update({res + '_utilization': val for res, 152 | val in resource_utilization.items()}) 153 | info.update({res + '_cost': val for res, 154 | val in resource_costs.items()}) 155 | num_operating = len(self.vnf_backtrack.get_operating_servers()) 156 | info.update({'operating_servers': num_operating}) 157 | 158 | return self.compute_state(done=self.done), self.reward, self.done, info 159 | 160 | def reset(self): 161 | """Resets the environment to the default state""" 162 | 163 | self.done = False 164 | # initialize arrival process that will generate SFC requests 165 | self.arrival_process = ArrivalProcess.factory(self.arrival_config) 166 | 167 | # initialize network and backtracking network, s.t. `vnf_backtrack` is updated after each successful VNF embedding 168 | self.network = Network(self.overlay_path) 169 | self.vnf_backtrack = deepcopy(self.network) 170 | 171 | # track indices for current SFC & VNF 172 | self.sfc_idx, self.vnf_idx = 0, 0 173 | 174 | # current batch of SFC requests, i.e. list of SFC objects to be processed 175 | self.request_batch = [] 176 | 177 | # progress time until first batch of requests arrives 178 | self.progress_inter_timeslots() 179 | 180 | return self.compute_state() 181 | 182 | def progress_intra_timeslot(self): 183 | """ Progress (SFC, VNF) indices to the next combination in the request batch that requires an 184 | invokation of the agent. 185 | """ 186 | 187 | # progress the SFC indices to a SFC for whom an interaction with the agent is required, 188 | # i.e. there exists a valid embedding 189 | while self.sfc_idx < len(self.request_batch): 190 | sfc = self.request_batch[self.sfc_idx] 191 | is_embeddable = self.vnf_backtrack.check_embeddable(sfc) 192 | 193 | # the current SFC can be embedded, invoke the agent 194 | if is_embeddable: 195 | return False 196 | 197 | self.sfc_idx, self.vnf_idx = self.sfc_idx + 1, 0 198 | 199 | # no embeddable SFC remains in the batch, hence the indices are reset 200 | batch_completed = self.sfc_idx >= len(self.request_batch) - 1 201 | self.sfc_idx, self.vnf_idx = 0, 0 202 | return batch_completed 203 | 204 | def progress_inter_timeslots(self): 205 | """ Progress `request_batch` and `network` over inter timeslots, i.e. until novel requests arrive. 206 | """ 207 | # empty the `request_batch` since we assume that all requests have been processed 208 | self.request_batch = [] 209 | 210 | try: 211 | while len(self.request_batch) <= 0: 212 | self.network.update() 213 | self.request_batch = next(self.arrival_process) 214 | 215 | logging.debug('Progressing time, next SFC request batch: {}'.format( 216 | self.request_batch)) 217 | 218 | # initialize backtracking for the invoked intra timeslot 219 | self.vnf_backtrack = deepcopy(self.network) 220 | return False 221 | 222 | except StopIteration: 223 | # the `arrival_process` is done generating further requests, finish the episode 224 | return True 225 | 226 | def render(self, mode='human'): 227 | req_batch = str(self.request_batch) 228 | resources = [[num, *[str(avail_res) + ' out of ' + str(max_res) for avail_res, max_res in zip(res[0].values(), res[1].values())]] 229 | for num, res in enumerate(zip(self.vnf_backtrack.calculate_resources(), self.vnf_backtrack.calculate_resources(False)))] 230 | 231 | sfcs = [[res.arrival_time, res.ttl, res.bandwidth_demand, res.max_response_latency, '\n'.join([str(vnf) for vnf in res.vnfs]), '\n'.join([str(node) for node in nodes])] 232 | for res, nodes in self.vnf_backtrack.sfc_embedding.items()] 233 | 234 | rep = str(tabulate(resources, headers=[ 235 | 'Node', 'Cpu', 'Memory', 'Bandwidth'], tablefmt="presto")) 236 | rep += '\n \n \n' 237 | rep += 'Currently active Service Function Chains in the network:\n \n' 238 | rep += str(tabulate(sfcs, headers=['Arrival time', 'TTL', 'Bandwidth', 239 | 'Max latency', 'VNFs (CPU, Memory)', ' Embedding Nodes'], tablefmt="grid")) 240 | rep += '\n \n' 241 | rep += 'Last reward = '+str(self.reward)+'\n' 242 | rep += 'Current request batch for (network) timestep ' + str( 243 | self.network.timestep)+': \n' + str(req_batch) 244 | rep += '\n \n \n' 245 | rep += '======================================================================================================================' 246 | rep += '\n' 247 | return rep 248 | 249 | def compute_state(self, done=False): 250 | """Compute the environment's state representation.""" 251 | 252 | if (done == True): 253 | return np.asarray([]) 254 | 255 | # compute remaining resources of backtrack network, i.e. (cpu, memory, bandwidth) for each node 256 | network_resources = self.vnf_backtrack.calculate_resources( 257 | remaining=True) 258 | network_resources = np.asarray([list(node_res.values()) 259 | for node_res in network_resources], dtype=np.float16) 260 | 261 | # normalize network resources by their max capacity (over all nodes) 262 | max_resources = self.vnf_backtrack.calculate_resources(remaining=False) 263 | max_resources = np.asarray([list(node_res.values()) 264 | for node_res in max_resources], dtype=np.float16) 265 | max_resources = np.max(max_resources, axis=0) 266 | network_resources = network_resources / max_resources 267 | # reshaping to 1d vector (flatten) 268 | network_resources = network_resources.reshape(-1) 269 | 270 | # compute (normalized) information regarding the VNF which is to be placed next 271 | sfc = self.request_batch[self.sfc_idx] 272 | vnf = sfc.vnfs[self.vnf_idx] 273 | 274 | norm_vnf_resources = np.asarray([*vnf, sfc.bandwidth_demand]) 275 | norm_vnf_resources = list(norm_vnf_resources / max_resources) 276 | 277 | # TODO: parameterize normalization of constants such as TTL? 278 | norm_residual_latency = (sfc.max_response_latency - 279 | self.vnf_backtrack.calculate_current_latency(sfc)) / 1000 280 | norm_undeployed = (len(sfc.vnfs) - (self.vnf_idx + 1)) / 7 281 | norm_ttl = sfc.ttl / 1000 282 | 283 | observation = np.concatenate((network_resources, 284 | norm_vnf_resources, norm_residual_latency, norm_undeployed, norm_ttl), axis=None) 285 | 286 | return observation 287 | 288 | def compute_reward(self, sfc, last_in_sfc, sfc_valid, batch_completed): 289 | """Computes the reward signal dependent on whether a SFC has been succsessfully embedded 290 | Args: 291 | sfc: The current SFC 292 | last_in_sfc (bool): determines, if the current sfc is finished i.e. the last vnf was processed 293 | sfc_valid (bool): determines, if the current sfc was valid 294 | batch_completed (bool): determines, if the current batch of sfc is completed""" 295 | 296 | if not (last_in_sfc and sfc_valid): 297 | reward = 0 298 | else: 299 | reward = (sfc.ttl*sfc.bandwidth_demand) / 10 300 | 301 | if batch_completed: 302 | # compute total operation costs of the network first from individual costs of each resource 303 | costs = self.vnf_backtrack.calculate_resource_costs() 304 | costs = sum(costs.values()) 305 | reward -= costs 306 | 307 | return reward -------------------------------------------------------------------------------- /nfvdeep/environment/network.py: -------------------------------------------------------------------------------- 1 | import functools 2 | import operator 3 | import networkx as nx 4 | from collections import Counter 5 | from networkx.exception import NetworkXNoPath 6 | from nfvdeep.environment.sfv import ServiceFunctionChain 7 | 8 | 9 | class Network: 10 | def __init__(self, overlay, costs={'cpu': 0.2, 'memory': 0.2, 'bandwidth': 0.006}): 11 | """Internal representation of the network & embedded VNFs. 12 | 13 | Args: 14 | overlay (str or networkx graph): Path to an overlay graph that specifies the network's properties 15 | or a valid networkx graph. 16 | costs (tuple of float): The cost for one unit of cpu, memory and bandwidth""" 17 | 18 | # parse and validate the overlay network 19 | self.overlay, properties = Network.check_overlay(overlay) 20 | self.num_nodes = properties['num_nodes'] 21 | 22 | self.timestep = 0 23 | self.costs = costs 24 | 25 | # the service function chains with its mapping to the network nodes: 26 | self.sfc_embedding = dict() 27 | 28 | def update(self, time_increment=1): 29 | """Let the network run for the given time""" 30 | 31 | # TODO: increment timestep before / after updating SFCs? 32 | self.timestep += time_increment 33 | 34 | # delete all SFCs that exceed their TTL 35 | def check_ttl(sfc): return sfc.arrival_time + sfc.ttl >= self.timestep 36 | sfc_embedding = {sfc: nodes for sfc, 37 | nodes in self.sfc_embedding.items() if check_ttl(sfc)} 38 | 39 | self.sfc_embedding = sfc_embedding 40 | 41 | def embed_vnf(self, sfc: ServiceFunctionChain, vnf: tuple, node: int): 42 | """Embeds the Virtual Network Function to a specified node.""" 43 | 44 | # reject an embedding if the network does not provide sufficient VNF resources or the action 45 | # voluntarily chooses no embedding 46 | if node >= self.num_nodes or not self.check_vnf_resources(vnf, sfc, node): 47 | return False 48 | 49 | if sfc not in self.sfc_embedding: 50 | self.sfc_embedding[sfc] = [] 51 | 52 | self.sfc_embedding[sfc].append(node) 53 | 54 | return True 55 | 56 | def calculate_resources(self, remaining=True) -> list: 57 | """Calculates the remaining resources for all nodes. 58 | 59 | Returns: 60 | List of dictionaries s.t. the i-th entry is a representation of the remaining resources of the i-th node 61 | """ 62 | resources = [{res: max_val for res, max_val in res.items()} 63 | for _, res in self.overlay.nodes(data=True)] 64 | 65 | if remaining: 66 | # calculated remaining resources 67 | for sfc, nodes in self.sfc_embedding.items(): 68 | for vnf_idx, node_idx in enumerate(nodes): 69 | resources[node_idx]['cpu'] -= sfc.vnfs[vnf_idx][0] 70 | resources[node_idx]['memory'] -= sfc.vnfs[vnf_idx][1] 71 | 72 | # bandwidth is demanded if successive VNFs are embedded on different servers, i.e. 73 | # no bandwidth is required if the VNF is placed on the same server as the previous VNF, 74 | # unless for the last VNF of the chain, for whom we always demand bandwidth 75 | if vnf_idx == len(nodes) - 1: 76 | # resources[node_idx]['bandwidth'] -= sfc.bandwidth_demand 77 | resources[node_idx]['bandwidth'] -= 0 78 | elif not nodes[vnf_idx] == nodes[vnf_idx+1]: 79 | resources[node_idx]['bandwidth'] -= sfc.bandwidth_demand 80 | elif (vnf_idx > 0) and not nodes[vnf_idx] == nodes[vnf_idx-1]: 81 | resources[node_idx]['bandwidth'] -= sfc.bandwidth_demand 82 | 83 | return resources 84 | 85 | def check_sfc_constraints(self, sfc): 86 | """ Check whether the (partial) SFC embedding satisfies the bandwidth and latency constraints, i.e. 87 | if the bandwidth demand can be satisfied by ANY node and if the SFC can still satisfy its latency constraints. 88 | """ 89 | 90 | # check if there exists a node which can cover the request's bandwidth demand 91 | resources = self.calculate_resources() 92 | max_available_bandwidth = max([res['bandwidth'] for res in resources]) 93 | bandwidth_constraint = sfc.bandwidth_demand <= max_available_bandwidth 94 | 95 | # check if the current bandwidth constrains hold 96 | if not all([node['bandwidth'] >= 0 for node in resources]): 97 | return False 98 | 99 | # distinguish whether SFC is already (partially) embedded or a novel request 100 | if not sfc in self.sfc_embedding: 101 | # solely verify bandwidth constraint for novel requests 102 | return bandwidth_constraint 103 | 104 | # if there is a next VNF and it can be embedded to the same node as the previous VNF, 105 | # no additional bandwidth is demanded 106 | elif not bandwidth_constraint and len(self.sfc_embedding[sfc]) < len(sfc.vnfs): 107 | last_node = self.sfc_embedding[sfc][-1] 108 | next_vnf = sfc.vnfs[len(self.sfc_embedding[sfc])] 109 | bandwidth_constraint = self.check_vnf_resources( 110 | next_vnf, sfc, last_node) 111 | 112 | # also verify the latency constraints for a (partially) embedded SFC, i.e. 113 | # does the latency of prior VNF embeddings violate the maximum latency of the request? 114 | try: 115 | latency = self.calculate_current_latency(sfc) 116 | latency_constraint = latency <= sfc.max_response_latency 117 | except NetworkXNoPath: 118 | latency_constraint = False 119 | 120 | return bandwidth_constraint and latency_constraint 121 | 122 | def calculate_current_latency(self, sfc): 123 | """Calculates the current latency of the SFC i.e the end to end delay from the start of the SFC to the currently 124 | last embedded VNF of the SFC 125 | 126 | Throws NetworkXNoPath, if there is no possible path between two VNFs""" 127 | 128 | latency = 0 129 | 130 | # compute transmission and processing delay if the SFC is already (partially) embedded 131 | if sfc in self.sfc_embedding: 132 | nodes = self.sfc_embedding[sfc] 133 | latency = sum([nx.dijkstra_path_length(self.overlay, nodes[idx-1], 134 | nodes[idx], weight='latency') for idx in range(1, len(nodes))]) 135 | 136 | latency += sum(sfc.processing_delays[:len(nodes)]) 137 | 138 | return latency 139 | 140 | def check_embeddable(self, sfc: ServiceFunctionChain, vnf_offset=0): 141 | """ Check whether the (partial) SFC embedding can still satisfy its constraints, i.e. check if for all remaining VNFs 142 | some node with sufficient resources exists and if the SFC constraints can still be satisfied. 143 | """ 144 | vnfs = sfc.vnfs[vnf_offset:] 145 | # check whether remaining resources are sufficient to embed further VNFs 146 | # TODO: we check only if there exists a node that provides sufficient resources for the next VNF 147 | # TODO: the paper does not specifiy how exactly this test is done, i.e. how to specify 148 | # that the agent will only be invoked if a valid embedding exists 149 | vnf_constraints = len(vnfs) <= 0 150 | if not vnf_constraints: 151 | next_vnf = next(iter(vnfs)) 152 | vnf_constraints = self.check_vnf_resources( 153 | next_vnf, sfc) 154 | 155 | # check whether SFC can still fullfill service constraints (SFC constraints) 156 | sfc_constraints = self.check_sfc_constraints(sfc) 157 | 158 | return vnf_constraints and sfc_constraints 159 | 160 | def check_vnf_resources(self, vnf, sfc, node=None): 161 | """ Check whether some node exists with sufficient resources or if the specified node provides enough resources. """ 162 | 163 | resources = self.calculate_resources() 164 | if node is not None: 165 | resources = [resources[node]] 166 | 167 | def constraints(res, vnf): return all( 168 | [res['cpu'] >= vnf[0], res['memory'] >= vnf[1]]) 169 | nodes = set(num for num, res in enumerate( 170 | resources) if constraints(res, vnf)) 171 | 172 | return bool(nodes) 173 | 174 | def calculate_occupied_resources(self): 175 | """Calculates a dictionary that summarizes the amount of occupied resources per type.""" 176 | 177 | # compute the amount of maximum resources / available resources per node 178 | resources = self.calculate_resources(remaining=False) 179 | avail_resources = self.calculate_resources(remaining=True) 180 | 181 | # reduce the respective resources over the entire network (i.e. summed over all nodes) 182 | resources = dict(functools.reduce(operator.add, 183 | map(Counter, resources))) 184 | avail_resources = dict(functools.reduce(operator.add, 185 | map(Counter, avail_resources))) 186 | 187 | # get the amount of depleted resources and their costs 188 | depleted = {key: resources[key] - 189 | avail_resources[key] for key in resources} 190 | costs = {key: depleted[key] 191 | * self.costs[key] for key in depleted} 192 | 193 | return costs 194 | 195 | def calculate_resource_utilization(self): 196 | """Calculates a dictionary that summarizes the resource utilization per resource type.""" 197 | 198 | # compute the amount of maximum resources / available resources per node 199 | max_resources = self.calculate_resources(remaining=False) 200 | avail_resources = self.calculate_resources(remaining=True) 201 | 202 | max_resources = dict(functools.reduce(operator.add, 203 | map(Counter, max_resources))) 204 | avail_resources = dict(functools.reduce(operator.add, 205 | map(Counter, avail_resources))) 206 | 207 | # compute resource utilization per type as a dictionary 208 | utilization = {key: ( 209 | max_resources[key] - avail_resources[key]) / max_resources[key] for key in max_resources} 210 | 211 | return utilization 212 | 213 | def get_operating_servers(self): 214 | """Computes the set of indices that describe all operating servers.""" 215 | operating_servers = { 216 | server for sfc in self.sfc_embedding for server in self.sfc_embedding[sfc]} 217 | return operating_servers 218 | 219 | def calculate_resource_costs(self): 220 | """Computes a dictionary that summarizes the current operation costs per resource type.""" 221 | # get a set of currently operating nodes 222 | operating_servers = self.get_operating_servers() 223 | 224 | if not operating_servers: 225 | return {key: 0 for key in self.costs} 226 | 227 | # filter the maximum available resources with respect to the operating servers 228 | resources = [res for idx, res in enumerate( 229 | self.calculate_resources(remaining=False)) if idx in operating_servers] 230 | 231 | # reduce the amount of resources per type 232 | resources = dict(functools.reduce(operator.add, 233 | map(Counter, resources))) 234 | 235 | # calculate the cost per resource type 236 | cost = {res: resources[res] 237 | * self.costs[res] for res in resources} 238 | 239 | return cost 240 | 241 | @staticmethod 242 | def check_overlay(overlay): 243 | """Checks whether the overlay adhers to the expected parameter types and attributes, returns the parsed network instance.""" 244 | 245 | # parse overlay from gpickle if 246 | if isinstance(overlay, str) and overlay.endswith('.gpickle'): 247 | overlay = nx.read_gpickle(overlay) 248 | 249 | node_attributes = {'cpu': int, 'memory': float, 'bandwidth': float} 250 | for _, data in overlay.nodes(data=True): 251 | assert(all([nattr in data for nattr, ntype in node_attributes.items( 252 | )])), 'Overlay must specify all required node attributes.' 253 | assert(all([type(data[nattr]) == ntype for nattr, ntype in node_attributes.items( 254 | )])), 'Overlay must specify the correct data types.' 255 | 256 | edge_attributes = {'latency': float} 257 | for _, _, data in overlay.edges(data=True): 258 | assert(all([eattr in data for eattr, etype in edge_attributes.items( 259 | )])), 'Overlay must specify all required edge attributes.' 260 | assert(all([type(data[eattr]) == etype for eattr, etype in edge_attributes.items( 261 | )])), 'Overlay must specify the correct data types.' 262 | 263 | # compute properties of the parsed graph 264 | properties = {} 265 | properties['num_nodes'] = overlay.number_of_nodes() 266 | _, resource = next(iter(overlay.nodes(data=True))) 267 | properties['num_node_resources'] = len(resource) 268 | 269 | return overlay, properties -------------------------------------------------------------------------------- /nfvdeep/environment/sfv.py: -------------------------------------------------------------------------------- 1 | class ServiceFunctionChain: 2 | def __init__(self, arrival_time, ttl, bandwidth_demand, max_response_latency, vnfs, processing_delays=None): 3 | '''Creating a new service function chain 4 | 5 | Args: 6 | arrival_time (int): Arrival time of the SFC request 7 | ttl (int): Time to live of the SFC 8 | bandwidth_demand (float): The minimal ammount of bandwidth that is acceptable 9 | max_response_latency (float): The maximal acceptable latency 10 | vnfs (list of tuples): A (ordered) list of all Vnfs of the SFC 11 | processing_delays (list of float): A (ordered) list of all delays of the Vnfs (default: no delays)''' 12 | 13 | self.arrival_time = arrival_time 14 | self.ttl = ttl 15 | self.bandwidth_demand = bandwidth_demand 16 | self.max_response_latency = max_response_latency 17 | self.vnfs = vnfs 18 | self.num_vnfs = len(self.vnfs) 19 | 20 | self.processing_delays = [ 21 | 0 for _ in self.vnfs] if processing_delays is None else processing_delays 22 | 23 | def __repr__(self): 24 | """String representation of the SFC instance.""" 25 | s = ' '.join([str([vnf for vnf in self.vnfs])]) 26 | return s 27 | -------------------------------------------------------------------------------- /nfvdeep/spaces/A2C_space.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "learning_rate", 4 | "type": "range", 5 | "bounds": [ 6 | 3e-05, 7 | 0.003 8 | ] 9 | }, 10 | { 11 | "name": "gamma", 12 | "type": "range", 13 | "bounds": [ 14 | 0.99, 15 | 1.0 16 | ] 17 | }, 18 | { 19 | "name": "gae_lambda", 20 | "type": "range", 21 | "bounds": [ 22 | 0.8, 23 | 1.0 24 | ] 25 | }, 26 | { 27 | "name": "max_grad_norm", 28 | "type": "range", 29 | "bounds": [ 30 | 0.3, 31 | 7.0 32 | ] 33 | } 34 | ] -------------------------------------------------------------------------------- /nfvdeep/spaces/PPO_space.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "learning_rate", 4 | "type": "range", 5 | "bounds": [ 6 | 3e-05, 7 | 0.003 8 | ] 9 | }, 10 | { 11 | "name": "gamma", 12 | "type": "range", 13 | "bounds": [ 14 | 0.99, 15 | 1.0 16 | ] 17 | }, 18 | { 19 | "name": "gae_lambda", 20 | "type": "range", 21 | "bounds": [ 22 | 0.8, 23 | 1.0 24 | ] 25 | }, 26 | { 27 | "name": "max_grad_norm", 28 | "type": "range", 29 | "bounds": [ 30 | 0.3, 31 | 7.0 32 | ] 33 | } 34 | ] -------------------------------------------------------------------------------- /nfvdeep/tuning.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import gym 3 | import numpy as np 4 | from copy import deepcopy 5 | from typing import Union 6 | from ray.tune import report 7 | from stable_baselines3.common.evaluation import evaluate_policy 8 | from stable_baselines3.common.vec_env import DummyVecEnv, VecEnv, sync_envs_normalization 9 | from stable_baselines3.common.callbacks import BaseCallback 10 | 11 | 12 | class OptimizationCallback(BaseCallback): 13 | 14 | def __init__(self, eval_env: Union[gym.Env, VecEnv], 15 | n_eval_episodes: int = 5, 16 | deterministic: bool = True, 17 | verbose=0): 18 | super(OptimizationCallback, self).__init__(verbose) 19 | self.eval_env = deepcopy(eval_env) 20 | self.eval_env.reset() 21 | self.n_eval_episodes = n_eval_episodes 22 | self.deterministic = deterministic 23 | 24 | def _on_step(self): 25 | sync_envs_normalization(self.training_env, self.eval_env) 26 | 27 | episode_rewards, episode_lengths = evaluate_policy(self.model, self.eval_env, 28 | n_eval_episodes=self.n_eval_episodes, 29 | render=False, 30 | deterministic=self.deterministic, 31 | return_episode_rewards=True) 32 | 33 | episode_reward_mean, std_reward = np.mean( 34 | episode_rewards), np.std(episode_rewards) 35 | mean_ep_length, std_ep_length = np.mean( 36 | episode_lengths), np.std(episode_lengths) 37 | 38 | report( 39 | episode_reward_mean=episode_reward_mean, 40 | std_reward=std_reward, 41 | mean_ep_length=mean_ep_length, 42 | std_ep_length=std_ep_length 43 | ) 44 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | absl-py==0.10.0 2 | aiohttp==3.6.2 3 | aioredis==1.3.1 4 | astunparse==1.6.3 5 | async-timeout==3.0.1 6 | attrs==20.1.0 7 | autopep8 @ file:///tmp/build/80754af9/autopep8_1596578164842/work 8 | ax-platform==0.1.14 9 | beautifulsoup4==4.9.1 10 | blessings==1.7 11 | blinker==1.4 12 | botorch==0.3.0 13 | brotlipy==0.7.0 14 | cachetools @ file:///tmp/build/80754af9/cachetools_1596822027882/work 15 | certifi==2020.6.20 16 | cffi @ file:///tmp/build/80754af9/cffi_1598370769933/work 17 | chardet==3.0.4 18 | click==7.1.2 19 | cloudpickle==1.6.0 20 | colorama==0.4.3 21 | colorful==0.5.4 22 | cryptography @ file:///tmp/build/80754af9/cryptography_1598371395109/work 23 | cycler==0.10.0 24 | decorator==4.4.2 25 | dill==0.3.2 26 | filelock==3.0.12 27 | future==0.18.2 28 | gast==0.3.3 29 | google==3.0.0 30 | google-api-core==1.22.1 31 | google-auth @ file:///tmp/build/80754af9/google-auth_1596863485713/work 32 | google-auth-oauthlib==0.4.1 33 | google-pasta==0.2.0 34 | googleapis-common-protos==1.52.0 35 | gpustat==0.6.0 36 | gpytorch==1.1.1 37 | grpcio @ file:///tmp/build/80754af9/grpcio_1597424474635/work 38 | gym==0.17.2 39 | h5py @ file:///tmp/build/80754af9/h5py_1593454122442/work 40 | hiredis==1.1.0 41 | idna @ file:///tmp/build/80754af9/idna_1593446292537/work 42 | importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1593446406207/work 43 | Jinja2==2.11.2 44 | joblib==0.16.0 45 | jsonschema==3.2.0 46 | Keras-Preprocessing==1.1.0 47 | kiwisolver==1.2.0 48 | Markdown @ file:///tmp/build/80754af9/markdown_1597433240441/work 49 | MarkupSafe==1.1.1 50 | matplotlib==3.3.1 51 | mdutils==1.2.2 52 | mkl-fft==1.1.0 53 | mkl-random==1.1.1 54 | mkl-service==2.3.0 55 | msgpack==1.0.0 56 | multidict==4.7.6 57 | networkx==2.5 58 | numpy @ file:///tmp/build/80754af9/numpy_and_numpy_base_1596233721170/work 59 | nvidia-ml-py3==7.352.0 60 | oauthlib==3.1.0 61 | opencensus==0.7.10 62 | opencensus-context==0.1.1 63 | opt-einsum==3.1.0 64 | pandas==1.1.1 65 | Pillow==7.2.0 66 | plotly==4.9.0 67 | prometheus-client==0.8.0 68 | protobuf==3.13.0 69 | psutil==5.7.2 70 | py-spy==0.3.3 71 | pyasn1==0.4.8 72 | pyasn1-modules==0.2.8 73 | pycodestyle==2.6.0 74 | pycparser @ file:///tmp/build/80754af9/pycparser_1594388511720/work 75 | pyglet==1.5.0 76 | PyJWT==1.7.1 77 | pyOpenSSL @ file:///tmp/build/80754af9/pyopenssl_1594392929924/work 78 | pyparsing==2.4.7 79 | pyrsistent==0.16.0 80 | PySocks==1.7.1 81 | python-dateutil==2.8.1 82 | pytz==2020.1 83 | PyYAML==5.3.1 84 | ray==0.8.7 85 | redis==3.4.1 86 | requests @ file:///tmp/build/80754af9/requests_1592841827918/work 87 | requests-oauthlib==1.3.0 88 | retrying==1.3.3 89 | rsa @ file:///tmp/build/80754af9/rsa_1596998415516/work 90 | scikit-learn==0.23.2 91 | scipy @ file:///tmp/build/80754af9/scipy_1597686649129/work 92 | seaborn==0.11.0 93 | six==1.15.0 94 | soupsieve==2.0.1 95 | stable-baselines3==0.8.0 96 | tabulate==0.8.7 97 | tensorboard==2.3.0 98 | tensorboard-plugin-wit==1.7.0 99 | tensorboardX==2.1 100 | tensorflow==2.2.1 101 | tensorflow-estimator==2.2.1 102 | termcolor==1.1.0 103 | threadpoolctl==2.1.0 104 | toml @ file:///tmp/build/80754af9/toml_1592853716807/work 105 | torch==1.6.0 106 | urllib3 @ file:///tmp/build/80754af9/urllib3_1597086586889/work 107 | Werkzeug==1.0.1 108 | wrapt==1.12.1 109 | yarl==1.5.1 110 | zipp==3.1.0 111 | -------------------------------------------------------------------------------- /results/abilene/dynamic/default/monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1614514546.2763753, "env_id": null} 2 | r,l,t 3 | 181318.837538,3586,76.93715 4 | 536407.690604,1347,103.261208 5 | 425536.821559,1789,138.952246 6 | 729256.314503,1152,163.285317 7 | 508419.06768,436,175.597233 8 | 548426.493845,1046,195.195623 9 | 400852.600669,704,208.346916 10 | -------------------------------------------------------------------------------- /results/abilene/dynamic/default/requests.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "type": "poisson_arrival_uniform_load", 4 | "static": false, 5 | "num_timeslots": [30000, 30000], 6 | "num_requests": [100, 1000], 7 | "service_rate": [100, 1000], 8 | "num_vnfs": 4, 9 | "sfc_length": [4, 4], 10 | "bandwidth": [20, 100], 11 | "max_response_latency": [10000, 10000], 12 | "cpus": [1, 20], 13 | "memory": [5.0, 10.0], 14 | "vnf_delays": [20, 100] 15 | } 16 | 17 | -------------------------------------------------------------------------------- /results/abilene/static/default/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [100, 1000], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10000, 10000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [20, 100] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene/static/latency_experiments/medium/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [100, 1000], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10, 15], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene/static/latency_experiments/relaxed/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [100, 1000], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10000, 10000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [20, 100] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene/static/latency_experiments/tight/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [100, 1000], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [4, 7], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | -------------------------------------------------------------------------------- /results/abilene/static/load_experiments/high_load/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [1100, 2000], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10000, 10000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [20, 100] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene/static/load_experiments/low_load/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [100, 1000], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10000, 10000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [20, 100] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene/static/load_experiments/medium_load/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [30000, 30000], 5 | "num_requests": [600, 1500], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10000, 10000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [20, 100] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene_v2/dynamic/default/requests.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "type": "poisson_arrival_uniform_load", 4 | "static": false, 5 | "num_timeslots": [6000, 6000], 6 | "num_requests": [20, 200], 7 | "service_rate": [100, 1000], 8 | "num_vnfs": 6, 9 | "sfc_length": [1, 6], 10 | "bandwidth": [20, 100], 11 | "max_response_latency": [1000, 1000], 12 | "cpus": [1, 20], 13 | "memory": [5.0, 10.0], 14 | "vnf_delays": [0, 0] 15 | } 16 | 17 | -------------------------------------------------------------------------------- /results/abilene_v2/static/default/firstfit.csv: -------------------------------------------------------------------------------- 1 | agent,trial,episode,reward,acceptance_rate,mean_cpu_utilization,mean_memory_utilization,mean_bandwidth_utilization,mean_operating_servers 2 | FirstFit_3,0,0,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 3 | FirstFit_3,0,1,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 4 | FirstFit_3,0,2,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 5 | FirstFit_3,0,3,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 6 | FirstFit_3,0,4,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 7 | FirstFit_3,0,5,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 8 | FirstFit_3,0,6,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 9 | FirstFit_3,0,7,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 10 | FirstFit_3,0,8,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 11 | FirstFit_3,0,9,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 12 | FirstFit_3,0,10,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 13 | FirstFit_3,0,11,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 14 | FirstFit_3,0,12,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 15 | FirstFit_3,0,13,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 16 | FirstFit_3,0,14,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 17 | FirstFit_3,0,15,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 18 | FirstFit_3,0,16,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 19 | FirstFit_3,0,17,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 20 | FirstFit_3,0,18,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 21 | FirstFit_3,0,19,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 22 | FirstFit_3,1,0,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 23 | FirstFit_3,1,1,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 24 | FirstFit_3,1,2,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 25 | FirstFit_3,1,3,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 26 | FirstFit_3,1,4,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 27 | FirstFit_3,1,5,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 28 | FirstFit_3,1,6,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 29 | FirstFit_3,1,7,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 30 | FirstFit_3,1,8,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 31 | FirstFit_3,1,9,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 32 | FirstFit_3,1,10,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 33 | FirstFit_3,1,11,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 34 | FirstFit_3,1,12,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 35 | FirstFit_3,1,13,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 36 | FirstFit_3,1,14,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 37 | FirstFit_3,1,15,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 38 | FirstFit_3,1,16,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 39 | FirstFit_3,1,17,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 40 | FirstFit_3,1,18,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 41 | FirstFit_3,1,19,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 42 | FirstFit_3,2,0,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 43 | FirstFit_3,2,1,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 44 | FirstFit_3,2,2,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 45 | FirstFit_3,2,3,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 46 | FirstFit_3,2,4,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 47 | FirstFit_3,2,5,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 48 | FirstFit_3,2,6,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 49 | FirstFit_3,2,7,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 50 | FirstFit_3,2,8,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 51 | FirstFit_3,2,9,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 52 | FirstFit_3,2,10,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 53 | FirstFit_3,2,11,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 54 | FirstFit_3,2,12,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 55 | FirstFit_3,2,13,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 56 | FirstFit_3,2,14,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 57 | FirstFit_3,2,15,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 58 | FirstFit_3,2,16,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 59 | FirstFit_3,2,17,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 60 | FirstFit_3,2,18,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 61 | FirstFit_3,2,19,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 62 | FirstFit_3,3,0,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 63 | FirstFit_3,3,1,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 64 | FirstFit_3,3,2,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 65 | FirstFit_3,3,3,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 66 | FirstFit_3,3,4,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 67 | FirstFit_3,3,5,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 68 | FirstFit_3,3,6,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 69 | FirstFit_3,3,7,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 70 | FirstFit_3,3,8,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 71 | FirstFit_3,3,9,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 72 | FirstFit_3,3,10,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 73 | FirstFit_3,3,11,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 74 | FirstFit_3,3,12,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 75 | FirstFit_3,3,13,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 76 | FirstFit_3,3,14,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 77 | FirstFit_3,3,15,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 78 | FirstFit_3,3,16,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 79 | FirstFit_3,3,17,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 80 | FirstFit_3,3,18,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 81 | FirstFit_3,3,19,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 82 | FirstFit_3,4,0,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 83 | FirstFit_3,4,1,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 84 | FirstFit_3,4,2,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 85 | FirstFit_3,4,3,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 86 | FirstFit_3,4,4,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 87 | FirstFit_3,4,5,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 88 | FirstFit_3,4,6,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 89 | FirstFit_3,4,7,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 90 | FirstFit_3,4,8,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 91 | FirstFit_3,4,9,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 92 | FirstFit_3,4,10,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 93 | FirstFit_3,4,11,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 94 | FirstFit_3,4,12,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 95 | FirstFit_3,4,13,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 96 | FirstFit_3,4,14,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 97 | FirstFit_3,4,15,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 98 | FirstFit_3,4,16,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 99 | FirstFit_3,4,17,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 100 | FirstFit_3,4,18,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 101 | FirstFit_3,4,19,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 102 | FirstFit_3,5,0,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 103 | FirstFit_3,5,1,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 104 | FirstFit_3,5,2,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 105 | FirstFit_3,5,3,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 106 | FirstFit_3,5,4,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 107 | FirstFit_3,5,5,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 108 | FirstFit_3,5,6,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 109 | FirstFit_3,5,7,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 110 | FirstFit_3,5,8,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 111 | FirstFit_3,5,9,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 112 | FirstFit_3,5,10,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 113 | FirstFit_3,5,11,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 114 | FirstFit_3,5,12,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 115 | FirstFit_3,5,13,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 116 | FirstFit_3,5,14,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 117 | FirstFit_3,5,15,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 118 | FirstFit_3,5,16,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 119 | FirstFit_3,5,17,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 120 | FirstFit_3,5,18,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 121 | FirstFit_3,5,19,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 122 | FirstFit_3,6,0,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 123 | FirstFit_3,6,1,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 124 | FirstFit_3,6,2,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 125 | FirstFit_3,6,3,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 126 | FirstFit_3,6,4,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 127 | FirstFit_3,6,5,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 128 | FirstFit_3,6,6,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 129 | FirstFit_3,6,7,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 130 | FirstFit_3,6,8,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 131 | FirstFit_3,6,9,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 132 | FirstFit_3,6,10,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 133 | FirstFit_3,6,11,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 134 | FirstFit_3,6,12,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 135 | FirstFit_3,6,13,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 136 | FirstFit_3,6,14,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 137 | FirstFit_3,6,15,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 138 | FirstFit_3,6,16,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 139 | FirstFit_3,6,17,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 140 | FirstFit_3,6,18,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 141 | FirstFit_3,6,19,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 142 | FirstFit_3,7,0,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 143 | FirstFit_3,7,1,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 144 | FirstFit_3,7,2,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 145 | FirstFit_3,7,3,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 146 | FirstFit_3,7,4,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 147 | FirstFit_3,7,5,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 148 | FirstFit_3,7,6,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 149 | FirstFit_3,7,7,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 150 | FirstFit_3,7,8,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 151 | FirstFit_3,7,9,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 152 | FirstFit_3,7,10,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 153 | FirstFit_3,7,11,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 154 | FirstFit_3,7,12,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 155 | FirstFit_3,7,13,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 156 | FirstFit_3,7,14,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 157 | FirstFit_3,7,15,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 158 | FirstFit_3,7,16,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 159 | FirstFit_3,7,17,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 160 | FirstFit_3,7,18,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 161 | FirstFit_3,7,19,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 162 | FirstFit_3,8,0,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 163 | FirstFit_3,8,1,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 164 | FirstFit_3,8,2,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 165 | FirstFit_3,8,3,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 166 | FirstFit_3,8,4,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 167 | FirstFit_3,8,5,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 168 | FirstFit_3,8,6,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 169 | FirstFit_3,8,7,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 170 | FirstFit_3,8,8,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 171 | FirstFit_3,8,9,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 172 | FirstFit_3,8,10,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 173 | FirstFit_3,8,11,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 174 | FirstFit_3,8,12,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 175 | FirstFit_3,8,13,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 176 | FirstFit_3,8,14,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 177 | FirstFit_3,8,15,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 178 | FirstFit_3,8,16,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 179 | FirstFit_3,8,17,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 180 | FirstFit_3,8,18,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 181 | FirstFit_3,8,19,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 182 | FirstFit_3,9,0,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 183 | FirstFit_3,9,1,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 184 | FirstFit_3,9,2,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 185 | FirstFit_3,9,3,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 186 | FirstFit_3,9,4,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 187 | FirstFit_3,9,5,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 188 | FirstFit_3,9,6,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 189 | FirstFit_3,9,7,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 190 | FirstFit_3,9,8,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 191 | FirstFit_3,9,9,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 192 | FirstFit_3,9,10,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 193 | FirstFit_3,9,11,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 194 | FirstFit_3,9,12,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 195 | FirstFit_3,9,13,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 196 | FirstFit_3,9,14,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 197 | FirstFit_3,9,15,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 198 | FirstFit_3,9,16,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 199 | FirstFit_3,9,17,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 200 | FirstFit_3,9,18,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 201 | FirstFit_3,9,19,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 202 | -------------------------------------------------------------------------------- /results/abilene_v2/static/default/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [1000, 1000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene_v2/static/latency_experiments/medium/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [10, 15], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene_v2/static/latency_experiments/relaxed/firstfit.csv: -------------------------------------------------------------------------------- 1 | agent,trial,episode,reward,acceptance_rate,mean_cpu_utilization,mean_memory_utilization,mean_bandwidth_utilization,mean_operating_servers 2 | FirstFit_3,0,0,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 3 | FirstFit_3,0,1,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 4 | FirstFit_3,0,2,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 5 | FirstFit_3,0,3,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 6 | FirstFit_3,0,4,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 7 | FirstFit_3,0,5,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 8 | FirstFit_3,0,6,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 9 | FirstFit_3,0,7,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 10 | FirstFit_3,0,8,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 11 | FirstFit_3,0,9,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 12 | FirstFit_3,0,10,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 13 | FirstFit_3,0,11,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 14 | FirstFit_3,0,12,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 15 | FirstFit_3,0,13,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 16 | FirstFit_3,0,14,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 17 | FirstFit_3,0,15,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 18 | FirstFit_3,0,16,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 19 | FirstFit_3,0,17,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 20 | FirstFit_3,0,18,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 21 | FirstFit_3,0,19,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 22 | FirstFit_3,1,0,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 23 | FirstFit_3,1,1,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 24 | FirstFit_3,1,2,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 25 | FirstFit_3,1,3,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 26 | FirstFit_3,1,4,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 27 | FirstFit_3,1,5,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 28 | FirstFit_3,1,6,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 29 | FirstFit_3,1,7,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 30 | FirstFit_3,1,8,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 31 | FirstFit_3,1,9,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 32 | FirstFit_3,1,10,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 33 | FirstFit_3,1,11,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 34 | FirstFit_3,1,12,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 35 | FirstFit_3,1,13,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 36 | FirstFit_3,1,14,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 37 | FirstFit_3,1,15,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 38 | FirstFit_3,1,16,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 39 | FirstFit_3,1,17,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 40 | FirstFit_3,1,18,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 41 | FirstFit_3,1,19,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 42 | FirstFit_3,2,0,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 43 | FirstFit_3,2,1,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 44 | FirstFit_3,2,2,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 45 | FirstFit_3,2,3,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 46 | FirstFit_3,2,4,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 47 | FirstFit_3,2,5,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 48 | FirstFit_3,2,6,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 49 | FirstFit_3,2,7,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 50 | FirstFit_3,2,8,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 51 | FirstFit_3,2,9,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 52 | FirstFit_3,2,10,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 53 | FirstFit_3,2,11,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 54 | FirstFit_3,2,12,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 55 | FirstFit_3,2,13,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 56 | FirstFit_3,2,14,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 57 | FirstFit_3,2,15,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 58 | FirstFit_3,2,16,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 59 | FirstFit_3,2,17,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 60 | FirstFit_3,2,18,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 61 | FirstFit_3,2,19,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 62 | FirstFit_3,3,0,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 63 | FirstFit_3,3,1,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 64 | FirstFit_3,3,2,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 65 | FirstFit_3,3,3,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 66 | FirstFit_3,3,4,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 67 | FirstFit_3,3,5,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 68 | FirstFit_3,3,6,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 69 | FirstFit_3,3,7,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 70 | FirstFit_3,3,8,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 71 | FirstFit_3,3,9,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 72 | FirstFit_3,3,10,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 73 | FirstFit_3,3,11,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 74 | FirstFit_3,3,12,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 75 | FirstFit_3,3,13,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 76 | FirstFit_3,3,14,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 77 | FirstFit_3,3,15,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 78 | FirstFit_3,3,16,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 79 | FirstFit_3,3,17,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 80 | FirstFit_3,3,18,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 81 | FirstFit_3,3,19,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 82 | FirstFit_3,4,0,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 83 | FirstFit_3,4,1,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 84 | FirstFit_3,4,2,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 85 | FirstFit_3,4,3,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 86 | FirstFit_3,4,4,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 87 | FirstFit_3,4,5,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 88 | FirstFit_3,4,6,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 89 | FirstFit_3,4,7,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 90 | FirstFit_3,4,8,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 91 | FirstFit_3,4,9,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 92 | FirstFit_3,4,10,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 93 | FirstFit_3,4,11,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 94 | FirstFit_3,4,12,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 95 | FirstFit_3,4,13,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 96 | FirstFit_3,4,14,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 97 | FirstFit_3,4,15,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 98 | FirstFit_3,4,16,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 99 | FirstFit_3,4,17,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 100 | FirstFit_3,4,18,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 101 | FirstFit_3,4,19,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 102 | FirstFit_3,5,0,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 103 | FirstFit_3,5,1,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 104 | FirstFit_3,5,2,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 105 | FirstFit_3,5,3,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 106 | FirstFit_3,5,4,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 107 | FirstFit_3,5,5,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 108 | FirstFit_3,5,6,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 109 | FirstFit_3,5,7,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 110 | FirstFit_3,5,8,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 111 | FirstFit_3,5,9,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 112 | FirstFit_3,5,10,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 113 | FirstFit_3,5,11,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 114 | FirstFit_3,5,12,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 115 | FirstFit_3,5,13,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 116 | FirstFit_3,5,14,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 117 | FirstFit_3,5,15,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 118 | FirstFit_3,5,16,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 119 | FirstFit_3,5,17,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 120 | FirstFit_3,5,18,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 121 | FirstFit_3,5,19,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 122 | FirstFit_3,6,0,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 123 | FirstFit_3,6,1,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 124 | FirstFit_3,6,2,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 125 | FirstFit_3,6,3,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 126 | FirstFit_3,6,4,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 127 | FirstFit_3,6,5,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 128 | FirstFit_3,6,6,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 129 | FirstFit_3,6,7,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 130 | FirstFit_3,6,8,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 131 | FirstFit_3,6,9,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 132 | FirstFit_3,6,10,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 133 | FirstFit_3,6,11,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 134 | FirstFit_3,6,12,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 135 | FirstFit_3,6,13,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 136 | FirstFit_3,6,14,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 137 | FirstFit_3,6,15,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 138 | FirstFit_3,6,16,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 139 | FirstFit_3,6,17,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 140 | FirstFit_3,6,18,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 141 | FirstFit_3,6,19,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 142 | FirstFit_3,7,0,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 143 | FirstFit_3,7,1,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 144 | FirstFit_3,7,2,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 145 | FirstFit_3,7,3,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 146 | FirstFit_3,7,4,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 147 | FirstFit_3,7,5,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 148 | FirstFit_3,7,6,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 149 | FirstFit_3,7,7,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 150 | FirstFit_3,7,8,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 151 | FirstFit_3,7,9,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 152 | FirstFit_3,7,10,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 153 | FirstFit_3,7,11,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 154 | FirstFit_3,7,12,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 155 | FirstFit_3,7,13,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 156 | FirstFit_3,7,14,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 157 | FirstFit_3,7,15,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 158 | FirstFit_3,7,16,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 159 | FirstFit_3,7,17,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 160 | FirstFit_3,7,18,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 161 | FirstFit_3,7,19,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 162 | FirstFit_3,8,0,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 163 | FirstFit_3,8,1,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 164 | FirstFit_3,8,2,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 165 | FirstFit_3,8,3,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 166 | FirstFit_3,8,4,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 167 | FirstFit_3,8,5,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 168 | FirstFit_3,8,6,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 169 | FirstFit_3,8,7,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 170 | FirstFit_3,8,8,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 171 | FirstFit_3,8,9,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 172 | FirstFit_3,8,10,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 173 | FirstFit_3,8,11,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 174 | FirstFit_3,8,12,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 175 | FirstFit_3,8,13,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 176 | FirstFit_3,8,14,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 177 | FirstFit_3,8,15,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 178 | FirstFit_3,8,16,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 179 | FirstFit_3,8,17,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 180 | FirstFit_3,8,18,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 181 | FirstFit_3,8,19,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 182 | FirstFit_3,9,0,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 183 | FirstFit_3,9,1,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 184 | FirstFit_3,9,2,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 185 | FirstFit_3,9,3,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 186 | FirstFit_3,9,4,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 187 | FirstFit_3,9,5,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 188 | FirstFit_3,9,6,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 189 | FirstFit_3,9,7,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 190 | FirstFit_3,9,8,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 191 | FirstFit_3,9,9,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 192 | FirstFit_3,9,10,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 193 | FirstFit_3,9,11,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 194 | FirstFit_3,9,12,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 195 | FirstFit_3,9,13,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 196 | FirstFit_3,9,14,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 197 | FirstFit_3,9,15,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 198 | FirstFit_3,9,16,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 199 | FirstFit_3,9,17,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 200 | FirstFit_3,9,18,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 201 | FirstFit_3,9,19,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 202 | -------------------------------------------------------------------------------- /results/abilene_v2/static/latency_experiments/relaxed/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [1000, 1000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene_v2/static/latency_experiments/tight/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [4, 7], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | -------------------------------------------------------------------------------- /results/abilene_v2/static/load_experiments/high_load/firstfit.csv: -------------------------------------------------------------------------------- 1 | agent,trial,episode,reward,acceptance_rate,mean_cpu_utilization,mean_memory_utilization,mean_bandwidth_utilization,mean_operating_servers 2 | FirstFit_3,0,0,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 3 | FirstFit_3,0,1,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 4 | FirstFit_3,0,2,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 5 | FirstFit_3,0,3,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 6 | FirstFit_3,0,4,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 7 | FirstFit_3,0,5,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 8 | FirstFit_3,0,6,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 9 | FirstFit_3,0,7,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 10 | FirstFit_3,0,8,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 11 | FirstFit_3,0,9,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 12 | FirstFit_3,0,10,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 13 | FirstFit_3,0,11,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 14 | FirstFit_3,0,12,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 15 | FirstFit_3,0,13,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 16 | FirstFit_3,0,14,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 17 | FirstFit_3,0,15,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 18 | FirstFit_3,0,16,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 19 | FirstFit_3,0,17,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 20 | FirstFit_3,0,18,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 21 | FirstFit_3,0,19,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 22 | FirstFit_3,1,0,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 23 | FirstFit_3,1,1,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 24 | FirstFit_3,1,2,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 25 | FirstFit_3,1,3,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 26 | FirstFit_3,1,4,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 27 | FirstFit_3,1,5,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 28 | FirstFit_3,1,6,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 29 | FirstFit_3,1,7,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 30 | FirstFit_3,1,8,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 31 | FirstFit_3,1,9,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 32 | FirstFit_3,1,10,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 33 | FirstFit_3,1,11,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 34 | FirstFit_3,1,12,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 35 | FirstFit_3,1,13,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 36 | FirstFit_3,1,14,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 37 | FirstFit_3,1,15,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 38 | FirstFit_3,1,16,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 39 | FirstFit_3,1,17,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 40 | FirstFit_3,1,18,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 41 | FirstFit_3,1,19,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 42 | FirstFit_3,2,0,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 43 | FirstFit_3,2,1,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 44 | FirstFit_3,2,2,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 45 | FirstFit_3,2,3,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 46 | FirstFit_3,2,4,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 47 | FirstFit_3,2,5,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 48 | FirstFit_3,2,6,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 49 | FirstFit_3,2,7,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 50 | FirstFit_3,2,8,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 51 | FirstFit_3,2,9,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 52 | FirstFit_3,2,10,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 53 | FirstFit_3,2,11,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 54 | FirstFit_3,2,12,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 55 | FirstFit_3,2,13,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 56 | FirstFit_3,2,14,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 57 | FirstFit_3,2,15,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 58 | FirstFit_3,2,16,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 59 | FirstFit_3,2,17,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 60 | FirstFit_3,2,18,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 61 | FirstFit_3,2,19,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 62 | FirstFit_3,3,0,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 63 | FirstFit_3,3,1,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 64 | FirstFit_3,3,2,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 65 | FirstFit_3,3,3,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 66 | FirstFit_3,3,4,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 67 | FirstFit_3,3,5,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 68 | FirstFit_3,3,6,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 69 | FirstFit_3,3,7,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 70 | FirstFit_3,3,8,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 71 | FirstFit_3,3,9,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 72 | FirstFit_3,3,10,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 73 | FirstFit_3,3,11,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 74 | FirstFit_3,3,12,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 75 | FirstFit_3,3,13,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 76 | FirstFit_3,3,14,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 77 | FirstFit_3,3,15,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 78 | FirstFit_3,3,16,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 79 | FirstFit_3,3,17,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 80 | FirstFit_3,3,18,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 81 | FirstFit_3,3,19,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 82 | FirstFit_3,4,0,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 83 | FirstFit_3,4,1,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 84 | FirstFit_3,4,2,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 85 | FirstFit_3,4,3,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 86 | FirstFit_3,4,4,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 87 | FirstFit_3,4,5,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 88 | FirstFit_3,4,6,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 89 | FirstFit_3,4,7,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 90 | FirstFit_3,4,8,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 91 | FirstFit_3,4,9,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 92 | FirstFit_3,4,10,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 93 | FirstFit_3,4,11,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 94 | FirstFit_3,4,12,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 95 | FirstFit_3,4,13,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 96 | FirstFit_3,4,14,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 97 | FirstFit_3,4,15,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 98 | FirstFit_3,4,16,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 99 | FirstFit_3,4,17,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 100 | FirstFit_3,4,18,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 101 | FirstFit_3,4,19,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 102 | FirstFit_3,5,0,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 103 | FirstFit_3,5,1,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 104 | FirstFit_3,5,2,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 105 | FirstFit_3,5,3,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 106 | FirstFit_3,5,4,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 107 | FirstFit_3,5,5,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 108 | FirstFit_3,5,6,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 109 | FirstFit_3,5,7,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 110 | FirstFit_3,5,8,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 111 | FirstFit_3,5,9,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 112 | FirstFit_3,5,10,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 113 | FirstFit_3,5,11,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 114 | FirstFit_3,5,12,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 115 | FirstFit_3,5,13,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 116 | FirstFit_3,5,14,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 117 | FirstFit_3,5,15,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 118 | FirstFit_3,5,16,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 119 | FirstFit_3,5,17,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 120 | FirstFit_3,5,18,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 121 | FirstFit_3,5,19,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 122 | FirstFit_3,6,0,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 123 | FirstFit_3,6,1,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 124 | FirstFit_3,6,2,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 125 | FirstFit_3,6,3,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 126 | FirstFit_3,6,4,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 127 | FirstFit_3,6,5,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 128 | FirstFit_3,6,6,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 129 | FirstFit_3,6,7,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 130 | FirstFit_3,6,8,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 131 | FirstFit_3,6,9,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 132 | FirstFit_3,6,10,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 133 | FirstFit_3,6,11,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 134 | FirstFit_3,6,12,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 135 | FirstFit_3,6,13,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 136 | FirstFit_3,6,14,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 137 | FirstFit_3,6,15,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 138 | FirstFit_3,6,16,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 139 | FirstFit_3,6,17,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 140 | FirstFit_3,6,18,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 141 | FirstFit_3,6,19,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 142 | FirstFit_3,7,0,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 143 | FirstFit_3,7,1,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 144 | FirstFit_3,7,2,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 145 | FirstFit_3,7,3,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 146 | FirstFit_3,7,4,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 147 | FirstFit_3,7,5,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 148 | FirstFit_3,7,6,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 149 | FirstFit_3,7,7,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 150 | FirstFit_3,7,8,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 151 | FirstFit_3,7,9,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 152 | FirstFit_3,7,10,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 153 | FirstFit_3,7,11,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 154 | FirstFit_3,7,12,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 155 | FirstFit_3,7,13,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 156 | FirstFit_3,7,14,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 157 | FirstFit_3,7,15,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 158 | FirstFit_3,7,16,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 159 | FirstFit_3,7,17,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 160 | FirstFit_3,7,18,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 161 | FirstFit_3,7,19,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 162 | FirstFit_3,8,0,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 163 | FirstFit_3,8,1,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 164 | FirstFit_3,8,2,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 165 | FirstFit_3,8,3,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 166 | FirstFit_3,8,4,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 167 | FirstFit_3,8,5,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 168 | FirstFit_3,8,6,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 169 | FirstFit_3,8,7,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 170 | FirstFit_3,8,8,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 171 | FirstFit_3,8,9,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 172 | FirstFit_3,8,10,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 173 | FirstFit_3,8,11,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 174 | FirstFit_3,8,12,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 175 | FirstFit_3,8,13,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 176 | FirstFit_3,8,14,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 177 | FirstFit_3,8,15,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 178 | FirstFit_3,8,16,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 179 | FirstFit_3,8,17,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 180 | FirstFit_3,8,18,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 181 | FirstFit_3,8,19,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 182 | FirstFit_3,9,0,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 183 | FirstFit_3,9,1,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 184 | FirstFit_3,9,2,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 185 | FirstFit_3,9,3,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 186 | FirstFit_3,9,4,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 187 | FirstFit_3,9,5,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 188 | FirstFit_3,9,6,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 189 | FirstFit_3,9,7,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 190 | FirstFit_3,9,8,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 191 | FirstFit_3,9,9,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 192 | FirstFit_3,9,10,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 193 | FirstFit_3,9,11,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 194 | FirstFit_3,9,12,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 195 | FirstFit_3,9,13,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 196 | FirstFit_3,9,14,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 197 | FirstFit_3,9,15,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 198 | FirstFit_3,9,16,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 199 | FirstFit_3,9,17,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 200 | FirstFit_3,9,18,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 201 | FirstFit_3,9,19,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 202 | -------------------------------------------------------------------------------- /results/abilene_v2/static/load_experiments/high_load/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [1000, 1000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene_v2/static/load_experiments/low_load/firstfit.csv: -------------------------------------------------------------------------------- 1 | agent,trial,episode,reward,acceptance_rate,mean_cpu_utilization,mean_memory_utilization,mean_bandwidth_utilization,mean_operating_servers 2 | FirstFit_3,0,0,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 3 | FirstFit_3,0,1,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 4 | FirstFit_3,0,2,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 5 | FirstFit_3,0,3,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 6 | FirstFit_3,0,4,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 7 | FirstFit_3,0,5,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 8 | FirstFit_3,0,6,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 9 | FirstFit_3,0,7,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 10 | FirstFit_3,0,8,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 11 | FirstFit_3,0,9,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 12 | FirstFit_3,0,10,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 13 | FirstFit_3,0,11,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 14 | FirstFit_3,0,12,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 15 | FirstFit_3,0,13,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 16 | FirstFit_3,0,14,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 17 | FirstFit_3,0,15,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 18 | FirstFit_3,0,16,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 19 | FirstFit_3,0,17,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 20 | FirstFit_3,0,18,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 21 | FirstFit_3,0,19,64688.54808711586,1.0,0.021600728980139206,0.16212784788305987,0.029874379555348798,3.1933174224343674 22 | FirstFit_3,1,0,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 23 | FirstFit_3,1,1,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 24 | FirstFit_3,1,2,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 25 | FirstFit_3,1,3,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 26 | FirstFit_3,1,4,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 27 | FirstFit_3,1,5,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 28 | FirstFit_3,1,6,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 29 | FirstFit_3,1,7,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 30 | FirstFit_3,1,8,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 31 | FirstFit_3,1,9,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 32 | FirstFit_3,1,10,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 33 | FirstFit_3,1,11,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 34 | FirstFit_3,1,12,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 35 | FirstFit_3,1,13,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 36 | FirstFit_3,1,14,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 37 | FirstFit_3,1,15,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 38 | FirstFit_3,1,16,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 39 | FirstFit_3,1,17,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 40 | FirstFit_3,1,18,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 41 | FirstFit_3,1,19,110144.54703304787,1.0,0.0310259518215328,0.13748501245872943,0.031630705725274766,3.430167597765363 42 | FirstFit_3,2,0,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 43 | FirstFit_3,2,1,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 44 | FirstFit_3,2,2,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 45 | FirstFit_3,2,3,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 46 | FirstFit_3,2,4,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 47 | FirstFit_3,2,5,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 48 | FirstFit_3,2,6,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 49 | FirstFit_3,2,7,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 50 | FirstFit_3,2,8,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 51 | FirstFit_3,2,9,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 52 | FirstFit_3,2,10,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 53 | FirstFit_3,2,11,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 54 | FirstFit_3,2,12,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 55 | FirstFit_3,2,13,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 56 | FirstFit_3,2,14,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 57 | FirstFit_3,2,15,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 58 | FirstFit_3,2,16,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 59 | FirstFit_3,2,17,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 60 | FirstFit_3,2,18,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 61 | FirstFit_3,2,19,29023.571191341834,1.0,0.02725403353369189,0.10118856543202542,0.014736466006121487,2.0826446280991737 62 | FirstFit_3,3,0,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 63 | FirstFit_3,3,1,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 64 | FirstFit_3,3,2,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 65 | FirstFit_3,3,3,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 66 | FirstFit_3,3,4,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 67 | FirstFit_3,3,5,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 68 | FirstFit_3,3,6,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 69 | FirstFit_3,3,7,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 70 | FirstFit_3,3,8,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 71 | FirstFit_3,3,9,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 72 | FirstFit_3,3,10,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 73 | FirstFit_3,3,11,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 74 | FirstFit_3,3,12,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 75 | FirstFit_3,3,13,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 76 | FirstFit_3,3,14,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 77 | FirstFit_3,3,15,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 78 | FirstFit_3,3,16,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 79 | FirstFit_3,3,17,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 80 | FirstFit_3,3,18,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 81 | FirstFit_3,3,19,219181.3997700741,1.0,0.06004629485231547,0.3334367965513707,0.07955815919036427,6.382456140350877 82 | FirstFit_3,4,0,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 83 | FirstFit_3,4,1,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 84 | FirstFit_3,4,2,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 85 | FirstFit_3,4,3,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 86 | FirstFit_3,4,4,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 87 | FirstFit_3,4,5,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 88 | FirstFit_3,4,6,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 89 | FirstFit_3,4,7,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 90 | FirstFit_3,4,8,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 91 | FirstFit_3,4,9,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 92 | FirstFit_3,4,10,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 93 | FirstFit_3,4,11,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 94 | FirstFit_3,4,12,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 95 | FirstFit_3,4,13,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 96 | FirstFit_3,4,14,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 97 | FirstFit_3,4,15,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 98 | FirstFit_3,4,16,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 99 | FirstFit_3,4,17,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 100 | FirstFit_3,4,18,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 101 | FirstFit_3,4,19,68189.6488506841,1.0,0.03123782145624436,0.16038086322995923,0.03356777571215851,3.5342960288808665 102 | FirstFit_3,5,0,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 103 | FirstFit_3,5,1,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 104 | FirstFit_3,5,2,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 105 | FirstFit_3,5,3,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 106 | FirstFit_3,5,4,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 107 | FirstFit_3,5,5,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 108 | FirstFit_3,5,6,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 109 | FirstFit_3,5,7,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 110 | FirstFit_3,5,8,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 111 | FirstFit_3,5,9,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 112 | FirstFit_3,5,10,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 113 | FirstFit_3,5,11,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 114 | FirstFit_3,5,12,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 115 | FirstFit_3,5,13,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 116 | FirstFit_3,5,14,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 117 | FirstFit_3,5,15,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 118 | FirstFit_3,5,16,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 119 | FirstFit_3,5,17,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 120 | FirstFit_3,5,18,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 121 | FirstFit_3,5,19,475334.08850472345,0.7531645569620253,0.13513745382012773,0.7711590574484447,0.2670698328608895,10.704016913319238 122 | FirstFit_3,6,0,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 123 | FirstFit_3,6,1,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 124 | FirstFit_3,6,2,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 125 | FirstFit_3,6,3,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 126 | FirstFit_3,6,4,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 127 | FirstFit_3,6,5,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 128 | FirstFit_3,6,6,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 129 | FirstFit_3,6,7,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 130 | FirstFit_3,6,8,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 131 | FirstFit_3,6,9,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 132 | FirstFit_3,6,10,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 133 | FirstFit_3,6,11,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 134 | FirstFit_3,6,12,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 135 | FirstFit_3,6,13,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 136 | FirstFit_3,6,14,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 137 | FirstFit_3,6,15,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 138 | FirstFit_3,6,16,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 139 | FirstFit_3,6,17,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 140 | FirstFit_3,6,18,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 141 | FirstFit_3,6,19,427083.906845606,0.9615384615384616,0.11177148519274918,0.635123088722678,0.17416909695472918,9.872047244094489 142 | FirstFit_3,7,0,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 143 | FirstFit_3,7,1,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 144 | FirstFit_3,7,2,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 145 | FirstFit_3,7,3,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 146 | FirstFit_3,7,4,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 147 | FirstFit_3,7,5,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 148 | FirstFit_3,7,6,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 149 | FirstFit_3,7,7,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 150 | FirstFit_3,7,8,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 151 | FirstFit_3,7,9,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 152 | FirstFit_3,7,10,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 153 | FirstFit_3,7,11,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 154 | FirstFit_3,7,12,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 155 | FirstFit_3,7,13,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 156 | FirstFit_3,7,14,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 157 | FirstFit_3,7,15,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 158 | FirstFit_3,7,16,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 159 | FirstFit_3,7,17,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 160 | FirstFit_3,7,18,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 161 | FirstFit_3,7,19,218669.70712700227,1.0,0.057464254562012096,0.4405086996514528,0.09580645672801749,7.53314121037464 162 | FirstFit_3,8,0,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 163 | FirstFit_3,8,1,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 164 | FirstFit_3,8,2,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 165 | FirstFit_3,8,3,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 166 | FirstFit_3,8,4,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 167 | FirstFit_3,8,5,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 168 | FirstFit_3,8,6,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 169 | FirstFit_3,8,7,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 170 | FirstFit_3,8,8,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 171 | FirstFit_3,8,9,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 172 | FirstFit_3,8,10,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 173 | FirstFit_3,8,11,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 174 | FirstFit_3,8,12,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 175 | FirstFit_3,8,13,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 176 | FirstFit_3,8,14,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 177 | FirstFit_3,8,15,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 178 | FirstFit_3,8,16,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 179 | FirstFit_3,8,17,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 180 | FirstFit_3,8,18,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 181 | FirstFit_3,8,19,180249.956284223,1.0,0.08161531603480364,0.3788739624636294,0.07899575744976305,6.414634146341464 182 | FirstFit_3,9,0,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 183 | FirstFit_3,9,1,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 184 | FirstFit_3,9,2,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 185 | FirstFit_3,9,3,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 186 | FirstFit_3,9,4,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 187 | FirstFit_3,9,5,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 188 | FirstFit_3,9,6,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 189 | FirstFit_3,9,7,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 190 | FirstFit_3,9,8,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 191 | FirstFit_3,9,9,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 192 | FirstFit_3,9,10,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 193 | FirstFit_3,9,11,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 194 | FirstFit_3,9,12,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 195 | FirstFit_3,9,13,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 196 | FirstFit_3,9,14,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 197 | FirstFit_3,9,15,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 198 | FirstFit_3,9,16,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 199 | FirstFit_3,9,17,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 200 | FirstFit_3,9,18,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 201 | FirstFit_3,9,19,205935.3633983695,0.9925925925925926,0.1075137353467866,0.5339364236809243,0.13464853782995082,8.983981693363845 202 | -------------------------------------------------------------------------------- /results/abilene_v2/static/load_experiments/low_load/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [1000, 1000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /results/abilene_v2/static/load_experiments/medium_load/requests.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "poisson_arrival_uniform_load", 3 | "static": true, 4 | "num_timeslots": [6000, 6000], 5 | "num_requests": [20, 200], 6 | "service_rate": [100, 1000], 7 | "num_vnfs": 6, 8 | "sfc_length": [1, 6], 9 | "bandwidth": [20, 100], 10 | "max_response_latency": [1000, 1000], 11 | "cpus": [1, 20], 12 | "memory": [5.0, 10.0], 13 | "vnf_delays": [0, 0] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /script.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | import logging 4 | import sys 5 | import pandas as pd 6 | from pathlib import Path 7 | from stable_baselines3.common.env_checker import check_env 8 | from stable_baselines3 import A2C, PPO, DQN 9 | from evaluation import evaluate_final_policy, safe_experiment 10 | from nfvdeep.environment.arrival import StochasticProcess 11 | from nfvdeep.environment.env import Env 12 | from nfvdeep.environment.arrival import * 13 | from nfvdeep.agent.baselines import * 14 | from nfvdeep.agent.logging import MetricLoggingCallback, NFVDeepMonitor 15 | 16 | 17 | if __name__ == '__main__': 18 | parser = argparse.ArgumentParser() 19 | 20 | # arguments to specify parameters of the experiment evaluation 21 | parser.add_argument('--total_train_timesteps', type=int, nargs='?', 22 | const=1, default=1000000, help='Number of training steps for the agent') 23 | parser.add_argument('--debug', action='store_false', 24 | help='Whether to enable debugging logs of the environment') 25 | parser.add_argument('--overlay', type=str, 26 | help='Path to overlay graph for the environment') 27 | parser.add_argument('--requests', type=str, 28 | help='Either path to request file or config of stochastic arrival process') 29 | parser.add_argument('--agent', type=str, 30 | help='Whether to use a RL agent or a baseline') 31 | parser.add_argument('--logs', type=str, nargs='?', const=1, 32 | default=r'./logs', help='Path of tensorboard logs') 33 | 34 | # arguments to specify the final policy's evaluation 35 | parser.add_argument('--eval_episodes', type=int, 36 | default=20, help='Number of evaluation steps for one trained agent') 37 | parser.add_argument('--trials', type=int, default=10, 38 | help='Number of trials evaluating the agent') 39 | parser.add_argument('--output', type=str, required=True, 40 | help='Path to the folder where all results will be stored at') 41 | 42 | args = parser.parse_args() 43 | 44 | # set logging level according to --debug 45 | logging.basicConfig() 46 | debug_level = logging.INFO if args.debug else logging.DEBUG 47 | logging.getLogger().setLevel(debug_level) 48 | 49 | # Create log dir & monitor training so that episode rewards are logged 50 | os.makedirs(args.logs, exist_ok=True) 51 | agent_name = args.agent 52 | 53 | # Create agent from experiment configuration 54 | if agent_name == 'Random': 55 | agent_type = BaselineHeuristic 56 | policy = RandomPolicy 57 | 58 | elif agent_name == 'FirstFit_1': 59 | agent_type = BaselineHeuristic 60 | policy = FirstFitPolicy 61 | 62 | elif agent_name == 'FirstFit_2': 63 | agent_type = BaselineHeuristic 64 | policy = FirstFitPolicy2 65 | 66 | elif agent_name == 'FirstFit_3': 67 | agent_type = BaselineHeuristic 68 | policy = FirstFitPolicy3 69 | 70 | elif agent_name == 'FirstFit_4': 71 | agent_type = BaselineHeuristic 72 | policy = FirstFitPolicy4 73 | 74 | elif agent_name == 'A2C': 75 | agent_type = A2C 76 | policy = 'MlpPolicy' 77 | 78 | elif agent_name == 'PPO': 79 | agent_type = PPO 80 | policy = 'MlpPolicy' 81 | 82 | elif agent_name == 'DQN': 83 | agent_type = DQN 84 | policy = 'MlpPolicy' 85 | 86 | else: 87 | raise ValueError('An unknown agent was specified') 88 | 89 | # load the arrival processe's properties 90 | with open(Path(args.requests), 'r') as file: 91 | arrival_config = json.load(file) 92 | 93 | results = dict() 94 | for trial in range(args.trials): 95 | # create the network's overlay structure & incoming requests for the environment 96 | arrival_config['seed'] = trial 97 | env = Env(args.overlay, arrival_config) 98 | env = NFVDeepMonitor(env, args.logs) 99 | 100 | callback = MetricLoggingCallback() 101 | agent = agent_type(**{'policy': policy, 'env': env, 102 | 'verbose': 1, 'tensorboard_log': args.logs}) 103 | 104 | tb_log_name = agent.__class__.__name__ if isinstance( 105 | policy, str) else policy.__name__ 106 | 107 | #if policy == 'MlpPolicy': 108 | # solely MLP policies require traning 109 | agent.learn(total_timesteps=args.total_train_timesteps, 110 | tb_log_name=tb_log_name, callback=callback) 111 | 112 | # evaluate final policy and log performances 113 | results[trial] = evaluate_final_policy(args.eval_episodes, agent, env) 114 | 115 | # save experiments to disk at specified output path 116 | safe_experiment(results, vars(args)) 117 | -------------------------------------------------------------------------------- /tests/network_requirements.txt: -------------------------------------------------------------------------------- 1 | _libgcc_mutex=0.1=main 2 | astroid=2.4.2=py38_0 3 | attrs=19.3.0=py_0 4 | autopep8=1.5.3=py_0 5 | backcall=0.2.0=py_0 6 | blas=1.0=mkl 7 | bleach=3.1.5=py_0 8 | brotlipy=0.7.0=py38h7b6447c_1000 9 | ca-certificates=2020.6.24=0 10 | certifi=2020.6.20=py38_0 11 | cffi=1.14.0=py38he30daa8_1 12 | chardet=3.0.4=py38_1003 13 | cloudpickle 14 | cryptography=2.9.2=py38h1ba5d50_0 15 | cycler=0.10.0=py38_0 16 | dbus=1.13.16=hb2f20db_0 17 | decorator=4.4.2=py_0 18 | defusedxml=0.6.0=py_0 19 | entrypoints=0.3=py38_0 20 | expat=2.2.9=he6710b0_2 21 | fontconfig=2.13.0=h9420a91_0 22 | freetype=2.10.2=h5ab3b9f_0 23 | future 24 | glib=2.65.0=h3eb4bd4_0 25 | gst-plugins-base=1.14.0=hbbd80ab_1 26 | gstreamer=1.14.0=hb31296c_0 27 | gym 28 | icu=58.2=he6710b0_3 29 | idna=2.10=py_0 30 | importlib-metadata=1.7.0=py38_0 31 | importlib_metadata=1.7.0=0 32 | intel-openmp=2020.1=217 33 | ipykernel=5.3.0=py38h5ca1d4c_0 34 | ipython=7.16.1=py38h5ca1d4c_0 35 | ipython_genutils=0.2.0=py38_0 36 | isort=4.3.21=py38_0 37 | jedi=0.17.1=py38_0 38 | jinja2=2.11.2=py_0 39 | jpeg=9b=h024ee3a_2 40 | json5=0.9.5=py_0 41 | jsonschema=3.2.0=py38_0 42 | jupyter_client=6.1.5=py_0 43 | jupyter_core=4.6.3=py38_0 44 | jupyterlab=2.1.5=py_0 45 | jupyterlab_server=1.2.0=py_0 46 | kiwisolver=1.2.0=py38hfd86e86_0 47 | lazy-object-proxy=1.4.3=py38h7b6447c_0 48 | ld_impl_linux-64=2.33.1=h53a641e_7 49 | libedit=3.1.20191231=h7b6447c_0 50 | libffi=3.3=he6710b0_2 51 | libgcc-ng=9.1.0=hdf63c60_0 52 | libgfortran-ng=7.3.0=hdf63c60_0 53 | libpng=1.6.37=hbc83047_0 54 | libsodium=1.0.18=h7b6447c_0 55 | libstdcxx-ng=9.1.0=hdf63c60_0 56 | libuuid=1.0.3=h1bed415_2 57 | libxcb=1.14=h7b6447c_0 58 | libxml2=2.9.10=he19cac6_1 59 | markupsafe=1.1.1=py38h7b6447c_0 60 | matplotlib=3.2.2=0 61 | matplotlib-base=3.2.2=py38hef1b27d_0 62 | mccabe=0.6.1=py38_1 63 | mistune=0.8.4=py38h7b6447c_1000 64 | mkl=2020.1=217 65 | mkl-service=2.3.0=py38he904b0f_0 66 | mkl_fft=1.1.0=py38h23d657b_0 67 | mkl_random=1.1.1=py38h0573a6f_0 68 | more-itertools=8.4.0=py_0 69 | nbconvert=5.6.1=py38_0 70 | nbformat=5.0.7=py_0 71 | ncurses=6.2=he6710b0_1 72 | networkx=2.4=py_1 73 | notebook=6.0.3=py38_0 74 | numpy=1.18.5=py38ha1c710e_0 75 | numpy-base=1.18.5=py38hde5b4d6_0 76 | openssl=1.1.1g=h7b6447c_0 77 | packaging=20.4=py_0 78 | pandas=1.0.5=py38h0573a6f_0 79 | pandoc=2.9.2.1=0 80 | pandocfilters=1.4.2=py38_1 81 | parso=0.7.0=py_0 82 | pcre=8.44=he6710b0_0 83 | pexpect=4.8.0=py38_0 84 | pickleshare=0.7.5=py38_1000 85 | pip=20.1.1=py38_1 86 | pluggy=0.13.1=py38_0 87 | prometheus_client=0.8.0=py_0 88 | prompt-toolkit=3.0.5=py_0 89 | ptyprocess=0.6.0=py38_0 90 | py=1.9.0=py_0 91 | pycodestyle=2.6.0=py_0 92 | pycparser=2.20=py_2 93 | pyglet 94 | pygments=2.6.1=py_0 95 | pylint=2.5.3=py38_0 96 | pyopenssl=19.1.0=py_1 97 | pyparsing=2.4.7=py_0 98 | pyqt=5.9.2=py38h05f1152_4 99 | pyrsistent=0.16.0=py38h7b6447c_0 100 | pysocks=1.7.1=py38_0 101 | pytest=5.4.3=py38_0 102 | python=3.8.3=hcff3b4d_2 103 | python-dateutil=2.8.1=py_0 104 | pytz=2020.1=py_0 105 | pyzmq=19.0.1=py38he6710b0_1 106 | qt=5.9.7=h5867ecd_1 107 | readline=8.0=h7b6447c_0 108 | requests=2.24.0=py_0 109 | scipy=1.5.0=py38h0b6359f_0 110 | seaborn=0.10.1=py_0 111 | send2trash=1.5.0=py38_0 112 | setuptools=47.3.1=py38_0 113 | sip=4.19.13=py38he6710b0_0 114 | six=1.15.0=py_0 115 | sqlite=3.32.3=h62c20be_0 116 | tabulate 117 | terminado=0.8.3=py38_0 118 | testpath=0.4.4=py_0 119 | tk=8.6.10=hbc83047_0 120 | toml=0.10.1=py_0 121 | tornado=6.0.4=py38h7b6447c_1 122 | traitlets=4.3.3=py38_0 123 | urllib3=1.25.9=py_0 124 | wcwidth=0.2.5=py_0 125 | webencodings=0.5.1=py38_1 126 | wheel=0.34.2=py38_0 127 | wrapt=1.11.2=py38h7b6447c_0 128 | xz=5.2.5=h7b6447c_0 129 | zeromq=4.3.2=he6710b0_2 130 | zipp=3.1.0=py_0 131 | zlib=1.2.11=h7b6447c_3 -------------------------------------------------------------------------------- /tests/test_env.py: -------------------------------------------------------------------------------- 1 | from nfvdeep.environment.network import Network 2 | from nfvdeep.environment.sfv import ServiceFunctionChain 3 | from nfvdeep.environment.env import Env 4 | from nfvdeep.environment.arrival import ArrivalProcess 5 | import networkx as nx 6 | 7 | 8 | def test_network(): 9 | '''test if the network works with a cycle graph''' 10 | G = nx.Graph() 11 | G.add_node(0, cpu=3, memory=10.0, bandwidth=20.0) 12 | G.add_node(1, cpu=3, memory=30.0, bandwidth=20.0) 13 | G.add_node(2, cpu=4, memory=10.0, bandwidth=20.0) 14 | G.add_node(3, cpu=4, memory=30.0, bandwidth=20.0) 15 | G.add_node(4, cpu=8, memory=50.0, bandwidth=1.0) 16 | G.add_node(5, cpu=8, memory=5.0, bandwidth=30.0) 17 | G.add_node(6, cpu=2, memory=50.0, bandwidth=30.0) 18 | 19 | G.add_edge(0, 1, latency=50.0) 20 | G.add_edge(1, 2, latency=1.0) 21 | G.add_edge(2, 3, latency=1.0) 22 | G.add_edge(3, 4, latency=1.0) 23 | G.add_edge(4, 5, latency=1.0) 24 | G.add_edge(5, 6, latency=50.0) 25 | G.add_edge(6, 0, latency=1.0) 26 | 27 | network = Network(G) 28 | resources = network.calculate_resources() 29 | assert resources[0] == {'cpu': 3, 'memory': 10.0, 'bandwidth': 20.0} 30 | assert resources[5] == {'cpu': 8, 'memory': 5.0, 'bandwidth': 30.0} 31 | 32 | assert not network.check_vnf_resources((2, 50.0), 20.0, 0) 33 | assert not network.check_vnf_resources((6, 30.0), 20.0, 6) 34 | #assert not network.check_vnf_resources((1, 1.0), 50.0, 6) 35 | assert not network.check_vnf_resources((60, 300.0), 200.0) 36 | 37 | # ServiceFunctionChain(arrivaltime, ttl, bandwidth, latency, vnfs, processing_delays) 38 | sfc1 = ServiceFunctionChain(0, 3, 20, 3, [(2, 30.0), (2, 30.0)], [1, 0]) 39 | 40 | # check if resources gets updated properly 41 | assert network.check_embeddable(sfc1) 42 | assert not network.embed_vnf(sfc1, (2, 30.0), 0) 43 | assert network.embed_vnf(sfc1, (2, 30.0), 1) 44 | assert not network.embed_vnf(sfc1, (2, 30.0), 1) 45 | assert network.embed_vnf(sfc1, (2, 30.0), 3) 46 | 47 | assert network.calculate_current_latency(sfc1) == 3 48 | 49 | resources = network.calculate_resources() 50 | assert resources[1] == {'cpu': 1, 'memory': 0.0, 'bandwidth': 0.0} 51 | assert resources[3] == {'cpu': 2, 'memory': 0.0, 'bandwidth': 0.0} 52 | assert resources[5] == {'cpu': 8, 'memory': 5.0, 'bandwidth': 30.0} 53 | 54 | # latency should be enough 55 | assert network.check_sfc_constraints(sfc1) 56 | 57 | network.update(3) 58 | # sfc is still active - resources should not change 59 | resources = network.calculate_resources() 60 | assert resources[1] == {'cpu': 1, 'memory': 0.0, 'bandwidth': 0.0} 61 | assert resources[3] == {'cpu': 2, 'memory': 0.0, 'bandwidth': 0.0} 62 | assert resources[5] == {'cpu': 8, 'memory': 5.0, 'bandwidth': 30.0} 63 | 64 | # sfc expires - resources should be back to normal 65 | network.update() 66 | resources = network.calculate_resources() 67 | assert resources[1] == {'cpu': 3, 'memory': 30.0, 'bandwidth': 20.0} 68 | assert resources[3] == {'cpu': 4, 'memory': 30.0, 'bandwidth': 20.0} 69 | assert resources[5] == {'cpu': 8, 'memory': 5.0, 'bandwidth': 30.0} 70 | 71 | # ServiceFunctionChain(arrivaltime, ttl, bandwidth, latency, vnfs, processing_delays) 72 | sfc1 = ServiceFunctionChain(0, 3, 1, 5, [(1, 1.0), (2, 2.0)]) 73 | sfc2 = ServiceFunctionChain(0, 3, 2, 5, [(1, 1.0), (2, 2.0)], [5, 4]) 74 | 75 | assert network.embed_vnf(sfc1, (1, 1.0), 1) 76 | assert network.embed_vnf(sfc1, (2, 2.0), 5) 77 | assert network.calculate_current_latency(sfc1) == 4 78 | assert network.embed_vnf(sfc2, (1, 1.0), 5) 79 | assert network.calculate_current_latency(sfc2) == 5 80 | assert network.embed_vnf(sfc2, (2, 2.0), 6) 81 | 82 | resources = network.calculate_resources() 83 | assert resources[1] == {'cpu': 2, 'memory': 29.0, 'bandwidth': 19.0} 84 | assert resources[5] == {'cpu': 5, 'memory': 2.0, 'bandwidth': 27.0} 85 | assert resources[6] == {'cpu': 0, 'memory': 48.0, 'bandwidth': 28.0} 86 | 87 | assert network.check_sfc_constraints(sfc1) 88 | # latency is not enough for sfc2: 89 | assert network.calculate_current_latency(sfc2) == 59 90 | assert not network.check_sfc_constraints(sfc2) 91 | 92 | network.update(5) 93 | # check if bandwidth is updated corretly 94 | sfc1 = ServiceFunctionChain(0, 3, 1, 5, [(1, 1.0), (2, 2.0), (1, 1.0)]) 95 | sfc2 = ServiceFunctionChain(0, 3, 2, 5, [(1, 1.0), (1, 2.0), (2, 2.0)]) 96 | 97 | assert network.embed_vnf(sfc1, (1, 1.0), 1) 98 | assert network.embed_vnf(sfc1, (2, 2.0), 5) 99 | assert network.embed_vnf(sfc1, (1, 1.0), 5) 100 | assert network.calculate_current_latency(sfc1) == 4 101 | assert network.embed_vnf(sfc2, (1, 1.0), 1) 102 | assert network.embed_vnf(sfc2, (1, 2.0), 1) 103 | assert network.embed_vnf(sfc2, (2, 2.0), 5) 104 | 105 | resources = network.calculate_resources() 106 | assert resources[1] == {'cpu': 0, 'memory': 26.0, 'bandwidth': 17.0} 107 | assert resources[5] == {'cpu': 3, 'memory': 0.0, 'bandwidth': 27.0} 108 | -------------------------------------------------------------------------------- /tune.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | import logging 4 | import ray 5 | import json 6 | from pathlib import Path 7 | from copy import deepcopy 8 | from evaluation import evaluate_final_policy, safe_experiment 9 | from nfvdeep.environment.env import Env 10 | from nfvdeep.environment.arrival import * 11 | from nfvdeep.agent.baselines import * 12 | from nfvdeep.agent.logging import MetricLoggingCallback, NFVDeepMonitor 13 | from nfvdeep.tuning import OptimizationCallback 14 | from ax.service.ax_client import AxClient 15 | from ray.tune.suggest.ax import AxSearch 16 | from ray.tune.schedulers import ASHAScheduler 17 | from stable_baselines3.common.env_checker import check_env 18 | from stable_baselines3 import A2C, PPO, DQN 19 | from stable_baselines3.common.evaluation import evaluate_policy 20 | from stable_baselines3.common.callbacks import EveryNTimesteps 21 | 22 | 23 | if __name__ == '__main__': 24 | 25 | parser = argparse.ArgumentParser() 26 | 27 | # arguments to specify parameters of the experiment evaluation 28 | parser.add_argument('--total_train_timesteps', type=int, nargs='?', 29 | const=1, default=1000000, help='Number of training steps for the agent') 30 | parser.add_argument('--debug', action='store_false', 31 | help='Whether to enable debugging logs of the environment') 32 | parser.add_argument('--overlay', type=str, 33 | help='Path to overlay graph for the environment') 34 | parser.add_argument('--requests', type=str, 35 | help='Either path to request file or key word for stochastic arrival process') 36 | parser.add_argument('--agent', type=str, 37 | help='Whether to use a RL agent or a baseline') 38 | parser.add_argument('--logs', type=str, nargs='?', const=1, 39 | default=r'./logs', help='Path of tensorboard logs') 40 | 41 | # arguments to specify ray's hyperparameter optimization procedure 42 | parser.add_argument('--sample_timesteps', type=int, nargs='?', const=1, default=200000, 43 | help='Number of timesteps used to train intermediate configurations') 44 | parser.add_argument('--report_interval', type=int, nargs='?', const=1, default=10000, 45 | help='Interval between reportings from callback (in timesteps)') 46 | parser.add_argument('--ray_eval_episodes', type=int, nargs='?', const=1, default=1, 47 | help='Maximum number of episodes for final (deterministic) evaluation') 48 | parser.add_argument('--ray_tune_samples', type=int, nargs='?', const=1, 49 | default=128, help='Number of trials for hyperparameter optimization') 50 | parser.add_argument('--ray_cpus', type=int, nargs='?', const=1, default=16, 51 | help='Number of cpus ray tune will use for the optimization') 52 | 53 | # arguments to specify the final policy's evaluation 54 | parser.add_argument('--eval_episodes', type=int, 55 | default=20, help='Number of evaluation steps for one trained agent') 56 | parser.add_argument('--trials', type=int, default=10, 57 | help='Number of trials evaluating the agent') 58 | parser.add_argument('--output', type=str, required=True, 59 | help='Path to the folder where all results will be stored at') 60 | 61 | args = parser.parse_args() 62 | 63 | # set logging level according to --debug 64 | logging.basicConfig() 65 | debug_level = logging.INFO if args.debug else logging.DEBUG 66 | logging.getLogger().setLevel(debug_level) 67 | 68 | # Create log dir & monitor training so that episode rewards are logged 69 | os.makedirs(args.logs, exist_ok=True) 70 | 71 | # Create agent from experiment configuration 72 | if args.agent == 'Random': 73 | agent = BaselineHeuristic 74 | policy = RandomPolicy 75 | 76 | elif args.agent == 'FirstFit_1': 77 | agent = BaselineHeuristic 78 | policy = FirstFitPolicy 79 | 80 | elif args.agent == 'FirstFit_2': 81 | agent = BaselineHeuristic 82 | policy = FirstFitPolicy2 83 | 84 | elif args.agent == 'FirstFit_3': 85 | agent = BaselineHeuristic 86 | policy = FirstFitPolicy3 87 | 88 | elif args.agent == 'FirstFit_4': 89 | agent = BaselineHeuristic 90 | policy = FirstFitPolicy4 91 | 92 | elif args.agent == 'A2C': 93 | agent = A2C 94 | policy = 'MlpPolicy' 95 | 96 | elif args.agent == 'PPO': 97 | agent = PPO 98 | policy = 'MlpPolicy' 99 | 100 | elif args.agent == 'DQN': 101 | agent = DQN 102 | policy = 'MlpPolicy' 103 | 104 | else: 105 | raise ValueError('An unknown agent was specified') 106 | 107 | EVAL_EPISODES = args.ray_eval_episodes 108 | TOTAL_TIMESTEPS = args.total_train_timesteps 109 | RAY_TUNE_SAMPLES = args.ray_tune_samples 110 | 111 | # load parameter optimization space from file 112 | with open('./nfvdeep/spaces/{}_space.json'.format(args.agent), 'r') as search_space: 113 | parameters = json.load(search_space) 114 | 115 | # modifiy name for experiment generation 116 | args.agent = '(tuned) ' + args.agent 117 | results = dict() 118 | 119 | # load the arrival processe's properties 120 | with open(Path(args.requests), 'r') as file: 121 | arrival_config = json.load(file) 122 | 123 | for trial in range(args.trials): 124 | # create the network's overlay structure & incoming requests for the environment 125 | arrival_config['seed'] = trial 126 | base_env = Env(args.overlay, arrival_config) 127 | 128 | # Define objective function for hyperparameter tuning 129 | def evaluate_objective(config): 130 | tune_env = deepcopy(base_env) 131 | tune_monitor = OptimizationCallback(tune_env, EVAL_EPISODES, True) 132 | monitor_callback = EveryNTimesteps( 133 | n_steps=args.report_interval, callback=tune_monitor) 134 | 135 | tune_agent = agent("MlpPolicy", tune_env, **config) 136 | tune_agent.learn(total_timesteps=args.sample_timesteps, 137 | callback=monitor_callback) 138 | 139 | ax_client = AxClient(enforce_sequential_optimization=False) 140 | 141 | ax_client.create_experiment( 142 | name="tune_RL", 143 | parameters=parameters, 144 | objective_name='episode_reward_mean', 145 | minimize=False, 146 | overwrite_existing_experiment=True 147 | ) 148 | 149 | # add scheduling of configurations, i.e. intensify solely 150 | asha_scheduler = ASHAScheduler( 151 | time_attr='training_iteration', 152 | metric='episode_reward_mean', mode='max') 153 | 154 | ray.init(num_cpus=args.ray_cpus) 155 | ray.tune.run( 156 | evaluate_objective, 157 | num_samples=RAY_TUNE_SAMPLES, 158 | search_alg=AxSearch(ax_client), 159 | scheduler=asha_scheduler, 160 | verbose=2 161 | ) 162 | 163 | # get best parameters, retrain agent and log results for best agent 164 | best_parameters, values = ax_client.get_best_parameters() 165 | 166 | ray.shutdown() 167 | 168 | env = NFVDeepMonitor(base_env, args.logs) 169 | callback = MetricLoggingCallback() 170 | eval_agent = agent(**{'policy': policy, 'env': env, 'verbose': 1, 171 | 'tensorboard_log': args.logs, **best_parameters}) 172 | 173 | tb_log_name = eval_agent.__class__.__name__ if isinstance( 174 | policy, str) else policy.__name__ 175 | eval_agent.learn(total_timesteps=args.total_train_timesteps, 176 | tb_log_name=tb_log_name, callback=callback) 177 | 178 | # evaluate final policy and log performances 179 | results[trial] = evaluate_final_policy( 180 | args.eval_episodes, eval_agent, env) 181 | 182 | # save experiments to disk at specified output path 183 | safe_experiment(results, vars(args)) 184 | --------------------------------------------------------------------------------