From 760d969beb5b074f6f284eaaa51fdbd6030af7ca Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Tue, 26 Oct 2021 17:37:22 -0400 Subject: [PATCH 01/16] Progress on propagating the setting to the action model. --- ml-agents/mlagents/trainers/cli_utils.py | 7 +++++++ ml-agents/mlagents/trainers/settings.py | 9 +++++++++ ml-agents/mlagents/trainers/torch/action_model.py | 2 ++ ml-agents/mlagents/trainers/torch/networks.py | 1 + 4 files changed, 19 insertions(+) diff --git a/ml-agents/mlagents/trainers/cli_utils.py b/ml-agents/mlagents/trainers/cli_utils.py index 5884c3a5c5..ca7fd1e02e 100644 --- a/ml-agents/mlagents/trainers/cli_utils.py +++ b/ml-agents/mlagents/trainers/cli_utils.py @@ -91,6 +91,13 @@ def _create_parser() -> argparse.ArgumentParser: "before resuming training. This option is only valid when the models exist, and have the same " "behavior names as the current agents in your scene.", ) + argparser.add_argument( + "--deterministic", + default=False, + dest="deterministic", + action=DetectDefaultStoreTrue, + help="Whether to use the deterministic samples from the data.", + ) argparser.add_argument( "--force", default=False, diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index fe52fb838c..24a46a7120 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -151,6 +151,7 @@ def _check_valid_memory_size(self, attribute, value): vis_encode_type: EncoderType = EncoderType.SIMPLE memory: Optional[MemorySettings] = None goal_conditioning_type: ConditioningType = ConditioningType.HYPER + deterministic: bool = parser.get_default("deterministic") @attr.s(auto_attribs=True) @@ -928,6 +929,7 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": key ) ) + # Override with CLI args # Keep deprecated --load working, TODO: remove argparse_args["resume"] = argparse_args["resume"] or argparse_args["load_model"] @@ -950,6 +952,13 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": if isinstance(final_runoptions.behaviors, TrainerSettings.DefaultTrainerDict): # configure whether or not we should require all behavior names to be found in the config YAML final_runoptions.behaviors.set_config_specified(_require_all_behaviors) + + for behaviour in final_runoptions.behaviors.keys(): + if not final_runoptions.behaviors[behaviour].network_settings.deterministic: + final_runoptions.behaviors[ + behaviour + ].network_settings.deterministic = argparse_args["deterministic"] + return final_runoptions @staticmethod diff --git a/ml-agents/mlagents/trainers/torch/action_model.py b/ml-agents/mlagents/trainers/torch/action_model.py index c5de586e4d..28fc161edd 100644 --- a/ml-agents/mlagents/trainers/torch/action_model.py +++ b/ml-agents/mlagents/trainers/torch/action_model.py @@ -32,6 +32,7 @@ def __init__( action_spec: ActionSpec, conditional_sigma: bool = False, tanh_squash: bool = False, + deterministic: bool = False, ): """ A torch module that represents the action space of a policy. The ActionModel may contain @@ -66,6 +67,7 @@ def __init__( # During training, clipping is done in TorchPolicy, but we need to clip before ONNX # export as well. self._clip_action_on_export = not tanh_squash + self.deterministic = deterministic def _sample_action(self, dists: DistInstances) -> AgentAction: """ diff --git a/ml-agents/mlagents/trainers/torch/networks.py b/ml-agents/mlagents/trainers/torch/networks.py index 4a2e1dafc6..19b97e2860 100644 --- a/ml-agents/mlagents/trainers/torch/networks.py +++ b/ml-agents/mlagents/trainers/torch/networks.py @@ -617,6 +617,7 @@ def __init__( action_spec, conditional_sigma=conditional_sigma, tanh_squash=tanh_squash, + deterministic=network_settings.deterministic, ) @property From 71ee0908a858ec65c18ed401e79d8e654c1ca4ea Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Wed, 27 Oct 2021 11:18:28 -0400 Subject: [PATCH 02/16] Added the _sample_action logic and tests. --- .../mlagents/trainers/tests/test_settings.py | 2 ++ .../trainers/tests/torch/test_action_model.py | 29 +++++++++++++++++-- .../mlagents/trainers/torch/action_model.py | 14 +++++++-- .../mlagents/trainers/torch/distributions.py | 13 +++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index 5fe453e43b..e53d0d566d 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -389,6 +389,7 @@ def test_exportable_settings(use_defaults): init_entcoef: 0.5 reward_signal_steps_per_update: 10.0 network_settings: + deterministic: true normalize: false hidden_units: 256 num_layers: 3 @@ -541,6 +542,7 @@ def test_default_settings(): test1_settings = run_options.behaviors["test1"] assert test1_settings.max_steps == 2 assert test1_settings.network_settings.hidden_units == 2000 + assert not test1_settings.network_settings.deterministic assert test1_settings.network_settings.num_layers == 1000 # Change the overridden fields back, and check if the rest are equal. test1_settings.max_steps = 1 diff --git a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py index 9722931446..1365c5fdba 100644 --- a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py +++ b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py @@ -11,10 +11,10 @@ from mlagents_envs.base_env import ActionSpec -def create_action_model(inp_size, act_size): +def create_action_model(inp_size, act_size, deterministic=False): mask = torch.ones([1, act_size * 2]) action_spec = ActionSpec(act_size, tuple(act_size for _ in range(act_size))) - action_model = ActionModel(inp_size, action_spec) + action_model = ActionModel(inp_size, action_spec, deterministic=deterministic) return action_model, mask @@ -43,6 +43,31 @@ def test_sample_action(): assert _disc.shape == (1, 1) +def test_deterministic_sample_action(): + inp_size = 4 + act_size = 2 + action_model, masks = create_action_model(inp_size, act_size, deterministic=True) + sample_inp = torch.ones((1, inp_size)) + dists = action_model._get_dists(sample_inp, masks=masks) + agent_action1 = action_model._sample_action(dists) + agent_action2 = action_model._sample_action(dists) + agent_action3 = action_model._sample_action(dists) + assert torch.equal(agent_action1.continuous_tensor, agent_action2.continuous_tensor) + assert torch.equal(agent_action1.continuous_tensor, agent_action3.continuous_tensor) + action_model, masks = create_action_model(inp_size, act_size, deterministic=False) + sample_inp = torch.ones((1, inp_size)) + dists = action_model._get_dists(sample_inp, masks=masks) + agent_action1 = action_model._sample_action(dists) + agent_action2 = action_model._sample_action(dists) + agent_action3 = action_model._sample_action(dists) + assert not torch.equal( + agent_action1.continuous_tensor, agent_action2.continuous_tensor + ) + assert not torch.equal( + agent_action1.continuous_tensor, agent_action3.continuous_tensor + ) + + def test_get_probs_and_entropy(): inp_size = 4 act_size = 2 diff --git a/ml-agents/mlagents/trainers/torch/action_model.py b/ml-agents/mlagents/trainers/torch/action_model.py index 28fc161edd..8d18416f68 100644 --- a/ml-agents/mlagents/trainers/torch/action_model.py +++ b/ml-agents/mlagents/trainers/torch/action_model.py @@ -75,15 +75,23 @@ def _sample_action(self, dists: DistInstances) -> AgentAction: :params dists: The DistInstances tuple :return: An AgentAction corresponding to the actions sampled from the DistInstances """ + continuous_action: Optional[torch.Tensor] = None discrete_action: Optional[List[torch.Tensor]] = None # This checks None because mypy complains otherwise if dists.continuous is not None: - continuous_action = dists.continuous.sample() + if self.deterministic: + continuous_action = dists.continuous.deterministic_sample() + else: + continuous_action = dists.continuous.sample() if dists.discrete is not None: discrete_action = [] - for discrete_dist in dists.discrete: - discrete_action.append(discrete_dist.sample()) + if self.deterministic: + for discrete_dist in dists.discrete: + discrete_action.append(discrete_dist.deterministic_sample()) + else: + for discrete_dist in dists.discrete: + discrete_action.append(discrete_dist.sample()) return AgentAction(continuous_action, discrete_action) def _get_dists(self, inputs: torch.Tensor, masks: torch.Tensor) -> DistInstances: diff --git a/ml-agents/mlagents/trainers/torch/distributions.py b/ml-agents/mlagents/trainers/torch/distributions.py index 1f5960d10b..00aee3aaa0 100644 --- a/ml-agents/mlagents/trainers/torch/distributions.py +++ b/ml-agents/mlagents/trainers/torch/distributions.py @@ -16,6 +16,13 @@ def sample(self) -> torch.Tensor: """ pass + @abc.abstractmethod + def deterministic_sample(self) -> torch.Tensor: + """ + Return the most probable sample from this distribution. + """ + pass + @abc.abstractmethod def log_prob(self, value: torch.Tensor) -> torch.Tensor: """ @@ -59,6 +66,9 @@ def sample(self): sample = self.mean + torch.randn_like(self.mean) * self.std return sample + def deterministic_sample(self): + return self.mean + def log_prob(self, value): var = self.std ** 2 log_scale = torch.log(self.std + EPSILON) @@ -113,6 +123,9 @@ def __init__(self, logits): def sample(self): return torch.multinomial(self.probs, 1) + def deterministic_sample(self): + return torch.argmax(self.probs).reshape((1, 1)) + def pdf(self, value): # This function is equivalent to torch.diag(self.probs.T[value.flatten().long()]), # but torch.diag is not supported by ONNX export. From 56597e750c88dabf636a804bd110f933230e5599 Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Wed, 27 Oct 2021 13:32:59 -0400 Subject: [PATCH 03/16] Add information to the changelog. --- com.unity.ml-agents/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index b91f9ae2bb..526f32f749 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -30,6 +30,8 @@ and this project adheres to 2. env_params.restarts_rate_limit_n (--restarts-rate-limit-n) [default=1] 3. env_params.restarts_rate_limit_period_s (--restarts-rate-limit-period-s) [default=60] +- Added a new `--deterministic` flag to make sure that actions are selected in a predictable deterministic manner. Same can +be achieved by setting a `deterministic: true` in the `network_settings` of the run options configuration. ### Bug Fixes - Fixed a bug where the critics were not being normalized during training. (#5595) - Fixed the bug where curriculum learning would crash because of the incorrect run_options parsing. (#5586) From f2d674e1934f3915e2f7df95e3a6a402dd8a8b97 Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Wed, 27 Oct 2021 17:17:35 -0400 Subject: [PATCH 04/16] Prioritize the CLI over the configuration file. --- ml-agents/mlagents/trainers/settings.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 24a46a7120..82a917900a 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -933,6 +933,7 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": # Override with CLI args # Keep deprecated --load working, TODO: remove argparse_args["resume"] = argparse_args["resume"] or argparse_args["load_model"] + for key, val in argparse_args.items(): if key in DetectDefault.non_default_args: if key in attr.fields_dict(CheckpointSettings): @@ -953,8 +954,11 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": # configure whether or not we should require all behavior names to be found in the config YAML final_runoptions.behaviors.set_config_specified(_require_all_behaviors) - for behaviour in final_runoptions.behaviors.keys(): - if not final_runoptions.behaviors[behaviour].network_settings.deterministic: + _non_default_args = DetectDefault.non_default_args + + # Prioritize the deterministic mode form the cli for deterministic actions. + if "deterministic" in _non_default_args: + for behaviour in final_runoptions.behaviors.keys(): final_runoptions.behaviors[ behaviour ].network_settings.deterministic = argparse_args["deterministic"] From d6ecfc84f7f9158dd7011e18d86c45c9f072d4ce Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Thu, 28 Oct 2021 13:54:52 -0400 Subject: [PATCH 05/16] Update documentation for config file. --- docs/Training-Configuration-File.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Training-Configuration-File.md b/docs/Training-Configuration-File.md index 537bea2f3e..669e050b3a 100644 --- a/docs/Training-Configuration-File.md +++ b/docs/Training-Configuration-File.md @@ -44,6 +44,7 @@ choice of the trainer (which we review on subsequent sections). | `network_settings -> normalize` | (default = `false`) Whether normalization is applied to the vector observation inputs. This normalization is based on the running average and variance of the vector observation. Normalization can be helpful in cases with complex continuous control problems, but may be harmful with simpler discrete control problems. | | `network_settings -> vis_encode_type` | (default = `simple`) Encoder type for encoding visual observations.

`simple` (default) uses a simple encoder which consists of two convolutional layers, `nature_cnn` uses the CNN implementation proposed by [Mnih et al.](https://www.nature.com/articles/nature14236), consisting of three convolutional layers, and `resnet` uses the [IMPALA Resnet](https://arxiv.org/abs/1802.01561) consisting of three stacked layers, each with two residual blocks, making a much larger network than the other two. `match3` is a smaller CNN ([Gudmundsoon et al.](https://www.researchgate.net/publication/328307928_Human-Like_Playtesting_with_Deep_Learning)) that can capture more granular spatial relationships and is optimized for board games. `fully_connected` uses a single fully connected dense layer as encoder without any convolutional layers.

Due to the size of convolution kernel, there is a minimum observation size limitation that each encoder type can handle - `simple`: 20x20, `nature_cnn`: 36x36, `resnet`: 15 x 15, `match3`: 5x5. `fully_connected` doesn't have convolutional layers and thus no size limits, but since it has less representation power it should be reserved for very small inputs. Note that using the `match3` CNN with very large visual input might result in a huge observation encoding and thus potentially slow down training or cause memory issues. | | `network_settings -> conditioning_type` | (default = `hyper`) Conditioning type for the policy using goal observations.

`none` treats the goal observations as regular observations, `hyper` (default) uses a HyperNetwork with goal observations as input to generate some of the weights of the policy. Note that when using `hyper` the number of parameters of the network increases greatly. Therefore, it is recommended to reduce the number of `hidden_units` when using this `conditioning_type` +| `network_settings -> deterministic` | (default = `false`) Ensures that actions are selected from the models output deterministically to ensure predictable and reproducible results. This can be overwritten by the `--deterministic` flag on the CLI. ## Trainer-specific Configurations From 2889a0713266372811d35134ef55007ec0a1aaa8 Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Fri, 29 Oct 2021 13:10:56 -0400 Subject: [PATCH 06/16] CR refactor. --- ml-agents/mlagents/trainers/torch/action_model.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ml-agents/mlagents/trainers/torch/action_model.py b/ml-agents/mlagents/trainers/torch/action_model.py index 8d18416f68..4928fa80a1 100644 --- a/ml-agents/mlagents/trainers/torch/action_model.py +++ b/ml-agents/mlagents/trainers/torch/action_model.py @@ -67,7 +67,7 @@ def __init__( # During training, clipping is done in TorchPolicy, but we need to clip before ONNX # export as well. self._clip_action_on_export = not tanh_squash - self.deterministic = deterministic + self._deterministic = deterministic def _sample_action(self, dists: DistInstances) -> AgentAction: """ @@ -80,13 +80,13 @@ def _sample_action(self, dists: DistInstances) -> AgentAction: discrete_action: Optional[List[torch.Tensor]] = None # This checks None because mypy complains otherwise if dists.continuous is not None: - if self.deterministic: + if self._deterministic: continuous_action = dists.continuous.deterministic_sample() else: continuous_action = dists.continuous.sample() if dists.discrete is not None: discrete_action = [] - if self.deterministic: + if self._deterministic: for discrete_dist in dists.discrete: discrete_action.append(discrete_dist.deterministic_sample()) else: From f9d2ea1c8e72bd90942c5ee804aa8d24c5754925 Mon Sep 17 00:00:00 2001 From: cmard <87716492+cmard@users.noreply.github.com> Date: Mon, 1 Nov 2021 09:34:12 -0400 Subject: [PATCH 07/16] Update docs/Training-Configuration-File.md Co-authored-by: Miguel Alonso Jr. <76960110+miguelalonsojr@users.noreply.github.com> Update com.unity.ml-agents/CHANGELOG.md Co-authored-by: Miguel Alonso Jr. <76960110+miguelalonsojr@users.noreply.github.com> Update com.unity.ml-agents/CHANGELOG.md Co-authored-by: Miguel Alonso Jr. <76960110+miguelalonsojr@users.noreply.github.com> Update com.unity.ml-agents/CHANGELOG.md Co-authored-by: Maryam Honari Update ml-agents/mlagents/trainers/settings.py Co-authored-by: Maryam Honari Update ml-agents/mlagents/trainers/cli_utils.py Co-authored-by: Maryam Honari --- com.unity.ml-agents/CHANGELOG.md | 4 ++-- docs/Training-Configuration-File.md | 2 +- ml-agents/mlagents/trainers/cli_utils.py | 2 +- ml-agents/mlagents/trainers/settings.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index 526f32f749..2b427c66d8 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -30,8 +30,8 @@ and this project adheres to 2. env_params.restarts_rate_limit_n (--restarts-rate-limit-n) [default=1] 3. env_params.restarts_rate_limit_period_s (--restarts-rate-limit-period-s) [default=60] -- Added a new `--deterministic` flag to make sure that actions are selected in a predictable deterministic manner. Same can -be achieved by setting a `deterministic: true` in the `network_settings` of the run options configuration. +- Added a new `--deterministic` cli flag to deterministically select the most probable actions in policy. The same thing can +be achieved by adding `deterministic: true` under `network_settings` of the run options configuration. ### Bug Fixes - Fixed a bug where the critics were not being normalized during training. (#5595) - Fixed the bug where curriculum learning would crash because of the incorrect run_options parsing. (#5586) diff --git a/docs/Training-Configuration-File.md b/docs/Training-Configuration-File.md index 669e050b3a..a3e6cc35fb 100644 --- a/docs/Training-Configuration-File.md +++ b/docs/Training-Configuration-File.md @@ -44,7 +44,7 @@ choice of the trainer (which we review on subsequent sections). | `network_settings -> normalize` | (default = `false`) Whether normalization is applied to the vector observation inputs. This normalization is based on the running average and variance of the vector observation. Normalization can be helpful in cases with complex continuous control problems, but may be harmful with simpler discrete control problems. | | `network_settings -> vis_encode_type` | (default = `simple`) Encoder type for encoding visual observations.

`simple` (default) uses a simple encoder which consists of two convolutional layers, `nature_cnn` uses the CNN implementation proposed by [Mnih et al.](https://www.nature.com/articles/nature14236), consisting of three convolutional layers, and `resnet` uses the [IMPALA Resnet](https://arxiv.org/abs/1802.01561) consisting of three stacked layers, each with two residual blocks, making a much larger network than the other two. `match3` is a smaller CNN ([Gudmundsoon et al.](https://www.researchgate.net/publication/328307928_Human-Like_Playtesting_with_Deep_Learning)) that can capture more granular spatial relationships and is optimized for board games. `fully_connected` uses a single fully connected dense layer as encoder without any convolutional layers.

Due to the size of convolution kernel, there is a minimum observation size limitation that each encoder type can handle - `simple`: 20x20, `nature_cnn`: 36x36, `resnet`: 15 x 15, `match3`: 5x5. `fully_connected` doesn't have convolutional layers and thus no size limits, but since it has less representation power it should be reserved for very small inputs. Note that using the `match3` CNN with very large visual input might result in a huge observation encoding and thus potentially slow down training or cause memory issues. | | `network_settings -> conditioning_type` | (default = `hyper`) Conditioning type for the policy using goal observations.

`none` treats the goal observations as regular observations, `hyper` (default) uses a HyperNetwork with goal observations as input to generate some of the weights of the policy. Note that when using `hyper` the number of parameters of the network increases greatly. Therefore, it is recommended to reduce the number of `hidden_units` when using this `conditioning_type` -| `network_settings -> deterministic` | (default = `false`) Ensures that actions are selected from the models output deterministically to ensure predictable and reproducible results. This can be overwritten by the `--deterministic` flag on the CLI. +| `network_settings -> deterministic` | (default = `false`) When set to true, ensures that actions are selected from the models output deterministically to ensure predictable and reproducible results. This can be overwritten by the `--deterministic` flag on the CLI. ## Trainer-specific Configurations diff --git a/ml-agents/mlagents/trainers/cli_utils.py b/ml-agents/mlagents/trainers/cli_utils.py index ca7fd1e02e..3aa2f8b8f8 100644 --- a/ml-agents/mlagents/trainers/cli_utils.py +++ b/ml-agents/mlagents/trainers/cli_utils.py @@ -96,7 +96,7 @@ def _create_parser() -> argparse.ArgumentParser: default=False, dest="deterministic", action=DetectDefaultStoreTrue, - help="Whether to use the deterministic samples from the data.", + help="Whether to select actions deterministically in policy. `dist.mean` for continuous action space, and `dist.argmax` for deterministic action space ", ) argparser.add_argument( "--force", diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 82a917900a..f0b859fa33 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -956,7 +956,7 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": _non_default_args = DetectDefault.non_default_args - # Prioritize the deterministic mode form the cli for deterministic actions. + # Prioritize the deterministic mode from the cli for deterministic actions. if "deterministic" in _non_default_args: for behaviour in final_runoptions.behaviors.keys(): final_runoptions.behaviors[ From efb1dea9442ce7889f4e184ce11f34c73ac3c1c5 Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Mon, 1 Nov 2021 10:32:21 -0400 Subject: [PATCH 08/16] Fix CR requests --- ml-agents/mlagents/trainers/tests/test_settings.py | 8 ++++++-- ml-agents/mlagents/trainers/torch/action_model.py | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index e53d0d566d..9d14fc5cc7 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -529,7 +529,10 @@ def test_environment_settings(): def test_default_settings(): # Make default settings, one nested and one not. - default_settings = {"max_steps": 1, "network_settings": {"num_layers": 1000}} + default_settings = { + "max_steps": 1, + "network_settings": {"num_layers": 1000, "deterministic": True}, + } behaviors = {"test1": {"max_steps": 2, "network_settings": {"hidden_units": 2000}}} run_options_dict = {"default_settings": default_settings, "behaviors": behaviors} run_options = RunOptions.from_dict(run_options_dict) @@ -542,8 +545,9 @@ def test_default_settings(): test1_settings = run_options.behaviors["test1"] assert test1_settings.max_steps == 2 assert test1_settings.network_settings.hidden_units == 2000 - assert not test1_settings.network_settings.deterministic + assert test1_settings.network_settings.deterministic is True assert test1_settings.network_settings.num_layers == 1000 + # Change the overridden fields back, and check if the rest are equal. test1_settings.max_steps = 1 test1_settings.network_settings.hidden_units == default_settings_cls.network_settings.hidden_units diff --git a/ml-agents/mlagents/trainers/torch/action_model.py b/ml-agents/mlagents/trainers/torch/action_model.py index 4928fa80a1..8730e04255 100644 --- a/ml-agents/mlagents/trainers/torch/action_model.py +++ b/ml-agents/mlagents/trainers/torch/action_model.py @@ -44,6 +44,7 @@ def __init__( :params action_spec: The ActionSpec defining the action space dimensions and distributions. :params conditional_sigma: Whether or not the std of a Gaussian is conditioned on state. :params tanh_squash: Whether to squash the output of a Gaussian with the tanh function. + :params deterministic: Whether to select actions deterministically in policy. """ super().__init__() self.encoding_size = hidden_size @@ -79,6 +80,7 @@ def _sample_action(self, dists: DistInstances) -> AgentAction: continuous_action: Optional[torch.Tensor] = None discrete_action: Optional[List[torch.Tensor]] = None # This checks None because mypy complains otherwise + print(self._deterministic) if dists.continuous is not None: if self._deterministic: continuous_action = dists.continuous.deterministic_sample() From f2f69f5d42306de108f13f56f009352eff6e8b4c Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Wed, 3 Nov 2021 13:53:04 -0400 Subject: [PATCH 09/16] Add tests for discrete. --- ml-agents/mlagents/trainers/tests/torch/test_action_model.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py index 1365c5fdba..1dc8b21a54 100644 --- a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py +++ b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py @@ -54,6 +54,9 @@ def test_deterministic_sample_action(): agent_action3 = action_model._sample_action(dists) assert torch.equal(agent_action1.continuous_tensor, agent_action2.continuous_tensor) assert torch.equal(agent_action1.continuous_tensor, agent_action3.continuous_tensor) + assert torch.equal(agent_action1.discrete_tensor, agent_action2.discrete_tensor) + assert torch.equal(agent_action1.discrete_tensor, agent_action3.discrete_tensor) + action_model, masks = create_action_model(inp_size, act_size, deterministic=False) sample_inp = torch.ones((1, inp_size)) dists = action_model._get_dists(sample_inp, masks=masks) @@ -66,6 +69,8 @@ def test_deterministic_sample_action(): assert not torch.equal( agent_action1.continuous_tensor, agent_action3.continuous_tensor ) + assert not torch.equal(agent_action1.discrete_tensor, agent_action2.discrete_tensor) + assert not torch.equal(agent_action1.discrete_tensor, agent_action3.discrete_tensor) def test_get_probs_and_entropy(): From c1fc35028f3262b77934a7cef0ef4175f50769c7 Mon Sep 17 00:00:00 2001 From: cmard <87716492+cmard@users.noreply.github.com> Date: Wed, 3 Nov 2021 14:09:45 -0400 Subject: [PATCH 10/16] Update ml-agents/mlagents/trainers/torch/distributions.py Co-authored-by: Maryam Honari --- ml-agents/mlagents/trainers/torch/distributions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/torch/distributions.py b/ml-agents/mlagents/trainers/torch/distributions.py index 00aee3aaa0..c60426c998 100644 --- a/ml-agents/mlagents/trainers/torch/distributions.py +++ b/ml-agents/mlagents/trainers/torch/distributions.py @@ -124,7 +124,7 @@ def sample(self): return torch.multinomial(self.probs, 1) def deterministic_sample(self): - return torch.argmax(self.probs).reshape((1, 1)) + return torch.argmax(self.probs, dim=1, keepdim=True) def pdf(self, value): # This function is equivalent to torch.diag(self.probs.T[value.flatten().long()]), From d23a719d2c652b342c4275b38e271b346b2676c9 Mon Sep 17 00:00:00 2001 From: Chingiz Mardanov Date: Mon, 15 Nov 2021 17:41:01 -0500 Subject: [PATCH 11/16] Added more stable test. --- .../trainers/tests/torch/test_action_model.py | 29 ++++++++++++++----- .../mlagents/trainers/torch/distributions.py | 1 + 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py index 1dc8b21a54..2f81aaf034 100644 --- a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py +++ b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py @@ -12,7 +12,7 @@ def create_action_model(inp_size, act_size, deterministic=False): - mask = torch.ones([1, act_size * 2]) + mask = torch.ones([1, act_size ** 2]) action_spec = ActionSpec(act_size, tuple(act_size for _ in range(act_size))) action_model = ActionModel(inp_size, action_spec, deterministic=deterministic) return action_model, mask @@ -45,13 +45,14 @@ def test_sample_action(): def test_deterministic_sample_action(): inp_size = 4 - act_size = 2 + act_size = 8 action_model, masks = create_action_model(inp_size, act_size, deterministic=True) sample_inp = torch.ones((1, inp_size)) dists = action_model._get_dists(sample_inp, masks=masks) agent_action1 = action_model._sample_action(dists) agent_action2 = action_model._sample_action(dists) agent_action3 = action_model._sample_action(dists) + assert torch.equal(agent_action1.continuous_tensor, agent_action2.continuous_tensor) assert torch.equal(agent_action1.continuous_tensor, agent_action3.continuous_tensor) assert torch.equal(agent_action1.discrete_tensor, agent_action2.discrete_tensor) @@ -63,14 +64,26 @@ def test_deterministic_sample_action(): agent_action1 = action_model._sample_action(dists) agent_action2 = action_model._sample_action(dists) agent_action3 = action_model._sample_action(dists) - assert not torch.equal( + + chance_counter = 0 + + if not torch.equal( agent_action1.continuous_tensor, agent_action2.continuous_tensor - ) - assert not torch.equal( + ): + chance_counter += 1 + + if not torch.equal( agent_action1.continuous_tensor, agent_action3.continuous_tensor - ) - assert not torch.equal(agent_action1.discrete_tensor, agent_action2.discrete_tensor) - assert not torch.equal(agent_action1.discrete_tensor, agent_action3.discrete_tensor) + ): + chance_counter += 1 + + assert chance_counter > 1 + chance_counter = 0 + if not torch.equal(agent_action1.discrete_tensor, agent_action2.discrete_tensor): + chance_counter += 1 + if not torch.equal(agent_action1.discrete_tensor, agent_action3.discrete_tensor): + chance_counter += 1 + assert chance_counter > 1 def test_get_probs_and_entropy(): diff --git a/ml-agents/mlagents/trainers/torch/distributions.py b/ml-agents/mlagents/trainers/torch/distributions.py index c60426c998..25b11edf85 100644 --- a/ml-agents/mlagents/trainers/torch/distributions.py +++ b/ml-agents/mlagents/trainers/torch/distributions.py @@ -225,6 +225,7 @@ def _mask_branch( # We do -1 * tensor + constant instead of constant - tensor because it seems # Barracuda might swap the inputs of a "Sub" operation logits = logits * allow_mask - 1e8 * block_mask + return logits def _split_masks(self, masks: torch.Tensor) -> List[torch.Tensor]: From 6af4d21cfdf7ceeb567b8428314a1c30211f1142 Mon Sep 17 00:00:00 2001 From: cmard <87716492+cmard@users.noreply.github.com> Date: Tue, 16 Nov 2021 11:53:38 -0500 Subject: [PATCH 12/16] Return deterministic actions for training (#5615) * Added more stable test. * Fix the tests. * Fix pre-commit * Fix help line to pass precommit. --- ml-agents/mlagents/trainers/cli_utils.py | 3 ++- .../trainers/tests/torch/test_action_model.py | 16 +++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ml-agents/mlagents/trainers/cli_utils.py b/ml-agents/mlagents/trainers/cli_utils.py index 3aa2f8b8f8..de420c42a4 100644 --- a/ml-agents/mlagents/trainers/cli_utils.py +++ b/ml-agents/mlagents/trainers/cli_utils.py @@ -96,7 +96,8 @@ def _create_parser() -> argparse.ArgumentParser: default=False, dest="deterministic", action=DetectDefaultStoreTrue, - help="Whether to select actions deterministically in policy. `dist.mean` for continuous action space, and `dist.argmax` for deterministic action space ", + help="Whether to select actions deterministically in policy. `dist.mean` for continuous action " + "space, and `dist.argmax` for deterministic action space ", ) argparser.add_argument( "--force", diff --git a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py index 2f81aaf034..a33f793927 100644 --- a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py +++ b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py @@ -65,24 +65,22 @@ def test_deterministic_sample_action(): agent_action2 = action_model._sample_action(dists) agent_action3 = action_model._sample_action(dists) - chance_counter = 0 - - if not torch.equal( + assert not torch.equal( agent_action1.continuous_tensor, agent_action2.continuous_tensor - ): - chance_counter += 1 + ) - if not torch.equal( + assert not torch.equal( agent_action1.continuous_tensor, agent_action3.continuous_tensor - ): - chance_counter += 1 + ) - assert chance_counter > 1 chance_counter = 0 if not torch.equal(agent_action1.discrete_tensor, agent_action2.discrete_tensor): chance_counter += 1 if not torch.equal(agent_action1.discrete_tensor, agent_action3.discrete_tensor): chance_counter += 1 + if not torch.equal(agent_action2.discrete_tensor, agent_action3.discrete_tensor): + chance_counter += 1 + assert chance_counter > 1 From 13e9a889c322551b57e0173d208dedf9fe3789e6 Mon Sep 17 00:00:00 2001 From: Maryam Honari Date: Tue, 16 Nov 2021 14:16:55 -0800 Subject: [PATCH 13/16] support for deterministic inference in onnx (#5593) * Init: actor.forward outputs separate deterministic actions * changelog * Renaming * Add more tests --- com.unity.ml-agents/CHANGELOG.md | 1 + .../trainers/tests/torch/test_action_model.py | 33 +++++++++++++++++++ .../mlagents/trainers/torch/action_model.py | 28 ++++++++++++++-- .../trainers/torch/model_serialization.py | 5 +++ ml-agents/mlagents/trainers/torch/networks.py | 14 ++++++-- 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index 2b427c66d8..040afbfcea 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to - Added a new `--deterministic` cli flag to deterministically select the most probable actions in policy. The same thing can be achieved by adding `deterministic: true` under `network_settings` of the run options configuration. +- Extra tensors are now serialized to support deterministic action selection in onnx. (#5597) ### Bug Fixes - Fixed a bug where the critics were not being normalized during training. (#5595) - Fixed the bug where curriculum learning would crash because of the incorrect run_options parsing. (#5586) diff --git a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py index a33f793927..5ffbd9ce6b 100644 --- a/ml-agents/mlagents/trainers/tests/torch/test_action_model.py +++ b/ml-agents/mlagents/trainers/tests/torch/test_action_model.py @@ -120,3 +120,36 @@ def test_get_probs_and_entropy(): for ent, val in zip(entropies[0].tolist(), [1.4189, 0.6191, 0.6191]): assert ent == pytest.approx(val, abs=0.01) + + +def test_get_onnx_deterministic_tensors(): + inp_size = 4 + act_size = 2 + action_model, masks = create_action_model(inp_size, act_size) + sample_inp = torch.ones((1, inp_size)) + out_tensors = action_model.get_action_out(sample_inp, masks=masks) + ( + continuous_out, + discrete_out, + action_out_deprecated, + deterministic_continuous_out, + deterministic_discrete_out, + ) = out_tensors + assert continuous_out.shape == (1, 2) + assert discrete_out.shape == (1, 2) + assert deterministic_discrete_out.shape == (1, 2) + assert deterministic_continuous_out.shape == (1, 2) + + # Second sampling from same distribution + out_tensors2 = action_model.get_action_out(sample_inp, masks=masks) + ( + continuous_out_2, + discrete_out_2, + action_out_2_deprecated, + deterministic_continuous_out_2, + deterministic_discrete_out_2, + ) = out_tensors2 + assert ~torch.all(torch.eq(continuous_out, continuous_out_2)) + assert torch.all( + torch.eq(deterministic_continuous_out, deterministic_continuous_out_2) + ) diff --git a/ml-agents/mlagents/trainers/torch/action_model.py b/ml-agents/mlagents/trainers/torch/action_model.py index 8730e04255..65dfd32b40 100644 --- a/ml-agents/mlagents/trainers/torch/action_model.py +++ b/ml-agents/mlagents/trainers/torch/action_model.py @@ -10,6 +10,7 @@ from mlagents.trainers.torch.action_log_probs import ActionLogProbs from mlagents_envs.base_env import ActionSpec + EPSILON = 1e-7 # Small value to avoid divide by zero @@ -173,12 +174,20 @@ def get_action_out(self, inputs: torch.Tensor, masks: torch.Tensor) -> torch.Ten """ dists = self._get_dists(inputs, masks) continuous_out, discrete_out, action_out_deprecated = None, None, None + deterministic_continuous_out, deterministic_discrete_out = ( + None, + None, + ) # deterministic actions if self.action_spec.continuous_size > 0 and dists.continuous is not None: continuous_out = dists.continuous.exported_model_output() - action_out_deprecated = dists.continuous.exported_model_output() + action_out_deprecated = continuous_out + deterministic_continuous_out = dists.continuous.deterministic_sample() if self._clip_action_on_export: continuous_out = torch.clamp(continuous_out, -3, 3) / 3 - action_out_deprecated = torch.clamp(action_out_deprecated, -3, 3) / 3 + action_out_deprecated = continuous_out + deterministic_continuous_out = ( + torch.clamp(deterministic_continuous_out, -3, 3) / 3 + ) if self.action_spec.discrete_size > 0 and dists.discrete is not None: discrete_out_list = [ discrete_dist.exported_model_output() @@ -186,10 +195,23 @@ def get_action_out(self, inputs: torch.Tensor, masks: torch.Tensor) -> torch.Ten ] discrete_out = torch.cat(discrete_out_list, dim=1) action_out_deprecated = torch.cat(discrete_out_list, dim=1) + deterministic_discrete_out_list = [ + discrete_dist.deterministic_sample() for discrete_dist in dists.discrete + ] + deterministic_discrete_out = torch.cat( + deterministic_discrete_out_list, dim=1 + ) + # deprecated action field does not support hybrid action if self.action_spec.continuous_size > 0 and self.action_spec.discrete_size > 0: action_out_deprecated = None - return continuous_out, discrete_out, action_out_deprecated + return ( + continuous_out, + discrete_out, + action_out_deprecated, + deterministic_continuous_out, + deterministic_discrete_out, + ) def forward( self, inputs: torch.Tensor, masks: torch.Tensor diff --git a/ml-agents/mlagents/trainers/torch/model_serialization.py b/ml-agents/mlagents/trainers/torch/model_serialization.py index 0fa946280c..f204b52445 100644 --- a/ml-agents/mlagents/trainers/torch/model_serialization.py +++ b/ml-agents/mlagents/trainers/torch/model_serialization.py @@ -56,10 +56,13 @@ class TensorNames: recurrent_output = "recurrent_out" memory_size = "memory_size" version_number = "version_number" + continuous_action_output_shape = "continuous_action_output_shape" discrete_action_output_shape = "discrete_action_output_shape" continuous_action_output = "continuous_actions" discrete_action_output = "discrete_actions" + deterministic_continuous_action_output = "deterministic_continuous_actions" + deterministic_discrete_action_output = "deterministic_discrete_actions" # Deprecated TensorNames entries for backward compatibility is_continuous_control_deprecated = "is_continuous_control" @@ -122,6 +125,7 @@ def __init__(self, policy): self.output_names += [ TensorNames.continuous_action_output, TensorNames.continuous_action_output_shape, + TensorNames.deterministic_continuous_action_output, ] self.dynamic_axes.update( {TensorNames.continuous_action_output: {0: "batch"}} @@ -130,6 +134,7 @@ def __init__(self, policy): self.output_names += [ TensorNames.discrete_action_output, TensorNames.discrete_action_output_shape, + TensorNames.deterministic_discrete_action_output, ] self.dynamic_axes.update({TensorNames.discrete_action_output: {0: "batch"}}) diff --git a/ml-agents/mlagents/trainers/torch/networks.py b/ml-agents/mlagents/trainers/torch/networks.py index 19b97e2860..be8fb4b732 100644 --- a/ml-agents/mlagents/trainers/torch/networks.py +++ b/ml-agents/mlagents/trainers/torch/networks.py @@ -676,12 +676,22 @@ def forward( cont_action_out, disc_action_out, action_out_deprecated, + deterministic_cont_action_out, + deterministic_disc_action_out, ) = self.action_model.get_action_out(encoding, masks) export_out = [self.version_number, self.memory_size_vector] if self.action_spec.continuous_size > 0: - export_out += [cont_action_out, self.continuous_act_size_vector] + export_out += [ + cont_action_out, + self.continuous_act_size_vector, + deterministic_cont_action_out, + ] if self.action_spec.discrete_size > 0: - export_out += [disc_action_out, self.discrete_act_size_vector] + export_out += [ + disc_action_out, + self.discrete_act_size_vector, + deterministic_disc_action_out, + ] if self.network_body.memory_size > 0: export_out += [memories_out] return tuple(export_out) From b34f3b9c3f2c717c7e67577483011302975b5d42 Mon Sep 17 00:00:00 2001 From: Maryam Honari Date: Thu, 18 Nov 2021 07:39:00 -0800 Subject: [PATCH 14/16] Package changes to support deterministic inference (#5599) * Init: actor.forward outputs separate deterministic actions * fix tensor shape for discrete actions * Add test and editor flag - Add tests for deterministic sampling - update editor and tooltips * Reverting to "Deterministic Inference" * dissect tests * Update docs --- com.unity.ml-agents/CHANGELOG.md | 9 +- .../Editor/BehaviorParametersEditor.cs | 4 +- com.unity.ml-agents/Runtime/Academy.cs | 6 +- .../Inference/BarracudaModelExtensions.cs | 107 +++++++++++++----- .../Inference/BarracudaModelParamLoader.cs | 24 ++-- .../Runtime/Inference/ModelRunner.cs | 14 ++- .../Runtime/Inference/TensorApplier.cs | 9 +- .../Runtime/Inference/TensorGenerator.cs | 13 ++- .../Runtime/Inference/TensorNames.cs | 2 + .../Runtime/Policies/BarracudaPolicy.cs | 13 ++- .../Runtime/Policies/BehaviorParameters.cs | 18 ++- .../Tests/Editor/Inference/ModelRunnerTest.cs | 94 +++++++++++++++ .../deterContinuous2vis8vec2action_v2_0.onnx | Bin 0 -> 73999 bytes ...erContinuous2vis8vec2action_v2_0.onnx.meta | 14 +++ .../deterDiscrete1obs3action_v2_0.onnx | Bin 0 -> 3715 bytes .../deterDiscrete1obs3action_v2_0.onnx.meta | 14 +++ .../Tests/Runtime/RuntimeAPITest.cs | 1 + docs/Getting-Started.md | 3 + docs/Learning-Environment-Design-Agents.md | 3 + docs/images/3dball_learning_brain.png | Bin 43926 -> 47424 bytes 20 files changed, 291 insertions(+), 57 deletions(-) create mode 100644 com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx create mode 100644 com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx.meta create mode 100644 com.unity.ml-agents/Tests/Editor/TestModels/deterDiscrete1obs3action_v2_0.onnx create mode 100644 com.unity.ml-agents/Tests/Editor/TestModels/deterDiscrete1obs3action_v2_0.onnx.meta diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index 040afbfcea..7122b4f38a 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -30,9 +30,12 @@ and this project adheres to 2. env_params.restarts_rate_limit_n (--restarts-rate-limit-n) [default=1] 3. env_params.restarts_rate_limit_period_s (--restarts-rate-limit-period-s) [default=60] -- Added a new `--deterministic` cli flag to deterministically select the most probable actions in policy. The same thing can -be achieved by adding `deterministic: true` under `network_settings` of the run options configuration. -- Extra tensors are now serialized to support deterministic action selection in onnx. (#5597) + +- Deterministic action selection is now supported during training and inference + - Added a new `--deterministic` cli flag to deterministically select the most probable actions in policy. The same thing can + be achieved by adding `deterministic: true` under `network_settings` of the run options configuration.(#5619) + - Extra tensors are now serialized to support deterministic action selection in onnx. (#5593) + - Support inference with deterministic action selection in editor (#5599) ### Bug Fixes - Fixed a bug where the critics were not being normalized during training. (#5595) - Fixed the bug where curriculum learning would crash because of the incorrect run_options parsing. (#5586) diff --git a/com.unity.ml-agents/Editor/BehaviorParametersEditor.cs b/com.unity.ml-agents/Editor/BehaviorParametersEditor.cs index c5e8ddc802..a95b2846f3 100644 --- a/com.unity.ml-agents/Editor/BehaviorParametersEditor.cs +++ b/com.unity.ml-agents/Editor/BehaviorParametersEditor.cs @@ -25,6 +25,7 @@ internal class BehaviorParametersEditor : UnityEditor.Editor const string k_BrainParametersName = "m_BrainParameters"; const string k_ModelName = "m_Model"; const string k_InferenceDeviceName = "m_InferenceDevice"; + const string k_DeterministicInference = "m_DeterministicInference"; const string k_BehaviorTypeName = "m_BehaviorType"; const string k_TeamIdName = "TeamId"; const string k_UseChildSensorsName = "m_UseChildSensors"; @@ -68,6 +69,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(so.FindProperty(k_ModelName), true); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(so.FindProperty(k_InferenceDeviceName), true); + EditorGUILayout.PropertyField(so.FindProperty(k_DeterministicInference), true); EditorGUI.indentLevel--; } needPolicyUpdate = needPolicyUpdate || EditorGUI.EndChangeCheck(); @@ -156,7 +158,7 @@ void DisplayFailedModelChecks() { var failedChecks = Inference.BarracudaModelParamLoader.CheckModel( barracudaModel, brainParameters, sensors, actuatorComponents, - observableAttributeSensorTotalSize, behaviorParameters.BehaviorType + observableAttributeSensorTotalSize, behaviorParameters.BehaviorType, behaviorParameters.DeterministicInference ); foreach (var check in failedChecks) { diff --git a/com.unity.ml-agents/Runtime/Academy.cs b/com.unity.ml-agents/Runtime/Academy.cs index 85cab21b26..409ccb1dca 100644 --- a/com.unity.ml-agents/Runtime/Academy.cs +++ b/com.unity.ml-agents/Runtime/Academy.cs @@ -616,14 +616,16 @@ void EnvironmentReset() /// /// The inference device (CPU or GPU) the ModelRunner will use. /// + /// Inference only: set to true if the action selection from model should be + /// Deterministic. /// The ModelRunner compatible with the input settings. internal ModelRunner GetOrCreateModelRunner( - NNModel model, ActionSpec actionSpec, InferenceDevice inferenceDevice) + NNModel model, ActionSpec actionSpec, InferenceDevice inferenceDevice, bool deterministicInference = false) { var modelRunner = m_ModelRunners.Find(x => x.HasModel(model, inferenceDevice)); if (modelRunner == null) { - modelRunner = new ModelRunner(model, actionSpec, inferenceDevice, m_InferenceSeed); + modelRunner = new ModelRunner(model, actionSpec, inferenceDevice, m_InferenceSeed, deterministicInference); m_ModelRunners.Add(modelRunner); m_InferenceSeed++; } diff --git a/com.unity.ml-agents/Runtime/Inference/BarracudaModelExtensions.cs b/com.unity.ml-agents/Runtime/Inference/BarracudaModelExtensions.cs index 6fd3872535..5e7338c057 100644 --- a/com.unity.ml-agents/Runtime/Inference/BarracudaModelExtensions.cs +++ b/com.unity.ml-agents/Runtime/Inference/BarracudaModelExtensions.cs @@ -112,8 +112,10 @@ public static int GetNumVisualInputs(this Model model) /// /// The Barracuda engine model for loading static parameters. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// Array of the output tensor names of the model - public static string[] GetOutputNames(this Model model) + public static string[] GetOutputNames(this Model model, bool deterministicInference = false) { var names = new List(); @@ -122,13 +124,13 @@ public static string[] GetOutputNames(this Model model) return names.ToArray(); } - if (model.HasContinuousOutputs()) + if (model.HasContinuousOutputs(deterministicInference)) { - names.Add(model.ContinuousOutputName()); + names.Add(model.ContinuousOutputName(deterministicInference)); } - if (model.HasDiscreteOutputs()) + if (model.HasDiscreteOutputs(deterministicInference)) { - names.Add(model.DiscreteOutputName()); + names.Add(model.DiscreteOutputName(deterministicInference)); } var modelVersion = model.GetVersion(); @@ -149,8 +151,10 @@ public static string[] GetOutputNames(this Model model) /// /// The Barracuda engine model for loading static parameters. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// True if the model has continuous action outputs. - public static bool HasContinuousOutputs(this Model model) + public static bool HasContinuousOutputs(this Model model, bool deterministicInference = false) { if (model == null) return false; @@ -160,8 +164,13 @@ public static bool HasContinuousOutputs(this Model model) } else { - return model.outputs.Contains(TensorNames.ContinuousActionOutput) && - (int)model.GetTensorByName(TensorNames.ContinuousActionOutputShape)[0] > 0; + bool hasStochasticOutput = !deterministicInference && + model.outputs.Contains(TensorNames.ContinuousActionOutput); + bool hasDeterministicOutput = deterministicInference && + model.outputs.Contains(TensorNames.DeterministicContinuousActionOutput); + + return (hasStochasticOutput || hasDeterministicOutput) && + (int)model.GetTensorByName(TensorNames.ContinuousActionOutputShape)[0] > 0; } } @@ -194,8 +203,10 @@ public static int ContinuousOutputSize(this Model model) /// /// The Barracuda engine model for loading static parameters. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// Tensor name of continuous action output. - public static string ContinuousOutputName(this Model model) + public static string ContinuousOutputName(this Model model, bool deterministicInference = false) { if (model == null) return null; @@ -205,7 +216,7 @@ public static string ContinuousOutputName(this Model model) } else { - return TensorNames.ContinuousActionOutput; + return deterministicInference ? TensorNames.DeterministicContinuousActionOutput : TensorNames.ContinuousActionOutput; } } @@ -215,8 +226,10 @@ public static string ContinuousOutputName(this Model model) /// /// The Barracuda engine model for loading static parameters. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// True if the model has discrete action outputs. - public static bool HasDiscreteOutputs(this Model model) + public static bool HasDiscreteOutputs(this Model model, bool deterministicInference = false) { if (model == null) return false; @@ -226,7 +239,12 @@ public static bool HasDiscreteOutputs(this Model model) } else { - return model.outputs.Contains(TensorNames.DiscreteActionOutput) && model.DiscreteOutputSize() > 0; + bool hasStochasticOutput = !deterministicInference && + model.outputs.Contains(TensorNames.DiscreteActionOutput); + bool hasDeterministicOutput = deterministicInference && + model.outputs.Contains(TensorNames.DeterministicDiscreteActionOutput); + return (hasStochasticOutput || hasDeterministicOutput) && + model.DiscreteOutputSize() > 0; } } @@ -279,8 +297,10 @@ public static int DiscreteOutputSize(this Model model) /// /// The Barracuda engine model for loading static parameters. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// Tensor name of discrete action output. - public static string DiscreteOutputName(this Model model) + public static string DiscreteOutputName(this Model model, bool deterministicInference = false) { if (model == null) return null; @@ -290,7 +310,7 @@ public static string DiscreteOutputName(this Model model) } else { - return TensorNames.DiscreteActionOutput; + return deterministicInference ? TensorNames.DeterministicDiscreteActionOutput : TensorNames.DiscreteActionOutput; } } @@ -316,9 +336,11 @@ public static bool SupportsContinuousAndDiscrete(this Model model) /// The Barracuda engine model for loading static parameters. /// /// Output list of failure messages - /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// True if the model contains all the expected tensors. - public static bool CheckExpectedTensors(this Model model, List failedModelChecks) + /// TODO: add checks for deterministic actions + public static bool CheckExpectedTensors(this Model model, List failedModelChecks, bool deterministicInference = false) { // Check the presence of model version var modelApiVersionTensor = model.GetTensorByName(TensorNames.VersionNumber); @@ -343,7 +365,9 @@ public static bool CheckExpectedTensors(this Model model, List fail // Check the presence of action output tensor if (!model.outputs.Contains(TensorNames.ActionOutputDeprecated) && !model.outputs.Contains(TensorNames.ContinuousActionOutput) && - !model.outputs.Contains(TensorNames.DiscreteActionOutput)) + !model.outputs.Contains(TensorNames.DiscreteActionOutput) && + !model.outputs.Contains(TensorNames.DeterministicContinuousActionOutput) && + !model.outputs.Contains(TensorNames.DeterministicDiscreteActionOutput)) { failedModelChecks.Add( FailedCheck.Warning("The model does not contain any Action Output Node.") @@ -373,22 +397,51 @@ public static bool CheckExpectedTensors(this Model model, List fail } else { - if (model.outputs.Contains(TensorNames.ContinuousActionOutput) && - model.GetTensorByName(TensorNames.ContinuousActionOutputShape) == null) + if (model.outputs.Contains(TensorNames.ContinuousActionOutput)) { - failedModelChecks.Add( - FailedCheck.Warning("The model uses continuous action but does not contain Continuous Action Output Shape Node.") + if (model.GetTensorByName(TensorNames.ContinuousActionOutputShape) == null) + { + failedModelChecks.Add( + FailedCheck.Warning("The model uses continuous action but does not contain Continuous Action Output Shape Node.") ); - return false; + return false; + } + + else if (!model.HasContinuousOutputs(deterministicInference)) + { + var actionType = deterministicInference ? "deterministic" : "stochastic"; + var actionName = deterministicInference ? "Deterministic" : ""; + failedModelChecks.Add( + FailedCheck.Warning($"The model uses {actionType} inference but does not contain {actionName} Continuous Action Output Tensor. Uncheck `Deterministic inference` flag..") + ); + return false; + } } - if (model.outputs.Contains(TensorNames.DiscreteActionOutput) && - model.GetTensorByName(TensorNames.DiscreteActionOutputShape) == null) + + if (model.outputs.Contains(TensorNames.DiscreteActionOutput)) { - failedModelChecks.Add( - FailedCheck.Warning("The model uses discrete action but does not contain Discrete Action Output Shape Node.") + if (model.GetTensorByName(TensorNames.DiscreteActionOutputShape) == null) + { + failedModelChecks.Add( + FailedCheck.Warning("The model uses discrete action but does not contain Discrete Action Output Shape Node.") ); - return false; + return false; + } + else if (!model.HasDiscreteOutputs(deterministicInference)) + { + var actionType = deterministicInference ? "deterministic" : "stochastic"; + var actionName = deterministicInference ? "Deterministic" : ""; + failedModelChecks.Add( + FailedCheck.Warning($"The model uses {actionType} inference but does not contain {actionName} Discrete Action Output Tensor. Uncheck `Deterministic inference` flag.") + ); + return false; + } + } + + + + } return true; } diff --git a/com.unity.ml-agents/Runtime/Inference/BarracudaModelParamLoader.cs b/com.unity.ml-agents/Runtime/Inference/BarracudaModelParamLoader.cs index 21917b303d..6fe10566fd 100644 --- a/com.unity.ml-agents/Runtime/Inference/BarracudaModelParamLoader.cs +++ b/com.unity.ml-agents/Runtime/Inference/BarracudaModelParamLoader.cs @@ -122,6 +122,8 @@ public static FailedCheck CheckModelVersion(Model model) /// Attached actuator components /// Sum of the sizes of all ObservableAttributes. /// BehaviorType or the Agent to check. + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// A IEnumerable of the checks that failed public static IEnumerable CheckModel( Model model, @@ -129,7 +131,8 @@ public static IEnumerable CheckModel( ISensor[] sensors, ActuatorComponent[] actuatorComponents, int observableAttributeTotalSize = 0, - BehaviorType behaviorType = BehaviorType.Default + BehaviorType behaviorType = BehaviorType.Default, + bool deterministicInference = false ) { List failedModelChecks = new List(); @@ -148,7 +151,7 @@ public static IEnumerable CheckModel( return failedModelChecks; } - var hasExpectedTensors = model.CheckExpectedTensors(failedModelChecks); + var hasExpectedTensors = model.CheckExpectedTensors(failedModelChecks, deterministicInference); if (!hasExpectedTensors) { return failedModelChecks; @@ -181,7 +184,7 @@ public static IEnumerable CheckModel( else if (modelApiVersion == (int)ModelApiVersion.MLAgents2_0) { failedModelChecks.AddRange( - CheckInputTensorPresence(model, brainParameters, memorySize, sensors) + CheckInputTensorPresence(model, brainParameters, memorySize, sensors, deterministicInference) ); failedModelChecks.AddRange( CheckInputTensorShape(model, brainParameters, sensors, observableAttributeTotalSize) @@ -195,7 +198,7 @@ public static IEnumerable CheckModel( ); failedModelChecks.AddRange( - CheckOutputTensorPresence(model, memorySize) + CheckOutputTensorPresence(model, memorySize, deterministicInference) ); return failedModelChecks; } @@ -318,6 +321,8 @@ ISensor[] sensors /// The memory size that the model is expecting. /// /// Array of attached sensor components + /// Inference only: set to true if the action selection from model should be + /// Deterministic. /// /// A IEnumerable of the checks that failed /// @@ -325,7 +330,8 @@ static IEnumerable CheckInputTensorPresence( Model model, BrainParameters brainParameters, int memory, - ISensor[] sensors + ISensor[] sensors, + bool deterministicInference = false ) { var failedModelChecks = new List(); @@ -356,7 +362,7 @@ ISensor[] sensors } // If the model uses discrete control but does not have an input for action masks - if (model.HasDiscreteOutputs()) + if (model.HasDiscreteOutputs(deterministicInference)) { if (!tensorsNames.Contains(TensorNames.ActionMaskPlaceholder)) { @@ -376,17 +382,19 @@ ISensor[] sensors /// The Barracuda engine model for loading static parameters /// /// The memory size that the model is expecting/ + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// /// A IEnumerable of the checks that failed /// - static IEnumerable CheckOutputTensorPresence(Model model, int memory) + static IEnumerable CheckOutputTensorPresence(Model model, int memory, bool deterministicInference = false) { var failedModelChecks = new List(); // If there is no Recurrent Output but the model is Recurrent. if (memory > 0) { - var allOutputs = model.GetOutputNames().ToList(); + var allOutputs = model.GetOutputNames(deterministicInference).ToList(); if (!allOutputs.Any(x => x == TensorNames.RecurrentOutput)) { failedModelChecks.Add( diff --git a/com.unity.ml-agents/Runtime/Inference/ModelRunner.cs b/com.unity.ml-agents/Runtime/Inference/ModelRunner.cs index 422e0f9744..f59b54ee23 100644 --- a/com.unity.ml-agents/Runtime/Inference/ModelRunner.cs +++ b/com.unity.ml-agents/Runtime/Inference/ModelRunner.cs @@ -28,6 +28,7 @@ internal class ModelRunner InferenceDevice m_InferenceDevice; IWorker m_Engine; bool m_Verbose = false; + bool m_DeterministicInference; string[] m_OutputNames; IReadOnlyList m_InferenceInputs; List m_InferenceOutputs; @@ -48,18 +49,22 @@ internal class ModelRunner /// option for most of ML Agents models. /// The seed that will be used to initialize the RandomNormal /// and Multinomial objects used when running inference. + /// Inference only: set to true if the action selection from model should be + /// deterministic. /// Throws an error when the model is null /// public ModelRunner( NNModel model, ActionSpec actionSpec, InferenceDevice inferenceDevice, - int seed = 0) + int seed = 0, + bool deterministicInference = false) { Model barracudaModel; m_Model = model; m_ModelName = model.name; m_InferenceDevice = inferenceDevice; + m_DeterministicInference = deterministicInference; m_TensorAllocator = new TensorCachingAllocator(); if (model != null) { @@ -108,11 +113,12 @@ public ModelRunner( } m_InferenceInputs = barracudaModel.GetInputTensors(); - m_OutputNames = barracudaModel.GetOutputNames(); + m_OutputNames = barracudaModel.GetOutputNames(m_DeterministicInference); + m_TensorGenerator = new TensorGenerator( - seed, m_TensorAllocator, m_Memories, barracudaModel); + seed, m_TensorAllocator, m_Memories, barracudaModel, m_DeterministicInference); m_TensorApplier = new TensorApplier( - actionSpec, seed, m_TensorAllocator, m_Memories, barracudaModel); + actionSpec, seed, m_TensorAllocator, m_Memories, barracudaModel, m_DeterministicInference); m_InputsByName = new Dictionary(); m_InferenceOutputs = new List(); } diff --git a/com.unity.ml-agents/Runtime/Inference/TensorApplier.cs b/com.unity.ml-agents/Runtime/Inference/TensorApplier.cs index d311010aae..a03b3d927e 100644 --- a/com.unity.ml-agents/Runtime/Inference/TensorApplier.cs +++ b/com.unity.ml-agents/Runtime/Inference/TensorApplier.cs @@ -44,12 +44,15 @@ public interface IApplier /// Tensor allocator /// Dictionary of AgentInfo.id to memory used to pass to the inference model. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. public TensorApplier( ActionSpec actionSpec, int seed, ITensorAllocator allocator, Dictionary> memories, - object barracudaModel = null) + object barracudaModel = null, + bool deterministicInference = false) { // If model is null, no inference to run and exception is thrown before reaching here. if (barracudaModel == null) @@ -64,13 +67,13 @@ public TensorApplier( } if (actionSpec.NumContinuousActions > 0) { - var tensorName = model.ContinuousOutputName(); + var tensorName = model.ContinuousOutputName(deterministicInference); m_Dict[tensorName] = new ContinuousActionOutputApplier(actionSpec); } var modelVersion = model.GetVersion(); if (actionSpec.NumDiscreteActions > 0) { - var tensorName = model.DiscreteOutputName(); + var tensorName = model.DiscreteOutputName(deterministicInference); if (modelVersion == (int)BarracudaModelParamLoader.ModelApiVersion.MLAgents1_0) { m_Dict[tensorName] = new LegacyDiscreteActionOutputApplier(actionSpec, seed, allocator); diff --git a/com.unity.ml-agents/Runtime/Inference/TensorGenerator.cs b/com.unity.ml-agents/Runtime/Inference/TensorGenerator.cs index feb521ebd8..39bed85792 100644 --- a/com.unity.ml-agents/Runtime/Inference/TensorGenerator.cs +++ b/com.unity.ml-agents/Runtime/Inference/TensorGenerator.cs @@ -44,11 +44,14 @@ void Generate( /// Tensor allocator. /// Dictionary of AgentInfo.id to memory for use in the inference model. /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. public TensorGenerator( int seed, ITensorAllocator allocator, Dictionary> memories, - object barracudaModel = null) + object barracudaModel = null, + bool deterministicInference = false) { // If model is null, no inference to run and exception is thrown before reaching here. if (barracudaModel == null) @@ -76,13 +79,13 @@ public TensorGenerator( // Generators for Outputs - if (model.HasContinuousOutputs()) + if (model.HasContinuousOutputs(deterministicInference)) { - m_Dict[model.ContinuousOutputName()] = new BiDimensionalOutputGenerator(allocator); + m_Dict[model.ContinuousOutputName(deterministicInference)] = new BiDimensionalOutputGenerator(allocator); } - if (model.HasDiscreteOutputs()) + if (model.HasDiscreteOutputs(deterministicInference)) { - m_Dict[model.DiscreteOutputName()] = new BiDimensionalOutputGenerator(allocator); + m_Dict[model.DiscreteOutputName(deterministicInference)] = new BiDimensionalOutputGenerator(allocator); } m_Dict[TensorNames.RecurrentOutput] = new BiDimensionalOutputGenerator(allocator); m_Dict[TensorNames.ValueEstimateOutput] = new BiDimensionalOutputGenerator(allocator); diff --git a/com.unity.ml-agents/Runtime/Inference/TensorNames.cs b/com.unity.ml-agents/Runtime/Inference/TensorNames.cs index dc20e1f8f3..48ae04b5f6 100644 --- a/com.unity.ml-agents/Runtime/Inference/TensorNames.cs +++ b/com.unity.ml-agents/Runtime/Inference/TensorNames.cs @@ -23,6 +23,8 @@ internal static class TensorNames public const string DiscreteActionOutputShape = "discrete_action_output_shape"; public const string ContinuousActionOutput = "continuous_actions"; public const string DiscreteActionOutput = "discrete_actions"; + public const string DeterministicContinuousActionOutput = "deterministic_continuous_actions"; + public const string DeterministicDiscreteActionOutput = "deterministic_discrete_actions"; // Deprecated TensorNames entries for backward compatibility public const string IsContinuousControlDeprecated = "is_continuous_control"; diff --git a/com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs b/com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs index 5e76084b20..96a15b50d8 100644 --- a/com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs +++ b/com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs @@ -45,6 +45,11 @@ internal class BarracudaPolicy : IPolicy ActionBuffers m_LastActionBuffer; int m_AgentId; + /// + /// Inference only: set to true if the action selection from model should be + /// deterministic. + /// + bool m_DeterministicInference; /// /// Sensor shapes for the associated Agents. All Agents must have the same shapes for their Sensors. @@ -73,19 +78,23 @@ internal class BarracudaPolicy : IPolicy /// The Neural Network to use. /// Which device Barracuda will run on. /// The name of the behavior. + /// Inference only: set to true if the action selection from model should be + /// deterministic. public BarracudaPolicy( ActionSpec actionSpec, IList actuators, NNModel model, InferenceDevice inferenceDevice, - string behaviorName + string behaviorName, + bool deterministicInference = false ) { - var modelRunner = Academy.Instance.GetOrCreateModelRunner(model, actionSpec, inferenceDevice); + var modelRunner = Academy.Instance.GetOrCreateModelRunner(model, actionSpec, inferenceDevice, deterministicInference); m_ModelRunner = modelRunner; m_BehaviorName = behaviorName; m_ActionSpec = actionSpec; m_Actuators = actuators; + m_DeterministicInference = deterministicInference; } /// diff --git a/com.unity.ml-agents/Runtime/Policies/BehaviorParameters.cs b/com.unity.ml-agents/Runtime/Policies/BehaviorParameters.cs index ae05284d50..b0d369b910 100644 --- a/com.unity.ml-agents/Runtime/Policies/BehaviorParameters.cs +++ b/com.unity.ml-agents/Runtime/Policies/BehaviorParameters.cs @@ -177,6 +177,20 @@ public bool UseChildSensors set { m_UseChildSensors = value; } } + [HideInInspector] + [SerializeField] + [Tooltip("Set action selection to deterministic, Only applies to inference from within unity.")] + private bool m_DeterministicInference = false; + + /// + /// Whether to select actions deterministically during inference from the provided neural network. + /// + public bool DeterministicInference + { + get { return m_DeterministicInference; } + set { m_DeterministicInference = value; } + } + /// /// Whether or not to use all the actuator components attached to child GameObjects of the agent. /// Note that changing this after the Agent has been initialized will not have any effect. @@ -228,7 +242,7 @@ internal IPolicy GeneratePolicy(ActionSpec actionSpec, ActuatorManager actuatorM "Either assign a model, or change to a different Behavior Type." ); } - return new BarracudaPolicy(actionSpec, actuatorManager, m_Model, m_InferenceDevice, m_BehaviorName); + return new BarracudaPolicy(actionSpec, actuatorManager, m_Model, m_InferenceDevice, m_BehaviorName, m_DeterministicInference); } case BehaviorType.Default: if (Academy.Instance.IsCommunicatorOn) @@ -237,7 +251,7 @@ internal IPolicy GeneratePolicy(ActionSpec actionSpec, ActuatorManager actuatorM } if (m_Model != null) { - return new BarracudaPolicy(actionSpec, actuatorManager, m_Model, m_InferenceDevice, m_BehaviorName); + return new BarracudaPolicy(actionSpec, actuatorManager, m_Model, m_InferenceDevice, m_BehaviorName, m_DeterministicInference); } else { diff --git a/com.unity.ml-agents/Tests/Editor/Inference/ModelRunnerTest.cs b/com.unity.ml-agents/Tests/Editor/Inference/ModelRunnerTest.cs index 0e81c4f8ad..da802a38d5 100644 --- a/com.unity.ml-agents/Tests/Editor/Inference/ModelRunnerTest.cs +++ b/com.unity.ml-agents/Tests/Editor/Inference/ModelRunnerTest.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using NUnit.Framework; using UnityEngine; @@ -6,9 +7,29 @@ using Unity.MLAgents.Actuators; using Unity.MLAgents.Inference; using Unity.MLAgents.Policies; +using System.Collections.Generic; namespace Unity.MLAgents.Tests { + public class FloatThresholdComparer : IEqualityComparer + { + private readonly float _threshold; + public FloatThresholdComparer(float threshold) + { + _threshold = threshold; + } + + public bool Equals(float x, float y) + { + return Math.Abs(x - y) < _threshold; + } + + public int GetHashCode(float f) + { + throw new NotImplementedException("Unable to generate a hash code for threshold floats, do not use this method"); + } + } + [TestFixture] public class ModelRunnerTest { @@ -19,6 +40,9 @@ public class ModelRunnerTest const string k_hybridONNXPath = "Packages/com.unity.ml-agents/Tests/Editor/TestModels/hybrid0vis53vec_3c_2daction_v1_0.onnx"; const string k_continuousNNPath = "Packages/com.unity.ml-agents/Tests/Editor/TestModels/continuous2vis8vec2action_deprecated_v1_0.nn"; const string k_discreteNNPath = "Packages/com.unity.ml-agents/Tests/Editor/TestModels/discrete1vis0vec_2_3action_recurr_deprecated_v1_0.nn"; + // models with deterministic action tensors + private const string k_deterministic_discreteNNPath = "Packages/com.unity.ml-agents/Tests/Editor/TestModels/deterDiscrete1obs3action_v2_0.onnx"; + private const string k_deterministic_continuousNNPath = "Packages/com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx"; NNModel hybridONNXModelV2; NNModel continuousONNXModel; @@ -26,6 +50,8 @@ public class ModelRunnerTest NNModel hybridONNXModel; NNModel continuousNNModel; NNModel discreteNNModel; + NNModel deterministicDiscreteNNModel; + NNModel deterministicContinuousNNModel; Test3DSensorComponent sensor_21_20_3; Test3DSensorComponent sensor_20_22_3; @@ -55,6 +81,8 @@ public void SetUp() hybridONNXModel = (NNModel)AssetDatabase.LoadAssetAtPath(k_hybridONNXPath, typeof(NNModel)); continuousNNModel = (NNModel)AssetDatabase.LoadAssetAtPath(k_continuousNNPath, typeof(NNModel)); discreteNNModel = (NNModel)AssetDatabase.LoadAssetAtPath(k_discreteNNPath, typeof(NNModel)); + deterministicDiscreteNNModel = (NNModel)AssetDatabase.LoadAssetAtPath(k_deterministic_discreteNNPath, typeof(NNModel)); + deterministicContinuousNNModel = (NNModel)AssetDatabase.LoadAssetAtPath(k_deterministic_continuousNNPath, typeof(NNModel)); var go = new GameObject("SensorA"); sensor_21_20_3 = go.AddComponent(); sensor_21_20_3.Sensor = new Test3DSensor("SensorA", 21, 20, 3); @@ -71,6 +99,8 @@ public void TestModelExist() Assert.IsNotNull(continuousNNModel); Assert.IsNotNull(discreteNNModel); Assert.IsNotNull(hybridONNXModelV2); + Assert.IsNotNull(deterministicDiscreteNNModel); + Assert.IsNotNull(deterministicContinuousNNModel); } [Test] @@ -99,6 +129,15 @@ public void TestCreation() // This one was trained with 2.0 so it should not raise an error: modelRunner = new ModelRunner(hybridONNXModelV2, new ActionSpec(2, new[] { 2, 3 }), inferenceDevice); modelRunner.Dispose(); + + // V2.0 Model that has serialized deterministic action tensors, discrete + modelRunner = new ModelRunner(deterministicDiscreteNNModel, new ActionSpec(0, new[] { 7 }), inferenceDevice); + modelRunner.Dispose(); + // V2.0 Model that has serialized deterministic action tensors, continuous + modelRunner = new ModelRunner(deterministicContinuousNNModel, + GetContinuous2vis8vec2actionActionSpec(), inferenceDevice, + deterministicInference: true); + modelRunner.Dispose(); } [Test] @@ -138,5 +177,60 @@ public void TestRunModel() Assert.AreEqual(actionSpec.NumDiscreteActions, modelRunner.GetAction(1).DiscreteActions.Length); modelRunner.Dispose(); } + + + [Test] + public void TestRunModel_stochastic() + { + var actionSpec = GetContinuous2vis8vec2actionActionSpec(); + // deterministicInference = false by default + var modelRunner = new ModelRunner(deterministicContinuousNNModel, actionSpec, InferenceDevice.Burst); + var sensor_8 = new Sensors.VectorSensor(8, "VectorSensor8"); + var info1 = new AgentInfo(); + var obs = new[] + { + sensor_8, + sensor_21_20_3.CreateSensors()[0], + sensor_20_22_3.CreateSensors()[0] + }.ToList(); + info1.episodeId = 1; + modelRunner.PutObservations(info1, obs); + modelRunner.DecideBatch(); + var stochAction1 = (float[])modelRunner.GetAction(1).ContinuousActions.Array.Clone(); + + modelRunner.PutObservations(info1, obs); + modelRunner.DecideBatch(); + var stochAction2 = (float[])modelRunner.GetAction(1).ContinuousActions.Array.Clone(); + // Stochastic action selection should output randomly different action values with same obs + Assert.IsFalse(Enumerable.SequenceEqual(stochAction1, stochAction2, new FloatThresholdComparer(0.001f))); + modelRunner.Dispose(); + } + [Test] + public void TestRunModel_deterministic() + { + var actionSpec = GetContinuous2vis8vec2actionActionSpec(); + var modelRunner = new ModelRunner(deterministicContinuousNNModel, actionSpec, InferenceDevice.Burst); + var sensor_8 = new Sensors.VectorSensor(8, "VectorSensor8"); + var info1 = new AgentInfo(); + var obs = new[] + { + sensor_8, + sensor_21_20_3.CreateSensors()[0], + sensor_20_22_3.CreateSensors()[0] + }.ToList(); + var deterministicModelRunner = new ModelRunner(deterministicContinuousNNModel, actionSpec, InferenceDevice.Burst, + deterministicInference: true); + info1.episodeId = 1; + deterministicModelRunner.PutObservations(info1, obs); + deterministicModelRunner.DecideBatch(); + var deterministicAction1 = (float[])deterministicModelRunner.GetAction(1).ContinuousActions.Array.Clone(); + + deterministicModelRunner.PutObservations(info1, obs); + deterministicModelRunner.DecideBatch(); + var deterministicAction2 = (float[])deterministicModelRunner.GetAction(1).ContinuousActions.Array.Clone(); + // Deterministic action selection should output same action everytime + Assert.IsTrue(Enumerable.SequenceEqual(deterministicAction1, deterministicAction2, new FloatThresholdComparer(0.001f))); + modelRunner.Dispose(); + } } } diff --git a/com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx b/com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx new file mode 100644 index 0000000000000000000000000000000000000000..56c1cd43559efe72121adcd439d51348661c4dbf GIT binary patch literal 73999 zcmb^Yc{rBO`#+9TqAb~xCE1q{WhrsbIX5j@Xx~#IRI+6&(jt_IBvC0+wvZN;;+}JE zrA;XnEhyUev{O=j@8|RN{v4n0`}_U<@&5dNzxz0@WA2%2=9=?yosT(Z=A85DFRLcE zIwmqS+;^o;Ut60o&fVu_;h=1hT(C|R7WubmCHj*;`@HIY>0ihvY z{vp1he*WP$tHVQm{Uahm!y{})+JuCL2m1sCtdo?7M}>q0gskui_V)=<>tpMr({Fav zGOv+FeI<#!mb|1yzR#$UYJKeNb^47DSmR}D)K`+oJIG5)B&7~Ivg3jRR(shQ$^4UA zD#`Z^_KDVzlFE0khB`5(|=rOh_6qim%WkffBso2$jkUd z2SjK|=S%mIFO-(l93^k_-(dXZl$TlNANjxYO7gOi;XWY|WB((j zu0+bwlIJ+;4456TA~-a_&uf&C+<*Q3=k3{zmRydK8e??&O^pij8g0~9lKcnWnExp} zJDdMAcy>1b1<&cf;5q*P0MALSkNwF14R6eUhbJM2y@VY0w*P_W^dER767AXB%8&5z z{g;Bl5`6{Pc=?8gLd$uM z|Cb1DC9>P=C`c$65$O{W>1Atc^ba%t%~%eS@3+P$D9Ycmzl!t}87avxUs^_9TY}9_ za!J^4FJb>bTD7(N4{kR}vBUoqc2MXFuLucgd?e2qr6cR==jUZ>Z`4IQ%J=h&j9Kmf zAF}=03G*s7`h-}L?;{YL1>{%c7jZ28BO{L_O3mV?88^*p;2~f27dmL{^7v^Are*v`2OE{_TT!m`;X~TQ~B43TCWO-wDyl)9U2~KsncIt zMSASOH4)lx1*#35CY~|HnvAF}Pb}@7!{Bic_P~HaInAyo>oR#8(%ko$nk= z=DfqvK53EE1tuZ;_KXRdtdQ=)j+Xc`#ie) z#!s66>NwS^(G$O1r6=}3yA1R%%FtVPF49EtS-vm(EDpUgN*L&Q47Zox;;s+MVZ=#q zZuQMjC|Z-q(-s@y1MMW9@Y|W*lRgZVb5255-yB%K-HB=p>qE_bHN-NLy{PUhfA$u@^FALWcw{Nk74bPN>vz$w5k9Q6Hpe{UGN=-ODWgES< zbsbM=(V=T<61bI05N$guOUJti>Bsf*VwVJax^RRN?b9vd!`Bt^u4rvuIdd=f)H4-& z{XN2Ojrz?$*wpgtkK35ipeJx)%K)LZ%XswnVyeGoAm6u6jh8P?K)=Y{JSOY~eGqt!3sFZruG1CXFF!|aI^Tt*E{-&M z{xh7azngcC?I2kT8aVt~%$FbkOCR@fpn;oosHbx)dlx7rUZ@{UzZ@;*zQyvwto{}B zioG#4k&Wk#%RkZR-4#?YbrufZ8uHxbLT@(edh939+)CO|0XCDvt z@`XnxMRa-UDHzayHD7dEM8}z_ac@02u4BB3=8XQaFmcl;1w>b7H(<9xKYmgLb8eC1S7VO25iDvYUXBE%7 zaRRR2-h-NgJf3G_A`Bj5jiT?K%sx{=ctUnR&n?`?Lmy3Nzg0E)&7weBH~%VieAq@U z^IG|#4GK^lqK+cQaHLo3+lO>qFEq|M&o5My$2) zPtFMOt%@$^A47N1edj9Ju+DwF)NV30s~AJZjR=6YxRrduJsV;EXea8H!np2gJvhK) zQTeYI-~Pf4q9(M^KPtodqxLt%O5+)Q^IJ_=U^P>CaIqSenyx zX$6@iYi>EH@2Me0$JK>*4fOCs!DJdywVVIqgrDjD#jU?~@Yyog`P4u4bm`^?_&QRZ zq+W~VqFL>9z}qSw{qYt5U_73VcxgvJoZm`ade5P6;6R}k?JJ%Yl}Lw`2zf`B9SvJN zmFI1&lE`QxR9Jn6ciwgq&MJA&Pd`iG@qR;uKN{!Ilv9+t?S9I`*fZ3&Iz@9}wm7!N zQ0T5Rmydluj{XhEgrJo}X-7>LfA%Mkzw$fIr#6_w`id-?`{)S0a?gs!Mh_DY8MH^> zuze7n@TC@tn2NCWK?BC5_UBO@8@QXl1NSTQq%Ond#D*(J@tf1*=;kwraoW|Z^nB|? z;Tx|^o}<1Res!HE7DHu)M^%gQ{yazF;~x!l!?6(VxL^)d+B6qWstAOSS8e95kE^&z zur>~8yZ~z#Kja?HzaUJ*nXhWiq#Fw_(fuKsG-~ZHu`4#UbKW|Ce<8jHT3Z(@j3{t2TA_+=g|^A@tE)FWz)uH8)e)#n+tZp~ejDn!iJ{{0TOr{1B-hwS*XJy*H$ncbqOTRY)!^#yA2${if1 zSyTB;Aw8q|6Ah;%(x$g+R9{_@mTXDq*PHa{u|P9%Z@0Smjb;xos@o$_Om`6LzfPr= zldQ#OhP~p$=jrja+aKZOJ%{MNsYj_U`_6TK-=L?jPN3Fg-K&n&O09~BiGrlXXfpxU`g2pwT6{;>KD+u%K1>^!R$Z;M`2wH5aud_y0ht6C9{ zS~XtWLb9lR_)+SA_yg6HDI_?_4%+rhiS>m(_~vyp&K6nWn~g5Q4>Db}F@Km)Vfq0& zr8u02V+?<`;U+IzIGjG}K1?-l#M24JwQT#%J@kToC!b$H#FaM~GyP%A*L%K0!M03l zKh{d@uDYL@%cu&cIS_U-#g?9tE~&|G84Y$*2hcCKn?bq*`I1{8ynFi*4g5HdCq5s? z&z(~h>aV%WwH#IpcN)zXI~>rZ@;5HhHL0b1V&(#VqGcSBdL}E3y*2~Bp3|n2=GXAR z!yCjiO%Bp+dw;{T{X)9?)jQrW%9d(smlO8~72LGHvG|zYWbuF*X2MR@|7dp zzJPDO)kYnzEyCTkPTWqZf$r9H;|;>g^rhl7dLU;6{l2~iE3d@yM3*{VEIolA-gTa< zDO})pH_V5CHP3i!`EmYZ%Q|kqDTN!}%A#{MuTkBxS9t0ac^tY$Pq;nULoDm7Lwln2 zgpUe(aC9LT6M zyRpj8N&HRlkso+u1`Ud{QKdzXFKD}pe}A{~;+!_R{f#<364r{b{3MTW(S$`$mqA8p zB9_}!LuB>~nl|kOp1kfUY*u`LI(kv8Wc&^osOHPx=^D{Vr}b%UyN~!qj5GiBy@Q$+ zOcQ6OpP}u))P+j!v#3egTc)?Gh7zT*{DjU?>eD`i8)bgsdq=9$#;JtvRDVehpYW%! zV!Uu&_;uVLb9U;ZnrjauJ-1P!lug7=&|l6g3bel5+#lV3ivu(ywC zi~1%uzx@z;d)4FIlO^p*RG54O6!I$+vLpwTEghg}>y`{gA%J}W1HJ7%~Uy;VR`Q0u!veF-8!xB)>vz$8q z)DQ=#jKS9;Q?Z=jEM*JEh_9p%6qoGj<(ZrTv}8S9BGKbPGgIM&tOb0# zp+08HTJb?)Td2PNXee|0j`j8PgiAajU$(!#VlMKp5MYN_j z1zrmXuC%#J8+(IcPf!89f54m`4_D&Tp6$e;3mRDNa8F^!7fou6eRz!5TKZABn`Z7) z7HXH+VT)HDJDC2P-fg-`J2Y}>(;Rh{Johfk?;0yKmb;3P?=twsCn~T(6hTc^0pBzF zJEZ}AxWxi#aUZ=(PDbv9;QQ0WJzPYMHHzt{f}?c6;CR{`??TVc{)APM`S0X_wcPP= z6AAmHg6_xvP~Cp%T+#Lfo)1$MPZ%_eo9RvE7oBVP7TId9-anqDC>-M-6g-7Sjml!- zq8e&lrpBMNw(>i>rcqqk2ZyfjW;%QJ)A$J*;=-a%u+}-pk4x4-_OeUqwn9B&Ow4&Y zqxlF$ua|t*cWs7l1BHpJyx6AZSKO~jo?9tp(c$m)=ohadA)ay+cU-(nBex$S?jiC* z)$o_FLhCyHH2Ea`sU0(g4I8Jc@aR#?!R z#0`bIbly`BacuKY`nT&E%6s({UQiw){;c_juQ>dT-@0icoEsu1{&M{wH`$X#gY#_p z**?msa#KY(ufK&bsWOues$0jtjvIg{{x}Ff^tkdj9xfmpb{#FNWF*c5iMQha$d@`L zPNwHt7@OFUg7@ZZ!ozn;P}yTL-u5`fMr)elg3PVhKWq{%=r+TM7f(rHcO>y<9|Yym zKiHL5sw7x^i;QxY#icKHV8JSRJf58hyL}bVbJI%f6&`1I6P%cFdkImqOLb1Lu3|lE z<1kr}Ne0PPjL4Lg&jye5IQDR;0TS?|oUD5Z+ zLosN<3%2gwNFv{>k82JYp^ua)ev3aWxX|@eRF#my>|J-TvI8>cb2$;F4?D(Izuth; z&lZb%XGS`=G)yMa!gA*GC7Wr!k0H-ZV@dG1VR*XoGmc6rCKkj4&A!RvhykDQrtcD# z_cjfGe6YiPZ?D$uimoOe@1kL(uN!+QcbxsOt#*#Mt%eJ{Hlhm+5GeB|e3y2B?2FJQ zM=o@+Dq#_uvE6`7%=HvlvbcYk^B?m35B*O6%d0%HqY&rx*$&gI52Jt0RBVe> z!}mQUsQWbpRxTSvH9AM~u~YYurcIZ@Z6f06phF;9{(>0%oWqCtAHm0SWw>YlX7YWt zGZ|m(2=1|ixW@VK;J5V&QE!q=^d(}9X!H_kZ88V5@c?1c^GW?C1)eQ91EDV(L{;^> zNL>b@VHa9)u$4NmDk+BOl6Wr6EJk*II*yugAFt;We5OL%#t03N@TqW9vOnRej`(TBS#bl#QUc(~;($Y1beO2hV&XF5WZ zouJN*awS|In~L72vT^_L5Z3;w7j?$S@<{(-w9}#wwzLl6JLYYx>DnQWhM((EIa!qq z4%4D78>&$;ZwMxq7}EgVIeetmIgGCD6^+v>WtOo$xIuOs{QbC?&-vL#+T-i-$!TL8 zYH$<-F7L$HHZ2&OYzaFOK9WUkNkp+%8kv(D`Eip5`o>nkZZ~f{($k0^ zXXXhCE%M3bpkADBH3x^a1hVM5NqmHFJP6K>fvO#+V9ugJ;QP3O_wF4+D%G+;P4)vM zCN5xW|HMLjoCIU~NXWj^O)jdyff&6VZ618ZQ~}nWTv>qwH-5&;=b11L@FOH#}1N0T=0Nz*-rT7l3=c21Qr*O7`1>G8`iPdXf3CyZpSjaSgnDj9d zbFMsM=O3wa+jz#*9#^q%i)G;8x=X~;HIH3e#;_ti4c}kvi>CgYnV(N4v1*vYN0~e! zIl=qb!t)9|WWGADTs{k10}bfB0f#YMQ<3L7M?mT{HBoMCF0$|dx@&V39IX!og%nqA ze&Z-^z26rs77oVeNjeaGH=P{qszi@Vuh=W&nIt1rkCqD-VbTC2zGd_djIi7bqsMvS z)z^wN9hXA#z+-6jUJvg2lrY}`GBpLCf53|&_RholUxJHI)j=~^nuOep2kiqJuy=(y z&A+0{Gsa2LS(fkMx$JJzv~Vylx>3tYevRQ#X2~$UG6fzbS>XPrcKEY@Bbi=x3ABb7 zfLc>5QCxWjZf;J+{80nZTK5QC>=}(w&lqGpAIa~VKZFV9zi?HQCtiN9$)j8{@lkDm z+VAKHI&B~zF8G87?!9QN`WoKk2jVh~y<@*X^^_W&{`DSaIUf~Wy(L3sQl|3(Kev#gU5hc|qBID%jDw^2A?09JdJN39B@R71MVNEa1mE78gcq-6 z!F;+BGR03s&gOe?(t;#``qWyqn_3IAo=Thx@#XmJy(XnIci@iXc=$Rt2rhn?!b9_Z zpjMPS%pM`b`+n$#75cSs^|~sbqZUUpPpe?Qb}Go4Btd3tFgD5#m24ojxuQ}KlU_R! zP3=oWEnBCt_p7F{oC{O=H=9iUY3_HNX*GcQOz42D3HP9EekqRi{6&6a4RP;l1(TB8 zVD;BSklf|Ry=O0k)O=NXyTKAQ9{<3a``LJB$|@F=Y*`a_$BWEodPy1(MS=1q16rGCZlh2dG=L^Zz?WaL1-<;I*$=}cTW=OkMnYzhO9N20aQ1CnIf zOXl@Uf-eWOpk#L($=UN17{nsk`_HAr8k1~Z23#jJy# zFlXu;TsD6!)ETA`vlaJ<%2!3YvT8g@Y91)qUeXs5B@WAGZD$?`dvMssP;4DG0>zQq z*iSDN8h#(eWxZ)2S=7S&iS2@GQ;)&MUCUtI>g|v$r@$*_Hxl9SVyFMlS-H~ej9xt=TWj@mDx zlO9LxmaaxqxiWI#ST3$j9!;MHucsmdYZ`s$KF;#CgVOlhV0WVxtDgt&a48o-i#e$M`TVcb!?@mvz+R^2Impk`L32AF@3?H#spRQl*!gs`* z;-TkuXq`KRx)yr0evA*cba!Lm25Y{0hcaEdjp3o4I)d{f`ce%GJy_$% zV5U_#>3K5_;u0w?TD%Op`sFoQ}GIri!1M1GX3BxWs zLE%v~df&Mb?1Q4w;I;|*{YZ)rUfm2g3l!*z;(Qn;y#N)y^bl*C#pHp_E|!y<2Fd$# zAyz%I=HS{Ff<+Y>D6Ue&5cy-yFO1)l`VH&BW9k}|4sxTHoeN1~p%vL~)C(GAS0Oau zI^?~Yjt}LN;azw<`SncVAj-N2^IInpY{j3> zr$zjI5JUyd!@51CAg!JP)7$&=ODT2`^q~s+<{d-*--+n9*BZ3+<=DCWLu~3BOZ?Sa z$qY}~@;B3NLxO`Y*Pj>4=cakVuNi8*Fx#JHI_0C4a}2tS6(R(GB`&_Ts5Z$Eo^`ik zt<)EosSt{hJ?5CY(GlKzZ^7$fquIJYM=(?{^S;4>(@Mv-R? zyn$`sQ=!w!80QztlEb3uvoOLZ7>+#a7Fh*nGMjxXctdvwvI~89>#i+e ztT&$NP0n?$DxJwcE-|E5wH3H?dMB(ee1{QQ3S2eg0ch^c2Z`4S+Xt+KTVszxz!PnJ zHS-*K8)k?WtLE{reG_q^mJvN1_5vpi%m$fGGa8e;1m;}dR{h5K4O@T|lIN#kQT1tTy0n=4N7!NP zo=4j8<%_9M0`H^5cKo);WZ;o;_lKi}fbMy3aX&4+ZT(mMy9*UacX zPbHr9sRY(HsMDCWVl3eIP<`BIcs_0udw4DnUY<)L+eSs;5sy6#hOc1TJTr-4x(MoR zUGey&2EieZJaQ~eip6JkvWveuA#YtP*bj^ZHf{nO)GOhi(h@=UPXTj$cM!WBkHP#v zM?UXY42X|aV$B~LOkMj?^h%~1x)UF)?+DfIfOBl*lEZV^v8g7uqLy`qi3!PAU{vsGz z@Ren}QpeuT0!Ut#50jjO!Q`w89sjNXZ?EXVz3YsKQhPuAtlS84MMco8(;}D>QjOA^ zD#0YL9L?jtkXcg%&w3@UR>yy%P{6&BCN&kQkbCeWVl-8R)Y?IOc>h317(W7EjP4R$&Q2p|HZ$OJU7&IM8vIhOi`voW zu>68N-D{eO{l}cg6kjbM5noW?rw^hL9jyJwOQ_jd$QHlO!O33JP(xBr`)?z@ePIWI z1@ibH?-iupj0WXL*KoAsdb0kA98=J(CHpt{!uS_gu~7N|Y%Ov?`K1f6a`Gk^qZx$p z{)9BR8nDMov*4<)DoG2w$8JV_uPJh^MTg6p^y+|29Pq6GPg!Nd!f(zv>D_*TgCzPU zPob80ZrqMs=Q-}(G#LC}KPGRt-oxotMYy@FM07V=n)}``!^?P{z2G}RDc1w0UvYH4 z5UGNjr{u$uW+m>EJBlm6uY$VO^^k8pS@5KOER<~D0VD2)fLC@0QilY{d)@~#ofhGc z)Ri?A1EbD_lxvM}D-UY5XWGwsMA_ zKjY!{8Waqum&fwA7r{{f2kgAu50iy=*^X0|s4{R8d6J!g!*=Epxi5Wq{K&=VaA61d zJAXoPKgv-yP-3$V;yELeN@BpLtkI0-m*2cB2B@UF67 zH44Ed^i!e~>)ZMgolI|uw#QAztMkvG;`&r}s?CfmRF=c4hQ8Qcssq|et*B|S9KP-J zfK_R(y#Jz&?C_9aUi+~h?{j4d^PN+Ux}Nd4%OjVZbv%RV(z#Ini13Dwy?C)?70c{T zaLIHJ)_U|T>v(()*ztCF`5*+>K5Bw+IECwt9huRJv7!OCvV8wi2Y$y`T%8kHjYn_E zv-WYeqRBl2sQ&2!yjw6FZ_G<4-Ugxk<|QxkCw?nTce_gtcKM)#c?A2asz7&IUx6^s zzF3=O$1~Tyhbl{Z{L{D##)Wv`j+go1wqP=Sy)cz+w?-&iV@*H3TZ?lYfsYlZqabz= zJ{^ttu} zE%QF%rD!9XApZ%pGsdCxwXZeqhgXPtnGKgVoXz|mMxbG8EY4V9%`RTp!hac;!u+HH zX3%&Awk=5j-3!U+mac>POMIv}LV?~{dVo!haA6nZ^ieQ=2Rhuz6O8zN6r68A0Owcv zsFonb+gkT9?S^=$?Yj~bu6MIh(q{Cw?ME0h@to+2Uo6mblkspJiaKZfVug$3+3>)F zIP0bicGZ5uU(u7uslUOZkayE0hg%0h>46h42ct*RKDQ#7Zs-J*b2)~46?U?If;^1U zlfk}e3FL;iFJwsqN%n`di;nFXhzm~*g4*@Yf}7{7(9qx@T#okU&ey8gcDWnG>HK>j zOLSSuPM*L$ih=jVxeQB{uEak?nWgM|>|6A~X;l;0o8{>r$R$#7tjl5GXN7K75^qTh) z6yMn3yylh`8Z6$1*{059Q}8HwvnEe8s9ITc`p_a`bzud3$$g8jpO&$S)33nVt4>ha z>Bn0qhojz%C-_pg0;J8W;7#LEII^~wsISgN;}u)Ll1F2Ir>Ruaeg=LFX@sz5JNPi^ z7}QR^iqGX!a7}7IKHx`x`p!R}om=-^P~2%s0#@j8rPyJh=dDUsC;Ovl*k+9CIt3TE z+VIR1Td^Z}EgLkIu+0zD=w9g%(o*RPVJ%wJFeM%|Q{!N9OdR$-@`}uRbp~Q8^5I>d zYmz;nrMsv?lz8EVcV|{h2cN!P?)*hd2(?Ayx4LPOZ!}cy;zOuWj$={xWU|Fk2y^j)RT8RT_I@j z1!Paec+H@bjPB?J$G==OzUMBSJF*AkgLN@K>VuP8sgNc{oxw9bhhb5OJU9Bf9(z*X z!ghy4us(h%$|}2o^{+Ub(tLpBD<-f71x{S;*h7K#&?3|e5lC!E2{^5NgX^7h1@Epr zBC3;W9Rx6fjKRn?k+cRz5#qhwe+qaW=_ zoyI~Gn{mN?4a^-ffVO)&^MEV2a8Aqv++ZYdK2oBM73ccH@#;5%hQouY%=d?Qt5pui zm&K9uf6}0==QiFsXF>Or6=3kH1RCTfhKFIg{H1|9-NONxgED2AIfibZ4;f|x`kQ}S&r7;dH8jZET4J%4y5F3QSUB_(#AFDb%Wuh zx>>j<{xevpJ%{;z+1%u0Cd*Qr2aoihKnc3w#+ypK(`qa9)+B>LN*arbh~P@COW?rS z9fGHVb`p2AFCUmG#o22g-0K(523yL2M~4Lx3wJVWg*q?%Q4Z}g`7pTkKGZIMfjiuD zFm%`tv`xK)Y2QEKi#Z4Ifbl2%_@OW z!s`k-$hF;uWBqE#nyw0nEKuc5ndzu8KLr+F>I>caCQK(#8h@q8(8X4gy;4>Qo8)>E zX_yr0av2IS8cEP^rwi}<+~`lrK%12$=-O;*$bbh72?yCDez^r0#$#wl}z@t;xqa!qBU0Cq*MNcpl!=O z_$+dzsWGKYuB93Bzs?1h_4$G+#DX>K9L`O*YyfH#L@gK)JgWE21UKZ@Us(rrbnp#^h_)~n~Nu!tof{B6&7)z5o=$?fI-ANl4em1 z-rKjrtdu5 z2vl6a&YZ|5=O^g%=gGDp9gzp}$5Y{>)y+ zUESr2vJNFgNBan#%YMn`gy`VhUyET(i9CPQzX=u!EP2z)N^JeD1g+;e+Epx|ljmLl zmx;+>dUGdsO&r9h_k0A}T85iKS4o1B`=H4#`-2) za+0B|i$}tV3Ian1-osD&4{`hmJ615`9opYZ+e}x*)&GpA;QWiM; zMJYQ!l(3>xD@aID64rG-gPrnWBLB{NWORldbtS!+uO-bJbelxFyqcX|+KU5=7jfmm zow)n2DI|2Az-HxJ#MMRvm88nZwMTPmYPC%O?(e~u)w@IserBQm?t%3FQhRLPZAi%= z3cpXkCEu2PCij*q@v&J|XezPE;($}IE@Y9@XtQ*<-ToW9{w{*vG86uB-$~3pu1({e zQ@~lvMyiPSXz^l+z#cHN14CYZCDmGrGxsyWHTGlrpw7tW3!UpTa^f(5<2i{p)wh!+z%Yo zn;_v&XmE0Wi|p^TM_nqbRF}j zIPsmzt3+3VT*!oAd)&V{n>2=o!p7Hqxu@N5w#wra*82|RJHIX=$Jcw4l%UCIwpAVW zrCh^dZ;nCRg)s0^eu?*P#p0OONrcUhB42K`{WIs|w#6f1%#264QDX=jy-5J38a2@S zh6>X>VDDpnbU0y)E462U+j=>kQE2|Nuyc3+9=7}BKpRt3Am*81U8M(Xl6^uPv#`236lCy2PsJ~@0EEj%a z6Zfg|K4WEZhIBcelac4kuMOv0=YNCx5x+sNc!g;5fCP-M+gGD#RLzW3j^qA5uJmNl zb3FOC5Cez!;jLo@f?HOKbhFe{O!W&#`)VEZsB;7pd3kox~-$^FxZ?adL4h%yugy zUyNFrQk5}W^gj=6C6r~RNH%Q6FP-aD22$17b~I^`<6D@YZcM5sn&8!0dstS+6T!0Q4X|WHB!5-nj~QE&;ke~z>`pS^ zwaPNs_Vf{)+V@wo59efeSr#h4eIlqYm`56!fNi`Tf_V+E@tE=sd}rN?ks?`|+%t{8 z?0!#-_MXOiKP}0A${b6L_Tuyb*J0(RVx~I#11VYeTM}r-(d*t2Hd6B8M6lix64u;` z^(RO24RbrmONqa|a7ZC;bY6p{rypZ-whF)V*`7lI9%H!iJS+B)>KC##V z)@SU6k=sv`klIABh|D3oD^7v)lvGx<){y#K=}&#`?*{dlm#Dc*i#-b31+^Ce)@V+H z!B3x6Ux+v2uj{mE(nDwL5E;Q1i+VP>K)|g}AV%(Zj6ZG#vi7@u_)8|hg0V7mL%a~R z?GC|bEni%-CIxdObJ#A%1(whL43Dp`gGmog6GImzdOf)vyRM(aMXhNVK5C1o zz;QJEv|T_7zn7s~e_wq4{vn(jFafVbzQpbuA{;Sh6Uizw<1-CE;G`mB9&ln04lq6C zyfwxiN4%d+)_*tz4d_7QRAZn{S%DUilaQ1z1F=o&bY;9cKbF*tb6OwZdh^RT(q{uc znq$R}%k`ktE<=8^s*40n?*`f91~A2sa>cz|FuT4MFSOkt7Rsvyx*OcUy!IF#+-%4l z+cMyg@=Z8d?#&fo7N5Rp0H0}f57WwDW8;U_Xx?bY;q@+vJerI%#WFZJNr5b=%3|{? zPKf6Dzro1++I-~uY=P@rIp<3TR1$z32)a8H(d)z+=Dev1^e1y@SKJM|gCDaI^XH;C zkrAms38GQ1A4qC+3(DL#rbqMYaa;Rvtoovl)e3UBHm(lpHWxXsSN1 z`#cdwrXI!~j~Q_EOgSlSTme#r7vY3e56iWBN5*`)NuHG*!^`^zP$RwXz>iDTf;!b? zZuUYf`zwIWrriuzxZ(KmMG)`v22U)>MuYLT{9Ta;c3zdHty0!JO8y33I{E{CE`ET= zGCpCo)nk%av=2h`cERB0Ke)BGv}X8>UEsOeiQaE9$9>oLv*!61Fkr+qxOzwl9Te@T zV)kw{dv*+MGuE)UsSS8Bf3sk^elJ<5`j8#mF2ZT%8RXF;4H|y*0<722q4KUpI7c)I zvnNn;E3b`|E?L5VCMELXpjzVMs=^y92BY0c1sZ@4*wcsOXw}iHXb{yZdiH!1Dh(RW zDo#ql)P+^h=u-+)e#z7A+Q-?)?8i9x(2yEC^%4BUC=t6A{tg$s>ca=yKEs6$mvE|a zJS^HiP_nPyi7iA1Iy%Smi;{Km;CpYeo}Xk?xR2ejo(1=NUqkZ?V`{(l2<)t-a4ohU z|8%DjO-d!_lIx#h?zQW9Xux4uI^7fQhQ~pUas_O@puo+nt-)t;EIWoq6eY19IWdgn z%}&CgcsF+Ahc+(w=?2DIp5Tl7mJkqk6>c=-k}2PwLbby)eB@9@Hm5{D)b;DI#A_g( zcj~1;?nDhXofd=hiv{fDmyM9%6@b0^d!4tx`v{9FwNPqwFRr<(EwWLVO7v1QF;#Mg z`ay9UabA>-AFDFS+n;urytE<(Be!H^QZ5a%#0s5|~q z@TJR_lorU*k{zSC-1Y}pbf}gje7S}G?#}$k=r5R-u!6iky@*JgtAX2MAB>#z9Y2LB z^P9yA_%Y!GUUJc*8ZgJ- zt!JV1?;X5Sq6k*H3nBl76xH04kKxuDban1EJh0B0lz2acZ+)JUMAagcRn>x+X{$iR zvOnC>m;sYSE3i>m>1-bt$q$Tcz*ieTiSDHv!PAhfY~(F9I^1J3^e-;Mm2)3J+FnOo zrWXi-X+F*q3uZvqs&-iJ_>(nB8Peb1JRzERFx~JtoPNq2&V`Ecn`StfwYZH{m6?<0 ziE^yN_W^|Qv+!rtaJDPU2STrBg5O_h*r7+UV){cgu2@8U-tlyU}Ffo8~hkoqiO;@@w z_o>8ZG6**;cE^{p_0Z991I9>I)0bx^!^92W$;$>MG#Wki zeMlM@j(f)nqBX&9vJ}_8Y67RK(^0WjnkLNA<(~=_M9%~3SW;~Zdat!6H+VWa|CPLN zufH&^{wFs4y$i|~uCVB&9bK_xKhZ6_FL*MlFXK|11-#e}UX4nCy(-RlU}`^JH@S(t zu$oEdefOr`&Xpu7FaRoZWch~@8SX1|#gu_v)jK`isO{P;r;2Y5JlfZcWKGq@*@7cv zm#jPgqh>@>r=>G}lVY}iQZ!CA7qiYio1tyrWL8Lnc+dT0 zB+||(ZAGD!($ErFC8O+>kx(KO8SlAIX_siKl$4^OlxY2o{GPvE*X#0no^#Iq9iM|+ z#5SRx!$0A*3kuxcKa!}B*@GU-BGGl)AekdKf#F|IOnG4gkf0=p%l(cW2IBN@#y!Dn zqiW)*HNfxh8kj87WgVzv2u71z@b!QFsC+R7^nC8%bIlq2VAhK>>Tf{v>J$Y2IsDlm z$IL@Yh1Y(c1zh?83d83M?c8S9ja)O2iJr8;nIVXaO~g3KNC)nzu0ON{ekBq+{?h7W zChTg?6?)>I1FfDAOWVdWqU~dYHPKPvcsFtWi`%p&Lb617m$4)qJ*Qp_R|dh z*P3VFgg=FgSjfdRT+^%yp}`}${V7wKJh<_D-bL#Fdp_j;5Te+$M(Q6rmaX_RpH|v+ zzz(-~m~rm`{oGKFqoe*%h3$6uN#MxraI(wK#zlHfHjzEj~Ai$pzTJ5CA zo&R~B9935%lEr5@HK%5B^u-rqH`S3WHCspZ`q#th)4Dh=Hy$pvZ$#tQDlA0wJrP`e zMn3#CW>+6=z@9TP@Z)YIU2<^@%54N;bnzXZF`c_-HAF6~0h4um;7weV!2hr}y0@5+U49=x?}8&arGCcx^pdk^ zHDWteK!5OFr-MV~#&9=n1I!#@!9=G&hj))fne>*C+~lP>pce0iyRBc)r7q9Wc19;Y zDbJxLZAs|Y>k3(G&!N1%INR^q03vfHf&j;{HrLDenv>`FdOT-qz6TroBiV|Q$(X3q z4)R{zU^UYLKg_m+tT*`}(SN=!Z25EYz)p_cbts}6bj8>;RzbopO~4+5yLfYMJ2iQs z3{IO8@p^3m>FoIg?PUwmZ}L?9CvL><4xc3lZ?D0J^<$aw=7YHHdml_&o(3y04>Z1b z;l1vos3%wk`-{VNO-G z(e}4!kKuGuH!}os#W%7;t*V%?w}KX0s<5B3f5AgtmWdds!0}yCT%P-J_TZ#BwR5-^?Q)p;1Ou)#^CDOUK7wzvE->${$vCFH6hcHFqE&(k_t5JB40iHo zraxn;?eKiunHkLVdrqQBq^nn<6uOQ|6r2?z$7<~Msg5*pQXEy>%ksXVr4SCk= zNmmys4r|5Q3)fMzVjRp&KS|Y2*3smFWlVZu?M=rCH*g6oD>ahYTnqnJQd4o194+qI(}_afK^U8 zuyv9mh8cVj1oU3POQ(N<*pf4FWtAh?ER*8Qj_5&UY9OvItwZhN01O0Ic@ zfYtbiVafAVkRmBSgF;!TG&+sGXARLZZ(3b3?8diK2~+#8N01VF74OBzL7ee4Y&Mf; zW)mg3xD<2nF}2|)?Q>zDci*D13;j^SzmUpZ{0?aoKVcHT@87JQ4Rf?!qkO17m;b^L z$JD)oMLR@Ldhsl}VfYx>yfh*|pcrq*MSz8$1m`WM4wg?8p;`3}Bt+eUZRdvR#hDJw zto1PHJeB4Q<}P9SAI7uY(a))2s}`=%ctBPz2KMhOKY-o&ORgUn&Hc%WVGlo=VUPP7 zNYko7wP~+lS^p3o9umb-F*$53+ib z;i#B9&X9~`GvxlDaO)Bn6IcSajf0?BsLbnJ1_aID;sp8CaOI^MGyV9BRus)ct8Xg^ znK&TqoTh=^^3t%lqa8yxZK3LXHtLpH4qk9L4Q;)KEHnQaq=G-W-x!77Uq-V+Yc+PT z=q;UFEya1nxC`9wq@de~)#&!jiPq>^5V=RnT$R5MmJ&srepCTOYa76&D^<`HAj*B~ zU&OiVk7i4iGGIsVH~RCMHFM~=LF>MLg-MU~VDIb6oYOXbT|BJ}8QNATF1?OM-U`HK zI*xh7$Z`YI%kk>gM;MuFPhXi;k{hYFu;9cHE*mp~5`{-XKRXIyi;mFOTijtC?7`%x zGr2X-rVuVood3cX!GZJUnEYrXTBvy7dM{P(vz-cSa(zJ$=J98?mVBhcFQ{XVBXgI{ zr)7_#*r^}Ua5>bFYg6i{v-rM|gg}yg=-!9pWma%gpU#3aQTforXNpfOmgnwksBp;v zmMHzTgot_Yx7uOVn$K}R4<8ORsKRukh@OXl|>?8!CyiX|E^b{h0Y{D_s zEjX=mCc7jp&(`Ica^p{YBkoT=ki|OZQ11F(Vkz+eQ^wYzEZ=qL-|$fwwmlqOq(-66 z;sLThcMm-nvXZ?Vp@L`b2g0iocBhYow;Jnm-P64*f>WxwtEOfPx7C= zae3Wj*=(3)>A>p`#;Cn9hWfdT1TOLkO|Xi=pOXrxVrMHU+o#0!j!wqGL#60HSCjKN zo{iZnRzh<84$L{a0!FtPvjw)^SRj4@w>!(vny`ZRDgs*}x=unk;=K=^+Fgrvw>Fb4 z#TCNachWI-#3j5}7fYx6Ide~~*0FNmA~>+ujI`yN*4fUFvYN{0vcE+&!WH%nCe1To zZFRmlwR8$9SxLaBnmZu2QyJUdf2Dr|#DxLovZNUGP((eQ&X~J^b@X`&6s~om;$lzM z)1=0ks2Oq>9U7U1&THyt9SIU@UYtMQ9qG#a3&O&8z`nMkhSf9Z3s7ZCub47B%QTd# zdjU#@hv7h)Bx`)yBbacn3Pk+(qE>Pq20rs*uLDNl5^|URJf+SW?~TE%-yEDiUcwiO zr;`ogf6;O4Y?O2R#_OB&an1_<41d=EIwlR!#s4*t=$#eRYVsuLjuqnsS(BKRgD#si zc@7s_*N=ATBiY{<0-Rk|3Hsp|(RbJxe6*ctTdoAtoRx?hvW0>VSKOG|^EH^kIkVu^ zhHUqBf3opw7;N5n6cjTD=$Ia5Xl~ahYF)!P>yQHmEZ9!I9+HRUzn9@sUw06u=b%>e zeLQIqLE9$!pw1}+y1H{N$`@#&=dK4tZ9yeQ2>gkt`$!hw6AX#QlI+A^D^OUxm%Uk8 zLdR|D1gFq-a69g%P|DX&7``9?wbcb&meDfSVReK}Gm6HByK!Xa+T)P7!VCP&N7BwU z!$d#10SA+Ma1Wmk9R9M#+I*e^-Pi7jum4DJpC4|=#0BT+=J}7|v6U#A(*V$`EWz=1 z=1kMRP;l*C8#(kafT_Q~0Z08$(!X&IctvRhxRGr_Zu3hVmrzM3XPXMvXuZN0#iO~= zwMv{&E|gq7n1bsz^`eI%@5KhKft`2a$&v=bx|ME`?v!PM-D*c5$36u%r8NrrFN?B- zH}>pKTsKD9O2fD_34$fFx^ZdkdtOfsMav*Uq{M}odX6v;>qu;um_tYTDzQTO5wNS@ z5q+9s@V}RVIOdoVg>_lP_}0czFL+^UL0FUhH7+~&VuE**Y5!_&isviVv_`QcSX3fe^+v{ZTHdt zpAy^<)#m<-RA5dsaAI8g#!|9fzxM{&suu0yN8HkQ%ud)NV##6IkLg`Za zd!i9tthE;YTK$Bjk)!c>(?_94&v`h%M)O0n>7mz;sXEyEs;j zb|?D;74@okZ`ujm?Ku+v?fHy~aV{iGLJhWQPsRWVE%2S81GlR(!NqhwR#v?OD~J7{ zY@v&li3%)d2@m2DmCtk-}VdqCz=69+Tj~&+qBl-E5 z_A*R(Trh#W9;uC~?dQPuLM~Bg6;E^SmWK1?1PUPa(i!~ z?rW+uhW=Axx!;zX`LLePLN9~^la^xZ)obwT#7R)K2qTl~ zoz_zGkj$w=N`0X@0tW9CE#T*iR#uEB~WV)EZLcq_!=>hXxT~?|K2G3T8se>@1vyyWq>pHv-Y(LDHFW+j`fjqY!0x zn;7LKk%D?He4;)`*1r?yI*UiM>y~_m^p+T&3_StDkG0mhkM@A@!enf*T_e=YD8e25 zxweE~GpWlR`Zd9hE^}-XZVOz29n1R#NkPtVZ~u8rd0YrZGn=WBzbx??JCeH=HJ5FH zM68O`N3Ui{Zn|eQ9QUdbp13`ob(lP(qc5%l2ahIrZ>x)r#y+U`PKExq7!58{Us6N; zV49-xoSdH2fs>UEFz4@LoccreI-N=x;cEXbl==Nu@Nm{dII;Ty7ClJ<<9E}!T_X30 z_XGp>>hvkR8cu}v3QxfFeg+lwk_UKo26C$>;AwMRc)k4)yc-t+PQ6~R`_>vhJ2;v( zBoz@0z8h!|oKHw_w{?Bg4M=vJ0ZYS7-H+hc^i&kN6xmwDv3IJqL7ENs4276hOg-EgQ<8ez?s-9q{ArJ zBvNcJ4mNfk!IAE^tk<%Hj(^TSx1J_+$B$m(&;P8tCac7nU zW^HnYvs3iQ`R*RH-x$Q^*c_oxr%z{}JK7+;uK_Z|+#z+sb?`Nw$@YzJ7B>B-$ksb0 z0uNY)u`6}(!>$=vwmXr2CZCZ$sK%YsE}_{!bN0Z*iFNBtrJlb|q995a8$D9-nHF#* zuT1dabuUyMtAv{l4GC19MbU-21^83?Fi2$E;lA8s*xv0AccwywYY`JAXr!+F5vF{)T4pz0Aw^ zWVk)%HJEfXj7}JAz)I5xs63p28e{7*#Ak~zHo8UF62klYnJ(0R(k-w#dIc31*fYbD zRBS2C6xpw7reA?8iYIOff-)&0!dLB?^u@6oKfj3#2FX2Ke5d zf?{iTf=#Z3^{254+&6`d?BW>$pMR;biHcAgr@0;;nTVjQ(hdyDT?a=44Peh46WS!H z%t|}XSx+&Zht-c(VmP09s;XX1mThW)Od~Nk=Q|Q?<0DxV@;!{^Be-Jk2rOey;dkLw zqFDAAMUGZb)rKNArsy+HiaJgV6m_@-Q_8Ftyr8fn;0?_@HCAX4>c=%1EM^n@e$b0S zi(%!eXttd1{XcAo5>+I zgSewgnB}{UBlFVeBfiHY6C}>Ly6?xo+kK#(&+_02O*kke%8gW>i}#dcP|`92cR#v| zRt|SC;%_Pl*(iLJ^p1QzzlJy!u4lK7&4DrJmB?+7U~jJ+#R*#m(07pn*Sq);>Y_i^ z_Y0t=@;3Zjl#Oh(5{qrz=LWOD^?uNcwK1rFTCUvKdI2Y~a_ z#JG!%dGLz&A_OYQWEG#w@p;yVxoa+iL7JP;W1s?p9rvSSU?T*-T8>}EHlyK^sm#{q z1->o1kHHN(%qDpfw{DUZOLQrRiLvuQobP;y6}aN?&tACbY>O>(MsTYSjO9*e8bYMD z9*4}27A)+6+A2NvKKQs`w97p9?V>Fa^_Amh`z%7up}abIZ%vr}T1@zTy1URLz=HMe z>czg#&8`H!Kzt~{0Rhn|35R~!Vnxe4Zld$3zi zGx2HANvIGEk*=B~cxZ1*Z}^jotn%$^Pvb!S!D5M^{-f zxU6*okFsa9vD+JoxEU#ktOV2d#V}H1I(KGjCaKR{1h3t0p-qoI9Pe06JZ25x7o${Q z(p?zaq0A&ohlF;m*Wk|G52#yu4jq&)^Bv-NP@6G|nO_oTeOxb`i|in3M{y$#*KM#zlTJD8=CchEkK^b;_dmEM{X49P-U4IZro$cy zZHV&?!%ZS0X!LqFv_*UclQ(l<;T9X%*TuglvG1UHfduy;LI&+7D8eK6O2LH_!DQIG z2Xe{^z;xs$l4v~{Lw>}8()w&>H1q{^KUNFxJkT;Xq6g?bm1UO-Bw%rgDi<7b z21`P+@s6|}o?U*HX1>hCpOG{0gJT!uERcoB^DZDcT8T4!au?ESVIF}P-m%J#NMTKBRPbMTdXVOzUjxo)`3wUa$Aty819j<(r z<9>yyp>&ZbSM^~z(YYo?ZVi^<6UfC@V|BV;GYH4$H`46Rll1WJ{rG7^CkZ|niz-#6Ikr)ZYQ14RWtLzG7+7sy9d=nzHt_dD{_hHSFNc7z*%|+h1#d8=$I8C2n(ov_*oh+9| zk+)?iTBFZYbCbyjgC;n<(gQ9X&V-n6ePoYU6J4-sGOI8xqzgud)9%dz_NM3>$rzFa zJ|4%GrG5i-k$h^mxtE&#L*ORrGm#K`{Hk=BKE6K%B@eHp=fr0d{SV4mZDWe@0a0w~ zzyW&oS2&K0x5C=F^4J#RF6_E!#bWu6@B6dwVA}`>PWjGLC{)$uL}okznQ{$WIpr-p z$gf1j9kr-k#$nQ7KKmAMA5Ytzft9jbpfbW8y#E}sp8a$#+jO1c4S@xC6nnEX`FHW) zn{srkJcE|M2^S=AW$T>p;2kefFq4}}-9ok5>je*C%iv;;%a}>s6H?%LrYTNtE5gL+ zYmn`hN|e6t6fT`?!I_92f=K8=*&n;{_W=dinL8bWLL$($S_Smi-X%7N8j#^ToHsav zjgUHy*KXV5{_qo|EX4-rM%SWE=~8a>s}0=ULN^ePwPaU05mx``54Jjo<6^G@nEL2D z4xL(oYgde7#&z#dw^x(6{1_!D*&xQ9AG!}a_bi0BcD=MuM;BUNKZE~nsInokk*uPj z7dz~utP8idW01x%;RGViq?bGrIR3GNDjqU?`-?WY{H2?WcnB!*H&hUEwi1md+K{Rw z7jTYiq96Z8V$re_xbxRDn9=wOBH9vA@@zBMj`GGIBjlO!%6+)eKMh_c9c5isw#;C& z66dQs4G+zhXI|}c;H59l{XDJ3^k>>*NZ=csx8X0Hqr4fNl|R8TvrlmQUk1)mw8fqG zy4@CmFfrM_5bk8HaX&^ehO!9T0?hdPh|AS z4De9d4}W$p5yslMVY{s^S964s>Ia_e=F1znp>7k(-4x@tDlEYCB}Y&ud^?Vl3jjfs z0oR^DVQ>5%Tr;Nt_AYP21^FMTMOp`1j!zauo>xKFbxauUqKGuXlLh%j;$qQjuy9t7 zaAim-Ic%Cm9&^+2vbru>y*tEp#oMtys~Q>2NE&t|(aUJ_e=)))P`7v`DwV93V=6c3$< za`B^(@jy0*$T#?~CLXsNm=IsrCGc}X6}-Hl0r;T?7qu0^%ZYLDwqJx>K4vwvgAeBW zO0v(Z7@TUm3ieN)!(Z1lG|tZktNFXAQT`EuRpvi5SF&UQCx2nJxFH(+H=eV30c34f zEbY*>V9)vIJHTo=eo$BDr0*u<<84iXw}p&0jMfCj3C^HvO<^#o9d}+jjt7>$q0?<< z304I<(7-T#wA%5J1}oZv%E^gBi5&;wqXe`==ykW&Y=PUqtl!sv@NwizBnc9?#bLTuAxkFzr zLGP!tLYcY%x-zzuDC|54X*&lW;AkLzWXDLVq^5q0JGGNh@<(l}|$0;119mdlh1g z8wE)k)3_<`1F$^U0%LpQ&|z6S*;v08eh-x4y>%SBR_@8xPT_TWaTn@+OpIiOig6MP z%IUM=0$97t9AD4jV0*@Oeg!#7w%4zK$wGvN0z)P{Gl*|1Ibr2ZUt)1>E2SSlW81Jc z(-j^@qk;-_ce+e!$0QSFOvlSFpQCD%GrsJbNh%iU!iI4}Xs~Y|n^_UgCHTuT(?{O8 z!Zirr^_LQvi7M9ZX?Z9fkdI>{MX14K8J3xQ8Il{rN%fwibWV~fv2vAQJ}2%Wb^C$A zukMrk3eT+<>5t$Ej(sa+J4<2oj|Awt#A|5Z^U!GjSxC8?jm76TqF(g{ zOnjxr*-UbR+`4q)t38R`YgDWgzxWCl29JlW6Wu^wxn1z{MGVyHH9@znH%OOz3IfAq zaQ?X{%-OaKCiX5y(V2%pth|sg^F*?#R1&<*Z{oerB9N|ehyIfg!42~^!}*{tq0zfC z7`?F+!gZ|Kp^0`}!54kJ8q-LF*WM76hdaZU`Q`kcF3o8z-j0*3)3CR31<9WL39^(s zV5FKUi;-<6^CqppIT@8azictS$}oZWlh)P;;?kh!(^kQ#OUCGQ`#7FAuR>3aatujbNK|e#y!KS?K13ReiG{ZTEdlwMM2-bBr^JNr!Z{yf5L;#GWdLsBDYd( zE?gEf=PD#l(K6*6{Fl2ESEXOU$v`GQPT__QWdV1+NqfC|s?>Z}J zX2F1>1vk*cYo&J|(EbEh79*WSX4P-Rfwu#+(daZeZ*&{q`ML_c_qx@sjF;iw?zo1= zt5Y%Jtv~#-kHni|QYaS@g)O5m&|aG`d^I4)_AI}M&upeJkMOxLccd9Rs8b9{P9~V5 z7lXn60_xD2hO#abS#Qy8Y#N@2HxyG);qYhb;>1d|B05l$DaMJ7wv@cM?cTwu3LcWQFyWPcmPvS|~ zz82z`Du?ddv#lMh4$`ffUHtz25v3-bz*(l7arILTc%HigrlncXanGjk)>n$PXHO2T z%_;_w_Hbza8x5uJ&QrSh5On$;!do+Dc4W0FijCkw{ouh2H2<>J*FX>GlIz^LX zVp80+>SWY=kxR>8Nw6S$Uz|Bs2gDTky!C{$7^ilEG~auRkBgfSkM+5DM5Ajvux8kcv$-}rQa!QZ#S z%UU{k;aV-NT9-=$PQHf2d!wL1_66Pf_!`QWu40!S`=Y_3{kUfKHj??{B+Lnv;Lfc$ z4(cDX@b7bbxEk6F*Hq8*d;MYNq!-T5!TrL1Efv_K+b;~2sE5brB)Broa>3l)j`gJJSRW^aBNCy;eD5B0!X0!MGl`w9k32A5#6DDfCq?*-3 zFn3Qg+{r${4lN(cE(ct~Uk~OG+Z*dy+sR6JleHO_wGV>*o(%l&Z!NEVKg6OLuHg4* z65FgKigPdOLTC>#pZgLZ5S}C6CfE3`^G`7RngL5T2SW7A3m7>siJpA)h&;TLLvJie z#oO(2rPRVM*%SN~ACh-0Hw7Cci6@g5**-Q)d`$6EW0{h>Wz@0e& zo-=+z_9Gm(;*<+sTjsid6bcux3#a1XqPvga&n;{8QgMa#pQ0db#VRV9Hw1ONc?hf8SNfyrK7H&b z0W|L_=GJPHaYo9xXuC5$8;qjVbv)|r&%*QS5jaz17kZW^piX}%JXmLf7q%Ir#MD#J zl3Ro?Gi;z$Dv``zX2gnge#3ze3fzZT39wrt8=lUz#Cv^HNx7RI(+yGq9N7ha@m5@O zf)ZP#HUpgHa$&aKW#IA>ASptF!0BdO`qGQd%*lXLJ(g@Luji@8$kNBzS~UNMKF(Dc z$D}t8&{4Ieyv9>a<)bc&9h$!&Mhzn>79H|JE4(WvyOo->3)n7IJ2U4<2c1*0{HdnECxO2 z^Lyqqc#k3-=7vji@0NIC;@1jPKYj(PWC`QM6>-P)oiu;HHjHlE2iGJ5gO3)o@!5OWR; zQl`QCKhq=NT1hvKH>(ub9`hrcUN6U%9iGIfVp#ZuZN|Qx88FtQ0F}!(Q1RzEB=*n; ztP`2ftP)0YtJX&l4NDCsdt8^~sG7jx0foBbOSDmUW+boC_TdcaadgT@b2Kvlj^y}y zoHP0c)hHK-n{7elX4ZLdDt|^kZa1TUwGKgIawvo)Y4h6P4cHa6f%a7G!^&}^SVv)+ zaQ4OfP&aQ6K3%Lxs(H`)dz3gkR~w0Dt39@(Yp79mXJKb984(Fz@P8 zSUvn7wvR}$Ue*yur))S)n$~Kvhc^U}>Yap{X}TCQb}UQ|n!>}auc2q(V(dDv%DE3G zljgG;nDq?d=q6=$%zZ4E?p-Z3^z9^t`>S!#b_(yKet~QKtu*x6Lo9hKN<#+L{k zIA$MfZ7(Yne9tDF8b*SrL?^i()AB~Ls$!2q5mj00VV5;E}8kv|{rq#ulB zIPW}hs50M6`6A>pMue9g5;J9}PDGIK1}ifD=(E9?!&A8E8xr)KF80Z#aQO?g@i;-2Ptzt*AZHQ=_PC7 z$Aa&8Y*!?lPf0{3ae*m7{>4YN7kT+ z%pkotWh;8s+@Wo*17z)?Qu<@cJ}6%)2Ge?~$s#ubCzdATtM$3)BZ$Go*E)2_DGehd zI*I167Iu_E8B{J^#XmS-(ll?_Yvb4cp+X#$0~AF{hf*r!ZV-3o{cuuq!2y z$8o+PS2ELJX2Eyiez$iZ621#?`&RgIbUL1EI!9ycMzhdPN3dF>&6vG8YtJ`FgXAsn zaHBE43|<90yKTU6S`oEUlmz40ASy5U9A@3Fs8em(BE&iUxOez1ysuJZe|9;sC?6|) zes&5J294nKDr*D=?jun#`XbSZXu~IwU1Zra8SZ`8RQ7d_0$nC~8n2vw0V|qhS!Ay| z?RP7~3S|rSWzxI4xqpILR*4Kz<+*yx24)I1KYgKJ4f)R7H2(jl6G;~Cy@a0|>L7B3 z8ms3SY5kpV$>1AVWIpoQ@Ki{3Vj$up?`0U} z-~#=<0>Og~%)G~gRXKemol|8v;nl^=<$#m0%sLk>WNtvs>vcGyR|I^|IYG%)MY5?% zodv%fCQG_TfuHw7FdOHFhXs?+@MaU_M16&x1Nz+W2u*wxtj<`PAF8#=3I{H(;V$lp zhMf9ha`w@0cyc!YuBrv$b>8!_7=A?OcRqmUiklsTAecn%;=B&W})>b_27?1J`nZU@;4GrH-XWKP%=}3V-ClZhZ zZvIB>+towZJAFNO=R3niw$YH0^;j6Vem5%oyu!2IG~nuNj=eCFgbT|rP;sBv7@f5S z_y6(~=v|h9TW^J6JiQW57ZeDkmOP~&YYfPh`ELdNd+&i*oG+9I>f(tqA3Us?2%?(> zq}AvI%u#s-dltN^s~P)}^1x=URnHeEcJD@saW|>T_2SyfdVlJo^bP&2cm}C(5MwP{ z(bGzX^?wj!KQc?}md;uVKgP%6t#KQ;tHqJ@#qQ0x?z9aagcs<^UB=3U37qx6eC&I< z73QziB>OB5!2Vh5AS`u+KsG9i9)I;vkg{ByT%MFjSCy*3xR0gSnd}IvOMOXdB*SdG zJ+S-oEbfCxKY5kYiT|zgph<6E3kF6@agnBHkj3=U@7oTN9j5omu!$itOIix5l4kJ! z_ZVU7VtE?=QW6HXszH84D(3c{z$MPQT>Z1rkRZxy2Nf>3ctip;PNX>Nuq(u_x*@!_ z$`)3vlI8LX9ATrF6EZCkZkdWQG1ODW)61%1Tu}=41!tht-8(orG#QdpKcRe?8)VGB z53vcy@$-%U;G6Faa%k@<;uQN0=E+52!p#!Q*GYxaFY}OCS3`u35SBIO)4zFxQ2Z&I znk2;$xvB)D8Eeqx$#-1bnTVgF)996@oph#+7rZ|Ei(HtJkH@rw@Zh%#Xgo=Qez%{` zpOxYv_I?RW#T(F_bC!ngumw|D3GU|FXNP;;s(#QRelKjLxa#( zKcaSQh6vBWx>=X8OoV%sn}~}#P0)GWH`MvI98{yKVXuD?{MN972tf(_;v zR?(?J%@}6ZC~#gnnSJ}svkR7|)595KVd=`bxHn&y+d63ryto$$Z?kzXHTJcYs@)lS z#xjj=vdSXAqPhT=3}8z=6`Jzz)nf}!lK=N7Hffh*L#{SX_!x!vw`|6FW7p%rCM`~O zRU+s~G+IaO%_LcV8`!g9OJOtnK zc?!1f6fv+~eU-q{UBb#wTFXzk19sWqV zh$5S#H(g*Q#o))QjU>r2fna?Q^^HCQ(X^DV>Rik-$kyXiNi+N-kl}oUhv9*x4?5>- z!rt0dxGe28T#Hcx?W8EQS5trsvgxRFX(t`#JJjW8=L*G+hrwgRe@JySxsZl^IPF_4 znGjk{cQ>~~;J<%xc8?-Nk5D3p>fZ%@%!6g@Nv5CfcauR^eWtUu9M-%W5Qvm%a=QB4 z(9lSc%T$hHB?=LOpq=BXo`)#NSBAm;Z&%3ajxZ?lZ=&9fT`0_3iFZzS&`~i8Z2mu0 z?%tam+GBqjJT4uD?b|Mq>&Sf|5EViSmeD}=Jw+{^GrjQwzr+~-1a>(|HAc1~u{2nC<=WG4o zYX3vHx4Z!@V`sB5a*{Z=LkbipDX~iLGw|O}QP$e}oLn9yfJs5&cya0zLHt&06f4){ zs`g(Jc0b)m&orDOa=stwnAb|o?9?{)U`zy#`gReoojwi*+X>F-x)0lnXRzE|uc7MY zW$4Unf~^{duyWN+-19>n?;qg%sX8*;eEOYgysxEeOOvr@-A1aT%dxP=(Sl_vgq!z4 zl#ZDijQ6igunNKEy5nYE==F~SubTBNd$Ao1d)acYN^1ol`MmlizdWp6V#EdaIiW}Xqb1FAfzcBUZ?z}X-0`C-_S+GT%uq_x-))|%Zx5qEVPntZ7%p@M1$Y&b# zU51OjqJgPpQ>?2bZlTJNHo;34%EZ1Nr zUPb8d)FX6zegIl3C0MK6XW+5_@al>TC+_+O4OPa%DT{~nWFTJ(@UVl6)Az!qTahq= z&R_vW-)% zv-CZ004S~cad-Af z($Sp(&!X#T=*Fqo=N67fY-dx0?k*5F&%uV9&!BB&DAmLUA*XqaEt)k9ZpJ&vW^onn zOq(3r+s5~FCm6AggZ1c`ID?Ji-+hy%XYk*vdb)n_6rSI-0^iK@gYogp!SpSEA?uDb znv{AR$TersIkXpVn;jJti1cH%W;~gY@vUxbSr?9wxlTI+^uS3f2x<<9DbaW0qF}n`ues`ow!{?zkPn>m?52A%{1oCbZ^>TJ%%6;dMi5{cN z-c_OH_R~V`@)KaEH5(WGYP9xUeg?}HWkE!L3W*Fb=Y%i!aR1#)!-U|)I4N)pdppjE za~;=~{`7AF#kI?vU(_U03Kr_h** zJ5NP_ZBh7}&_M1C&tiCJH2ZrB*c)Y4)?A`Nbj)0EP1P8H?Y)AJ4RbV~-l?p9$px0|5dv$6OgdLj!^N)echxejl4t>YA<0_nfF zYPkA*Dk?N@LQmDTVE#>sEmd&l^CS$vdluldk|IE#lj#3k2gf{~!4+tGk(qVVxb^4G zgX@Kdw56;L_szNrqstpn^qwm-=)6j9J~x2Lqf>}_xF6~6K8ym5*__z(Ix3@HMgLvE#J+{|KJ1TMM^?$8qE0 zrEt}hDtKC7LA^H=pifT;-KhTnWDjs`-x!XIi_H`k4o>AZ`*sOFN)C}RrZsHux^s~K zelnaJxPXde7-BQ!xs`hN&@1x{gbfd1hvpP^^jtYUYRL!HJY${%smj8?@w0QPJa&zm z#+LP_Vc_9mC@+6Vmj36A-97wSTW|#}-x8t0z!%VPIYRX<#aK&UQr*3yVlXRwJ{O+< zMBw3d6H}*#(`jz2a81JvShFPw%jaAX78hQ^`3rl9{0A*k9GZbukFCK@P(IuBGcO)k_g2Oz! zH@LuF3_?}jz<0ZTLCkPJO4mt}T}_G5QXdS5XcKJMc~$7Q{svXfJC4gDYEbs)dmR4J z2A#i4sKYsg(nr^6$$59yA3qoGEHFX+|JteY&`-g;chk^#LnC$vp62zR#SoHZ3cU_- zk?pn}vWp5HTwHXWTC78k7D9*S) zgamw;!4A*f0v`?8RZI$bEoXZ?Enz0Or)-2>$+fS>8`ulh@>?W_J zZ^Q*=r%3*R&lo=E7*t6abJEuvP?cwU9KH0LOv;OZj4u;ddC~s5uXnd|pO%>L`H2=x z$-h9NY!uiSn_|4SFccH5b0FCMEVOUP13e{2A>U)=4u<~3suS**wq!Njc;f;s(-LsR zm0XZo)CXVqzTi&lDJ=Jb7R&!rfM;tK2*^J(xRR8Ok1EDe%her3I_e44>-7*;1igak z|J{WJF7L7F%NAOF{VORyl>$zqbHU@41>BouMyq8uWBaAmJmbt68~ygt*c$$CakwD# znW0Bav*lP7&l1-4&H(B5Ul=>d5AI}`!EfJo;ef<+)_gLRMy;{}t&cKfQ-7=Q)cEbp zb$k}6|2T)i&BmyuE(GiJBd~q@7IcUK?yBT@`lI>)HmA5kb96fyDsqPz64&rY3g7n( z55RXDrVFCBG|&*QG%h!GKyc7giD!F{<7(#K#Jo5$E_44)L3vy`t{1UjtGN2(Oe>LBhL;wM8miAk+^ks46|Pl0CdX;gg?@p zNwNz2y3C)+2$Jb;#{zWun#p&~dg;||e_(~C85S&*Vkb7g;5npYNWMmk@XPLbe5Ymy zEEM^T`m5XFNpBS1`WH{sEu`o^m6LeXvjk-&jKSH}6{I{O*eOq*iQUiVsvwfy+O5ag zWlV&q)tV@^)dr6QIw4dSr zH&Mi5gBpLC?PL1(z+38Kd5ZMS?4Y*<52(FWC$iO)=L5%Z<)``e+d2uKuFM3os0Tk6 zDPev18~laGsew`%#NEyl?j7w7>XAIZk>}MF7^uS3#B!8+UWQADlA*$6A(hxL3TNxR zCQ4@nyz(AKZd8osf^+>b$)lbw%$&g*{zbt3KTTjr?YYqG^W?|tDdgp|` z*E4r5e1G#6!~!BQD*Xq!EEx`Y^|rV$Xa+vh5N8i-3*dZJoZ!~I2w30~N&EcEarkyD zBuoxxdum6(s^3L;dU_Dqa%Km;_efh9Hl)w3(~gJ7pIR_a`3{cWhtTPifbP%3v9M$U zxA<8WcBt%N-a*%JiP=1QZSe=}ysrjRo1)1Q4Il@1s6o4rI4-Lj2a3}Fb95dKHNNj3 zZ_`lPX=x}Gm8R<4*Mo|PNJXebqz_WEDKtbzNy99q6e*ENI`?%Og{H_#DkEtK8Ih3h z^ZWe==bTRGx$oKiF%KR^gXb|X&ZDX)uY{@5*~}^ za|HGbww;{<_b+UMRqwS}kf<#u_LqZt9&nlZ`WyDQ)x*sTS>U8_7R@gfqr*KBjx#XC zEfNng#YIJ6Gs7PxPV;=Tg0Hx<&=MNP>T(m;iNJact}XV66k!=)fTn3`t%D z(NBx$qGKbu!1ZAmwzYty&XmO-ni zncEGE-hU+rpNg{bZ4)_dJx_eche+3N5g{$t+*rKAEwp!hK}uQ{;!vy(>wW8vgFiKS zv9mt+J|-GjVI~ya4}*d87I;fF4qeWkqgxiJG3yX{fuJb|?vDLIYF+wh)MWuTygUK2 zp9Ycy+Ya)I=MStN)Z{)K%!1>eB)DV=9j1KbuJFv#wUFPmAE{U%Tci_5qU*Q8n!j@( zNjh8D{a+?Vj2a-Bf$Pz>HV4k7IGhRm31Q5Wl`k#o6?g@X~8rPSU)ZhF4nRy4}~& zZ_OsGQf;ibY#af01D&Ll_m6eHR_2x+JVjla3`t$5q%hmG2w#d^BQ=g{c)9SjfZHa5 zzs{SW_bNZ8X{(Jo)0eWXbxG7QBaA+MrpR%kmGHYQo<1n0gkSTr_TS%WRFFJ5{_+)Q zIPm!=(N9nmBF2&i8*xRAG%UP&9M5hO;0&HGbmDv<4xP0^+f#95wNQfOo=Ya%=cIzd zMGcTLc?#cVp62=Mim;(J6xy#;lJj3K;ux_j*y*_#>)SGjS+x)TR^Ll(e$0STbuOs7 zG8P?k#h~7K52nsbs?ZhxOSAZy*g(o>Y<;kd_6a@M*d_B&zFCDceIbKpkFP@S$Zwb` z$)WL2BXZV<{|(dYgrnPTBFmR&Mj<`qp=cR&9r*;i(!Y@kdIE=QB=F;br6`b?$@Drj z*tp~7+-#FqSbe}&VnEDeG<_A}2?r1K(^1WFJiFl>5q}fJC5gTSxgFo3rNx#z{xcjet0&>&jj6EZ ze7~^c*<%oYyoY|(<$Fra-gF<&&>1JY1LpLY;NqD9*!J`;Y`SX??HBp%R)UIfcv~}E zJX(VJIr7|*-d)7unm0WZk^!!h7sAQ8lZk%LWxDiHHkeKxhc-Japw?29o3{KW74_;9 z?7Q_5G~XVj*|VBy!a{kFyJW|<{TK@KcFJ^y28I77h z6G{GEX)HRqiSHjbkVX9G@Hpiqy_P!@eA4)CuR=Lkfg*f5u8emd+`+`|5v*}nIV`$1 z5pzAR;K8qs&}8Dn{WDC&`60GsvXK(lf0@rVerbYBDdrF$eE?#w-bOo*TKf3DHJ)wl z#{eG-Ixg@8O#D$u>&GdA+{aR~Z8#2;hb1+u*o(BE!hRl)n=+CngA*Hk(sTpSSaH#D3_RMnEq(}bXpSMylYkf2*>^Ue1-73a)tD3?F!-wFw+ls>)Lsn5#N!}Eya}I+}V7o5^ z-%c?FQ!PKZu(=-xll%%`+0rpQSMM&-OybY{dq?6m zt_`*FRpH`{ZcH(0Cl+FadwOCYy}BkC^i=&YafgObM=&_5^*XRh?X8J{R_ZAoB#-xlHM1U?_~BORx`K8?`|1F))onb3IrVVrj$ z61P3Lj6DSrGR;c?|7(Ovz;uEXRx+C9V2q);iJmu#2{mUcEui|($7x8 zfx5e}XYzLVtENhN!lxijmcp0e6Syxc4`ALK8CX;Fm&XA{T!GmgTiH^$t|ljGPF|HGKDI!NIAD+mT7 z4%^uMihdBUA&F0|S>sJvoYJ3Ep%|G>54-n)a@bjc@7Y$oYnuu$)1;ZIKF@8OGK&ES*Z5F9g2@8p+XTQcfLgME{a4*{8j99D}9*n=-AP{yQ_)vzSCGFo{Yus z;)Ki8EZOhUEczfu1HHO?=(}|dq(@x|!h{Ma=41k%_y3Z>3rR4}RY1;9v*Ns8EW^=L zL-EQjHC&xhjd!mYqF&^4*l-C+y14^J%}K=?17+^l_OB#9)w-g$tcU7CC+u^n+*LyWwrjSSQol$?)6T z3BD|UO3#~D!tM+?9Ou3e$~U!PON%)O*6}mcAu^%u zB9_*PgSqZz!HZkvnDRv&f)Cfj(7n0D_p~||RIg@531_QuFXV6re?E^+D+m2wQiAToMm(?BmHj)ijqkJA za&0PKagNmoR4P}dp5LONsl0_I&r#$qMn1=?al9KyqJ%rD>&t#etj6;Xa*5_UKEGEv zg2iqAhu~$-3bo68{)}2#S`?NQaZZL z;{7Dw%IIgiwQTQyE8us464TJl#nEroSsszXz7tjCxP376#coGS$r<2uwg4XYZpC9< z8^r8TM#Ixvg`e~s*xhBu(7V`-_^jb~f!b26dG~pzf*B96V4n;9C8mQDUY@}H{l(z; zESa5l%R#-`9K4@UNSgmOk$@fNsBnZL3ky%hm-6u>XZStL3#q3c`d{Jsuxc9c*pE&T zvB0H^tx2wlgz(bME%MAF0cLije$|mAoEWlrpR0qcJH_dd1LI! zl#LvlG!a26CJ2jN(?IS=7TgMo#xaNg!GX1dur>54&$O=>*m+(DpP^|)`)fb6Y>S~A z9#?|)X-N`3IbC3KS%y9Fk>!jnld&wdRH&6Oh7;;6hkoy~AYPq98#cQ!F)u|{=2L~e zv&7hdS`9sLW-Auw?}0wQP5Ac9BP=a5fqlJwg4ZFBg*E%V>8NG=IcdfyCRlHQx5s|N z6w4tT-7C$7nLWUBR|@fbq6CZk?FA1O4Zw|{tN3(57SZE-xn9ekP?5pKEQLvMUE8B@ zY{FjVw&OjvRwbj-pR-6a`a%6UKZ)Z#W`iTLa76ztcx#pqbvoj3Bd`dnF37R4m>T+| zm{A#jJHQoIOixjcITu9Zd&6|B;N7G1PYlqtqry=uav>|*G!u>8rjYly@8HY-9@9t3 zDj?WW0BMF9*eEZAG4vwYdv+C$o*6{S-D2Ua1>f7DPB1kk1*-dwLiI0M@LA?hGgHgy z@TGHb*d!09epTgU%m(PM7k8kzaTe>de@D4#*96j^PNAkmGU$C?3rWMR(P?cB9k0Z_Sa8-D8Ulyq}Qf>j^JyPD2ml1H6kP8TM~{N9?OaxmR^3 z@zl*^*tz#J%zJW%J}C$%&O9G)TdO-g8@7pabaO`gQTl9NDWeP4@Gjx7XyPk#7|UB` z(kyQi?i(A0GYeuk`)mcaXgT5T9ubE&iDb0iIarZ9YYn&ixE5QZ{Ry6ms>AH>S8-OH zJvlOEH{SBIMrWRLz52lx_%`VX8g*@Ap?k-1kuS?oeg7`BG&>9bA{((r+mK1$v*uJ^ zuVWtiH5J<=0*T7z?`XSL8#bxNFb5WcJS7VW?A9rq_A*?pTJHoJ2a$jV4^H?RhObw@Ivopl1cQ{U;}@kAIA zEQa4+%o1p52U3lYBycF;{R7KHxs?1=vRip7#6Hr2oh44hVoWAIF49TFhR@PO`T3|@ zqK~&{zQH3R-^g|-B8CTE(a0;Btj;0;d;^-GSEmugPM*RU)}vU^yfebei;i54^lX5O z#@x2Q)xx)Xt=S5VpXf2*09Izf^yyt)rk?Le+MP7H_A_~4{^m3$y{^X##ZjO$uY?@p zJ@?|i^KijFUn)1byW->5{kWy<8`%>-32d)Wl;-DrDK2}+uz|WD%-Vz1jH!f_qZW8X z^E~`}e;50A&Oo^%T^K*~oP2Fph8deY+4Qv&h;ySQ`}{K>cBqxp@hUvupU?QugIu=f z)d@HwS0;FT+<|@Qxd!7;tijBAr{GA~7`9_mJWh!Yq)t-LP)zY7bgm7Bhf{3WD_2KW zaN--EAF<-BQ#A4Cs##23qm6c184Lbg8%a_lfIB}TkL)@p3-2aX(|L!+f`{!*(xP?{ z)Ov4{JLf!@)?hgXq(;zxJP)Ag%Tx3oq0C9ChJR6#s!&d?xDl_7Z_l_7J%GJ^}a?00Fhiu(om(im#K$hR8g! zLsJZ|d@6vsu1mS2*;ayAe+U?DpTx?nc^5W|hL>6Dbmd!BR@5X$qF<}Ww7Gc5_F!olGRic;NxQ#a5K-_knLO! zjU%2A#q9B{HCvqNDSZ(}FNr0Kr`uw<$YiE|)r5IG8o@s7lNZJ;x(z$DUeLjoQ&@YZ z5@de1k}`cDp*dG@mhD&!$XfxK%WLtaSsE4iC(vu<0jOg6k*ZWxqKwyTJe9H!CUlw5 z)VnI&>hWc?*G-Zg(R>6?3#Vel#4O=snS1=5C56!Udfe;mQxN=qH0`yGq9Oh6+{xxX zytCvth@&Aye?5%5*>r}KIA!4fPvm_*k(nF)R8nRDT{IhHc% zJNe{)lj?-rqk5)2q(#^#^mSejkCrFll$cQ1E?O--x4??e5!Jwt`O#oCuo?DGHfA?I zj>n64mx1kqktA-@Bf3(;8PY4nSwu`SbnHHgE^1y_d%%n{mQ`2x=x^k{CZ4RseygZ zt>IOACKyI{|YvJDZvVCJh`uV&5$NP zi96h;$<9=Yaqp#c@T`L(N3xr!-+?{28OnQJr-OQ{Sg+wO95GLeolSj#ORsq`(N@`t&H+D~*6L8vI!=Ts$)1Lrf#b0K zydB%*6i5722GOFV9*@hY!WVy4RvR%Lm6xsKw#pr%^;ed%QMzroE^q=29@B#?@9|tq z?gH%D`-yiS&V}Sx(N2?oNOQ`&$Dqw8Ip!t*nM60G(L(i!RI9+7Wc#Rcjj0u&8nXeX zcQ*?jxkZu2ic&#Qbug=+p+uA(pQITY<1uk$85Vh60LS$SSexF55@{!K$f6#q#Em7%P#*bjfKyhltXy+yqpE%0xnA?s%)Xk2y*_IuQW;+mIG zVz-E1S#}jbbOyUWu7jKlp3auL&x1CdRWRT^lFay|gx>$jqMd9YM71x1yS<;tcuzU* z*th+-wL2UfM8~n#30YLNMuOWTlS+;`D>Cm3v%U3a1z5QDxB^0Nc(}13?Fd zkLH<1?GH)fkObOq>BXjvN_=PY3~9I(j2Tu%xQoaFCK(>Y^(W%_?SncJ=^uqY-DY?`yc&(e*JSThFqSk?1Pj#p62 zXPylCZdgIF5WmhJ2OmZ+L$=5kz8{Ij6}7I|qwxhx6^*%1-mw@qRRXpQ-6q!ES7B=H zZ6dR15bEh`G&wUQTsnv_u&|hJob(0f8}V$Dd~r7N&vdA|H;<)0(&7Y~f5_|d+az3S zKLpJ0z{z8^nZ=v?f>r-q9A)k~ap#F6w(lN9uP5WVYqQI7apr3n?iIk|sk+R2)Je8x zL@K^}r^tS7li}FWdh*Nr4F7&cux+VcpuHmo0{?x%nVZTt9T3)_B1xPXd_z9fSa~t8H-#e`Nr^_u+F2nB`22h}U5O!8=hl+KpphqCW z)Tei2-_SHF()WIA(Z{d$~mh`i-BF6Mfa<_fNh+AzXvH$s#isY9Omt+2T z=9dUdo@G?AceVp)NGJ+Q`W-NIbS^&laT5YM`{1*|Qa0jRHAY&G6^{4xq5I?qp~d7e zzWcO;O<0kR`}|yC>sg+k^E92xwCw}K`92`Isz+MTqmlt4f!cBwEPIzSw10wR`(D+scdb)}*E%`^} z#U@h-6bT2JPtWnWcR%W>OS1zb$MXzkBNjBug4-!CNnx`N3$qeJUz#U(YX1+o5quJD zCx4=*ef31PjdzK;FRPx7x;kE=}z!At!2A#J}Q+aztkT5Yp&gwAtlwU~-0c1S=9 z{~pTrrBJ!QL(t?GD9F`04c|Mu@UpEf7{0dVR%_Yg9dk>kZ)1nZ==qwgT{8zTk`*_Wbrn0)dIsSkYsrekNaB~uenO<9J<$Bjfe zn?(B7M~s>7lOW?(4?~*Z0dbXxa7s=2iT)1<>4l@}#Hj5F*2NDBFK_=v42?r@^sULX zJrE$-R*DmrL_ne3GJNHrMO}({|L1=vp=jn8tm~N!e?{KFuaB!qM@|8`bH<$O)4l}f zmmk9Hq1&`mu#K*G9!;+-p9OV+YG}kWw})Sb(bTgqu>IwA*nF{=UgY!7Ss7o1vl=gw zwUe6R$e3PuTOEzE6Aod`PA^dE)8PKtNkjSX9Bkh{k>}hVBsZTJGb5UXXCz1A`R$8v z_D)rS=R-d%{xAl}xp$;St_dG2J%H_-+dxk1BCNXaOgAsChru!wLjMG&9%u<4<+l<0 zH+n25M;TirT`@KOE9p~{=Q>`fvhvQ!oPld5wd4H^LBW?Wb4`t)>3bnAUY-b1i+pK{ z%v<8U@;Yue45HsXHJH!AS(wJgp_S${)b<|(PJOrNA=M@--CKhj?wy0Xs^@Wff;!i2 zJcZCn2QjbcGZ`~^G`qZR2^1$Kpz+FS?7Ko7`IfK9jr@ELulvZMSLtpV=vPL6jP+-p z52tZAb_vL?Pgg+X-D4KSe?EWQRaq3D@^~IJ9Z!6Efr}j!Sog$7l*n0sOmtbf^$ z>y95LA<2GtA?u=Gvd=RJ|KTR+{wB%2?l57KjV0KoenWQH;x7$IE~S^+|3LXEU3RbW z7TvTf6As&s7w(Qk)RM75lln?Lp5=~p{nzp06;n>4UI%JNxNvQI(n;jc%jC|ZGK^k# z9N&u^KvC6DCabB4e%+q9IBPFV?JI{B-}VQ4<#ZMxw)=6u~~?0s2&>fPaD%w{+GB zcJFUGddBYLcm3DMq^0HfT_2&we;V935oL0G=C-^-n=O!Ngq`nnFyVI;>u}$UD(?-j zWlWxM|A#|tIp4*!5y}e`d(=3Ms0Mfyqy$@g)ENfJunYbtfgIdGCK!~!vzTGtRj!C7 zEf2uq;}Kfapv69%O5+ZQAAm{E_k)c70>IXDpjFjOFTWjx*PD|C-Ye(B*3W%7QmqF+ z@Hv6z^|L`GWErj){ft<8CP1-9IG8Se1G4oR+$odS@WL<##)n6cb?a;S4s$ka^Q%I! zhA6Uc!#0FjBLyS!TS$Pr2#Y)>!d?E94l)CW;gj4}IJdBZ{Iy~NU7;HMUG^Nr6UDf} zJvW?c7^BJW9l6gM0=BC62i(wsh;_>MSI)>kojv?s@(h z&#*&V2W~f4Vzfm(35$w^9uaxYCu$#zk=%^Uqz&FI3WTcmQQTjf8(>}|iKfZ+lxmsa z-?D7#RHV!WThC$KDhDi!8zu(AY*0R63opGqSi+u3=yYcY#ouR=0lwcEwD1YNWh;(_ z7bEb|D|JD^%Pja%D*+1*f5r(1q&SyVi`d3t2QEG-AJ=zY!;uvloc;U}%;@_f&Qdua z919gtE@TtYR#*v1FO`MAg0F*39Kmb{bLJl;&mGNoWH!22pi;B9LVx%>$@E%H#xHy% zFk0G9_k?UEDg(Xz|I!#H@0&@#jTB)gBWxU-2n}lLd=Fv@31vtsB7S)g(rYn&`j|h%tMK#CFiE=ghAX_X|0t|* zbRcaB$54y!i|b(sdPgkbq?Q{n@e5U z#cDz1C}UJwP=ZQZf>;2t8R4P(9CT_ zzpO%P(vVF)xfyXEfAmr#XLa(X#e~>D+fQ74EMUFYUmQGffF{%o5|Pw?)R9?7Ocin< zpxcPGdHSQAN;`IoSKy8KL@+qjM4KF(xW|tw;bvB!Acm`_PbFlCw&64KuqBx+^?Xd5 z&cwjZS(j-}bT+P3B`8yU1ZN4pfOf=4l0YH^bHnGMM12yx8RzmrL6)i0W{e-B2b z>!ZjgYwo&?GBM+s|MMKR;99q`(-JfSi@Q4g2%}Npu#^l`s?0d z$C^;M-_6fAd9Hz2sRC^9c}J$!{30(uhQhziCwQK3G8#N{#|_5P%h z-ys1-QU3To^%cawF=cM2!qLTW4eeZT4q~nzfLHoC_;kWGdg`AQ$&yUN`-?_6y=Z>` zYg~bb%KQXN-^WCJ)?f0i=R5r-o`WqvFVo;XN!ryX~W@f^uG)c2an z>Hb!93Q<<{g7sZyFpYc>a#d*n7xIZ$@FgWo9wQ2ea`ZogT zO5bldAC6&IkO=2?OqLaXG-C7TSPSCfr;%6nYe4gBD8llC5Y;o9S)c`*_|l5FuS})? zCN9Pi+tyI;SrL5Zyac9OeaCG+hoCPakPU~}bN;S@IL3J{Hp+Dp->dn2=WsqI-aLqt zlg-(R@(`S3xCIYw9-?P2^EqGheefjxH)%G_!+`^hnAX1z?Iuh^1C>y?{Ob`}kRs1X zMc>A0vr2J_u>yB=_H0>PHY_` zEwMu3Oz$|nf4>l7d@oVSY5~cawFK4Qr@%h-_ozIxO-S(|_xj#Qfq6v-9hf2oz6p{z zYp*+uv&(~tPq*S>{l(;#=V6>av6+5VRfL|kZ{Vs|JxT`*W13Sui8t7S3v7WJ`fTTl z=NuDUed&W82SOmg?H5d|69ezkn}SkNRp#Zmit~?{N$1SfW*u2$Sp3FxQZdqm$f~-r zx}Q0uy?g@KtWVhaUf{eG$8rzbWw~-GYxHr+#*x#ez|!6#FfB@;j=Cw(=QENKLrI~} zzX*I^<_l$nzYC{rN3YX$s9o7fa5c{`G?im&Z{MQ0t^zB(_5sXJ`m@B~k=zuIbr{-_ zfs>~xvT1w=>*CFU$bB!qaf?Yi>o+c0DM{ zs=)p{2@qsTbGFf0lx0-n3b7aP->6#fN=YMr2}g-T@L06*jv-6;T_PnL{c(M3qHyC) zan^|=h0@0+A{k7^%UAmFiIyf;#rv&`j*VhR7l(7NlT&dd?0^%$o6*@;pWTb&J0cQ# zZ01}`SY5pgH%#h=hE;*AlWd0I)y{0A$3!^jCBwydjI3}rL$dvdEco6z0E%rFVV;o! zSL(YOj_gt9xhZa3gADI~juS`EJTnkI{ESTeGZtKy24hB`0%z`Qz>b15`o6sa#6pSO zz){Hvfi#DR6( zI0h#3Pmo@D{ye<(A1+w8ku;lk2?w8js`wdlnY7H@>0~wdAFkZfjqO*AIomPw@#?6r z2+2ojgtoD8d#xt-1*m7`2pQ;3_;u%(yJDvEMTBHela`v@*8zZr*)mI%*H;P<2- z;_yoY-!0mv!L`+z@?RlG#J7X^v1AY4)g8qa%Bx|?i+h44=e40i$UCT8B1x6cbfE~p zi^fBfnB71s%t^iiTmFW_K@Dr@&zJ{c{XeMYMqM`Kx|9a>f59!08UpDte{tAaoO{0$ zvH9?5_RS|cyFe?Zz6bp=W|$tPhs^|H`W$;8Z_Il zfP!x*#@>4cKg-u*qs~zjNfPDa?_Y&QMm=Pq&NDb#Kg{n+oVj4r$y{`DKG^&h&t2;K z3PXF$*zGpnA@(#JR7LaY=r`u9zC=+V@uw8Rb>73ty;bNeD-R>B|AW~x!lAgf6%sF= zhrcH^xI?cAj_y)|A2vB;%EzbBT)G-Rw5K#joW zbToHQO$8>1Nr7h0A9|~ygM9Y3;^*}GEbYk<>YOt`Xz>L7r4R95ZZH%^?#BsV2C(kj z1bogrf?j;^gZKrZXq!OsPVaFNb+;JS99oQ$&Ppij7flD@yimtc6qbKb=BnqeK#M0w za8L3Cc+`;yN!%Sso;Q{~>UM^%%U!VhfCn*qkc9yc??CEKG1OXc367YT2&E^j5^Rv? zx#kAE13gm@&sV6Dj+8El(5WOa&-i8{ zoo|CMFnh0Xhe#3)6TbkRqkFKUCJsecIN%rGm$2seEv$Gw8`swTq9Q}@iKTHh#(sBT zXN_fHzF(bie250z^>l$*KSl#etj6GhM%s7vI&I3li7V#C6355tT)gvbl+eA6_Gjy0 z!RhII|LPVUu6KamohjhDM4P3iS3oB?O%s6`iC-^MdS;|RBME_PK1RXi2UWb-bs5u8%AVIlKI z)5}Tm+`7MlJxDf}Nw->@Z>pHJhP_yU|(QBJ*f z{6XP`H4OECL)`8=U@rR^bABF#rLz8D@F<18y{X3n?pc%S)d%2q`XJv`+>2hbOjuz4 zCo;2!_X4`);iIqr;jM%`Fpw@q5yd{KA?#~I9yS3ya2 zQA{!z%Ppu%qnibC?Ax6A*p>JXt|q)iXSJ!qdvQHbEIvRCE9OF_ml-avROVcJjL6+X zt+4JxJXYFjVEOtQ3`;cPvbP7bBL>@`HpmCRl>G}LG^xm}BU?jFe{WbkK4NmbC(TLEhicVk7iEv~*~f>x5&g3^dE@=k7u7MN~i zyC$3>zsP$K^0T8?rA0gsAU{QA(_ly4^ zt13pYKbcLiJSCRc|1)G>wo)Y7atoFZJRtr_BIxj@R1gz%ipP3O^$;}@G_lLW>4t!UWoEo`do$cqY2xK5k7-rErIQ zJJE{b=kHSEg>wqiaaKSSX#VkG8PN&C)OS)`e!CT$J^BLf=#9o5{w?(9ds~ncs^Y07 zNqGEs0qFGXLsOm47~*>mr~Ij-JJL7O-Y=E(jQs>wyiAv^n|crPbL;SQO&&Umt)~-R z-V4lo8t`T7E}S3zu;OY;BToHz4Qn*>pcLBfs(^!|}YHIwY05o|1!?5#V^wQy-V>cJW<=QORXf#AudtXBr)u;G=+hvSB zFpen;OVHJSzR*?T6j^zw8ytI2k>TyK?4iONm~QEY+*NgM$~_yF@bwZV%04CKZ?*BM zZ6tA#2>|J{8(IFG3;6Z)320V0h!@{9^Ief`D4V>TcVm{K#Qqkjb9Ug~tR2a6ww%Vz z#g!Q5F^3o(<9F+eKSJ`EsW<$V^IS0}FFd?!7m5`>BU{P@=wzzE)+>FbJ1cI5!q$LNn6dnzu-s=2giN~%f5tmOnIpeH zNy@^T>@7VMCd%@L`13;34eIJSm;Z^C;NpI%z{|i4%-600_3!{{$j?>2JHF<*ohocf zX*k!ka3a2|+)ePwQKw3GNw^+#0Y}xBQFXUkYB8%59fwLF)O808h8ChAax~jhP>b=U zBe*~NH1Jb1l4U1m!a-wOEP82#vd0#au*Gs*{Mi+7W`7r*t+x{+Jpu*ZIi^hLwt$|> zxqwtqhY#mmfbPLFkSS&f*LT{HqV{&MS=S2JqE2v2V>M9sp@k3}e;`{{Nbjv5#oo|& zu-vBy{-`pj5nBjj7so=o^-Yj9yM@0FEMd}p0KZ6lZ;!YFxt9LfF(6#Fib^WV>P>Qet0Ce$@40G?~?_4$K+wbVNVdhy9e)`w*fD?r?Bk3IAqOxgFV|Mz+&oj4BHb8 z%PZ@tVrwnEkyuK$FD<2F|7p{+D*eQD%|W=KxfXwA>tooHOcL~M8qa`~gTLmFQM@n@ zFZG4e)=hj9@`5RmotXm9BD)1v@rn4+`xnMJ5d3M*JDiey>6P)HF5L zzBUX?PhP`tem_+Eax})(XHjuC3(jCpCEr=)yCE+$1;J}vux5q@lem5fO#>$}&2eR@ zf?Md%U`_P5d`ZIJ@LiFHKD>0>3oMWK!Cs{-@I2^<>mP9V=Eq(^R7n^F+nWhjOluY{ zxZ6kfE6WgCkqqkIH7J)+4OSZO;2+Pino;ATATM9ZxZ4=nX7e=7C*W2g#9` z7vyZQ6x+^oovG~?9924-nL3pdRU-uuanpv&2g<3~Egy`^mEcnJj1klQ1+H_B(pyVL zvF46*P$pA~P0#(vx#jL)gWBM~-VmBDOu*PDW0-7A7G0I5T|QtGfy;JJ!@T07R7}@^ z+Ze_7!;CEOgT5r|FODUTTjOxx_YSb}l&6*cN&=Iyh0qf(3fl}-nD*@w*pPG*b@D^m ztjcR3UgS#0w^-t@V zGJn=2c;XSrT%%J_n6XeWw*DP@ugiv%&(dtY%|Z6@_Z=+jKFc$P8U^lsF<|jdg=d7x za9jWOp!JLhr?4DJmeTnTwiP|VNguxoENUYJH(3!4*nlL8(_>DT(@?W{IxSy1kt6Lb z7$w4w9VS8Ncu&AZsP;IsbwAd)D< zh9>30?$A(bGrpfnoo+z!bNqe6fsn|YO2PH{=i$#B5%{5+N)&He(D0qXT#v?fX04;d z%`A8WS#qcGKkL0to+qmXyWQOV?stZ@Wvlbge6XUFybNHW?PS@{9?G7l!PtjS+1gr^|kP zv!y3?MB~*1@oYtq6t0^t19{?a@S0TzieJ4<=R6kW8Atc<=a>Rq;E_#gR@e!uEHlVy z83TIsm=zbFyB~6I-vB8!Gbo(07`|V$<1T$xAQgUMSSsH{{_rydchhI+;;4&13!dZQ z8fEAlv}6+wy3qT14&+_;btJ!Matl_qqK~i(JmhTHc-bD57!!bd|HyE&{CF0sB=48n z`GSU*b)vJ%HFA;Z(HgNk*#GA^NnNK-vX7LbN)Cf*+q;R0p)L*xL-BO48@yv1=~b&u z5St|nISWr>O-B_o>iJ4DhMu5-Cg1BE^@Qx%)`hPhPsQSkJ}li-3MO)g!E|Ujd$Ds7 z?l!3eGJYCtbW4L{pCg5Pb`^q{`%^66=!K0kfAG{?ac-%o5Rw#IQA{a{B#Fx7xXrWK zr%#7q$0~6ee#9L`t1__N=suc6oo>&(Ypy`erYm%Bp#-=;8pnM+`hjkI;)XlICeg@a)3H=AhJD6-jU z{Ji=sNH`m^0=`e_v2iV3_*jaqzbC-Trb24@y%8SuxkGQxC6vBbhm4hD;x+zz8)U+5 z*4m0SZhP?SE)9CY+=`gX{y;mPkucpMj7&Ud!4;)MGA$i|D_tMqj^PnhKE4au#f)&D zS1PW#><2|61A-hE7gDuyA9=sygK*W`TJq8QFOD>oqv-*+Q2qK7yqdL`HLkiN)ZwJL zFS^y#dvhh8e9{eRCMyILdij{P^(dWQQHe(FPAph70G<`hVuk-kkesgPR5_sluf}DA z{g@@BPVNmH(&-fFE~*rkOc$cp8cD8HSpuhx9}RcCoiWklB21Cb6Ik`%gi8k*%-UQD zhi`~;`mu}o{q0>i`tc!l)`+pTuyA;Je=WPTP8wwAAE#R_w}5z_BhWlwFblGVd?jUM zHGSl|e>BYPzlHO6Ey4!1r}SO0Kejmx(YCG*!2`u!ewO#SqWf|Xyt2svZpL;n<0!AKUlC*Z98Xg-Vb2~j{2Hvm zbd&yqtNkc4sbVU;%g@F~4T>bcV>^%)^>ldNet}bN3l2Xmhs1T>pPa*>Z^l1kKrb0-p!?^Lwo3q-wouAYYpUPhO_*o{X&m3*&wGmhW@nN zNm82clajNeprvDoDsunGkNFpI!S!;|dfkS7-Z>L&cXWfw!vOrU^a&Jg@eua%J@QGH z%E_^*Q_v(h2k+I4;iS5Asok}27`0a##*Dg(&zGBXBXd8JaFHeWN%d`oh0jkCqB)J& zKRJLUZ9L0(C<&Y&NTH~iC4LV2il6kBgDvk2=}}j~*Y0LSe@zHHD_MaTefQ)0lcLYKI@~_!tcus z;RoMkO5NlM=4m?It>GIm7k0Ax#SiGPVjA!NmEg*HjId($BkWqX3+>)Yas6`|QSbLg zAg{9#LdN0Bc)kC3oXNXvN4aS(>~B?WMU&2MJ}<0_+p9(~uX!gyZCMBSUVB0}>`&zM zuNDhDlyz8aVmw=zJcJhnCrRth5JGfZwJ+m(1nW5WVmQo9)z_FN>rkxz-p zIdQbp*5X{3H(-gk3AH+Y2QEs^C-tO?j9EAnttJ}45?3WOoYg7x2>n83L+5jW&j+b< zj2|B4@BHQeU59!neLw|*otskVi_U(s&T&5uG?;R#zkBKXIt$djUJYNRW^>z5uR+ae zJK$T)|0p^Sf2_YYj@w&iMn=*OWtDNC>nnsxQre3&^lPU@n~3Z!BZ@SXN?CEA>y(wO z(judzqS8i1%kzEy1Gg9FKIghVpZ8mlyVVd1$B&ys*NBg>!h8Z(TGRY14o0&cI8XKIgs!?bZPhU&iN(;PxA_J;N6hK3UtKjkLyXfKVjJxLrvP%9eKH9!CDM_eZ-Cw#+VYZ=_Co(NlVucFq2+i*3pSCF#q8wOcQquwte z$e$K)XD1bqwAcWUO__i-&SSx8gC{QGGe%4EXOdm-=9d5%*jZ0<=zn zCqFx&>!A+(Jn)cAlFNhzQ9l9Ar0s987RpmCK$d`j!mv}q$=TdU_iA&Lg}&~ zY1;?*`Rgv8SJGkK+dq@@J|+BT8NvNnkw!yqZ=_T5S8@q@SD`Vy0gum1#k=+;7?RYB zN0zGcX!3u{+G;5E?-f6F((Abbhl^?BAnEIDsH+--`6u&L|kCEnWonk!$$o#ptYO#Z`g>lioX+KLJ8kT9!Nl!+zQM+T@2yv zUvL$h$hH$n_!j2KM2!Gt?pMN*^~C}u-BiJvhqK{Cbq(EcJDGT@41i1VbTZg)i7t{C zv6O%BEZ2O6~G6NyZ3oN@dC zZEKhh&ElTmKD?0qw=fne_HQAxzD?ll|2xVAALAkTyA82^{TZhoy9Gg8<4DVyJNSv8 zi)4APq_?Cy1#&}XtX5Qa@lyKBDxHcg zDuv{VGepdL2D$ej3WslmqtYxPiIBQ193}gjYIm(CRV#}~=$i>tEjk)~bT31?s|uTM zEXs;MY=M6h3{bu!AJPuCpjOT_ytzCP)Pv(O^TH>rn|_4^Uyp^_X8`furreOtOH!vC z0$1e^z@9iQ?(lX4&P?tYiZB0zTcj;u{+wtUbBoWs&7O-=a`yPGLX!jz??D%fG8)%( z57W+xUpDH5~lL8^XVPryx|-f~}9$2YJ6c zl+*7ea}~mIQuS@}bd5cDU6tf6_8XGZ`%Uq1eg>T+o=CTyt))$=S}?9zgP{?M%Z!0fs!^qH0?peI#3j z8bTRP<#aFXmr2EgYFA={jT;OAoznJG-K*#*;vok-J+FZ9O5G|W)A4F7o7jPDz3I<-!oxp~h=afM)w({fSoo`fSFujbOg!H|(nXO;Q3`6S%9 zSe@0zKc$+tWtretEj~K67{32H!48YM!omFx?C~L2F53DDIPEOJ*fpubdb5wvaCAG) z+ab%Dh`pif#+&nR)CAmQuFC!eUW9Z$TORWz3MW)e#s_iH@YZAuPT0NzmWXb~4*x7X zaP$m@iR$pIi7@o~6od&{zv=!$J*NI>Htu=#mIP-0!B~}25~f~?W1swiX9sOyWAT8n zWThpyu>6y7TG>um@#_z4HhDx!H~zwPeg6@u?N9K=>QZo9Hw{$7=3`J<4D=;0Wan1d z;MCPh?9J7O#LejefBvlCnGwfmj444=#R%1w>cOQ^#7-ga#1UqYO!YQTQ>Qk>ZBz|?d3 z+|FwL_tBb6j}agA$k{;>BYSb3vjNxg{wcWqt%uBtZVu2Rr-OAYoPT7yr+=71Rd1)Xvgc9T6KIX;fu_-lDo zdW#b3L<7njNHZr{H5A=o%)Ou*+;QV8m_2s6?JI}#c<0S4Ow#1ITO_w6^qHngGPDqA)a@UT<8V! zE{any#qAZJ#Cq-$bj#k1vjjwZe0g^* z7IdDY-RrIswVMHO>pv5y{H+KNs2^!=Q^lK}!C=yCCS2@Rjp^Gmp~dVD{q;--A1!Xe zdW&j7TJjgv{#OofJWj&gZfU$TITvs2T!eR`iv@ZQKhYawlJV~vo*k^^k3?f1PQEsU zoeK$pQ#+pt|CnpjkuJO=>5>*2e($CKIS&bs@?3|=19ea}?uo!@q+=J8j_IZsZIpc^f$(J8_RFWyV> z$(xMHti;c9%J}03pU>m56X#t(r;vujNob(O$4*ei?S&JqIpRUt!;y0`i)_)4n=r zf^xn+@JIbSPByfMUH+!b@5m|UrM(TQ_+vDh&pUoz?!aSGCQMslGTWy(3&noqQjJ4u z@cm&CZAq4a#-9t(V%#)#VWA;&(OwOwrzqef{UU5^_JHAH71k81!u6LXL*+PG^a~Ks z@S-YcteJv?+pf`-rmrF5K@qH9a22|j$#HIOGTdO}Vimjk!n z56Ah=M1j0BRzJT)cS}{Hi{m{~ec=}knq2^IZWFjPax<}6y$Ju!NXIHI1LAY!0YA%A z9*D4FjMU{zmrhnxDatp48-THQpTN;MCs5~( z0)%CT2+TCI>D@AZ1_X|fZ^1i8tvA57x)34c`o%9gnH!q)T+p3_EVxlOk}5 zv}b*n!*Ob=A$fO81WtF1r~8AxQ+A<35a$p|j%K~Y{inmhAlHt)o!&+=CtIRzz7ej< z$N^PO6W$gv9Pu)VWY%9p`SG{OW2r^#UbP#L4?6JX#4@yXXd)AIT)A$@W>-NJJjA z6VsPxK=i|J_%QPUy>=*FSO)?B_qw9*&rp=f(7?n%-rxP>D?GHULOq@%ViHu2am5y3 zS`vZRr;R|D{Q@?rEC@&cz6yU9SKt%T1aibITqs%;3%BIQ5S&m_!x|)IMK^8S}v;iyL=aA@Uu-XrfP-0tqk)&J$0Z0_$to}agVD5?j$?GH$ul?)kP z`~=s}ZGqsmwXoJ!nuWbp;Eq(B1*3vay5IdN+I^|Tf&E7@&&`P)O*jA%ToVnGe@SDE zb@12M3~=9h5B%)Hkt<&bN3?ZVo2f6Zc;SIP*}2Mz!3bL-8?8eN+Gldk*09L`mopNU`^qXEEU)Ar@$d z;NrT6B)_-{+`N+^=Akck=?Y*LpW`(T$`eNHaKlY&#L1OBao`r8rY<9D!0yyOOmT^$ z%XU14#(kgpe2^ZuW`#9ploJ6Z-_>f*Hj@XGJwT`Ec6vHkPTAiB!A1Z10MHq zK-maiZHywFQXQ}(vV)#B@h&Uj7Y%XdRrG7(HyZV#02)_)hrbIamI;haz%bdJwH%lZ z7c{z2u=yH}s5WDpdN0wAZBFnaVFQfzT?X$)EQUL`F5zawznGS>lr>y0h7Agf*}_%H zxK?E*7p(OFmQ#LT$a4cmd^(7h*CufSD|0@>@4&5UPoUOHIq>^G5%#f69n~Kk$GO9z z>~>%RhKXem<(^71a@QWb-**~%#@NIB{=%{k-^DrQyUOr7#~dQrGWap!CRlk{p|rLL zWL{W|mK*d)vRo%z{P>&PZ?a?_&HqU2JKh2IpAHMicjYF2^rD+>ZlT?dU}YpfJf3oBq>h_B+)u_m(&lu^GwbwvQ{_x1XP}c%6rDlcVXa-tjnR#Xf5HFa>p+ zkHN!kXL4BcFzxvGnEH1`!kR)?l+4e-6@$vGFPG;dIm&Z=?|A0X;cK>YRI1>&(_$!@ zA_PzEHWcA|Vn@II6m*F#;6}TRV3l(NAucK%KD-HnJ?muH+VZVf@T?jp$DF6XBX}Q& z|6a(68pndtlQ2=p_Yx1uF|FO_p`n83{3-Xr-bL5To;_+I15Y!_p@FAD--;V#f-*vI z<|{hks4{%0eukQ_KY-P99b9>=3{#uBNb|$zG*tKt(^enEW46BR>=_$+!rhBMA2nfI zQWS1}Cm|d!76?VzH;A&}H}9(TfTNi+xi#H~LDyTG{qp$u zvuV_paGK_sBsg;E2667#%O+&VFn_Tk9Js5?rVHJh_Cr9YzRBqy#U zPJziqR*;TS+u7Db>DXlM3O`If(O(Hd*vdmUtWF;w>&)DR@7D9P_is~}I=w6)fjp03 zr5>g%{DM25Ok-8&Mu0bqMLD}@aN7_~@61zTiYwBguZo`?-{tQWTLR!gfDRlq96{7K zPY{aQE3zv;TFCJaH|V&Of7HDtM$oY|4_^(3!)`$wyld^pr)RxcMC>HGx!^7787Tlc zl1E$k|Aq0g*`#n*tzgyRRGg@Ho&N63f|rh3TxrY-w7ZdnS$lioa-c5f@hFNdnl>M& z+5LuDw#wW&gPo|mZx!A?|AqHxRO5{yMrDo%(V4H-F?k&i+8vtr-X)S5Xk0 zyRjP1H{ZpJ{x_j`=3il^HprgjeqzK=Tr_RHK@USBllT;C4mF%@*Wc^qWP zc3@)SN3vP*9=u&Ym+!EsV~o2sS2SILGuyYGUC!T%qqhc<@Ae8TDDbFYEv(@Tq^7_N z-xhTBG{&UK*RjD{k{Qhg(2qC@v))8;i&S}+ZtFEDx-GyJ$I3zSXg>CzSPbPOtEi-u z4A<~$2Ph>(!C94eFzmhx^qO|z*xZrKG`fvCZII{GjZzVoo-iG%l*=ne4kRV!=ppZolCfn)$tqXJ_w# z$nRIERMTjTdbtr6A5(!(9mmnQv5pisxpHjIbG%o5isb7Tkxf6(!+X{3G{`OzzxS5m zj)r~U_G$=&<-G;ApLKCuW+{{wjbUf!EW^^>r{GeV0jJbbgn9vIG03}vrYntwS+7%x z%AsN?@*2&%3j*eZ3QykhOCJ8g3fPCalSm@Rwp04TDY4o zo3$4c{$zs7{O6Qac$2>!*I>pfBQ%T2fEwQ#(&d>(cYUbEh0(zX?UT8%SqpLM+z?ba za9yzBW3Axp@~iYtt~yigo=cwI?go=>i6rd7Xu%rXh9Rr@x8q&DXS9vKmm7V9TTjlh zWyKuIudv|Oc-#f4=5!2JbLLF^cA@4mMb;n8`!PNG!6|+Kwv2Ou5|er8#&@NwE2D+7 zvW+C?xGZ{}5n*u(d3gA-0`IT*Lar~b5hQI4C;m$$AvJ71kXNVC(ar#KdH2z9fgIcn z8^_*lcn1$(&cu6S@$e=71J2I;4uWP4{C2B>JX^LCU4~uZ+N=NY&?5=n;nfQ^d_G{~ zAq}?1{0sGo<#$mtJlWNSGjL(MBefY!6BJ(M=Aid^DTEzXhrA+N^p?q9e6*ms%N#PHB<=-Cbv)%!j@dpIqZoo+dq=H{$phYPW5=_#5(+$WX+;)&tS%_b`WJL%VlinrRKAwSe3OK zUe-59zsf0S;wQ-#Tx638bq(K<_LlT6RIk@~wE~+-XFH2F~gNZrY(93%|j*)7> z(x119eDiZ~9gM(xjeY1h=M?t4?Z@ZlY2?Z42&Trbx|?o>z}2iKSSA{`4c&5OE)&#Q5nWI zOyumJEPy@T^1_ufRE68shtTqbFUp+A!xiP`xZvP%XfqFnTaA&ZG)0At9rX+3QlHTG z@800AlvD7NvtrM8s?rqS7+B&Nhz$~ZnAF8uVanL&LLDV_;-@+Yrfw;)dbcZ=_i_ts z`}3=;@nItFt_j86N$=tMv#-QQUyGS59i=;4KV$b?JEpq$5;%XqCpbOtCDsLrlYcuu zpwM?ZJ9V`bPd!?~j)Y`ktBN&$7k7c0;XsgF_YlH`c`(~@o$xI4 zp^eHS+zy?SOyYJl?v}ZRarTp$*47Hl=fiB)FnR|6LUR8fUpDy($(%e?TV_jW##3Y{>?Owngu2~0R z{EWfK{Sw~ieR*vqFR140x#;cGkF#`o!DD3xsXARq%$A+PwW)L9poXB;~n>cQPj&_kVT&(W_@p7Xw4iXNf!p|xxWULY$4BOa@AU+$;FAxRl7 zNc|K&ldzu78raF59(Y4l`@Oj)EietLygF>RNPER&w5wWFv z(EFn;x3ggo`bZA;$v>l(X8=Z}dqaq6vM|aj4I}-7g}pCY;BjaOxezDH^fhk*dp`&6 z@$Bl)NAfUkek)n0sRQd5nF2b@!-f(cyL-U3)5 zYYk^3i(y3UeA2HKh1XN!Fe3g9NT&ot-rEcCg!?A^IxiJG3Rb~62}$-5KH}P|DL8AY z93DJ+g;e-j!l(Q`?0fJR%H=D-;=U^p=kDUu$Egr^E(X`?@vu&39I}%>px%hhVpOEnR2*1~2jsT&LhC&y7L>((srv&g`gJliL0 zR~|_!)xcf-o!E5396qfYjZYFo$ui)(HrWl3Vj#=5^bNt3$N+p~SV7OK_t^F|Z@}ca zZctftgU|L&=jMH@#g_o+}Mn-bWeH75a!jkbmpt1#9 ze9>pyK>(BgP~80mH2n(zhsQq!Ti!*$HkU8>?%f%v@L2-V^%VWgvT1u2#ohW>uy5uQ zd_HH0T#Z`>)_yu{=fqA_RkxzybQ+$>d4jd;R`U6MKA)cML3F*Iz;@Sjm?A!is=MUK z-*9p4c2R}kvqF&m>xd5V>%nJ&1-R_zS+h~!$mJR-*5TWQv9g9JFlv^(`5kQYBS2nN9d=F|#OVXIxXDwFnP*C)Q&u60XkNsPSG3R}YXN@j z+z%hFUdB;|@4?yf3*Ix}xnYmCqv#tO_C9U_Gkz^f?jN*dzg}8kP|H!y*kn4}(#ZGK zWyHA92rqP)5yoaMKaOf{zU1PaOH5<^8m`ShgBt5*;{JuRNKL09sCc%4>Psd1@>L}~ z<751Z# zMiNS{Pyie59NzumC$zh=2S0om%{fdz17YqWZ1Ms*XkIpvrIqc2fXT=PA6!S<0!!*q zo+wzy^oUOZ|D7Iq0nLI_g%#tvp?OpVS)R8MZk(C`9`9tCT}?YIyFQb1SvQIm+d43R zN8Z^xeI$#hi9prQB7(!8&I)t_qVcnR30<(nime=X8pKsZ8m{0(1+t5HWrr*QrO>X4Z*F6#HM^P3kmxKb!SGiF0pW)vz}9Sj%TVA{hrI2 z{gGg^wum!xLvvQU^#(bnX$W5wEn!c4J>TJ#VYF69_{D!VPLIibKG4BvGJae0F z%pHlj)3f39#BBHgccJgll+uG)SVY3w7XPGocyn#*N-Ha__GUk zKM-RJzcu3Nn}u|Xu??HC_&nZ=wPX%nFQBbu8hmrCpGTDyF=Izg>SD(1a9nO%NUqojX#9a^7(7OueXvKI7M+ETNG+fufpx`rs%9rsSS!l_n-~nLG0$CWkxeUM7oMf|C{72^hNy7im7=nIT8{OsaKu^~( zI4b)YBKI6bG%AK1sU2`mvH3Kt=g?vwd?iH`rN4{t4q?>hySg@$)$MMr;nq z1b(&EKHrIt1Fhhrcsd@ixP>OXPcl(Kk;P@mac{nSgNqLm@oRDsj2jyd58o6Dz%mWH z?p~$udh<#Dq3K-0(~)Qpdlf7PrHGB>O2}0fVfE=w=u^0)SQixibjRl>qImAdbWS$r49^Ch z%EJ02p*6J^wnloDBH63-`+&KF_BRF;GHPw2LRBFvAmU!n8)+Q;i z)1^&Nv_*x}ueys)H*?{XlpWL7b;tg1#n7-)gtHN=B(c#dwvHnY;-0go=xSz-k9If0 z#usc?tIKf(J?@o?mRD@3QR#i-Ut5aE(gFUWtDVSSoH*h#~2&D?N$C$1BNJ7ekP3wpT7Fb@;d#JQ4EGv=qdkg8pK3rl^@ z;B1)zsI6_{-NM^3y2}=8cebJUqf-3RbQUZ>mY||t7Dz9?ZJV;W30tT8P_ZgiRx>>U z;!ntNPAv_nq%@YbY}XdXL|r8AMdzTlsT5pJ@^`U;d2r~47!ztiVdhw{5)=7<59EB645(?@U!1`8g^2#QTWzSJTx5}xgwc`%ynN})D zeBFj;`rcsf3~Sad+7Hqeo*2FM8ydz8P|LDYIChr`u1gl;RuL%_;eBl;`}gA!S#22c zK@(TT^DbIrJ#OcI5gd4eK$Eq&GLKGF344$E8b$QtMp>4d_#WquX~Q+mGoiucCyXk2 z26}gS*6;34T0gl68mbfM@te-zW7z`|f!V0wVaBnfa$Ps3#65qRLeA-gRb3L(-H!Fp>WUN8+t z!A%vmTiK1dZc^o%npC(=qBGduOA^=>vKB_|mx5=!C*lTEq4J8;+0=-&@SkWc-6HXV z#A*k?r?^6l_mO87_>R__j)Psx7SKz#J_+{M=;K|d&v;dEf~qg*KgNqqlQfNR@@AihdjSmbNU z-F@{3TWLLP_uGgQZ^#l^w;S+5T?*f9&Za8QtKp9Bd93iBg~8&=FnY2o_sYT#hcd0; z!`Kq~>W?CK{r4=PO#VVni7m!cL9*Og-;qKYpA(pnGzZ7o-y}`28CSVl;BWuyILD@( z_|Pjj-To|i`_yB}b;7xC^MwcV#$ZRwZ^879@+@Mn7#^EY1nrWsuzaipwr+{1yXqgK z;F}vYQ%)6XbYI1u!Yja!6v4#)2`0~$frivoaQwkGH2bk%_&|a%?uiV2ug}2P;V^-O zQaHVTIbOUpfg2Xn$N$6+;BWJtcyvoL-fTDnE$J~3x!Rbm-u51MoDkrkMaPX-Q&n=YV?&nsLw#$9kJo5zoeNG9F)l0A`!SbwmEG6Z6 zry%_OL>xG(ilf!yVD|wjDp7YB*0m4fe_@BY>7F*^>(C;s^_>FEQ^Y{?);2P}w+C`3 zi~(m`dm3*xTexfNI~-b-g~cu7==BvTSW|z8ri@FbizQUBMr05wu2q3xPZ9Crc@>tg z_6Tq8A-Ln)VIouNi-QCFo7Jik_Q%VCR;n0XKF@&5&gmvn9tKR>$P}Yjf$*>Q3Mxh? zV)SNZ+&`qxy)98>*{?5QNqPo(KWQX%j*W!_zPT{3VJocuTS*dnyRqFwj_T<3;=hwF8h79FRh*Eq|<+iAypvD*B4@L*HnIfu^lf>EQCXufDK0*s$=jaL?FSpx>eT>GO zuNL@W&<83`Rni+7fiynqBsk4pkMB7(dOX^Y%NcqEQ#Qr2#f9;7L$$u(N8Aqd``b-l z^7~7LGh<b1(G8p!T&kp+b>>h%(t63WL*P~W+mbYy_=wyDZzL6 z6EP^Q8N1Ay$yASij63@czfRC&HlJRT0pp*-_NaKH@sTn0RFiRu-{LWg=E~pjec49tz$DK<1fM`s1wcz)#DwU*9EGriS6G+~vqqcgZ%VUaV#& zoWmCvxDfsjw%E8p2)}db%E^WTKG)dtB#&CmR^meBs>!A2qHv?N1#7gk!0`b?moOD_ zTlFX2wOWLi!%h<26kq=5iGc6drC8;Jo!BFzBBj!l_K~ zZTW#3jwglldON{-^96eS+ps|XQaHrSx8OZCl1zBzIoR@ViEUXoF}K+k{m0+KKa0{> zoTLiVf1%BirIx@vi`DSrmiCG!Ma5P(-haRzfI@i zps^0X2~C)ukOA4biO}J^l~mv1IL~MIK*sMCN&lRLr+)gQv*|1RJwlYqg&|DaI}3*A zi7@ZA#biV2HoSeg8uBlT;%SSI`0--|`Jn!mB(J*z;|3V}A+So(02&dvh?vp$eoQr{T3xIk?kUms=cqlWZ&=q8CLoF~55= zEQ$Y$Z2f)ce7GIXUs(+%S%X;oR|E4jbMgDo7qUarnR-d_d+{<0G!Ri^o2L$fso0U2gBuM(VHa_Pd_NpQS02+Iw3(vQijp@2WrR_6PH}K~@Cs;D#^n#md(l2LFww2|<}Se$7jwdR&ED zXDEaAM`S@WSOixM*~07%W$<&73G7!%z)2BTFgFsIpJN@d%{CH@neYIcZ>xc-dJT0d zIK;bWPY8bhilu)<){rHGMqF*f7w}zb2&a53AU9((D_Rm=7HD=6Ccd(w!Ks5FzW5lP zi0el2HVtl`MlICe5@i*Y5|@g_7X+u9IkeeSy;g&w~ATzGxbD5p|aaqlbe6OVc}x{jPth`;UEOf^HPo zw|5#>_g0a;F$o3rDW6Ev%GsC^Yl$12W07urE9}uyW~+uz!j%4z(Ee&WRy>IWH~VyW z(fk87=URhqVjVHXndG9q7$^L`k`prj$E3FCyv#1H6 z@bn?v`d|!6t3vQ*o;9fdQ{zP5Ucr|e-qRpaU7GEFl1wZd6ugsC0F`}LffJpI+m@+u zPH~H2&5>!`f8nM0G$t3m6&P}{)%jF$jS<@N-6*g0OOP>2ie1oFMBnrLonmPg_u$q9 zc3*c3{`=z!7gtPTFRXf@FYE-{S{Q=zH+;}9?JJ+HP=ZLMcUWSYNEJ#ggqExM-{)vK zRMWddOxp zym=K>godcEE5f$-yRj2zWO4VclcYi^1oc@I%-h~cFXtvhnZ^S8)_x0{yC$0);k}+a z&pgEfzB{+5eG$e~HsQo0{qXIH6*q$S-nMkupx>QB*kmY8CO>zfs}5L`$NyBh(rrZ~ z!f238ul!4D`z+D$;uYIyo<)8?Y!LOIn*P7HfN^WQ1)Dw|6e`K&30K~fK_lf-nqoeQ znd$9Ahux+$*{qzN%aX$`#odrKco$PGeqw2tJC@Z=#BB$X$ll*sH|5c--ruNOl9wH27zN~06l%2XZ56i!rO2H)6Bg< z|Ii3__kIG?*>DY%Qmirilrb0kXAH}XOkl%tt6-8r9jsOhVOO6=5pPT0`4t_5F60_^ zRsX@}-8mFgZgJMlB7;0BIwXiu{W& z($(OCC7p0uDd?Vho%&4?qFZ+ZCR_3>6Q?xHajL`NdAIp)$|s`KSI0A! zr!%u1!O&-;%Z=9eLch=oV&XS~`%jtCIk$q@vJ_Xgd4C`aPYeSRCC&mvD{wd-Vfmt? z5Tzs(%t`8ppfSPF@M9gz?;Hic2IaZmqdnm2dne}bAJ1>9I|SJiYDn#0ZIIj)DCEon z1?qQ|xWDIr;9TAH;B9>gypo3Lc4rH8oLV4Ajy;HzEWcsppDcKL=^Q*M+RQX=+L0q4 z5=h?XB$l}~0m9@`;h{hbmu0TNJ+&ESY2WWtBkc-)ZrP2CCSK$@j&mS(awj?lD)4zq zWwtU`$G2u zHPAVj&AVj8Fk3i`O*Oou#;=Dw><@ry)`H3!GHgo15&ZJ#Em^!HPq?tI7)zG6(q;om z)beP=8SAyUOCm#P`{E`3g>Krt!X9ocx`Ihwe3p1e2d1WJBd0M$ou*{KbtwUN@R}cW zPn9H})XnkczLDIMfm0yj{1&Q|O{hCRgP8KKjrgui#TozfxkkTKDE;UL(TB7cuUUa7 z^H0FHNuQwS`7`iuHv@$)G2k}U9Ak9;;KH(-yz3wmcRpH&vAwI=M5>PxpZJ|(sTiz( zw2mc)?1%HO$HAMvv+(f>-&ZKCaShJdentNeV^BS4z&q0mMGF&vSFZ7oQ}OVJ@l|! zJIL%Tq*b$r$m`*Ug6CtpK-%f6h=e_ldK47V_IL_LqgOTBZD5G@| z)|oz_jYB0kb< ztB--11D&M%)>f*Vc$z#Zu7o!O)7cJXHPG%*;&!2(XY zW+XiF*@FjgLQXS4R#8v zaRWbFt;qjNB7gsc<~2b$@jnGF;9Nh9l3NLP_dP{Px20t>y+*PA^l~C5_yg2fH19}2(BYN5Q!1J}!(L;X)l5H%xH zxIon2^`oBqGXt~{En zZ|x((H?!hLNGVf71L=GAb3}s*QAwqN43$deL=%YyB`Ha1kcj3a@jd%FXilXf6w)A~ zNdr<+_uSuo|G0O(?|Rq$=d5+s-s_xo*4gXX&wifIfJp@-z%TeBxgKZ3I`t7ru2Kec zCci@GStm$R&lF54YLZNF>7y^@M!=bEBK|u6`Q=`ROKY34fweQ1}qnA-~^|sLKXu`Rxw$h+W*?6h;BkXmLMa}-MLY^YWh0im` z&Qf;>bQniu6&7N^#a(3naywRgo+9ALO7y#a7O%UnfcCe>)Tm7ca%V%b)BG`=jCV@-SW>E~Ityi%klXssL07inC_y)L8S z*@^YEVskt`v$G>QrzEgSU}1PuRsPns{`~D|AKLGYpz&mT0=MUd^Q)7Juxr;P{JkXs zWo;awYK9@Peenf?ZW^<;OXPTm-gf+acM$Q9-v?gKnt0stDZTW{0!f}K8*CCTVDPNi zghO*lN8xQa)S5&z<~{{8h26xaVh?veVGdpYwh!(n7U0UAMbPeZ1$_U!l4uJ#Lh*5T z(w#k6&?&S5KPMCZoo*2*uCE0(uO~ttpIqW>+Jr9pE!f}ewb##hMMDwl(+@jCEc-7Sz4LgTm zIg&%|vZIK@T9kh4ktj#6-ngxaE5>$j^7656m*zt(&h3 zXN;Y2KS(&A&ljQl9DA}vd=_3#?m*Xh3vk?z=h(SFO7ckE0zaNTNym1+CRO`waqnk> zA1=kw(rXLwa_9=`Ke-sV`+~ln!)xLarO&_nYR#RWITB*!ZK=5W5{zv!2bUx*^49|a zQ@ly2Yi`UYwzoL0r~MmMdU=yut(A^LKZjz>_e8R5_hNLsdH^=x2?hJELY%v}9kM&K z>8V=517ijcQj=u(Hyd^Nan6Fru+a3W}CC_>Z8cZpV%fPSF5r|3!tgkb` zXr&Icnf3;jxL9EG*BK;ua~_I1OxgHrjw~7v;BD$pq20GE`mC;7@DBYzoR_(pNbHqr{{;G$K`h)Szx-@#aLn zBtw}mi9SihMe+QX3>Nm(hp>S<#pt}X3?#=4c{QbVknvcHt}}DP0~y&6abP06$}uE6 zJrgj}dJ>KgU&g2pSPRDcN5dwUXl9hlESNFaf}h^q0%;rbQ2RzIwN$(aS9%N}!X}q& zun6WR#nq9u4>h=~nkZ-cfebDK4-0kqm(?qa02W<$0Gno>~afja#wi za2%W>viLY?AUk-_eKlg%kSgpIqa(Z#({GGX`twtDVWA$PB4mJb{V+L{&ctk4ys_OF0h2g@-w z?IaE?86}(<55qfeHQ2mWo|O^s?bj;v!A@WBZH+ucGX<{xtzbL${s(Q=?CU~I?~S8= zDs?n?p98<_vo7oN))=L{zhT~n{`}cRjdau@YrIe@;8A)c;%lxC-_9?> zHH!V&x>E{Jv~DU^9=B!pKT?I2LGy%j9LE@(Xh4h6r=hTS3Ems_lSCTWb1Um*!Q_Ji zJI`l1mENEPZJ{@z=B^cgtxTv33O!h-k=D?)UX!<2FOQ#xE3#S+4+YQK0(hWdJz?RI z#Z*JkY-|0h!V{kY&ie5yW?-l%_RO`wMS4%kyUsM$v8Eqy{8u2`CwO4H9@Ar_<7??a z^)#r-Cp{dKrf zJQC+dZi3q~zll+~2uIgX1-Csfu_ z-%G}1ycd10oR7Dwj?lGw4&?Q35tLUt(J9X7v0}n$IBy`sry8mA_Ge-Rox}xXkNth9 zYxF@M9VzzQ@K~r?)XlsaWCt_qEm@BxGQ8#elW=yj3V-Ef2~B!+5d+Hyv01uDVO+-( zT-K(?9%H}KiDj?J3+qS3Vu>^_Xn>QAwJV_5HBRWm=%JE_oS+f%5HcQ2#e{{jd`*am zZF|~}k9_c*&R!XY^IKJTYttHL{NxK<*r4s;;w9)8$+XgPl};`^u@}liRoO7j{z8q% zh$x;8M%>k)OU)<}d&l-AdrA1Mxa3Q}LQc9#C$0I@FdTIk%)RRs} ziN~^CdkW~$ncJb^+ZkB?VhDS@HXX)0hhcMa0(y>Fj!HiDz*Oe|C-@kdo^Zq7utu^! z(}1e{QpYm_A6!n*E>d{C53fACj77&Lkopr&d|s0&^W}wbmQMIawbS=O+vWk-vosZY z-|Rziw+U62m4|^k=Rnud1f8OqA$svqy82rvd6xuy^R->%(Up8y87Bp$QGh2lJ%xu+ zKgche>txl)3GDTV7|a_Y#+GZ3@Qml4?K3i-ziu5ZQ2tyq?a6j~z>^HqZS3lZ@xgDnC+xs6u^U+&zd9MjL z$=I@_3)z`S3u!(EDW#e{*&~)**U^oS%7!id~urAAsn)B0o&^* z%VsV+i?__ifc?S&aJT6rXA|JWy^ATQd(H}uOJVi2EG-)fE$=YDmgaMrvkw!`oSP(J ziG+;ZWRB1>3Fk!0q1=mHGH>S)wqf@s@_d>ZADv%MnyJ!PUVP%+pS&#j>y@rZ>)!FIOTm+uZM(k=5uoF%?I3Xkn_q&ZGH~P!tR&Bxa;bI<> zvEGd&o^Zi0tT7+@`7)X>uA>KrE8y2NCrGp6PB1T$Rfv^VlXkRN6A%#<9Jb2aH`qVg z^6#s6z#9Kx|9~*d@PJV7)k~uT!on@bSo#Jo4WAJ!YqI^fBxr{@I*-`Rm}T9ke_0#T z(k}u)S+jx}Ugs)acrK1JjdTX1te=!5tfK4KRMJr=Oll6=^9nd{S! zC96dyz_e%6+|VvYMqw6gn=pkoXcv)7N?P>8p4lXSo-s9Os-wL|)1f-PocnV8FVtU? zPq*kwQ%yB#YNf$bHII0jnPv!Lqm$&0Vh&M$S4uY=^?)547ePbfcrtD=PrWK~xYm+A zw7^P=(OoW!%d*_)jmr&W*PSXdxZz{T+6gbH<9b8zy`a=&^S+ za>r_D*`dpATRD!NT~LX1<`%j;c^fHD4#vACcHG_G-ONqfR4QMq4EmvgxN=o78BrNe zQZ#wyuiFPW#pr%wkC&&>$0P+;9#BF_@G-3F&Bkt_N-iIBliJshf%)aDV3$cE@!ytA zRtcTZdzrz=n9Qe(TXgB`@DSWWfD9GiXR^A^V!(GPiSE&TFCYQk;9#V{gS8lM~7CK`F>$b|kO@BMw~g|DAT_%9i> zx)Z_emh=(XTYK=()lSkp^8r0psL3>m8_1TahJsW4PtGv?n!tuBVNOjCBem^Hbf?V* zZpI-3r3pvrlYvAW8Q3W)^fSl6>#;QK=wPDZP>uoe<1uvFL2A&xOX6u4O9DswL-+8# zTuayu;xp$xm)S84?KD#{LdZ}HA~MP2x#rB~0ShED)>WKSZy~X@n$1+q*+eg7JOKB` zKql$C4V?mNWMB>8%z_`Zd*Kc)zi9{Ac}0hATBgq2-fMz#^M{e+v2LVvj6Kn+zCt{H zIZ>la=eSj4TS-ynR&khYJhP}Sg(JBtoTs%ay<8DN!bI04Uwuw+JKx_UiAg{Vng-(T z=3zwZk~|zyErJmx+sR|Sy-c`~41{WJ1m)!^jM<_pPSZ>tOQMxw+hq@oHjsnn_`P^t zWfG>w7E-eLDkrtBK(hOcGHr}aryf}eOwo~5c($~H?DFeR^+c;^&rMbAYduN+Xpe%Q z=3a2v{2gh#~ibUkA*-OY)oWk|Zi2~hG#bm#$JRa;m4_f0@&{jGDMs~%}^D7^Ll)f+A zI5`M^XsUr-X&6L2P2$p{JkaW;E%`oO2Hk`m^kR<;=CsVmizTm$6_loPu3kpqDkVeT z)fIE8O*gpos~gDLH>T7*ehN&yHHLW;bqrOj4EBMVC(|Aq2Bzqx(0XL4;R$G8OMERjf?;?DsM0xa$!z)VVs3Ox;|->c0y=Lge^+<5KVopE8=ha94uj>i?SE#DWhaUC z?MF0yWLv7W?3W(vWX+ZSo;iAktd!KmiT`sq=3jSSdLp@C-*9hh4NZ}{g0zORNM1wE zcWH#*3XzP0g0G%PWv#Gp{xd+Xi45`$2-6UW6ohHA!l<;bj%YwoKu~a4v=AC&0{&yj zOr-H|q4ZxL8UBC0L&n!aWbnVHdIv{FghWPohp$)~@}CbLFEaEGhzJM^3S1+^=Rm)I OkJ$g;YaC_N6#oI-_It_z literal 0 HcmV?d00001 diff --git a/com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx.meta b/com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx.meta new file mode 100644 index 0000000000..cc92cc94b8 --- /dev/null +++ b/com.unity.ml-agents/Tests/Editor/TestModels/deterContinuous2vis8vec2action_v2_0.onnx.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: e905d8f9eadcf45aa8c485594fecba6d +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 683b6cb6d0a474744822c888b46772c9, type: 3} + optimizeModel: 1 + forceArbitraryBatchSize: 1 + treatErrorsAsWarnings: 0 + importMode: 1 diff --git a/com.unity.ml-agents/Tests/Editor/TestModels/deterDiscrete1obs3action_v2_0.onnx b/com.unity.ml-agents/Tests/Editor/TestModels/deterDiscrete1obs3action_v2_0.onnx new file mode 100644 index 0000000000000000000000000000000000000000..3aa846e204fcf2a36a91c60709bfbc9fb1aba43e GIT binary patch literal 3715 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 literal 43926 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

d(jHm@JJaI&!Ud-}LYQO9*6vFe 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%0Aa z4`G_sXWjI)zlh!htT6 zVCPFK=A3^BwVO>Zl!gagEh^VyNxJm-`l>2&u+4Qm6A2k!r2Fc1=1HuQGYB2f@aNGQ$58N_7Y>B!`JrvGF-*_u zIkc^XpErmL-}KZEsazYlp?_5TOntts2$%oNakBVw9)CAc(ew!KktC z{#whxi()|g%@5bWx5xV_D&-k9oc6j%77M+YvjW22j^ZT3T6BfE*iS7PK2F`%$-ia@ zQZ3m!>DWU^`{ce;=X%;xb=UCDA}I>ImvW*l#hOR8qLSTZ*uu_Re;RlywQ0;jquJt? z_4GKI8>YlfyT3pTa6n8>JuU9x;AWU`U7O@^mXQZ*EFl68<7)ePV0 z1@|1`NE(B=S9Di+u|J~U1#1-OPf=bRPHyr9s+Wf4@m Date: Thu, 18 Nov 2021 09:55:08 -0800 Subject: [PATCH 15/16] Update CHANGELOG.md --- com.unity.ml-agents/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index 7122b4f38a..47fccd2a68 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -31,9 +31,9 @@ and this project adheres to 3. env_params.restarts_rate_limit_period_s (--restarts-rate-limit-period-s) [default=60] -- Deterministic action selection is now supported during training and inference +- Deterministic action selection is now supported during training and inference(#5619) - Added a new `--deterministic` cli flag to deterministically select the most probable actions in policy. The same thing can - be achieved by adding `deterministic: true` under `network_settings` of the run options configuration.(#5619) + be achieved by adding `deterministic: true` under `network_settings` of the run options configuration.(#5597) - Extra tensors are now serialized to support deterministic action selection in onnx. (#5593) - Support inference with deterministic action selection in editor (#5599) ### Bug Fixes From e212e732c8b2c6b62759a3699b90223c51f2157e Mon Sep 17 00:00:00 2001 From: cmard <87716492+cmard@users.noreply.github.com> Date: Tue, 30 Nov 2021 11:20:40 -0500 Subject: [PATCH 16/16] Fix the deterministic showing up all the tiime (#5621) --- ml-agents/mlagents/trainers/torch/action_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/torch/action_model.py b/ml-agents/mlagents/trainers/torch/action_model.py index 65dfd32b40..b4c3282de5 100644 --- a/ml-agents/mlagents/trainers/torch/action_model.py +++ b/ml-agents/mlagents/trainers/torch/action_model.py @@ -81,7 +81,6 @@ def _sample_action(self, dists: DistInstances) -> AgentAction: continuous_action: Optional[torch.Tensor] = None discrete_action: Optional[List[torch.Tensor]] = None # This checks None because mypy complains otherwise - print(self._deterministic) if dists.continuous is not None: if self._deterministic: continuous_action = dists.continuous.deterministic_sample()