diff --git a/docs/source/pydatastructs_urban_dictionary_example.ipynb b/docs/source/pydatastructs_urban_dictionary_example.ipynb new file mode 100644 index 00000000..3212a2fb --- /dev/null +++ b/docs/source/pydatastructs_urban_dictionary_example.ipynb @@ -0,0 +1,907 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Analysis of the PyDataStructs string matching API\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dataset\n", + "\n", + "We have used the [Urban Dictionary Words and Definitions](www.kaggle.com/datasets/therohk/urban-dictionary-words-dataset) from [Urban Dictionary](https://www.urbandictionary.com/). The intent of this demo is to show how the different **pydatastructs** string matching API can be used and their performances.\n", + "\n", + "The Urban Dictionary Words and Definitions dataset contains a collection of crowdsourced slang terms and their meanings from Urban Dictionary, a popular user-driven dictionary for contemporary language and internet jargon. This dataset includes word entries, corresponding definitions, upvote/downvote counts, and other metadata, making it valuable for natural language processing (NLP) tasks, sentiment analysis, and linguistic research. Due to its informal nature, the dataset captures evolving slang, cultural references, and colloquial expressions, providing insights into modern language trends.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# Import API for string searching\n", + "from pydatastructs import find\n", + "\n", + "# Import util modules\n", + "import time\n", + "import pandas as pd\n", + "from pandas.core.frame import DataFrame\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Load dataset\n", + "df: DataFrame = pd.read_csv(\"urbandict-word-defs.csv\", low_memory=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dataset Shape:\n", + "(1048525, 12)\n", + "Dataset Columns:\n", + "Index(['word_id', 'word', 'up_votes', 'down_votes', 'author', 'definition',\n", + " 'Unnamed: 6', 'Unnamed: 7', 'Unnamed: 8', 'Unnamed: 9', 'Unnamed: 10',\n", + " 'Unnamed: 11'],\n", + " dtype='object')\n", + "Dataset Info:\n", + "\n", + "RangeIndex: 1048525 entries, 0 to 1048524\n", + "Data columns (total 12 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 word_id 1048525 non-null int64 \n", + " 1 word 1048500 non-null object\n", + " 2 up_votes 1048497 non-null object\n", + " 3 down_votes 1048521 non-null object\n", + " 4 author 1048524 non-null object\n", + " 5 definition 1048362 non-null object\n", + " 6 Unnamed: 6 153 non-null object\n", + " 7 Unnamed: 7 34 non-null object\n", + " 8 Unnamed: 8 6 non-null object\n", + " 9 Unnamed: 9 2 non-null object\n", + " 10 Unnamed: 10 1 non-null object\n", + " 11 Unnamed: 11 1 non-null object\n", + "dtypes: int64(1), object(11)\n", + "memory usage: 96.0+ MB\n", + "None\n", + "Dataset Description:\n", + " word_id\n", + "count 1.048525e+06\n", + "mean 1.411658e+06\n", + "std 8.498497e+05\n", + "min 7.000000e+00\n", + "25% 6.826870e+05\n", + "50% 1.398224e+06\n", + "75% 2.115287e+06\n", + "max 2.856896e+06\n", + "Dataset Sample:\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
word_idwordup_votesdown_votesauthordefinitionUnnamed: 6Unnamed: 7Unnamed: 8Unnamed: 9Unnamed: 10Unnamed: 11
07Janky296255dc397b2fUndesirable; less-than optimum.NaNNaNNaNNaNNaNNaN
18slumpin'1637dc397b2flow down and funky, but [knee deep] enough to ...NaNNaNNaNNaNNaNNaN
29yayeeyay1927dc397b2faffirmation; suggestion of encouragement, appr...NaNNaNNaNNaNNaNNaN
312hard-core16296d1610749anything out of our league that can be good or...NaNNaNNaNNaNNaNNaN
413brutal124540ece1efanything that makes you sweatNaNNaNNaNNaNNaNNaN
\n", + "
" + ], + "text/plain": [ + " word_id word up_votes down_votes author \\\n", + "0 7 Janky 296 255 dc397b2f \n", + "1 8 slumpin' 16 37 dc397b2f \n", + "2 9 yayeeyay 19 27 dc397b2f \n", + "3 12 hard-core 162 96 d1610749 \n", + "4 13 brutal 12 45 40ece1ef \n", + "\n", + " definition Unnamed: 6 Unnamed: 7 \\\n", + "0 Undesirable; less-than optimum. NaN NaN \n", + "1 low down and funky, but [knee deep] enough to ... NaN NaN \n", + "2 affirmation; suggestion of encouragement, appr... NaN NaN \n", + "3 anything out of our league that can be good or... NaN NaN \n", + "4 anything that makes you sweat NaN NaN \n", + "\n", + " Unnamed: 8 Unnamed: 9 Unnamed: 10 Unnamed: 11 \n", + "0 NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Display some info about dataset\n", + "print(\"Dataset Shape:\")\n", + "print(df.shape)\n", + "print(\"Dataset Columns:\")\n", + "print(df.columns)\n", + "print(\"Dataset Info:\")\n", + "print(df.info())\n", + "print(\"Dataset Description:\")\n", + "print(df.describe())\n", + "print(\"Dataset Sample:\")\n", + "display(df.head())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Search Methodologies\n", + "\n", + "We employ four different search techniques to analyze word queries within the dataset. They all use the pydatastructs backend and API.\n", + "The four algorithms are as follows:\n", + "\n", + "1. Knuth-Morris-Pratt\n", + "2. Rabin–Karp\n", + "3. Boyer-Moore\n", + "4. Z-Function\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "class Searcher:\n", + " \"\"\"\n", + " Provides static methods for performing string search using various algorithms\n", + " from the pydatastructs library. It also includes a method to evaluate the performance of these\n", + " search algorithms.\n", + "\n", + " Methods\n", + " -------\n", + " pydatastrcuts_rabin_karp_serach(text: str, pattern: str) -> int\n", + " Uses the Rabin-Karp algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " pydatastructs_kmp_search(text: str, pattern: str) -> int\n", + " Uses the Knuth-Morris-Pratt algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " pydatastructs_boyer_moore_search(text: str, pattern: str) -> int\n", + " Uses the Boyer-Moore algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " pydatastructs_z_function_search(text: str, pattern: str) -> int\n", + " Uses the Z-Function algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " evaluate_search_performance(search_func, text: str, query: str) -> Tuple[int, float]\n", + " Evaluates the performance of a given search function by measuring the execution time\n", + " and the number of results found for a specific query in the text.\n", + " \"\"\"\n", + "\n", + " @staticmethod\n", + " def pydatastrcuts_rabin_karp_serach(text: str, pattern: str) -> int:\n", + " \"\"\"\n", + " Uses the Rabin-Karp algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " Parameters\n", + " ----------\n", + " text : str\n", + " The text in which to search for the pattern.\n", + " pattern : str\n", + " The pattern to search for in the text.\n", + "\n", + " Returns\n", + " -------\n", + " int\n", + " The number of occurrences of the pattern found in the text.\n", + " \"\"\"\n", + " positions = find(text, pattern, algorithm='rabin_karp')\n", + " return len(positions)\n", + "\n", + " @staticmethod\n", + " def pydatastructs_kmp_search(text: str, pattern: str) -> int:\n", + " \"\"\"\n", + " Uses the Knuth-Morris-Pratt algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " Parameters\n", + " ----------\n", + " text : str\n", + " The text in which to search for the pattern.\n", + " pattern : str\n", + " The pattern to search for in the text.\n", + "\n", + " Returns\n", + " -------\n", + " int\n", + " The number of occurrences of the pattern found in the text.\n", + " \"\"\"\n", + " positions = find(text, pattern, algorithm='kmp')\n", + " return len(positions)\n", + "\n", + " @staticmethod\n", + " def pydatastructs_boyer_moore_search(text: str, pattern: str) -> int:\n", + " \"\"\"\n", + " Uses the Boyer-Moore algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " Parameters\n", + " ----------\n", + " text : str\n", + " The text in which to search for the pattern.\n", + " pattern : str\n", + " The pattern to search for in the text.\n", + "\n", + " Returns\n", + " -------\n", + " int\n", + " The number of occurrences of the pattern found in the text.\n", + " \"\"\"\n", + " positions = find(text, pattern, algorithm='boyer_moore')\n", + " return len(positions)\n", + "\n", + " @staticmethod\n", + " def pydatastructs_z_function_search(text: str, pattern: str) -> int:\n", + " \"\"\"\n", + " Uses the Z-Function algorithm to find occurrences of a pattern in a given text.\n", + "\n", + " Parameters\n", + " ----------\n", + " text : str\n", + " The text in which to search for the pattern.\n", + " pattern : str\n", + " The pattern to search for in the text.\n", + "\n", + " Returns\n", + " -------\n", + " int\n", + " The number of occurrences of the pattern found in the text.\n", + " \"\"\"\n", + " positions = find(text, pattern, algorithm='z_function')\n", + " return len(positions)\n", + "\n", + " # Evaluate performance of search functions\n", + " @staticmethod\n", + " def evaluate_search_performance(search_func, text: str, query: str) -> tuple[int, float]:\n", + " \"\"\"\n", + " Evaluates the performance of a given search function by measuring the execution time\n", + " and the number of results found for a specific query in the text.\n", + "\n", + " Parameters\n", + " ----------\n", + " search_func : function\n", + " The search function to evaluate. It should take two arguments: text and query.\n", + " text : str\n", + " The text in which to search for the query.\n", + " query : str\n", + " The query to search for in the text.\n", + "\n", + " Returns\n", + " -------\n", + " tuple[int, float]\n", + " A tuple containing the number of occurrences of the query found in the text\n", + " and the execution time of the search function.\n", + " \"\"\"\n", + " start_time = time.time()\n", + " result = search_func(text, query)\n", + " end_time = time.time()\n", + " execution_time = end_time - start_time\n", + " return result, execution_time" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# Best and worst case words for each algorithm\n", + "\n", + "boyer_moore_best: list[str] = [\"xylophone\"] # Unique letters allow large skips\n", + "boyer_moore_worst: list[str] = [\"aaaaa\"] # Repetitive patterns force O(mn)\n", + "\n", + "kmp_best: list[str] = [\"banana\"] # Repeating prefixes make KMP efficient\n", + "# No repeating substrings, so KMP has no major optimizations\n", + "kmp_worst: list[str] = [\"xyzabc\"]\n", + "\n", + "# Quickly identifies repeated prefix-suffix patterns\n", + "z_function_best: list[str] = [\"abracadabra\"]\n", + "# No repeating substrings, making Z-function similar to KMP\n", + "z_function_worst: list[str] = [\"qwerty\"]\n", + "\n", + "# Great for multi-pattern searches\n", + "rabin_karp_best: list[str] = [\"hello\", \"world\", \"search\"]\n", + "# Hash collisions can degrade performance to O(mn)\n", + "rabin_karp_worst: list[str] = [\"abcdefghij\"]\n", + "\n", + "# Test queries\n", + "test_queries = boyer_moore_best + boyer_moore_worst + kmp_best + kmp_worst + \\\n", + " z_function_best + z_function_worst + rabin_karp_best + rabin_karp_worst\n", + "\n", + "\n", + "methods = {\n", + " \"Rabin-Karp\": Searcher.pydatastrcuts_rabin_karp_serach,\n", + " \"Knuth-Morris-Pratt\": Searcher.pydatastructs_kmp_search,\n", + " \"Boyer-Moore\": Searcher.pydatastructs_boyer_moore_search,\n", + " \"Z-Function\": Searcher.pydatastructs_z_function_search\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Run evaluation\n", + "performance_results = []\n", + "text = df['word'].str.cat(sep=' ') # Concatenate all words in the dataset\n", + "for method_name, method_func in methods.items():\n", + " for query in test_queries:\n", + " num_results, exec_time = Searcher.evaluate_search_performance(\n", + " method_func, text, query)\n", + " performance_results.append(\n", + " [method_name, query, num_results, exec_time])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Results\n", + "\n", + "The comparison of the **Boyer-Moore, Knuth-Morris-Pratt (KMP), Z-function, and Rabin-Karp** string search algorithms highlights their strengths and weaknesses across different scenarios.\n", + "\n", + "- **Boyer-Moore** excels in average-case performance, often achieving **sublinear time**, making it ideal for long patterns in large alphabets. However, it suffers from **O(mn) worst-case performance** on repetitive text.\n", + "- **KMP** and **Z-function** guarantee **O(n + m) worst-case complexity**, making them more reliable for structured pattern matching, though they lack the efficiency of Boyer-Moore in general cases.\n", + "- **Rabin-Karp**, leveraging hashing, performs well in **O(n + m) average-case** but degrades to **O(nm) worst-case** due to hash collisions, making it more suitable for multiple-pattern searches.\n", + "\n", + "Ultimately, the choice depends on the text structure, pattern length, and performance guarantees required for the application.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
MethodQueryResults FoundExecution Time (s)
0Rabin-Karpxylophone716.368275
1Rabin-Karpaaaaa25530.503066
2Rabin-Karpbanana51163.199950
3Rabin-Karpxyzabc062.661349
4Rabin-Karpabracadabra158.821800
5Rabin-Karpqwerty6314.416847
6Rabin-Karphello25516.551707
7Rabin-Karpworld102315.397617
8Rabin-Karpsearch12756.959028
9Rabin-Karpabcdefghij1522.469995
10Knuth-Morris-Prattxylophone73.466889
11Knuth-Morris-Prattaaaaa2553.379942
12Knuth-Morris-Prattbanana5113.340413
13Knuth-Morris-Prattxyzabc03.506472
14Knuth-Morris-Prattabracadabra13.423525
15Knuth-Morris-Prattqwerty633.244726
16Knuth-Morris-Pratthello2553.567353
17Knuth-Morris-Prattworld10232.514962
18Knuth-Morris-Prattsearch1272.727760
19Knuth-Morris-Prattabcdefghij152.416548
20Boyer-Moorexylophone70.409917
21Boyer-Mooreaaaaa2550.582294
22Boyer-Moorebanana5110.765548
23Boyer-Moorexyzabc00.721526
24Boyer-Mooreabracadabra10.285021
25Boyer-Mooreqwerty631.034254
26Boyer-Moorehello2550.670151
27Boyer-Mooreworld10230.705552
28Boyer-Mooresearch1270.847801
29Boyer-Mooreabcdefghij150.395121
30Z-Functionxylophone726.620959
31Z-Functionaaaaa25522.801260
32Z-Functionbanana51122.610493
33Z-Functionxyzabc021.820343
34Z-Functionabracadabra120.470267
35Z-Functionqwerty6324.497443
36Z-Functionhello25525.262055
37Z-Functionworld102324.878788
38Z-Functionsearch12724.227696
39Z-Functionabcdefghij1524.152845
\n", + "
" + ], + "text/plain": [ + " Method Query Results Found Execution Time (s)\n", + "0 Rabin-Karp xylophone 7 16.368275\n", + "1 Rabin-Karp aaaaa 255 30.503066\n", + "2 Rabin-Karp banana 511 63.199950\n", + "3 Rabin-Karp xyzabc 0 62.661349\n", + "4 Rabin-Karp abracadabra 1 58.821800\n", + "5 Rabin-Karp qwerty 63 14.416847\n", + "6 Rabin-Karp hello 255 16.551707\n", + "7 Rabin-Karp world 1023 15.397617\n", + "8 Rabin-Karp search 127 56.959028\n", + "9 Rabin-Karp abcdefghij 15 22.469995\n", + "10 Knuth-Morris-Pratt xylophone 7 3.466889\n", + "11 Knuth-Morris-Pratt aaaaa 255 3.379942\n", + "12 Knuth-Morris-Pratt banana 511 3.340413\n", + "13 Knuth-Morris-Pratt xyzabc 0 3.506472\n", + "14 Knuth-Morris-Pratt abracadabra 1 3.423525\n", + "15 Knuth-Morris-Pratt qwerty 63 3.244726\n", + "16 Knuth-Morris-Pratt hello 255 3.567353\n", + "17 Knuth-Morris-Pratt world 1023 2.514962\n", + "18 Knuth-Morris-Pratt search 127 2.727760\n", + "19 Knuth-Morris-Pratt abcdefghij 15 2.416548\n", + "20 Boyer-Moore xylophone 7 0.409917\n", + "21 Boyer-Moore aaaaa 255 0.582294\n", + "22 Boyer-Moore banana 511 0.765548\n", + "23 Boyer-Moore xyzabc 0 0.721526\n", + "24 Boyer-Moore abracadabra 1 0.285021\n", + "25 Boyer-Moore qwerty 63 1.034254\n", + "26 Boyer-Moore hello 255 0.670151\n", + "27 Boyer-Moore world 1023 0.705552\n", + "28 Boyer-Moore search 127 0.847801\n", + "29 Boyer-Moore abcdefghij 15 0.395121\n", + "30 Z-Function xylophone 7 26.620959\n", + "31 Z-Function aaaaa 255 22.801260\n", + "32 Z-Function banana 511 22.610493\n", + "33 Z-Function xyzabc 0 21.820343\n", + "34 Z-Function abracadabra 1 20.470267\n", + "35 Z-Function qwerty 63 24.497443\n", + "36 Z-Function hello 255 25.262055\n", + "37 Z-Function world 1023 24.878788\n", + "38 Z-Function search 127 24.227696\n", + "39 Z-Function abcdefghij 15 24.152845" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Display performance results\n", + "performance_df = pd.DataFrame(performance_results, columns=[\n", + " \"Method\", \"Query\", \"Results Found\", \"Execution Time (s)\"])\n", + "display(performance_df)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+gAAAImCAYAAADANqCUAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAfxVJREFUeJzt3Qm8lOP///HPOe1JUdqF5BtFq0pkqZCkKFsiZK2kkiWVhCgRESUtEhGFQvKVbCFKq61CSSotSqv2zvwf7+v7v+c3ZzrLzDlzzrnPzOv5eMzjnLnnnnuu+7rXz7XdSYFAIGAAAAAAACBPJeftzwMAAAAAACFABwAAAADABwjQAQAAAADwAQJ0AAAAAAB8gAAdAAAAAAAfIEAHAAAAAMAHCNABAAAAAPABAnQAAAAAAHyAAB0AgBCBQCCvkwA47Iv5D9sMQHYRoAPwrR9//NHuu+8+a9q0qdWuXdsuuOACe/DBB23NmjUWL55//nk7+eSTLT+ZO3euXXTRRXbaaafZrbfemuY8ffr0ceuV3qtJkybmR7/99pt16NAh1TSlV9spJ61duzbD/PJe8+bNs+bNm7v89atffvnF2rZt6/aPVq1axXz5119/fao8OeWUU6xevXp2+eWX26uvvmoHDx5MNX94foXvv7t27bIuXbpYnTp1rGHDhvbHH3+YHyxcuNBuv/32TOfbvXu32z+V1zpPnn766XbNNdfYW2+95btgMbvHktZLy5g5c2aOLD8rx+zUqVPd+x07dljv3r1twYIFqfZVvQAgGgWjmhsAcsnrr79ugwcPtjPOOMPuueceK1eunK1evdpeeukl+/jjj+2VV15xN+b53VVXXWXnnHOO5SdPPvmkpaSk2JgxY6xMmTLpzle2bFkbMWJEmp8VKlTI/Oijjz6yxYsXp5o2efJkq1ChQo7+rvZv/Y7n77//tjvvvNO6du3qCqg8J510ksvTEiVKmF+NHDnS/vrrL/e3dOnSOfIbNWvWtIceesj9f+jQIdu+fbt9+eWX9vjjj7sA6dlnn7Xk5P/VQYTnV/j+++6779rnn39uAwYMsP/85z927LHHmh8owF65cmWG8ygAV+HC77//7oJ5pX/fvn329ddfu8JMFTj169fP4oHWUcdm9erV7c0333SFLHnJO2aPO+44937ZsmX23nvv2RVXXJGn6QKQ/xGgA/Ad1RwNGjTIrrvuOnvggQeC0xWsqxZdtXO66fRqLvIzBX45HfzF2rZt21xN41lnnZXhfIULF7a6detafpcb6xCeV6qdE938h/++glM/27p1qwuizjvvvBz7DQXc4fmimvITTzzRnTs++OADu/TSS9PMr/D9d9asWe7vtddea0lJSZbfzpVqVTF+/PhUrVJUqKMCitdee81uu+02V1iW3+l8X7lyZevcubPde++9rsD2+OOPz7P0xMv5DYD/0MQdgO+olvzII4+0u++++7DPVCOn5qrnn3++a9rp1aCpxr1NmzauiaduTp966ilXk+TRd2655RZX46EgX/OpueSqVatc7Zm+qyauqtFWTUjo99RE8e2337ZmzZq5prQ33nijLV++PFW65s+f75avG381nVWwoKaWqqkLbQ758ssvW8uWLd1vvfPOO4c1cf/zzz9djZgKIzRP+/btbfbs2Yc1/ddvaZ769eu7+VVT5tENu5b57bff2s033+yWo5v3oUOHurzKiJr39ujRw82vm0+tu4KA0HVYt26dq3X0mlxnx08//WSnnnpqqibIW7ZssTPPPNNuuummYBNd1chqf2jUqJFbH22DpUuXplqWmio/+uijrkWC0q6arC+++CLD5q+h+a//vRr/0HnDv7dp0ybr27evC0C1H1155ZX26aefplquvqN9UgVMSrP2m549e9rmzZstu0KbbHvbRDX/d9xxh1tvBZ4vvPCCyw8VZKnJs6Zp+4c2edbxodpkrYf2WR0DH3744WHbR3mtZWgdOnXqZEuWLEk3bUrLd999546H0Oa/Ge1XGR0f0erYsaOVL1/e1bCG51da+6/S4W1btcjx8jWSvNFy1cpH+aP9wCtMVAGAauOV57Vq1bKrr77aHYvR7B9Kx7Rp01xaQ/MxnFpaiHeeCaUCh169eqUqdIjkOFI+qan22Wef7Y5NHYt6r4KXzNZdx8b999/vvqN10vYIb5Gi/TJ0vbVfZHZc6LylbaZzsM7fxYsXT9XiJD1qgaACCp0ntT2eeeYZd+yGNjvXtlZrD+132l4tWrRwrStC81Tzq1BAadX+q3NTaBN3nQdvuOEGN6/+hi5fx9zYsWODXbV0Tv/hhx+Cn2v/02+roKh169YuDZdddpnLNx1ruibpe/osdD/au3evPfzww3buuee6fVTL0LUTQP5HgA7AV3Qzo+aZusErVqxY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f72dfPLJds0116Q7T69evdw8ffr0iXi5CxcutNtvvz34fu3atW4ZU6dOtZyQ08sHAAAAgFgjQMdhkpOTbcmSJW40+3AaHfzzzz+PeplvvfWWrVy5MkYpBAAAAID4Q4COw9SsWdOKFCliH3300WGfKTjXCOHly5fPk7QBAAAAQLwiQEeao3+fd955aQboH374oV100UVWsOD/PaEvJSXFxowZYxdeeKGddtpp7vOJEycGP1dT+GnTptm6desOa3b+999/W48ePaxevXrWqFEje/DBB+3ff/9N9di7119/3dq0aWO1a9e2pk2b2lNPPWX79u1Lla6PP/7YLr30UjdPu3btbPny5TmQMwAAAACQcwjQkaZWrVod1sx9165d9uWXX1rr1q1Tzfvwww/bc8895wLkF1980Vq2bGmDBw+2kSNHus/vuOMOF/CXLVvWJk+e7IJsz/Dhw61ixYr2wgsv2I033mhTpkyxESNGBD8fMGCAPf7443bBBRfYqFGj7LrrrrPXXnvNLdMbdO6zzz5zQb6Cf/3mxRdfbPfdd18u5BIAAAAAxM7/VYMCIRREqym7atE7derkps2aNcvKlCljp59+enC+VatWuaD67rvvDg4Cd/bZZ7tHfI0ePdquvfZaO+6446x06dJWuHBhq1u3brAvu6i2vW/fvu7/M8880+bMmWNz585171esWGFvv/223XPPPcFlN2nSxMqVK2e9e/d2hQUK/BWUq+Z86NChbp5zzjnH/X366adzMccAAAAAIHuoQUeaihYtas2bN0/VzH3GjBmudjr0+doKplWTrXkPHjwYfOm9mqFr9PaMNGjQINX7Y4891nbs2OH+/+6779zfSy65JNU8el+gQAGbN2+e7d27137++Wdr1qxZqnmUTgAAAADIT6hBR7oU5N55552umbsGjfv222/trrvuSjXPtm3b0gyiPRs3bszwN1RLHz6CvNd0ffv27e6vmsaHUv/3o48+2nbu3Onm0fx6H0q17AAAAACQnxCgI13nnnuuHXHEEa4WXQPHqXZbg8CFKlmypPv7yiuvuHnDVapUKcu/X6pUqeBAcpUrVw5OP3DggG3dutUF5UcddZQL6jdv3pxmwQEylpISsOTkJN8tCwAAAEhEBOhIl/qMa3C2mTNnuibvadWSe03UFTA3btw4OH327NluJHf1L1e/dQXR0dKo7l7Teq8Puvdeo7urL7xq9jUCvEZx79atW7D5vQaOQ+YUUI98Y46t2/S/1gpZVblcKevWoUnM0gUAAAAkIgJ0ZDqae+fOnV2A3b9//8M+18jpGr1dj0fTY9RUw66B45555hlX437CCScEa9pVy63AvUaNGhH99kknneQemaYR4vfs2WMNGza0ZcuWuVHezzjjjOBgcBqgTiPAqzl++/bt3e9rNHlERsH5H+u25nUyAAAAgIRHgI4MnXXWWS641qPQqlWrluY8egyaRmx/8803XX911ZgrsFd/dQ3mJpdffrkLzlXLrUei6fNIDBo0yI4//nh75513bOzYsa5v+Q033OAes+bVyqsWX58NGzbMBekqGNBj3rp06RLDnAAAAACAnJUU8EbkShA//vij+1urVq00P9eo4KqBrVq1qmvWDeRXke7L/YZ/mO0a9BMqH22De0ZW6JLo6PcPAACQeH7MJA71UIMOALmIfv8AAABIDwE6AOQy+v0DAAAgLdEPrQ0AAAAAAGKOAB0AAAAAAB8gQAcAAAAAwAcI0AEAAAAA8AECdAAAAAAAfIAAHQAAAAAAHyBABwAAAADABwjQAQAAAADwAQL0KKSkBPLV715//fV28sknp3qddtpp1rRpUxs4cKDt2bMnouVMnTrVfTcjzZs3t+effz5L6QxNb58+fQ6bPn78ePf7L7zwQraWDwAAAAB+VjCvE5CfJCcn2cg35ti6Tdtz7Tcrlytl3To0yfL3L774YnvggQeC73fv3m1ff/21Pf7445aSkmIPP/xwTNL59ttvW5EiRSzWXn75ZXviiSfsvvvus1tvvTXmywcAAAAAv/BFgP7uu+/amDFjbM2aNXbcccfZnXfe6QJLWbt2rT366KM2f/58K168uF155ZXWvXt3K1CgQJ6kVcH5H+u2Wn5RtGhRK1u2bKppxx9/vP3000/24YcfxixAL126tMXahAkTXHCuAoYbbrgh5ssHAAAAAD/J8ybu7733ngvArrvuOpsxY4a1bt3a7r77blu8eLEdOHDAbrnlFjffm2++6YLJN954w0aOHJnXyc73VNtdsOD/ymf++usv69Wrl5155pl26qmn2rnnnmtDhw51NeyhpkyZYuecc47VqVPHunTpYuvWrUuzibv+durUyRW6aFm1atWyjh072sqVKyNO3yuvvOKC84ceeuiw4Hz79u3Wv39/lxalV+nWe6/J/rx586xmzZru98844wy7/PLLXeGPmsmrMEj7WO3ate3qq6+2hQsXZisfAQAAACAuatADgYANHz7cBWAK0KVr1662YMEC++6771wAqOBRgWGpUqWsevXqtmXLFnvyySddgFi4cOG8TH6+dPDgQdfEXQUj11xzTTDPVcuu5uRHHHGEffrpp64JfL169eyCCy4IfnfixIlueynf1aqhW7duNm3aNEtKSjrsd7QNVQigIFkFLb1797ZHHnnEXn311UzTqHkGDx5sl112mXXo0OGwz9VPfePGjTZixAgrU6aMLVq0yPr162cnnXSSKxiQQ4cO2ezZs23y5MkucPfSOGTIEBfM16hRw8aOHWs333yzffDBB1alSpVs5SsAAAAA5OsAfdWqVS4Ib9OmTarpL730kvurGnPVkCo49zRu3Nh27dply5YtczW5yNj06dNt5syZwfd79+61SpUquZYJKuTQewXC6lJQsWJFN4+CXAWvv/zyS6oAXbXqp5xyivtftdsXXXSRffvtt3bWWWelWRCgghRv26kwQN/PjAoP3n//fbed1QRfNe+q7Q7VpEkTa9iwYXDgumOPPdZee+01+/XXX1PNp+D7hBNOCHaVkNtvv93VoIsKGebOnesKgO65556I8xQAAAAA4q6JuwJ0b+AyBYxqqnzVVVfZZ5995qZv2LDBKlSokOo75cqVc3/Xr1+fBynOf9T0XM26VdOtGuySJUu6gFrBuZq4q4+6gmD18X/sscfstttuc83SN2/enKqJu2rWveBcFPgq+A4Pij3HHHNMqoKVI4880tWky4svvuhq573XgAEDgvNt3brVBfYqIKhWrZoLnFUgE+raa691TdZVG671UCHCDz/8cFiTfC84D6Um755ChQq5Ue3TWwcAAAAASJgadC/wuv/++93AcPfee6+r7b3jjjtcc2vV7iqgDOWNFL5v375sNa1XoUBatFwFemoirVeovBqYTsLTEul6amA91TCLmnErcFZhSHJysguMlQ/qYqC8Vo24atNVY61Hnnn5oL9a9/A0aLqCXE3Xb4XO700PnddbDxXCtGjRIvhZiRIlgsto2bJlcIBA1dJrXqXTq33XctQk/7fffnM14Zpf/c3VV13f935fQtPgTdN6h6ZLNf1q/p6V/PU7Ly/UxD+88EK03sWKFYvpb+q3tB2QNvIcAAAgMQUCgTS7BvsqQFcAJQoY27Vr5/5X3+ClS5e6AF21u/v370/1HS8wV+CZVarJVRP59KhmObwAQIFdrG+so6F8SCvIyogXMCv49qhbgGrM1c9bTcX1mfJ71qxZrj+3NwibatCVT/pcf3fs2OGCYq+vtv7fuXOnG3Vf82iHU7Cr//VX70N/16s91zRtV71CabrSq53W+55+SwU3w4YNc03aL730UrfdvvrqKzeInAaf85b9559/uqb7+q63z2gbesvytqf6qyvN3vd+/vlnt++FpjVeaJ21LX7//fc0P9f+rMKNWLeK8Qbrw+HIcwAAgMRVOIIx1PI0QC9fvrz7q8HfQmmwry+++MIaNWp0WPPjTZs2pfpuVgsG9BvpBTUamE419eFBZF7KyoB4KlRQzXf4emjEdg2gpoHg1ExcPv74Y1errW4FzzzzTDDI1neVX1qWBmLTAGve+ADaPl7/cwXWXpN5/dX70N/1CmMyytO00qvCmzlz5rjadP1e5cqV3fLVDUJ95rdt22ajR492BQoqjNB3vbwK3YZey4sXXnjBfU/L0QB2CszVZN5P2zqWlFcqkEjrGfWRlOBFq2rVqtTmZoA8BwAASEwrVqyIaL48DdA1AJz6Nn///ffWoEGD4HQF5QoqVGuq/tNqCq9m0KJBvcL7Q2flJjm9GngFiV6gmFaT9srl/q9fdW7wfi8rzeu1nnqFf1frrv7matqumvO+ffu6Z44/99xzruCjVatWrjZaz0rXd5Ufes65mr+rRlu1dc2aNXPBurds/Y6Xb/ob/rualtl6pJdeBeeqPVd/dA3opkIFPcpNj9zT6PNNmzZ1A9spaPd+3/tNb1neNAXjai6vQhi1JtDI9OHjHMQLLy9Ua5tbBRB52cokUZHnAAAA8VNRkxTI46oX1WiOGzfOBg4c6Po+61noChQVMNatW9f1Mz7++ONd/3SNxK1npqt/tALFrPjxxx/dX695dDjVqKrJqGqlwoOalJSAJSfHvgYsM3n1u/FE+87555/vmvaHDhQXzzLal0P1G/6h/bFua7Z+64TKR9vgnq2ytYxEQp4DAAAklh8ziUN9UYMuGhBONUBqVq1nW2vkbtWOekGUgneNPn711Ve7UcFVA6rv5IW8CpIJzgEAAAAg/uV5gC433XSTe6VFtefjx4/P9TQBAAAAAJBwATqQ0/SouV9++SWvkwEAAAAA6frfyFkAAAAAACBPEaADAOKaBtr047IAAADC0cQdABDXNNDmyDfm2LpN27P92MtuHZrELF0AAADhCNABAHFPwXl2H20HAACQ02jiDgAAAACADxCgAwAAAADgAwTocax58+b2/PPPHzb9sccesxo1ati0adNi8jtbt261t956K/j++uuvtz59+kS9nJNPPtm9Pv744zQ/v+WWW9znU6dOtVjLapo9SpOXfu912mmnuW3wxBNP2L59+7KVvt27d9vrr78efH/gwAGbMGFCtpYJAAAAwF/ogx6FQEqKJSUn5+vfVXD+xhtv2NChQ61169YxWeaTTz5pa9eutauuuirbyypUqJDNnDnTWrRocVghwLx58yynqCCjQIEC2V7O119/nSqIXrx4sfXr188F6AMGDMjycsePH+8KAa677jr3/oMPPrDHH3/cOnXqlO00AwAAAPAHAvQoKEhe9cFY27Nlfa79ZrEyFa1q69tisqxBgwbZm2++acOGDbOLLrrIYiUQiN1jh84880z7/PPPXUBbpEiR4HTVqtetW9fmz59vOeGoo46KyXLKli2b6n2lSpVs7ty5Nn369GwF6OF5HMs8BwAAAOAPNHGPkoLzPRv/zL1XjAoDBg8e7ILz5557LlVwribYL730knXv3t3q1atnZ5xxhqtlP3jwYKqm26FCp6lZuJrKf/fdd6nm+/fff61v377WoEEDO/300918aqadmaZNm1pKSop99dVXqaZ/+OGH1qpVq8Pm/+KLL+zqq692aT/77LNdrfLevXuDnytNWudmzZq5z//4449gs3MtT+urtIc2cT906JBrYXDeeee5ZuotW7Z0rQ6ySjXzhQsXDubdhRde6PJY+XLHHXe46Z988olrgaBCiFq1atnll18ezAPV7o8YMcLWrVsXbOKvvPXWLydbFgAAAADIPQToCWDIkCH2yiuv2K233uqC03DDhw+3hg0b2vvvv2+9e/e21157zTWhjsQDDzxgF198sQuQQ5t3q8a7XLlyLphUE3gF2GPHjs10ecWKFXNB+n//+9/gtM2bN9uiRYtcoBxq1qxZ1rVrVze/fueRRx5xv3P33Xenmm/SpEkuSFeQe8IJJ7hpWsf+/fvbuHHjXFAcPv9HH31kzzzzjGtu37FjR3v44YdtwYIFFo39+/e7AoT33nvP5ZHnzz//tE2bNtm7775r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bP28IH727NluXfSZ1lX94eW1116ziRMn2tFHH21XX321C9wBAAAAICcQoMc51VzXq1fPvTRInALzY4891tq0aeOCWNUmq9ZZ70844QS74YYb7Nprr3U1ygqQNX3//v32ySefuOXpO/pfgbso+O3atasLntV8XjXUqnlWYLtv375gOrTMk046ydViZ0bLUKC9ePFi9/7XX3+19evX23nnnZdqvkmTJrkadRUGnHLKKVanTh177rnnbMuWLfbee+9FtH4e9dPX5zVq1HAFDTt27LChQ4e65VavXt0F7ipYmDJlSsy2DQAAAACEog96nLvmmmuCtcEHDx601atX2zPPPONqkh999FE7cOBAqr7e0qhRI1cjrUD3mGOOcc3SVWveunVrV5N95JFH2tlnn23//POPbdiwwYYNG2bDhw8Pfl9NxBWcq3l7kSJF3LTjjz8++PmLL77oCg48Cp4HDhwYfF+mTBlr2LChq7mvX7++a95+4YUXupryUArcVegQOl1N5KtWreo++/333zNdP4+Cc8/SpUtt+/btLg2htE5qUg8AAAAAOYEAPc6VKlUqVXBcrVo1N021yF9++WWa3/H6jxcs+L/d44orrnB9sBXQvv/++3bZZZdZgQIFgvOpj/pZZ5112HIqVqxomzZtOqzfuwoN1Izdk1aT91atWtmoUaPcI9VUKKBR3cOF1oCHp1+jwWf0eej6iVeQ4H2uIF+/Hy68DzwAAAAAxApN3BOQF7iq+bYC2YULF6b6fMGCBa4mWoG8qLZc79W8W595zdtV0126dGlbs2aNKwTwXj///LPra54e9V0PnV/LCacaczVzV79w1WanVQCgwed+/PFH1wTfs3nzZtdKQAURekWyfuHUpP2vv/5yLQW8NFaqVMmefvppmz9/fia5CwAAAABZQ4Ae53bv3u0CXb1Um63gdPDgwVauXDk3qroGWVO/bQ0cp8D29ddfd3271Sfbe+a4nv+u0dzVNF19yBX4ij6/7bbb3CBq6nP+559/2qxZs+zhhx92NebhTdKjocBfo6erH3iLFi1S1XZ7OnToYP/++6/dd999tnz5cjcAXs+ePd2AbuoTr5r5SNYv3KWXXuqCd/Vd//77712zdtXkq8WBCgUAAAAAICfQxD1KlUqVz1e/p5HN9fICbdVe69FhGlitWLFirnm6Alq9V+2z+mIPGDDAjVge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AwAAAADgAwWz+sXdu3fb+vXrbdeuXXb00Udb+fLlrUiRIrFNHQAAAAAACSKqAH3//v329ttv2/Tp0+3HH3+0Q4cOBT8rUKCANWjQwC6++GJr166dFS5cOCfSCwAAAABAYgfoU6dOtaefftr27dtnzZo1c4F45cqVrXjx4rZ9+3bbsGGDLVq0yIYNG2YjRoywHj162FVXXZWzqQcAAAAAIJEC9M6dO9vff/9tAwYMcMF5erXjnTp1crXsH374ob388sv28ccf29ixY2OdZgAAAAAAEjNAb9GihV1xxRURLVDBe9u2be2yyy5zzeEBAAAAAECMRnGPNDgPlZSURBN3AAAAAABychT3NWvWuKbs1apVs507d9qzzz5r69ats5YtW7racwAAAAAAkMPPQZ89e7YbIM5rvq5+6W+++aZt3LjR+vbta2+99Va0iwQAAAAAIOFFHaCPGjXKzj77bOvWrZvt2LHDZs2aZbfffrtNmzbN/X311VdzJqUAAAAAAMSxqAP05cuX24033mglSpSwL7/80j0L/aKLLnKfNWnSxFavXp0T6QQAAAAAIK5FHaAXKVLEDh486P7/+uuvrUyZMnbKKae495s3b7aSJUvGPpUAAAAAAMS5qAeJq1+/vo0fP941b585c6a1a9fOTf/pp59sxIgR7nMAAAAAAJDDNej9+vWzDRs22D333GOVK1e2rl27uumdO3d2I7vfe++90S4SAAAAAICEF3UNepUqVezDDz+0LVu22DHHHBOcPnLkSKtZs6YVLlw41mkEAAAAACDuRVSD/u2336Z6n5SUlCo4l7p16x4WnH/zzTexSCMAAAAAAHEvogB96NChduedd9qyZcsiWuiCBQtck3d9LxqrVq2yevXq2dSpU4PT9JsdO3Z0BQDNmzfnMW4AAAAAgMRt4j5lyhT3/PP27du7fuctWrSw2rVr27HHHmvFixd3A8atX7/eFi5caF999ZWtWbPGOnXq5AaNi9SBAwdc//Xdu3cHp23dutVuuukmF5g/8sgjtmTJEvf3iCOOsCuuuCJrawwAAAAAQH4N0AsWLGjdu3d3AfrLL7/sarhHjx7tmrp7AoGAVapUyT0TXcF5+fLlo0rI888/756tHl4wUKhQIRs4cKBLQ7Vq1dxz1seMGUOADgAAAABI3EHiypUrZ/fff797rVy50tauXWs7d+60o48+2gXnVatWzVIi5s+fb5MnT7Z3333XmjZtmqqpfKNGjVxw7mncuLErHNAz18P7wQMAAAAAkDCjuHtUm61Xdql5fO/eva1///5WsWLFVJ/pcW7Vq1c/rJBA1KSeAB0AAAAAYIkeoMfKww8/7AaGa9OmzWGf7d2797CR4YsUKeL+7tu3L8u/qeb4oX3dgUSkLirFihWL6TL37Nnjji+kjTzPfeQ5AMQHzufI77SvhXYR92WAribtasY+ffr0ND8vWrSo7d+/P9U0LzDX4HRZpQHpIh2RHohXusjVrFkzpsvUkxh0sUPayPPcR54DQHzgfI54EF757LsA/Z133rEtW7ak6ncuDz30kH344YdWoUIF27RpU6rPvPfRDkIXSgPPnXTSSVn+PhAPIinBi5bGoaAkOn3kee4jzwEgPnA+R363YsWKiObL0wD9qaeecs3YQ+kRbj169LBLL73U3nvvPXvzzTft0KFDVqBAAff53Llz3cFUpkyZbB3g2amBB5C2WDc9Q+bI89xHngNAfOB8Dj8WMiVn9QdSUlJs+fLl9uWXX9quXbts27ZtUS9DteDHH398qpco+NZnepSalv3AAw+4Egc93m3ChAnWuXPnrCYbAAAAAABfylINumq2n376adfcPDk52d566y33HHM1Hdf0SNrWR0KB+rhx42zQoEHWrl07K1u2rBvxXf8DAAAAAJDQAbr6hus56GqC3qxZM+vVq5ebfuGFF9ojjzxiL7zwgt11111ZTtAvv/yS6n3t2rXdM9IBAAAAAIhnUQfoL774ol1zzTXu8WjqG+5Rc/R//vnHpkyZkq0AHQAAAACARJSclccRqLY8LXXq1LGNGzfGIl0AAAAAACSU5Kz0C1+5cmWan2l6dkZXBwAAAAAgUUUdoLdq1cqee+45++ijj2z//v3BIeN/+ukn1/+8ZcuWOZFOAAAAAADiWtR90NW//Ndff3V/NYK7XH/99bZ7925r0KCB9ezZMyfSCQAAAABAXIs6QNcj1PToszlz5ti3335r27dvtyOPPNIaNWpk5513XsQPYAcAAAAAANl8Dro0adLEvQAAAAAAQB4F6DNnzrRFixbZjh07DvtMNeiDBw+OQdIAAAAAAEgcUQfoTz31lGviXqJECStZsuRhn9PEHQAAAACAXAjQp02bZtdee60NGDAgCz8HAAAAAABi8pi1ffv2WYsWLaL9GgAAAAAAiGWAruD8k08+ifZrAAAAAAAglk3c+/XrZ1dddZV79nnt2rWtWLFih/VB79atW7SLBQAAAAAgoUUdoE+cONFWrVrlXvPnzz/scwJ0AAAAAAByIUB/7bXXrE2bNtanTx8rU6ZMFn4SAAAAAABkuw/67t277corryQ4BwAAAAAgLwP0s846y+bNmxfLNAAAAAAAkPCibuJ+6aWX2oMPPmirV6+2evXqWYkSJQ6bp23btrFKHwAAAAAACSHqAL1nz57u74wZM9wrrUHiCNABAAAAAMjhAP3TTz+N9isAAAAAACDWAXrlypWj/QoAAAAAAIhFgN63b1+74447rEqVKu7/jKiJ++DBgyNZLAAAAAAAiCZA16jtN954Y/D/zAJ0AAAAAACQAwH6kCFDXO25fPbZZ1H+BAAAAAAAiMlz0FV7vnLlykhmBQAAAAAAORWgBwKBrCwbAAAAAADEMkAHAAAAAAA+ecza7Nmz7ffff49o3rZt22YnTQAAAAAAJJyIA/SRI0dGNJ9GcSdABwAAAAAghwL0ESNGWI0aNaJcPAAAAAAAiGmAXq5cOatcuXKkswMAAAAAgCgwSBwAAAAAAD5AgA4AAAAAQH5p4v7pp59a2bJlcz41AAAAAAAkqIgCdPqeAwAAAACQs2jiDgAAAACADxCgAwAAAADgAwToAAAAAAD4AAE6AAAAAAD5ZZC4UP/8848NGjTIvvjiC9uzZ48FAoFUnyclJdnSpUtjmUYAAAAAAOJe1AH6wIED7fPPP7dLLrnEKlSoYMnJVMIDAAAAAJDrAfqXX35p/fr1s/bt22f7xwEAAAAAwP9EXf1dqFAhq1KlSrRfAwAAAAAAsQzQL7zwQvvggw+i/RoAAAAAAIhlE/eaNWvas88+a2vWrLE6depY0aJFDxskrlu3btEuFgAAAACAhJalQeJk/vz57hWOAB0AAAAAgFwI0JcvX56FnwEAAAAAADEN0EOtXLnSdu7caaVLl7bjjjsuO4sCAAAAACChZSlA1yBxTzzxhG3evDk47ZhjjrF77rnH2rZtG8v0AQAAAACQEKIO0D/77DO77777rHHjxnb33Xe7wHzTpk32/vvvW9++fe2oo46ypk2b5kxqAQAAAACIU1EH6KNGjbKWLVvaM888k2r6FVdcYb169bLRo0cToAMAAAAAkNPPQf/111+tXbt2aX6m6QwiBwAAAABALgToRx99tG3fvj3Nz7Zt22aFCxfOQjIAAAAAAEhsUQfoZ555po0YMcI2bNiQavr69ett5MiR1qRJk1imDwAAAACAhBB1H3QNDKf+5i1atLB69eq5QeI0mvvixYutVKlSbiR3AAAAAACQwzXoZcuWtWnTptn1119ve/bssZ9++sn91XtNr1y5crSLBAAAAAAg4WXpOehlypRxj1oDAAAAAAC5GKCrz/lVV11l5cuXd/9nJCkpybp16xaj5AEAAAAAkBgiDtDPPffcHAnQt2zZYkOGDLGvvvrK9u3bZw0bNrT777/fqlWr5j5ftmyZDRo0yDWlL126tHXq1MluuOGGiJcPAAAAAEDcBOihzzaP9XPOFcynpKTYmDFj7IgjjrDhw4e7IPzjjz+2vXv32k033WTNmze3Rx55xJYsWeL+aj4NVAcAAAAAQMIOEqca9I0bN6b52dq1a23gwIERL0vPU9egco899pjVrl3b1ZrfcccdtmnTJvvtt99sypQpVqhQIbdMfaagXMG7gnnEn5SUgC+XBQAAAAC+HCROzzr3mruH+/777+2tt96yAQMGRLQsPZbt6aefDr7/559/bMKECVahQgU76aST7Pnnn7dGjRpZwYL/l8zGjRvb6NGj3aPd9Ig3xI/k5CQb+cYcW7dpe7aWU7lcKevWoUnM0gUAAAAAvgnQr7nmGhd8SyAQsPbt26c7b61atbKUkAcffNDVmBcuXNhGjRplxYsXtw0bNlj16tVTzVeuXDn3d/369VkO0LUOu3fvztJ3kTM0dkGxYsVccP7Huq0xWaYe/6dtjYzzPJbI84yR57mPPAeA+MD5HPmd9jXtxzEJ0NUE/aOPPnILVQ26mpqrljtUcnKylSxZ0lq0aJGlBN94440u8H/99dddv/RJkya5PugK2EMVKVLE/dWAcll14MABN/gc/EMn3Jo1a8Z0matWrXInXqSNPM995HnuI88BID5wPkc8CI9tsxygq7n5nXfe6f5X1O89ci2W9BuiEdtVW//aa69Z0aJFbf/+/anm8wJz1bBnlfq1e78Hf4ikNClaVatWpVQ0A+R57iPPcx95DgDxgfM58rsVK1bkTB90L1CPBfU5//bbb+2iiy4K9jNXTbyCZw0Up1p6/Q3lvc9OAYEO8OwE+MgfYt0MCpkjz3MfeZ77yHMAiA+cz+HHQqaoA/RTTjkl04VH2nxcA73dfffdNm7cODvnnHOCzc+XLl3qHq2mPuZvvvmmHTp0yAoUKOA+nzt3rivtKlOmTLRJBwAAAADAt6IO0NU/PDxA//fff23RokX2559/2r333hvxsjQAnEaEVx93vTSqu0Zo37Fjh3ucmvqbK3h/4IEH7NZbb7UffvjBjfKuZ6EDAAAAAJDQAXr37t3T/ax37972008/uUHkIjVs2DD3qLVevXrZzp07rUGDBm6guEqVKrnPFaCrX3q7du2sbNmy7jf0PwAAAAAACR2gZ0SB81133WUPPfRQxN858sgj7eGHH3avtNSuXdsmT54cw1QCAAAAAOA/ybFcmJq4Hzx4MJaLBAAAAAAgIURdgz5ixIjDpqWkpNiGDRvsww8/tGbNmsUqbQAAAAAAJIyYBOhSokQJu+CCC6xv376xSBcAAAAAAAkl6gB9+fLlOZMSAAAAAAASWJb6oC9cuNBGjhwZfK/nlvfs2dON4A4AAAAAAHIhQJ89e7bdeOON9vXXXwen6bnof/zxh1177bW2YMGCLCQDAAAAAIDEFnWA/vzzz9sll1xikyZNCk6rUaOGvffee3bxxRe755oDAAAAAIAcDtBXrlxpbdu2dbXm4TSdPuoAAAAAAORCgH7kkUfaqlWr0vxszZo1Vrx48SwkAwAAAACAxBZ1gH7hhRfa8OHD7fPPP081/auvvnLT9TkAAAAAAMjhx6z16tXLfvzxR+vatasVKlTIjjrqKNu2bZsdPHjQ6tSpY/fcc0+0iwQAAAAAIOFFHaCXKFHC3nzzTTeaux63tn37dtfsvUGDBta0aVNLTs7Sk9sAAAAAAEhoUQfooiC8WbNm7rVv3z5Xk05gDgAAAABA1mUpqv7999/trrvuskaNGlm9evVs2bJl9sgjj9jEiRNjn0IAAAAAABJA1AG6gvErr7zSfv75Z2vdurUFAgE3vUCBAjZ48GCbNm1aTqQTAAAAAIC4FnUT9yeeeMJOO+00Gz9+vHs/adIk97d///6uufurr75q7dq1i31KAQAAAACIY1HXoC9ZssQ6depkBQsWtKSkpFSftWrVyv74449Ypg8AAAAAgIQQdYBepEgR27t3b5qf6XFrhQsXjkW6kMMCKSm+XBYAAAAAJKqom7g3adLEnnvuOatfv76VLVvWTVNN+r///uuavZ911lk5kU7EWFJysi0ZNdp2/bU+W8spUami1e3aOWbpAgAAAIBEFXWAft9991n79u2tZcuWdsopp7jgfMiQIbZq1So3YNywYcNyJqWIOQXnO1avzutkAAAAAACy0sS9YsWK9t5779mNN97oAvLjjjvOdu/e7UZ0nzp1qlWpUiVnUgoAAAAAQByLugZdjj76aOvVq1ean+3YscNKliyZ3XQBAAAAAJBQoq5Bv+WWW+zvv/9O87PPP//c1aQDAAAAAIAcDtCXLl1qbdq0sVmzZgWn7dq1y/r27Wtdu3a18uXLR7tIAAAAAAASXtQB+owZM+z000+37t27W79+/Vygfskll9jMmTPd+ylTpuRMSgEAAAAAiGNR90EvXbq0jRw50qZNm2YPPPCA+6vR3BWYU3sOAAAAAEAu1aDLvHnzbOzYsZacnGynnnqqLVu2zAXtO3fuzGIyAAAAgLQFUlJ8uSwAyPMadPU1f/fdd6169er29ttvu9rzyZMn25NPPmmfffaZDRgwwFq0aBHzhAIAACAxJSUn25JRo23XX+uztZwSlSpa3a6dY5YuAMjzAH369OnWpUsX69atmxUs+L+vt2/f3s4++2zX5L1nz56uRh0AAACIFQXnO1avzutkAIC/AnTVlqtZe7jKlSvbhAkTbNKkSbFKGwAAAIA8oK4Aarngt2UB8S7qAD2t4Nyzb98+q1+/fnbTBAAAACAP0a0A8HGArubrGhSuRo0awWkvv/yyXXbZZW5Ud8/y5cvtmmuuoYk7AAAAkM/RrQDIfRG1Ndm8ebMdOHAg+P7QoUNuULj167NXogYAAJDfMKI4AMA3Tdw9gUAgtikBAADIB2j6CwDwXYAOAACQqGj6CyDWGJgv9/kxzwnQAQAAACCP0Ton9/kxzwnQAQAAAMAHaJ2T+/yW59mqg09KSopdSgAAAAAASGAR16B369bNChcunGpaly5drFChQsH3+/fvj23qAAAAAABIEBEF6O3atcv5lAAAAAAAkMAiCtAff/zxnE8JAAAAAAAJjLH3AQAAAADwAQJ0AAAAAAB8gAAdAAAAAAAfIEAHckkgJcWXywIAAACQzx6zBiB7kpKTbcmo0bbrr/XZWk6JShWtbtfOMUtXPFNBhvLdb8sCAAAA0kKADuQiBec7Vq/O62QkDApFAAAAsi4lJWDJyUm+W1Y8I0AHENcoFAEAAMgaBdQj35hj6zZtz9ZyKpcrZd06NIlZuuIZAToAAAAAIE0Kzv9YtzWvk5Ew6FAJAAAAAIAPEKADAGKGpxUAAABkHU3cAQAxw8B8AAAAWUeADgCIKQbmAwAAyBqauAMAAAAA4AME6AAAAAAA+AABOgAAAAAAPkCADgAAAACADxCgAwAAAADgA3keoG/bts0GDBhg5557rtWvX986dOhgCxYsCH7+7bff2uWXX2516tSxli1b2owZM/I0vQAAAAAAxGWAfvfdd9vixYtt2LBh9s4771iNGjXslltusd9//91WrlxpnTt3tnPOOcemTp1qV111lfXu3dsF7QAAAAAAxJM8fQ766tWrbc6cOTZp0iQ7/fTT3bQHH3zQvvrqK5s+fbpt2bLFTj75ZOvVq5f7rFq1arZ06VIbN26cnXnmmXmZdAAAfCGQkmJJycm+WxYAAMhnAfrRRx9tY8aMsVq1agWnJSUludeOHTtcU/cLLrgg1XcaN25sgwYNskAg4OYDACCRKaBeMmq07fprfbaWU6JSRavbtXPM0gUAAPJZgF6yZEk777zzUk2bOXOmq1nv16+fTZs2zSpUqJDq83LlytmePXts69atVrp06Sz9roL73bt3W6JSwUaxYsViukxtE+VrPKUplvy4fn5MUyz5cf38mKZY8uP6+TFNseStn4LzHatXx936+VG871N+RJ7nPj/muR/TFEt+XD8/pimWcnv9Iq1gztMAPdyiRYusb9++1qJFC2vatKnt3bvXChcunGoe7/3+/fuz/DsHDhywZcuWWaLSjlizZs2YLnPVqlVuh4ynNMWSH9fPj2mKJT+unx/TFEt+XD8/pimW4n39/Ig8z33kee7zY577MU2x5Mf182OaYikv1i88tvV1gP7JJ5/Yvffe60Zyf+qpp9y0IkWKHBaIe++zU9pRqFAhO+mkkyxR5UTXgKpVq2a7hM5vaYolP66fH9MUS35cPz+mKZb8uH5+TFMsxfv6+RF5nvvI89znxzz3Y5piyY/r58c0xVJur9+KFSsiWoYvAvTXXnvN9SvXY9SeeOKJYMlCxYoVbdOmTanm1fvixYvbkUcema2NoWUgdmLdPCRe0xTv6+fHNMX7+vkxTfG+fn5MUyzF+/r5EXme+8jz3OfHPPdjmuJ9/fyYptxav0gLBPJ8qFaN4P7oo4/adddd5x61Flrt36BBA/vuu+9SzT937lxXy57MKLMAAAAAgDiSpzXoaqM/ePBgu/DCC93zzjdv3hz8rGjRonb99ddbu3btXJN3/Z09e7Z99NFH7jFrAAAAAADEkzwN0DViuwZsmzVrlnuFUkA+ZMgQe+GFF2zo0KH2yiuv2LHHHuv+5xnoAAAAAIB4k6cBepcuXdwrI+eee657AQAAAAAQz+jIDQAAAACADxCgAwAAAADgAwToAAAAAAD4AAE6AAAAAAA+QIAOAAAAAIAPEKADAAAAAOADBOgAAAAAAPgAAToAAAAAAD5AgA4AAAAAgA8QoAMAAAAA4AME6AAAAAAA+AABOgAAAAAAPkCADgAAAACADxCgAwAAAADgAwToAAAAAAD4AAE6AAAAAAA+QIAOAAAAAIAPEKADAADkcykpAV8uCwAQnYJRzp8wdHFKTk7y3bIAAADC6T5j5BtzbN2m7dlaTuVypaxbhyYxSxcAIDoE6OngQgcAAPIT3bP8sW5rXicDAJANBOgZ4EIHAAAAAMgt9EEHAAAAAMAHCNABAAAAAPABAnQAAAAAAHyAAB0AAAAAAB8gQAcAAACixLPnAeQERnEHAAAAosQjeQHkBAJ0AAAAIAt4JC+AWKOJOwAAAAAAPkCADgAAAACADxCgAwAAAADgAwToAAAAAAD4AAE6AACIKR4/BQBA1jCKOwAAiCkePwUAQNYQoAMAgJjj8VMAAESPJu4AAAAAAPgAAToAAAAAAD5AgA4AAAAAgA8QoAMAAAAA4AME6AAAAAAA+AABOgAAAAAAPkCADgAAAACADxCgAwAAAADgAwToAAAAAAD4AAE6AAAAAAA+QIAOAAAAAIAPEKADAAAAAOADBOgAAAAAAPgAAToAAAAAAD5AgA4AAAAAgA8QoAMAAAAA4AME6AAAAAAA+AABOgAAAAAAPkCADgAAAACADxCgAwAAAADgAwToAAAAAAD4AAE6AAAAAAA+4KsAffTo0Xb99denmrZs2TLr2LGj1a1b15o3b26vvvpqnqUPAAAAAIC4D9Bff/11e/bZZ1NN27p1q91000123HHH2TvvvGPdunWzp556yv0PAAAAAEA8KZjXCdi4caM99NBDNm/ePDvhhBNSfTZlyhQrVKiQDRw40AoWLGjVqlWz1atX25gxY+yKK67IszQDAAAAABB3Neg///yzC8Lff/99q1OnTqrPFixYYI0aNXLBuadx48b2xx9/2ObNm/MgtQAAAAAAxGkNuvqV65WWDRs2WPXq1VNNK1eunPu7fv16O+aYY3IljQAAAAAAxH2AnpG9e/da4cKFU00rUqSI+7tv374sLzcQCNju3bvT/TwpKcmKFStmsbRnzx73u37gx/XzY5piyY/r58c0xZIf18+PaYolP66fH9MUS35cPz+mKZb8uH5+TFMs+XH9/JimWPLj+vkxTbHkx/XzY5piKbfXT9P1m/k6QC9atKjt378/1TQvMC9evHiWl3vgwAE3Onx6tKFq1qxpsbRq1Sq3wfzAj+vnxzTFkh/Xz49piiU/rp8f0xRLflw/P6Yplvy4fn5MUyz5cf38mKZY8uP6+TFNseTH9fNjmmLJj+vnxzTFUl6sX3jlc74L0CtUqGCbNm1KNc17X758+SwvV33eTzrppHQ/j6RkI1pVq1b1VWmR39bPj2mKJT+unx/TFEt+XD8/pimW/Lh+fkxTLPlx/fyYpljy4/r5MU2x5Mf182OaYsmP6+fHNMWSH9fPj2mKpdxevxUrVkS0DF8H6A0bNrQ333zTDh06ZAUKFHDT5s6d61a8TJky2doY2amBz4pYN5/wGz+unx/TFO/r58c0xfv6+TFN8b5+fkxTvK+fH9MU7+vnxzTF+/r5MU3xvn5+TFO8r58f05Rb6xdpgUCej+KeET1KbdeuXfbAAw+4EoepU6fahAkTrHPnznmdNAAAAAAAYsrXAbpqyceNG+fa8rdr185GjBhhvXv3dv8DAAAAABBPfNXEfciQIYdNq127tk2ePDlP0gMAAAAAQG7xdQ06AAAAAACJggAdAAAAAAAfIEAHAAAAAMAHCNABAAAAAPABAnQAAAAAAHyAAB0AAAAAAB8gQAcAAAAAwAcI0AEAAAAA8AECdAAAAAAAfIAAHQAAAAAAHyBABwAAAADABwjQAQAAAADwAQJ0AAAAAAB8gAAdAAAAAAAfIEAHAAAAAMAHCNABAAAAAPABAnQAAAAAAHyAAB0AAAAAAB8gQAcAAAAAwAcI0AEAAAAA8AECdAAAAAAAfIAAHQAAAAAAHyBABwAAAADABwjQAQAAAADwAQJ0AAAAAAB8gAAdAAAAAAAfIEAHAAAAAMAHCNABAAAAAPABAnQAAAAAAHyAAB0AAAAAAB8gQAcAAAAAwAcI0AEAAAAA8AECdAAAAAAAfIAAHQAAAAAAHyBABwAAAADABwjQAQAAAADwAQJ0AAAAAAB8gAAdAAAAAAAfIEAHAACAU+rIohZISYnJsmK1HABIJAXzOgGJcqFLSs5+WUislgMg/+PckvvIcySCI4oWdvvmqg/G2p4t67O8nGJlKlrV1rfFNG0AkAgI0HMYF7rcx0107iPPcx/nltxHniORaB/fs/HPvE4GACQcAvRcwoUu93ATnfvI87zDuSX3kee5h8I/AECiIUBH3OImOveR5wBiicI/AECiIUAHAAC+RuEfACBR0NYLAAAAQMLgaQXwM2rQAQAAACQMus/AzwjQAQAAgDzCYIh5h+4zuYf9PHIE6AAAAEAeoTYXiYD9PHIE6AAAAEAeozYXiYD9PHPx2zYAAAAAAIB8hAAdAAAAAAAfIEAHAAAAAMAHCNABAAAAAPABAnQAAAAAAHyAAB0AAAAAAB8gQAcAAAAAwAcI0AEAQFwreERJS0lJyetkAACQqYKZzwIAAJB/FSxS3JKTk2307Fftr+0bs7Ws2pVr2BWnt45Z2gDk/8I/nV+AhArQteOPGDHC3nrrLdu5c6c1bNjQBgwYYFWqVMnrpAGIIS50uY88RyJRcL56y9psLaNiqXIxSw8QS5zPcx+Ff0jYAP2FF16wSZMm2ZAhQ6xChQo2dOhQu/XWW2369OlWuHDhvE4e4hQXutzHhS73kecAcgLX0NzH+TzvUPiHhArQ9+/fb+PHj7d7773XmjZt6qY988wzds4559jHH39srVsnxsmDC13u40KXd7jQ5T7yHEAscQ3NO5zPEc8KJkBM5PsAffny5fbvv//amWeeGZxWsmRJq1mzps2fPz9xAnQudHmGCx2AWEqEmwvAwzUUQCwVTICYKCkQCATMx1RL3r17d/v++++taNGiwek9e/a0vXv32ujRo6Na3qJFi0yrXKhQoQznS0pKsh279tqhbI76WrhQQTuiWGE7uHunBVIOZXk5yQULWYGiR9jOvbvsYDaW49JUsJAdUbi47d+x01IOHczWspILFLTCJY90eZpd5HmE6SLPI0sTeR4R8jzv8nz3/j12KJt5XqhAIStaqAh5ngn288iR55EjzyNMF3keWZrI87jP8wMHDrj8rF+/fv6uQd+zZ4/7G97XvEiRIrZ9+/aol6dMCf2bkZIl/q9AILsKFj8yJss5smgJixXtRLESSX5GgjyPHHkeGfI8MuR57ud58cLFLFbI88iwn0eOPI8MeR458jwy5Hn85rk+i2Sb+D5A92rN1Rc9tAZ93759VqxY9Dc39erVi2n6AAAAAACIBd93gKtYsaL7u2nTplTT9b58+fJ5lCoAAAAAABIsQD/llFOsRIkSNm/evOC0HTt22NKlS93z0AEAAAAAiAe+b+KuvucdO3a0p556ykqXLm2VK1d2z0HX89BbtGiR18kDAAAAACAxAnTp0aOHHTx40Pr37+9GblfN+UsvvZTpSOwAAAAAAOQXvn/MGgAAAAAAicD3fdABAAAAAEgEBOgAAAAAAPgAAToAAAAAAD5AgA4AAAAAgA8QoAMAAAAA4AME6AAAAAAA+AABOgAAAAAAPkCAnsOuv/5669OnT8yWN2/ePDv55JNt7dq1MVsmEA3tf1OnTs3rZCAX6Rymc1k8eP7556158+aWH0R7vuf6EFtbt261t956yxJdLM75ocvIT8dgPFH+aztkRNtF2we5J96Oh5xYn6kR7LvhRo0aZY0aNbJ69erZjz/+mO37HF1XlQZdZ3MivgtXMMeWDAAAkE89+eST7qbsqquuyuukAAAitHPnThs+fLh16dLFnb/LlStn2VWxYkX7+uuvrVSpUsGCiAIFClhOIUAHAAAIEwgE8joJAIAo7dixw52/GzdubJUrV7ZYUDBetmzZ4PujjjrKchJN3CMwc+ZM16xBfz333HOPnXPOOXbqqafaiBEjUs3/5ptv2tlnn20HDx48bFkrV650JTpnnHGGnX766dajRw9bt25d8HM1mRg0aJDdfffdVqdOHTv33HNtzJgxh90ozJ4921q3bm2nnXaaXXLJJfbFF18EPzt06JBNmDDBLrroIqtVq5b7+8YbbwQ/V/OMmjVrplpGy5Yt7ZNPPgnOo98bO3asnX/++S4dl112mb3//vuWH/z666/WuXNna9iwoVs3rcP48ePdZykpKTZ69GiXJ/qsfv36duutt9qff/4Z0fdjtYz87vfff7drrrnGrdvFF19s//3vf6PKHx1Pb7/9tnXq1Mlq167tjpfQ4yi3lpEI56FvvvnGfS+t13fffefmXbBggd1www0uj7xt+t5776Vans5njz76qJtH56+BAwfavn37gp9v3rzZevfuHTy3af9fvXq15YVIjr+RI0e6tGp97r33Xtu2bVvwM+XNc889Z82aNXN5+Mcff9hff/1lvXr1sjPPPNPlt87NQ4cOdfuZ54cffnD7o5rUnXXWWfbQQw/Znj173Gfbt2+3/v37B7eXlqP33ufedlBpv/bnSy+91JYvX54qzZEsQz777DO74IIL3Plf15TQ5ej9gw8+6H6nQYMG7ry+f/9+e+KJJ1yzROWXmgX27NnT/vnnH8tLGzdutG7durn8PO+881xzc6Vx4sSJdsopp6RKX9u2bd31LDSvdJ1Tnsrnn39ul19+ucvbCy+80J599lm33ultcx1b06ZNc8eIPtP1Ub8Zer2W9u3bu7yLd6tWrXL7tvYp7X86t4bKLH8zomPvkUcecdtY39e1xWtGmkiUf4899ljwvfY57XsfffRRcNqQIUPcdsgsz1S717FjR3fO0jlO5+60ahnvv/9+dx5QIPPyyy9bItC9r/Ja97Y6h6qZss4X3j36bbfd5s453nng77//jvgc7N1f675d1xf9jq4RkVwf9R1dV7Q9dZ7WdcevsnuN/ffff90+qTxWXmtf/emnn4Kfz5o1y9q0aePON9dee627/obSuUXXX20Hff/qq692tdveNvCa2N94443BZuu69/O2rb6n/V3nqtDuOwcOHHDncx0PdevWtTvuuMNtu7xo4q5ADBG47777Ak2aNAls27YtMH369ECNGjUC8+fPDwwePDhw4YUXppq3ffv2gSeeeML937Fjx8D999/v/l+7dm3g9NNPD3Tv3j2wbNmywJIlSwLXXHNNoGnTpoGdO3cG5z/11FMDAwYMCKxYsSIwderUQO3atQOjR492n8+dOzdQvXr1QIsWLdz/v//+e+COO+4I1KlTJ7Br1y43z2OPPRZo2LBh4P333w+sWrUq8Morr7hlvvzyy6mWcckllwS++eYbN4/SVL9+/eAynn766UCzZs0Cn3/+eWD16tWBt99+O1CvXr3Aa6+9FvCz3bt3u+3Uu3dvl39atyeffNKt79KlS10eKG8+++wztz20/ueff36ga9euEX1fYrGM/EzrcdpppwXeeOMNt/8988wzgZNPPjnw448/RpQ/3jIaNGgQePfddwN//vlnYNSoUW7ad999l6vLSITz0L59+wKbNm0KvpRXF110UaBTp06BAwcOBDZs2ODOMdpH//jjj8Bvv/3m9l2dM/7++2+3LJ3DlLc9e/YM/Prrry5PzzrrrMCjjz7qPtdy2rRpE2jXrl1gwYIFbr+/9dZbAxdccEHg4MGDuZpHmR1/zz33nPtf59qff/45MG/ePHc+7dKlS3AZ+vyMM84I/PDDD4HFixe7aZdeemnglltucedu5aH2L803a9Ys97mm1a1b122jX375xeWD9jfv/K/lK3903l+zZk3gvffeS3Ve1vdr1aoVePDBB126P/roo0CjRo3cb2j+SJbhndvPO++8wJdffunS0blzZ5cfyhfReut41fVBn//zzz9uOzZv3tzlhY6VTz/91P22riV5Zf/+/YFWrVoFrr76andu0X6u91rf119/3e2zM2bMcPNu2bIlcMopp7h137x5s5v2wQcfBBo3bhw4dOhQYPbs2W5+nbN0Pfvqq6/cNu/Ro0e623zHjh1uf9dxpONG+/iZZ54ZGDlyZPA7Ov/pezpm4pnWUfv2tGnT3H6qPNA0nVMl0vx955133P86BnV/ITo/aJ9u3bq12/+UlzoGtJ2///77QCJRvrRs2TL4/pFHHnHH6sMPPxycpnP3hAkTMs0z7zynY1jbTOdB5b+meW6++Wb3ezq2dG684YYb3Of6brzSuUL3L7qX1blO52md+/r16+euhTrv6Xyoc7DOO7fffrvbV//999+ozsHXXnuty3Pla2bXR29b6Vyt64u2obazluFHsbjGeuuv65TuO/r06ePu13Rvs3DhQrffP//88+4cO2XKFHdtDN1377777sBll13m8lu/P378eLcdFLPonkd5qPlnzpwZ2Lp1q0uztqP2eeWx9nkdP/od77zk3edoX1i5cqVbts75uqaLtrc+1/Tw+C4nEKBHSAG0Auk777zTBQXacUQ3ONpgixYtSvOCHboBtQOfc845bufx6MKvHc8LfDW/dpqUlJTgPEOHDnUHg6Z5B/8XX3wR/FwHgKZph1Q6tZNOnDgxVfoHDRrkdrTQZXg3lqId1lsPnYiUptDPZfjw4cGLqp9PvirM8AoaZO/evW7ddHOhG08FF6GUv7qRjuT7Eotl5GdaDwWEoXQTe88990SUP94ywm/+dVy9+OKLubqMRDkPeXT8d+vWzd2Ubd++3U3TDfXYsWNTnXN00dX3dRETncN0DtJ+7Jk8ebI71+jCp4us5tfvenSzM2TIEHc85KbMjj/dPOj85hU+yNdff+0+141CWvv4nj17Ai+99FLgr7/+SvVbKqQYMWKE+/+pp55y20Y3Y55vv/028MILL7j/dU5evnx5qu9fddVVgb59+wa/r/NraIGGVwjgBeiZLcM7t3/yySfBz7WdFVzpJse7xrRt2zbVMlTI5W1rz1133eVu2POKrnFaF918eRQ8e4Gebma99VZh1eWXX+6ur17Qfu+997qbPunQocNh5wptm9C8Teu8pv1e+eXR/qwbTc+wYcMCV1xxRSDeKW90/xJKlQ1jxoyJKn/TCtC97axzmEfnIu2joQF+Ivjpp59cXnjnGe1rqoC5+OKLg+dqfa6Km8zyzAuSVNDkCQ3QFYCEFrKIzokKXuM5QFcAqfUOvTdQobPugVXZoILYULq+qfDJ23ezcg7O7Pqo/Na11Kuo8879+l0/yu411tv3VJAX+n2df3W+79WrlzunhNL5xdt3tYy0KrxUYOCdr8ODaVUyqiJTwXp43BMaoOs+R4W6HhXWeMdfbgfo9EGPUIkSJezxxx93zSXUrKVr165uevXq1V0TjHfffdc1m9BfNU856aST0mwSoqYghQsXDk5Tf4aqVau6zzxqEpKUlBR8r+WqublGlPXoO56SJUu6v3v37nVNj9VEQ01oQqnJ4iuvvGJbtmwJTjvxxBNTrZ/ouytWrHBNV9W0Jzk5OVUTVzUr0e8ULVrU/Kh06dKuOcwHH3xgS5cudU1avOadamakZi/ff/+9GzxCTfb00vqWL18+ou9LLJaR34XvX2oqNnfu3Ijyx1OtWrVU74888ki3/+X2MhLpPKQmYfPnz3dNhb3zxnHHHeea4b366qvuPBS6v6q7jEfnriJFigTfa/nKazXD0/c0cEroeUn5rOaTuS2S4+/444+3Y445JtX+K7/99pv7zJvHo/OdmuCpqamasatp4i+//OKavnnLVB5omxQs+H+XVTWT00uUJjU9V7Np5Zn2RTWZ887D+r6aRoYOOqOmgaEyW0Zax6e28wknnJDqGhO6bqIuTOoK8dRTT7nl6jqi40VNX/OKtoX2KaXdo328ePHiweP7hRdecP/PmTPHNTVV83Odh9Rl66uvvgo2F9Z+oO2mLjEer9uYmrQee+yxaeZLuCuuuMI149R5Rfu/ugeoyWQiCN0O3n7ldXGJNH/Tov1S522dwzy6/9G+5zVZTRQ6f+i8qf1ZXWR0bOucre4oamatrow1atRw551I8qxMmTJuvrR45wMdUx6dE6tUqWLxTPmnrjDqaqr77yZNmljTpk1dU2ftxzrv6BoaSvu59uNozsGhx0sk10dtK+8+3Du+dK/tR9m9xnrdf9WE3KN7i759+wbzq0mTJql+U9tE9yii3xSlIZTuR7z7mnD6jvI/tN+4uiyFHx+6HwqNe7Td8mo7EKBHQf0jdPOlGxf1h/BOZLpoP/PMM/bAAw/Y9OnTXT/XaAac0Q5dqFCh4PvQGzzvcwm9cQvdgUKXn9FvhC87tKAgrWWoD1n4SSe97/mFLmLqE6gTiG7g1L9FFyD10/L6+KhfTLt27dwNnfpyffrppzZjxoyIvh+rZeR34fufAjlvv8gsfzLb/3J7GYlyHlJQrgucAgxdhDy6wdCFTjeHuils0aKFHX300YeNXB0+Wql3TtE2CD9n5aVIjr/wdfEKIkLPw6GFkLt373YBui7UCv60TylAu+6664LzZJQHyiv119PNiW4OW7Vq5fJbfcFDb7DDC/BClxnJMjJav9BjJbyAdcCAAW5sA/XjVp6p3/dLL73k+oDnpbQKNL310E210q0b52+//daN3aIAXelWAK0+od5Nnpaj40HbLVzooD+ZFTyrwEs3mgrMtS8oUArt9x7P0hqt2DvXRpq/aUnvnkXT/XReyS0aA0EBuui8pfOMgjn1e1XfafX1jTTPMtqfvUqgjM458erpp59257gvv/zSFUzed999rlBT538VqGrskHAK5KI5B4cWZkeSpzk5Grhfr7HpSetaWCjke97+//rrr9sRRxyRar60YiMvPZFUkPlpO8T/kRgjKh1STZwG5VDtlAZ70M6hnUEHqgbu0IADGV2wNbiANyCPd5Oh+VUbE1oSFP68vkWLFrkSaG9o/4yoRlE78sKFC11JoUcD5ehCGckyFJTrhKKbf10sPLq51828BofyK5XoaSAK3Wx6B7RquryD+sUXX3Qn5ttvvz34Hd3QeQd8Zt+XWCwjv/v555/dIFSh+6hKIyPJn0j4ZRnxch7STYi+8/DDD7vWNOGDyan0PnSAINUQSGheLVu2zF3gvAugzjG6AVQBgQIXDZ6jc5lXC6kBvDTYnAaTCi0pz2mRHH+q+di1a1ewxkLropuCtFo+iWqltM/rxtmrFdBvqEWSt0x9VwUjuhHxLvIa6EYtHlQzrZvBKVOmBGsSVNqvmgevgEXHjwarCb0+hA6ao/zPbBkefU+FUt520PrefPPNaa6bWmZNnjzZFe7ohtOjWnSvtjov6MZXg1jpZvg///mPm7ZmzZrgQEN6bI5adWgAVG0H3WCr4Ek3y1ofFTYVK1bMzavvq0ArtIZcAY+uaTom0lvP0JZsHhWEqeZex4LOgenV2CSSrOavd1+k7axaM69GWMeUjsn0jsd4poBHNas6z3rHsP7qnKw89QYty26eefeHunarsMsb+Tq/DqIaKRXeqZC+X79+7l5XBfe6L1eQrpZkulbqcVreOVjnG22Pm266yQXpkZ6DQ2V2fcxvsnuN9QaPVKzj7eOqVVflgO5pdC1cvHhxqt8MvRZ61wMdB2p15tE1TMeNBjgNp2VquyndXi26Cnd1HPkVo7hHQDuTdhrd2F555ZWu2ZyaS6jZueigVfMYXbRVupneBbtDhw5u5EKdCHSjrSZh2pFUW6WR2EODaY0mqx1cTcZ0A55erXw4HQwq2dL3dRDphKDvT5o0yd2gpXXDEU7roxFBFQhoJGfdFCkdamoVi2cJ5qQKFSq4mhM1RVUBg26sNSK+tx114tVNtgoadAOqA/rjjz8OnjAy+77EYhn5nZ4SoCZeWv/Bgwe7GwWvqWdm+RMJvywjHs5DugjpaRE6/+jmTxc176XzkfbXDRs2uNoZ1UAqj3RT7f2mZ/369e6mRgGTLswaJVjnJd3I6CKrYEk3MjqvaR79rxJ2BVq5KZLjT00W77rrLpd/2kc0mqxqj9N7HIuWKbqRUx7pHK3RXXVz5i1ThawKdlX7ojxXVwI9R9t7zIsKPfW0A51PdWOi39c28L6v7aN0K4/1fY2KrTz2qGAgs2V4VLOsWmUF9RrFWcdCaPAdfs3QvqPWJV7TfQW5KpDIy2NF+aZmjbpe6mZN6dH/obQ/KxhXAZBXWKTCbF23dAx4dG7SPqsnHSiQVN6oOaVuzjKq4VVguWnTJpffHl2rdbOtwpS0aowTUVbzV1T7pmBRgadGzNe+r0oAXVPUlSfR6Fyq85POw6EBuo575aUCkljkmQqz1BpI31NQqu/q+pJfr4+R0vlO98O6n9X5Tuv94Ycfuibp6jKmfVYjjuseXS+dP3WuVUFINOfgUH66PsZCdq+xamquYFyVBuqSpHOGrjn6ju5vFKssX77cjaauz3Tdfe2111IF6Ko81LVWBVfaFroPUmFHaOvAUKqwUKzlbdslS5YEryeRxEV5gQA9ArqxVx8Trz+bDmTd8OrmSTdAopI3NXnT3/ToxkE7mUopFUTfcsst7oSrGoDQoF43Fjrh6jE7qgXUhU43b5HS/HpkkmptdDOh5euGLb0alIyWoSDdK+XTOqtG0s90wVG+qiZR6VbwqGBGj4LQyVQ3zNpOqgVRk1WdnHWSUA2MTjSZfV9isYz8TsGJHnWkfVQ3CGpO7vWvyix/IuGXZcTDeUg3H7rpUG2WbhR0c+e91Nxdx7n2U92c6SI2atQod7HVhTR0f9V5STXDepyJ8lHnJO0HolJrFQzowq2aBn2mJn7jxo2LqElbLEVy/OlmSTe4WnfdROjRNmk1a/SomanOicpDLVP/a3nKL2+Zaoaq/FRhkG5EdGOnmwide/WZ0qObCQXKKpjVNNXeeDUDeq9xQlRYosBP83tjDHifZ7YMj7aL0qjrjApQtB3S65qk7aPzvI4PPdZGhS66+dI+oMKt8Ee45RbdNOn6p5sxXbsUBGrbhgfouiH0+vmLas4ltPWXvqfjR4+t0jrqxiz8sYxp0XbU+ms7e839dYOvmnO1RgvvJ5mospq/onOKjhsFnnfeeac7XyuAUSFwbra88Qsdp9qHdU711l/nbW8MnVjmmQIgNUvWuUrddVS7qXNjPFMrU10zFRjq+Na1SvmpAE/Bne7RVXCt6bpv0PlR530F09Gcg0P56frol2usvqP5lYe6X1EFgFo4Kp/1vbFjx7oWI7rH1H6tMQNC6XyjIF/XV20LtShUN6f0Ck2966AK1XUP0717d3fciF+3QZJGisvrRMQDlabroFctRHp9ICKh5+rpxlg7PgDkxXkI8Cs1iVa3gYwKw3OartMawE+BDQDA39auXetaJavg0KNCVxUcqJVxVgZEVUGLCrXUOiAn0Ac9m9TsTjUmalKu0jZuigHkNs5DQM5TDbFaq6h5pFroAAD8b9++fW48InULUc27WhVqIGy1RPTGE4iUvus9GSg04I817uKySRfq/v37uw2ciP2lAOQ9zkNAzlMTSTWBVY2J+vUDAPJH14Zhw4a5gVzVZUldDTTGiAbHjbaJu8bYUCsqDfinpv05hSbuAAAAAAD4ADXoAAAAAAD4AAE6AAAAAAA+QIAOAAAAAIAPEKADAAAAAOADPGYNAIA4t3DhQps4caItXrzYtm7damXLlrWzzjrLOnXq5Ea4BQAA/kANOgAAcWz06NF23XXX2a5du6x3797ucWFdunSxn3/+2dq1a2czZszI6yQCAID/j8esAQAQp2bPnm2333673XHHHdazZ89Unx04cMDuuece+/zzz23q1Kn2n//8J8/SCQAA/ocadAAA4tSoUaPsxBNPtB49ehz2WaFChWzgwIFWoEABGzt2rJt28skn2/PPP59qPr3X9FALFiywjh07Wp06daxRo0Z2//332z///BP8XAF/zZo17a233rImTZq4eV5//XW3nFWrVqVa1nvvvWc1atSw9evXx3jtAQDIfwjQAQCIQ+prrj7n559/viUlJaU5z1FHHeX6on/66acRL3f+/Pmu73rRokXt2WeftX79+tl3331nN9xwg+3duzc436FDh2z8+PE2aNAg69u3r7Vu3dqKFCniAvJQ7777rp155plWsWLFbKwtAADxgQAdAIA49Ndff7m/lStXznC+448/3vVP37ZtW0TLffrpp61q1aqub3uzZs2sbdu2LhD//fff7Z133kk1r/q6N23a1PV1L1WqlF144YX2/vvvm9e7bsOGDTZ37ly7/PLLs7yeAADEEwJ0AAASmFe7npKSkum8e/bsse+//97OO+88F2QfPHjQvapUqeJGg58zZ06q+dV0PdSVV15p69atc03kvdrzI444wgXuAACAx6wBABCXvCbja9euzXA+fV68eHHX3D0zO3bscIG8+qx7/dZDqQl7KC03VOPGje3YY491gXnDhg3d31atWh32PQAAEhUBOgAAcah06dJWr149++STT9xo7cnJ/2s0t337dhdoq9Z7586d9s0339jZZ58d/Fx9x0Pt3r07+L9qu1Xjrj7ol1xyyWG/WaxYsQzTpO+qubueyd6hQwc3YNwTTzwRozUGACD/o4k7AABx6s4777TVq1fb8OHDg9O+/vpra9GihfXp08cGDBjgmq2rr7iUKFHCNm7cmGoZixYtCv6vzzU6u/qb16pVK/jSI9o02vu8efMyTZP6m6uAQIG5msVrJHgAAPA/1KADABCnVDOuR6A9+eSTtnTpUld7Xb58eTfi+oQJE4IB86mnnur+14BuM2bMcEGzBo/T49IU4Ie6++673bPVVSt/6aWXBkdrV990PW89M5UqVXIjx6ug4N57782hNQcAIH9KCnhDqQIAgLikx6298sorrjZcj1875phj3LPJ1cx93LhxLiDX49D06LRHH33UvvzySytYsKDrH37aaadZ//797Zdffgku79tvv7URI0bYTz/95J6nrgC/e/fu1qBBA/e5Ans9Wk2Pb1Of83Bq4v7444/bF198YeXKlcvVvAAAwM8I0AEASPDHsSlgVnN49THPDbfeeqsbGG7kyJG58nsAAOQXBOgAACBXKCDXwHAffPCBTZo0yerXr5/XSQIAwFfogw4AAHLFZ599Zn/++af17t2b4BwAgDRQgw4AAAAAgA/wmDUAAAAAAHyAAB0AAAAAAB8gQAcAAAAAwAcI0AEAAAAA8AECdAAAAAAAfIAAHQAAAAAAHyBABwAAAADABwjQAQAAAADwAQJ0AAAAAAAs7/0/nPb+TOgC2tYAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Set the aesthetic style of the plots\n", + "sns.set_theme(context=\"notebook\", style=\"whitegrid\")\n", + "\n", + "# Create a bar plot\n", + "plt.figure(figsize=(12, 6))\n", + "sns.barplot(x=\"Query\", y=\"Execution Time (s)\",\n", + " hue=\"Method\", data=performance_df)\n", + "\n", + "# Add titles and labels\n", + "plt.title(\"Comparison of Execution Times for Different Search Algorithms\")\n", + "plt.xlabel(\"Query\")\n", + "plt.ylabel(\"Execution Time (s)\")\n", + "\n", + "# Display the plot\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}