From 0c3625c660ab713f434fb53cfa8fd849c0bc4bee Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 16 Apr 2025 09:44:46 +0200 Subject: [PATCH 01/24] feat: setup first introduction pgmds workshop Signed-off-by: jaapschoutenalliander --- power-grid-model-ds/introduction.ipynb | 567 +++++++++++++++++++++++++ 1 file changed, 567 insertions(+) create mode 100644 power-grid-model-ds/introduction.ipynb diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb new file mode 100644 index 0000000..5cb4243 --- /dev/null +++ b/power-grid-model-ds/introduction.ipynb @@ -0,0 +1,567 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e708f200", + "metadata": {}, + "source": [ + "# Hands-on Workshop: Extending and Modifying a Power Grid Model DS Grid\n", + "\n", + "## Introduction & Setup\n", + "Power Grid Model DS (PGM-DS) is an open-source Python toolkit for modeling electric power grids. It extends the core power-grid-model engine with a user-friendly interface for data science applications​. In PGM-DS, a power network is represented by a Grid dataclass that manages all network components (nodes, lines, transformers, loads, etc.) and ensures their consistency​.\n", + "\n", + "This library provides a graph-based representation of the network and an API to modify the network structure (e.g. adding or removing equipment), which is very useful for simulation studies​. In this workshop, you will perform a series of short exercises to get hands-on experience with two key features of PGM-DS:\n", + "- Extending a grid with custom properties – how to subclass PGM-DS data structures to add your own fields.\n", + "- Modifying a grid object – how to build and alter a grid (add nodes, lines, etc.) programmatically.\n", + "\n", + "We assume you are comfortable with Python and Jupyter notebooks. Before we begin, make sure you have PGM-DS installed:\n", + "\n", + "```bash\n", + "pip install power-grid-model-ds\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "fd2741c2", + "metadata": {}, + "outputs": [], + "source": [ + "# ⚙️ Setup\n", + "import numpy as np\n", + "from dataclasses import dataclass\n", + "\n", + "from power_grid_model_ds import Grid\n", + "from power_grid_model_ds.arrays import NodeArray, LineArray, SymLoadArray, SourceArray\n", + "from power_grid_model_ds.enums import NodeType\n", + "\n", + "# 📦 Extend the grid with x, y, u (node) and i_from (line)\n", + "from numpy.typing import NDArray" + ] + }, + { + "cell_type": "markdown", + "id": "b53605bc", + "metadata": {}, + "source": [ + "## Exercise 1: Extending the Grid with Custom Properties\n", + "Context: By default, the PGM-DS Grid includes standard attributes for each component (like node voltage ratings, line impedances, etc.). However, certain project-specific data (for example, simulation results or custom labels) are not included out of the box​. PGM-DS allows you to extend the grid data model by subclassing its array classes to add new columns. In other words, you can inherit the existing functionality and add your own fields​.\n", + "\n", + "In this exercise, we will extend the grid to include an output voltage u for nodes and an output current i_from for lines, which are not present in the basic grid.\n", + "\n", + "### Step 1: Define Extended Node and Line arrays\n", + "We create subclasses of NodeArray and LineArray that include the new properties. We'll call them MyNodeArray and MyLineArray. Each subclass defines a class attribute for the new column and (optionally) a default value for that column via a _defaults dictionary." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb5c7f4", + "metadata": {}, + "outputs": [], + "source": [ + "# ⚙️ Create two Array extensions to hold the x, y, u (extending NodeArray) and i_from (extending LineArray) attributes\n", + "# Hint: <>" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "bf5fec95", + "metadata": {}, + "outputs": [], + "source": [ + "class MyNodeArray(NodeArray):\n", + " _defaults = {\"x\": 0.0, \"y\": 0.0, \"u\": 0.0}\n", + " x: NDArray[np.float64]\n", + " y: NDArray[np.float64]\n", + " u: NDArray[np.float64]\n", + "\n", + "class MyLineArray(LineArray):\n", + " _defaults = {\"i_from\": 0.0}\n", + " i_from: NDArray[np.float64]" + ] + }, + { + "cell_type": "markdown", + "id": "8ef5b9fa", + "metadata": {}, + "source": [ + "### Step 2: Create an Extended Grid class\n", + "Now we'll integrate these new arrays into a custom Grid class. We do this by subclassing the PGM-DS Grid and specifying that our grid should use MyNodeArray and MyLineArray instead of the default NodeArray and LineArray. We'll use Python's dataclass to define the new Grid schema:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2da55398", + "metadata": {}, + "outputs": [], + "source": [ + "# ⚙️ Create a new grid class that uses the extended arrays\n", + "# Hint: <>" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "07cd9186", + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class ExtendedGrid(Grid):\n", + " node: MyNodeArray\n", + " line: MyLineArray" + ] + }, + { + "cell_type": "markdown", + "id": "75264a22", + "metadata": {}, + "source": [ + "This ExtendedGrid class inherits all the behavior of Grid but with our extended node and line definitions​. Essentially, we've informed the Grid that whenever it creates or manipulates the node or line arrays, it should use the extended versions that include the extra columns." + ] + }, + { + "cell_type": "markdown", + "id": "430f88b5", + "metadata": {}, + "source": [ + "### Step 3: Initialize an Extended Grid\n", + "With the classes defined, let's create an instance of our extended grid. PGM-DS provides a convenient class method Grid.empty() to initialize an empty grid. We'll call this on our ExtendedGrid:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c6040e5b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ExtendedGrid(_id_counter=0, graphs=GraphContainer(active_graph=, complete_graph=), node=MyNodeArray([[]]), transformer=TransformerArray([[]]), three_winding_transformer=ThreeWindingTransformerArray([[]]), line=MyLineArray([[]]), link=LinkArray([[]]), source=SourceArray([[]]), sym_load=SymLoadArray([[]]), sym_gen=SymGenArray([[]]), transformer_tap_regulator=TransformerTapRegulatorArray([[]]), sym_power_sensor=SymPowerSensorArray([[]]), sym_voltage_sensor=SymVoltageSensorArray([[]]), asym_voltage_sensor=AsymVoltageSensorArray([[]]))" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Instantiate an empty extended grid\n", + "grid = ExtendedGrid.empty()\n", + "grid" + ] + }, + { + "cell_type": "markdown", + "id": "06983bc4", + "metadata": {}, + "source": [ + "Verification: To ensure our extended properties exist, you can access the new attributes:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ee1afd73", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Node 'u' field exists? True\n", + "Line 'i_from' field exists? True\n" + ] + } + ], + "source": [ + "print(\"Node 'u' field exists?\", hasattr(grid.node, \"u\"))\n", + "print(\"Line 'i_from' field exists?\", hasattr(grid.line, \"i_from\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "19df772e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Node array: id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", + "\n" + ] + } + ], + "source": [ + "print(\"Node array:\", grid.node)" + ] + }, + { + "cell_type": "markdown", + "id": "7eb8b79f", + "metadata": {}, + "source": [ + "Since we haven't added any nodes or lines yet, these arrays are empty" + ] + }, + { + "cell_type": "markdown", + "id": "c0b7b9e7", + "metadata": {}, + "source": [ + "## Exercise 2: Building and Modifying the Grid Structure\n", + "\n", + "Context: The Grid object allows you to add, remove, and manipulate grid components in-memory. We will now construct a simple network step-by-step using our ext_grid. This will demonstrate how to modify a grid object by adding nodes and branches. In practice, you can start with an empty grid and programmatically add substations, lines, transformers, loads, sources, etc., as needed​. We will create a minimal example with two nodes (a source node and a load node) connected by a line, and verify that the grid is updated accordingly. (For brevity, we'll use a very small grid, but the same methods apply to larger networks.)\n", + "\n", + "Note: PGM-DS typically distinguishes node types (e.g., substation vs. regular node) and requires unique IDs for each element. We will manually specify IDs for clarity. The library’s Grid.append() method will be used to add new component records to the grid​.\n" + ] + }, + { + "cell_type": "markdown", + "id": "6b2d3489", + "metadata": {}, + "source": [ + "### Step 1: Add a substation node\n", + "First, let's add a substation node to the grid. We create an MyNodeArray with one entry representing the substation. We need to provide at least an id, a rated voltage (u_rated), and a node type.\n", + "We will use the enum NodeType.SUBSTATION_NODE for the type.\n", + "In this example, we will assign the substation an ID of 101 and a rated voltage of 10500.0 (which could represent 10.5 kV):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c03c85f4", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a substation node entry\n", + "substation_node = MyNodeArray(\n", + " id=[101],\n", + " u_rated=[10500.0], # e.g., 10.5 kV base voltage\n", + " node_type=[NodeType.SUBSTATION_NODE.value] # type = 1 (Substation node)\n", + ")\n", + "# Append this node to the grid\n", + "grid.append(substation_node, check_max_id=False)" + ] + }, + { + "cell_type": "markdown", + "id": "91ca3ea2", + "metadata": {}, + "source": [ + "Here we constructed a MyNodeArray with one record and then appended it to grid. We set check_max_id=False to disable internal ID checks since we're manually managing IDs in this exercise. After running this, the grid now contains one node. Verification: Check that the node was added. For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "8695367f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nodes in the grid:\n", + " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", + " 101 | 10500.0 | 1 | -2147483648 | -2147483648 | 0.0 | 0.0 | 0.0 \n" + ] + } + ], + "source": [ + "print(\"Nodes in the grid:\")\n", + "print(grid.node)" + ] + }, + { + "cell_type": "markdown", + "id": "88cd0bb5", + "metadata": {}, + "source": [ + "### Step 2: Add a second node\n", + "Next, we'll add another node to represent a load or another bus in the grid. This node will be of a generic type (we'll use NodeType.UNSPECIFIED, which equals 0 in the enum). We'll give it an ID of 102 and the same base voltage (10.5 kV):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "780b1c35", + "metadata": {}, + "outputs": [], + "source": [ + "# Create another node\n", + "load_node = MyNodeArray(\n", + " id=[102],\n", + " u_rated=[10500.0],\n", + " node_type=[NodeType.UNSPECIFIED.value]\n", + ")\n", + "grid.append(load_node, check_max_id=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "3791cef2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nodes in the grid:\n", + " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", + " 101 | 10500.0 | 1 | -2147483648 | -2147483648 | 0.0 | 0.0 | 0.0 \n", + " 102 | 10500.0 | 0 | -2147483648 | -2147483648 | 0.0 | 0.0 | 0.0 \n" + ] + } + ], + "source": [ + "print(\"Nodes in the grid:\")\n", + "print(grid.node)" + ] + }, + { + "cell_type": "markdown", + "id": "a6f17195", + "metadata": {}, + "source": [ + "### Step 3: Add a line connecting the two nodes\n", + "Now that we have two nodes, we will connect them with a line. We'll use our MyLineArray to create a single line record. We need to specify an ID for the line (let's use 201), the from_node and to_node it connects (101 to 102), and statuses to indicate the line is active. We should also provide line electrical parameters (resistance, reactance, etc.) – we'll use some placeholder values here for demonstration:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4baa9b6", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a line between node 101 and 102\n", + "new_line = MyLineArray(\n", + " id=[201],\n", + " from_node=[101],\n", + " to_node=[102],\n", + " from_status=[1], # 1 = active from-side, \n", + " to_status=[1], # 1 = active to-side (both ends active)\n", + " i_n=[200.0], # line current capacity (e.g., 200 A)\n", + " r1=[0.1], x1=[0.03], # line resistance and reactance\n", + " c1=[0.0], tan1=[0.0] # line capacitance and loss tangent (0 for simplicity)\n", + ")\n", + "grid.append(new_line, check_max_id=False)" + ] + }, + { + "cell_type": "markdown", + "id": "fa1e3f2f", + "metadata": {}, + "source": [ + "This adds a line (ID 201) connecting node 101 to 102. We marked the line as active by setting both from_status and to_status to 1. We also provided some dummy impedance values. The approach of constructing a LineArray (or in our case, MyLineArray) with the necessary fields and appending it to the grid is shown in the official examples​. Verification: Check that the line was added to the grid:" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "e2914592", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", + " 201 | 101 | 102 | 1 | 1 | -2147483648 | -2147483648 | False | 0.1 | 0.03 | 0.0 | 0.0 | 200.0 | 0.0 \n" + ] + } + ], + "source": [ + "print(grid.line)" + ] + }, + { + "cell_type": "markdown", + "id": "f7a5bc49", + "metadata": {}, + "source": [ + "### Step 4: Add a load to the second node\n", + "We'll now add a load connected to node 102. PGM-DS uses a SymLoadArray for symmetrical loads. We will create a single load with an ID of 401 at node 102. We need to specify the node it is attached to, a load type code (we'll use 1 for a basic load type), the specified active (p_specified) and reactive (q_specified) power (let's say 1e6 each, representing 1 MW and 1 Mvar for example), and set its status to active (1):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ddd3445c", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a load at node 102\n", + "load = SymLoadArray(\n", + " id=[401],\n", + " node=[102],\n", + " type=[1], # load type (e.g., 1 for constant power load)\n", + " p_specified=[1_000_000.0], # 1e6 W = 1 MW\n", + " q_specified=[1_000_000.0], # 1e6 VAR\n", + " status=[1] # active\n", + ")\n", + "grid.append(load, check_max_id=False)" + ] + }, + { + "cell_type": "markdown", + "id": "972efb50", + "metadata": {}, + "source": [ + "This adds one load to node 102. In practice, adding loads ensures that node 102 will be consuming power in any simulation. Verification: Check that the load appears in the grid:" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "a6e900eb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | node | status | type | p_specified | q_specified \n", + " 401 | 102 | 1 | 1 | 1000000.0 | 1000000.0 \n" + ] + } + ], + "source": [ + "print(grid.sym_load)" + ] + }, + { + "cell_type": "markdown", + "id": "da53ba14", + "metadata": {}, + "source": [ + "### Step 5: Add a source to the substation node\n", + "Finally, we'll add a power source to supply the grid at the substation (node 101). We'll use SourceArray for this. We'll create a source with ID 501 at node 101, status active (1), and set a reference voltage u_ref. Typically, u_ref might be the slack/reference voltage magnitude or angle; we'll use 0.0 as a reference angle (assuming the default usage):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e741dec4", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a source at node 101\n", + "source = SourceArray(\n", + " id=[501],\n", + " node=[101],\n", + " status=[1],\n", + " u_ref=[0.0] # reference voltage or angle (0.0 as a placeholder)\n", + ")\n", + "grid.append(source, check_max_id=False)" + ] + }, + { + "cell_type": "markdown", + "id": "bda9752e", + "metadata": {}, + "source": [ + "This adds a source (e.g., a generator or slack source) at node 101, so the grid now has a supply. Verification: Check the source:" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "3047ecf6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | node | status | u_ref \n", + " 501 | 101 | 1 | 0.0 \n" + ] + } + ], + "source": [ + "print(grid.source)" + ] + }, + { + "cell_type": "markdown", + "id": "e5e6eb1b", + "metadata": {}, + "source": [ + "You should see [501] as the source ID and [101] as the node, indicating the source is at node 101. The count of sources should be 1. Now we have built a simple grid with 2 nodes (101 and 102), 1 line connecting them, 1 load at node 102, and 1 source at node 101. It's good practice to ensure all IDs are unique and there are no inconsistencies. PGM-DS provides a method grid.check_ids() to validate this​" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "b756a4d5", + "metadata": {}, + "outputs": [], + "source": [ + "grid.check_ids()" + ] + }, + { + "cell_type": "markdown", + "id": "26f831f3", + "metadata": {}, + "source": [ + "If everything is correct, this should execute without errors (it will raise an exception if any duplicate or conflicting IDs were found). We expect no issues since we chose unique IDs for each element type. For a final summary, let's print out the contents of our grid's key components:" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "c94ab378", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nodes: [101 102]\n", + "Lines: [201]\n", + "Loads: [401]\n", + "Sources: [501]\n" + ] + } + ], + "source": [ + "print(\"Nodes:\", grid.node.id) # Expect [101 102]\n", + "print(\"Lines:\", grid.line.id) # Expect [201]\n", + "print(\"Loads:\", grid.sym_load.id) # Expect [401]\n", + "print(\"Sources:\", grid.source.id) # Expect [501]\n" + ] + } + ], + "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.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 495ebf4f7b20b11181bafd4b23943fd3a3278390 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 16 Apr 2025 09:51:28 +0200 Subject: [PATCH 02/24] feat: setup first introduction pgmds workshop Signed-off-by: jaapschoutenalliander --- power-grid-model-ds/introduction.ipynb | 150 +++--------------- ...ntroduction_1_1_define_array_extensions.py | 9 ++ 2 files changed, 32 insertions(+), 127 deletions(-) create mode 100644 power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb index 5cb4243..ea50fab 100644 --- a/power-grid-model-ds/introduction.ipynb +++ b/power-grid-model-ds/introduction.ipynb @@ -23,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "id": "fd2741c2", "metadata": {}, "outputs": [], @@ -62,25 +62,9 @@ "outputs": [], "source": [ "# ⚙️ Create two Array extensions to hold the x, y, u (extending NodeArray) and i_from (extending LineArray) attributes\n", - "# Hint: <>" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "bf5fec95", - "metadata": {}, - "outputs": [], - "source": [ - "class MyNodeArray(NodeArray):\n", - " _defaults = {\"x\": 0.0, \"y\": 0.0, \"u\": 0.0}\n", - " x: NDArray[np.float64]\n", - " y: NDArray[np.float64]\n", - " u: NDArray[np.float64]\n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html\n", "\n", - "class MyLineArray(LineArray):\n", - " _defaults = {\"i_from\": 0.0}\n", - " i_from: NDArray[np.float64]" + "# %load solutions/introduction_1_1_define_array_extensions.py" ] }, { @@ -105,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "07cd9186", "metadata": {}, "outputs": [], @@ -135,21 +119,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "c6040e5b", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "ExtendedGrid(_id_counter=0, graphs=GraphContainer(active_graph=, complete_graph=), node=MyNodeArray([[]]), transformer=TransformerArray([[]]), three_winding_transformer=ThreeWindingTransformerArray([[]]), line=MyLineArray([[]]), link=LinkArray([[]]), source=SourceArray([[]]), sym_load=SymLoadArray([[]]), sym_gen=SymGenArray([[]]), transformer_tap_regulator=TransformerTapRegulatorArray([[]]), sym_power_sensor=SymPowerSensorArray([[]]), sym_voltage_sensor=SymVoltageSensorArray([[]]), asym_voltage_sensor=AsymVoltageSensorArray([[]]))" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Instantiate an empty extended grid\n", "grid = ExtendedGrid.empty()\n", @@ -166,19 +139,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "ee1afd73", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node 'u' field exists? True\n", - "Line 'i_from' field exists? True\n" - ] - } - ], + "outputs": [], "source": [ "print(\"Node 'u' field exists?\", hasattr(grid.node, \"u\"))\n", "print(\"Line 'i_from' field exists?\", hasattr(grid.line, \"i_from\"))" @@ -186,19 +150,10 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "19df772e", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node array: id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", - "\n" - ] - } - ], + "outputs": [], "source": [ "print(\"Node array:\", grid.node)" ] @@ -261,20 +216,10 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "id": "8695367f", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Nodes in the grid:\n", - " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", - " 101 | 10500.0 | 1 | -2147483648 | -2147483648 | 0.0 | 0.0 | 0.0 \n" - ] - } - ], + "outputs": [], "source": [ "print(\"Nodes in the grid:\")\n", "print(grid.node)" @@ -307,21 +252,10 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "id": "3791cef2", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Nodes in the grid:\n", - " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", - " 101 | 10500.0 | 1 | -2147483648 | -2147483648 | 0.0 | 0.0 | 0.0 \n", - " 102 | 10500.0 | 0 | -2147483648 | -2147483648 | 0.0 | 0.0 | 0.0 \n" - ] - } - ], + "outputs": [], "source": [ "print(\"Nodes in the grid:\")\n", "print(grid.node)" @@ -367,19 +301,10 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "id": "e2914592", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", - " 201 | 101 | 102 | 1 | 1 | -2147483648 | -2147483648 | False | 0.1 | 0.03 | 0.0 | 0.0 | 200.0 | 0.0 \n" - ] - } - ], + "outputs": [], "source": [ "print(grid.line)" ] @@ -422,19 +347,10 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "id": "a6e900eb", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | node | status | type | p_specified | q_specified \n", - " 401 | 102 | 1 | 1 | 1000000.0 | 1000000.0 \n" - ] - } - ], + "outputs": [], "source": [ "print(grid.sym_load)" ] @@ -475,19 +391,10 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "id": "3047ecf6", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | node | status | u_ref \n", - " 501 | 101 | 1 | 0.0 \n" - ] - } - ], + "outputs": [], "source": [ "print(grid.source)" ] @@ -502,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": null, "id": "b756a4d5", "metadata": {}, "outputs": [], @@ -520,21 +427,10 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": null, "id": "c94ab378", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Nodes: [101 102]\n", - "Lines: [201]\n", - "Loads: [401]\n", - "Sources: [501]\n" - ] - } - ], + "outputs": [], "source": [ "print(\"Nodes:\", grid.node.id) # Expect [101 102]\n", "print(\"Lines:\", grid.line.id) # Expect [201]\n", diff --git a/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py b/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py new file mode 100644 index 0000000..90bb9b8 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py @@ -0,0 +1,9 @@ +class MyNodeArray(NodeArray): + _defaults = {"x": 0.0, "y": 0.0, "u": 0.0} + x: NDArray[np.float64] + y: NDArray[np.float64] + u: NDArray[np.float64] + +class MyLineArray(LineArray): + _defaults = {"i_from": 0.0} + i_from: NDArray[np.float64] \ No newline at end of file From 1f0494f9dfed08f16080302cc2eee3ccfd8585c5 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 30 Apr 2025 18:51:34 +0200 Subject: [PATCH 03/24] chore: setup solution files Signed-off-by: jaapschoutenalliander --- power-grid-model-ds/introduction.ipynb | 115 ++++++------------ .../introduction_1_2_define_my_grid.py | 4 + .../solutions/introduction_1_3_grid_empty.py | 2 + .../introduction_1_3_grid_verification.py | 3 + .../introduction_2_1_add_substation.py | 8 ++ .../solutions/introduction_2_2_add_node.py | 7 ++ .../solutions/introduction_2_3_add_line.py | 12 ++ .../solutions/introduction_2_4_add_load.py | 10 ++ .../solutions/introduction_2_5_add_source.py | 8 ++ .../solutions/introduction_2_6_check_ids.py | 1 + 10 files changed, 92 insertions(+), 78 deletions(-) create mode 100644 power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py create mode 100644 power-grid-model-ds/solutions/introduction_1_3_grid_empty.py create mode 100644 power-grid-model-ds/solutions/introduction_1_3_grid_verification.py create mode 100644 power-grid-model-ds/solutions/introduction_2_1_add_substation.py create mode 100644 power-grid-model-ds/solutions/introduction_2_2_add_node.py create mode 100644 power-grid-model-ds/solutions/introduction_2_3_add_line.py create mode 100644 power-grid-model-ds/solutions/introduction_2_4_add_load.py create mode 100644 power-grid-model-ds/solutions/introduction_2_5_add_source.py create mode 100644 power-grid-model-ds/solutions/introduction_2_6_check_ids.py diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb index ea50fab..9711b60 100644 --- a/power-grid-model-ds/introduction.ipynb +++ b/power-grid-model-ds/introduction.ipynb @@ -36,7 +36,6 @@ "from power_grid_model_ds.arrays import NodeArray, LineArray, SymLoadArray, SourceArray\n", "from power_grid_model_ds.enums import NodeType\n", "\n", - "# 📦 Extend the grid with x, y, u (node) and i_from (line)\n", "from numpy.typing import NDArray" ] }, @@ -64,7 +63,7 @@ "# ⚙️ Create two Array extensions to hold the x, y, u (extending NodeArray) and i_from (extending LineArray) attributes\n", "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html\n", "\n", - "# %load solutions/introduction_1_1_define_array_extensions.py" + "# %load solutions/introduction_1_1_define_array_extensions" ] }, { @@ -84,20 +83,9 @@ "outputs": [], "source": [ "# ⚙️ Create a new grid class that uses the extended arrays\n", - "# Hint: <>" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07cd9186", - "metadata": {}, - "outputs": [], - "source": [ - "@dataclass\n", - "class ExtendedGrid(Grid):\n", - " node: MyNodeArray\n", - " line: MyLineArray" + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html\n", + "\n", + "# %load solutions/introduction_1_2_define_my_grid" ] }, { @@ -124,9 +112,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Instantiate an empty extended grid\n", - "grid = ExtendedGrid.empty()\n", - "grid" + "# ⚙️ Instantiate an empty extended grid\n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#creating-an-empty-grid\n", + "\n", + "# %load solutions/introduction_1_3_grid_empty" ] }, { @@ -144,18 +133,10 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"Node 'u' field exists?\", hasattr(grid.node, \"u\"))\n", - "print(\"Line 'i_from' field exists?\", hasattr(grid.line, \"i_from\"))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19df772e", - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Node array:\", grid.node)" + "# ⚙️ Print some information about the grid\n", + "# Hint: be creative! You can use the grid's attributes and methods to get information about the grid.\n", + "\n", + "# %load solutions/introduction_1_3_grid_verification" ] }, { @@ -196,14 +177,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Create a substation node entry\n", - "substation_node = MyNodeArray(\n", - " id=[101],\n", - " u_rated=[10500.0], # e.g., 10.5 kV base voltage\n", - " node_type=[NodeType.SUBSTATION_NODE.value] # type = 1 (Substation node)\n", - ")\n", - "# Append this node to the grid\n", - "grid.append(substation_node, check_max_id=False)" + "# ⚙️ Add a substation to the grid\n", + "# Hint: \n", + "\n", + "# %load solutions/introduction_2_1_add_substation" ] }, { @@ -241,13 +218,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Create another node\n", - "load_node = MyNodeArray(\n", - " id=[102],\n", - " u_rated=[10500.0],\n", - " node_type=[NodeType.UNSPECIFIED.value]\n", - ")\n", - "grid.append(load_node, check_max_id=False)" + "# ⚙️ Add a node to the grid\n", + "# Hint: \n", + "\n", + "# %load solutions/introduction_2_1_add_substation" ] }, { @@ -277,18 +251,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Create a line between node 101 and 102\n", - "new_line = MyLineArray(\n", - " id=[201],\n", - " from_node=[101],\n", - " to_node=[102],\n", - " from_status=[1], # 1 = active from-side, \n", - " to_status=[1], # 1 = active to-side (both ends active)\n", - " i_n=[200.0], # line current capacity (e.g., 200 A)\n", - " r1=[0.1], x1=[0.03], # line resistance and reactance\n", - " c1=[0.0], tan1=[0.0] # line capacitance and loss tangent (0 for simplicity)\n", - ")\n", - "grid.append(new_line, check_max_id=False)" + "# ⚙️ Add a line to the grid\n", + "# Hint: \n", + "\n", + "# %load solutions/introduction_2_3_add_line" ] }, { @@ -325,16 +291,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Create a load at node 102\n", - "load = SymLoadArray(\n", - " id=[401],\n", - " node=[102],\n", - " type=[1], # load type (e.g., 1 for constant power load)\n", - " p_specified=[1_000_000.0], # 1e6 W = 1 MW\n", - " q_specified=[1_000_000.0], # 1e6 VAR\n", - " status=[1] # active\n", - ")\n", - "grid.append(load, check_max_id=False)" + "# ⚙️ Add a load to the grid\n", + "# Hint: \n", + "\n", + "# %load solutions/introduction_2_4_add_load" ] }, { @@ -371,14 +331,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Create a source at node 101\n", - "source = SourceArray(\n", - " id=[501],\n", - " node=[101],\n", - " status=[1],\n", - " u_ref=[0.0] # reference voltage or angle (0.0 as a placeholder)\n", - ")\n", - "grid.append(source, check_max_id=False)" + "# ⚙️ Add a source to the grid\n", + "# Hint: \n", + "\n", + "# %load solutions/introduction_2_5_add_source" ] }, { @@ -414,7 +370,10 @@ "metadata": {}, "outputs": [], "source": [ - "grid.check_ids()" + "# ⚙️ Check whether all IDs are correct\n", + "# Hint: \n", + "\n", + "# %load solutions/introduction_2_6_check_ids" ] }, { @@ -435,7 +394,7 @@ "print(\"Nodes:\", grid.node.id) # Expect [101 102]\n", "print(\"Lines:\", grid.line.id) # Expect [201]\n", "print(\"Loads:\", grid.sym_load.id) # Expect [401]\n", - "print(\"Sources:\", grid.source.id) # Expect [501]\n" + "print(\"Sources:\", grid.source.id) # Expect [501]" ] } ], diff --git a/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py b/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py new file mode 100644 index 0000000..1123da4 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py @@ -0,0 +1,4 @@ +@dataclass +class ExtendedGrid(Grid): + node: MyNodeArray + line: MyLineArray \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py b/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py new file mode 100644 index 0000000..598b800 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py @@ -0,0 +1,2 @@ +grid = ExtendedGrid.empty() +grid \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py b/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py new file mode 100644 index 0000000..f1a0cb3 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py @@ -0,0 +1,3 @@ +print("Node 'u' field exists?", hasattr(grid.node, "u")) +print("Line 'i_from' field exists?", hasattr(grid.line, "i_from")) +print("Node array:", grid.node) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_1_add_substation.py b/power-grid-model-ds/solutions/introduction_2_1_add_substation.py new file mode 100644 index 0000000..3d8f28a --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_2_1_add_substation.py @@ -0,0 +1,8 @@ +# Create a substation node entry +substation_node = MyNodeArray( + id=[101], + u_rated=[10500.0], # e.g., 10.5 kV base voltage + node_type=[NodeType.SUBSTATION_NODE.value] # type = 1 (Substation node) +) +# Append this node to the grid +grid.append(substation_node, check_max_id=False) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_2_add_node.py b/power-grid-model-ds/solutions/introduction_2_2_add_node.py new file mode 100644 index 0000000..78a33dc --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_2_2_add_node.py @@ -0,0 +1,7 @@ +# Create another node +load_node = MyNodeArray( + id=[102], + u_rated=[10500.0], + node_type=[NodeType.UNSPECIFIED.value] +) +grid.append(load_node, check_max_id=False) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_3_add_line.py b/power-grid-model-ds/solutions/introduction_2_3_add_line.py new file mode 100644 index 0000000..fa6fdc4 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_2_3_add_line.py @@ -0,0 +1,12 @@ +# Create a line between node 101 and 102 +new_line = MyLineArray( + id=[201], + from_node=[101], + to_node=[102], + from_status=[1], # 1 = active from-side, + to_status=[1], # 1 = active to-side (both ends active) + i_n=[200.0], # line current capacity (e.g., 200 A) + r1=[0.1], x1=[0.03], # line resistance and reactance + c1=[0.0], tan1=[0.0] # line capacitance and loss tangent (0 for simplicity) +) +grid.append(new_line, check_max_id=False) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_4_add_load.py b/power-grid-model-ds/solutions/introduction_2_4_add_load.py new file mode 100644 index 0000000..b7d45c9 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_2_4_add_load.py @@ -0,0 +1,10 @@ +# Create a load at node 102 +load = SymLoadArray( + id=[401], + node=[102], + type=[1], # load type (e.g., 1 for constant power load) + p_specified=[1_000_000.0], # 1e6 W = 1 MW + q_specified=[1_000_000.0], # 1e6 VAR + status=[1] # active +) +grid.append(load, check_max_id=False) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_5_add_source.py b/power-grid-model-ds/solutions/introduction_2_5_add_source.py new file mode 100644 index 0000000..e27e4d3 --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_2_5_add_source.py @@ -0,0 +1,8 @@ +# Create a source at node 101 +source = SourceArray( + id=[501], + node=[101], + status=[1], + u_ref=[0.0] # reference voltage or angle (0.0 as a placeholder) +) +grid.append(source, check_max_id=False) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_6_check_ids.py b/power-grid-model-ds/solutions/introduction_2_6_check_ids.py new file mode 100644 index 0000000..a457c3d --- /dev/null +++ b/power-grid-model-ds/solutions/introduction_2_6_check_ids.py @@ -0,0 +1 @@ +grid.check_ids() \ No newline at end of file From a7c69f1de542b95838fb0441b78e25523a6513e4 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 1 May 2025 08:39:07 +0200 Subject: [PATCH 04/24] feat: draft advanced workshop --- power-grid-model-ds/advanced.ipynb | 439 +++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 power-grid-model-ds/advanced.ipynb diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb new file mode 100644 index 0000000..69ada4f --- /dev/null +++ b/power-grid-model-ds/advanced.ipynb @@ -0,0 +1,439 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "59d49e29", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" + ] + } + ], + "source": [ + "!pip install power-grid-model-ds[visualizer] --quiet" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cf475775", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from dataclasses import dataclass\n", + "from power_grid_model_ds import Grid, GraphContainer\n", + "from power_grid_model_ds.arrays import NodeArray, LineArray\n", + "from power_grid_model_ds.enums import NodeType" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "37f4bd29", + "metadata": {}, + "outputs": [], + "source": [ + "# 📦 Extend the grid with x, y, u (node) and i_from (line)\n", + "from numpy.typing import NDArray\n", + "\n", + "class MyNodeArray(NodeArray):\n", + " _defaults = {\"x\": 0.0, \"y\": 0.0, \"u\": 0.0}\n", + " x: NDArray[np.float64]\n", + " y: NDArray[np.float64]\n", + " u: NDArray[np.float64]\n", + "\n", + "class MyLineArray(LineArray):\n", + " _defaults = {\"i_from\": 0.0}\n", + " i_from: NDArray[np.float64]\n", + "\n", + " @property\n", + " def is_overloaded(self) -> NDArray[np.bool_]:\n", + " \"\"\"Check if the line is overloaded.\"\"\"\n", + " return self.i_from > self.i_n\n", + "\n", + "@dataclass\n", + "class MyGrid(Grid):\n", + " node: MyNodeArray\n", + " line: MyLineArray\n", + " graphs: GraphContainer" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "78d0639e", + "metadata": {}, + "outputs": [], + "source": [ + "from power_grid_model_ds.generators import RadialGridGenerator\n", + "\n", + "# Generate a radial grid\n", + "grid_gen = RadialGridGenerator(grid_class=MyGrid, nr_nodes=20, nr_sources=1)\n", + "grid = grid_gen.run(seed=42)\n", + "\n", + "np.random.seed(42)\n", + "num_nodes = grid.node.size\n", + "x_coords = np.random.randint(0, 1000, size=num_nodes)\n", + "y_coords = np.random.randint(0, 1000, size=num_nodes)\n", + "\n", + "grid.node.x = x_coords\n", + "grid.node.y = y_coords" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "01f369f7", + "metadata": {}, + "outputs": [], + "source": [ + "grid.sym_load.p_specified = np.random.randint(300000, 1200000, size=grid.sym_load.size)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a375a3f8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", + " 1 | 10500.0 | 0 | 81 | 61 | 102.0 | 308.0 | 0.0 \n", + " 2 | 10500.0 | 0 | 63 | 61 | 435.0 | 769.0 | 0.0 \n", + " 3 | 10500.0 | 0 | 63 | 61 | 860.0 | 343.0 | 0.0 \n", + " 4 | 10500.0 | 0 | 66 | 61 | 270.0 | 491.0 | 0.0 \n", + " 5 | 10500.0 | 0 | 73 | 61 | 106.0 | 413.0 | 0.0 \n", + " (..11 hidden rows..) \n", + " 17 | 10500.0 | 0 | 63 | 61 | 99.0 | 856.0 | 0.0 \n", + " 18 | 10500.0 | 0 | 63 | 61 | 871.0 | 560.0 | 0.0 \n", + " 19 | 10500.0 | 0 | 73 | 61 | 663.0 | 474.0 | 0.0 \n", + " 20 | 10500.0 | 0 | 63 | 61 | 130.0 | 58.0 | 0.0 \n", + " 61 | 10500.0 | 1 | -2147483648 | -2147483648 | 661.0 | 510.0 | 0.0 \n" + ] + } + ], + "source": [ + "grid.set_feeder_ids()\n", + "print(grid.node)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "206be67b", + "metadata": {}, + "outputs": [], + "source": [ + "from power_grid_model_ds import PowerGridModelInterface\n", + "\n", + "pgm_interface = PowerGridModelInterface(grid)\n", + "pgm_interface.calculate_power_flow()\n", + "pgm_interface.update_grid()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "38a7dfae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", + " 61 | 10500.0 | 1 | -2147483648 | -2147483648 | 661.0 | 510.0 |10498.658..\n" + ] + } + ], + "source": [ + "old_sub = grid.node.filter(node_type=NodeType.SUBSTATION_NODE)\n", + "print(old_sub)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ae5d93b7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "All node IDs and coordinates:\n", + "ID: 1 - (102.0, 308.0)\n", + "ID: 2 - (435.0, 769.0)\n", + "ID: 3 - (860.0, 343.0)\n", + "ID: 4 - (270.0, 491.0)\n", + "ID: 5 - (106.0, 413.0)\n", + "ID: 6 - (71.0, 805.0)\n", + "ID: 7 - (700.0, 385.0)\n", + "ID: 8 - (20.0, 191.0)\n", + "ID: 9 - (614.0, 955.0)\n", + "ID: 10 - (121.0, 276.0)\n", + "ID: 11 - (466.0, 160.0)\n", + "ID: 12 - (214.0, 459.0)\n", + "ID: 13 - (330.0, 313.0)\n", + "ID: 14 - (458.0, 21.0)\n", + "ID: 15 - (87.0, 252.0)\n", + "ID: 16 - (372.0, 747.0)\n", + "ID: 17 - (99.0, 856.0)\n", + "ID: 18 - (871.0, 560.0)\n", + "ID: 19 - (663.0, 474.0)\n", + "ID: 20 - (130.0, 58.0)\n", + "ID: 61 - (661.0, 510.0)\n", + "ID: 93 - (212.0, 133.0)\n" + ] + } + ], + "source": [ + "# 🏗️ Add a new substation at (212, 133)\n", + "new_sub = MyNodeArray(\n", + " node_type=[NodeType.SUBSTATION_NODE.value],\n", + " u_rated=[10500.0],\n", + " x=[212],\n", + " y=[133]\n", + ")\n", + "grid.append(new_sub)\n", + "new_id = new_sub.id\n", + "\n", + "print(\"\\nAll node IDs and coordinates:\")\n", + "for i in range(len(grid.node)):\n", + " print(f\"ID: {grid.node.id[i]} - ({grid.node.x[i]}, {grid.node.y[i]})\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8be6c8f5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# visualize the grid\n", + "# TODO: Link some good first issues for the visualizer\n", + "\n", + "from power_grid_model_ds.visualizer import visualize\n", + "visualize(grid)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7d9378b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", + " 67 | 2 | 14 | 1 | 1 | 63 | 61 | False |0.180..|0.008..| 0.0 | 0.0 |163.035..|380.959..\n", + " 70 | 14 | 18 | 1 | 1 | 63 | 61 | False |0.077..|0.025..| 0.0 | 0.0 |237.064..|250.859..\n", + "Closest node in overload path to new substation: 10\n" + ] + } + ], + "source": [ + "# 📍 Identify a route with an overload\n", + "print(grid.line[grid.line.is_overloaded])\n", + "\n", + "overloaded_line = grid.line[grid.line.is_overloaded][0]\n", + "overloaded_nodes = grid.node.filter(feeder_branch_id=overloaded_line.feeder_branch_id)\n", + "\n", + "# 🔎 Find closest node in the overloaded route to the new substation\n", + "pos_new = np.array([new_sub.x, new_sub.y])\n", + "closest_node = min(\n", + " overloaded_nodes.id,\n", + " key=lambda nid: np.linalg.norm(pos_new - np.array([\n", + " grid.node.x[grid.node.id == nid][0],\n", + " grid.node.y[grid.node.id == nid][0]\n", + " ]))\n", + ")\n", + "print(f\"Closest node in overload path to new substation: {closest_node}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "b57104f4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected new substation to node 10\n" + ] + } + ], + "source": [ + "# Add a connection from the new substation to its closest node\n", + "all_nodes_except_new = grid.node.id[grid.node.id != new_id]\n", + "distances = [\n", + " (nid, np.linalg.norm(pos_new - np.array([\n", + " grid.node.x[grid.node.id == nid][0],\n", + " grid.node.y[grid.node.id == nid][0]\n", + " ])))\n", + " for nid in all_nodes_except_new\n", + "]\n", + "\n", + "closest_existing_node = sorted(distances, key=lambda x: x[1])[0][0]\n", + "\n", + "grid.append(MyLineArray(\n", + " from_node=[new_id],\n", + " to_node=[closest_existing_node],\n", + " from_status=[1],\n", + " to_status=[1],\n", + " i_n=[200.0],\n", + " r1=[0.05], x1=[0.01], c1=[0.0], tan1=[0.0]\n", + "))\n", + "\n", + "print(f\"Connected new substation to node {closest_existing_node}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "6a2afb10", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Path from overload to old substation: [10, 17, 14, 2, np.int32(61)]\n" + ] + } + ], + "source": [ + "# 🔗 Trace path from that node to the current (old) substation\n", + "path, length = grid.graphs.active_graph.get_shortest_path(closest_existing_node, old_sub.id[0])\n", + "print(\"Path from overload to old substation:\", path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5089d8f1", + "metadata": {}, + "outputs": [], + "source": [ + "# 🔪 Insert open point such that the load connected to old substation (node 1) is < 2_000_000W\n", + "cut_index = None\n", + "\n", + "for i, node_id in enumerate(path[1:]):\n", + " nodes_in_between = grid.graphs.active_graph.get_connected(2, nodes_to_ignore=[1, 3], inclusive=True)\n", + " cumulative_load = grid.sym_load.filter(node=path[:i]).p_specified.sum()\n", + " if cumulative_load > 2_000_000:\n", + " cut_index = i - 1\n", + " break\n", + "\n", + "if cut_index is None:\n", + " cut_index = len(path) - 2\n", + "\n", + "nodes_to_cut = path[cut_index:cut_index + 2]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04fa37b3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Line to open: \n", + " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", + " 67 | 2 | 14 | 1 | 1 | 63 | 61 | False |0.18..|0.008..| 0.0 | 0.0 |163.035..|380.95..\n" + ] + } + ], + "source": [ + "line_to_open = grid.line.filter(from_node=nodes_to_cut, to_node=nodes_to_cut)\n", + "print(f\"Line to open: \\n{line_to_open}\")\n", + "grid.make_inactive(line_to_open)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "83099a5e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", + "\n" + ] + } + ], + "source": [ + "pgm_interface = PowerGridModelInterface(grid)\n", + "pgm_interface.calculate_power_flow()\n", + "pgm_interface.update_grid()\n", + "\n", + "print(grid.line[grid.line.is_overloaded])" + ] + } + ], + "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.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From d14bfdcd7ee9865d9e405a7abee184fa5c89e872 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Tue, 6 May 2025 17:10:59 +0200 Subject: [PATCH 05/24] chore: create backstory --- power-grid-model-ds/advanced.ipynb | 166 +++++++++++++++++++++++++++-- 1 file changed, 155 insertions(+), 11 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 69ada4f..920a146 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -20,6 +20,27 @@ "!pip install power-grid-model-ds[visualizer] --quiet" ] }, + { + "cell_type": "markdown", + "id": "d5e1958f", + "metadata": {}, + "source": [ + "# ⚡ Advanced Power Grid Workshop: Solving an Overload Scenario\n", + "\n", + "You're a senior grid analyst at GridNova Utilities, overseeing a legacy radial distribution network in a semi-rural region. Recently, customer load growth has increased dramatically, particularly in areas served by a single long feeder. This has pushed some branches past their capacity, triggering repeated overloads.\n", + "\n", + "Your task: augment the grid by adding a second substation and relieving the overloaded feeder through targeted switching.\n", + "\n", + "This hands-on simulation walks you through each step of diagnosing, planning, and solving this overload using the Power Grid Model DS library.\n", + "\n", + "## 🎯 Workshop Goals\n", + "- Detect a line overload after load increase.\n", + "- Find a suitable node to connect a new substation.\n", + "- Trace the overloaded route.\n", + "- Strategically open a line to reroute power and relieve the feeder.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": 2, @@ -34,6 +55,22 @@ "from power_grid_model_ds.enums import NodeType" ] }, + { + "cell_type": "markdown", + "id": "8a4a9dbb", + "metadata": {}, + "source": [ + "# 🧪 Step 1: Extend the Data Model\n", + "Goal: Add coordinate fields and tracking for simulated voltages and line currents.\n", + "\n", + "You’ll subclass NodeArray and LineArray to add:\n", + "\n", + "- x, y coordinates for spatial logic and plotting\n", + "- u for node voltage results\n", + "- i_from for line currents\n", + "- A computed .is_overloaded property for easy filtering" + ] + }, { "cell_type": "code", "execution_count": 3, @@ -66,6 +103,21 @@ " graphs: GraphContainer" ] }, + { + "cell_type": "markdown", + "id": "8e2d5fbe", + "metadata": {}, + "source": [ + "# 🏗️ Step 2: Generate and Prepare the Grid\n", + "Goal: Build a synthetic radial grid with randomized node positions and realistic load levels.\n", + "\n", + "You’ll use RadialGridGenerator to build a 20-node grid and then:\n", + "\n", + "- Randomize node coordinates in a 1000×1000 space\n", + "- Assign loads to simulate high demand\n", + "- You’ll then compute a power flow to get realistic line currents." + ] + }, { "cell_type": "code", "execution_count": 4, @@ -128,18 +180,62 @@ "print(grid.node)" ] }, + { + "cell_type": "markdown", + "id": "6ac4eb43", + "metadata": {}, + "source": [ + "# 🧯 Step 3: Detect the Overload\n", + "Goal: Identify which line(s) are exceeding their rated current.\n", + "\n", + "You’ll:\n", + "\n", + "- Use the .is_overloaded property to find the problem\n", + "- Isolate the feeder route to the affected line\n", + "\n", + "This gives a clear target for where you need to intervene." + ] + }, { "cell_type": "code", "execution_count": 7, "id": "206be67b", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", + " 67 | 2 | 14 | 1 | 1 | 63 | 61 | False |0.180..|0.008..| 0.0 | 0.0 |163.035..|380.959..\n", + " 70 | 14 | 18 | 1 | 1 | 63 | 61 | False |0.077..|0.025..| 0.0 | 0.0 |237.064..|250.859..\n" + ] + } + ], "source": [ "from power_grid_model_ds import PowerGridModelInterface\n", "\n", "pgm_interface = PowerGridModelInterface(grid)\n", "pgm_interface.calculate_power_flow()\n", - "pgm_interface.update_grid()\n" + "pgm_interface.update_grid()\n", + "\n", + "print(grid.line[grid.line.is_overloaded])" + ] + }, + { + "cell_type": "markdown", + "id": "008fafb9", + "metadata": {}, + "source": [ + "# 🧭 Step 4: Plan a Relief Strategy\n", + "Goal: Place a second substation near the overloaded path.\n", + "\n", + "You’ll:\n", + "- Add a new substation at a specified location\n", + "- Connect it to the closest node in the network\n", + "- Visually inspect the grid with visualize()\n", + "\n", + "This substation will act as a new injection point for rerouting load.\n" ] }, { @@ -217,7 +313,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "8be6c8f5", "metadata": {}, "outputs": [ @@ -236,7 +332,7 @@ " " ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -251,10 +347,26 @@ "visualize(grid)" ] }, + { + "cell_type": "markdown", + "id": "8f2b17e3", + "metadata": {}, + "source": [ + "# 🔗 Step 5: Trace and Analyze the Overloaded Route\n", + "Goal: Identify a switchable line along the route from the new node to the old substation.\n", + "\n", + "You’ll:\n", + "- Use the graph interface to trace the shortest path from the new substation to the original\n", + "- Calculate cumulative load along the path\n", + "- Find a cut point where the remaining load toward the old substation is < 2 MW\n", + "\n", + "This ensures you relieve the feeder while maintaining supply continuity." + ] + }, { "cell_type": "code", "execution_count": 11, - "id": "7d9378b6", + "id": "1bfe4e6e", "metadata": {}, "outputs": [ { @@ -289,7 +401,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "id": "b57104f4", "metadata": {}, "outputs": [ @@ -326,9 +438,26 @@ "print(f\"Connected new substation to node {closest_existing_node}\")\n" ] }, + { + "cell_type": "markdown", + "id": "4a9ef582", + "metadata": {}, + "source": [ + "# ✂️ Step 6: Open the Right Line\n", + "Goal: Deactivate a line to offload the original feeder.\n", + "\n", + "You’ll:\n", + "- Identify and deactivate the line between two nodes on the critical path\n", + "- Rerun power flow after the switch\n", + "- Confirm the overload is resolved\n", + "\n", + "This final step demonstrates how network topology and load can be managed dynamically with switching and distributed generation.\n", + "\n" + ] + }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "id": "6a2afb10", "metadata": {}, "outputs": [ @@ -342,13 +471,13 @@ ], "source": [ "# 🔗 Trace path from that node to the current (old) substation\n", - "path, length = grid.graphs.active_graph.get_shortest_path(closest_existing_node, old_sub.id[0])\n", + "path, length = grid.graphs.active_graph.get_shortest_path(closest_existing_node, int(old_sub.id[0]))\n", "print(\"Path from overload to old substation:\", path)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "5089d8f1", "metadata": {}, "outputs": [], @@ -371,7 +500,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "04fa37b3", "metadata": {}, "outputs": [ @@ -393,7 +522,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "id": "83099a5e", "metadata": {}, "outputs": [ @@ -413,6 +542,21 @@ "\n", "print(grid.line[grid.line.is_overloaded])" ] + }, + { + "cell_type": "markdown", + "id": "1c2de102", + "metadata": {}, + "source": [ + "# ✅ Wrap-Up\n", + "You’ve just:\n", + "\n", + "Diagnosed a power system constraint\n", + "- Planned and executed a grid topology change\n", + "- Verified success with power flow simulations\n", + "\n", + "We hope you enjoyed working with Power Grid Model DS and would love to hear your feedback" + ] } ], "metadata": { From ecbf83cae8d3db8fd07b0cbb6681a90f6a623d51 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 8 May 2025 15:34:37 +0200 Subject: [PATCH 06/24] feat: cleaner functions --- power-grid-model-ds/advanced.ipynb | 428 +++++++++++------------------ 1 file changed, 158 insertions(+), 270 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 920a146..313adc4 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -2,20 +2,10 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "59d49e29", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "!pip install power-grid-model-ds[visualizer] --quiet" ] @@ -43,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "cf475775", "metadata": {}, "outputs": [], @@ -73,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "37f4bd29", "metadata": {}, "outputs": [], @@ -120,7 +110,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "78d0639e", "metadata": {}, "outputs": [], @@ -142,7 +132,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "01f369f7", "metadata": {}, "outputs": [], @@ -152,29 +142,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "a375a3f8", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", - " 1 | 10500.0 | 0 | 81 | 61 | 102.0 | 308.0 | 0.0 \n", - " 2 | 10500.0 | 0 | 63 | 61 | 435.0 | 769.0 | 0.0 \n", - " 3 | 10500.0 | 0 | 63 | 61 | 860.0 | 343.0 | 0.0 \n", - " 4 | 10500.0 | 0 | 66 | 61 | 270.0 | 491.0 | 0.0 \n", - " 5 | 10500.0 | 0 | 73 | 61 | 106.0 | 413.0 | 0.0 \n", - " (..11 hidden rows..) \n", - " 17 | 10500.0 | 0 | 63 | 61 | 99.0 | 856.0 | 0.0 \n", - " 18 | 10500.0 | 0 | 63 | 61 | 871.0 | 560.0 | 0.0 \n", - " 19 | 10500.0 | 0 | 73 | 61 | 663.0 | 474.0 | 0.0 \n", - " 20 | 10500.0 | 0 | 63 | 61 | 130.0 | 58.0 | 0.0 \n", - " 61 | 10500.0 | 1 | -2147483648 | -2147483648 | 661.0 | 510.0 | 0.0 \n" - ] - } - ], + "outputs": [], "source": [ "grid.set_feeder_ids()\n", "print(grid.node)" @@ -198,28 +169,32 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "206be67b", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", - " 67 | 2 | 14 | 1 | 1 | 63 | 61 | False |0.180..|0.008..| 0.0 | 0.0 |163.035..|380.959..\n", - " 70 | 14 | 18 | 1 | 1 | 63 | 61 | False |0.077..|0.025..| 0.0 | 0.0 |237.064..|250.859..\n" - ] - } - ], + "outputs": [], "source": [ + "# Check the grid for capacity issues\n", + "# 1. Use the PowerGridModelInterface to calculate power flow\n", + "# 2. Update the grid with the calculated values\n", + "# 3. Return the lines that are overloaded\n", + "\n", + "# Hint: You can use the `is_overloaded` property of the `MyLineArray` class to check for overloaded lines.\n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/quick_start.html#performing-power-flow-calculations\n", + "\n", "from power_grid_model_ds import PowerGridModelInterface\n", "\n", - "pgm_interface = PowerGridModelInterface(grid)\n", - "pgm_interface.calculate_power_flow()\n", - "pgm_interface.update_grid()\n", + "def check_for_capacity_issues(grid: Grid) -> LineArray:\n", + " \"\"\"Check for capacity issues on the grid.\n", + " Return the lines that with capacity issues.\n", + " \"\"\"\n", + " pgm_interface = PowerGridModelInterface(grid)\n", + " pgm_interface.calculate_power_flow()\n", + " pgm_interface.update_grid()\n", "\n", - "print(grid.line[grid.line.is_overloaded])" + " return grid.line[grid.line.is_overloaded]\n", + "\n", + "print(check_for_capacity_issues(grid))" ] }, { @@ -240,19 +215,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "38a7dfae", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | u_rated | node_type | feeder_branch_id | feeder_node_id | x | y | u \n", - " 61 | 10500.0 | 1 | -2147483648 | -2147483648 | 661.0 | 510.0 |10498.658..\n" - ] - } - ], + "outputs": [], "source": [ "old_sub = grid.node.filter(node_type=NodeType.SUBSTATION_NODE)\n", "print(old_sub)" @@ -260,89 +226,37 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "ae5d93b7", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "All node IDs and coordinates:\n", - "ID: 1 - (102.0, 308.0)\n", - "ID: 2 - (435.0, 769.0)\n", - "ID: 3 - (860.0, 343.0)\n", - "ID: 4 - (270.0, 491.0)\n", - "ID: 5 - (106.0, 413.0)\n", - "ID: 6 - (71.0, 805.0)\n", - "ID: 7 - (700.0, 385.0)\n", - "ID: 8 - (20.0, 191.0)\n", - "ID: 9 - (614.0, 955.0)\n", - "ID: 10 - (121.0, 276.0)\n", - "ID: 11 - (466.0, 160.0)\n", - "ID: 12 - (214.0, 459.0)\n", - "ID: 13 - (330.0, 313.0)\n", - "ID: 14 - (458.0, 21.0)\n", - "ID: 15 - (87.0, 252.0)\n", - "ID: 16 - (372.0, 747.0)\n", - "ID: 17 - (99.0, 856.0)\n", - "ID: 18 - (871.0, 560.0)\n", - "ID: 19 - (663.0, 474.0)\n", - "ID: 20 - (130.0, 58.0)\n", - "ID: 61 - (661.0, 510.0)\n", - "ID: 93 - (212.0, 133.0)\n" - ] - } - ], + "outputs": [], "source": [ + "def build_new_substation(grid: Grid, location: tuple[float, float]) -> NodeArray:\n", + " \"\"\"Build a new substation at the given location.\n", + " Return the new substation.\n", + " \"\"\"\n", + "\n", + " new_substation = MyNodeArray(\n", + " node_type=[NodeType.SUBSTATION_NODE.value],\n", + " u_rated=[10500.0],\n", + " x=[location[0]],\n", + " y=[location[1]]\n", + " )\n", + " grid.append(new_substation)\n", + " return new_substation\n", + "\n", "# 🏗️ Add a new substation at (212, 133)\n", - "new_sub = MyNodeArray(\n", - " node_type=[NodeType.SUBSTATION_NODE.value],\n", - " u_rated=[10500.0],\n", - " x=[212],\n", - " y=[133]\n", - ")\n", - "grid.append(new_sub)\n", - "new_id = new_sub.id\n", - "\n", - "print(\"\\nAll node IDs and coordinates:\")\n", - "for i in range(len(grid.node)):\n", - " print(f\"ID: {grid.node.id[i]} - ({grid.node.x[i]}, {grid.node.y[i]})\")\n" + "new_substation = build_new_substation(grid, (212, 133))" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "8be6c8f5", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# visualize the grid\n", - "# TODO: Link some good first issues for the visualizer\n", - "\n", "from power_grid_model_ds.visualizer import visualize\n", "visualize(grid)" ] @@ -365,77 +279,94 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "1bfe4e6e", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", - " 67 | 2 | 14 | 1 | 1 | 63 | 61 | False |0.180..|0.008..| 0.0 | 0.0 |163.035..|380.959..\n", - " 70 | 14 | 18 | 1 | 1 | 63 | 61 | False |0.077..|0.025..| 0.0 | 0.0 |237.064..|250.859..\n", - "Closest node in overload path to new substation: 10\n" - ] - } - ], + "outputs": [], + "source": [ + "def get_all_congested_routes(grid: Grid) -> list[NodeArray]:\n", + " \"\"\"Get all routes that originate from a given substation node.\"\"\"\n", + " grid.set_feeder_ids()\n", + " lines_with_congestion = check_for_capacity_issues(grid)\n", + " feeder_branch_ids_with_congestion = np.unique(lines_with_congestion['feeder_branch_id'])\n", + " return [grid.node.filter(feeder_branch_id=branch_id) for branch_id in feeder_branch_ids_with_congestion]\n", + " \n", + "congested_routes = get_all_congested_routes(grid)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "263818f6", + "metadata": {}, + "outputs": [], "source": [ - "# 📍 Identify a route with an overload\n", - "print(grid.line[grid.line.is_overloaded])\n", - "\n", - "overloaded_line = grid.line[grid.line.is_overloaded][0]\n", - "overloaded_nodes = grid.node.filter(feeder_branch_id=overloaded_line.feeder_branch_id)\n", - "\n", - "# 🔎 Find closest node in the overloaded route to the new substation\n", - "pos_new = np.array([new_sub.x, new_sub.y])\n", - "closest_node = min(\n", - " overloaded_nodes.id,\n", - " key=lambda nid: np.linalg.norm(pos_new - np.array([\n", - " grid.node.x[grid.node.id == nid][0],\n", - " grid.node.y[grid.node.id == nid][0]\n", - " ]))\n", - ")\n", - "print(f\"Closest node in overload path to new substation: {closest_node}\")" + "def find_connection_point(route: NodeArray, new_substation: NodeArray) -> NodeArray:\n", + " \"\"\"Calculate the connection point for the new route.\n", + " This should be the geographically closest node to the new substation.\n", + " \"\"\"\n", + " pos_new = np.array([new_substation.x, new_substation.y])\n", + "\n", + " distances = [\n", + " (nid, np.linalg.norm(pos_new - np.array([\n", + " grid.node.x[grid.node.id == nid][0],\n", + " grid.node.y[grid.node.id == nid][0]\n", + " ])))\n", + " for nid in route.id\n", + " ]\n", + "\n", + " closest_existing_node = sorted(distances, key=lambda x: x[1])[0][0]\n", + " closest_node = grid.node.get(closest_existing_node)\n", + " return closest_node\n", + "\n", + "\n", + "def connect_to_route(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", + " \"\"\"Connect the new substation node to the connection point.\n", + " \"\"\"\n", + " # Create a new line that connects the two nodes\n", + " new_line = MyLineArray(\n", + " from_node=[new_substation.id],\n", + " to_node=[connection_point.id],\n", + " from_status=[0], # status is 0 to make sure the line is not active\n", + " to_status=[1],\n", + " i_n=[200.0],\n", + " r1=[0.05], x1=[0.01], c1=[0.0], tan1=[0.0]\n", + " )\n", + " grid.append(new_line)" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "b57104f4", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Connected new substation to node 10\n" - ] - } - ], + "outputs": [], "source": [ - "# Add a connection from the new substation to its closest node\n", - "all_nodes_except_new = grid.node.id[grid.node.id != new_id]\n", - "distances = [\n", - " (nid, np.linalg.norm(pos_new - np.array([\n", - " grid.node.x[grid.node.id == nid][0],\n", - " grid.node.y[grid.node.id == nid][0]\n", - " ])))\n", - " for nid in all_nodes_except_new\n", - "]\n", - "\n", - "closest_existing_node = sorted(distances, key=lambda x: x[1])[0][0]\n", - "\n", - "grid.append(MyLineArray(\n", - " from_node=[new_id],\n", - " to_node=[closest_existing_node],\n", - " from_status=[1],\n", - " to_status=[1],\n", - " i_n=[200.0],\n", - " r1=[0.05], x1=[0.01], c1=[0.0], tan1=[0.0]\n", - "))\n", - "\n", - "print(f\"Connected new substation to node {closest_existing_node}\")\n" + "def transfer_routes(grid: Grid, new_substation: NodeArray) -> NodeArray:\n", + " \"\"\"Migrate a subset of the routes of the old substation to the new substation.\n", + " Each route can be migrated fully or partially.\n", + "\n", + " \"\"\"\n", + " congested_routes = get_all_congested_routes(grid)\n", + "\n", + " newly_connected_nodes = []\n", + " for route in congested_routes:\n", + " closest_node = find_connection_point(\n", + " route=route,\n", + " new_substation=new_substation\n", + " )\n", + "\n", + " connect_to_route(\n", + " grid=grid,\n", + " connection_point=closest_node,\n", + " new_substation=new_substation,\n", + " )\n", + "\n", + " print(f\"Connected new substation to node {closest_node.id}\")\n", + " newly_connected_nodes.append(closest_node)\n", + " return newly_connected_nodes\n", + "\n", + "newly_connected_nodes = transfer_routes(grid=grid, new_substation=new_substation)" ] }, { @@ -457,90 +388,47 @@ }, { "cell_type": "code", - "execution_count": 13, - "id": "6a2afb10", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Path from overload to old substation: [10, 17, 14, 2, np.int32(61)]\n" - ] - } - ], - "source": [ - "# 🔗 Trace path from that node to the current (old) substation\n", - "path, length = grid.graphs.active_graph.get_shortest_path(closest_existing_node, int(old_sub.id[0]))\n", - "print(\"Path from overload to old substation:\", path)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "5089d8f1", + "execution_count": null, + "id": "a494d54c", "metadata": {}, "outputs": [], "source": [ - "# 🔪 Insert open point such that the load connected to old substation (node 1) is < 2_000_000W\n", - "cut_index = None\n", - "\n", - "for i, node_id in enumerate(path[1:]):\n", - " nodes_in_between = grid.graphs.active_graph.get_connected(2, nodes_to_ignore=[1, 3], inclusive=True)\n", - " cumulative_load = grid.sym_load.filter(node=path[:i]).p_specified.sum()\n", - " if cumulative_load > 2_000_000:\n", - " cut_index = i - 1\n", - " break\n", - "\n", - "if cut_index is None:\n", - " cut_index = len(path) - 2\n", - "\n", - "nodes_to_cut = path[cut_index:cut_index + 2]\n" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "04fa37b3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Line to open: \n", - " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", - " 67 | 2 | 14 | 1 | 1 | 63 | 61 | False |0.18..|0.008..| 0.0 | 0.0 |163.035..|380.95..\n" - ] - } - ], - "source": [ - "line_to_open = grid.line.filter(from_node=nodes_to_cut, to_node=nodes_to_cut)\n", - "print(f\"Line to open: \\n{line_to_open}\")\n", - "grid.make_inactive(line_to_open)" + "def optimize_route_transfer(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", + " \"\"\"Attempt to optimize the route transfer moving the naturally open point (NOP) upstream towards the old substation.\n", + " This way, the new substation will take over more nodes of the original route.\n", + "\n", + " Note that a node cannot be taken over if that results in a capacity issue on the grid.\n", + " \"\"\"\n", + " # 🔗 Trace path from that node to the current (old) substation\n", + " old_substation_node_id = connection_point.feeder_node_id.item()\n", + " path, length = grid.graphs.active_graph.get_shortest_path(connection_point.id.item(), old_substation_node_id)\n", + " print(\"Path from overload to old substation:\", path)\n", + "\n", + " current_branch = grid.line.filter(\n", + " from_node=[connection_point.id.item(), new_substation.id.item()],\n", + " to_node=[connection_point.id.item(), new_substation.id.item()]\n", + " )\n", + " for i, (from_node, to_node) in enumerate(zip(path[0:-1], path[1:])):\n", + " # Check if the line is overloaded\n", + " if not any(check_for_capacity_issues(grid)):\n", + " break\n", + "\n", + " grid.make_active(current_branch)\n", + " current_branch = grid.line.filter(from_node=[from_node, to_node], to_node=[from_node, to_node])\n", + " grid.make_inactive(current_branch)\n", + "\n", + "for connection_point in newly_connected_nodes:\n", + " optimize_route_transfer(grid=grid, connection_point=connection_point, new_substation=new_substation)" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "83099a5e", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " id | from_node | to_node | from_status | to_status | feeder_branch_id | feeder_node_id | is_feeder | r1 | x1 | c1 | tan1 | i_n | i_from \n", - "\n" - ] - } - ], + "outputs": [], "source": [ - "pgm_interface = PowerGridModelInterface(grid)\n", - "pgm_interface.calculate_power_flow()\n", - "pgm_interface.update_grid()\n", - "\n", - "print(grid.line[grid.line.is_overloaded])" + "print(check_for_capacity_issues(grid))" ] }, { From ec9378e0393f658351d98e4846ae1cfe89a2a4c0 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 8 May 2025 16:24:35 +0200 Subject: [PATCH 07/24] feat: cleaner distance function --- power-grid-model-ds/advanced.ipynb | 143 ++++++++++++++++------------- 1 file changed, 81 insertions(+), 62 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 313adc4..f2eacc1 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -177,11 +177,16 @@ "# Check the grid for capacity issues\n", "# 1. Use the PowerGridModelInterface to calculate power flow\n", "# 2. Update the grid with the calculated values\n", - "# 3. Return the lines that are overloaded\n", + "# 3. Return the lines (LineArray) that are overloaded\n", "\n", "# Hint: You can use the `is_overloaded` property of the `MyLineArray` class to check for overloaded lines.\n", "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/quick_start.html#performing-power-flow-calculations\n", "\n", + "def check_for_capacity_issues(grid: Grid) -> LineArray:\n", + " \"\"\"Check for capacity issues on the grid.\n", + " Return the lines that with capacity issues.\n", + " \"\"\"\n", + "\n", "from power_grid_model_ds import PowerGridModelInterface\n", "\n", "def check_for_capacity_issues(grid: Grid) -> LineArray:\n", @@ -192,6 +197,8 @@ " pgm_interface.calculate_power_flow()\n", " pgm_interface.update_grid()\n", "\n", + " # update attribute overload_status\n", + "\n", " return grid.line[grid.line.is_overloaded]\n", "\n", "print(check_for_capacity_issues(grid))" @@ -213,17 +220,6 @@ "This substation will act as a new injection point for rerouting load.\n" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "38a7dfae", - "metadata": {}, - "outputs": [], - "source": [ - "old_sub = grid.node.filter(node_type=NodeType.SUBSTATION_NODE)\n", - "print(old_sub)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -258,7 +254,7 @@ "source": [ "# visualize the grid\n", "from power_grid_model_ds.visualizer import visualize\n", - "visualize(grid)" + "# visualize(grid)" ] }, { @@ -305,18 +301,12 @@ " \"\"\"Calculate the connection point for the new route.\n", " This should be the geographically closest node to the new substation.\n", " \"\"\"\n", - " pos_new = np.array([new_substation.x, new_substation.y])\n", - "\n", - " distances = [\n", - " (nid, np.linalg.norm(pos_new - np.array([\n", - " grid.node.x[grid.node.id == nid][0],\n", - " grid.node.y[grid.node.id == nid][0]\n", - " ])))\n", - " for nid in route.id\n", - " ]\n", - "\n", - " closest_existing_node = sorted(distances, key=lambda x: x[1])[0][0]\n", - " closest_node = grid.node.get(closest_existing_node)\n", + " x_difference = route.x - new_substation.x\n", + " y_difference = route.y - new_substation.y\n", + " distances = (x_difference**2 + y_difference**2) ** 0.5\n", + " \n", + " idx_closest_node = np.argmin(distances)\n", + " closest_node = grid.node[idx_closest_node]\n", " return closest_node\n", "\n", "\n", @@ -335,40 +325,6 @@ " grid.append(new_line)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "b57104f4", - "metadata": {}, - "outputs": [], - "source": [ - "def transfer_routes(grid: Grid, new_substation: NodeArray) -> NodeArray:\n", - " \"\"\"Migrate a subset of the routes of the old substation to the new substation.\n", - " Each route can be migrated fully or partially.\n", - "\n", - " \"\"\"\n", - " congested_routes = get_all_congested_routes(grid)\n", - "\n", - " newly_connected_nodes = []\n", - " for route in congested_routes:\n", - " closest_node = find_connection_point(\n", - " route=route,\n", - " new_substation=new_substation\n", - " )\n", - "\n", - " connect_to_route(\n", - " grid=grid,\n", - " connection_point=closest_node,\n", - " new_substation=new_substation,\n", - " )\n", - "\n", - " print(f\"Connected new substation to node {closest_node.id}\")\n", - " newly_connected_nodes.append(closest_node)\n", - " return newly_connected_nodes\n", - "\n", - "newly_connected_nodes = transfer_routes(grid=grid, new_substation=new_substation)" - ] - }, { "cell_type": "markdown", "id": "4a9ef582", @@ -415,10 +371,43 @@ "\n", " grid.make_active(current_branch)\n", " current_branch = grid.line.filter(from_node=[from_node, to_node], to_node=[from_node, to_node])\n", - " grid.make_inactive(current_branch)\n", + " grid.make_inactive(current_branch)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb4092a1", + "metadata": {}, + "outputs": [], + "source": [ + "def transfer_routes(grid: Grid, new_substation: NodeArray) -> NodeArray:\n", + " \"\"\"Migrate a subset of the routes of the old substation to the new substation.\n", + " Each route can be migrated fully or partially.\n", "\n", - "for connection_point in newly_connected_nodes:\n", - " optimize_route_transfer(grid=grid, connection_point=connection_point, new_substation=new_substation)" + " \"\"\"\n", + " congested_routes = get_all_congested_routes(grid)\n", + "\n", + " for route in congested_routes:\n", + " closest_node = find_connection_point(\n", + " route=route,\n", + " new_substation=new_substation\n", + " )\n", + "\n", + " connect_to_route(\n", + " grid=grid,\n", + " connection_point=closest_node,\n", + " new_substation=new_substation,\n", + " )\n", + "\n", + " optimize_route_transfer(\n", + " grid=grid,\n", + " connection_point=closest_node,\n", + " new_substation=new_substation)\n", + " \n", + " print(f\"Connected new substation to node {closest_node.id}\")\n", + "\n", + "transfer_routes(grid=grid, new_substation=new_substation)" ] }, { @@ -431,6 +420,36 @@ "print(check_for_capacity_issues(grid))" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d7802d5", + "metadata": {}, + "outputs": [], + "source": [ + "grid.sym_load.filter(node=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e174738d", + "metadata": {}, + "outputs": [], + "source": [ + "print(grid.line)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0e73d1d", + "metadata": {}, + "outputs": [], + "source": [ + "visualize(grid)" + ] + }, { "cell_type": "markdown", "id": "1c2de102", From f3f6496ac06877cc9b3623b2b611685e3969c9dc Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 8 May 2025 16:29:27 +0200 Subject: [PATCH 08/24] fix: loadflow --- power-grid-model-ds/advanced.ipynb | 40 ++++--------------- .../solutions/introduction_2_5_add_source.py | 2 +- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index f2eacc1..47453ed 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -41,7 +41,7 @@ "import numpy as np\n", "from dataclasses import dataclass\n", "from power_grid_model_ds import Grid, GraphContainer\n", - "from power_grid_model_ds.arrays import NodeArray, LineArray\n", + "from power_grid_model_ds.arrays import NodeArray, LineArray, SourceArray\n", "from power_grid_model_ds.enums import NodeType" ] }, @@ -231,7 +231,6 @@ " \"\"\"Build a new substation at the given location.\n", " Return the new substation.\n", " \"\"\"\n", - "\n", " new_substation = MyNodeArray(\n", " node_type=[NodeType.SUBSTATION_NODE.value],\n", " u_rated=[10500.0],\n", @@ -239,6 +238,13 @@ " y=[location[1]]\n", " )\n", " grid.append(new_substation)\n", + "\n", + " new_source = SourceArray(\n", + " node=[new_substation.id.item()],\n", + " status=[1],\n", + " u_ref=[1],\n", + " )\n", + " grid.append(new_source)\n", " return new_substation\n", "\n", "# 🏗️ Add a new substation at (212, 133)\n", @@ -420,36 +426,6 @@ "print(check_for_capacity_issues(grid))" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "8d7802d5", - "metadata": {}, - "outputs": [], - "source": [ - "grid.sym_load.filter(node=10)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e174738d", - "metadata": {}, - "outputs": [], - "source": [ - "print(grid.line)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e0e73d1d", - "metadata": {}, - "outputs": [], - "source": [ - "visualize(grid)" - ] - }, { "cell_type": "markdown", "id": "1c2de102", diff --git a/power-grid-model-ds/solutions/introduction_2_5_add_source.py b/power-grid-model-ds/solutions/introduction_2_5_add_source.py index e27e4d3..55c2ebd 100644 --- a/power-grid-model-ds/solutions/introduction_2_5_add_source.py +++ b/power-grid-model-ds/solutions/introduction_2_5_add_source.py @@ -3,6 +3,6 @@ id=[501], node=[101], status=[1], - u_ref=[0.0] # reference voltage or angle (0.0 as a placeholder) + u_ref=[1.0] ) grid.append(source, check_max_id=False) \ No newline at end of file From 2104c13e297439235a17fc7861bf08df9e49d4a4 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 8 May 2025 16:38:19 +0200 Subject: [PATCH 09/24] chore: cleanup --- power-grid-model-ds/advanced.ipynb | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 47453ed..38d517d 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -260,7 +260,7 @@ "source": [ "# visualize the grid\n", "from power_grid_model_ds.visualizer import visualize\n", - "# visualize(grid)" + "visualize(grid)" ] }, { @@ -296,6 +296,16 @@ "congested_routes = get_all_congested_routes(grid)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf6b4bb8", + "metadata": {}, + "outputs": [], + "source": [ + "congested_routes[0]" + ] + }, { "cell_type": "code", "execution_count": null, @@ -363,14 +373,14 @@ " \"\"\"\n", " # 🔗 Trace path from that node to the current (old) substation\n", " old_substation_node_id = connection_point.feeder_node_id.item()\n", - " path, length = grid.graphs.active_graph.get_shortest_path(connection_point.id.item(), old_substation_node_id)\n", + " path, _ = grid.graphs.active_graph.get_shortest_path(connection_point.id.item(), old_substation_node_id)\n", " print(\"Path from overload to old substation:\", path)\n", "\n", " current_branch = grid.line.filter(\n", - " from_node=[connection_point.id.item(), new_substation.id.item()],\n", - " to_node=[connection_point.id.item(), new_substation.id.item()]\n", + " from_node=[connection_point.id, new_substation.id],\n", + " to_node=[connection_point.id, new_substation.id]\n", " )\n", - " for i, (from_node, to_node) in enumerate(zip(path[0:-1], path[1:])):\n", + " for from_node, to_node in zip(path[0:-1], path[1:]):\n", " # Check if the line is overloaded\n", " if not any(check_for_capacity_issues(grid)):\n", " break\n", From 6e98648b4d657d27a7b8a1649c1b923b2efb256a Mon Sep 17 00:00:00 2001 From: Sven van der Voort Date: Fri, 9 May 2025 16:50:25 +0200 Subject: [PATCH 10/24] PGM-DS: Add data example Grid --- power-grid-model-ds/advanced.ipynb | 93 +++++++++++++++++++----------- power-grid-model-ds/data/lines.csv | 25 ++++++++ power-grid-model-ds/data/loads.csv | 22 +++++++ power-grid-model-ds/data/nodes.csv | 23 ++++++++ 4 files changed, 129 insertions(+), 34 deletions(-) create mode 100644 power-grid-model-ds/data/lines.csv create mode 100644 power-grid-model-ds/data/loads.csv create mode 100644 power-grid-model-ds/data/nodes.csv diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 38d517d..a75e089 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -7,7 +7,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install power-grid-model-ds[visualizer] --quiet" + "!pip install pandas power-grid-model-ds[visualizer] --quiet" ] }, { @@ -39,10 +39,12 @@ "outputs": [], "source": [ "import numpy as np\n", + "import pandas as pd\n", "from dataclasses import dataclass\n", "from power_grid_model_ds import Grid, GraphContainer\n", - "from power_grid_model_ds.arrays import NodeArray, LineArray, SourceArray\n", - "from power_grid_model_ds.enums import NodeType" + "from power_grid_model_ds.arrays import SymLoadArray, LineArray, NodeArray, SourceArray\n", + "from power_grid_model_ds.enums import NodeType\n", + "from power_grid_model_ds.visualizer import visualize" ] }, { @@ -98,14 +100,14 @@ "id": "8e2d5fbe", "metadata": {}, "source": [ - "# 🏗️ Step 2: Generate and Prepare the Grid\n", - "Goal: Build a synthetic radial grid with randomized node positions and realistic load levels.\n", - "\n", - "You’ll use RadialGridGenerator to build a 20-node grid and then:\n", - "\n", - "- Randomize node coordinates in a 1000×1000 space\n", - "- Assign loads to simulate high demand\n", - "- You’ll then compute a power flow to get realistic line currents." + "# 🏗️ Step 2: Load and Prepare the Grid\n", + "Goal: Load a synthetic medium-voltage grid from the provided data.\n", + "\n", + "You'll use pandas to load the data from included CSV files and then:\n", + "- Create an empty Grid object using your custom MyGrid class\n", + "- Create and fill NodeArray, LineArray and LoadArray objects with data from the CSV files and append them to your Grid\n", + "- Using a SourceArray, add a voltage source to each substation in the Grid\n", + "- You’ll then compute a power flow on the synthetic grid to get realistic line currents" ] }, { @@ -115,29 +117,52 @@ "metadata": {}, "outputs": [], "source": [ - "from power_grid_model_ds.generators import RadialGridGenerator\n", - "\n", - "# Generate a radial grid\n", - "grid_gen = RadialGridGenerator(grid_class=MyGrid, nr_nodes=20, nr_sources=1)\n", - "grid = grid_gen.run(seed=42)\n", - "\n", - "np.random.seed(42)\n", - "num_nodes = grid.node.size\n", - "x_coords = np.random.randint(0, 1000, size=num_nodes)\n", - "y_coords = np.random.randint(0, 1000, size=num_nodes)\n", - "\n", - "grid.node.x = x_coords\n", - "grid.node.y = y_coords" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "01f369f7", - "metadata": {}, - "outputs": [], - "source": [ - "grid.sym_load.p_specified = np.random.randint(300000, 1200000, size=grid.sym_load.size)" + "nodes_csv = pd.read_csv(\"data/nodes.csv\")\n", + "loads_csv = pd.read_csv(\"data/loads.csv\")\n", + "lines_csv = pd.read_csv(\"data/lines.csv\")\n", + "\n", + "grid = MyGrid.empty()\n", + "\n", + "nodes = MyNodeArray(\n", + " id=nodes_csv.id.tolist(),\n", + " u_rated=nodes_csv.u_rated.tolist(),\n", + " node_type=nodes_csv.node_type.tolist(),\n", + " x=nodes_csv.x.tolist(),\n", + " y=nodes_csv.y.tolist(),\n", + " u=[-1.0] * len(nodes_csv),\n", + ")\n", + "loads = SymLoadArray(\n", + " id=loads_csv.id.tolist(),\n", + " node=loads_csv.node.tolist(),\n", + " status=[1] * len(loads_csv),\n", + " type=[0] * len(loads_csv),\n", + " p_specified=loads_csv.p_specified.tolist(),\n", + " q_specified=loads_csv.q_specified.tolist(),\n", + ")\n", + "lines = MyLineArray(\n", + " id=lines_csv.id.tolist(),\n", + " from_node=lines_csv.from_node.tolist(),\n", + " to_node=lines_csv.to_node.tolist(),\n", + " from_status=lines_csv.from_status.tolist(), # 1 means active connection from-side, \n", + " to_status=lines_csv.to_status.tolist(), # 1 means active connection to-side\n", + " i_n=lines_csv.i_n.tolist(), # line max current capacity (e.g., 200 A)\n", + " r1=lines_csv.r1.tolist(), # line resistance\n", + " x1=lines_csv.x1.tolist(), # line reactance\n", + " c1=lines_csv.c1.tolist(), # line capacitance\n", + " tan1=lines_csv.tan1.tolist() # line loss tangent\n", + ")\n", + "sources = SourceArray(\n", + " id=[401],\n", + " node=[101],\n", + " status=[1],\n", + " u_ref=[1.0],\n", + ")\n", + "\n", + "grid.append(nodes, check_max_id=False)\n", + "grid.append(loads, check_max_id=False)\n", + "grid.append(lines, check_max_id=False)\n", + "grid.append(sources, check_max_id=False)\n", + "# visualize(grid)" ] }, { diff --git a/power-grid-model-ds/data/lines.csv b/power-grid-model-ds/data/lines.csv new file mode 100644 index 0000000..6e2c374 --- /dev/null +++ b/power-grid-model-ds/data/lines.csv @@ -0,0 +1,25 @@ +id,from_node,to_node,from_status,to_status,i_from,r1,x1,c1,tan1,i_n +301,101,1,1,1,0,0.04172331553871052,0.052980486528544264,0.0,0.0,210.28427536474146 +302,1,2,1,1,0,0.15725110380730004,0.022290287012795527,0.0,0.0,105.94268839245518 +303,2,3,1,1,0,0.15725110380730004,0.022290287012795527,0.0,0.0,105.94268839245518 +304,3,4,1,1,0,0.025752163570459393,0.017975680453095257,0.0,0.0,252.81330598432984 +305,4,5,1,1,0,0.184580749945473,0.05679935115815177,0.0,0.0,308.29168286950096 +306,5,6,1,1,0,0.09247280056072502,0.04061706379498719,0.0,0.0,146.12039826984656 +307,6,7,1,1,0,0.09247280056072502,0.04061706379498719,0.0,0.0,146.12039826984656 +308,7,101,1,0,0,0.13774802878276293,0.023316760013206598,0.0,0.0,435.44293210319637 +309,101,8,1,1,0,0.13774802878276293,0.023316760013206598,0.0,0.0,435.44293210319637 +310,8,9,1,1,0,0.03155099592582141,0.1684585911623038,0.0,0.0,386.9416504130695 +311,9,10,1,1,0,0.38045029098187605,0.0063983451879243095,0.0,0.0,595.6252329736612 +312,10,11,1,1,0,0.38045029098187605,0.0063983451879243095,0.0,0.0,595.6252329736612 +313,11,12,1,0,0,0.2711350129219581,0.0239320695659479,0.0,0.0,109.56302502830336 +314,12,13,1,1,0,0.7512185900820556,0.016025736292976843,0.0,0.0,320.73771673448846 +315,13,14,1,1,0,0.2332922408038184,0.010579215551474988,0.0,0.0,221.24699130886745 +316,14,15,1,1,0,0.2884431875887676,0.016206534923606564,0.0,0.0,305.34636498186455 +317,15,16,1,1,0,0.06893013265387658,0.002501770712404082,0.0,0.0,129.78347503297758 +318,16,101,1,1,0,0.17466926178911735,0.04197366431254047,0.0,0.0,223.462291908927 +319,101,17,1,1,0,0.0014230825354318865,0.005366123634368465,0.0,0.0,143.19692487769424 +320,17,18,1,1,0,0.05535894789343593,0.015888270665417342,0.0,0.0,348.82546139151896 +321,18,19,1,1,0,1.1336902294005273,0.0034372075909574274,0.0,0.0,109.4472896415015 +322,19,20,1,1,0,0.02756399437186089,0.001442850824658642,0.0,0.0,315.15332070790726 +323,20,21,1,1,0,0.15000233423633422,0.012783549273682825,0.0,0.0,505.6064937043503 +324,21,101,1,0,0,0.4527663172740473,0.010942584326900677,0.0,0.0,235.29434874845845 diff --git a/power-grid-model-ds/data/loads.csv b/power-grid-model-ds/data/loads.csv new file mode 100644 index 0000000..6ca1fe4 --- /dev/null +++ b/power-grid-model-ds/data/loads.csv @@ -0,0 +1,22 @@ +id,node,p_specified,q_specified +201,1,75559.96424922015,2119.7561886191743 +202,2,3897910.78949213034,-8632.07774532976 +203,3,95478.41471359684,18229.00620748075 +204,4,-63249.17346947564,-712.0333973476627 +205,5,-64900.69141993268,14743.624463381835 +206,6,348049.77201387816,36026.00482909736 +207,7,21984.741221515593,24426.02990667891 +208,8,-67789.02445002584,32094.560258638798 +209,9,194810.9302324328,4783.500971894942 +210,10,-65128.11331122106,-4447.890651114186 +211,11,143731.66910079535,5949.794993746957 +212,12,224756.36715177132,39976.29538075794 +213,13,80358.3966250818,22745.972387370846 +214,14,313227.5266984018,23551.04963072692 +215,15,234550.7662600798,19216.914424467115 +216,16,293012.8372641854,-9912.346527315487 +217,17,386582.49982988625,-2654.9452654344077 +218,18,-68922.11726350724,13959.630269749312 +219,19,329471.2892289656,-5256.568898739658 +220,20,3828501.06297316383,27023.499817300326 +221,21,55155.355929427635,37523.58862659218 diff --git a/power-grid-model-ds/data/nodes.csv b/power-grid-model-ds/data/nodes.csv new file mode 100644 index 0000000..eec47d2 --- /dev/null +++ b/power-grid-model-ds/data/nodes.csv @@ -0,0 +1,23 @@ +id,u_rated,node_type,x,y +1,10500.0,0,0,200 +2,10500.0,0,0,400 +3,10500.0,0,0,600 +4,10500.0,0,0,800 +5,10500.0,0,-200,800 +6,10500.0,0,-400,600 +7,10500.0,0,-400,400 +8,10500.0,0,-200,0 +9,10500.0,0,-400,0 +10,10500.0,0,-600,0 +11,10500.0,0,-600,-200 +12,10500.0,0,-600,-400 +13,10500.0,0,-400,-400 +14,10500.0,0,-200,-400 +15,10500.0,0,0,-400 +16,10500.0,0,0,-200 +17,10500.0,0,200,0 +18,10500.0,0,400,0 +19,10500.0,0,600,200 +20,10500.0,0,400,200 +21,10500.0,0,200,200 +101,10500.0,1,0,0 From 794e9e89ca3a461e9a519b86ce6a5a03f7c42522 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Fri, 9 May 2025 17:20:53 +0200 Subject: [PATCH 11/24] chore: match new input to solutions --- power-grid-model-ds/advanced.ipynb | 40 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index a75e089..44338b1 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -272,8 +272,8 @@ " grid.append(new_source)\n", " return new_substation\n", "\n", - "# 🏗️ Add a new substation at (212, 133)\n", - "new_substation = build_new_substation(grid, (212, 133))" + "# 🏗️ Add a new substation at (512, 433)\n", + "new_substation = build_new_substation(grid, (512, 433))" ] }, { @@ -285,7 +285,7 @@ "source": [ "# visualize the grid\n", "from power_grid_model_ds.visualizer import visualize\n", - "visualize(grid)" + "# visualize(grid)" ] }, { @@ -321,16 +321,6 @@ "congested_routes = get_all_congested_routes(grid)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "bf6b4bb8", - "metadata": {}, - "outputs": [], - "source": [ - "congested_routes[0]" - ] - }, { "cell_type": "code", "execution_count": null, @@ -347,7 +337,7 @@ " distances = (x_difference**2 + y_difference**2) ** 0.5\n", " \n", " idx_closest_node = np.argmin(distances)\n", - " closest_node = grid.node[idx_closest_node]\n", + " closest_node = route[idx_closest_node]\n", " return closest_node\n", "\n", "\n", @@ -360,7 +350,7 @@ " to_node=[connection_point.id],\n", " from_status=[0], # status is 0 to make sure the line is not active\n", " to_status=[1],\n", - " i_n=[200.0],\n", + " i_n=[360.0],\n", " r1=[0.05], x1=[0.01], c1=[0.0], tan1=[0.0]\n", " )\n", " grid.append(new_line)" @@ -406,13 +396,17 @@ " to_node=[connection_point.id, new_substation.id]\n", " )\n", " for from_node, to_node in zip(path[0:-1], path[1:]):\n", - " # Check if the line is overloaded\n", - " if not any(check_for_capacity_issues(grid)):\n", + " # Check if the route is still overloaded\n", + " capacity_issues = check_for_capacity_issues(grid)\n", + " route_capacity_issues = capacity_issues.filter(feeder_branch_id=connection_point.feeder_branch_id)\n", + " if not any(route_capacity_issues):\n", " break\n", "\n", " grid.make_active(current_branch)\n", " current_branch = grid.line.filter(from_node=[from_node, to_node], to_node=[from_node, to_node])\n", - " grid.make_inactive(current_branch)" + " grid.make_inactive(current_branch)\n", + " \n", + " grid.set_feeder_ids()" ] }, { @@ -451,6 +445,16 @@ "transfer_routes(grid=grid, new_substation=new_substation)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "8226a9c1", + "metadata": {}, + "outputs": [], + "source": [ + "visualize(grid)" + ] + }, { "cell_type": "code", "execution_count": null, From 8e8e8808aca3836a2b3b45e2cefebed91242a480 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 15 May 2025 21:21:40 +0200 Subject: [PATCH 12/24] feat: create solutions --- power-grid-model-ds/advanced.ipynb | 203 +++++------------- power-grid-model-ds/helper.py | 53 +++++ power-grid-model-ds/input_network.png | Bin 0 -> 79518 bytes .../advanced_3_check_for_capacity_issues.py | 13 ++ .../advanced_4_build_new_substation.py | 13 ++ .../advanced_5_1_get_all_congested_routes.py | 8 + .../advanced_5_2_find_connection_point.py | 11 + .../advanced_5_3_connect_to_route.py | 0 .../advanced_6_optimize_route_transfer.py | 24 +++ 9 files changed, 173 insertions(+), 152 deletions(-) create mode 100644 power-grid-model-ds/helper.py create mode 100644 power-grid-model-ds/input_network.png create mode 100644 power-grid-model-ds/solutions/advanced_3_check_for_capacity_issues.py create mode 100644 power-grid-model-ds/solutions/advanced_4_build_new_substation.py create mode 100644 power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py create mode 100644 power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py create mode 100644 power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py create mode 100644 power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 44338b1..62ade1f 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -39,10 +39,10 @@ "outputs": [], "source": [ "import numpy as np\n", - "import pandas as pd\n", + "\n", "from dataclasses import dataclass\n", "from power_grid_model_ds import Grid, GraphContainer\n", - "from power_grid_model_ds.arrays import SymLoadArray, LineArray, NodeArray, SourceArray\n", + "from power_grid_model_ds.arrays import LineArray, NodeArray, SourceArray\n", "from power_grid_model_ds.enums import NodeType\n", "from power_grid_model_ds.visualizer import visualize" ] @@ -80,13 +80,19 @@ " u: NDArray[np.float64]\n", "\n", "class MyLineArray(LineArray):\n", - " _defaults = {\"i_from\": 0.0}\n", + " _defaults = {\"i_from\": 0.0, \"overload_status\": 0}\n", " i_from: NDArray[np.float64]\n", + " overload_status: NDArray[np.int8]\n", + "\n", + " def set_overload_status(self):\n", + " \"\"\"Set the overload status based on the current and nominal current.\"\"\"\n", + " self.overload_status = np.where(self.i_from > self.i_n, 1, 0)\n", "\n", " @property\n", " def is_overloaded(self) -> NDArray[np.bool_]:\n", " \"\"\"Check if the line is overloaded.\"\"\"\n", - " return self.i_from > self.i_n\n", + " self.set_overload_status()\n", + " return self.overload_status == 1\n", "\n", "@dataclass\n", "class MyGrid(Grid):\n", @@ -117,63 +123,9 @@ "metadata": {}, "outputs": [], "source": [ - "nodes_csv = pd.read_csv(\"data/nodes.csv\")\n", - "loads_csv = pd.read_csv(\"data/loads.csv\")\n", - "lines_csv = pd.read_csv(\"data/lines.csv\")\n", - "\n", - "grid = MyGrid.empty()\n", - "\n", - "nodes = MyNodeArray(\n", - " id=nodes_csv.id.tolist(),\n", - " u_rated=nodes_csv.u_rated.tolist(),\n", - " node_type=nodes_csv.node_type.tolist(),\n", - " x=nodes_csv.x.tolist(),\n", - " y=nodes_csv.y.tolist(),\n", - " u=[-1.0] * len(nodes_csv),\n", - ")\n", - "loads = SymLoadArray(\n", - " id=loads_csv.id.tolist(),\n", - " node=loads_csv.node.tolist(),\n", - " status=[1] * len(loads_csv),\n", - " type=[0] * len(loads_csv),\n", - " p_specified=loads_csv.p_specified.tolist(),\n", - " q_specified=loads_csv.q_specified.tolist(),\n", - ")\n", - "lines = MyLineArray(\n", - " id=lines_csv.id.tolist(),\n", - " from_node=lines_csv.from_node.tolist(),\n", - " to_node=lines_csv.to_node.tolist(),\n", - " from_status=lines_csv.from_status.tolist(), # 1 means active connection from-side, \n", - " to_status=lines_csv.to_status.tolist(), # 1 means active connection to-side\n", - " i_n=lines_csv.i_n.tolist(), # line max current capacity (e.g., 200 A)\n", - " r1=lines_csv.r1.tolist(), # line resistance\n", - " x1=lines_csv.x1.tolist(), # line reactance\n", - " c1=lines_csv.c1.tolist(), # line capacitance\n", - " tan1=lines_csv.tan1.tolist() # line loss tangent\n", - ")\n", - "sources = SourceArray(\n", - " id=[401],\n", - " node=[101],\n", - " status=[1],\n", - " u_ref=[1.0],\n", - ")\n", - "\n", - "grid.append(nodes, check_max_id=False)\n", - "grid.append(loads, check_max_id=False)\n", - "grid.append(lines, check_max_id=False)\n", - "grid.append(sources, check_max_id=False)\n", - "# visualize(grid)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a375a3f8", - "metadata": {}, - "outputs": [], - "source": [ - "grid.set_feeder_ids()\n", - "print(grid.node)" + "from helper import load_dummy_grid\n", + "\n", + "grid = load_dummy_grid(MyGrid)" ] }, { @@ -212,21 +164,9 @@ " Return the lines that with capacity issues.\n", " \"\"\"\n", "\n", - "from power_grid_model_ds import PowerGridModelInterface\n", - "\n", - "def check_for_capacity_issues(grid: Grid) -> LineArray:\n", - " \"\"\"Check for capacity issues on the grid.\n", - " Return the lines that with capacity issues.\n", - " \"\"\"\n", - " pgm_interface = PowerGridModelInterface(grid)\n", - " pgm_interface.calculate_power_flow()\n", - " pgm_interface.update_grid()\n", - "\n", - " # update attribute overload_status\n", - "\n", - " return grid.line[grid.line.is_overloaded]\n", + "print(check_for_capacity_issues(grid))\n", "\n", - "print(check_for_capacity_issues(grid))" + "# %load solutions/advanced_3_check_for_capacity_issues.py" ] }, { @@ -235,6 +175,9 @@ "metadata": {}, "source": [ "# 🧭 Step 4: Plan a Relief Strategy\n", + "\n", + "![input_network.png](input_network.png)\n", + "\n", "Goal: Place a second substation near the overloaded path.\n", "\n", "You’ll:\n", @@ -256,36 +199,8 @@ " \"\"\"Build a new substation at the given location.\n", " Return the new substation.\n", " \"\"\"\n", - " new_substation = MyNodeArray(\n", - " node_type=[NodeType.SUBSTATION_NODE.value],\n", - " u_rated=[10500.0],\n", - " x=[location[0]],\n", - " y=[location[1]]\n", - " )\n", - " grid.append(new_substation)\n", - "\n", - " new_source = SourceArray(\n", - " node=[new_substation.id.item()],\n", - " status=[1],\n", - " u_ref=[1],\n", - " )\n", - " grid.append(new_source)\n", - " return new_substation\n", - "\n", - "# 🏗️ Add a new substation at (512, 433)\n", - "new_substation = build_new_substation(grid, (512, 433))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8be6c8f5", - "metadata": {}, - "outputs": [], - "source": [ - "# visualize the grid\n", - "from power_grid_model_ds.visualizer import visualize\n", - "# visualize(grid)" + "\n", + "# %load solutions/advanced_4_build_new_substation.py" ] }, { @@ -313,18 +228,14 @@ "source": [ "def get_all_congested_routes(grid: Grid) -> list[NodeArray]:\n", " \"\"\"Get all routes that originate from a given substation node.\"\"\"\n", - " grid.set_feeder_ids()\n", - " lines_with_congestion = check_for_capacity_issues(grid)\n", - " feeder_branch_ids_with_congestion = np.unique(lines_with_congestion['feeder_branch_id'])\n", - " return [grid.node.filter(feeder_branch_id=branch_id) for branch_id in feeder_branch_ids_with_congestion]\n", - " \n", - "congested_routes = get_all_congested_routes(grid)" + "\n", + "# %load solutions/advanced_5_1_get_all_congested_routes.py" ] }, { "cell_type": "code", "execution_count": null, - "id": "263818f6", + "id": "32b32015", "metadata": {}, "outputs": [], "source": [ @@ -332,28 +243,22 @@ " \"\"\"Calculate the connection point for the new route.\n", " This should be the geographically closest node to the new substation.\n", " \"\"\"\n", - " x_difference = route.x - new_substation.x\n", - " y_difference = route.y - new_substation.y\n", - " distances = (x_difference**2 + y_difference**2) ** 0.5\n", - " \n", - " idx_closest_node = np.argmin(distances)\n", - " closest_node = route[idx_closest_node]\n", - " return closest_node\n", - "\n", "\n", + "# %load solutions/advanced_5_2_find_connection_point.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "263818f6", + "metadata": {}, + "outputs": [], + "source": [ "def connect_to_route(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", " \"\"\"Connect the new substation node to the connection point.\n", " \"\"\"\n", - " # Create a new line that connects the two nodes\n", - " new_line = MyLineArray(\n", - " from_node=[new_substation.id],\n", - " to_node=[connection_point.id],\n", - " from_status=[0], # status is 0 to make sure the line is not active\n", - " to_status=[1],\n", - " i_n=[360.0],\n", - " r1=[0.05], x1=[0.01], c1=[0.0], tan1=[0.0]\n", - " )\n", - " grid.append(new_line)" + "\n", + "# %load solutions/advanced_5_3_connect_to_route.py" ] }, { @@ -383,30 +288,24 @@ "def optimize_route_transfer(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", " \"\"\"Attempt to optimize the route transfer moving the naturally open point (NOP) upstream towards the old substation.\n", " This way, the new substation will take over more nodes of the original route.\n", - "\n", - " Note that a node cannot be taken over if that results in a capacity issue on the grid.\n", " \"\"\"\n", - " # 🔗 Trace path from that node to the current (old) substation\n", - " old_substation_node_id = connection_point.feeder_node_id.item()\n", - " path, _ = grid.graphs.active_graph.get_shortest_path(connection_point.id.item(), old_substation_node_id)\n", - " print(\"Path from overload to old substation:\", path)\n", - "\n", - " current_branch = grid.line.filter(\n", - " from_node=[connection_point.id, new_substation.id],\n", - " to_node=[connection_point.id, new_substation.id]\n", - " )\n", + " # Get the path from the connection point to the old substation\n", + " ...\n", + "\n", + " # filter the first branch in the path\n", + " ...\n", + "\n", + " # Iterate over the path and check if the route is still overloaded\n", " for from_node, to_node in zip(path[0:-1], path[1:]):\n", " # Check if the route is still overloaded\n", - " capacity_issues = check_for_capacity_issues(grid)\n", - " route_capacity_issues = capacity_issues.filter(feeder_branch_id=connection_point.feeder_branch_id)\n", - " if not any(route_capacity_issues):\n", - " break\n", - "\n", - " grid.make_active(current_branch)\n", - " current_branch = grid.line.filter(from_node=[from_node, to_node], to_node=[from_node, to_node])\n", - " grid.make_inactive(current_branch)\n", + " ...\n", + " \n", + " # Move the Open Point (NOP) upstream\n", + " ...\n", " \n", - " grid.set_feeder_ids()" + " grid.set_feeder_ids()\n", + "\n", + "# %load solutions/advanced_6_optimize_route_transfer.py" ] }, { @@ -452,7 +351,7 @@ "metadata": {}, "outputs": [], "source": [ - "visualize(grid)" + "print(check_for_capacity_issues(grid))" ] }, { @@ -462,7 +361,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(check_for_capacity_issues(grid))" + "visualize(grid)" ] }, { diff --git a/power-grid-model-ds/helper.py b/power-grid-model-ds/helper.py new file mode 100644 index 0000000..1d9ad4d --- /dev/null +++ b/power-grid-model-ds/helper.py @@ -0,0 +1,53 @@ +import pandas as pd +from power_grid_model_ds.arrays import SymLoadArray, SourceArray + +def load_dummy_grid(grid_class): + nodes_csv = pd.read_csv("data/nodes.csv") + loads_csv = pd.read_csv("data/loads.csv") + lines_csv = pd.read_csv("data/lines.csv") + + grid = grid_class.empty() + + nodes = grid.node.__class__( + id=nodes_csv.id.tolist(), + u_rated=nodes_csv.u_rated.tolist(), + node_type=nodes_csv.node_type.tolist(), + x=nodes_csv.x.tolist(), + y=nodes_csv.y.tolist(), + u=[-1.0] * len(nodes_csv), + ) + loads = SymLoadArray( + id=loads_csv.id.tolist(), + node=loads_csv.node.tolist(), + status=[1] * len(loads_csv), + type=[0] * len(loads_csv), + p_specified=loads_csv.p_specified.tolist(), + q_specified=loads_csv.q_specified.tolist(), + ) + lines = grid.line.__class__( + id=lines_csv.id.tolist(), + from_node=lines_csv.from_node.tolist(), + to_node=lines_csv.to_node.tolist(), + from_status=lines_csv.from_status.tolist(), # 1 means active connection from-side, + to_status=lines_csv.to_status.tolist(), # 1 means active connection to-side + i_n=lines_csv.i_n.tolist(), # line max current capacity (e.g., 200 A) + r1=lines_csv.r1.tolist(), # line resistance + x1=lines_csv.x1.tolist(), # line reactance + c1=lines_csv.c1.tolist(), # line capacitance + tan1=lines_csv.tan1.tolist() # line loss tangent + ) + sources = SourceArray( + id=[401], + node=[101], + status=[1], + u_ref=[1.0], + ) + + grid.append(nodes, check_max_id=False) + grid.append(loads, check_max_id=False) + grid.append(lines, check_max_id=False) + grid.append(sources, check_max_id=False) + + grid.set_feeder_ids() + + return grid \ No newline at end of file diff --git a/power-grid-model-ds/input_network.png b/power-grid-model-ds/input_network.png new file mode 100644 index 0000000000000000000000000000000000000000..f3f8732f06fcf4079520bc65e1cbba717a995dc0 GIT binary patch literal 79518 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 LineArray: + """Check for capacity issues on the grid. + Return the lines that with capacity issues. + """ + pgm_interface = PowerGridModelInterface(grid) + pgm_interface.calculate_power_flow() + pgm_interface.update_grid() + + return grid.line[grid.line.is_overloaded] + +print(check_for_capacity_issues(grid)) diff --git a/power-grid-model-ds/solutions/advanced_4_build_new_substation.py b/power-grid-model-ds/solutions/advanced_4_build_new_substation.py new file mode 100644 index 0000000..1ea9f8e --- /dev/null +++ b/power-grid-model-ds/solutions/advanced_4_build_new_substation.py @@ -0,0 +1,13 @@ +from power_grid_model_ds import PowerGridModelInterface + +def check_for_capacity_issues(grid: Grid) -> LineArray: + """Check for capacity issues on the grid. + Return the lines that with capacity issues. + """ + pgm_interface = PowerGridModelInterface(grid) + pgm_interface.calculate_power_flow() + pgm_interface.update_grid() + + return grid.line[grid.line.is_overloaded] + +print(check_for_capacity_issues(grid)) diff --git a/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py b/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py new file mode 100644 index 0000000..d3c10bf --- /dev/null +++ b/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py @@ -0,0 +1,8 @@ +def get_all_congested_routes(grid: Grid) -> list[NodeArray]: + """Get all routes that originate from a given substation node.""" + grid.set_feeder_ids() + lines_with_congestion = check_for_capacity_issues(grid) + feeder_branch_ids_with_congestion = np.unique(lines_with_congestion['feeder_branch_id']) + return [grid.node.filter(feeder_branch_id=branch_id) for branch_id in feeder_branch_ids_with_congestion] + +congested_routes = get_all_congested_routes(grid) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py b/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py new file mode 100644 index 0000000..807ed77 --- /dev/null +++ b/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py @@ -0,0 +1,11 @@ +def find_connection_point(route: NodeArray, new_substation: NodeArray) -> NodeArray: + """Calculate the connection point for the new route. + This should be the geographically closest node to the new substation. + """ + x_difference = route.x - new_substation.x + y_difference = route.y - new_substation.y + distances = (x_difference**2 + y_difference**2) ** 0.5 + + idx_closest_node = np.argmin(distances) + closest_node = route[idx_closest_node] + return closest_node \ No newline at end of file diff --git a/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py b/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py new file mode 100644 index 0000000..e69de29 diff --git a/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py b/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py new file mode 100644 index 0000000..42d981d --- /dev/null +++ b/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py @@ -0,0 +1,24 @@ +def optimize_route_transfer(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None: + """Attempt to optimize the route transfer moving the naturally open point (NOP) upstream towards the old substation. + This way, the new substation will take over more nodes of the original route. + """ + old_substation_node_id = connection_point.feeder_node_id.item() + path, _ = grid.graphs.active_graph.get_shortest_path(connection_point.id.item(), old_substation_node_id) + print("Path from overload to old substation:", path) + + current_branch = grid.line.filter( + from_node=[connection_point.id, new_substation.id], + to_node=[connection_point.id, new_substation.id] + ) + for from_node, to_node in zip(path[0:-1], path[1:]): + # Check if the route is still overloaded + capacity_issues = check_for_capacity_issues(grid) + route_capacity_issues = capacity_issues.filter(feeder_branch_id=connection_point.feeder_branch_id) + if not any(route_capacity_issues): + break + + grid.make_active(current_branch) + current_branch = grid.line.filter(from_node=[from_node, to_node], to_node=[from_node, to_node]) + grid.make_inactive(current_branch) + + grid.set_feeder_ids() \ No newline at end of file From 337dae586c7ebbbdd3372ec7a0f08730352b2e09 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 15 May 2025 21:25:00 +0200 Subject: [PATCH 13/24] feat: add visualize --- power-grid-model-ds/introduction.ipynb | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb index 9711b60..e1ed7a2 100644 --- a/power-grid-model-ds/introduction.ipynb +++ b/power-grid-model-ds/introduction.ipynb @@ -17,10 +17,20 @@ "We assume you are comfortable with Python and Jupyter notebooks. Before we begin, make sure you have PGM-DS installed:\n", "\n", "```bash\n", - "pip install power-grid-model-ds\n", + "pip install power-grid-model-ds[visualizer]\n", "```" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "86c14151", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install power-grid-model-ds[visualizer] --quiet" + ] + }, { "cell_type": "code", "execution_count": null, @@ -396,6 +406,18 @@ "print(\"Loads:\", grid.sym_load.id) # Expect [401]\n", "print(\"Sources:\", grid.source.id) # Expect [501]" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49c3e647", + "metadata": {}, + "outputs": [], + "source": [ + "from power_grid_model_ds.visualizer import visualize\n", + "\n", + "visualize(grid)" + ] } ], "metadata": { From 569905b9095273e03f9349f0cc5b82eb9ebdce77 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Thu, 15 May 2025 21:29:46 +0200 Subject: [PATCH 14/24] feat: update visuals --- power-grid-model-ds/advanced.ipynb | 21 ++++++++++++++++-- power-grid-model-ds/input_network.png | Bin 79518 -> 91220 bytes .../input_network_with_overload.png | Bin 0 -> 79518 bytes 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 power-grid-model-ds/input_network_with_overload.png diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 62ade1f..a24e3a7 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -128,6 +128,14 @@ "grid = load_dummy_grid(MyGrid)" ] }, + { + "cell_type": "markdown", + "id": "4d2df7f4", + "metadata": {}, + "source": [ + "![input_network.png](input_network.png)" + ] + }, { "cell_type": "markdown", "id": "6ac4eb43", @@ -169,14 +177,23 @@ "# %load solutions/advanced_3_check_for_capacity_issues.py" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "1774170b", + "metadata": {}, + "outputs": [], + "source": [ + "visualize(grid)" + ] + }, { "cell_type": "markdown", "id": "008fafb9", "metadata": {}, "source": [ "# 🧭 Step 4: Plan a Relief Strategy\n", - "\n", - "![input_network.png](input_network.png)\n", + "![input_network_with_overload.png](input_network_with_overload.png)\n", "\n", "Goal: Place a second substation near the overloaded path.\n", "\n", diff --git a/power-grid-model-ds/input_network.png b/power-grid-model-ds/input_network.png index f3f8732f06fcf4079520bc65e1cbba717a995dc0..6090091d4dcc4e0b32ec029e1222ab6c069b5c92 100644 GIT binary patch literal 91220 zcmdSBg;$kb)IF-AproWo3MwE{0@9&?(t@Ovbayw1NQsn4*NX~BcQ;2$x}>|L<4D(C z2fy$B{(yVO9pf?vLpiaZz1Oq%iaF>b@+X76CGYj z{rH*{{<&(eATDwxubW~8{ zktQkjT*>9_`k8a0=8EU^kykfwl>Ty}&r7OKY_>QKJ%UFHv@c%whks^L>sOC9(1>;# z9;@zichp|1uA8b}+e2UDYcG1JL69r<+DDJ*(Pxgt*()4ZjBb zT8yb3qy88;NZx}iuuQP4lu1))EVHy2Z$S!p2x;%(-@Lwkau%DusVFF=Ih>}DDbEs< zy_IV@PU`>K)B4Oy*yq`ml%4=x(o$9$T3S0*Sj6`{-cZD^Uzp#%eap$onc;c0=bT)A zwBxezeVh%OAn3ZUudjonBR)2Ic70@kT&9wql~w4@j&1*n!=B(G-B!M7d`U@3f%k=% zy1IG+Q}!`Gn5jAy%;eZwX1TPy92XZy6D9SUi6na{n_rg{J>8Vx=Jmj4JqIVJ{(%8e zPO@A|M!aW2DaJ-d{zpfyMWak<3b%$Gw^q;gjyyhy(0p!xASfv4;NUQGaAF?tF)(oA z3mAM5XS_^JOUuy0;?v@yA!8I~^0G4hOhmY(wCFqkiWHYYai%#0JC5Cp0GT`yI^*J^ z*K|paHWOPaqA~*y;$+y_*q*7X-kG(jSej-!5G{O@qmr+XIp{e1ixcPbli(%)D?vZP zV2}p}vsK~DBL;R{cZ3nLyDse$?{#{QFn@P zPgB#iytTP17XPd1x@^6aO9Rux%^lR6>E-v|UnOl>LTf-aR3G=qbT4J+vm(j81=?4T zkEDq2^qg4DNIf8+5O4|4%VS~Yua?ssHgs}|j);g@yB4kcu7{o1^+99LnT;^DOL~-8 zXZ_LCThFjjH}CwqRt~Hi=QAC}r&HS9>|BZswPZhJ2YzzO^6~NUcpS3f;NT2j(7--4 zgB{(LyyQy7!NH+f<&epD3*(Q;t?iYqwWUbvbvtK|!}(ii@`!6}u#hYbd@8s~KsTK2G&Y=K1n-i=(hJ`(bGHLM0V( ztG=C354ERj==9ksQw+WRNNB+HRz`h&%IvJJUg4V!MZ-G_cDyXwb)5?f4;Jn2rWh8~ zvo?i!mjqBBO|cyF-#_$h*+3veTxP1M496F9gCBVz<v^20IX8B~8sYJoW#nrZG_fzkQa+%ZU@iCuu{TY{{ zqT)zdh~Zt2dH4bu9TKIezkjr3~7act~=cRgrkTC$<)>Hz1>Ls|cmuN2g;3M$m+c9n2jZQG2B-$cLA*Z&rc|1q%5 z5l)4HoGnEF_zSoLGD0b>TO5Z$VNS^Diw$1^+aFg`wx(qLaS->Y_H0j|eKu)p{o@e2 z=MbmK5@4v7<+1)=A@k?qAx~svVBB-Wfbe{`-Ew2O17yS zHZteJ{GW54Oc}r8`=%cs2JG!Q$_#ujEPOqAvpiEF(`KdrAx!&|<@oheI^mO`w_Yps z{w7v8H_eFGjARD>tE6d|P32iz!L-)ymd{gSAPE+u#h(MusVFA){T2B8w&Vz@v0(Bk?OL$?a_6+LQyqNjGgqwJp784;H><-0xgh@QDbbXx6*cQ6%wz z;QBS6G2=F7I3+DDEpIe6e;VKQnDeAOos`4tpC+!&r!f!KC3PtEH<3ELo6_~9_|11s z7D7xv6Em|a)}g2P_^uVEPbve~Z>>1QgDaLwBZxNKPF)^%IS)$5AS}vb$L8s!o^KWE zM-T=OfEAjWL`vuAoUIHE(~hS%4t;o7y(@x6eRnVjipt(ZHwM$IA8uo9h#^SQ6oR6n zh#}5w$m8Q@ib6=;Z7a4+0KY(T=gy8m7@ojDr}*^1E78+N)exD189(}Xm;J(**SsRZ zC9SS9R%+%s{g@Dg$YN;d=OGk!Rlu_(!kF5;s=nj7H7)+$&g>m^*PV8{E78%>v2k&! z;Qw)n@gw-Yff2)MEV!ikl3L0v@dE)@;zK9SUS z%dRC{=zq*`W)HUdRbw!)9=}LmMt*s0wPC&WOGoa@nP-Cc*6xu&oD6!atyw@&pakV; zn)PG+2#otluOizGY_wwPLT`&7G)uOel_EA{*IYd|LWs}Lg@ros&X)64sq2sHYr8U$ zp5D~vpyA864+=EycQ0_p(p)=IbX$+sq|5aQJG&xOl(zx(nB`5?QOJF zT2{!z&<#0=0A;?lYE*e^Po5+!$F-6jb!dBsVx^p2xg&IP)$79B)Biwd=zXCtI`)bC zH*5#LC!f0hD0M5BuH~KADnX8zX^q;<64^?OL%7ywllXk<+%Zd* zF_!KIyIiujgdupSllhi#qMJ$_-deY5S7+Z`-j+`cUAmXN9MQAVVls3PWk!uw%Sy6)6l}#_P8g$N={q;dBKEgLI-KcPoKK&OxS*1Y$GvTj}Viv zMaH5snd%Q>I5_EjzZVe~xhB+~=!-gNdwQ3jq{X(6om$sB#(5u)>sKT99gjW{HY1y5}7!V{%NZ*_2KJ0xWV%hbb3bH%Du_#I?;@ zjmbRb2N?^0gr%IN3V|E0dHi=Ggw@+U$op^pOP9S)zKx9y3SPSp(a|IohKL7wQnou^<7u@w%=eqNx-qCd_hnnZOmD$aNc zd((C0$w6rJ&3L-&r?6Ji9a^8Yr-YMHZ6iu*4$3_GKuMokOGb+5&KK`T3FDP zQ+n=^7O=^p^&mG*E|LNR*R}W)A_4;ibn@0z4jLi$c};iIb)#v$7CMWtO7^Y^vT36w zWn0+@yd8EdvCPPCg+>*89Q1+vF@;xglXwc_c89Rik~@{X>8pzJ9KE3gspeFLQHuzw zTWVq={Mp#D-HVkx$+Hd5J`o0xvpFBt7aNitdZMQn9v$qC)hE!>DtJTQun=KH`toV) zNLj$Vg}2^X)pnBe@1w|ibse)*`LoJ-Hy5fyCPI4*EsV;lnjD8xMipC6k3E_2>Eq8~ z$VhZzcjNrp;X@BPuM49J#%M~Z#iS(Z(gKCKq{ny9o4w;_^y~jJPG2}{&uX8Z^T2*9 zK6SomWSXp7}NF zobA%BobZnEk+P12J6vsdEdAYRKlt*Wj7+qBkzD4gesFwt)nd43)Hc}ryzyQ)GD5kwd(PKd47W*8E1gSe~1uRc%?0aj1#VJNPBEg zF?na+`|!y3bo;<*2zR_pVRTXZG{ZJ}Sh~6&`+j8cQAWL^-^E7x%OOX3F)`F_?c-u+ zZ$h~llHk*`6w(D%Z#Q8|=5b5JrVqyGdqh+wh5mq=CLVhAee8o~iJwj+MOV(dsAYHM zy!1b0`q4r)N+IMCYr^R^8Owi5GhdtisMz`>PHS|Q`VUQX`x1})K4l9%-HIvR4xaby z6=7u1`Izqb5+BvpCqss4iqK8z+qG5BR@K@c*D~2JI_j&NE{^#1W7AVa18{9;8m=-^ z6X9nnR&~+QhH=(UYioUdTKz`HwN{CLVUrZSupq3}pU`8yHtBTcgwJ(O9+CGUM{{ba zU(CNUs!Ld(hk}mOS$K6dlh%%@2E&=#{G(z zoZW3SkBe@MNac~ElG?23LvQF;52{SN7P_IUMk16VM+3Ju6qQ5XXQm2MeJof%?ZMH%t{Z<+*9Sg3WLm8^^{Xj8Vs3tt>5>k!~`NJQRm1AqV#~G?U zAh`9lkD+YdR+kB^Yq3#4S;&Nz(lZftaFA4pZTzy|f6=#sFS)2R|SCKN{y3MQaNjed4PaTeobl1owsUw zg366WOnQYQI0wd)x5jGS4-%t2^bq1==kh)exly;bWVTU&vDt-1UUR;W zZZi5`V4!B&Wmf1S@JfKHl?{6-TKcq^o5Xeb7lN?N4uaI_5^a8xM(f^x#l?~P`%X#4 z4j52MWM>D5hT=BNXk-i@1zR(P{}K=&AA&Fm`WlbT=X$0*xBd^ENxU|PnsUgMix3o0B%}uLoJ{!r4bhNbYeyF1Tu?d|Uuk(S1~lF^-UIG^A7 zM6iCc)}?y+uOE@Nn`6+P!;O?4adY#>FsRuY3oY#%@i3~hQWQufV1|uo;FM*L!yeTP z9Ze&stm(4R{#3TKvEetCDbhDP?P>LK`gp+fw<0m@P*G9QlJatMTCW&bQRsa5tBm$V zX&F``6PfESr_TuLw;CrnJeH;6FObeJkHCI~NnK{Y8yenaMbXk;gM6we=7UH=z_?Md z+O8ihp}nif^T_+6wsU<6DXNaFUpiPWj`8RZ>%EK<{T2zRdWVNw;k#9RmcF{A05U-e zySBDQ^byzirNZ^oCA3=_km;TeQOj&sdq0s*T_6Z+9R(O5DJcoF?|&~x>fcC+plR|- zi1Wif((^;=-(?K#Xguc$8acbgbM(H8+S4%9`z(M^Gp^fLw|{!N#|I4~@a4DoK1`Fa5&nOgIF&bz$%^Bu5sI78{#zA0HnLs%Ol! zw0kd5b^Rys&BCXjTMz2#8_mWR`(5Ha`j$G=I3cY^c)nIA+uC4n0(5EmtexoM#5#9W+j|>Z-IX*c^2NXS@rjJ<2c@@90@NIX3~vGMSx z_htuZX^RdnJ*4$x1IkV39W@=&-l;$Hz4B;lYQ8&h6mU~k{Aj0LjgzAG2qrCQ;y+gp zymvRO{b^j!*K_fgm34<+TSJFgxsgq#s=AsNfHF8+tLzoQ*ob=+xREk+g_b9)$pQ)G z`35|WUd7e=#^!-0F3#76AxK@!9kd=9U+8|>s)_t6Z+FX2WPQ9`uH*R&v4!-@>_vsV zs4O=9x%sy+dR(s0%*S`*I$twHt4;pcZaKm^U*&)NMT*5z_BkyLR!3EJP|=!8jxi(Z z%%1nvlg&*5l7c5(m} z{N{1#3-HXOto5fwswblO5#o(qBEO?$re?6LV?B0oNRu>Y`_rVESXt3@;?Q?~ywGpz z@i`|=Iedm8ysdyi$()dcWlg7D;JVmJR)27G_f?WyVbN=&`}&G`6(~o(zcnpqZJkdy zd*HL|N)-GeJtN~TCFR3}u4}iq6F7f*ay~pu6zFdV^Zp)iC)tFStkN;c+%~OE+rvJh z$ICG}qMZq_m6b%_c?&P)va&Ke2+w04Es!*{R2ap?di;$Q<^*0Tqh+#mk-C7u!b@f|>>*vf#9>E&OmO@AC~A(Uj)VM} zHGA%R?$v5ZE5~X-Dyn&#F7E&pQgZp|MnPd=L|vT_96E?BW7hPvwB?rpB(WMtjVeL; zVGj~+Aixxzo!9`y8WgKtBG|g52~jKqoNTge`6}N8dJuaJj)D}<$doHWDPi&qV&dW$ zu=yWEN-}jQ5U*X`5y*G@u`@VGgoTAggn7ea+&{ZRlGz@al3rLjjMcCwFp<5LJ#Xdz z7{Lad0Hg+PZf<`zH|Z#F_2ZrEv0p>DL>*)S1>C)=)0v^o_vM&s-h0t67{#9&XqlUf zyvP7OI`xA7ohUt%i~cjI59hij&H zdg;l;Jo|*>iKi>DLeA2tt*h=#R&>7lNhErrGWAsqnjlO1t&k^S`e-bIxyR%8X=$r3 zKP465MpR^Q@U&&-&pSmN75_#fQ<3*w^5M5bn8d=KBj`yI>)-` zFGy(C@~4VMBF%o2D3`)b;hvm(EH1V%m0f02|Dx@9?vWqUXkD(E%9bo@ zJj$DwlhHzfmUx|wR4`t7rRKH~jk$T{e{j`d`HYT6s;%gu9OjU|Y~@^%GfP7Jh@?v2 zd`eh?v&~v!j)qcEiKe`hS#kVg?|_}LG9y9>LjZq3?EfJ6P8e#KbleL~Ey#p4N@1v;2@_81-qX5I5hg?m)-etMur367bu9?Ltp0 zk?Uy9o}_~u{fgnZ&O^iSUs~J%DJ_I%etk%L5CZqlnq1AdkJmRMuB-JlOLBAyTXFc; z5)K_n=W0dJ4T)uQao`XqcmbNLWF;zEc)l%QqxtRFMr+$@JEmi=!8V`T-B%a2El^D1 zW~Hd0v&*Y!5fr1ij*nV}9OdfX;USVs9HU0VKgSHq*^dc0#!)oXeor1%XK`_8Kp5BZ zKi48J`b}H}Ij{j93J7r*p+OOkt0;1Ey$V&#d3P_F)Vt4zE6cY5OBqos3)gcRGHSEq z8QYqv?n};j-x%}ikpaxMZ3@M5R=>O)!Qe93V_sf0VoL#rrX08Muni86QoS7K7_}Yv zi|!V!YXmSot-FmXB2WnGczQUBDYeswMHDe>Fi(U{Fc}bI*Ex(Wm>XYC^!quAjnW!7 z^RWFs-RNB$?)VGd^2{+NLM`Ke-hGX_2!5p?%6|H&jKj&XawbGXrEIK8>)#3!V1*MA zx#5l_)3v5;$6wVeg28z2P_G7!`{lq9gFi2+h=u6Q2L_&MmtR}pLm5{Q6+j$*&E;QS zQY;TOac+kU8tEvMkt3Xe&;?xSatfn&QB&w{gl#YAjtq|)O1}KaILabfz9{?tUi#C} zB^tetGGX9EGECszzia2AKGP+rR*t2X!CdF0@^1pKVD*EQFzi^8WaQSi} zf2M)wj@dlcKeO{^{P$2HW0TXs^WT~m@*wRQO!XCH5w=Mn+0^DU+}SH8F&~S(v^dJa zu68yicOe49_NouhO6$+8+K$K6lu>3CD+9;!J(S_!B&op&j&nLaLohi^HC2s@$Ct0K ze|jG+LCNDHJ0IMTD-unn4GRif$GpKDA-EYT68+D@>x`(sbI6L0tqD=55XLr8g?X*N z#&FjZ+V8X!`Cn5I!d2YmOLv-cqp{57E^mh*Sh}e7-z)@NQ17>0I)LQ~b_36&lIG#d z9U`{*2z3oTNbgpht?m}pIko61|Fd2)*c1-I<&vmaV1Td+eq6PG8%u2S4tz~~gfbw9 zgCyJZpAAnSbzZ=CRQ=z3dm@GU`}^f4-L-)m?JDt<{vK7{*~*Z85$qGwe-lN6iSFLU zJf1xZ8?Uh$tYopU^vn4M+opsbb-osS;IO&gbmVqlU$Z;y>|w zjm1=?9SCl2?<`x4kz3oVxfOhVU+;nFDW58ABQnDXY%7H{2dDysBz_S)5f-oA5pB9@ z_@@^Qcj&i%-t;4f>IkF@qQD%Yq!$w+AU3eH3>g|y?qA`Ai`!Lxn&*MEZmp^!FW59b zHa*Bt4MOzv7Ck{wxWoe!Q`6MU%pe`MHz&Kpw~lA&h2&>FTa(6BN@mPPq{uza`GwxT z9wDdY40GdePIFQo^#TU#xRVOtwbj8@wx*k~z+mTwUd_>XP|ARuXqkB^6e zX~;sR_GAgcDZo7-XCT7t?CN^L&o9lD02&LOajxX$*~wXdh5=4sU?C-eau%goaB?ER z4Y1}hC11BW`g>v#ic?WqUzM7MOQ)@tnvDERqPxfu{Nf(;)OMpKiP;d`vwPp zLb(dH+?(jqN{j6?;;Dnf>KGgrOH$25_DVKO_F9Y2b!2(Ji2WYpzmuUuKniVdZ*NdM zYSyp{xM6>gQ8MrEhVwdxNlRU_IWLi`!Ep5%?i~S!=%m%XYAA8sXnOn#v8O%kLk5<) z-$+~6y}ft)ztmJ8Nco|XoOUcmxdwGG*8xSVF6d>zTySFxEy?S97J7BQP@n72Q+w5g zOm*KZ41B?$qpMbq#~nKVnz7md$;Bakqi#F*;rU^{$9C-mQz zTNIGxrOTwNav_wa1L2Z+%#7OEdZY&*+Cp_JP=WTsQe7{*z%=3dU zV2bTHDjRQG?FD}k$7uHHGAl2Y7O#0M1s8jqbn<29gqX$y%65Ema+i#ZmI8OU?n7YU zO$HOmT6>Cs!onvlt*z|_>=k*^=HF6MF8Zzt?VP`I<8OMPf6kAo%016Rm1*G@wa1=v z)P!BXS81Al=Obyl_=rPI?J6mN zOSR#Vc|efqSq3~UB!ijK8c{hgQ+O}>7PV(#i1+pY!ee_>g>3HXCrb1j@*scDzs@g4 zhRO8>we;KyC4{u~90kQkab~d|Y!?vaiCO6y8u~><;KM0wwCAl7?#@45xGlU_C{#5j za_GVTLvK>7!McBnVxi#~_PfG3iWQ4EU~_dz0S!L&^4=JL1Pjn*Nv*N5$f$OM0-3{R zxjiJ_`H~l?DIQSlP7Wl_AH+G7`Md1Oqaiz9%(+l54*`L^gmml*q&YJj`T5SCo_QWzR-w^0FrrX0F#UCYIm`fjj*))P zebhGSkvy74dnAGnI45m{{F+IGIV^a6or#c;5DL>{KGD;r4z$w|aW@IEvx5@MGZyrp z_u)P?<)krc#Os zNH$pSg8T8>)fZgf3ZAKA0posG$Q(ifn8L9b-rdG0%6C4gs!=RxYJJh zX`vmTS5*Ar4M+J`d@` zY%y1YBNG#oJQE2@0Vt958rB53!5ejT+L#VqGIVOUx{!Gc0)CJjm52Gyh4fh z{%}7c!UWf7UPR~EV@m<5k$jaPfvF1_4&lRd+|PX&8bNvNIzQ-}PExE=>p38~u&}TI z+}T|Gf3JaZ3Mi-75s^x|<(UwPl%sP1TqtZc*5 zz5n+YYzX*Lq7wo0JRlhYSZ0GQqN>mlaaG4#`^yFlp`GYQf3<9EH z+>6}<`opHj!91bm8_Wr_;mw7!*Abox#4AdSX`8TjP>Qwv8j;jzEHMaMin-Upb=_=1 zlQ{L>!$OOp zchP~!Tt4*aqNA+T47K3O_UD2rK}Eh_1GsdiQWH`D7yIX*wNEoh%ZvQ;)t7PhF#{z} zF?iXDGAe1FX&c8PYWDn`PpcC z+x@Td3`+C@wUoN?pZPVoD&iUSW6||Fc+X>|YdQg5A2`ju*pWS-Bgay*aBfY)CMWdz zI@?vClBrZ8F1`A@RQKWCgTC02+1a1y0ER+fd6?jQ=nKjX!1)cC24?QFmJwFEOsa=|B+&9Al;>III(xn5!kkO=w-bWXT{-NX z#%1-R-x}sMyT8Xmqj9f2_*!SC+*xJ`p-v-8>c;q#W_L{Bu~W%{bFeOip#@B?$K-~f zE&U{86sN&B$HR~H!Yk!@ueBc8j4M^>Jf#1DgHLWSk0SGOO&rUvqvS)Pn;(}gH}_mt zP0&!bqsM)^y>sByKTfqY5ygpo%s;M390oFkI*q=uc$1HV3FeR0cRTxw`rxZg1?AT#t&~ktGdSud`yv*~;v5D~3$<0IO{b3g2u;^n|eWkyh@~`tPKg)834YE-=n;XXh@L{*_oA1=G%O?3_3kS#7&D{`bP& zJ{%!xn=CXIsN3*Y&nHRKD*aZpsZtELTXM#lDxA6vibH*a3QcIc5H9r|0r(9SQ3 zx!L>`y2MY9g<#yY-K7V;wgPrH0wmgKJxa++wT`}uRu&yqMH}kISIMLasYNT-Iw4;K zh}aqrTNN&B2WZF7a|`pg|2kf>)7vtmfBnv;w`t^gv^_=G$BjAHgbqT`0*|y~L0NTQ zmV;*$3E-;N#nR_*eo?fU>)m`lrB83T&hF4n)g>;0U5KP{r`^n>kl#$vtL{5+T9+A3 z=YfVgwc>6GWDbsBA1PSpot>n#j~dwVYrI@5mce`&kY88UnQg3MOBvP?saAKm3gCJB zY$FIEH$QH;eEG$ax2Eh1)#M4BP8mFUUOq}cRo6dU=w|aW3wa97TjW&!irAM{aiGw%6!71Z; z$IO{r`K2TYG`mOb7yCpPhtr>W2g+OpM8!M0tv-*GNmtIzRq4d1GlDArpQC}jp_*>T zloxFlFhQwboVDk>wYDI9k?DEL?Y(xT{+I)C+J;g6#{y?4w9dR^?IF8rwiTrFJ+K>d zExxFYj%aR{TcSgL#FampGSTC`SA23blyY|omBNCXKIP}p#`{kRrJuGKMsUgkV2_f0 z>GPkc;JaS`Id4lFanoNHmDJb?$?cdmn^c3U6Qat@vqXp%JOV@+nKbg2dWD4Z#jYg7 zT=ZXNZDOD47%zJT31mSU6CrWEqv%b~2pk@@x8tKB1OpQ_PI%ZqU3P8IK%n4I;=jFB zAc@;B=;6~BN0B!_dvF3!Ih6Udjuy+)Otg5s_0w_>2pX4>P+oL0kw|RWF8> zgM&9FpK@3Jjht!)TfDAU+6Ry)NNV&mo4N!3EFSK1P`OA2IWSvHUY)k6xz0u`IFF+C)k<2#3I zirJc8ZToH>=Lx~!9Ldr?O2bHTGN@q%5o~`}SHD(QlOxzFc_QXDtn-RW5b31VD{u}y z_Op>WIjZ0%V2P&QaD2eTXQ0oi$jjQ}Pf3~0mCoGACmwsTr74L7r9kXkCKXX#kY4je z2We^vjZ93)aFV5I+8!NeD!+9#$2p++VV1^DTxaVRHE>6vf(n+_KQxq<@PL*UAlyB~ z*1^E^v>Y%td05&<`|RH5dwv*R#saDZN9(G~t{W44#N*$9)w)z1BvB?a7O4Wk1G<3R z+}zmo_BMmi9uM7UZr1N+0aL0`A3N@7Yt4n#v&-=r15smYW%ax0IX?c?20pjHfAWXU zs$&{0wmtV*OQ9euIe#rfP)JT4b_=qyB(sQlrm+*_b|-R>5G?Jg-PNGlYb zf4;~obQFX_q-azCD0%^%3f7m3yN!uY4?+gAPp9koTN3UlR^&Yg`-7lhXo(W;$u!)P zyx4R}2BNP@j1e7+BN8!jYD{c{l)69os~%(EPG^4H*d5L9MzVT)e~xI^d}@G$i>re7 zh9p8(gB#jt9!9o@cSXTgoiCp0)k%D_a6TEkEfB^%H9C`WF~y^O(#_ahByDfcadNPg zk(ntuoOg*o4}ODP^MHURrX!+j>5X(0uW&RC)y|V%;)kRa2anCLUIYjq{}QM_kF%Ys z``qY+QjP#Go1IqOCJP$~^fyQWz`dYwgYu1d+z{2AaXOX4Ydp?koj5%+EX>iZT~{Q- zwbk3(+i-q%va-JZvuM-XP*Y5d>J|7Z=d#UD;@@7Q#JLusP?>`OYFmwMg!rKw-d5-` zCRhEAcqGbT-F`bvX+_eY;DD-{lbhT8E1eydP>OZ&qnDL3d`WbX**1oZ9lzY-lK0s* zx>Cn7*0b{K>N+nDxLJ{^(`pZsN^b=qP#Dtia0a3o_-{bg6=Hxw2W8I9>yYLWeS85y z?j>C@=sEe+MK~W`i(T4ex#|X54(*Fh9?++8e0sH9NC^m+K5)|@4A|%(s6+$A$c6`U za!4}SD={I{F(SbN9otxfX!YB;WNnsRcQ^yX-qwl3-In2xc>t>0-xwFy)}~JFt;KPH z3hxgp(>5eU2jA%;;N{q(k{lxA7ZJpiUtjyGY^L`&={>5Q4F((D(AEisi0R`A&Wl!W zipAi3mf`{hbi{YK9cUQ1y<=lp)w8tDCfSUWBO`%^YN`hoQE_jXY*tUvIf8F|ej+T3 zbM>@t1B0apDPe4h68>KNEf+tktxsG8FJxzktO$f*lzFJa2Y3x^?|6NV} zv0|Yhh>M`d#q(qzv;Y9U8zf-*T>~iaQ&<>O2TyQJ0#8=9Fp+bSvZvb^)u^~I+dHYH z-(mi+ZodW7dne?@tE6ciw^WI`KcEG%w6t8Gu1^7_>op&YfgOPIsk|UssBUR4+wnr# z6qlTAGq z6RLHG8CI}I>6_Ixm}QAn&grR){W) z6YCUr)(A{Zz8Qc%Pca$uUp|M7ev_Oc?K6Q@gsmVKJMr%UVvrYpl3jK&=0vm^L2qN2W5;lTPZ1G28U=t@;)3B{S(n>RXcZt>6!GS3r>{^30d zC>jJ-?-P~WJj8}(oeoYL%`m&>Z+g{`0mUWC@-53V@dKi&aRedI+L{&Qz$kg0P)am; z&^ke@EmRn&sXu+%49#+-rpc>!T;G*hfxb7ya{PZV{f=kV(5Ul? z^_WeTaDcOr2@5(EdzJ^NfM^><;qI1)gYK4f2a*XkvWUXzld3S*lrjcohXaiT-QRr+ zyL}myzd6uTE<(flmz-FDzSH`qu|Yeob0z(%zZz1$j==T7`qnOw&>y>k*0lVt+_O^H zAt;GupoG?ni5)N3On>4w>E=H0p#+1jv!E`z?D71bx4!k4r*~d2{x+r?#p<3Cib2-` zMh>#6Z{PYB|Gblyo~s^@JaFWtAeUDLR>%pZ7Y-Z@In$!TaOcie(`b6m^It7wU;i^8 zivySIR+f?F=yYkNwe%&O&x}gW6z=%*aaUtc{V}PwxsB_PoduVuUPjmEh7IB_Z5-KJ zcr_+^p&ACH#tD&rM=2$%SCNdjcQJSvfQDi7xSe?oxMn1Mj&tOeRth4z1h}418^=H#?7+8ssa2LW!C<#EAHxQ0;Z{>@B27NIleX;X z-+w+by|S}#-entcJI5I3S5&+Y?d~&&aux>JvxfQ|@ z2O7Mdg>_(wQ@-U{?VViLo6-^D>fPL3pY3`QaH5GVAoY)Tb%Z0az(sMVJA}M5H~x@$ z`=p`d9r*(Nz{F|oG{$@|9bqutqSOWhFnRc+Yp`K98_dQQHf}{O4&w9=;aC`8cZc3( zvid`S;`%bh<8OSNxZ3K+p^vWELFZCh?^!O*fv%5?&blOd9Z?)IZf?5l6cx9X#?V+B zSt4cmo3V;Lp3C8@QN#BdDR+6rN)BDB2C7i*{*IOEkiyf;?IYhyP|07O zZI&62V(@8Eo?n*mujOvi*Hc?=v9cGN_fHr4^Od^QZt+qB47(J!8 zZfIJx{@n4nluJPY2p!u{SE1SpV+bQoe%ew19|MBC1*9vj4?FWM@)T2O&+^v=Eoa>O zX0w(s>37g{s;>_k^y>)uGBLX@j`o3ndQ7IbZpJJQi0lx6dk@F zPX}GB$fKKnBB0!Z;AmoHMHeT-=nyo40Rg{b@r{OtKJdpVouvGK3YkjztqL-SB2X&!_Y*)^<$I2Ghy$%7i2@T1I&vSx2IUw`2yoR8J?V(Y)8y?K zqBWrn3JUoQ*6*Y#U5ZSW=$suzPza*Z0_YScBPS=W5OV^JC6q-ZBqXSr!?N`XZ@$xg zCT<^2k4Mi7h(a2Te65qO7vZq4o-1;!>y8D;?Q0w#bsZIAXLc^_S;y1$nS5DVGJ>9Q z$ix+AAj+Y{EtOR=HbzG2>dkQDW9b}9(Ou7X=%5KG!WYdJ_&-j%)9Yt+UMWF6#-I@m zUDF+>D%()Vs>sQB48TGKPx9ip@$ljPsH0KzM;=_D#=&?X354v&yos&|Ep)!1sHh19 zo6sQ(48Xrme3%|t-NMq$mXVZON2QIs{5dw%XUw^Oli1K~~2-fcEhQ*8D@!bRu{oULQ<`;36@5zRU=mY8qQoQoR( zaF6rF*6mEiX1$1&6;o)WSJTiyI8uhuI8ug)6__w^hI4gY%P{6(UziF50`YF79 zcSgWrFVYgagtw2JjCT#<(V0V@I)!RMae5fh=tDZ&ySd^0>4gWjqc|^D;ysd`C$;iAhP7gF6y+Ii zWBNg+U-cRcH;gLrKspLMq|{S`W?B;Avz@o7$$)l1@__>=RJP=S1|1?>>ea#S*^5nN zEr=LREV%0rc`E=O!$PuRdAkB(kU^u`)1i&ixG_N6WU>A*^Q`7#MJ1m6+IW`EWT@d? zPVVa?(|6L+Xd0T#P+dBHO-8B+6V9xM4Ul(Gf>rqcJ+Xj}jt(kbPVU2_O1b?Vq%dCt z2&TO*HkAskjIygr^XWfsxXE-bs>xaU=RVUx7AQI1CvxQ;cFd+R*VjkeKAc+S68()O z$B7?&XqHm6riV}MtA+o$u-3*(I$r>DRr3~nx27XAK`F-i}3a*$mx4a~bI zn=Nf!{Jf3gE*M-ctX@GG2OI-ahmHed>o2z;y+WvYL2~R-=T3bHqJ~*Wd>zx|8QA#v ze(mnEyRf93KBMkmv+Z;G|gDC_rst_aQjj2no1pW+}7^<-mG^ zJQ(ghNLRwBCALvKIhfd-Oq3Q(9WO zs@qOmG)m(DOtV6!n5ucWoL52QmSfq>vjFoeEzw>L$Q zzn5chR1>*gf#4-AEe-tfTtwGH-!0doAf1^;ZFCekjVCZJrPwc5_{IP<9x`-_{4(EJ zM$5XO_dHVx^Ib;R)9t>4l7WfsnFG;{t&rW>gOb90`uFoZD2lYCTQ*4r})HH&S0Z)*DCFE&pbnTvC3!RFPPhTYOpNyT(IgM$E)Es1z z;Nrcs)rx_b$d{By2`RVZ%jeRoO)%?G3z8lr4?EHPihc+uU773KsB+i)XGUQgA3rcn zohV^ppx0HaK8})_b$z=bA5rz1(UQt@h6gv~7BzhsC)*%-E~S&IS^ns1>6(_O1p=O` z05G=A9@}3BzFc$QOu94I{u}gzM^OM60neyFJrx6B!xBKXvX8`I2*u{_}IOIhS=7xme7#SP4FC$^s?gSk; zTCtE%r0ey~LaaKP?CIIg(AJ*G&S&O$s(tV7!NBbUeG6n@fJCnzD5!u)3}+n!r3{R9 z^Lp6k$A;fC`w^WU_+a^m*2gxfkfH42Dfpo&ox zCaBz|ECOFJ;o>zzYvnL*wLWp{{4WC%cq~gsNLX#TFX~|`$vm+-5I`4ByZ6O#51N6- zXyxSYS?^dzstYmDDzyI3jD`w|V9CxJHwVTxJ=fNNoXs}=9UI?+oY;AZ`&ax)dF5Xd zX=t@c&z8oMP9untN^^n=9U=y_xeN4s1HRQ+!$e$`4M@vo!Y+8O$1%8O1lv7|l0fmZ z3YIS&{A;^$pN>qeZbC+qx288<2IctwVKEU>*6y(_Kf4)U4Xdj^-ievk{0h6Znji92N|#kXCQ?f3 z#`pGBsYy<;)c4#YV#|Im-OBOr#El{`{Y0LcI6~t|;D$w!Q!YG!fhj)*m5F`hEh#SZ zRc+Ry%P`g=k-CZvb_o~ zpe^*0sC2e`k^PNVg0>8qMF?!{?!Jltc^(@){Q#KDWxJ2!XCLxe!ip?4VEkyy@gZ|= zsy+O$_3qMO4Cu7FY%K0vfX%2%z>r59jq8?>(ca?jhT#a~W_oN`V59$i8Ocb>Ix((x}?{tl60A;;2|> zs1}>fqL?WcZK#|-so6-UI->cq!jkG!*TPZf9i!1UrNhC1YS#;n-0HIbi>U8_=W_kS zZcn3$vPxFjBP-ERNk-W-*_D;OsU#r@A%s-OULm`T?5ymNO|r8`@AWwU_kGXjoX`0* z@O$p(zQ5!8Ue|S-H(Q8SA0=-C9K~%ro`NtZ8o=)!c%JLXzP?5Cp5#dF)Be?e3VfnQ z98ibu-OUje@JK7-W{lO*edTrBql>FHs_8#CpztMCAA2LioRj%hDd98Z-$#pcy<)@UREO$m0-7)z+1_m#BUj!x-fzg`_lI}V z!|}{jA6G=ZvtHUZ%rUW-Fn|;eeqBLP>zp{tFD5>^^||Vcn$b zBwa^on=LVFTh6Vwnp`2phz1Gd0tb>ICSwzeT!gSQOAm?3^uWq&$eQa(cx!jhR) zYU^vaJ7lr0J-Z^e<{n1byH5B^f^BBJ=}AJAi3j{D5+4mkH1b=W>-bw#cff`PW0$@X z)nMH!rbAx%(=6+oztw?fQuu5QH`12jqQGo8H-a&~OZ7IF#XZr|`w5RhH4c?Nhl(P|kIr+=mWnuzKLy8K^FeMcwdNh6B_?T<*Z7Euhb24uA)$KnW zOPPHv+xDhuQN-N)V?BAVO6CMY*1io`oGm?YFy3l~;$_|e->aCJF(28N9+@(Y;ojuf zp$`+E`9q0rN=>b|;8f3#ABv=&4D;0^bKtv5@P>X+v|a8`yx~04!X%|qALc}rWcF%# zI6P64s%uT!t73rhkXNS;Fh(O{K#5_Plhe5wdzyy|QznEUF=II*%cq9}s@0L=+)9lQ zd7+eR=*ZEGs0*;#)N_+S4LmkF`ekH}M_7B1I!^iZoBB2~mlK4^NKWfgNlvijhzYoX zm?Yo}7#L8WiUS6~FI5uN1qgoy=aC5;nh`qF&d>YfzMD@6wFSdp3!}lY-@lu#I{GIf zLST{zdZK3A05ScXm>-I;Bk$gcAz#tPw|yfO8B|ZNYiLl@($b3D#f%G&;fgUC$e=*G z?@+xFiR!o8(0$6LKyJIY51XQRj*<`YdEhf0{v5r!Vm? zfIh;dj`)4Oy13~dm}VYLOqnF8xFz#KlW5Sw^b z!cK##x!{@>rx}Cx1Hx)-ImC^-DrSa#MPhEQfZF3xe8~`v|oyF);_ep1e zf#Z|+1W)^6bTAKkOO(MH!KPZ8uYYc3$ml+P48rS7^Iow-UQa|kyf<0D=VzClar)ur z)L|0rYaJTDybUu>^J}l4mKBlzm^Qy%n(xFr4tG|HgOVg?aXlle(~u-f{CbWd#Dd1bEio2FHE-g~+g` z^VVK7p`v=3!myhPe!3<4Z5G?3nmJMVW8qvyd1b|G>w7o;q*8`zpYB`SZ9h{^x%?we ztX$9Uyz==sHZCp^Xui$_d5+&S@b`SQsb9bp4kTfdqB0bR5WZp{YsGs(w7)dN)^%bV zbm@fcPPiLyx!c;@F;1Dm2j|@}t%JZ;+qCH#i)cV=R`#eE{ciQFV3-8f2^LdYpnlELYjd<`*k0KQYUlND+4K()1>h?6ZxX(F z$>I^iHK?33Rm)00ynpZRzMH(MwKaB_5+4#4UWkIE8c?&M6N^^W)yb-i@nWa^#)k|a zs=;}aJy)WHBKoaE*O@lQgxZdp(?m`r40T)=xeS-8$Jt;9fI0EqyLTXpXNhtSsGxIt zjvWJ^L}%wW3URXjRr*4fgL~jWP(CNhaq39!RuEkf(vR$eKDAueD@)OfjZYZtIG4yNqk{QS!LCA}t9W(@J?7*g+(F}ogBs>ehx55ZeXJN5?)Qq(86-mR- z11FAWR8rC^D;U7brs=aG&9*5C$Y%DVx450_Vw#bRj z>;S-srwgq5AdIK0ctMLCg$A%oRVI3?qiwkUoXEatIBl^ z`t%llXRmqp9~26)4h-!QbbFD_%%Drc z8AcPC(P1)wyeM#(_o>bSl3mxC13~RV1Vq|Iv$+#ce=Zxq`5X|rhb(i|O{)zv(T)Mv zfVJJGmxp3l3mw9pBj~}l}f-5;-k{Ki4@zYL?^<~WvsPV6)pt~8*1%CPEQ<2le z)6%}*S=1ojc``yB`IDFgjKQ)G$J0>0EFk|ZgM(Z3yViN zy{<5Y{1zxDRt3XToL#ixx1A==0swrVm9xMkF}Q2fX;v{+yC$upS1DTaQKQG5`Of*( z^(E(`E`b7K$N-28(lx}-P-%H~3XsM`mj?s?E-tEska2Qx&DEK^2Erqfm`@!4GrhE7 zWYXHS%Wa01K3;QT4<@-0x%2AG2Xm(|1^^=-#&}OXJyZ9q85;KZqZ_N7;4-Olyt+LN9m@|6&Mwk5^?M%;(cSb?__@7QXMlH1R zGG|nM=I77P?uEf_BK3F%BrkBl&FOL6UtwY2@5KUCnc={mAJFb-CL7X@Ew;Bgtg8`& z-rqLI8g3I~)GOGKe$NoGplAU~1vLvT?a+^Sh5wz%sz4Tpg$|=*G&DaVp>!KHu@(L? z9`O0%kksa!+O+dM)9f=i4@)ycc7Z8|<;I!=C`O1$1EY=avHjmQ)~WRa0b6!1!ru6; z+(2GWYw57?Qf7MBmEO8S^}DIW8XPCq;3SY_A4)FEmA_;6D@735(p5W?XH$27{Pt+#i}5zE5s+qh9jt^AFjJoW7Yg_8BlX7=L1FK}Di`xfO#I^MaXOn4uB1Rmg2euSbuzX1Rvs!D*s< zhf%Ohk!x%JxDiKBD1Q}YuU5SJ^<&N>O~aqtIKu{S>`I@W2ssXk)z9ZxwLb?j@axJ( zxQ0vggO$Jc@XSPds_>(aL!O5*5>ew;{mSc{=5o^R5O}S9mMWCzSSXJL&8X@8Gmlhy zJA?0oZ00LME*-l1-}G(E85Ou$yW0FPXw6kffNuDpM$H~=hoPfI>l5Y>1bvUb>}kI? zQ-NTC0vhx*L{-28F7f0Y+t`z+Tdtik((QfAC7o`P7O*k-*~7-&B--{BC>;^aCO7oS zkz_!ILb4(zH$=+xmqd+~ZOSJg@C{oZ?IThw0MCgVgt)nqlNgxlX||zm@GjTQYJO|l zrJ3vOfvkIrGep?-57m@Iz0>H_R9htB1n%#2;Ua#9rB(>sNWVv(uK^UUlA_u7V~ns} zrE~hjLq;!FJ3Y-UcYgi|l%T4?N~?!3uVBd7j^pQ~7=7~&taZ&@#x)9NzEQWlv>9zU ziS7yIGF&xQ*X<+o5(yFcA7AlJl)Cqgw0KYoa55k!Z{0L(`tkX1E5KX^nu0eqyr@b@Df zf1l3F%S))^M$dq}(#&tuij)4VlI$)sll(PgQ;2-F5HvF|nb>PeY_y;#beO9Xgi1nm zV`+edloU*)``R#f!4E;}BT1W}cn0-GCj59w)#Bu$m;}K;auvtJninlI$H_)8M95kVRvtu+A%)gBGjp>JZD_c;YP~u0CdImn0Nx~= zB5^>jW(C;%Y3IRcatlJz(9lslLf-?`pv_mEk8>qo0ihm>u!rIo5b06-*UWNVd__!mR zpMUZt@X4F3M+l=};Q0cv@B+b_i)Pw<({^}q63{f~L47w> zFh>R^)?pUehURAX`jPE-pe{qCz^ILeOvMd;Tnr3Tgq?#DT-Cd>d1Nw=$0D5IFJWsF zf-*NZ@p|!pqA+!7aeslBCNb!UEjmjm&)%GO3Px@kIglr#_935!;vHGmQ`*$c&KQ*1jWQKJ$?FA2vH1;Jtn`X{O;Ym*LVm99S8k4 zzk>SAf0J1VsX?%l6I*87BoliL2%!z(78JY&0&{x$L7;U1ogN!V*-?4hXyKe@o5CQ6 zo8&*uXLFpK0_zbW$G@yx1=HIwoKG+#&d;W4Th5>Z9pOlGUIQNGZ5~PJkRMF{x=3sz ztnGhW2tNjy1@ijp`xNHmeI zEB7MZHXKmBY;J`QW?-XLYT-l>>xiuG%Y%@EK zkQxgljN2~rN}QUXFQDrsvQJ!oTqjBC=FI>oY!&Fw;-koG^RFKCH-)8o?f36!W5M@@ z?fS2|Rd^9$%g9EF$)u|ewx{b6XOU!=@#b07uLlXhpB7UWG!`IHWF1|LSBN7jD7dzZ zuK#ToUHy{@yaSo|eiX6YGFXU*c!AaA)XFQ`%LLyCW7KgY{qd_B7(IZ}fS+AQzf*fY24g2sC0!#G%oz zC#*TN&}@Oth$POhy5xXP&ofsAwt%ID4aVwl>QrAQgS{Fw2PSHB#nv7=cvj+!3U@XMfIO_h%%6O^dMkM#RRu?Y5IIpV9XNsGa-HP?3N# zUk-6OLcsq%HsLtn zqN#=o{(faA9u)flLe{39p6^!m=LrIHut5tUzJ^?f*zc3^I7oyyFUTKjpq0K{6<3Vg{_AQMC{RMPk0tiB9z zg5N(*qZ-Cr?1$4OEcdl_h>t>d4=ZS?EransYQxsn*4J;|4E`N!204XDifH)=(_Uha z=H#f5^5QE7{XvIfSX2@SA1d+KUoczER7WAG)L*oTDQ$ki=0j+~ zoeOCc%Y$4XjKfcCf&BfHoZJW~*k8z9Ev?hU=JJDg35bUX8#Y=PnP!`ow!EDGer{?S z{{bX+KrD8c%pEyKL#5ab`jr1QZ@g7eZq$cE)klf^4z%^GKGUJS$ckUTTo7MhcM)~y zzYZG5e|vtmfjA_)30=~n37mLVR#rCCI5d*~v#Jmyb}gpo$9$fNKEPIl)dTuK2nLEd z_3LVDr-#GMmCqecn9s+17u`q1qiDR0#Kc5cRRG>Vyhe=61Xl)$#vTPaQKTa#z#F1v zGcOND6H7u4)=y<+4Y(NcX#vi^KZc| zBXD*bLQhq~P4a?XTvkrbkGKKgS>qNvN9mFeb1jiC$^4e+Ymm<0NUHW zvA8IB!|jG2@@52?{erDpdD+;wzICiQZuz@iQ7J+W6c@yYf=?@2gVBizLMtG_@V`*F z8-r*Gy89YB#Af`W59D7-bJNId7Z^DzTse9a_B@&2Q!9uLN|nd5wzbbEE)= zJ`YMXk7x5ad%LiR#my>(*Dxy(LN#q_aaydwH1 zshGzj4k+!x6GKZ4p$I58?jNqzwi;Q%x4tMR+fil|lo-KWOy&>_A^bz~W=tL{M z4zr}O`=I=YJDx!tTqs>oS-lZ+2}2AApMK(oWCYeqD&|tUDuh&^b=2=uoIg?(1$G=nQ)^H0MA_POQUp)9t$@Oxf;bsFAfh}g48sxZ&hCT5()PdsQYv4PI(xs+6u>Zk4?9^Q+7M@Dl z_#$(;qrhfj#aZm}*I%cWJBX=|-z#*>ctx@IctOm9!384cM_YQ#U5S#Ic$`boDA(e* zqbI@%M;yV{fk(%0%H;`@U8!48^nkRE0wF6a2zb}E{u_mKI4iKg0MOI2m~)dASJ_N7 z*rgM5CFxC?Ip|k_GL?zQ*??6y#C$;0oedaDPc>wBX>}G9gl1%)t%-ZiNpq zanoT7jsWUy07-~~kmJ($UIku*sX{|*>%z@mb|SK0ljWu=n-fKqlc=@ZMT|aWoX`ef z1H<=!H(WM*8a+RYt{|}>bQ6d2^Jm1huX6&${kTfv0}^&UPhcY82>y5XA{MR>&I`wu)`Rl^=D6YM_Kb1c2l$6(c{txV88q=p0s; zUqVO0FnnrI@U*gKlUlfRcFFyOT0({~+kH{riyK zxh-m+S@aljz?>dw7J($bhp|I96uh!4#tJX>t>-#@Z?BukjtKPj&P#g)Q9BC=^7F%Y zS_U->9*%sdj(c;X)1pckiFA5__XAwuf0YCJ*Wp;htDJt^!ou-sS)NK~j-n9?jfyhD z)0+tRn07t6%*;W$6_i1m4oWB~pTjR7{0rg|pHIsMksR&%mICl73H8`EQo;LNdKmt@ zfWI+$z?1=-7V|Kq$*`BbEVxOC?G=tx%NZv7vQrch$rl&qC4@7$zQfl;#;fiGtO}YxPy>laTxE);8*^`4m^ZO62sXq1U5M`r2 z3V};a242>Gvb`$`3eA^=Pxks`pLs>#&Rkr$Y(aopWv6s!xcgt5r>V;(WCwjzTj~w# zy9)LOS81=C+-A3Q<*x(Y&gXLl8X6N%&y7qqB5JDPHI{mkTcHEu4Xw2~IgYT5<^%P2 z1pzR_naXbiPyydPM_T-?gm|@|AHZsyXrUb3K z@ZbfK%uC#p{2ALcdhv{g4zTGmlSsB^wW5`keW?*zEZRSR)}wrbm1S&ds@%1!KlT1& zk>VC2e5C?C!8hT#+|P%Dq@YO zJ1ITh>NJL%W8yvP>W8axMIjs=*`Lauo|o=$_$;i5dU|A0&|zkoCFgdB$m;$S_~a84 zObDP=`Uxi!qocQ`$o?RT_a29lh;yB#C;eXhXTt$^5fH7NgW-YnWaNe5EN%p_2lc@^ z+sw`U>9`}jfo3tySsHIQu+b05DiHqG;4di&Tq1aypeX%zyY1YjVcx7 zWy_I=ISLlXDByD9ud2Tq}w}L2wIm2`MwR$m7>u@`#i9^hUoTC0-RO&yc?wo z2)ZEAqGJT97^4l)nx>no48_)*sjn?gv5#^l2QO6{*Wjus17Z$dqX5>?DLOwsetyFA zsqyZog?kzM0TjaRw9Q3e(dMZ`Z*yJ2UwyvbRZVKsy04va-Ra&FmIh}kD2uWx*^F9= z8yIdF8(@NoX#@cqzya3to#nm%YxjfumoWE$y9a_d6=3ozmZ+qsNk9+FeJFF$7z2() zv+Z5}Zd)52av;EsJG#1$p=07Vfx{E?#)2Qow4hjPjg_BZ4SCF zAx1sdRt#wr3^H;>J4~`WHT!gyF7>jZ+XU~9O(lhBPU98dWinN=^z?q^DiEzCcT4ku z?*H*44HY3XmS2Kn<9p_oqIZGNG_xuVql2V4!Tj!{K36v7+Y&m)l%`72slW#Sm5S{L zt!gRWZ+h}<{tEa?ZP=sqk0w%M$A+0Ns0>f8PtAv7}_vVQAh1k^? zW)j3^9-fQLfhQ@_?PnwoyDc`mua#YMa+tI~?A88VES#hHZPv+3_;b-5lWI7yn4W#h z&>>l}D6ONefnSEfzjFIO6J;WMMUFUx2llrrBY$Be2re3$$uEFZF$@=-|Dgb^9&$9a zj{7wHaOZ>ysT#(W615c-yLrG@@cPmQ%6Rw3c;%Czwb3xz6}{1 zK%42Yl&YmkG>%57*>TYutYbd1)XKReg+#6TyTUI)lJQSh*1y)L_YUk;BeA{$kB`zR zzSkOOV64j+QgiD}P(nA0!N`A(GjKivy2U+>)p@MFT;;Mh>Y0CR((mB(RF9=*4KF;y zsV05Ej|P4IvuG%jHY;|?7DUhc4>E5+EO%D_=)RrD4~vPd=$`vmE;l*wo-4cg70I6- zqs*L0ng<;w`soZ{O<#o?%y@R($xPjtLRu zMe^*a3(11S*nQIU$OLYlkT}g0JR^MaB;GGhW)9dQ!0Few-#=K8msed|D}7df9uuC$ zMwDeJ?@^ZF5<=5|9OT7PF(pvF0**mX2sXa>Uogmf{79iF?eB5%*FJTC8yD3yv{2}R zcJ}v@zh=q>)Wne!vu}$U=xxwE&CJaF))`n`J+-!mQ#{byd*fQo!eVE)ufz|+eCzAO zayWEjRZz7>=H%vFTb;?Sm=i_0kPCH~pP<6xSfhR|CQ!B$slymxC9|>#(UR+>I{g2HA zjx&KCX=>_Yf*;5t*90l>|KgDR*_KM6!%j?w~ki*b& zTzrf{VTb4qW1JP(pi2bKn704s{+ykCm3S*|X@OCzeXc9{3|W__d{FtR7(Y{ttp%|r zx5Uut9}Wj!_GAF~*X-=zucKZb{&L|JvBvZ(7bqKPt$lyOef#b`5<-e?miuMNBvL;9 zxegT}ir?F(1+WrMi##wKyH^tEd3epeI5%p9&OCwEQG02f*|hFr$wi-k;!caSw^eL= z7B})2#R~i1F5d3gnk#YCcRox+2X_J3h#m7{=wncc0pOo=9IvnqNiUBOfE6M zc&}UayXo##zOZ9tPFwds>yevU|6}=2NXSSsZR?4>j|W#o>krN!pgysS+9_haYg}t8 zPb7-r2-~YgrB7Y3og61Go|0%dw4=}e!@c9kexO(YP?;Sf9K4&lx@xfNJ|-rXPMoP1 z!)|LD`@6z*^3Mr4?_-{eddww)Y@?GU&;H+G-$iqo)?Mw%`|9SEFQspzWL6+Z{LF`M zr>fN6H$_*ekBS>D8Oi05s&z5fndb9<=v~u%+Kqo27MStPB?=n`qn8?5XcUVgztT~p z_S#bmLS_rLd&A8^%3vyjMwAx^& zFD)x8&pJ3}YBjwqXFJztq`_^f7xdN9Ht~`|a*%yOS^NzPsTj)^@A{Fhh1uTSi)2iD z9zTd0vJ{2{LkRO4*at*LM&7RsVBFi?(8y0(%Kg$n?Z?Q}O+XPhSwCf`kiGabGxJCF zJlU#yaffL_=1hO%t_9LO9_xrZ+|PQaD8u#4p^5%7wFqSSu4&rrBNpm*@j)%O_Uu3d zuXXp^Vr!awbv6`e=n%72*|Rrp_E9J*5mZ8wU0X+|tcfp(PweOk?+#DzIzl!vGxIar zkujcT4{l*yc6MElF5v*`0@@pnMlbHGbTqP7MdTM1w`y{1X4dvjq=6(AhRjW!LKs$FFDo8MBKXceE+!kUcjN zAw|5WgjWY6#oZne6Ykl;Dqy{tM&!VH@E~9>Smbw)i)-0mKuMgdNmk1JF)6y?oQE{kKJrmR^zxx?B(cq1 z`qeDck}iB;kBRXdTO-M3?2oHp0R~BB6cjv9NWk?UnNEvl1wFHl0B=jtR!86bm}h2u zZnu8lRX|XfSz%e7cK>w#TgdVElW-e-_Pso_2Rgh}IlcSdvf?Tb*$Qyl4PM=7=o z%W8QCR=-M9PyX@a$Fo?foalrzuEq2K^XksbH93VX4X$eNgbFN>s5V!RO#7rJJh=iSS}Ou^fPix%>trs&D73m3| zOOm^jeZ#rNI4NvowO-5>+Fknl>D)|SHD6?I!8e52jX&WvZ^9+Hb6@J1o%U(gdH2=m zV$YYXiq7^ob;iz9s?VgA%k_C1+uJ{z%J9%lBx)Ymp%Wpc7Se4NhpFQ644h+1uG@nk z+t?T0CZiRRFftn1-eGr{wb>>Dz>7%4)nKNlPMV7!lBC;6IqN7#VjCL zYQg8tkZ$*-v?q&Y0ZC1QA$^0p?>H`+5YbQ@=V|WI@BI-e^+@s&{Tq_Z zS7zLMzk8P)iLvva(?NdX$+JJje1kh>L<8I;m0G7T!(rTOJD=w;bg73U- zuFBN2sk9V6@$^#kIWc{_qr|FTg{w+p8`fU*=M#8E-VRuq|D|`eAIp;!)9%rh4QBdn z%x;}ywz2hf!f(yjQnUHmZw7o74(=pdJ`9BM?ReuPJ(G3`jPapO^nyw+>s^`X{#bLX0?hR{(wbru(W+}6L z+wLahG__>pp3j`!>AP}#KUZ->HA`=AwP%#^@W7NYIzVApo~!X60;}Q+Yy?W|diG(x zgmT*Bn{Y~D#bmDhc~EbUv3T)gwzv7p7tw!6uE_L|4TmCeema%l_$ zrL{fXyIrWmPd>J6Y9e)iL`E64-bf}ktI0?F(A6jtM(rP=YSo9HQM`U5$Ja2_p9xJ$ z<6`!7&zwIrj;3E$%J`VXoE7y8Lzs+e9+x%%$%Ly%Bt^VCCr<~_Jx9(%24WIA!xvWGQOVL!zVYK{rch~Zu zk15RTI0~ljZfE=IEG%h$DY>Hdf!*?As-aMAj2|MOEOB*rwa`xulNe1nP zQ4XoaI%T)cs~%A;S+JhB}J{GA~r_xbE01}T6f=ZvH=BQf3Z_FLvE{|mD5zu8pn zZRb}{A7Prk;`KC)+Ktn%`o_tMp(-Wa^c|+Y0=Hd@Jls!(cP(;8vh(D=jP5Zq_*ipA z=yt!Ci`e}_3U8(eE0sWL&JW9f{XX?sg!(giDJl=Gwd_##seKe3M%v~WBDG6pq`AOC z#QPm90vFi0t@O6ql2I!^;^?CGaPE1W_M*=4a+?jo)B<-6;PGo|W@{~?iovK39LhV% z?yV8k9#5QDj{AbzN?_v0XlJI!-CUl9^fVW2q{*Bd;}X zY~|j}oR!$ub@6Mf|HSHwm*1aOlrcoV1kfX0yo&=QV~f6$ojAPoZqcD`3v8!Itj!Af z`Gb^~e;X$jxQdiqi!_F`i~kn;*x>%-w&5k@vQHh>6`%N>??v4*WIGYgll5{K$|gp) z*%l_Gr~ilmuWszn+T}hWawQU9v4xhP28wB?}mL1H)2@x{Kr%3MAkYhDBhOSH}C4D=q0{ZE$a5K zSNod@VWwXSE44Pf=%2b&2XEoyQopPQCal+ya=;eIX6iy^WJc!j?uwVQj+ZyDpt-zElS(`x6#{Y z_-9|GPB46X|C^0qR{(o-<)LpBbgxzGENwLLfv(8cFg;#X6q~Wmm3VNO+#FvVcj;gdaL^jDg# zt@W%%+H`{xWdy9XdRzAeg|Ch5MW%6uB?dvU0{klyc$Ca@Y--8~qKZGASw4-8jlZ9V zJop!%pl<3vnZ_n0*toEIk-O@UVc-+?AWEy=dpzp{vPvz#MX2&+zTN9Bu`#&7D*ubi z?bk?``Ofy1@!?bTS-<9fuI^^w^z=Gzx9p^-bTo>uer`9v*v#|lxz+h|yOJurV#i+n zn4K!V?q9vyV|wyle8P8Z#DC*mH#8$|%r)`J6f8-cQqFu{C+`~HnV<7B%<$%!G1h=j zeJR#Q!El>Y-23`SM9Mb?deINFeJpgvXI1UqB^>Y2%-vbkopRI7Pw;fGzSkp87Ibcx zL=tDR+P2fs`{|smA+gPS&~a2iD0HWBIHk%r%7dSFTs%NW+%*6Uh3HN}+mb!2PuznC z!mz&Dw~@I%OVh$n*V}2X2P7DaSa)B@xBd5qwo=t;<#zhaJgZ;ac)j^Djd`m)cLk-k zT3`Dz>$Sy}*{a2yrk;Y_c@^rIv7uwH?5aLw{PL@2%r-Y&FTMCqo!6LZXg7Iy*kjfG zG9iZY&<|6p?i*ZcpX0!DZzs!t%y|8WBZs|~VM+QWn_;1lwn|DHwD5+_!ztpWpEvB% zK1w|aJoFXjB6D5$&v&K>7q5`El@}shI!yIBx(*M?-WKir;zZuUCnE3O!QR~Xr~Sv0 zy6d#k23;zxUA8+>ZtO7zxPVy(MpR(1eZ}dTS*|t~M#Dk;CMT!7wl>(eKCGt->Y<>w zS>O&*x^86Nv(qH*=Gh3{>(|<91W)RkwoYg{x$+4INf=tmg&vMSluAc#^;`bUB2ChO z!jyT8gAaAAnFMe0q3f^O?uOMF_N!5+M)1v)(}yjsSR9UHHqecq$bZyTCGGv(!BqTH zz|@QT}usUlhle(Zbav>_ zUb)qtWlZTwPLEB27X39?nP3R1vQxmsgD1T1jksIn^767q_Ew5X+(kNq;thn{H1meK zR5#aWeqy~D8)?ZrzmhZkojP#?uhOy|R72+LGyDmh7{-)MPp9qC%t8!c1XL-j>jk1GZUx(I0Ss^gMvn#SBs@qA73jZWcD_jZUTN$9`xd%&te7PLgK z9p1;KoqNgmMxVKJtY`0%hp%8MD}~KQe~XgqxL@4e_#EEs#Mr#87J3muM%TtiP3>lf zJ6N?H4Ln3rcScpzT5`*wm>O~Y4YfeNEwvc(H5!shRsxuTN!3+ObP}iaFkdN={F0jPhFTcU}0Kzr^CE_u8+(&R8!K z5AOPV#gK}MJL~nZo2#Cegu21on(HEohn^h~;{G!f$dwJP5;a|-o)<&$zafW>Mz?~; z<+{;ePn7fwmz0Ejz{%I}2&-@Yns}+}9)MEDqvRmA>Bb{=3 zmtG+7Z1#GDrX*iZfWe10t)jiX9|Y?qmg@dFdeFalF0Z0eG1;Auk#*kWYu_CyEzio> zjHESRyI8w%S?&zV9B8Hy7k*L7JU1uaT2;KFkuRv3p~OD+CYNT!Y3d1Ua0)%FERzZr zA8bEWXx6`p5#)-7Uuq`#Np{$CajCso+ibDun6_JYJ=Z@dBzNowaRT_Ocd5mCkC|-v z#YNg}Z9_Xlx&AdsFl1Jl|2lcd%gBCpaEF2dpEZBSQn*`Ii1xBc?@Fma8TTDC;nMQ4 zBdC;OQerhv%d_6sjJ!Vg-GepZK014}C6OXGuhn&44)T4`k{B)eZ^lh}&itSLuJF2V z;DMvi!76bPFzLn5MAfaOMH?#Z(EA3QO1z|W^_r<9pm_vS7i5})pC;WQMZ!RlAOYzF zE@wsk8JJqr7hiDtapZl5twccU?*%ru;>pjxVQRJ0TyFo)xUFO{u`5#pg#)F~bZL0j z0;Vg3Dgk1q=YR8-c8d#sF%oMp+DOwllbZi|#`(IjlX_Kvb$6ZZkaOz4Ro@01cP?i; z54SaXF23S0+yzVwbhUE)TCF@?+P}sanSf&1>E8y!^5csj zK421)!_H&XN#Yn*!_jMJbF6J=3ZDX$cN~1_f0>KDJSCxc!abPa9`>c3UR&~1Uv~TF zSE!ovdFvWSYMsr9ZKB?MnTfaC%DKbNeff!PrgdqwblnxF5&rE?2UewlXAG|1ojbqs zULN(5prWT|Ik1NyvOp@~oslJYtZx|jGH1yC#1<*$I12}X@{;?u>pB|D*N1$irj!nZ zX-Zn%WA-q6Slahx3;;^%IxCb{EyoDh>z#Pc%(=L%D-+%fI_it^NA{`}%^2oe7Pb9b zzdE>Iq~fUeIENN4=D(#?q#SM2U}R z>Ld22&wF+UGxn~m-L}(8j%d?}SoBr>J0fIzQi?NG56zIhXwC#@c-4*P^;OPuPrSI+ z8_IHI&-k_AMxl0-bk)k?v%@NuPu^+t>dgkX4d+?qx6JT|v0L0@-f29}W10-Dc=<1g#ac_iFa4@7L@Vi{~D9`)i)ebiG73{g<`K)@MvU=%i3J z8{0XU3GykA>_2W*a}28>8Stdeu&Z_QtKWvX`-wdzTDXS=z`o^h?J*cG)q)&_ll88s zC=#r`#+H^VV1e%@qXGHOVm)rZT{JJ>jx?Ie%(Sp>dFts^Q>IrVvnJm9SChpK=5z@b zlZ{%uW8FvRw>zZf%Js8Cg8sh-%iCXc4R&yo#8NcBDGa#KM*7G09G#!hWx@WVZM#xb zzOyDt(5-iIh1Xq`ks(EFR=lcbc=|GT-dwCRa0`zX_L}HflbGhQB!RE(AB~MZ_vA4K zc6}S!N$%ZpKY8QLTHm%fu8>qe+H%&^ddGF^C(^Q|y6HE;E>D*3AoJS@LRa{J9L;;m z?ZRq8oQEkVMs5V_d0}DUci=>|Z^+#Vmnqd`Wg4>G-tP{`1=+7UC#i4C2-JKdYcYBM z5a?v43s=`HloS+@N45trS~xJ51Il8Q@A{Eq>K?~(h-+pcmlefaOGkBeHhH)b>sMV# z!_x&{-PTSjho1lV%JVy?fv{MS*X&o*m4kJugZ6XMuP$AzFcBEA77^svaNr9qcp`o# zkjt!D@ZXjW6M_52#>h>Q1!dtzr=)95A1E7#yNWW&;Ignfa@i+3rY2@)W<9OxYCrex zd3?eIL{Df>qgnUi)8RTQtbblgCX}d<_XlVQe~sKhMh(;nB#w$Qk0Zvf`+(X6SgjM$nb&&J0~jW`Rch^Xl=qQs;m6d%9Ue zNCo)$pY1lFz9SG$T*l@swvQbut{>J4$RntG@WPqen+2H0OKvZLZlbGLJN`doF0-x&;L9>l!=IC%yRin zl(cej8(6}oE({yonOzeoVftq55jtK(_|5+IdXQW9(>*&|r8%dU(@L6ObGUH;=eoeS9dTt5O8ME-*u%7hlsGS<5;EatXn0evbT=tt1-iVLCOFT?#MArK&Cnb zXf)0izV5TzSY)sGUV-wMpvN^gpL!gOXj2NaINS@Us-|`l#O%w;IP=)?!5CdW{(8s3 z?SLAElWF%(pK{zY2wiG`$Yvtx90^lfso%#%@> zkJj|B7`;GrJ)^)Fz$&kz7oA$VJo&V*tCE`}c+FvBwT)t_#7?>DXm!vo*eZ727I?PV zbZMxtQ{X^i_b*I#6V~)e6U8=g+k=kaS@Rflj(Y;DB+djK(lPcy_h}*!2wUhFd5ObU z*8D|D#n`%&$!cRKTrQJe*}vA26TBRl%8`EP4E7aqT|risO;^-wv3<3Md>QPZ9ZJSo zvG243Ug$zA8}>V?>$oOq>91L9@7|4GE9U{{#POIBHT(9ilxOm`+ z)7z#djW!!1;dtz)OzWB;I8(g5kK4wwX3RFs!XQ`xzNqrU2v185@sp&%Nbzgw^|T%l#`##J!g35|4uJ z(1nyrn1@?+Ro4Q>&#Aw%BBK_kLQz}I}mj?rA4SgDw2F;cb3`aC3P z3U3YM78^X7(f697-9LLy`}M$XmiMEM4hlnPgw)m5%d(s(KV&IyC?{r#vPD$&kq;rT z%MS=N%bS-P7P{$WMpLuzo?WXq=a^a5zWr-f`gmrCG>!u(H!U(#^gA|znMoKpNNyTJ z4%p@kTaO;Vvb?S{g!W--(Q5v;60iysR$6V1{HE(62PfakKUGv~4y+nh+cyZf^Nv8x zrym*??b3_RT5{(ziT=@G+~s;T)V=Om`x(DPi0e_qUfx51qfM zM#P9sHoWjQf6>EMr!9B-UX3~$)n-{=`YHBU($m?sA#&wqE;q57a3j6Djt=6Vz-#U7 z>?FSW4$lp1{;s49I|+7MN{ZQfoC({1D|S#xsgd6o(jiFKkVL7Teud5v8cldW5f~~IQb{(AhjonS zj$HX_mV>er+Q1KdL)0^&G3?QIx0XH>Ngax;Gvi1yTwbAe-56yX`bNnXy^X>rMkG*4 zMTLc;p_d5EaQDFo5vQeo+;?DwXR4#a_FLckp-Zsi*?Oyf1pA!4jltG!%0}mEFZgz^A6}iI#l}S|mKfYWD z|N2!dqVzIQUOgV&_cs-1*rC%17%)uKf{khxB zM4(GuAz)kd-N>2vBbZB+1u$7}|D(J!U#a6SiAvGi^wIj6;ZW9p1JpOxW^g&i_hq56 zB)C4jEiBY}l9WIAKqw)(DX@wW8`-bIy-J@by75p5Kp@IU$BJ4xEJ(faXrWnlUf$|a z8ha^VWYVrxU*$^Kh7ofAh+RP+MN4yxAgbY}k&gpJce96+e(Po3G zyO-jlDi4x@!0V42wo^m&e5EsX9;w(qsU85P0hQt;LhywTOq1*YnL~HMXR52np9ly zi+_?Nbqr=oLy$QFN~2R!YIDm=yBHRG(5D;vRib_EcjwnILAU z_|S%wKDqAC9jY&#@nq}Auonr(Un#oZ%~<y;4Z*#mEp4S`yddEY!`Do zx*>@%40%JXp5Xw084pJ5y_a6`4*($?TpVZRY zN?hlwpb)4UXcGmiTXfzaY~d$C-y9aJlT$@vEhNnS$KYc{d5b~u0aCnkQpO#_DY z4?R&R%H}`5?#~nY!LGtk=~@ekcY-WK3@=ZJt~1z%p^TI%%%QLAUviDM>^4WW2@&+v z$HIpH&>J~@wX4Af{|W!@p4I;!@ylt!#D+Y&TINHVLlAW~Zp?Er$W+_Hxc9g*#~<41 zhTgFc-weLp_fJ>XuVp?~%FP;FE!emG?kczXuO@46uVu^7|>Hu{;@ zIFSo*EiNH2#BYGIO31pwj7C+C&h7v*DSq)fG&EZA44xNaZLkF(=7-*TOX8K-%#LqG z7r7$pZ2uVZX=2pyPV#Qp#pn+TtiSc=j^B7hLkwB9t8TFd89@ud2ftcW`b`ZD55a3Y zC|5#H32rCKKW-{Uh_IxY6EoM$;!1Aj_;eSV9Uo6>XWti`HOF=xQ;VTFji&1#q@+3Y zKXZqc(L30&XQ8ctzNWoh(#2(cyXo_3ZXUK>S=4(}jwbA@U^%iedX726V|F`hDR+X* zTexFAy6~3f^Oh^YA5(cU?HWq&gzWdLdD6nJr{;8Q*OC9j(|N~Z-M9b0u6EI&NJu0} zLUx2Jq=Y82H)ZdUjH{3&JH#1^kiC*kRcpcB<$&u>d3#D%mxE2V9ey`JrR7^M@ccz}#0v>?`wz2VXV>7dF)}(6Rjc9|Z zHoGBRvq;!wkq5u%;Ow^at6D?o%wvC20UIJtVWI&VzQeOc_Ouk0Z^9yxd%z|Fr~NXY zlEJQvL4iZF>lyMgqs|3sc?tA)BOh247g_a=+6~M*6P-1$UcD-03d|G;UHya$i0J!< z*Rbt(bP-(7$ZX!c`$t<Bgq`6gIw(c%JXt$55OvOVkQ^4w`Ts_dMAoq3uYug)dUN{9RVVYv_>| zYkXwXZaGZfcIaD=nOQpj1vLplQ3iiTx=fCZ-QK=^ueS%3yk6aG?$d2=vv;Mh!!dS@7qVCeT-uFyw zR}(|~E}Oc_`e#y6ce~5Pl52a7(MAyPE~wRHXu7|WxcD~=Q-m!C{n-f4@fi$z zEfsjhq?;*++U1nJ-T*pM8284uH<05i$^(a#l zJR-!ID6tb{8Zj|VP4`^7&^hOcbLm^pv_;*vc4HDBZ#Erjo*z+q(RIJZ*yFg=5vF@L z=#xp6C>zh{u8Y|>xKuK~5`7E_g|-22gh|dLQ>n1}p@EM< z#~IGqc%q~5#-vSvEcw}v-)}FUFS(@W9wT3}(49E2Z;*cJs>AB`TvdJrsW3yVGCF$t zxb$@Y+FDtEM$r%O-i1lhkiU5(60(o7HXhy}OLW4VY!_`D;)cehq0n>U;B2oXT z-BqzyFYkRim*2jpNp`)j?5?-!=-n9hv!;%x^vtgDbGmZ?U%?275b%5E+SDzrQJ(o` zAp~U|GMOH4L?G+vqr`g^B`qCqa#G}KjJ;)I$}cBAXtw`D+NEoYaO(c=p9IPY)gm-v zqcfDS8K9{XX&d?zae3chIlWW#@(F_yJ88o=gH3~ayr<97UKcDD9JfAh^tZf>@EC?= zGeM%?8_Su8)cB*Y>2F-lb~K=+qr(Tvrb9Q?q<_7Im7U5Rvwv&M{!!hY(sAtBGu6Ek zFXB&$-T?IT{=y_d-AHMDLLSH2fKkn8i2a|a`SWKgPNqz$cFxR1^^y4FosT4G-d~X( z*g-2V9jv!fOt-O|j~+vog`6LUvTrp(Kp}`M=!U}>1vKg5A>$JLGWvF>x?@sVV_$*m zku&yFJ<{!IfoCo^>|nLIXq{svgi0EYEG4Cs&Gja^TD0$wCq(@u{m@<#eR(KAU3i2<_9u!{e_|?0}z+NH8??5TyT6J2aEh zp{P=OvC)%le$1Q~rBUZpMOHaygnouJ0-N zbJyJ5EB6E4?F=mftboG=JQhSPv2tB(1!mhXU9x!5m>g)B87aM^B5l^`JmJd#FajwX z?g%>(nDB|d(kt=LqoNGm+_awU*IGq=cYBFihR^cROtD(t`C20S?9b0w1GcC^=C_PiWJj8k+d-C56U5AmFW-ZTl z3RDnDX0S#SDOGU@LR-haLz57C>a$cd)=zlaYY2LrwBREt-H2*^;;WkGm)T*4Xq=ay z-xFSQ5aG~+TA(2ubrnbLfoqsYas|TJ&_iOCpUM2gB^j1!&2kqh#7`dB7}4N`a00gx zDu&4F@q;n&0FsK04Zg~)RnfCK_NJ?8+nXm#R?U>Xx_5UJKW{ChM!^AoAprFVDj1>+ zu$&N*V-j7X5#)61-``Y$Mv(qU<;kd5IrMPk;>SYTs^g;2t{B;4n$drN+XUj7o*?Ng zg$KBQqqh=OwX_ltixarl&z~RE+L4kXYo50l@q9~a>B!HbcMbWclJSU#`H|rKvV35< zq+K<|up3pwaNiGodL@MlED=8tH45+qkofH1_`zlz22qEY$F=tJ5zY-!m3aP76AoAb z!mi8w^{0md?Q!)w-*>haX21r)4t{=4C9$lvuS4vJLhklQn^RYvEOy@5e%E=aQqWhL zjXUcwRgT*DIflKcA8m#kUzlMp-VIyGuJC%V`XR7XF#`vR^ue+KJnYAT^Ew-QHq#^Y z3fd?L=p}lj;Dbc_ECERQ`qh(F4jL2wr*fU^&-SMeTK}i}K2_VuMwKn}^mq}ujLe=HpNyQlhLz`}+E;*5aS>|;uA;!up-k2+RtG6zB%g%;_8 zwn!Ba1=DcVs|O@yqG(8hM7IR4Z#OBd%k=0z zS!9XIFv1TU09dmG+(k&}9*?Fr-8kLzDZXmrkPMHnD7eP?Gi zyNZLJjFO(IJFYblEBibvmVQX>%VZ8gQrfq}gTIUsjH8B4wB4dz0q0Sz!Ohf;LZ5fe z9zjj?cix6o@`lqI+*GxWvj%>MpzokWgSMIUacqAxL3R6-2X-RBno!I*X*3w%?qrs1 zYdZG#nqtB41lGvpcAf!mEs$LH$MrAXc$1M)Gd`cbu6UvSAg*HM4orW z`fbI-)g9U$+c|+)zVhgXwb0ct3e;pY&Z{6C0igQ1XA#|&t z4u#QBG=`oP2})}3rg};U3>Ptihn~K2aK;LV7oyh{tUO#(dPYVv|Nk4a{Qc`!f>}|X z&ek|u*8;;dx3-as3j?yg{z`A+xg#-UG22CNl%;}m1=J(NsD6;i9Xg$x|s;NW1pnIIfKqZ1SH>FMd6Yhs~S($=X0 z7_(%?eA?I?Glomu*0XGGOgqV^%h86nRr zF5X1&mk8Cn!wjnTXCT5l%w&RD5yIxG>l*%++ut_lT=KIc#~T0uf{X{kCssNd^U!G_ z4}QpDih+ecH;sS*4kD4H-* z0JE_lk6WSj>sJCxMjo#onagsV>M>~-v7bFS(!3FL>nVgC`+1DTV8U$Ucs(zPMK@|! z_?K#ep_eEY5s)$Bh-+fR^2A2+dbN+_1i#!bBa<&k&D%XfK6F^D=m#W0iu*|;e7 zGnt~HOZPC|3Se`{%n{RD!6`I0P7l!%6&$FEq{ehS=JR;W&VnRAFki4R zkV9bE;GH8IK=O}|MP_>BeO0O1!%RMeKBi|3{Jseq)Vi#v%3>2q|J_8y_b1}^MxoxS zsReE7?6DwL^xY%YvD2)9t`m_~^Bg@9Wo0o0Z2<*-!q62VPo% zY~}d;KU73(v)Fwa*DsS8CFJH?^sB3=LSRH|%(po5C1FjRhfdwar*fWA2d{0Oo^N&ub) zpTD(#^8x1Z{u3L!|2T-N7#@oV0sBwsP6m;PH@(nBJ0k`a6W{RCCGWd|Gmm*mjbF*+ z!MUYC!wBR-c(-^-cQ8SY00m-0@k&Unt2_(ZT~Ybo2$Lv|Fp1cW2Ohd6TkNJa+-i$m zz^~^=Y+QYGWB=1Pn=_5%%4?cSw9`_+uQ2*_ZtY3 zMn^|=5t?InW}>glVWRUQZ^U<8ZUp@iPDMCl!0Az2AH_{|jGSKEY401Tq#1HTvdy1u z;~nWI@Y?F;s%5FAwFc&bk%bmxz!>4cBG7zb>t1Yk-dUUd6syN1SDF3=&QE+sH8@$Q zhyh182MQREfPm7O(}%Y9muIW$yuLN)k*6ARNRD_rSPIO?{+`&6Hm*sX!&vlqzO8|+ zNN9-3+hb#3q5(1indI=JthM^{c1OJh)ZkUX<%z@N)%Bg5GRW$bZTN4{MvZGROGSQT z``y^3$|RE7?ZB48kbUq#_R)XzWC$DK+0aI#i0An?HFNCEKPJOMapT!|;n!WFFSgEw%v^<_5tlaxLy$GqS+eD zA$408Cc+`Rfja_P|9_1^NaL*0i-{FgC6D8Je`w(R zmmqcTR4288`8_NKVrCm5l2e0{MgAEh{7y1(bS1cK0OG{c^(;bNEad;s; z!F&KsG7i4hObh^l7i?rAuNQwmq0{<0607mfK>HK{)tR?d`j~!KqB#W>TU4}`DCad92?B}1DzQyf`9PaOZ30nf1oBrOH zR>B}-|Gh8&{u=y%<&FFD;U@C41EuqA>cm&Sc!St)C?a$gG#TaSW~rcaIJK*DGY(S- z`9w1+VOQ$vl4CzOfK`f21x#yXOAw9@WD@%zy|z&5qw{KU#X|Fw$%p$+&v2cBc}DR> zh%A05UK99=_}3vVfjNc-V4Nq+7&6%1eWq@w<9~=vpa7umM93q=xsDIwIZSK^@N8}I zEK8-&BFPOHW2S zJ%m*kU0$1fs|f?EA_p`RcAC0BI!YDF0JWePM3^7{?=o$7Dd<}c*u9VX?;FU!u;G-@ zJG>p45c*n)AOZNXxVShhq=6YHo(OsPId~&xm(!yrZ>Yo>=5=9fzk-PoEy3&uD@<|* z9E$Mfk%=No0#U~Fe!SSqpO{@0aXNFjw*xL!O!&~DX1}#R0a7E;HRvs|(oe}O7tD$n z9C@uKIZLHyLWTXC1g;1q*8U9VDnJzMD01XRScwbZteBVrvMa>+FmMu0?ima5L} z@FwrQz2XKw0;&Nt8wsnY`jw3aVchemx#95M0toB#$jAZMtx?c~BX;!X&x3}Z3lUut zAPohej*DefO0foU>1_?B8MHQob-xx^NrE)fP6Ygy)Qd0jKO zS;x>2uHkJ|K2`p!OM5B?jpCS7G`QHYw`GV77=Is61(Z@HB~VJSI^vQ!V4s6x3?#>c zn!yV#{9rzKN$ReKw;wqA;U%%%7#N7T@i_LOO++RrRfct#C7^Dxb1Mc0Yy@QchXhnb zm_%Iu1kNvS!@^>hz9nk8a$wS*XkUX%ij~wzG&6x##0Y?bfI-KEgUV^X1_R#9!K`g& z-N*4>fQ8-5AWRsGh->y}fHxq?h`$gO;Mj*X?g}T3`rpHR3OmL2<8qHN&OW7$C~zlz z7^aRL+>J9DVLQUsO|VxG;d$uk+o@Et&;ERJ7i8x0A**Emg8|v!5vFtEBSb?I9 zFoXaxFU|}S_{-YbT1HV{_MHKw#%Ft;1kT^3j`u)fi#)($Ozh}BEExbp`Ocnw@K-Ao zyZ;+8HPl>i<`{E~e(0WJv_t0I+KR9O?a>=qYlQ(X^dpoou-kzL1O`qoh6qIjsk2Mn z+i>n4zq%0)?j%7N#aznWxLEsu7;Oy{0CEBaZA7rxf(YU+?&@bN(BLAti{MYvf!q!$ z0Q(zKz$bo6h$(7mSPc9MU1yn<_aAi(6;O5Dt&0DQovDtyw(18yT6 zDYXWYt+-Ef@q#_1Ev;nT}IhxW;jH{ZCxPCGbCzG;VpEy#{=K z+|mVogHnJ0dcB<{lqwLI;9*3BhjazDb9_Oh zDhRv?SyyzbxDo>j*l9P?P0oJhsv{fgHvN$AMQl41kD#aEh(bhwS~4N*4nl;IVoHLmY>cxa7BGM;(^w}pP^gp%c(?YXe4=|O+>8x?mbY5$a^#&{H3S1S6Asinx1ylt zRDy)iMkET_GVZjaKOzM$>`%YLmyv5Fk(yofr;S+-nfU)Mw0*d7q**TTA4z-144#^y zj?Si(Ry8pc=TLtMVjV5@_JOzQ*nS-(P}kYF%G}$|MXJBafs2PhC9Unx(RXHo^eAx= zRSE=UxP8#chs+Ge1%8kY&qu7%yDrQ-MIY}}tuWe1DUN-k-O&3UrH>P*PIr-`ey$qy zH!I-=EOO8dUlkP4q29+8USv6Bot#WXu^pi7w6%Q*s=NgKi1314O`N)y4?G8=elV6m?z;R)I_GP}8{=o&3m$kzA4>^epSYO> zKUXm~pE^2?FW$ft8L}F+IewZKhI`yW7N~NR*&I+cPS(An3%|?*~;5*#dT@nIJW$X(zUfmsN$OannAdj8IMrtsJg= z+J5PcP;1)Kmh(kmWh-Nf)}A_;0v(I0&j%G4ER6%1FLN5I2|J@2h1rq zx!T!st-snl+uXH@ruLyy_JC3`d!fAKHI3Ucck{ZYWZUsgC@3g+z}H9g1KS!tn^JwR zH(|&}-v`DhZ)8!-l3`YP8mc~rKu-|YX0H=xHfqEm- zXp6kt+NdI3ym4J={@sJuH@Sob1nd3PrG+;genQkzkB52flM<=Q9LW|--D&x*ZE;*~7wzKZb}sN<_}hK-kMV>u&m z#298j8K_TC20q~pq>r}>s6siqne=u|4pPx393Ulb7ijRk&iwCtDRG2CS9y~RAV1V{ zDkUWd_c(RHmGP;Lg`7;VC%N&*S!G)-9*uV=YfSH|r*5?=SI@dkQ=CnEFT~Ij3pRr+ z2iq;f-ri}klObS2?*!sEr$ZiJ5OD@7-x#J9bop__UvYqH^8X&nZH`bBv5*5HcExRm z%LBTAmt=n!H-au!S)p$2)3q#LD>#w&(+?E>Z4qDb)P zRrL1Q+lLYg0yw#-Xt+NI#YuWsWg@{J02M5E>=UN~y%&*Q;bU z{Z{4J%q|^*-#~wS!$H+4O0r_CtR9elJ; zVpG>`D)z>WizFv2H)kX#w}z*WV`HPB8?BF&qtyhc5a#-UdmpYQ8Xv*jQ)f2;g_LOR zw!%84ri{M{x=>6BN%ion1~_>)=wQIx8n1e15c*b!nURG>x=522eRld8T82zY3lp|+ zqhRMJGvBr~CExKmAf;@8V-~jk*9i&RQBPWO!QBdL7iL+Gmq~{rOmuYI!XqYDvQ}9^ zqxfO?it%tRd2%^xsdGW=te^ygAfF%!f?t>obyVZiM&dPw>{N4l6xDWyzHPKr!zOszbqS-q}*^5BGVM4bc$-1_EVNmI&DVoO;3M6wj2p@lJnz zw5#NG`E|IA%rjT~#_-0!6b@7g@u$UO$|fHm1t7c%1-TG2Y{%_HW}Hiq-_E@MPS|Uq zW#A8zcB?^;EM!aJ4Qb^Ru>I)roVlwn%qZJ}EiJJiuqt&wcRA8LnmJf zHC~aTBFj=`-e@lG)Tt=t$HWa4yi-lxZsHizZZCum-)#yM!b|@K6*#w0+qZ6cCxuHL zdMJE1@D)Rs&-cnb2$MDbM;wyVFpRi5NWXNm+OT4xa^@owhj<$Hl>~Y!MYU%_=yuT7 z4j_*o5;9kR8~PGDZ1upvfPMEi_4u|~an-gpN`cb$r?11lORjZCoWTKr`7lWN5#+)< zb?jlAtI^@@OD=2C{*6$ya7I1Oy0_!a)5g#QUI=}F$c*xK`}sF2^HDh7C0=sqPBqf& zWNe>DIQPfKOzd-HD|s^249;Jr2AId?DBsnhUEZ4I7D{N(Gt)XwYPme3SdqmNBpswE zBh~tJ>^%%)*SiC%E%JJQ%RaTTgzFCCIYx!<+zJkSE4`H}tfvMhB}O2*pxv6mVOyd? zxmnn$B$196GHi)Km&13~_`=eeeUDL7==#C5l^ZL9W!tg5ls*<-rowT_3eQ~A^SBq}~R!C1-O`*z7i z99sfnWX+I`E^oJHZRemt&V@ZhPJ+=bqop|N>eA|V1~8nHL^SFnEx9%A&r4pxlT^E) zhR*BfaO&puxS2J5ubV2-GwX@q(6{A3Qa!cMYiE|8l6Bp^vE3~16nnOG`gQTVh!-;F zl~@m-3BH_i@QHJ7F#0<_Z{Vt>?9JTrG_Duff4ovoPkZqrEC_hw*Hyaa3~(AJaTi`s#edwiZsgqu^9#zyLT~t-l&iW)@S29hayS=l zef^VdkeNX#&dmDhhRXB9vNYWgj+mqG>7Tjm+*Pn|DOB7_P7 zA}|1<8x~E9h5UQNI%k-i3w^p*k23sLc(y{fUykP9oY^zWvO{R^+ZwXR_zN8+s}Dpn zxZzRN`=D1)CbTbrPoV`*1h*z;Zd^%HtS}4yVUo-DWpH5WIHk*U5?i4fY83SQEoF%DHIu zi%gtm?ryoplp0_9VK>Q1qLG%LOP+11bKgp_t9TulHac%T)9InbBPIOt^Jnq+yP<$B zc(dqfM2bNG0xOk5y)|KyH!?9vR^xJNxAAl{?RDL!dT7^~TCbIRO-UntW^>1`;L0!``JYNyfSJ z1$*6xjI&C7&$Vl3qw*dWJFqlVkFw64zV{^AAGU7{ekfdvH`4zGmqH-f*`4r*sYvHC8W7j1448 zbXJUr>(tnVw46q8%lTGx_oi48NyG_r0AVOSD$jbHDx6I{eXS)nfL*5j5*|m_cu_u5<{1695txND;Ul z>@?%zd+Kbx#};b?>}G+G9QLZD{7O~}8fskq2`}PEu9eQm`hGF-&Lb1YF7RrygtT0a z|AO0Tj74kaksA)>8)q((A|oNQ=nBgIauiwoe228S#56vf;g;{QMM~?%-j;-(kDKM$ zBHqb}URr3&w*2JLte^0D3@-R2`Dg=PuLNT#GB}r?7Zg*fh6NeILd^5j=G6Rhc!Du1 zhJsjU-^Qzf!WCnv8fBmTc93l~$ECcnS8qTEZ$9>voPHa352YY-6N z>Y-)wjSX#i1~Ml?o2dOxoT5=u8#Cu`jXX>0S=|8#%A^4B0$_0=n?ex~WC>`Zcc&xn zEqT$nE!Es#%A!>twXoIcsp70j!#iA!;`-ol&)77RS}t^_%%0a@&f)wiOow}@x}i-> zu|wDn(Cy2t4-<@kj@i$2gm*5*GffS79iRW&svANLLUBC|XTlPrDSFV2lIeyisQcoFa&4d|Wjr3$ElFUJEDcDs*>V4&<_ z5vgu2x3M_J6~Ai>vkwxF%-rK-CsC-3pL*iitgqYqpSP>j(Vxm**Ha%$yvT4k`&Nb1 z@u$W~v#apqW1I^lcEm>@NrwD!UHNh+oryH1e9o#vSokL4yw(%~{>ta1Z$pN`bJg0< zDyH#8t^To>iC6{dKpsSUVpZpJ(cq-o!2O*`$r2ih{gCND^;-d`{4!#$Et6%RpISxmLXJtQ9pfIU6kNb-T zL7Ywo`+~WGK2d-F#Q?BQbv`~t-NEbuQilj)BylTCR$_1Ch(t$qvsT*I-HUisb3^ zKm3A@dFKvKTE8;c{@`--<=FSZ67?o3@p+XVExLnga>TQZ#s*Il;lXo?d#P99g6Mu8X!Me&}8N_w~ObA&H6{J`n-;flDTIH&{SW7K^E= zB7k{7Sk=7J6mS%ix_5G3{B&ivMJi1MFfw;z;S1eXH@>C8C`Y)AUU8QyO5=E%^o4uG zA4jCln`KXQ^Gb?ckf{&6k_hJkEN!28U8tel9r06c&TC}>9+A?0+}71)z%?yDYGJ|U zHium25%aBa+mxm5eThKxkJi)11=!|@s0^+ZsLQ~-iqG~Kxy|Rep3lnoU3&goF<`4k zuWS4olX=R5PcU$!KY3^MD;=kMcPiL$6Eyq0w5Lu^<`osK$BzPR_npjXiFN&MKQDDixTb@f&0X}JuBU& zViLNa0xv}FuNoKR%YFWVi6gMq=!Vjv@cI)LP46y~?GcdSv_hpoW3LyJ>ow}KmD|pA zj7c4ed?7`k712#Pc<5T$Gb`}lz#tZ7by;84QPI<(SA@EsE@l?+hSR zKVVpr#HK=dA~xg)&1j)k8Vhu3Ck;07Uv|gKmOI4v`hWel5Ln$=XdF;4Z&|eEVpzUN zI2#prCRGC;6aOof;sNG&#DmL)XTP;`8oofX;Rd#lkGnS}*h|znHRsEZ93n(L@%&^| zEqq`INT0=f;@o93;mfm4jT)4=9Pi!U8jlB9hJN*JBLr$%&RlT8G8 zw4o(HN-N)?0Zk!~<2YyN6{MtRwR(~35MCghXsi_5i=tfCY6_i}yxPq7s2+O4@>%gt zwNX%nhCH?Zp^w8h(B93>)AH$hSu1%^a>Cc&zjG_`Ma26CZ?9e9zVy2-U1Fuw_MAN8 z*4jh-Y(_1tU$)J9*%V|PCVAag*qUaKRY}P6R6b~BbopMuw)PClR1OsRZr)-2!V4ANYqy&&*Nz`GjQUW8Y6 zd|oeCjm*ULElJ~3Az$4#%WAf+H#bZI?F-aoo?lIb?}SmYu3%(iE)g0HPj=IQ0K+wq^{;mPL-Weq(wRr4M9W_z)0a&k7#gkQh-gAFp>KUQ+PCWJ3An&(f& zf6E)Nk3g@Yzm2KT-OV+8u0LNXkG`S9V`rTWj8H;$sD|g@MXp9xSwqE5F5)rl`t4{ogYK<(FXUEjpMJB@93Qvim)5cG7fSD_o!N~p z@LPN65@>V2+iXKYLo0(eXQ}*~!TG1iuAmrUuf1^aidk0K5#!>1nybcRm9Fg%C;CXy zpqIL}-gE|~QY_MMscE+6a#Q2=+n6*Q%Nw)nluZ2TKq=y&*$@KKKwp6wBrN>jMxDkY6KT}lPJ3!aiI}k=-=!1 zd#I_=(#Lk6Y_N1m^TRIV;cwCpTdjyPan}TJ8QEvtnujN!XKwKt1aTq9`3xS>Zzva z(gq8%objYEcmz^+NNuXbuPo(Lv@f1NfAc668u>}iYdi+@ok3U(1HqaRI*eJQJHWn(|+1mAvWLV-r^XD z%#M>rs)gTSp=dEEk%T3d1_DP%*Hr)NHU3W;mhrfz@c1}F)!d(3QHPT9;j8Ol1<_n& zd!feozWXn=ggf6;|8Y?{!;9%*CZ#Bvj{9m6hRsB&Dew$*ns=M!L zjqyOlXAv;Cf>@!CAX&ApEJ=Vwj+Bd)>H;roWc+Y0&7{XZrH{$e99q9Sep|n{+r%V( zrP@ZQ;Yu9M%>H=H2}8483gTih@gBay)o}-lJB~4=J2hkIl0;zj>iXrUjr7m1CPGXF zGdyyPlR)0>@OEr!|E6L}M4&(E?QpO|pn_0f?Yev6=}t8=1ZsE%S$By~8yv6fPNyXA zlUwMsKZ${vJ7SFWUMHTfhfW6tPW|Zq2DVJ~3qg6mm-dBhj6A!fq=c)KK)-6HsdLMz zx=*&1y^Aeq`VjKR6w3$|F6F0XD{V;6)&$0f`w={`x z$NO5ZzFqtk;gNgZJ^yH)6tEQ`@@#p<)@iH{>i0T~SGrI1q!#Ifd~IN!V_r^OeSXhL z?(O*}-mAY?8F(10d}$S00lUyOF&PWmrS6dOpyl2Cy1xOh>cpn59)m$Z%HNu2&U{@S zw>_QVhsoa4px-k#3S#Zh_(E-NWBUCu2;BgboQ^lLNcBUwCo+`_W-5XnAr~BPCd+8k z$EP-CyCR)#0C`Bz*ITEegr)6nTGH3Y(Bd^Vj)RkN$LV`*M>^wTeORdHjL~ITBhVc@ zd(qFQfFIZpkXU8NlrQ#D4=c#O5;bS@52(pMACjQ*WqQelWbs5-kdFV4j&^{5HAQXe z)8sUXvCr8UqS-r@sKPnB0_5P&Rr9xk7OwAZlIuhpVu}xItFx!+<(&eQAdIa2G24@D zZsfvI``ra><;&1L0hqa^-D1r5!;HVZHR;xuV?iB@BjQgLm57oT{K_3$W1OqjhD{bj~zZ+`&G~yQ#fiL7Q9tF zyj-W~!lk&Yuh@g?%xCC3H*@eck}YI3EL^NT%Zpyr1{>_s_6=xrHAhvBD8 z&)pr2aT8w`TJ;4f}6;jf3h3V+eB5o@l6DmS>C z1Kumqf2@-1*`3grY2lLk?zy347K`PJ-62gT2$9hpdhr%TfAszfrVxB=a(8`r)h*yM zyv5v3P*l+6l`@)3weO3)*LHCaZK45-e2B!Z)Jgzrr-~WB<3Jy+rpT#RHTgy}<{C!1 zLj<9;z%%ZB?6p+EtmcbGX-6`h?W4QnW-2cD{i~tJHT`2p8W1m#4GPoevPMYvdV{vV zP&XS%AKwmalFLx8l7EzM_J)Wk$C7q)Bxj)1H)^7!$>x)Yqkt?|27-n+Nl6`_Dohg_ zU*?qSm|Y)n-NC=TlY&NyD&@0ZS(4aOs2muNjFhsIWbQJ2sZ;oEk&&s;zf@=l*B{Y$ zS@qilY3aFY9gykepI#O8JZUZT+LXt3`;+kf6Xn13?rqVJY4#?MW0nLZ$7a))-F>wO zq80*7+8eCw(aO+W;Xbn0DrNHFHI-%Px;RN@mG?s|JVO=gn1;90m7Li=#ngIu^i!59Mta0%mcK`(4t#1%g&cSrx={S* z$J`l`7OnZ=OooQJ9oo?&zlMZC^~>x!NQL3qFZ`z`@*c`_JhF~5ngUKN8Y zAPHFhaP2V*CV;>oRv|BkOndjP)9ZyCMOKf`o1*|(zcF%_hxBi2yH(#6Rw_(eOY>`V z5T7Zfi5AIRN)zO7>{~H-D6v+5kt&JG+aa8!1cdKU1V6!q3<)0?dUR6`Q7Vkt%%TBKZ zJ<4TcM52dEcix!`XGs)l;}p?{KQFb1a7e6ag(fcCb&AScdvOVMI@Y3hbeWZGEuYP5 z1`FqIHK@xbC;@C_$Ts}NWp<1C$_H+Wx$kRgJtFi&zv6|fW7j58^R9g&ZCMoZp>tNj zh%KZ*A0%m`PvqD+u;{NzB+ky>;wUPzXK=jHG{*z0sX@*VeP6fh(Phy|i_?#!ldC}I z4CWqNX+)mlzFNTpox9ZieARb7qxun=mwDZ?$UJgnQRE4_ns}qthW0ZlX=`eUn23bU z<-wfhlwv#S_>v3mZ{*x8wYb`=nCEnt(^j8P#TLEPQ+{KfVc47aJ8OJMQ<(lmYXF=p zlX5O&9aPN|Eu)qtwz9gID;s{gnZIqR;jKW2;L4}0 z*w@3uB`Q~a7w5#5d<6IVijcD?i^osQOUM z)j~`7OXg_SxsY4uuvNp$%Ia!;t$&%OBV!txn7fhQ6u;CFF1j>Q##_NCH;Y$IYxiwGOl^j#fCQ^dn|&`APrF2Ix=mfCxfG z{Gy|8Bd)-2?HF~eNS%>CJ+uj;sJcT~vHg1vca30H1KGmmColb8Mmdt8vZE9k zN`}Lwwgqiz1oBmT zrAJBpS2Ua3z$H;05~fb}^{&?PuUSRMtf`ztB1MWmkd_Zd1k;MQ9KbRA(ZEH_r2O_x zV>KVg*>}FfCghIZ#FnlVi~K@m-s9FTlDguVYsUlpC1nT3GpRLD>RBlk>@p)fBQy zN%0dsW#L)AOTxeSyoG;j`&%!&N9pzzxJ51qgs5EMonCXJ0R7N?iKBmMy3pO;luGU4 z%!=^HSKF$`ubv+yoC*Ld z<}JB+N}k69?}Tok0h@``$*PLVOIy=&zr;bKKd{>iXuw(GjE@#mEL+R$;Vf;5cSzN(iztQsIozd`leBqF%{N7LZL+NBqqa+L0B{}XV?i;|Qdmbx zac$|+lF+fphrNrl*%Gmd-+V!S`P@ zc(OjzcoC)9vk?ZIY(BL9fV{EFX+ zhXFZuY}a%r&Z^sbOr%>rBaN9uBoFHd<#b=0Ff5&s`Ok8V=l#uN-m*bc%fsyx{Q7xe zWnd{+7%7jMe!k~mSs*<1mCc2$ zt_(Ksvqt?+eoOSZ8M5K9bTmH zJ$rjRY|2gPBK?)W@L1SHvyMh?UWj}^=Hbx))!C>iE5&WRFn`ud&LOMo-N+-}3g7U= zY44+HZT+nR8rQ-Xf8}r>DEndBniYAa^^0nFrJYpms?5i1yP9D-6wwO;*-G0km*-W} zS!UGBud4lbnnuZHsYc(gEy_uA`?aaIrJ03fVw4i%l}2&Kh}n|R4p!Y9c2XHR$im%i z%jbVAU+juA*zb0+8Lue@iLpQ1a@ z{L|*_rMJsIEiIO8SeQPvrYvl>8?zcJK9}U8vUbja>xyjasIl#*4!vH*?)Ap@G#deF z)5u3%>DEq{N2I(34rE#kbdHnFf_cns&aUR#ZE3p7dO1Okh%=`|zr2UEvoxL4$lAhj zlIue)t)-Ss&W*jKhpuV1uM&*;ot1hVuMbs!zQnDggc1wDSZEeF{OG|h>XIwmu5G0X zjQ{Yt&-=-Qyu4w%|!*O((bCti&FS9NGj!9ed%0LO}T$e1z zgK-aU0sp#JW6KxpU-H6KHtP+h+Rj6KknLfmwV}o?1M^3n@=f zt@)(0;HjJTtM7CV>v5myk9OMH`$cG~Qx&Os0ht`eDTiR><99{9q?`7-_Q!6%Hwr?% zKhH(a_H=S`T!xpRQi$sAdWM+m`NG^m4bNge?KU(D+11i1t{;&q^UBHbWd7^1@4iO} zt4Hrj`~hN^%+fbG#;;_RHyK%db7pHvKXZ4V*kV8Ntu9+$gxl6$cKGMpiehca^U@{J ztRFy#WII2GJm#8JbRq~3xnx(kL_>46|OA!Y#!c1btmy)I%nN$+bj0_ zKHePd9v{%!gUZ&9S^nkJx82oiK3=g}N0~NVRK9++I*~=);Ba8w6%ExuVv7CYuv5lE zwkh;OSxZ{H6ztFJu0%d)Oul|k!~ASL*5Xo$PRM#f0)6ZJSTL*Dm$W}#6UW_rH(k7u zOsn|rrMYwAl0R#^Xdm5v(0xwQR7Z%YM>D?G(=cd%57Yg>=~|V>wFzP+<7exI_?BWj{uBx=v;{z zm{{rJq@m3_W0q7+HM1m46Ye#+@auZ7=C%4#_v{j1{sZAI1>0{|WsFBO5PhQ0|(NVLk8PT%RrF0La?U?M-Iv%N;`R@7xG3}@! zR9MjWVeDl%R0w6`7gkN<|A^mvvZ9ran1X(Ev=}d(%Mdi+7SVoKCRw!1*)q> zJ}TLlk@D;lZ;}4f$=0fVCIrgu0Mkkt?b0xb8Hj>EzbE2gFIu+F+p?@~zxVg(uiU%* zOB7~8s&l0J%I{C)*|VxGzcT~!v$BvOKix=9K#h8(BxZ7u?3V3bZ_4xjSkz|>kx#*} z!9JU3WJ$K0Cpt+#i+@EY%<8S8F5$KmdT4E`x1`Ri_8_PWPoF;3$m=UCH-(U(Z<%-D zn(x&#digrPO1oohXGg+iN6795BWEdmT0(de(@lV~;S&(Jc>d@mL4(40i|9=83yHbZ zUX6Ypeb&v1q)98MaevZT|i8~K(Hn^DZ>eU0ZtuGhSAD-}Ddnel6KS|-I<D$lb-W%6te?5qz zbF7{|zW4oqihIK(d8y@iu|m{AatEP}xj@7v|S|w_GRffy`I5_o%Sdro8)u z_tSP&G(LWr`!2i&6go6;eRXbJDYrcO9fQZrou*6tHz#t}6!1iR7mKt1)2BzXvM6_x9d%GbpG)|8_X zBFDFcOK{9cXbV`I*w~h7?<2vL1>PgZ(~g9Tw>0*yj&4@V(>Q9diOMUM7>-GB?aj0X z3#8`HyS}7}smUIi+dag+4pQ-u_If#-r2n8*4lA|KuBY8N?bQdJYvCWFk9tH8({CYX z$zg^^eS^)SMd_=F#AFT>Ls6Iyz7iiu8R1qCbG+^N+er01@K}r%8cMFsf0;Ae*ODR6 z=ct$N{IB_a#!7C=&u$QvIIf4r(2i1c< z=g1#SSCj%!mcYKEu>_s?mL1oP6OYh;TKbwZH1Bn2>7T9CLpt^rG6l>!N(4_ytN1e7 zo8e<|Tg}*KzQlYdNim&&XZ3EEpG#q5Y8+BRPU9NS=0aq(gl{%qUl0DaNg;73e$ zD_g5Sgkgk<_$Wef_>`IZ|G0baa4z5X57>_Ek*%x{Z>wY_8E=FnWp5dgy~)VlD}}7A zD0^?&qsU4K*%=WT*{bKf_5FQ+zvFoRd;Waxqr>s}@OHbe>%Ok@I>+mLy?!2;7;6&E zh!kvV&ARvN3Sr+D3(qa{pa5x){d4MRLmi%Rg690YZ2xm&=eTZ3 zDn?{b{_UQw$9A~;EUEIDewWcxwpJ(R9zgmTdT0ADi%*3N@)X@)|eogKd^nHpex}%Bt4<{4Nukgj2 za(bqJxjWP8HiK478&_pKag8osW}S#1eajc|8ePse#h0Y-#PGyEu&4F(j&ZI-F#@zd12{I zeb&TCS)Z;uGG1+ZvzE=3nKKc2^7CzvPwjY4@i4Y0ArB)TySn$$uudA&17^jmK-^45 z5<1u@HHC3sss37;0ks+zL78pqM%lc}3+!?0#ihGW{INhO1Hg8FeZEld;ns8!v}2t} z*%HYmo|TH?;lSD%`i|f3pL1%bwfL^+ooLx@m)<&7qKLhDNrAN(IMp(tmCf$ps7?AB z&PPt%sE^@cZ_ulG7;07XZWt9rTymIiIM5$CMgHD!AM4MwChTX z5d)`GBDzY%({XlV&tt`aSafKKKUUm+JFTSm0+IK6xTl1V1OWpUEW6>MA%`}K1R2HF z&g`&lT=MUX#=2N(SLdAY$>fYJ6kF@9z6XeuXZpA2lz?P{~P4Tnx3-wzPFv>=#iW|JvRgk3sh9hC>~H*sFqK z9d9ZVY~RP4edPgy&Y}wL zWh@DOrIXxI?QtZg?2E-+)D`#q5%AHBUjSx_;;IHHzjxQBkG0*cLm>JSIXh z>}nf#CRAPveMC`Z$-e(8AQE%_Uo%f{*H)Z2$V6n~Bg=w>Cj zO>O?1sufkE)q;SvPn0pld_wekd?F zO|NKZSOJYLDKeaW#5!0qS+7KJW_q%NNQ|ggW|~f)WV|9QM!w4A2(hTY~); z{3zL2n~zXb5HJfyBoy`3iIpxW*=*OoOb}x31XN=d>pJY974){oS4EM!NPvKC;m~k z-ap**XL?QVF||AX7N!1yd)w(~-q6VC5-_`!eviw2;rHB>_2MMDRToGGfF1=3aG6wh zqEuGO z<(-l4Yn+MO$G55Ttk|f|vrwHkC@cDL|3$W+mOQ(}aYa!6;moaC=;8zh7rR=}(VS1H zq>JjODo8bO49*UBUOc}H1k&-68TQJmok^dtUU_J=D+hkMUQX7X``)SkS3PiugOEwZ`Ihjwt<%jj2W-Ac6^GHbttwD3zwdaMdKA|WOHdAi;Yxl?@SQA zdLrgH8vU3qB=`ZF4&$x#5Zk0nU!kyJ{pYJej1^*#y?5VY=cM9m7s8AJiwJyG?{EL? zP5yjW%V;*Of1Ngcz*MYQODUCK$Uf1Mhqh`=o0zwTSi)7p|JjwLg0(Hz>GlUbl(esU zJF08|y$+h;yzcvn#BZO}Uz=Ws`Z?Sb_$%J4W2!Q#8v8DV96T;h8{6tsR;EqmlcMS? zjI({z#g@yJ`Pz2FeNnekS0*xn*~du$+cxzicQoF1!oyVnY#@p)VR+s}oE#sAPmlV^ zmE_Z48rr(CB3?G4U>R6uru*9UQTL{F>9WdX|4tR{q!sP<;hvnFlpZ;?X&imp_a&9h zy0`R>_SMJ5@FWUt?dFE#<)fg8H%5ltbLfll>@18VrFvIfN-H*Y_W7sk6|{Mubt_%} z0Poe^rlqP_K!qW2@%$_CSAGQv3Ov7k|K?qCpfLDYJ=-^a4;a2-h-kIW$kN>H&T^di zcI94K{7ytg|?W7eKaX7XxzzB9!Z68Jwq|x`=dF@W5jIVF!Y#0M22f``bA*3$$tXN>V%%>jV6IUPUf`$rrN02ScR* zO+Ng~Jbdc%qIR*1bv4yj+Y6=Z^~;)6HC^lHsvEYt?gF3``W9j33*2ESC9&9Au+A^c zv#&uhloFe7{p#z3Zv&?zAeel1@s57`LR<@`0ZjDv>aZMgB11emH^Sh2zN=vvA(0RDuWqEny zBHvF#5S3<4zngQ9%UCRjh29Bp-LaXf%@1i5MyebaZ0Iw5EV14wP~isz0e>)TRVR%! z6_Bk-G-pZb%hFaCluT9d`5cU${zv7fxu$Y`lYgkMXsEq}WUR-17zY}9exSeh!by4~ zwdXrS%ajm+^m?m>a$y-18w!nkG25G7`MZ&l!oN^SsxtR1M_J(G4wf*`Tyf>c(s9e%i$1?7<{noNFpfYYY`Ogmj!q&#(V*bHgNt2e z`^)ukSbHUa-7xuJxW?uVKh^e@o3iT(XIufsR zJ8yZi!!MG5X`dmQGKVRSTH5N#xYYK%CoyYH7=8^nJm74fn6L+`6~J{tln+($_uS%F z#hCg9X(m%8*7pr3crTB3#=bIYe{?COGg%EcfD058n4pa%)$p5Hi{5V(bkRdQcfALB zfkk%dbZp35>w{Z7!epuihi`tWE?UP9usj~JUVmnCV&cQOv{d#8R$!r$%m~f?CP>52@=VjQjK`tt zc)9C!1piHmz(HSAitlNd0PO)1-9+O1{eqSnLOLg z?^H_gudDubq~dQ%3@}ex*@SlHpOF`e-CzTR*iIqSOrw5>m%2|?b;>6!h_UhbmBp@j z^UO1^nv)hgLRuOXpkMKHZk58O@vF!IDE|l`GKj!l19JpxA~`Lh-h-gQBnu)yht~2%lgS!e z)SK%Pryp4*526*Dgwp~$=B0pM04O!oIUT%qFdvlizTY~%8>qBd~p3JVE=q#|vqT&0l4MU4ui`y%8nyiss|X~@M& z;gl`595Quf<4*EhVlG^4RYv8x!9P}1suzvq%gtB-y3re{omg?RF!xcOm5dq{mnX5Q z*JVBu3=A_-MYOc~HBYl$aa{(9u;BC?)HODJ-9H`@7sS>#QgT*ZIh#y`*wu{xW?BhOroL=>DLJ;O1C~eEG7Ejlw0neug;7bme$C zDtqz6BEjhdP0!X=rK4qoLGrb!PoLT~WNH-?%^?Y_ofr(3uPEEZMLbqrQ$hJ1!yfrc zOfYX>1#HfP{-?X61Wm#(0=W_txWQWbSqka?=0#s`%XB4x9{hNAX$_4RO56({ChN|;_y*(LcJs)HCSuw$42D_Ay8*6ofRx3g+8F5i%7A%oG zebS7fhP9T%clge!|Hkk9V62N`4PhPJ5^}%7Ny{f540fr*?tV`);YG+)vCk+qV zM?KF&+*_v$30K(k;b?sG3WReH8%A+;`08Atj#B%u_X7Z6(wA~>1ue@Wi$aEq1^k}tlD0f2)pYc0W8Ad?-JC{xml&p zwfj#V^moOFSDK1>Z_itKZ>Bz{P3D%0H%B;W!+0YbG{`1BV=<@n$Tf|wZ{AClckb`$F6}F^XXs{2M9EZm*X)CuZE;BP zs6esR(ve5$t3IhK^l|3oc5m=wl_xdlt`ad25?tUsckRs5j~J!4PHaoyWHmiffV%z4 z#t#f&=Jym(LqQtkvFNo|9rfFccSb@+K+S{ik!SY4<^^Sr?nmc6)|Sk@m$L{Yesy@F z_^cD&O+hHBL(-s9XdVQ_^1zDbLzhL1zBl>%s!Sr`CZkRw55p6hNI5vH>vLJ}l9ec8|85|rGLHX#~;mW0tbJvVAIwu@)v$bbl)B!IXi}g9^`UMa>2DHZc z#cK(QKWI%ZXCxX4c))kiKV?8%_d10(m3J;5R`Ui}l>`L~a@9nUD5K)5b8oM02;mj? zk!e!*z>Es0P=dThSA0yHBQAfslIfFj{Jsj72rPCrKXw8#IZR+0szgB;Vj`AfYAMrp zkfGE0rbW`fRN`vnb}}ofk#Pr3Y&a1iUau`qm2M~libc1^EGv4Yf{3E*#e_<$Ch?cj zthsF!7&;Uzidbffeq8uTyas|Q48if?N4XS+lIh*!PemhJ{`87oyx9=66h)%Qed}lw z5+z`TR=#eK0bPo*0KQJ58h64yZmXBkNn4-tsqlI(P$}WzWS!P0bd3&f=Bk$1VmFvT zPp_buUhDH73Xmww+d7y{Y2O|JSD69!9~?lUK*qJUw&uZ7>OWfMdi@3Yaxqp&K`-t) zd~Z=xw$MBWK9`c0rHx`q7~NW{N5y0)LMUM}A#9e<*q~YZF3B`S_`DqDZa76uy3)M$ zt+WngGD0)L*%C%s`eJ&yT!0luc8r7!CySy+^JIBJY1aFPI^ex}eJW8AacD@`Fs!B8 z(uPDAWt%!RGnPsIO}}#bTjUK4Nl5*je*Wjl$zE>k$?NS<^zc}6k8YF)>=z(lOnrSX zLZ32}(4;DhhoePisoGSqS*oskfFYJQ_!90nh}ohLFwWK{Wcw|W<3)hKep{cQ~O)Y#PaS@%P25^y_^73aQ^Ns8mV@=)MsDYa59u+QFTq=LrY2UBT zuSw1|{zCDE5q7^dB)A5}QV(AwFn7PKx38R7;TqeHxL9lHlPLwFv9(Y1P zlFh|RhR;kN4U$dR5F?0~H$s0l@JE?iSl|I)DD2xBTQhX^Y$Ft!g&(`qFV@;wl&^CceRbDa@`2B5<-0 zGy!VLlg~Z8WL;ZdzbI|?VR@69D;M+Pdl*I&OTeZue~PJ{P}f)dW6fiWSRzH7^Oq@= zhJ)fo;@-a~yl(+rkzy~pb~&HJ`G=|D;|#`-ra9A~BeNP#6_(^X4V& zU1JOCCb>lKYz==^c@FFUls8RhC@-UIurs-m`_QD``?;H)ew&PpoLaT9j@uGJ?Cj6d zudf}ctPiYG5bAnBG;7$sR~adK5iTEa^;rCL_3?Ig{y=cII1QF0ol;w8yAweq!G*<2 z+^B(X&pxgWxe(U;?p8{K7E%a_5-|FA8@+6%=&7}&^c$qi&^HeF`J-5#AY`|;7s$nfwXK7Z+t=Uq;1(|}ikW-lNf0Avre zfsgI=!zp=_XMCnxTqI?!ch@E%+aJtg@Dc@wMP$;CR6SkYq0gT?uWlODOo|MC{D`y( zH|cohtA9_O<|B`G|IzM| zH*lZI!h7K%vK$w*w0)Lm1qo-6D3B6Qhq(yNvjQ_&^RB#Bol5R@JWlNtam#EhG{FHA zq{cGwa019Bkj3^ua}bCD-Q!NkTo*_6O%5Ghz`=yG62h1bH#SuU3BK|KvK_YD6IH0Acm*Gna zG$vf7JaKrlez!_gk2$BN(4D$S#{Aj>@K%AtapmvQqbDm9HNcysz1v(5e9dqdI5s6> zwT6O^m+$A}j0n|!7CG^j1ir-meiu0y?#SbwvdJqiw8|cstcu?m@w1}^h5^OQk$FE< zUz`~oNhq);Htw+VQb)EeZf_~}X~=76Kx&%(`G?;7e^c@R=}ybDGFH)h*}np%1(cPz zXX)EeOQ8r$q29ZHxL*vels7d+xriG~bn1>&_0}6O6(_P2RG>QM9n>}ZK?Vd4A{c4m z$LpEX)ePoA_CO@HQ0E)96rdG88k%0{f8+uLkPwyu9VxJ;dVG^u!}e_D&em3EQDl{{qfrW>iPYgo zD|lX))k&l)DZ#9n6*&hcdki0soe_eH!%s%-+3)Z@VeJ46@~Rm* z`EZDUC49X;_}wKNLSrB=#1EDcz@=mx!+*tpGnUR453kqRT;$<~MW^yU1zNG_M{(yn z_pmU_9NH@Qs;W(_2aHGw&x#$r7<;NrUydvbQ`G<#TT6s3(To5{C{{N%meNqHtdmrR zg76E2+IsS|_&D6=LHq^$h80l`)%p(im^uZ2f5Gj;rK^BXT=N)ZX3f62Bx4@bF}8KN z4_~Vf*J#X0{%cI7eq2~sO|*1mSlB)zxCk*ZG0HEYo8m3+UDz}RdoyaWWFL^^1+x^q(n8ToMY$jCw~r{qu&Y4bZwU)4RWaF~SHvq`v+ z)X^=~80_!HFz%|mYF}NDN=8m@%MeJ7+_PAaA@l}skhid|DK$yW)K>k*ngtq-o@&pO zL!(c+*DN))9*AkzGiuX~J{)3Y&7M5_>SMZLImS?`Bl^Y8NgXEoam3kQ!bSd4YVchr9M5hOaP}9fMC2>^Zt8Za!6ynXpM7qGn}_(gu*FGovk)G+`s~5I z68lURjp0f1qNDG>D=!`Eo}?rvHy}D2vkr`T+||}b$oj(BQ&9hV3a1->RjhNPav}DB;X6=6JVR9|KWuejE{fi7Q zwxS=I-{B`%H{^s_qQo(_wf9>03n!iN*>3g}-j=s!@ayMchlwXwK(@qSg>9>@b1NX0 zO4i&G`{Urzr#g^1hfCcQSzX9=z5D;q-@48kzD}x!gM&ZX&x|jO9yT1`Kh-=Nw+pZ7 zP{Ff?%wUEFR8#(JXX>%aFJV208?ZRT4*g}B?5h|oE9Z98W@EyTtHc0ti{Ce%(%0qp zv=27-OFas#&Sxped2`u&{cY6IH;!gxJAB*6B)rt5pa2$Ac~*IaUE)_!)CA7SLs&}0 zF_xq6>#ZrW>C@1EFj z7UV}g{%()MJ<$K}G6u0Uaw)r5GN{Bb30eoePTvNHTVB$;>(FdubnuA(tWOxlaI!1%>|O~6x_%D zpOg1(fi8i1o>lhEJhtaF&v-sSJ{vNo;1MluBmd?dq{u`+$)VM);fT+=CzY=*(^;Bx zy`Y07d5D!;_PU&(fR>%P30Pnh>U>pa5J85ajCs-Y{SfAnL%tfB-!dB^8fz`{7ZU zNrw>TNQKEuVV8~&^Mu(a;QfGa2(<>t;6pI9rN~V_%u&3N3S@60zL5}A#mz6U}f zPyoXZz<`4b(y&1DzTXdri4~D-sQHI5mbi~JIRl;>cW8b9NSAzz5+ZGe& z+``LHnXgm0UflVn%(2kNoktV#QuXb<>x9~#+4Rx!$N+$-45+K#SLp9i!ik{^5yeQA z(yWAt$T>MRZX;6Uo(;ngHVUlfOzD?muyaU-d>K!^EZ-C8%;+=UzfK78yzikmxBr7YTMx0?=iv0X*Zq4LP-D<<3cA!%6=Z))Fm^noQv2@u z5HV6UGcYg!k~Xv1J21@4Op@M*&qw(`G29vHgp~!#r=h@c4PId0OG^93YLb>e#v;Cp zj~X2prSK(7o9_Q?5vyQlW^|ZS84pILA_)8L3w6r;q7ZLsS&rxawp03;$TI>91$f%X zp!@ql=>Y<^t^Fy}!z5BSKs@FVDv$)%&WQA}va)d6)$>J7mBzv?Gw%sK8(6z{o*P(B zh&uen*Oz4Iz>Ab7(oHf>;Q;5x0aU_)Hn**Yw@Rdbn}^h8?$+-$%&$JLNepY%f7|M5 z(zq>@q~?fzrIEUtW6EcUZhp&_e5XxF1uDFTL*bUQ*NCt|G62M6fl-r{oxsxCWl`(a zQ26ZcQS7?iJTC87ll@r{A!#1FDr!V7xN!qku%zEF^^vv%8$9r9hl`Mtr-w?fvqEHg zHMtYW+kq2$J`VR+wb!;@%a=%_Cz+Jd<>`g}_W1{MdH!VQFFRkhNxuE&8X1m%p&>X; z7CM^d>^#qIw=PjR8mMCY9S`-|>LYbwrgqeLs;q(^;J42~YPU)#a}9-{P59~Guk;bJ z;s#2eZAy~BF*(q=1^GT!xI+bsQH-|p>7Q!MroVqIg0N!Nmao$gh;Qe~n&4vzNaQo; z&_W;|$DU7718yhfR1K)030}P#05A7TO>in+z~M&h-n{Is;egDiD<@qIWt8IwxbrSy zwCTNU3B2|pM48AhhP7t8niLcuvJeRke`7dA{w$UPsnmf``%1BaSntxI#8nd4b7f^k z4+j8VtgjXBdppSs8TIBOtp60V5J2iIZL~Z5JSdbpddawPi4Qq}%0s7v$6gz<_&8l9np8E6hyAoZGaP7y4FY z*I?bC`wlwtzPG1~gv>jIL7WF6Ge{_os)U12ZzCKD9O4k*L0bD_T`9rO##%bx+0D=* z4Zyq|=AILG7<|SB*d^|Sc35{V2BmgN;OvqGj?pKYo0ynnRnTn{|2}( zN@C~U%uEI?AMc=l!W#qd)feGfX}0Wl{S_#n%>@=1jMiteED{d(*CtB?nva(K$!2`q z+345O;M@#HV?i3{M=JOr($>YJoOzJ%l8gM0R#D7tW#4 zotf2RFdW#dHdEaOB61FYnfBfi8r8?QJ-)di+4OV9!lm|!u^u&uVm<3yDo6#Vg$~}1 zi3uj`!EB7LKI{?h)1!WK7hYcT62zYNZ93V+bE)w#)h_*^oI}xbc z;fO_JdW=sKuUhSDicAS~lo``fJNU1Wk5rk^Qo|EiBvp8pI zaFgtt|DtcOY4@bM8#f=fGKt6+rrL&?C!84eiMN;vt1v*`-+S0E&$jt#^LHtHdvPi} z40xT1Zs5fSjupscLE{0Kpa5UGjp&Pq!j zuGYeps~*4VMKAh7rkqg^0kwo!8Eu(N1jE{J$Q&W9eSiicYs7dH=@x?Hz-{hfU!P0j zlkR)_6UVDZB|_I#7}!QUPmgF60I;FV^F6l z3%s?Tq5g(FRa0J9hY!6K$U7nce&zci#($|QqV%S4WXtbmc8=v< z1|n=J#p~Oj`;ZEi!uBAk>f(ti|J>h`b}l51jN%won)MYktPNr~4qW~DtF6Ws%oa!{ zBavQJtbk?lM@-PP0;--MS?aBUM*5-Yild6QhaWoE*>sRfkjHoR^OyIcWh%a?r`dMRG}l}9nx`Mz`EmV-J>)%;ZF9mLU$KS(kkJtw3B zgdP;nXT6?alHRHe%l&*T#~t!!2aq7Gmc6Xw(3=90-pX=_Sy0>M{x+(ei_Qz z!~n}HMb@hqT;?4YX8F`~2rF~_$>p~}r&q;OZ*F;ts0r6SwBd*?y(Jt8-T-V-<~c9Z ziv9aa9U@O9V!c0fZit}oU79{-W!O_gD*an^eQ#7pgkCN$_mPE%l~@2PxaLpmF!AA$ zr><7n0r3&l=$>+hk$6d9NG)$)}ViA^{MEb)R&f{1U%)GV77CzhsCk` z3!ACg>&J#2RnHy}t%d-3jfCXyJ%ZD=M|j&^KUGaF@B8Q3mKeFdXZ^}YkgZLk`y&Z# zU~MsH#7(n}2MVQn0VvxITd}V+Xw}A23cs;6yIqsa8-9MOAvdBjr{ z&ptlB=Spa(dNe!3HByzuK#gJm9|K~aVM&OfoCJ;D(Nb#^QW%$59Ay*qb0y_MB2n#I zK6~~%K(j~zwOznOlm8Flnyxx#>DH_njIVs;x1O-XB;Cz*SkT8)y{HWEO(K`0!j{E& zqLGjSoibD^k`JM+Dx;{<3{=W8lbN*}qVThPAMU5x9lWFZo}cZTyN%~CF~)luVoPzz zdu$jWX;m(Mzh_exLlm0SUD1N^`$ zdHlQ?y=wWyRQ8D?#a4};>EUdP&&@x(rNndYf8=icS*loj@m6YM#1AzX+=iPhm7EzB<(rVo+ZNSp77QHtSa=QCmi9ZXud_! z<(~0xSw3kp0Oz!)+D9z#+84-rJwF#;b>t^hsomLWgBfB4N$b|{E-*&&4M^bdL@GiR z0E$u_HMSC`KUhOJcU#9UrfqUf)tmwGUfnmIlKK}z@h?NVFf2Rl9v4o_ENLIsfC?9F ziaG#0FQEFm^Piy%8MyfgE)n5D|2c9Z3`@3WRwG3Ne<=)@>x4?3sJkmX&Y5msIj{`M z&E^l2g{UdG(Q0T&EP6{CogH)l0A?oR8cd*1y<%*0Efs$%b=|0z?fHn~WA@1WUO-pe?e4q{0b);Mn;$BLsjk)JcRAXGq=)+XPa(UJkq*j^!O~eNB^>OBoXobKAs) z?W3UP0a<-%va+;K0+M=CcPHkuY1@~N$2Vw`2TUEZB_@}*J%Cp6iwGt8hBJ|_HS}{p zh5C!|*49X*hmR6|nUPuS1(ReXl4k(BhCDUEiS7$+|9(TW zeWA*&H=!37dj`1%C4U8LDCx!hjgKANe=oOz_+vajL~=NBkOX~=QRthk008I z5V*OwOfbM#tgWqcUx$GGp}@g}{Hdjtl|NU6sMyP{90i*4I4%v5cdURM39qy|otqF{ zP$Y(m3y`t+{$1XmLlQcn($)yNdTea0H|>o=M&#nRdlm=Fj|~Fu3vB&?;VN;g&xio0n9uN+P#i{l?1w`I z2*MH80U#VD^*WO-CATFHqoOwK9ySpJ;K8eDj|iv9yc*?KLI(v-+rHkDV_RNI)E%O#nbg_*5b>WUDZw#JvxmcPQ6iOy%eeZB1t3Gm-dr7JTc6gioDR>DE-qcuks<@`d_=9!r zNi6*?hLmusT-LqL9}mg1F&KXkFt2)f4x16JRJw!1e_02^F1fjflb2Y8UH7;`0jBVTd2UK+DFypo6!20ac? zQIJDXPa(e*R$_-hy6~}pnib;MY%Z>RarwMnHa&12aePR^76uG&U+-@(1gs|FKYc4V zr&6MZ+y)7gxcZe07S>5scEy4hO9>r`FDt!Yjg zK&tkKpBx`^6M{Y$xxe)Kf|-sy;BU*dL6k><n3Leb2F5J>pvhbRSsw ztq(1dp$Zv#GHTU`YAR>~L(h;?{B`mTJ+Nv^P8tOy@pQzc#E2gop}og+r^cnbU);I&1nb{ztU z2hTa{#`%b#%<4AA_6626DIs2O=SGe&At$y5z7_&K-pk(V#I zH%j2WpG6RLhsJmc3ozh#czCo>`x%3(C6u24wgw5O%Njj%K>r>QY ziy0~4@PYMbr8+N7B?r)q)dv5=iU{bsafI_bL~Z7g^5_QfK|df-5{3l?wOZFZz_q?H za`=2Oc5Wh}d1BrH;1QYyL}ofAe|R9y$H4f9^blsL?}mgGgtMS81u}2|Ed-}C6xI6k znZt+_K18+zwM-;zj9i2B@s|O0+FE1#(!%psuYm1G{)DZ?q{OYjM~i@O%)D1+tm|g} zM;f5X0L+1R!S7`%g|5n=3-Jedz@0mHnA7i;uBT#4(uw>!w>4sK-EKRsKt>|Utc>+K z@>jpJvfSxm7Y>pQGp)ph{Q-U!**U~$O%mZ1^FoOgs^YC6Ckq;4E(W3II%T#D0T^gm zlFy;(__&PtM@(B@mtpnm&q&D&#tnSezVr5d(w#4Eo(ZzhUgg%P26hi{0f6mtq=I}E zCEut>Br6$#=n$DJ>#95Rx1{;q-mC(;XveHfIwIIRyJEAe4rE3W#uUG1WDK0hC#<54j?kP(Kq|2T?a)XBAe~Cpq?GLdE*`EgxG( z(Uzf@UpYd$TwT5bIat+r1uQq>0NeQ0dGIE*rmP!YqNi_%{|*ItnN3%CM>qS`7=C&@ z_cy!SYT9FNDep=M=h=qIO~irXiN|NOtaNZL4PI|Vxm@4&WP^9%Vx0L=lj3K93ytsf zVnMR7%8Q-6ZsiFj=~wei7X8goRh2N0RXVzkO7DFrY*u#^_L6LSNC2S>0Pv?80=>$} z$PL8ySO`OJ^yTOjHqi4j+SG~`Kw0eie-oqot}ZTfP+ViMt6!pKl<+8X0tq{y00zC` zHG3AQMX-mrKJz7XXA+)wZrN@a!NkW{PQpd4)J;N3V-)YK`eyW&RHv@_v5>XKqnu#O zn8)PgYQ%z;8)Ro?{4B2Ch8%V7wu;_VGYazI%{cU&RAY4W7~w&SFKI6inXuvEI+R{g zySfD2kPats;`I5(8^)dM86hW{S+LeH9v)`7A|!|M-nvK$&r#T-o<-&V^BtG75mL4! zh=G>{I(R?~2^r|p8^92oJ3Sjfu>;yV6kIDnaY6S*(G9S7X33Ss;bCrp z>{!?vNtgQnQ#QQ-rJjdV!bBaSKg&>&sTaUei4Q3=m=WQr*!Hb0Y-^WF#XXl14vwa< z!=+*-kjaHA35ZOB>H&Ap>8S+ZaD-F}|4_qF%4aMXLd9)c@m^$ObWkxz`f2aIEPsvl zy~)o;+Rp-?>n#@b2x|rIS!GtQLrnJuno157r10C1Bdd^-QXn$O#@3aJ`GcnIzxJy& zTbp{sLUQ8=ZJa%538y0X5cA_cL(ud_=8pcCILbhPD z!Xy2A^owW9vep3&K^LRGhuE#uk zMsBAGmg;|g1_?v>7AUGdo(Az@VwI7CRLGdYo4g37Octc}9D11C=l-1hG;;syu^0_z zakT$zY?h=@J7a-bM0$EUw4xfhBeBbO7flh)e**}D+TlcvPa8N>aP14j63VuszyE;> zR{R(fh^~j2sQ>q~4Aei#q{)~gSkaC?iPb2=JgX9~Xm~&8L{MP#rrXJ3Q5~G{iz*Z% zt-iI5h+7EP1`83)61eg9KI?khGY8G?(~f<-wXJ~b`|quhpck%x^8*lOs`Fqd*JA*^ z)K~GpV}*?w1^_*F3Nib^B5%o9b#7cxFntH_`bKP|3Dmyq=EKHFfV3ZU4j?nTP9mpP zxAw2#d9eqc?$hXKu%7+93&WN!)9avDF6w(KdO!d3zkTh9ydyV41$aTIK4^#n)vVUrpdhP))S7af>Y=vsyvSx>$5$`}(ch~Lww{_g~& zTfC!onY=j#(VHUrZy+r2KGIsGH z?G1FIxoG;p?*7M5u1qO;Z52iTObz@9)|sAYcC{?DV!-?|lWDs8cZ-5_zug<7Jzsy zy#YpL&O!A5%+uNXGuHuhUqcBf&}b)i1q&b(6t<5E&j(tr;A05fx)lorHRMSEgbOES zL&^VHsMet<6lyM*#;|p6jv4yb5QhUOROS-245dM*?|%&sfP&@7|I+~ul<-4CWCO2m zg0^HNoaZ=L{>YgISN6>y>B4RZ>LE@C5inr=1&LKaQv>P$)|LPS8W2LlO4zGCLn91d zYy+4Zh>k+X#RszriVDpu5dm#&(r{8%RaXnz{M&D809mLIHZ#9U2ZRSjggS+Av-j`u zK@PU#%o+|~1h5=7V0RfwavB>MzPlV}vsjN#mW|HLkYo&MO+!Hyt`ZZt4HCG3Vlvo6 zIMR%+nib!t!i9|kZ%7K>2B?X;0^|v<26;itQKX!IH93eY0{k2RL^pi!1VAm6sUT1i zP7Max36--OuhJub9x4t#pW@s_c0#eHwLf7fe6 z=cYS(OU#%!Q<J^B!*h#wsAnCUs@!D+RflEk3E_VWz=vR@;HK{$z6ec0ea1D2YI6@KVl-yjO^H z_27jfEUSPf0lLXM91pJ0VMA|;pDZ<$n%^Vs3&vA^CX)h03=Jl-qr5Md8SLM&D6?M*LlPc+`NfkaE}_eFz$xphsye)5(dk;uo8oJ>aX)!HV_-s z8W$g#)lb`jiagQ;-)0==zka^lwsFV7%-frB+rxW0kX(^s4iMHQzHYb}c^ZGd(&rJY z)Mf%x?(R!yhY9U~G=Pk$si`^pbGMAMQxf(GBG-FAU;VNuA=X?Rt|$|$nN_YmHSU)> zmswQbRqzdl{u3G_krX8?T|l)%NC(ynLOKkoM4Y;GR(+nH=yL%8=%76(?z3vUn^pV) zTcc7yOsjR(<)ZBK^RJ%rhJO!cRqvNktj=5$MiojNKpoMp$QbRp^9fHmelqkizsn~ zUVT~~Zp=V!)5utdw3iGIw=wJ(m`w@a89{SAM~oK~;DAjIUCvkpDfGKK=tq&~Y8lTj zHq07mP)-A~YPJ$F3mdHoS(v z)ZUH-%K@YjOs4i5nkQBg8~`MMAVg+rb{^GM4`UnD3P@_TeyIw$W_ms*<1Tb=V5k_) ziYUhi!O3#Ae!w^~nCVc%6vCa#%E~Yd#-Z7ziI04I4-Y|LKwVdyag#8cWi1G0bc|Q{ zI_0G<*TOerB3l>bWBzaa|2BAc0h9nQ3n!i%PS~o*?mHZnqfla zeu^Y?8>)8>Q}g&FF305O^?il7(?ZP>lKy6Wk(+h%vmcVXZOf(d~U57D|B z)Y$VS-uZ~4+U`}FJ^jJc_cDe57M0#cYGXsg(DXEM>3H8DA7C}90IBmbFC1cYU|wZO zzbi|Ik)a@C6iSLfi7t8C-i84`ogmP8sefv3~0I)o)$3O+Fr&B!j4(9pDIhsUOcC;c(}uMP1ILB zdZ~(}qiTNd$?*6%(mxA9)l3=aR@8ve5)c&)1D}F61QRf5);WasExaMI&866|Du_Z& z*E5Pg)MGUtucDgwIwe9lcHUng`XUVZU?i&tz%Ln~RI|^a2e$&s{IraW0P^=^#_+XA z&_X`_hxP8YS%sr|zik;TQiKg9pSROA--y1{^0M_#)2YCncy>6u=Ue@;5hTHCHfV>vn7Wc(I2!r)kjKa4uTTG0!%|AR(G*_uX`t2V(yiFVU$;qe z6Buf+&yi%-)+RaMdi=2h1z`U)F=sp=iz35qh3)Z|N$_-E;l!bbcsM0p?@OyqQy9{| z)%_Q8Xc8fzAOLviP~5xZI>&ZvBF5-%G9S?QSU>SK zl1OOJ_&b8{dnkjYl=W3afwzD4OS-1_~+<0rnjn03t}VK?l;VAq&D&ce{RR^F5rRI;9+!RhH+J6L0j z2oJ&VAwv>}#_ZqYJ6%?Ivenq~1OwZ^KjoDkzSPjq)|(;W83ze#er|jZ1zGZeUtXouZehTS=sCvLj%7aQ;OAf!qg3l7a6A zN4l>YC4f1zd>}d% zPX@4q&<;cuv7|x5M516WCo|aqtt1d%0*e$@8C1=??0u?eE}eWQ`K(~=P1ziRiWL3I zfQH_6!f=XZ%F7_70r@!4UV`LS$C$8AV(`SogwpH}*GL$g_~{=`ysc)h)cLxPj77YZ z7%f`ed+(%iysrYp;PxX|s`CJgik4z-r7-@N&Bg*q34(`96AN?^Cx#c!x%sx|(x1i- z1RQqz(}2-!bDd5m5i~imn1E2eu~;$N^L{K0uyf#i?$r+ACFg~QhZBIa4k~wTKNGf$ z{w!ghj`bW5>HjRTYi47W=0w`Q%;Y=1morA>?!3BN=vBCF;k^z+xSJsv{r$TYKGqPU z^St{lUyPR1KX(tC8Yv$(PI=euH3&e5cnHS@=p2S!G`O<3AUp+CaB$I)!{ZE)cKYj` z%AtLWBfk4r+G6-?P^pJgiEZ^c@V(&C<(^JlC&C7WM+7UYAz*0$C4DvhFd0riO7F(R0oSZK~>@Ftf{q3FY;p)kx zJFi)>lQ>#`oKlLl7}DRd@sF94`r0G4LqQ-uf6xmVV<-s+WPjtioPBX{pL%ej6hJ_D=gyVG5e6(V%c-n~APpEjWgoWr zcor3b1t-q@?t9UjDRS~x?Ctm>9-4o52j3d6m^;r3L8}2!HqeS54&a4@TaFk9GxUKY z^(P|Dg}Jx$qhhi??9ALe^1cYJjx$ybydV=77b-waWn%zpN&a+ zU+_UT$rwT(XyzY|!~VOr(y;X`!zR=PS7wYmLqQ%uI#zN$P!3hsfLKLZh<@oUM0x(P z>f>Na0JjSgl4Lk@P}uH(!vBCu$qY`ZUi*!okJ0w2H0{05Pj z^$^f&a1;@ENCb2Qo=SzDciSfet(dB9dG2+dhOt#hj5YC<3Hmh(dJ?cy!AXHCG84A3 z#ET5J10!b!`sUNuqIMCG*dgK4&i8Po7eH*IOY-$3p{oH&Jc!oyp2Wi~(q2pOjI2YU zM%^`?D|q04pyl`(UbZY64TW~2sRz=c|Al62N?uEUYbu6)_;iO>TjlZlG}AuL7p5_G zoUkcPd}Z(B!wxe-YfeHX;w-ep0iiXOP9fk5*aN4z;zs?po?-wRCXEGF;_U-*-z0=m zHH@By6Tg{oRaJ`y{zs_8fh3ECnh>matb|Z2w^1&=_@_Yx0Kt|eBxMLr6~?$r0TmZ? zzb@|d!AUNj<${OpWQ4|>x(Bi{h@h?_g` zK0HqC)o>;;{dCDC=lwwRy|M`T7T8+qi9-(!bOw*_v{WhZJf8Nq;SK+#3j0<_37U?C zvwz?dRk(SS-=Oo0=Qwgm`7jxx_@LG^QIzZJI9b88;^mz$!At$}9umQ{-4CGs(UHkl2~{4o93SYYVR2xe{MuN_<}snLewkKm zgihM`kJ*5q?zzH7e_g>oTL93w`nDG0&cg-0l4lH;?8I^f(IGS+S6_m zzBBia@f8rlpS81=U4A#!4(Z?jmFBph<>6x73_0@cEod8|Oj06$k8>y8|b0zC2&E z)0EbCTaqvg=QEcX{G?#(dmt*7h%wIG5BuxS@a3*>8zkQ%s;Ma_q>>A;#CVKy>}Y(& z;AUSMWeTo!Ydtl58t_ER>|0I3sSs*L+B#>7=N4^I)TQ-rn_vtR1aEtGO>kn?Gdz>y zG`tG$!M{~t$J=f${36aX8?)-puXr}S6+!jlh3$5ku5CovCT0Kz&(XD%+lzu$AiPGm!+(QJS4do(+YM%rvhGZQ~GH6BId)DJYg30*I9otpDJm4MYRfXjqv-rRD}|tPKDE>Cs)(H|99-ivY)mi( ztW(9d43}_q?u}0=TC`1nwXc#VwpaE)3nW-2Bm5BD^TC5jpR=f*{Tf>9#`cTb-|M6 zG-$HaQmXbf8CE>y2x7rF!cfjl2C)=q`^ut?E(MMD83ClCVS8i?(GuWra`|o++A+zj zjZ;l~TM^8Jj|=NjdPZDu)`P>NPFGaQZ5eWARw!2HND#4-3vgK7ETQgVRL4DsxxDKq zAylyDrZ$|+TL1d+-nw(m?A=6=yJ?K{3m?HfomLR$Tj{y>Yh#Dpz*}Z5rq{$gg?u1N z5%UEfm=Bax5{3dUQ2SSVdQ$TPu?w!A5p8G0sBxyze{S1q^t8%vvZ!s?>B^kEKwPCZC;i=I4?G(e;*s9ei;27??eg$jZ zd=4A|;cROv^suOhhgr&5Uf>7I?7Z;LwobLrajBSpP=uOV_A>qc4gO`8Sy%%!)xrD$ zVyKyQ0)$3wcBOrTC+w~c7Zt5?A5vmtQ4;a+tt<~RZnq0}Wh#4*Y9vRo_!l$Zp;=2& z=3gUV-m=0m{Z!xs)l@olDyHG_&+T6qo(^*PHCG#tyI3hrvY@DCe*c{Fp&r?-^_2H6 z7CcNi$J?MlshuEI-n!6gB_nbU*czRE>+fEz!1*08tCa^0xUG*CQP_k{w1ZHj^cGjbCkoIsSFnQsYC3InbKjcNx6jz#`nR_TnT& zums_9^fO~mmi(a%qew9WOaS>wvHU(ar$+un1$(Gq>ZkQO9KAU<+hX+bpAsXn@t5Ih zIG&Qeh^87oC3Dkn@!um5aGJ}HqN3#3@i*-F$3{gZJZ)vCpDpxuXjm63IF z^nn#Cc6V{Uz?k$?gAIik*u8^$1@YZ+)PI7|rho6k4P?&D!1WA+pi)hO}oyy*!b zMFZY|?dH~XIN6NzeBCuqb_uo?{r02t9sle`mrIdfb48R`JSddnb8MTgccvpdEMTZ7 zO}bioT%P$Y&<|8G(bbFd9s8Yqp(SGX@lh05LAPJ1wV0kde5%(4Jz9%~bF>*~TVBri zOuJZ|Gp&Fp5+Lz)zS1$H_v9o>o)=cLtLM;Wrwv`P8J+Vx;__g&Zu=H|#|PRqxW7E` z{=0I}pZw>JZtm#4<1}9~21+MRw%|BY6nc&(xwv{C9UR z=H6cmNda$>WsGCnr;~0=^}?aw6XK)=%c(?u+8vn-x!4+S&fVv&+#5de!x_EoC-S~~ z=nBQMY{G-*_Lwb^-Zg?%#Ek?UH{ zjgIBbMFnYQ(zh%2XeLLyzQ)?DO0l@T^%DWsqpp`YW*97`3+Ot`RJj zz9ama+um6Ht_~OG?=E^C9Z|&}k@LW?DJrlIM_rbH0!d-!c)of%o#KlHUx$e*+?*mH zyymUSkL%UB;`CFcJrbBf*M`|E)+Ntx=ObsfR;W&fZxqfHOYCJW>{Yq*XIkyLr&dr; zQAOLL1e3YLR?*QPG&lw_50=}2ILA)bP^!L6CIgCCe;TOhsNQB(z1=vLNMlwIFjiIn zoqwmkzpBS6#vvy;Tby5=z>ltIQ9ySV=O5wDjyNC1={!tou1F%uU;?;v{`4r?3ise^ zubsw+UXu}dGGT29X6a8ohpOB|TP0IgdGcLbf6-VvD*T|~)+{5_>%O8Qg1s>_e??*Q z-9b}Cn{|D%t)Qyt&vt5#9pK`{9o1Q*;<}Gd&Al^}8>n6W5^XHM_B>vE?OPcg5@RI# z5$1momb@SMcef4;#u@KSDhaT3VGEy6 zo^a9nQSYD5wi20RtK zL<-!cKij6bj+4e&or!zo5sNIv%zGYV@1^)Fh#c!;oB>Cj#kjm;9lj3Aqtcx;*kS`l zfu0|b+BZV*yG^T5c=HWqPi{xJF1ywhTeg;<=LF4h2r8JMfqQGGBI-Yfe&~2;a|2j-a z<_*VtJWaz^)&sTOe9oC*+YaNJFxuMR8-;hoKk%taJaS^+p0Z8dTkAcz7MjD`L2<{r?3C596NCC3kaY$%-+#_ZldaJ8T3j9gkLYqm|K2dy^CJ?Zm-?=u`M zA$^g~3>`uvuK(gVB}xpC?81L7b3{(?e)XuF-BR@YiRnqhDR)PA@SG+E{RpB_+buB@ zIM1a8___9;>;sUOg-*L%IlkN^Oqpm6+MY^&h(3e<8MsH5r~Kx>-X%dl?cclgajwQT zXfm^Qt~P!0tH+!TC?JxHcLFMV(cU|cBh5QC$;+{^Z$DBETkfe!0|T)6eHf%cLA$>K zNM3tC1}~e()CmlKAYvL+?nRn+(0X}k$(u<3HDRO|3io86Aq}aB-$p^aXx@2xC_1nK zNB!twMObN7^YCuZn0&;Z%mALq!wK!Qpp9RnuM6v4TW2t*LkJ%9tMx;%e)?j?^~N+x zIb3Ua3-*DW&|}uc=b+XLt$#3#&irv@$BK%C-!34==kRx|nFvkU2!7m3*GRaGu4Y`U ze4~16{zCQhk9nBzaXI~qXCsHsvtP@8y7nhFA}%;c#o*V;V)6$&B>{n$1aQ=isEZEm&t$k6r&+v89clz z{EHjT!ljg@LPVISj&>I~?@I@fYY1gy&)7&#fA+#_Z1XO=d>CN8QTh}c+we7m9k`$q z*RtCnO=-z*O&Z?wz5p>&r|sz8A1B;n_NI>wNaGtZA#5@^-7f(}fS#0=6nCL#RRQ^5 zE2g?71zPE)12kVOj_5s4Y77Rum15wk0Mr*EwrGFBu*03Ed+5qy7E9&6a(6OOjcGnr zO)c@k&6mK3#j^-TPuNVq43W8$c!M-(b+vA%X8oYQM^gy?P3(0Z@N0wC04aeF4H?n> zm5U(E|0Pumf3Lr@y9mZS%IFO9+^}6vbn9GOu0}kJ*X#sO3S6AjF)Ba-_VXM@5@}f9 z>|`vYOU@Z&={vX>pY$sK?%TYwwfg;GWseq4Q`SlX%RuSY==Z%pONLzq6*vO`Du8?n zP7LvbebcKvt^O|W5qKIo7G~5yR$t)NGHQ96J185m~Le< zHoAM~QoxhKj!9#r#(9g27O-}Jx*~qp_sd5;Hj`#2Pr!|jow+;Pp2pFf zsz{827%~X*3*ogwR{)x|P37)TQ-w~*Jt=r!57bdeq|3wOvWTJd%ns#x5^siKNzX_V ze6?Vw2XPErxjGyUx9&#>xWX>!_dbhM+nL2%d$q|@EKw9_nc(bnW-#FEIJ?z~XcaHl z#1Y3-I9vszMVgj2ekJkyw9@5cd#G2gHI~U8T#=)8GX+z17`;L2H^_50jki6XtaZJ0 zDzzKu%f%H6-Ads^01@>9|S%^^X51&Vsv=^UnZ1hWif6?09{wWn_6Cy&O<0YZ+~qlbtNU=nrH z$!WSay-b{>p6i*Y8*ZT5hO6xyhiM%+w_Q#vsPx4qawxa5tpI&_Z{b9EW#Md5@ zORgwR`LG(Sur_brTgc!kZ(qCsa}w0uLUI$jcUtn(uc{HUJl4Pd6X$f;xx-iIc0gD8 zgZ&Vb-P8j>rP%3<4;Q``f=|2L1N^b=##f3x?-~_uTUlLDXru2>UXrc75$mv8`swKt z$4}`rU*72)H$L>{M86Y~K-gczNj>UnctD0YGKW>YkB)ffa+yKgHWzv za0|s2oymq4d~a5q5>hn%SxD_k$5`29PbMaKWXbJ%r}%0I_A#F=f4{wh1yI$y`BMHz z#cujj@Eh-?ojugBIxC9G85$}U(^?M4`jwqCRTOUJd8uBoq(A_s;qMtsT}@3agsQcU zb3}E{M|sd9S=|%;d4adC6&Ig+C*DBrl7fnb!-QAtLEC?21_;~7_>x;71MuYR8fdG% zZx@AK_pf~ROmcSNtgBRkJX{=L)lcC0xme;Q(N$2O$m%XunxsT8n zpF@P_N$oJJ1lp~vf4yPW#RAUIe6q*Z8nQT-PCf$!2Kw@|?O~jjmX>VypJD?r-?zB> zQx@#4#ni`T-NSyBS*Qfc9dZ-XjEBKHsCspXFoB;7{++}-ZVF}MdJt($(S7B|$0K$+ zPrZMdFrM`}3_unnMj($g(zh%MO2nbDu|pQ=XL1aQ;N#3Md3^aA^zOjGj(1D#6Sb4t z?kmh&1`?~0DDBCt`xt0mGu%bhV5ummM;ca2V$POuF(HY$4zp-GU@=8=Q{W)~M({hBSmEYkIb7b`xt(s@+b*7(E2&vM-c9$n91E z(w@w(6rMbK%U^&tYK8$<50w^;idHyB+n+H`R3;Zq33K$FHbK5nPucg_o?g-9D)d5T45SwYk=uq6i-~&dco0 z_H58Gf}%AzUMwzmHm_1ax~De6?-nn2!ww0u#)EX?i;2J}!n`{dFRvM%!l982AXM{R zK~y*>FIb@E>#alwRVmTgG<4m2b^Wgw0#t&RL0D;nqF1_DqAbS}P+Vm%P)EfXz}6s7?%vB2e> z-`vFlVS|E?%1fj4<-xQ$yB&0t@4IJp-oW0N1t|m|7{id&@m@I~CSiGpVL4zq2`NkH z_y=WEtlEX|FpHd&hO+({tEQYV2QIM4&@c@nyc`XnccsQE z3 ztXln{0__eSj~vRlA`&kL?ubVR!N>vw(R!DvyTP*b>n@P?FJVf7v@KW=sF{s;lrmHx zo^toipu9(x;J_RP0>tppX)rdv3oIz$Yu;~s`N2{TPqX8?AWMQTi*x7U+AhmE%HifmAbzVv^GPSmK=StC^ z@Le!Yd&Uo=s=jQ`!{KQ}YClIMoFmls-RQu@;DHw_CAB4TjR{rS=}v$_KE0B+-j#kE z57l0-E8<8i_@DqA`s3cn?PvMPPzT-H#T^a%;l_F6%6IsVgXQ6V&9)LWTti6 z6fOl~m*0A{-sQAYVKwo@ZDPS_8A>SgjhH)ZsVcQ}01Npm`2gbM9}rOXrbsJHRTw&A zz#*1o@(P&4S5R9ohTkJuDBTGmS#|BNteVi!l)u3Vn+MZb--E+93)gJsco{lc3Qq}hG5|qV4PN2q2 zvuCHhTbW%vJ>hbX%v`a8q&1AcfuJRlx$A3N(XarE4SSNJ5zpP0qoesx2g}``nxM4p zY&uTt{Sg3Si3V5`i*!U41*NXoOSu_jE0aZ#PTs8ryCqnbANKqRqI{DB%hEXC1%_S0 zN_ZjEtsh_zLeR3dAL%uQw*yt0=P~%tK`-2R$%!MpizQD1Eh6i;19TRpZnyv4_MJWMO9W zGd=Nm2IaPSq6l}=fAW!kGNSxA8Idki`X@fVR|ceTxm&uEpLRgjvGeNwqqi!^W_q4g z^=#}Djq}U*m|>6)@ON<6KLo{gk+eG}10D3hdp4>V>1~zLIzTM_Q1fNpG%YyCKcumj zq(!Fvdnag}BuAN;0T*d#U?l@`69!xO4bs1~@7cOIP4!4- z{wkXYr8{E^S1ZE)6}v)OeAR&$U^`lk7|_#c1EB)GG;15h1AczZ`8?DfyVM< z36q}a1L~3Q*LSLauIJ>NvJ8&Zr69K4G>LTBUkh{^K{_ z*VQpiR7r+!fD;F?J0X^pqsxG4CP^*@+RV6*L3nm4@OD`OLA5fnR8=YItmDe=VpWv_ z69_v$V<9VgU)}8qa1RK)d+r>}J)-Ijal{lahVUTFY6`z7U@f^ve`remyreh_B(TnH zd3ead4h%BMLBuUC*qn=E(NSslr-7x10e8UC!{=6aXy!6#o`Koer+NiINAi2rSBVbv z&OW|m3+Wc37i8`PG=i7?wk@U7Ie)DShzX5H+;$-@RP`TiKq70JwZjQi{|d>@d= zZAnQ=-pg7YQ&Yh39f1XbR6@S1S-)48%)DW$FwjTMbJ<|K@oW>7M!aO2)JHBuyFv8P z7g?pWPQ8NbK|5FJlY0523dw;`OaWapTn2cMuTghPLzWTt2>^;b%gzS(ap`7XG?jdN z*2e`y-fBBxbqH{m>EOIr4hYCfhF9E+(>w%6f}pudE*Q!3usdzr-irAK$fV)m4LdUj zBwmSae_44M_;olSKg-F9fA&sN)KDN!WAk#l zXoS5;=Xf-%hRF0>qgY9JyD+N~Y}t35ax>Q%M$L*;1>g{wR?K5&E|n*F3}_vH{}1`$ z6)-mqkZdI-B_uRCbPo*2F-{h+wLq8>U?90JzqS56YWvlEFLdks?{PIT-Ahv38t^aR z!87N-I<0Es@0#xlqj~^n;e$E@w0+b3YC{Z0vzIED0=90{Qxle#|B=$uH_!H%fQB$& z704-(vqbPOi=;m?;D0BbRAuj<$mwL9hd=(YxTkdQ#EJZf^ZQ0;;O}$xa@tNO zPLS6Veor>peKtLD;wb%*%sqAYXG;feD1E&5IKH~`PN~}o8m24fURJi-Ynh8C7(cqE zU8&Vm)-1$O%4XeEk%)BlP2BIt&qR(Iw3_>7S!WK0Cp8Pj^j&XTQ2R6~xJ`1Q@^tBr znvd^`SAlNy=Pt6H{GJlgVHG_wF|y&EVuz}3MTwC)AJ|#USTEtIA-3k z|NCzVPbMxMVLZO3z?@3-_!`rW z|Gzg{-|SWK>X4$ML?_aR5v8k!AcYkqQ!>>#pKwO!*(4hB%L&q7rw@B4pDxE9^{U>8 zyY0CTz4o=_xo%6r<~f{cq4w*Bsa7FJ{aAZZRK1XVy6Qjv_Y~E3ieNS{?G?%kTyE5QxBf|vtN&C35v1fn&{0VL_UKq@Ye3({S zS9eM?_nDcM)ww1I+cL?4-0m%Fr-MJVf%g#17Hu&+o12>#NCNmt)9~{TWK5$TPh5zs zXvHDS&CSc4=PwQ+shb?^8HrEy^5=bVG1KxXqO8>7gL?3%lF z;q1@x@vd+t@v}ko9o6zOGQuZeJ<-;)b8~1EUI2%~i8vdVZUy2uiT8G!qx3)Np3=(j zv!a(GWy}e}y6e$#ts7JccE(nVD3lnUHq@r}sZQb1Ey;75Q-;Cx+C?YMl=JrX_Ue^8 zhv@MJ*XHhx`OmZ|G^T;qRZ?N?v#Q0szFe%86ZdW3wn`n^o9G9Q%# z17svGw803wE)Dv1%~}8HU}Y_cylEfYtbYrEXb(6~^I4sG)0@V6)W3#d5KrJt!7kK9td%? zb$sr7PD(-HG}C(dc`-eB#1Q?&oaAtqitp!?e$y8+zhrOZA4h28`!58ENXqtt;+Ph^{mZxA^4T4ZK~~8p{#tl|q^s zcbm?+Kqe-pj?9qYW+Kz&@#-UyMBf{%jvT)hU3i~;Z=Pw3&FXu;=@Pih;_LIadhfjW zP$kbp!KM1|eR;JTNiJ;y!LkQSbiwPp(l&zhycR(lR0@|1hPYvcO$D-kt_wS&8EJU+ z43Wq;;N!JP4u`e5OOu*Ds25e8{IxHNzf@0d1P4CioSmD<`A2rU_-)Go+P?TMT8}-Y z>(beO1beQs7Mz0!(VUQH<7M_*x$@auO}OY$o56TX7pe@*exXh0!B0zL+KEC%ov4${ zBS}9BChGc5q3=h_r{BLp#mXEZlEOZq&Ura7D2R@UslmmDS!$$JYIkN7wHBgmOgaAL z<-^U2k?>Tw-E zsf*=!&F-!!82?|LY)5B2et1$>Yd`3AL|3Dzox%u&hy#%+)4r-9%+;ttLkl?1{&F zY~WE&y-F<*`7A6TfYk_2B*|iSe~VXuDaQu<%;>&jYc(VfS8OldVi`ilWM$oaUaaG! zMoBqzVr5L^O)%0uT0UTCNP7d17@fbO!f0#K6r<%-C}g2c6d^I#YC=(LOv^7W-qzl( z=v1h5Go>q+>KUR$s-U$z`iOm*4Z>R6flS8=H(TTk{TaTgoQdmu$xIt zOpKPE-VYoiS!}G+i)C4BENp?U6+^DX(EOpL~4&ms`!VwFhVCMCqeqKS#yYJorH+Sq{bP2BU;|Ml-OhX?s?tv z)ppm+hia4SiAHfmL9QHkia5^I?C%r4*3mJhA+XTxxI=8!{|YM#+nKRxaxIx{)k~Im z{c|;X=*zcRdhM9nYs9)9JN3)%$+B7MAGNrJMJ`cBx+oJ)vf#yr5jY|-Ue`#sWn)AC zjDAGr*Ge7k&k(wO!%!N@LRf z$T*t9O3QyUT3*Nc8f(GH*ddQ|Pw0;L4bw{h5+XcR#JVICgb^1&f+< zW0_+)$gV`Lh6;*!>tqu&0U%g#+ z2AB7dwvLXDHV0({UhcYvRQV*Dd0Z-bvT*!^`7O;R2aO$(jXkCE;g`-uL}2-8M|2{2 z04#?jAt*6D`Pv7E0vlEm+_Za$8fm++ji61ui7ixwNc1W9wxWSWT#5RLYC9JeP5*-@ zuD1HT`)=N?0}PKiV*MMBHe1A4?%4JYtWc78GR#W%I55Jl3w!8a)p4LcHh zk8eMQQV~qqC&hH^?7BUC-CiZ>euP;S>!j;s3yVPF<yeBtCYnoA)NO^4 ziHGQD)nKTj%iCGODXMe^&3uGEZ-T-FocU-J8WPWGb5lwRH|aCxQN)z8+CO(h^_uK3 z;>bP3cb&MtsJJ-aZd|gwyj&wZGm5!sM+{MbNv$9|B}su3I#@G4!>b&p*q&SE>_g|13O7^+wi7PjSss^SLQG zzoS*(@^*_V#3M*Zh$)!aAR#$+JNaX`3#H+6Tp79Jx=oBHt}aMasVXf+w_qHR5x!eN z(t6B18v~M6(JRiuxsu{-0gnc8TB>7rzy!W>AT^2QZ zLT3J5UtEC&ZryBS(BwR}Ft3`e^IJL^A_XKp@?V6nZ%SX744`Qc<&*}J+E zzndHO=GSwfkA4Cyo`bV?M_Ne{mGwrtbH!O|b{kffCw$tjQ5ot>osy)f*Lqg{&i35T z;)I)aH345AbW+d^qJ=LZwAcy24pU1c{=94Hx@>%cEENC9a;%MeeW0SuK&K zCsXbjMn^Z~zM;Y6>=bd;2a7la{`@$W<*@&O&#Du4|G?KNnMTov4h!Mb8ga?=tlq zXn%+0e7T!s<2AVLNGyEeEPvv89I@{VwzTT^Tpt&Eu_um>AjdWk94^jtnO}oV^c5_jy^RvGDL-&|RD$8AH8VZzzs}Wx&arm`8&1$ch z;NTHoC^@FX^SIBq72J4=l)qeoUsGD&Qd#-wl*KfK8S}E;@$a)vCpZ@2xh7&IF9iMRXbZk@#6iCgD zX%DchjcV#wK5}l21QF366KxN%4E$ z`_yRMXQn;2Nq_7b_&RV%;SZ~3%}X2oRr?xCB#bFpVv1j%|L4Q^I4sLiP$+6ew{UZ3 z$7yZi-pB5l>^D$%9Q2+I3Lc@9Orc2WYBJ8L{jDBvJg*c;Iu>X~SHyP8xisjvEk$=c zIpw)rUZj2Y+lkFONBtm6L3wWKipjF&yQxTf*I(1)zC&F{TNWpuG5wj8O~c+rKYx2O zXH_=U*r=lI8lyD!dZ%6|c5J0nmq?~w@}0xcmwKX_LFagdw6?7$r~FQ&KK_gj2@d{d z0>z}GEZfC%7eoFD$2z!vu4(8tc8c9(~vta$CFVa32xYSjkl9fk(yIC27^*u3QYc5Yd#F2nD=Y>8+{<52mZ$LV266 z`s+EbFMb3u?roJ1qf*NfLmlklP;=?m6?@sD&NMzM)YNe& z<7Wd*rfR3>)X;tZ{(g;~`Av*+<}hi`yx{2Q=!;r61D$E7@q`SGY7y%@RZhl!QutxE z;&KIRYc73#eXipB5LK{0OLK!qZe>{Y3=KUJOUlr3!-v{+to2z~BqnB~6{|X9t3=v% zo@v(=ptz3Mwa1jWla!;BGg~g(RCycwt)}Sc2drUk3G2`5^6}cce1Xh7y|57HA|4F2 zPov@g)IJ3|es@nm6+egLHf?R^>Hj@{_ST@U+XAP$HM#F@^dp}=m0W=otDj?Ioh3Gy zU-8~yk8jANbsIW3M8ZLr{<CW zszV8O(rH2kFW$;eS~tnR zEj;g>pkLt{smSgU1{vycW{)i&=1vx)XaD`x$w#!QujQfwS`6cr=3IQnh)gVo3^P-G z&_{K&w3B1+Qx+_B!L%uy35h9Da$y>KF}}({ORD;{ui11%kB(238w2TB)SFzT-;fCS z%<(FT_hqQzrIg zcEsK-LASW42*v?%h=Xu0dvtiQ9&5(WU1B%h3An>p(a&*n*siIM&!%+A=4-LV z@;OaDkA!04v;<{&ubZpj^Q&su@q_NChj`zrI^&#sS1uT0N^D3;NpDB~ul`1oxHXCTIW+h>{fm_FXKjeCt1UF*=~KHSw6 z&g_i1Ehs3Huk~Z@wxz=EP!H4W&tx_hd?fFf!{;#fUpvE@RkgqLqH`rg+6Jnny6}^y zF5Q0m+Kgeqe|y{2b$R%KmsiC~Lhj4O^7r!BbDmYU{{DTV`1$4P@lS<3H6_XXvfJsq zKhz``#}eySeQ{gVnjG?|?ZjTxT*H|_j#kCar#Cg36nj5bR3s7{TRvSdOkT$H5`d7A zn4ZXu-I{vg)xn)Vc}AGE%G=Zi`+gDVZ}-xS)NWA4#l;a|2zm4yE4o*w*w;TlkhOm6 z%z2l4>KgU>H7_I$IfI6hY8F>@Gu0hFiy-s{($dod{QOReiHn~Ls$XaxBkICg z3erzI-gzi18~@?Mr|!=t@kEpVKH{9rth|2LTHr2X>Kc7MKbgN{U#eC~3w2Cxw{eLw zdchdO8)y}&oJmJZdnHNv5-CyfT|I#D2;+XbSSDPszUvbtr#5IgxVEItV(`bW0ohnn zx%~+1!CYb!)ix6sA8+L8nQ%Y#1y(dJ!_Vxc6@6Ue2L0&)oc-twj~&xMJub%DyQrw> zXK$~xtSoV)+&^sv8bZsm&$?Xnp^E!k2?JONH4G$bX7q9F0MQxo8aNJ|9yrsaPwtmo zs<)U{S(&u5Vhcez^|74MV;G+*VSJA`BqVq9VB;{>`7zW#tUTG3EQDV;C)G=Ldcb=* zz6}sg2S#`ZfKUw$4*>mv3R@@pVYWuSi#|${rPlE6F|3+iTpSH92k}laMdh9e89FBv z;^(3ZNx-S|=g&iB6}_mIJK&%nd-qD7W0-M1t&NS%C)KQI{X8l`2wozD^4e_vRTD7_ znp!xa-<&UqEHpQHt3^L)Ryb?ej5T%e2;$pFyZ zF6-LNdg@}ulgfMRE33%`yPsN+uxovj`DEM4iPw9&5_dKdRAtN)r zMHrlt%O^ca`}W!VgWQyd0dwm~QEf&hSM4UUa?v-DtBxLqdmFzSNlr75tT><|z9wbC z_go0yBXcQn|9%u#FTP#T_TbqFq^i>-7B(s)2tcCmA!S$X-7 z&Kxl3^Y7-I31;#5Ihz(SruBQZB9mKkXJq5K^8K+P-4p^2j`(WhrOCCc0@FbTw%cB50Th zDMK=G*N6PweVnBE?SzNd!8BhpYpxcYE6$9`d?Hab?x8>UVn&Q1#cQky)&KL913VSY z1E*}FqHOET=_VxexUY@Kmw}B5agNxzsjj)At!$u+MkLRWM=E`~J+pCWLLRYPp<#g) zVkE9|>6vos(*1IU7arpVoKZ7-cci1ocyS)3&6mRCKrUIe|1tvqAuEr-F#WycXXJ+a z(UTpr`iJ#_7M(gM{F$hsZx4lmhMDe!s5Lav^C)76$;EwtV)1Xt(&t?e`ARYcHz*(i zFBZ;ouEWAelM$ADxkHvD3|&cuy9=RzM`11NCvEEgT*VW$W)#FhA@<5&g!!w;1Rh6i zAYpW?^7HXHjxRb*xM%_{A|K8@&ro8rw(k+jS3P0k`RMWwKyOWL0KG!;FF%T@Z}b}o zB5U%q=t@A%6aTfTTM$f^=$$g$K?_S(A2Lal$}@w?8!zM+_l+ zCbq1FPgJ=LgSGbJ+GvO2(t_?L3HD68{f|Psq^cQ()qklF?j;QOazT2S*3U5QF&Zm9 zI6yK~d6|2Ne7W=V0u4Y-UcgzHCN0SEXkPGbl1$XvZOrS=oAiP~Z@g^yRu@QEV`*@M z#m8dv>s4tG$P#6R7s%YVzcmaz+qe~Vi*V|}b8Zrz!=Chtg4xM^>V>r6?w`DMFkEis z=i>!(^o8VDTNYN3g4ud)_oNq$K;$d~!S?BYFGwL=zyU_x5d1QmZD-?k2Z@?_Wp@WD zD#8o{r9^9j<@)^=dq2ZABJ6_BDFvxA;V^k40yVjE4aT^G-eyBh#2wUIspn35v>9PT z$9HZeb_;S6zJ3G|XQT=C@~V_M?gzsgJDL=dyip99LO>;V|=qa8?DR8QH!4%XmSF`E^l1|i|)mP z3wY0Z4!Sq_#A-EH7%l2z0#}o@$Nn?a{?mke$jP>1z2P2S{seo+7ebt7PqR`d_%Z>A z9O39W7r`QN9PKRC20x2Tpq;14YbG^)Xuj(I0T!?^k0IJc>Q)U!U`c7lEtkz zW@xzCX=)q{q6nYL^q(Vq%$Bt2e$*{O&Jcc@kR-H1k`T(CbL<%3)Cfku>(zrjEo+mE zfF+;wfMkad|1JKzTfEg^9Bs#DpIzH!ct!SNHEDevzshIl{q=ayEhd4v^nVfd{;fo} zrNY?KDsLW&DzDb5^If{_W`DyBk`$ig_6Y3mEsJEv%w41ycW-x@6o*iG^u6KR>puV< zG!uQSx#~#c{7KJe^E2Tj`%x!i>uoK5oHcsZ8uMCnA_(i@8uU~vA?awQQx#3j=MM4AuF2GHzIlmxslGYTPCnYP4-|#Egbu{Yc4)1DgE({3+IL89?%b# zki9U|rur%=a9t`=?iJJ~Kw+)z9dxL`VVC&!R1i`Qve@`|Iv}}kQjw^CeF_OKz`Gt} zt@ZqG7?_Vi9~o}y|D?>oW8->H+ndfgE{A0&*-5E9ziP48u)60y`|UyT7)pKm5Hfin z?^;?O3B;48t6E*ptKODy9^Kk`Yo`6rsgtacX8~XWgkTthS;wP95Y>RDFq1GAqyjvg zk(mih*OkN$)!YHi`wux+(kdimycAxPn7)u3{HWui)!wJwE)*A+{k8=|8|Y`105=3k z%-h@hSTrzN*0mfIfk91|9h5KI8F?%}tTN^oG;=f>nO=BPyZP}^&YOORX73Ih0vM-D zmoBxpw?F2L)~GA*vUsa}=J)d1?u5YVNS3wj-YrE3fOJmd=^!aOhiu+YFPslK?R)fsN<@JM#0dvpvr}i>qL`C#W zZw}PV;Q;jey#S?Ki49xSz;+}xkoNcdr28c>C3Gw-7VhqGpjKEE+bjy&&3AKKpJbUg z)>U~GBlAM*S5TKH&V?=<`-B@~x#_8aA=HT)qD)0PJF{Xqku|Q3gntHXdsVPh2>p%NM6f5#;^Ay|b z(~-ie>obt)HUBYc_Bp*(u2Ayxims*otbDT6pM`(MCG+K~rYCmx=70Y-1OTU~v{WR8 z6L^95r-Hs&1CjbwGgm-B;C_}mE3*(D$kW}Boh?Uu*_X}=Cx8&5c`hE_bibrCy_?l{ zzweynUWXNRp)jDL%a~G}Ldx&C!Lbu_jf#O8im#vg->2gglCF5tQaSOz6PQ`pJ4?qi2a`K*mfgrqw zI4>dM{tpyazzlFkU|=9EJ^e>L5Qs2Oi1?Vl1zs65RDJE9z)F+g_>{(yF29n$)(=@b zui&8V47rAVy(I2i6F>ja{6^TOIuIb zSJKqFUaWxY(WPjUGr`mDUb!m}|BFdS+YM;OYuBy;SKnhP2*fnger|PHD6t#IxicD4 zpeIo5y>b~>=;rm(v2XTA{8FoM#k%{xOGOOj1AV`SP3C{$a2#dw;az_~K z4pJZfiLgme6FTc=^!Dn6$j}(g^{B5-<~Kn4aFvP#;LbkncP=JYRv}5MH$M${M_Wo z5Y;FCWHcP`(Iytl)IuIP$rKA)Tjiwd+BDQOH1P=uAG_YKdp__~Q?{YcWi;!_CT zni=l4X0p0c%a5R@riPK**s}lk_Hg1Lg+sBT-*>uQ$8eV7k!zLlji%Z}ES?`j-Ix?i zCJKs*WKthn+Oj(uIE>B=EKE(Y=I1r!pT0@HjCM<8hS28Tl&VqU8U$=SXdM9iO-KYU z5QAcHu@RI8pgVhU;C~K4N;~cK-44-`rk`3N)hOHWIThZ>mcGQqk@wjWl-sMpQNegX z)Tv0$AXK77rw`3A!hO##V@f;>HD9_hS#y-X{<(r?zKwednB}Q)4+p>a08abG+YCHy z6Ki8^5mLWiFP2k~tG8;2dECf?Q8EOD0>x#M&)5NjFWVu2gdFyM`Nqu3Wb} zvW&BM_H6pL0sWkmx9j`J7FDO-QZsF$3SwjAGI{T@m{0v{8xvpT-jmeFTIZIFpu%Y8w9$q^fk<8h?rTsy@HJr@`?xc93EA5Ohh>m zwjvzV$Fi{XACbc3tNQvbQ<{9HbjjR=SbaF$RJvBkGIXEcP(Zk{e2XS%Cj&G@C*7xU z9`fnB6uhi%fL@sj(7`h2EBeRC7(TTYaXgc#M&rb0EP42cqh!61WuAkoXm_kFRCFaf zVhvO%63bW1hfk?3{}nVjPKmi|?Ndbz`=k8<47Gfwv@9 z2RQcL3MA&4M{X#D!hc~C+|Sm~MK4;#H!eK4qn+?%)-A7N6#rRwx*`hUQ%2S+7?)sh zV7zMola*F|;_Y7IVmXK+dG3|>q|UOJ{wN?Vagp8amK7Iu{WoAffYTyKqjW-?a;rPx zECHQt4*Ud9_{B+`sYBEfmm)W)6aUCKo+vOMwX;()GCR-eR^R%bqsye24-eaAe7_c9 z!8=#`;%?0+p35~BbX4+RQ&h`ZeZzq&Jx%aXNDKE5XKvEuEaoRDAxV2DYDXUl;E6ao z%|G`uK10MdY#IJ5(lfH3@pO^AI55;qJ1%2P)zMdg)a1H7_Y4EKsb;BiogkUAK_{+Z zwKMN+R{s01xD7maGO-u&R7Z!Md_FRYi#OsqAw_pvEWQU&%whUiGMsH(I>g0It3J{cUzG z)ndid>~m6})~a_!9IjN0wjHghsHlAzL@nu$78&U7dVk%xo|tZZM$}t!ywyt|;9{aP zCJ3-6-{OeBmb5quf@E$9{eCWe|i4Kx?;^ zZyCP=!&;wi0zR&L-q9&4aS9i|G#)uICsiIm@T0?RI7)CVqjmlj@4o8lo-y5UF^`RL zOU2<)T&pgS{n8SmQ}DyISM_bhB7se9ik&$tE8IjsJ`!X?4$i*k_lPdBVGp0$P_!1~ zm#(RqwLXmn4w1jCT>Lw$b%&r5aNLq95iMwXpu&+}F0~T0{IDx=KgXzocG3rXn66&X zIv8k~){CB87s#+$@MZ&*RQ4gm{b^p$<@aA!tG+jL(G=`7aQ15QO@kmXV$t&l)&b5A zr%RE0aISt*y$O;hpbcXj$zIR&@oiM8={1>{r?&n=MZ-7{%mZ?%aO#4dd-0{2_7CG* zFKe%u+`gQn9FrxqazI_A*{JYFSrdvSAbRhoVldCuO?j?gJO}qYQHIc%-ki~MimI?h zmDJ5Ec(h(7u>Y))mbOqCE`A`yr$8g%PL(;M>q;b^RmPcEe*ZPHltZ7yiCbu3R6rB0 zyMJ&;zL&bR=HE;AtkQn< z;T?7hE(EUiVw&3Jzm&spDiBJiRVUuM)X(9%F&G80B=egC6AXOqPPSz~VW^0OG&M=78t#cvBD?Pk1-R6jfh z$0P;E)P!Qw(#onT` z<|cxFSFf3zG?QB;H86tgs6_F$vG}^Y12q>^j>*Z)tdV^*6I6gG#TNS>9gZUpQ=1Q3 z1(o)Fq(J4~kbcUf*G%W44|pKu_b{6~b}?A@{aTtv{D7}}^!gAd5XC@qy=(bI$Vxy? z;91!Txqt$i9&hY_n8OcJL**b}=P&K6hYdG;*E{H*lSKei1ZA1Jue6M*Kfzpce?ATv z=Qr=GhUCwaR5D$4-IUG$R=l`bk<&C+EzwcEpDX==ffs5j;4D8?ROn*dTg#0JT6kJa ziMCFwfRI6|o(t_#L{EO}^GOk|D7&?IK9x0=L(B~YJW*0o5<%_^p7E2Hwcs8h*qbD< zL-pT^N3#(*j`*^&Z z$J2+%+`sk;kce0CNL`<5-}LPVsanRasqN^=8D%wYWcS!bwh4m+{odytlRx4~kG3NM z@&0__PG;ZU%$yex6>SFEJXnS`;S}p)f)VYj`&U19-w4O%y}!wSOLwyUaWb;%o{Cp+ z%#URoHSub7EMJun*s7i1z{@td;e(Qb0vB`&e9X+0T?9m(z*%b#+qnfqk@ z_$d<)dJ1FbFN$o_Y1b*Q{1%yHFT9t9blNZu_dT+>w%?x;zE&9<8>j#6Qpk@%v=axW z)J}8oEgANYXE;b}AlE7IFsF`@ZVI_g=a^2EWOI-8>SD%#96G$oxTJF+IT3rbV-UDo zpQ{L#^mFV>D=dtX@Y?=4G?bM97*pb_|Mqcc+vTj5Ic+UG1%WgWvqfyEP1jchR(kg| z55j{@$=4!IZjhC+Xib}_1p6fG4v09SoSr6om_Sfd~h053!3E?gjn z*D1Wp@NUin+9KFFI6yOgJ*CSeo;k?|1dMe{zaut&t-F%1Ds{hGyF{+@>LqnX{`bZ# zRi_(I8F|C02+0D-rz|{ETc`EH(ADG#CDMY`WJ-Uux}2W6eS0xER>>+ zjg4AbS~U)g`;z|spHjm6XDW&$+iD6(73*uZ5R6UGzR~(L2vkX+s_?9DDB#x7)g3A@ zJHNcV49zL1D)CZbnQ0&O+<}|ap@7>E8UV7?>u?Cxt5KaLSF&49oUHaUR}qM3qav|#Ca}FvCf<@YmDse-2tc(sKW_yRYk(cx z$1v5u$m*}qlJ-F8gh13{`c97RqsMGP7RZL7-$0!cKss6$7LKTv3DHhWRRn2$4L>PF z)5^+9KprlIHbCRZa0rA|;FI5ywK*_CuS4JS=!a?d2wILdXuY{X9STe^#3~SO!g&E> zq7I#e@E>p=rm3{|Rw=jJ@-c60*1#elaZro{EMlB5ht_L!iOp1akoE)~22s#b@HI$O z7|C;gbpW*9q2MPie5MNrbwc*CQ21(AWH_+PG`)fj>+6+;S3BPXu0fi?81ntxfD2@e zfHfd7=DM;;_BGfM_Y)~yLB}|w^+M`jN>MmE$W;_Ibt}!b8 zcTXZD4#>UdS;8%UT+6HIO0U*e`}!YN7dU4!XAefkHFp~;`uZ38-n2f~;i(7y|e*a&_C?(9mPKagjDJvupAm@_Vt<#nKuSFD1HE`f6#YCrzE&GK)TJA%I_3dcM*jonh( zBALh~`?}#&vOfNp=Yce{|0wflHZZv-j45fC9Oj>Q>%e`r3G^@!*@X?)C<7*~qC&Ck zxI3p!Jcb%uuc^HV#kMus5dRtWz;uIDZiw;ky*kXust(^Zton{N5q?8y437F7Y?p$X zj;8KN#j=y?X(mnsP(m>F_b}rIL)4g|bEm0uC!3n!`b3~?)qXwJ#ED4Z%xTTjU{%2R zAwywhwSGjf5`ob8U)a4ym<#;;FY2cQpxpAR6woLo&hE(hwcm30YkW-@prIv%k7c}P zvb%4Al6-9NA;F*;K&lE0V*LD1^GY485J?@4iLLrHXYfpp{%o}HU>sju!>wlH2){Ki z{LTK~F9kUE0VFjzy4sz%efEqk(j?*MPyq^&^g^fpUmX!!BpYGrzQP(Zj14`B!kMs> zRp6T!lbD3i{Ih#_*_j? z#N5%S{fFxqLh%Em@E!5zQVf!uN|P80KyTJcSC{&4@9NR1)|UnRM&I`$`Dz_$KSLD zNLiSy%U|IVdn|`haDbb~!+8nA5gU3}8&4VKl*UfOp*UOE!9y6zv~oU(zK#;1 z2XZKwu_+be>eoK));`+AtXqOZSJdnwMAq|bFtcuWCeJ~2Zj(>n@;DmZK<^YPMD0XA z*M#5==PSLfG};C+j^&uF;fanWgN7U+NCNKrL2Hd8nlT&;Db0j&Ja3Nmgpm;~QHB*9 z8NZj7K$9}i#viY9(8{D+5Z6WEL?B0&%j}h5r9?>@ z;M86RH?u=U!T`AgfF|th?9Jwd0J#7PQ>$h@Q{#maO41?1I;N1<@bd}3b;cb-zeIUd~Ro#Sy~F!*RK(ENOXY19C{45G%+!0 z@9caBjXHhLxthu`{!18UlYd28`&an0WL`iY%%F2X_q>2b4prQTuQ|vFhO__3v0Zd_ zc7{et71qezNxq9i|3br~Kn3~{5_QdN4LSw} z>_XpH!2c9aL-Irzw8v(x#x@zdrNW`eokbzykUV*>?Sq*}8 znUL`4mLRXvhY6?f6yyM43XODifZ#(8VcOnAfM|CsDu5HH?O!?DoflwL)t6}LA#aks zA^<%b?a`;kcWV)V<#9vO4SKZf?ChlxbX0P3@~j#Nas7LEpBCiI;5-N&f^>AL>YVw- z;y<9fFv8$q-3Gb@c|k1?+WokU^?sw%H79xngI{@Xx&;nZNYwfzorBgOkXyzj@ThWA zgSSAs((x#ktky-J(6Q&f&U*XyZFgILu;h##0fU;YKR|3hW*A+*`tl?$qhEk7(67tl zo%}z8V=Ob!80A&kbW4dgi8Hb-7BV`nG-hDbqynJIjA zfL_?ifu^(t04b0&P0(l!W?0(6Z}maf)#;($;deSM?!MrTGIY7;5s#( zY(7Uxxl$&yL|J7i%id3rm>G~LE9Ts%2CY6{e|As zsNELcch*$GIk-JVPfYy}R>_C#ZHnzwS$zvKX-`H|qg@(Y^x=WD%*>503kVlPN3O5u zTj`3ZQlWr_Wj&T#Bg0IodQPI=cT`dVWrzcHtIm!8RJ&86nwro|31yG?l#YTrTf;YUMMw$3PhH0g_BdPtO|L=CE}49RaoieXfntL*WEE zqEE&?fc%=CcTv`Fe_|&H$+=D!nDbutL1}0+li+dlBWZ~ZF2}@5ay!RXOlNhaZW(CJ zls|?ns~(@2PR9Z-4)-4~d5vy9fa2wE&m$XUvHM)Upb8_%TSpplPoE~*O9SG8ykz?o zum`Zlkmo1pLL4Wur>QoQv5mlrws&NXpI=r)El@C7q^%~Jn~pd z6((PSrnCxc=-)|3j5My;+=4SoK|w+NYu|snF`LWbh=bmDK^=rI5V1 z9=6)GUVYeBxIcX4@qA{T;b>EE9A(5jP+5HQ$$+&pv}(ad3b=oAz$FppB?8ALP$2^@ z1S*6hq9~iQ2*}rXz|C`^IZf)%@_B@>;!b5FRbL6p#;1oKQ% zgL&3EFv9qN=LQ~RX^_5h>r77L#-GsIsv8w0yi!nGp07V+PW}9=&bM+e-8bOX@K8MJ znVZE-RZQ2M=Ka09cCREbQyofU8flXo%a_hW>rd}1f9iSlx7B|R8B-1#skS-q%esj* zSJjGwaym=B=NKY%4wVp&^h#6B`sO^FB0ADKDRI+Qhy@V4L#A^+``(rNBeErH`EIVg zF{Eq1{j(XR1|8eFh}V85QxUs00?~0l_1_1%j^jY3>ha17Ctj!Je^mO9+z(rCi{b{o zB%J1X*g}$cbrF>#ONvS+BRCrbB-|GLFmt!(tth%N%pY~KRc}z`*;Jt8|MmkF@Iu)R zG|UOza#rV(Y+H*jhBa)IxJwa#M170zrq8Yc8B?+~HoW<5aai{hFb(H|6uv{pX> z4xpSDm~kjdRlMGUiBMI#DnskR5j)IwbJ*3DjN42fdFZYrkpRdaozM#?IW#*B_A@}F zhm&~Av+}KD*}qxG57)P65Qu%g51@+-Q@bJFD|h9%&ujV{q&q_bD1aCj=w=_)hYM)?UX zLN}n6{sd%-YprM0wABgVsG;#%ZZ`)-V2G-4w8R5ZC!0bgjjTu*2U9DmzeYIIf;7t z_2x^mJ^O=d5+Vp@iC^UlOye0eU*0H2=W{EpUW48rIl?3$)fT8*AC0Bv zxwg=7%t`=+-4fd70&K{Q5Sfqvm%WAetia1YveZci{8v+2?Oi_;kbW^K^@$%t+~|)= ztdWp4X4(+N=ab!Hs&GB0x>EG&wnzcVBP^a*pwV09Oh}lo7!=@F6hh(c9vSE%eJ8V` zW&=r)rd`DVE$)ZVGei9bHVyRG71;iLlM6IQm~IFIUhC>1-z=fkwhq2!;Oi3}A0P&1 z3=b#gagKJm8m|bLo!|KC+~y1dt_^QMR-%Uzob)4TI!$-~?94fg%=}DN&V0J5@*mCv z1PuWtCBlHj0WFB%FU_P&%n}sQRf8t6l)Y`iu9VgnMg$lTI{w7u3wU8H&}{ z^b#@>*m9jwE8B8cg!`m(AVG`NixUDd8g%(_iFXqOB*y>kv~#Q$P`U(=GRS8fvTA_9#-ynbX~%GZ(5d=wG-z|M{js)lZ7PH;nLE$>f)9^S6GGX;Syiw?m!CN?1ol6SP$OPq6DzNv4gfIl%%wzpk5n7CdUVm zzzZ{g52;)>dQ(iol-#t743OHb6ZPGXjiQq0C9o7wS`hNn|6wU;iGbm#=O-jH?KEhy zCv_HdAPBk;I)aZ3hXTz4-i$*)-eVss{4jQq+)Sld|D~of>A~D!oR6o9+)DsNlR6X% z@lXY5RO5Qnr7m~d9jtgfmkOx6!17rzZ%FWw?Pgp6p@|_e&+sbd-u?}pxA5LF9+F>CDg=Z(f zgh5(%cGzfz8<1?NAlNOaCDea2I6P1hP|-v7-s|)rurU-i2V?m{v!8XsM_c9rbPBo}668XCHWhTg#C(av4^Qkm7wg}$%t z=P`Xp?U#=W_khrW{CtI33=;!)X_W?Y(yZ=KU zf61t*9wqT36Q8s=qZQ{*nP(&jI;z6{XgwJCgw}r#jY#6+(ZYPFXu8C5Iyx#9L{3B{ zOeygq!1&{L-gyxxysh$mG-x7R zcje7;4ps5FzoyAXQ68Pu>^%sqXgaR7lU|w5OEKTxXS! z?b~v1!k?2ayp%k7kA}!Mz)Nt*@cb;#&%u`nd)os=BgU)Jr!RAaFo#sbr33>LGrApk zHvC?=_yCMTM18=snwP+c=Gji9&W%#6V&l&m__%dg&5f{iC&^ZO8f+Ml(hJ4r2eLqW=r z8a@g3lgA~$PQrju|G0Va+I0YyLKE_*!aW{_;p=c@@r!U|;q0`357@_C zGIPO2yDw&{oeHcZ9M@Qa`ltJfL3{q7Ai;>yT}U;+N527{XpZz08jmz?mRHmCyXP|I zmF991lp^dbhrpd+npIoX-=8ak)rJ|I06nJ4_-4S15kfZJU=R}`?E`S zYcGZa&gx$0tbI|%+4w^9t5f)b9FQ*ihfgjKQXozu&Tadjb=K(Al=jgD^w-#u``jhw z5}3xM-Ydlzm`2Puk%_f#-&qwP(9%0`crO9)-C%}j;W}UVP>ZtmkYmqUH@OZWK1I^f zdDWKH=>d?F&! zu;%Lh=7!u6XeV-ui$)jh%N2W>%K;0_3hd1nge4vIsbkNnyh_>WVQ<2IZQ0{K7A+Tx zrb})YRgQybP#19`yf)pc{1%~-_q+^nmza)%I}U($adGii^VP|lmG^?JADIej@SOiw zSH}yh_-?JZkrJx_nFB8f$O{h6xkdH`prsLq3kGI5TwvmetWOuy3qN``IXOvu4Qq^H zXmAaEU+agi2fxg|-x#94ekh~X6W#Q|=9er1y!st{aq`fEBjydPugn3vp*SXV#nn|D zxGBbjIHwpy*2epE9#OksH7~1uN+FexG4FAYX~Q&0rtWT-n7FCp9=}#6t^00M256sSkj&Mwt5rFkc&) zm^ih64`dSOLaG50b{>ql3Bf_&PADIyt9A>REmQP>S}8Jow-(!d1EiO7di`r!Dg6Q z)e?|IK$TnNuMti&{%=W?kUiCGO+NrfOU0$nZgOhol~e|v0n1-xwt|^n(DI3&pC9%e zF$gjuL{MJ%u2P>Pf(X55WTOVZC)~l5gTZ0s1o$*<1&;iLOCz-pFTvPnvg{$GL;iS_ zx(LBye64bkq_#FA^e2#5V*n17!k%4!mn4^y*ewQI=+a|!4G?7DV;UUgqs@eX+LUr-LHEek8`zuJY$)?!Cs zEjzas{SNV_XRBD9rW|_+RG;vO!K*<-1G*OSjz+8ERZNTzq)p zyh$20YyrN8mh*z*Ho^;0?b!eQN>vg(`kgy>5G|n^vFmd`0;)I>!UoFyi9gUZYCZRG zYtg|Ys}Oo#t1sxh%2O{gN5=VidI!)iHxkNpqgFz{zH{eJ6b3qB4mW+U1O8ksI2d5V z6kcoDSA;-ZBqihbfakvf0aQ2{IXTzST}cAey)sxxh`s#KUBou3sIpB8P$;Kp^u>i} zF&)}BQ^D+SK0hKip+$&cm&ozfZQf~cSZ%D^qqZmyy7sHEvHP%^DvMYo`^PZDaMBo`& zZUkj*?H;MCvp5P(XuzDph~uCM27h`ThA6ipg-WgJMa!qBxsZ_&!t_pskS zisc2daH7O#w*%pX00jlh_|Hrqd}bTsvVi^U$&|5lgL(#7BOKmZy%a)rdl9uMrVB7! z#HO+vjSD#&Qa#?0?N4kxW>5dKTPIQzg#Pr$0AFW*C#BAITGd5o_AhQ?3+oE9;T0Odx|>K7TT z7vqrj@JD7FE>l`8PwTi74!XoJ_zIsFif}Fap~F%3zm8&PH99)lhjI>FHKdp=V-V_uZgQ*6~3x8iA`-n-GG>zVa`j!VE1oU77u8b<^mtQ2k}YE zX1wS@8)Ara^e8$Tq@jmKHwWyi4_D%VfGAHKMa)`TeuE2-Swoe_Bq^z~uX3I7t5c^$iXC z@fLPs(CRNTyXTr8eN0kP($+g@A0&R%JB`%qF8F35osn{WhN;kSpC_X}ai;N`us;&F zj@_1vgXvF9bcn{9ICQA|uQAv^+1PNAZiX)ip;43s$Nb8bZO`JPU49yEfV8ZBUM3K& zjMe(G1)4z=Ul$DOxDW@0B2QEMoag2)T3>gXOGx(<^t+6nflpAfx`b;%?HFwG*8UvI zUsL^=9*ORPuwGT1r0U3mPbX+;Tc(UV|Al-C!^1=S4v_7(xzo!qBVsm0+hPb+)@qe? z3;rP&%}E+EDtI)@bR8@_0=r$U)H}&a$|(UR9V)>Kc}8!^@0cRvKJDZ#=EA-=pMLCy z97W_p*x*PhD<4652)|k@=(&i~jg=3R4Y7Hvl!UGlEi2*-@RM5!yN0;2+IZp>r&j@c zt}tQZjA{wIIdq#RspQHZlG{gJi<3t!jfu2!iX3v;=-KUC?ck==OdYy55r#9N(!g}X zqm?F)x7uJhN0_e|Dd1s?JWL=Vg?-Z3sU5Dz7IJ>m7uwZhbI{Pu?VB%`*E>r(`tlPY)#v&7ubmEzxqbG-lW*B; z(mXPOc)74{3X)3JV0JGSPHKEW97gOh>=f_`W+NA{bg)PR zYt~vw<|I`kZyvedz-r{>n|cnP25ZD;8HR=Q=e#^!@!`!8M$m(hnMv0lV+$O7h%{;C9SR+YnZ ztUC9RZ~*smUARz;3{=zE+1b(E9_R=&p}$=&m^s+lY101RHum__8|(DkjX3s4ZdIuG z)5&%C1->~!TFmqQJH1rU5NH4B3QKX|DGseIPDyhJ=}Q(4$XKx^Xy%ZBSGl$RDYrn6 zsSEDTDKZbY(~i5}h**9MD(JXxJmu5Wae(P4)}ya?);deRB}T!bf|^#kMu`Siex~og zdS$3$BH8p26BOdbp(+O`AGR-hA4*ZMn*P_lswKa8ss?B2-T)G{whZ<6c?{ z{0IS3Uk*c@w@gC+$Cs%W_!M;>yeWYI8WI9M-NgSqZ(#Q)CHWxYVK6m94F z$5LHSP7@(FTU(r%Ut9#38!j8f4?lhEYobwvuCRaUTOGSxx7FuJs1oPCrkn&JoNerv zrW}(SlP2YvwchKHz9Mtf0e5?{EK9;-t%W`?U}q~ zkB{xmTDrP-ncSn?M|ZBeb!1h6!QC%g85xzY{_LO?=Hi4PeD-E^Th+Cmmg4RS3nrZ& z8BcPsqEB{F=}ujY*eOf}S5tF(|D?dHv+hiQOQP%JAA0kD+j0>&!l|W;CPXc{Xfj#O zW#~@Faww%)pPQ_8I-p`MbJA3sosc)DSU+_WJ~-YH^*Z*{MHsJHWCF zlgakQSRR}XVe^1$9dIR4TA&a>Gmf&2P~LFwV_FIxw#OP<&GcVI#(dzV?liBdxh3%G z9ys>tovG{0eV+0A81!^?+}ri%^qslG?}oi0B?UMNjl~_?Zs0gamqk={zX!!A4CdE%Dc;N`qCSg#>?-$%1GOD;BLV}y*`XE~&j1@*_H%>?Z*b8iTukU!f_=6j@K zm=q8c`0j8)UHK$K%yB2*OU7OT?cYlD*O6ZYsDK3`DkV%#aE}Ev?C6|ef<8BDd4xbg z@Jq2$@O2+38;{6}U-KTlTOLdU3YY7wUgCwiihmWpZ{uf&9?A_Q|9y(u_r9)TZhLSI}#5h|a4x-G5g8zLB zi%1UZx1N=iV@~}E40#<>#w5*C1c@Wf%IFzX=CDJx)U$W&g1+b2hwhSvivmJI`=W|3 zJ5sHGaj`hU=xo5>*AS_BlX{;T*}Nq5-f>#Ce|`FU^EfJXE${e`py#MKrVL9)-3#dJ z5Bf?9x~vOe9DofJbDMDf180)H+`fZdM9&0)f&(B84jsFNk8DA<=a-d(9qpnYAF0Qd z#fm*zyta2)hQpWoRhVYV4RhzjuE_C=skTwWX*oGL+^e7BgiGM-%=%?IE%{S+N*Bdd z_R4L-*(DIvagYsH4hCN)-0eR-KaKtv#Q92egx)VdcS+!0Vv$3rfp z=7#hO6{W?hWfV%EVf*mH%WINabbII)Xer0N=ayXU`59f(Nt+>!q<4wFVRr2mdzVg` z0gDE$YBxpumK=nCqV_PT`Kkw7Nl%*q&w?!?5FrA-7ISupyWWe^UPQYZsbh_aO?NDUu}UsM2~7eD9hMwz7^0x+B0a)^vZO8B*`BrqmioRHB-hM)o<4+- zX9pbDbA?nfM7oYrou0z%=hZ=U>gn&Gziq#;QRGgFTUH!89EHwEB z-7&gi&?o7IpKskh}3X)D$Yx;UFA3zsGBCq#^ZA5MA#`0Iq zy-zfvceGNyWk1?GKSUpxp@&j1E>5pG^>9v#S~9ngP}ShzNzKu1*fK6IeX;6hjs<14 zvuo1W0AN{hM%TZnWIuAN>qGt*AZ8U|NE_fd6O|u&anx|03=R+Cs4vIK>lhkJ`BY53 zfI1HoM|ibZe_90*aAC$P-oezwHdy#I`_ZqT$m%pIF9@m^@yI~WCv@{-nu^r2zlrgq_LhtDw?O|IU$4hsq3U4K16g|~qy8zJgQ-D=aG zZ_BxbI94CaLUoQ}I%Uk#&di(9`P!LA-l!e39%KSpU)-0(e_Z0a`@B*&*yvy5Szgho zVf0C{=T1u6$f1I*mCJIMB{tj#7j?;gKMe0@c!v3EubhWFA zk7ma0_&oO@jCt(^U?Z$O4lV9zh&0U1lmGfDU$laRaS9$XpK{xOUU(fZS^{1Cz1RHG zXkHu~XgjjP)lKcNJ1tvLKA~$T2#+;2)0l1nrECYJTkg*|Jkl78hL1P;v~9(LVLxc2 zby?eF=^v_VWn1`LfBGl&58b_LI&xj^Es|ll6voo1`Ym&7K+XeQ@m>5t_k`G|Yzd&@5&F^>NrmXR*rD|rp4S7znGZg3R7fG&*7Gx;K`OL5rqVy2!TMI zd+(%NTYn3c20ZuoYTw5hRe4WU>_z3^yYByZ(WZ%s-HMa{1sdnNEn|-q_r{_yWe_W0 zs#eWR=~T^hO|?%Ao5GE z;sOO%;GYvo2I_Qp|sQB zXtSG`n`|K!ES#P=iaI||!{U1OF0P)mhyeUd}CpFm`lc7!ygw2ELUB~ z_&&ygUbt{^oE|D=r{K!m7!mE|IHE;997Jjkyu zXE2%W8z84J&Cl(z`I0Xt^`L|An8~-HQB(eEHz*yoon8HU);ei?a)q|}dQ>M=3vP^$ z-8odvmohxl1h$m(BkIPiqpXdS1Z~Mxm1GN^AEI^8= z(E*eb$RThjVjuxb7SQ)pW#@u#g^eaOiI~z|uXvNeoAY}@*vfr(kAqHBs;Ka_)7s?= z-5aD!wXcE+$?ZlR7g(kM8)DNsZ*&_Qcf8ZkN^xuqq)0P3?x$DqXY7l-4PoW=bamO? z-?UFzjQ4AR^EqhmX+l{B@)$xS_pO(LDdKoaHrc}HSmc$O^599Xw5OTe$yJVSMy53T zDT<)aqZGe4=T&afZTnq+iaO-M$ihTxtV2OzdTe)HvRwDtgK`;XNj*|>Xy3;>X$QWn zrJ1ZZoykIusPZw$sNql&bUszy-nWCOR$LZFP0(fbubV#(sI;8BQxF6G6C7D2znY=* zsvNScmFfM->+LBDpV--%a$~U#6*pT(%eKY=lcyK=KwO0JMNvB0YJL$soefQAJwzz= zsgs=gIxgTo68oyuy+b!w$};6t@N-Ruj)>(2fwf%!C9k5hN#@W;-q&9))ZFoBOVu{! zp?z7+Z)?K855-RI8H^clwNWpovk~I1Q6btcp%;&T1tMFMqM6^8X>L-9XFN5=Ws#ZtxsSb5&_YA|#LebxzkP}p|YG@-2fu>eZ{fah1Wm1)Y|lMeD9 zp{F`8E}X^2sbR)L8*a+eN?bL=UuHsbKs5yUoJ$77{<^gL)oObNt=lK62Wuo5hRE1@-<1_PtuC6wi;%ZI{Ux zQtgl4sMCX&d>P#1e|>$t^Q}C;t+FLEfFa^NgN-4!u1m5x$iJ9z|8R5nFKVOpR!-jw z1u6qm>zx$x7UHGezV+Nhe}5~YcG^gs_qstxt=WOqrgpZ?>1>W^*v}9uZ=liu)pv;b zPjpRx{kQh6f4Lt+NH5*|)Guyxoz6EuR5U9Jv_G3WJa%0RwE{jdJMaH!PIxoAn4i~k zb2kH-%**APkn$N^9`fg#*hYVN^Rrro<>Afd?b}eBZ*k}UJN;$Z%cQn`+M{shkNw6k zak0w5&je^;kC`ghzt%AbMF^@)(D z?#EnK0y~y_Hp`-Zoi?km5rNBzVV916Oj)$+{TI<2x5WWW91Ulg3r&^Yzb|b4XFSO_ zH^TR*=TD`g%dgAMPJ@wVUl?Mw{<r}z`P_9SbVB+k`jj#MQ39&)JOz9zeA>8+9WP4@Gbkf_D|n?pVW zAQP_`wC*Se*%Sh^-OW79L$X~Oy~~p~N!QE71#8^{_Nix^4tbSRWW?9s-&FF9bcVsR znF&jm!@|&1?aYAdlAe&7^p*omwyXZf+)DMi-WH!+x*gYY`=@;wYi10zqx)fq54#?a z@9xYgx{PD)I&)hG2!;)~Qo;AKCj~Em$HyP8FAoRUz^9!U!{aVT zVhk^6<#98F14X%@<=~!c{tTMusLv)5CPhr8x}CB{v*f0idzb+risXr;7F$Hfk5vpOegVm{_x9{d2TuZZUgZ*vo zMshf_vAIcP?ZP?NcRJ>*u3D`N0{juf7qoE~o-JW)Xk~7&BU+D&Oog9KEaitL*o7nP z#@S;THABZzHA2i^e=E+{B!WJpXuomT$8VWSn5-i_rd8B#{^^!FX$%1p>6Bo%AFlZE zyJplR>uLbsiQ0l?_WSm$%&pyH;U=W!#6ILC4%+_>gaPLO&nL(SfPO%!0^s4YS?m0< znl8UErzK02cJWX1c8iE1&gn5z{R5Mdx-?}~uK8mQ0;wzEpHERDUxK{+E>t~nrqT8h zfl|K8ZlZIcgCpaYjj$PLhF?YS(?s*<_-jcS)p0!wn$RyW@(=I(v)R5jHB!+uUpTkk z?O43F=XkG7QT&o>iZg$^jJynM@Rb01Ddt+TbG~Qm3^NT3Y)|^u)m*>-=+UERXXW2s z@qT-quX3?lL0Q?heZG79UbA9H#-;8*%=_g+uj^7b(TPM`ef@Rr%1LgE$BsQcMp5NF zxqRURsfGFfUA<$sQ0^#@F8uGCvjXFWu}S&uXSaP_P1F`qY@a=PKrL|JuhsehshAHR z_sgl=5c?eMX5jwj?AW*aNy;OWEQ*m5H-;PPwtboTO|elH?CMB>r38F2MNFvElBU`nTdvYt%_YIYsSsEJMFDL_1tI9K1KD zOIb0|bD1fp^DN75@*F6Wh!X$vi^?bI>QA@DA4(q@w^NF*d6|y$1sx2L|7CArF}=x zYQSxiT{fSz_5QlHtJ7}JxU!xw%e6PmeKY6Yshtj9xwaUgBlR#(u>Tr3sqSB(XNqwCpJD-j^!}z&IIce$rz3J3%Wh>w#GjUY`@I9DQ;A5 zI(U^{4?QOQ$b7IOKt1aT4_zg>&CziNW1c@_My}#^5n&1|u~Y5WO_Hm|?!fezmAzND4gh2cmp>q zL1}iq-`{2~e{=l!562HDmDon#S}975MfR#{H&#*q{!mi&VC;|EWySnoi5TIF`+$CHiZ<+dJnf z3^V&Ja}hE=lva1DJeYS}K7Pxy>~?f`asJM1CuuVK9!ff%F#ms?lpKU3)G6pb)Youa zmHJS|+BWg1({#yXtzPCJ_do7)&9vI$DKn+nJcW*BMKy^MLxP4$O(L?pKT@$0g%;wP6MpQT_r$@6x~)bsWMpA#{w-bv^uDmd5~|rsyOYK zJWjjFEjE%H|8e{Nn~H+YyyRo9*HV|hIns#U%yKC|An~;P14NB*6?C*T%A^G$o&d#s zN{f6r3%AH(BhUQ?8L!A40xS=hKhKovrlMCIW8KCEi5$xqTT0N=ldJ-fx17X!Ox)Th zu+$nHM{dOjK1i=x$X#de@{4|{`>v|fG9b?s8a0?3|6G1SeXxT1P+k24r@0(=&O*H* zM*|+}H@}1Hg+*#VD6!s(KX_H{l^WZ0!O|PbiMz9IDk`kAze0C;Y{x(O((`5J6nh>; z8d*e6w}9tdX*S#X$QyT+)s-Aip~$+0pq=hP4?+(fxkINt+ji8Wa$PEbG3r_D*?oNB zCLJ;#jO+9B_V*th-x>XEl26#gASq)i9H{{Vhd%Rn9!W z%l23eU+8IFA9GW+A-XecpKTT6=IK9Jzfb(RDp))CyHn+?$S1eTrD`r|rTcm*wZGIa z40E)SM6))KKQ%byr`^0diP6+EQFo1l8qMfefN;ye?ETff~17^nxN3YL!Q)d+Myua^q=-ycz@sS?w4uK;R{!f&UCSK zi<3?%OQ?Rx(N&R^<@E4p0lBo*RrjDLQVU0?xVr}z9MqFUntlFpF=tx5;%~PCQQ&SO_MI$ElJ58f{PZW zvTtuUtu&7AGK;=xToC&8@*@+z^6YN!kMs$>3l5-^bYz`04Qw$yb!Z&gq= zEQt!UfuTR@oc^mHOXLrWZ5ABf`0dF0Aj}tTdtlk}7aDiS9g4Gg#};*6E`=}AWrA+5 ztGTMEm@7l0m$Hzj-oNgxdA=xE+BbT)@yHm-NS(SPn5Y<;c8St$sp0yJ4m$9p3-%lS z;^F#+g-?5?44j;tZmM@j@o&AgmoPklFoo7PJw3f?A04Q3D#=Q~{fvx^bTit0%?|UE z2ZMK6so>$1CfQ)1XWaY8P|!c@VHo|FSN%)k;^lF4_6Rfp>UZsU?915|%tlS>{f1}v z%}V;X^joeWJ^>3ZwEmY1Zx82BU0EsSFiHY@9c;);%{=?u zlY^+cZW;5@dA|Vyuj)If>Ju_*oN=LZEHB9IfKQTvM^M;8_r zI*QRvi)5&+4Y*L1qlMZo)(~G&gHd~|X&3{Yn&h99lo}ON% z4!X8p8hxTx(NC9KhDkH#cGJ;g)B7n*lIP~#Dvpdf4M(2+GIzuZp&6kAmfKWhyZH;P zJDPaNeM$)fc52y!vdXvr-FeVO!|$4Fs@Eyj^-=!dWj9Xt=j=3~$($Dw@@`&PmKbfm zvcnV6a>!hOFq)iN3Y3Zy096#?9nAIM>Equz1`7kJk+zF+hsGDnUY`xGPNQN+mKmWC z9vSlsH(9(uTW@j z9D8$S+)j7rrc_Js;LxGXUsf6Gy}CP+G7sz_*}XgK&q|mt5(E-Cb{SKs9p4JNz)U1$F+~V*c8vz^^DT^bh+G_lx1>gI@zxDJEb95%}Wq zf15{723GF(1X~jBQ2L}ars_s2hU}p3j|0IT%9NKg_03nM!g^M!1q)Y{ zo;X#$MfAer?Rfk(%Xv?aSL@giASYt7Va!+ExlUy?!)@fnJ+WQ5;1~tZM4wB&rMr;0 z$gyGDjeEgUjQ;oU#ek!WI{2KhGYMZfd3+9< zX|!IaT{Anma)=^65G-Ge#IrQDJ(F)A`p2{QajiacNc};t;ZU`TJFW2Yh*1Ac<(kSg z!|gh|aCM`%npBz{5-kxdh3VSGvyU(DnUQ9t_CXnslMF5i=+%_|<=`_C<03#c>iSHj zYhiA2Krv6N-!(l|-)XsBMsdW@ws%e>;^>4zRu$!~5@L}D)XgL-56d8C!=5Mb)=ap$ z06j#O7K0TB@POE4%nbe)zT}`>c=rLnst~6F;?(cyb_woPQ_kP_D$sT5T zFQwwhr@Fhx9|@ag(_NLT81`XH#(>`}VyuBY@Oiy=wN7rT)y@@($Y$jxr^$|+>y53{ z_G=p6VJWa*tzBLg=rgxduU|GPyO(x1y936A5SjHp$_Fnl9t>V5vHJBQ?m5)dBww?#f|%> zDittx*%3Hr-;_)HC|s(+pxA*?{jg0JB2ZuE!1;}lBvPl1{3L7z^_}f#CXCm*dFjr* z^Gen#Rj+7@(uieEzizrC!&l$Sl6UdS04Utr$N20#ro4(;lHF7@?Rl7 zP7~OUYn=6SajmUSPmh5a3Q_<7+>m>uTS>!5E%^tFd$?2_0Y+^DDfJ$XAvEET03z0? zO;kSG?Gnb5O>ZZ{faO-;$e`x5v|ye2XdIPNxEs8!K#+T2W)|`>?Q#9^eE^bxd6blu0mI{wL>MT+=YJ4J zn9Q$81Oz=8pp~f`@;X_ikhGgx=9{VFl+Z_BnZSFh1{TRBj>CaYeQT`iGs;I+%EIM- z^ef_DCm3vYb}CtUT{~r(&2u$!x=f+u4rk^5@?yA1*JHGFhtbSFkG*_8-d%~^Hj-Uj z(m350ZeHycI67SaC9@>j)yj)8;`;NtQ9Kt`2sG%I$);npCt^L~U&S$}Nhuq9)wOYV z&FKAXl9N7kui*08J`PlCc`1QahjPwG53etfks6&srTFSY&+zyB;Fupaf!0}NxO}e1 z`Ak)`lXJkA)7YcNAaIme<#VlJLru<5_EP-Jb!){A<)2k z|CA+6AmKmZ-H}opaq~fQh?Vx_q?vNC!2?8>v?#oVvzS<5Q@UkYtAixSp zN(np|^nF}VodKdh;xE*~y+1RJ(AnYEQTQ@IYq!oon(ral*8Sg_jvT& z|3_NBy^L4QSNWCpx%3>R{#A{rN{q_hJnk}$2R@8lP}KL)xG`524sq2(Dypg{sJxy_ zpN76}m$MRu^fJwaZFB3W?lpfO^9IQZv*NMz+s!gBLRk`wgMw5-L*tlk22d%#v+7h~ zlTQlI(cr*g9~m7DI2}56;&M`}xuW+j?!BGvY;~5~wZ(j6_Ls|0 zIZx&Wm}hp@GU-X)f0qoxeVqryJRCLWZG?{gwmCSjx_8ASCz2MW4!1gURAM?k`}u4Q zU7h5TI677Rkelxly~_u{ZufzrO7&aUMIt@tqPfBBsV_)b>l;KpVBCV52!6ztu;)11 zxhqTozGhvEK;5G2@y<+-ey5eZzq^3_Zrqtpnws6MJ25b14oyf4K6_9`;hZx0p{w8S zr9roXdGpCF5pUf5#4&7_nIclokB&>Ghpxipffx=4hlC(1f!PMZ#kK~UNWdZ|sZLP) z;5G~#Dcp(Kl}JU=K4O^NoW&qequ*P>BcXFrHBO74E=h@x4!tDAkxHffsx5Zr;B6_e zz&ilM))%*MJqft|7D5URMSki#u4(dL*QafLz%F+p?8CjVDYI6>LJw<@m6c`k#a)V* zOe0RjWb|yxJqCl^f5pQ~$DpJw|CGqmiDCBq=xV3OAg!!>KoYjR%)nntFq zspk22cp8YBpXBE4A7#P0OfbG5r$IEY%41@!jg2RgXv3cq1pr58b~YgeL+K190wE^0 zE6~!i>-z^)>R;Skl0~HpS0I7m1=>0a1uO%1=;xu{Keen^YA+?W7?w^gWlQDl-mzUG z<~a{@{?63an-I#y$q)QHN({2b#&#a3^_}Tg^fZ7|(nI+*A@KCkkOR!t)iaMY zr1=!bH2&FwLH2z1OmlXn{kk;86!Xs?0zKJs2-eMj+dd^4_k zE*qHXwanGko8Eby=q|G{#UTtpxQ`;x;eMak_pfL|lWcQfX()tKrAanbx7*$}& zWcaF<>3uKkd#k}5Hj`l{3Q(dOa;YvSnQU}bac~pB7^`Kb$R;d&owgx zuDOMGcZJ9gHJgEWbuz_MKYrAf&M<#Bw$--blF6`m?Idc>lUiS9 z^!Dt&#Kf$9Lf0u{k^_kMopR0_BJ*ECA=*0D#)tlWz*7ah3cO3SBR_tS%zRU$)Yd!` z;e9t*>8bU6j5=+f#O`bA{NP)ai!Bni^&mKmwWelET!R@1DET0Y_VAHzT;lWaeHTvh zslW1t(fr**UlnW4bGrt0XRi20nr<^XPdWD2#H(*=I&oo> z0a+&K79xHrV@O4hCOe5cvMY7DBLpnqs^Bg|BEmTMOSLUre2`XD6#sv``0Jb2#vj@5 zx^9$C9-lDlSdPxt%@||GA9ketJ@4Xh)aP+^4wM2ObpO5{;uVgD<1D+1}6Yz{Od^Q0Rl+GVsXp z>6IVgBwbWggkvali%e8r*W32rJD8}`TOEH?BkT=p)-(NXd-qtwv;!tnCmwkg_xI1d z7(IKUBnw$7p_R`01o}~^ZdX=Tl&;M(U-L5uDWj-wx-8q<2EU>H^uy{BIhlk1Ob<0b zkss^3Y%JBxgMZ`QLp~`obvDRWE#QEGiV)m(Lz7rTB`zw7&$7H^pI3Ne?)2 zFUye;U$*^H<+sBQKYu3KH1s zJ+dD?dYdsHIs(+ckOHbq*&L@m)cjWTaGaS5g=6OIhAYX3Ocvg7x0heY?*x?2okmjz z#RV~6MD-5I?O#>9ov0R7J6~ z^lFIbmG^VO;x|PEiL$W+*wz~rHeBRYj(u&B--WLvVDsl-Kz7)$Vt1Zd==*6Vwfgt(;oAuvG+!qeO=cPlzT;`V=@$1*uKh62>In z5Bu5m+tUPYw4T<9HMC7{;;pzhb$zVxPWI0V$Mu)=roWXsWL(4SUJwXD7O!S2W?U#B z=jVCwbD*%bfP5Eq9GVMq9Y0rpOK$#VTl~3}L?^TFZjxexs`1;M6CEx=#Pxz5 z9dNJ!nGXS0EA>c7wR^|JY0Sy~tfH~3Da+n>;zu#+Ks~!Yp)R^QW1iwN%i(Q41eCxSU?;8~sxWBz1@;28Kek^)cUo>H*PDRaNy;s}1-sEx#l4nMu>S z&ixzz>b~6ut!CP(?=o3(UFVFS#s_{N)}R16i#yaf*%({B*x}kN#BdNzp+35#sOViP zOqmmHU{bl~4{JsnpK4c5XtGwv4`;zcS9Q$IpA+)d?ruL=p!3L}puiXm3UvH{s-mJI z;@3a;@XleMs>hL(#)Fzyx;}P&%yZGdTvV2E6-AK52di8S!k%7?5qSYhWFkO;lY^N` z`M?Yqn^~G8=E3{sukefKrv(^(h#oRuJ1eL`C;msnD!&WKa?5ckg+Is|&>jSR2u+xr z-8h}SwD0+T+c&RHcT0HmxsT0XIbxRIqhL%C+)DYhS~bnU2VLM373H&sz(fXzQeEi9 z6cmLp&;U3PUTd1~H@Ikc^jb2)(dhwF9Tt|ls^r=O8ByDe`n0$U_n)#I=(V$_Bj1BJ z4gvl>U0qc`bw9f4e%u+Z70Yg8 zG@?ej#LfFD1pnL1RNoiHnI>5Z?Z$kB(AsHv&(58H&}>2FS6y9=Lk_MPq4G8{kx7)> zo93lI+7T0XF7M6F_jF;}d~3!?UpL$ABu)I|A0tc!JPZSgA9*Y6T}CHACw)#4}S)qQg#IeN^*8VsyR z6}GGip%)|>dw&K7sBftM?2#1tZd2{**lk}xbb+X&V1R&Ubos&<-|W>q3T`W^udAm6 zzqN7QXMK{B;I=$VF7)PR_I&%rqB5(iN(eap6e#e3<`P~QVC+)R3pD(`u0`a9F|3g> zU&2x$#^MqOkH8ylpUtjXrIE);*L>rmjK9=GcK`dDeiZmG*w5Yl+m z8VHJQSLXh;yI}mlpQC!p;=6}B=23j3*or5u+(Lipm?Yko~FE$&^WW5Wghw8RdJ9wNE63zasEV8zBs60EAaSWi#a z@|CJH7U}u>SGc#hb3{PLPQ(}+)9t<)yZ1^)I0~3H;H_Oe{&8la|ENwzJ8rR&_~ zkIt^xlalcH!p7w*)D#)wktsIJ%wl<&kSGOI3RI&~(`+m7_+XN9BF@Y`$4#kCCE~4c zo^=Nw%U-$;pO>YFC7zPp#*HIEQfIwE2JeH5%y%OjLcv*5awUn`o+-f2ROp5Hl%7SG zDL+scLQ3o_seY_PljF#v{767$(A|Ve@3ty_mc0K>ckA_s2LUYeqFi%B@ z|53{%Q}knR4h`ucZw=NE=Q}0Un2bZF@vwUE#}h=CE+Ik>=?U2DTr_Xv<4MA6C1Y;) zt}cv$z}^5c{NtS@Z<$x_)D2lSwzOPD-41;pW?ayCR-%}|sbYX1jXr`0O13mF*q1)m zZ)Bn{MtG^(QxZTtL z#l9}v9zCf2!F?r+M1KD+>N7{qOlvnj>&?V^Ox8m0Am1%DDfmiP8vV$All2Po@|hzqtb!Y8L%8Q3y=5W%xQeK3xHg$ zxA*wBySF9E?_i!!;6baat3+}K6pyl#@Du@SMy=)jll|Fuqz}rTul6gwf!w6RH+sDA zCvV%xaSomP9WRIw>wi62i8-+H_Sr)!J|75M0(f%bTL@86{U7=I8ai{G^KwNes}8DPU# z?^Zfra#Q!mT#ylQmn4~qswgsX=1ZjFE0GyIcLu-WHd8<^s8j&MFv=?G7InlE6XT=E z)8VyLdv-zCji!(xK%Zm=mLgnYVs*$yPiyrDYCv10!kOg$6U{uyEsSwm zslcD$3PUvUn6tp4qtff(86X2M4HYDe-zfST_6dnLmgaks3uc`7LG+PN?8uOKhb)gK zwMdCY5960Ww@w^p#MXyf7n=3YEZ_O!JFLp?Gd5#K13QZ0xwNb-NxVE*uvrUP2t^`g zAo!u`!Y_T2BWTRl^ZLyH0!IHWU3bJH20%#gLxLnN4BYwbqB0alN=ZR@p*l2pP8^i7 zY#)-r89QPt5hQyAqPYD0{FX~1K~lI7K}B6X(8EQd^RXe#a@esFW}o-A#7??wEV=cT zPjB5Xfe+!48h`_-%^;%+!Ac1E8xDs6cslU?Yk(Iptpeu_Xc3xqVg&)+;nD4Is0l|K zaIuKA{lwu8$;@QiEPKoQoQHasg`WBd2e2#RP3*$;+O_(Zn|V-=<|1eRwHg6(>(^y^ z2A&9P)cl1DUXH<83ibuvl8lF5YjD8H1fU8sH_A%Xgb4}fnnpi8AwR(v^C8vvQ&E}6 zI~T=v$x~Suw`!Wb4}xo)QA4Qf42%TC5^8D7TnxVvOCFLfZ~I@$xy-n_AA(}oTUg@M z05Wg1iL}gpMxZa}NJ`vMb<~ta7D<-=x|?ftvB+cjBGI4q??pKSq3d=6G;~;V*#1;9 zmSFNC9OFbIdln0qD&eG|DnNtqkay0=!w>y}IXttV7Ue6H*<)cvGBZSHeKmxSoGvMH zCnA)w7g2HB682C?FV=qzKZ|or;1=cZYO$w@L{( zAR;XwAl)FHf;2-)NjFFiNY}f^`+cAHe|Uem&%MuOm>JIJoPG9Qd#$zAjP7*72}ocf z9WZ@n_4dDy_>Wh#2-_3Ahsr?K1jqvj#US28ZOO*Q_Ta4{Hac^6-CBYI3o=02WDz7> zG%(W?Qp)MApgoQjvG?N)Z)#!<+YHirTalP>*StUZcU2}~fS(~0Dv;m*gu!WONaO93 zuR{?+iLxL@h6ex}dl>TZz@Q+0x9tb$nk;}w*DN3mRtl(EXm%NhQ0KJ*ZePj>uK8%} zh7zcY2pB)MQntobP4}y;#QXOM7{KJI&zT%rek}%IO9c5ApZ(lb0AJ8|GIZVe2aD0n zr{>v4i?UR6lAIilKG8-1CHvrPKlK8VDf$!E#q7-S1>AvL|1$y6>*toOY!OvYAT}Y(4WSO_S*ViJ3nF>mo1{!o`0pbWKNUerfvzimD*fa_4*x*8 zPJ36BmB8*F{`0bcRDdTzM&Q%5lgT_dX3c@t4bmn1jo)R%!`bk-V3(%1q3>ei>q%bm z=z0ZWHDE4*w-~&cDE$9Da}%Y}>h2Z75ZtoHn;q)X&SP|4fJt4Gz7}R0n_%B0Lx;okkbI6v|GBm#NURVb7PGtsK$erNJ#HhFw;f%n+Jq`vCMs2}~08EoC3DjZw_ThZau0wOV+5KDah^ zIf|&65-<_^zOmAx)3CLhm!cF9R{(^29_^92zh8cA!OYAI^*DHRY1ezjK~McAshE`* zJ5Fs2v!4_q>Q)!6{{qw48iK1HDSXGppMKSoF!;6sd9?yjDXRUsfS0rIx~F8 zdzt^rjkY;_9R(;qC@BBkd>_Cy8FGH0sDP&!+_2^GSIa@-=TZZHIC=T`!X=koLEG(N zACWzzva`tXNQW+cEsI5s2}cM^w=f1u4$gnxKPK+(kR}GegES~cryJVZFm(=H2h3#@ z_2)@AXBHLH!=uCacS!Gpxk&KyhXDP6UmZFZgs%+uIWwW5g+kC9>B>}3F2&3}RFQ@751CgujT6)WU?PEr)`0T>H7IO;kjX-B2K^;)nx2l-Q*l^Eo(jnqN|R ztL>KmccvXW!KwDxOqLJ}ZaXWqWpa?nU#ePNR_HH9MG?Ra0BUoyc&H*OA3FisQZlwq zo^YM;UsePjqG_5111U~mw1|2kca>g0M4R8#kj4zHL&7Z zV9tQcwC=L#?Hl0ZDgoXXXqRe8VI!q!fowpR%vw}i>onf*>W012>Uax-M=E9CQ*C&3 zIR6r@B>Rxm#^YHFnL*8E66rx8iUQyb(2qHZYHrycS~dq5)I>5+HWK4WN03F_Qti5X+lN1#*d_}}yUuT+tRqymafO(sHQ;9J*$;o-mx^ZeaA zGSCcxfCG|NdIBj*Vji1lP6us9y*aB5X7fjgk!54R-++)ct|}1k%?+N7rA<+Q@F8hA=({)aA!&3WGUHhicRr_65s^~Hn$M2r=yHNO?t zkus}iq9^}r{+Eq7ACX3JNl6fij_Mgrz&wvduO6(8zI++`4`Wa8M7}pm7;Zb9uP(o%a z!>v&v6sj)z)pvJ{yk;^iCuhg=FEMu;Hfdo*!5V#tLzml+Sv%lfR&eQ>eXd6q8QO;w z$OydWO+a5|a-Xh-o%Ge31FQ_U37FmQ+3&u21rO*_2LuO)Dk!}ma>Dt*4SIIHJpBDX z7!&$LV^-zP-jeBxYb3z&0!E}x+R`4BAkb=ri~wFs(H;)R8g?m1oV4W{^b~(t*^Sgn z$Yz#01M~o$Dxw4=?TDG5=Pfd5SK$d;aV>rzBa$Mry-5!07dVMfv(eZIeT4>1ioDqw z1qgz*lEje&=}X^6ki8Ep#u3w7w&cHw@RH5r0hHJ|^0KT2Z9QbRuH>wMssW>xA{?_} zI(%?-;x7phbUf>NB@P0w%mJ!Zwr8yj(4Ek$yL_7pP(MYy1geA9g;qXvOov7B@kuU3 z5!aJrX^As}&3Qz&{*h&``u$K1AiU2eER?Re8g2PmHWL8OExqKWGEHCa`D3n%ls6gX z(1?Yz3hjT$xggf^coEn)fJq*d&;<%WtBmQ&@7;OpG01IjmNIrIY@tm#Xw^M@-46`{ zp=nn1)53v=-WEGVqzAV@Hri7H z87NLVW61ImMR-NXwJg$2=ZRU31t$TZ_d?ADEpfmIlEm>8U^t&nf-+2dZOXnBQhijq z0z;K^7%9S+qfH}5)~t1?uh|il;IL|E(pA6l7<6e)P=m7fedgP%VUGu#69J-udly2# zH0@xlcNsm-UNs-vX4+%3XG#RhDo<6W8tjR$e`XW_!ZVAk$*V;YsR^D01lY`jGF!_} zvubR*0h|k9cn2_GtE(khVy-kU%HOB_TjV+FH*G1dLhyYrq0aoBO)N3(0v0!Lw?K|X zr)SlDw`$S`q8!|xFdG+wCXbhjJu6@kkflK`3wnFaD>MylO`CUE4gG9{WU+HF{1jI!B@;5$hNU z=1)phSmymzJ|)p-P15jMbcF%5KGd0MiH~w;tZp>|OUZNEJE$cdJKlmZw-7CY+ zCbksqetuWsW?-TNBaI)vWLcFE(Dwo72mU0G4*;^_)!`v<1x1t=qK70gNJipVhm823 zG;O3q>O`#eyXbSR#`0N`I#J7{jv+oDhL)P;$Zi%Qc&p~Wig$D{p}h{^C7AxY)lDJv zbgck=G4b(9g1Z^2AD-OK9&(%guw&v)N7QVyHQ5wF<6220d4U3r!cuKu9SR-;js{|4ZJ&GISa_{emlLIaZ*FQ9N!Pdfd_4G}p3b>6x z?-2^e0hXMK6qDA=>rVii=uw2M z#POth*;3+}-~GT>Dc^RFgNdg_DdzJzZ)Ol;{c;X~qXsQi$dD6wI_|<$&`2Q8!ru&R zvCmzPu2(0Lec49cqx`ebrVH-Uvp-X(zT2E#cABJ#&)fd(si5o0+8Qjyu%y1pM`#afNR17#K)1q)UK^$ZO_zOotb|ze)GsG>o;LTGVL#CzpALa(>{Vt zmRsUlrDZHJ36LeD`Jm2h-^Z--Qmj$n)RI{=4BfIvU{xU9E7h z1!}+!tg0UuR9&-mcHRrieK7tMmKfpO`P&+Fd!O zn`EvqTpMOGXi&CCk8#e;nu<)d^m>;BO*ZRVm1C+0vr#1$q7o~pLFE|jwj~xKJq5Td zy6iDET_!g@eGW~4Z;A|1wf+DBW2`eAQq-SJ&%+KpS5Q$0v^ZRhyd05N+MTKckAdY2MLl{9M4hVsx9JwvQ*~a^gJ4WbR^q@{ z4|Nt_WX_|h^=@lcpS=2CH(Jbc$_88+7I0CDftY47aJYpF{^NlCz6Lu|&HT=kL?54B z+grQ2$>gsqdlBVBW21r!jrt>_oa@Hlrk_>il-_-OM`{6}*nA5iR}!up0NdwlIMxi! zGzUF99WMN^J>r`e)Z@~2<(5&3ePH8OS&418oL;6M2zV^=o--$)p!f6p3Zc*3v&4UI07vKNmiP8RIYj+CC62GV<@n4DA1jzVR;7vRfyoxYyBXBj z-S}E8JU<-1^wkVl&koslcyx>Ex7C}kzmX}v(}!V}A<_9Vk|h&X2P989t)-}~`Y}nQ zi+r{+6vF66 zHJ6}pglRl?6Q~{>V9*Hw8>92S+~FZY&2{_0#|Kl;LkCYt7kKRzgH4BDgM!I*B?%Iv z)Ponj5LqcRrRv*N>(2#`0eH)dz8WS2wGtEnzybQI$*`O9jOx5&nqo0iWI(*}z)p=E zUp%E^utU8eA>M|qL6Ih!8M;o;GUfPM=Le`Iv`sbj=LcDXjtYH@{lh7&+g9Bw@gzbs z*nX{<0AJLppmk0&_<0T_#q%gAh8Ib!Ul(ju*%nxR$7DV|rK>p#^0kaj^TfdWzVrQl zjg0ZPUKzch$d@He1DbEG3f`AYrE98UlSa}5D2%XBPKP~9$EvR9wXUDmkukb$>7)GY zk)ct$GRdQ7ylXG(b-)T3>U`ker^vULTDCXap6{?V9FH8YTDV%dTlT2ZWBH%*K=dyj zS0+>q&66Na*CNLaQdX)3`9wFw3V^M%e(_h+HQJta-VnXWrl{QvI^oRA!Ai7talv)Z z9+EMM!OkOex@%@;ooE!)`oA^2<)nj--T$TnJq&U=I`TcAWEa_$Tz*E`K9whIW?EUu z{xwm9@#D)yb{R*l-oB|RfsJcUcgRD8Fz z>sm>bSnj(p95Y)LaNLE`#n|{-47tzoyv}J1ESz_m&u2_+_v(AO;>KAcGMnrZcl~EXzZ*$N~VKY?O~)W zC(p_pD|~xf2~=aw?P8b zHTP9iR&EN~2|fmTa?$tbOx0X~5x3pSm%FD;^yeRqONB4KIaK9>l}M+y{st9@O@-(9 z)JeRlHSDBSn~GgaQQ^kv^Ee-`a5gJ0cWpw@hCsGEV&eFX6EP&lVCIku^kuM?%U1r> z??cpZ{^z#uS(}I5C?%>l594w&;+%!9SUDh-z4t& z`84rdrs(jVItJBRieY7iec*DZQ&^N41z^|HTQTr*=&nMXA6UgdX|4Si$U2CcN%i*I z)$B_Yj%fwv*3gC+vT&a7Dkq12*7Jt|G2lZ|((E;-E@(4i zm}IXsqr~d69c;M4XT=CjXqZq?(4ZG@SCccc2JZ~`EJaMKsqX4blwS&h)pOyU4{5Sb zx?c=%GjS5lxI9L#yY;3an_5H5i6|{FQ9&J55jiPlX}wN)fi*e$H7NPajrWQUF642LcYf|#M6iy#0M{Hm`oDkoHzxsk z^A2|MAF3HougFN5nxH!LbDwjt04NXm<3OoI1_ZdpznoFeToZt50UFkgrn9A#Yeom} zZRfivut5NcPKCS;bs_9HJ4ZPQ)S-;WWx=2ksN!9V#G9@=!9>6BulR6q@Gkbx__fsyI{>4hi8Q|SR2yOr zF#qWKrjZ}TSD419`@KAH-mq6z4 zCd4v-4W<04v6v;f7Yy#9jY2j?J~Ns$^Q@4~o)zi`x1%TTc^aaWa}+pse9Uq>c1sdD zqa?v~@bcl$Vi#S0VvmJop3NnA`=j;<9x@(Soyp^xNo*DF{-g=f*_19L4gj--SP8kjmj7_rNbm{-tD))NLJ8Cl4*Tq}HoEHs^aA0je-ZI|AiC@3ZWzYXWPcch$zQ$X6 z&b+`Rv)nvnR5?gQs3O$~d7!OD3@T_3|;d zz=_IvYTGs`RcIOiE`t$j?kXqhpz#eDopDx`)je{Di=WME z=KIr>lCtG*=J623pq<^X9EnGXg@R`*}II=2(I&R%8WhWLn5c(N?S##v4 zUEZP3DM{!2#*-^quf9CF`|4pZ2gGrpp_|SfJh!5}%QtNM0O~(D<^p1bK1Z3yeBT|{ z2%NFf1<;k_#cmL<+3q-?IGEQ=VnV!*Fmn-%lt(1XbeyrYe_aJCoZ83C)!etlK6MSc z<1{y-(eN7H`aE$3u&*ewY+RuBboM!YFI$zvR+A&2Z;PVb{cJ(eCq)|xcmXOjc~jr2 zv2@Y$mlJ5tiFCDQcMxO&iixDy?i@!XlN(_t0_$o8EBS1zpeetK;VLX-GbDZ7ROCB4 zV|e1MJCz>Uo!wpFZTHgsH}?V8vID<}6aCL#-;#u$a!;Wv#!W5R%uugsrv0_6?^(?? z4>3;c_vsau!MLQ(9pzTt8Ia8!;YM8<)I3{*TlB?cwBOv$sC(ufrt>~dd>$=6p`qLX zcQwD2a@UZmQo~7sL^}P|Y7DXy!8W&5%G&3T)Qo2rFjRvO!N8Gk_w~5yTS#eJ5t9;* zt6!|8Uh_Rrcchr#8i#^(hWcWG+G%Ue_v*an~7LZuJTu3L_Y)?O}dWkVF1c+u)rqh~DsSISX z+q`1425(utYy(yUgjz~|RIS~I&)p9{u^SaRG_BL+jMZRtIQO_7+9JkA{JD94E_=sG z^eJT|jJ*OYQq^4c`sQbHZfm!qQiHK&o5!O`RvQ;=&BR$^#=nmjWbnLeEw)c=*f&VjJ2FCqZ;Y7l#tEfH zV}|Phon0~e()PglgA)mF`1&$|`a8p8G<($@zDH6B%N@PbIb6aK$y!&cGSs40iRsTa zfCE)S#YA9y&V-k|acSd|pbjQa9H0Ft65n}4Zr#{ER8_a9jyep5--TLA$R(k(fC{hK z+ZDIX6)+>yf^P~chc6m9nncg`Zi;wiAwZuO@za}3RfS~y9^MDu9z#I&hkN@aWNSLi z3Om~N*G}hN{DFVg*2ncEs<pq#(R* zzdl>EcjKv8zR4%x9=q0t$=z#V133i_QqR!q7{gDB*Gx*HNR9VG1Ly?!p@@1SVSUVb zKdoftjs**{hK~z-^X#eyTNg(mIonP3w=cS2H`reAVjdFt`qGK+qF8+Pp`IuUcS^OH zrJ8loSXl$kw>p67G|Ph) zVh`Tb8AJeNohmJ=U4mCb#wHNOFEASfMuPb=CEeJ_^hz4p^|Ce+*S$=T$; zmbT4|jKRAKl^EzH;-pRHrTpDejRFk4zkaW+l?EnY*& zT!|pia}qYLAu+9}vu-h=AS<(4P!xk3e47#&5meh_EWN(1v| zn41!h82EKiA?xiH-b07SZS$F8`J~2g?tXxx_>V1i^8?Wu7*iAycf<|cR?#z*tcX3c zSMPYX)8xY5J%nE@*gebG*OXZi00*YaJEI2Pp5)3BNU3T_ zDQ6Aiq;_B_VPAuc2$SygpbRVB9LuyYgWrc8F=^9~Z}n}^hGW#+!R>o-Dr#0(pl*Yf zFrWQl_Ar5>`?X28>H>v!OW4A}$`O$ELpxLpng=vim&^zeQ_t%B+nN^)-Pb7ui`Uo* zWtsc<`+uxtN(5_%upJ%K>}e+UJ$aAbmL4K947vt0Etmi1$Uahgs-Uto^`&l^AS`1^ zGRR~~lcQpctk0apEkpwZhQNBwKH4TIxmtRYEb1;JZJ5P>?WM#a))prk6D=5V@~#| zGVBUaP*$OeC~yF$fHJp$dKOkzij{BFSrhw?N6g+hE+h!M*-J8(r#|5a_y2z9F4thd z`kX6YV;=Mb04{g;IIuv&0Ixk%@`d!^iEbUGjjV~EM3$#t-MKS zIODv+M@|C8pzq#EBmnB|)2G4p2;W~B^{6!N^PuUPp152M;LtY$F%PcxnqH$9F+Y-? z`U(3XhCU##&jja*F=op1CT(<`p6IDBh2P}U3-!j$DXy?6YPlB8z zJf*e6#(m{1oZp)gaL8%gDNz)kt)c4#?@ly@)VHtb$8lbz;EaRmiKo%ZR?w=M1|YNdJ|hV%hNQtaW8)B|CSg( z`qAK#I4W&5A5%rgPu zTFa4`+MuTR^YH%qgROmqGX9sQ9NKjrQ838C=h!guwD+Py_`_dY>+~W;?yQkpPR$Ew z8ydJTF2+U2T%~5z)gSLv**;F8$GX_Iy=7}|X*)QUYkpqi>zQa(dRs=#Xn*6fmE0P71YG^6^W$Lb4nB;|47^b5&Xl6d2T;(9MA-6`|mZ z0)g;^F7^A7HKZbjWm%s)uiGZR>H}5y*2=I+bV(J-R+1b?jdp59W@K>6gOflRk?(5D z_b_o>ZV|ibAns=&E7x!D#C<<;&k&swAYa@lwRh54Zqviv-Fe$*?RS8eN{^Ls8Q^QE z2cF+mp#`hi+Rr9dea)dK(|W?yL@^m9wVqVsv}&1!blp?MmoNjJMXKeN(@t(lc*HZ2 zR9uXOU{EY?Tuhmw<`-J{M1=@43!8hw>+nqs+As^}td&P@=?YR9+N8HbW#ee3cBz@| z)i+D0^0C#?x#x`%TVJHMm*R}lw7g8;K#PHlob%|=ClPOhXJw16c#5h^U3pt1U?l4! z>rNssk=yP<(@DB*KC6h`=o^Xc+~^$TP?g^=e&6?U|9EKhCEy;m|BI%-4Wn{i96bYZ zk1h$c3aV>2tr`p>+?1e? zLXMu|msr#{%*`S*NmG7ub$sq*7Ei?w5l6Q$9FtdC%Ua}L_v2fsMp+;iz}aEU>nxf8 zcaRMnqmf5z8X`vqvHfp7*VYu6*S;io+ihw_Q`dN%{*iO;BUQCMsq%^zIo*`F9FA0H zzKt9EVL#R>2uFLrHN=!A+StS;0tOpQDNr_SXD11Y`0|#hE0eh(l*?P8U&xZ#`u3(M z*g`_yjkfN|CKBYUrh6lbZ_9NLOAPf^ zdDKl={9baf0DCxB!(w_qE0VyQ$H#xfs&f2xe6Ho>gE3nr86x6i^KW(J;d&_g0cTRb z7E*hpvIS$c%L*cL=nrc5vR51ZlPNv3uYe=km)>~?v%gM!;C1oq z6R8cai=KVz39Z37-5fXVPF4%lhjC^u34z|&L1es2ImFtPNmMgsXdGsC9ukdirbJ~6 zffyU3s$}bV1fw8A?=#E-nbufr_9Sh1fhmDA(Q|V6EE%KUD0nQL1}5#uugD9mRP2em zjUHYa5{uF-4s5Y`sz87*^JB?e`F1XWZ8Fj~wl*h5*OF4CCCEG;C>E)~G%9rpuhuov z?hCxt4gtRZx_bRvrl>}B)-%hB99R}Dcwo#DlA{}pC#~f?v(B6`&!}gtnXko~7z$3i z%oN3~Q*ixTnR30%Nj2LjQ&oJ5PJZz5x3x|=PETH6q<-=H=r0pF)X}oqlKlefsLRap zAE#I5D4{4`1A<3^PpuAuHVNw##pqBA{bd!S>MBPJK*XOJ!XP^X1W8j|TsGLj7~ zddCsv0+L^U5JA~CPdGB|oSzzsq$=ic*_@8Q1?rHcQTcgqomOzvO}G5h<6ObR!V9pT zbG=5q;xOQi7l6UTfpf2!O#wfkI_35&2JJXCjW8zHe3zYC@YzBM_sRUh+ZOz0fe=m8 z!8 zbOG_A=75P3sq~&`8}AV1FEpy-QadRknSHlo^~FfqkDoLeavU0UvfUq2vao=BR9}EQ zQ7*_VC%h;vo?_wnai=13rz~ZBoqlarows|q?n3{iQO-{#mFjWw{24n|ND3U%QC$P4 zI@7q&Cyh|4tj=Pu$&k;_t@td`a3DB9`?>XbybV`*t3FSCfqv}TqD#fT3Qnp0mI}VH z)Z$ox+m{8pyU@VTkDpuBMi?AXeRzWJw)o_|ByvWouy9*#T4!n8_64}JTPRbErJAKm z3yj3dFsP{X$XI%v%OF_mtY;C}geD_gors}BnV~=O1&p5=g$60(Tf&gTH!K469U5LJ zsv0~3?=?o>edMG1!`~cw=RX*Q_346KCw*f^6~!~Pxk#r*1ea*kzW{- z=TdzlN;GNlvCtG3S3NxSykAKrcsix8CuWz2l<^r=1yQf*O1%xGZ*AzCynbg;c`u>V z{$;KFz^mo0I{TSKpngE3>xa#9bj77f=7hp~ueccfR`Zn&zL}snG=8PZi*u% ztaoo}(mQK!vNUD>S;F&WZKPd0*~&xSCaCog7cWO_e(diVLH%(nV|qzX#N^w@2k&!+ zaj=ZZRaBBgMHuFe9tO3J^xC1NIN*gaeL?DXI?MIoTrV3i*zCrKQ?FcW1P-PZJBpO&wk*KEMw(An@7fB*Oc`;8XkQ8@x0-w zZ%r`LU~0!yPfs~cSH&i~1jT&Z8m@ZSc~Ah5=n>`ltn7KN9(h$E%X}4-^R@RDJEiB} zWVad5LWjT9H?LoC(dTr_*TL^%5zkh>U>r@+2U$xoybSsG(0#j zqfD2)Rq!}RJ81}rxCYSkgxQTX13h=T?zr%~%qmofRN2$%2-Xmv{i3%d8mUC3kzVpY z7W?39@}<1k1^?Pkgpks7qQTLC!;#?reOdp{`n0pJitwVfgsy ze9MO;ZUJ0VpwIlD2k=%|mz$8vEP$yLG3ng8?F$yQ&a^)~iIhh38DH-VoZn7%(_bUF z-*6)PS?^-2H=@0dKC8&Iw>9Pl>L;`bworCJW&)_^C{E64NA6-bST(zvuA@)pyiGKA zLGR*-xkDQ5a}KgrhjHe@Aq>y!&ik8e_t&^ruzBN&FMBPLV^0gDM6lX!1nzyWKBB$Q zyO>lsM-?LG8p5qF<7uVm?24XF(OfJiBWLW6MO4n8%Ejn&Rnh zZD9U>CKBn_EZ}+lR$z@x)7#d3`^PEU=@pM_y%$&OB#^DKzzojsvmbScoeZ1Ad*md< zfGo04^?E0D{K!HQ0rR_ox({+IxxMl`zC0Z(>&60~EH5eNyOhA=eInRjZc~ypPP(j; zs{%;BF|6;5pwun)kFy_ZZF!UEVGI#l z5!fiefT+>dn474dLUpcdZSBCRbQ0+2LV#MZ8+&!~^v|bu)aaPeJ8Jl3bup26=kqyHxbEIp-2;N_APL8)8^fe zgP18^rIFdw@14mF`m?*XnuoLE*i1JGnkPCOzSIyR`@1vXL+rZzP+6z;aZh^nV&qXUDm8R4T}55$Gf1W2c;U# ztDaxIcG+IRU+jIyXRz=qR2ctyOB$| z^jOdquNVhoOG5_{xdJ=i6?edqihrV4#NvI4)f#Tt-ISG(6>wO=d%VQyhvI2%4+9u0g~ z4hQQx^vWn)@Z>R4WL`wTPC)fVP3pt0@`1O4!bBd`9#wcJ$HI@F*D3H z*E~PI9EsIs{@5c@dnM{1P20R@K@A)}fCo7IW50%7p`Bp%kQ)Iz+SuZ#=gN#}FlgYt z@l0YuwG+Cy84HA-0^ZV5B^0MkUN{okyF5P7omWgD4S9?|8;Q>HTVQ+6w_@4fiuU3vlzc_z(&v^8W&P|UmI)JTh_Ai`*o~0_b zBO_B9oJk`GmR?jS1K2NtlITG6=y4m~Gp_s{t!R;3?1QR5#fiy|Cu%e9m$@|Qf;mtSWX!*qQE)e>ma0Glj&|;(GR&?}3aj<}Y z&8}F#=8{vxphk+RYbobbyp#e4d$!2mXgk-_g-D%6KGC?vg+;Ca19Gr#Uafjl!!FZK zK)TGAgo%t21GfPVo%y<5hK!};2}W@G;&Rs75VuHF!(~S*5sNn{P`PsVmiT@ zfE>mmrzi~KGVdAcwFe1YHXeF$GQ0vII5JwKJ3l$q&=@nz(b&Kzw{cpWI`4sJ4rUy1 zNMSWdGv_{2NG$$5`P{DTet_=w94*@js-)ncx)YgxO@b9?dTFVBxrs@3BN&OwIYk+= zE6!npm9c{}Fswm^)QjZ4+Z*m#b5EoV+(c*Xh{4aM$s%s6fymfr@rS_tRG}tv<^%+Z zb@4yg@PW*0?2Zo#E|^0HhCg&H8SZD#KRiF~AX8?DcB(&-^#_w`GeRb?syQIzOL_t7 zKU9$t_moJ?0zwHzS1xSNtvXkBkg8oB(F{C#oa+_HykxMjgR#)y|0$%4$DsHnKUoKl zTn;2nqE=t(z@@E}n1{k2sJQe+}4i?qq%lqb7|Gr+?y)zn7N zEo$hZ$ET-hrk6ucSuF zU)fy@Q$mRkA`9qw_ZDID#s(uOV&_QiSiPWdl;9lK8&^? z7MN*G6;9fEA)qyHDXP6FS6}}8p;9I|(ZWtz->1{V*f$5!1Qf79SP;^nNz7%RSk7qZ za@Io-Y{lIKLt5YCy+`NGYJ~kV2v}&)q;6>vKYLFnj?s1<_7D)>c@hjw*k2TX1F}=f zE<29d;24Q7YQy+^g(;L-f)QZw(>u*#(`ZCCm&zs;*~R~z_|s&h(g6btqK9!f?Lyyp3*T`f?C9jGH)u2 zBWu`=DfK$Zrw`2TpPrWU^}Q&+wSnx@FGlxtzA>3|EDhcfun{ROF7`WgxkW02OdbIS zljOH2Gz#!1w#XN*MTmy}uT@-eVGs>XV5q%;0$st?jgOdq+|2eeL-FS)<4QSIP1sU?fn!rKOq>t01E$q6~d_Az>UDm1(l&wn{u2^RtA2Z6Jb zfMf@n*&|JZqBe2Y(c;C;!Gj$6yxpa-t7t#zT5p~Jh!rrb6MV^|a-6^vD+XWL{j?Wq4kvgK|-i8Y&On7EY2=apM6L$SW>oEJJ`;Jw zsZxJn^LhF#SHs7S14R6$zyP0})#oR&!$fxKfROJwM_ZF*nzW5tP2v>p@-uHjeV(2n zuUSu~({rL_K1c4*@eLCgOaOw{oBngzv~TBe;UXdo4FHd=V&$a)Wojp|3bpnjEeQI~ zy#NNYqQ`$QF3zQ}rF)3B-AGQ5CnqOcqjxm8CWH)0y~JB;Tnaya6q%e^+lTd~8OzXWptsMWFtfy1^`A^dqe zsS|yDhWOS|@PrU(4k1AJLb-Y6;(n$%3CNHVkSJYT#4N9#sw_^fi(fiy!ABc1`3VbR~@^=v04N=qzNY3>;;)!C*R3u|LJ~Aga-V>W$D1E9=RK&r@L^heHl5h zGB`li-q~ojrmO-&*0Oi{Roe5vtn+LvgT(A3p-k3HXlv6q zoE&Mu$}lmDck+?RLbDDW$w6)|HCh>p$d!w;2>c!)!O47Bc4_~`ZGm|GGtaD;oeS8#tPf ztbn;njSLmpcYCwUWIRfXw2HyElQ{-uIqF<6zXaR#iwt-$!Dkbh9PA(5y z2}D1GBO@>9@joTBd4pLL^p#<}>wl!oGR>C7KHy5&S=qiJ+P}VfW2{(1C6Dl$j1ric zYa+j?^1jc^{Zc=1!yg=|LmrVM4d7`2MD`T&EuRLx>m>&rY&g)?1D+Q6aR6B~FlFA} z0%uRa9Vm`|f@k2poJR-^4RIAx{W?wFEL9mmd|@Ef95j4#i?Px}-hxL3ydx;YY;Ct3 zhi)DzQHux2pET*2d^!TiYiAe)WoV9Ykv%22 z#)6y}47otx0?C0oml?J?0KSXBR3j$ceqB*_!HkhL0v!0Gv0*X>tasNI!Y$+FOeJQZKKLY}&8R8DK{gCR z*Oh9BG&3$15aMxb0w;4)Nof~Do@S>;vi|wZBtQ%EY;MJLi9fjg6|9B!_g(nO&OfeH zPp$M9*GdEDRGuEP5H_4EH8L&pzwG$A$o5;CD|LApR7gf>)qXLk;lODDtbw8tpd=_z z+%JjJfbRJD!ylcUSlP-Ua5tA}UXvzsAt>y6*IY37-4YrnWj68!D=>TJ=#y-jNjc*o zB>f-(h3OYy&-3ba10Hl$p<4{ZzK-Rct2Z1DsRD8DMSe?~vs#tT?Uisee%50(K{?0; z!gas`LD2{XE#Mjgvd;MGb7lu~zL8|{ON%+O*#kGo0zQT5bK$1fXcwry-U5#)8{g+c zQRVlW*+5bPD}Eax0d5EtABcnsmOzkL`#Sz}7t-<@Z@CQ<7Tn1I9>BVQN4^~&GZ1X0 zKY@DGNe48kU`(xbB?D$hfMj8R>>aELFy0s$LA0G zD>@kgLoH_EVtQ0_r(jPi2~5g``wC0&W_E zR{o(&+$Ea%d}Lw6S1R-KZ-IhEfBUjE4mmO^tS+q1jp6}1oA^|kegMj3?wp`Dwhs~w z2}YkF{{}J_INRi_+E(@2EBTVi3>Ja1%#jM*vgPS%#xp7I=!}rwBD)vtNy5rSN9!#@ z2|szwMjzGmlT!wx?F!Jo!9f9p^JNxsKkVW@X0n@s-+%5tnor^V%Mi zNHj)5MhO97&C$)k)T%1%>z|Nt&iG~aM@>;`z;ynOMPN8ExPf|oh6`e8b=KnXQ!`wn zMA=O3pth|0B5>~iX^OwmBPQ{X%Ml-le(p+Ov^_Jbh&@g0{dL%0-}*sukkV_sb8Xou z7tGC9T^v{7i~8TN|LNc_941_;a?lzx9RY4e{-UQseTyh%hyg`+Jg9>e5;a@pv zk}|J+h7TXyZhHd_N~C(F-r@OtaANgxRSUlB4nBO-VuswI-&o|x4HZP6eOzrsP=e%i z5_58GzTbb}5bcC^!=4v1Jiy0>RbeQ<}urt&xYgf`oJ zUt>|=#FeX-{?b0fCy+Cp^9xJj(kGwb9L=aA_*es_o#$wufVc6c0+5Aoy9s}LX`ka0 z5_;SMP6WZhH~;+!Hq>(0;Kf=4%yHv5Ki3Lm@LvLEE z8-&7Cev^Iz6q$Jr=!YAHwnl;FsiR=@O7O=L59p`x6TTAo-wy-+{gATV#5~VN+Nz|w z{}&O@D6iFwqxI%R@8#*_PsCLd;BBDNBTW3{W#`ipO?98ImZE*G+9Kfp$>^YG;PFL;Dh zHXM`+N3HhQdTzNWdwtdM!@IOGL&M7rhtUDprHmQ>R`1`JgJrlK{^{TMfM5GbO^vpD zgpa&|YXA44=>Hbt_Gd@BpHHslAT~T zg7prp1~{En(Y&31OE3MG^z={WpVQ&qkt0N}>KONHE3Z4r0!G_fqI%1e=T?b8_C;0k z*8lq*vG>c7SHm!0$J53vD-)(-nW0aeOxm#u z!QXg%B>p|B_scO?!-5{fDOJ{Ied@M3mG;wb9J&@&_5PjBg!iN8|9ed^yrz+Dru%be zcYI(~hfB7T?(AHiB-i6_w}D!F%k~iZN4bW&ihO_o?5`Q%M@@|5;MOy~l!NkS?_N^@mjN z@qa(vl|$bM7;S~-+Ios?w_YyK{&^>%t;+kqKlBm&uGAtyh8ov^JM2=D$gYq)oBux8 zS_-3$+Rj38@#nYJMfa%Z67?aMJ;lD1tpJ&|9_xIy_#yDe~Gr0DZzgTO{x#ld?0A&x52P76RQoll-KmdK$ zIVup{A!49F2A;)`PrLc!i_7!5*Zv@4)d1ZVsGPt$n8|p91ujKvJ4^;4eWWC4IsFxo zG~yV56`x349#TQr%hi}+g9R%EkR1k%q@kq-^Fr&xN&l-8V3Vl=>P4r8KrZOxf(Wcq z$L9CU86{<_-wS^W(2!aJbOz{1U@i4H%)cV`E0jC%2oQ-v4AR%v_p4SF>&P7A+nO}~ zJ*(e}Q6(!#|D#gorO24aNuL!n$Y1$_ZVM=l_x2(pzf<;t+CZ#=E&}?4 zlNt4jvr2B0J84epq%+|5#XL?mf5E%}6u2^dgM2km76g5XE|B&Gq3&_prukf0z{EhE z;R{$$$et?8LJy2V{+r)vSJ&0A1TJnm^WU1a2Op3td)Y49q?wL>U?9q6`%#M`l)5kRp<212XGtKOQ#$N_;25 zxhsN~_bo3}sBp9@gNOBkZvbDhoT!*6^I;9k(V!fdb{R(aw$8 zGkJ}|az2Rw+eR`de&XZfBkmu;k??iT4<-n^AJ;dWFp%qmMn7t4kQ~h}dKsih?dUUtx z%t4^vR(+?YVpB7T`;YHWw4~ce)TIA?mi`Td3Hd0a#5rO6500o_V}u4qh+BcLVGwf( zOL=(%=fs28SqmE^HoAM}YDh_mhx5%>5sDWl-kyUyPVA%?BZMpd;F5vya}x?1vF$yh zQ{%cGC5gIwFYZ`%ha~EbJA7GO-sv5fFmd4M)XJ7F)q1L|3=TD$v*1)oO6QXTLaEZS zvWQ}4p~7@e{8_IPtTXDMFoyw_?ZZl{5aFY<>*9VlB3z?B@LLW6k*WFpdFr|V=s5)4 zo@-%^W;Rait#=kD(GUA27{0nz62xS({hXwybg(sIZk*rW$2nX;tGtf;EFP)j%qAmhWU`K1(B5Izg+b3@EO>7c_ru~ zsQ+O1riixfS|jCu^8RBP$NqC+M$vi4ehb4EWy~Qc2p-RwtaPuh&O889I$qwuc(t|i}Fnk+eesB%vj*C0aK>&|+WYm@| zpVG)y5l`*_*<)o(5X%D}g{^uRMcVL*NQ2?Y1Ji0AsB&*?@D|3S?pC!sEZw^%;vzv$ zT_p<&DEj)3-T2{XJU}yOV%tA78?oX0S+KsfZSJ_rGP93KFmF%RVrOqJbic0=CBved zqQx$6YWe(N{I*waC9SAb-D4IsxE2@;6-cC9oj6pFg082O7Yto}^Aj=WuL)@W; zZ&yV4I*V5lC&ypjsQVBZAlisYI>W2;>visZC|KB+YI$Bm)&l-3luWhwkkZ215=u%Y zChT>HX_&G8X--Ptfby6diV)h}yk6h4{{BpBL3A*Bcl!wCag_e8t*)iN_10(VT465% z&EE{TAc)!Y$Bw%0;`3Ams7)m?bitIA2rR}lSumE|xMX6G4+A(@$IvGBL9P;G4x#G&!g_Z> zXyL3yKz(>VbNRvfiUX^q?@!{g5<}k2*p+gPoNUWF?c{lr+>}v;d6AxCyjRs&v=pE_ z25BfyYk>;A(T<~A|L+wWm*y3NdLteklg>x4h(@}f>ltr}389&J&oVUAXv1s+RUis9);>`G~P;Bomox3%< zA$@sy%Cp$<>KBTDtpv@%yi`bL)?SD0ht%efp*D zhD53HSAONzW;3~(gV@cW{vw%NQ#Ou-84SIlkb~{pgM^?B>}dR-x!Pt`=1*%HzFzUq zZ1?zI#-z2W-hep{r4h+7zFz-3gnVmd6hxGU(D83Mg9*@ig9)~Mn^g^HUAI^-A@0?k+`&V!ILmXw6(G}KtG%33}h7j!QY;rdtab(GgtbNb1B!M4neDi zPG9CVYji;8w_!2Mn6$-uWUXt{OgA~A>v6oTtbNQVNfHsW_ABG(4Bn;Gmi1OudE$S+ zy-dZUe&PqGC6>H2@WWrOO-0#%#ED2JtYg>mTJ6{7DS~zJ^LY{$E(&0GtH8+ma7Ia4 zymv&PvJIL1T81`$4?q|{X`wa80{F#01`bRsnn@!_dP=9pFCrP|jFkMpeF2fF4w3$; zA<-WzzjeyVl?T2I{p>Ou&9@^`_DDc=a^6$lgP8nortVO0NXNI4r(& zg%Z46wLEK5Ir;(`Z(|oM?Rxv>UB$C>s%P}RU?otdN37j2w3Vi(kTSxIm~vlV^))G_ zkHM@qXG(OmbEq!4d+@37;N$O6R_sJMZ4+GFo%Tctp}5+&&^)Li?gs>UzL6bRHAyK% z={`sD91gg6s_NQu=5u5$x@NymuD*>eUPtj3=E!;p8GdbSOkWCY2%*=@`H-HJiGB1rx^54u5nfVdvB7$%E*C)S; zpE_SiA`gg++LjloKp+G7(kZ`f*V1RAu;f! zd-hFwW?N(HmiUP6o@hvO>Gfu5fXyVJ2RDEO2CD%K)>9E*5k~Idbi(wTi4T5~xr+6f zlZI8jH*!dRm6-{CnL<=@p6pN-`v}6bD?8^`C*IpiBV%F1)|^T`<*8OTPS9h}SnNB4AhpRGnU_6WJKh3Z%EqxfOn zw?9#|D{%FD!SKYwB5Sb*nQQMMuK51_d)M&ryWEB06Nflh|C^`L=+B;aZ{KcRPmv&t z)?k1#H6%?vweae$LP^w=3z%e6bx(Y}-CV|H%(R}HWFGFWiBq}q0Hgvkg_5;k`iX>J z9iTgh=nvk+|Ik5xxN@g`ef68vzoXSj${Sz|yd&2u3T%jVV=NV(4k!-nSC z>v+4h0Ls;$ImD;YEiS_3Y{m|BrtLyyMj z*?YN;G=PN}Fr?mJ`B(If3=}1R0jjJF(NG)9^sV@|$u1HIhSyvRLo61*Qb**ijn&*c zUQlh=ZN6dW@cS`%4nntE!JlIIqITE$bo^SUe#|)_C5$M^cX1sY{JM2BeV1|KT(rnz zoX)ZuQWW@;-<@>*SpK%g}aA%g(>I)J`{l0m~-U5ybYQj~q) z=fZ&yY|glYmfCr#RCD%9wLdsStgCx@3DeEBW{^IDNILQcFi;)OCwMl-hXaof&U0+| z5PMB>x+Vxl(E!`Z{)@|Ra+biLG{!Ey?XS$S9^HR_IwZK?30`~Y&DlV7CnTIz9dvvV zBON(8A`nwOmhiu7P#ZsR0vyj5%%smhOHv9XjMupk$|$auaSyYQXe*L0uYI-p@=Ka@ zf+WF(x*3h(Zr1gD8Pv;(c&Y*5hM0KR@@bu1Q zTprA+V)kk?$8gtFtRF%#>pOAer4&_ zG^KooNSTQYT)C=$C&Fj0*L_eX7KaiT_>j+EkF3%AI!^io&Tm>|6#=?cAhCH0Ljr*K zDp!T9SiAQ}q`Mf`#dw!ta;o&8WJaaT*3MFoW<4XC&Lg>oTemt5Kk~$+fte68*8z9~ zK+;U<8hFvcULXKmbjU+KCMF_&6^xPKLp5Z*XrYAojDprvN=C+85aa~r!#&f>)FT|s ztzcxv23A}G@o9i!X7zo|Zg8S~*!u}KA21OG9ddBRxxdi^NlGjLdkNs&2I(0n@PR~w zMvg*OAKY{;8=DMjE7g7abfc4viH)6GUT&D#=sWoa^_nP<4MH9fULUmd3oUeT6`95q zP4my#@~QYeMWMcJ!j07Nz)F4|0=A?V|DapP9R%{NVnLZdcLAUyKnR19!65guzuaZJ z?o5>|s3Sodu;)S5*O8(pU+4i80pO5<9xb^d6fLu<;Y@R79r4a1&Cr4TE3Rqwn6dWa1JkV#HpVjy|rP;(eETr>6{1gmyop}6=!AGYw z4V`>5-F&sr8acWAfYFd;ji|)#{C+VR^Sf1;LNOS3)Khe3>`F8x3v6VOp92lgo5eJM zCrjyETI?@MnAKb2up1`->9Ptamv(Zh5_*@(Wd1E3`-9$n4}wY;lIwgtYOuM3A%+g> zb?rEkyxGamn-&a=zPzzr8yx;VnE@)Rpd1}j%hkT0499nO zbH|Re#Kvpq#nF!R8rXs4!9wNz|yjKFqBKc6QT4phUG80#k{3_R@s z7BY3<)~r~1RsX1w$(^^uWaw%u1M}z4!pPM)T<^je_~^C$ehZW0koS+}RsEiB(Z5l( z*a~}~f&Yb2f~a;AY}+VslmCR;Y;W(d3)(1=cv(dT;$Nr3u&+FqeQ$QDkbA~!^IeDP zoi1c_UZ#FetxO@+%avQcEFiKT9+u4yoGfG`MvC$I5B?YXu_V7jNzqhf1q=_Ut6C7= zl7(^$vdS_=*XH}2E;U>-nkWo-9K}q>px{I2f8akwqQu-zhXD{3^C2+cmH-PKPpH_P z{`exC^qI2q_ToUTRq^klX>g>@M!p)HxUT4*|ACvqaeQMgDHf72nL$(tMh9>XdnD( z+F{x+1ph@~kZ0}J1Ja%}-M4ATsF9iq@`HX-xcEP<1&FOmn8^NYjG>no2J_|gZ&!zW z;X@k@ZD(!U{xr9sSN+dx(}q($ib=CO+QM$+hk07IvvYAN=_(K^bAETadl<(-Y$TXYwOT(>((;TGJQWexuAJf$T>p@`|V-5zDzfdaS zvS~1TMiv<4eE;)O!N~yeF0}|%VpRS=KkMNNp|CFT3G+UjvG-JO z(ypDd&w-Yg)4(2nh>W3f0G4n=~psKF42g3Rg501qt+=F{TY zv-DojOanhZP@6}hedN!72gS`xfrPgw)*A23jMexFZTA}vyRTHniFlU%pRx02%k369 zITYgT!ATaXf57!H0>^ifDZd{h-JVwqk0~W9Z~W+FI}|RRNTcz=yiqlvo>m z@9y6tw`t(kVdny^V(?@FPwKpAHkPEn5U%CR>wGNl8z94 zoB8)ZKJpR3Az+sTeGt0b4sambO|AGDaD(tOR<~&R&vD8C?wo<+y1V5My-s4f?C30E zW`{qc1zo>-*kA6z<7GMK^?hq{F9%jGGd>>P|8wVE}fxr6^x@FDgw(NAkdd;LDxU%>%zVU z>}sgHZES#eZV)(kYq6a6%Yg#G3*yw{L}H3X>8V164B&UEd30NiEjj#Nn zWM2TWOz+KTM|)Gty+J_W;Avyhnz^sTi}0EB05k#)R%8CqZW0|E3oZf>m(2&~LQ)1x z^5@dhTTmu|4Ta#2fgvbqgN~IFBb4{yEm6nIRxQ6ivgMO@cIE}=XlQwAoOJztFRXqK zX5A@DI$PHWJq2ic^# zxg2C_xU5=~Bkb#Gbh$E=9&`*}g$W51R-nOwYe|9F;U$o8gogrX=;oa}^ogD4KQW9s zW$spxThFXJDk%HMszgZ9p~xb+bm^;A?5Wt89`p+X zI|rWpOlIbo-GfmHYjjX+MiS$T40R>=eSvtsk-^7S=kPQ$AQ5tcMJNODk0mFm^H9-3 z&{%RM=t21FSORkiN|Fn|ObG=qyEqPNYH8&QwxtS+;jgTA|DLAS<+v5wg0j!7u0elz zC;O+F6#v5jd32nQ{venp^^H+KD4gjmvVuGvEMcHy0T7KdkjW%pqt^**c!UmP+VLL{ zysB4%m6NJ_&ZueZP*B~RAtZNO*3P`_QIZj~$~BP?Fyn!Y>t9j%N&C{zKO7R6TS4iJ zO;E5Ej0GX926ACnUN^D*#E$9WJdthtF zQgh_~J?ozV2|9kni%I<2K=i5;yPH z<2rZF3yWwGMrQb5r>EZ#diY`7|HiF}48~I5$28ihO8H%m@nFpdYbnS^=BbHj!8H8^ zDA-x3?gOL>I1>z5NLc}G;nf~#YaIFAu6#gqp+X>YdoYr6C?H0kz4FCGIZ@jhByYE( zn<6^M)p-6kzDRSCM@DTr!d?dgM!>yZ7okskUY&P?K(KUjkfCaKLvjLHnTSvmgYJ(cMmFUMjMwH7$JKFocJ34rF%DX!EXhahag=Kb5TtGAIh$|mGyPN zbJmlfpL}+E+#$~08n6*!DZ0R?J%>v~X|9_ud{dPoJ-VM@9sg>iH!N&P+B6CPat#0> z;zQVMbX~?j?Y*C;-`Npwcbt{7()eu?GD2;CEau6_G#NVG$+u)54r?npDTO{j`mT_x z2J}yOSvM&u>!$4cP9WlW^FZ=kBfnadc!tsh?Ap?Daw!a?5A^Aab#70gAAa@A+L5s3 z$LeO}TLGANxaCa02W8T@7?uxAm*+5P>zaI-=9*=pp9+?rn?8T4W*GHOB%jRPd;rKEx{)Lx3uXoA?}gEZZh zT`o64A&=P(S&`#qsr>Reud4k zt2J&Pw$sK-4XUZL40kAcMic&|m+R20O373gv{V2evR&*)X5Om1l69p(i}(Ia`CjS{ zc)7ZHk*KRQWby{a4||AnsxA{mG%G^^5KvMGJmBJRj_=7;p&B_2px6vX+TfUWop5#- z^^(kcH`d+tWGViMZ^uTit$B>7YHZ+8o|XQmp~fEy(P{;vG$1O@07W#Qgw7nT*pLC* z3ez7x3V^|BDfRWNl{Pqu2a7t^!v+~W$#JrG918t-Cfx#O<9h8RK3B(jEzHF3}OA@c77849us!z>}^Yaj0m2)8vz zGSe~ADyl;n;`-aaNH$V#(a zDbhzYvq5jk#E)~~@BKOvszOzIqOC1TvmmxsRzPEznXUyW0Pj2gfTYwjTAB_14hXJb zqlT~$;*$RExpD0B++@nie9h!Y#maMeVgb$J*XIajWv8MwndORWgVB!k$`XOiH?zid#kQ zUoBnMp2WBmKpQb&8qWikvR`j=qAV<1$2^ORHwMB8dPqGD&rvghY&$kEjZtXZ!&eIf z)uB(NrRu)r5UxC4H+m=q`9}CNy&=+Kt=m)89ajfkbDua;!>(Am6hk_gA`8_uunKid zA6;rIvVyHxT}|x~c5Hb_pk%6LmVf70KQsvq*8DDZ9NRF3^anDf0R5k2Lr(AsV1NLt zo^}>)$I*5pvU}ekR#utB8cYZTb8W;G^&z5!{CeMDNC8UpP!eQ}L`KrDtmI9niZx-p zvRr!@9>BOUjJX88D2;6)`&_Jslxv?xYMb zUIshvEY^Z0@SK1LfR9vp{%mg5=eKFAvAoU`F-O-}hDd&JnZpeuoPuyG`e^Cv!S!FQ zf)`jq0HL<^4Cj@W3q)(?zT@axN`;WRoh2{md;CCA`|vO&)Jgap`~~wY#((n`W69iW zhi%n4t5#9JpZE$u?0XvaozhoMF)65~(xF@R)k%xBZy2wP?FX<8@YF?+*!vff#7Nc~ z0Sm(;ty&?|S6_`l24`+*(|*#p9Vh_MhXOZm>29&uJ!?1M^84#Z_zifWN{kn)wTp{@ zgB7~~Gz_yrqYZ9J-d2jW?r5%BdA~R_IFosC^NLvS?peUMpo;*u3ecu6vV|3nQOi2a0 ztGQVSmczINSUglH%Fx?Hmr9l&-AFUbJwAejuwUbs`qWSvl&<_m&j#k&_F>pO;}>ok zd@Vrj-Z|NN?sd33F)ziV%jU9f`{Cj7Iz!c-_nm2040}zJOM+xhewW>mu?$eD42O8Y zVGxYsbpIqf?0u@wLEqdg*4!25(KzqzA7u>9C*VBkGR)Zh6>mjAr8nP-Pgrs6j<-;2 z(&SuZ1l(}RN(LXarKKEp%!I9_G?J=I@=`4eBwK6H$ihYnS*S*i3UcoHuW;^<4qWQH z!>zH(m;^`}fMuhQ(KWQ3l?Gg|rdbu#E2*6*rWq&p%- zO<2I=bhWIt@|j}~5`)&VyjO)1cjISv>sEvsZM>G*9=b6H^i?}oIPv;)J2qlt!|>5wVSm zqcRndlNFYlrJmi`6*;>_rQGm11S65~o$_ou2_ znpJ_C6sT->7?!RT(6Nl(Fn8go((i}-;cznSB|-)0i~NPE{f=A!S%h@mMhU$RB5H*W zwS4oAOam0Alr{Qw>q*>27w_OEGeA?9DieyV+_Y<2%!YF}hp4Y)GKgHe8%sn5Tw7^6 zzvOC6(p1PUxpIcaJDHii`O4nI#esVr=0bsyZ0n2p#1D4|&M9uB28j9PGHGET zFA6b>(KKo52vv!d8&RLs#Z)yAxQFzO+2vaNE13#498u+e$nAOthj))@>pwJeN+^2F z)bKxTKxKikqUE%KG0VWMiIwA7$>Z^`yor+|BJ_H0abZ%z!b21P#+>fnrbuA4-Or&4fi@g+wkOgjrndmiZ7nkJ3h)Pg6Zb4iz{cb z4oNC-7Y{~99=CtJnP`=*Ku*XvYrQqLV-9M5LG=?+uGg4?M7!`-N_zh2dVg&=u;IA5 z_+8aaNM}zFj7Q-*XRuUnzS?|U+vD!V6UQ9>eh!3!C%&w_7ga6jGI5=?hJNIzN(^vb z{gg8xo@Atu8^^skPq~eMpJ~WEK-tkwLaaQH;_mV)W|6s+`S9o z?ZSIwJ0D2zpdbc|05JU4w=FcHbfXCPxFhL_ZDHq;mzABKTUv$ffzgp<;qq6~Sy516&AoUm$>ALm=8si&my_v)WXo-F^uM%&89d`RXA6R$UJH#JjqZmH7jYo&%UGGJP*@4tKXb zl3OLI+NgJ0oXfvC`&GVgYV6u-^)gj(r6(y%<2pBo^u=Be*N{{>WR6QHB6VZjs`{-(h>zR=-;D zxzN@t1}Z|O%T2I$ads0k;f(nhYI@npNptf%v-d#^?zO6R%xzM^a^@FNdEuq@A!^Z8 zP}u>#q(SGaM52mHKW&0-(Nq+7&j2}k3HRFSJaH=>&?a9GrG|sp3%mvnMPs-8Hp5QV zqzqh{$2cs3zh2BTs50vaL{H6TP=bC4lvT@X@gSZ`9!7Nv=UK{*m>`+4+a?1jI(zTT zQF~3^J^$qHg8KmU^&kKCe%K;|=G_Q(-pX}thN0MI@V4r3`T}*8Ul=AUHn*sup?Gx1 z=-tVo{|!i(r-{5#NCGihHqBB&62E7zvp~cet?V-Wx}}$%Yx)LbeNcOIz8!RE!3g(Q z=G|F^xG8y#;HOc?dRsX0Lr z`|%F|@h4dmX~X>=9)|orY>;qU2)4XmM1Z>DpB`#KN#6VBC2@=L&0DvoAUg-+gS|@K zp?cw!#mtj#RDsp*vLC9ACCX)VNN~=2L+>LG(d~DrMWxW#Jj>~~WD%bWxV?@NFaayw z3Il(_Fb=*C_ZAeP_U5&t>a?CG@=IOUQYzyXTj`hee)-6|HyGzCBy(R(?XF!z^7weH z#GYIgCN^s)&qkrjc)(-oKoMr`?qVa(6&y+^JMCqyNPl3xRk0DE0zok)Rl9wo;{%V? z4q3|m1?SJ5EK$3?Rs79B?VyD&ToCh3gkii7E*fZ9usEFyw!^-AwKXW^&23Clc=b=I+3XI;*;+u7pYAF{Hva5cWI z60pxev5U?!!>w9R5~13i2pM*g!2=52OQYnqNP8g`60~AH8-5#Sd$Z=pelGf&R(@ah`aV;$+VW%~LoK7VNm zSY)=2;d$#2spVB_pR&LRWZ7{ivo_X9-EzFNP%+hR$BV56MQyMD1TeIsguIp+{hYPT zt`o$-=GK}tG5E=Sb}XFu?j%2HREx(>4S&MJgz+Y|P(O(t+HWDsCd$f>HKQF0elva} zB-kHf9zn^36fg0vmZDEYj;P{4<>l+AfIgAMT=z` zs}IqXz$|qtU@!Cyj;kGi)ElMi1g!tkGWN)Z2u0W93C$b8b`;qg(SdkDDeG6v)`G4a zqvl;*jb%^ye?u}%tNI3bh+El66nE!P0=n+c3~8pHVpZMTvO})uG)qUadKkvp4D(80 z^j#WMOZB?E8 zAi_ua=kTuhH-?&fY{=u_$eI3W#f4ZD3@r*Zrncd5_fHw)#&(?_!y;HJZ-w@fYnG3v zo=+~x^Qtc6q1t^eBUP}rUvHkqK}&}AcW&OI7_C(EHDIy{t%>4Rjdu2-zq41|T@4!D zGZ1JYxoB)W`;&Zo-2iVO`A2_TOC^pYX6LnEFCJs${JIVgWPIPb%S-HSJ|=88s9YDU zEgDblW*!g?Ss-MVBj0i7dP=_mEToz#CD+}7dvr6w!>*o85TE3^C1Qi`F$t|I#m$7i zgn}~kOpUE^iEIMMTc;T-O|Cm&e7HJZ3;G4?b3~i#HX{5_yo>WN{rtuo+{f#&Hz;os zu6IxjHj$Vg*7MQ>X?ZtB|6)5ePU4>bS?f~9vgsM!R&*6-bK-IPbJ@;+OBM@Sp%Pm$ ztJ%F$^5akL0)C7it2b*s?q_@4&UfZQ_G)*dbTp-)UX0+WP+dLFJ3;ZDtQ-1SL{VGU zHO*0WQp)6e^EFMCqg7uNFvkLWcJJVhtRiEq$Dy$Bu!Ae-z5w0l6Kr1GAGu>U{931P z-X~sw+RX=RIV@vF#yok+vq&_Cd_B~uqXOtd&4ui=?y71X+>RG;3^HsCy|%4+IFh$C z0mTf>jlG3}@$MP4nxrzsDJB{!0kd)XF+8Iu1IX8Ow^=fExmW5?)Nsdh?!w7r)+AJR z3v5P3lDiw0tBNzzUbX+mQdArTp#!PZnI0PodUUA;I&JXlc z&cku^Q&8>01EmMlSoPV%W2|m7g0a`@dvX^&02q1PmRVINZ6=tuXW@?d)lI?OB{>2J zxrQG3RJTA}O=dlI%sNuyb~u@+-D}$qyf#>rrqPT5 z+?&3;&-CNcD*#`$={Qxt$P0a|nGjf{y1e?f+)cIi64T^CUM201lZ_SDaVc+GeyF5t ztM)^yLX?6s?mcJ&%%2MIWhRPO_^76|yFA&7ou%)b%ezc*rYtvQK_DZ$#-Knnr>H|; z8Mk67h+)OseFm<^6mc*Le0mW(RhwG<^Z#gm30EJ89tL#QiT4+$eLkB^(;t$jY08-W zPks-N0{rMha|tK_g~}y7h>c^lGvKINP6ENGRlpn8GRmE^0|?Gk$<2tZ%ucL`IFp>L zVVybqdtLg^0QvP}3@Z>AfvU3Q3gEDT1u!cVqPGr?X3IJta~@EOcEkko)+>~?SY}IS zSb|sJ>cNpFjV+L_^6`W3`zH!zZItHm@BO+f@OIJS#9AcL#_>(PVc>@fwhz`W3Ogol zYfl1d>A(HNr+^l%&SFeLelcUKN)rhht#b4$h1~lvOxDZoS;`BqB@2h?ojj!np`lYZ zW6dr7T4jt`S8DA|Y0tmHF4Qk*kFq5fGuFPg)aN%nTsk5=-d%u3u`~nqJg*QXW$ntR zd&$iP$)fq+kH;|GmhP_U>&>M!Ks=hbmF{`W$Tvq$j&%IQS-F#D4Rx?_P;Hy0a6*w}?^7=d~ zxvc8}z=)@t4x;6_1TnCl?GefwQ2dHQ?L(Up0xFS*KN}n z38H%p@r@TwLTt^;s>N{7FfnaPslMPL`aD1x4oY6#O`<*7Ts;?HM>RJkIH7rHnG(XzL~>61hzu zl?^0~D}l9|)>|nXF#kbf_)|)XVIg|*INk8y(J_6&0R6Sfz-d^KgOx0JAfSgEl@vEi zy;zx=>YtWIhkGyhj!0RxAI{`Q8(TT0e52I}dIJP=gVzA$00{{R&wQ(9(8MGR1g$P< z)+oS9Z#Fif`fXObG954tldQDB=r`g19w?ghpJMI6?h5nEsD$<@d!vGjvT|gzmX4f1 zC&jS5RUBqRJc=9ljvH0wP{6k*R(|Q?0HFsU6l41 z>QVVZbGuPRcFb5ldNYOsq@4XPyKFf=c^Mfkdd816zL{Km(|H0)1XBx$aOQ8Y9bEc{`y!r)v<} zMfO&7h3k0%UdgxY9U18WvB{#g772=bS1$u`1M0BvWTu+X_)gpV(9D(NzO%Lk8&xl- z`0=b1{Vwc&re(6AeB$Zpsc9m5^7MtWBe#Q50e@(Gi-9^10Bz$t^ReUt__fm+wa<@- zpgApn21(w5Tr{_|6xroP3XSeou^>Q6r>SR;d6RaZ@+R(tof-Uwkt6~>ZPQGZTMUr0 z!Acvh0R#q{`B6kUgg5L$D2OA$z)wye!n@tbz@tw>w8Gv_m64qf3(6okNU1) zTt|gIfi7S@khB-y95Mp2#=012y-!$l$5u_FV1`!P+V+Y{z_)T>Zaq01G+Xv$4$T#u zU05*G(|dGoJPQ^?z*RwBr`aKVp#HjSdW&Azoji9GnBkeO?gl@H*eyb6ZKBo3*4FmL zxg_{h`hW)drT)p!oa_G4&ZgD$2QI2L7=J6qLWC82tCT>9f!=wLks@w|>H}S5PJuVuv#xX-QyXM9H6>j*nF^-gO_wnEGQVCC z0-A(ZUe5rZ8Q9Vg8j_-e;7VyK-}(h_R?l?vu-qJc-;CWI=_K8)Wer`g!@CdMAQ*{@ zBbAzT8%W87-e-~<joOSPTiw+PA3gbTS-0Fd zO46#d&u(Y=H-}Bi*_YdN_tC9TzK0Sgv?p96U_dgf5+48Ul^nyy@0^`!=;LDi4ep9jBQ5z840)zf}p30iZ^fwDNptNp8CP?2W>SNv*6<8medq> zN7u+C|A|zcKQvc#VaW(B0>tSw4UL2v6FrUJJv^LXXl%sGA{jW3L)i7}m(ydCsU=Z) zVqn(zJksO7NhKIL1#KAb+p)8j>dWju3mspJQ9!?xQCdsQ-TTKIx^ZLP$17Jzuai)Q zPU$PT?<_}>gptFvIVELDAzizftA}e`4?T>oQN&^hVN)3EiVQfJwi-&)%72!YHN2w~ z=Y8@pbbaSx+&$gz(1wk4Q&hU|ARIq$B(EX;jFir77B$|GQ9~2O?c2r%2EM?VH;Zxk z%~-7SyRC8bcWY{SRAXv+Jh^P3Z*JD?;5y4-fSEj}B_pt^`V2&Lrg0u>j%n_6vWsZ` zC_wL^K}=fLD%@%_l|@H|G4dvy6DU5=IBu+d!IS)KDaS_15~SEvvXU~sW_32Q9(wSulwcyG-rOig z?TPd_UTkdX67SW*1ZEaa9Wbb}A!X3flU^=J{^fJkU_y1y7~0yt2Y%V#UWzB@B>dpS zk&*}+4-jXhz4hz+ZG^sX@(~25&R=t_MnRR=Ci#Zi+%Q zqhZbNfOwFCka91yP(*&lGm4=DS{Kmda#TJ7Ni2y8dTzA}IGa+-Me!Y6p;&#Lkgtgp zKaDg9s&y{ME&&i^LgxshGM=(>w_`l))xZEUwXldddcgwvC5GVd4fHF}A1u@$7%H+W zR}x5OVHv$W(GySYCLpv~3b*0UZ1*=2(KfilUM^s64vFljW-#EE z<>p~t9qjJ|4=Ac|h8GlI48b87;C^_RG&6&nm!h`z%kO7p20`Hk#SI)Pq(#eanj%|^ zg%fCOKYtQK_eU?6>PiY0MR$3=OqTX~5)k_!R=VPc@Ztf#Lty>3wihgD)javTou!;u za7gIt=@IqzhGpQ%k58~yC_)ongt0ovzvOkO$%#*0>4{Ce^KQ$d1R|Ge(fXd7En&N+<Do@oUxM551?!2Z};K-w~2fP^8NX2l}mD!2c>p zrG4-(vqbPOi=;m?;D0BbRAuj<$mwL9hd=(YxTkdQ#EJZf^ZQ0;;O}$xa@tNO zPLS6Veor>peKtLD;wb%*%sqAYXG;feD1E&5IKH~`PN~}o8m24fURJi-Ynh8C7(cqE zU8&Vm)-1$O%4XeEk%)BlP2BIt&qR(Iw3_>7S!WK0Cp8Pj^j&XTQ2R6~xJ`1Q@^tBr znvd^`SAlNy=Pt6H{GJlgVHG_wF|y&EVuz}3MTwC)AJ|#USTEtIA-3k z|NCzVPbMxMVLZO3z?@3-_!`rW z|Gzg{-|SWK>X4$ML?_aR5v8k!AcYkqQ!>>#pKwO!*(4hB%L&q7rw@B4pDxE9^{U>8 zyY0CTz4o=_xo%6r<~f{cq4w*Bsa7FJ{aAZZRK1XVy6Qjv_Y~E3ieNS{?G?%kTyE5QxBf|vtN&C35v1fn&{0VL_UKq@Ye3({S zS9eM?_nDcM)ww1I+cL?4-0m%Fr-MJVf%g#17Hu&+o12>#NCNmt)9~{TWK5$TPh5zs zXvHDS&CSc4=PwQ+shb?^8HrEy^5=bVG1KxXqO8>7gL?3%lF z;q1@x@vd+t@v}ko9o6zOGQuZeJ<-;)b8~1EUI2%~i8vdVZUy2uiT8G!qx3)Np3=(j zv!a(GWy}e}y6e$#ts7JccE(nVD3lnUHq@r}sZQb1Ey;75Q-;Cx+C?YMl=JrX_Ue^8 zhv@MJ*XHhx`OmZ|G^T;qRZ?N?v#Q0szFe%86ZdW3wn`n^o9G9Q%# z17svGw803wE)Dv1%~}8HU}Y_cylEfYtbYrEXb(6~^I4sG)0@V6)W3#d5KrJt!7kK9td%? zb$sr7PD(-HG}C(dc`-eB#1Q?&oaAtqitp!?e$y8+zhrOZA4h28`!58ENXqtt;+Ph^{mZxA^4T4ZK~~8p{#tl|q^s zcbm?+Kqe-pj?9qYW+Kz&@#-UyMBf{%jvT)hU3i~;Z=Pw3&FXu;=@Pih;_LIadhfjW zP$kbp!KM1|eR;JTNiJ;y!LkQSbiwPp(l&zhycR(lR0@|1hPYvcO$D-kt_wS&8EJU+ z43Wq;;N!JP4u`e5OOu*Ds25e8{IxHNzf@0d1P4CioSmD<`A2rU_-)Go+P?TMT8}-Y z>(beO1beQs7Mz0!(VUQH<7M_*x$@auO}OY$o56TX7pe@*exXh0!B0zL+KEC%ov4${ zBS}9BChGc5q3=h_r{BLp#mXEZlEOZq&Ura7D2R@UslmmDS!$$JYIkN7wHBgmOgaAL z<-^U2k?>Tw-E zsf*=!&F-!!82?|LY)5B2et1$>Yd`3AL|3Dzox%u&hy#%+)4r-9%+;ttLkl?1{&F zY~WE&y-F<*`7A6TfYk_2B*|iSe~VXuDaQu<%;>&jYc(VfS8OldVi`ilWM$oaUaaG! zMoBqzVr5L^O)%0uT0UTCNP7d17@fbO!f0#K6r<%-C}g2c6d^I#YC=(LOv^7W-qzl( z=v1h5Go>q+>KUR$s-U$z`iOm*4Z>R6flS8=H(TTk{TaTgoQdmu$xIt zOpKPE-VYoiS!}G+i)C4BENp?U6+^DX(EOpL~4&ms`!VwFhVCMCqeqKS#yYJorH+Sq{bP2BU;|Ml-OhX?s?tv z)ppm+hia4SiAHfmL9QHkia5^I?C%r4*3mJhA+XTxxI=8!{|YM#+nKRxaxIx{)k~Im z{c|;X=*zcRdhM9nYs9)9JN3)%$+B7MAGNrJMJ`cBx+oJ)vf#yr5jY|-Ue`#sWn)AC zjDAGr*Ge7k&k(wO!%!N@LRf z$T*t9O3QyUT3*Nc8f(GH*ddQ|Pw0;L4bw{h5+XcR#JVICgb^1&f+< zW0_+)$gV`Lh6;*!>tqu&0U%g#+ z2AB7dwvLXDHV0({UhcYvRQV*Dd0Z-bvT*!^`7O;R2aO$(jXkCE;g`-uL}2-8M|2{2 z04#?jAt*6D`Pv7E0vlEm+_Za$8fm++ji61ui7ixwNc1W9wxWSWT#5RLYC9JeP5*-@ zuD1HT`)=N?0}PKiV*MMBHe1A4?%4JYtWc78GR#W%I55Jl3w!8a)p4LcHh zk8eMQQV~qqC&hH^?7BUC-CiZ>euP;S>!j;s3yVPF<yeBtCYnoA)NO^4 ziHGQD)nKTj%iCGODXMe^&3uGEZ-T-FocU-J8WPWGb5lwRH|aCxQN)z8+CO(h^_uK3 z;>bP3cb&MtsJJ-aZd|gwyj&wZGm5!sM+{MbNv$9|B}su3I#@G4!>b&p*q&SE>_g|13O7^+wi7PjSss^SLQG zzoS*(@^*_V#3M*Zh$)!aAR#$+JNaX`3#H+6Tp79Jx=oBHt}aMasVXf+w_qHR5x!eN z(t6B18v~M6(JRiuxsu{-0gnc8TB>7rzy!W>AT^2QZ zLT3J5UtEC&ZryBS(BwR}Ft3`e^IJL^A_XKp@?V6nZ%SX744`Qc<&*}J+E zzndHO=GSwfkA4Cyo`bV?M_Ne{mGwrtbH!O|b{kffCw$tjQ5ot>osy)f*Lqg{&i35T z;)I)aH345AbW+d^qJ=LZwAcy24pU1c{=94Hx@>%cEENC9a;%MeeW0SuK&K zCsXbjMn^Z~zM;Y6>=bd;2a7la{`@$W<*@&O&#Du4|G?KNnMTov4h!Mb8ga?=tlq zXn%+0e7T!s<2AVLNGyEeEPvv89I@{VwzTT^Tpt&Eu_um>AjdWk94^jtnO}oV^c5_jy^RvGDL-&|RD$8AH8VZzzs}Wx&arm`8&1$ch z;NTHoC^@FX^SIBq72J4=l)qeoUsGD&Qd#-wl*KfK8S}E;@$a)vCpZ@2xh7&IF9iMRXbZk@#6iCgD zX%DchjcV#wK5}l21QF366KxN%4E$ z`_yRMXQn;2Nq_7b_&RV%;SZ~3%}X2oRr?xCB#bFpVv1j%|L4Q^I4sLiP$+6ew{UZ3 z$7yZi-pB5l>^D$%9Q2+I3Lc@9Orc2WYBJ8L{jDBvJg*c;Iu>X~SHyP8xisjvEk$=c zIpw)rUZj2Y+lkFONBtm6L3wWKipjF&yQxTf*I(1)zC&F{TNWpuG5wj8O~c+rKYx2O zXH_=U*r=lI8lyD!dZ%6|c5J0nmq?~w@}0xcmwKX_LFagdw6?7$r~FQ&KK_gj2@d{d z0>z}GEZfC%7eoFD$2z!vu4(8tc8c9(~vta$CFVa32xYSjkl9fk(yIC27^*u3QYc5Yd#F2nD=Y>8+{<52mZ$LV266 z`s+EbFMb3u?roJ1qf*NfLmlklP;=?m6?@sD&NMzM)YNe& z<7Wd*rfR3>)X;tZ{(g;~`Av*+<}hi`yx{2Q=!;r61D$E7@q`SGY7y%@RZhl!QutxE z;&KIRYc73#eXipB5LK{0OLK!qZe>{Y3=KUJOUlr3!-v{+to2z~BqnB~6{|X9t3=v% zo@v(=ptz3Mwa1jWla!;BGg~g(RCycwt)}Sc2drUk3G2`5^6}cce1Xh7y|57HA|4F2 zPov@g)IJ3|es@nm6+egLHf?R^>Hj@{_ST@U+XAP$HM#F@^dp}=m0W=otDj?Ioh3Gy zU-8~yk8jANbsIW3M8ZLr{<CW zszV8O(rH2kFW$;eS~tnR zEj;g>pkLt{smSgU1{vycW{)i&=1vx)XaD`x$w#!QujQfwS`6cr=3IQnh)gVo3^P-G z&_{K&w3B1+Qx+_B!L%uy35h9Da$y>KF}}({ORD;{ui11%kB(238w2TB)SFzT-;fCS z%<(FT_hqQzrIg zcEsK-LASW42*v?%h=Xu0dvtiQ9&5(WU1B%h3An>p(a&*n*siIM&!%+A=4-LV z@;OaDkA!04v;<{&ubZpj^Q&su@q_NChj`zrI^&#sS1uT0N^D3;NpDB~ul`1oxHXCTIW+h>{fm_FXKjeCt1UF*=~KHSw6 z&g_i1Ehs3Huk~Z@wxz=EP!H4W&tx_hd?fFf!{;#fUpvE@RkgqLqH`rg+6Jnny6}^y zF5Q0m+Kgeqe|y{2b$R%KmsiC~Lhj4O^7r!BbDmYU{{DTV`1$4P@lS<3H6_XXvfJsq zKhz``#}eySeQ{gVnjG?|?ZjTxT*H|_j#kCar#Cg36nj5bR3s7{TRvSdOkT$H5`d7A zn4ZXu-I{vg)xn)Vc}AGE%G=Zi`+gDVZ}-xS)NWA4#l;a|2zm4yE4o*w*w;TlkhOm6 z%z2l4>KgU>H7_I$IfI6hY8F>@Gu0hFiy-s{($dod{QOReiHn~Ls$XaxBkICg z3erzI-gzi18~@?Mr|!=t@kEpVKH{9rth|2LTHr2X>Kc7MKbgN{U#eC~3w2Cxw{eLw zdchdO8)y}&oJmJZdnHNv5-CyfT|I#D2;+XbSSDPszUvbtr#5IgxVEItV(`bW0ohnn zx%~+1!CYb!)ix6sA8+L8nQ%Y#1y(dJ!_Vxc6@6Ue2L0&)oc-twj~&xMJub%DyQrw> zXK$~xtSoV)+&^sv8bZsm&$?Xnp^E!k2?JONH4G$bX7q9F0MQxo8aNJ|9yrsaPwtmo zs<)U{S(&u5Vhcez^|74MV;G+*VSJA`BqVq9VB;{>`7zW#tUTG3EQDV;C)G=Ldcb=* zz6}sg2S#`ZfKUw$4*>mv3R@@pVYWuSi#|${rPlE6F|3+iTpSH92k}laMdh9e89FBv z;^(3ZNx-S|=g&iB6}_mIJK&%nd-qD7W0-M1t&NS%C)KQI{X8l`2wozD^4e_vRTD7_ znp!xa-<&UqEHpQHt3^L)Ryb?ej5T%e2;$pFyZ zF6-LNdg@}ulgfMRE33%`yPsN+uxovj`DEM4iPw9&5_dKdRAtN)r zMHrlt%O^ca`}W!VgWQyd0dwm~QEf&hSM4UUa?v-DtBxLqdmFzSNlr75tT><|z9wbC z_go0yBXcQn|9%u#FTP#T_TbqFq^i>-7B(s)2tcCmA!S$X-7 z&Kxl3^Y7-I31;#5Ihz(SruBQZB9mKkXJq5K^8K+P-4p^2j`(WhrOCCc0@FbTw%cB50Th zDMK=G*N6PweVnBE?SzNd!8BhpYpxcYE6$9`d?Hab?x8>UVn&Q1#cQky)&KL913VSY z1E*}FqHOET=_VxexUY@Kmw}B5agNxzsjj)At!$u+MkLRWM=E`~J+pCWLLRYPp<#g) zVkE9|>6vos(*1IU7arpVoKZ7-cci1ocyS)3&6mRCKrUIe|1tvqAuEr-F#WycXXJ+a z(UTpr`iJ#_7M(gM{F$hsZx4lmhMDe!s5Lav^C)76$;EwtV)1Xt(&t?e`ARYcHz*(i zFBZ;ouEWAelM$ADxkHvD3|&cuy9=RzM`11NCvEEgT*VW$W)#FhA@<5&g!!w;1Rh6i zAYpW?^7HXHjxRb*xM%_{A|K8@&ro8rw(k+jS3P0k`RMWwKyOWL0KG!;FF%T@Z}b}o zB5U%q=t@A%6aTfTTM$f^=$$g$K?_S(A2Lal$}@w?8!zM+_l+ zCbq1FPgJ=LgSGbJ+GvO2(t_?L3HD68{f|Psq^cQ()qklF?j;QOazT2S*3U5QF&Zm9 zI6yK~d6|2Ne7W=V0u4Y-UcgzHCN0SEXkPGbl1$XvZOrS=oAiP~Z@g^yRu@QEV`*@M z#m8dv>s4tG$P#6R7s%YVzcmaz+qe~Vi*V|}b8Zrz!=Chtg4xM^>V>r6?w`DMFkEis z=i>!(^o8VDTNYN3g4ud)_oNq$K;$d~!S?BYFGwL=zyU_x5d1QmZD-?k2Z@?_Wp@WD zD#8o{r9^9j<@)^=dq2ZABJ6_BDFvxA;V^k40yVjE4aT^G-eyBh#2wUIspn35v>9PT z$9HZeb_;S6zJ3G|XQT=C@~V_M?gzsgJDL=dyip99LO>;V|=qa8?DR8QH!4%XmSF`E^l1|i|)mP z3wY0Z4!Sq_#A-EH7%l2z0#}o@$Nn?a{?mke$jP>1z2P2S{seo+7ebt7PqR`d_%Z>A z9O39W7r`QN9PKRC20x2Tpq;14YbG^)Xuj(I0T!?^k0IJc>Q)U!U`c7lEtkz zW@xzCX=)q{q6nYL^q(Vq%$Bt2e$*{O&Jcc@kR-H1k`T(CbL<%3)Cfku>(zrjEo+mE zfF+;wfMkad|1JKzTfEg^9Bs#DpIzH!ct!SNHEDevzshIl{q=ayEhd4v^nVfd{;fo} zrNY?KDsLW&DzDb5^If{_W`DyBk`$ig_6Y3mEsJEv%w41ycW-x@6o*iG^u6KR>puV< zG!uQSx#~#c{7KJe^E2Tj`%x!i>uoK5oHcsZ8uMCnA_(i@8uU~vA?awQQx#3j=MM4AuF2GHzIlmxslGYTPCnYP4-|#Egbu{Yc4)1DgE({3+IL89?%b# zki9U|rur%=a9t`=?iJJ~Kw+)z9dxL`VVC&!R1i`Qve@`|Iv}}kQjw^CeF_OKz`Gt} zt@ZqG7?_Vi9~o}y|D?>oW8->H+ndfgE{A0&*-5E9ziP48u)60y`|UyT7)pKm5Hfin z?^;?O3B;48t6E*ptKODy9^Kk`Yo`6rsgtacX8~XWgkTthS;wP95Y>RDFq1GAqyjvg zk(mih*OkN$)!YHi`wux+(kdimycAxPn7)u3{HWui)!wJwE)*A+{k8=|8|Y`105=3k z%-h@hSTrzN*0mfIfk91|9h5KI8F?%}tTN^oG;=f>nO=BPyZP}^&YOORX73Ih0vM-D zmoBxpw?F2L)~GA*vUsa}=J)d1?u5YVNS3wj-YrE3fOJmd=^!aOhiu+YFPslK?R)fsN<@JM#0dvpvr}i>qL`C#W zZw}PV;Q;jey#S?Ki49xSz;+}xkoNcdr28c>C3Gw-7VhqGpjKEE+bjy&&3AKKpJbUg z)>U~GBlAM*S5TKH&V?=<`-B@~x#_8aA=HT)qD)0PJF{Xqku|Q3gntHXdsVPh2>p%NM6f5#;^Ay|b z(~-ie>obt)HUBYc_Bp*(u2Ayxims*otbDT6pM`(MCG+K~rYCmx=70Y-1OTU~v{WR8 z6L^95r-Hs&1CjbwGgm-B;C_}mE3*(D$kW}Boh?Uu*_X}=Cx8&5c`hE_bibrCy_?l{ zzweynUWXNRp)jDL%a~G}Ldx&C!Lbu_jf#O8im#vg->2gglCF5tQaSOz6PQ`pJ4?qi2a`K*mfgrqw zI4>dM{tpyazzlFkU|=9EJ^e>L5Qs2Oi1?Vl1zs65RDJE9z)F+g_>{(yF29n$)(=@b zui&8V47rAVy(I2i6F>ja{6^TOIuIb zSJKqFUaWxY(WPjUGr`mDUb!m}|BFdS+YM;OYuBy;SKnhP2*fnger|PHD6t#IxicD4 zpeIo5y>b~>=;rm(v2XTA{8FoM#k%{xOGOOj1AV`SP3C{$a2#dw;az_~K z4pJZfiLgme6FTc=^!Dn6$j}(g^{B5-<~Kn4aFvP#;LbkncP=JYRv}5MH$M${M_Wo z5Y;FCWHcP`(Iytl)IuIP$rKA)Tjiwd+BDQOH1P=uAG_YKdp__~Q?{YcWi;!_CT zni=l4X0p0c%a5R@riPK**s}lk_Hg1Lg+sBT-*>uQ$8eV7k!zLlji%Z}ES?`j-Ix?i zCJKs*WKthn+Oj(uIE>B=EKE(Y=I1r!pT0@HjCM<8hS28Tl&VqU8U$=SXdM9iO-KYU z5QAcHu@RI8pgVhU;C~K4N;~cK-44-`rk`3N)hOHWIThZ>mcGQqk@wjWl-sMpQNegX z)Tv0$AXK77rw`3A!hO##V@f;>HD9_hS#y-X{<(r?zKwednB}Q)4+p>a08abG+YCHy z6Ki8^5mLWiFP2k~tG8;2dECf?Q8EOD0>x#M&)5NjFWVu2gdFyM`Nqu3Wb} zvW&BM_H6pL0sWkmx9j`J7FDO-QZsF$3SwjAGI{T@m{0v{8xvpT-jmeFTIZIFpu%Y8w9$q^fk<8h?rTsy@HJr@`?xc93EA5Ohh>m zwjvzV$Fi{XACbc3tNQvbQ<{9HbjjR=SbaF$RJvBkGIXEcP(Zk{e2XS%Cj&G@C*7xU z9`fnB6uhi%fL@sj(7`h2EBeRC7(TTYaXgc#M&rb0EP42cqh!61WuAkoXm_kFRCFaf zVhvO%63bW1hfk?3{}nVjPKmi|?Ndbz`=k8<47Gfwv@9 z2RQcL3MA&4M{X#D!hc~C+|Sm~MK4;#H!eK4qn+?%)-A7N6#rRwx*`hUQ%2S+7?)sh zV7zMola*F|;_Y7IVmXK+dG3|>q|UOJ{wN?Vagp8amK7Iu{WoAffYTyKqjW-?a;rPx zECHQt4*Ud9_{B+`sYBEfmm)W)6aUCKo+vOMwX;()GCR-eR^R%bqsye24-eaAe7_c9 z!8=#`;%?0+p35~BbX4+RQ&h`ZeZzq&Jx%aXNDKE5XKvEuEaoRDAxV2DYDXUl;E6ao z%|G`uK10MdY#IJ5(lfH3@pO^AI55;qJ1%2P)zMdg)a1H7_Y4EKsb;BiogkUAK_{+Z zwKMN+R{s01xD7maGO-u&R7Z!Md_FRYi#OsqAw_pvEWQU&%whUiGMsH(I>g0It3J{cUzG z)ndid>~m6})~a_!9IjN0wjHghsHlAzL@nu$78&U7dVk%xo|tZZM$}t!ywyt|;9{aP zCJ3-6-{OeBmb5quf@E$9{eCWe|i4Kx?;^ zZyCP=!&;wi0zR&L-q9&4aS9i|G#)uICsiIm@T0?RI7)CVqjmlj@4o8lo-y5UF^`RL zOU2<)T&pgS{n8SmQ}DyISM_bhB7se9ik&$tE8IjsJ`!X?4$i*k_lPdBVGp0$P_!1~ zm#(RqwLXmn4w1jCT>Lw$b%&r5aNLq95iMwXpu&+}F0~T0{IDx=KgXzocG3rXn66&X zIv8k~){CB87s#+$@MZ&*RQ4gm{b^p$<@aA!tG+jL(G=`7aQ15QO@kmXV$t&l)&b5A zr%RE0aISt*y$O;hpbcXj$zIR&@oiM8={1>{r?&n=MZ-7{%mZ?%aO#4dd-0{2_7CG* zFKe%u+`gQn9FrxqazI_A*{JYFSrdvSAbRhoVldCuO?j?gJO}qYQHIc%-ki~MimI?h zmDJ5Ec(h(7u>Y))mbOqCE`A`yr$8g%PL(;M>q;b^RmPcEe*ZPHltZ7yiCbu3R6rB0 zyMJ&;zL&bR=HE;AtkQn< z;T?7hE(EUiVw&3Jzm&spDiBJiRVUuM)X(9%F&G80B=egC6AXOqPPSz~VW^0OG&M=78t#cvBD?Pk1-R6jfh z$0P;E)P!Qw(#onT` z<|cxFSFf3zG?QB;H86tgs6_F$vG}^Y12q>^j>*Z)tdV^*6I6gG#TNS>9gZUpQ=1Q3 z1(o)Fq(J4~kbcUf*G%W44|pKu_b{6~b}?A@{aTtv{D7}}^!gAd5XC@qy=(bI$Vxy? z;91!Txqt$i9&hY_n8OcJL**b}=P&K6hYdG;*E{H*lSKei1ZA1Jue6M*Kfzpce?ATv z=Qr=GhUCwaR5D$4-IUG$R=l`bk<&C+EzwcEpDX==ffs5j;4D8?ROn*dTg#0JT6kJa ziMCFwfRI6|o(t_#L{EO}^GOk|D7&?IK9x0=L(B~YJW*0o5<%_^p7E2Hwcs8h*qbD< zL-pT^N3#(*j`*^&Z z$J2+%+`sk;kce0CNL`<5-}LPVsanRasqN^=8D%wYWcS!bwh4m+{odytlRx4~kG3NM z@&0__PG;ZU%$yex6>SFEJXnS`;S}p)f)VYj`&U19-w4O%y}!wSOLwyUaWb;%o{Cp+ z%#URoHSub7EMJun*s7i1z{@td;e(Qb0vB`&e9X+0T?9m(z*%b#+qnfqk@ z_$d<)dJ1FbFN$o_Y1b*Q{1%yHFT9t9blNZu_dT+>w%?x;zE&9<8>j#6Qpk@%v=axW z)J}8oEgANYXE;b}AlE7IFsF`@ZVI_g=a^2EWOI-8>SD%#96G$oxTJF+IT3rbV-UDo zpQ{L#^mFV>D=dtX@Y?=4G?bM97*pb_|Mqcc+vTj5Ic+UG1%WgWvqfyEP1jchR(kg| z55j{@$=4!IZjhC+Xib}_1p6fG4v09SoSr6om_Sfd~h053!3E?gjn z*D1Wp@NUin+9KFFI6yOgJ*CSeo;k?|1dMe{zaut&t-F%1Ds{hGyF{+@>LqnX{`bZ# zRi_(I8F|C02+0D-rz|{ETc`EH(ADG#CDMY`WJ-Uux}2W6eS0xER>>+ zjg4AbS~U)g`;z|spHjm6XDW&$+iD6(73*uZ5R6UGzR~(L2vkX+s_?9DDB#x7)g3A@ zJHNcV49zL1D)CZbnQ0&O+<}|ap@7>E8UV7?>u?Cxt5KaLSF&49oUHaUR}qM3qav|#Ca}FvCf<@YmDse-2tc(sKW_yRYk(cx z$1v5u$m*}qlJ-F8gh13{`c97RqsMGP7RZL7-$0!cKss6$7LKTv3DHhWRRn2$4L>PF z)5^+9KprlIHbCRZa0rA|;FI5ywK*_CuS4JS=!a?d2wILdXuY{X9STe^#3~SO!g&E> zq7I#e@E>p=rm3{|Rw=jJ@-c60*1#elaZro{EMlB5ht_L!iOp1akoE)~22s#b@HI$O z7|C;gbpW*9q2MPie5MNrbwc*CQ21(AWH_+PG`)fj>+6+;S3BPXu0fi?81ntxfD2@e zfHfd7=DM;;_BGfM_Y)~yLB}|w^+M`jN>MmE$W;_Ibt}!b8 zcTXZD4#>UdS;8%UT+6HIO0U*e`}!YN7dU4!XAefkHFp~;`uZ38-n2f~;i(7y|e*a&_C?(9mPKagjDJvupAm@_Vt<#nKuSFD1HE`f6#YCrzE&GK)TJA%I_3dcM*jonh( zBALh~`?}#&vOfNp=Yce{|0wflHZZv-j45fC9Oj>Q>%e`r3G^@!*@X?)C<7*~qC&Ck zxI3p!Jcb%uuc^HV#kMus5dRtWz;uIDZiw;ky*kXust(^Zton{N5q?8y437F7Y?p$X zj;8KN#j=y?X(mnsP(m>F_b}rIL)4g|bEm0uC!3n!`b3~?)qXwJ#ED4Z%xTTjU{%2R zAwywhwSGjf5`ob8U)a4ym<#;;FY2cQpxpAR6woLo&hE(hwcm30YkW-@prIv%k7c}P zvb%4Al6-9NA;F*;K&lE0V*LD1^GY485J?@4iLLrHXYfpp{%o}HU>sju!>wlH2){Ki z{LTK~F9kUE0VFjzy4sz%efEqk(j?*MPyq^&^g^fpUmX!!BpYGrzQP(Zj14`B!kMs> zRp6T!lbD3i{Ih#_*_j? z#N5%S{fFxqLh%Em@E!5zQVf!uN|P80KyTJcSC{&4@9NR1)|UnRM&I`$`Dz_$KSLD zNLiSy%U|IVdn|`haDbb~!+8nA5gU3}8&4VKl*UfOp*UOE!9y6zv~oU(zK#;1 z2XZKwu_+be>eoK));`+AtXqOZSJdnwMAq|bFtcuWCeJ~2Zj(>n@;DmZK<^YPMD0XA z*M#5==PSLfG};C+j^&uF;fanWgN7U+NCNKrL2Hd8nlT&;Db0j&Ja3Nmgpm;~QHB*9 z8NZj7K$9}i#viY9(8{D+5Z6WEL?B0&%j}h5r9?>@ z;M86RH?u=U!T`AgfF|th?9Jwd0J#7PQ>$h@Q{#maO41?1I;N1<@bd}3b;cb-zeIUd~Ro#Sy~F!*RK(ENOXY19C{45G%+!0 z@9caBjXHhLxthu`{!18UlYd28`&an0WL`iY%%F2X_q>2b4prQTuQ|vFhO__3v0Zd_ zc7{et71qezNxq9i|3br~Kn3~{5_QdN4LSw} z>_XpH!2c9aL-Irzw8v(x#x@zdrNW`eokbzykUV*>?Sq*}8 znUL`4mLRXvhY6?f6yyM43XODifZ#(8VcOnAfM|CsDu5HH?O!?DoflwL)t6}LA#aks zA^<%b?a`;kcWV)V<#9vO4SKZf?ChlxbX0P3@~j#Nas7LEpBCiI;5-N&f^>AL>YVw- z;y<9fFv8$q-3Gb@c|k1?+WokU^?sw%H79xngI{@Xx&;nZNYwfzorBgOkXyzj@ThWA zgSSAs((x#ktky-J(6Q&f&U*XyZFgILu;h##0fU;YKR|3hW*A+*`tl?$qhEk7(67tl zo%}z8V=Ob!80A&kbW4dgi8Hb-7BV`nG-hDbqynJIjA zfL_?ifu^(t04b0&P0(l!W?0(6Z}maf)#;($;deSM?!MrTGIY7;5s#( zY(7Uxxl$&yL|J7i%id3rm>G~LE9Ts%2CY6{e|As zsNELcch*$GIk-JVPfYy}R>_C#ZHnzwS$zvKX-`H|qg@(Y^x=WD%*>503kVlPN3O5u zTj`3ZQlWr_Wj&T#Bg0IodQPI=cT`dVWrzcHtIm!8RJ&86nwro|31yG?l#YTrTf;YUMMw$3PhH0g_BdPtO|L=CE}49RaoieXfntL*WEE zqEE&?fc%=CcTv`Fe_|&H$+=D!nDbutL1}0+li+dlBWZ~ZF2}@5ay!RXOlNhaZW(CJ zls|?ns~(@2PR9Z-4)-4~d5vy9fa2wE&m$XUvHM)Upb8_%TSpplPoE~*O9SG8ykz?o zum`Zlkmo1pLL4Wur>QoQv5mlrws&NXpI=r)El@C7q^%~Jn~pd z6((PSrnCxc=-)|3j5My;+=4SoK|w+NYu|snF`LWbh=bmDK^=rI5V1 z9=6)GUVYeBxIcX4@qA{T;b>EE9A(5jP+5HQ$$+&pv}(ad3b=oAz$FppB?8ALP$2^@ z1S*6hq9~iQ2*}rXz|C`^IZf)%@_B@>;!b5FRbL6p#;1oKQ% zgL&3EFv9qN=LQ~RX^_5h>r77L#-GsIsv8w0yi!nGp07V+PW}9=&bM+e-8bOX@K8MJ znVZE-RZQ2M=Ka09cCREbQyofU8flXo%a_hW>rd}1f9iSlx7B|R8B-1#skS-q%esj* zSJjGwaym=B=NKY%4wVp&^h#6B`sO^FB0ADKDRI+Qhy@V4L#A^+``(rNBeErH`EIVg zF{Eq1{j(XR1|8eFh}V85QxUs00?~0l_1_1%j^jY3>ha17Ctj!Je^mO9+z(rCi{b{o zB%J1X*g}$cbrF>#ONvS+BRCrbB-|GLFmt!(tth%N%pY~KRc}z`*;Jt8|MmkF@Iu)R zG|UOza#rV(Y+H*jhBa)IxJwa#M170zrq8Yc8B?+~HoW<5aai{hFb(H|6uv{pX> z4xpSDm~kjdRlMGUiBMI#DnskR5j)IwbJ*3DjN42fdFZYrkpRdaozM#?IW#*B_A@}F zhm&~Av+}KD*}qxG57)P65Qu%g51@+-Q@bJFD|h9%&ujV{q&q_bD1aCj=w=_)hYM)?UX zLN}n6{sd%-YprM0wABgVsG;#%ZZ`)-V2G-4w8R5ZC!0bgjjTu*2U9DmzeYIIf;7t z_2x^mJ^O=d5+Vp@iC^UlOye0eU*0H2=W{EpUW48rIl?3$)fT8*AC0Bv zxwg=7%t`=+-4fd70&K{Q5Sfqvm%WAetia1YveZci{8v+2?Oi_;kbW^K^@$%t+~|)= ztdWp4X4(+N=ab!Hs&GB0x>EG&wnzcVBP^a*pwV09Oh}lo7!=@F6hh(c9vSE%eJ8V` zW&=r)rd`DVE$)ZVGei9bHVyRG71;iLlM6IQm~IFIUhC>1-z=fkwhq2!;Oi3}A0P&1 z3=b#gagKJm8m|bLo!|KC+~y1dt_^QMR-%Uzob)4TI!$-~?94fg%=}DN&V0J5@*mCv z1PuWtCBlHj0WFB%FU_P&%n}sQRf8t6l)Y`iu9VgnMg$lTI{w7u3wU8H&}{ z^b#@>*m9jwE8B8cg!`m(AVG`NixUDd8g%(_iFXqOB*y>kv~#Q$P`U(=GRS8fvTA_9#-ynbX~%GZ(5d=wG-z|M{js)lZ7PH;nLE$>f)9^S6GGX;Syiw?m!CN?1ol6SP$OPq6DzNv4gfIl%%wzpk5n7CdUVm zzzZ{g52;)>dQ(iol-#t743OHb6ZPGXjiQq0C9o7wS`hNn|6wU;iGbm#=O-jH?KEhy zCv_HdAPBk;I)aZ3hXTz4-i$*)-eVss{4jQq+)Sld|D~of>A~D!oR6o9+)DsNlR6X% z@lXY5RO5Qnr7m~d9jtgfmkOx6!17rzZ%FWw?Pgp6p@|_e&+sbd-u?}pxA5LF9+F>CDg=Z(f zgh5(%cGzfz8<1?NAlNOaCDea2I6P1hP|-v7-s|)rurU-i2V?m{v!8XsM_c9rbPBo}668XCHWhTg#C(av4^Qkm7wg}$%t z=P`Xp?U#=W_khrW{CtI33=;!)X_W?Y(yZ=KU zf61t*9wqT36Q8s=qZQ{*nP(&jI;z6{XgwJCgw}r#jY#6+(ZYPFXu8C5Iyx#9L{3B{ zOeygq!1&{L-gyxxysh$mG-x7R zcje7;4ps5FzoyAXQ68Pu>^%sqXgaR7lU|w5OEKTxXS! z?b~v1!k?2ayp%k7kA}!Mz)Nt*@cb;#&%u`nd)os=BgU)Jr!RAaFo#sbr33>LGrApk zHvC?=_yCMTM18=snwP+c=Gji9&W%#6V&l&m__%dg&5f{iC&^ZO8f+Ml(hJ4r2eLqW=r z8a@g3lgA~$PQrju|G0Va+I0YyLKE_*!aW{_;p=c@@r!U|;q0`357@_C zGIPO2yDw&{oeHcZ9M@Qa`ltJfL3{q7Ai;>yT}U;+N527{XpZz08jmz?mRHmCyXP|I zmF991lp^dbhrpd+npIoX-=8ak)rJ|I06nJ4_-4S15kfZJU=R}`?E`S zYcGZa&gx$0tbI|%+4w^9t5f)b9FQ*ihfgjKQXozu&Tadjb=K(Al=jgD^w-#u``jhw z5}3xM-Ydlzm`2Puk%_f#-&qwP(9%0`crO9)-C%}j;W}UVP>ZtmkYmqUH@OZWK1I^f zdDWKH=>d?F&! zu;%Lh=7!u6XeV-ui$)jh%N2W>%K;0_3hd1nge4vIsbkNnyh_>WVQ<2IZQ0{K7A+Tx zrb})YRgQybP#19`yf)pc{1%~-_q+^nmza)%I}U($adGii^VP|lmG^?JADIej@SOiw zSH}yh_-?JZkrJx_nFB8f$O{h6xkdH`prsLq3kGI5TwvmetWOuy3qN``IXOvu4Qq^H zXmAaEU+agi2fxg|-x#94ekh~X6W#Q|=9er1y!st{aq`fEBjydPugn3vp*SXV#nn|D zxGBbjIHwpy*2epE9#OksH7~1uN+FexG4FAYX~Q&0rtWT-n7FCp9=}#6t^00M256sSkj&Mwt5rFkc&) zm^ih64`dSOLaG50b{>ql3Bf_&PADIyt9A>REmQP>S}8Jow-(!d1EiO7di`r!Dg6Q z)e?|IK$TnNuMti&{%=W?kUiCGO+NrfOU0$nZgOhol~e|v0n1-xwt|^n(DI3&pC9%e zF$gjuL{MJ%u2P>Pf(X55WTOVZC)~l5gTZ0s1o$*<1&;iLOCz-pFTvPnvg{$GL;iS_ zx(LBye64bkq_#FA^e2#5V*n17!k%4!mn4^y*ewQI=+a|!4G?7DV;UUgqs@eX+LUr-LHEek8`zuJY$)?!Cs zEjzas{SNV_XRBD9rW|_+RG;vO!K*<-1G*OSjz+8ERZNTzq)p zyh$20YyrN8mh*z*Ho^;0?b!eQN>vg(`kgy>5G|n^vFmd`0;)I>!UoFyi9gUZYCZRG zYtg|Ys}Oo#t1sxh%2O{gN5=VidI!)iHxkNpqgFz{zH{eJ6b3qB4mW+U1O8ksI2d5V z6kcoDSA;-ZBqihbfakvf0aQ2{IXTzST}cAey)sxxh`s#KUBou3sIpB8P$;Kp^u>i} zF&)}BQ^D+SK0hKip+$&cm&ozfZQf~cSZ%D^qqZmyy7sHEvHP%^DvMYo`^PZDaMBo`& zZUkj*?H;MCvp5P(XuzDph~uCM27h`ThA6ipg-WgJMa!qBxsZ_&!t_pskS zisc2daH7O#w*%pX00jlh_|Hrqd}bTsvVi^U$&|5lgL(#7BOKmZy%a)rdl9uMrVB7! z#HO+vjSD#&Qa#?0?N4kxW>5dKTPIQzg#Pr$0AFW*C#BAITGd5o_AhQ?3+oE9;T0Odx|>K7TT z7vqrj@JD7FE>l`8PwTi74!XoJ_zIsFif}Fap~F%3zm8&PH99)lhjI>FHKdp=V-V_uZgQ*6~3x8iA`-n-GG>zVa`j!VE1oU77u8b<^mtQ2k}YE zX1wS@8)Ara^e8$Tq@jmKHwWyi4_D%VfGAHKMa)`TeuE2-Swoe_Bq^z~uX3I7t5c^$iXC z@fLPs(CRNTyXTr8eN0kP($+g@A0&R%JB`%qF8F35osn{WhN;kSpC_X}ai;N`us;&F zj@_1vgXvF9bcn{9ICQA|uQAv^+1PNAZiX)ip;43s$Nb8bZO`JPU49yEfV8ZBUM3K& zjMe(G1)4z=Ul$DOxDW@0B2QEMoag2)T3>gXOGx(<^t+6nflpAfx`b;%?HFwG*8UvI zUsL^=9*ORPuwGT1r0U3mPbX+;Tc(UV|Al-C!^1=S4v_7(xzo!qBVsm0+hPb+)@qe? z3;rP&%}E+EDtI)@bR8@_0=r$U)H}&a$|(UR9V)>Kc}8!^@0cRvKJDZ#=EA-=pMLCy z97W_p*x*PhD<4652)|k@=(&i~jg=3R4Y7Hvl!UGlEi2*-@RM5!yN0;2+IZp>r&j@c zt}tQZjA{wIIdq#RspQHZlG{gJi<3t!jfu2!iX3v;=-KUC?ck==OdYy55r#9N(!g}X zqm?F)x7uJhN0_e|Dd1s?JWL=Vg?-Z3sU5Dz7IJ>m7uwZhbI{Pu?VB%`*E>r(`tlPY)#v&7ubmEzxqbG-lW*B; z(mXPOc)74{3X)3JV0JGSPHKEW97gOh>=f_`W+NA{bg)PR zYt~vw<|I`kZyvedz-r{>n|cnP25ZD;8HR=Q=e#^!@!`!8M$m(hnMv0lV+$O7h%{;C9SR+YnZ ztUC9RZ~*smUARz;3{=zE+1b(E9_R=&p}$=&m^s+lY101RHum__8|(DkjX3s4ZdIuG z)5&%C1->~!TFmqQJH1rU5NH4B3QKX|DGseIPDyhJ=}Q(4$XKx^Xy%ZBSGl$RDYrn6 zsSEDTDKZbY(~i5}h**9MD(JXxJmu5Wae(P4)}ya?);deRB}T!bf|^#kMu`Siex~og zdS$3$BH8p26BOdbp(+O`AGR-hA4*ZMn*P_lswKa8ss?B2-T)G{whZ<6c?{ z{0IS3Uk*c@w@gC+$Cs%W_!M;>yeWYI8WI9M-NgSqZ(#Q)CHWxYVK6m94F z$5LHSP7@(FTU(r%Ut9#38!j8f4?lhEYobwvuCRaUTOGSxx7FuJs1oPCrkn&JoNerv zrW}(SlP2YvwchKHz9Mtf0e5?{EK9;-t%W`?U}q~ zkB{xmTDrP-ncSn?M|ZBeb!1h6!QC%g85xzY{_LO?=Hi4PeD-E^Th+Cmmg4RS3nrZ& z8BcPsqEB{F=}ujY*eOf}S5tF(|D?dHv+hiQOQP%JAA0kD+j0>&!l|W;CPXc{Xfj#O zW#~@Faww%)pPQ_8I-p`MbJA3sosc)DSU+_WJ~-YH^*Z*{MHsJHWCF zlgakQSRR}XVe^1$9dIR4TA&a>Gmf&2P~LFwV_FIxw#OP<&GcVI#(dzV?liBdxh3%G z9ys>tovG{0eV+0A81!^?+}ri%^qslG?}oi0B?UMNjl~_?Zs0gamqk={zX!!A4CdE%Dc;N`qCSg#>?-$%1GOD;BLV}y*`XE~&j1@*_H%>?Z*b8iTukU!f_=6j@K zm=q8c`0j8)UHK$K%yB2*OU7OT?cYlD*O6ZYsDK3`DkV%#aE}Ev?C6|ef<8BDd4xbg z@Jq2$@O2+38;{6}U-KTlTOLdU3YY7wUgCwiihmWpZ{uf&9?A_Q|9y(u_r9)TZhLSI}#5h|a4x-G5g8zLB zi%1UZx1N=iV@~}E40#<>#w5*C1c@Wf%IFzX=CDJx)U$W&g1+b2hwhSvivmJI`=W|3 zJ5sHGaj`hU=xo5>*AS_BlX{;T*}Nq5-f>#Ce|`FU^EfJXE${e`py#MKrVL9)-3#dJ z5Bf?9x~vOe9DofJbDMDf180)H+`fZdM9&0)f&(B84jsFNk8DA<=a-d(9qpnYAF0Qd z#fm*zyta2)hQpWoRhVYV4RhzjuE_C=skTwWX*oGL+^e7BgiGM-%=%?IE%{S+N*Bdd z_R4L-*(DIvagYsH4hCN)-0eR-KaKtv#Q92egx)VdcS+!0Vv$3rfp z=7#hO6{W?hWfV%EVf*mH%WINabbII)Xer0N=ayXU`59f(Nt+>!q<4wFVRr2mdzVg` z0gDE$YBxpumK=nCqV_PT`Kkw7Nl%*q&w?!?5FrA-7ISupyWWe^UPQYZsbh_aO?NDUu}UsM2~7eD9hMwz7^0x+B0a)^vZO8B*`BrqmioRHB-hM)o<4+- zX9pbDbA?nfM7oYrou0z%=hZ=U>gn&Gziq#;QRGgFTUH!89EHwEB z-7&gi&?o7IpKskh}3X)D$Yx;UFA3zsGBCq#^ZA5MA#`0Iq zy-zfvceGNyWk1?GKSUpxp@&j1E>5pG^>9v#S~9ngP}ShzNzKu1*fK6IeX;6hjs<14 zvuo1W0AN{hM%TZnWIuAN>qGt*AZ8U|NE_fd6O|u&anx|03=R+Cs4vIK>lhkJ`BY53 zfI1HoM|ibZe_90*aAC$P-oezwHdy#I`_ZqT$m%pIF9@m^@yI~WCv@{-nu^r2zlrgq_LhtDw?O|IU$4hsq3U4K16g|~qy8zJgQ-D=aG zZ_BxbI94CaLUoQ}I%Uk#&di(9`P!LA-l!e39%KSpU)-0(e_Z0a`@B*&*yvy5Szgho zVf0C{=T1u6$f1I*mCJIMB{tj#7j?;gKMe0@c!v3EubhWFA zk7ma0_&oO@jCt(^U?Z$O4lV9zh&0U1lmGfDU$laRaS9$XpK{xOUU(fZS^{1Cz1RHG zXkHu~XgjjP)lKcNJ1tvLKA~$T2#+;2)0l1nrECYJTkg*|Jkl78hL1P;v~9(LVLxc2 zby?eF=^v_VWn1`LfBGl&58b_LI&xj^Es|ll6voo1`Ym&7K+XeQ@m>5t_k`G|Yzd&@5&F^>NrmXR*rD|rp4S7znGZg3R7fG&*7Gx;K`OL5rqVy2!TMI zd+(%NTYn3c20ZuoYTw5hRe4WU>_z3^yYByZ(WZ%s-HMa{1sdnNEn|-q_r{_yWe_W0 zs#eWR=~T^hO|?%Ao5GE z;sOO%;GYvo2I_Qp|sQB zXtSG`n`|K!ES#P=iaI||!{U1OF0P)mhyeUd}CpFm`lc7!ygw2ELUB~ z_&&ygUbt{^oE|D=r{K!m7!mE|IHE;997Jjkyu zXE2%W8z84J&Cl(z`I0Xt^`L|An8~-HQB(eEHz*yoon8HU);ei?a)q|}dQ>M=3vP^$ z-8odvmohxl1h$m(BkIPiqpXdS1Z~Mxm1GN^AEI^8= z(E*eb$RThjVjuxb7SQ)pW#@u#g^eaOiI~z|uXvNeoAY}@*vfr(kAqHBs;Ka_)7s?= z-5aD!wXcE+$?ZlR7g(kM8)DNsZ*&_Qcf8ZkN^xuqq)0P3?x$DqXY7l-4PoW=bamO? z-?UFzjQ4AR^EqhmX+l{B@)$xS_pO(LDdKoaHrc}HSmc$O^599Xw5OTe$yJVSMy53T zDT<)aqZGe4=T&afZTnq+iaO-M$ihTxtV2OzdTe)HvRwDtgK`;XNj*|>Xy3;>X$QWn zrJ1ZZoykIusPZw$sNql&bUszy-nWCOR$LZFP0(fbubV#(sI;8BQxF6G6C7D2znY=* zsvNScmFfM->+LBDpV--%a$~U#6*pT(%eKY=lcyK=KwO0JMNvB0YJL$soefQAJwzz= zsgs=gIxgTo68oyuy+b!w$};6t@N-Ruj)>(2fwf%!C9k5hN#@W;-q&9))ZFoBOVu{! zp?z7+Z)?K855-RI8H^clwNWpovk~I1Q6btcp%;&T1tMFMqM6^8X>L-9XFN5=Ws#ZtxsSb5&_YA|#LebxzkP}p|YG@-2fu>eZ{fah1Wm1)Y|lMeD9 zp{F`8E}X^2sbR)L8*a+eN?bL=UuHsbKs5yUoJ$77{<^gL)oObNt=lK62Wuo5hRE1@-<1_PtuC6wi;%ZI{Ux zQtgl4sMCX&d>P#1e|>$t^Q}C;t+FLEfFa^NgN-4!u1m5x$iJ9z|8R5nFKVOpR!-jw z1u6qm>zx$x7UHGezV+Nhe}5~YcG^gs_qstxt=WOqrgpZ?>1>W^*v}9uZ=liu)pv;b zPjpRx{kQh6f4Lt+NH5*|)Guyxoz6EuR5U9Jv_G3WJa%0RwE{jdJMaH!PIxoAn4i~k zb2kH-%**APkn$N^9`fg#*hYVN^Rrro<>Afd?b}eBZ*k}UJN;$Z%cQn`+M{shkNw6k zak0w5&je^;kC`ghzt%AbMF^@)(D z?#EnK0y~y_Hp`-Zoi?km5rNBzVV916Oj)$+{TI<2x5WWW91Ulg3r&^Yzb|b4XFSO_ zH^TR*=TD`g%dgAMPJ@wVUl?Mw{<r}z`P_9SbVB+k`jj#MQ39&)JOz9zeA>8+9WP4@Gbkf_D|n?pVW zAQP_`wC*Se*%Sh^-OW79L$X~Oy~~p~N!QE71#8^{_Nix^4tbSRWW?9s-&FF9bcVsR znF&jm!@|&1?aYAdlAe&7^p*omwyXZf+)DMi-WH!+x*gYY`=@;wYi10zqx)fq54#?a z@9xYgx{PD)I&)hG2!;)~Qo;AKCj~Em$HyP8FAoRUz^9!U!{aVT zVhk^6<#98F14X%@<=~!c{tTMusLv)5CPhr8x}CB{v*f0idzb+risXr;7F$Hfk5vpOegVm{_x9{d2TuZZUgZ*vo zMshf_vAIcP?ZP?NcRJ>*u3D`N0{juf7qoE~o-JW)Xk~7&BU+D&Oog9KEaitL*o7nP z#@S;THABZzHA2i^e=E+{B!WJpXuomT$8VWSn5-i_rd8B#{^^!FX$%1p>6Bo%AFlZE zyJplR>uLbsiQ0l?_WSm$%&pyH;U=W!#6ILC4%+_>gaPLO&nL(SfPO%!0^s4YS?m0< znl8UErzK02cJWX1c8iE1&gn5z{R5Mdx-?}~uK8mQ0;wzEpHERDUxK{+E>t~nrqT8h zfl|K8ZlZIcgCpaYjj$PLhF?YS(?s*<_-jcS)p0!wn$RyW@(=I(v)R5jHB!+uUpTkk z?O43F=XkG7QT&o>iZg$^jJynM@Rb01Ddt+TbG~Qm3^NT3Y)|^u)m*>-=+UERXXW2s z@qT-quX3?lL0Q?heZG79UbA9H#-;8*%=_g+uj^7b(TPM`ef@Rr%1LgE$BsQcMp5NF zxqRURsfGFfUA<$sQ0^#@F8uGCvjXFWu}S&uXSaP_P1F`qY@a=PKrL|JuhsehshAHR z_sgl=5c?eMX5jwj?AW*aNy;OWEQ*m5H-;PPwtboTO|elH?CMB>r38F2MNFvElBU`nTdvYt%_YIYsSsEJMFDL_1tI9K1KD zOIb0|bD1fp^DN75@*F6Wh!X$vi^?bI>QA@DA4(q@w^NF*d6|y$1sx2L|7CArF}=x zYQSxiT{fSz_5QlHtJ7}JxU!xw%e6PmeKY6Yshtj9xwaUgBlR#(u>Tr3sqSB(XNqwCpJD-j^!}z&IIce$rz3J3%Wh>w#GjUY`@I9DQ;A5 zI(U^{4?QOQ$b7IOKt1aT4_zg>&CziNW1c@_My}#^5n&1|u~Y5WO_Hm|?!fezmAzND4gh2cmp>q zL1}iq-`{2~e{=l!562HDmDon#S}975MfR#{H&#*q{!mi&VC;|EWySnoi5TIF`+$CHiZ<+dJnf z3^V&Ja}hE=lva1DJeYS}K7Pxy>~?f`asJM1CuuVK9!ff%F#ms?lpKU3)G6pb)Youa zmHJS|+BWg1({#yXtzPCJ_do7)&9vI$DKn+nJcW*BMKy^MLxP4$O(L?pKT@$0g%;wP6MpQT_r$@6x~)bsWMpA#{w-bv^uDmd5~|rsyOYK zJWjjFEjE%H|8e{Nn~H+YyyRo9*HV|hIns#U%yKC|An~;P14NB*6?C*T%A^G$o&d#s zN{f6r3%AH(BhUQ?8L!A40xS=hKhKovrlMCIW8KCEi5$xqTT0N=ldJ-fx17X!Ox)Th zu+$nHM{dOjK1i=x$X#de@{4|{`>v|fG9b?s8a0?3|6G1SeXxT1P+k24r@0(=&O*H* zM*|+}H@}1Hg+*#VD6!s(KX_H{l^WZ0!O|PbiMz9IDk`kAze0C;Y{x(O((`5J6nh>; z8d*e6w}9tdX*S#X$QyT+)s-Aip~$+0pq=hP4?+(fxkINt+ji8Wa$PEbG3r_D*?oNB zCLJ;#jO+9B_V*th-x>XEl26#gASq)i9H{{Vhd%Rn9!W z%l23eU+8IFA9GW+A-XecpKTT6=IK9Jzfb(RDp))CyHn+?$S1eTrD`r|rTcm*wZGIa z40E)SM6))KKQ%byr`^0diP6+EQFo1l8qMfefN;ye?ETff~17^nxN3YL!Q)d+Myua^q=-ycz@sS?w4uK;R{!f&UCSK zi<3?%OQ?Rx(N&R^<@E4p0lBo*RrjDLQVU0?xVr}z9MqFUntlFpF=tx5;%~PCQQ&SO_MI$ElJ58f{PZW zvTtuUtu&7AGK;=xToC&8@*@+z^6YN!kMs$>3l5-^bYz`04Qw$yb!Z&gq= zEQt!UfuTR@oc^mHOXLrWZ5ABf`0dF0Aj}tTdtlk}7aDiS9g4Gg#};*6E`=}AWrA+5 ztGTMEm@7l0m$Hzj-oNgxdA=xE+BbT)@yHm-NS(SPn5Y<;c8St$sp0yJ4m$9p3-%lS z;^F#+g-?5?44j;tZmM@j@o&AgmoPklFoo7PJw3f?A04Q3D#=Q~{fvx^bTit0%?|UE z2ZMK6so>$1CfQ)1XWaY8P|!c@VHo|FSN%)k;^lF4_6Rfp>UZsU?915|%tlS>{f1}v z%}V;X^joeWJ^>3ZwEmY1Zx82BU0EsSFiHY@9c;);%{=?u zlY^+cZW;5@dA|Vyuj)If>Ju_*oN=LZEHB9IfKQTvM^M;8_r zI*QRvi)5&+4Y*L1qlMZo)(~G&gHd~|X&3{Yn&h99lo}ON% z4!X8p8hxTx(NC9KhDkH#cGJ;g)B7n*lIP~#Dvpdf4M(2+GIzuZp&6kAmfKWhyZH;P zJDPaNeM$)fc52y!vdXvr-FeVO!|$4Fs@Eyj^-=!dWj9Xt=j=3~$($Dw@@`&PmKbfm zvcnV6a>!hOFq)iN3Y3Zy096#?9nAIM>Equz1`7kJk+zF+hsGDnUY`xGPNQN+mKmWC z9vSlsH(9(uTW@j z9D8$S+)j7rrc_Js;LxGXUsf6Gy}CP+G7sz_*}XgK&q|mt5(E-Cb{SKs9p4JNz)U1$F+~V*c8vz^^DT^bh+G_lx1>gI@zxDJEb95%}Wq zf15{723GF(1X~jBQ2L}ars_s2hU}p3j|0IT%9NKg_03nM!g^M!1q)Y{ zo;X#$MfAer?Rfk(%Xv?aSL@giASYt7Va!+ExlUy?!)@fnJ+WQ5;1~tZM4wB&rMr;0 z$gyGDjeEgUjQ;oU#ek!WI{2KhGYMZfd3+9< zX|!IaT{Anma)=^65G-Ge#IrQDJ(F)A`p2{QajiacNc};t;ZU`TJFW2Yh*1Ac<(kSg z!|gh|aCM`%npBz{5-kxdh3VSGvyU(DnUQ9t_CXnslMF5i=+%_|<=`_C<03#c>iSHj zYhiA2Krv6N-!(l|-)XsBMsdW@ws%e>;^>4zRu$!~5@L}D)XgL-56d8C!=5Mb)=ap$ z06j#O7K0TB@POE4%nbe)zT}`>c=rLnst~6F;?(cyb_woPQ_kP_D$sT5T zFQwwhr@Fhx9|@ag(_NLT81`XH#(>`}VyuBY@Oiy=wN7rT)y@@($Y$jxr^$|+>y53{ z_G=p6VJWa*tzBLg=rgxduU|GPyO(x1y936A5SjHp$_Fnl9t>V5vHJBQ?m5)dBww?#f|%> zDittx*%3Hr-;_)HC|s(+pxA*?{jg0JB2ZuE!1;}lBvPl1{3L7z^_}f#CXCm*dFjr* z^Gen#Rj+7@(uieEzizrC!&l$Sl6UdS04Utr$N20#ro4(;lHF7@?Rl7 zP7~OUYn=6SajmUSPmh5a3Q_<7+>m>uTS>!5E%^tFd$?2_0Y+^DDfJ$XAvEET03z0? zO;kSG?Gnb5O>ZZ{faO-;$e`x5v|ye2XdIPNxEs8!K#+T2W)|`>?Q#9^eE^bxd6blu0mI{wL>MT+=YJ4J zn9Q$81Oz=8pp~f`@;X_ikhGgx=9{VFl+Z_BnZSFh1{TRBj>CaYeQT`iGs;I+%EIM- z^ef_DCm3vYb}CtUT{~r(&2u$!x=f+u4rk^5@?yA1*JHGFhtbSFkG*_8-d%~^Hj-Uj z(m350ZeHycI67SaC9@>j)yj)8;`;NtQ9Kt`2sG%I$);npCt^L~U&S$}Nhuq9)wOYV z&FKAXl9N7kui*08J`PlCc`1QahjPwG53etfks6&srTFSY&+zyB;Fupaf!0}NxO}e1 z`Ak)`lXJkA)7YcNAaIme<#VlJLru<5_EP-Jb!){A<)2k z|CA+6AmKmZ-H}opaq~fQh?Vx_q?vNC!2?8>v?#oVvzS<5Q@UkYtAixSp zN(np|^nF}VodKdh;xE*~y+1RJ(AnYEQTQ@IYq!oon(ral*8Sg_jvT& z|3_NBy^L4QSNWCpx%3>R{#A{rN{q_hJnk}$2R@8lP}KL)xG`524sq2(Dypg{sJxy_ zpN76}m$MRu^fJwaZFB3W?lpfO^9IQZv*NMz+s!gBLRk`wgMw5-L*tlk22d%#v+7h~ zlTQlI(cr*g9~m7DI2}56;&M`}xuW+j?!BGvY;~5~wZ(j6_Ls|0 zIZx&Wm}hp@GU-X)f0qoxeVqryJRCLWZG?{gwmCSjx_8ASCz2MW4!1gURAM?k`}u4Q zU7h5TI677Rkelxly~_u{ZufzrO7&aUMIt@tqPfBBsV_)b>l;KpVBCV52!6ztu;)11 zxhqTozGhvEK;5G2@y<+-ey5eZzq^3_Zrqtpnws6MJ25b14oyf4K6_9`;hZx0p{w8S zr9roXdGpCF5pUf5#4&7_nIclokB&>Ghpxipffx=4hlC(1f!PMZ#kK~UNWdZ|sZLP) z;5G~#Dcp(Kl}JU=K4O^NoW&qequ*P>BcXFrHBO74E=h@x4!tDAkxHffsx5Zr;B6_e zz&ilM))%*MJqft|7D5URMSki#u4(dL*QafLz%F+p?8CjVDYI6>LJw<@m6c`k#a)V* zOe0RjWb|yxJqCl^f5pQ~$DpJw|CGqmiDCBq=xV3OAg!!>KoYjR%)nntFq zspk22cp8YBpXBE4A7#P0OfbG5r$IEY%41@!jg2RgXv3cq1pr58b~YgeL+K190wE^0 zE6~!i>-z^)>R;Skl0~HpS0I7m1=>0a1uO%1=;xu{Keen^YA+?W7?w^gWlQDl-mzUG z<~a{@{?63an-I#y$q)QHN({2b#&#a3^_}Tg^fZ7|(nI+*A@KCkkOR!t)iaMY zr1=!bH2&FwLH2z1OmlXn{kk;86!Xs?0zKJs2-eMj+dd^4_k zE*qHXwanGko8Eby=q|G{#UTtpxQ`;x;eMak_pfL|lWcQfX()tKrAanbx7*$}& zWcaF<>3uKkd#k}5Hj`l{3Q(dOa;YvSnQU}bac~pB7^`Kb$R;d&owgx zuDOMGcZJ9gHJgEWbuz_MKYrAf&M<#Bw$--blF6`m?Idc>lUiS9 z^!Dt&#Kf$9Lf0u{k^_kMopR0_BJ*ECA=*0D#)tlWz*7ah3cO3SBR_tS%zRU$)Yd!` z;e9t*>8bU6j5=+f#O`bA{NP)ai!Bni^&mKmwWelET!R@1DET0Y_VAHzT;lWaeHTvh zslW1t(fr**UlnW4bGrt0XRi20nr<^XPdWD2#H(*=I&oo> z0a+&K79xHrV@O4hCOe5cvMY7DBLpnqs^Bg|BEmTMOSLUre2`XD6#sv``0Jb2#vj@5 zx^9$C9-lDlSdPxt%@||GA9ketJ@4Xh)aP+^4wM2ObpO5{;uVgD<1D+1}6Yz{Od^Q0Rl+GVsXp z>6IVgBwbWggkvali%e8r*W32rJD8}`TOEH?BkT=p)-(NXd-qtwv;!tnCmwkg_xI1d z7(IKUBnw$7p_R`01o}~^ZdX=Tl&;M(U-L5uDWj-wx-8q<2EU>H^uy{BIhlk1Ob<0b zkss^3Y%JBxgMZ`QLp~`obvDRWE#QEGiV)m(Lz7rTB`zw7&$7H^pI3Ne?)2 zFUye;U$*^H<+sBQKYu3KH1s zJ+dD?dYdsHIs(+ckOHbq*&L@m)cjWTaGaS5g=6OIhAYX3Ocvg7x0heY?*x?2okmjz z#RV~6MD-5I?O#>9ov0R7J6~ z^lFIbmG^VO;x|PEiL$W+*wz~rHeBRYj(u&B--WLvVDsl-Kz7)$Vt1Zd==*6Vwfgt(;oAuvG+!qeO=cPlzT;`V=@$1*uKh62>In z5Bu5m+tUPYw4T<9HMC7{;;pzhb$zVxPWI0V$Mu)=roWXsWL(4SUJwXD7O!S2W?U#B z=jVCwbD*%bfP5Eq9GVMq9Y0rpOK$#VTl~3}L?^TFZjxexs`1;M6CEx=#Pxz5 z9dNJ!nGXS0EA>c7wR^|JY0Sy~tfH~3Da+n>;zu#+Ks~!Yp)R^QW1iwN%i(Q41eCxSU?;8~sxWBz1@;28Kek^)cUo>H*PDRaNy;s}1-sEx#l4nMu>S z&ixzz>b~6ut!CP(?=o3(UFVFS#s_{N)}R16i#yaf*%({B*x}kN#BdNzp+35#sOViP zOqmmHU{bl~4{JsnpK4c5XtGwv4`;zcS9Q$IpA+)d?ruL=p!3L}puiXm3UvH{s-mJI z;@3a;@XleMs>hL(#)Fzyx;}P&%yZGdTvV2E6-AK52di8S!k%7?5qSYhWFkO;lY^N` z`M?Yqn^~G8=E3{sukefKrv(^(h#oRuJ1eL`C;msnD!&WKa?5ckg+Is|&>jSR2u+xr z-8h}SwD0+T+c&RHcT0HmxsT0XIbxRIqhL%C+)DYhS~bnU2VLM373H&sz(fXzQeEi9 z6cmLp&;U3PUTd1~H@Ikc^jb2)(dhwF9Tt|ls^r=O8ByDe`n0$U_n)#I=(V$_Bj1BJ z4gvl>U0qc`bw9f4e%u+Z70Yg8 zG@?ej#LfFD1pnL1RNoiHnI>5Z?Z$kB(AsHv&(58H&}>2FS6y9=Lk_MPq4G8{kx7)> zo93lI+7T0XF7M6F_jF;}d~3!?UpL$ABu)I|A0tc!JPZSgA9*Y6T}CHACw)#4}S)qQg#IeN^*8VsyR z6}GGip%)|>dw&K7sBftM?2#1tZd2{**lk}xbb+X&V1R&Ubos&<-|W>q3T`W^udAm6 zzqN7QXMK{B;I=$VF7)PR_I&%rqB5(iN(eap6e#e3<`P~QVC+)R3pD(`u0`a9F|3g> zU&2x$#^MqOkH8ylpUtjXrIE);*L>rmjK9=GcK`dDeiZmG*w5Yl+m z8VHJQSLXh;yI}mlpQC!p;=6}B=23j3*or5u+(Lipm?Yko~FE$&^WW5Wghw8RdJ9wNE63zasEV8zBs60EAaSWi#a z@|CJH7U}u>SGc#hb3{PLPQ(}+)9t<)yZ1^)I0~3H;H_Oe{&8la|ENwzJ8rR&_~ zkIt^xlalcH!p7w*)D#)wktsIJ%wl<&kSGOI3RI&~(`+m7_+XN9BF@Y`$4#kCCE~4c zo^=Nw%U-$;pO>YFC7zPp#*HIEQfIwE2JeH5%y%OjLcv*5awUn`o+-f2ROp5Hl%7SG zDL+scLQ3o_seY_PljF#v{767$(A|Ve@3ty_mc0K>ckA_s2LUYeqFi%B@ z|53{%Q}knR4h`ucZw=NE=Q}0Un2bZF@vwUE#}h=CE+Ik>=?U2DTr_Xv<4MA6C1Y;) zt}cv$z}^5c{NtS@Z<$x_)D2lSwzOPD-41;pW?ayCR-%}|sbYX1jXr`0O13mF*q1)m zZ)Bn{MtG^(QxZTtL z#l9}v9zCf2!F?r+M1KD+>N7{qOlvnj>&?V^Ox8m0Am1%DDfmiP8vV$All2Po@|hzqtb!Y8L%8Q3y=5W%xQeK3xHg$ zxA*wBySF9E?_i!!;6baat3+}K6pyl#@Du@SMy=)jll|Fuqz}rTul6gwf!w6RH+sDA zCvV%xaSomP9WRIw>wi62i8-+H_Sr)!J|75M0(f%bTL@86{U7=I8ai{G^KwNes}8DPU# z?^Zfra#Q!mT#ylQmn4~qswgsX=1ZjFE0GyIcLu-WHd8<^s8j&MFv=?G7InlE6XT=E z)8VyLdv-zCji!(xK%Zm=mLgnYVs*$yPiyrDYCv10!kOg$6U{uyEsSwm zslcD$3PUvUn6tp4qtff(86X2M4HYDe-zfST_6dnLmgaks3uc`7LG+PN?8uOKhb)gK zwMdCY5960Ww@w^p#MXyf7n=3YEZ_O!JFLp?Gd5#K13QZ0xwNb-NxVE*uvrUP2t^`g zAo!u`!Y_T2BWTRl^ZLyH0!IHWU3bJH20%#gLxLnN4BYwbqB0alN=ZR@p*l2pP8^i7 zY#)-r89QPt5hQyAqPYD0{FX~1K~lI7K}B6X(8EQd^RXe#a@esFW}o-A#7??wEV=cT zPjB5Xfe+!48h`_-%^;%+!Ac1E8xDs6cslU?Yk(Iptpeu_Xc3xqVg&)+;nD4Is0l|K zaIuKA{lwu8$;@QiEPKoQoQHasg`WBd2e2#RP3*$;+O_(Zn|V-=<|1eRwHg6(>(^y^ z2A&9P)cl1DUXH<83ibuvl8lF5YjD8H1fU8sH_A%Xgb4}fnnpi8AwR(v^C8vvQ&E}6 zI~T=v$x~Suw`!Wb4}xo)QA4Qf42%TC5^8D7TnxVvOCFLfZ~I@$xy-n_AA(}oTUg@M z05Wg1iL}gpMxZa}NJ`vMb<~ta7D<-=x|?ftvB+cjBGI4q??pKSq3d=6G;~;V*#1;9 zmSFNC9OFbIdln0qD&eG|DnNtqkay0=!w>y}IXttV7Ue6H*<)cvGBZSHeKmxSoGvMH zCnA)w7g2HB682C?FV=qzKZ|or;1=cZYO$w@L{( zAR;XwAl)FHf;2-)NjFFiNY}f^`+cAHe|Uem&%MuOm>JIJoPG9Qd#$zAjP7*72}ocf z9WZ@n_4dDy_>Wh#2-_3Ahsr?K1jqvj#US28ZOO*Q_Ta4{Hac^6-CBYI3o=02WDz7> zG%(W?Qp)MApgoQjvG?N)Z)#!<+YHirTalP>*StUZcU2}~fS(~0Dv;m*gu!WONaO93 zuR{?+iLxL@h6ex}dl>TZz@Q+0x9tb$nk;}w*DN3mRtl(EXm%NhQ0KJ*ZePj>uK8%} zh7zcY2pB)MQntobP4}y;#QXOM7{KJI&zT%rek}%IO9c5ApZ(lb0AJ8|GIZVe2aD0n zr{>v4i?UR6lAIilKG8-1CHvrPKlK8VDf$!E#q7-S1>AvL|1$y6>*toOY!OvYAT}Y(4WSO_S*ViJ3nF>mo1{!o`0pbWKNUerfvzimD*fa_4*x*8 zPJ36BmB8*F{`0bcRDdTzM&Q%5lgT_dX3c@t4bmn1jo)R%!`bk-V3(%1q3>ei>q%bm z=z0ZWHDE4*w-~&cDE$9Da}%Y}>h2Z75ZtoHn;q)X&SP|4fJt4Gz7}R0n_%B0Lx;okkbI6v|GBm#NURVb7PGtsK$erNJ#HhFw;f%n+Jq`vCMs2}~08EoC3DjZw_ThZau0wOV+5KDah^ zIf|&65-<_^zOmAx)3CLhm!cF9R{(^29_^92zh8cA!OYAI^*DHRY1ezjK~McAshE`* zJ5Fs2v!4_q>Q)!6{{qw48iK1HDSXGppMKSoF!;6sd9?yjDXRUsfS0rIx~F8 zdzt^rjkY;_9R(;qC@BBkd>_Cy8FGH0sDP&!+_2^GSIa@-=TZZHIC=T`!X=koLEG(N zACWzzva`tXNQW+cEsI5s2}cM^w=f1u4$gnxKPK+(kR}GegES~cryJVZFm(=H2h3#@ z_2)@AXBHLH!=uCacS!Gpxk&KyhXDP6UmZFZgs%+uIWwW5g+kC9>B>}3F2&3}RFQ@751CgujT6)WU?PEr)`0T>H7IO;kjX-B2K^;)nx2l-Q*l^Eo(jnqN|R ztL>KmccvXW!KwDxOqLJ}ZaXWqWpa?nU#ePNR_HH9MG?Ra0BUoyc&H*OA3FisQZlwq zo^YM;UsePjqG_5111U~mw1|2kca>g0M4R8#kj4zHL&7Z zV9tQcwC=L#?Hl0ZDgoXXXqRe8VI!q!fowpR%vw}i>onf*>W012>Uax-M=E9CQ*C&3 zIR6r@B>Rxm#^YHFnL*8E66rx8iUQyb(2qHZYHrycS~dq5)I>5+HWK4WN03F_Qti5X+lN1#*d_}}yUuT+tRqymafO(sHQ;9J*$;o-mx^ZeaA zGSCcxfCG|NdIBj*Vji1lP6us9y*aB5X7fjgk!54R-++)ct|}1k%?+N7rA<+Q@F8hA=({)aA!&3WGUHhicRr_65s^~Hn$M2r=yHNO?t zkus}iq9^}r{+Eq7ACX3JNl6fij_Mgrz&wvduO6(8zI++`4`Wa8M7}pm7;Zb9uP(o%a z!>v&v6sj)z)pvJ{yk;^iCuhg=FEMu;Hfdo*!5V#tLzml+Sv%lfR&eQ>eXd6q8QO;w z$OydWO+a5|a-Xh-o%Ge31FQ_U37FmQ+3&u21rO*_2LuO)Dk!}ma>Dt*4SIIHJpBDX z7!&$LV^-zP-jeBxYb3z&0!E}x+R`4BAkb=ri~wFs(H;)R8g?m1oV4W{^b~(t*^Sgn z$Yz#01M~o$Dxw4=?TDG5=Pfd5SK$d;aV>rzBa$Mry-5!07dVMfv(eZIeT4>1ioDqw z1qgz*lEje&=}X^6ki8Ep#u3w7w&cHw@RH5r0hHJ|^0KT2Z9QbRuH>wMssW>xA{?_} zI(%?-;x7phbUf>NB@P0w%mJ!Zwr8yj(4Ek$yL_7pP(MYy1geA9g;qXvOov7B@kuU3 z5!aJrX^As}&3Qz&{*h&``u$K1AiU2eER?Re8g2PmHWL8OExqKWGEHCa`D3n%ls6gX z(1?Yz3hjT$xggf^coEn)fJq*d&;<%WtBmQ&@7;OpG01IjmNIrIY@tm#Xw^M@-46`{ zp=nn1)53v=-WEGVqzAV@Hri7H z87NLVW61ImMR-NXwJg$2=ZRU31t$TZ_d?ADEpfmIlEm>8U^t&nf-+2dZOXnBQhijq z0z;K^7%9S+qfH}5)~t1?uh|il;IL|E(pA6l7<6e)P=m7fedgP%VUGu#69J-udly2# zH0@xlcNsm-UNs-vX4+%3XG#RhDo<6W8tjR$e`XW_!ZVAk$*V;YsR^D01lY`jGF!_} zvubR*0h|k9cn2_GtE(khVy-kU%HOB_TjV+FH*G1dLhyYrq0aoBO)N3(0v0!Lw?K|X zr)SlDw`$S`q8!|xFdG+wCXbhjJu6@kkflK`3wnFaD>MylO`CUE4gG9{WU+HF{1jI!B@;5$hNU z=1)phSmymzJ|)p-P15jMbcF%5KGd0MiH~w;tZp>|OUZNEJE$cdJKlmZw-7CY+ zCbksqetuWsW?-TNBaI)vWLcFE(Dwo72mU0G4*;^_)!`v<1x1t=qK70gNJipVhm823 zG;O3q>O`#eyXbSR#`0N`I#J7{jv+oDhL)P;$Zi%Qc&p~Wig$D{p}h{^C7AxY)lDJv zbgck=G4b(9g1Z^2AD-OK9&(%guw&v)N7QVyHQ5wF<6220d4U3r!cuKu9SR-;js{|4ZJ&GISa_{emlLIaZ*FQ9N!Pdfd_4G}p3b>6x z?-2^e0hXMK6qDA=>rVii=uw2M z#POth*;3+}-~GT>Dc^RFgNdg_DdzJzZ)Ol;{c;X~qXsQi$dD6wI_|<$&`2Q8!ru&R zvCmzPu2(0Lec49cqx`ebrVH-Uvp-X(zT2E#cABJ#&)fd(si5o0+8Qjyu%y1pM`#afNR17#K)1q)UK^$ZO_zOotb|ze)GsG>o;LTGVL#CzpALa(>{Vt zmRsUlrDZHJ36LeD`Jm2h-^Z--Qmj$n)RI{=4BfIvU{xU9E7h z1!}+!tg0UuR9&-mcHRrieK7tMmKfpO`P&+Fd!O zn`EvqTpMOGXi&CCk8#e;nu<)d^m>;BO*ZRVm1C+0vr#1$q7o~pLFE|jwj~xKJq5Td zy6iDET_!g@eGW~4Z;A|1wf+DBW2`eAQq-SJ&%+KpS5Q$0v^ZRhyd05N+MTKckAdY2MLl{9M4hVsx9JwvQ*~a^gJ4WbR^q@{ z4|Nt_WX_|h^=@lcpS=2CH(Jbc$_88+7I0CDftY47aJYpF{^NlCz6Lu|&HT=kL?54B z+grQ2$>gsqdlBVBW21r!jrt>_oa@Hlrk_>il-_-OM`{6}*nA5iR}!up0NdwlIMxi! zGzUF99WMN^J>r`e)Z@~2<(5&3ePH8OS&418oL;6M2zV^=o--$)p!f6p3Zc*3v&4UI07vKNmiP8RIYj+CC62GV<@n4DA1jzVR;7vRfyoxYyBXBj z-S}E8JU<-1^wkVl&koslcyx>Ex7C}kzmX}v(}!V}A<_9Vk|h&X2P989t)-}~`Y}nQ zi+r{+6vF66 zHJ6}pglRl?6Q~{>V9*Hw8>92S+~FZY&2{_0#|Kl;LkCYt7kKRzgH4BDgM!I*B?%Iv z)Ponj5LqcRrRv*N>(2#`0eH)dz8WS2wGtEnzybQI$*`O9jOx5&nqo0iWI(*}z)p=E zUp%E^utU8eA>M|qL6Ih!8M;o;GUfPM=Le`Iv`sbj=LcDXjtYH@{lh7&+g9Bw@gzbs z*nX{<0AJLppmk0&_<0T_#q%gAh8Ib!Ul(ju*%nxR$7DV|rK>p#^0kaj^TfdWzVrQl zjg0ZPUKzch$d@He1DbEG3f`AYrE98UlSa}5D2%XBPKP~9$EvR9wXUDmkukb$>7)GY zk)ct$GRdQ7ylXG(b-)T3>U`ker^vULTDCXap6{?V9FH8YTDV%dTlT2ZWBH%*K=dyj zS0+>q&66Na*CNLaQdX)3`9wFw3V^M%e(_h+HQJta-VnXWrl{QvI^oRA!Ai7talv)Z z9+EMM!OkOex@%@;ooE!)`oA^2<)nj--T$TnJq&U=I`TcAWEa_$Tz*E`K9whIW?EUu z{xwm9@#D)yb{R*l-oB|RfsJcUcgRD8Fz z>sm>bSnj(p95Y)LaNLE`#n|{-47tzoyv}J1ESz_m&u2_+_v(AO;>KAcGMnrZcl~EXzZ*$N~VKY?O~)W zC(p_pD|~xf2~=aw?P8b zHTP9iR&EN~2|fmTa?$tbOx0X~5x3pSm%FD;^yeRqONB4KIaK9>l}M+y{st9@O@-(9 z)JeRlHSDBSn~GgaQQ^kv^Ee-`a5gJ0cWpw@hCsGEV&eFX6EP&lVCIku^kuM?%U1r> z??cpZ{^z#uS(}I5C?%>l594w&;+%!9SUDh-z4t& z`84rdrs(jVItJBRieY7iec*DZQ&^N41z^|HTQTr*=&nMXA6UgdX|4Si$U2CcN%i*I z)$B_Yj%fwv*3gC+vT&a7Dkq12*7Jt|G2lZ|((E;-E@(4i zm}IXsqr~d69c;M4XT=CjXqZq?(4ZG@SCccc2JZ~`EJaMKsqX4blwS&h)pOyU4{5Sb zx?c=%GjS5lxI9L#yY;3an_5H5i6|{FQ9&J55jiPlX}wN)fi*e$H7NPajrWQUF642LcYf|#M6iy#0M{Hm`oDkoHzxsk z^A2|MAF3HougFN5nxH!LbDwjt04NXm<3OoI1_ZdpznoFeToZt50UFkgrn9A#Yeom} zZRfivut5NcPKCS;bs_9HJ4ZPQ)S-;WWx=2ksN!9V#G9@=!9>6BulR6q@Gkbx__fsyI{>4hi8Q|SR2yOr zF#qWKrjZ}TSD419`@KAH-mq6z4 zCd4v-4W<04v6v;f7Yy#9jY2j?J~Ns$^Q@4~o)zi`x1%TTc^aaWa}+pse9Uq>c1sdD zqa?v~@bcl$Vi#S0VvmJop3NnA`=j;<9x@(Soyp^xNo*DF{-g=f*_19L4gj--SP8kjmj7_rNbm{-tD))NLJ8Cl4*Tq}HoEHs^aA0je-ZI|AiC@3ZWzYXWPcch$zQ$X6 z&b+`Rv)nvnR5?gQs3O$~d7!OD3@T_3|;d zz=_IvYTGs`RcIOiE`t$j?kXqhpz#eDopDx`)je{Di=WME z=KIr>lCtG*=J623pq<^X9EnGXg@R`*}II=2(I&R%8WhWLn5c(N?S##v4 zUEZP3DM{!2#*-^quf9CF`|4pZ2gGrpp_|SfJh!5}%QtNM0O~(D<^p1bK1Z3yeBT|{ z2%NFf1<;k_#cmL<+3q-?IGEQ=VnV!*Fmn-%lt(1XbeyrYe_aJCoZ83C)!etlK6MSc z<1{y-(eN7H`aE$3u&*ewY+RuBboM!YFI$zvR+A&2Z;PVb{cJ(eCq)|xcmXOjc~jr2 zv2@Y$mlJ5tiFCDQcMxO&iixDy?i@!XlN(_t0_$o8EBS1zpeetK;VLX-GbDZ7ROCB4 zV|e1MJCz>Uo!wpFZTHgsH}?V8vID<}6aCL#-;#u$a!;Wv#!W5R%uugsrv0_6?^(?? z4>3;c_vsau!MLQ(9pzTt8Ia8!;YM8<)I3{*TlB?cwBOv$sC(ufrt>~dd>$=6p`qLX zcQwD2a@UZmQo~7sL^}P|Y7DXy!8W&5%G&3T)Qo2rFjRvO!N8Gk_w~5yTS#eJ5t9;* zt6!|8Uh_Rrcchr#8i#^(hWcWG+G%Ue_v*an~7LZuJTu3L_Y)?O}dWkVF1c+u)rqh~DsSISX z+q`1425(utYy(yUgjz~|RIS~I&)p9{u^SaRG_BL+jMZRtIQO_7+9JkA{JD94E_=sG z^eJT|jJ*OYQq^4c`sQbHZfm!qQiHK&o5!O`RvQ;=&BR$^#=nmjWbnLeEw)c=*f&VjJ2FCqZ;Y7l#tEfH zV}|Phon0~e()PglgA)mF`1&$|`a8p8G<($@zDH6B%N@PbIb6aK$y!&cGSs40iRsTa zfCE)S#YA9y&V-k|acSd|pbjQa9H0Ft65n}4Zr#{ER8_a9jyep5--TLA$R(k(fC{hK z+ZDIX6)+>yf^P~chc6m9nncg`Zi;wiAwZuO@za}3RfS~y9^MDu9z#I&hkN@aWNSLi z3Om~N*G}hN{DFVg*2ncEs<pq#(R* zzdl>EcjKv8zR4%x9=q0t$=z#V133i_QqR!q7{gDB*Gx*HNR9VG1Ly?!p@@1SVSUVb zKdoftjs**{hK~z-^X#eyTNg(mIonP3w=cS2H`reAVjdFt`qGK+qF8+Pp`IuUcS^OH zrJ8loSXl$kw>p67G|Ph) zVh`Tb8AJeNohmJ=U4mCb#wHNOFEASfMuPb=CEeJ_^hz4p^|Ce+*S$=T$; zmbT4|jKRAKl^EzH;-pRHrTpDejRFk4zkaW+l?EnY*& zT!|pia}qYLAu+9}vu-h=AS<(4P!xk3e47#&5meh_EWN(1v| zn41!h82EKiA?xiH-b07SZS$F8`J~2g?tXxx_>V1i^8?Wu7*iAycf<|cR?#z*tcX3c zSMPYX)8xY5J%nE@*gebG*OXZi00*YaJEI2Pp5)3BNU3T_ zDQ6Aiq;_B_VPAuc2$SygpbRVB9LuyYgWrc8F=^9~Z}n}^hGW#+!R>o-Dr#0(pl*Yf zFrWQl_Ar5>`?X28>H>v!OW4A}$`O$ELpxLpng=vim&^zeQ_t%B+nN^)-Pb7ui`Uo* zWtsc<`+uxtN(5_%upJ%K>}e+UJ$aAbmL4K947vt0Etmi1$Uahgs-Uto^`&l^AS`1^ zGRR~~lcQpctk0apEkpwZhQNBwKH4TIxmtRYEb1;JZJ5P>?WM#a))prk6D=5V@~#| zGVBUaP*$OeC~yF$fHJp$dKOkzij{BFSrhw?N6g+hE+h!M*-J8(r#|5a_y2z9F4thd z`kX6YV;=Mb04{g;IIuv&0Ixk%@`d!^iEbUGjjV~EM3$#t-MKS zIODv+M@|C8pzq#EBmnB|)2G4p2;W~B^{6!N^PuUPp152M;LtY$F%PcxnqH$9F+Y-? z`U(3XhCU##&jja*F=op1CT(<`p6IDBh2P}U3-!j$DXy?6YPlB8z zJf*e6#(m{1oZp)gaL8%gDNz)kt)c4#?@ly@)VHtb$8lbz;EaRmiKo%ZR?w=M1|YNdJ|hV%hNQtaW8)B|CSg( z`qAK#I4W&5A5%rgPu zTFa4`+MuTR^YH%qgROmqGX9sQ9NKjrQ838C=h!guwD+Py_`_dY>+~W;?yQkpPR$Ew z8ydJTF2+U2T%~5z)gSLv**;F8$GX_Iy=7}|X*)QUYkpqi>zQa(dRs=#Xn*6fmE0P71YG^6^W$Lb4nB;|47^b5&Xl6d2T;(9MA-6`|mZ z0)g;^F7^A7HKZbjWm%s)uiGZR>H}5y*2=I+bV(J-R+1b?jdp59W@K>6gOflRk?(5D z_b_o>ZV|ibAns=&E7x!D#C<<;&k&swAYa@lwRh54Zqviv-Fe$*?RS8eN{^Ls8Q^QE z2cF+mp#`hi+Rr9dea)dK(|W?yL@^m9wVqVsv}&1!blp?MmoNjJMXKeN(@t(lc*HZ2 zR9uXOU{EY?Tuhmw<`-J{M1=@43!8hw>+nqs+As^}td&P@=?YR9+N8HbW#ee3cBz@| z)i+D0^0C#?x#x`%TVJHMm*R}lw7g8;K#PHlob%|=ClPOhXJw16c#5h^U3pt1U?l4! z>rNssk=yP<(@DB*KC6h`=o^Xc+~^$TP?g^=e&6?U|9EKhCEy;m|BI%-4Wn{i96bYZ zk1h$c3aV>2tr`p>+?1e? zLXMu|msr#{%*`S*NmG7ub$sq*7Ei?w5l6Q$9FtdC%Ua}L_v2fsMp+;iz}aEU>nxf8 zcaRMnqmf5z8X`vqvHfp7*VYu6*S;io+ihw_Q`dN%{*iO;BUQCMsq%^zIo*`F9FA0H zzKt9EVL#R>2uFLrHN=!A+StS;0tOpQDNr_SXD11Y`0|#hE0eh(l*?P8U&xZ#`u3(M z*g`_yjkfN|CKBYUrh6lbZ_9NLOAPf^ zdDKl={9baf0DCxB!(w_qE0VyQ$H#xfs&f2xe6Ho>gE3nr86x6i^KW(J;d&_g0cTRb z7E*hpvIS$c%L*cL=nrc5vR51ZlPNv3uYe=km)>~?v%gM!;C1oq z6R8cai=KVz39Z37-5fXVPF4%lhjC^u34z|&L1es2ImFtPNmMgsXdGsC9ukdirbJ~6 zffyU3s$}bV1fw8A?=#E-nbufr_9Sh1fhmDA(Q|V6EE%KUD0nQL1}5#uugD9mRP2em zjUHYa5{uF-4s5Y`sz87*^JB?e`F1XWZ8Fj~wl*h5*OF4CCCEG;C>E)~G%9rpuhuov z?hCxt4gtRZx_bRvrl>}B)-%hB99R}Dcwo#DlA{}pC#~f?v(B6`&!}gtnXko~7z$3i z%oN3~Q*ixTnR30%Nj2LjQ&oJ5PJZz5x3x|=PETH6q<-=H=r0pF)X}oqlKlefsLRap zAE#I5D4{4`1A<3^PpuAuHVNw##pqBA{bd!S>MBPJK*XOJ!XP^X1W8j|TsGLj7~ zddCsv0+L^U5JA~CPdGB|oSzzsq$=ic*_@8Q1?rHcQTcgqomOzvO}G5h<6ObR!V9pT zbG=5q;xOQi7l6UTfpf2!O#wfkI_35&2JJXCjW8zHe3zYC@YzBM_sRUh+ZOz0fe=m8 z!8 zbOG_A=75P3sq~&`8}AV1FEpy-QadRknSHlo^~FfqkDoLeavU0UvfUq2vao=BR9}EQ zQ7*_VC%h;vo?_wnai=13rz~ZBoqlarows|q?n3{iQO-{#mFjWw{24n|ND3U%QC$P4 zI@7q&Cyh|4tj=Pu$&k;_t@td`a3DB9`?>XbybV`*t3FSCfqv}TqD#fT3Qnp0mI}VH z)Z$ox+m{8pyU@VTkDpuBMi?AXeRzWJw)o_|ByvWouy9*#T4!n8_64}JTPRbErJAKm z3yj3dFsP{X$XI%v%OF_mtY;C}geD_gors}BnV~=O1&p5=g$60(Tf&gTH!K469U5LJ zsv0~3?=?o>edMG1!`~cw=RX*Q_346KCw*f^6~!~Pxk#r*1ea*kzW{- z=TdzlN;GNlvCtG3S3NxSykAKrcsix8CuWz2l<^r=1yQf*O1%xGZ*AzCynbg;c`u>V z{$;KFz^mo0I{TSKpngE3>xa#9bj77f=7hp~ueccfR`Zn&zL}snG=8PZi*u% ztaoo}(mQK!vNUD>S;F&WZKPd0*~&xSCaCog7cWO_e(diVLH%(nV|qzX#N^w@2k&!+ zaj=ZZRaBBgMHuFe9tO3J^xC1NIN*gaeL?DXI?MIoTrV3i*zCrKQ?FcW1P-PZJBpO&wk*KEMw(An@7fB*Oc`;8XkQ8@x0-w zZ%r`LU~0!yPfs~cSH&i~1jT&Z8m@ZSc~Ah5=n>`ltn7KN9(h$E%X}4-^R@RDJEiB} zWVad5LWjT9H?LoC(dTr_*TL^%5zkh>U>r@+2U$xoybSsG(0#j zqfD2)Rq!}RJ81}rxCYSkgxQTX13h=T?zr%~%qmofRN2$%2-Xmv{i3%d8mUC3kzVpY z7W?39@}<1k1^?Pkgpks7qQTLC!;#?reOdp{`n0pJitwVfgsy ze9MO;ZUJ0VpwIlD2k=%|mz$8vEP$yLG3ng8?F$yQ&a^)~iIhh38DH-VoZn7%(_bUF z-*6)PS?^-2H=@0dKC8&Iw>9Pl>L;`bworCJW&)_^C{E64NA6-bST(zvuA@)pyiGKA zLGR*-xkDQ5a}KgrhjHe@Aq>y!&ik8e_t&^ruzBN&FMBPLV^0gDM6lX!1nzyWKBB$Q zyO>lsM-?LG8p5qF<7uVm?24XF(OfJiBWLW6MO4n8%Ejn&Rnh zZD9U>CKBn_EZ}+lR$z@x)7#d3`^PEU=@pM_y%$&OB#^DKzzojsvmbScoeZ1Ad*md< zfGo04^?E0D{K!HQ0rR_ox({+IxxMl`zC0Z(>&60~EH5eNyOhA=eInRjZc~ypPP(j; zs{%;BF|6;5pwun)kFy_ZZF!UEVGI#l z5!fiefT+>dn474dLUpcdZSBCRbQ0+2LV#MZ8+&!~^v|bu)aaPeJ8Jl3bup26=kqyHxbEIp-2;N_APL8)8^fe zgP18^rIFdw@14mF`m?*XnuoLE*i1JGnkPCOzSIyR`@1vXL+rZzP+6z;aZh^nV&qXUDm8R4T}55$Gf1W2c;U# ztDaxIcG+IRU+jIyXRz=qR2ctyOB$| z^jOdquNVhoOG5_{xdJ=i6?edqihrV4#NvI4)f#Tt-ISG(6>wO=d%VQyhvI2%4+9u0g~ z4hQQx^vWn)@Z>R4WL`wTPC)fVP3pt0@`1O4!bBd`9#wcJ$HI@F*D3H z*E~PI9EsIs{@5c@dnM{1P20R@K@A)}fCo7IW50%7p`Bp%kQ)Iz+SuZ#=gN#}FlgYt z@l0YuwG+Cy84HA-0^ZV5B^0MkUN{okyF5P7omWgD4S9?|8;Q>HTVQ+6w_@4fiuU3vlzc_z(&v^8W&P|UmI)JTh_Ai`*o~0_b zBO_B9oJk`GmR?jS1K2NtlITG6=y4m~Gp_s{t!R;3?1QR5#fiy|Cu%e9m$@|Qf;mtSWX!*qQE)e>ma0Glj&|;(GR&?}3aj<}Y z&8}F#=8{vxphk+RYbobbyp#e4d$!2mXgk-_g-D%6KGC?vg+;Ca19Gr#Uafjl!!FZK zK)TGAgo%t21GfPVo%y<5hK!};2}W@G;&Rs75VuHF!(~S*5sNn{P`PsVmiT@ zfE>mmrzi~KGVdAcwFe1YHXeF$GQ0vII5JwKJ3l$q&=@nz(b&Kzw{cpWI`4sJ4rUy1 zNMSWdGv_{2NG$$5`P{DTet_=w94*@js-)ncx)YgxO@b9?dTFVBxrs@3BN&OwIYk+= zE6!npm9c{}Fswm^)QjZ4+Z*m#b5EoV+(c*Xh{4aM$s%s6fymfr@rS_tRG}tv<^%+Z zb@4yg@PW*0?2Zo#E|^0HhCg&H8SZD#KRiF~AX8?DcB(&-^#_w`GeRb?syQIzOL_t7 zKU9$t_moJ?0zwHzS1xSNtvXkBkg8oB(F{C#oa+_HykxMjgR#)y|0$%4$DsHnKUoKl zTn;2nqE=t(z@@E}n1{k2sJQe+}4i?qq%lqb7|Gr+?y)zn7N zEo$hZ$ET-hrk6ucSuF zU)fy@Q$mRkA`9qw_ZDID#s(uOV&_QiSiPWdl;9lK8&^? z7MN*G6;9fEA)qyHDXP6FS6}}8p;9I|(ZWtz->1{V*f$5!1Qf79SP;^nNz7%RSk7qZ za@Io-Y{lIKLt5YCy+`NGYJ~kV2v}&)q;6>vKYLFnj?s1<_7D)>c@hjw*k2TX1F}=f zE<29d;24Q7YQy+^g(;L-f)QZw(>u*#(`ZCCm&zs;*~R~z_|s&h(g6btqK9!f?Lyyp3*T`f?C9jGH)u2 zBWu`=DfK$Zrw`2TpPrWU^}Q&+wSnx@FGlxtzA>3|EDhcfun{ROF7`WgxkW02OdbIS zljOH2Gz#!1w#XN*MTmy}uT@-eVGs>XV5q%;0$st?jgOdq+|2eeL-FS)<4QSIP1sU?fn!rKOq>t01E$q6~d_Az>UDm1(l&wn{u2^RtA2Z6Jb zfMf@n*&|JZqBe2Y(c;C;!Gj$6yxpa-t7t#zT5p~Jh!rrb6MV^|a-6^vD+XWL{j?Wq4kvgK|-i8Y&On7EY2=apM6L$SW>oEJJ`;Jw zsZxJn^LhF#SHs7S14R6$zyP0})#oR&!$fxKfROJwM_ZF*nzW5tP2v>p@-uHjeV(2n zuUSu~({rL_K1c4*@eLCgOaOw{oBngzv~TBe;UXdo4FHd=V&$a)Wojp|3bpnjEeQI~ zy#NNYqQ`$QF3zQ}rF)3B-AGQ5CnqOcqjxm8CWH)0y~JB;Tnaya6q%e^+lTd~8OzXWptsMWFtfy1^`A^dqe zsS|yDhWOS|@PrU(4k1AJLb-Y6;(n$%3CNHVkSJYT#4N9#sw_^fi(fiy!ABc1`3VbR~@^=v04N=qzNY3>;;)!C*R3u|LJ~Aga-V>W$D1E9=RK&r@L^heHl5h zGB`li-q~ojrmO-&*0Oi{Roe5vtn+LvgT(A3p-k3HXlv6q zoE&Mu$}lmDck+?RLbDDW$w6)|HCh>p$d!w;2>c!)!O47Bc4_~`ZGm|GGtaD;oeS8#tPf ztbn;njSLmpcYCwUWIRfXw2HyElQ{-uIqF<6zXaR#iwt-$!Dkbh9PA(5y z2}D1GBO@>9@joTBd4pLL^p#<}>wl!oGR>C7KHy5&S=qiJ+P}VfW2{(1C6Dl$j1ric zYa+j?^1jc^{Zc=1!yg=|LmrVM4d7`2MD`T&EuRLx>m>&rY&g)?1D+Q6aR6B~FlFA} z0%uRa9Vm`|f@k2poJR-^4RIAx{W?wFEL9mmd|@Ef95j4#i?Px}-hxL3ydx;YY;Ct3 zhi)DzQHux2pET*2d^!TiYiAe)WoV9Ykv%22 z#)6y}47otx0?C0oml?J?0KSXBR3j$ceqB*_!HkhL0v!0Gv0*X>tasNI!Y$+FOeJQZKKLY}&8R8DK{gCR z*Oh9BG&3$15aMxb0w;4)Nof~Do@S>;vi|wZBtQ%EY;MJLi9fjg6|9B!_g(nO&OfeH zPp$M9*GdEDRGuEP5H_4EH8L&pzwG$A$o5;CD|LApR7gf>)qXLk;lODDtbw8tpd=_z z+%JjJfbRJD!ylcUSlP-Ua5tA}UXvzsAt>y6*IY37-4YrnWj68!D=>TJ=#y-jNjc*o zB>f-(h3OYy&-3ba10Hl$p<4{ZzK-Rct2Z1DsRD8DMSe?~vs#tT?Uisee%50(K{?0; z!gas`LD2{XE#Mjgvd;MGb7lu~zL8|{ON%+O*#kGo0zQT5bK$1fXcwry-U5#)8{g+c zQRVlW*+5bPD}Eax0d5EtABcnsmOzkL`#Sz}7t-<@Z@CQ<7Tn1I9>BVQN4^~&GZ1X0 zKY@DGNe48kU`(xbB?D$hfMj8R>>aELFy0s$LA0G zD>@kgLoH_EVtQ0_r(jPi2~5g``wC0&W_E zR{o(&+$Ea%d}Lw6S1R-KZ-IhEfBUjE4mmO^tS+q1jp6}1oA^|kegMj3?wp`Dwhs~w z2}YkF{{}J_INRi_+E(@2EBTVi3>Ja1%#jM*vgPS%#xp7I=!}rwBD)vtNy5rSN9!#@ z2|szwMjzGmlT!wx?F!Jo!9f9p^JNxsKkVW@X0n@s-+%5tnor^V%Mi zNHj)5MhO97&C$)k)T%1%>z|Nt&iG~aM@>;`z;ynOMPN8ExPf|oh6`e8b=KnXQ!`wn zMA=O3pth|0B5>~iX^OwmBPQ{X%Ml-le(p+Ov^_Jbh&@g0{dL%0-}*sukkV_sb8Xou z7tGC9T^v{7i~8TN|LNc_941_;a?lzx9RY4e{-UQseTyh%hyg`+Jg9>e5;a@pv zk}|J+h7TXyZhHd_N~C(F-r@OtaANgxRSUlB4nBO-VuswI-&o|x4HZP6eOzrsP=e%i z5_58GzTbb}5bcC^!=4v1Jiy0>RbeQ<}urt&xYgf`oJ zUt>|=#FeX-{?b0fCy+Cp^9xJj(kGwb9L=aA_*es_o#$wufVc6c0+5Aoy9s}LX`ka0 z5_;SMP6WZhH~;+!Hq>(0;Kf=4%yHv5Ki3Lm@LvLEE z8-&7Cev^Iz6q$Jr=!YAHwnl;FsiR=@O7O=L59p`x6TTAo-wy-+{gATV#5~VN+Nz|w z{}&O@D6iFwqxI%R@8#*_PsCLd;BBDNBTW3{W#`ipO?98ImZE*G+9Kfp$>^YG;PFL;Dh zHXM`+N3HhQdTzNWdwtdM!@IOGL&M7rhtUDprHmQ>R`1`JgJrlK{^{TMfM5GbO^vpD zgpa&|YXA44=>Hbt_Gd@BpHHslAT~T zg7prp1~{En(Y&31OE3MG^z={WpVQ&qkt0N}>KONHE3Z4r0!G_fqI%1e=T?b8_C;0k z*8lq*vG>c7SHm!0$J53vD-)(-nW0aeOxm#u z!QXg%B>p|B_scO?!-5{fDOJ{Ied@M3mG;wb9J&@&_5PjBg!iN8|9ed^yrz+Dru%be zcYI(~hfB7T?(AHiB-i6_w}D!F%k~iZN4bW&ihO_o?5`Q%M@@|5;MOy~l!NkS?_N^@mjN z@qa(vl|$bM7;S~-+Ios?w_YyK{&^>%t;+kqKlBm&uGAtyh8ov^JM2=D$gYq)oBux8 zS_-3$+Rj38@#nYJMfa%Z67?aMJ;lD1tpJ&|9_xIy_#yDe~Gr0DZzgTO{x#ld?0A&x52P76RQoll-KmdK$ zIVup{A!49F2A;)`PrLc!i_7!5*Zv@4)d1ZVsGPt$n8|p91ujKvJ4^;4eWWC4IsFxo zG~yV56`x349#TQr%hi}+g9R%EkR1k%q@kq-^Fr&xN&l-8V3Vl=>P4r8KrZOxf(Wcq z$L9CU86{<_-wS^W(2!aJbOz{1U@i4H%)cV`E0jC%2oQ-v4AR%v_p4SF>&P7A+nO}~ zJ*(e}Q6(!#|D#gorO24aNuL!n$Y1$_ZVM=l_x2(pzf<;t+CZ#=E&}?4 zlNt4jvr2B0J84epq%+|5#XL?mf5E%}6u2^dgM2km76g5XE|B&Gq3&_prukf0z{EhE z;R{$$$et?8LJy2V{+r)vSJ&0A1TJnm^WU1a2Op3td)Y49q?wL>U?9q6`%#M`l)5kRp<212XGtKOQ#$N_;25 zxhsN~_bo3}sBp9@gNOBkZvbDhoT!*6^I;9k(V!fdb{R(aw$8 zGkJ}|az2Rw+eR`de&XZfBkmu;k??iT4<-n^AJ;dWFp%qmMn7t4kQ~h}dKsih?dUUtx z%t4^vR(+?YVpB7T`;YHWw4~ce)TIA?mi`Td3Hd0a#5rO6500o_V}u4qh+BcLVGwf( zOL=(%=fs28SqmE^HoAM}YDh_mhx5%>5sDWl-kyUyPVA%?BZMpd;F5vya}x?1vF$yh zQ{%cGC5gIwFYZ`%ha~EbJA7GO-sv5fFmd4M)XJ7F)q1L|3=TD$v*1)oO6QXTLaEZS zvWQ}4p~7@e{8_IPtTXDMFoyw_?ZZl{5aFY<>*9VlB3z?B@LLW6k*WFpdFr|V=s5)4 zo@-%^W;Rait#=kD(GUA27{0nz62xS({hXwybg(sIZk*rW$2nX;tGtf;EFP)j%qAmhWU`K1(B5Izg+b3@EO>7c_ru~ zsQ+O1riixfS|jCu^8RBP$NqC+M$vi4ehb4EWy~Qc2p-RwtaPuh&O889I$qwuc(t|i}Fnk+eesB%vj*C0aK>&|+WYm@| zpVG)y5l`*_*<)o(5X%D}g{^uRMcVL*NQ2?Y1Ji0AsB&*?@D|3S?pC!sEZw^%;vzv$ zT_p<&DEj)3-T2{XJU}yOV%tA78?oX0S+KsfZSJ_rGP93KFmF%RVrOqJbic0=CBved zqQx$6YWe(N{I*waC9SAb-D4IsxE2@;6-cC9oj6pFg082O7Yto}^Aj=WuL)@W; zZ&yV4I*V5lC&ypjsQVBZAlisYI>W2;>visZC|KB+YI$Bm)&l-3luWhwkkZ215=u%Y zChT>HX_&G8X--Ptfby6diV)h}yk6h4{{BpBL3A*Bcl!wCag_e8t*)iN_10(VT465% z&EE{TAc)!Y$Bw%0;`3Ams7)m?bitIA2rR}lSumE|xMX6G4+A(@$IvGBL9P;G4x#G&!g_Z> zXyL3yKz(>VbNRvfiUX^q?@!{g5<}k2*p+gPoNUWF?c{lr+>}v;d6AxCyjRs&v=pE_ z25BfyYk>;A(T<~A|L+wWm*y3NdLteklg>x4h(@}f>ltr}389&J&oVUAXv1s+RUis9);>`G~P;Bomox3%< zA$@sy%Cp$<>KBTDtpv@%yi`bL)?SD0ht%efp*D zhD53HSAONzW;3~(gV@cW{vw%NQ#Ou-84SIlkb~{pgM^?B>}dR-x!Pt`=1*%HzFzUq zZ1?zI#-z2W-hep{r4h+7zFz-3gnVmd6hxGU(D83Mg9*@ig9)~Mn^g^HUAI^-A@0?k+`&V!ILmXw6(G}KtG%33}h7j!QY;rdtab(GgtbNb1B!M4neDi zPG9CVYji;8w_!2Mn6$-uWUXt{OgA~A>v6oTtbNQVNfHsW_ABG(4Bn;Gmi1OudE$S+ zy-dZUe&PqGC6>H2@WWrOO-0#%#ED2JtYg>mTJ6{7DS~zJ^LY{$E(&0GtH8+ma7Ia4 zymv&PvJIL1T81`$4?q|{X`wa80{F#01`bRsnn@!_dP=9pFCrP|jFkMpeF2fF4w3$; zA<-WzzjeyVl?T2I{p>Ou&9@^`_DDc=a^6$lgP8nortVO0NXNI4r(& zg%Z46wLEK5Ir;(`Z(|oM?Rxv>UB$C>s%P}RU?otdN37j2w3Vi(kTSxIm~vlV^))G_ zkHM@qXG(OmbEq!4d+@37;N$O6R_sJMZ4+GFo%Tctp}5+&&^)Li?gs>UzL6bRHAyK% z={`sD91gg6s_NQu=5u5$x@NymuD*>eUPtj3=E!;p8GdbSOkWCY2%*=@`H-HJiGB1rx^54u5nfVdvB7$%E*C)S; zpE_SiA`gg++LjloKp+G7(kZ`f*V1RAu;f! zd-hFwW?N(HmiUP6o@hvO>Gfu5fXyVJ2RDEO2CD%K)>9E*5k~Idbi(wTi4T5~xr+6f zlZI8jH*!dRm6-{CnL<=@p6pN-`v}6bD?8^`C*IpiBV%F1)|^T`<*8OTPS9h}SnNB4AhpRGnU_6WJKh3Z%EqxfOn zw?9#|D{%FD!SKYwB5Sb*nQQMMuK51_d)M&ryWEB06Nflh|C^`L=+B;aZ{KcRPmv&t z)?k1#H6%?vweae$LP^w=3z%e6bx(Y}-CV|H%(R}HWFGFWiBq}q0Hgvkg_5;k`iX>J z9iTgh=nvk+|Ik5xxN@g`ef68vzoXSj${Sz|yd&2u3T%jVV=NV(4k!-nSC z>v+4h0Ls;$ImD;YEiS_3Y{m|BrtLyyMj z*?YN;G=PN}Fr?mJ`B(If3=}1R0jjJF(NG)9^sV@|$u1HIhSyvRLo61*Qb**ijn&*c zUQlh=ZN6dW@cS`%4nntE!JlIIqITE$bo^SUe#|)_C5$M^cX1sY{JM2BeV1|KT(rnz zoX)ZuQWW@;-<@>*SpK%g}aA%g(>I)J`{l0m~-U5ybYQj~q) z=fZ&yY|glYmfCr#RCD%9wLdsStgCx@3DeEBW{^IDNILQcFi;)OCwMl-hXaof&U0+| z5PMB>x+Vxl(E!`Z{)@|Ra+biLG{!Ey?XS$S9^HR_IwZK?30`~Y&DlV7CnTIz9dvvV zBON(8A`nwOmhiu7P#ZsR0vyj5%%smhOHv9XjMupk$|$auaSyYQXe*L0uYI-p@=Ka@ zf+WF(x*3h(Zr1gD8Pv;(c&Y*5hM0KR@@bu1Q zTprA+V)kk?$8gtFtRF%#>pOAer4&_ zG^KooNSTQYT)C=$C&Fj0*L_eX7KaiT_>j+EkF3%AI!^io&Tm>|6#=?cAhCH0Ljr*K zDp!T9SiAQ}q`Mf`#dw!ta;o&8WJaaT*3MFoW<4XC&Lg>oTemt5Kk~$+fte68*8z9~ zK+;U<8hFvcULXKmbjU+KCMF_&6^xPKLp5Z*XrYAojDprvN=C+85aa~r!#&f>)FT|s ztzcxv23A}G@o9i!X7zo|Zg8S~*!u}KA21OG9ddBRxxdi^NlGjLdkNs&2I(0n@PR~w zMvg*OAKY{;8=DMjE7g7abfc4viH)6GUT&D#=sWoa^_nP<4MH9fULUmd3oUeT6`95q zP4my#@~QYeMWMcJ!j07Nz)F4|0=A?V|DapP9R%{NVnLZdcLAUyKnR19!65guzuaZJ z?o5>|s3Sodu;)S5*O8(pU+4i80pO5<9xb^d6fLu<;Y@R79r4a1&Cr4TE3Rqwn6dWa1JkV#HpVjy|rP;(eETr>6{1gmyop}6=!AGYw z4V`>5-F&sr8acWAfYFd;ji|)#{C+VR^Sf1;LNOS3)Khe3>`F8x3v6VOp92lgo5eJM zCrjyETI?@MnAKb2up1`->9Ptamv(Zh5_*@(Wd1E3`-9$n4}wY;lIwgtYOuM3A%+g> zb?rEkyxGamn-&a=zPzzr8yx;VnE@)Rpd1}j%hkT0499nO zbH|Re#Kvpq#nF!R8rXs4!9wNz|yjKFqBKc6QT4phUG80#k{3_R@s z7BY3<)~r~1RsX1w$(^^uWaw%u1M}z4!pPM)T<^je_~^C$ehZW0koS+}RsEiB(Z5l( z*a~}~f&Yb2f~a;AY}+VslmCR;Y;W(d3)(1=cv(dT;$Nr3u&+FqeQ$QDkbA~!^IeDP zoi1c_UZ#FetxO@+%avQcEFiKT9+u4yoGfG`MvC$I5B?YXu_V7jNzqhf1q=_Ut6C7= zl7(^$vdS_=*XH}2E;U>-nkWo-9K}q>px{I2f8akwqQu-zhXD{3^C2+cmH-PKPpH_P z{`exC^qI2q_ToUTRq^klX>g>@M!p)HxUT4*|ACvqaeQMgDHf72nL$(tMh9>XdnD( z+F{x+1ph@~kZ0}J1Ja%}-M4ATsF9iq@`HX-xcEP<1&FOmn8^NYjG>no2J_|gZ&!zW z;X@k@ZD(!U{xr9sSN+dx(}q($ib=CO+QM$+hk07IvvYAN=_(K^bAETadl<(-Y$TXYwOT(>((;TGJQWexuAJf$T>p@`|V-5zDzfdaS zvS~1TMiv<4eE;)O!N~yeF0}|%VpRS=KkMNNp|CFT3G+UjvG-JO z(ypDd&w-Yg)4(2nh>W3f0G4n=~psKF42g3Rg501qt+=F{TY zv-DojOanhZP@6}hedN!72gS`xfrPgw)*A23jMexFZTA}vyRTHniFlU%pRx02%k369 zITYgT!ATaXf57!H0>^ifDZd{h-JVwqk0~W9Z~W+FI}|RRNTcz=yiqlvo>m z@9y6tw`t(kVdny^V(?@FPwKpAHkPEn5U%CR>wGNl8z94 zoB8)ZKJpR3Az+sTeGt0b4sambO|AGDaD(tOR<~&R&vD8C?wo<+y1V5My-s4f?C30E zW`{qc1zo>-*kA6z<7GMK^?hq{F9%jGGd>>P|8wVE}fxr6^x@FDgw(NAkdd;LDxU%>%zVU z>}sgHZES#eZV)(kYq6a6%Yg#G3*yw{L}H3X>8V164B&UEd30NiEjj#Nn zWM2TWOz+KTM|)Gty+J_W;Avyhnz^sTi}0EB05k#)R%8CqZW0|E3oZf>m(2&~LQ)1x z^5@dhTTmu|4Ta#2fgvbqgN~IFBb4{yEm6nIRxQ6ivgMO@cIE}=XlQwAoOJztFRXqK zX5A@DI$PHWJq2ic^# zxg2C_xU5=~Bkb#Gbh$E=9&`*}g$W51R-nOwYe|9F;U$o8gogrX=;oa}^ogD4KQW9s zW$spxThFXJDk%HMszgZ9p~xb+bm^;A?5Wt89`p+X zI|rWpOlIbo-GfmHYjjX+MiS$T40R>=eSvtsk-^7S=kPQ$AQ5tcMJNODk0mFm^H9-3 z&{%RM=t21FSORkiN|Fn|ObG=qyEqPNYH8&QwxtS+;jgTA|DLAS<+v5wg0j!7u0elz zC;O+F6#v5jd32nQ{venp^^H+KD4gjmvVuGvEMcHy0T7KdkjW%pqt^**c!UmP+VLL{ zysB4%m6NJ_&ZueZP*B~RAtZNO*3P`_QIZj~$~BP?Fyn!Y>t9j%N&C{zKO7R6TS4iJ zO;E5Ej0GX926ACnUN^D*#E$9WJdthtF zQgh_~J?ozV2|9kni%I<2K=i5;yPH z<2rZF3yWwGMrQb5r>EZ#diY`7|HiF}48~I5$28ihO8H%m@nFpdYbnS^=BbHj!8H8^ zDA-x3?gOL>I1>z5NLc}G;nf~#YaIFAu6#gqp+X>YdoYr6C?H0kz4FCGIZ@jhByYE( zn<6^M)p-6kzDRSCM@DTr!d?dgM!>yZ7okskUY&P?K(KUjkfCaKLvjLHnTSvmgYJ(cMmFUMjMwH7$JKFocJ34rF%DX!EXhahag=Kb5TtGAIh$|mGyPN zbJmlfpL}+E+#$~08n6*!DZ0R?J%>v~X|9_ud{dPoJ-VM@9sg>iH!N&P+B6CPat#0> z;zQVMbX~?j?Y*C;-`Npwcbt{7()eu?GD2;CEau6_G#NVG$+u)54r?npDTO{j`mT_x z2J}yOSvM&u>!$4cP9WlW^FZ=kBfnadc!tsh?Ap?Daw!a?5A^Aab#70gAAa@A+L5s3 z$LeO}TLGANxaCa02W8T@7?uxAm*+5P>zaI-=9*=pp9+?rn?8T4W*GHOB%jRPd;rKEx{)Lx3uXoA?}gEZZh zT`o64A&=P(S&`#qsr>Reud4k zt2J&Pw$sK-4XUZL40kAcMic&|m+R20O373gv{V2evR&*)X5Om1l69p(i}(Ia`CjS{ zc)7ZHk*KRQWby{a4||AnsxA{mG%G^^5KvMGJmBJRj_=7;p&B_2px6vX+TfUWop5#- z^^(kcH`d+tWGViMZ^uTit$B>7YHZ+8o|XQmp~fEy(P{;vG$1O@07W#Qgw7nT*pLC* z3ez7x3V^|BDfRWNl{Pqu2a7t^!v+~W$#JrG918t-Cfx#O<9h8RK3B(jEzHF3}OA@c77849us!z>}^Yaj0m2)8vz zGSe~ADyl;n;`-aaNH$V#(a zDbhzYvq5jk#E)~~@BKOvszOzIqOC1TvmmxsRzPEznXUyW0Pj2gfTYwjTAB_14hXJb zqlT~$;*$RExpD0B++@nie9h!Y#maMeVgb$J*XIajWv8MwndORWgVB!k$`XOiH?zid#kQ zUoBnMp2WBmKpQb&8qWikvR`j=qAV<1$2^ORHwMB8dPqGD&rvghY&$kEjZtXZ!&eIf z)uB(NrRu)r5UxC4H+m=q`9}CNy&=+Kt=m)89ajfkbDua;!>(Am6hk_gA`8_uunKid zA6;rIvVyHxT}|x~c5Hb_pk%6LmVf70KQsvq*8DDZ9NRF3^anDf0R5k2Lr(AsV1NLt zo^}>)$I*5pvU}ekR#utB8cYZTb8W;G^&z5!{CeMDNC8UpP!eQ}L`KrDtmI9niZx-p zvRr!@9>BOUjJX88D2;6)`&_Jslxv?xYMb zUIshvEY^Z0@SK1LfR9vp{%mg5=eKFAvAoU`F-O-}hDd&JnZpeuoPuyG`e^Cv!S!FQ zf)`jq0HL<^4Cj@W3q)(?zT@axN`;WRoh2{md;CCA`|vO&)Jgap`~~wY#((n`W69iW zhi%n4t5#9JpZE$u?0XvaozhoMF)65~(xF@R)k%xBZy2wP?FX<8@YF?+*!vff#7Nc~ z0Sm(;ty&?|S6_`l24`+*(|*#p9Vh_MhXOZm>29&uJ!?1M^84#Z_zifWN{kn)wTp{@ zgB7~~Gz_yrqYZ9J-d2jW?r5%BdA~R_IFosC^NLvS?peUMpo;*u3ecu6vV|3nQOi2a0 ztGQVSmczINSUglH%Fx?Hmr9l&-AFUbJwAejuwUbs`qWSvl&<_m&j#k&_F>pO;}>ok zd@Vrj-Z|NN?sd33F)ziV%jU9f`{Cj7Iz!c-_nm2040}zJOM+xhewW>mu?$eD42O8Y zVGxYsbpIqf?0u@wLEqdg*4!25(KzqzA7u>9C*VBkGR)Zh6>mjAr8nP-Pgrs6j<-;2 z(&SuZ1l(}RN(LXarKKEp%!I9_G?J=I@=`4eBwK6H$ihYnS*S*i3UcoHuW;^<4qWQH z!>zH(m;^`}fMuhQ(KWQ3l?Gg|rdbu#E2*6*rWq&p%- zO<2I=bhWIt@|j}~5`)&VyjO)1cjISv>sEvsZM>G*9=b6H^i?}oIPv;)J2qlt!|>5wVSm zqcRndlNFYlrJmi`6*;>_rQGm11S65~o$_ou2_ znpJ_C6sT->7?!RT(6Nl(Fn8go((i}-;cznSB|-)0i~NPE{f=A!S%h@mMhU$RB5H*W zwS4oAOam0Alr{Qw>q*>27w_OEGeA?9DieyV+_Y<2%!YF}hp4Y)GKgHe8%sn5Tw7^6 zzvOC6(p1PUxpIcaJDHii`O4nI#esVr=0bsyZ0n2p#1D4|&M9uB28j9PGHGET zFA6b>(KKo52vv!d8&RLs#Z)yAxQFzO+2vaNE13#498u+e$nAOthj))@>pwJeN+^2F z)bKxTKxKikqUE%KG0VWMiIwA7$>Z^`yor+|BJ_H0abZ%z!b21P#+>fnrbuA4-Or&4fi@g+wkOgjrndmiZ7nkJ3h)Pg6Zb4iz{cb z4oNC-7Y{~99=CtJnP`=*Ku*XvYrQqLV-9M5LG=?+uGg4?M7!`-N_zh2dVg&=u;IA5 z_+8aaNM}zFj7Q-*XRuUnzS?|U+vD!V6UQ9>eh!3!C%&w_7ga6jGI5=?hJNIzN(^vb z{gg8xo@Atu8^^skPq~eMpJ~WEK-tkwLaaQH;_mV)W|6s+`S9o z?ZSIwJ0D2zpdbc|05JU4w=FcHbfXCPxFhL_ZDHq;mzABKTUv$ffzgp<;qq6~Sy516&AoUm$>ALm=8si&my_v)WXo-F^uM%&89d`RXA6R$UJH#JjqZmH7jYo&%UGGJP*@4tKXb zl3OLI+NgJ0oXfvC`&GVgYV6u-^)gj(r6(y%<2pBo^u=Be*N{{>WR6QHB6VZjs`{-(h>zR=-;D zxzN@t1}Z|O%T2I$ads0k;f(nhYI@npNptf%v-d#^?zO6R%xzM^a^@FNdEuq@A!^Z8 zP}u>#q(SGaM52mHKW&0-(Nq+7&j2}k3HRFSJaH=>&?a9GrG|sp3%mvnMPs-8Hp5QV zqzqh{$2cs3zh2BTs50vaL{H6TP=bC4lvT@X@gSZ`9!7Nv=UK{*m>`+4+a?1jI(zTT zQF~3^J^$qHg8KmU^&kKCe%K;|=G_Q(-pX}thN0MI@V4r3`T}*8Ul=AUHn*sup?Gx1 z=-tVo{|!i(r-{5#NCGihHqBB&62E7zvp~cet?V-Wx}}$%Yx)LbeNcOIz8!RE!3g(Q z=G|F^xG8y#;HOc?dRsX0Lr z`|%F|@h4dmX~X>=9)|orY>;qU2)4XmM1Z>DpB`#KN#6VBC2@=L&0DvoAUg-+gS|@K zp?cw!#mtj#RDsp*vLC9ACCX)VNN~=2L+>LG(d~DrMWxW#Jj>~~WD%bWxV?@NFaayw z3Il(_Fb=*C_ZAeP_U5&t>a?CG@=IOUQYzyXTj`hee)-6|HyGzCBy(R(?XF!z^7weH z#GYIgCN^s)&qkrjc)(-oKoMr`?qVa(6&y+^JMCqyNPl3xRk0DE0zok)Rl9wo;{%V? z4q3|m1?SJ5EK$3?Rs79B?VyD&ToCh3gkii7E*fZ9usEFyw!^-AwKXW^&23Clc=b=I+3XI;*;+u7pYAF{Hva5cWI z60pxev5U?!!>w9R5~13i2pM*g!2=52OQYnqNP8g`60~AH8-5#Sd$Z=pelGf&R(@ah`aV;$+VW%~LoK7VNm zSY)=2;d$#2spVB_pR&LRWZ7{ivo_X9-EzFNP%+hR$BV56MQyMD1TeIsguIp+{hYPT zt`o$-=GK}tG5E=Sb}XFu?j%2HREx(>4S&MJgz+Y|P(O(t+HWDsCd$f>HKQF0elva} zB-kHf9zn^36fg0vmZDEYj;P{4<>l+AfIgAMT=z` zs}IqXz$|qtU@!Cyj;kGi)ElMi1g!tkGWN)Z2u0W93C$b8b`;qg(SdkDDeG6v)`G4a zqvl;*jb%^ye?u}%tNI3bh+El66nE!P0=n+c3~8pHVpZMTvO})uG)qUadKkvp4D(80 z^j#WMOZB?E8 zAi_ua=kTuhH-?&fY{=u_$eI3W#f4ZD3@r*Zrncd5_fHw)#&(?_!y;HJZ-w@fYnG3v zo=+~x^Qtc6q1t^eBUP}rUvHkqK}&}AcW&OI7_C(EHDIy{t%>4Rjdu2-zq41|T@4!D zGZ1JYxoB)W`;&Zo-2iVO`A2_TOC^pYX6LnEFCJs${JIVgWPIPb%S-HSJ|=88s9YDU zEgDblW*!g?Ss-MVBj0i7dP=_mEToz#CD+}7dvr6w!>*o85TE3^C1Qi`F$t|I#m$7i zgn}~kOpUE^iEIMMTc;T-O|Cm&e7HJZ3;G4?b3~i#HX{5_yo>WN{rtuo+{f#&Hz;os zu6IxjHj$Vg*7MQ>X?ZtB|6)5ePU4>bS?f~9vgsM!R&*6-bK-IPbJ@;+OBM@Sp%Pm$ ztJ%F$^5akL0)C7it2b*s?q_@4&UfZQ_G)*dbTp-)UX0+WP+dLFJ3;ZDtQ-1SL{VGU zHO*0WQp)6e^EFMCqg7uNFvkLWcJJVhtRiEq$Dy$Bu!Ae-z5w0l6Kr1GAGu>U{931P z-X~sw+RX=RIV@vF#yok+vq&_Cd_B~uqXOtd&4ui=?y71X+>RG;3^HsCy|%4+IFh$C z0mTf>jlG3}@$MP4nxrzsDJB{!0kd)XF+8Iu1IX8Ow^=fExmW5?)Nsdh?!w7r)+AJR z3v5P3lDiw0tBNzzUbX+mQdArTp#!PZnI0PodUUA;I&JXlc z&cku^Q&8>01EmMlSoPV%W2|m7g0a`@dvX^&02q1PmRVINZ6=tuXW@?d)lI?OB{>2J zxrQG3RJTA}O=dlI%sNuyb~u@+-D}$qyf#>rrqPT5 z+?&3;&-CNcD*#`$={Qxt$P0a|nGjf{y1e?f+)cIi64T^CUM201lZ_SDaVc+GeyF5t ztM)^yLX?6s?mcJ&%%2MIWhRPO_^76|yFA&7ou%)b%ezc*rYtvQK_DZ$#-Knnr>H|; z8Mk67h+)OseFm<^6mc*Le0mW(RhwG<^Z#gm30EJ89tL#QiT4+$eLkB^(;t$jY08-W zPks-N0{rMha|tK_g~}y7h>c^lGvKINP6ENGRlpn8GRmE^0|?Gk$<2tZ%ucL`IFp>L zVVybqdtLg^0QvP}3@Z>AfvU3Q3gEDT1u!cVqPGr?X3IJta~@EOcEkko)+>~?SY}IS zSb|sJ>cNpFjV+L_^6`W3`zH!zZItHm@BO+f@OIJS#9AcL#_>(PVc>@fwhz`W3Ogol zYfl1d>A(HNr+^l%&SFeLelcUKN)rhht#b4$h1~lvOxDZoS;`BqB@2h?ojj!np`lYZ zW6dr7T4jt`S8DA|Y0tmHF4Qk*kFq5fGuFPg)aN%nTsk5=-d%u3u`~nqJg*QXW$ntR zd&$iP$)fq+kH;|GmhP_U>&>M!Ks=hbmF{`W$Tvq$j&%IQS-F#D4Rx?_P;Hy0a6*w}?^7=d~ zxvc8}z=)@t4x;6_1TnCl?GefwQ2dHQ?L(Up0xFS*KN}n z38H%p@r@TwLTt^;s>N{7FfnaPslMPL`aD1x4oY6#O`<*7Ts;?HM>RJkIH7rHnG(XzL~>61hzu zl?^0~D}l9|)>|nXF#kbf_)|)XVIg|*INk8y(J_6&0R6Sfz-d^KgOx0JAfSgEl@vEi zy;zx=>YtWIhkGyhj!0RxAI{`Q8(TT0e52I}dIJP=gVzA$00{{R&wQ(9(8MGR1g$P< z)+oS9Z#Fif`fXObG954tldQDB=r`g19w?ghpJMI6?h5nEsD$<@d!vGjvT|gzmX4f1 zC&jS5RUBqRJc=9ljvH0wP{6k*R(|Q?0HFsU6l41 z>QVVZbGuPRcFb5ldNYOsq@4XPyKFf=c^Mfkdd816zL{Km(|H0)1XBx$aOQ8Y9bEc{`y!r)v<} zMfO&7h3k0%UdgxY9U18WvB{#g772=bS1$u`1M0BvWTu+X_)gpV(9D(NzO%Lk8&xl- z`0=b1{Vwc&re(6AeB$Zpsc9m5^7MtWBe#Q50e@(Gi-9^10Bz$t^ReUt__fm+wa<@- zpgApn21(w5Tr{_|6xroP3XSeou^>Q6r>SR;d6RaZ@+R(tof-Uwkt6~>ZPQGZTMUr0 z!Acvh0R#q{`B6kUgg5L$D2OA$z)wye!n@tbz@tw>w8Gv_m64qf3(6okNU1) zTt|gIfi7S@khB-y95Mp2#=012y-!$l$5u_FV1`!P+V+Y{z_)T>Zaq01G+Xv$4$T#u zU05*G(|dGoJPQ^?z*RwBr`aKVp#HjSdW&Azoji9GnBkeO?gl@H*eyb6ZKBo3*4FmL zxg_{h`hW)drT)p!oa_G4&ZgD$2QI2L7=J6qLWC82tCT>9f!=wLks@w|>H}S5PJuVuv#xX-QyXM9H6>j*nF^-gO_wnEGQVCC z0-A(ZUe5rZ8Q9Vg8j_-e;7VyK-}(h_R?l?vu-qJc-;CWI=_K8)Wer`g!@CdMAQ*{@ zBbAzT8%W87-e-~<joOSPTiw+PA3gbTS-0Fd zO46#d&u(Y=H-}Bi*_YdN_tC9TzK0Sgv?p96U_dgf5+48Ul^nyy@0^`!=;LDi4ep9jBQ5z840)zf}p30iZ^fwDNptNp8CP?2W>SNv*6<8medq> zN7u+C|A|zcKQvc#VaW(B0>tSw4UL2v6FrUJJv^LXXl%sGA{jW3L)i7}m(ydCsU=Z) zVqn(zJksO7NhKIL1#KAb+p)8j>dWju3mspJQ9!?xQCdsQ-TTKIx^ZLP$17Jzuai)Q zPU$PT?<_}>gptFvIVELDAzizftA}e`4?T>oQN&^hVN)3EiVQfJwi-&)%72!YHN2w~ z=Y8@pbbaSx+&$gz(1wk4Q&hU|ARIq$B(EX;jFir77B$|GQ9~2O?c2r%2EM?VH;Zxk z%~-7SyRC8bcWY{SRAXv+Jh^P3Z*JD?;5y4-fSEj}B_pt^`V2&Lrg0u>j%n_6vWsZ` zC_wL^K}=fLD%@%_l|@H|G4dvy6DU5=IBu+d!IS)KDaS_15~SEvvXU~sW_32Q9(wSulwcyG-rOig z?TPd_UTkdX67SW*1ZEaa9Wbb}A!X3flU^=J{^fJkU_y1y7~0yt2Y%V#UWzB@B>dpS zk&*}+4-jXhz4hz+ZG^sX@(~25&R=t_MnRR=Ci#Zi+%Q zqhZbNfOwFCka91yP(*&lGm4=DS{Kmda#TJ7Ni2y8dTzA}IGa+-Me!Y6p;&#Lkgtgp zKaDg9s&y{ME&&i^LgxshGM=(>w_`l))xZEUwXldddcgwvC5GVd4fHF}A1u@$7%H+W zR}x5OVHv$W(GySYCLpv~3b*0UZ1*=2(KfilUM^s64vFljW-#EE z<>p~t9qjJ|4=Ac|h8GlI48b87;C^_RG&6&nm!h`z%kO7p20`Hk#SI)Pq(#eanj%|^ zg%fCOKYtQK_eU?6>PiY0MR$3=OqTX~5)k_!R=VPc@Ztf#Lty>3wihgD)javTou!;u za7gIt=@IqzhGpQ%k58~yC_)ongt0ovzvOkO$%#*0>4{Ce^KQ$d1R|Ge(fXd7En&N+<Do@oUxM551?!2Z};K-w~2fP^8NX2l}mD!2c>p zrG Date: Mon, 19 May 2025 16:15:46 +0200 Subject: [PATCH 15/24] feat: add hints to introduction --- power-grid-model-ds/introduction.ipynb | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb index e1ed7a2..d0703b9 100644 --- a/power-grid-model-ds/introduction.ipynb +++ b/power-grid-model-ds/introduction.ipynb @@ -188,7 +188,7 @@ "outputs": [], "source": [ "# ⚙️ Add a substation to the grid\n", - "# Hint: \n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-substations\n", "\n", "# %load solutions/introduction_2_1_add_substation" ] @@ -229,9 +229,8 @@ "outputs": [], "source": [ "# ⚙️ Add a node to the grid\n", - "# Hint: \n", "\n", - "# %load solutions/introduction_2_1_add_substation" + "# %load solutions/introduction_2_2_add_node" ] }, { @@ -262,7 +261,7 @@ "outputs": [], "source": [ "# ⚙️ Add a line to the grid\n", - "# Hint: \n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-lines\n", "\n", "# %load solutions/introduction_2_3_add_line" ] @@ -302,7 +301,7 @@ "outputs": [], "source": [ "# ⚙️ Add a load to the grid\n", - "# Hint: \n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-loads\n", "\n", "# %load solutions/introduction_2_4_add_load" ] @@ -342,7 +341,7 @@ "outputs": [], "source": [ "# ⚙️ Add a source to the grid\n", - "# Hint: \n", + "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-a-source\n", "\n", "# %load solutions/introduction_2_5_add_source" ] @@ -381,7 +380,7 @@ "outputs": [], "source": [ "# ⚙️ Check whether all IDs are correct\n", - "# Hint: \n", + "# Hint: The grid has a method for that!\n", "\n", "# %load solutions/introduction_2_6_check_ids" ] @@ -407,6 +406,14 @@ "print(\"Sources:\", grid.source.id) # Expect [501]" ] }, + { + "cell_type": "markdown", + "id": "a1abb080", + "metadata": {}, + "source": [ + "Now we can visualize the resulting network" + ] + }, { "cell_type": "code", "execution_count": null, From b34b1d3616cefb0d2e01a9fb229b85996df803c6 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Mon, 19 May 2025 16:26:43 +0200 Subject: [PATCH 16/24] feat: prepare advanced excercises --- power-grid-model-ds/advanced.ipynb | 71 +++++++++++++++++-- .../advanced_5_3_connect_to_route.py | 13 ++++ 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index a24e3a7..7d88b1f 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -2,10 +2,20 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "59d49e29", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" + ] + } + ], "source": [ "!pip install pandas power-grid-model-ds[visualizer] --quiet" ] @@ -33,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "cf475775", "metadata": {}, "outputs": [], @@ -65,7 +75,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "37f4bd29", "metadata": {}, "outputs": [], @@ -118,7 +128,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "78d0639e", "metadata": {}, "outputs": [], @@ -157,7 +167,15 @@ "execution_count": null, "id": "206be67b", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], "source": [ "# Check the grid for capacity issues\n", "# 1. Use the PowerGridModelInterface to calculate power flow\n", @@ -212,6 +230,8 @@ "metadata": {}, "outputs": [], "source": [ + "# Check the introduction workshop on adding a substation\n", + "\n", "def build_new_substation(grid: Grid, location: tuple[float, float]) -> NodeArray:\n", " \"\"\"Build a new substation at the given location.\n", " Return the new substation.\n", @@ -243,12 +263,23 @@ "metadata": {}, "outputs": [], "source": [ + "# Hint: The lines have been extended with extra properties in Step 1\n", + "# Hint: The arrays in the grid have a filter option, https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/array_examples.html#using-filters\n", + "\n", "def get_all_congested_routes(grid: Grid) -> list[NodeArray]:\n", " \"\"\"Get all routes that originate from a given substation node.\"\"\"\n", "\n", "# %load solutions/advanced_5_1_get_all_congested_routes.py" ] }, + { + "cell_type": "markdown", + "id": "ee84e60c", + "metadata": {}, + "source": [ + "Next we will use the nodes x and y coordinates to find a suitable node to connect to the new substation. You will create a find_connection_point function that return the Node in a route which is closest to the new_substation." + ] + }, { "cell_type": "code", "execution_count": null, @@ -260,10 +291,20 @@ " \"\"\"Calculate the connection point for the new route.\n", " This should be the geographically closest node to the new substation.\n", " \"\"\"\n", + " # Calculate the distance of each node in the route to the new_substation\n", + " # Return the closest one\n", "\n", "# %load solutions/advanced_5_2_find_connection_point.py" ] }, + { + "cell_type": "markdown", + "id": "a75e9b73", + "metadata": {}, + "source": [ + "Finally we build a function that creates a new line between the connection point and the new substation. We will first create it with an open connection and optimize the opening in the next step." + ] + }, { "cell_type": "code", "execution_count": null, @@ -271,6 +312,8 @@ "metadata": {}, "outputs": [], "source": [ + "# Hint: in the introduction you learned how to add a LineArray to the grid\n", + "\n", "def connect_to_route(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", " \"\"\"Connect the new substation node to the connection point.\n", " \"\"\"\n", @@ -325,6 +368,14 @@ "# %load solutions/advanced_6_optimize_route_transfer.py" ] }, + { + "cell_type": "markdown", + "id": "dbf3243e", + "metadata": {}, + "source": [ + "Now we combine the functions you created to solve the issues in the network" + ] + }, { "cell_type": "code", "execution_count": null, @@ -361,6 +412,14 @@ "transfer_routes(grid=grid, new_substation=new_substation)" ] }, + { + "cell_type": "markdown", + "id": "82546c38", + "metadata": {}, + "source": [ + "Check we resolved all contingencies" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py b/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py index e69de29..ddd5961 100644 --- a/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py +++ b/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py @@ -0,0 +1,13 @@ +def connect_to_route(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None: + """Connect the new substation node to the connection point. + """ + # Create a new line that connects the two nodes + new_line = MyLineArray( + from_node=[new_substation.id], + to_node=[connection_point.id], + from_status=[0], # status is 0 to make sure the line is not active + to_status=[1], + i_n=[360.0], + r1=[0.05], x1=[0.01], c1=[0.0], tan1=[0.0] + ) + grid.append(new_line) From 4f217878ee4025e4fc4467f160eeafea7983a371 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Mon, 19 May 2025 16:34:31 +0200 Subject: [PATCH 17/24] feat: text --- power-grid-model-ds/advanced.ipynb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 7d88b1f..0308c49 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -117,13 +117,7 @@ "metadata": {}, "source": [ "# 🏗️ Step 2: Load and Prepare the Grid\n", - "Goal: Load a synthetic medium-voltage grid from the provided data.\n", - "\n", - "You'll use pandas to load the data from included CSV files and then:\n", - "- Create an empty Grid object using your custom MyGrid class\n", - "- Create and fill NodeArray, LineArray and LoadArray objects with data from the CSV files and append them to your Grid\n", - "- Using a SourceArray, add a voltage source to each substation in the Grid\n", - "- You’ll then compute a power flow on the synthetic grid to get realistic line currents" + "Goal: Load a synthetic medium-voltage grid from the provided data" ] }, { @@ -143,6 +137,8 @@ "id": "4d2df7f4", "metadata": {}, "source": [ + "We now loaded our the network visualised here\n", + "\n", "![input_network.png](input_network.png)" ] }, @@ -152,6 +148,8 @@ "metadata": {}, "source": [ "# 🧯 Step 3: Detect the Overload\n", + "This is your first excercise.\n", + "\n", "Goal: Identify which line(s) are exceeding their rated current.\n", "\n", "You’ll:\n", @@ -195,6 +193,14 @@ "# %load solutions/advanced_3_check_for_capacity_issues.py" ] }, + { + "cell_type": "markdown", + "id": "4bd3aea9", + "metadata": {}, + "source": [ + "We can use PGM-DSs visualization function to explore the resulting grid. Check out the highlighting parts of the grid based on it's attributes to find out where the overload occurs" + ] + }, { "cell_type": "code", "execution_count": null, @@ -211,9 +217,11 @@ "metadata": {}, "source": [ "# 🧭 Step 4: Plan a Relief Strategy\n", + "We found out the north west part of the area is overloaded. To relieve the problem we will build a new substation near the overloaded area and connect part of the grid there.\n", + "\n", "![input_network_with_overload.png](input_network_with_overload.png)\n", "\n", - "Goal: Place a second substation near the overloaded path.\n", + "Goal: Place a second substation near the overloaded paths.\n", "\n", "You’ll:\n", "- Add a new substation at a specified location\n", From 8beaafad4f873894ef48f2bd784bd3d52ae54e77 Mon Sep 17 00:00:00 2001 From: Sven van der Voort Date: Mon, 19 May 2025 17:33:02 +0200 Subject: [PATCH 18/24] PGM-DS workshop: Improve descriptions in advanced notebook --- power-grid-model-ds/advanced.ipynb | 92 +++++++++---------- .../advanced_5_1_get_all_congested_routes.py | 2 +- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 7d88b1f..48d05b7 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -25,20 +25,18 @@ "id": "d5e1958f", "metadata": {}, "source": [ - "# ⚡ Advanced Power Grid Workshop: Solving an Overload Scenario\n", + "# ⚡ Advanced PGM-DS Workshop: Solving an Overload Scenario\n", "\n", - "You're a senior grid analyst at GridNova Utilities, overseeing a legacy radial distribution network in a semi-rural region. Recently, customer load growth has increased dramatically, particularly in areas served by a single long feeder. This has pushed some branches past their capacity, triggering repeated overloads.\n", + "You're a senior grid analyst at GridNova Utilities, responsible for operating a legacy distribution grid in a rural area. The grid is radially operated, with some cables inactive as back-up in case failures. Recently, customer load growth has increased dramatically, particularly in areas served by several long feeders. This has pushed some branches past their capacity, triggering repeated overloads.\n", "\n", - "Your task: augment the grid by adding a second substation and relieving the overloaded feeder through targeted switching.\n", + "Your task: upgrade the grid by adding a second substation and relieving the overloaded feeder through new connections to the new substation.\n", "\n", - "This hands-on simulation walks you through each step of diagnosing, planning, and solving this overload using the Power Grid Model DS library.\n", + "This hands-on simulation walks you through each step of diagnosing, planning, and solving this overload using the Power Grid Model Data Science library.\n", "\n", "## 🎯 Workshop Goals\n", - "- Detect a line overload after load increase.\n", - "- Find a suitable node to connect a new substation.\n", - "- Trace the overloaded route.\n", - "- Strategically open a line to reroute power and relieve the feeder.\n", - "\n" + "- Detect a line overload using PGM load flow calculations.\n", + "- Find a suitable node to create a connection to the new substation.\n", + "- Strategically open a line to reroute power and relieve the feeder.\n" ] }, { @@ -63,9 +61,9 @@ "metadata": {}, "source": [ "# 🧪 Step 1: Extend the Data Model\n", - "Goal: Add coordinate fields and tracking for simulated voltages and line currents.\n", + "Goal: Add coordinate fields to nodes and fields for tracking simulated voltages and line currents.\n", "\n", - "You’ll subclass NodeArray and LineArray to add:\n", + "We subclass NodeArray and LineArray to add:\n", "\n", "- x, y coordinates for spatial logic and plotting\n", "- u for node voltage results\n", @@ -119,11 +117,13 @@ "# 🏗️ Step 2: Load and Prepare the Grid\n", "Goal: Load a synthetic medium-voltage grid from the provided data.\n", "\n", - "You'll use pandas to load the data from included CSV files and then:\n", + "We use pandas to load the data from included CSV files and then:\n", "- Create an empty Grid object using your custom MyGrid class\n", "- Create and fill NodeArray, LineArray and LoadArray objects with data from the CSV files and append them to your Grid\n", "- Using a SourceArray, add a voltage source to each substation in the Grid\n", - "- You’ll then compute a power flow on the synthetic grid to get realistic line currents" + "- You’ll then compute a power flow on the synthetic grid to get realistic line currents\n", + "\n", + "(Code is already given in helper.py file, please take a look to see how the grid data is loaded!)" ] }, { @@ -152,14 +152,13 @@ "metadata": {}, "source": [ "# 🧯 Step 3: Detect the Overload\n", - "Goal: Identify which line(s) are exceeding their rated current.\n", + "Goal: Identify which line(s) are exceeding their rated current (the `i_n` property).\n", "\n", - "You’ll:\n", + "You can do this step by step (don't forget to check the PGM-DS documentation):\n", "\n", - "- Use the .is_overloaded property to find the problem\n", - "- Isolate the feeder route to the affected line\n", - "\n", - "This gives a clear target for where you need to intervene." + "1. Use the PowerGridModelInterface to calculate power flow\n", + "2. Update the Grid object with the calculated values\n", + "3. Return the lines (LineArray) that are overloaded" ] }, { @@ -177,11 +176,6 @@ } ], "source": [ - "# Check the grid for capacity issues\n", - "# 1. Use the PowerGridModelInterface to calculate power flow\n", - "# 2. Update the grid with the calculated values\n", - "# 3. Return the lines (LineArray) that are overloaded\n", - "\n", "# Hint: You can use the `is_overloaded` property of the `MyLineArray` class to check for overloaded lines.\n", "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/quick_start.html#performing-power-flow-calculations\n", "\n", @@ -211,14 +205,15 @@ "metadata": {}, "source": [ "# 🧭 Step 4: Plan a Relief Strategy\n", + "\n", + "If you visualize the grid and highlight the overloaded cables, this is what you will see:\n", + "\n", "![input_network_with_overload.png](input_network_with_overload.png)\n", "\n", - "Goal: Place a second substation near the overloaded path.\n", + "Goal: Place a second substation near the overloaded path. In the next steps we will use this substation to relieve overloaded cables.\n", "\n", "You’ll:\n", - "- Add a new substation at a specified location\n", - "- Connect it to the closest node in the network\n", - "- Visually inspect the grid with visualize()\n", + "- Create a new substations using the NodeArrayobject at the correct location.\n", "\n", "This substation will act as a new injection point for rerouting load.\n" ] @@ -245,15 +240,13 @@ "id": "8f2b17e3", "metadata": {}, "source": [ - "# 🔗 Step 5: Trace and Analyze the Overloaded Route\n", - "Goal: Identify a switchable line along the route from the new node to the old substation.\n", + "# 🔗 Step 5: Analyze and Connect the Overloaded Route\n", + "Goal: Identify the best way to connect the new substation to the overloaded routes.\n", "\n", "You’ll:\n", - "- Use the graph interface to trace the shortest path from the new substation to the original\n", - "- Calculate cumulative load along the path\n", - "- Find a cut point where the remaining load toward the old substation is < 2 MW\n", - "\n", - "This ensures you relieve the feeder while maintaining supply continuity." + "- Compute which routes (/feeders) are overloaded to see where we need to invervene.\n", + "- Find which node on an overloaded route is geographically closed to the new substation.\n", + "- Create a new cable to connect the closest node to the new substation." ] }, { @@ -267,7 +260,7 @@ "# Hint: The arrays in the grid have a filter option, https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/array_examples.html#using-filters\n", "\n", "def get_all_congested_routes(grid: Grid) -> list[NodeArray]:\n", - " \"\"\"Get all routes that originate from a given substation node.\"\"\"\n", + " \"\"\"Get all nodes on routes that contain an overloaded line.\"\"\"\n", "\n", "# %load solutions/advanced_5_1_get_all_congested_routes.py" ] @@ -302,7 +295,9 @@ "id": "a75e9b73", "metadata": {}, "source": [ - "Finally we build a function that creates a new line between the connection point and the new substation. We will first create it with an open connection and optimize the opening in the next step." + "Finally we build a function that creates a new line between the connection point and the new substation.\n", + "\n", + "❗ IMPORTANT ❗ The new line should first be created with an open connection; we will optimize the location of the line opening in the next step." ] }, { @@ -326,15 +321,16 @@ "id": "4a9ef582", "metadata": {}, "source": [ - "# ✂️ Step 6: Open the Right Line\n", - "Goal: Deactivate a line to offload the original feeder.\n", + "# 🔌 Step 6: Open the Right Line\n", + "Goal: Find the optimal line to open to relieve the original overloaded feeder.\n", "\n", "You’ll:\n", - "- Identify and deactivate the line between two nodes on the critical path\n", - "- Rerun power flow after the switch\n", + "- Trace a path from the newly created cable to the old substation\n", + "- Evaluate each line on the path by running `check_for_capacity_issues()` and find the optimal line to open\n", + "- Open the correct line\n", "- Confirm the overload is resolved\n", "\n", - "This final step demonstrates how network topology and load can be managed dynamically with switching and distributed generation.\n", + "This final step demonstrates how network topology can be programmatically optimized using the Power Grid Model Data Science toolkit!\n", "\n" ] }, @@ -346,7 +342,7 @@ "outputs": [], "source": [ "def optimize_route_transfer(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", - " \"\"\"Attempt to optimize the route transfer moving the naturally open point (NOP) upstream towards the old substation.\n", + " \"\"\"Attempt to optimize the route transfer moving the normally open point (NOP) upstream towards the old substation.\n", " This way, the new substation will take over more nodes of the original route.\n", " \"\"\"\n", " # Get the path from the connection point to the old substation\n", @@ -448,9 +444,9 @@ "# ✅ Wrap-Up\n", "You’ve just:\n", "\n", - "Diagnosed a power system constraint\n", - "- Planned and executed a grid topology change\n", - "- Verified success with power flow simulations\n", + "- Loaded a grid topology and grid loads from a file\n", + "- Analyse grid components that are or will soon be overloaded using load flow analysis\n", + "- Automatically optimize a solution to relieve (future) congestions on the energy grid\n", "\n", "We hope you enjoyed working with Power Grid Model DS and would love to hear your feedback" ] @@ -458,7 +454,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "power-grid-model-workshop", "language": "python", "name": "python3" }, @@ -472,7 +468,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "undefined.undefined.undefined" } }, "nbformat": 4, diff --git a/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py b/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py index d3c10bf..86fbaed 100644 --- a/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py +++ b/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py @@ -1,5 +1,5 @@ def get_all_congested_routes(grid: Grid) -> list[NodeArray]: - """Get all routes that originate from a given substation node.""" + """Get all nodes on routes that contain an overloaded line.""" grid.set_feeder_ids() lines_with_congestion = check_for_capacity_issues(grid) feeder_branch_ids_with_congestion = np.unique(lines_with_congestion['feeder_branch_id']) From e2ea1b7f28ef878b5aeed1d497516f6dfb362470 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Tue, 20 May 2025 08:07:53 +0200 Subject: [PATCH 19/24] feat: small changes --- power-grid-model-ds/advanced.ipynb | 44 ++++++++++-------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index bacf93b..78cdc11 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -2,20 +2,10 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "59d49e29", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "!pip install pandas power-grid-model-ds[visualizer] --quiet" ] @@ -41,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "cf475775", "metadata": {}, "outputs": [], @@ -61,19 +51,21 @@ "metadata": {}, "source": [ "# 🧪 Step 1: Extend the Data Model\n", - "Goal: Add coordinate fields to nodes and fields for tracking simulated voltages and line currents.\n", + "Goal: Add coordinate fields and tracking for simulated voltages and line currents. This allows us to store and analyse metadata of the grid needed to to decide where to invest in the grid.\n", "\n", - "We subclass NodeArray and LineArray to add:\n", + "You’ll subclass NodeArray and LineArray to add:\n", "\n", "- x, y coordinates for spatial logic and plotting\n", "- u for node voltage results\n", "- i_from for line currents\n", - "- A computed .is_overloaded property for easy filtering" + "- A computed .is_overloaded property for easy filtering\n", + "\n", + "This shows how the Grid can be extended to suit the needs of a specific project." ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "37f4bd29", "metadata": {}, "outputs": [], @@ -115,13 +107,13 @@ "metadata": {}, "source": [ "# 🏗️ Step 2: Load and Prepare the Grid\n", - "Goal: Load a synthetic medium-voltage grid from the provided data" + "Goal: Load a synthetic medium-voltage grid from the provided data\n", "(Code is already given in helper.py file, take a look to see how the grid data is loaded!)" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "78d0639e", "metadata": {}, "outputs": [], @@ -163,15 +155,7 @@ "execution_count": null, "id": "206be67b", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "None\n" - ] - } - ], + "outputs": [], "source": [ "# Hint: You can use the `is_overloaded` property of the `MyLineArray` class to check for overloaded lines.\n", "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/quick_start.html#performing-power-flow-calculations\n", @@ -460,7 +444,7 @@ ], "metadata": { "kernelspec": { - "display_name": "power-grid-model-workshop", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -474,7 +458,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "undefined.undefined.undefined" + "version": "3.12.6" } }, "nbformat": 4, From 76babd9a0910938c209eb1fec9d22e5a2b10933e Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Tue, 20 May 2025 13:29:20 +0200 Subject: [PATCH 20/24] Split solution cells Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- power-grid-model-ds/introduction.ipynb | 197 +++++++++++++++++++------ 1 file changed, 154 insertions(+), 43 deletions(-) diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb index d0703b9..62b9531 100644 --- a/power-grid-model-ds/introduction.ipynb +++ b/power-grid-model-ds/introduction.ipynb @@ -60,19 +60,30 @@ "In this exercise, we will extend the grid to include an output voltage u for nodes and an output current i_from for lines, which are not present in the basic grid.\n", "\n", "### Step 1: Define Extended Node and Line arrays\n", - "We create subclasses of NodeArray and LineArray that include the new properties. We'll call them MyNodeArray and MyLineArray. Each subclass defines a class attribute for the new column and (optionally) a default value for that column via a _defaults dictionary." + "We create subclasses of NodeArray and LineArray that include the new properties. We'll call them MyNodeArray and MyLineArray. Each subclass defines a class attribute for the new column and (optionally) a default value for that column via a _defaults dictionary.\n", + "\n", + "**⚙️ Assignment**: Create two Array extensions to hold the x, y, u (extending NodeArray) and i_from (extending LineArray) attributes\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html" ] }, { "cell_type": "code", "execution_count": null, - "id": "fcb5c7f4", + "id": "7cfe11a7-80ed-4fe9-8c7f-0daf0ec1c27a", + "metadata": {}, + "outputs": [], + "source": [ + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ada3e60-8bd7-4687-9f29-3ae5ff029228", "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Create two Array extensions to hold the x, y, u (extending NodeArray) and i_from (extending LineArray) attributes\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html\n", - "\n", "# %load solutions/introduction_1_1_define_array_extensions" ] }, @@ -82,19 +93,32 @@ "metadata": {}, "source": [ "### Step 2: Create an Extended Grid class\n", - "Now we'll integrate these new arrays into a custom Grid class. We do this by subclassing the PGM-DS Grid and specifying that our grid should use MyNodeArray and MyLineArray instead of the default NodeArray and LineArray. We'll use Python's dataclass to define the new Grid schema:" + "Now we'll integrate these new arrays into a custom Grid class. We do this by subclassing the PGM-DS Grid and specifying that our grid should use MyNodeArray and MyLineArray instead of the default NodeArray and LineArray. We'll use Python's dataclass to define the new Grid schema:\n", + "\n", + "**⚙️ Assignment**: Create a new grid class that uses the extended arrays.\n", + "\n", + "**💡 Hint 1**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html#adding-the-new-arrays-to-the-grid\n", + "\n", + "**💡 Hint 2**: Make sure to add the `@dataclass` decorator to your grid." ] }, { "cell_type": "code", "execution_count": null, - "id": "2da55398", + "id": "de236a67-1632-4f81-9145-7a904c63746b", + "metadata": {}, + "outputs": [], + "source": [ + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7512d0d-5d85-44b6-b42e-11be0fa6802a", "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Create a new grid class that uses the extended arrays\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html\n", - "\n", "# %load solutions/introduction_1_2_define_my_grid" ] }, @@ -112,7 +136,11 @@ "metadata": {}, "source": [ "### Step 3: Initialize an Extended Grid\n", - "With the classes defined, let's create an instance of our extended grid. PGM-DS provides a convenient class method Grid.empty() to initialize an empty grid. We'll call this on our ExtendedGrid:" + "With the classes defined, let's create an instance of our extended grid. PGM-DS provides a convenient class method Grid.empty() to initialize an empty grid. We'll call this on our ExtendedGrid:\n", + "\n", + "**⚙️ Assignment**: Instantiate an empty extended grid\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#creating-an-empty-grid" ] }, { @@ -122,9 +150,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Instantiate an empty extended grid\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#creating-an-empty-grid\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d5464bf-5689-4919-a85b-b6548b475537", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_1_3_grid_empty" ] }, @@ -133,7 +168,11 @@ "id": "06983bc4", "metadata": {}, "source": [ - "Verification: To ensure our extended properties exist, you can access the new attributes:" + "Verification: To ensure our extended properties exist, you can access the new attributes:\n", + "\n", + "**⚙️ Assignment**: Print some information about the grid.\n", + "\n", + "**💡 Hint**: Be creative! You can use the grid's attributes and methods to get information about the grid. Using `print()` on an array will format it for better readability." ] }, { @@ -143,9 +182,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Print some information about the grid\n", - "# Hint: be creative! You can use the grid's attributes and methods to get information about the grid.\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4d131c6-094a-49a2-a283-5bdbd05e961d", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_1_3_grid_verification" ] }, @@ -177,7 +223,11 @@ "### Step 1: Add a substation node\n", "First, let's add a substation node to the grid. We create an MyNodeArray with one entry representing the substation. We need to provide at least an id, a rated voltage (u_rated), and a node type.\n", "We will use the enum NodeType.SUBSTATION_NODE for the type.\n", - "In this example, we will assign the substation an ID of 101 and a rated voltage of 10500.0 (which could represent 10.5 kV):" + "In this example, we will assign the substation an ID of 101 and a rated voltage of 10500.0 (which could represent 10.5 kV):\n", + "\n", + "**⚙️ Assignment**: Add a substation to the grid.\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-substations" ] }, { @@ -187,9 +237,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Add a substation to the grid\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-substations\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c641c07-1cc7-44bc-87ff-49bed38e7d5c", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_2_1_add_substation" ] }, @@ -218,7 +275,9 @@ "metadata": {}, "source": [ "### Step 2: Add a second node\n", - "Next, we'll add another node to represent a load or another bus in the grid. This node will be of a generic type (we'll use NodeType.UNSPECIFIED, which equals 0 in the enum). We'll give it an ID of 102 and the same base voltage (10.5 kV):" + "Next, we'll add another node to represent a load or another bus in the grid. This node will be of a generic type (we'll use NodeType.UNSPECIFIED, which equals 0 in the enum). We'll give it an ID of 102 and the same base voltage (10.5 kV).\n", + "\n", + "**⚙️ Assignment**: Add a node to the grid. " ] }, { @@ -228,8 +287,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Add a node to the grid\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f987c7c-ea3b-472c-b9f9-f379a478bc4e", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_2_2_add_node" ] }, @@ -250,7 +317,11 @@ "metadata": {}, "source": [ "### Step 3: Add a line connecting the two nodes\n", - "Now that we have two nodes, we will connect them with a line. We'll use our MyLineArray to create a single line record. We need to specify an ID for the line (let's use 201), the from_node and to_node it connects (101 to 102), and statuses to indicate the line is active. We should also provide line electrical parameters (resistance, reactance, etc.) – we'll use some placeholder values here for demonstration:" + "Now that we have two nodes, we will connect them with a line. We'll use our MyLineArray to create a single line record. We need to specify an ID for the line (let's use 201), the from_node and to_node it connects (101 to 102), and statuses to indicate the line is active. We should also provide line electrical parameters (resistance, reactance, etc.) – we'll use some placeholder values here for demonstration:\n", + "\n", + "**⚙️ Assignment**: Add a line to the grid.\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-lines" ] }, { @@ -260,9 +331,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Add a line to the grid\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-lines\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0211f7ec-0890-4880-b78a-65610e1eaf10", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_2_3_add_line" ] }, @@ -290,7 +368,11 @@ "metadata": {}, "source": [ "### Step 4: Add a load to the second node\n", - "We'll now add a load connected to node 102. PGM-DS uses a SymLoadArray for symmetrical loads. We will create a single load with an ID of 401 at node 102. We need to specify the node it is attached to, a load type code (we'll use 1 for a basic load type), the specified active (p_specified) and reactive (q_specified) power (let's say 1e6 each, representing 1 MW and 1 Mvar for example), and set its status to active (1):" + "We'll now add a load connected to node 102. PGM-DS uses a SymLoadArray for symmetrical loads. We will create a single load with an ID of 401 at node 102. We need to specify the node it is attached to, a load type code (we'll use 1 for a basic load type), the specified active (p_specified) and reactive (q_specified) power (let's say 1e6 each, representing 1 MW and 1 Mvar for example), and set its status to active (1):\n", + "\n", + "**⚙️ Assignment**: Add a load to the grid.\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-loads" ] }, { @@ -300,9 +382,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Add a load to the grid\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-loads\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5499a30c-8820-4066-a322-ee03d5cfb8cf", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_2_4_add_load" ] }, @@ -330,7 +419,11 @@ "metadata": {}, "source": [ "### Step 5: Add a source to the substation node\n", - "Finally, we'll add a power source to supply the grid at the substation (node 101). We'll use SourceArray for this. We'll create a source with ID 501 at node 101, status active (1), and set a reference voltage u_ref. Typically, u_ref might be the slack/reference voltage magnitude or angle; we'll use 0.0 as a reference angle (assuming the default usage):" + "Finally, we'll add a power source to supply the grid at the substation (node 101). We'll use SourceArray for this. We'll create a source with ID 501 at node 101, status active (1), and set a reference voltage u_ref. Typically, u_ref might be the slack/reference voltage magnitude or angle; we'll use 0.0 as a reference angle (assuming the default usage):\n", + "\n", + "**⚙️ Assignment**: Add a source to the grid.\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-a-source" ] }, { @@ -340,9 +433,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Add a source to the grid\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_examples.html#adding-a-source\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ab72aec-acc5-42ac-b429-18f608d6bd38", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_2_5_add_source" ] }, @@ -369,7 +469,11 @@ "id": "e5e6eb1b", "metadata": {}, "source": [ - "You should see [501] as the source ID and [101] as the node, indicating the source is at node 101. The count of sources should be 1. Now we have built a simple grid with 2 nodes (101 and 102), 1 line connecting them, 1 load at node 102, and 1 source at node 101. It's good practice to ensure all IDs are unique and there are no inconsistencies. PGM-DS provides a method grid.check_ids() to validate this​" + "You should see [501] as the source ID and [101] as the node, indicating the source is at node 101. The count of sources should be 1. Now we have built a simple grid with 2 nodes (101 and 102), 1 line connecting them, 1 load at node 102, and 1 source at node 101. It's good practice to ensure all IDs are unique and there are no inconsistencies. PGM-DS provides a method grid.check_ids() to validate this.\n", + "\n", + "**⚙️ Assignment**: Check whether all IDs are correct.\n", + "\n", + "**💡 Hint**: The grid has a method for that!" ] }, { @@ -379,9 +483,16 @@ "metadata": {}, "outputs": [], "source": [ - "# ⚙️ Check whether all IDs are correct\n", - "# Hint: The grid has a method for that!\n", - "\n", + "# Build your solution here..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "403f00f3-d0bd-497a-8b93-8eaba629d68b", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/introduction_2_6_check_ids" ] }, @@ -429,7 +540,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -443,7 +554,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.13.2" } }, "nbformat": 4, From bb3c6ed4a1b6d04261cb883ae35bbb0662bb1621 Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Tue, 20 May 2025 13:43:28 +0200 Subject: [PATCH 21/24] Apply changes from feedback --- power-grid-model-ds/advanced.ipynb | 114 +++++++++++++++++++------ power-grid-model-ds/introduction.ipynb | 4 +- 2 files changed, 88 insertions(+), 30 deletions(-) diff --git a/power-grid-model-ds/advanced.ipynb b/power-grid-model-ds/advanced.ipynb index 78cdc11..81993ce 100644 --- a/power-grid-model-ds/advanced.ipynb +++ b/power-grid-model-ds/advanced.ipynb @@ -147,7 +147,11 @@ "\n", "1. Use the PowerGridModelInterface to calculate power flow\n", "2. Update the Grid object with the calculated values\n", - "3. Return the lines (LineArray) that are overloaded" + "3. Return the lines (LineArray) that are overloaded\n", + "\n", + "**💡 Hint**: You can use the `is_overloaded` property of the `MyLineArray` class to check for overloaded lines.\n", + "\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/quick_start.html#performing-power-flow-calculations" ] }, { @@ -157,16 +161,21 @@ "metadata": {}, "outputs": [], "source": [ - "# Hint: You can use the `is_overloaded` property of the `MyLineArray` class to check for overloaded lines.\n", - "# Hint: https://power-grid-model-ds.readthedocs.io/en/stable/quick_start.html#performing-power-flow-calculations\n", - "\n", "def check_for_capacity_issues(grid: Grid) -> LineArray:\n", " \"\"\"Check for capacity issues on the grid.\n", " Return the lines that with capacity issues.\n", " \"\"\"\n", "\n", - "print(check_for_capacity_issues(grid))\n", - "\n", + "print(check_for_capacity_issues(grid))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18973302-105f-42c3-9ffd-1408b90aeb10", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/advanced_3_check_for_capacity_issues.py" ] }, @@ -199,7 +208,7 @@ "\n", "![input_network_with_overload.png](input_network_with_overload.png)\n", "\n", - "We found out the north west part of the area is overloaded.\n", + "We found out the north-east part of the area is overloaded.\n", "Goal: Place a second substation near the overloaded path. In the next steps we will use this substation to relieve overloaded cables.\n", "\n", "You’ll:\n", @@ -220,8 +229,16 @@ "def build_new_substation(grid: Grid, location: tuple[float, float]) -> NodeArray:\n", " \"\"\"Build a new substation at the given location.\n", " Return the new substation.\n", - " \"\"\"\n", - "\n", + " \"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bff1e30f-5dd3-4774-977b-5707322a8f59", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/advanced_4_build_new_substation.py" ] }, @@ -234,9 +251,13 @@ "Goal: Identify the best way to connect the new substation to the overloaded routes.\n", "\n", "You’ll:\n", - "- Compute which routes (/feeders) are overloaded to see where we need to invervene.\n", + "- Compute which routes (/feeders) are overloaded to see where we need to intervene.\n", "- Find which node on an overloaded route is geographically closed to the new substation.\n", - "- Create a new cable to connect the closest node to the new substation." + "- Create a new cable to connect the closest node to the new substation.\n", + "\n", + "**💡 Hint**: The lines have been extended with extra properties in Step 1\n", + "\n", + "**💡 Hint**: The arrays in the grid have a filter option, https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/array_examples.html#using-filters" ] }, { @@ -246,12 +267,17 @@ "metadata": {}, "outputs": [], "source": [ - "# Hint: The lines have been extended with extra properties in Step 1\n", - "# Hint: The arrays in the grid have a filter option, https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/array_examples.html#using-filters\n", - "\n", "def get_all_congested_routes(grid: Grid) -> list[NodeArray]:\n", - " \"\"\"Get all nodes on routes that contain an overloaded line.\"\"\"\n", - "\n", + " \"\"\"Get all nodes on routes that contain an overloaded line.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc494d36-5ee7-401c-8a3b-59e701777f8d", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/advanced_5_1_get_all_congested_routes.py" ] }, @@ -275,8 +301,16 @@ " This should be the geographically closest node to the new substation.\n", " \"\"\"\n", " # Calculate the distance of each node in the route to the new_substation\n", - " # Return the closest one\n", - "\n", + " # Return the closest one" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ce16108-4580-4c32-9e18-60239144ae4f", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/advanced_5_2_find_connection_point.py" ] }, @@ -287,7 +321,9 @@ "source": [ "Finally we build a function that creates a new line between the connection point and the new substation.\n", "\n", - "❗ IMPORTANT ❗ The new line should first be created with an open connection; we will optimize the location of the line opening in the next step." + "❗ **IMPORTANT** ❗ The new line should first be created with an open connection; we will optimize the location of the line opening in the next step.\n", + "\n", + "**💡 Hint**: In the introduction you learned how to add a LineArray to the grid." ] }, { @@ -297,12 +333,18 @@ "metadata": {}, "outputs": [], "source": [ - "# Hint: in the introduction you learned how to add a LineArray to the grid\n", - "\n", "def connect_to_route(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None:\n", " \"\"\"Connect the new substation node to the connection point.\n", - " \"\"\"\n", - "\n", + " \"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e711bc3c-a09c-4454-b3a5-be4bf15fa077", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/advanced_5_3_connect_to_route.py" ] }, @@ -349,8 +391,16 @@ " # Move the Open Point (NOP) upstream\n", " ...\n", " \n", - " grid.set_feeder_ids()\n", - "\n", + " grid.set_feeder_ids()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "471b9ff0-43ca-432c-9ce9-71fc06d95b86", + "metadata": {}, + "outputs": [], + "source": [ "# %load solutions/advanced_6_optimize_route_transfer.py" ] }, @@ -423,7 +473,15 @@ "metadata": {}, "outputs": [], "source": [ - "visualize(grid)" + "visualize(grid) " + ] + }, + { + "cell_type": "markdown", + "id": "a2532f9d-60a9-4fcb-ac23-af6bd3ba47a2", + "metadata": {}, + "source": [ + "*Note: Jupyter notebook only supports one visualizer instance at a time. You might need to restart the kernel and re-run some cells for this final visualizer to work properly. If you do, make sure to not run earlier cells that contain `visualize(grid)`*" ] }, { @@ -444,7 +502,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -458,7 +516,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.13.2" } }, "nbformat": 4, diff --git a/power-grid-model-ds/introduction.ipynb b/power-grid-model-ds/introduction.ipynb index 62b9531..c219ca0 100644 --- a/power-grid-model-ds/introduction.ipynb +++ b/power-grid-model-ds/introduction.ipynb @@ -97,9 +97,9 @@ "\n", "**⚙️ Assignment**: Create a new grid class that uses the extended arrays.\n", "\n", - "**💡 Hint 1**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html#adding-the-new-arrays-to-the-grid\n", + "**💡 Hint**: https://power-grid-model-ds.readthedocs.io/en/stable/examples/model/grid_extensions_examples.html#adding-the-new-arrays-to-the-grid\n", "\n", - "**💡 Hint 2**: Make sure to add the `@dataclass` decorator to your grid." + "**💡 Hint**: Make sure to add the `@dataclass` decorator to your grid." ] }, { From 8d2e98a0d4efe4aafa634016f0909410069b947a Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Wed, 21 May 2025 08:10:39 +0200 Subject: [PATCH 22/24] Add license files Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- power-grid-model-ds/advanced.ipynb.license | 3 +++ power-grid-model-ds/helper.py | 4 ++++ power-grid-model-ds/input_network.png.license | 3 +++ power-grid-model-ds/input_network_with_overload.png.license | 3 +++ power-grid-model-ds/introduction.ipynb.license | 3 +++ 5 files changed, 16 insertions(+) create mode 100644 power-grid-model-ds/advanced.ipynb.license create mode 100644 power-grid-model-ds/input_network.png.license create mode 100644 power-grid-model-ds/input_network_with_overload.png.license create mode 100644 power-grid-model-ds/introduction.ipynb.license diff --git a/power-grid-model-ds/advanced.ipynb.license b/power-grid-model-ds/advanced.ipynb.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/advanced.ipynb.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/power-grid-model-ds/helper.py b/power-grid-model-ds/helper.py index 1d9ad4d..4158cba 100644 --- a/power-grid-model-ds/helper.py +++ b/power-grid-model-ds/helper.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + import pandas as pd from power_grid_model_ds.arrays import SymLoadArray, SourceArray diff --git a/power-grid-model-ds/input_network.png.license b/power-grid-model-ds/input_network.png.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/input_network.png.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/power-grid-model-ds/input_network_with_overload.png.license b/power-grid-model-ds/input_network_with_overload.png.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/input_network_with_overload.png.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/power-grid-model-ds/introduction.ipynb.license b/power-grid-model-ds/introduction.ipynb.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/introduction.ipynb.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 From afe3fa62761072fcd07e2d5e6128701763e90333 Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Wed, 21 May 2025 08:13:06 +0200 Subject: [PATCH 23/24] Add more license files Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- .../solutions/advanced_3_check_for_capacity_issues.py | 4 ++++ .../solutions/advanced_4_build_new_substation.py | 4 ++++ .../solutions/advanced_5_1_get_all_congested_routes.py | 4 ++++ .../solutions/advanced_5_2_find_connection_point.py | 4 ++++ .../solutions/advanced_5_3_connect_to_route.py | 4 ++++ .../solutions/advanced_6_optimize_route_transfer.py | 4 ++++ .../solutions/introduction_1_1_define_array_extensions.py | 4 ++++ .../solutions/introduction_1_2_define_my_grid.py | 4 ++++ power-grid-model-ds/solutions/introduction_1_3_grid_empty.py | 4 ++++ .../solutions/introduction_1_3_grid_verification.py | 4 ++++ .../solutions/introduction_2_1_add_substation.py | 4 ++++ power-grid-model-ds/solutions/introduction_2_2_add_node.py | 4 ++++ power-grid-model-ds/solutions/introduction_2_3_add_line.py | 4 ++++ power-grid-model-ds/solutions/introduction_2_4_add_load.py | 4 ++++ power-grid-model-ds/solutions/introduction_2_5_add_source.py | 4 ++++ power-grid-model-ds/solutions/introduction_2_6_check_ids.py | 4 ++++ 16 files changed, 64 insertions(+) diff --git a/power-grid-model-ds/solutions/advanced_3_check_for_capacity_issues.py b/power-grid-model-ds/solutions/advanced_3_check_for_capacity_issues.py index 1ea9f8e..13c9869 100644 --- a/power-grid-model-ds/solutions/advanced_3_check_for_capacity_issues.py +++ b/power-grid-model-ds/solutions/advanced_3_check_for_capacity_issues.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + from power_grid_model_ds import PowerGridModelInterface def check_for_capacity_issues(grid: Grid) -> LineArray: diff --git a/power-grid-model-ds/solutions/advanced_4_build_new_substation.py b/power-grid-model-ds/solutions/advanced_4_build_new_substation.py index 1ea9f8e..13c9869 100644 --- a/power-grid-model-ds/solutions/advanced_4_build_new_substation.py +++ b/power-grid-model-ds/solutions/advanced_4_build_new_substation.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + from power_grid_model_ds import PowerGridModelInterface def check_for_capacity_issues(grid: Grid) -> LineArray: diff --git a/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py b/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py index 86fbaed..f4f4bd3 100644 --- a/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py +++ b/power-grid-model-ds/solutions/advanced_5_1_get_all_congested_routes.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + def get_all_congested_routes(grid: Grid) -> list[NodeArray]: """Get all nodes on routes that contain an overloaded line.""" grid.set_feeder_ids() diff --git a/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py b/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py index 807ed77..58e0b63 100644 --- a/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py +++ b/power-grid-model-ds/solutions/advanced_5_2_find_connection_point.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + def find_connection_point(route: NodeArray, new_substation: NodeArray) -> NodeArray: """Calculate the connection point for the new route. This should be the geographically closest node to the new substation. diff --git a/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py b/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py index ddd5961..f4d1705 100644 --- a/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py +++ b/power-grid-model-ds/solutions/advanced_5_3_connect_to_route.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + def connect_to_route(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None: """Connect the new substation node to the connection point. """ diff --git a/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py b/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py index 42d981d..e4db730 100644 --- a/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py +++ b/power-grid-model-ds/solutions/advanced_6_optimize_route_transfer.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + def optimize_route_transfer(grid: Grid, connection_point: NodeArray, new_substation: NodeArray) -> None: """Attempt to optimize the route transfer moving the naturally open point (NOP) upstream towards the old substation. This way, the new substation will take over more nodes of the original route. diff --git a/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py b/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py index 90bb9b8..6682d2b 100644 --- a/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py +++ b/power-grid-model-ds/solutions/introduction_1_1_define_array_extensions.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + class MyNodeArray(NodeArray): _defaults = {"x": 0.0, "y": 0.0, "u": 0.0} x: NDArray[np.float64] diff --git a/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py b/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py index 1123da4..40ea049 100644 --- a/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py +++ b/power-grid-model-ds/solutions/introduction_1_2_define_my_grid.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + @dataclass class ExtendedGrid(Grid): node: MyNodeArray diff --git a/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py b/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py index 598b800..e4ff136 100644 --- a/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py +++ b/power-grid-model-ds/solutions/introduction_1_3_grid_empty.py @@ -1,2 +1,6 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + grid = ExtendedGrid.empty() grid \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py b/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py index f1a0cb3..9291ef7 100644 --- a/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py +++ b/power-grid-model-ds/solutions/introduction_1_3_grid_verification.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + print("Node 'u' field exists?", hasattr(grid.node, "u")) print("Line 'i_from' field exists?", hasattr(grid.line, "i_from")) print("Node array:", grid.node) \ No newline at end of file diff --git a/power-grid-model-ds/solutions/introduction_2_1_add_substation.py b/power-grid-model-ds/solutions/introduction_2_1_add_substation.py index 3d8f28a..023e8ef 100644 --- a/power-grid-model-ds/solutions/introduction_2_1_add_substation.py +++ b/power-grid-model-ds/solutions/introduction_2_1_add_substation.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + # Create a substation node entry substation_node = MyNodeArray( id=[101], diff --git a/power-grid-model-ds/solutions/introduction_2_2_add_node.py b/power-grid-model-ds/solutions/introduction_2_2_add_node.py index 78a33dc..fca1ad6 100644 --- a/power-grid-model-ds/solutions/introduction_2_2_add_node.py +++ b/power-grid-model-ds/solutions/introduction_2_2_add_node.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + # Create another node load_node = MyNodeArray( id=[102], diff --git a/power-grid-model-ds/solutions/introduction_2_3_add_line.py b/power-grid-model-ds/solutions/introduction_2_3_add_line.py index fa6fdc4..feafe8a 100644 --- a/power-grid-model-ds/solutions/introduction_2_3_add_line.py +++ b/power-grid-model-ds/solutions/introduction_2_3_add_line.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + # Create a line between node 101 and 102 new_line = MyLineArray( id=[201], diff --git a/power-grid-model-ds/solutions/introduction_2_4_add_load.py b/power-grid-model-ds/solutions/introduction_2_4_add_load.py index b7d45c9..ffd72cc 100644 --- a/power-grid-model-ds/solutions/introduction_2_4_add_load.py +++ b/power-grid-model-ds/solutions/introduction_2_4_add_load.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + # Create a load at node 102 load = SymLoadArray( id=[401], diff --git a/power-grid-model-ds/solutions/introduction_2_5_add_source.py b/power-grid-model-ds/solutions/introduction_2_5_add_source.py index 55c2ebd..08384e1 100644 --- a/power-grid-model-ds/solutions/introduction_2_5_add_source.py +++ b/power-grid-model-ds/solutions/introduction_2_5_add_source.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + # Create a source at node 101 source = SourceArray( id=[501], diff --git a/power-grid-model-ds/solutions/introduction_2_6_check_ids.py b/power-grid-model-ds/solutions/introduction_2_6_check_ids.py index a457c3d..d8a1bc7 100644 --- a/power-grid-model-ds/solutions/introduction_2_6_check_ids.py +++ b/power-grid-model-ds/solutions/introduction_2_6_check_ids.py @@ -1 +1,5 @@ +# SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project +# +# SPDX-License-Identifier: MPL-2.0 + grid.check_ids() \ No newline at end of file From 1a8eab82155cbbf64fefab66449fde04e58e781d Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Wed, 21 May 2025 08:13:56 +0200 Subject: [PATCH 24/24] Add license files for data Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- power-grid-model-ds/data/lines.csv.license | 3 +++ power-grid-model-ds/data/loads.csv.license | 3 +++ power-grid-model-ds/data/nodes.csv.license | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 power-grid-model-ds/data/lines.csv.license create mode 100644 power-grid-model-ds/data/loads.csv.license create mode 100644 power-grid-model-ds/data/nodes.csv.license diff --git a/power-grid-model-ds/data/lines.csv.license b/power-grid-model-ds/data/lines.csv.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/data/lines.csv.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/power-grid-model-ds/data/loads.csv.license b/power-grid-model-ds/data/loads.csv.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/data/loads.csv.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/power-grid-model-ds/data/nodes.csv.license b/power-grid-model-ds/data/nodes.csv.license new file mode 100644 index 0000000..7fa378e --- /dev/null +++ b/power-grid-model-ds/data/nodes.csv.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0