{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import json\n", "\n", "import matplotlib.pyplot as plt\n", "from dataclasses import dataclass\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "this_dir = os.path.dirname(os.path.abspath(''))\n", "# results is in \"../results\"\n", "results_dir = os.path.join(this_dir, \"results\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#experiment_folder = \"casestudy_example\"\n", "experiment_folder = \"casestudy_wildfire_drone\"\n", "experiment_name = \"cs_example_edf\"\n", "\n", "experiment_file = os.path.join(results_dir, experiment_folder, experiment_name + \".json\")\n", "if not os.path.exists(experiment_file):\n", " print(\"Experiment file not found: \", experiment_file)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "with open(experiment_file) as f:\n", " experiment_data_raw = json.load(f)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of records: 12055\n", "First record: {'entry': {'operation': 'start_work', 'chain': 0, 'node': 'node_0', 'count': 500, 'next_release_us': 99890}, 'time': 0.0001}\n", "Operation types: ['wait_for_work', 'get_next_executable', 'next_deadline', 'end_work', 'start_work']\n" ] } ], "source": [ "def pre_process_data(data):\n", " for record in data:\n", " record[\"time\"] = int(record[\"time\"])\n", "\n", " min_time = min([record[\"time\"] for record in data])\n", " for record in data:\n", " record[\"time\"] -= min_time\n", " record[\"time\"] /= (1000 * 1000)\n", "\n", " if record[\"entry\"][\"operation\"] == \"next_deadline\":\n", " #print(\"Record: \", record)\n", " record[\"entry\"][\"deadline\"] = int(record[\"entry\"][\"deadline\"])\n", " record[\"entry\"][\"deadline\"] -= min_time\n", " record[\"entry\"][\"deadline\"] /= (1000 * 1000)\n", "\n", " # data = sorted(data, key=lambda x: x[\"time\"])\n", " return data\n", "\n", "experiment_data = pre_process_data(experiment_data_raw)\n", "\n", "print(\"Number of records: \", len(experiment_data))\n", "print(\"First record: \", experiment_data[0])\n", "operation_types = list(set([record[\"entry\"][\"operation\"] for record in experiment_data]))\n", "print(\"Operation types: \", operation_types)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "@dataclass\n", "class Record:\n", " start_time: float\n", " end_time: float\n", " node_name: str\n", "\n", "@dataclass\n", "class RecordLine:\n", " node_name: str\n", " count: int\n", "\n", " def __eq__(self, other):\n", " return self.node_name == other.node_name and self.count == other.count\n", "\n", " def __hash__(self):\n", " return hash((self.node_name, self.count))\n", "\n", "def get_records(data) -> list[Record]:\n", " # used to match start_work and end_work records\n", " current_records: dict[RecordLine, Record] = {}\n", " records = []\n", " for record in data:\n", " if record[\"entry\"][\"operation\"] == \"start_work\":\n", " current_record = Record(start_time=record[\"time\"], node_name=record[\"entry\"][\"node\"], end_time=None)\n", " current_record_line = RecordLine(node_name=record[\"entry\"][\"node\"], count=record[\"entry\"][\"count\"])\n", " if current_record_line in current_records:\n", " raise Exception(\"Overlapping records\")\n", " current_records[current_record_line] = current_record\n", " elif record[\"entry\"][\"operation\"] == \"end_work\":\n", " current_record_line = RecordLine(node_name=record[\"entry\"][\"node\"], count=record[\"entry\"][\"count\"])\n", " if current_record_line not in current_records:\n", " raise Exception(\"No start record\")\n", " current_record = current_records[current_record_line]\n", " current_record.end_time = record[\"time\"]\n", " records.append(current_record)\n", " del current_records[current_record_line]\n", " return records\n", "\n", "records = get_records(experiment_data)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of nodes: 4\n" ] } ], "source": [ "num_nodes = len(set([record.node_name for record in records]))\n", "print(\"Number of nodes: \", num_nodes)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "eabdbc0b05594f0bbbb97b9b63edf92e", "version_major": 2, "version_minor": 0 }, "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAJMtJREFUeJzt3XuQleV9wPHf4eKCwC5urMtuXQ2ICeAsmoIi6gjWHbu0MzJNGkiG8dJZTcU2mNiIcabAYnA1aiZ0TGwVUsUZWqVTp84kmZrVJjSTwipWGoVNJi5EiASoIqzasF727R8OZ9zKZdFz2cPz+cycYS/PeZ7nfc9h9zvvcpZclmVZAACQjCHl3gAAAKUlAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEjOs3BuoZH19fbFr164YM2ZM5HK5cm8HABiALMvijTfeiIaGhhgyJM1rYQLwY9i1a1c0NjaWexsAwEewc+fOOP3008u9jbIQgB/DmDFjIuL9J1B1dXWZdwMADERPT080Njbmv4+nSAB+DId+7FtdXS0AAaDCpPzPt9L8wTcAQMIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIE4CCWy71/G8iYgY4rxZhizFWoMaWcq1zrlfq5YL3B+1wo5XoDma9SH5vjWe9YBvNzYTA+NhSPAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABITMUEYFtbW5x33nnl3gYAQMWrmAAspF//+tfR2toa48ePj5EjR8ZZZ50Vy5Yti7fffrvcWwMAKLph5d5AOfziF7+Ivr6+eOCBB2LixInx4osvxvXXXx9vvfVW3HvvveXeHgBAURXlCuDs2bNj0aJFsXjx4qitrY1x48ZFW1tb/vM7duyIuXPnxujRo6O6ujrmzZsXe/bs6TfHXXfdFXV1dTFmzJhobW2NgwcPfmid1atXx+TJk2PEiBExadKkuP/++we0v5aWlnjooYfiiiuuiAkTJsSVV14ZX/va1+Lxxx//WMcNAFAJivYj4DVr1sSoUaOis7Mz7r777rj99tujo6Mj+vr6Yu7cubFv375Yv359dHR0xLZt22L+/Pn5+65bty7a2tqivb09Nm3aFPX19R+Ku7Vr18bSpUvjjjvuiK6urmhvb48lS5bEmjVrPtJ+Dxw4ELW1tR/rmAEAKkEuy7Ks0JPOnj073nvvvfjpT3+a/9gFF1wQf/iHfxiXX355zJkzJ7Zv3x6NjY0REbF169Y455xz4plnnonzzz8/LrroovjMZz4T3/3ud/P3v/DCC+PgwYOxefPmiIiYOHFifOMb34gvfvGL+TErVqyIH/7wh/Gf//mfx7Xfl156KaZNmxb33ntvXH/99Ucc19vbG729vfn3e3p6orGxMQ4cOBDV1dXHteZA5HLv/3m0R+jQmIGOK8WYYsxVqDGFXO9Yc5VrvULsy3qlX+/QuEp97mXZseer1MfmeNar5K9DhZir0I9N4QvlfT09PVFTU1O079+VoGhXAKdOndrv/fr6+ti7d290dXVFY2NjPv4iIqZMmRJjx46Nrq6uiIjo6uqKGTNm9Lv/zJkz82+/9dZb0d3dHa2trTF69Oj8bcWKFdHd3X1c+3zllVeipaUlPv/5zx81/iIi7rzzzqipqcnfPngMAACVomgvAhk+fHi/93O5XPT19RVk7jfffDMiIlatWvWhUBw6dOiA59m1a1dcdtllcdFFF8WDDz54zPG33XZb3Hzzzfn3D10BBACoJCV/FfDkyZNj586dsXPnzn4/At6/f39MmTIlP6azszOuvvrq/P02btyYf7uuri4aGhpi27ZtsWDBgo+0j1deeSUuu+yymDZtWjz00EMxZMixL4ZWVVVFVVXVR1oPAGCwKHkANjc3R1NTUyxYsCBWrlwZ7777btx4440xa9asmD59ekRE3HTTTXHttdfG9OnT4+KLL461a9fGli1bYsKECfl5li9fHosWLYqamppoaWmJ3t7e2LRpU7z++uv9rtIdziuvvBKzZ8+OM888M+699974n//5n/znxo0bV5wDBwAYJEoegLlcLp544on48pe/HJdeemkMGTIkWlpa4r777suPmT9/fnR3d8fixYvj4MGD8bnPfS4WLlwYTz75ZH7MddddFyeffHLcc889ccstt8SoUaOiqakpvvKVrxxzDx0dHfHSSy/FSy+9FKeffnq/zxXhNTEAAINKUV4FnIpiv4poML8abjC+UrGSX33nVcDWOzSuUp97XgVc+V+HCjGXVwFXjiT/KzgAgJSdkAHY3t7e79fDfPA2Z86ccm8PAKCsTsj/C/iGG26IefPmHfZzI0eOLPFuAAAGlxMyAGtra/23bgAAR3BC/ggYAIAjE4AAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJGVbuDXBkWVaYMYWcq9TrFXIu61lvMK9XyLnKtd6xxlb68VXiXCf6enx0rgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAVoBcrrRzFWpModc71rhDYwYyrhDrHc9cpVxvoAbr41wojq+056CQx3Y8BtvfwUI/pwbb43w8czG4CUAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxFRMALa1tcV5551X7m0AAFS8ignAQrvyyivjjDPOiBEjRkR9fX1cddVVsWvXrnJvCwCg6JINwMsuuyzWrVsXv/zlL+Nf/uVforu7O/7sz/6s3NsCACi6ogTg7NmzY9GiRbF48eKora2NcePGRVtbW/7zO3bsiLlz58bo0aOjuro65s2bF3v27Ok3x1133RV1dXUxZsyYaG1tjYMHD35ondWrV8fkyZNjxIgRMWnSpLj//vsHvMevfvWrceGFF8aZZ54ZF110UXz961+PjRs3xjvvvPORjxsAoBIU7QrgmjVrYtSoUdHZ2Rl333133H777dHR0RF9fX0xd+7c2LdvX6xfvz46Ojpi27ZtMX/+/Px9161bF21tbdHe3h6bNm2K+vr6D8Xd2rVrY+nSpXHHHXdEV1dXtLe3x5IlS2LNmjXHvdd9+/bF2rVr46KLLorhw4cfcVxvb2/09PT0uwEAVJysCGbNmpVdcskl/T52/vnnZ7feemv2ox/9KBs6dGi2Y8eO/Oe2bNmSRUT2zDPPZFmWZTNnzsxuvPHGfvefMWNGdu655+bfP+uss7J//Md/7DfmG9/4RjZz5swB73Px4sXZySefnEVEduGFF2avvvrqUccvW7Ysi4gP3Q4cODDgNT+KQj5KA5mrUGMKvd6xxh0aM5BxhVjveOYq5XoDNVgf50JxfKU9B8X5bnJsg+3vYKGfU4PtcT6euQazAwcOlOT792BWtCuAU6dO7fd+fX197N27N7q6uqKxsTEaGxvzn5syZUqMHTs2urq6IiKiq6srZsyY0e/+M2fOzL/91ltvRXd3d7S2tsbo0aPztxUrVkR3d/eA93jLLbfE888/Hz/60Y9i6NChcfXVV0eWZUccf9ttt8WBAwfyt507dw54LQCAwWJYsSb+/z9KzeVy0dfXV5C533zzzYiIWLVq1YdCcejQoQOe59RTT41TTz01PvWpT8XkyZOjsbExNm7c2C82P6iqqiqqqqo++sYBAAaBkr8KePLkybFz585+V8+2bt0a+/fvjylTpuTHdHZ29rvfxo0b82/X1dVFQ0NDbNu2LSZOnNjvNn78+I+0r0Nx2tvb+5HuDwBQKYp2BfBImpubo6mpKRYsWBArV66Md999N2688caYNWtWTJ8+PSIibrrpprj22mtj+vTpcfHFF8fatWtjy5YtMWHChPw8y5cvj0WLFkVNTU20tLREb29vbNq0KV5//fW4+eabj7qHzs7OePbZZ+OSSy6JU045Jbq7u2PJkiVx1llnHfHqHwDAiaLkVwBzuVw88cQTccopp8Sll14azc3NMWHChHjsscfyY+bPnx9LliyJxYsXx7Rp0+Lll1+OhQsX9pvnuuuui9WrV8dDDz0UTU1NMWvWrHj44YcHdAXw5JNPjscffzwuv/zy+PSnPx2tra0xderUWL9+vR/xAgAnvFx2tFc9cFQ9PT1RU1MTBw4ciOrq6qKtk8u9/1qwUs1VqDGFXi/i6OMOjRnIuEKsdzxzlXK9gRqsj7PjG5jB9ne5kMd2PAbb38FCP6cKsadi7KvSy6FU378Hs2T/JxAAgFSdkAHY3t7e79fDfPA2Z86ccm8PAKCsSv4ikFK44YYbYt68eYf93MiRI0u8GwCAweWEDMDa2tqora0t9zYAAAalE/JHwAAAHJkABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASMywcm+AY8uy0s5VqDGlXq/UeyrkXIVcb6Aq+TwMhOMr7Tko5LEdj0o9D4Px+VnouRjcXAEEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEjMsHJvgCPL5d7/M8uOPWag40oxppLXOzSuktcrxL6sV/r1CjlXOdbLsmM/l49nrqMp53PhaGML9Xe5kHOV67lXqLmOtW8+OlcAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABJTMQHY1tYW5513Xrm3AQBQ8SomAAtt3759sWDBgqiuro6xY8dGa2trvPnmm+XeFgBA0SUbgAsWLIgtW7ZER0dHfP/734//+I//iC996Uvl3hYAQNEVJQBnz54dixYtisWLF0dtbW2MGzcu2tra8p/fsWNHzJ07N0aPHh3V1dUxb9682LNnT7857rrrrqirq4sxY8ZEa2trHDx48EPrrF69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/vNs7ty5fg1MEc7za6+9lj3//PPZD37wgywiskcffTR7/vnns9/+9rclP77BpNDn+u23386uvPLK7PTTT882b97c79c59Pb2luUYB4NCn+c333wzu+2227INGzZkv/71r7NNmzZlf/7nf55VVVVlL774YlmOcbAoxteP/8+rgAt/nt94443sa1/7WrZhw4Zs+/bt2VNPPZX9wR/8QXb22WdnBw8eLMsxVhIBWAL33XdfdsYZZ2QnnXRSdsEFF2QbN27Mf27WrFnZNddc02/8unXrsk996lPZSSedlJ1zzjnZD37wg36f7+vry5YsWZLV1dVlVVVV2eWXX5798pe/LMWhDGqFPs8PPfRQFhEfui1btqwERzO4FfJcH/o1O4e7/fjHPy7REQ1OhTzPv/vd77I//dM/zRoaGrKTTjopq6+vz6688srsmWeeKdXhDGqF/vrx/wnA9xXyPP/v//5vdsUVV2S/93u/lw0fPjw788wzs+uvvz4flBxdLsuyrDzXHgEAKAf/BhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDH/Bx8t/0b+Fn1kAAAAAElFTkSuQmCC", "text/html": [ "\n", "