Created
May 20, 2023 07:53
-
-
Save R3M4G/e2dd0d07ba02930f4f131ecf6b62d7a5 to your computer and use it in GitHub Desktop.
dl_codes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"assignment 6 \n" | |
], | |
"metadata": { | |
"id": "ZzpNS8WkGIGQ" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import numpy as np\n", | |
"import matplotlib.pyplot as plt\n", | |
"import tensorflow as tf\n", | |
"from tensorflow import keras\n", | |
"\n" | |
], | |
"metadata": { | |
"id": "rxokHvL2JsYt" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Load the Boston housing dataset from Keras\n", | |
"boston = keras.datasets.boston_housing\n", | |
"(X_train, y_train), (X_test, y_test) = boston.load_data(test_split=0.2, seed=42)\n", | |
"\n", | |
"# Normalize the features\n", | |
"mean = X_train.mean(axis=0)\n", | |
"std = X_train.std(axis=0)\n", | |
"X_train = (X_train - mean) / std\n", | |
"X_test = (X_test - mean) / std\n", | |
"\n" | |
], | |
"metadata": { | |
"id": "NRBm6EkeMA_4" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Define a function to train and evaluate the models with varying training sizes\n", | |
"def evaluate_models(train_sizes):\n", | |
" mae_scores_dnn = []\n", | |
" mse_scores_dnn = []\n", | |
" medae_scores_dnn = []\n", | |
" mae_scores_lr = []\n", | |
" mse_scores_lr = []\n", | |
" medae_scores_lr = []\n", | |
"\n", | |
" for size in train_sizes:\n", | |
" # Select a subset of the training data\n", | |
" idx = np.random.choice(X_train.shape[0], int(X_train.shape[0] * size), replace=False)\n", | |
" X_train_subset, y_train_subset = X_train[idx], y_train[idx]\n", | |
"\n", | |
" # Deep neural network model\n", | |
" model = keras.Sequential([\n", | |
" keras.layers.Dense(64, activation='relu', input_shape=(X_train_subset.shape[1],)),\n", | |
" keras.layers.Dense(1)\n", | |
" ])\n", | |
" model.compile(optimizer='adam', loss='mse')\n", | |
" model.fit(X_train_subset, y_train_subset, epochs=100, verbose=0)\n", | |
" y_pred_dnn = model.predict(X_test)\n", | |
"\n", | |
" # Linear regression model\n", | |
" lr_model = np.linalg.lstsq(X_train_subset, y_train_subset, rcond=None)[0]\n", | |
" y_pred_lr = np.dot(X_test, lr_model)\n", | |
"\n", | |
" # Compute evaluation metrics\n", | |
" mae_scores_dnn.append(np.mean(np.abs(y_test - y_pred_dnn)))\n", | |
" mse_scores_dnn.append(np.mean(np.square(y_test - y_pred_dnn)))\n", | |
" medae_scores_dnn.append(np.median(np.abs(y_test - y_pred_dnn)))\n", | |
" mae_scores_lr.append(np.mean(np.abs(y_test - y_pred_lr)))\n", | |
" mse_scores_lr.append(np.mean(np.square(y_test - y_pred_lr)))\n", | |
" medae_scores_lr.append(np.median(np.abs(y_test - y_pred_lr)))\n", | |
"\n", | |
" return mae_scores_dnn, mse_scores_dnn, medae_scores_dnn, mae_scores_lr, mse_scores_lr, medae_scores_lr\n", | |
"\n" | |
], | |
"metadata": { | |
"id": "xEUiC0KHMFlE" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# Specify the training sizes\n", | |
"train_sizes = np.linspace(0.1, 1.0, 10)\n", | |
"\n", | |
"# Evaluate models and get evaluation scores\n", | |
"mae_scores_dnn, mse_scores_dnn, medae_scores_dnn, mae_scores_lr, mse_scores_lr, medae_scores_lr = evaluate_models(train_sizes)\n", | |
"\n" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "bcfNOKCqMKdb", | |
"outputId": "ba34bd4a-f9bc-456d-8993-c7a5a948deb0" | |
}, | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"4/4 [==============================] - 0s 4ms/step\n", | |
"4/4 [==============================] - 0s 4ms/step\n", | |
"4/4 [==============================] - 0s 5ms/step\n", | |
"4/4 [==============================] - 0s 4ms/step\n", | |
"4/4 [==============================] - 1s 4ms/step\n", | |
"4/4 [==============================] - 0s 4ms/step\n", | |
"4/4 [==============================] - 0s 4ms/step\n", | |
"4/4 [==============================] - 0s 3ms/step\n", | |
"4/4 [==============================] - 0s 4ms/step\n", | |
"4/4 [==============================] - 0s 7ms/step\n" | |
] | |
} | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"plt.plot(train_sizes, mae_scores_dnn, label='DNN MAE')\n", | |
"plt.plot(train_sizes, mse_scores_dnn, label='DNN MSE')\n", | |
"plt.plot(train_sizes, medae_scores_dnn, label='DNN MedAE')\n", | |
"plt.plot(train_sizes, mae_scores_lr, label='LR MAE')\n", | |
"plt.plot(train_sizes, mse_scores_lr, label='LR MSE')\n", | |
"plt.plot(train_sizes, medae_scores_lr, label='LR MedAE')\n", | |
"\n", | |
"plt.xlabel('Training Size')\n", | |
"plt.ylabel('Performance')\n", | |
"plt.title('Performance vs Training Size')\n", | |
"plt.legend(loc='best')\n", | |
"plt.show()" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 472 | |
}, | |
"id": "GMiW1rdtRogf", | |
"outputId": "d4a87be7-3a20-49b9-92fa-165dd4cd1902" | |
}, | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/plain": [ | |
"<Figure size 640x480 with 1 Axes>" | |
], | |
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkQAAAHHCAYAAABeLEexAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB8RElEQVR4nO3dd3wT9f8H8Nclabo3nVBoKatlQwUKoiJIkSEgyrAsiyAKCjIEFFmi4ARB+OLowJ8gKIKCMmXKVqCslj2lCyjdM8n9/kgbek1b2pI2afN6Ph5H7z73uc+90wvNO5/73J0giqIIIiIiIjMmM3YARERERMbGhIiIiIjMHhMiIiIiMntMiIiIiMjsMSEiIiIis8eEiIiIiMweEyIiIiIye0yIiIiIyOwxISIiIiKzx4SIyIR99tlnaNiwIeRyOdq0aWPscMjIBEHAvHnzKrWtr68vRo8ebdB4DG3evHkQBMHYYZCZYkJEVAFRUVEQBEE3WVlZoUmTJpg4cSISExMNuq+dO3fi3XffRZcuXRAZGYmPP/7YoO2TYRR/T5Q2+fr6GjtUo8nIyMDcuXPRokUL2NrawtXVFW3atMGkSZMQFxdn7PCIAAACn2VGVH5RUVF49dVXsWDBAvj5+SEnJwcHDx7E//3f/6FBgwY4d+4cbGxsDLKvmTNn4rPPPkN2djaUSqVB2iTDu3btGg4fPiwpe+2119ChQweMGzdOV2ZnZ4cBAwY81r5ycnKgUCigUCgqvG1ubi5kMhksLCweK4aKys/PR8eOHXHhwgWMGjUKbdq0QUZGBs6fP48tW7bgl19+wTPPPAMAUKlUUKlUsLKyqtYYiQCg4v+riAjPP/88goKCAGg//FxdXfHll1/i999/x7Bhwx6r7aysLNjY2CApKQnW1tYGS4ZEUUROTg6sra0N0h5pNWzYEA0bNpSUjR8/Hg0bNsTw4cNL3U6lUkGj0VTo+D5OomBpaVnpbR/Hb7/9hlOnTmHNmjV45ZVXJOtycnKQl5enW65sskdkCDxlRmQAzz77LADg+vXrurIff/wR7du3h7W1NVxcXDB06FDcvn1bst0zzzyDFi1a4MSJE3jqqadgY2OD9957D4IgIDIyEpmZmbpTLlFRUQC0H6Qffvgh/P39YWlpCV9fX7z33nvIzc2VtO3r64u+fftix44dCAoKgrW1Nb755hvs27cPgiDg559/xvz581G3bl3Y29vjpZdeQmpqKnJzczF58mS4u7vDzs4Or776ql7bkZGRePbZZ+Hu7g5LS0sEBgbif//7n97vpTCGgwcPokOHDrCyskLDhg3xww8/6NVNSUnBO++8A19fX1haWqJevXoYOXIk7t27p6uTm5uLuXPnolGjRrC0tISPjw/effddvfiKmzhxIuzs7JCVlaW3btiwYfD09IRarQYA/PvvvwgJCUGdOnVgbW0NPz8/hIWFldn+o9y4cQOCIODzzz/H0qVLdccuJiYGeXl5mDNnDtq3bw9HR0fY2tqia9eu2Lt3r147xccQFY65uXLlCkaPHg0nJyc4Ojri1Vdf1XutxccQFZ7qO3ToEKZMmQI3NzfY2tpi4MCBuHv3rmRbjUaDefPmwdvbGzY2NujWrRtiYmLKNS7p6tWrAIAuXbrorbOysoKDg4Pe6yk0evToUk9BFv09VPZ9QVQUU3EiAyj8o+/q6goA+Oijj/DBBx9g8ODBeO2113D37l0sX74cTz31FE6dOgUnJyfdtvfv38fzzz+PoUOHYvjw4fDw8EBQUBC+/fZbHD9+HN9//z0AoHPnzgC0PVKrV6/GSy+9hKlTp+LYsWNYtGgRYmNjsWnTJklcFy9exLBhw/D6669j7NixaNq0qW7dokWLYG1tjZkzZ+LKlStYvnw5LCwsIJPJ8ODBA8ybNw9Hjx5FVFQU/Pz8MGfOHN22//vf/9C8eXO88MILUCgU2LJlC958801oNBpMmDBBEsOVK1fw0ksvYcyYMRg1ahQiIiIwevRotG/fHs2bNwegHWPStWtXxMbGIiwsDO3atcO9e/ewefNm/Pfff6hTpw40Gg1eeOEFHDx4EOPGjUNAQADOnj2LJUuW4NKlS/jtt99KPT5DhgzBihUr8Oeff+Lll1/WlWdlZWHLli0YPXo05HI5kpKS0LNnT7i5uWHmzJlwcnLCjRs3sHHjxvK+FcoUGRmJnJwcjBs3DpaWlnBxcUFaWhq+//57DBs2DGPHjkV6ejrCw8MREhKC48ePl2sw/eDBg+Hn54dFixbh5MmT+P777+Hu7o5PPvnkkdu+9dZbcHZ2xty5c3Hjxg0sXboUEydOxPr163V1Zs2ahU8//RT9+vVDSEgITp8+jZCQEOTk5Dyy/QYNGgAAfvjhB8yePbtCg6Zff/119OjRQ1K2fft2rFmzBu7u7gDwWO8LIgmRiMotMjJSBCD+9ddf4t27d8Xbt2+L69atE11dXUVra2vxv//+E2/cuCHK5XLxo48+kmx79uxZUaFQSMqffvppEYC4atUqvX2NGjVKtLW1lZRFR0eLAMTXXntNUj5t2jQRgLhnzx5dWYMGDUQA4vbt2yV19+7dKwIQW7RoIebl5enKhw0bJgqCID7//POS+sHBwWKDBg0kZVlZWXrxhoSEiA0bNpSUFcZw4MABXVlSUpJoaWkpTp06VVc2Z84cEYC4ceNGvXY1Go0oiqL4f//3f6JMJhP//vtvyfpVq1aJAMRDhw7pbVu0jbp164qDBg2SlP/888+S+DZt2iQCEP/5559S2yoPW1tbcdSoUbrl69eviwBEBwcHMSkpSVJXpVKJubm5krIHDx6IHh4eYlhYmKQcgDh37lzd8ty5c0UAevUGDhwourq6SsoaNGggianwvdyjRw/d71gURfGdd94R5XK5mJKSIoqiKCYkJIgKhUIcMGCApL158+aJACRtliQrK0ts2rSpCEBs0KCBOHr0aDE8PFxMTEzUq1v4ekpz+fJl0dHRUXzuuedElUoliuLjvS+IiuIpM6JK6NGjB9zc3ODj44OhQ4fCzs4OmzZtQt26dbFx40ZoNBoMHjwY9+7d002enp5o3Lix3qkQS0tLvPrqq+Xa79atWwEAU6ZMkZRPnToVAPDnn39Kyv38/BASElJiWyNHjpQMsO3YsSNEUdQ7PdSxY0fcvn0bKpVKV1Z0HFJqairu3buHp59+GteuXUNqaqpk+8DAQHTt2lW37ObmhqZNm+LatWu6sl9//RWtW7fGwIED9eIs7FH45ZdfEBAQgGbNmkl+r4WnK0s6xVS0jZdffhlbt25FRkaGrnz9+vWoW7cunnzySQDQ9dz98ccfyM/PL7W9yho0aBDc3NwkZXK5XDeOSKPRIDk5GSqVCkFBQTh58mS52h0/frxkuWvXrrh//z7S0tIeue24ceMkvTZdu3aFWq3GzZs3AQC7d++GSqXCm2++KdnurbfeKlds1tbWOHbsGKZPnw5Ae6puzJgx8PLywltvvVXu01qZmZkYOHAgnJ2d8dNPP0EulwN4vPcFUVFMiIgqYcWKFdi1axf27t2LmJgYXLt2TZd4XL58GaIoonHjxnBzc5NMsbGxSEpKkrRVt27dcg+svXnzJmQyGRo1aiQp9/T0hJOTk+5DrJCfn1+pbdWvX1+y7OjoCADw8fHRK9doNJJE59ChQ+jRowdsbW3h5OQENzc3vPfeewCglxAV3w8AODs748GDB7rlq1evokWLFqXGCmh/r+fPn9f7nTZp0gQA9H6vxQ0ZMgTZ2dnYvHkzAO1puq1bt+Lll1/WJQRPP/00Bg0ahPnz56NOnTro378/IiMjDTYWpbTjsXr1arRq1QpWVlZwdXWFm5sb/vzzT73fZWmK/46dnZ0BQPI7ruy2he+p4u85FxcXXd1HcXR0xKeffoobN27gxo0bCA8PR9OmTfH111/jww8/LFcbY8eOxdWrV7Fp0ybdqWng8d8XRIU4hoioEjp06KC7yqw4jUYDQRCwbds23bfYouzs7CTLlbnqq7zjMMpqu6TYyioXC+7QcfXqVXTv3h3NmjXDl19+CR8fHyiVSmzduhVLliyBRqOpUHvlpdFo0LJlS3z55Zclri+eyBXXqVMn+Pr64ueff8Yrr7yCLVu2IDs7G0OGDNHVEQQBGzZswNGjR7Flyxbs2LEDYWFh+OKLL3D06FG9Y1dRJR2PH3/8EaNHj8aAAQMwffp0uLu7Qy6XY9GiRbqxaY/yOL9jQx2f8mrQoAHCwsIwcOBANGzYEGvWrMHChQvL3Oarr77CTz/9hB9//FFvTNXjvi+ICjEhIjIwf39/iKIIPz8/3bdUQ2nQoAE0Gg0uX76MgIAAXXliYiJSUlJ0A1ir0pYtW5Cbm4vNmzdLehce59SEv78/zp0798g6p0+fRvfu3St9N+PBgwfjq6++QlpaGtavXw9fX1906tRJr16nTp3QqVMnfPTRR1i7di1CQ0Oxbt06vPbaa5Xab1k2bNiAhg0bYuPGjZLXNXfuXIPvqzIK31NXrlyR9HDdv3+/XD1QpXF2di7Xcf/7778xbdo0TJ48GaGhoXrrDfG+IAJ4yozI4F588UXI5XLMnz9f71u2KIq4f/9+pdvu3bs3AGDp0qWS8sJvx3369Kl02+VV2KNQ9LWlpqYiMjKy0m0OGjQIp0+f1rtKruh+Bg8ejDt37uC7777Tq5OdnY3MzMxH7mfIkCHIzc3F6tWrsX37dgwePFiy/sGDB3rHrLBHoqou4S7p93ns2DEcOXKkSvZXUd27d4dCodC7rcLXX39dru1Pnz4tuXVCoZs3byImJkZy5WNx8fHxGDx4MJ588kl89tlnJdYxxPuCCGAPEZHB+fv7Y+HChZg1axZu3LiBAQMGwN7eHtevX8emTZswbtw4TJs2rVJtt27dGqNGjcK3336LlJQUPP300zh+/DhWr16NAQMGoFu3bgZ+Nfp69uwJpVKJfv364fXXX0dGRga+++47uLu7Iz4+vlJtTp8+HRs2bMDLL7+MsLAwtG/fHsnJydi8eTNWrVqF1q1bY8SIEfj5558xfvx47N27F126dIFarcaFCxfw888/6+63VJZ27dqhUaNGeP/995Gbmys5XQZox/KsXLkSAwcOhL+/P9LT0/Hdd9/BwcFBl4waWt++fbFx40YMHDgQffr0wfXr17Fq1SoEBgZKBoAbi4eHByZNmoQvvvgCL7zwAnr16oXTp09j27ZtqFOnziN7ZXbt2oW5c+fihRdeQKdOnWBnZ4dr164hIiICubm5ZT6b7e2338bdu3fx7rvvYt26dZJ1rVq1QqtWrQzyviACmBARVYmZM2eiSZMmWLJkCebPnw9AO5ahZ8+eeOGFFx6r7e+//x4NGzZEVFQUNm3aBE9PT8yaNavaTrE0bdoUGzZswOzZszFt2jR4enrijTfegJubW6VvYGhnZ4e///4bc+fOxaZNm7B69Wq4u7uje/fuqFevHgBAJpPht99+w5IlS/DDDz9g06ZNsLGxQcOGDTFp0qRyn54cMmQIPvroIzRq1Ajt2rWTrCtMMNetW4fExEQ4OjqiQ4cOWLNmTZkD1B/H6NGjkZCQgG+++QY7duxAYGAgfvzxR/zyyy/Yt29fleyzoj755BPY2Njgu+++w19//YXg4GDs3LkTTz755CPvnj1o0CCkp6dj586d2LNnD5KTk+Hs7IwOHTpg6tSpZSbxd+/ehVqt1ruqEtCeUmzVqpXB3hdEfJYZERFVWEpKCpydnbFw4UK8//77xg6H6LFxDBEREZUpOztbr6xwHFvhg1mJajqeMiMiojKtX78eUVFR6N27N+zs7HDw4EH89NNP6NmzZ4nPKCOqiZgQERFRmVq1agWFQoFPP/0UaWlpuoHWj7p/EFFNwjFEREREZPY4hoiIiIjMHhMiIiIiMnscQ1QOGo0GcXFxsLe3563hiYiIaghRFJGeng5vb2/IZGX3ATEhKoe4uDg+IJCIiKiGun37tu4mr6VhQlQO9vb2ALS/UAcHByNHQ0REROWRlpYGHx8f3ed4WZgQlUPhaTIHBwcmRERERDVMeYa7cFA1ERERmT0mRERERGT2mBARERGR2eMYIiIiqpHUajXy8/ONHQYZmVKpfOQl9eXBhIiIiGoUURSRkJCAlJQUY4dCJkAmk8HPzw9KpfKx2mFCRERENUphMuTu7g4bGxveMNeMFd44OT4+HvXr13+s9wITIiIiqjHUarUuGXJ1dTV2OGQC3NzcEBcXB5VKBQsLi0q3w0HVRERUYxSOGbKxsTFyJGQqCk+VqdXqx2qHCREREdU4PE1GhQz1XmBCRERERGaPCRERERGZPSZEREREVWz06NEQBAGCIMDCwgIeHh547rnnEBERAY1GI6nr6+sLQRBw9OhRSfnkyZPxzDPP6JbnzZsHQRAwfvx4Sb3o6GgIgoAbN26UGs8zzzwDQRCwePFivXV9+vSBIAiYN2+e3rqffvoJcrkcEyZM0Fu3b98+3WssPiUkJJQai6lgQmRkuVn5SLyeZuwwiIioivXq1Qvx8fG4ceMGtm3bhm7dumHSpEno27cvVCqVpK6VlRVmzJjxyDatrKwQHh6Oy5cvVzgeHx8fREVFScru3LmD3bt3w8vLq8RtwsPD8e677+Knn35CTk5OiXUuXryI+Ph4yeTu7l7h+KobEyIjSrieisgZh7Dtm7PQaERjh0NERFXI0tISnp6eqFu3Ltq1a4f33nsPv//+O7Zt26aXmIwbNw5Hjx7F1q1by2yzadOm6NatG95///0Kx9O3b1/cu3cPhw4d0pWtXr0aPXv2LDGBuX79Og4fPoyZM2eiSZMm2LhxY4nturu7w9PTUzIZ4k7SVc30I6zF3OrZw0IpR2ZKLm6dv2/scIiIaiRRFJGVp6r2SRQf/4vss88+i9atW+slF35+fhg/fjxmzZqld0qtuMWLF+PXX3/Fv//+W6F9K5VKhIaGIjIyUlcWFRWFsLCwEutHRkaiT58+cHR0xPDhwxEeHl6h/Zk63pjRiOQWMjTp6IEze/5D7OF4+LasY+yQiIhqnOx8NQLn7Kj2/cYsCIGN8vE/Rps1a4YzZ87olc+ePRuRkZFYs2YNRowYUer27dq1w+DBgzFjxgzs3r27QvsOCwtD165d8dVXX+HEiRNITU1F37599cYPaTQaREVFYfny5QCAoUOHYurUqbh+/Tr8/PwkdevVqydZbtCgAc6fP1+huIyBPURGFtjFGwBw4/Q9ZKXlGTkaIiKqbqIolngvHTc3N0ybNg1z5sxBXl7Znw8LFy7E33//jZ07d1Zo361bt0bjxo2xYcMGREREYMSIEVAo9JO8Xbt2ITMzE7179wYA1KlTRzcovLi///4b0dHRuulRp/1MBXuIjMy1rh3cfR2QdCMNF48loO1z9Y0dEhFRjWJtIUfMghCj7NcQYmNj9XpZCk2ZMgUrV67EypUry2zD398fY8eOxcyZMyt8KissLAwrVqxATEwMjh8/XmKd8PBwJCcnw9raWlem0Whw5swZzJ8/XzJGyM/PD05OThWKwRSwh8gEBHbRjuaPPRRnkHPSRETmRBAE2CgV1T4Z4g7Je/bswdmzZzFo0KAS19vZ2eGDDz7ARx99hPT09DLbmjNnDi5duoR169ZVKIZXXnkFZ8+eRYsWLRAYGKi3/v79+/j999+xbt06Sc/PqVOn8ODBgwr3Spkq9hCZgMZBHjj4y2U8SMhC4vU0eDZ0NHZIRERkYLm5uUhISIBarUZiYiK2b9+ORYsWoW/fvhg5cmSp240bNw5LlizB2rVr0bFjx1LreXh4YMqUKfjss88qFJezszPi4+NLfTDq//3f/8HV1RWDBw/WSwJ79+6N8PBw9OrVS1eWlJSkd0m+q6vrYz14tTqwh8gEKK0VaNROe4ljzME4I0dDRERVYfv27fDy8oKvry969eqFvXv3YtmyZfj9998hl5d++s3CwgIffvhhqff9KWratGmws7OrcGxOTk6wtbUtcV1ERAQGDhxYYo/YoEGDsHnzZty7d09X1rRpU3h5eUmmEydOVDim6iaIPEfzSGlpaXB0dERqaiocHByqZB9xl1Ow6YuTUFjK8eonXaC0YucdEVFxOTk5uiubrKysjB0OmYCy3hMV+fxmD5GJ8GrkCCcPG6hy1bhyIsnY4RAREZkVJkQmQhAEBHR+OLiaiIiIqg8TIhPStJMnBJmAhGtpSI7PNHY4REREZoMJkQmxdbSEb0tXAOwlIiIiqk5MiExMQMGdqy8eS4BaVfbza4iIiMgwmBCZmAbNXWDjqER2ej5unLn36A2IiIjosTEhMjEyuQzNOmkHV8ccijdyNEREROaBCZEJKrza7HbMfWQ8ePSNuIiIiOjxMCEyQU4eNvBu7ARRBC4cYS8RERFRVWNCZKICCh/4ejgeooY3EyciIqpKTIhMlH87dyit5Ei7l4M7lx4YOxwiInoMo0ePhiAIEAQBFhYW8PDwwHPPPYeIiAhoNNIrin19fSEIAo4ePSopnzx5Mp555hnd8rx58yAIAsaPHy+pFx0dDUEQcOPGjVLjeeaZZyAIAhYvXqy3rk+fPhAEAfPmzdOVXb9+Ha+88gq8vb1hZWWFevXqoX///rhw4YKuTuHrKz6tW7euHL8h42NCZKIslHI07uAJgIOriYhqg169eiE+Ph43btzAtm3b0K1bN0yaNAl9+/aFSqWS1LWyssKMGTMe2aaVlRXCw8Nx+fLlCsfj4+ODqKgoSdmdO3ewe/dueHl56cry8/Px3HPPITU1FRs3bsTFixexfv16tGzZEikpKZLtIyMjER8fL5kGDBhQ4diMgU8QNWGBXbxw/sAdXDt1FzmZ+bCytTB2SEREVEmWlpbw9NR+0a1bty7atWuHTp06oXv37oiKisJrr72mqztu3DisWrUKW7duRe/evUtts2nTpnB3d8f777+Pn3/+uULx9O3bFz///DMOHTqELl26AABWr16Nnj174tatW7p658+fx9WrV7F79240aNAAANCgQQPdNkU5OTnpXmNNwx4iE+ZW3x6ude2gVmlw6XiiscMhIjJNogjkZVb/JD7++M5nn30WrVu3xsaNGyXlfn5+GD9+PGbNmqV3Sq24xYsX49dff8W///5boX0rlUqEhoYiMjJSVxYVFYWwsDBJPTc3N8hkMmzYsAFqtbpC+6hJ2ENkwgRBQEAXLxz8+TJiD8ehVbd6xg6JiMj05GcBH3tX/37fiwOUto/dTLNmzXDmzBm98tmzZyMyMhJr1qzBiBEjSt2+Xbt2GDx4MGbMmIHdu3dXaN9hYWHo2rUrvvrqK5w4cQKpqano27evZPxQ3bp1sWzZMrz77ruYP38+goKC0K1bN4SGhqJhw4aS9oYNGwa5XC4pi4mJQf369SsUlzGwh8jENe3gCZlCwL3bGbh7K93Y4RARkYGJoghBEPTK3dzcMG3aNMyZMwd5eXlltrFw4UL8/fff2LlzZ4X23bp1azRu3BgbNmxAREQERowYAYVCv69kwoQJSEhIwJo1axAcHIxffvkFzZs3x65duyT1lixZgujoaMnk7W2EZLUS2ENk4qzsLNCwjRuu/JuEmENxeLp+U2OHRERkWixstL01xtivAcTGxsLPz6/EdVOmTMHKlSuxcuXKMtvw9/fH2LFjMXPmTISHh1do/2FhYVixYgViYmJw/PjxUuvZ29ujX79+6NevHxYuXIiQkBAsXLgQzz33nK6Op6cnGjVqVKH9mwr2ENUAgZ212fWl44lQ5dXe87dERJUiCNpTV9U9ldCrU1F79uzB2bNnMWjQoBLX29nZ4YMPPsBHH32E9PSyzxLMmTMHly5dqvBl7q+88grOnj2LFi1aIDAwsFzbCIKAZs2aITMzs0L7MmVMiGqAes2cYe9ihbxsFa6eumvscIiIqBJyc3ORkJCAO3fu4OTJk/j444/Rv39/9O3bFyNHjix1u3HjxsHR0RFr164ts30PDw9MmTIFy5Ytq1Bczs7OiI+PL3X8UXR0NPr3748NGzYgJiYGV65cQXh4OCIiItC/f39J3ZSUFCQkJEimmpI0MSGqAQSZUOTO1UboFiYiose2fft2eHl5wdfXF7169cLevXuxbNky/P7773oDkYuysLDAhx9+iJycRz/bctq0abCzs6twbE5OTrC1LXmAeL169eDr64v58+ejY8eOaNeuHb766ivMnz8f77//vqTuq6++Ci8vL8m0fPnyCsdjDIIoGuC6wVouLS0Njo6OSE1NhYODg1FiSE/OwQ/vHwZEYPiHneDoZphz10RENUlOTg6uX78OPz8/WFlZGTscMgFlvScq8vnNHqIawt7FCvUDXAAAsbxzNRERkUExIapBArpoB1dfOBIPjbrsG3URERFR+TEhqkH8WtWBla0FMlPzcCsm2djhEBER1RpMiGoQuYUMTTtqnxHD02ZERESGw4Sohim82uzGmXvISiv7zqVERERUPkZNiA4cOIB+/frB29sbgiDgt99+k6wXRRFz5syBl5cXrK2t0aNHD1y+fFlSJzk5GaGhoXBwcICTkxPGjBmDjIwMSZ0zZ86ga9eusLKygo+PDz799NOqfmlVxrWuHTz8HKDRiLh4NMHY4RAREdUKRk2IMjMz0bp1a6xYsaLE9Z9++imWLVuGVatW4dixY7C1tUVISIjkXgyhoaE4f/48du3ahT/++AMHDhzAuHHjdOvT0tLQs2dPNGjQACdOnMBnn32GefPm4dtvv63y11dVAjo/vCcR75pARERkAKKJACBu2rRJt6zRaERPT0/xs88+05WlpKSIlpaW4k8//SSKoijGxMSIAMR//vlHV2fbtm2iIAjinTt3RFEUxZUrV4rOzs5ibm6urs6MGTPEpk2blju21NRUEYCYmppa2ZdnULlZ+eKqt/aKX7++W4y7/MDY4RARVZvs7GwxJiZGzM7ONnYoZCLKek9U5PPbZMcQXb9+HQkJCejRo4euzNHRER07dsSRI0cAAEeOHIGTkxOCgoJ0dXr06AGZTIZjx47p6jz11FNQKpW6OiEhIbh48SIePHhQ4r5zc3ORlpYmmUyJ0lqBRu3dAQAxhzm4moiI6HGZbEKUkKAdH+Ph4SEp9/Dw0K1LSEiAu7u7ZL1CoYCLi4ukTkltFN1HcYsWLYKjo6Nu8vHxefwXZGCF9yS6ciIJeTkqI0dDREQkFRUVBScnJ2OHUW4mmxAZ06xZs5Camqqbbt++beyQ9Hj5O8LJwwaqXDWu/Jtk7HCIiKgMo0ePhiAIEAQBFhYW8PDwwHPPPYeIiAhoNNIb7fr6+kIQBBw9elRSPnnyZDzzzDO65Xnz5kEQBIwfP15SLzo6GoIg4MaNG6XG88wzz0AQBCxevFhvXZ8+fSAIAubNm1fh11ke2dnZcHFxQZ06dZCbm6u3vvD1F59KitWQTDYh8vTU3m8nMTFRUp6YmKhb5+npiaQkaTKgUqmQnJwsqVNSG0X3UZylpSUcHBwkk6kRBEE3uDrmEB/4SkRk6nr16oX4+HjcuHED27ZtQ7du3TBp0iT07dsXKpW0p9/KygozZsx4ZJtWVlYIDw/XuwK7PHx8fBAVFSUpu3PnDnbv3g0vL68Kt1dev/76K5o3b45mzZrpXV1eaMGCBYiPj5dMb731VpXFBJhwQuTn5wdPT0/s3r1bV5aWloZjx44hODgYABAcHIyUlBScOHFCV2fPnj3QaDTo2LGjrs6BAweQn5+vq7Nr1y40bdoUzs7O1fRqqkbTTp6QyQQkXk9DclymscMhIqIyWFpawtPTE3Xr1kW7du3w3nvv4ffff8e2bdv0EpNx48bh6NGj2Lp1a5ltNm3aFN26ddN76nx59O3bF/fu3cOhQ4d0ZatXr0bPnj31hqPk5uZi2rRpqFu3LmxtbdGxY0fs27dPUicqKgr169eHjY0NBg4ciPv375e43/DwcAwfPhzDhw9HeHh4iXXs7e3h6ekpmWxtbSv8GivCqAlRRkYGoqOjER0dDUA7kDo6Ohq3bt2CIAiYPHkyFi5ciM2bN+Ps2bMYOXIkvL29MWDAAABAQEAAevXqhbFjx+L48eM4dOgQJk6ciKFDh8LbWzvG5pVXXoFSqcSYMWNw/vx5rF+/Hl999RWmTJlipFdtOLaOlmjQ0hUAEHOYvUREZJ5EUURWfla1T6IBbnvy7LPPonXr1ti4caOk3M/PD+PHj8esWbP0TqkVt3jxYvz666/4999/K7RvpVKJ0NBQREZG6sqioqIQFhamV3fixIk4cuQI1q1bhzNnzuDll19Gr169dD1Tx44dw5gxYzBx4kRER0ejW7duWLhwoV47V69exZEjRzB48GAMHjwYf//9N27evFmhuKuKwpg7//fff9GtWzfdcmGSMmrUKERFReHdd99FZmYmxo0bh5SUFDz55JPYvn07rKysdNusWbMGEydORPfu3SGTyTBo0CAsW7ZMt97R0RE7d+7EhAkT0L59e9SpUwdz5syR3KuoJgvs4o3rp+/h4tEEBA/wh1xhsp1+RERVIluVjY5rO1b7fo+9cgw2FjaP3U6zZs1w5swZvfLZs2cjMjISa9aswYgRI0rdvl27dhg8eDBmzJghOatSHmFhYejatSu++uornDhxAqmpqejbt69k/NCtW7cQGRmJW7du6Tobpk2bhu3btyMyMhIff/wxvvrqK/Tq1QvvvvsuAKBJkyY4fPgwtm/fLtlfREQEnn/+ed0ZmpCQEERGRuqNV5oxYwZmz54tKdu2bRu6du1aoddXEUZNiJ555pkyM2xBELBgwQIsWLCg1DouLi5Yu3Ztmftp1aoV/v7770rHacrqN3eBjaMSWal5uH76nu5yfCIiqhlEUYQgCHrlbm5umDZtGubMmYMhQ4aU2cbChQsREBCAnTt36p3uKkvr1q3RuHFjbNiwAXv37sWIESOgUEhTg7Nnz0KtVqNJkyaS8tzcXLi6as9SxMbGYuDAgZL1wcHBkoRIrVZj9erV+Oqrr3Rlw4cP171GmezhF/rp06dj9OjRkvbq1q1b7tdVGUZNiOjxyeQyNAv2wsntNxF7OI4JERGZHWuFNY69cswo+zWE2NhY+Pn5lbhuypQpWLlyJVauXFlmG/7+/hg7dixmzpxZ6ric0oSFhWHFihWIiYnB8ePH9dZnZGRALpfjxIkTkMvlknV2dnbl3s+OHTtw584dveROrVZj9+7deO6553RlderUQaNGjSr0Oh4XE6JaIKCzNiG6FZOM9OQc2LtYPXojIqJaQhAEg5y6MoY9e/bg7NmzeOedd0pcb2dnhw8++ADz5s3DCy+8UGZbc+bMgb+/P9atW1ehGF555RVMmzYNrVu3RmBgoN76tm3bQq1WIykpqdRTVgEBAbobIhcqftuA8PBwDB06VG8A+EcffYTw8HBJQmQMTIhqASd3G3g3dkLc5RRcOBKPJ/qU/E2DiIiMJzc3FwkJCVCr1UhMTMT27duxaNEi9O3bFyNHjix1u3HjxmHJkiVYu3at7grqknh4eGDKlCn47LPPKhSXs7Mz4uPjYWFhUeL6Jk2aIDQ0FCNHjsQXX3yBtm3b4u7du9i9ezdatWqFPn364O2330aXLl3w+eefo3///tixY4fkdNndu3exZcsWbN68GS1atJC0P3LkSAwcOBDJyclwcXEBAKSnp+vdPNnGxqZKb4PDEbi1RGCXwge+xkPU8IGvRESmZvv27fDy8oKvry969eqFvXv3YtmyZfj999/1TkUVZWFhgQ8//FDyYPPSTJs2rUKnsQo5OTmVeVl7ZGQkRo4cialTp6Jp06YYMGAA/vnnH9SvXx8A0KlTJ3z33Xf46quv0Lp1a+zcuVMyKPqHH36Ara0tunfvrtd29+7dYW1tjR9//FFXNmfOHHh5eUmmwgHbVUUQDXHdYC2XlpYGR0dHpKammuRNGgEgP0+NqBmHkJetwguT28CnmYuxQyIiMricnBxcv34dfn5+kiuOyXyV9Z6oyOc3e4hqCQulHE2e0D6jLfYQH/hKRERUEUyIapGAgtNm107dRU5m/iNqExERUSEmRLWIW317uNazg1qlwaXjCY/egIiIiAAwIapVBEHQDa6OORRvkNvKExERmQMmRLVMkw6ekCtkuP9fBu7eSjd2OERERDUCE6JaxsrWAg3b1AHAwdVERETlxYSoFgroon343qV/EqHKUxs5GiIiItPHhKgWqtfUGfauVsjLVuHqqbvGDoeIiMjkMSGqhQSZgIDOBXeuPhRn5GiIiIhMHxOiWqpZsBcgAHcupSAlKcvY4RAREZk0JkS1lL2LFeoHah/fEXuYg6uJiIxp9OjRGDBgQKnrfX19IQgCBEGAjY0NWrZsie+///6R7RZuV9IT7ps3bw5BEBAVFaW3btGiRZDL5SU+CDYqKkoXS9Gptj8qhQlRLRbQWTu4+sKReGjUGiNHQ0REZVmwYAHi4+Nx7tw5DB8+HGPHjsW2bdseuZ2Pjw8iIyMlZUePHkVCQkKpD2yNiIjAu+++i4iIiBLXOzg4ID4+XjLdvHmz4i+qBmFCVIv5ta4DKzsLZKXm4db5ZGOHQ0REZbC3t4enpycaNmyIGTNmwMXFBbt27XrkdqGhodi/fz9u376tK4uIiEBoaCgUCoVe/f379yM7OxsLFixAWloaDh8+rFdHEAR4enpKJg8Pj8d7gSaOCVEtJlfI0LSjJwAghoOriaiWEkURmqysap+q6mkAGo0Gv/76Kx48eAClUvnI+h4eHggJCcHq1asBAFlZWVi/fj3CwsJKrB8eHo5hw4bBwsICw4YNQ3h4uEHjr6n0U0eqVQK6eOH07tu4efY+stLyYOPw6P9cREQ1iZidjYvt2lf7fpuePAHBxsZg7c2YMQOzZ89Gbm4uVCoVXFxc8Nprr5Vr27CwMEydOhXvv/8+NmzYAH9/f7Rp00avXlpaGjZs2IAjR44AAIYPH46uXbviq6++gp2dna5eamqqZBkAunbtWq5TeDUVe4hqOVdvO3j4OUCjEXHhKAdXExGZqunTpyM6Ohp79uxBx44dsWTJEjRq1Khc2/bp0wcZGRk4cOAAIiIiSu0d+umnn+Dv74/WrVsDANq0aYMGDRpg/fr1knr29vaIjo6WTOUZ5F2TsYfIDAR28Ubi9TTEHopH2+fqQxAEY4dERGQwgrU1mp48YZT9GlKdOnXQqFEjNGrUCL/88gtatmyJoKAgBAYGPnJbhUKBESNGYO7cuTh27Bg2bdpUYr3w8HCcP39eMrZIo9EgIiICY8aM0ZXJZLJyJ2O1BRMiM9AoyB1//3IZKYlZiL+aCu9GTsYOiYjIYARBMOipK1Pg4+ODIUOGYNasWfj999/LtU1YWBg+//xzDBkyBM7Oznrrz549i3///Rf79u2Di4uLrjw5ORnPPPMMLly4gGbNmhnsNdQ0TIjMgNJKgUbt3XHhcDxiD8UxISIiMoLU1FRER0dLylxdXeHj41Ni/UmTJqFFixb4999/ERQU9Mj2AwICcO/ePdiUkhyGh4ejQ4cOeOqpp/TWPfHEEwgPD9fdl0gURSQkJOjVc3d3h0xWO0fb1M5XRXoCCx7lceVEEvKyVUaOhojI/Ozbtw9t27aVTPPnzy+1fmBgIHr27Ik5c+aUex+urq6wLuFUXl5eHn788UcMGjSoxO0GDRqEH374Afn5+QC0g6+9vLz0pqSkpHLHUtMIYlVdN1iLpKWlwdHREampqXBwcDB2OJUiiiLWzjuGlMQsPBPaFM271jV2SEREFZaTk4Pr16/Dz8+v1t85mcqnrPdERT6/2UNkJgRBQECXgge+8lEeREREEkyIzEizTl6QyQQkXk/D/bgMY4dDRERkMpgQmREbByV8W9UBAMQeYi8RERFRISZEZqbwtNnFowlQ5/OBr0RERAATIrNTP9AFto5K5GTm4/qZe8YOh4iIyCQwITIzMrkMzYILBlfzga9EREQAmBCZpcLTZrdik5GenGPkaIiIiIyPCZEZcnSzQd0mToAIXDjCwdVERERMiMxUQBdvANp7Eoka3puTiIjMGxMiM+Xf1g1KawXS7+fgv4sPjB0OERGRUTEhMlMKpRxNOngA4OBqIqKqNnr0aAwYMKDU9b6+vhAEAYIgwMbGBi1btsT333//yHYLt1u3bp3euubNm0MQBERFRenKTp8+jRdeeAHu7u6wsrKCr68vhgwZontG2Y0bN3RxFJ+OHj1a4dddkzAhMmOBBafNrkbfRU5GvpGjISIybwsWLEB8fDzOnTuH4cOHY+zYsdi2bdsjt/Px8UFkZKSk7OjRo0hISICtra2u7O7du+jevTtcXFywY8cOxMbGIjIyEt7e3sjMzJRs/9dffyE+Pl4ytW/f3jAv1EQxITJjbvXtUcfHDhqViIvHE4wdDhGRWbO3t4enpycaNmyIGTNmwMXFBbt27XrkdqGhodi/fz9u376tK4uIiEBoaCgUCoWu7NChQ0hNTcX333+Ptm3bws/PD926dcOSJUvg5+cnadPV1RWenp6SycLCwnAv1gQxITJzAZ0LBlcfiococnA1EdU8oigiP1dd7VNV/c3UaDT49ddf8eDBAyiVykfW9/DwQEhICFavXg0AyMrKwvr16xEWFiap5+npCZVKhU2bNvHvfQkUj65CtVmTDh44/OsV3L+Tgbu30uHewMHYIRERVYgqT4NvJ+2v9v2O++ppWFjKDdbejBkzMHv2bOTm5kKlUsHFxQWvvfZaubYNCwvD1KlT8f7772PDhg3w9/dHmzZtJHU6deqE9957D6+88grGjx+PDh064Nlnn8XIkSPh4eEhqdu5c2fIZNI+k4yM2v1QcPYQmTkrWws0bOsGAIjhA1+JiIxm+vTpiI6Oxp49e9CxY0csWbIEjRo1Kte2ffr0QUZGBg4cOICIiAi93qFCH330ERISErBq1So0b94cq1atQrNmzXD27FlJvfXr1yM6Oloy1XbsISIEdPHC5X8Scfl4Arq81AgWSsN94yEiqmoKpQzjvnraKPs1pDp16qBRo0Zo1KgRfvnlF7Rs2RJBQUEIDAx8dCwKBUaMGIG5c+fi2LFj2LRpU6l1XV1d8fLLL+Pll1/Gxx9/jLZt2+Lzzz/XnXIDtAO1y5uM1RbsISLUa+IMhzpWyMtR49rJJGOHQ0RUIYIgwMJSXu2TIAhV9pp8fHwwZMgQzJo1q9zbhIWFYf/+/ejfvz+cnZ3LtY1SqYS/v7/eVWbmiD1EBEEmIKCzF45tvo6YQ/Fo2snL2CEREdU6qampeqeeXF1d4ePjU2L9SZMmoUWLFvj3338RFBT0yPYDAgJw79492NjYlLj+jz/+wLp16zB06FA0adIEoihiy5Yt2Lp1q95l+/fv30dCgvTqYycnJ1hZWT0yjpqKCREBAJoFe+H4luuIu5yClMQsOHmU/B+KiIgqZ9++fWjbtq2kbMyYMaXegDEwMBA9e/bEnDlzsHXr1nLtw9XVtdR1gYGBsLGxwdSpU3H79m1YWlqicePG+P777zFixAhJ3R49euht/9NPP2Ho0KHliqMmEkRee/dIaWlpcHR0RGpqKhwcau9VWFuWn8at8/fRLqQBggf6GzscIiI9OTk5uH79Ovz8/Gp1bwWVX1nviYp8fnMMEekEdtGeKrtwNB4atcbI0RAREVUfJkSk49uqDqztLZCVmoeb55ONHQ4REVG1MemESK1W44MPPoCfnx+sra3h7++PDz/8UHKHTVEUMWfOHHh5ecHa2ho9evTA5cuXJe0kJycjNDQUDg4OcHJywpgxY2r9DaYqQ66QoUlHTwB84CsREZkXk06IPvnkE/zvf//D119/jdjYWHzyySf49NNPsXz5cl2dTz/9FMuWLcOqVatw7Ngx2NraIiQkBDk5Obo6oaGhOH/+PHbt2oU//vgDBw4cwLhx44zxkkxeYMGjPG6cvY/M1FwjR0NERFQ9TDohOnz4MPr3748+ffrA19cXL730Enr27Injx48D0PYOLV26FLNnz0b//v3RqlUr/PDDD4iLi8Nvv/0GAIiNjcX27dvx/fffo2PHjnjyySexfPlyrFu3DnFx7AUpzsXbFp4NHSBqRFw8yge+EhGReTDphKhz587YvXs3Ll26BAA4ffo0Dh48iOeffx4AcP36dSQkJEguD3R0dETHjh1x5MgRAMCRI0fg5OQkuYdDjx49IJPJcOzYsRL3m5ubi7S0NMlkTgK6FDzw9TAf+EpERObBpBOimTNnYujQoWjWrBksLCzQtm1bTJ48GaGhoQCgu2lU8YfSeXh46NYlJCTA3d1dsl6hUMDFxUXvplOFFi1aBEdHR91U2k2zaqtG7d2hsJQjJTEL8VdSjR0OERFRlTPphOjnn3/GmjVrsHbtWpw8eRKrV6/We95KVZg1axZSU1N10+3bt6t0f6ZGaaVA4/baJJKDq4mIyByYdEI0ffp0XS9Ry5YtMWLECLzzzjtYtGgRAMDTU3tFVGJiomS7xMRE3TpPT08kJUmfz6VSqZCcnKyrU5ylpSUcHBwkk7kpPG125WQS8rJVRo6GiIioapl0QpSVlQWZTBqiXC6HRqO9aaCfnx88PT2xe/du3fq0tDQcO3YMwcHBAIDg4GCkpKTgxIkTujp79uyBRqNBx44dq+FV1EyeDR3g7GkDVZ4Gl/9NfPQGRERUK82bNw9t2rQxdhhVzqQTon79+uGjjz7Cn3/+iRs3bmDTpk348ssvMXDgQADaJxxPnjwZCxcuxObNm3H27FmMHDkS3t7eGDBgAADtw+569eqFsWPH4vjx4zh06BAmTpyIoUOHwtvb24ivzrQJgoCAgkvwYw7FGzkaIqKabfTo0brPpZL4+vpCEAQIggAbGxu0bNmy1GeclbTdunXr9NY1b94cgiAgKirqMSIv3X///QelUokWLVqUuL7w9RSfSorVFJh0QrR8+XK89NJLePPNNxEQEIBp06bh9ddfx4cffqir8+677+Ktt97CuHHj8MQTTyAjIwPbt2+XPM9kzZo1aNasGbp3747evXvjySefxLfffmuMl1SjNO3kCZlMQNKNNNy/wxtZEhFVpQULFiA+Ph7nzp3D8OHDMXbsWGzbtu2R2/n4+Og9rf7o0aNISEiAra1tVYWLqKgoDB48WHdmpiSRkZGIj4+XTGUlhsZk0gmRvb09li5dips3byI7OxtXr17FwoULoVQqdXUEQcCCBQuQkJCAnJwc/PXXX2jSpImkHRcXF6xduxbp6elITU1FREQE7Ozsqvvl1Dg2Dkr4tq4DAIhlLxERmShRFJGfk1Ptk6FvS2Jvbw9PT080bNgQM2bMgIuLC3bt2vXI7UJDQ7F//37JBUAREREIDQ2FQqGQ1E1JScFrr70GNzc3ODg44Nlnn8Xp06cldRYvXgwPDw/Y29tjzJgxkhsdFxJFEZGRkRgxYgReeeUVhIeHlxibk5MTPD09JZOpPpRX8egqZM4COnvh2qm7uHAsHsED/SG3MOkcmojMkCo3F8tGvVTt+3179QZYVMGHu0ajwaZNm/DgwQNJB0BpPDw8EBISgtWrV2P27NnIysrC+vXrsX//fvzwww+Sui+//DKsra2xbds2ODo64ptvvkH37t1x6dIluLi44Oeff8a8efOwYsUKPPnkk/i///s/LFu2DA0bNpS0s3fvXmRlZaFHjx6oW7cuOnfujCVLllRpj1RV46cblal+c1fYOlkiN1OFa6fvGjscIqJaa8aMGbCzs4OlpSVeeuklODs747XXXivXtmFhYYiKioIoitiwYQP8/f31BkIfPHgQx48fxy+//IKgoCA0btwYn3/+OZycnLBhwwYAwNKlSzFmzBiMGTMGTZs2xcKFCxEYGKi3v/DwcAwdOhRyuRwtWrRAw4YN8csvv+jVGzZsGOzs7CTTrVu3Kv7LqQbsIaIyyWQCmgV74sS2m4g9HI/GQR6P3oiIqBopLC3x9uoNRtmvIU2fPh2jR49GfHw8pk+fjjfffBONGjUq17Z9+vTB66+/jgMHDiAiIgJhYWF6dU6fPo2MjAy4urpKyguHpADax12NHz9esj44OBh79+7VLaekpGDjxo04ePCgrmz48OEIDw/H6NGjJdsuWbJE8jQJACZ7QRMTInqkgM7eOLHtJm7HJiPtfjYcXK2NHRIRkY4gCFVy6qq61alTB40aNUKjRo3wyy+/oGXLlggKCiqxh6Y4hUKBESNGYO7cuTh27Bg2bdqkVycjIwNeXl7Yt2+f3jonJ6dyx7l27Vrk5ORIbl0jiiI0Gg0uXbokGcfr6elZ7qTO2HjKjB7J0c0adZs6ASJw4Qgf+EpEVNV8fHwwZMgQzJo1q9zbhIWFYf/+/ejfvz+cnZ311rdr1w4JCQlQKBS6xKtwqlNHewFNQECA3hVjR48elSyHh4dj6tSpiI6O1k2nT59G165dERERUYlXaxrYQ0TlEtDZG3cupuDC4Xg80dsXgkwwdkhERDVKamoqoqOjJWWurq6lPi9z0qRJaNGiBf7991/JA8pLExAQgHv37sHGxqbE9T169EBwcDAGDBiATz/9FE2aNEFcXBz+/PNPDBw4EEFBQZg0aRJGjx6NoKAgdOnSBWvWrMH58+d1g6qjo6Nx8uRJ3e1siho2bBgWLFiAhQsX6q5uS0lJ0XtuqL29vUkOvmYPEZWLf1s3WNookJ6cg/8uPDB2OERENc6+ffvQtm1byTR//vxS6wcGBqJnz56YM2dOuffh6uoKa+uShzUIgoCtW7fiqaeewquvvoomTZpg6NChuHnzpu4h6UOGDMEHH3yAd999F+3bt8fNmzfxxhtv6NoIDw9HYGCgXjIEAAMHDkRSUhK2bt2qK3v11Vfh5eUlmZYvX17u11OdBNHQN1KohdLS0uDo6IjU1FSzfK5ZoQM/XcTZ/XfQqL07QsaWfGdSIqKqlJOTg+vXr8PPz89k72dD1aus90RFPr/ZQ0TlVvjA12un7yInI9/I0RARERkOEyIqN7f69qjjYweNSsTFYxxcTUREtQcTIqqQwIJeotjDcQa/bT0REZGxMCGiCmn8hAfkChnu38lE0s10Y4dDRERkEEyIqEKsbC3QsK0bACD2UJyRoyEic8UeaipkqPcCEyKqsMAuXgCAy/8kIj9PbeRoiMicWFhYAACysrKMHAmZiry8PACAXC5/rHZ4Y0aqsLpNnOFQxwpp93Jw9WQSmnXyMnZIRGQm5HI5nJyckJSUBACwsbGBIPBGseZKo9Hg7t27sLGx0d0MsrKYEFGFCTIBAZ29cWzzNcQcjGNCRETVytPTEwB0SRGZN5lMhvr16z92YsyEiCqlWbAXjm+5hvgrqUhJzIKTR8m3iiciMjRBEODl5QV3d3fk5/OeaOZOqVRCJnv8EUBMiKhS7JwtUb+5K26eu4/Yw3EIHlgznmZMRLWHXC5/7HEjRIU4qJoqLaBgcPWFIwnQqDVGjoaIiKjymBBRpfm2rANrewtkpeXh5rn7xg6HiIio0pgQUaXJFTI07agd3BhzKN7I0RAREVUeEyJ6LIUPfL157j4yU3ONHA0REVHlVDohUqlU+Ouvv/DNN98gPV37CIe4uDhkZGQYLDgyfS5etvBs6AhRI+LCEfYSERFRzVSphOjmzZto2bIl+vfvjwkTJuDu3bsAgE8++QTTpk0zaIBk+goHV8ceioc6n4OriYio5qlUQjRp0iQEBQXhwYMHsLa21pUPHDgQu3fvNlhwVDM0au8OpbUCqXez8ef/zvBxHkREVONUKiH6+++/MXv2bCiVSkm5r68v7ty5Y5DAqOZQWinw/OstoFDKcDsmGX8sP428HJWxwyIiIiq3SiVEGo0GarV+L8B///0He3v7xw6Kap56zVzwwtttYGElR9zlFGz+Khq5WbyDLBER1QyVSoh69uyJpUuX6pYFQUBGRgbmzp2L3r17Gyo2qmG8Gjmh/+S2sLRRIPF6Gn5bcgrZGXnGDouIiOiRBFEUxYpu9N9//yEkJASiKOLy5csICgrC5cuXUadOHRw4cADu7u5VEavRpKWlwdHREampqXBwcDB2OCbv3n8Z2PzVKWSn58PZyxb9J7eBraOlscMiIiIzU5HP70olRID2svv169fj9OnTyMjIQLt27RAaGioZZF1bMCGquAcJmfh9ySlkpubB0d0a/Se3hb2LlbHDIiIiM1ItCZE5YUJUOal3s/H70lNIv58Dexcr9H+nDRzdbIwdFhERmYmKfH5XagzRokWLEBERoVceERGBTz75pDJNUi3k6GaNgVPbwdHdGunJOdj0+Uk8SMg0dlhERER6KpUQffPNN2jWrJleefPmzbFq1arHDopqD3sXKwyc2g4u3rbITM3Dpi9O4t5/6cYOi4iISKJSCVFCQgK8vLz0yt3c3BAfz8c3kJStoyUGTGkLt/r2yE7Px29fnkLijTRjh0VERKRTqYTIx8cHhw4d0is/dOgQvL29Hzsoqn2s7ZToP7kNPPwckJulwu9LTyHuSoqxwyIiIgJQyYRo7NixmDx5MiIjI3Hz5k3cvHkTEREReOeddzB27FhDx0i1hKWNBV6Y1AZ1mzghP0eNLcuicTs22dhhERERVe4qM1EUMXPmTCxbtgx5edob71lZWWHGjBmYM2eOwYM0Nl5lZlj5eWpsX3UWt2KSIVfI0Ov1FvBtWcfYYRERUS1TbZfdZ2RkIDY2FtbW1mjcuDEsLWvnzfeYEBmeOl+DHd+fw/XT9yCTC+g5pjn829WuG3oSEZFx8T5EBsaEqGqo1RrsjozB5X+TIAhA99GBaNrR09hhERFRLVGRz29FZXaQmZmJxYsXY/fu3UhKSoJGo5Gsv3btWmWaJTMjl8vQI6w55Eo5LhyOx19RMVDlqdG8a11jh0ZERGamUgnRa6+9hv3792PEiBHw8vKCIAiGjovMhEwm4NnhzWBhIcPZ/Xewb81FqPI0aN3dx9ihERGRGalUQrRt2zb8+eef6NKli6HjITMkyAR0HdoECqUcp3bdwsFfLkOVr0b7Xr7GDo2IiMxEpS67d3Z2houLi6FjITMmCAKCX/THE318AQBHf7uGY5uvgUPciIioOlQqIfrwww8xZ84cZGVlGToeMmOCIKBDv4YIHugPAPh36w0c+vUKkyIiIqpylTpl9sUXX+Dq1avw8PCAr68vLCwsJOtPnjxpkODIPLULaQCFUo6/11/C6b9uQ5WnwdNDm0CQcawaERFVjUolRAMGDDBwGERSrbrVg0Ipw94fL+D8gTtQ56nRbUQzyOSV6tQkIiIqE+9DVA68D5HxXPonAX9FxkLUiGjU3h09wgIhZ1JERETlUJHPb36ykElr8oQneo1tAZlcwJUTSdj+zTmo8tXGDouIiGqZSiVEarUan3/+OTp06ABPT0+4uLhIJiJDatjWDb3faAW5hQw3ztzD1pVnkJ/HpIiIiAynUgnR/Pnz8eWXX2LIkCFITU3FlClT8OKLL0Imk2HevHkGDfDOnTsYPnw4XF1dYW1tjZYtW+Lff//VrRdFEXPmzIGXlxesra3Ro0cPXL58WdJGcnIyQkND4eDgACcnJ4wZMwYZGRkGjZOqVoMWrug7sTUUlnLcjn2AP5afRl6OythhERFRLVGphGjNmjX47rvvMHXqVCgUCgwbNgzff/895syZg6NHjxosuAcPHqBLly6wsLDAtm3bEBMTgy+++ALOzs66Op9++imWLVuGVatW4dixY7C1tUVISAhycnJ0dUJDQ3H+/Hns2rULf/zxBw4cOIBx48YZLE6qHvWaOuOFt9tAaSVH3OUU/L40GjmZ+cYOi4iIaoFKDaq2tbVFbGws6tevDy8vL/z5559o164drl27hrZt2yI1NdUgwc2cOROHDh3C33//XeJ6URTh7e2NqVOnYtq0aQCA1NRUeHh4ICoqCkOHDkVsbCwCAwPxzz//ICgoCACwfft29O7dG//99x+8vb0fGQcHVZuWpJtp2LwsGrmZKtTxscMLb7eBtb3S2GEREZGJqfJB1fXq1UN8fDwAwN/fHzt37gQA/PPPP7C0tKxMkyXavHkzgoKC8PLLL8Pd3R1t27bFd999p1t//fp1JCQkoEePHroyR0dHdOzYEUeOHAEAHDlyBE5OTrpkCAB69OgBmUyGY8eOlbjf3NxcpKWlSSYyHe4NHDBwSjtYOyhx73YGNn15CpmpucYOi4iIarBKJUQDBw7E7t27AQBvvfUWPvjgAzRu3BgjR45EWFiYwYK7du0a/ve//6Fx48bYsWMH3njjDbz99ttYvXo1ACAhIQEA4OHhIdnOw8NDty4hIQHu7u6S9QqFAi4uLro6xS1atAiOjo66yceHDxo1Na517TBwSlvYOlniQXwmNn1+EunJOY/ekIiIqASVujHj4sWLdfNDhgxB/fr1ceTIETRu3Bj9+vUzWHAajQZBQUH4+OOPAQBt27bFuXPnsGrVKowaNcpg+ylu1qxZmDJlim45LS2NSZEJcva0xYvT2uG3JaeQejcbGz8/gf6T28LJ3cbYoRERUQ1jkPsQBQcHY8qUKQZNhgDAy8sLgYGBkrKAgADcunULAODp6QkASExMlNRJTEzUrfP09ERSUpJkvUqlQnJysq5OcZaWlnBwcJBMZJoc6ljjxWnt4ORhg4zkXGz64iSS4zONHRYREdUwleohAoC4uDgcPHgQSUlJ0Gg0knVvv/32YwcGAF26dMHFixclZZcuXUKDBg0AAH5+fvD09MTu3bvRpk0bANrenGPHjuGNN94AoE3WUlJScOLECbRv3x4AsGfPHmg0GnTs2NEgcZJx2TlbYeDUdvh96Skkx2Xity9P4oVJbVCnnr2xQyMiohqiUleZRUVF4fXXX4dSqYSrqysE4eFDNwVBwLVr1wwS3D///IPOnTtj/vz5GDx4MI4fP46xY8fi22+/RWhoKADgk08+weLFi7F69Wr4+fnhgw8+wJkzZxATEwMrKysAwPPPP4/ExESsWrUK+fn5ePXVVxEUFIS1a9eWKw5eZVYz5GTkY/OyaNy9lQ5LGwX6vdUGHn48XkRE5qoin9+VSoh8fHwwfvx4zJo1CzJZ1T79448//sCsWbNw+fJl+Pn5YcqUKRg7dqxuvSiKmDt3Lr799lukpKTgySefxMqVK9GkSRNdneTkZEycOBFbtmyBTCbDoEGDsGzZMtjZ2ZUrBiZENUdutgp/LD+NhGupsLCSo++E1vBu7GTssIiIyAiqPCFydXXF8ePH4e/vX+kgaxImRDVLXo4KW/93BncupkBhIUPvN1vBJ4CPlCEiMjdVfh+iMWPG4JdffqlUcERVTWmlQN8JrVG/uStU+Rr8ueIMbpy5Z+ywiIjIhFWqh0itVqNv377Izs5Gy5YtYWFhIVn/5ZdfGixAU8AeoppJna/BzvDzuBZ9FzKZgOfGNEej9u6P3pCIiGqFinx+V+oqs0WLFmHHjh1o2rQpAOgNqiYyBXILGULGNsdfUbG4/E8idn5/Dqr8ADTr5GXs0KpMfp4ayXGZuH8nA/k5ang3dkKdenYQZPx/SURUlkolRF988QUiIiIwevRoA4dDZFgyuQw9Xg2EQilD7KF47I6KhSpPgxZP1TV2aI9FoxGRdjcb9+9kaKe4TNz/LwOp97KBYn2+1vYWqNfMBfWbu8AnwAW2joZ7vA4RUW1RqYTI0tISXbp0MXQsRFVCJhPQLbQZFEo5zu79D/vXXoQ6X4PW3WvG3cez0vL0Ep8H8ZlQ5WtKrG9tbwHXunaQW8gQdykF2en5uPxPIi7/o72BqWtdO9QPdIFPcxd4+ztBblG1V4oSEdUElRpDtGjRIsTHx2PZsmVVEZPJ4Rii2kEURRz97SpO7tDe6bzjCw0R1NvXuEEVUfR0V/KdTNy7k4HkuAxkp+eXWF9hIYOLty1c69rBta4dXOrawtXbDjYOSl0dtUqDhGupuB2TjFsxybh7K12vDe8mzqgfqO1BcvKw4WlvIqo1qvyy+4EDB2LPnj1wdXVF8+bN9QZVb9y4saJNmjQmRLWHKIr4d+sNHN9yHQDQvlcDdOzfsFqTgIqc7gIACICjm7Uu8XEtSHwc3Kwhq+DYoOz0PNy+kIzb55NxKzYZWal5kvV2LpaoH+ACn0BX1GvmDCtbi1JaIiIyfVU+qNrJyQkvvvhipYIjMiZBEPBEHz8oLOQ4vPEKTmy/CVWeBl1eblQlSVFlT3e5etvBtZ6298fZyxYWSrlB4rG2V6LJE55o8oQnRFFEclwmbp1Pxq2Y+4i/koqM5FzEHIpHzKF4CALg7utQ0HvkCvcG9pDJeXqtokRRRGZKHjIe5MDWyRJ2TpYc5E5kgircQ6RSqbB27Vr07Nmz1Iej1jbsIaqdzu77DwfWXQIANO/qjaeHNa30B1VlT3e51LWDq7ctXOvZ6Z3uqm75eWrEXU7R9h7F3MeDhCzJeksbBeo1dYZPoAt8Al3g4GptpEhNV05GPu7HZWjfC3GZSC6Yz81S6erILWRwdLN+OLnbwNHdGk7uNkyWiAysyk+Z2djYIDY2VveQ1dqOCVHtFXs4Dnv/7wJEEWja0RPPjmxWZi/IY53uKjLepzKnu6pbenIObscm49b5ZPx3IVnyoQ4ATh422sHZgS6o28QZFpaG6cWqCfJyVEiOyyxIfDJ081lpeSXWF2QCbB2VyErNg0ZT+p9cuUIGhzpWD5OkwoTJzRp2LlYm/54hMjVVfsqsQ4cOOHXqlNkkRFR7BXT2hsJCjl2RMbh4LAGqfDWeC2sOuUL2WKe7XOpqkx8XL9samyjYu1ghsIs3Art4Q6MRkXQzDbdjknE7JhkJ19OQkpiFlMQsnNn7H2QKAV7+TroEqU49u1oxOFuVp8aDhCxtT098Qa/PnUykJ+eUuo1DHSu4eGuPvXbQuy2cPGygsJBDo9YgPTkHqUnZSL2bjZSkLKTezUZqUjbS7mVDrdLgQUKWXu8cAMgUAhzrFPYsaRMmR3ftvL2LJU9nEj2mSvUQ/fzzz5g1axbeeecdtG/fHra2tpL1rVq1MliApoA9RLXftei72PH9OWhUIhzdrZGXrSr1dJfcQgbXoqe7Cnp9jHm6q7rlZuXjv4sPcCtGO0C7eIJg7aAsGJytvfeRqf9u1GoNUhOzC5Kehz0+qUlZKO0vpI2jUvs+8LbTJj7ednD2soHSqlLfM6FRa5DxILcgWcpCSkHSlJqUhdR72dCoSv9TLZMLcChMltwfJkxO7tawd7FiskRmq8pPmZX0hHtBECCKIgRBgFqtrmiTJo0JkXm4df4+tq46C3VhD5AAONaxLhjfU7NOd1UnURSRmpSNWzH3cTsmGf9dSoEqV/o3oI5Pwb2PAl3h5e8IucI4H9CiRkTa/Rwkx2UUjPHRjvN5kJAFjbrkP4WWtgptr5+3rSQBqs4r8DQaERkPcnS9SakFPUspSdlIu6vtWSqNTCbA3vXhaThHN+14JUc3a9jXsYKcyRLVYlWeEN28ebPM9bXtVBoTIvNx778M3LudDmcv2xp9usuY1PkaxOvufXQf925nSNYrLOWo20R7eq1+oCsc3a0Nfnqt8Mquh4lPQa9PfCZUeSUnDwpLeUHCY6tLgFy8bWHjoDTp03+iRkRGSq4uSUpNKnIq7m72wwS/BEJBsuRUbIC3o5s1HOpYGy1xJTKUKk+IzA0TIqLKy0rLw+1Y7dijW7HJyC428NjexQo+zV1QP9AF9Zo6w9KmYj0v2Rl5SL6T+XCMTwlXdhUlV8jg7GXzcIxPQfJj72JV667wEjUiMlNzSxyzlHo3q9TkEAAEAdqepSIDux3dbeBYxxqWtgpYWMphoZTXut8Z1S7VkhBdvXoVS5cuRWxsLAAgMDAQkyZNgr+/f2WaM2lMiIgMQ9SIuHcnQ3fn7PirKZKxMYJMgIevg+65a+6+DrrTk3nZKiTHS6/suh+XqZdgFW3Lyd26oKfHTtf74+hmzTE10PaiZaXmPRyvVGzsUvHTnqVRWMq1yZGlHEqrh/MPp4LkqYR12vrF1jPJAqA9TarO10Cdr4EqXwO1Sq39WVimejgvkwtQKOUFkwwWBT8VSjkUFjLILWQm3ctZlao8IdqxYwdeeOEFtGnTRvdMs0OHDuH06dPYsmULnnvuucpFbqKYEBFVjfxcNe5ceqBLkFIS9e99VMfHDql3s5GRnFtqO7oru4qM83H2sOFz2ipJFEVkpeXpkqSiPUxp93KQl6Mq+TYTBqJQyiQJVYmJllWRhKvEREwOpZU22VJYyis87k+jEaEuknSo8jVQ5atLTEi0CUuR+YLlhwmMuoL1NWXenqHCBO29z6QJkzRpUijlsChcLrJOUmYhe7hNCcmXTC6YXOJV5QlR27ZtERISgsWLF0vKZ86ciZ07d+LkyZMVbdKkMSEiqh5p97N1l/bfvvAAednS0162jkq41C2S+Hg93pVdVDmiKEKVr0F+jhr5uUWmHJV0WVeuRl6uSrJc0nZVOYBDYSGTJE4KpRxiQdJTUlJS2iB7Y5DJBMgLenoUFjLIFdJ5jUaEKk+N/DwNVHlqqAp+VvdrEGSCfiJl8TCBKiyTK2WwsCiSkBX8tLRRoHGQh0FjqvKEyMrKCmfPnkXjxo0l5ZcuXUKrVq2Qk1P6PTpqIiZERNVPo9Yg6WY6kuMz4eRuU+1XdlH1EkXtKaLiyVRezqMTqZKmvIK6ogF6WspMSAqWdfMWMigUMsgt5BWsX7R9eZG6QqVP8arVGqjzCnq38tTIL5IsPfypn0ip8jTIz1frlany1EXaKlg2YCJr7aBE2KdPGqaxAlV+Y0Y3NzdER0frJUTR0dFwd3evTJNERBIyuQyeDR3h2dDR2KFQNRCEh+NgrO0N06YoanuA9JKpHG1y8KhER2Ehf6yExNjkchnk1jIoq/ApO6IoQqMWHyZSxZKtomXq/JKSr4dlxu7prdTex44di3HjxuHatWvo3LkzAO0Yok8++QRTpkwxaIBERESVIQgCFBZyKCzksLYzdjS1kyAIkCsEyBUyWNoYO5rHU6lTZqIoYunSpfjiiy8QFxcHAPD29sb06dPx9ttvm9ygqsfFU2ZEREQ1T5WMIdq8eTOef/55WFhIz+Gnp6cDAOztDdTHaYKYEBEREdU8Ffn8LveJ0YEDByIlJQUAIJfLkZSUBECbCNXmZIiIiIhqv3InRG5ubjh69CgA6J5ZRkRERFQblHtQ9fjx49G/f38IgvbGS56enqXWrW0PdyUiIqLardwJ0bx58zB06FBcuXIFL7zwAiIjI+Hk5FSFoRERERFVjwpddt+sWTM0bdoUo0aNwqBBg2Bnx+sYiYiIqOar8N2mRFHEmjVrEB8fXxXxEBEREVW7CidEMpkMjRs3xv3796siHiIiIqJqV6n7kS9evBjTp0/HuXPnDB0PERERUbWr1J2qnZ2dkZWVBZVKBaVSCWtr6YNSkpOTDRagKeCNGYmIiGqeKn+469KlSyuzGREREZFJqlRCNGrUKEPHQURERGQ0lRpDBABXr17F7NmzMWzYMN1jPLZt24bz588bLDgiIiKi6lCphGj//v1o2bIljh07ho0bNyIjIwMAcPr0acydO9egARIRERFVtUolRDNnzsTChQuxa9cuKJVKXfmzzz6re94ZERERUU1RqYTo7NmzGDhwoF65u7s77t2799hBEREREVWnSiVETk5OJd6p+tSpU6hbt+5jB0VERERUnSqVEA0dOhQzZsxAQkICBEGARqPBoUOHMG3aNIwcOdLQMRIRERFVqUolRB9//DECAgJQv359ZGRkIDAwEE899RQ6d+6M2bNnGzpGIiIioipVofsQaTQafPbZZ9i8eTPy8vIwYsQIDBo0CBkZGWjbti0aN25cVXESERERVZkKJUQfffQR5s2bhx49esDa2hpr166FKIqIiIioqviIiIiIqlyFTpn98MMPWLlyJXbs2IHffvsNW7ZswZo1a6DRaKoqPiIiIqIqV6GE6NatW+jdu7duuUePHhAEAXFxcQYPjIiIiKi6VCghUqlUsLKykpRZWFggPz/foEERERERVacKjSESRRGjR4+GpaWlriwnJwfjx4+Hra2trmzjxo2Gi5CIiIioilUoISrpKffDhw83WDBERERExlChhCgyMrKq4iAiIiIymkrdmNFYFi9eDEEQMHnyZF1ZTk4OJkyYAFdXV9jZ2WHQoEFITEyUbHfr1i306dMHNjY2cHd3x/Tp06FSqao5eiIiIjJVNSYh+ueff/DNN9+gVatWkvJ33nkHW7ZswS+//IL9+/cjLi4OL774om69Wq1Gnz59kJeXh8OHD2P16tWIiorCnDlzqvslEBERkYmqEQlRRkYGQkND8d1338HZ2VlXnpqaivDwcHz55Zd49tln0b59e0RGRuLw4cM4evQoAGDnzp2IiYnBjz/+iDZt2uD555/Hhx9+iBUrViAvL89YL4mIiIhMSI1IiCZMmIA+ffqgR48ekvITJ04gPz9fUt6sWTPUr18fR44cAQAcOXIELVu2hIeHh65OSEgI0tLScP78+RL3l5ubi7S0NMlEREREtVeFBlUbw7p163Dy5En8888/eusSEhKgVCrh5OQkKffw8EBCQoKuTtFkqHB94bqSLFq0CPPnzzdA9ERERFQTmHQP0e3btzFp0iSsWbNG74aQVWnWrFlITU3VTbdv3662fRMREVH1M+mE6MSJE0hKSkK7du2gUCigUCiwf/9+LFu2DAqFAh4eHsjLy0NKSopku8TERHh6egIAPD099a46K1wurFOcpaUlHBwcJBMRERHVXiadEHXv3h1nz55FdHS0bgoKCkJoaKhu3sLCArt379Ztc/HiRdy6dQvBwcEAgODgYJw9exZJSUm6Ort27YKDgwMCAwOr/TURERGR6THpMUT29vZo0aKFpMzW1haurq668jFjxmDKlClwcXGBg4MD3nrrLQQHB6NTp04AgJ49eyIwMBAjRozAp59+ioSEBMyePRsTJkyQPIKEiIiIzJdJJ0TlsWTJEshkMgwaNAi5ubkICQnBypUrdevlcjn++OMPvPHGGwgODoatrS1GjRqFBQsWGDFqIiIiMiWCKIqisYMwdWlpaXB0dERqairHExEREdUQFfn8NukxRERERETVgQkRERERmT0mRERERGT2mBARERGR2WNCRERERGaPCRERERGZPSZEREREZPaYEBEREZHZY0JEREREZo8JEREREZk9JkRERERk9pgQERERkdljQkRERERmjwkRERERmT0mRERERGT2mBARERGR2WNCRERERGaPCRERERGZPSZEREREZPaYEBEREZHZY0JEREREZo8JEREREZk9JkRERERk9pgQ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ftnb2NSRJkguDQHXgp/WztUTNxER1WpMiAyMCVElZKcAD64XJEjXgPvXHs5nJpW9rbVzsWTJ/+G8jQuvbiMionKpyOd3+R7mRVRR1k6AdVvAu63+utx0IPm6tiepMElKLkie0uO145LunHj4SJGiLB21p99c/fV7mGzdmCwREVGlMCGi6mdpD3i10k7F5WU+TI6KT2l3gNxUID5aOxWntNcfq+TSUJs82XkwWSIiolIxISLTorQFPFtop+Lys4EHN4qchrv6sHcp9TaQlw4knNFOxVnYFBvcXaSHyd4LkMmq/KUZnCgCokZ700yNGhDVBfOah/Pq/IIylf5yifP52raKLqtVRdapCpaLzhfWK9hWt67IconrVKXUKxavqAYgFCS0BT8FWcnzKFgWUIG6RdstZR96dSu5D+2B0x67iswXHu9HzqPk7R+73SLzQMFrkgMyhfY+ZIJc+3+ovGUyRcF8WWXF5nXtyMpZJtfGKZMXa1v2sB6gfX+JmoJJLDJfMGnKWq8utiyWsW3x9cXXFVmvt13x7UtoV++YQnrMio+OkSyXsl156hhkuwLWzsCQ/4OxMCGimsPCGnAP0E7FqXKBBzcfDuou2rOUcgvIzwISz2mn4hRWgLPfw4Hdtu4P/+hoCieVdFksXq4pMq96+AetrGRF0k5F91Gw3mwU+SDnqEei2snO06i7Z0JEtYPCEnBrop2KU+VpkyK903BXtUmUKge4G6udahOZApBZaH/Ki88XLMstCr5BF64r+Kmblxeppyi2roR53XLBtrp1FtL9lhVT8XWFd0LXfRMWi80XLOvmi5Tr1S1tHsXaKGW+xH2XJ6aCeV3PEaDrMSrae/RY81XRZvF5PDwWkkRf/bBMkrQX/1JQ7EuAJOkvo029LxElfDl4ZJsllBX24MnkD3v39Cb5w16+ouWFvU26SShWv/gklLBNOaZSYysWV3HF32cllUmGERQvK892lW27lDgVVvrrqxETIqr9FEqgTiPtVJw6X3u6rejA7sx7xbrhFUW63Uvogtfrpi+l/LG3L7qupO2LltfAU4BEREbEhIjMm9zi4VgiIiIyW/waSURERGaPCRERERGZPSZEREREZPaYEBEREZHZY0JEREREZo8JEREREZk9JkRERERk9pgQERERkdljQkRERERmjwkRERERmT0mRERERGT2mBARERGR2WNCRERERGaPCRERERGZPSZEREREZPaYEBEREZHZY0JEREREZo8JEREREZk9JkRERERk9pgQERERkdljQkRERERmjwkRERERmT0mRERERGT2mBARERGR2WNCRERERGaPCRERERGZPYWxAzBnoloNVUICBKUSgqWl9qdSCUHGPJWIiKg6MSEyInVqKq5076G/QqGAoFRCVpggFU6WlhCUFpBZFC9TQlBaFGxjKd1GqYRgWUJbyoK29NopmCyUkFkqtbEIQvX/coiIiKoREyIjykp5gD2BDSBoRMhEEYIoQiZCMq/9qYKgzocsMwOyDG2ZtrxoncI2Stq+pHUPl0uqr4sFgMxCmzjJHpWQyRWAIGgnACj8IQhFFx7+LEc9EYAoCBABQBAhitoqovYfiEJBHV09sWA7UVunYD3EYvVEEaIg6vYBCAXbFNYVtXVE7Yban9oWRLGgpqS8YF633cNliNp2JW3pykXoFlGkHbHI6yjYDrq6ol6sD+s/XP9Qab/z4sekpLKH64SC3yd0P4usL1dbRbcp0kaJ80KR4oJjoxF1r1X7K9Ho/U5Fye+64PdVpFxyLFDYjljkmBf5PaNo3SI/JfOF6wrfRw9/8w/bg66s6G9LkCwLkl/tw0mQ1C8sEYQi2xSpKwiPqFdwLGRF5gvXC0XLBEG6rGv7YVtF32EorazI/79y1SvenqRQBAr/FujVK1Za3vZKikVS7+EBfFiv2JxYQpluXv+Fl91OGdtC/3WWFHvZSvlyW+7vvCVUfKzvy9KNLa2s0P/7Hx6nwcfChMiIBCdH5FjUnEMgTdzyIdPkQchKhyxTm1wJxZIQseAvvGS+8A9VwR82yXzB/42HCRB7pqiGK/dbuIIfbaVVr/gnJJHJsMzJMOr+a86ncS1k4+CI4YuWQq1SQaNWQaNW6+bVKhU0qoKfJZTrlenWqaFW5UvWa+fzC9aVsE1hXdXDuqJGoxevKBOgfryvA1VGm28JD7/JFsxDAGQQCtZJyyXfenU/BUl70G1TZLmwnlC4hGLLQkEnyMPtivZ+FdYtGgsK2hSKzEu2L3wNAh6uK9LTIhTdRiiyTaGi3yxFXSr68ANU1Fsosljkm6yknWLblNaWWLysSJtikTpCKeUQIQgyyWuTFS4X/H5ksofLgiADZIW/z4LfQ9FlQQAEWZH5ItsLAiCTQVbkdyzIZNLtCpa12xW2JYMgK1JfF48MglzQxY/Cni5RA01Bj5eoKejp0hT2LmqkPzUa7a9QU7z8YS9m0XKIIjSiCBQsazRisfLi+ymMQ9RbRvH2AYii5uF7WfcPpGWFJSV8qREKemiLrnvYRAllRdsusi+9lgX9sqL/b/WjFCX/pwuLi84Xj1vyf1hXXzIjjUwoVr9I3Ye/uyK9gMV7UyV/M4q/jhJilqhAdlzY9a7XQiltlFgslhxH8d67MlhYWZe7blVgQmRE97NzMGrvRsgEBRSCAnKZ9qdCVjAJFrp5C5kCFjIlLOQ2UFhYQGmlLVfKLKBUWEApU8BCbgELmRwKuRwKmQCFXIBcJsBSJoNcJkAhEyCXC7AoXC5Yr5Bpf1rIH9aTobA3SA25qAZEDQSNGoKogaBWaf+gq6SJlSiKkOk+PAo+OGQF80U+KB5+yBSsL5wXhBKWi2wjyLQfXLKH89LkgIiIqHLMKiFasWIFPvvsMyQkJKB169ZYvnw5OnToYLR4krNTcUfxf9JCEYC6YKokUSMHIAdEGURRDojaeUBeZLnI+oK6EOUQRRkgKrTrUGRbsWBbyHTbywUFBMghF+QQBAVkkD8cv1D4bR2ygt4XGQq/FsmK9MTIICvyDUcGWWHdwl6PgrqSeoKgbQPa3gCZrjdE0O2rsCdFVnBniYf1Cue1ey/cUqbrMYBum6LjkSS/X8k3HlHvC5CIEnrX9MYZ6I9fEIstlbyPksY9SMe4lNRCyYp+G39UQimUMl+8VnW1U3b7j966pJ6L8tUrec3jJOTlP//1qGNa6jf6wvUlfls33Hk2yTjAwrIS5rR1i9YRitQp4dg8srWHJYW9vfprBUk9faX9vvX/35a0TckdIeU5hsX/35Y+tqm0FvRV5P9WWe/d0t/lj9NOae06WimxfMizZbRTtcwmIVq/fj2mTJmCVatWoWPHjli6dClCQkJw8eJFuLu7GyUmR2trNHPoBLWogkqjglpUQ6XJh1rUzmtElWReAzXUogoaUQURamigRkn/OQTZw4yquvpNCvO4GqvIWSSTVJ4DyU4yehRzeI+Y8v9jKlumAwDjJUSCWPJXhlqnY8eOeOKJJ/D1118DADQaDXx8fPDWW29h5syZZW6blpYGR0dHpKamwsHBoTrCLTe1Rg1VQUKl0qiQr8mX/JRMogr56vyH8yXVKbptQf08dT7yNNr5fLUKeRptWWFb+bpttAnawyuAtN92Cq+U0ujGIGizD92VXNCObdBdQaRbJ92+pPXa/WlQeF2VtA5061DKOmk/UOH6Yp8bknEN+t8yS/8+XMpYhFJ6SUrsFSn2bbf0bUuOV6fM3qOSv6GWRP+qmbK+PZe1bRkR6MVa0T9RFf+TVi1bFBs3I1Vyedn5S2nblLJVGaeVK7NGq3jvacnryuxZKbO9kt8zZfWylHRlV8nr9MfNlPZ/sOw6j+or1K+vfygedfzLEWeB8v+u9UtK+30/eqmMvxl6KUbpLdkrnHHglV2ltlUZFfn8Noseory8PJw4cQKzZs3SlclkMvTo0QNHjhzRq5+bm4vc3FzdclpaWrXEWRlymRxyyGEptzR2KERERDWWWdwS+d69e1Cr1fDw8JCUe3h4ICEhQa/+okWL4OjoqJt8fHyqK1QiIiIyArNIiCpq1qxZSE1N1U23b982dkhERERUhczilFmdOnUgl8uRmJgoKU9MTISnp6defUtLS1ha8hQUERGRuTCLHiKlUon27dtj9+7dujKNRoPdu3cjODjYiJERERGRKTCLHiIAmDJlCkaNGoWgoCB06NABS5cuRWZmJl599VVjh0ZERERGZjYJ0ZAhQ3D37l3MmTMHCQkJaNOmDbZv36430JqIiIjMj9nch+hxmPJ9iIiIiKhkFfn8NosxRERERERlYUJEREREZo8JEREREZk9JkRERERk9pgQERERkdljQkRERERmjwkRERERmT2zuTHj4yi8VVNaWpqRIyEiIqLyKvzcLs8tF5kQlUN6ejoAwMfHx8iREBERUUWlp6fD0dGxzDq8U3U5aDQaxMXFwd7eHoIgGDsck5SWlgYfHx/cvn2bd/M2ATwepoXHw/TwmJiWqjoeoigiPT0d3t7ekMnKHiXEHqJykMlkqFevnrHDqBEcHBz4x8WE8HiYFh4P08NjYlqq4ng8qmeoEAdVExERkdljQkRERERmjwkRGYSlpSXmzp0LS0tLY4dC4PEwNTwepofHxLSYwvHgoGoiIiIye+whIiIiIrPHhIiIiIjMHhMiIiIiMntMiIiIiMjsMSGicluxYgV8fX1hZWWFjh074vjx46XW/e6779C1a1c4OzvD2dkZPXr0KLM+VVxFjkdR69atgyAIGDBgQNUGaGYqejxSUlIwYcIEeHl5wdLSEk2aNMHWrVurKVrzUNFjsnTpUjRt2hTW1tbw8fHBO++8g5ycnGqKtvY6cOAA+vXrB29vbwiCgN9+++2R2+zbtw/t2rWDpaUlGjVqhKioqCqPEyJROaxbt05UKpViRESEeP78eXHs2LGik5OTmJiYWGL9V155RVyxYoV46tQpMTY2Vhw9erTo6Ogo/vfff9Ucee1U0eNR6Pr162LdunXFrl27iv3796+eYM1ARY9Hbm6uGBQUJPbu3Vs8ePCgeP36dXHfvn1idHR0NUdee1X0mKxZs0a0tLQU16xZI16/fl3csWOH6OXlJb7zzjvVHHnts3XrVvH9998XN27cKAIQN23aVGb9a9euiTY2NuKUKVPEmJgYcfny5aJcLhe3b99epXEyIaJy6dChgzhhwgTdslqtFr29vcVFixaVa3uVSiXa29uLq1evrqoQzUpljodKpRI7d+4sfv/99+KoUaOYEBlQRY/H//73P7Fhw4ZiXl5edYVodip6TCZMmCA+++yzkrIpU6aIXbp0qdI4zU15EqJ3331XbN68uaRsyJAhYkhISBVGJoo8ZUaPlJeXhxMnTqBHjx66MplMhh49euDIkSPlaiMrKwv5+flwcXGpqjDNRmWPx4IFC+Du7o4xY8ZUR5hmozLHY/PmzQgODsaECRPg4eGBFi1a4OOPP4Zara6usGu1yhyTzp0748SJE7rTateuXcPWrVvRu3fvaomZHjpy5Ijk2AFASEhIuT9vKosPd6VHunfvHtRqNTw8PCTlHh4euHDhQrnamDFjBry9vfXe5FRxlTkeBw8eRHh4OKKjo6shQvNSmeNx7do17NmzB6Ghodi6dSuuXLmCN998E/n5+Zg7d251hF2rVeaYvPLKK7h37x6efPJJiKIIlUqF8ePH47333quOkKmIhISEEo9dWloasrOzYW1tXSX7ZQ8RVbnFixdj3bp12LRpE6ysrIwdjtlJT0/HiBEj8N1336FOnTrGDocAaDQauLu749tvv0X79u0xZMgQvP/++1i1apWxQzNb+/btw8cff4yVK1fi5MmT2LhxI/788098+OGHxg6Nqgl7iOiR6tSpA7lcjsTEREl5YmIiPD09y9z2888/x+LFi/HXX3+hVatWVRmm2ajo8bh69Spu3LiBfv366co0Gg0AQKFQ4OLFi/D396/aoGuxyvz/8PLygoWFBeRyua4sICAACQkJyMvLg1KprNKY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\n" | |
}, | |
"metadata": {} | |
} | |
] | |
} | |
], | |
"metadata": { | |
"colab": { | |
"provenance": [] | |
}, | |
"kernelspec": { | |
"display_name": "Python 3", | |
"name": "python3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <queue> | |
#include <omp.h> | |
using namespace std; | |
struct Node { | |
int id; | |
vector<int> neighbors; | |
bool visited; | |
Node(int id) { | |
this->id = id; | |
visited = false; | |
} | |
}; | |
void bfs(vector<Node> &nodes, int start) { | |
queue<int> queue; | |
queue.push(start); | |
while (!queue.empty()) { | |
int current = queue.front(); | |
queue.pop(); | |
cout << current << " "; | |
#pragma omp parallel for | |
for (int neighbor : nodes[current].neighbors) { | |
if (!nodes[neighbor].visited) { | |
nodes[neighbor].visited = true; | |
queue.push(neighbor); | |
} | |
} | |
} | |
} | |
int main() { | |
int n; | |
cout << "Enter the number of nodes: "; | |
cin >> n; | |
vector<Node> nodes; | |
for (int i = 0; i < n; i++) { | |
nodes.push_back(Node(i)); | |
} | |
for (int i = 0; i < n; i++) { | |
int num_neighbors; | |
cout << "Enter the number of neighbors for node " << i + 1 << ": "; | |
cin >> num_neighbors; | |
for (int j = 0; j < num_neighbors; j++) { | |
int neighbor; | |
cout << "Enter the neighbor " << j + 1 << " for node " << i + 1 << ": "; | |
cin >> neighbor; | |
nodes[i].neighbors.push_back(neighbor); | |
} | |
} | |
nodes[0].visited = true; | |
bfs(nodes, 0); | |
cout << endl; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <stack> | |
#include <omp.h> | |
void parallelDFS(const std::vector<std::vector<int> >& graph, int startVertex, std::vector<bool>& visited) { | |
std::stack<int> dfsStack; | |
dfsStack.push(startVertex); | |
while (!dfsStack.empty()) { | |
int currentVertex = dfsStack.top(); | |
dfsStack.pop(); | |
if (!visited[currentVertex]) { | |
std::cout << "Visiting vertex: " << currentVertex << std::endl; | |
visited[currentVertex] = true; | |
#pragma omp parallel for num_threads(4) | |
for (int i = 0; i < graph[currentVertex].size(); ++i) { | |
int neighborVertex = graph[currentVertex][i]; | |
if (!visited[neighborVertex]) { | |
#pragma omp critical | |
dfsStack.push(neighborVertex); | |
} | |
} | |
} | |
} | |
} | |
int main() { | |
int numVertices; | |
std::cout << "Enter the number of vertices: "; | |
std::cin >> numVertices; | |
std::vector<std::vector<int> > graph(numVertices); | |
std::cout << "Enter the adjacency list for each vertex:\n"; | |
for (int i = 0; i < numVertices; ++i) { | |
int numNeighbors; | |
std::cout << "Enter the number of neighbors for vertex " << i << ": "; | |
std::cin >> numNeighbors; | |
std::cout << "Enter the neighbors for vertex " << i << ": "; | |
for (int j = 0; j < numNeighbors; ++j) { | |
int neighborVertex; | |
std::cin >> neighborVertex; | |
graph[i].push_back(neighborVertex); | |
} | |
} | |
int startVertex; | |
std::cout << "Enter the start vertex: "; | |
std::cin >> startVertex; | |
std::vector<bool> visited(numVertices, false); | |
#pragma omp parallel | |
{ | |
#pragma omp single | |
{ | |
parallelDFS(graph, startVertex, visited); | |
} | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <omp.h> | |
#define ARRAY_SIZE 1000 | |
int main() { | |
int array[ARRAY_SIZE]; | |
int min, max, sum; | |
double avg; | |
double start_time, end_time; | |
// Initialize the array with random values | |
for (int i = 0; i < ARRAY_SIZE; i++) { | |
array[i] = rand() % 1000; | |
} | |
// Initialize reduction variables | |
min = array[0]; | |
max = array[0]; | |
sum = 0; | |
// Start timing | |
start_time = omp_get_wtime(); | |
// Compute reduction using parallel reduction pragma | |
#pragma omp parallel for reduction(min:min) reduction(max:max) reduction(+:sum) | |
for (int i = 0; i < ARRAY_SIZE; i++) { | |
sum += array[i]; | |
if (array[i] < min) { | |
min = array[i]; | |
} | |
if (array[i] > max) { | |
max = array[i]; | |
} | |
} | |
// Compute average | |
avg = (double)sum / ARRAY_SIZE; | |
// End timing | |
end_time = omp_get_wtime(); | |
// Print the results | |
printf("Array: "); | |
for (int i = 0; i < ARRAY_SIZE; i++) { | |
printf("%d ", array[i]); | |
} | |
printf("\n"); | |
printf("Minimum: %d\n", min); | |
printf("Maximum: %d\n", max); | |
printf("Sum: %d\n", sum); | |
printf("Average: %.2f\n", avg); | |
printf("Execution time: %.6f seconds\n", end_time - start_time); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <omp.h> | |
#include <chrono> | |
using namespace std; | |
void bubbleSort(vector<int>& arr) { | |
int n = arr.size(); | |
#pragma omp parallel for | |
for (int i = 0; i < n - 1; i++) { | |
for (int j = 0; j < n - i - 1; j++) { | |
if (arr[j] > arr[j + 1]) { | |
int temp = arr[j]; | |
arr[j] = arr[j + 1]; | |
arr[j + 1] = temp; | |
} | |
} | |
} | |
} | |
int main() { | |
int n; | |
cout << "Enter the number of elements: "; | |
cin >> n; | |
vector<int> arr(n); | |
for (int i = 0; i < n; i++) { | |
cout << "Enter element " << i + 1 << ": "; | |
cin >> arr[i]; | |
} | |
cout << "Unsorted array: "; | |
for (int i = 0; i < n; i++) { | |
cout << arr[i] << " "; | |
} | |
cout << endl; | |
// Bubble sort. | |
cout << "Sequential bubble sort: "; | |
auto start = std::chrono::high_resolution_clock::now(); | |
bubbleSort(arr); | |
auto end = std::chrono::high_resolution_clock::now(); | |
std::chrono::duration<double> elapsed = end - start; | |
cout << elapsed.count() << " seconds" << endl; | |
cout << "Sorted array: "; | |
for (int i = 0; i < n; i++) { | |
cout << arr[i] << " "; | |
} | |
cout << endl; | |
// Parallel bubble sort. | |
cout << "Parallel bubble sort: "; | |
start = std::chrono::high_resolution_clock::now(); | |
#pragma omp parallel | |
bubbleSort(arr); | |
end = std::chrono::high_resolution_clock::now(); | |
elapsed = end - start; | |
cout << elapsed.count() << " seconds" << endl; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <omp.h> | |
#include <chrono> | |
using namespace std; | |
bool isSorted(const vector<int>& arr) { | |
int n = arr.size(); | |
for (int i = 1; i < n; i++) { | |
if (arr[i] < arr[i - 1]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
void merge(vector<int>& arr, int low, int mid, int high) { | |
int i = low; | |
int j = mid + 1; | |
vector<int> merged(high - low + 1); | |
for (int k = 0; k < merged.size(); k++) { | |
if (i > mid) { | |
merged[k] = arr[j++]; | |
} else if (j > high) { | |
merged[k] = arr[i++]; | |
} else if (arr[i] <= arr[j]) { | |
merged[k] = arr[i++]; | |
} else { | |
merged[k] = arr[j++]; | |
} | |
} | |
for (int k = 0; k < merged.size(); k++) { | |
arr[low + k] = merged[k]; | |
} | |
} | |
void mergeSort(vector<int>& arr, int low, int high) { | |
if (low < high) { | |
int mid = (low + high) / 2; | |
// Recursively sort the left and right halves. | |
mergeSort(arr, low, mid); | |
mergeSort(arr, mid + 1, high); | |
// Merge the sorted halves. | |
#pragma omp parallel | |
{ | |
#pragma omp for | |
for (int i = low; i <= high; i++) { | |
// Do nothing, just for parallelization. | |
} | |
merge(arr, low, mid, high); | |
} | |
} | |
} | |
int main() { | |
int n; | |
cout << "Enter the number of elements: "; | |
cin >> n; | |
vector<int> arr(n); | |
for (int i = 0; i < n; i++) { | |
cout << "Enter element " << i + 1 << ": "; | |
cin >> arr[i]; | |
} | |
cout << "Unsorted array: "; | |
for (int i = 0; i < n; i++) { | |
cout << arr[i] << " "; | |
} | |
cout << endl; | |
// Merge sort. | |
cout << "Sequential merge sort: "; | |
auto start = std::chrono::high_resolution_clock::now(); | |
mergeSort(arr, 0, n - 1); | |
auto end = std::chrono::high_resolution_clock::now(); | |
std::chrono::duration<double> elapsed = end - start; | |
cout << elapsed.count() << " seconds" << endl; | |
// Parallel merge sort. | |
cout << "Parallel merge sort: "; | |
start = std::chrono::high_resolution_clock::now(); | |
#pragma omp parallel | |
{ | |
#pragma omp single | |
mergeSort(arr, 0, n - 1); | |
} | |
end = std::chrono::high_resolution_clock::now(); | |
elapsed = end - start; | |
cout << elapsed.count() << " seconds" << endl; | |
cout << "Sorted array: "; | |
for (int i = 0; i < n; i++) { | |
cout << arr[i] << " "; | |
} | |
cout << endl; | |
// Check if the array is sorted. | |
if (isSorted(arr)) { | |
cout << "The array is sorted." << endl; | |
} else { | |
cout << "The array is not sorted." << endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment