a49579b6b0
Signed-off-by: Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>
1324 lines
180 KiB
Plaintext
1324 lines
180 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"id": "71f85f2a-423f-44d2-b80d-da9ac8d3961a",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import simpy\n",
|
||
"import random\n",
|
||
"import numpy as np\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"import pandas as pd\n",
|
||
"from enum import Enum\n",
|
||
"import os\n",
|
||
"import shutil\n",
|
||
"from tqdm import tqdm\n",
|
||
"import math\n",
|
||
"from dataclasses import dataclass, field\n",
|
||
"from typing import List, Union, Dict\n",
|
||
"\n",
|
||
"# Constants\n",
|
||
"SEED = 42\n",
|
||
"ACCESS_COUNT_LIMIT = 1000 # Total time to run the simulation\n",
|
||
"EXPERIMENT_BASE_DIR = \"./experiments/\"\n",
|
||
"TEMP_BASE_DIR = \"./.aoi_cache/\"\n",
|
||
"BASE_FILE = pd.read_csv(\"../calculated.csv\")\n",
|
||
"BASE_FILE.index += 1\n",
|
||
"\n",
|
||
"ZIPF_CONSTANT = 2 # Shape parameter for the Zipf distribution (controls skewness) Needs to be: 1< \n",
|
||
"\n",
|
||
"# Set random seeds\n",
|
||
"random.seed(SEED)\n",
|
||
"np.random.seed(SEED)\n",
|
||
"\n",
|
||
"os.makedirs(TEMP_BASE_DIR, exist_ok=True)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"id": "d88effd8-d92b-47d1-9e15-527166073e81",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Types of cache\n",
|
||
"class EvictionStrategy(Enum):\n",
|
||
" LRU = 1\n",
|
||
" RANDOM_EVICTION = 2\n",
|
||
" TTL = 3"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"id": "1d6a3c67-f9a5-4d9c-8ade-e1ca6944867c",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"@dataclass\n",
|
||
"class DatabaseObject:\n",
|
||
" id: int\n",
|
||
" data: str\n",
|
||
" lambda_value: int\n",
|
||
" mu_value: Union[float, None]\n",
|
||
" ttl: Union[float, None]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"id": "f40af914-a6c3-4e44-b7de-b3b40a743fb2",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"@dataclass\n",
|
||
"class CacheObject:\n",
|
||
" id: int # id of object\n",
|
||
" data: DatabaseObject # body of object\n",
|
||
" initial_fetch_timer: float # time at which the object was initially pulled into the cache (object_start_time)\n",
|
||
" age_timer: float # time at which the object was last pulled into the cache (initial fetch)\n",
|
||
" last_access: float # time at which the object was last accesse\n",
|
||
" next_refresh: Union[float, None] # scheduled time for the object to be requested (for refresh cache)\n",
|
||
" next_expiry: Union[float, None] # scheduled time for the object to be evicted (for ttl cache) (ttl)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"id": "00a944e4-842b-49ba-bb36-587d9c12fdf4",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Base class for all cache types\n",
|
||
"@dataclass\n",
|
||
"class SimulationConfig:\n",
|
||
" db_objects: Union[int, List[DatabaseObject]]\n",
|
||
" cache_size: int\n",
|
||
" eviction_strategy: EvictionStrategy\n",
|
||
"\n",
|
||
" def __post_init__(self):\n",
|
||
" if not hasattr(self, 'eviction_strategy') or self.eviction_strategy is None:\n",
|
||
" raise ValueError(\"Eviction strategy must be defined in subclasses.\")\n",
|
||
" \n",
|
||
" def generate_objects(self):\n",
|
||
" if isinstance(self.db_objects, int):\n",
|
||
" self.db_objects = [\n",
|
||
" DatabaseObject(id=i, data=f\"Generated Object {i}\", lambda_value=np.random.zipf(ZIPF_CONSTANT), mu_value=None, ttl=None) \n",
|
||
" for i in range(self.db_objects)\n",
|
||
" ]\n",
|
||
"\n",
|
||
" def from_file(self, path: str, lambda_column_name: str):\n",
|
||
" df = pd.read_csv(path)\n",
|
||
" lambdas = df[lambda_column_name]\n",
|
||
"\n",
|
||
" self.db_objects = [\n",
|
||
" DatabaseObject(id=i, data=f\"Generated Object {i}\", lambda_value=lambdas[i], mu_value=None, ttl=None) \n",
|
||
" for i in range(self.db_objects)\n",
|
||
" ]\n",
|
||
" \n",
|
||
"# Specific cache type variants\n",
|
||
"@dataclass\n",
|
||
"class TTLSimulation(SimulationConfig):\n",
|
||
" eviction_strategy: EvictionStrategy = field(default=EvictionStrategy.TTL, init=False)\n",
|
||
" \n",
|
||
" def generate_objects(self, fixed_ttl):\n",
|
||
" if isinstance(self.db_objects, int):\n",
|
||
" self.db_objects = [\n",
|
||
" DatabaseObject(id=i, data=f\"Generated Object {i}\", lambda_value=np.random.zipf(ZIPF_CONSTANT), mu_value=None, ttl=fixed_ttl) \n",
|
||
" for i in range(self.db_objects)\n",
|
||
" ]\n",
|
||
" \n",
|
||
" def from_file(self, path: str, lambda_column_name: str, ttl_column_name: str):\n",
|
||
" df = pd.read_csv(path)\n",
|
||
" lambdas = df[lambda_column_name]\n",
|
||
" ttls = df[ttl_column_name]\n",
|
||
"\n",
|
||
" self.db_objects = [\n",
|
||
" DatabaseObject(id=i, data=f\"Generated Object {i}\", lambda_value=lambdas[i], mu_value=None, ttl=ttls[i]) \n",
|
||
" for i in range(self.db_objects)\n",
|
||
" ]\n",
|
||
" \n",
|
||
"@dataclass\n",
|
||
"class LRUSimulation(SimulationConfig):\n",
|
||
" eviction_strategy: EvictionStrategy = field(default=EvictionStrategy.LRU, init=False)\n",
|
||
"\n",
|
||
"@dataclass\n",
|
||
"class RandomEvictionSimulation(SimulationConfig):\n",
|
||
" eviction_strategy: EvictionStrategy = field(default=EvictionStrategy.RANDOM_EVICTION, init=False)\n",
|
||
"\n",
|
||
"@dataclass\n",
|
||
"class RefreshSimulation(TTLSimulation):\n",
|
||
" \n",
|
||
" def generate_objects(self, fixed_ttl, max_refresh_rate):\n",
|
||
" if isinstance(self.db_objects, int):\n",
|
||
" self.db_objects = [\n",
|
||
" DatabaseObject(id=i, data=f\"Generated Object {i}\", lambda_value=np.random.zipf(ZIPF_CONSTANT), mu_value=np.random.uniform(1, max_refresh_rate), ttl=fixed_ttl) \n",
|
||
" for i in range(self.db_objects)\n",
|
||
" ]\n",
|
||
" \n",
|
||
" def from_file(self, path: str, lambda_column_name: str, ttl_column_name: str, mu_column_name: str):\n",
|
||
" df = pd.read_csv(path)\n",
|
||
" lambdas = df[lambda_column_name]\n",
|
||
" ttls = df[ttl_column_name]\n",
|
||
" mus = df[mu_column_name]\n",
|
||
"\n",
|
||
" self.db_objects = [\n",
|
||
" DatabaseObject(id=i, data=f\"Generated Object {i}\", lambda_value=lambdas[i], mu_value=mus[i], ttl=ttls[i]) \n",
|
||
" for i in range(self.db_objects)\n",
|
||
" ]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "5cea042f-e9fc-4a1e-9750-de212ca70601",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"class Database:\n",
|
||
" data: Dict[int, DatabaseObject]\n",
|
||
" \n",
|
||
" def __init__(self, data: List[DatabaseObject]):\n",
|
||
" self.data = {i: data[i] for i in range(len(data))}\n",
|
||
"\n",
|
||
" def get_object(self, obj_id):\n",
|
||
" # print(f\"[{env.now:.2f}] Database: Fetched {self.data.get(obj_id, 'Unknown')} for ID {obj_id}\")\n",
|
||
" return self.data.get(obj_id, None)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "499bf543-b2c6-4e4d-afcc-0a6665ce3ae1",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"class Cache:\n",
|
||
" capacity: int\n",
|
||
" eviction_strategy: EvictionStrategy\n",
|
||
" cache_size_over_time: List[int] # To record cache state at each interval\n",
|
||
" storage: Dict[int, CacheObject]\n",
|
||
" hits: Dict[int, int] # hit counter for each object\n",
|
||
" misses: Dict[int, int] # miss counter for each object\n",
|
||
" access_count: Dict[int, int] # access counter for each object (should be hit+miss)\n",
|
||
" next_request: Dict[int, float] # scheduled time for each object to be requested\n",
|
||
" cumulative_age: Dict[int, List[float]] # list of ages of each object at the time it was requested (current time - age_timer)\n",
|
||
" cumulative_cache_time: Dict[int, List[float]] # list of total time of each object spent in cache when it was evicted (current time - initial fetch time)\n",
|
||
" request_log: Dict[int, List[float]] # list of timestamps when each object was requested\n",
|
||
" \n",
|
||
" def __init__(self, env, db, simulation_config):\n",
|
||
" self.env = env\n",
|
||
" self.db = db\n",
|
||
" self.capacity = simulation_config.cache_size\n",
|
||
" self.eviction_strategy = simulation_config.eviction_strategy\n",
|
||
" self.cache_size_over_time = []\n",
|
||
" self.storage = {}\n",
|
||
"\n",
|
||
" db_object_count = len(self.db.data)\n",
|
||
" \n",
|
||
" self.hits = {i: 0 for i in range(db_object_count)}\n",
|
||
" self.misses = {i: 0 for i in range(db_object_count)}\n",
|
||
" self.access_count = {i: 0 for i in range(db_object_count)}\n",
|
||
" self.next_request = {i: np.random.exponential(1/self.db.data[i].lambda_value) for i in range(len(self.db.data))}\n",
|
||
" self.cumulative_age = {i: [] for i in range(db_object_count)}\n",
|
||
" self.cumulative_cache_time = {i: [] for i in range(db_object_count)}\n",
|
||
" self.request_log = {i: [] for i in range(db_object_count)}\n",
|
||
"\n",
|
||
" \n",
|
||
" def get(self, obj_id):\n",
|
||
" assert len(self.storage) <= self.capacity, f\"Too many objects in cache ({len(self.storage)}).\"\n",
|
||
" # print(f\"[{self.env.now:.2f}] Requesting Object {obj_id}... (Cache Size: {len(self.storage)})\")\n",
|
||
"\n",
|
||
" # Schedule next request\n",
|
||
" next_request = self.env.now + np.random.exponential(1/self.db.data[obj_id].lambda_value)\n",
|
||
" self.request_log[obj_id].append(next_request)\n",
|
||
" self.next_request[obj_id] = next_request\n",
|
||
" self.access_count[obj_id] += 1\n",
|
||
" # print(f\"[{self.env.now:.2f}] Client: Schedule next request for {obj_id}@{next_request:.2f}\")\n",
|
||
" \n",
|
||
" if obj_id in self.storage:\n",
|
||
" # Cache hit: Refresh TTL if TTL-Cache\n",
|
||
" if self.storage[obj_id].next_expiry:\n",
|
||
" assert self.env.now <= self.storage[obj_id].next_expiry, f\"[{self.env.now:.2f}] Cache should never hit on an expired cache entry.\"\n",
|
||
" self.storage[obj_id].next_expiry = self.env.now + self.db.data[obj_id].ttl\n",
|
||
" \n",
|
||
" # Cache hit: increment hit count and update cumulative age\n",
|
||
" self.hits[obj_id] += 1\n",
|
||
" age = self.env.now - self.storage[obj_id].age_timer\n",
|
||
" self.cumulative_age[obj_id].append(age)\n",
|
||
" self.storage[obj_id].last_access = self.env.now\n",
|
||
"\n",
|
||
" assert len(self.cumulative_age[obj_id]) == self.access_count[obj_id], f\"[{self.env.now:.2f}] Age values collected and object access count do not match.\"\n",
|
||
" # print(f\"[{env.now:.2f}] {obj_id} Hit: Current Age {age:.2f} (Average: {sum(self.cumulative_age[obj_id])/len(self.cumulative_age[obj_id]):.2f}) \")\n",
|
||
" return self.storage[obj_id]\n",
|
||
" else:\n",
|
||
" # Cache miss: increment miss count\n",
|
||
" self.misses[obj_id] += 1\n",
|
||
" self.cumulative_age[obj_id].append(0)\n",
|
||
" \n",
|
||
" # Cache miss: Add TTL if TTL-Cache\n",
|
||
" # When full cache: If Non-TTL-Cache: Evict. If TTL-Cache: Don't add to Cache.\n",
|
||
" if len(self.storage) == self.capacity:\n",
|
||
" if self.eviction_strategy == EvictionStrategy.LRU:\n",
|
||
" self.evict_oldest()\n",
|
||
" elif self.eviction_strategy == EvictionStrategy.RANDOM_EVICTION:\n",
|
||
" self.evict_random()\n",
|
||
" elif self.eviction_strategy == EvictionStrategy.TTL:\n",
|
||
" # print(f\"[{self.env.now:.2f}] Cache: Capacity reached. Not accepting new request.\")\n",
|
||
" return\n",
|
||
"\n",
|
||
" # Cache miss: Construct CacheObject from Database Object\n",
|
||
" db_object = self.db.get_object(obj_id)\n",
|
||
" initial_fetch_timer=self.env.now\n",
|
||
" age_timer=self.env.now\n",
|
||
" last_access=self.env.now\n",
|
||
" next_refresh = (self.env.now + np.random.exponential(1/db_object.mu_value)) if db_object.mu_value is not None else None\n",
|
||
" next_expiry = (self.env.now + db_object.ttl) if db_object.ttl is not None else None\n",
|
||
" cache_object = CacheObject(id=obj_id, data=db_object, \n",
|
||
" initial_fetch_timer=initial_fetch_timer, age_timer=age_timer, \n",
|
||
" last_access=last_access,next_refresh=next_refresh, next_expiry=next_expiry\n",
|
||
" )\n",
|
||
" self.storage[obj_id] = cache_object\n",
|
||
" \n",
|
||
" assert len(self.cumulative_age[obj_id]) == self.access_count[obj_id], f\"[{self.env.now:.2f}] Age values collected and object access count do not match.\"\n",
|
||
" # print(f\"[{env.now:.2f}] {obj_id} Miss: Average Age {sum(self.cumulative_age[obj_id])/len(self.cumulative_age[obj_id]):.2f} \")\n",
|
||
" return self.storage[obj_id]\n",
|
||
"\n",
|
||
" def refresh_object(self, obj_id):\n",
|
||
" \"\"\"Refresh the object from the database to keep it up-to-date. TTL is increased on refresh.\"\"\"\n",
|
||
" assert obj_id in self.storage, f\"[{self.env.now:.2f}] Refreshed object has to be in cache\"\n",
|
||
" db_object = self.db.get_object(obj_id)\n",
|
||
" age_timer = self.env.now\n",
|
||
" next_refresh = self.env.now + np.random.exponential(1/db_object.mu_value)\n",
|
||
" # next_expiry = self.env.now + db_object.ttl if db_object.ttl is not None else None\n",
|
||
"\n",
|
||
" self.storage[obj_id].data = db_object\n",
|
||
" self.storage[obj_id].age_timer = age_timer\n",
|
||
" self.storage[obj_id].next_refresh = next_refresh\n",
|
||
"\n",
|
||
" # print(f\"[{self.env.now:.2f}] Cache: Refreshed object {obj_id}\")\n",
|
||
" \n",
|
||
" def evict_oldest(self):\n",
|
||
" \"\"\"Remove the oldest item from the cache to make space.\"\"\"\n",
|
||
" assert self.capacity == len(self.storage), f\"[{self.env.now:.2f}] Expecting cache to be at capacity\"\n",
|
||
" oldest_id = min(self.storage.items(), key=lambda item: item[1].last_access)[0]\n",
|
||
" \n",
|
||
" # print(f\"[{self.env.now:.2f}] Cache: Evicting oldest object {oldest_id}.\")\n",
|
||
" self.cumulative_cache_time[oldest_id].append(self.env.now - self.storage[oldest_id].initial_fetch_timer)\n",
|
||
" del self.storage[oldest_id]\n",
|
||
" \n",
|
||
" def evict_random(self):\n",
|
||
" \"\"\"Remove a random item from the cache to make space.\"\"\"\n",
|
||
" assert self.capacity == len(self.storage), f\"[{self.env.now:.2f}] Expecting cache to be at capacity\"\n",
|
||
" random_id = np.random.choice(list(self.storage.keys())) # Select a random key from the cache\n",
|
||
" \n",
|
||
" # print(f\"[{self.env.now:.2f}] Cache: Evicting random object {random_id}.\")\n",
|
||
" self.cumulative_cache_time[random_id].append(self.env.now - self.storage[random_id].initial_fetch_timer)\n",
|
||
" del self.storage[random_id]\n",
|
||
" \n",
|
||
" def check_expired(self, obj_id):\n",
|
||
" \"\"\"Remove object if its TTL expired.\"\"\"\n",
|
||
" assert self.storage, f\"[{self.env.now:.2f}] Expecting cache to be not empty\"\n",
|
||
" assert self.env.now >= self.storage[obj_id].next_expiry\n",
|
||
" \n",
|
||
" # print(f\"[{self.env.now:.2f}] Cache: Object {obj_id} expired\")\n",
|
||
" self.cumulative_cache_time[obj_id].append(self.env.now - self.storage[obj_id].initial_fetch_timer)\n",
|
||
" del self.storage[obj_id]\n",
|
||
"\n",
|
||
" \n",
|
||
" def record_cache_state(self):\n",
|
||
" \"\"\"Record the current cache state (number of objects in cache) over time.\"\"\"\n",
|
||
" self.cache_size_over_time.append((self.env.now, len(self.storage)))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "687f5634-8edf-4337-b42f-bbb292d47f0f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def client_request_process(env, cache, event):\n",
|
||
" \"\"\"Client process that makes requests for objects from the cache.\"\"\"\n",
|
||
" last_print = 0\n",
|
||
" with tqdm(total=ACCESS_COUNT_LIMIT, desc=\"Progress\", leave=True) as pbar:\n",
|
||
" while True:\n",
|
||
" request_id, next_request = min(cache.next_request.items(), key=lambda x: x[1])\n",
|
||
" expiry_id = -1\n",
|
||
" next_expiry = float('inf')\n",
|
||
" refresh_id = -1\n",
|
||
" next_refresh = float('inf')\n",
|
||
"\n",
|
||
" if cache.storage:\n",
|
||
" expiry_id, next_expiry = min(cache.storage.items(), key=lambda x: x[1].next_expiry if x[1].next_expiry is not None else float('inf'))\n",
|
||
" next_expiry = cache.storage[expiry_id].next_expiry\n",
|
||
" refresh_id, next_refresh = min(cache.storage.items(), key=lambda x: x[1].next_refresh if x[1].next_refresh is not None else float('inf'))\n",
|
||
" next_refresh = cache.storage[refresh_id].next_refresh\n",
|
||
"\n",
|
||
" events = [\n",
|
||
" (request_id, next_request),\n",
|
||
" (expiry_id, next_expiry),\n",
|
||
" (refresh_id, next_refresh)\n",
|
||
" ]\n",
|
||
"\n",
|
||
" event_id, event_timestamp = min(events, key=lambda x: x[1] if x[1] is not None else float('inf'))\n",
|
||
" \n",
|
||
" # if event_id == request_id and event_timestamp == next_request:\n",
|
||
" # print(f\"[{env.now:.2f}] Waiting for request...\")\n",
|
||
" # elif event_id == expiry_id and event_timestamp == next_expiry:\n",
|
||
" # print(f\"[{env.now:.2f}] Waiting for expiry until...\")\n",
|
||
" # elif event_id == refresh_id and event_timestamp == next_refresh:\n",
|
||
" # print(f\"[{env.now:.2f}] Waiting for refresh...\")\n",
|
||
" \n",
|
||
" yield(env.timeout(event_timestamp - env.now))\n",
|
||
"\n",
|
||
" if event_id == request_id and event_timestamp == next_request:\n",
|
||
" assert env.now >= next_request, f\"[{env.now}] Time for request should've been reached for Object {request_id}\"\n",
|
||
" cache.get(request_id)\n",
|
||
" elif event_id == expiry_id and event_timestamp == next_expiry:\n",
|
||
" assert env.now >= next_expiry, f\"[{env.now}] Time for expiry should've been reached for Object {expiry_id}\"\n",
|
||
" cache.check_expired(expiry_id)\n",
|
||
" elif event_id == refresh_id and event_timestamp == next_refresh:\n",
|
||
" assert env.now >= next_refresh, f\"[{env.now}] Time for refresh should've been reached for Object {refresh_id}\"\n",
|
||
" cache.refresh_object(refresh_id)\n",
|
||
" else:\n",
|
||
" assert False, \"Unreachable\"\n",
|
||
"\n",
|
||
" # For progress bar\n",
|
||
" if (int(env.now) % 1) == 0 and int(env.now) != last_print:\n",
|
||
" last_print = int(env.now)\n",
|
||
" pbar.n = min(cache.access_count.values())\n",
|
||
" pbar.refresh()\n",
|
||
" \n",
|
||
" # Simulation stop condition\n",
|
||
" if all(access_count >= ACCESS_COUNT_LIMIT for access_count in cache.access_count.values()):\n",
|
||
" print(f\"Simulation ended after {env.now} seconds.\")\n",
|
||
" for obj_id in cache.storage.keys():\n",
|
||
" cache.cumulative_cache_time[obj_id].append(env.now - cache.storage[obj_id].initial_fetch_timer)\n",
|
||
" event.succeed()\n",
|
||
" \n",
|
||
" cache.record_cache_state()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"id": "c8516830-9880-4d9e-a91b-000338baf9d6",
|
||
"metadata": {
|
||
"scrolled": true
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"class Simulation:\n",
|
||
" def __init__(self, simulation_config: Union[TTLSimulation, LRUSimulation, RandomEvictionSimulation, RefreshSimulation]):\n",
|
||
" # Initialize simulation environment\n",
|
||
" self.env = simpy.Environment()\n",
|
||
" \n",
|
||
" # Instantiate components\n",
|
||
" self.db = Database(simulation_config.db_objects)\n",
|
||
" self.cache = Cache(self.env, self.db, simulation_config)\n",
|
||
"\n",
|
||
" def run_simulation(self):\n",
|
||
" # Start processes\n",
|
||
" # env.process(age_cache_process(env, cache))\n",
|
||
" stop_event = self.env.event()\n",
|
||
" self.env.process(client_request_process(self.env, self.cache, stop_event))\n",
|
||
" \n",
|
||
" # Run the simulation\n",
|
||
" self.env.run(until=stop_event)\n",
|
||
" self.end_time = self.env.now"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 10,
|
||
"id": "e269b607-16b9-46d0-8a97-7324f2002c72",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Simulate with a Cache that does random evictions, We'll have 100 Database Objects and a Cache Size of 10\n",
|
||
"# We'll generate lambdas from a zipf distribution\n",
|
||
"# config = RandomEvictionSimulation(100, 10)\n",
|
||
"# config.generate_objects()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 11,
|
||
"id": "33fdc5fd-1f39-4b51-b2c7-6ea6acf2b753",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Simulate with a Cache that does lru, We'll have 100 Database Objects and a Cache Size of 10\n",
|
||
"# We'll generate lambdas from a zipf distribution\n",
|
||
"# config = LRUSimulation(100, 10)\n",
|
||
"# config.from_file('./input/2024-12-13/input.csv', 'Lambda')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 12,
|
||
"id": "6c391bfd-b294-4ff7-8b22-51777368a6b9",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Simulate with a Cache that does Refreshes with TTL based eviction, We'll have 100 Database Objects and a Cache Size of 10\n",
|
||
"# We'll generate lambdas from a zipf distribution. Each object will have a fixed ttl of 1 when its pulled into the cache. Mu for the refresh rate is 10\n",
|
||
"config = RefreshSimulation(100, 10)\n",
|
||
"config.from_file(path='./input/2024-12-13/output.csv', lambda_column_name='Lambda', ttl_column_name='TTL_2', mu_column_name='u_opt_2')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 13,
|
||
"id": "0a444c9d-53dd-4cab-b8f1-100ad3ab213a",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Simulate with a Cache that does TTL based eviction, We'll have 100 Database Objects and a Cache Size of 10\n",
|
||
"# We'll take lambdas from the \"lambda\" column of the file \"../calculated.csv\" and the TTLs for each object from the \"optimal_TTL\" column of the same file.\n",
|
||
"# config = TTLSimulation(100, 10)\n",
|
||
"# config.from_file(\"../calculated.csv\", \"lambda\", \"optimal_TTL\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"id": "66f65699-a3c9-48c4-8f1f-b9d7834c026a",
|
||
"metadata": {
|
||
"scrolled": true
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Progress: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊| 999/1000 [00:53<00:00, 18.64it/s]"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Simulation ended after 41546.30037303802 seconds.\n",
|
||
"CPU times: user 50.4 s, sys: 8.37 s, total: 58.7 s\n",
|
||
"Wall time: 53.6 s\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"%%time\n",
|
||
"\n",
|
||
"simulation = Simulation(config)\n",
|
||
"simulation.run_simulation()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 15,
|
||
"id": "6f900c68-1f34-48d1-b346-ef6ea6911fa5",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"cache = simulation.cache\n",
|
||
"db = simulation.db\n",
|
||
"simulation_end_time = simulation.end_time\n",
|
||
"database_object_count = len(db.data)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"id": "3b6f7c1f-ea54-4496-bb9a-370cee2d2751",
|
||
"metadata": {
|
||
"scrolled": true
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Object 0: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 1: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 2: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 3: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 4: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 5: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 6: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 7: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 8: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 9: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 10: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 11: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 12: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 13: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 14: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 15: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 16: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 17: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 18: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 19: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 20: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 21: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 22: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 23: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 24: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 25: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 26: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 27: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 28: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 29: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 30: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 31: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 32: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 33: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 34: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 35: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 36: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 37: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 38: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 39: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 40: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 41: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 42: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 43: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 44: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 45: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 46: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 47: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 48: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 49: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 50: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 51: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 52: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 53: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 54: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 55: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 56: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 57: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 58: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 59: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 60: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 61: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 62: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 63: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 64: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 65: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 66: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 67: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 68: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 69: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 70: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 71: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 72: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 73: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 74: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 75: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 76: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 77: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 78: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 79: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 80: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 81: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 82: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 83: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 84: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 85: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 86: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 87: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 88: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 89: Hit Rate = 0.00, Expected Hit Rate = 0.00, Average Time spend in Cache: 0.00, Average Age = 0.00, Expected Age = 0.00\n",
|
||
"Object 90: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.55, Expected Age = 20367.51\n",
|
||
"Object 91: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.54, Expected Age = 20926.62\n",
|
||
"Object 92: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.51, Expected Age = 20502.64\n",
|
||
"Object 93: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.49, Expected Age = 20425.76\n",
|
||
"Object 94: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.46, Expected Age = 20902.52\n",
|
||
"Object 95: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.43, Expected Age = 20666.00\n",
|
||
"Object 96: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.39, Expected Age = 20772.20\n",
|
||
"Object 97: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.35, Expected Age = 20708.69\n",
|
||
"Object 98: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.30, Expected Age = 20858.00\n",
|
||
"Object 99: Hit Rate = 1.00, Expected Hit Rate = 1.00, Average Time spend in Cache: 1.00, Average Age = 0.22, Expected Age = 20546.25\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"statistics = []\n",
|
||
"# Calculate and print hit rate and average age for each object\n",
|
||
"for obj_id in range(database_object_count):\n",
|
||
" if cache.access_count[obj_id] != 0:\n",
|
||
" output = \"\"\n",
|
||
" expected_hit_rate = None\n",
|
||
" hit_rate = cache.hits[obj_id] / max(1, cache.access_count[obj_id])\n",
|
||
" output += f\"Object {obj_id}: Hit Rate = {hit_rate:.2f}, \"\n",
|
||
" if db.data[obj_id].ttl is not None:\n",
|
||
" expected_hit_rate = 1-math.exp(-db.data[obj_id].lambda_value*(db.data[obj_id].ttl))\n",
|
||
" output += f\"Expected Hit Rate = {expected_hit_rate:.2f}, \"\n",
|
||
" avg_cache_time = sum(cache.cumulative_cache_time[obj_id]) / max(1, simulation_end_time) \n",
|
||
" output += f\"Average Time spend in Cache: {avg_cache_time:.2f}, \"\n",
|
||
" avg_age = sum(cache.cumulative_age[obj_id]) / max(len(cache.cumulative_age[obj_id]), 1)\n",
|
||
" output += f\"Average Age = {avg_age:.2f}, \"\n",
|
||
" expected_age = hit_rate / (db.data[obj_id].lambda_value * (1 - pow(hit_rate,2)))\n",
|
||
" output += f\"Expected Age = {expected_age:.2f}\"\n",
|
||
" print(output)\n",
|
||
" if db.data[obj_id].ttl is not None:\n",
|
||
" statistics.append({\n",
|
||
" \"obj_id\": obj_id,\n",
|
||
" \"hit_rate\": hit_rate, \n",
|
||
" \"expected_hit_rate\": expected_hit_rate, \n",
|
||
" \"avg_cache_time\":avg_cache_time, \n",
|
||
" \"avg_age\": avg_age, \n",
|
||
" \"expected_age\": expected_age\n",
|
||
" })\n",
|
||
" else:\n",
|
||
" statistics.append({\n",
|
||
" \"obj_id\": obj_id,\n",
|
||
" \"hit_rate\": hit_rate, \n",
|
||
" \"avg_cache_time\":avg_cache_time, \n",
|
||
" \"avg_age\": avg_age, \n",
|
||
" \"expected_age\": expected_age\n",
|
||
" })"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"id": "b2d18372-cdba-4151-ae32-5bf45466bf94",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"stats = pd.DataFrame(statistics)\n",
|
||
"stats.to_csv(f\"{TEMP_BASE_DIR}/hit_age.csv\",index=False)\n",
|
||
"stats.drop(\"obj_id\", axis=1).describe().to_csv(f\"{TEMP_BASE_DIR}/overall_hit_age.csv\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"id": "be7e67e7-4533-438a-ab65-ca813f48052a",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"expected_hit_rate = None\n",
|
||
"expected_hit_rate_delta = None"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 19,
|
||
"id": "80971714-44f1-47db-9e89-85be7c885bde",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>access_count</th>\n",
|
||
" <th>hits</th>\n",
|
||
" <th>misses</th>\n",
|
||
" <th>mu</th>\n",
|
||
" <th>lambda</th>\n",
|
||
" <th>hit_rate</th>\n",
|
||
" <th>expected_hit_rate</th>\n",
|
||
" <th>expected_hit_rate_delta</th>\n",
|
||
" <th>avg_cache_time</th>\n",
|
||
" <th>cache_time_delta</th>\n",
|
||
" <th>avg_age</th>\n",
|
||
" <th>ages</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>1062</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1062</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.0251</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>1088</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1088</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.0253</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>1000</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.0255</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>1044</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1044</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.0257</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>1129</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1129</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.0260</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>...</th>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>95</th>\n",
|
||
" <td>11404</td>\n",
|
||
" <td>11403</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>2.344666</td>\n",
|
||
" <td>0.2759</td>\n",
|
||
" <td>0.999912</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>-0.000088</td>\n",
|
||
" <td>0.999941</td>\n",
|
||
" <td>-0.000028</td>\n",
|
||
" <td>0.428322</td>\n",
|
||
" <td>[0, 0.0891512597998787, 0.06415110059353868, 0...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>96</th>\n",
|
||
" <td>13706</td>\n",
|
||
" <td>13705</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>2.563445</td>\n",
|
||
" <td>0.3299</td>\n",
|
||
" <td>0.999927</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>-0.000073</td>\n",
|
||
" <td>0.999946</td>\n",
|
||
" <td>-0.000019</td>\n",
|
||
" <td>0.386432</td>\n",
|
||
" <td>[0, 0.31426861097273395, 0.07673416342145734, ...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>97</th>\n",
|
||
" <td>17197</td>\n",
|
||
" <td>17196</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>2.876043</td>\n",
|
||
" <td>0.4152</td>\n",
|
||
" <td>0.999942</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>-0.000058</td>\n",
|
||
" <td>0.999968</td>\n",
|
||
" <td>-0.000026</td>\n",
|
||
" <td>0.349340</td>\n",
|
||
" <td>[0, 0.9920726875299433, 0.11549947514999914, 0...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>98</th>\n",
|
||
" <td>23958</td>\n",
|
||
" <td>23957</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>3.381806</td>\n",
|
||
" <td>0.5743</td>\n",
|
||
" <td>0.999958</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>-0.000042</td>\n",
|
||
" <td>0.999999</td>\n",
|
||
" <td>-0.000041</td>\n",
|
||
" <td>0.297864</td>\n",
|
||
" <td>[0, 0.055604529502096156, 0.05810636385222967,...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>99</th>\n",
|
||
" <td>41093</td>\n",
|
||
" <td>41092</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>4.462294</td>\n",
|
||
" <td>1.0000</td>\n",
|
||
" <td>0.999976</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>-0.000024</td>\n",
|
||
" <td>0.999997</td>\n",
|
||
" <td>-0.000022</td>\n",
|
||
" <td>0.223745</td>\n",
|
||
" <td>[0, 0.1683508324120914, 0.24845511096226777, 0...</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>100 rows × 12 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" access_count hits misses mu lambda hit_rate \\\n",
|
||
"0 1062 0 1062 1.000000 0.0251 0.000000 \n",
|
||
"1 1088 0 1088 1.000000 0.0253 0.000000 \n",
|
||
"2 1000 0 1000 1.000000 0.0255 0.000000 \n",
|
||
"3 1044 0 1044 1.000000 0.0257 0.000000 \n",
|
||
"4 1129 0 1129 1.000000 0.0260 0.000000 \n",
|
||
".. ... ... ... ... ... ... \n",
|
||
"95 11404 11403 1 2.344666 0.2759 0.999912 \n",
|
||
"96 13706 13705 1 2.563445 0.3299 0.999927 \n",
|
||
"97 17197 17196 1 2.876043 0.4152 0.999942 \n",
|
||
"98 23958 23957 1 3.381806 0.5743 0.999958 \n",
|
||
"99 41093 41092 1 4.462294 1.0000 0.999976 \n",
|
||
"\n",
|
||
" expected_hit_rate expected_hit_rate_delta avg_cache_time \\\n",
|
||
"0 0.0 0.000000 0.000000 \n",
|
||
"1 0.0 0.000000 0.000000 \n",
|
||
"2 0.0 0.000000 0.000000 \n",
|
||
"3 0.0 0.000000 0.000000 \n",
|
||
"4 0.0 0.000000 0.000000 \n",
|
||
".. ... ... ... \n",
|
||
"95 1.0 -0.000088 0.999941 \n",
|
||
"96 1.0 -0.000073 0.999946 \n",
|
||
"97 1.0 -0.000058 0.999968 \n",
|
||
"98 1.0 -0.000042 0.999999 \n",
|
||
"99 1.0 -0.000024 0.999997 \n",
|
||
"\n",
|
||
" cache_time_delta avg_age \\\n",
|
||
"0 0.000000 0.000000 \n",
|
||
"1 0.000000 0.000000 \n",
|
||
"2 0.000000 0.000000 \n",
|
||
"3 0.000000 0.000000 \n",
|
||
"4 0.000000 0.000000 \n",
|
||
".. ... ... \n",
|
||
"95 -0.000028 0.428322 \n",
|
||
"96 -0.000019 0.386432 \n",
|
||
"97 -0.000026 0.349340 \n",
|
||
"98 -0.000041 0.297864 \n",
|
||
"99 -0.000022 0.223745 \n",
|
||
"\n",
|
||
" ages \n",
|
||
"0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... \n",
|
||
"1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... \n",
|
||
"2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... \n",
|
||
"3 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... \n",
|
||
"4 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... \n",
|
||
".. ... \n",
|
||
"95 [0, 0.0891512597998787, 0.06415110059353868, 0... \n",
|
||
"96 [0, 0.31426861097273395, 0.07673416342145734, ... \n",
|
||
"97 [0, 0.9920726875299433, 0.11549947514999914, 0... \n",
|
||
"98 [0, 0.055604529502096156, 0.05810636385222967,... \n",
|
||
"99 [0, 0.1683508324120914, 0.24845511096226777, 0... \n",
|
||
"\n",
|
||
"[100 rows x 12 columns]"
|
||
]
|
||
},
|
||
"execution_count": 19,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"access_count = pd.DataFrame.from_dict(cache.access_count, orient='index', columns=['access_count'])\n",
|
||
"hits = pd.DataFrame.from_dict(cache.hits, orient='index', columns=['hits'])\n",
|
||
"misses = pd.DataFrame.from_dict(cache.misses, orient='index', columns=['misses'])\n",
|
||
"mu = pd.DataFrame.from_dict({l: db.data[l].mu_value for l in range(database_object_count)}, orient='index', columns=['mu'])\n",
|
||
"lmbda = pd.DataFrame.from_dict({l: db.data[l].lambda_value for l in range(database_object_count)}, orient='index', columns=['lambda'])\n",
|
||
"\n",
|
||
"hit_rate = pd.DataFrame(stats['hit_rate'])\n",
|
||
"hit_rate.index = range(database_object_count)\n",
|
||
"if 'expected_hit_rate' in stats:\n",
|
||
" expected_hit_rate = pd.DataFrame(stats['expected_hit_rate'])\n",
|
||
" expected_hit_rate.index = range(database_object_count)\n",
|
||
" expected_hit_rate_delta = pd.DataFrame((hit_rate.to_numpy()-expected_hit_rate.to_numpy()), columns=['expected_hit_rate_delta'])\n",
|
||
" expected_hit_rate_delta.index = range(database_object_count)\n",
|
||
"avg_cache_time = pd.DataFrame(stats['avg_cache_time'])\n",
|
||
"avg_cache_time.index = range(database_object_count)\n",
|
||
"cache_time_delta = pd.DataFrame((hit_rate.to_numpy()-avg_cache_time.to_numpy()), columns=['cache_time_delta'])\n",
|
||
"cache_time_delta.index = range(database_object_count)\n",
|
||
"\n",
|
||
"avg_age = pd.DataFrame(stats['avg_age'])\n",
|
||
"avg_age.index = range(database_object_count)\n",
|
||
"\n",
|
||
"ages = {k: str(v) for k,v in cache.cumulative_age.items()}\n",
|
||
"ages = pd.DataFrame.from_dict(ages, orient='index', columns=['ages'])\n",
|
||
"\n",
|
||
"merged = access_count.merge(hits, left_index=True, right_index=True).merge(misses, left_index=True, right_index=True) \\\n",
|
||
" .merge(mu, left_index=True, right_index=True).merge(lmbda, left_index=True, right_index=True) \\\n",
|
||
" .merge(hit_rate, left_index=True, right_index=True)\n",
|
||
"if 'expected_hit_rate' in stats:\n",
|
||
" merged = merged.merge(expected_hit_rate, left_index=True, right_index=True).merge(expected_hit_rate_delta, left_index=True, right_index=True)\n",
|
||
"merged = merged.merge(avg_cache_time, left_index=True, right_index=True).merge(cache_time_delta, left_index=True, right_index=True) \\\n",
|
||
" .merge(avg_age, left_index=True, right_index=True).merge(ages, left_index=True, right_index=True)\n",
|
||
"merged.to_csv(f\"{TEMP_BASE_DIR}/details.csv\", index_label=\"obj_id\")\n",
|
||
"merged"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 20,
|
||
"id": "01f8f9ee-c278-4a22-8562-ba02e77f5ddd",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "iVBORw0KGgoAAAANSUhEUgAACVcAAAHWCAYAAAB5HisgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABkzklEQVR4nOzdeZid48E/8O/Jvm/IgoiQ2EKqKI19CaFqaSlRilhLlNCqoJZYatfgtVZraala69UiYk3tYldBEKraSEkiJMQk8/z+8Mu8pjNhJmZyppnP57pyXXOe536e8z1nTuaOub7uu1QURREAAAAAAAAAAACqaVHuAAAAAAAAAAAAAE2RchUAAAAAAAAAAEAtlKsAAAAAAAAAAABqoVwFAAAAAAAAAABQC+UqAAAAAAAAAACAWihXAQAAAAAAAAAA1EK5CgAAAAAAAAAAoBbKVQAAAAAAAAAAALVQrgIAAAAAAAAAAKiFchUAAABAkgcffDClUik333xzuaPUyXvvvZddd901Sy21VEqlUsaOHdtg937rrbdSKpVy7rnnfuXYk08+OaVSqcGee3EolUo5+eSTyx2jQZRKpRx22GHljvFfbcUVV8y+++5b7hgAAABAE6VcBQAAACw2V199dUqlUtq1a5d33323xvnNN988a665ZhmS/fc58sgjM27cuBx77LH53e9+l2233fZLx8+ePTunnnpqBg8enA4dOqRr167ZZJNNcu2116YoisWUuv7uvPPO/5oi1IMPPpjvf//76d27d9q0aZOePXtmhx12yK233lruaA2ioqIiF154Yb71rW+lc+fO6dSpU771rW/lwgsvTEVFRbnjVVlQlKzLHwAAAICv0qrcAQAAAIDmZ+7cuTnzzDNz0UUXlTvKf637778/O+20U372s5995dj33nsvW221VSZNmpThw4fnsMMOy6effppbbrkl++yzT+68885cd911admyZb1z/OIXv8jo0aMX5SXUyZ133pmLL764QQtWn3zySVq1athfi5100kk55ZRTMnDgwBx88MHp169fPvjgg9x5553ZZZddct111+WHP/xhgz7n4jR79uxsv/32eeihh/Ld7343++67b1q0aJG77747RxxxRG699db85S9/SceOHcsdNauvvnp+97vfVTt27LHHplOnTjn++ONrjH/11VfTooX/BxUAAAConXIVAAAAsNitvfba+fWvf51jjz02yy67bLnjLFazZ89ukALKtGnT0q1btzqN3WeffTJp0qTcdttt2XHHHauOH3744Tn66KNz7rnn5pvf/GaOOeaYeudo1apVgxeVGlu7du0a9H4333xzTjnllOy66665/vrr07p166pzRx99dMaNG9ekVnZaFEcddVQeeuihXHTRRdW2ITzkkENy8cUX57DDDsvPfvazXHrppYstU1EU+fTTT9O+fftqx3v16pW99tqr2rEzzzwzSy+9dI3jSdK2bdtGzQkAAAD8d/O/ZAEAAACL3XHHHZf58+fnzDPP/NJxb731VkqlUq6++uoa50qlUrXVjE4++eSUSqW89tpr2WuvvdK1a9css8wyOeGEE1IURd55553stNNO6dKlS3r37p3zzjuv1uecP39+jjvuuPTu3TsdO3bMjjvumHfeeafGuCeeeCLbbrttunbtmg4dOmSzzTbLI488Um3Mgkwvv/xyfvjDH6Z79+7ZeOONv/Q1v/nmm/nBD36QHj16pEOHDvn2t7+dv/zlL1XnF2ytWBRFLr744q/c3uzxxx/PuHHjsu+++1YrVi1wxhlnZODAgTnrrLPyySef1Dj/q1/9Kv369Uv79u2z2Wab5aWXXqr1Nf6n3//+91l33XXTvn379OjRI8OHD1/o+/id73wn3bt3T8eOHTN48OBccMEFSZJ99903F198cZLUupXbDTfckHXXXTedO3dOly5dstZaa1Vd+2UW9tl5/fXXs++++6Zbt27p2rVrRowYkTlz5nzl/U444YT06NEjv/3tb6sVqxYYNmxYvvvd7yZJPvvss5x44olZd91107Vr13Ts2DGbbLJJHnjggRrXVVZW5oILLshaa62Vdu3aZZlllsm2226biRMn1hj7pz/9KWuuuWbatm2bQYMG5e67764x5t13381+++2XXr16VY377W9/+5Wv7x//+Ed+85vfZMstt6xWrFpg5MiR2WKLLXLllVfmH//4R5JkzTXXzBZbbFHra1puueWy6667Vjs2duzYDBo0KO3atUuvXr1y8MEHZ8aMGdWuXXHFFfPd734348aNy3rrrZf27dvn8ssv/8r8X2XFFVfMvvvuW/V4wd+xhx9+OIcffniWWWaZdOvWLQcffHA+++yzzJw5M3vvvXe6d++e7t275+c//3mNrTXr+poAAACApk+5CgAAAFjs+vfvn7333ju//vWv889//rNB77377runsrIyZ555ZjbYYIOcdtppGTt2bLbeeusst9xyOeusszJgwID87Gc/y4QJE2pcf/rpp+cvf/lLjjnmmBx++OEZP358hg4dWq14dP/992fTTTfNrFmzctJJJ+WXv/xlZs6cmS233DJPPvlkjXv+4Ac/yJw5c/LLX/4yBx544EKzv/fee9lwww0zbty4HHrooTn99NPz6aefZscdd8xtt92WJNl0002rtjzbeuut87vf/a7GFmhfdMcddyRJ9t5771rPt2rVKj/84Q8zY8aMGuWwa6+9NhdeeGFGjhyZY489Ni+99FK23HLLvPfeewt9vuTz93DvvffOwIEDc/7552fUqFG57777summm2bmzJlV48aPH59NN900L7/8co444oicd9552WKLLfLnP/85SXLwwQdn6623TpKq17ngtY4fPz577LFHunfvnrPOOitnnnlmNt988xqvoT522223fPTRRznjjDOy22675eqrr86YMWO+9JrJkyfnlVdeyc4775zOnTt/5XPMmjUrV155ZTbffPOcddZZOfnkk/Pvf/87w4YNy3PPPVdt7P77759Ro0alb9++OeusszJ69Oi0a9cujz/+eLVxDz/8cA499NAMHz48Z599dj799NPssssu+eCDD6rGvPfee/n2t7+de++9N4cddlguuOCCDBgwIPvvv3/Gjh37pZnvuuuuzJ8/f6GfoeTzz9e8efOqSl277757JkyYkKlTp9bI+s9//jPDhw+vOnbwwQfn6KOPzkYbbZQLLrggI0aMyHXXXZdhw4bVWPHr1VdfzR577JGtt946F1xwQdZee+0vzf51/OQnP8nkyZMzZsyY7LjjjrniiitywgknZIcddsj8+fPzy1/+MhtvvHHOOeecGn8H6/OaAAAAgCauAAAAAFhMrrrqqiJJ8dRTTxVvvPFG0apVq+Lwww+vOr/ZZpsVgwYNqno8ZcqUIklx1VVX1bhXkuKkk06qenzSSScVSYqDDjqo6ti8efOK5ZdfviiVSsWZZ55ZdXzGjBlF+/bti3322afq2AMPPFAkKZZbbrli1qxZVcdvvPHGIklxwQUXFEVRFJWVlcXAgQOLYcOGFZWVlVXj5syZU/Tv37/Yeuuta2TaY4896vT+jBo1qkhS/PWvf6069tFHHxX9+/cvVlxxxWL+/PnVXv/IkSO/8p4777xzkaSYMWPGQsfceuutRZLiwgsvLIri/9739u3bF//4xz+qxj3xxBNFkuLII4+s8RoXeOutt4qWLVsWp59+erXnePHFF4tWrVpVHZ83b17Rv3//ol+/fjWyffF9HTlyZFHbr7COOOKIokuXLsW8efO+8j34Twv77Oy3337Vxn3ve98rllpqqS+91+23314kKX71q1/V6bnnzZtXzJ07t9qxGTNmFL169ar2/Pfff3+RpNrfjwW++P4kKdq0aVO8/vrrVceef/75Iklx0UUXVR3bf//9iz59+hTvv/9+tXsNHz686Nq1azFnzpyFZl7wuXz22WcXOuaZZ54pkhRHHXVUURRF8eqrr9bIUBRFceihhxadOnWqer6//vWvRZLiuuuuqzbu7rvvrnG8X79+RZLi7rvvXmiOhRk0aFCx2Wab1XquX79+1X4WLPg59Z9/x4cMGVKUSqXixz/+cdWxBT9jvnjv+rwmAAAAoOmzchUAAABQFiuttFJ+9KMf5Yorrsi//vWvBrvvAQccUPV1y5Yts95666Uoiuy///5Vx7t165ZVV101b775Zo3r995772orEO26667p06dP7rzzziTJc889l8mTJ+eHP/xhPvjgg7z//vt5//33M3v27Gy11VaZMGFCKisrq93zxz/+cZ2y33nnnVl//fWrbR3YqVOnHHTQQXnrrbfy8ssv1+1N+IKPPvooSb50VaUF52bNmlXt+M4775zllluu6vH666+fDTbYoOq9qM2tt96aysrK7LbbblXvzfvvv5/evXtn4MCBVdvfPfvss5kyZUpGjRqVbt26VbvHl21zuEC3bt0ye/bsjB8//ivH1tV/fp822WSTfPDBBzXely9acK4uq1Yln38m27Rpk+TzreOmT5+eefPmZb311sszzzxTNe6WW25JqVTKSSedVOMe//n+DB06NCuvvHLV48GDB6dLly5Vn++iKHLLLbdkhx12SFEU1b4vw4YNy4cffljtuf/TonyGVllllay99tr54x//WDVm/vz5ufnmm7PDDjukffv2SZKbbropXbt2zdZbb10t17rrrptOnTrV2C6xf//+GTZs2EJzNKT999+/2nu9wQYb1PhZsuBnzBd/ltT3NQEAAABNW6tyBwAAAACar1/84hf53e9+lzPPPDMXXHBBg9xzhRVWqPa4a9euadeuXZZeeukax7+4bdoCAwcOrPa4VCplwIABeeutt5J8vg1ckuyzzz4LzfDhhx+me/fuVY/79+9fp+xvv/12NthggxrHV1999arza665Zp3utcCC0stHH31Uo8S0wMLKM//5XiSfl2ZuvPHGhT7f5MmTUxRFrdcmSevWrZMkb7zxRpLU+/UscOihh+bGG2/Mdtttl+WWWy7bbLNNdtttt2y77baLdL+k5mdnwfdwxowZ6dKlS63XLDi+4D2si2uuuSbnnXdeXnnllWpbxH3xc/LGG29k2WWXTY8ePeqde0H2GTNmJEn+/e9/Z+bMmbniiityxRVX1HqPadOmLfT+X/wMLUxtn6Hdd989xx13XN59990st9xyefDBBzNt2rTsvvvuVWMmT56cDz/8MD179qxTrrr+XWoItf0sSZK+ffvWOL7gvU7q/5oAAACApk25CgAAACiblVZaKXvttVeuuOKKjB49usb5ha1gNH/+/IXes2XLlnU6lny+ok99LViV6pxzzsnaa69d65hOnTpVe7xglZ5yWH311fOnP/0pL7zwQjbddNNax7zwwgtJkjXWWONrP19lZWVKpVLuuuuuWt/3/3xvFlXPnj3z3HPPZdy4cbnrrrty11135aqrrsree++da665ZpHuuSifk9VWWy1J8uKLL9bpOX7/+99n3333zc4775yjjz46PXv2TMuWLXPGGWdUFc7q66tyL/jM7rXXXgstBQ4ePHih919Q7nvhhRcW+pmv7TO0++6759hjj81NN92UUaNG5cYbb0zXrl2rFeAqKyvTs2fPXHfddbXed5lllqn2eHH+XVrY+1rb8S9+Rur7mgAAAICmTbkKAAAAKKtf/OIX+f3vf5+zzjqrxrkFKwfNnDmz2vG333670fIsWJlqgaIo8vrrr1eVTxZsv9alS5cMHTq0QZ+7X79+efXVV2scf+WVV6rO19d3v/vdnHHGGbn22mtrLVfNnz8/119/fbp3756NNtqo2rn/fC+S5LXXXsuKK6640OdbeeWVUxRF+vfvn1VWWeVLxyXJSy+99KXv45dtEdimTZvssMMO2WGHHVJZWZlDDz00l19+eU444YQMGDBgodc1pFVWWSWrrrpqbr/99lxwwQVfWR67+eabs9JKK+XWW2+t9tr+c/u/lVdeOePGjcv06dPrtHrVl1lmmWXSuXPnzJ8/f5E+s9ttt11atmyZ3/3ud9l7771rHXPttdemVatW1YpT/fv3z/rrr58//vGPOeyww3Lrrbdm5513Ttu2bavGrLzyyrn33nuz0UYblbWE2JCWxNcEAAAAzVmLcgcAAAAAmreVV145e+21Vy6//PJMnTq12rkuXbpk6aWXzoQJE6odv+SSSxotz7XXXltt+7Obb745//rXv7LddtslSdZdd92svPLKOffcc/Pxxx/XuP7f//73Ij/3d77znTz55JN57LHHqo7Nnj07V1xxRVZcccVFWllqww03zNChQ3PVVVflz3/+c43zxx9/fF577bX8/Oc/r1EE+dOf/pR333236vGTTz6ZJ554ouq9qM33v//9tGzZMmPGjKmx4lNRFFVbMa6zzjrp379/xo4dW6M898XrOnbsmKRmwe4/t3Rs0aJFVQFu7ty5C83XGMaMGZMPPvggBxxwQObNm1fj/D333FP13i9Y9eiLr/GJJ56o9j1Pkl122SVFUWTMmDE17lffFddatmyZXXbZJbfcckteeumlGue/6jPbt2/fjBgxIvfee28uvfTSGucvu+yy3H///dl///2z/PLLVzu3++675/HHH89vf/vbvP/++9W2BEyS3XbbLfPnz8+pp55a477z5s2r8X3/b7AkviYAAABozqxcBQAAAJTd8ccfn9/97nd59dVXM2jQoGrnDjjggJx55pk54IADst5662XChAl57bXXGi1Ljx49svHGG2fEiBF57733Mnbs2AwYMCAHHnhgks9LPFdeeWW22267DBo0KCNGjMhyyy2Xd999Nw888EC6dOmSO+64Y5Gee/To0fnDH/6Q7bbbLocffnh69OiRa665JlOmTMktt9ySFi0W7f+Tu/baa7PVVltlp512yg9/+MNssskmmTt3bm699dY8+OCD2X333XP00UfXuG7AgAHZeOONc8ghh2Tu3LkZO3Zsllpqqfz85z9f6HOtvPLKOe2003Lsscfmrbfeys4775zOnTtnypQpue2223LQQQflZz/7WVq0aJFLL700O+ywQ9Zee+2MGDEiffr0ySuvvJK//e1vGTduXJLPy2xJcvjhh2fYsGFp2bJlhg8fngMOOCDTp0/PlltumeWXXz5vv/12Lrrooqy99tpV29gtLrvvvntefPHFnH766Xn22Wezxx57pF+/fvnggw9y991357777sv111+f5POVxG699dZ873vfy/bbb58pU6bksssuyxprrFGtrLfFFlvkRz/6US688MJMnjw52267bSorK/PXv/41W2yxRQ477LB6ZTzzzDPzwAMPZIMNNsiBBx6YNdZYI9OnT88zzzyTe++9N9OnT//S63/1q1/llVdeyaGHHpq77767aoWqcePG5fbbb89mm22W8847r8Z1u+22W372s5/lZz/7WXr06FFj5azNNtssBx98cM4444w899xz2WabbdK6detMnjw5N910Uy644ILsuuuu9Xqt5bYkviYAAABozpSrAAAAgLIbMGBA9tprr1xzzTU1zp144on597//nZtvvjk33nhjtttuu9x1113p2bNno2Q57rjj8sILL+SMM87IRx99lK222iqXXHJJOnToUDVm8803z2OPPZZTTz01//M//5OPP/44vXv3zgYbbJCDDz54kZ+7V69eefTRR3PMMcfkoosuyqeffprBgwfnjjvuyPbbb7/I9+3Tp0+efPLJnHfeebnppptyyy23pFWrVhk8eHCuvvrq7L333rVuv7f33nunRYsWGTt2bKZNm5b1118///M//5M+ffp86fONHj06q6yySn71q19VrbzUt2/fbLPNNtlxxx2rxg0bNiwPPPBAxowZk/POOy+VlZVZeeWVq4psyecrYf3kJz/JDTfckN///vcpiiLDhw/PXnvtlSuuuCKXXHJJZs6cmd69e2f33XfPySefvMgltK/jtNNOy5ZbbpkLL7wwl156aaZPn57u3bvn29/+dm6//faq173vvvtm6tSpufzyyzNu3LisscYa+f3vf5+bbropDz74YLV7XnXVVRk8eHB+85vf5Oijj07Xrl2z3nrrZcMNN6x3vl69euXJJ5/MKaeckltvvTWXXHJJllpqqQwaNKjWLTn/U6dOnXLfffflkksuye9///scffTRKYoiq622WsaOHZtDDz00rVu3rnHd8ssvnw033DCPPPJIDjjggFrHXHbZZVl33XVz+eWX57jjjkurVq2y4oorZq+99qqxVeV/iyXxNQEAAEBzVSrqu444AAAAAPx/J5xwQs4444xat8MDAAAAgP92i/9/4wMAAABgifGvf/0rSy+9dLljAAAAAECjsC0gAAAAAPX25ptv5rbbbstNN92U7373u+WOAwAAAACNwspVAAAAANTbhAkTMmbM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Pz5bb721+R4AlmDmfABoHsz5ANA8mPNZks2aNStLL730V5armvS2gEcffXRGjx6d4cOHJ0nWWmutvP322znjjDMWWq5q27Zt2rZtW+N469at/UVvolq0aFH1te8TACz5zPcA0DyY8wGgeTDnA0DzYM5nSVTXz3SLrx5SPnPmzKlWvEmSli1bprKyskyJAAAAAAAAAACA5qJJr1y1ww475PTTT88KK6yQQYMG5dlnn83555+f/fbbr9zRaEBNeGdKAAAAAAAAAACasa9drpo1a1buv//+rLrqqll99dUbIlOViy66KCeccEIOPfTQTJs2Lcsuu2wOPvjgnHjiiQ36PJSXahUAAAAAAAAAAE1RvctVu+22WzbddNMcdthh+eSTT7LeeuvlrbfeSlEUueGGG7LLLrs0WLjOnTtn7NixGTt2bIPdEwAAAAAAAAAAoC5a1PeCCRMmZJNNNkmS3HbbbSmKIjNnzsyFF16Y0047rcEDAgAAAAAAAAAAlEO9y1UffvhhevTokSS5++67s8suu6RDhw7ZfvvtM3ny5AYPSDNgX0AAAAAAAAAAAJqgeper+vbtm8ceeyyzZ8/O3XffnW222SZJMmPGjLRr167BA7LkK7SrAAAAAAAAAABoglrV94JRo0Zlzz33TKdOndKvX79svvnmST7fLnCttdZq6HwAAAAAAAAAAABlUe9y1aGHHpoNNtggf//737P11lunRYvPF79aaaWVcvrppzd4QJZ8hYWrAAAAAAAAAABoguq9LeApp5yS1VdfPd/73vfSqVOnquNbbrll7r333gYNBwAAAAAAAAAAUC71LleNGTMmH3/8cY3jc+bMyZgxYxokFM2LlasAAAAAAAAAAGiK6l2uKooipVKpxvHnn38+PXr0aJBQAAAAAAAAAAAA5daqrgO7d++eUqmUUqmUVVZZpVrBav78+fn444/z4x//uFFCsmQrYukqAAAAAAAAAACanjqXq8aOHZuiKLLffvtlzJgx6dq1a9W5Nm3aZMUVV8yQIUMaJSQAAAAAAAAAAMDiVudy1T777JMk6d+/fzbaaKO0alXnSwEAAAAAAAAAAP7rtKjvBbNnz859991X4/i4ceNy1113NUgompfCroAAAAAAAAAAADRB9S5XjR49OvPnz69xvCiKjB49ukFC0bzoVgEAAAAAAAAA0BTVu1w1efLkrLHGGjWOr7baann99dcbJBQAAAAAAAAAAEC51btc1bVr17z55ps1jr/++uvp2LFjg4SiebEtIAAAAAAAAAAATVG9y1U77bRTRo0alTfeeKPq2Ouvv56f/vSn2XHHHRs0HAAAAAAAAAAAQLnUu1x19tlnp2PHjllttdXSv3//9O/fP6uvvnqWWmqpnHvuuY2RkSWepasAAAAAAAAAAGh6WtX3gq5du+bRRx/N+PHj8/zzz6d9+/YZPHhwNt1008bIBwAAAAAAAAAAUBb1LlclSalUyjbbbJNNN900bdu2TalUauhcNCOFhasAAAAAAAAAAGiC6r0tYGVlZU499dQst9xy6dSpU6ZMmZIkOeGEE/Kb3/ymwQMCAAAAAAAAAACUQ73LVaeddlquvvrqnH322WnTpk3V8TXXXDNXXnllg4ajebBwFQAAAAAAAAAATVG9y1XXXnttrrjiiuy5555p2bJl1fFvfOMbeeWVVxo0HM1DYV9AAAAAAAAAAACaoHqXq959990MGDCgxvHKyspUVFQ0SCgAAAAAAAAAAIByq3e5ao011shf//rXGsdvvvnmfPOb32yQUAAAAAAAAAAAAOXWqr4XnHjiidlnn33y7rvvprKyMrfeemteffXVXHvttfnzn//cGBkBAAAAAAAAAAAWu3qvXLXTTjvljjvuyL333puOHTvmxBNPzKRJk3LHHXdk6623boyMLOGKcgcAAAAAAAAAAIBa1HvlqiTZZJNNMn78+IbOQjNVaFcBAAAAAAAAANAE1XvlKgAAAAAAAAAAgOagTitX9ejRI6+99lqWXnrpdO/ePaVSaaFjO3XqlEGDBuWss87K4MGDGywoSy4LVwEAAAAAAAAA0BTVqVz1q1/9Kp07d06SjB079kvHzp07N3feeWdGjBiRp59++msHBAAAAAAAAAAAKIc6lav22WefWr9emO222y7rrrvuoqeiWSkKa1cBAAAAAAAAAND01KlcVZuJEydm0qRJSZLVV1896623XtW5vn37Ztq0aV8/Hc1Cp7aL/DEEAAAAAAAAAIBGU+9Wyz/+8Y/sscceeeSRR9KtW7ckycyZM7PhhhvmhhtuyPLLL9/QGVnC7fzN5XLXS1PLHQMAAAAAAAAAAKppUd8LDjjggFRUVGTSpEmZPn16pk+fnkmTJqWysjIHHHBAY2RkCdehTcskyXIdbA8IAAAAAAAAAEDTUe+Vqx566KE8+uijWXXVVauOrbrqqrnooouyySabNGg4modCpwoAAAAAAAAAgCao3itX9e3bNxUVFTWOz58/P8suu2yDhAIAAAAAAAAAACi3eperzjnnnPzkJz/JxIkTq45NnDgxRxxxRM4999wGDQcAAAAAAAAAAFAuddoWsHv37imVSlWPZ8+enQ022CCtWn1++bx589KqVavst99+2XnnnRslKAAAAAAAAAAAwOJUp3LV2LFjGzkGAAAAAAAAAABA01KnctU+++zT2DloxopyBwAAAAAAAAAAgFrUqVz1Re+++25uueWWvPbaa0mSVVddNd///vez3HLLNXg4mpcv7DwJAAAAAAAAAABlV69y1SWXXJKjjjoqn332Wbp06ZIkmTVrVo4++uicf/75OfTQQxslJAAAAAAAAAAAwOLWoq4D//KXv+Twww/PYYcdlnfffTczZ87MzJkz8+677+bQQw/NEUcckTvvvLMxswIAAAAAAAAAACw2dV656pxzzsno0aNz2mmnVTvep0+fnH/++enQoUPOPvvsfOc732nwkAAAAAAAAAAAAItbnVeueuaZZ/KjH/1ooed/9KMf5ZlnnmmQUDQvRVGUOwIAAAAAAAAAANRQ53LV/Pnz07p164Web926debPn98goQAAAAAAAAAAAMqtzuWqQYMG5fbbb1/o+T/96U8ZNGhQg4QCAAAAAAAAAAAot1Z1HThy5Mgccsghadu2bQ466KC0avX5pfPmzcvll1+eX/ziF7nkkksaLSgAAAAAAAAAAMDiVOdy1T777JMXX3wxhx12WI499tisvPLKKYoib775Zj7++OMcfvjh2XfffRsxKkuqotwBAAAAAAAAAACgFnUuVyXJueeem1133TV/+MMfMnny5CTJZpttluHDh+fb3/52owQEAAAAAAAAAAAoh3qVq5Lk29/+tiIVjaJU7gAAAAAAAAAAAPAFLcodAAAAAAAAAAAAoClSrgIAAAAAAAAAAKiFchXlV5Q7AAAAAAAAAAAA1KRcBQAAAAAAAAAAUAvlKgAAAAAAAAAAgFq0qsugb37zmymVSnW64TPPPPO1AgEAAAAAAAAAADQFdSpX7bzzzlVff/rpp7nkkkuyxhprZMiQIUmSxx9/PH/7299y6KGHNkpIAAAAAAAAAACAxa1O5aqTTjqp6usDDjgghx9+eE499dQaY955552GTUezUKQodwQAAAAAAAAAAKihRX0vuOmmm7L33nvXOL7XXnvllltuaZBQNE9123gSAAAAAAAAAAAWj3qXq9q3b59HHnmkxvFHHnkk7dq1a5BQAAAAAAAAAAAA5VanbQG/aNSoUTnkkEPyzDPPZP3110+SPPHEE/ntb3+bE044ocEDAgAAAAAAAAAAlEO9y1WjR4/OSiutlAsuuCC///3vkySrr756rrrqquy2224NHpAlX1GUOwEAAAAAAAAAANRU73JVkuy2226KVAAAAAAAAAAAwBKtxaJcNHPmzFx55ZU57rjjMn369CTJM888k3fffbdBw9G8lErlTgAAAAAAAAAAAP+n3itXvfDCCxk6dGi6du2at956KwcccEB69OiRW2+9NX//+99z7bXXNkZOAAAAAAAAAACAxareK1cdddRR2XfffTN58uS0a9eu6vh3vvOdTJgwoUHDAQAAAAAAAAAAlEu9y1VPPfVUDj744BrHl1tuuUydOrVBQn3Ru+++m7322itLLbVU2rdvn7XWWisTJ05s8OehfIqi3AkAAAAAAAAAAKCmem8L2LZt28yaNavG8ddeey3LLLNMg4RaYMaMGdloo42yxRZb5K677soyyyyTyZMnp3v37g36PAAAAAAAAAAAAP+p3uWqHXfcMaecckpuvPHGJEmpVMrf//73HHPMMdlll10aNNxZZ52Vvn375qqrrqo61r9//wZ9DpqO+VawAgAAAAAAAACgCal3ueq8887Lrrvump49e+aTTz7JZpttlqlTp2bIkCE5/fTTGzTc//7v/2bYsGH5wQ9+kIceeijLLbdcDj300Bx44IELvWbu3LmZO3du1eMFq2xVVFSkoqKiQfPRMMa//Pl2kv+YXfI9AoAl2IJ53nwPAEs2cz4ANA/mfABoHsz5LMnq+rkuFUWxSOsFPfzww3nhhRfy8ccfZ5111snQoUMX5TZfql27dkmSo446Kj/4wQ/y1FNP5Ygjjshll12WffbZp9ZrTj755IwZM6bG8euvvz4dOnRo8Ix8faMea5kipSTJBUPmlTkNAAAAAAAAAABLujlz5uSHP/xhPvzww3Tp0mWh4xa5XLU4tGnTJuutt14effTRqmOHH354nnrqqTz22GO1XlPbylV9+/bN+++//6VvBOUz8IR7qr5++cQt0rp16zKmAQAaS0VFRcaPH5+tt97afA8ASzBzPgA0D+Z8AGgezPksyWbNmpWll176K8tV9d4WMEnuu+++3HfffZk2bVoqKyurnfvtb3+7KLesVZ8+fbLGGmtUO7b66qvnlltuWeg1bdu2Tdu2bWscb926tb/o/wV8nwBgyWe+B4DmwZwPAM2DOR8AmgdzPkuiun6m612uGjNmTE455ZSst9566dOnT0qlUr3D1dVGG22UV199tdqx1157Lf369Wu05wQAAAAAAAAAAEgWoVx12WWX5eqrr86PfvSjxshTzZFHHpkNN9wwv/zlL7PbbrvlySefzBVXXJErrrii0Z8bAAAAAAAAAABo3lrU94LPPvssG264YWNkqeFb3/pWbrvttvzhD3/ImmuumVNPPTVjx47NnnvuuVieHwAAAAAAAAAAaL7qXa464IADcv311zdGllp997vfzYsvvphPP/00kyZNyoEHHrjYnhsAAAAAAAAAAGi+6rQt4FFHHVX1dWVlZa644orce++9GTx4cFq3bl1t7Pnnn9+wCQEAAAAAAAAAAMqgTuWqZ599ttrjtddeO0ny0ksvVTteKpUaJhUAAAAAAAAAAECZ1alc9cADDzR2DgAAAAAAAAAAgCalRX0v+PDDDzN9+vQax6dPn55Zs2Y1SCgAAAAAAAAAAIByq3e5avjw4bnhhhtqHL/xxhszfPjwBgkFAAAAAAAAAABQbvUuVz3xxBPZYostahzffPPN88QTTzRIKAAAAAAAAAAAgHKrd7lq7ty5mTdvXo3jFRUV+eSTTxokFAAAAAAAAAAAQLnVu1y1/vrr54orrqhx/LLLLsu6667bIKEAAAAAAAAAAADKrVV9LzjttNMydOjQPP/889lqq62SJPfdd1+eeuqp3HPPPQ0eEAAAAAAAAAAAoBzqvXLVRhttlMceeyx9+/bNjTfemDvuuCMDBgzICy+8kE022aQxMgIAAAAAAAAAACx29V65KknWXnvtXHfddQ2dBQAAAAAAAAAAoMlYpHLVAp9++mk+++yzase6dOnytQIBAAAAAAAAAAA0BfXeFnDOnDk57LDD0rNnz3Ts2DHdu3ev9gcAAAAAAAAAAGBJUO9y1dFHH537778/l156adq2bZsrr7wyY8aMybLLLptrr722MTICAAAAAAAAAAAsdvXeFvCOO+7Itddem8033zwjRozIJptskgEDBqRfv3657rrrsueeezZGTgAAAAAAAAAAgMWq3itXTZ8+PSuttFKSpEuXLpk+fXqSZOONN86ECRMaNh0AAAAAAAAAAECZ1LtctdJKK2XKlClJktVWWy033nhjks9XtOrWrVuDhgMAAAAAAAAAACiXeperRowYkeeffz5JMnr06Fx88cVp165djjzyyBx99NENHhAAAAAAAAAAAKAcWtX3giOPPLLq66FDh+aVV17J008/nQEDBmTw4MENGg4AAAAAAAAAAKBc6l2u+k/9+vVLv379GiILAAAAAAAAAABAk1HnbQHvv//+rLHGGpk1a1aNcx9++GEGDRqUv/71rw0aDgAAAAAAAAAAoFzqXK4aO3ZsDjzwwHTp0qXGua5du+bggw/O+eef36DhAAAAAAAAAAAAyqXO5arnn38+22677ULPb7PNNnn66acbJBQAAAAAAAAAAEC51blc9d5776V169YLPd+qVav8+9//bpBQAAAAAAAAAAAA5VbnctVyyy2Xl156aaHnX3jhhfTp06dBQgEAAAAAAAAAAJRbnctV3/nOd3LCCSfk008/rXHuk08+yUknnZTvfve7DRoOAAAAAAAAAACgXFrVdeAvfvGL3HrrrVlllVVy2GGHZdVVV02SvPLKK7n44oszf/78HH/88Y0WFAAAAAAAAAAAYHGqc7mqV69eefTRR3PIIYfk2GOPTVEUSZJSqZRhw4bl4osvTq9evRotKAAAAAAAAAAAwOJU53JVkvTr1y933nlnZsyYkddffz1FUWTgwIHp3r17Y+UDAAAAAAAAAAAoi3qVqxbo3r17vvWtbzV0FgAAAAAAAAAAgCajRbkDAAAAAAAAAAAANEXKVZRd/6U7ljsCAAAAAAAAAADUoFxF2Y3YaMUkSatSUd4gAAAAAAAAAADwBXUqV62zzjqZMWNGkuSUU07JnDlzGjUUzUuHNq2SJAO7KlcBAAAAAAAAANB01KlcNWnSpMyePTtJMmbMmHz88ceNGgoAAAAAAAAAAKDcWtVl0Nprr50RI0Zk4403TlEUOffcc9OpU6dax5544okNGhAAAAAAAAAAAKAc6lSuuvrqq3PSSSflz3/+c0qlUu666660alXz0lKppFwFAAAAAAAAAAAsEepUrlp11VVzww03JElatGiR++67Lz179mzUYAAAAAAAAAAAAOVUp3LVF1VWVjZG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TZ1yFWVXFOVOAAAAAAAAAAA0N2+++WbWW2+9TJ48OX/4wx/y+uuv57LLLst9992XIUOGZPr06fW63zLLLJMOHTo0UtpF0xCZJk6cmHXXXTevvfZaLr/88rz88su57bbbstpqq+WnP/1pAyVtupSraDJK5Q4AAAAAAAAAAHxtRVFkzmfzyvKnqMcKLyNHjkybNm1yzz33ZLPNNssKK6yQ7bbbLvfee2/efffdHH/88dXGf/TRR9ljjz3SsWPHLLfccrn44ournf/PlaZmzpyZAw44IMsss0y6dOmSLbfcMs8//3y1a+64445861vfSrt27bL00kvne9/7XpJk8803z9tvv50jjzwypVIppdLnrYq33347O+ywQ7p3756OHTtm0KBBufPOOxf6Gv8zU6lUypVXXpnvfe976dChQwYOHJj//d//Xej1RVFk3333zcCBA/PXv/4122+/fVZeeeWsvfbaOemkk3L77bdXjT3mmGOyyiqrpEOHDllppZVywgknpKKiok6vd4E5c+Zkv/32S+fOnbPCCivkiiuuqHb+nXfeyW677ZZu3bqlR48e2WmnnfLWW28tNH9DaNWodwcAAAAAAAAAoFn5pGJ+1jhxXFme++VThqVDm6+uw0yfPj3jxo3L6aefnvbt21c717t37+y555754x//mEsuuaSq2HTOOefkuOOOy5gxYzJu3LgcccQRWWWVVbL11lvX+hw/+MEP0r59+9x1113p2rVrLr/88my11VZ57bXX0qNHj/zlL3/J9773vRx//PG59tpr89lnn1UVpW699dZ84xvfyEEHHZQDDzyw6p4jR47MZ599lgkTJqRjx455+eWX06lTp3q9R2PGjMnZZ5+dc845JxdddFH23HPPvP322+nRo0eNsc8991z+9re/5frrr0+LFjXXcOrWrVvV1507d87VV1+dZZddNi+++GIOPPDAdO7cOT//+c+T5Etf7wLnnXdeTj311Bx33HG5+eabc8ghh2SzzTbLqquumoqKigwbNixDhgzJX//617Rq1SqnnXZatt1227zwwgtp06ZNvd6HulKuAgAAAAAAAACgWZk8eXKKosjqq69e6/nVV189M2bMyL///e/07NkzSbLRRhtl9OjRSZJVVlkljzzySH71q1/VWq56+OGH8+STT2batGlp27ZtkuTcc8/Nn/70p9x888056KCDcvrpp2f48OEZM2ZM1XXf+MY3kiQ9evRIy5Yt07lz5/Tu3bvq/N///vfssssuWWuttZIkK620Ur1f+7777ps99tgjSfLLX/4yF154YZ588slsu+22tb5PSbLaaqt95X1/8YtfVH294oor5mc/+1luuOGGqnLVl73eBb7zne/k0EMPTfL5Sli/+tWv8sADD2TVVVfNH//4x1RWVubKK6+sKrxdddVV6datWx588MFss8029Xkb6ky5CgAAAAAAAACABtO+dcu8fMqwsj13fdRnG8EhQ4bUePzFLfe+6Pnnn8/HH3+cpZZaqtrxTz75JG+88UaSz1eF+uKqVHVx+OGH55BDDsk999yToUOHZpdddsngwYPrdY8vju/YsWO6dOmSadOm1Tq2Pu/PH//4x1x44YV544038vHHH2fevHnp0qVL1fm6vN4vZiuVSundu3dVtueffz6vv/56OnfuXO2aTz/9tOo9bQzKVQAAAAAAAAAANJhSqVSnrfnKacCAASmVSpk0aVK+973v1Tg/adKkdO/ePcsss8wi3f/jjz9Onz598uCDD9Y4t2Arvf/cjrAuDjjggAwbNix/+ctfcs899+SMM87Ieeedl5/85Cd1vkfr1q2rPS6VSqmsrKx17CqrrJIkeeWVV/LNb35zofd87LHHsueee2bMmDEZNmxYunbtmhtuuCHnnXde1Zi6vN4vy/bxxx9n3XXXzXXXXVfjukX9PtVFzc0QAQAAAAAAAABgCbbUUktl6623ziWXXJJPPvmk2rmpU6fmuuuuy+677161/VySPP7449XGPf744wvdVnCdddbJ1KlT06pVqwwYMKDan6WXXjrJ56s03XfffQvN2KZNm8yfP7/G8b59++bHP/5xbr311vz0pz/Nr3/96zq/7vpae+21s8Yaa+S8886rtYA1c+bMJMmjjz6afv365fjjj896662XgQMH5u2336429qte71dZZ511Mnny5PTs2bPGe9q1a9dFvu9XUa6i7LYf3CfX7Ltutly29hYkAAAAAAAAAEBD+5//+Z/MnTs3w4YNy4QJE/LOO+/k7rvvztZbb53lllsup59+erXxjzzySM4+++y89tprufjii3PTTTfliCOOqPXeQ4cOzZAhQ7LzzjvnnnvuyVtvvZVHH300xx9/fCZOnJgkOemkk/KHP/whJ510UiZNmpQXX3wxZ511VtU9VlxxxUyYMCHvvvtu3n///STJqFGjMm7cuEyZMiXPPPNMHnjggYUWvBpCqVTKVVddlddeey2bbLJJ7rzzzrz55pt54YUXcvrpp2ennXZKkgwcODB///vfc8MNN+SNN97IhRdemNtuu63avb7q9X6VPffcM0svvXR22mmn/PWvf82UKVPy4IMP5vDDD88//vGPBn3dX6RcRdkt371DNlx5qfTpUO4kAAAAAAAAAEBzMXDgwEycODErrbRSdtttt6y88so56KCDssUWW+Sxxx5Ljx49qo3/6U9/mokTJ+ab3/xmTjvttJx//vkZNmxYrfculUq58847s+mmm2bEiBFZZZVVMnz48Lz99tvp1atXkmTzzTfPTTfdlP/93//N2muvnS233DJPPvlk1T1OOeWUvPXWW1l55ZWrtr2bP39+Ro4cmdVXXz3bbrttVllllVxyySWN9A59bv3118/EiRMzYMCAHHjggVl99dWz44475m9/+1vGjh2bJNlxxx1z5JFH5rDDDsvaa6+dRx99NCeccEK1+3zV6/0qHTp0yIQJE7LCCivk+9//flZfffXsv//++fTTT9OlS5eGfMnVlIqiKBrt7k3ArFmz0rVr13z44YeN+kby9VRUVOTOO+/Md77znRr7ZwIASwbzPQA0D+Z8AGgezPkA0DzUdc7/9NNPM2XKlPTv3z/t2rVbjAmblj59+uTUU0/NAQccUO4o/H9f9tmsa6eoVWOHBAAAAAAAAACAJdWcOXPyyCOP5L333sugQYPKHYcGZltAAAAAAAAAAABYRFdccUWGDx+eUaNGZciQIeWOQwOzchUAAAAAAAAAACyiUaNGZdSoUeWOQSOxchUAAAAAAAAAAEAtlKsAAAAAAAAAAPjaiqIodwSopiE+k8pVAAAAAAAAAAAsstatWydJ5syZU+YkUN2Cz+SCz+iiaNVQYQAAAAAAAAAAaH5atmyZbt26Zdq0aUmSDh06pFQqlTkVzVlRFJkzZ06mTZuWbt26pWXLlot8L+UqAAAAAAAAAAC+lt69eydJVcEKmoJu3bpVfTYXlXIVAAAAAAAAAABfS6lUSp8+fdKzZ89UVFSUOw6kdevWX2vFqgWUqwAAAAAAAAAAaBAtW7ZskEILNBUtyh0AAAAAAAAAAACgKVKuAgAAAAAAAAAAqIVyFQAAAAAAAAAAQC1alTtAYyuKIkkya9asMifhy1RUVGTOnDmZNWtWWrduXe44AEAjMN8DQPNgzgeA5sGcDwDNgzmfJdmCLtGCbtHCLPHlqo8++ihJ0rdv3zInAQAAAAAAAAAAmpKPPvooXbt2Xej5UvFV9av/cpWVlfnnP/+Zzp07p1QqlTsOCzFr1qz07ds377zzTrp06VLuOABAIzDfA0DzYM4HgObBnA8AzYM5nyVZURT56KOPsuyyy6ZFixYLHbfEr1zVokWLLL/88uWOQR116dLFD2QAWMKZ7wGgeTDnA0DzYM4HgObBnM+S6stWrFpg4bUrAAAAAAAAAACAZky5CgAAAAAAAAAAoBbKVTQJbdu2zUknnZS2bduWOwoA0EjM9wDQPJjzAaB5MOcDQPNgzoekVBRFUe4QAAAAAAAAAAAATY2VqwAAAAAAAAAAAGqhXAUAAAAAAAAAAFAL5SoAAAAAAAAAAIBaKFcBAAAAAAAAAADUQrmKsrv44ouz4oorpl27dtlggw3y5JNPljsSAPD/TZgwITvssEOWXXbZlEql/OlPf6p2viiKnHjiienTp0/at2+foUOHZvLkydXGTJ8+PXvuuWe6dOmSbt26Zf/998/HH39cbcwLL7yQTTbZJO3atUvfvn1z9tln18hy0003ZbXVVku7du2y1lpr5c4772zw1wsAzdEZZ5yRb33rW+ncuXN69uyZnXfeOa+++mq1MZ9++mlGjhyZpZZaKp06dcouu+yS9957r9qYv//979l+++3ToUOH9OzZM0cffXTmzZtXbcyDDz6YddZZJ23bts2AAQNy9dVX18jj9wQA0DguvfTSDB48OF26dEmXLl0yZMiQ3HXXXVXnzfcAsOQ588wzUyqVMmrUqKpj5nyoP+UqyuqPf/xjjjrqqJx00kl55pln8o1vfCPDhg3LtGnTyh0NAEgye/bsfOMb38jFF19c6/mzzz47F154YS677LI88cQT6dixY4YNG5ZPP/20asyee+6Zv/3tbxk/fnz+/Oc/Z8KECTnooIOqzs+aNSvbbLNN+vXrl6effjrnnHNOTj755FxxxRVVYx599NHsscce2X///fPss89m5513zs4775yXXnqp8V48ADQTDz30UEaOHJnHH38848ePT0VFRbbZZpvMnj27asyRRx6ZO+64IzfddFMeeuih/POf/8z3v//9qvPz58/P9ttvn88++yyPPvporrnmmlx99dU58cQTq8ZMmTIl22+/fbbYYos899xzGTVqVA444ICMGzeuaozfEwBA41l++eVz5pln5umnn87EiROz5ZZbZqeddsrf/va3JOZ7AFjSPPXUU7n88sszePDgasfN+bAICiij9ddfvxg5cmTV4/nz5xfLLrtsccYZZ5QxFQBQmyTFbbfdVvW4srKy6N27d3HOOedUHZs5c2bRtm3b4g9/+ENRFEXx8ssvF0mKp556qmrMXXfdVZRKpeLdd98tiqIoLrnkkqJ79+7F3Llzq8Ycc8wxxaqrrlr1eLfddiu23377ank22GCD4uCDD27Q1wgAFMW0adOKJMVDDz1UFMXn83vr1q2Lm266qWrMpEmTiiTFY489VhRFUdx5551FixYtiqlTp1aNufTSS4suXbpUzfE///nPi0GDBlV7rt13370YNmxY1WO/JwCAxat79+7FlVdeab4HgCXMRx99VAwcOLAYP358sdlmmxVHHHFEURT+Gx8WlZWrKJvPPvssTz/9dIYOHVp1rEWLFhk6dGgee+yxMiYDAOpiypQpmTp1arW5vGvXrtlggw2q5vLHHnss3bp1y3rrrVc1ZujQoWnRokWeeOKJqjGbbrpp2rRpUzVm2LBhefXVVzNjxoyqMV98ngVj/JsBABrehx9+mCTp0aNHkuTpp59ORUVFtbl4tdVWyworrFBtzl9rrbXSq1evqjHDhg3LrFmzqlbD+Kr53O8JAGDxmT9/fm644YbMnj07Q4YMMd8DwBJm5MiR2X777WvMy+Z8WDStyh2A5uv999/P/Pnzq/1QTpJevXrllVdeKVMqAKCupk6dmiS1zuULzk2dOjU9e/asdr5Vq1bp0aNHtTH9+/evcY8F57p3756pU6d+6fMAAA2jsrIyo0aNykYbbZQ111wzyefzcZs2bdKtW7dqY/9zzq9trl5w7svGzJo1K5988klmzJjh9wQA0MhefPHFDBkyJJ9++mk6deqU2267LWussUaee+458z0ALCFuuOGGPPPMM3nqqadqnPPf+LBolKsAAAAASPL5/9n60ksv5eGHHy53FACgEay66qp57rnn8uGHH+bmm2/OPvvsk4ceeqjcsQCABvLOO+/kiCOOyPjx49OuXbtyx4Elhm0BKZull146LVu2zHvvvVft+HvvvZfevXuXKRUAUFcL5usvm8t79+6dadOmVTs/b968TJ8+vdqY2u7xxedY2Bj/ZgCAhnPYYYflz3/+cx544IEsv/zyVcd79+6dzz77LDNnzqw2/j/n/EWdz7t06ZL27dv7PQEALAZt2rTJgAEDsu666+aMM87IN77xjVxwwQXmewBYQjz99NOZNm1a1llnnbRq1SqtWrXKQw89lAsvvDCtWrVKr169zPmwCJSrKJs2bdpk3XXXzX333Vd1rLKyMvfdd1+GDBlSxmQAQF30798/vXv3rjaXz5o1K0888UTVXD5kyJDMnDkzTz/9dNWY+++/P5WVldlggw2qxkyYMCEVFRVVY8aPH59VV1013bt3rxrzxedZMMa/GQDg6yuKIocddlhuu+223H///TW261133XXTunXranPxq6++mr///e/V5vwXX3yxWql6/Pjx6dKlS9ZYY42qMV82n/s9AQAsfpWVlZk7d675HgCWEFtttVVefPHFPPfcc1V/1ltvvey5555VX5vzYREUUEY33HBD0bZt2+Lqq68uXn755eKggw4qunXrVkydOrXc0QCAoig++uij4tlnny2effbZIklx/vnnF88++2zx9ttvF0VRFGeeeWbRrVu34vbbby9eeOGFYqeddir69+9ffPLJJ1X32HbbbYtvfvObxRNPPFE8/PDDxcCBA4s99tij6vzMmTOLXr16FT/60Y+Kl156qbjhhhuKDh06FJdffnnVmEceeaRo1apVce655xaTJk0qTjrppKJ169bFiy++uPjeDABYQh1yyCFF165diwcffLD417/+VfVnzpw5VWN+/OMfFyussEJx//33FxMnTiyGDBlSDBkypOr8vHnzijXXXLPYZpttiueee664++67i2WWWaY49thjq8a8+eabRYcOHYqjjz66mDRpUnHxxRcXLVu2LO6+++6qMX5PAACNZ/To0cVDDz1UTJkypXjhhReK0aNHF6VSqbjnnnuKojDfA8CSarPNNiuOOOKIqsfmfKg/5SrK7qKLLipWWGGFok2bNsX6669fPP744+WOBAD8fw888ECRpMafffbZpyiKoqisrCxOOOGEolevXkXbtm2Lrbbaqnj11Ver3eODDz4o9thjj6JTp05Fly5dihEjRhQfffRRtTHPP/98sfHGGxdt27YtlltuueLMM8+skeXGG28sVllllaJNmzbFoEGDir/85S+N9roBoDmpba5PUlx11VVVYz755JPi0EMPLbp371506NCh+N73vlf861//qnaft956q9huu+2K9u3bF0svvXTx05/+tKioqKg25oEHHijWXnvtok2bNsVKK61U7TkW8HsCAGgc++23X9GvX7+iTZs2xTLLLFNstdVWVcWqojDfA8CS6j/LVeZ8qL9SURRFedbMAgAAAAAAAAAAaLpalDsAAAAAAAAAAABAU6RcBQAAAAAAAAAAUAvlKgAAAAAAAAAAgFooVwEAAAAAAAAAANRCuQoAAAAAAAAAAKAWylUAAAAAAAAAAAC1UK4CAAAAAAAAAACohXIVAAAAAAAAAABALZSrAAAAAGjS9t133+y8885le/4f/ehH+eUvf1mnscOHD895553XyIkAAAAAWFxKRVEU5Q4BAAAAQPNUKpW+9PxJJ52UI488MkVRpFu3bosn1Bc8//zz2XLLLfP222+nU6dOXzn+pZdeyqabbpopU6aka9euiyEhAAAAAI1JuQoAAACAspk6dWrV13/84x9z4okn5tVXX6061qlTpzqVmhrLAQcckFatWuWyyy6r8zXf+ta3su+++2bkyJGNmAwAAACAxcG2gAAAAACUTe/evav+dO3aNaVSqdqxTp061dgWcPPNN89PfvKTjBo1Kt27d0+vXr3y61//OrNnz86IESPSuXPnDBgwIHfddVe153rppZey3XbbpVOnTunVq1d+9KMf5f33319otvnz5+fmm2/ODjvsUO34JZdckoEDB6Zdu3bp1atXdt1112rnd9hhh9xwww1f/80BAAAAoOyUqwAAAAD4r3PNNddk6aWXzpNPPpmf/OQnOeSQQ/KDH/wgG264YZ555pn8v/buGKTKLowD+N9MSiwQuhZJYESiEWZXImhpkLpTrUGDQ5BTIK1BODQ0NFZQU4Mg0lINDdaQQ7WUhF0qqBCyrSgxCC1B/aYuXLrxfcN3LeP3gwP3fe45nPOsL3/OWyqVMjAwkPn5+STJ3Nxc+vv7UywWMzk5mfHx8Xz48CEnTpz45R7lcjlfvnzJgQMHKrXJyckMDQ3lwoULef36dcbHx3P48OGqdQcPHsyTJ0/y/fv3+jQPAAAAwKoRrgIAAABgzent7c358+fT2dmZc+fOZePGjSkUChkcHExnZ2eGh4fz+fPnlMvlJMnVq1dTLBZz8eLFdHd3p1gs5saNG5mYmMibN29q7jEzM5PGxsZs3bq1Unv//n1aWlpy7NixdHR0pFgsZmhoqGpde3t7FhcXqz55CAAAAMDaJFwFAAAAwJqzb9++yu/GxsZs2bIlPT09ldq2bduSJB8/fkySPH/+PBMTE9m0aVNldHd3J0mmp6dr7rGwsJANGzakoaGhUjt69Gg6Ojqya9euDAwMZHR0tHI71g/Nzc1J8lMdAAAAgLVHuAoAAACANaepqanquaGhoar2IxC1vLycJPn69WuOHz+eqampqvH27dufPuv3Q6FQyPz8fBYXFyu1zZs359mzZxkbG8v27dszPDyc3t7ezM3NVebMzs4mSdra2v6XXgEAAAD4fYSrAAAAAPjr9fX15eXLl9m5c2d2795dNVpaWmqu2b9/f5Lk1atXVfX169fnyJEjuXTpUsrlct69e5cHDx5U/n/x4kV27NiRQqFQt34AAAAAWB3CVQAAAAD89c6cOZPZ2dmcPHkyT58+zfT0dO7du5dTp05laWmp5pq2trb09fXl0aNHldrdu3dz+fLlTE1NZWZmJiMjI1leXk5XV1dlzsOHD1MqlereEwAAAAD1J1wFAAAAwF+vvb09jx8/ztLSUkqlUnp6enL27Nm0trZm3bpfvyI7ffp0RkdHK8+tra25detW+vv7s2fPnly/fj1jY2PZu3dvkuTbt2+5c+dOBgcH694TAAAAAPXXsLKysvK7DwEAAAAAf6KFhYV0dXXl5s2bOXTo0L/Ov3btWm7fvp379++vwukAAAAAqDc3VwEAAADALzQ3N2dkZCSfPn36T/Obmppy5cqVOp8KAAAAgNXi5ioAAAAAAAAAAIAa3FwFAAAAAAAAAABQg3AVAAAAAAAAAABADcJVAAAAAAAAAAAANQhXAQAAAAAAAAAA1CBcBQAAAAAAAAAAUINwFQAAAAAAAAAAQA3CVQAAAAAAAAAAADUIVwEAAAAAAAAAANQgXAUAAAAAAAAAAFDDP0PRkfGX3Gu/AAAAAElFTkSuQmCC",
|
||
"text/plain": [
|
||
"<Figure size 3000x500 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"# Extract recorded data for plotting\n",
|
||
"times, cache_sizes = zip(*cache.cache_size_over_time)\n",
|
||
"\n",
|
||
"# Plot the cache size over time\n",
|
||
"plt.figure(figsize=(30, 5))\n",
|
||
"plt.plot(times, cache_sizes, label=\"Objects in Cache\")\n",
|
||
"plt.xlabel(\"Time (s)\")\n",
|
||
"plt.ylabel(\"Number of Cached Objects\")\n",
|
||
"plt.title(\"Number of Objects in Cache Over Time\")\n",
|
||
"plt.legend()\n",
|
||
"plt.grid(True)\n",
|
||
"plt.savefig(f\"{TEMP_BASE_DIR}/objects_in_cache_over_time.pdf\")\n",
|
||
"\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 21,
|
||
"id": "f30a0497-9b2e-4ea9-8ebf-6687de19aaa9",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAArMAAAIjCAYAAAAQgZNYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABDjklEQVR4nO3de1xVVf7/8fcB5YAaF0NBkMRb3hPTkbDUalA0s5zpoo4TaFbWWGZMF+0iXvqKpZVTWX7zm1p9pzQvWTOZZqSZSlpe8j4ZaZYJispFTVBYvz/6eb4dAYUjcFz6ej4e5zGetdfe+7PX2R7fs1t7H4cxxggAAACwkI+3CwAAAAA8RZgFAACAtQizAAAAsBZhFgAAANYizAIAAMBahFkAAABYizALAAAAaxFmAQAAYC3CLAAAAKxFmAWAKvD111+rS5cuql27thwOhzZt2uTtktxER0fr5ptv9nh9h8OhsWPHVl5B5bRnzx45HA5NmTLF420MHjxY0dHRlVZTZW+vLLNnz5bD4dCePXtcbef7OQIXA8IsYLFt27bpr3/9qyIjI+V0OhUREaFBgwZp27Zt3i7tknby5EndcccdOnz4sF566SW98847atSokbfLAoCLUg1vFwDAMwsXLtTAgQNVt25dDR06VI0bN9aePXv05ptvav78+ZozZ47+9Kc/ebvMS1JGRoZ+/PFHzZgxQ/fcc4+3y0EVmzFjhoqLi71dBnDJIswCFsrIyNBdd92lJk2aaOXKlapXr55r2cMPP6yuXbvqrrvu0ubNm9WkSRMvVlrS8ePHVatWLW+XUaUOHDggSQoODvZuIagWNWvW9HYJwCWNaQaAhSZPnqzjx4/rjTfecAuykhQaGqr//u//1rFjx/T888+7Ldu3b5+GDh2qiIgIOZ1ONW7cWA888IAKCwtdfXJycvTII48oOjpaTqdTDRs2VGJiorKzsyWVPm9PklasWCGHw6EVK1a42q6//nq1bdtW69evV7du3VSrVi09+eSTkqQPP/xQffr0cdXStGlTTZgwQUVFRW7bPb2N7du364YbblCtWrUUGRlZ4tgk6cSJExo7dqyuvPJK+fv7q0GDBvrzn/+sjIwMV5/i4mJNnTpVbdq0kb+/v8LCwjRs2DAdOXKkXGP/+eefq2vXrqpdu7aCg4N16623aseOHa7lgwcPVvfu3SVJd9xxhxwOh66//vqzbjMnJ0cjR45UVFSUnE6nmjVrpueee67E1b4pU6aoS5cuuvzyyxUQEKCOHTtq/vz5pW7zf//3f9W5c2fVqlVLISEh6tatmz799NMS/VatWqXOnTvL399fTZo00dtvv12ucTjTjz/+qL/97W9q0aKFAgICdPnll+uOO+4ocZ6cPn9WrVqlESNGqF69egoODtawYcNUWFionJwcJSYmKiQkRCEhIXr88cdljCl1ny+99JIaNWqkgIAAde/eXVu3bi3RZ9GiRWrbtq38/f3Vtm1bffDBB6VuqyJje6Yz58z+fl7vG2+8oaZNm8rpdOoPf/iDvv7663Jtc9u2bbrxxhsVEBCghg0b6tlnnz3r1d9PP/1UMTEx8vf3V+vWrbVw4cJy7Qe4GHBlFrDQv/71L0VHR6tr166lLu/WrZuio6P18ccfu9p++eUXde7cWTk5ObrvvvvUsmVL7du3T/Pnz9fx48fl5+eno0ePqmvXrtqxY4fuvvtuXX311crOztZHH32kn3/+WaGhoRWu9dChQ+rdu7cGDBigv/71rwoLC5P0W6ipU6eOkpOTVadOHX3++ecaM2aM8vLyNHnyZLdtHDlyRL169dKf//xn3XnnnZo/f76eeOIJtWvXTr1795YkFRUV6eabb1ZaWpoGDBighx9+WPn5+Vq2bJm2bt2qpk2bSpKGDRum2bNna8iQIRoxYoR2796tV199VRs3btTq1avPepXts88+U+/evdWkSRONHTtWv/76q1555RVde+212rBhg6KjozVs2DBFRkZq4sSJGjFihP7whz+4jrk0x48fV/fu3bVv3z4NGzZMV1xxhdasWaPRo0dr//79mjp1qqvvP/7xD91yyy0aNGiQCgsLNWfOHN1xxx3697//rT59+rj6jRs3TmPHjlWXLl00fvx4+fn5ae3atfr888/Vs2dPV7/vv/9et99+u4YOHaqkpCTNnDlTgwcPVseOHdWmTZvyf8j67Ya3NWvWaMCAAWrYsKH27Nmj119/Xddff722b99e4mr8Qw89pPDwcI0bN05fffWV3njjDQUHB2vNmjW64oorNHHiRC1evFiTJ09W27ZtlZiY6Lb+22+/rfz8fA0fPlwnTpzQP/7xD914443asmWLa7w//fRT3XbbbWrdurVSU1N16NAhDRkyRA0bNixRf3nHtiLeffdd5efna9iwYXI4HHr++ef15z//WT/88MNZz7PMzEzdcMMNOnXqlEaNGqXatWvrjTfeUEBAQKn9d+3apf79++v+++9XUlKSZs2apTvuuENLlixRjx49PKodsIoBYJWcnBwjydx6661n7XfLLbcYSSYvL88YY0xiYqLx8fExX3/9dYm+xcXFxhhjxowZYySZhQsXltln1qxZRpLZvXu32/Lly5cbSWb58uWutu7duxtJZvr06SW2d/z48RJtw4YNM7Vq1TInTpwosY23337b1VZQUGDCw8PNbbfd5mqbOXOmkWRefPHFMmv/8ssvjSTzz3/+0235kiVLSm0/U0xMjKlfv745dOiQq+3bb781Pj4+JjEx0dV2eizmzZt31u0ZY8yECRNM7dq1zXfffefWPmrUKOPr62v27t3rajtzzAoLC03btm3NjTfe6GrbtWuX8fHxMX/6059MUVGRW//T42CMMY0aNTKSzMqVK11tBw4cME6n0/z9738/Z92STEpKSpm1GWNMenp6ic/u9PmTkJDgVk9cXJxxOBzm/vvvd7WdOnXKNGzY0HTv3t3Vtnv3biPJBAQEmJ9//tnVvnbtWiPJPPLII662mJgY06BBA5OTk+Nq+/TTT40k06hRI7dayzO2ZUlKSnLb3ukaL7/8cnP48GFX+4cffmgkmX/9619n3d7IkSONJLN27VpX24EDB0xQUFCJv3unP8cFCxa42nJzc02DBg1Mhw4dzlk7cDFgmgFgmfz8fEnSZZdddtZ+p5fn5eWpuLhYixYtUt++fdWpU6cSfR0OhyRpwYIFat++fak3jp3uU1FOp1NDhgwp0f77q0z5+fnKzs5W165ddfz4ce3cudOtb506dfTXv/7V9d7Pz0+dO3fWDz/84GpbsGCBQkND9dBDD5VZ+7x58xQUFKQePXooOzvb9erYsaPq1Kmj5cuXl3kc+/fv16ZNmzR48GDVrVvX1X7VVVepR48eWrx4cTlGo6R58+apa9euCgkJcaspPj5eRUVFWrlypavv78fsyJEjys3NVdeuXbVhwwZX+6JFi1RcXKwxY8bIx8f9K/7Mz7B169ZuV/fr1aunFi1auI1ref2+tpMnT+rQoUNq1qyZgoOD3eo7bejQoW71xMbGyhijoUOHutp8fX3VqVOnUuvp16+fIiMjXe87d+6s2NhY1+dw+vNKSkpSUFCQq1+PHj3UunXrs9Zf1thWVP/+/RUSEuJ6f3qszzW+ixcv1jXXXKPOnTu72urVq6dBgwaV2j8iIsLt72xgYKASExO1ceNGZWZmelw/YAumGQCWOR1ST4fasvw+9B48eFB5eXlq27btWdfJyMjQbbfdVjmF/n+RkZHy8/Mr0b5t2zY9/fTT+vzzz5WXl+e2LDc31+19w4YNSwSxkJAQbd682fU+IyNDLVq0UI0aZX+t7dq1S7m5uapfv36py0/fuFWaH3/8UZLUokWLEstatWqlpUuX6tixY6pdu3aZ2yirps2bN5eY+1xaTf/+97/17LPPatOmTSooKHC1/35sMjIy5OPjU2pgO9MVV1xRoi0kJKTc84d/79dff1VqaqpmzZqlffv2uc1zPfPzLG3fpwNnVFRUifbS6mnevHmJtiuvvFLvv/++pP/7vErr16JFixIhtTxjW1FnHuPpYHuu8f3xxx8VGxtbor20c0+SmjVrVqLOK6+8UtJv83fDw8PLXTNgI8IsYJmgoCA1aNDALciVZvPmzYqMjFRgYKB+/fXXStt/Wf+4n3nj1mmlzfPLyclR9+7dFRgYqPHjx6tp06by9/fXhg0b9MQTT5S40cXX17fUbZsybgwqS3FxserXr69//vOfpS4vK1BWpeLiYvXo0UOPP/54qctPh5Ivv/xSt9xyi7p166bXXntNDRo0UM2aNTVr1iy9++67Hu27ssZV+m0O7KxZszRy5EjFxcUpKChIDodDAwYMKPXGpbL2XVq7J/VURFWMrVS54wugbIRZwEI333yzZsyYoVWrVum6664rsfzLL7/Unj17NGzYMEm/hbTAwMBS7/b+vaZNm56zz+mrSzk5OW7tp6+ElceKFSt06NAhLVy4UN26dXO17969u9zbOFPTpk21du1anTx5ssyba5o2barPPvtM1157bZk305Tl9I8e/Oc//ymxbOfOnQoNDa3wVdnTNR09elTx8fFn7bdgwQL5+/tr6dKlcjqdrvZZs2aV2F5xcbG2b9+umJiYCtfjqfnz5yspKUkvvPCCq+3EiRMlzpPKsmvXrhJt3333neupAqc/r9L6nfkZlndsq0ujRo3KVfdp33//vYwxbv9H87vvvpOkavllMsDbmDMLWOixxx5TQECAhg0bpkOHDrktO3z4sO6//37VqlVLjz32mCTJx8dH/fr107/+9S998803JbZ3+krRbbfdpm+//bbUxxed7nP6qQC/n8tZVFSkN954o9z1n75i9fsrVIWFhXrttdfKvY0z3XbbbcrOztarr75aYtnp/dx5550qKirShAkTSvQ5derUWYNXgwYNFBMTo7feesut39atW/Xpp5/qpptu8qjuO++8U+np6Vq6dGmJZTk5OTp16pSk38bM4XC4XQHfs2ePFi1a5LZOv3795OPjo/Hjx5e4IlqVVwR9fX1LbP+VV14p84r9+Vq0aJH27dvner9u3TqtXbvW9XSL339ev5/msGzZMm3fvr1E7eUZ2+py00036auvvtK6detcbQcPHizzvyj88ssvbn9n8/Ly9PbbbysmJoYpBrgkcGUWsFDz5s311ltvadCgQWrXrl2JXwDLzs7We++95wqekjRx4kR9+umn6t69u+677z61atVK+/fv17x587Rq1SoFBwfrscce0/z583XHHXfo7rvvVseOHXX48GF99NFHmj59utq3b682bdrommuu0ejRo3X48GHVrVtXc+bMcYWu8ujSpYtCQkKUlJSkESNGyOFw6J133jmvsJWYmKi3335bycnJWrdunbp27apjx47ps88+09/+9jfdeuut6t69u4YNG6bU1FRt2rRJPXv2VM2aNbVr1y7NmzdP//jHP3T77beXuY/Jkyerd+/eiouL09ChQ12P5goKCtLYsWM9qvuxxx7TRx99pJtvvtn1WKxjx45py5Ytmj9/vvbs2aPQ0FD16dNHL774onr16qW//OUvOnDggKZNm6ZmzZq5TTlp1qyZnnrqKU2YMEFdu3bVn//8ZzmdTn399deKiIhQamqqR3Wey80336x33nlHQUFBat26tdLT0/XZZ5/p8ssvr5L9NWvWTNddd50eeOABFRQUaOrUqbr88svdpmukpqaqT58+uu6663T33Xfr8OHDeuWVV9SmTRsdPXrU1a+8Y1tdHn/8cb3zzjvq1auXHn74YdejuRo1alRqPVdeeaWGDh2qr7/+WmFhYZo5c6aysrK8dmUZqHbeeIQCgMqxefNmM3DgQNOgQQNTs2ZNEx4ebgYOHGi2bNlSav8ff/zRJCYmmnr16hmn02maNGlihg8fbgoKClx9Dh06ZB588EETGRlp/Pz8TMOGDU1SUpLJzs529cnIyDDx8fHG6XSasLAw8+STT5ply5aV+miuNm3alFrL6tWrzTXXXGMC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STHt27evvMIuEVyZvYilp6crODhYnTp1crXFx8fLx8dHa9euLfd2cnNzFRgYqBo13H9jY/jw4QoNDVXnzp01c+ZMGYsfWVxYWKj169crPj7e1ebj46P4+Hilp6eXuk56erpbf0lKSEhw9d+9e7cyMzPd+gQFBSk2NrbMbdrIk7E70/Hjx3Xy5EnVrVvXrX3FihWqX7++WrRooQceeECHDh2q1NovBJ6O39GjR9WoUSNFRUXp1ltv1bZt21zLOPfKf+69+eabGjBggGrXru3WfimcexV1ru+8yvg8LiXFxcXKz88v8b23a9cuRUREqEmTJho0aJD27t3rpQrtQZi9iGVmZqp+/fpubTVq1FDdunWVmZlZrm1kZ2drwoQJJaYmjB8/Xu+//76WLVum2267TX/729/0yiuvVFrt1S07O1tFRUWuX547LSwsrMyxyszMPGv/0/9bkW3ayJOxO9MTTzyhiIgIt38Ee/XqpbfffltpaWl67rnn9MUXX6h3794qKiqq1Pq9zZPxa9GihWbOnKkPP/xQ//u//6vi4mJ16dJFP//8syTOvfIe57p167R161bdc889bu2XyrlXUWV95+Xl5enXX3+tlO+CS8mUKVN09OhR3Xnnna622NhY1/S+119/Xbt371bXrl2Vn5/vxUovfF7/OVtU3KhRo/Tcc8+dtc+OHTvOez95eXnq06ePWrdurbFjx7ote+aZZ1x/7tChg44dO6bJkydrxIgR571fXFomTZqkOXPmaMWKFW43MQ0YMMD153bt2umqq65S06ZNtWLFCv3xj3/0RqkXjLi4OMXFxbned+nSRa1atdJ///d/a8KECV6szC5vvvmm2rVrp86dO7u1c+6hqr377rsaN26cPvzwQ7eLTr1793b9+aqrrlJsbKwaNWqk999/v9R7V/Abrsxa6O9//7t27Nhx1leTJk0UHh5eYtL9qVOndPjwYYWHh591H/n5+erVq5cuu+wyffDBB6pZs+ZZ+8fGxurnn39WQUHBeR+fN4SGhsrX11dZWVlu7VlZWWWOVXh4+Fn7n/7fimzTRp6M3WlTpkzRpEmT9Omnn+qqq646a98mTZooNDRU33///XnXfCE5n/E7rWbNmurQoYNrbDj3zn2cx44d05w5c8oVEC7Wc6+iyvrOCwwMVEBAQKWcy5eCOXPm6J577tH7779fYtrGmYKD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",
|
||
"text/plain": [
|
||
"<Figure size 800x600 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"from collections import Counter\n",
|
||
"# Count occurrences of each number\n",
|
||
"count = Counter([l.lambda_value for l in db.data.values()])\n",
|
||
"\n",
|
||
"# Separate the counts into two lists for plotting\n",
|
||
"x = list(count.keys()) # List of unique numbers\n",
|
||
"y = list(count.values()) # List of their respective counts\n",
|
||
"\n",
|
||
"# Plot the data\n",
|
||
"plt.figure(figsize=(8, 6))\n",
|
||
"plt.bar(x, y, color='skyblue')\n",
|
||
"\n",
|
||
"# Adding labels and title\n",
|
||
"plt.xlabel('Number')\n",
|
||
"plt.ylabel('Occurrences')\n",
|
||
"plt.title('Occurance of each lambda in db')\n",
|
||
"plt.savefig(f\"{TEMP_BASE_DIR}/lambda_distribution.pdf\")\n",
|
||
"\n",
|
||
"# Show the plot\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 22,
|
||
"id": "c192564b-d3c6-40e1-a614-f7a5ee787c4e",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAs0AAAIoCAYAAACSxtawAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB4SElEQVR4nO3deVxU5f4H8M+ZgZlhcdhkVQTS3BBXFDBzSRKNLM1ubhmp5YaaUpre3K2r2WppmZlLpWl60xLLDUMzcNdUTErFLR1ABQaQdc7z+8Mfcx1BBxAZGD/v14vXdc555sz3zBduHw7PPEcSQggQEREREdFdKSxdABERERFRTcfQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTEQPpZdffhmSJOH8+fP3fazz589DkiS8/PLL930sIiKqmRiaiahKlQTInj17WroUqgJ79uyBJEmQJAnr16+3dDk1TkZGBt5++22EhYXBzc0Ntra2cHd3R3h4OD799FPk5ORYusR76tq1KyRJsnQZRLUCQzMREd3VV199BQCQJAnLly+3cDU1S1xcHBo1aoTp06cjKysL//rXvzB58mT069cPV65cwfjx49GqVStLl0lEVcTG0gUQEVHNpNfrsWHDBrRs2RKenp7Yvn07Ll26BF9fX0uXZnF//PEHevfuDQD49ttvMXjw4FJj4uPjMXXq1OoujYgeEF5pJiKLycrKwrvvvosuXbrAx8cHKpUKPj4+eOmll3D27NlS42fNmgVJkhAfH48VK1YgKCgIdnZ2CAgIwCeffAIAEELggw8+QJMmTaDRaPDoo4/i66+/vmsNsixjwYIFePTRR6HRaBAQEIA5c+agqKio1FiDwYB3330XjRo1gkajQaNGjTBv3jzIslzmsX/99VcMGzYMTZo0gaOjIxwdHREcHIylS5eW+z3q3r07FAoFLly4UOb+8ePHQ5Ik7Nixw7jtv//9L7p06QIPDw9oNBr4+PggPDwc//3vf8v9ugDw3Xff4ebNm3jppZfw0ksvQZZlrFy58q7j09LS8Prrr6NJkyaws7ODq6srQkJC8P7775ca+8cff2Dw4MGoX78+1Go1vL290bNnT2zevLnU2B9//BHdu3eHi4sLNBoNWrRogffffx8Gg8FknCzLWLZsGTp06ABXV1fY2dmhfv366N27N+Lj403G3u97NH78eOTl5eHTTz8tMzADt6Y+3Pm6ALBixQqEhIQYvydCQkLKfF9XrlwJSZLK3BcfHw9JkjBr1iyT7ZIkoWvXrkhNTUVUVBTq1q0LOzs7hIaGlqpFkiTs3r3b+O+SL87NJ7oLQURUhVJSUgQAERERYXZsYmKiUKlUIiIiQowZM0ZMmjRJ9O7dWyiVSuHq6irOnz9vMn7mzJkCgHj22WeFk5OTeOmll8T48eNFvXr1BADx5ZdfijFjxghPT08xfPhwMXr0aOHi4iIAiN27d5scKyoqSgAQvXv3Fq6urmLUqFHijTfeEE2aNBEARL9+/UrVO2zYMAFABAQEiJiYGDFmzBhRt25d8fTTTwsAIioqymR8RESEaNiwoRg8eLB48803xciRI4Wfn58AIGJiYsr1fq5YsUIAEO+8806pfUVFRcLd3V34+PgIg8EghBDis88+EwCEt7e3GDFihJg6daoYOnSoCAwMFIMHDy7Xa5Zo3769UCqV4urVqyI3N1c4OjqKgIAAIctyqbGnT58W3t7eAoDo1KmTmDx5soiOjhZdu3YVLi4uJmM3bNggVCqVsLW1Fc8995yYOnWqGD58uGjRooV49tlnTcZOmTJFABD16tUTw4YNExMnThTBwcECgHj++edNxk6ePFkAEA0bNhTR0dFiypQpYsiQISIgIEC89dZbxnH3+x79/fffAoDw9fU1vu/lNW7cOOP5jB8/3uT7d/z48SZjS3q/YsWKUsf59ddfBQAxc+ZMk+0ARKtWrUSjRo1Eu3btxIQJE8SgQYOEUqkUKpVKnDhxwjh25syZxu/HmTNnGr82btxYoXMielgwNBNRlapIaM7MzBTXr18vtX3Xrl1CoVCIV155xWR7SWh2dXUVZ8+eNW6/ePGiUKlUwsnJSTRu3FikpaUZ9+3bt88Yjm9XEprd3d3FpUuXjNsLCgpE586dBQCxYcMG4/aSkNKqVSuRk5Nj3H758mVRt27dMkPzuXPnSp1bUVGRePLJJ4VSqRQXLlww8w4JodfrhZ2dnWjevHmpfZs3bxYAxBtvvGHc1rZtW6FSqURqamqp8deuXTP7eiWOHz9eqo8vvfSSACB27txZanxJkF26dGmpfbe/vzqdTjg4OAgHBwdx5MiRe47dvn27sYbb33NZlsWoUaNK9cjV1VX4+PiI3NzcUse9/fvsft+jlStXCgDixRdfNDv2drt37xYARLNmzURmZqZx+40bN0Tjxo0FALFnzx7j9sqGZgBizJgxJoF+2bJlAoAYOXKkyfguXboIXj8jKh9OzyAii3FycoKrq2up7d26dUNgYCB27txZ5vNee+01PPLII8bHvr6+6NSpE7KysvDWW2/B3d3duC8kJASPPPII/vjjj7seq379+sbHKpUK77zzDgCY/Fm8ZIrHjBkz4ODgYNxer149vPbaa2UeOyAgoNQ2GxsbjBo1CgaDAb/++muZz7tdnTp10KdPH5w6dQpHjhwx2ffNN98AAF588UWT7ba2trC1tS11LDc3N7OvV6LkA4AvvfSScVvJv0v2lThw4AAOHTqEzp0749VXXy11rNvf31WrViE3Nxevv/462rRpc8+xixYtAgAsXbrU5D2XJAnz58+HJEn47rvvTJ6vUqmgVCpLHffO77P7eY90Ol2pWstj1apVAG5NM3JycjJud3FxwcyZMwHgntNfysvBwQHvvvsuFIr//Sc+KioKNjY2OHjw4H0fn+hhxQ8CEpFFxcfH4+OPP8b+/ftx7do1FBcXG/epVKoyn9O6detS27y9ve+5b//+/WUe6/HHHy+1LSwsDDY2Njh69KhxW0noLmt8WdsAIDs7G++//z42bdqEs2fPIjc312T/lStXynzenYYMGYLvvvsO33zzDdq2bQvg1of0Nm/ejKCgIJMVGgYMGIDJkyejRYsWGDRoELp164ZOnTpBq9WW67UAoKCgAN9++y3q1KmDvn37Grd369YNvr6+2LhxIzIyMuDi4gLgVmgGgB49epg9dkXG7tu3Dw4ODnddtcPOzg6nT582Ph4wYAA+++wztGjRAgMGDEC3bt0QFhYGOzs7k+dVxXtUGSXfT127di21r1u3bgCAY8eO3ffrNG7cGI6OjibbbGxs4OnpiczMzPs+PtHDiqGZiCxm/fr16N+/PxwdHREREQF/f3/Y29sbP/x0tw+/lRVubGxs7rnv9jB+O09Pz1LblEol3NzckJWVZdyWlZUFhUKBunXrlusYhYWF6Nq1K44cOYI2bdpgyJAhcHNzg42NDc6fP49Vq1ahoKCgzJru1KNHD3h6emLt2rV4//33oVQqsWHDBuTl5WHIkCEmY9944w24ubnh888/xwcffID3338f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s58VeY0a893VvXt3nDhxAseOHTN+BQcHY/DgwcZ/29raIi4uzvic5ORkXLx4EWFhYQCAsLAwnDhxwmSVix07dkCr1aJ58+bGMbcfo2RMyTFUKhXatWtnMkaWZcTFxRnHEBEREdHDpcZcaa5Tpw5atGhhss3BwQFubm7G7cOHD0dMTAxcXV2h1Woxbtw4hIWFITQ0FADQo0cPNG/eHEOGDMGCBQug0+kwbdo0REdHG68Cjxo1CosWLcLkyZMxbNgw7Nq1C99//z22bNlifN2YmBhERUUhODgYHTp0wMcff4zc3FwMHTq0mt4NIiIiIqpJakxoLo+PPvoICoUC/fr1Q0FBASIiIvDZZ58Z9yuVSsTGxmL06NEICwuDg4MDoqKiMGfOHOOYgIAAbNmyBRMnTsTChQtRv359LFu2DBEREcYx/fv3R3p6OmbMmAGdTofWrVtj69atpT4cSEREREQPB0kIISxdhDXS6/VwcnJCVlZWhT8IWFNvH0kVw15aF/bTurCf1oO9tC7V3c+K5DV+dxERERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkRo0KzZ9//jlatmwJrVYLrVaLsLAw/PLLL8b9Xbt2hSRJJl+jRo0yOcbFixcRGRkJe3t7eHh4YNKkSSguLjYZEx8fj7Zt20KtVqNRo0ZYuXJlqVoWL14Mf39/aDQahISE4MCBAw/knImIiIio5qtRobl+/fqYP38+Dh8+jEOHDuGJJ57As88+i6SkJOOYV199FVevXjV+LViwwLjP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REQEPvvsM+PzlUolYmNjMXr0aISFhcHBwQFRUVGYM2eOcUxAQAC2bNmCiRMnYuHChahfvz6WLVuGiIgI45j+/fsjPT0dM2bMgE6nQ+vWrbF169ZSHw4kIiIiooeDJIQQli7CGun1ejg5OSErK6vCHwRMS0uDh4cH52bVcuyldWE/rQv7aT3YS+tS3f2sSF7jdxcRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZwdBMRERERGRGpULzxYsXkZeXd9f9eXl5uHjxYqWLIiIiIiKqSSoVmgMCArBx48a77v/pp58QEBBQ6aKIiIiIiGqSSoVmIcQ99xcVFUGh4MwPIiIiIrIONuUdqNfrkZmZaXx8/fr1MqdgZGZmYu3atfD29q6SAomIiIiILK3cofmjjz7CnDlzAACSJGHChAmYMGFCmWOFEHj77berpEAiIiIiIksrd2ju0aMHHB0dIYTA5MmTMXDgQLRt29ZkjCRJcHBwQLt27RAcHFzlxRIRERERWUK5Q3NYWBjCwsIAALm5uejXrx9atGjxwAojIiIiIqopyh2abzdz5syqroOIiIiIqMaqVGgGgIyMDHz33Xc4d+4cMjIySq2oIUkSvvrqq/sukIiIiIjI0iq1Lty2bdvQoEEDjB07FsuWLcOuXbvw66+/lvqqqHnz5qF9+/aoU6cOPDw80KdPHyQnJ5uM6dq1KyRJMvkaNWqUyZiLFy8iMjIS9vb28PDwwKRJk1BcXGwyJj4+Hm3btoVarUajRo2wcuXKUvUsXrwY/v7+0Gg0CAkJwYEDByp8TkRERERU+1XqSvPrr78OLy8v/PDDDwgKCqqyYnbv3o3o6Gi0b98excXF+Pe//40ePXrg1KlTcHBwMI579dVXjSt5AIC9vb3x3waD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dREZGYmZM2fCz6/0fDMiIqL71bFjR4SGht7XHQGJiCqqUqH59OnT6NSpEzIzM/Hkk0+iWbNmxu1ff/01Nm/ejL1796JJkyZVWiwRERFwa6pGUFCQpcsgoodIpULzlClToFAocPTo0VL/p3Xy5El0794dU6ZMwcaNG6ukSCIiIiIiS6rU37J2796N8ePHl/lbfosWLTB27FjEx8ffb21ERERERDVCpUJzUVHRPT/0Z29vj6KiokoXRURERERUk1QqNLdp0wbLli1DVlZWqX16vR5fffUV2rZte9/FERERERHVBJWa0zx79mz07NkTTZs2xdChQ423zE5OTsaqVatw/fp1LF68uEoLJSIiIiKylEqF5ieeeAI///wzJk2ahPnz55vsa926Nb755ht069atSgokIiIiIrK0Sq/THB4ejqNHj0Kn0+HChQsAAD8/P3h5eVVZcURERERENcF93xHQy8uLQZmIiIiIrFq5Pwj4999/Q6PRYPLkyfccN2nSJNjZ2SElJeW+iyMiIiIiqgnKHZo/+eQTeHl54Z133rnnuHfeeQdeXl745JNP7rs4IiIiIqKaoNyhefv27RgwYABsbW3vOU6lUmHAgAH45Zdf7rs4IiIiIqKaoNyh+eLFi2jSpEm5xj766KPGDwcSEREREdV25Q7NarUaOTk55Rqbm5sLlUpV6aKIiIiIiGqScofmpk2bYufOneUaGxcXh2bNmlW6KCIiIiKimqTcobl///6IjY3Fpk2b7jnuxx9/RGxsLPr373+/tRERERER1QjlDs1jxoxBmzZt8K9//QujR4/G77//Dr1eDyEE9Ho9fv/9d4wePRrPP/88WrVqhTFjxjzIuomIiIiIqk25b26iVquxbds2REVF4YsvvsDSpUtLjRFCoGfPnvj666+hVqurtFAiIiIiIkup0B0B3dzcEBsbiwMHDuCnn37Cn3/+Cb1eD61Wi6ZNm6J3794IDQ19ULUSEREREVlEpW6j3aFDB3To0KGqayEiIiIiqpHKPaeZiIiIiOhhxdBMRERERGQGQzMRERERkRkMzUREREREZjA0ExERERGZUaWh+dy5c/jzzz+r8pBERERERBZXqdD8ySefYMCAASbbhg4dikcffRQtWrRAcHAw0tLSqqRAIiIiIiJLq1RoXrZsGTw9PY2Pt23bhlWrVmHEiBH49NNPce7cOcye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W1UqNGdmZuKxxx7DoEGD8N133+Gnn35Ceno6AMDR0RHjx4/HwoULq7RQIiIiIiJLqVRonjJlCpKSkrBt2zacO3cOt8/wUCqVeP755/Hzzz9XWZFERERERJZUqdC8adMmjBs3Dk8++SQkSSq1v3Hjxjh//vz91kZEREREVCNUKjRnZWWVWkP5dkVFRSguLq50UURERERENUmlQnPDhg1x5MiRu+7fvn278UYiRERERES1XaVC8yuvvILly5dj3bp1xvnMkiShoKAAb731FrZu3YqRI0dWaaFERERERJZSqZubvPbaa0hKSsLAgQPh7OwMABg0aBCuX7+O4uJijBw5EsOHD6/KOomIiIiILKZSoVmSJHz55ZeIiorChg0b8Pfff0OWZTRs2BAvvPACOnfuXNV1EhERERFZTKVCc4lOnTqhU6dOVVULEREREVGNVKk5zSkpKdi8efNd92/evJlLzhERERGR1ajUleY33ngDer0evXv3LnP/4sWL4ezsjLVr195XcURERERENUGlrjQnJibiySefvOv+7t2747fffqt0UURERERENUmlQnNGRgbq1Klz1/2Ojo64fv16pYsiIiIiIqpJKhWaGzRogN9///2u+3/77TfUr1+/0kUREREREdUklQrNAwcOxHfffYdPPvkEsiwbtxsMBixcuBDr1q3DoEGDqqxIIiIiIiJLqtQHAadOnYq9e/diwoQJeOedd9CkSRMAQHJyMtLT09G1a1e89dZbVVooEREREZGlVCo0q9VqbN++HatWrcIPP/yAs2fPAgA6dOiAfv364aWXXoJCUamL2EREtZIsy0hKSkJGRgZcXFwQGBjI/x8kIrIilb65iUKhwNChQzF06NCqrIeIqNZJSEjA4iVLkXz+HxQWG6CyUaKJfz1EjxqBjh07Wro8IiKqApW6DHLjxg0cP378rvtPnDiBjIyMShdFRFRbJCQkYPL0OTido4F/r5FoM3QO/HuNRHKuBpOnz0FCQoKlSyQioipQqdA8ceJEjBgx4q77R44ciTfeeKPSRRER1QayLGPxkqXIc/JHq97D4OTtBxtbNZy8/dDy6WHId/bHZ198afKBaSIiqp0qFZp37dqFZ5555q77e/fujZ07d1a6KCKi2iApKQnJ5/9BQPtwSJJksk+SJPgFd8fplMtISkqyUIVERFRVKhWa09PTUbdu3bvud3NzQ1paWqWLIiKqDTIyMlBYbIBDXa8y9zu6eaGw2MDpakREVqBSodnb2xtHjx696/7Dhw/D3d290kUREdUGLi4uUNkokXtNV+b+nOs6qGyUcHFxqebKiIioqlUqNPfp0wdfffUVfvrpp1L7fvzxR6xYsQJ9+/a97+KIiGqywMBANPGvh/OHdkIIYbJPCIELh+LQNKA+AgMDLVQhERFVlUotOTdr1izs3LkTffv2RatWrdCiRQsAwMmTJ/HHH3+gWbNmmD17dpUWSkRU0ygUCkSPGoHJ0+fgeOxy+AV3h6ObF3Ku63DhUBw0mecx5vUZXK+ZiMgKVOr/yZ2cnLBv3z5MmzYNRUVF2LBhAzZs2ICioiJMnz4d+/fvh7OzcxWXSkRU83Ts2BEL5s5AE4d8XPhlKY6unIkLvyxFU8cCLJg7g+s0ExFZiUrf3MTBwQGzZ8++6xXlkrtiERFZu44dOyI0NJR3BCQismKVDs1lKSgowE8//YTVq1dj69atyM/Pr8rDExHVWAqFAkFBQZYug4iIHpD7Ds1CCMTFxWH16tXYuHEj9Ho93N3dMWjQoKqoj4iIiIjI4iodmg8fPozVq1dj7dq10Ol0kCQJAwYMwNixYxEaGlpqoX8iIiIiotqqQqH53LlzWL16NVavXo2///4b9erVw+DBg9GhQwf0798f/fr1Q1hY2IOqlYiIiIjIIsodmsPCwnDgwAHUrVsXzz//PJYtW4ZOnToBAM6ePfvACiQiIiIisrRyh+b9+/cjICAAH374ISIjI2FjU6WfISQiIiIiqrHKvR7SokWL4O3tjb59+8LLywsjR47Er7/+WuouWERERERE1qbcoXnMmDHYu3cvzp49iwkTJuC3335D9+7dUa9ePcyYMQOSJPHDf0RERERklSq88n5AQACmTZuGU6dO4eDBgxgwYADi4+MhhMCYMWMwYsQIxMbGco1mIiIiIrIa93W7qnbt2uHDDz/EpUuXsH37dkRERGDdunV45plnULdu3aqqkYiIiIjIoqrkHq8KhQLh4eFYuXIlUlNT8d1336F79+5VcWgiIiIiIourktB8O41Gg/79++PHH3+s6kMTEREREVlElYdmIiIiIiJrU6NC8549e9C7d2/4+PhAkiRs2rTJZP/LL79sXKWj5Ktnz54mY27cuIHBgwdDq9XC2dkZw4cPR05OjsmY48eP4/HHH4dGo4Gvry8WLFhQqpb169ejadOm0Gg0CAoKws8//1zl50tEREREtUONCs25ublo1aoVFi9efNcxPXv2xNWrV41f3333ncn+wYMHIykpCTt27EBsbCz27NmDESNGGPfr9Xr06NEDfn5+OHz4MN577z3MmjULS5cuNY5JSEjAwIEDMXz4cBw9ehR9+vRBnz59cPLkyao/aSIiIiKq8WrUbf169eqFXr163XOMWq2Gl5dXmfv+/PNPbN26FQcPHkRwcDAA4NNPP8VTTz2F999/Hz4+Pli9ejUKCwuxfPlyqFQqBAYG4tixY/jwww+N4XrhwoXo2bMnJk2aBACYO3cuduzYgUWLFmHJkiVVeMZEREREVBvUqNBcHvHx8fDw8ICLiwueeOIJvP3223BzcwMAJCYmwtnZ2RiYASA8PBwKhQL79+9H3759kZiYiM6dO0OlUhnHRERE4N1330VGRgZcXFyQmJiImJgYk9eNiIgoNV3kdgUFBSgoKDA+1uv1AABZliHLcrnPT5ZlCCEq9ByqmdhL68J+Whf203qwl9aluvtZkdepVaG5Z8+eeO655xAQEICzZ8/i3//+N3r16oXExEQolUrodDp4eHiYPMfGxgaurq7Q6XQAAJ1Oh4CAAJMxnp6exn0uLi7Q6XTGbbePKTlGWebNm4fZs2eX2p6enl6hG73IsoysrCwIIaBQ1KjZM1RB7KV1YT+tC/tpPdhL61Ld/czOzi732FoVmgcMGGD8d1BQEFq2bImGDRsiPj7e4utCT5061eTqtF6vh6+vL9zd3aHVast9HFmWIUkS3N3d+cNfy7GX1oX9tC7sp/VgL61LdfdTo9GUe2ytCs13euSRR1C3bl2cOXMG3bt3h5eXF9LS0kzGFBcX48aNG8Z50F5eXkhNTTUZU/LY3Ji7zaUGbs21VqvVpbYrFIoKN12SpEo9j2oe9tK6sJ/Whf20HuyldanOflbkNWr1d9fly5dx/fp1eHt7AwDCwsKQmZmJw4cPG8fs2rULsiwjJCTEOGbPnj0oKioyjtmxYweaNGkCFxcX45i4uDiT19qxYwfCwsIe9CkRERERUQ1Uo0JzTk4Ojh07hmPHjgEAUlJScOzYMVy8eBE5OTmYNGkS9u3bh/PnzyMuLg7PPvssGjVqhIiICABAs2bN0LNnT7z66qs4cOAAfv/9d4wdOxYDBgyAj48PAGDQoEFQqVQYPnw4kpKSsG7dOixcuNBkasVrr72GrVu34oMPPsDp06cxa9YsHDp0CGPHjq3294SIiIiILK9GheZDhw6hTZs2aNOmDQAgJiYGbdq0wYwZM6BUKnH8+HE888wzaNy4MYYPH4527drht99+M5kWsXr1ajRt2hTdu3fHU089hU6dOpmswezk5ITt27cjJSUF7dq1w+uvv44ZM2aYrOXcsWNHrFmzBkuXLkWrVq2wYcMGbNq0CS1atKi+N4OIiIiIagxJCCEsXYQ10uv1cHJyQlZWVoU/CJiWlgYPDw/Ozarl2Evrwn5aF/bTerCX1qW6+1mRvMbvLiIiIiIiMxiaiYiIiIjMqNVLzhGRdZBlGUlJSca7cgYGBvLPrEREVKMwNBORRSUkJGDxkqVIPv8PCosNUNko0cS/HqJHjUDHjh0tXR4REREATs8gIgtKSEjA5OlzcDpHA/9eI9Fm6Bz49xqJ5FwNJk+fg4SEBEuXSEREBIChmYgsRJZlLF6yFHlO/mjVexicvP1gY6uGk7cfWj49DPnO/vjsiy8hy7KlSyUiImJoJiLLSEpKQvL5fxDQPhySJJnskyQJfsHdcTrlMpKSkixUIRER0f8wNBORRWRkZKCw2ACHul5l7nd080JhsQEZGRnVXBkREVFpDM1EZBEuLi5Q2SiRe01X5v6c6zqobJRwcXGp5sqIiIhKY2gmIosIDAxEE/96OH9oJ+68MakQAhcOxaFpQH0EBgZaqEIiIqL/YWgmIotQKBSIHjUCmszzOB67HJlXz6O4MB+ZV2891mSex5iRr3K9ZiIiqhG4TjMRWUzHjh2xYO6MW+s0/7LUuE5z04D6GPP6DK7TTERENQZDMxFZVMeOHREaGso7AhIRUY3G0ExEFqdQKBAUFGTpMoiIiO6Kl3KIiIiIiMxgaCYiIiIiMoOhmYiIiIjIDIZmIiIiIiIzGJqJiIiIiMxgaCYiIiIiMoOhmYiIiIjIDIZmIiIiIiIzGJqJiIiIiMxgaCYiIiIiMoOhmYiIiIjIDIZmIiIiIiIzbCxdABFZnizLSEpKQkZGBlxcXBAYGAiFgr9TExERlWBoJnrIJSQkYPGSpUg+/w8Kiw1Q2SjRxL8eokeNQMeOHS1dHhERUY3AS0lED7GEhARMnj4Hp3M08O81Em2GzoF/r5FIztVg8vQ5SEhIsHSJRERENQJDM9FDSpZlLF6yFHlO/mjVexicvP1gY6uGk7cfWj49DPnO/vjsiy8hy7KlSyUiIrI4hmaih1RSUhKSz/+DgPbhkCTJZJ8kSfAL7o7TKZeRlJRkoQqJiIhqDoZmoodURkYGCosNcKjrVeZ+RzcvFBYbkJGRUc2VERER1TwMzUQPKRcXF6hslMi9pitzf851HVQ2Sri4uFRzZURERDUPQzPRQyowMBBN/Ovh/KGdEEKY7BNC4MKhODQNqI/AwEALVUhERFRzMDQTPaQUCgWiR42AJvM8jscuR+bV8yguzEfm1VuPNZnnMWbkq1yvmYiICFynmeih1rFjRyyYO+PWOs2/LDWu09w0oD7GvD6D6zQTERH9P4Zmoodcx44dERoayjsCEhER3QNDMxFBoVAgKCjI0mUQERHVWLyURERERERkBkMzEREREZEZDM1ERERERGZwTjNRLSPLMj+0R0REVM1q1H9p9+zZg969e8PHxweSJGHTpk0m+4UQmDFjBry9vWFnZ4fw8HD8/fffJmNu3LiBwYMHQ6vVwtnZGcOHD0dOTo7JmOPHj+Pxxx+HRqOBr68vFixYUKqW9evXo2nTptBoNAgKCsLPP/9c5edLVFEJCQkY8vIwDI2OwdgpszA0OgZDXh6GhIQES5dGRERk1WpUaM7NzUWrVq2wePHiMvcvWLAAn3zyCZYsWYL9+/fDwcEBERERyM/PN44ZPHgwkpKSsGPHDsTGxmLPnj0YMWKEcb9er0ePHj3g5+eHw4cP47333sOsWbOwdOlS45iEhAQMHDgQw4cPx9GjR9GnTx/06dMHJ0+efHAnT2RGQkICJk+fg9M5Gvj3Gok2Q+fAv9dIJOdqMHn6HAZnIiKiB0gSd94/t4aQJAkbN25Enz59ANy6yuzj44PXX38db7zxBgAgKysLnp6eWLlyJQYMGIA///wTzZs3x8GDBxEcHAwA2Lp1K5566ilcvnwZPj4++Pzzz/HWW29Bp9NBpVIBAKZMmYJNmzbh9OnTAID+/fsjNzcXsbGxxnpCQ0PRunVrLFmypMx6CwoKUFBQYHys1+vh6+uLjIwMaLXacp+3LMtIT0+Hu7s7/+Rey1VlL2VZxsvDX8XpHA1aPf0yJEky7hNC4PiWlWjqWIAVy5by++YB4c+mdWE/rQd7aV2qu596vR4uLi7Iysoym9dqzZzmlJQU6HQ6hIeHG7c5OTkhJCQEiYmJGDBgABITE+Hs7GwMzAAQHh4OhUKB/fv3o2/fvkhMTETnzp2NgRkAIiIi8O677xrniCYmJiImJsbk9SMiIkpNF7ndvHnzMHv27FLb09PTTa6EmyPLMrKysiCE4A9/LVeVvTx//jwMkg06dQ2Hvaqw1P6OXboj7fA2HDp0CP7+/vf1WlQ2/mxaF/bTerCX1qW6+5mdnV3usbUmNOt0OgCAp6enyXZPT0/jPp1OBw8PD5P9NjY2cHV1NRkTEBBQ6hgl+1xcXKDT6e75OmWZOnWqSdAuudLs7u5e4SvNkiTxN2YrUJW9TE5Oxp9/n4P6MQ/kFKlL7S9We+DPv8+hoKCg1M8AVQ3+bFoX9tN6sJfWpbr7qdFoyj221oTmmk6tVkOtLh1mFApFhZsuSVKlnkc1T1X10tXVFTZKBXKupcLJ26/U/uzrqbBRKuDq6srvmweIP5vWhf20HuyldanOflbkNWrNd5eXlxcAIDU11WR7amqqcZ+XlxfS0tJM9hcXF+PGjRsmY8o6xu2vcbcxJfuJqltgYCCa+NfD+UM7cefHEIQQuHAoDk0D6iMwMNBCFRIREVm3WhOaAwIC4OXlhbi4OOM2vV6P/fv3IywsDAAQFhaGzMxMHD582Dhm165dkGUZISEhxjF79uxBUVGRccyOHTvQpEkTuLi4GMfc/jolY0peh6i6KRQKRI8aAU3meRyPXY7Mq+dRXJiPzKu3Hmsyz2PMyFd5lYWIiOgBqVH/hc3JycGxY8dw7NgxALc+/Hfs2DFcvHgRkiRhwoQJePvtt/HTTz/hxIkTeOmll+Dj42NcYaNZs2bo2bMnXn31VRw4cAC///47xo4diwEDBsDHxwcAMGjQIKhUKgwfPhxJSUlYt24dFi5caDIf+bXXXsPWrVvxwQcf4PTp05g1axYOHTqEsWPHVvdbQmTUsWNHLJg7A00c8nHhl6U4unImLvyyFE0dC7Bg7gx07NjR0iUSERFZL1GD/PrrrwJAqa+oqCghhBCyLIvp06cLT09PoVarRffu3UVycrLJMa5fvy4GDhwoHB0dhVarFUOHDhXZ2dkmY/744w/RqVMnoVarRb169cT8+fNL1fL999+Lxo0bC5VKJQIDA8WWLVsqdC5ZWVkCgMjKyqrQ8wwGg7h69aowGAwVeh7VPA+qlwaDQRw/flzs3r1bHD9+nN8r1YQ/m9aF/bQe7KV1qe5+ViSv1dh1mms7vV4PJyencq37dztZlpGWlgYPDw/+qb2WYy+tC/tpXdhP68FeWpfq7mdF8hq/u4iIiIiIzGBoJiIiIiIyg+s0E1UzWZaRlJRkvANlYGAg/6RIRERUwzE0E1WjhIQELF6yFMnn/0FhsQEqGyWa+NdD9KgRXP2CiIioBuPlLaJqkpCQgMnT5+B0jgb+vUaizdA58O81Esm5GkyePgcJCQmWLpGIiIjugqGZqBrIsozFS5Yiz8kfrXoPg5O3H2xs1XDy9kPLp4ch39kfn33xJWRZtnSpREREVAaGZqJqkJSUhOTz/yCgfTgkSTLZJ0kS/IK743TKZSQlJVmoQiIiIroXhmaiapCRkYHCYgMc6nqVud/RzQuFxQZkZGRUc2VERERUHgzNRNXAxcUFKhslcq/pytyfc10HlY0SLi4u1VwZERERlQdDM1E1CAwMRBP/ejh/aCfuvAmnEAIXDsWhaUB9BAYGWqhCIiIiuheGZqJqoFAoED1qBDSZ53E8djkyr55HcWE+Mq/eeqzJPI8xI1/les1EREQ1FNdpJroPFblRSceOHbFg7oxb6zT/stS4TnPTgPoY8/oMrtNMRERUgzE0E1VSZW5U0rFjR4SGhvKOgERERLUMQzNRJZTcqCTPyR8BvUbCoa4Xcq/pkHxoJyZPn4MFc2cgNDS0zOcqFAoEBQVVc8VERER0P3h5i6iCeKMSIiKihw9DM1EFlfdGJadOnbJQhURERFTVGJqJKog3KiEiInr4cE4zURnutSrG7TcqcfL2K/Vc3qiEiIjI+jA0E93B3KoYJTcqST60Ey2fHmYyReP2G5U0b94c165ds+CZEBERUVXh9Ayi25SsinE6RwP/XiPRZugc+PcaieRcDSZPn4OEhATeqISIiOghxP+qE/2/iqyKUXKjkiYO+bjwy1IcXTkTF35ZiqaOBVgwlzcqISIisjacnkH0/4yrYvQaefdVMX5ZiqSkJAQFBfFGJURERA8Rhmai/1eZVTF4oxIiIqKHAy+JEf2/21fFKAtXxSAiInp4MTQT/b+SVTHOH9oJIYTJvttXxQgMDLRQhURERGQpDM30UJJlGSdOnMCePXtw4sQJyLLMVTGIiIjorjinmR465tZhXjB3xq39vyw17m8aUB9jXueqGERERA8rhmayanfe2S8rKwtTZr6NPCd/BPQaCYe6Xsi9pkPyoZ2YPH2Ocbk4ropBREREt2NoJqt15xVlW6UCN3SXYfdoCEJ7/+9OfiXrMB+PXY7PvvgSoaGhXBWDiIiITPDSGVmlsu7s59q2F67lA/naBsjIzDQZb1yHOeUykpKSLFM0ERER1Vi80kxW5847+5VcUVbZO0JdxxWScz2cv3ABLi7OkPC/m5iUtQ4zEREREcArzWSFjHf2ax9ucmc/lb0WCgVgI8nIuZmP7Oxsk+dxHWYiIiK6G4Zmsjp3u7OfS71HoHWui+zkfZBlGUVFRcZ9XIeZiIiI7oXTM8gq3L5KRnp6OlQ2CuRe08HJ2884RlIo0LTLs9j/3yUo0F9HnpcWxY4OyLmuw4VDcbfWYX59BlfJICIiolIYmqnWu9sqGTd/24zQf0WbTNHwaBQEN696KLhyGtf3rMbVYpnrMBMREZFZDM1Uq5WsknHnusu5277FlaPx2Aeg2eNPw9HNy3hFua4yH/OXL4OTkxPXYSYiIqJyYWimWutuq2Q4efuhY9S/kbDqP8g7sx8Xcv5BIa8oExER0X1gaKZay7hKRq+RJlMwgFvrLgdGDMb5n7/A1NdGw93dnVeUiYiIqNIYmqnWKfnQX3x8PLJzb8K+rmeZ4xzdvFBkkOHu7o7OnTtXc5VERERkTRiaqVa5/UN/+qwsXE1Lx8G98WjaOgSud6yvzHWXiYiIqKowNFONV3Jl+bfffsOyb9ZC8m6OgF4jYe/qgd1LZyHt9GHIGmc0b9rEGJy57jIRERFVpVo1uXPWrFmQJMnkq2nTpsb9+fn5iI6OhpubGxwdHdGvXz+kpqaaHOPixYuIjIyEvb09PDw8MGnSJBQXF5uMiY+PR9u2baFWq9GoUSOsXLmyOk6PypCQkIAhLw/Dy2Mm4q0583ChqA4Mvm1h0Ghhq7ZDUM/BUN28hmvH4nD66D4UFeYh8+p5HI9dfmvd5ZGvcg4zERER3bdalyYCAwNx9epV49fevXuN+yZOnIjNmzdj/fr12L17N65cuYLnnnvOuN9gMCAyMhKFhYVISEjAqlWrsHLlSsyYMcM4JiUlBZGRkejWrRuOHTuGCRMm4JVXXsG2bduq9Tzpf8vJnc7RwLVtL9i61Ufd9pHINSjxZ/JfuJGRAc9HW6LdM0PhUKzH5R0rsP+Lqbjwy1I0dSzAgrlcJYOIiIiqRq2bnmFjYwMvL69S27OysvDVV19hzZo1eOKJJwAAK1asQLNmzbBv3z6EhoZi+/btOHXqFHbu3AlPT0+0bt0ac+fOxZtvvolZs2ZBpVJhyZIlCAgIwAcffAAAaNasGfbu3YuPPvoIERER1XquDytZlnHixAnMnPM2Mu280b73UKT9dQxCSHBw94Nkq4I+9SLOX7gAFxdneD7aEl19G2Hf55Mw9uUB6Nq1K1fJICIioipV60Lz33//DR8fH2g0GoSFhWHevHlo0KABDh8+jKKiIoSHhxvHNm3aFA0aNEBiYiJCQ0ORmJiIoKAgeHr+b7WFiIgIjB49GklJSWjTpg0SExNNjlEyZsKECfesq6CgAAUFBcbHer0ewK0AKMtyuc9PlmUIISr0HGuSmJiIz5cuwx9JybhwRQe3x9vi+PHjcLYBlDYSivWpULvVh6NzXdxMv4icbD20dbS4mZEGJ2dndOnSxTiH2dLv4cPeS2vDfloX9tN6sJfWpbr7WZHXqVWhOSQkBCtXrkSTJk1w9epVzJ49G48//jhOnjwJnU4HlUoFZ2dnk+d4enpCp9MBAHQ6nUlgLtlfsu9eY/R6PfLy8mBnZ1dmbfPmzcPs2bNLbU9PT0d+fn65z1GWZWRlZUEI8VBdKZVlGbt378YPm3+GcK6P4J4t4XHqCFzatkFR3k1Ihny0CQqEyEmGi783RB1b3BQaeNoWwNEmH7m6E+ga2g5169ZFWlqapU8HwMPbS2vFfloX9tN6sJfWpbr7mZ2dXe6xtSo09+rVy/jvli1bIiQkBH5+fvj+++/vGmary9SpUxETE2N8rNfr4evrC3d3d2i12nIfR5ZlSJIEd3f3h+aHPzExEZ998SW279oN4dUcrm3bw+bCdaSf/hveDbKgcquP7OuXIBW7Ivvg71CcT4Xjox1QXJiHQskG10/HQpN5HmNnTytz6o6lPIy9tGbsp3VhP60He2ldqrufGo2m3GNrVWi+k7OzMxo3bowzZ87gySefRGFhITIzM02uNqemphqDlJeXFw4cOGByjJLVNW4fc+eKG6mpqdBqtfcM5mq1Gmq1utR2hUJR4aZLklSp59U2sixj9erVeO+Tz3HTzgOygxs8O/aFrdYDuRl2KBQKpP3xK+p1GwKNkztuFtxE4yf+hUsHd+By7CdQKSU4NaiHpgG+GBMzvUZ+6O9h6eXDgv20Luyn9WAvrUt19rMir1Grv7tycnJw9uxZeHt7o127drC1tUVcXJxxf3JyMi5evIiwsDAAQFhYGE6cOGHy5/sdO3ZAq9WiefPmxjG3H6NkTMkxqGokJCTgxaihmPDmNFyWnZGnbYCCYhkKx7qwVdvBycsfdZp3wc2LJ6HbvRpFWWkwFBVAobKDk4cPGvm4Ye7kcVix+CN8veKrGhmYiYiIyHrUqivNb7zxBnr37g0/Pz9cuXIFM2fOhFKpxMCBA+Hk5IThw4cjJiYGrq6u0Gq1GDduHMLCwhAaGgoA6NGjB5o3b44hQ4ZgwYIF0Ol0mDZtGqKjo41XiUeNGoVFixZh8uTJGDZsGHbt2oXvv/8eW7ZsseSpW407ry6jjju8HnsOxfk3kXlqLzKvXoCr76NQ2drCrVkYUJwPZepppG5fgsKcTNj7eKF180cx5qP3GJSJiIio2tSq0Hz58mUMHDgQ169fh7u7Ozp16oR9+/bB3d0dAPDRRx9BoVCgX79+KCgoQEREBD777DPj85VKJWJjYzF69GiEhYXBwcEBUVFRmDNnjnFMQEAAtmzZgokTJ2LhwoWoX78+li1bxuXmqkBCQgIWff4FtsXFQ3gHwk7bAAX/XITCsS7quNlB4+yB3L8SoXGrB1snJyhVamg8AtC8UzjOblsJH5scvP/ufAQFBfFPcERERFStJCGEsHQR1kiv18PJyQlZWVkV/iBgWloaPDw8rCoY7t27F+Mn/RsZSidkpv4D715jUJx/E//sXAmXLlFw9X0UhVf/wj/xa2DjHgCPtt2hcnCBPuUP1Ln5D5zzrta6m5VYay8fVuyndWE/rQd7aV2qu58VyWu16koz1U579+7FkKGvQO/UEGrXABT8cxkFSgfYe3qZXF12ahAI7y4DofttPdJ3foWim9nQSMXo1KUjokfVrsBMRERE1oWhmR6YkvnLc+e/j/Q8GfXCI6FQKKD/ax8KstIhFDZwbhWOtL3f43rCeijbdofarT6cW3aDKjUJdjkCkyeOw+DBg3n1gIiIiCyKoZkeiNvnLxc6ekO2VaBY4wJ7xzpQ13FF3tmDsAl+FrZ1A+DdZQB0v20wubr8eJeOiB41mVeXiYiIqEZgaKYqJcsyvvnmG7zz/kLk2XtCtneDe3BPpB382eTqcnrCBugPboLdI+2grevNq8tERERUozE0U5UomYqx8NPFOHHqNFSPtIdK2wD5qVcg120IWwdn06vLnQfg2uFfkBG/CpnF+bBXyry6TERERDUWQzPdl5Kw/Mmiz3Ay+QyKJRtIjnVRp00kFAoJN88eQkHWDWiadkLOkS3Gq8uu9QLg1r43UveugycEpk95g1eXiYiIqMZiaKZKS0hIwKw5byPx6AkUyApIGi3U7gGQ8/SwdasPKG1g6+iGvLMHoG3/LJyClcg7vQcZ8atwU61G8c0suNtJWL78S3Tq1MnSp0NERER0V7ysR5WSkJCAN96ahQN/noNNvUDY2NWBwk4L+0dDAACG7OuQJAUcWnZHUeoZ6A9shLC1g3u3l+DUpAOcXV3RyMcNXzMwExERUS3A0EwVJssyZs/9D/6+UYRCSQMbj0dhKC4GFDbQBLSFwt4JOad/AyQJap+mcAn9F4qzdMjYvQqX1s1F8el4dHzUE4s/eo+BmYiIiGoFhmYqN1mW8ccff+DVV1/Fb4eOAW7+kGxsofFuBElpAxiKYMhKh2PLHii8+heyEtah6Ppl2Lj7oU6rHrC1r4N6Tmp8+PZ0fLNyOT/wR0RERLUG5zRTuezduxeTp/wbf5xMQt7Nm7BxrQeFe0PI50/AoFDC1tkbhdcvIjf5NziFDYA2pB9yT+xERvwKQJYh8rLgpbXF8uXLeHWZiIiIah1eaSazvvjiCzzz/AAcPPkXChUaKOvUhULtAIWjM5QOzriZnACHoO6QFErc/GsfMn/7FgqVPZweGwD7hu1gq1bDt24dfMPATERERLUUrzTTPe3ZswdTZsxBrlBBYWcPW3c/GHIzobTTIu+vfXBs2QP6/RsAAHXaPIXcU/HITdqFm8l7oVAqYa+yQWir5pg57d+cjkFERES1FkMz3dXevXvR74UByCmSIKltoVDbw65RCHKPb4fdI+2Qe2o3AMC+aWfkpRxGwaUkyEV5AGT41XVE/389jxdeeAFBQUFcf5mIiIhqNYZmKtPevXsxOGoYMnILobBzgiQpAKUtNP6tkXfmAIoyrkAb2g85x3eg8OpfkGUDUJQH2+I8tGvZHHvif4WNDb+9iIiIyDow1ZAJWZaxatUqTHjjTeQWA5LGEZJaAxiKAUMx5OzrcGz5JPT7/n9KRnAfiIJcFKWdRfE/SXhEK+H9Be8yMBMREZFVYbIho4SEBLw2MQZHjicBtmoo7Z2hUDtAUjvCkJ0OufAmck//BqeO/aENfR45x7cjc/cKQDYAeXp4aW3x6fvLOHeZiIiIrA5D80NOlmUkJSUhPj4es/+zABlZ2ZDUjpCUNlDYO8PG3glQ2kC+mQHDzSzc/CsBwlAE+yaPwymsP/L+PoCiy3/A26EOli9ZxNUxiIiIyCoxND/EEhISsHjJUuz5PRGXL164dWXZrg4UansAEiTZALuAtsj9cw9s3XwhKZQounEFOX9sQ+6fv0FSKKFWSngsuCVXxyAiIiKrxtD8kEpISMCkabNx6uxFZKb+c2vdZbUdJKUNJE0dKO20KM74B0WZV1Hn/29UItlqoHT2gnwzCyjIQeMAX3z7zddo1aoVV8cgIiIiq8bQ/BAqLi7GiNHROKMHClIvQ2mrARRKSCp7QMKtK8yPtEP2UR1u/pUIYShCneBnIOdlo+BKMgqvnEZ9TSG+/GIR2rRpY+nTISIiInrgGJofIrIsY+XKlRg3bjzylXZQqOyhVNtBslFDFBfdusqsdoSccw3FmVfh3OVl6PdtQO6fe3Dzr0RICiVEcQHcHVVYvuJbTscgIiKihwZD80MiISEBAwcNwsXLVwEASkdHQC4GJCUkuzqQs29ALrgJlbMX5JsZxivMzl1eguFmJvL+3o+itLNo4K7F8i8W8wN/RERE9FBhaH4I7NmzBz2fikReQTGgtIHCVg3IMmCrAeR8SApb2Dh5wJBzHYW6M7D18EdxVhpyT+3GzeQEQJKAogK0DXwUH72/gFeYiYiI6KHDT29ZuUWLFqFL1yeQV1AEhUoDhdIWUKoghAwhKSEkBUR+NmxdvKG0d4IwFKHg4kkYcjMBKCDn6SGyr2FS9HAk7t3DwExEREQPJV5ptlKyLCMyMhJbt24HlDaQbNWApIBko7z1YT9751th2dkTxRlXUHglGbaej0AuyIMhNxMiPxvCUAi1rRIffDAfo0ePtvQpEREREVkMQ7OVkWUZX3/9NcaPfw3ZObmAQgEolZAUt8KyUNgCQoZCyLBx90dx5lUotR4oztDBkHIEkq0dIAREcT78fDzw9YrlnL9MREREDz1Oz7Aie/bsgW8DfwwdPgLZOTmA0gawUUFS2kJIEgQUQFE+bJ3cIednw5CVCpVnQ0g2aiidPQGVA+TCm1AWZuPN18bgTPJpBmYiIiIi8Eqz1Zg4cSI+XrwEkA23PrgnKSEpFICtBkJSAMUFUGocIAzFKM7UQensheKMqzCcPwbJVgMIARTnw8vNGd9/t5phmYiIiOg2DM1WIDg4GIePnQAMBkBtBxiKAKUtoFACShsohYDk6AL5ZiYkWzsI2YCi9AuAyg4QMuS8LMBQjJcGD8SKFSt4dz8iIiKiOzA013LBwcE4fPjYrakYCgkQBuPd/QQAqSgfSrcGMGSnQ2HvjGL9NWOYlgrzIeQiaB3tsHnjRnTu3NnSp0NERERUIzE012ILFy7E4cNHb33YT/7/q8tCAEpbSBCw0ThCCDsYsq5C6eQNQ851SBotROFNoOAmhKEY7YPbYt++fby6TERERHQPTEq1VHFxMd6aMeNWYJZwax6zjQqQBWAogijKh9LRDZLCBpLaAUXXLkCWDZDkQkgQgJDxwr/64cCBAwzMRERERGYwLdVSP/74I3Jzc3ErMSsAperWlWZJuvVhQCFQmHYOCgdnKOy0kBzrQjIUQxQWQBTlYcK4aKxbt87Sp0FERERUK3B6Ri115coVQEi35idLEmCjBgpvwsbZA8VZqYAQkIsKUPDPaSjUDpAk3LoLoFyEgS/8Cx999JGlT4GIiIio1uCV5lrKx8cHktIWgAQYioHiAijstJDzsmHj5AlhKAZkGZAUkAtyYLipBwrzsOjjD7FmzRpLl09ERERUq/BKcy317LPPwsO9LlJTU29Ny5CLgeJCwEZ1a4UMTR2guODWl6EYXl6euHTpEmxs2HIiIiKiiuKV5lrKxsYGM6dNhUICJKUSUNhAzsuGnKcHbDRAcf6tEC0b8Npr43H16lUGZiIiIqJKYoqqxUaPHo2UlBR8+MliGCAAtQNQkAcUZQAAHLR1EPvjj+jatatlCyUiIiKq5XiluZZbsGABdm3/BR1DO8C5jgPquDijnn8jDBj8Irb/8gsDMxEREVEV4JVmK9C5c2f8Fr8LSUlJyMjIgIuLCwIDA7n+MhEREVEVYaoyY/HixfD394dGo0FISAgOHDhg6ZLKpFAoEBQUhM6dOyMoKIiBmYiIiKgKMVndw7p16xATE4OZM2fiyJEjaNWqFSIiIpCWlmbp0oiIiIioGjE038OHH36IV199FUOHDkXz5s2xZMkS2NvbY/ny5ZYujYiIiIiqEec030VhYSEOHz6MqVOnGrcpFAqEh4cjMTGx1PiCggIUFBQYH+v1egCALMuQZbncryvLMoQQFXoO1UzspXVhP60L+2k92EvrUt39rMjrMDTfxbVr12AwGODp6Wmy3dPTE6dPny41ft68eZg9e3ap7enp6cjPzy/368qyjKysLAghOC+5lmMvrQv7aV3YT+vBXlqX6u5ndnZ2uccyNFeRqVOnIiYmxvhYr9fD19cX7u7u0Gq15T6OLMuQJAnu7u784a/l2Evrwn5aF/bTerCX1qW6+6nRaMo9lqH5LurWrQulUnnrNtW3SU1NhZeXV6nxarUaarW61HaFQlHhpkuSVKnnUc3DXloX9tO6sJ/Wg720LtXZz4q8Br+77kKlUqFdu3aIi4szbpNlGXFxcQgLC7NgZURERERU3Xil+R5iYmIQFRWF4OBgdOjQAR9//DFyc3MxdOhQS5dGRERERNWIofke+vfvj/T0dMyYMQM6nQ6tW7fG1q1bS304kIiIiIisG0OzGWPHjsXYsWMtXQYRERERWRDnNBMRERERmcHQTERERERkBkMzEREREZEZnNP8gAghAPzvdtrlJcsysrOzodFouN5kLcdeWhf207qwn9aDvbQu1d3PkpxWktvuhaH5ASm5LaOvr6+FKyEiIiKie8nOzoaTk9M9x0iiPNGaKkyWZVy5cgV16tSBJEnlfl7J7bcvXbpUodtvU83DXloX9tO6sJ/Wg720LtXdTyEEsrOz4ePjY/bKNq80PyAKhQL169ev9PO1Wi1/+K0Ee2ld2E/rwn5aD/bSulRnP81dYS7ByT9ERERERGYwNBMRERERmcHQXMOo1WrMnDkTarXa0qXQfWIvrQv7aV3YT+vBXlqXmtxPfhCQiIiIiMgMXmkmIiIiIjKDoZmIiIiIyAyGZiIiIiIiMxiaiYiIiIjMYGi2gMWLF8Pf3x8ajQYhISE4cODAPcevX78eTZs2hUajQVBQEH7++edqqpTMqUgvv/zySzz++ONwcXGBi4sLwsPDzfaeqldFfzZLrF27FpIkoU+fPg+2QKqQivYzMzMT0dHR8Pb2hlqtRuPGjfn/tzVERXv58ccfo0mTJrCzs4Ovry8mTpyI/Pz8aqqW7mXPnj3o3bs3fHx8IEkSNm3aZPY58fHxaNu2LdRqNRo1aoSVK1c+8DrLJKharV27VqhUKrF8+XKRlJQkXn31VeHs7CxSU1PLHP/7778LpVIpFixYIE6dOiWmTZsmbG1txYkTJ6q5crpTRXs5aNAgsXjxYnH06FHx559/ipdfflk4OTmJy5cvV3PlVJaK9rNESkqKqFevnnj88cfFs88+Wz3FklkV7WdBQYEIDg4WTz31lNi7d69ISUkR8fHx4tixY9VcOd2por1cvXq1UKvVYvXq1SIlJUVs27ZNeHt7i4kTJ1Zz5VSWn3/+Wbz11lvihx9+EADExo0b7zn+3Llzwt7eXsTExIhTp06JTz/9VCiVSrF169bqKfg2DM3VrEOHDiI6Otr42GAwCB8fHzFv3rwyx7/wwgsiMjLSZFtISIgYOXLkA62TzKtoL+9UXFws6tSpI1atWvWgSqQKqEw/i4uLRceOHcWyZctEVFQUQ3MNUtF+fv755+KRRx4RhYWF1VUilVNFexkdHS2eeOIJk20xMTHisccee6B1UsWVJzRPnjxZBAYGmmzr37+/iIiIeICVlY3TM6pRYWEhDh8+jPDwcOM2hUKB8PBwJCYmlvmcxMREk/EAEBERcdfxVD0q08s73bx5E0VFRXB1dX1QZVI5Vbafc+bMgYeHB4YPH14dZVI5VaafP/30E8LCwhAdHQ1PT0+0aNEC//nPf2AwGKqrbCpDZXrZsWNHHD582DiF49y5c/j555/x1FNPVUvNVLVqUg6yqfZXfIhdu3YNBoMBnp6eJts9PT1x+vTpMp+j0+nKHK/T6R5YnWReZXp5pzfffBM+Pj6l/s+Aql9l+rl371589dVXOHbsWDVUSBVRmX6eO3cOu3btwuDBg/Hzzz/jzJkzGDNmDIqKijBz5szqKJvKUJleDho0CNeuXUOnTp0ghEBxcTFGjRqFf//739VRMlWxu+UgvV6PvLw82NnZVVstvNJMZAHz58/H2rVrsXHjRmg0GkuXQxWUnZ2NIUOG4Msvv0TdunUtXQ5VAVmW4eHhgaVLl6Jdu3bo378/3nrrLSxZssTSpVEFxcfH4z//+Q8+++wzHDlyBD/88AO2bNmCuXPnWro0quV4pbka1a1bF0qlEqmpqSbbU1NT4eXlVeZzvLy8KjSeqkdlelni/fffx/z587Fz5060bNnyQZZJ5VTRfp49exbnz59H7969jdtkWQYA2NjYIDk5GQ0bNnywRdNdVebn09vbG7a2tlAqlcZtzZo1g06nQ2FhIVQq1QOtmcpWmV5Onz4dQ4YMwSuvvAIACAoKQm5uLkaMGIG33noLCgWvF9Ymd8tBWq22Wq8yA7zSXK1UKhXatWuHuLg44zZZlhEXF4ewsLAynxMWFmYyHgB27Nhx1/FUPSrTSwBYsGAB5s6di61btyI4OLg6SqVyqGg/mzZtihMnTuDYsWPGr2eeeQbdunXDsWPH4OvrW53l0x0q8/P52GOP4cyZM8ZffgDgr7/+gre3NwOzBVWmlzdv3iwVjEt+GRJCPLhi6YGoUTmo2j96+JBbu3atUKvVYuXKleLUqVNixIgRwtnZWeh0OiGEEEOGDBFTpkwxjv/999+FjY2NeP/998Wff/4pZs6cySXnaoiK9nL+/PlCpVKJDRs2iKtXrxq/srOzLXUKdJuK9vNOXD2jZqloPy9evCjq1Kkjxo4dK5KTk0VsbKzw8PAQb7/9tqVOgf5fRXs5c+ZMUadOHfHdd9+Jc+fOie3bt4uGDRuKF154wVKnQLfJzs4WR48eFUePHhUAxIcffiiOHj0qLly4IIQQYsqUKWLIkCHG8SVLzk2aNEn8+eefYvHixVxy7mHy6aefigYNGgiVSiU6dOgg9u3bZ9zXpUsXERUVZTL++++/F40bNxYqlUoEBgaKLVu2VHPFdDcV6aWfn58AUOpr5syZ1V84lamiP5u3Y2iueSraz4SEBBESEiLUarV45JFHxDvvvCOKi4uruWoqS0V6WVRUJGbNmiUaNmwoNBqN8PX1FWPGjBEZGRnVXziV8uuvv5b538KSHkZFRYkuXbqUek7r1q2FSqUSjzzyiFixYkW11y2EEJIQ/FsFEREREdG9cE4zEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzEREREZEZDM1ERERERGYwNBMRERERmcHQTERERERkBkMzERFVir+/P55++ulKP3/lypWQJAnnz5+vuqKIiB4QhmYiolqkJGgeOnTI0qUQET1UGJqJiIiIiMxgaCYiIiIiMoOhmYjIihQWFmLGjBlo164dnJyc4ODggMcffxy//vqrybjz589DkiS8//77WLx4MR555BHY29ujR48euHTpEoQQmDt3LurXrw87Ozs8++yzuHHjRpmvuX37drRu3RoajQbNmzfHDz/8UGpMUlISnnjiCdjZ2aF+/fp4++23IctyqXE//vgjIiMj4ePjA7VajYYNG2Lu3LkwGAxV8wYREVWSJIQQli6CiIjKZ+XKlRg6dCgOHjyI4ODgUvuvXbuGli1bYuDAgXj00UeRnZ2Nr776CufOncOBAwfQunVrALdCc0BAAFq3bo3CwkK88soruHHjBhYsWIC2bdviiSeeQHx8PAYMGIAzZ87g008/xcsvv4zly5cbX8vf3x9qtRppaWkYNWoUPDw8sGLFCiQlJWHr1q148sknAQA6nQ4tW7ZEcXExXnvtNTg4OGDp0qWws7PD8ePHkZKSAn9/fwBA3759oVKp0L59ezg6OmLXrl1Yv3493njjDbz33nsP/P0lIrorQUREtcaKFSsEAHHw4MEy9xcXF4uCggKTbRkZGcLT01MMGzbMuC0lJUUAEO7u7iIzM9O4ferUqQKAaNWqlSgqKjJuHzhwoFCpVCI/P9+4zc/PTwAQ//3vf43bsrKyhLe3t2jTpo1x24QJEwQAsX//fuO2tLQ04eTkJACIlJQU4/abN2+WOqeRI0cKe3t7k9cmIqpunJ5BRGRFlEolVCoVAECWZdy4cQPFxcUIDg7GkSNHSo3/17/+BScnJ+PjkJAQAMCLL74IGxsbk+2FhYX4559/TJ7v4+ODvn37Gh9rtVq89NJLOHr0KHQ6HQDg559/RmhoKDp06GAc5+7ujsGDB5eqx87Ozvjv7OxsXLt2DY8//jhu3ryJ06dPV+i9ICKqSgzNRERWZtWqVWjZsiU0Gg3c3Nzg7u6OLVu2ICsrq9TYBg0amDwuCdC+vr5lbs/IyDDZ3qhRI0iSZLKtcePGAGBcf/nChQt49NFHS712kyZNSm1LSkpC37594eTkBK1WC3d3d7z44osAUGb9RETVxcb8ECIiqi2+/fZbvPzyy+jTpw8mTZoEDw8PKJVKzJs3D2fPni01XqlUlnmcu20XD/BjMJmZmejSpQu0Wi3mzJmDhg0bQqPR4MiRI3jzzTfL/OAgEVF1YWgmIrIiGzZswCOPPIIffvjB5ArwzJkzH8jrnTlzBkIIk9f666+/AMD44T4/Pz/8/fffpZ6bnJxs8jg+Ph7Xr1/HDz/8gM6dOxu3p6SkPIDKiYgqhtMziIisSMkV4tuvCO/fvx+JiYkP5PWuXLmCjRs3Gh/r9Xp8/fXXaN26Nby8vAAATz31FPbt24cDBw4Yx6Wnp2P16tVmay8sLMRnn332QGonIqoIXmkmIqqFli9fjq1bt5ba3rVrV/zwww/o27cvIiMjkZKSgiVLlqB58+bIycmp8joaN26M4cOH4+DBg/D09MTy5cuRmpqKFStWGMdMnjwZ33zzDXr27Gmy5Jyfnx+OHz9uHNexY0e4uLggKioK48ePhyRJ+Oabbx7olBAiovJiaCYiqoU+//zzMrdfvHgROTk5+OKLL7Bt2zY0b94c3377LdavX4/4+Pgqr+PRRx/Fp59+ikmTJiE5ORkBAQFYt24dIiIijGO8vb3x66+/Yty4cZg/fz7c3NwwatQo+Pj4YPjw4cZxbm5uiI2Nxeuvv45p06bBxcUFL774Irp3725yPCIiS+DNTYiIiIiIzOCcZiIiIiIiMxiaiYiIiIjMYGgmIiIiIjKDoZmIiIiIyAyGZiIiIiIiMxiaiYiIiIjMYGgmIiIiIjKDoZmIiIiIyAyGZiIiIiIiMxiaiYiIiIjMYGgmIiIiIjKDoZmIiIiIyIz/A0wytBjtYbbrAAAAAElFTkSuQmCC",
|
||
"text/plain": [
|
||
"<Figure size 800x600 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"# Plotting lambda against access_count.\n",
|
||
"\n",
|
||
"plt.figure(figsize=(8, 6))\n",
|
||
"plt.scatter(merged['lambda'], merged['access_count'], alpha=0.7, edgecolor='k')\n",
|
||
"plt.title('Lambda vs Access Count', fontsize=14)\n",
|
||
"plt.xlabel('Lambda', fontsize=12)\n",
|
||
"plt.ylabel('Access Count', fontsize=12)\n",
|
||
"plt.grid(alpha=0.3)\n",
|
||
"\n",
|
||
"plt.savefig(f\"{TEMP_BASE_DIR}/lambda_vs_access_count.pdf\")\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 23,
|
||
"id": "00a12eea-c805-4209-9143-48fa65619873",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAq4AAAIjCAYAAADC0ZkAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABAQ0lEQVR4nO3deVxV1R738e8BZXAAQQQcSBHNOccsMYdrpLestCzTx3IsrTAzb6Y0aKmJ2mSpZXVzaLp2HRvuVTM1TTMzZ9PMCNNbIqICDjnBev7o4TweBoXjkeOSz/v1Oq+XZ+211/6dxQK+bvbZx2GMMQIAAACucD7eLgAAAAAoDIIrAAAArEBwBQAAgBUIrgAAALACwRUAAABWILgCAADACgRXAAAAWIHgCgAAACsQXAEAAGAFgiuAq9qGDRsUGxursmXLyuFwaMuWLd4uyUWNGjV0++23e7sMtzkcDj3//POX/Tjt27dX+/btnc+//vprORwOzZs375LGnTRpkurWravs7OxLrNA7nn/+eTkcDo+OmXuud+7cqVKlSmnHjh0ePQ7gDoIr4AE//vij7r//flWtWlX+/v6qUqWKevXqpR9//NHbpZVoZ8+e1b333qsjR47otdde0wcffKDq1at7uyxcITIzMzVx4kSNGDFCPj78OixI/fr11blzZ40aNcrbpQAq5e0CANstWLBAPXv2VGhoqAYMGKDo6Gjt3btX7733nubNm6c5c+borrvu8naZJVJSUpJ+++03vfvuu3rwwQe9Xc5V6c8//1SpUnb+KpkxY4bOnTunnj17eruUK97DDz+s2267TUlJSYqJifF2OSjB7PxpA1whkpKS9MADD6hmzZpavXq1KlWq5Nz2+OOPq02bNnrggQe0bds21axZ04uV5nXy5EmVKVPG22VcVqmpqZKkChUqeLeQq1hAQIC3S3DbzJkzdeedd170NZw7d07Z2dny8/MrpsquPHFxcQoJCdHs2bM1ZswYb5eDEoy/jQCX4KWXXtLJkyf1zjvvuIRWSQoLC9Pbb7+tEydOaNKkSS7bfv/9dw0YMEBVqlSRv7+/oqOj9cgjj+jMmTPOPunp6XriiSdUo0YN+fv7q1q1aurdu7fS0tIkSbNmzZLD4dDevXtdxs659u/rr792trVv314NGzbUxo0b1bZtW5UpU0ZPP/20JOnTTz9V586dnbXExMRo7NixysrKchk3Z4ydO3fqb3/7m8qUKaOqVavmeW2SdOrUKT3//PO69tprFRAQoMqVK+vuu+9WUlKSs092drYmT56sBg0aKCAgQBERERo0aJCOHj1aqLlfsWKF2rRpo7Jly6pChQrq0qWLdu3a5dzet29ftWvXTpJ07733yuFwuFy3l5/09HQNHTpUUVFR8vf3V61atTRx4sQ81z++/PLLio2NVcWKFRUYGKjmzZsXeK3lhx9+qJYtW6pMmTIKCQlR27Zt9eWXX+bpt2bNGrVs2VIBAQGqWbOm3n///YvOwd69e+VwOPTyyy9r2rRpqlmzpsqUKaOOHTtq//79MsZo7NixqlatmgIDA9WlSxcdOXLEZYyCrlGtUaOG+vbte9Eacu+fc83lL7/8or59+6pChQoKDg5Wv379dPLkyYuOJ0nvvPOOYmJiFBgYqJYtW+qbb74psG9WVpaefvppRUZGqmzZsrrzzju1f//+ix4jOTlZ27ZtU1xcnEv7+XM6efJkxcTEyN/fXzt37pR08XUn/bX2atSokeeY+V2P6nA4NHjwYC1atEgNGzaUv7+/GjRooCVLluTZf82aNbr++usVEBCgmJgYvf322wW+vg8//FDNmzdXYGCgQkND1aNHj3znpbBzXbp0abVv316ffvppgccEigNnXIFL8Pnnn6tGjRpq06ZNvtvbtm2rGjVq6D//+Y+z7Y8//lDLli2Vnp6ugQMHqm7duvr99981b948nTx5Un5+fjp+/LjatGmjXbt2qX///mrWrJnS0tL02Wef6X//+5/CwsKKXOvhw4d16623qkePHrr//vsVEREh6a8AXK5cOQ0bNkzlypXTihUrNGrUKGVmZuqll15yGePo0aP6+9//rrvvvlvdu3fXvHnzNGLECDVq1Ei33nqrpL+CxO23367ly5erR48eevzxx3Xs2DEtW7ZMO3bscP6ZcdCgQZo1a5b69eunIUOGKDk5WVOnTtXmzZu1du1alS5dusDX8tVXX+nWW29VzZo19fzzz+vPP//UlClT1Lp1a23atEk1atTQoEGDVLVqVY0fP15DhgzR9ddf73zN+Tl58qTatWun33//XYMGDdI111yjb7/9VgkJCTpw4IAmT57s7Pv666/rzjvvVK9evXTmzBnNmTNH9957r7744gt17tzZ2e+FF17Q888/r9jYWI0ZM0Z+fn5av369VqxYoY4dOzr7/fLLL7rnnns0YMAA9enTRzNmzFDfvn3VvHlzNWjQ4KJf248++khnzpzRY489piNHjmjSpEnq3r27OnTooK+//lojRozQL7/8oilTpujJJ5/UjBkzLjrmperevbuio6OVmJioTZs26Z///KfCw8M1ceLEC+733nvvadCgQYqNjdXQoUP166+/6s4771RoaKiioqLy9H/xxRflcDg0YsQIpaamavLkyYqLi9OWLVsUGBhY4HG+/fZbSVKzZs3y3T5z5kydOnVKAwcOlL+/v0JDQwu17tyxZs0aLViwQI8++qjKly+vN954Q926ddO+fftUsWJFSdL27dvVsWNHVapUSc8//7zOnTun0aNH57umX3zxRT333HPq3r27HnzwQR06dEhTpkxR27ZttXnzZudfIIo6182bN9enn36qzMxMBQUFufVagUtmALglPT3dSDJdunS5YL8777zTSDKZmZnGGGN69+5tfHx8zIYNG/L0zc7ONsYYM2rUKCPJLFiwoMA+M2fONJJMcnKyy/aVK1caSWblypXOtnbt2hlJZvr06XnGO3nyZJ62QYMGmTJlyphTp07lGeP99993tp0+fdpERkaabt26OdtmzJhhJJlXX321wNq/+eYbI8l89NFHLtuXLFmSb3tuTZo0MeHh4ebw4cPOtq1btxofHx/Tu3dvZ1vOXMydO/eC4xljzNixY03ZsmXNzz//7NI+cuRI4+vra/bt2+dsyz1nZ86cMQ0bNjQdOnRwtu3Zs8f4+PiYu+66y2RlZbn0z5kHY4ypXr26kWRWr17tbEtNTTX+/v7mH//4xwVrTk5ONpJMpUqVTHp6urM9ISHBSDKNGzc2Z8+edbb37NnT+Pn5uXxdJZnRo0fnGbt69eqmT58+Fzx+fvuPHj3aSDL9+/d36XfXXXeZihUrXnCsM2fOmPDwcNOkSRNz+vRpZ/s777xjJJl27do523K+tlWrVnV+bxljzL///W8jybz++usXPNazzz5rJJljx465tOfMaVBQkElNTXXZVth116dPH1O9evU8x8yZm/NJMn5+fuaXX35xGVOSmTJlirOta9euJiAgwPz222/Otp07dxpfX1+XMffu3Wt8fX3Niy++6HKc7du3m1KlSjnbizLXOT7++GMjyaxfvz7PNqC4cKkA4KZjx45JksqXL3/Bfjnb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/fffS/rrbOvkyZP17LPPqkuXLpKk999/XxEREVq0aJF69OjhtdoBAABQvLx6xjU2NlbLly/Xzz//LEnaunWr1qxZo1tvvVWSlJycrJSUFMXFxTn3CQ4O1g033KB169blO+bp06eVmZnp8gAAAID9vHrGdeTIkcrMzFTdunXl6+urrKwsvfjii+rVq5ckKSUlRZIUERHhsl9ERIRzW26JiYl64YUXLm/hAAAAKHZePeP673//Wx999JE+/vhjbdq0SbNnz9bLL7+s2bNnuz1mQkKCMjIynI/9+/d7sGIAAAB4i1fPuA4fPlwjR450XqvaqFEj/fbbb0pMTFSfPn0UGRkpSTp48KAqV67s3O/gwYNq0qRJvmP6+/vL39//stcOAACA4uXVM64nT56Uj49rCb6+vsrOzpYkRUdHKzIyUsuXL3duz8zM1Pr169WqVatirRUAAADe5dUzrnfccYdefPFFXXPNNWrQoIE2b96sV199Vf3795ckORwODR06VOPGjVPt2rUVHR2t5557TlWqVFHXrl29WToAAACKmVeD65QpU/Tcc8/p0UcfVWpqqqpUqaJBgwZp1KhRzj5PPfWUTpw4oYEDByo9PV033XSTlixZooCAAC9WDgAAgOLmMOd/TNVVKDMzU8HBwcrIyFBQUFCxHHPC5rRiOQ6K38imYd4uAQCAq05h85pXr3EFAAAACovgCgAAACsQXAEAAGAFgisAAACsQHAFAACAFQiuAAAAsALBFQAAAFYguAIAAMAKBFcAAABYgeAKAAAAKxBcAQAAYAWCKwAAAKxAcAUAAIAVCK4AAACwAsEVAAAAViC4AgAAwAoEVwAAAFiB4AoAAAArEFwBAABgBYIrAAAArEBwBQAAgBUIrgAAALACwRUAAABWILgCAADACgRXAAAAWIHgCgAAACsQXAEAAGAFgisAAACsQHAFAACAFQiuAAAAsALBFQAAAFYguAIAAMAKBFcAAABYgeAKAAAAKxBcAQAAYAWCKwAAAKxAcAUAAIAVCK4AAACwAsEVAAAAViC4AgAAwAoEVwAAAFiB4AoAAAArEFwBAABgBYIrAAAArEBwBQAAgBUIrgAAALACwRUAAABWILgCAADACgRXAAAAWIHgCgAAACsQXAEAAGAFgisAAACsQHAFAACAFQiuAAAAsALBFQAAAFYguAIAAMAKBFcAAABYgeAKAAAAKxBcAQAAYAWCKwAAAKxAcAUAAIAVCK4AAACwAsEVAAAAViC4AgAAwAoEVwAAAFiB4AoAAAArEFwBAABgBYIrAAAArEBwBQAAgBUIrgAAALACwRUAAABWILgCAADACgRXAAAAWIHgCgAAACsQXAEAAGAFgisAAACsQHAFAACAFQiuAAAAsALBFQAAAFYguAIAAMAKBFcAAABYgeAKAAAAKxBcAQAAYAWCKwAAAKxAcAUAAIAVCK4AAACwgteD6++//677779fFStWVGBgoBo1aqQffvjBud0Yo1GjRqly5coKDAxUXFyc9uzZ48WKAQAA4A1eDa5Hjx5V69atVbp0aS1evFg7d+7UK6+8opCQEGefSZMm6Y033tD06dO1fv16lS1bVp06ddKpU6e8WDkAAACKWylvHnzixImKiorSzJkznW3R0dHOfxtjNHnyZD377LPq0qWLJOn9999XRESEFi1apB49ehR7zQAAAPAOr55x/eyzz9SiRQvde++9Cg8PV9OmTfXuu+86tycnJyslJUVxcXHOtuDgYN1www1at25dvmOePn1amZmZLg8AAADYz6vB9ddff9Vbb72l2rVra+nSpXrkkUc0ZMgQzZ49W5KUkpIiSYqIiHDZLyIiwrktt8TERAUHBzsfUVFRl/dFAAAAoFh4NbhmZ2erWbNmGj9+vJo2baqBAwfqoYce0vTp090eMyEhQRkZGc7H/v37PVgxAAAAvMWrwbVy5cqqX7++S1u9evW0b98+SVJkZKQk6eDBgy59Dh486NyWm7+/v4KCglweAAAAsJ9Xg2vr1q21e/dul7aff/5Z1atXl/TXG7UiIyO1fPly5/bMzEytX79erVq1KtZaAQAA4F1evavAE088odjYWI0fP17du3fX999/r3feeUfvvPOOJMnhcGjo0KEaN26cateurejoaD333HOqUqWKunbt6s3SAQAAUMy8Glyvv/56LVy4UAkJCRozZoyio6M1efJk9erVy9nnqaee0okTJzRw4EClp6frpptu0pIlSxQQEODFygEAAFDcHMYY4+0iLqfMzEwFBwcrIyOj2K53nbA5rViOg+I3smmYt0sAAOCqU9i85vWPfAUAAAAKg+AKAAAAKxBcAQAAYAWCKwAAAKxAcAUAAIAVCK4AAACwAsEVAAAAViC4AgAAwAoEVwAAAFiB4AoA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/fr16tu376XWBAAAAOThVnDdvHmzWrdunaf9xhtv1JYtWy61JgAAACAPt4Krw+HQsWPH8rRnZGQoKyvrkosCAAAAcnMruLZt21aJiYkuITUrK0uJiYm66aabPFYcAAAAkMOtuwpMnDhRbdu2VZ06ddSmTRtJ0jfffKPMzEytWLHCowUCAAAAkptnXOvXr69t27ape/fuSk1N1bFjx9S7d2/99NNPatiwoadrBAAAANw74ypJVapU0fjx4z1ZCwAAAFAgt864zpw5U3Pnzs3TPnfuXM2ePfuSiwIAAABycyu4JiYmKiwsLE97eHg4Z2EBAABwWbgVXPft26fo6Og87dWrV9e+ffsuuSgAAAAgN7eCa3h4uLZt25anfevWrapYsaJbhUyYMEEOh0NDhw51tp06dUrx8fGqWLGiypUrp27duungwYNujQ8AAAC7uRVce/bsqSFDhmjlypXKyspSVlaWVqxYoccff1w9evQo8ngbNmzQ22+/reuuu86l/YknntDnn3+uuXPnatWqVfrjjz909913u1MyAAAALOfWXQXGjh2rvXv36uabb1apUn8NkZWVpT59+hT5Gtfjx4+rV69eevfddzVu3Dhne0ZGht577z19/PHH6tChg6S/3hRWr149fffdd7rxxhvdKR0AAACWcuuMq5+fnz755BOtX79eH330kRYsWKBff/1VM2bMkJ+fX5HGio+PV+fOnRUXF+fSvnHjRp09e9alvW7durrmmmu0bt26Asc7ffq0MjMzXR4AAACwX5HPuKanp+uZZ57RJ598oqNHj0qSQkJC1KNHD40bN04VKlQo9Fhz5szRpk2btGHDhjzbUlJS5Ofnl2e8iIgIpaSkFDhmYmKiXnjhhULXAAAAADsUKbgeOXJErVq10u+//65evXqpXr16kqSdO3dq1qxZWr58ub799luFhIRcdKz9+/fr8ccf17JlyxQQEOBe9flISEjQsGHDnM8zMzMVFRXlsfEBAADgHUUKrmPGjJGfn5+SkpIUERGRZ1vHjh01ZswYvfbaaxcda+PGjUpNTVWzZs2cbVlZWVq9erWmTp2qpUuX6syZM0pPT3c563rw4EFFRkYWOK6/v7/8/f2L8rIAAABggSJd47po0SK9/PLLeUKrJEVGRmrSpElauHBhoca6+eabtX37dm3ZssX5aNGihXr16uX8d+nSpbV8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",
|
||
"text/plain": [
|
||
"<Figure size 800x600 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"from collections import Counter\n",
|
||
"# Count occurrences of each number\n",
|
||
"count = Counter(np.array([l.mu_value if l.mu_value is not None else 0.0 for l in db.data.values() ]).round(0))\n",
|
||
"\n",
|
||
"# Separate the counts into two lists for plotting\n",
|
||
"x = list(count.keys()) # List of unique numbers\n",
|
||
"y = list(count.values()) # List of their respective counts\n",
|
||
"\n",
|
||
"# Plot the data\n",
|
||
"plt.figure(figsize=(8, 6))\n",
|
||
"plt.bar(x, y, color='skyblue')\n",
|
||
"\n",
|
||
"# Adding labels and title\n",
|
||
"plt.xlabel('Number')\n",
|
||
"plt.ylabel('Occurrences')\n",
|
||
"plt.title('Occurance of each mu in db (rounded)')\n",
|
||
"\n",
|
||
"# Show the plot\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 24,
|
||
"id": "adbfeb40-76bd-4224-ac45-65c7b2b2cb7b",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def plot_requests(object_id: int):\n",
|
||
" mu = db.mu_values[object_id]\n",
|
||
" lmb = db.lambda_values[object_id]\n",
|
||
" rq_log = np.array(cache.request_log[object_id])\n",
|
||
" df = rq_log[1:] - rq_log[:-1]\n",
|
||
" pd.DataFrame(df, columns=[f\"{object_id}, mu:{mu:.2f}, lambda: {lmb:.2f}\"]).plot()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 25,
|
||
"id": "1f550686-3463-4e50-be83-ceafb27512b0",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def print_rate(object_id: int):\n",
|
||
" # Calculate time intervals between consecutive events\n",
|
||
" intervals = np.diff(np.array(cache.request_log[object_id])) # Differences between each event time\n",
|
||
" \n",
|
||
" # Calculate the rate per second for each interval\n",
|
||
" rates = 1 / intervals # Inverse of the time interval gives rate per second\n",
|
||
" \n",
|
||
" # Optional: Calculate the average event rate over all intervals\n",
|
||
" average_rate = np.mean(rates)\n",
|
||
" print(\"Average event rate per second:\", average_rate)\n",
|
||
" print(\"The mu is: \", db.lambda_values[object_id])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 26,
|
||
"id": "5b6dac2e-8596-4e7c-97d8-aaf9632e4154",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"count 90.000000\n",
|
||
"mean 0.050767\n",
|
||
"std 0.027965\n",
|
||
"min 0.025100\n",
|
||
"25% 0.030700\n",
|
||
"50% 0.040200\n",
|
||
"75% 0.060625\n",
|
||
"max 0.146900\n",
|
||
"Name: lambda, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 26,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"merged[merged['hits']==0]['lambda'].describe()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 27,
|
||
"id": "29393374-e379-42c8-8333-abfecc18e828",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"count 10.000000\n",
|
||
"mean 0.356500\n",
|
||
"std 0.259982\n",
|
||
"min 0.158500\n",
|
||
"25% 0.194825\n",
|
||
"50% 0.257200\n",
|
||
"75% 0.393875\n",
|
||
"max 1.000000\n",
|
||
"Name: lambda, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 27,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"merged[merged['hits']>0]['lambda'].describe()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 30,
|
||
"id": "3f314883-98ec-4a59-ba80-11cf753a423e",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"__main__.SimulationConfig"
|
||
]
|
||
},
|
||
"execution_count": 30,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"SimulationConfig.mro"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 28,
|
||
"id": "b47990b1-0231-43ac-8bc5-8340abe4a8b3",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# os.makedirs(EXPERIMENT_BASE_DIR, exist_ok=True)\n",
|
||
"# folder_name = experiment_name.replace(\" \", \"_\").replace(\"(\", \"\").replace(\")\", \"\").replace(\".\", \"_\")\n",
|
||
"# folder_path = os.path.join(EXPERIMENT_BASE_DIR, folder_name)\n",
|
||
"# os.makedirs(folder_path, exist_ok=True)\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 29,
|
||
"id": "db83cad4-7cc6-4702-ae3a-d1af30a561d2",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# file_names = os.listdir(TEMP_BASE_DIR)\n",
|
||
" \n",
|
||
"# for file_name in file_names:\n",
|
||
"# shutil.move(os.path.join(TEMP_BASE_DIR, file_name), folder_path)"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "graphs",
|
||
"language": "python",
|
||
"name": "graphs"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.12.7"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|