From 6947a23d6c3c283ed83a0c22b20233d343f1d1a4 Mon Sep 17 00:00:00 2001 From: Anthony Wu <462072+anthonywu@users.noreply.github.com> Date: Sun, 12 Oct 2025 03:20:40 -0700 Subject: [PATCH] Scheduler interface implementation. Implement pre-existing linear scheduler only. (#258) Co-authored-by: Anthony Wu Co-authored-by: filipstrand --- pyproject.toml | 3 +- src/mflux/config/config.py | 2 + src/mflux/config/runtime_config.py | 42 ++++------ src/mflux/generate.py | 1 + src/mflux/generate_controlnet.py | 1 + src/mflux/generate_depth.py | 1 + src/mflux/generate_fill.py | 1 + src/mflux/generate_in_context_catvton.py | 1 + src/mflux/generate_in_context_dev.py | 1 + src/mflux/generate_in_context_edit.py | 1 + src/mflux/generate_kontext.py | 1 + src/mflux/generate_redux.py | 1 + .../model/flux_transformer/transformer.py | 2 +- .../concept_attention/flux_concept.py | 12 ++- .../flux_concept_from_image.py | 7 +- .../variants/controlnet/flux_controlnet.py | 10 ++- .../models/flux/variants/depth/flux_depth.py | 10 ++- .../optimization/dreambooth_loss.py | 2 +- .../models/flux/variants/fill/flux_fill.py | 10 ++- .../in_context/flux_in_context_dev.py | 14 +++- .../in_context/flux_in_context_fill.py | 10 ++- .../flux/variants/kontext/flux_kontext.py | 10 ++- .../models/flux/variants/redux/flux_redux.py | 10 ++- .../models/flux/variants/txt2img/flux.py | 12 ++- .../qwen_transformer/qwen_transformer.py | 2 +- .../qwen/variants/txt2img/qwen_image.py | 12 ++- src/mflux/schedulers/__init__.py | 68 +++++++++++++++ src/mflux/schedulers/base_scheduler.py | 26 ++++++ src/mflux/schedulers/linear_scheduler.py | 49 +++++++++++ src/mflux/ui/cli/parsers.py | 1 + tests/arg_parser/test_cli_argparser.py | 15 ++++ .../reference_controlnet_dev_lora_depth.png | Bin 46950 -> 47229 bytes tests/schedulers/test_base_scheduler.py | 12 +++ tests/schedulers/test_linear_scheduler.py | 79 ++++++++++++++++++ tests/schedulers/test_scheduler_lookup.py | 17 ++++ uv.lock | 2 + 36 files changed, 394 insertions(+), 54 deletions(-) create mode 100644 src/mflux/schedulers/__init__.py create mode 100644 src/mflux/schedulers/base_scheduler.py create mode 100644 src/mflux/schedulers/linear_scheduler.py create mode 100644 tests/schedulers/test_base_scheduler.py create mode 100644 tests/schedulers/test_linear_scheduler.py create mode 100644 tests/schedulers/test_scheduler_lookup.py diff --git a/pyproject.toml b/pyproject.toml index e975519..5d28898 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,6 +65,7 @@ classifiers = [ [project.optional-dependencies] dev = [ + "matplotlib>3.10,<4.0", "pytest>=8.3.0,<9.0", "pytest-timer>=1.0,<2.0", "mlx==0.27.1", # Used ONLY during test runs to ensure deterministic test results @@ -173,7 +174,7 @@ disable_error_code = [ "union-attr", "return", "return-value", - "var-annotated" + "var-annotated", ] error_summary = true ignore_missing_imports = true diff --git a/src/mflux/config/config.py b/src/mflux/config/config.py index 2f357a1..001923a 100644 --- a/src/mflux/config/config.py +++ b/src/mflux/config/config.py @@ -22,6 +22,7 @@ class Config: redux_image_strengths: list[float] | None = None, masked_image_path: Path | None = None, controlnet_strength: float | None = None, + scheduler: str = "linear", ): if width % 16 != 0 or height % 16 != 0: log.warning("Width and height should be multiples of 16. Rounding down.") @@ -36,3 +37,4 @@ class Config: self.redux_image_strengths = redux_image_strengths self.masked_image_path = masked_image_path self.controlnet_strength = controlnet_strength + self.scheduler_str = scheduler diff --git a/src/mflux/config/runtime_config.py b/src/mflux/config/runtime_config.py index 809373c..6fa4e62 100644 --- a/src/mflux/config/runtime_config.py +++ b/src/mflux/config/runtime_config.py @@ -2,10 +2,11 @@ import logging from pathlib import Path import mlx.core as mx -import numpy as np from mflux.config.config import Config from mflux.config.model_config import ModelConfig +from mflux.schedulers import SCHEDULER_REGISTRY, try_import_external_scheduler +from mflux.schedulers.linear_scheduler import LinearScheduler logger = logging.getLogger(__name__) @@ -18,7 +19,7 @@ class RuntimeConfig: ): self.config = config self.model_config = model_config - self.sigmas = self._create_sigmas(config, model_config) + self._scheduler = None @property def height(self) -> int: @@ -96,27 +97,20 @@ class RuntimeConfig: return None - @staticmethod - def _create_sigmas(config: Config, model_config: ModelConfig) -> mx.array: - sigmas = RuntimeConfig._create_sigmas_values(config.num_inference_steps) - if model_config.requires_sigma_shift: - sigmas = RuntimeConfig._shift_sigmas(sigmas=sigmas, width=config.width, height=config.height) - return sigmas + @property + def scheduler(self): + if self._scheduler is not None: + return self._scheduler - @staticmethod - def _create_sigmas_values(num_inference_steps: int) -> mx.array: - sigmas = np.linspace(1.0, 1 / num_inference_steps, num_inference_steps) - sigmas = mx.array(sigmas).astype(mx.float32) - return mx.concatenate([sigmas, mx.zeros(1)]) + if self.config.scheduler_str == "linear": + self._scheduler = LinearScheduler(self) + elif (registered_scheduler := SCHEDULER_REGISTRY.get(self.config.scheduler_str, None)) is not None: + self._scheduler = registered_scheduler(self) + elif "." in self.config.scheduler_str: + # this raises ValueError if scheduler is not importable + scheduler_cls = try_import_external_scheduler(self.config.scheduler_str) + self._scheduler = scheduler_cls(self) + else: + raise NotImplementedError(f"The scheduler {self.config.scheduler_str!r} is not implemented by mflux.") - @staticmethod - def _shift_sigmas(sigmas: mx.array, width: int, height: int) -> mx.array: - y1 = 0.5 - x1 = 256 - m = (1.15 - y1) / (4096 - x1) - b = y1 - m * x1 - mu = m * width * height / 256 + b - mu = mx.array(mu) - shifted_sigmas = mx.exp(mu) / (mx.exp(mu) + (1 / sigmas - 1)) - shifted_sigmas[-1] = 0 - return shifted_sigmas + return self._scheduler diff --git a/src/mflux/generate.py b/src/mflux/generate.py index 37458db..bcde5c4 100644 --- a/src/mflux/generate.py +++ b/src/mflux/generate.py @@ -51,6 +51,7 @@ def main(): guidance=args.guidance, image_path=args.image_path, image_strength=args.image_strength, + scheduler=args.scheduler, ), ) # 4. Save the image diff --git a/src/mflux/generate_controlnet.py b/src/mflux/generate_controlnet.py index d0872ab..a2336f1 100644 --- a/src/mflux/generate_controlnet.py +++ b/src/mflux/generate_controlnet.py @@ -48,6 +48,7 @@ def main(): width=args.width, guidance=args.guidance, controlnet_strength=args.controlnet_strength, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/generate_depth.py b/src/mflux/generate_depth.py index 7890ab5..c477ceb 100644 --- a/src/mflux/generate_depth.py +++ b/src/mflux/generate_depth.py @@ -46,6 +46,7 @@ def main(): guidance=args.guidance, image_path=args.image_path, depth_image_path=args.depth_image_path, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/generate_fill.py b/src/mflux/generate_fill.py index 34e9a40..6fbc052 100644 --- a/src/mflux/generate_fill.py +++ b/src/mflux/generate_fill.py @@ -46,6 +46,7 @@ def main(): guidance=args.guidance, image_path=args.image_path, masked_image_path=args.masked_image_path, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/generate_in_context_catvton.py b/src/mflux/generate_in_context_catvton.py index 7e27741..6f8f8a8 100644 --- a/src/mflux/generate_in_context_catvton.py +++ b/src/mflux/generate_in_context_catvton.py @@ -61,6 +61,7 @@ def main(): guidance=args.guidance, image_path=args.person_image, masked_image_path=args.person_mask, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/generate_in_context_dev.py b/src/mflux/generate_in_context_dev.py index 6e1f57f..6b4d8ed 100644 --- a/src/mflux/generate_in_context_dev.py +++ b/src/mflux/generate_in_context_dev.py @@ -56,6 +56,7 @@ def main(): width=args.width, guidance=args.guidance, image_path=args.image_path, + scheduler=args.scheduler, ), ) # 4. Save the image diff --git a/src/mflux/generate_in_context_edit.py b/src/mflux/generate_in_context_edit.py index e1b0db7..23c9391 100644 --- a/src/mflux/generate_in_context_edit.py +++ b/src/mflux/generate_in_context_edit.py @@ -61,6 +61,7 @@ def main(): height=height, width=width, guidance=args.guidance, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/generate_kontext.py b/src/mflux/generate_kontext.py index f979df0..f56aaeb 100644 --- a/src/mflux/generate_kontext.py +++ b/src/mflux/generate_kontext.py @@ -47,6 +47,7 @@ def main(): width=args.width, guidance=args.guidance, image_path=args.image_path, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/generate_redux.py b/src/mflux/generate_redux.py index 452aaef..c1a322c 100644 --- a/src/mflux/generate_redux.py +++ b/src/mflux/generate_redux.py @@ -56,6 +56,7 @@ def main(): guidance=args.guidance, redux_image_paths=args.redux_image_paths, redux_image_strengths=redux_image_strengths, + scheduler=args.scheduler, ), ) diff --git a/src/mflux/models/flux/model/flux_transformer/transformer.py b/src/mflux/models/flux/model/flux_transformer/transformer.py index bbb14d4..e8228ba 100644 --- a/src/mflux/models/flux/model/flux_transformer/transformer.py +++ b/src/mflux/models/flux/model/flux_transformer/transformer.py @@ -150,7 +150,7 @@ class Transformer(nn.Module): time_text_embed: TimeTextEmbed, config: RuntimeConfig, ) -> mx.array: - time_step = config.sigmas[t] * config.num_train_steps + time_step = config.scheduler.sigmas[t] * config.num_train_steps time_step = mx.broadcast_to(time_step, (1,)).astype(config.precision) guidance = mx.broadcast_to(config.guidance * config.num_train_steps, (1,)).astype(config.precision) text_embeddings = time_text_embed(time_step, pooled_prompt_embeds, guidance) diff --git a/src/mflux/models/flux/variants/concept_attention/flux_concept.py b/src/mflux/models/flux/variants/concept_attention/flux_concept.py index 7f985b8..d498003 100644 --- a/src/mflux/models/flux/variants/concept_attention/flux_concept.py +++ b/src/mflux/models/flux/variants/concept_attention/flux_concept.py @@ -66,7 +66,7 @@ class Flux1Concept(nn.Module): img2img=Img2Img( vae=self.vae, image_path=config.image_path, - sigmas=config.sigmas, + sigmas=config.scheduler.sigmas, init_time_step=config.init_time_step, ), ) @@ -102,6 +102,9 @@ class Flux1Concept(nn.Module): attention_data = GenerationAttentionData() for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Predict the noise noise, attention = self.transformer( t=t, @@ -115,8 +118,11 @@ class Flux1Concept(nn.Module): attention_data.append(attention) # 5.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/concept_attention/flux_concept_from_image.py b/src/mflux/models/flux/variants/concept_attention/flux_concept_from_image.py index 410be6e..491c301 100644 --- a/src/mflux/models/flux/variants/concept_attention/flux_concept_from_image.py +++ b/src/mflux/models/flux/variants/concept_attention/flux_concept_from_image.py @@ -78,7 +78,7 @@ class Flux1ConceptFromImage(nn.Module): latents = LatentCreator.add_noise_by_interpolation( clean=ArrayUtil.pack_latents(latents=encoded_image, height=config.height, width=config.width), noise=static_noise, - sigma=config.sigmas[config.init_time_step], + sigma=config.scheduler.sigmas[config.init_time_step], ) # 2. Encode the main prompt @@ -112,6 +112,9 @@ class Flux1ConceptFromImage(nn.Module): attention_data = GenerationAttentionData() for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Predict the noise (we don't use the noise, only the attention) _, attention = self.transformer( t=t, @@ -128,7 +131,7 @@ class Flux1ConceptFromImage(nn.Module): latents = LatentCreator.add_noise_by_interpolation( clean=ArrayUtil.pack_latents(latents=encoded_image, height=config.height, width=config.width), noise=static_noise, - sigma=config.sigmas[t + 1], + sigma=config.scheduler.sigmas[t + 1], ) # (Optional) Call subscribers in-loop diff --git a/src/mflux/models/flux/variants/controlnet/flux_controlnet.py b/src/mflux/models/flux/variants/controlnet/flux_controlnet.py index 678a7cd..8521b30 100644 --- a/src/mflux/models/flux/variants/controlnet/flux_controlnet.py +++ b/src/mflux/models/flux/variants/controlnet/flux_controlnet.py @@ -96,6 +96,9 @@ class Flux1Controlnet(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Compute controlnet samples controlnet_block_samples, controlnet_single_block_samples = self.transformer_controlnet( t=t, @@ -118,8 +121,11 @@ class Flux1Controlnet(nn.Module): ) # 6.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/depth/flux_depth.py b/src/mflux/models/flux/variants/depth/flux_depth.py index 4279560..5e68fc0 100644 --- a/src/mflux/models/flux/variants/depth/flux_depth.py +++ b/src/mflux/models/flux/variants/depth/flux_depth.py @@ -92,6 +92,9 @@ class Flux1Depth(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Concatenate the updated latents with the (static) depth map hidden_states = mx.concatenate([latents, static_depth_map], axis=-1) @@ -105,8 +108,11 @@ class Flux1Depth(nn.Module): ) # 6.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/dreambooth/optimization/dreambooth_loss.py b/src/mflux/models/flux/variants/dreambooth/optimization/dreambooth_loss.py index 7a3fac3..10c804f 100644 --- a/src/mflux/models/flux/variants/dreambooth/optimization/dreambooth_loss.py +++ b/src/mflux/models/flux/variants/dreambooth/optimization/dreambooth_loss.py @@ -49,7 +49,7 @@ class DreamBoothLoss: latents_t = LatentCreator.add_noise_by_interpolation( clean=clean_image, noise=pure_noise, - sigma=config.sigmas[t], + sigma=config.scheduler.sigmas[t], ) # Predict the noise from timestep t diff --git a/src/mflux/models/flux/variants/fill/flux_fill.py b/src/mflux/models/flux/variants/fill/flux_fill.py index c9b8f78..9d9703e 100644 --- a/src/mflux/models/flux/variants/fill/flux_fill.py +++ b/src/mflux/models/flux/variants/fill/flux_fill.py @@ -89,6 +89,9 @@ class Flux1Fill(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Concatenate the updated latents with the static masked latents hidden_states = mx.concatenate([latents, static_masked_latents], axis=-1) @@ -102,8 +105,11 @@ class Flux1Fill(nn.Module): ) # 6.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/in_context/flux_in_context_dev.py b/src/mflux/models/flux/variants/in_context/flux_in_context_dev.py index c15f977..ec75526 100644 --- a/src/mflux/models/flux/variants/in_context/flux_in_context_dev.py +++ b/src/mflux/models/flux/variants/in_context/flux_in_context_dev.py @@ -89,6 +89,9 @@ class Flux1InContextDev(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Predict the noise noise = self.transformer( t=t, @@ -99,8 +102,11 @@ class Flux1InContextDev(nn.Module): ) # 5.t Take one denoise step and update latents - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # 6.t Override the left-hand side of latents by linearly interpolating between latents and static noise latents = Flux1InContextDev._update_latents( @@ -109,6 +115,7 @@ class Flux1InContextDev(nn.Module): latents=latents, encoded_image=encoded_image, static_noise=static_noise, + sigmas=config.scheduler.sigmas, ) # (Optional) Call subscribers in-loop @@ -180,6 +187,7 @@ class Flux1InContextDev(nn.Module): latents: mx.array, encoded_image: mx.array, static_noise: mx.array, + sigmas: mx.array, ) -> mx.array: # 1. Unpack the latents unpacked = ArrayUtil.unpack_latents(latents=latents, height=config.height, width=config.width) @@ -192,7 +200,7 @@ class Flux1InContextDev(nn.Module): unpacked[:, :, :, 0:latent_width] = LatentCreator.add_noise_by_interpolation( clean=encoded_image[:, :, :, 0:latent_width], noise=unpacked_static_noise[:, :, :, 0:latent_width], - sigma=config.sigmas[t + 1], + sigma=sigmas[t + 1], ) # 4. Repack the latents diff --git a/src/mflux/models/flux/variants/in_context/flux_in_context_fill.py b/src/mflux/models/flux/variants/in_context/flux_in_context_fill.py index d9da0f8..8073acd 100644 --- a/src/mflux/models/flux/variants/in_context/flux_in_context_fill.py +++ b/src/mflux/models/flux/variants/in_context/flux_in_context_fill.py @@ -99,6 +99,9 @@ class Flux1InContextFill(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Concatenate the updated latents with the static masked latents hidden_states = mx.concatenate([latents, static_masked_latents], axis=-1) @@ -112,8 +115,11 @@ class Flux1InContextFill(nn.Module): ) # 6.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/kontext/flux_kontext.py b/src/mflux/models/flux/variants/kontext/flux_kontext.py index ae0ec09..694c3aa 100644 --- a/src/mflux/models/flux/variants/kontext/flux_kontext.py +++ b/src/mflux/models/flux/variants/kontext/flux_kontext.py @@ -88,6 +88,9 @@ class Flux1Kontext(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 4.t Concatenate the updated latents with the static image latents hidden_states = mx.concatenate([latents, static_image_latents], axis=1) @@ -105,8 +108,11 @@ class Flux1Kontext(nn.Module): noise = noise[:, : latents.shape[1]] # 7.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/redux/flux_redux.py b/src/mflux/models/flux/variants/redux/flux_redux.py index 08f233c..b9deeb2 100644 --- a/src/mflux/models/flux/variants/redux/flux_redux.py +++ b/src/mflux/models/flux/variants/redux/flux_redux.py @@ -92,6 +92,9 @@ class Flux1Redux(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = runtime_config.scheduler.scale_model_input(latents, t) + # 3.t Predict the noise noise = self.transformer( t=t, @@ -102,8 +105,11 @@ class Flux1Redux(nn.Module): ) # 4.t Take one denoise step - dt = runtime_config.sigmas[t + 1] - runtime_config.sigmas[t] - latents += noise * dt + latents = runtime_config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/flux/variants/txt2img/flux.py b/src/mflux/models/flux/variants/txt2img/flux.py index 8df2686..313f4d2 100644 --- a/src/mflux/models/flux/variants/txt2img/flux.py +++ b/src/mflux/models/flux/variants/txt2img/flux.py @@ -63,7 +63,7 @@ class Flux1(nn.Module): img2img=Img2Img( vae=self.vae, image_path=config.image_path, - sigmas=config.sigmas, + sigmas=config.scheduler.sigmas, init_time_step=config.init_time_step, ), ) @@ -88,6 +88,9 @@ class Flux1(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = config.scheduler.scale_model_input(latents, t) + # 3.t Predict the noise noise = self.transformer( t=t, @@ -98,8 +101,11 @@ class Flux1(nn.Module): ) # 4.t Take one denoise step - dt = config.sigmas[t + 1] - config.sigmas[t] - latents += noise * dt + latents = config.scheduler.step( + model_output=noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/models/qwen/model/qwen_transformer/qwen_transformer.py b/src/mflux/models/qwen/model/qwen_transformer/qwen_transformer.py index 9472fb5..2bfbbfc 100644 --- a/src/mflux/models/qwen/model/qwen_transformer/qwen_transformer.py +++ b/src/mflux/models/qwen/model/qwen_transformer/qwen_transformer.py @@ -89,7 +89,7 @@ class QwenTransformer(nn.Module): time_text_embed: QwenTimeTextEmbed, config: RuntimeConfig, ) -> mx.array: - time_step = config.sigmas[t] + time_step = config.scheduler.sigmas[t] batch = hidden_states.shape[0] timestep = mx.array(np.full((batch,), time_step, dtype=np.float32)) text_embeddings = time_text_embed(timestep, hidden_states) diff --git a/src/mflux/models/qwen/variants/txt2img/qwen_image.py b/src/mflux/models/qwen/variants/txt2img/qwen_image.py index e79d8de..0d681f1 100644 --- a/src/mflux/models/qwen/variants/txt2img/qwen_image.py +++ b/src/mflux/models/qwen/variants/txt2img/qwen_image.py @@ -67,7 +67,7 @@ class QwenImage(nn.Module): width=runtime_config.width, img2img=Img2Img( vae=self.vae, - sigmas=runtime_config.sigmas, + sigmas=runtime_config.scheduler.sigmas, init_time_step=runtime_config.init_time_step, image_path=runtime_config.image_path, ), @@ -92,6 +92,9 @@ class QwenImage(nn.Module): for t in time_steps: try: + # Scale model input if needed by the scheduler + latents = runtime_config.scheduler.scale_model_input(latents, t) + # 3. Predict the noise noise = self.transformer( t=t, @@ -110,8 +113,11 @@ class QwenImage(nn.Module): guided_noise = QwenImage._compute_guided_noise(noise, noise_negative, runtime_config.guidance) # 4.t Take one denoise step - dt = runtime_config.sigmas[t + 1] - runtime_config.sigmas[t] - latents = latents + guided_noise * dt + latents = runtime_config.scheduler.step( + model_output=guided_noise, + timestep=t, + sample=latents, + ) # (Optional) Call subscribers in-loop Callbacks.in_loop( diff --git a/src/mflux/schedulers/__init__.py b/src/mflux/schedulers/__init__.py new file mode 100644 index 0000000..8f3549f --- /dev/null +++ b/src/mflux/schedulers/__init__.py @@ -0,0 +1,68 @@ +from .linear_scheduler import LinearScheduler + +__all__ = [ + "LinearScheduler", +] + + +class SchedulerModuleNotFound(ValueError): ... + + +class SchedulerClassNotFound(ValueError): ... + + +class InvalidSchedulerType(TypeError): ... + + +SCHEDULER_REGISTRY = { + "linear": LinearScheduler, + "LinearScheduler": LinearScheduler, +} + + +def register_contrib(scheduler_object, scheduler_name=None): + if scheduler_name is None: + scheduler_name = scheduler_object.__name__ + SCHEDULER_REGISTRY[scheduler_name] = scheduler_object + + +def try_import_external_scheduler(scheduler_object_path: str): + import importlib + import inspect + + from .base_scheduler import BaseScheduler + + try: + last_dot_index = scheduler_object_path.rfind(".") + + if last_dot_index < 0: + raise SchedulerModuleNotFound( + f"Invalid scheduler path format: {scheduler_object_path!r}. " + "Expected format: some_library.some_package.maybe_sub_package.YourScheduler" + ) + + module_name_str = scheduler_object_path[:last_dot_index] + scheduler_class_name = scheduler_object_path[last_dot_index + 1 :] + module = importlib.import_module(module_name_str) + except ImportError: + raise SchedulerModuleNotFound(scheduler_object_path) + + try: + # Step 2: Get the object from the module using its string name + SchedulerClass = getattr(module, scheduler_class_name) + except AttributeError: + raise SchedulerClassNotFound(scheduler_object_path) + + # Step 3: Validate that it's a class and inherits from BaseScheduler + if not inspect.isclass(SchedulerClass): + raise InvalidSchedulerType( + f"{scheduler_object_path!r} is not a class. " f"Schedulers must be classes inheriting from BaseScheduler." + ) + + if not issubclass(SchedulerClass, BaseScheduler): + raise InvalidSchedulerType( + f"{scheduler_object_path!r} does not inherit from BaseScheduler. " + f"All schedulers must inherit from mflux.schedulers.BaseScheduler." + ) + + return SchedulerClass diff --git a/src/mflux/schedulers/base_scheduler.py b/src/mflux/schedulers/base_scheduler.py new file mode 100644 index 0000000..ffacb7e --- /dev/null +++ b/src/mflux/schedulers/base_scheduler.py @@ -0,0 +1,26 @@ +from abc import ABC, abstractmethod + +import mlx.core as mx + + +class BaseScheduler(ABC): + """ + Abstract base class for all schedulers. + """ + + @property + @abstractmethod + def sigmas(self) -> mx.array: + """ + The sigma schedule for the diffusion process. + """ + ... + + @abstractmethod + def step(self, model_output: mx.array, timestep: int, sample: mx.array, **kwargs) -> mx.array: ... + + def scale_model_input(self, latents: mx.array, t: int) -> mx.array: + """ + Scale the denoising model input. By default, no scaling applied. + """ + return latents diff --git a/src/mflux/schedulers/linear_scheduler.py b/src/mflux/schedulers/linear_scheduler.py new file mode 100644 index 0000000..6500e46 --- /dev/null +++ b/src/mflux/schedulers/linear_scheduler.py @@ -0,0 +1,49 @@ +from typing import TYPE_CHECKING + +import mlx.core as mx + +if TYPE_CHECKING: + from mflux.config.runtime_config import RuntimeConfig + +from mflux.schedulers.base_scheduler import BaseScheduler + + +class LinearScheduler(BaseScheduler): + """ + Linear scheduler - the default/classic scheduler used in mflux. + Creates a linear schedule from 1.0 to 1/num_steps. + """ + + def __init__(self, runtime_config: "RuntimeConfig"): + self.runtime_config = runtime_config + self._sigmas = self._get_sigmas() + + @property + def sigmas(self) -> mx.array: + return self._sigmas + + def _get_sigmas(self) -> mx.array: + model_config = self.runtime_config.model_config + sigmas = mx.linspace( + 1.0, + 1.0 / self.runtime_config.num_inference_steps, + self.runtime_config.num_inference_steps, + ) + sigmas = mx.array(sigmas).astype(mx.float32) + sigmas = mx.concatenate([sigmas, mx.zeros(1)]) + if model_config.requires_sigma_shift: + y1 = 0.5 + x1 = 256 + m = (1.15 - y1) / (4096 - x1) + b = y1 - m * x1 + mu = m * self.runtime_config.width * self.runtime_config.height / 256 + b + mu = mx.array(mu) + shifted_sigmas = mx.exp(mu) / (mx.exp(mu) + (1 / sigmas - 1)) + shifted_sigmas[-1] = 0 + return shifted_sigmas + else: + return sigmas + + def step(self, model_output: mx.array, timestep: int, sample: mx.array, **kwargs) -> mx.array: + dt = self._sigmas[timestep + 1] - self._sigmas[timestep] + return sample + model_output * dt diff --git a/src/mflux/ui/cli/parsers.py b/src/mflux/ui/cli/parsers.py index 005f340..e0c9e30 100644 --- a/src/mflux/ui/cli/parsers.py +++ b/src/mflux/ui/cli/parsers.py @@ -108,6 +108,7 @@ class CommandLineParser(argparse.ArgumentParser): self.add_argument("--negative-prompt", type=str, default="", help="The negative prompt to guide what the model should not generate.") self.add_argument("--seed", type=int, default=None, nargs='+', help="Specify 1+ Entropy Seeds (Default is 1 time-based random-seed)") self.add_argument("--auto-seeds", type=int, default=-1, help="Auto generate N Entropy Seeds (random ints between 0 and 1 billion") + self.add_argument("--scheduler", type=str, default="linear", help="Choose from implemented schedulers (linear only for now). Or bring your own: 'your_package.some_module.FooScheduler'") self._add_image_generator_common_arguments(supports_dimension_scale_factor=supports_dimension_scale_factor) if supports_metadata_config: self.add_metadata_config() diff --git a/tests/arg_parser/test_cli_argparser.py b/tests/arg_parser/test_cli_argparser.py index 039ec4a..d4b0e25 100644 --- a/tests/arg_parser/test_cli_argparser.py +++ b/tests/arg_parser/test_cli_argparser.py @@ -674,6 +674,21 @@ def test_fill_default_guidance(): assert args.guidance == ui_defaults.DEFAULT_DEV_FILL_GUIDANCE +def test_scheduler_by_name(mflux_generate_parser, mflux_generate_minimal_model_argv): + with patch("sys.argv", mflux_generate_minimal_model_argv + ["--scheduler", "linear"]): + args = mflux_generate_parser.parse_args() + # we just want the arg to be accepted + assert args.scheduler == "linear" + + with patch("sys.argv", mflux_generate_minimal_model_argv + ["--scheduler", "foobar"]): + # let the CLI will accept "foobar" - later RuntimeConfig will validate + args = mflux_generate_parser.parse_args() + + with patch("sys.argv", mflux_generate_minimal_model_argv + ["--scheduler", "mflux.someplugin.SchedulerBaz"]): + # let the CLI will accept external import paths - later RuntimeConfig will validate + args = mflux_generate_parser.parse_args() + + def test_save_depth_args(mflux_save_depth_parser, mflux_save_depth_minimal_argv): # Test required arguments with patch("sys.argv", mflux_save_depth_minimal_argv): diff --git a/tests/resources/reference_controlnet_dev_lora_depth.png b/tests/resources/reference_controlnet_dev_lora_depth.png index a3fe91cca717e0177818460368a659cdbd723516..8ea75a634e3e40411c33030347e3846bb952385a 100644 GIT binary patch literal 47229 zcmV)9K*hg_P)O@ z><;OfXSs zV8B0=HY}?LUJF(QhXpwu`8pNkyg;BA_fcTwNI~sV0ln9;ms=+IszzSt(?_+s%(Z38x>(MknLNqQ~kAB8nzaW2m{-#+IC|F30Xp4vZjSiNfNnqIxUag;KhblDv;GTd1+{Y|MF%8 zWAb1y_8-m}H>+~|UuA6&_S7T+T4T|y)?bS4(i zjy3>cSYzKeXH&j12#;vV`Y*7+TBV`Qul!O z=CIYZ%>>rf@hcicq}U9cn8w0U4Hy@m!FJ`$`Ez@>fvUnsm5o5vtZU4Pvm zwwb9w^)IE=|0VIU)k<{WO&WAzO#m*Iv(_(rk6NJjL28m4g>d28)@y^n+TI#o8HB5m zAbc}P^v!vRuRR-v4R&xdcyM94IeYEq7wR@UDwQr}!__M-kVmAmTc@iR)n2KCA`C9p zhhbgzj>3slIi2S~INr-mg>V^(UbCdNJ|u=gf_f2zSMGW}9n@b>?srq>akHm1M95mN z)$%4D2!72WtUNlZ8&dLJDFzt7pr?)h^Nm@T6#>lspkJ}?+rNYY)eS7dWvBW&78t)7 zj5Wv&Dk!oc*K?-2Ay(#Lo^fowvijxmfL?W|L(}$Nl0z zTcQ8(n8{!B``HY-Zzw)^oyY%47z6%MQ?ykX;Z%k*;S z>?PKExK-gvHhCsNyz<=pe z0UyRe9-Ir|H50EjyXr#qFTFri$a)17W~F)91|@b^2=@>obmcR9ReKHT6OfRi*B6yt zX!0oR-L?p}WNR99g3tSud!w-n9zg2wz8Is5)3`h zY`)Plg7wtx(Nf@)p<_+UQRYrHfJo;jDTdh3~Rf3(%WbXG5+ZK}m$xm+x-ub!Vie){6<{EF8C1|9GTl@4fO8F{`PCz4Zqo@t~s^>Yo&8^$JpZX^zritpFg}{tY#9< zra2pJ1zs_PVNa|@@7=ALg{}KS+PordmG$BGet7?2s)cC5c;#}-yOS%{Etl6XKL5jK zkFGk#n4s8d6qY$M8*|#_wX*>{-o0W&?jRktI+vTdE7Iify+3_t*6=SJwp7Q|P-LtE zcKzt1KYaRPxma}K0SgTF^@VUAfNu(f`&(#aZEt`3hi`4Gz-Nij1jY)HB{6e|9RMB?h07`rcpHm~j0)EZeW5!3uYY#X7~>x}Y7?Tth*Y!d z=O6#(!)MEm3t*!HxcnX2<^jAmsIC4k7L%p98Jd%S^OGGBvjG;XgX3yI3eL;e{K@bB z{^856>$>XILim*ccx_-?^=%A73*!_(^X9+)!4zr`R!WS*fnha`77*?#cJ=Xp{_W|K zV{tx!*FdC4gz%aU8(x+2$Hl8R|C{ejIc?T}$M~%Z;|yHkzWkT}sTpj4b9e6-PdKc{ zoz|<K)cJ#Av>@?AR5btF4*Mm_p zcr6evDywZ-n7zk2aAxHSeIzDLUhe$x@KyOE(z0q`+AzQ9A_;S2ya(#zw^~V9BO;bp zh#xH`>634~Q8@2)z2=Jj(g^?cBo*EegrS~HcU`oD=mfBROT$*}489J#-=2m?iI1N# z#cJcF-ozBfRw=^`p=NtW5`VK8BBX!4`#Rq&WqxC0R2iw!s#$i{X7X5}u&uXt2ag7( z7bR-#y?+chN81@(hG*HiVFjvca`){PZP32=h#;r7Ue@=Hg->;6vzv;-^-%R|oe4&( z0fn(@a_iQBoH7u60#IFd!I`YM|2GZcdh{M&Sz*hgeHVQpQ6It>sfDk$J9Rwubi0I{ zwKg1vvDKs@H-(K>hP_VLytXA;yFW0}ch)f6Z{T21IK?PcMl8bne*#|Cgoic8@{`(u-a3e@}Y0ny{^%~kiX36ytX?R6hcJfP6hsDSP z&}ooFK?)^ltAjH1C0bun!YiW>XG0tu8U3W;4AqnCM0aUJ_F5sl={#9$6^^qm_fn-kQK7#Xeahn1 z#K30HuBsbZ%II``(^Lcec3v4(~)&^w4eh@=7yPY`^ z=6wmk9OjRggWW2#X!Hup2IFDy=nx)iRqa19*xDU)r@`WR61*#qwHXMrUJ`v%aJawh zZ6S#G!DD`5fvM|Iw5nR3SL-e-crz84YkIrN8ZUD=QFl$-;nr5qIYY1nLV;zOuOegR zzT)~ZBSXj$~SM_VJhQRsjvEqS74-#jZD)Z=l(fzR_ZwJ=RxJRXqD=ehT zKu&^X-jD6wp1YMZRP!5fQFJ}3MRM&(>>#QA%Bs63A(qSf`a<>P&XBpa7@M3NY>FnW z7G#!gEOXI}_9h!KYH7Y{qEq;%-5>6d7^A`Bl_)&rA)8H*>p)-`M?&Fs7SI9U8AiE0 zyWQHd59?M=QxRj%0N}0na18@rFn|2vY&T3NRug#;dE(h>a&)jbU-Hz_l4J+USZh{R za~waW;d9u?JK?6lQy{_4JG&|?hjdEf$n?HP8WDQoTkXAwTwng-A3k|;#c?>JlfV@7UuLZU9uvZw0WgE@?dkDr@4c}-o$+i? zj0?Y7^ujV0sBDM1;LyplI7?=%>K3OT|Mr&;x!vRIhQb8EUoQwlH$6DIe{}bq{Rvbc zeM1ExF?7My#^?E|iD&@ZtkHrfT)+JAfB87HM{W>=LucBU2WR$wL)b7hZ~pX~d(-K( z(*eO$yrNPT*wF$~k3CNkpE%mu+Z!aX8C(AL|MMa5=LSPKAVg9Cj|#l?z7@c?{vU5l z8gV@iw>R0GbyX6;QQ(@Sr0SFSzXG%TyZHV8{M#D7egH1dG?JIyY^~Z7RC_;uO*uhB zKtz(yO(HXsC^}FycgDigel z1mi_#x++bbND_{^1Py!2l|@ByCfxDVvI1}-y}0cW1D@A=`{&P|`;*U@dda3(MR5+c zZP#kcSXXIxW-8{UlU6FO5{YR^@JeBt$-N_=08JsxZ$6V5Wo4#Wl>!`dUPQIUUYOjw zd$zpU5Dw7kc73ob=&N+tdZ*?5P#CeaB}!6HuDwc_DjE%%r5YhvozHcW#mXM2fQ-aw z#fb&DZ-4uX(~w1aT!Yrg=;Ngw8kfPYsa!v}I2LzlXf6o|nKjDFX==)CKWKo+)&|0w zy^8&!zGzk~Jbb#XZ~x|O11~r3>V~`^GUkxgcS+<)*@4;O4}bHSG#&~ahB1E60{_F7 z;;YtfDiV-{B9p8~mPJ*5Hx?5SXS!GYkNQ#_z70dOA(Xt{Se^#rUtfwIl}e8<74pKM z`Sr0Kl{7yee>2%rRmbF`9Gqj?YQZY><@ux>}*U8VCms9b-bc zK+7!waR*Re{Nh(fciw;hc)|r@t^EewQ&)_jE@89Rr7vN3aU8ogY^JmkifO;?04 zYTj-DLDzBvG2=%J-P5PP|Lgbv>|P_3-~yC!tHpV`s*ytBd%|$A<7~ z(u-~0-Z17`q%i_d1NHc?fB7drI&SLLpfSDsP8A>b0wWpomsGJq;;wI;>#@k#fh(J(ZcN^1>kW(TsGH|eg(^ARkQor|L_KX0s_F~KnYBB2ujUb zXEutn1+dkTy3c?8==AyH)QxDPLwFP&v)#z`^rg4)IZ${MS5^M}`!_*`qTKVIylT zKlyhb&6o00(l{hXXTxLchLtkitOa-t9RL=komNNB*uhT%Ro4?AElAHI0>`IqNQ znfJ~@FtT0Oa2U5DonDm(-xvtP+4&*=m!ITY*2@%>^^svLG!0p>&~wI~{o{vc7Z-;6 zj#M_OGjBB09jvqV^WTemyRk0@Bj*S96i}Wo##n|qR$}uO)Cq%-?m zg%kH=x*J!}THi$vRR!mNdx^ek7*$5%LU5L+!RScXYbZ?5^T)sb^^5Dp0w*vFKuRcanm5&~amkD^^km6{{RlL0T)i0l2U(E#qhf4VLKha@nEmVK-DsMWK;rc4q zFMqkvN|VrZD1!}tLErq^^H2WxY_V7p9O@>k+wJ< z8DY&~@q)cSXrL@~alsuAe@QP)*=}eM2TH-Vacn zfArNQGHw)u3wn0N8Cx9yX#wz=M32W?rBYo$yI5JDBbL{ ze|~Vf(C|&rd)OdW3@an1GF(f=zJ5qY@aR`Ku(0YG2P?tYAOh8+fB5pnd^4IZYzDx+ zR62LM8@Fp={S+3zc##cWr(iTa`}>bxUdZGA#8o^a6;w*K(P9v4PL?O#AxTrmgr?U;X{F3_X<>d@@Lct@`rs z|I^dUg-ltw;@jlzgtc^AYUs%4ubU^+W=MGO3oA&2_?vdK^PgP&=f8d$#NUV$M|x(} zS_-Vik~J>i*7NFc_0P|wr%lgLEclfzt{(l(-#lN~^P@0FAA9m^q|ybsD)T)NUWu2# z8uZbJx9YGr76g(gIp42eKK|!lU3A#JuGcLsT_e-srg+7&8Gv*oFhc)y1uM?@c<9Iza!F zJLpP37uQ=cvLQot%g@lkHlr_#>}R6Ku5P~i=mQa+58}2C@jKC$u%#OPFu#8Q*B}4( z0l$>e<`d4F`bcjww3`ITK*W2vrQcGYJ$AC@SO7L#pH24nCh(nqGZD`~h>Zv@u<&d? z>Qsi$=ToSv%g=xF`{!NNDQ`-3bm31pa8$8@1uJhE2JqJn!t%TXy2@ryH__bv%wZ|Xe&&PLA70Jwjgf_bpD16W)_ z2hGWkKRBo>)?LjGBn0c=fsiE88g$xCesL*)Gpn@eaR27+|ZGiAgJDQ?^BG$oL`$k;qP`jc3jGw*KD_@FYVo z>n_k(0>$utf-UP6M7mcbOsj}8G7qRHx4!?czR}7AJ9V{Ck}^{#OVl<+)g|#+oge8} z`o{nB*78+p{ljg5A#xQZ(OJY|46;+aVO2_RTL7S$-TT3}_Z!C3lZpnH12ak#; zBD@aj)lvV-ybe}{8)*!$t1zQ*sz(*5v6 zv6vXMbbG51Nn?pb{N~Sp>|E~QO|#foJ^C?nZ!f(!fNxNc8aNcxyWjuutyTxMR3Sq% ziwz_-Br9x7g<5=KyZ`E*62`}vW^q~Zyj9u(#t0uB4TXmlVC^@5dZ*?#3Of>jxDb{X zM`EV(x0JNK5O2Y^YxeqIwj@Tv{SX2|9|~_$^ALlL5M7w-{+rR!kk_Al_pe^B)v=ky zVr8cgMSQY%IXE!3Cl6wi2=k`sjMYDVUnx&?UP&t5_X?Y%(lFk6@GC-M0f_qDfBQyb zNvkdB$cUL|ULQtN78miTUS(%c?ft7mZ3cA)MxVV|_0Bry-Ab!QO9p^*&JV|eU2jJ& zh~U=G@5zgyohwJR>7w#fU(y*)pd)Dj4+T(O@7+7!&&rf{lS>W;XB`obxDe5<9O}xe z?tJfEesUy!t$Jd+$s8hRFeL+v4cn7z&FFltv4dq2;D?sMtGy(u{bjXZ+@n$%Du7 zxXd@l2A|sNpS2T4b@ZdR_$9Nd4V8X;hb*@{k$;j7tWO!`t;B5lvpdE}4VkZ!L+|>l zpea==AGBqSGe)fyA#CweC;(0K+F$;7YU7f06;+KXO-YJSUS~SXyXjnAG>z|?2KL$q zlVNkcDMc}_j53Ncw9;Z2OqC{@rr!G5cV|lG)rMzWSRw_3xvoxsm%VUiu5y4#Hr)L1 z$P7NFm{EkotBh2S?+-mni4LX=G!;O*{l*)+YX17U{U86U+)RF`=j4J4xBLdywlhhgI6m9I17<8r?fhRIYflthN-RSu(@RAgI!j2+{Uc-0ddd5AeW?B5q|??jn_Lr z{_W$QX@`Cr7s7)V9^W54VxYmQJ;@dJ#Z%U`C-42}Udw@tTw={XhNf$TuUH4%$C5+c zQHtzGqJNQ2#m0I4d;fm%%CBl1I)Sz{Xk`S$UH)7tv?^fJ!*BoS_LOn^42r9h2q?Rz zJQ&0!v7AVUkX>Q4{mCcMyu#MIzj{32l}47d212+kpHvp@N%oV=%FQ3~0RRr)|KaV{ zi<&gps{U1BO6GTQk*KK{md_0<4hSQYcWyuLge1KNG+xWyyPLS$ZWN&$Ep`ocd-vzx z+!Fj$lV`F8@KWikM#21zT`$X}Hr1L~DUH3GRn_6^pI%9`Sd@ST;dB!&6>eXN?4CDM z3=@E6=e-}lK2cYTy4=^+lU~yrzKnE3wI$sF=?T$jh1bAX^NnASt5-I)Ok{?%}N}?cLeKd)?{I2FHoasKsrb-t=Wvg zS4!RH2e$Xl10MU(=RuHshZQRgs2kx5E`To!D`Y0=ZR8>q@=D*7JErF|y zAA$DvtkIHb9a7F6H{W~o;d0IZollKH#tQo?t{WG!V8alOdRz#xwu3u=`TZ>n3l;ZE z)Fj7xXgY@U(87OGw~0^$sPFvw?jIgsEU4*pyfrA1o=Wd@RL7le>Fp(Nn1adpRfVY% zShe%+&)?#nGgfl80LCB@J&*(}K*AP6G8szoAcBeA&7xwL=JTruAOGR;1-S-|<-Kaw z8k9hdjiDy>?x{>1UMb{A9F)~NfAOO|Wt2n^4IriwvW%IdB3zhSHDnE>P2-;Nc@pog zf$8+{&PPwbJijbIJba~8dbl3E8GQ<1=P!P|EfQd1Gh(DR0g8q%Z9={pW47|wBLiS^ z3=Nx|>>qu+{YiT9S87D(DVRc`)5Cy3OIP$Z-ne>o2C8+QK8Do!Gqvy z`!L5y{A}a??%mxFJCuypmK(5Gqg%2vFEn4_5slDY%76d-}1Ug zU+fK1Sb|0nu4*{i*+2T{Pp|ZShN|@XOpJ~z1?Zjt@OT!F%$?xW;(qAc@BjIZ>#!2B zVZ~+z^vD8zB%zhY3~f)Q2!zF>dh6EiZuj6q<1qS-ZPddfzw&Cf=&>~2P%X}PXFvI~ zJ(X7>fGf^@cZ4)2Mh829c_OGaJ=}1htA1&>zB&ERe>^jnqy;P|gG-S_nk@iC)Fe?d zy2zbUxvo$H%zpCcdo&A!5u>F|+A>YsUN}se+7&-A3~Ea1KuT9t05&~pyQFB&159Nk zDeJn$(|`JhCv)f4EVgN_QdG}?@~Wpv3|8Pyt-$@7l9hL~fqDN!&tl{v7-9J9LD7@KlT;pGMn|9rY`>0l4XYwC_ z?H~R0z|nmJicx@XIyEY+9-F_!Ux0I9Uv#7Tmgxqnsy+Pa?%#ec@7|Gil&n`Sy)mo;jgKBMc7Zdh3KCUu-gaKtLj;R%&Z&kB zVcL4{$467O6-bcN>IFt^w(%@Gi7fOs45ixo)1M!NAW8(?{-G+;tNB~kfxgW-hMs1m zOWA3=_pSGDa}z3=e&2+u&6oDo$Oe)6npRHV|LH!Fjp*GR2i)^uXuDd}94Pc!M@+y~ypme=6`7Vm5pWR&E+(-_`UvU|RJHbcRKt5S7% zom5(NuT;0O{i0XeoYnvV?YF+O6=J|{@vT$(TR=+!?WKiM;-McM_@b4PBQf7^6RK+K z+o$t~OkV#{@TzNtFtzJss!1D^{-AE({?S2Uo5*Kb6h`U@?|^jN!vpYA6PX+8!|%Pp zjcw~FW374nip^|ZA8_yI_wCVaxK3_g6($Xmfj0gvEJXSBELpA-rp9Yw|7!1i@BDOO z@A$}_*Lrc7luQ!622n9M48ZZ9y)6>+2k9@8h4I|57;VkQ7QT}8vPxX5LYiV?ju>$K z=+T+(^v#z~zcj}V*)SRZd^lR#F&%u%rsTgRRMp|1eM@DY^nUVjOnTLtp99Pn$Z*)e z;q{K;n|Kp)#t+TTyD!g9J(H!hX;v$iQ6L-;IbKzPx`xA_f4~!8Q7zUMg_+*LPd^t1 zk+?J$zQG#)cmU8IeeYXS)34fwAp=aZ!!?$A)GSIx>0tcClg-J`KG@=U844C44rv!+ z8ott48UupE1bigI8X7=7Ir-pLYlseU)lNegHkxgAEC>(ZnNTKzlv7n3JA)GDQyxx$xOdLc@;uYXfr2cm`vf9{#x+KN__MuYI6!f|2J?tk}t+{2FE zR_3939yp!Hp#Ow$93yQ|wo3@~0L|VHKG=zI%T*z~Iu6r3HGRX4R3|Wvx~X@+^FtoN zfXgtML3zSy%?Ts4x88dvYEF3NB2FDS8{cq&X0rY6_mA2H z6l`7eSs&)45f2beP4<~UTRb!Sk03a+qc=|mq1q<+a6S5Hxf4R?Z@kI&+wY6SW<~Eq z;foN_M@i_Jy{+g}GvCn3phKWTgy_vCcyC1iB02uV8`Z3{LsD(+KLF^v+D&y^tQrUuue(E}nw^M;k;O=}r5u$6hKZwL33XLvyfyYbz;;$IH4|Bh8aF zj!}#F5u1ndJFO)by{UKJ`0?8^vFIA!7rag#^RoBBIT-A>SZ?3_>ei*WMJrIbr~P=2 zs~NWFu^=4y2&AKAH62!tBkP;0$aWqv<-s&fbdJ=uAL9|?86g9H=<#Q!7)4w zi{;_LbartAd}8_&p|MS$Jpj~u?|pDbTbb|};gREywIeL`nuR{9pe{^`F%gutM^#gf z9@a~w?zV4DC-Ue&BRHz)*Hu^CRp7>!p`7B)5}-c#?vL+C_S-wSa&{#gnEW341_;T` z9H@5aC+tbSg2&LIeGNMq6_#w$HKf#=9nLc(0c?Nw1D+Wec^_vC;Lu+590Jy6Kv1Ue z4GDmH2XP9mjTwI8MEVl2bAPrRyjqz{K1hQJm|)g>g98%Zbd9^q8~*6p3QX0ApTnNs=Bc&=4p86Md%n3mh+6cI>2yT$3V*IUf# zk|;txHU%VP!1OoNEzREJ^%NMyRMprH^}&00n}p8U2jP4WS7QKptvGB4f%@QQe{m!; zKL^-ppZys>aiUA?7r@U$Ats@NLz8|`HxgP?P$C5U#R~T*tlkMsBN@M$gb;)1MlHSGQ zR+~j)#p(E^Q}_S!$6F-sD^!Szl5ojTzhT6ytPmFK-rX&_5HB1r1s-akyKfE;4q&CV zS`Q;$DGAGvqEQ8^$=g4FM6Pg#NVj65X?4`%4F z$D`G6TBwH#+Bfb__{Wt9Up9nuS!fc2*Tjaodt?39U)+)I8$}I+LkHH~`2>9(JDi$G zSPFhtD+*5n>f7JF-MA-Wk$J6FM~~P8Wbt#FM6U*Q%K`Z z!FlYhNALM_R&Nj@g^K5REJS0tLHsDcpVU~>$-mTU*A`!`>A)f_pe)( zCXB@PtH-MWW0^O1;^rD@hDY-9IoJx#bno_UrPOb<1SJy~F-J$qD{-Sw)4cT;ces4j zzd2IcD89cT;%5VqhI(J&Y9U7f{EgCmb)7Wov4VECcW}h?g}u?S`%3u^32a>Rsm~0Y z=~Gey;<|bLzvlQG)oNqpk}et+e4X!ovjV&+^4K&@G#vCA0hrvmeYj;V+=ESWJ=er< zNQLd%+d%4;PAgQL(Y%4kNRk%R&G9>jRZqzO8ds*M!ccwVFAhWcZyNU^F=vt_`85NxfgV{h(8R3}`IYRB$-&m~ zaWi5Tq?;8VoT9kOB>ByMb4P!~zeZNXJk}zXhii0%fX}8Z@waq-i4PF%!uosx!0zqC z*JjbdGI}elGh%dMuD+xkqP&F@M*P?R?Q8KPpa7In7RU$-PU01yZ^4S%j%-mp;D4vb zNh7%Yr`c~$4jYk0yvH3nha`>w;sQfQ;c%J|V<(%F|LV2SLd7~x9^uQq6s~WNs32pW zwnOqv11+e1xU*7IsjIEyt-E_FJ6_Mg8$sfFox>qnS^Ts0^KVJ(ac@UFfvZt~#oy?) zg``;stD#@QaK1R5^xvw2KDKxEcTdDI=qMC+Mmto|9 z$m2lz?=bz&nX0X+HuLoUc7sFyUvWXMgV)Uywm*0?ej8}AW0uu~lXPDXCdIPW&`kmOt551P zUmalj+HIMSYbc2sT<;ae2SZhFzxloG=rGXliWyLYJ!Lu^fCd&Pk-?T`*h>s~#E9Jt`(PfS^*SORpCe!zHSz50* ze022D_?y*jedjwp7CaWRP?|7o|C}LBK8Yv=d9x%S40=hVylIW*1=ZG_dNvU*w9cG^ zBlk~EO$ctP9?WwHPToB!MqrJTEFgO4rTPz3;ABY|!Frgu`MG)h-b^L191+4pu-M#R zP})i9Q1$*da!l}<Uw*3 zZyF4H-mEYki)_dlu1L|_|CYSROy)(%Dl*doi=6iRqep{@fj;x4@5~7iu(FhVR#nZ; z@$rthIi_#g#idl#iUfe?jFdS7M}!l3&tIYm0z8qS$tmc#~7~-fyN}+w(=dM({lth z)ws8b(!*RoBF*f*ybe)e&ARf}?ZI33c1x}-DpG<<>aLOpH)j~JdhOA6I0=HTO624?7V8(wAcu$kVv6QbrL zic@)}_4OM%Sk>Am`pC*}(2M*qJ-)@SpeQB1tMX{K{pvipf79*Hhzf$$RNB@mzUm(Z-2n1OXOr;= zB2x}Hjrfw5l=#Bj6$=`5d;IQ6`|9r<>q+5|HNTLfyZ(v)cbqus4`sPSG+K~s+IL7z zF=+0>0}_N*Q4*(#*?oyQCnY5#gil|4XBG~>PH)k1_e49|p#oZN`mCAAL89wrZ2Ms0 zDyi-$F+Ry6vC?cZWAxS*E3CN%BcwuoN@EP0+}~SN-I@|e=aya)Jw&j>pP`ySco$iQ z#_v7QPc3|PnPZF&X1fcp>2V4;eWfKV(u~{rj}DV5SvFEKBK*rcrA_MHX-G>_RdtLY z_Cu7=ln4x$4;KO6=#<{WV7FkN5>&BVw`*-XGlGHNrTY=~j#_cx4uy+4=B~)Fmkyv9 zqzUXz!d7=fRno9J%a_H#O--T?p z$9Ks9f;%FS&M}A&xCSo&l6#~z{GJtP zt)$_zDY=RYeblLf6hga4fB)MTT@CeAR#MFf{nf>jZ>_zdBG0s_?i36#Sn)D%C54N( z**<=B*^`qc+RKUtc3lE)2hkyi4G6Oq-&|vQL;p%3D;CSTs_S6!{Ez?ma0&cg_F34@ zfmvwyIk@#S@9%pNnGrZ~&3m#f>VLXFvdqP_cHWV+@87>2V6wMX9BR=)}!*;!tOG9Hf(Z$fF10qAg8_(A@pAZ|Go9Hr>U& z`4SXLR2q}8pm&zG5AW1#02Z10%^o)aL@WS#eXXVwLm37Sz+p~uNwloNKvyO*wn3<> z$v2Oie^vr(+fthJC$Fo7)e&yu{P{%aV5C$IIax;_=% zJw##5u6&-0!z&#>3^*<<8IIGpEBYOQQ3K3o;xUWbo&4)VIl%)9;C@Fl`lpH^vEPr$ z`GT7eusR^^#VgT%dd${FezS_mZd^J}S^eeN+$fXajt=^I$%Zhj5PUYWpNK7tRr4qI@^gY1YBf#rXlH6w{qEhm(KaR8 zgY4Utp-Bgh;0uA@sbh{WWRWdpQ677F&_2B}>UMg&HCmH8N*P>A4`z=Z&XK7osJB?8MnGoG`>#VSg7nfO2AJ;^=KvM9W?Ra zZQJe1Zc`&6A~dme1)lK|KB~OKmr0> z1jdkF9-{f6>Grr$;>kJBs`g}WdxE25BAukB6&o;JNmXlCGDBvyV2iIVvt(Os-Zv+8 z-POSx2YZQ^3#F4Lk`;Kbl`t){PAiT2oWXfR%R^%){@!EQIoRI18u@&`f8p&sur0cL z7Fi%>?A(>I+-~f8X=e&)yuCg;+0%xs02+n3u)EISzgA?{28N#F@k z#14m&;X_3q*BmR;qwn5GewJ%k&U>8^J~`jx$0 zB&jNjebF+FGT_$x`@u*x<|ADHG^!pHc6Uq8_HehSeI2dbZ=IZM%^G!Tmqz2^)(9J1 z*qf_zh`q$YLi<$(|FAhX1InjyTOGXsK>9Lu6P>r!Vq|iW0wS#`{cq-|>*jhGLSpTm zs95jA)lGXIv(X&i-(P0MysiY|SgFSugrXq%h5xw{;V0ptoXw$ki16^Jr(4`BP;18& zmB~Sp^8vG8hMRa(Bj0hzOo#weQxx4yIJ6MI5X^49-UI`kHv;0pd9sR{T|5ry6;>lg zx-r;rrMj+L6qp$BhYr$U7tpf!vSz>`&y%6Zb!+iWiYSaa;6}f<`|rNd#4_E7I;_Sl z!}DYXn?)L)f8sm%qYbZ5{tby1pX$2iXQ_k=l42zy4c8#o1YMhq?g?S45}6h;tht@| z>=)TYEJp;G-Tu!01Uq+c5{XyHlT`rW#h2$!JE5` zuc~P&DHck}(1e6za~Cmd+JB*{+xE3vZCjg*h5O5h5Uw|}jo8y?q;Jf(91K+mEK1$9 zDs3d`O#QXk7TN@e*=h!kv*m33dsy|DZ~}2Vs}u_|brw3`@jl`dkxYha6dl z;JVp9cyr1Hrz`J&fT7JocT*nqG|!vEurwzVh?PuXggF5#XN;=oWoPcM#* z992^R8lOT$NVM#so}GOEcD*bLs<*!N z4mU^-Sk6@-Aas%5I^&@6;-d@6HO(0SmY3yFf@P3^7XH0yMP!5vIl?DNUm>GNb^;}8 z-S*{Z$@dL7jrgD*_&v)$rU&0RsfY2y;Sdnba>h*N6v``%J^3nqy>~;5WT`iVwazu+MYayN8=6cmr5{Wt}KyO#Fx^=F6U#Y#NWho!X*M8 zvT`63xp6nb??t8n&>YX|{9yawluKG8pP{l*28n_~wPcUJIEt8Zw8OM-_0XRhnXW}Y zH}DOvW*UK2iT)hWc9qwJ$>#4^pFJE#Z4IGeJI5;vGs4%Uw9y81Gc~7|zqyQG$zg?P zZwOAKh0!w5r~Dm%@Lc3rYHHBCgEbF!C2V(?0DRS1sS+2PyW6YFGMUZs3YH6YLpS2$ zqleVn)O0BS&`TYV6M#^i1ca55(nxDQ^9`ePyaY5MmUF7C+dD8C9mqdKXv z0ZW#8h5Gc@SD_;ruB(~7t#OzjjO1-vyvE`c`iOyTeq!=~22c2{^nsgDV=q~3J9R`FQ?KC*OeSvX%^qXsTi}b zg4l>pnynm#Mp%uo$}%}o7m}Jc@ZU4Hq-s0hAEtW`X;i`UUtT$8eDMWozNxVgH8WZL z>Ec`1L!l#LW%dZqUK|*@mo%bN3i23z-kBmAQ*s?k=pC|a4h$b11meZ7KBv8?+$#hP z{k5n505%51rH~$ht`Y)PXcPruhrSRT9~?afz+l4D%mhbQGbmV9?AS-2I}bK=n#2pM zp8xZuNY_fW3qv?DU!!i8)|*zfarmxN@X%%1LwdT*~t7Jk+t4ZWQtsNHm*}ezlH=sjM3>b$tZ?3$Pd;x4-XMns>PmO zUI*^z^Jg`?JmyrhA30CW4je$mlXKH)Oj8NBRm6Y;^OFjhVLC; z_HHC91lj^y>Ij#52U&2`i3sSg5+1C#|eD4Pv8v z4?FKIZ2`+izZO~U`B87MHw(PfpyZSAN$ z7DcPO3KEO?N5V(T`YnMld-mYmm5;3Vn%fy;tRoH_60khBB>`V|ax4@VMF|K7x{6y2 z(-kFV$t~v(6*vY|52pKt+4cRghm>}G_kBdl#gmuDXzwkC2VdoBE^p1!8mZ=GF>1#m z*NZYj^E~QIj(!w`z3QqKt9Vi^bCpM;$UII^P44brs*6VKZ&?RYD}f@hs|uJ!?snjn z7LU)CtIoHkZn=l?s}o6gXf{-?Fb)SEpn6jI9KY>9-K@Ty53r`y=p?luUhN@4tE-b})| zfgr-NbGkGe4)ut{jO~MVOF-B{y{rr}D35mocpe?$E?5^v(Ii)I>u2f@In)X2Aozp# z=1{JMfX{>d70_R0&c$G-etq$$z0=NB`s+ZIoKgZ_SkDdMIYhmlTfsOulF*C%`|2=q z#M`=PFAMX-21N(42qKlys)@lJG!#nyB}*9yPaO{aX2ykvA}$mZ`|_l=f!2dIGu0#KdPe{`B|CqsZ0d|pem!J7G^C! zMqPy$fI(MhvNv)iIOfCZw7{CMT&*p}Ub&UzWS6_nj!_b@fK~M1!8;7|CU$jt>Ea$o zU2&#hNiBr6OV)M#|8g_v7Wy=zSNvg_FF;!=(u{?|47g%qEt_n=0X=8J1&lD_*6q@d zLPJNsAmB@s>L11~o}Uw9sW_@}h4K80^$Mxr6(nkLQjPhqQBs42^*JV|Ue9yh>TPW5 z>d?CO{t4fs_?)#zT=`TBPj?oy{`78 zC_HJmU-BFQOxdTSRd7Bf^#fGx$w^M1z!b;SH9wX-~>ov%d=1CW}TS?0%i8p z)=g$-{^&_WWQo|ocueEtAvZ^T@@9@+I-XT&U~E$U_~GajHvdvMN9#i5;G~eryE7?h zQ*-J?WM;H7QusND-g&{%eI+S8rf<#Se|FxQsB?_;{KliJ>%Sm6B=;^~o?*K(S=59w ztIqrrsneckbnfDg$kd z=_Lxd-@S!Q%6Z1o3OQ_Rqz!F0=Ly_7koMux?3F!*BS4bgAjE7f?-b zSS*|nZ%I!ft7V3b34+MgFVjlqYgn)ZaUYQU`9M8+V>eIF8wrQqy9*06pjC!t%hTVz zAbi$%(Q!ksP*RnHjG7i_%`{^Wf^d%BQl(sRt2*iz53R@`;*-ckTnY(8=ZBgj&?59radxsPka(s3 zw{xet;NnNoEM8Uc84MS*s_MmWpQ$iRleWZE!ze78@i38Yxy(5$8@3`qn*~I3S6NDr z?BTwy(KfTBXGvgY!!aou0KQheScz4OPycu&!+zCM9Ym)zTv%@1U2fyVXKJn z_2?Evm=+LrCu5%!%Bf|tcVrCey(RK+%2-G>Q>eOwTX%}X3Kf=2*B?Iyyo?AF2iweB}xxL2NdvI@c6pf{b)kpSc3RsP8t# z6B=%Ih;OFy>jAO`MKSIdzq_>~(x791J9R2AP7XQJ8mpx6J7-IJz_~^;$D&*r%+(2D z_Y*BsA;TtP1UP4|zO(P{{fqs!e0D=wc8VRW2Zv?H zqU-MQe_$W%p~d3Qmsb~O)z(BJ5U|edL8yh1x&uYwWCPQuGlV~Al`%0LQ$~G0RJskB z9t5f9)RZL-UsVEKguJSa?4zpcop*lwtZt?BQB(@Sp{C!i9+osXQwUV-tABs_{gc`{ zlXl(t^GDrPwZFI5kT@Z+^fgy7Tq>>m>X{(q&WUhc^B6-?9)0-gyH<6*d&5zPAwd1c zpPgR4tOxj33W`?Rs2yY13E_RLXS26j>TD*EB zW*D#$n8+A`eRrseMuae>5Rv4JC}X3@E}~D&*yP^7Wq)&8>%7^8l(*0ZHWGk`;V|O_ z`1--Kz5Sitt;zK4V*Y%&JY`k2*Ue7$w{@*fgPIdK;a0m85Dp=*s|;5r#fDQaJzpW! zODJg@d9W?kj1cm=ceoL<4s3G#Z(sa}4(DhYf2m>o2>+sDq?N8>SBtYrD-@#ne7Wc< zsIOjjuf1j#nAtR~P&J*eO(!2;s+GU7dzvMGS;|&cZNlaehtxBS#>s#?jxzyQHh@`uQ zY4gKR|F_GbRMOm+*)z!45&nZ{4mVnM%jH58<;uG3x+Ta%LlwS+xUISmJf!%CAF&we zws=QF2i3GlRrI5SopL@JyuOMQoE=oNKfAwzw_|?vOP&*Xwppvx$4SQva;Pp9c)2Ug zayh9hW09uvlsyOb`wI+FDP=1%1GCE5_fY>O#w+*a&ooxhr7CdhYBN#i=sPAzdQgG9 zA4c}@E7_2yt~BjhjYl9Zzb0&1H7W%!CCD|6en?D$N%EY_WKeOFhiC~HeH4^C!-LMG zdLq-99&XE<{)U!_-2(fE+dG#hCKt;D%>?NQ{RlaMx$PP0*d8Lyol#GH5Py zvDl)2*w2GpAwoQkrnk*&UehjzUtDWaKVmnYu1_gMT%xz zH|DPoapIs#{Fn%puz3XWXZeqI-VG25>$T$~@lj^2{rd!?ovH=JYKwu!uf|l_TUet2 zEUZ={aj$#8WB=kOaV%iELe}*~1cg-^VwDL^A87*ty_G!D~zE0v|UnvYx8B|R6JK-e? z6S;|lp2MTPM{yFC0#2M$D;A6^kBd|nY`ItpH$0W-aL_3s6xR1SwdKI(8L5P11iz}= z7gW`3eW#t9;lZmMR5ZdkZHhQQ0^r9ER;>*naNH(Y72X^eIHkAlh#EDyf(1rf?3-Hgty5&nb+F@mv0J4-Rw=3a4lFN#(`GJC%gGw@3XV?#du0 zYLbn~$SApYII_Z5j;oUN7_3< zHl7}weHE9gJ`RNaCiV8N`NCG-%M1f7yrj@O+wgrjOn7a3xyXreN@9(EZlx^NrLJ%o z3&g7#I@Si^-EDkBk$grfxKE6a6v+6rH zpi=x*=C1H`I=vA^fb{v3F59+07>gqj{@LwwYW5OW&wZ&qmPVeKv5FwDYbOd878^SD zBw+uyxm4^~w3F0SXG9E6fpcuWA!Gt3#vXmyH|z9FvzoN42S|*K#0;w0?Fs%>xmG$J z5%%8{ajw=? zXQKekm?#@`iX8CT!QV8Z^OH;kSixR}v#$+sP`IuzUl~ROfnI+4tIMKgE|xMODP-ki zW=_qri|d;^NA5%EI^lat^c0pqY~QSm9|wKDteQ&fMuD#)+KTGaTFn-GTZ>p#$F6?$ znegY3EIDru1Kwwp3!*c`vLXm?-9zUrR*1&1Er2sKa!}!kA)b;^)^LQ90O^uJBjOw+ z1V#3k&^X#RSVqmUcA8#zu0>1M2AaGIw$gbWkzWnzOyCJMB8z`z`&sAXArQhb9{u$egU~3y?X;9C~ zrxfWv56bQZ#@d!iCZ(#X9O5eBG`%Z`OkWtUC43+KAHTj1yidmK6+$>|=qRyVu12IW zdub-yMpscRNyfSa z8IW$<%IY1zERk42MUIinryu>FpIq@wQNcaO#=xfa_+*XbN7UZkaik8%mQes-=0CFS z@_Go^LL4jR0>sS-=77Qc)Lp7X6uSQP^^%=_@tfa0774H;Hn}|fOw_{t_D1*@NhWEL zKNtSnd{wZOG8F5bXS`zSpJ3%a3NH>4@ODr%S*;4kZaK>(G+dYwLFqhx*@$CTkM1D= z1FN1rn?L{RvjO_|qG)oq>Nyh7YrwsD1 z`hd@i7Ttnv@f1K%UC)^~%NCjKo&zeR;V;tQtWHl4d7#+Dnv?ivg_D>>HQm?p(6!37C4^mq4mn#By?6Iwj02r7r+iM z_1=TuPOFRS3YvX+xf$op=kqHv*z(Eav$-%vmu$Aaf=HL&ZHW|JUUC$% z>C9Bfydo21>K~nEGCgH8Yq@K93bw{3a5C`KC%R5b!-Lu7B?la9?$kPFaB;P~rquZ5 zRkiT%4O+QKOE+vVx-ecdAzEmA&s0MlLB*5xjcJqA)nT;TNApG;-m(cf>kwy-jO}BTQigi!n=i&!31B;7 zRMS!>!Ph48;NjA7bwiTA$;@OnFU^-XP6x2&ZMYvV^d?h!DS+L2RAb99uA8b#q$bAHU6`u&1;^?aZzNp%R#wqPw=T-K7@_~J@jp^4vC9|)H)xmCnk86O;&dq&HZYQ>w^ z&5UO;Bqt4N>Bba~<}%AklQ+i3dvuJKHp>;oX#Tj~-Qwf4jZW3Fd@!#)1X@OScM6Pf zGkNfk0+ZQ}GIWR{(?S=@SQfsOzE@md+fz6lntTl-EDlN(pX$9`UY}oGEq}Ru!f%dcek^{%wrO-TvuF1H$;KH-0%zWRipDZzv%lQEU&i(23L zl-$E3VpP2nz0ac3rHDMGPSIvPLXLNVLV(Bg-AY4~%25(Ns~;5*J0O};;3PT)AF*W z;Q;WWZn7fJa?W9m7X(voYWjz)@ZXRNmb!eJ|4*!LmfMb3I!2v#$eg8zr4k0~-MtqT zt1kcdfBNpx?rR+|Zv2>%d;l-F3s0WwVYEV_9IB8*%oKd5M{1`0n@(-!*2)=?uysA2xe zSNuM-db&sK3|9|Ze*8e=oxMTw)+%$lt6uS*T{Bm56ON16e1M{o&}fjsf#m~{P(fJu zIrfCz@DjzTt!CrI!l^@t$sG}-#8>s=SDY3%2Pg6sq=;2Ld(^b}qQ3YV^vtS2oQ_L$ zB_@wN829!f4pJwrlbN~5{DO)+N0Qo+qZ2#-rh9R09axgLW-VcjKH4>@JAU^u188rn z7#t<-{pv|q%NxuyIPFNAVAU($OX~K|nhOQnTj6_X((N7a8P$kM7~8|bpuHwLu$vw#rg;_xf1M zM2>j#SN&38x}^1-U?pev6UB0QttT()dWY{-(-Hgim(^m)54+vt%8@M$#MNu80Pv9@ zTs7OP^p)#Ke|vGgm^Zl+QbxTn zou<#yR+SQ=a zv#oCy;pOrlKk63C<=nF19zL3hGM=%Qe(f=v6-hT^K)42TGj^;=+%}D@l$t_!9JJ!! zrGT>fO^20c%$Q~j#-bk`pWm`E5oT67!K=jtrOXBPyZ>~>@0}R?B97h#U9tVRUeo-h zDVh1(j7@@8TzK038(cOf#Ax|Hp4vBBF{c=-3wE+JR9oP6J8N5Y`z<$c34B%vUtj#6 z5BXuCl(Fp#Cs!kLW?EPYx>=8Q19)zOzBt|v6qnLrxGvT>I27!}0GC{BSR>3x6mi*W zI&P_yH(^X?HNV?XYI;w9x8wjWwWO`Y@I*=YnA34a7q>!%1EW!vEPr@Pp(D}?I=f*) z#6n+DlYA*lHuB!c7_gA$1bZ@jg8*w++q<8j`-jJ{T*$PRtYo!ThH&QLbE)i<79JA6 zvQFIShZ!x=J5!xt@JY;N`ms=xga;ipXXU(B+OUbWCD`7P0)%w2(@GMns>i>+Rw*h= zrRY^5%uls4M;cMSM`vvMgHA!!>{yqqME-C3>U3&GuwpVZv(}shg~auA4@u5!l0TzK z8;M#U94h`iJCv6q2qG>M_KO;eFHcc+;SdV1jSoA1yPFC*Qv?pj<0`hcy{8>Ij6n~N z>!Gvr`da^$U8<=aml1 zfC37#U=dalrk_Mcwm~bEF=4WKJ5f26Oijqnbtyftj52H$VKjx^ou?Y&SD*deH}>jk z$+h3Aoq<%+27`DgC)PQgMz)X+?G&c_#OE&46W<$1=tRtcZ&fW9trT{+SR@mT_V;Z7 zgDi~5+@T*x$I5-~ODQ0{_^58)X_?5l!`j(malKOd!l4ja>;1t4x}NO`?a^3y^M=D! ztm3;g=lmKKG4Y^kFnm7?*)92D7Gtd4>E>JwUZD(HbrFlZ zK6sUD&-J!W6)nF9|BdvDOd8^^60xj3gZpLCK;aUKsjV&UB#_0Ug6W|MJ`;-1;@R)7 zmAqHgML%_q=BQXg&X!LvOv{s5pM@jGn{oh**Baqp-tBBpe$FxNbs3+^z(;d!&3HfvLy!Vh*<1ef1 zl9d&)BwwbLbGjrDRP$0s4)+IhQX=~6loY^!&>pp`mLeqP&e`i8sEDl8?H0+9PChwY zFIWt-WpZ(uNx&kdYL3BWPIs|W4V|cg&JDJdOPN%xY*Trz6wUJ9`(nkl%)su9^GkMv zyo&rj9cXr%{)+v5$;2y_6mbkL3lhz39fk4We#%N`E(+BApXnA->`+$9I{Vmev|4Il zr(qeG#}>BgZF-@OHc;n|W0TrRZ@bDn{N*&79uM`~AN-#%(;)P_)2S#$JLx1;WKkL& z!d`@bDcj7g*k`d2o2%Z#p2Ybh1PmQZ6&PG0Jy?rgxj3w~XNtmBSyHQ|W0Ux!%S(Gc z$xNPW9=N3Ldg!CDx#TWaBC9thBJ1QN@wrr0vx^h3IKi3)v*Y@ZxX864JXm5?An9FC zZ}^xIJIwlT0do{O$F44AHNFW@lJmYd$YsS@)#`Ph8j;HBUI3=bvDiv4>2^-BCqG_z?C z)MwpAJwewDIYhl+7<BoQ3afGI-*|j*37H1?TA{9&Vo&PNR*;1?fxVEX{7McQT%zJ-I@7QEgM9VUL9&y1*{a_ zaYM8w{fVekma`yp2Nxn+ewVOmcdCgyU?ZmYUL)B2qsimPyFYjY2-g&YJ%d85sP#8i zN^_D_`9Ko}5LHWaV%7uV&~qwenWrY)jEfNbFj#+W(FIv+D{#Y;k+N2sa)<9{4vdc5 zDfJh(SnQT1AN#3snaIL;}QT&;AMpE=FS(&;}PAyuWqH;PuxJ(IJl}t;gchsSO z_?m2PKMK=CkO_xx+6eVQaGU%_DGQx(J;l<`Wfk3K`8;^tNDNhTK<n75L_Xn?2m4oAB#~~|oG~{I^?2ml_?r^%D z_+@Cxc}OVVRc$nDy{NxM6y535?73LwhJwJL<+cuTCvbEJwzws=nX7;!OmJ z2JV687QT~V$sMD|%KAENC#>5Rotzat`=9P}HQ26wp@5}JkBC+E(P)KneI@8lB#d!J zh86(UKO|BZt`)+Ag3k&q)DiK*IgWw7gQ+XBkbh%EA0g?lT(C)&jtg1oP;A$rrT2u< zfg_WIwl!CdasbOT4!le}cftV>9suHDmvZF#8{qnSaxv%cW+&hiJ>cTAPRccj!pP+N z!$@V2Q+Su62w@phDx@s)uF`viKbjt|md9UJELJdvlIUU`$nN}#mc{n z_ywQ3sHE#D^A%yv0o!(ruJHTqlo?Z)vJB$a`$^x5d~+~tO2`@u!rHdc>~GU_2$}62 z;27gkqD5yn2GWwegCumCh;AYEg#`Nrsz$)kGGV(lq(5Qmt;UD&D#2$XLRfUfW+x{7 z%7CK7G}&^|bITd1yrikV5>KQVni!*rpv7&`rfxUy^pI>KZ6KS4@M>z(s8)}9wnqd$ zV~LKJpvT4{m=Bf~$)+=Wbv$PdUXoHDYp^~fT{>j-R-JXHXz|DphMVM*)oktZT+t=P zc~9X=(Qz|YuVU5p{I36)|40xUcILIvRvsNN#X|J8Jp^vK$8_&2WrnR(*|nt7HWU{} z#Nl>#yQVhi-o9Or8)5$KQ-UKWhG}zU6f}lZ8@YN;ypERhVg)BR_$+hj#a*aFZzd`l zDcwyyJ=}I4p_NMv;Vj#-R|~FaTxW3Etw^Q5do)^3%Wqt_Dgaz83|mN%kFU|CHF}Iw z)XKzq1viBQ42IVT69?G3vn4mV)su1ya*6I1SxuSE)Zr>yesdurCH?YjKH;jGDhSK6 zuy*f@&NF|leoLIXO@MZ4u9WA6M9kQrJxbqOgxfz3l1!rfG5A1)QGAs)TDh{#@{q^b;^X|o!{u!{0l_6jZVts)&VJUiK zZqZjbWi#F!LuVii#`0#s{?hqYtf)_i7NgO#`0VQX9N*8>EzEwHQf)c|fTKWR_4wey zEl^Xawoe?N_aalYiAoab135Mbd;1a1laNP;K8%u z&6?el{`5Muut6tDya4cMBbBVB$}5QUNAl3i$8{wrkrltqr@9%URjvx+sN3u?7BF}o z^}!x(T!g;*gO{|wHwMD|DJ)?#CI8N)Dsc5NsH%>}U5Tf8MvYbQIO#S!Xul1k?a=Zx z(T>HptO#_>Q<5ra56LlPm3-Kor;&w}agW*3 zyvFzlSbk*PB2&hyDioR>?zsPHSml7c3Q*m!z8hpY7+QR$Hw8K};qGs6(JP^X`IZf)D zjQd*6;ViafnMEkU#j_yNX^KjbK*hq41uGNZWD_Acd&cI-4yB?7n`^i;iyIjV? zhYZEZw-`fS=KT|5QIl7+4`R!rEChX#TiY-kPE?rq9?#634PjUpiB?j7asRZ1Ob`;7 zCRFVf_k%D$*z?Pfsrtic!8mqODy0(39aKe(j)hoS;r zpGmb=r@LX%{;5{{mqsK&v-i*qF=R!rHPeOsoNx3JCA2MrrQVwm(c3y8w0nv9tqZ~% z2wln1b)X@)VPzL{#K$ityz0#_%J4_AAFPQZZI@22&B$`;q=qZY4MCXMj5yHkzS$sd6L` z!|aHxO76m2i?6tdvT#r)6I!bF?$5#Ag2zr2Y|zq_*TT{vma5%N#DLQt^IW6zmVZTC z^e7;1j`nFc#ho&K4_0ZTWdYX~S{#C{bDsH`6+f(%h zgswnyYsaitDI$tCh4hxmfh1LT+a>#92|Jy7h1q?bZ&sAKNoEMCRLLuGK)0p@I*bJ1 z)o~cM?ieEvD@Q5uSEj})+8hk0%kn*Do!KC>q&m-}!n0{oAI)&H?m}H3UR4yebKbEC z#Pl@7KzIZUUNwg>>=V_|2UNd)D-wYB#g1#KRLw9!7fdL`Q7be#kUZP zF~x>aN%TrEo*W;Mu(MK9%`;==ANA|P7&moT87obyLnkEUv2o0T>JIjgWtU3)gKCR} z7b5FOs;o>OUo8*jl3+c%zpK9&Ghhju?mEj|)+x$Meu!Bmkx!{^cQ6xXa%xhQ3pCE? z9&QGJ2Rl^O2d`0|_i~E496+Hf|MmuVZpK6*4nI&92lXkUCXWQ~=Jj4(zM#zZ74*(@MrK{csn2*7Z)Ncy0cSRDry>|e5a zDLYJ*C&beelHQRQciH=(P|ScuVTybPORi#$Oj+twcy{+iXM`Q#7_4R|va@*WlYPQ4 z5XR`fYSYoGQgPV?cB$eREIr47;;P`X0@xg#RYD_#WG{BCd^e<~VyVl@3gw{oI=7GA za)Y}XHj(=FvC$9J!5uM6hYR_oqw(C?g~^nL;oqoxK#%(ee&cy<6S^_(v!g!)&&26> zQ%3TN3(o4~hT04+1$z~yx6H+>zMoZw8@g>YfKD%MqB7H$ITWNP#B|&Q&2DEqm{%_q z59XE*HxjY0FTeA0xR6BEVTPVms*WXXmvD{kW*a1o){Vb_!G z*Lj$R{=vF*fI3cE1;XW}FTdW3sYHV9rsMHRK=aE2lZez zs~d8*5iADS0QK1eq_)|2G1)3NDZ^&OCTSz*pvk25iwb79-sIUkJv0p*05}&~VaUjf z)rS<8dWceagzs8%j*}FSYii`S1`_9T5q(it{Lu#As>PVpd9ONVKE{so5-C(P7O)#nq~CqNv2m0;JZps zk}c#_#{5sxDQjJlR=a_OSkbxH)19MjPx2@n0T{$En909^AJsEItAhPGB-ZJ$e&J+^ zr90%Z1#nn(_It{zz)E+C{)P(wWl!ADr)Jn0pB;NI2aI4p$PL~cB%X`};u@O$sOmsVdc#86 zr<@i^_Zf}{gAB?Z(1i)SkX}5!&v&g7G#C$=lFug)$VBIKS(5raOAj6D_&x%NfoC9% zBmwWGK)4kENz!aPVKE(AE`B|c_WvFZ=o(#YC$8|RpvUfQ={(@t!Cn-!oq9CLY@fSz z-r2C~sRTD;Z6B(jq{Q)2jwy?4!ey!kh%0akh=)vRW|7vq#<+M5(F}N||vPnh=B`JvpEeyXhARL@S{YXxrJOwbLtAF z><`OZ9mZpLbPUDfdh00QtP?d#ryhoxuqT|810g5KBwdib!b`T{GS#}_%-tBU%q2kq z&*<^cI0R!D(W|nsz7&o2dB{o_Gkp0dsw#=jI6DmqzHuz9B?s=Cxi)v;rdn)<0K7S? zZtKcs|3)LIfTDcHpjs8cn3OSnvW8%BdwAdv@5on(7pEMk>KF=FbO})xTzU3t#HoeI z+M?1>1SDtDU~7w8$JKm!YC~Bj;Z#`}1#U*R+5CBkH?L=RccK-1+8X|#2XA7kFr?(N z$jm~eTLdg(#Iw>!Q!ts@C?p+y#y>l^QmERo5uJgC^1)%v!m}vaY4!Bv-ZX`oN%HKC z9WiEAu}%ca2XNRgN?elqY*;x$CJ!!NHLc~?-I;aD3hNB{1h^XPlckS%aEQyGlG4jC zXW-;+`;8+XiRgKb5vJod%aq8(=t%`exzqtgU_L=-DtmU~{L&gPq^hdU78<#m?MVPk3j^5Zx$u;ew&^>T z0x|_mJ)*sejiJtNNTNiO6WWR%mU_c2&25=Tu&92j#o27|KpEEOmYnLUsHfmu;?4ri z!9APPz!b9r$`Q)0NDmtZUlq1AfNMG0{YvXr9$?&7&XRQ=IUtgthvZ?z*l)!$%8AGF;Qrba% zsKwN=bw$4k|EJ!!J{>l+q3(6*C^+%Yt(#9YMm*@}y-jv|B363sQs}7=4F!Ir>obc@ zf(3^R*s;?=rx*#^wM_{weEVc6DGft`Q?L^~e>R;VO=BE*lqDlAshsYqp6#XW&weGK|#k%V?O!5D8nyMutOVV;dhQrRSGx{^+e!#`g2~S6@f< zL_6!Cf`!b0uoHkVk%Ib855QX6>VO-Ue+Z4fK`4GZC|t;a=5}FiyO}0hS*ls~f$%z9 zc2?DtE0{@RKx|dDQ>7CklS?&yhXl)^4iEuT1sNr;p%t8ir#!jV*x74Hms6(%-A_=-}Hz$XI=Dt?{qnLd=!E6wd4fq>PnwZI5x`MaNZI zbjQX|B$V_2E^6(`(b-CqofQsxb82}{N*&)L9hd9KFx%oAJ7FS>SuK+Mrl}J#`^+}a zjdd~Hmx<#l_qqNpP%h^xW&~9HD6iK#7c>^#J(9D^rh98U9|OSodbe^mgsR!zF1>9u z1z|mSQ}?FpV3GwF#9L{>DfE*%N>ocKEnfT+ObzhN6~a(8zUp6cyG(&81lEy8sbJW8 zvd4o86SLJpxz;%C)o}jB!f~`yko6+o0jV>Gq7V>P-`!$rMLK((QyoZbU&!I$6(0B} z&w>rdkz(QOfCISq<>={f;EOXzojT6^9tua!QAZB+(LTQS-mZGTZr*d+ z0BeF<>4WfN4;TQeNi4 zU|wcECA=wJ`?DF%m0`o6w%?}>;|G#_H5W#*hiT$~WlfYiz!ZjFRaj8?Rdz8wDDcVg z;vpx(blnBk^h%oG4<0a?+J8b)p4NM@8xZ<=a(`N}iib|X+$dWW;{b+H?;PtZ@w5?Z z1hJKNqt>KgI<)>1#FTQ)^dF%GM+~KUVCKLV^qGM_V*_g3RsDv_mQ~m4z>v>O`s$`s zc_g>MD0a+*6umYOqtvZA%1=qp%9a&w&5&^Puii1IS@YGe?21q)%yQWLl?zWaJL2M?=Ob>e-#ZypLfbsAY4y)ku;>jax-wBkk zYNUU`pInH?=LGf>(hXDAQt~Cdoy4C&5@@Kp8FwlKsOIOkX-&?w;zNgq%35!~)~h)W zW@lfXFAekawNCuSfp?!uoDi~9(MIATQ*@|?4^}He)gbRgt{9;64=f=Ju{RXtb<9DH?)r2iykx1#F#T`lbkR66A6^KFm9ay9SlzR&pwYPZCK+MU z@vn7X1FFU2U;gfeFyaNJ`zj5!5L1NQ7lM=^rc+0__6~O-jlz;Z8^zY{OIF_%S8lTI zTwftvv1Ti1Eg1sj+&1HQbkL#QkHKV-^M}>-Telq7N-0fobK$b8>#4#U{a?Rg)5oJg z^g{1{m41)$4kM#cR}A%yN3+OH%PQF41K_6=XIF-Px7+cVmD}zjWN7UG4o<`?-SvZ) zU%mIn9(Q%c{EkC+ad~l3&u)2<3K?+$^emqFvj7%yc~5psL!^TASyd6cMV&mc?URYP z6zl5BrcYLBqk=OZWS{M2P@4d7xGdST>lcsSxxLfa73{b@VR?P}>C^Li?@v7!H3z~$ z<08RN;Ax57QbG?COJ@M$4k2-vRnvEVbtx`wScm{}UYdPWCD>)|=zcqv1h7inrML1h zQ-5LUs`Kj?58izJcs5ZlqeCoi9#&)M{yw><125Jom+%pn^a<_BTxgziIz zFN!WhIGkgV&^ySE1XfTy+-XEqgNXpI>OJoEnFy+Md(WwbX6e-jCIM_uLrmq^@{CwI z)-BJ!`rWO2_l~w3)?J@nRaXxmy*NK-+}Ct@s(s`n2y*exaTNip|H^;LGbqb`^oJ0~ zR)Ma3$Dl=<$}i|@RoK$>B@@E_P+9fS%v6%rk)tz@d7?0x?0&Xvy9THvn6g0v~Q`0nQ93o?C{YleoC3J6dk$@j2Dd`Jp z8(dR{K81u8yq0oo~{UN&B0g)*Nf9HKW#6smR&Vv7jr{;FHqj}K#BbZRYz~y za?4PMZ1W+A4?aI;Y}PEHVi$8JYyi@NIc#t>$be-py>=WAHWvDt3Z?XwjK;z#TZ26^)<0Pg(k7jrp*{WL(YZXy0Aly8Dt7ts3!ZpxKoRf_`49!IB#d?4#e=Ve<1Cva z8ZQKZar~e1puApFrR7Y4nGjH;Wn$>oKdd0-C`ugVXIBqCzkTPHiY%zOxqrbX6X@8* zi^pHK--^T~(cS}q6bg5YKKr$o=MUz<@1+8JYl9bXKg2@mbkIZ6)@#X<^eB?M#QEsK zZ^7@*#=wn2n7(0KJvskk|MhR2)KGP-hWYcC7uB7k>lZIS`)a0Eoh`Z_9rew-wgey?c&&D~xw<@k^5rd_8ghC( zefG&^GrRce(ZkDU-K4t11J6UlJF<4X;QdNOZFKU~b=NOG{9-9=l-B8vC!!5>I0B5_ z1+{eZRoSAoSdysH^~U-J3u}+J*s{L-`~g%@@7!ISox=hA_VRMMT*5U=r+J8uDDzz@ z*oH`nwU`M8eEs~BFBS`aOC_s}zQ-!=E3J>4Nb8Y}NN@uV8|XZoW#ca_En3dTgp32j z!+p`ZtGSBul6A0CKYO}l+$P+?o_^yLOJ@Pad$|zj_e3%DRbR<|=a-K^`trq4JV6!h9mwwd8X0B&*gC*NK$pqRsk z_+Zo)El*$p?l%$0h71+zTlZ@W9QY@36yr*_{d6LHZa z<)F=v{WuSeE`R`M*DX#Te)i>~XLFv+P`|G_x?!;0n@}@e27#FaxM$4*`zplHN5x;w zrwq%>K1|~8r0(x!0yMzgLrkZ$eUswUj+IAH*s|v$YGJ2g%d<~^|M`on#j+C<(A-s` zZ3E3Bfx>G5^9VfHniun{M+;i*aK*rhFzKCJqjwuYRV!Rc{j;|pmZ617M3VP zaP&5khB#gpFFySJr>EBvx(bq3TAb|hQR$I`v{gU=W!Sf`%P;@%=@&1qmdkk9lyc>0C%&72Gs?&%nM0esQmTyzne&6Q z?UgYC^?uS`2kpgG9W@n3#>Ta;&KAoLFJAr$7t~Ci%5HJ`;FAv@KEGOY&cyTtq}!b= z?N;0+nynXudrtItQ6`+x4!BZ73rvXlQ~L0A%KqfavuE(aM23gTJA$MZW>kfIygXZ0 z-A6B;e^ZdL?~9vDr^{D#noaTJryz88G7p?-X}k1qoZtq=X&c zGm5ogMfAqplBuV7%q&Z9=HIts2Ir~%p~Nz#2RVDmZQBq3=6CPDe}5aQ`uhCk<1asX ze0p`I@=-|0dCP&4bl7~eK`1*WI~Z!+KqcxIy+#{p7XC^xI`{Y^fO!r=FfrD&CeN%6 z8Qii?uV?3+)^?|7pa1c#!&$}7UOfNm`FzR4ZKUoL+cow*npvNh4UB3xl#vbNC`vsF zw_h*#)fQpk3z|3*MMFktf6V`#W~uhNlLrEkH|U>C2<@1@KKVZM}{uhOZvFb-hdXY6@0c`hhO(3nC>;g;i*X) zmQQu29X6kfl>O4N*Blvz3ji7ub{iv!t*Rk8hd=>?60FUVMTbUqmG~t6pY(k+B^*;P z+H9f@+eu-Q+u4>%(oX#CPHieBR&kG54qvS9SRus}sH&~w36Fgd6>Afmw1yIVu~%!! zO8vr^ughivy6&#Lb!1!<-9GVh+vNLfE-y{uJ7uIYD3fYiAKnpuev(b&jL~EJ>4b-` zUR~+S-i?mNdsc$}3>BQ2EZnB>BsaHJd~Q~8N%fLzx;W3R&aIM$@3gHXH4%GjMo7r| zkt=TK7{PI4#ln__x{NI?GXZG2@L-bdJK4lOP|sYSqH5@l?GS-}pq*^BmvT1z_j(#r zgV$87kQHFic^15(CEB}=wiPTc({`*rD@8PX=>}|_KDw(Df`(?nQdVgu4iVxio;Ojk zf;?mN`~smp&r30mJ6#!oi*Y4aL(S@dJl4JGQ<->)2m95vw{%d!+2zUmd6V1W7{8YjpsFKciFcMtj1OT7 zjmMmnhW(DGelJE(3LCcUr$vHg#NjKLw-w0Dd0}=>8MRW@guxO1gHbxQF=-JfGfa|> zsF>hexT5fM^(44nW@x=;eEfmGh>{%r1K~B7R~CHMUxVwJ9(Xh19bP>K_PpP8l)ZtZ zt5vW;Km)NKpt>^hH`H6eWV(tCK{y<`vRMTrt0H*v3^ z*cE;W3(af^qd?dMOKd`l&NO%Qt`dsy&!noduDY-io739#;9k>O-@pTfOudssI8pN)Wf-Ks7MA#CCl)CQqoeMN%h6%3MGicj&$ClEcrqNmG$&9}?^H`sRw%#5 zsFm0~GIMD)LNU>WVM{~!7q$wR`|;MQBiNFaqR~ixrYl-en=MQl_lVg5f_GS5`^|^;>;- zH1+Z~U|A^Km;MquV$OIWsH(}tgf_^_$W+>;+fD?l5<*jUDl%YINiC|CiPT~{j$)< zH>e~R!u+^AI}h9#$)57;k|F5aR|#R|7xSEx_EFo;QUedBG9m>ap($JHaU`vP*902o<~V#32^5Z zSSl-+3|#wmP&aH0!$+?`y8U)WP5dc-nZOV;i6c_5(lL$Wh5V{Pm4n=1OOf=V=w0P1^ETmONm zAAz--&@x2=smEyj*D#+bn$CHSVc%F8VPmlovMGs(F3d-df#-o4&FG3rUC})+RC5Rk zgDh&~1oR2ETCGbJkp!fN<+Ssle`O=U)zm^#)(RXL#v;+Km7u6uq3OPY?lLIWWB^A7 zAu#uGZE^|c_hxxK&w$h`7<%9Me^1U1OgBx-FUwNG{~#WWHbw>_uSBAI`IlGQCrgRa zopm(hLe$d+ohyp}M5;)C`6dU2YCk>#?w+SEho{V5J<}gfzj)1jo@}>F9w<2kfenz) zdn>w5cdI-5^|0VF%6O4-ze%CqWl&9GlihxCjY{R{><6hyp*|we6-a#j;rF+-P&M7H z`E_U!F095Zqt!`pQ;&`eRbJ1bWawdg1{jY4Re2D4hexRgft@dw;tE`#3{XD%iIZ&sOie13?)ycpz@mfXdI7pjZO^2c`uDkY zd;RN7zXzsu5)0GYZnbSM;FrMHI(jmorZ-|uAkoZu8r?K2UdNuFJG3N z!((<0)#bH$QqTBZA?l)G1ZK1S)wV!A+26w-EVKi^wHp$j2XW%dm-`x0+6y2EIVBI7 zn@g|G<+?IDhx+oP`#W;?1>|9tG%W=T}~@{C)H6vaa|7hj#e7K~&F_GZOsz7E%4 zNxoi)!*Zu}!ZBJ*r{3m7)A!mnXzIF2Qoc$ZJAGw~*6Q<%rb2ZTcQW47O1QlZkc!bM zbtf=TK(ID)^zzF~dnyaK(zUt{vAn?9!CiiCGbf@0U7K9e^&%JRJ*RE3q!&* z9WzxH8oxu0u_>-!jt=zAme*P53`CpZtXm?EGbHwzZpM zhrR*%PBKEk%RdUeRZG8424a%=SEH&?lYmt(yH=Z@w}px?LF^8z>8<9Wl-MJ=EL`xu zQ(e~vgK4`&FNEv{q;sD+YD2AiV^Cb}(C^1xksX{12#PL9US9JUTr*d&Rl6?vW~PzF zT&*8pp2>GJ%w2uJA`xYlssjI~W-k}U@2(X%C5o}VuPCqHTB4P=h!Ax(4WO@{sv&8TPT5T# zs%=F~fx%8myWsKW%f~3q9gyD_&sd6|liv`08C?Ee`eTY1Bk}+EG!&gh9Js2kZF;Q9 zwz&5l`x|I-YH+}VCd3_n&1;4U!hrBmLzc6U9?K;-4VJy!+ij1?Trik6IjxGp^^;(L zc*XV6M~kN4yDLy$d~A%LQZ)&h1yHxf>Mggu2p*RZo*bH}3m24T*8WBCjyFj-Lq({x z#4jyFw$c=j+Rt!fhi95N6vcNexsJ>WNnzsPH0L#NS;$ng4t9e0?|d;UBKNw3=co3r zOsbmD+DPoxv`TPIv{Tz%6(J=mcqui#P91SOO8tU`+oG}9m0^qvfKgKzrv|Dh-b9dR znSu^ut0VTIeOz{RlD&f4UV8yK0gKL73)Sep;G4!di!#+w2ZW6Z#w2KTr<1zzr%k;~ z2P*nA%c+c)z&=13-+O`UYB}Z+QnQ0I5zIlLuU#VK^%!WTu{_|&-2YlUv@oCtL+Y&( z75J3rUrL;#j(W;@&IdaBBmrD^S9as_V1xh}K@A_9f%_{6tyQj_CH$?u54w zl&4OzY2_ygSye(xoR;|$tRsy)Qv8T}F5$HJ92G#?j1a}C4qt4#y=ZLjMig9RP z#Q1_0%hFeWhs|cJ-a=xXERrNbRqd%O+VhLpV$bLD@^9WDR>556V17WbmSp4F2k-!@ ztJfp8!vYV7yX?e`W?>_`w{62%Z?-2#+~uIjsY89t9aT=2numb}-leB>f4ovb`egbM zOB5yBN)gsV787{}h&3nt5=4AMIO}kqP$$N41uKQFSlhCrkoY3Dlxp3Wgjir1ik)3Z zUnb9fMola(Ce8Gj5z~_qM>hbhIrMDXk@qJ_e-}?Wu}~r?yEGF1;CM|3tG77Xuu9S>X zNa^w{V7F1BD`2Zg3~aU}TvEH*7r@!`7qt|86~;y-wU9(4c9u%-BT5b77#P|T8yGDD z+w4$D&ZX9zuYwEUUTzQpa{!G4T94QUX1Y-b%k9AP+IYf}J6%NE^|3~^H@!kuZ$L|x z8%#-oy!iN>U%ikES6{Rf8R*R0xG2#(!9h)ioTX*WAX+Hh~Y4{nQ&%{y3-$Qb!8 z3}%T@$Q=obV_vAX6uRpzoVYB)zWuVleWlYR0NV93m7#NOK>Qu8SKP%P7BxwglbA$^ zL<_8yU*sYX*6nXzVz0;IPRJ!xRtrEyt|C}VR%vmzU1-Ln0^w?c3M1|*EFrWP#_Hx| z*EwNHPF5}qW3#>IE@7|bs3*H*mYMA7@|j4IW%ostt_Hp+L6_G$Rb?%wqI&3V zzuVxo)c-_82P4f~@_Py~3VX-i=9LXicEnu_&9*_wX9GcNlA48qtbV{Pd{qq-1fN73 z%8T7lkYU53A(^?2ceOHruAmNq&5z!RlCw)BDzf(NAM7V^CS-1w0Rxv8f(Gh6Z}wCB z=3dTrp`c?`b>0cSsi7xLS$=4NBkn4JMEVIdRy~83UtDSy5_v@uj$(-q_PE2W%#jCN zqq_KBGmXLSi_?7)kZ-7e3XbY9TR@8``d|e;q5#q}vOYb)y6L+=JeIb;(ER+zhDt*< zM+QZ()7p7cc*_vfB3)w6rYXMaQs%GK{1i(-_?2ChGuFxpk``NeFB_Jal!$;QX56!M z1>GyM{gSnCu|?Ix7;M24+UWQPJuul#6yY)ZG08Q}nyF7{=jwf+#fhEoeQ#GTYK-Yo zgPGn;oW)5Lu{=+egIgNjPDfM@)SnfZhwAR#uXutw*(skLGNzNoRAU)%$v%JqOw4UM zP;r&Z&_A>pun=N5r>N;hiA5l0=UTtE<@wB|D4p7sth)2(|M8LK!dgrUkxJ}o z#jDifgr$ahI+3W%X+Z?f+}NKJX)}jMXH-aUaG;^8up=OBOx0r z35OL6E{^^A7ZMI?X8^$N{P4cA$y>9Cy9oB1U28GO&fRBL1Ym}&9DK8h0TatXj3oR4I3705L4un5iOLiSO1Sk5(jjB@>pKoYm(n2U5q0?Br*6WK#!m@uZy3hGhbqeeY8) zW;u21Z{5ktu832?DiYDWz4(tWKo~p3N-MfRPQlG0SORTeS~sl}-^DLA)SPO|FJ!lw zK1`?R3nkAk{je;`dF{3~HV3-aUU6x;LtRZ3XOHl&24R(VphjPN9Ai%i`F~sQ-*(^= z;yjvBQWWNo-hAt~$}bM=$@BhuT+lJA9wP#nS?Jg??sf@^?Up`yj*_!`od4!lSWIqZ+H#b~CEs1Pg^b?a9SLQxuaCTDO8IQ(!jg zx>1oOYhw3auj70&h|*fzmCRu4J0H(E9R;*Oy8H5y*9a0jN|$ldm(XU-TQC1p$8lK9 z6a|;K0tr@BWrzZ|f;C225lfjNxqdjj4hz>CHnz^b;a@ zUGwedzZdM=XBw^`jG-X+HOE-_P{`no1h6L0A;)wKRtj$|$>$X&O_gX3F!$UNq~A1>%Dvei}5c_P%>2(+7gwC=A$}ulujx zvrLwsF{ozWfBskiCW=E2)*-0z^k+t%fGNLXmYW+5#YJKhMb^L<6ROb%V`kMPF*}#n z`z4-Co5N62*x(ofeKj<6v=IUhq7(wRcU24^R*~$>#|?`b!WC=Y{^CPq6o#tX`|g%7 zR^T2(OXS>HVZm3RfQvw|v z0mI!`+swAPfA8}~#TdjE%6fTd*eT5IP&o1I{+ZqG0mMR&@Xro;G+++SMUXJ+EBbt73U{zJU6Hg#~5D$|WUl9TC#mhtdqdTtvJ0{jF@n<>}T~(^m^n^!z1@t4o zPx>4)g#EqeNQ@3IFA)l4CDCSyy1V`De_SMlyVTYTaDQ*_s|XS`Lu{%ngK#|D-2cT! z-V&07Aukzo!{@eqe81)gIJA%S?5xr&DeBg~aD-&4VXH0<4vQyw!d5qL8!Ib`IVXIi zy`5;k)$e`&C<)*=P@@}>!WSJ#XaI*(3Z#n3dEz#r$H0i;+bB{iQ}BA~oJl1@hpPJO z^E***&(stxPwr-S9$ODNd|YR!0_1loCw%>I-ms|3p`PHAcxz#RTAH$iFCk-ajKWw$ zWEZ0WA=oh##=;o(=4H%aaO9vOT9maS_yd)>%$DMkwtv_q#V_%f$xh+=HxCZCZkzOu zN_x(~Go7RtSbHK;L)ZF5R^3|SNF{mis}T6B$IDvI(@MSxV!&*|7gn{~4c;)5CX{Qj zpYsM?b+Hme&{sUbBs$2kz21yS6NyT2e=rtF>Lxt642=pqHnSQfrjRo~jf+rK-rM!c|PjgZ{f7axtW z^;eb-0a$JIOaRC5*ZaX(B;6IW9SS`{F;77n0P5FwF-bx>0%kCD*v058~wq5^hy zoAb}aYiayv!PFo8+U~0g`0-y#OOim93LmaCIX36Py!qJ+gx#Taq;TvJv+$2zZ-7X2 z_{L7BbVAgPrxf77J5P*aM0!`>%mocn&+DM-geCsyor!X^wM}eHi=DrHH3x@zH%yXt z-pPZ#qb+?P?F4TLF(ATH%|G4Z*}3uh4K5R(zvQ#pu7IXFzt%}uSXEuiJOlcr!iyfE z%dvI$49B{y_UK^dd?Q`7oh)jLNTn$u+Y+4xGmvUAkKC4gvbnD!$fyE<@YZ$NL-r1V zkQY2Ok%@Qa4EV*bkM7*!2mbmy~7o*~h3Y!21b>#H*%0fXaP$nInWU#C$j zZB%zI;$JG!l3!JOe);(JxA&E$6erMAS>-**su2{rL$wqHI*@6{UBHl_d-?G2NW-jq ze#N!HXl?&_K8^OKRku8jr{E4lpN!F8144i7CkkPOcoK5A-{Bz$J_>sXjjX)L_9^bR zYgGDK*$EHudsx4{*CH})-o+RTi0Y)2H@O+=$>I4WM>njLsHNjI^b=PA(N$l5wXXvk zmoJ4ywl}~cM*321=<4v&%H#grX0CUv_p=K}wEp%ZI6Rqu5>l3;s?&Qr)T|$!9q-fh zW0)zAOI*~vuTGOrVaIy#Z2yg;M)GE54%QS2!wrMkcu`JX+j{VPA>H|iB8(+wB03{@ zvwF#WZ)Km?&t-&rlH6jImwe9h+ZQ$E8ww#S*9a|_B$2bpp5faj^aIk7aa5Q+%I&IV zaXiMNpUjDJ{o+Rbv^IPVvwPE>l+F3ns|>onO|%o}T+h%P;bq{opn049&%6@c@KInk|$aA3tF zkWHs$%=WwqT?ro?OB54JWgN>PlRo4%vhtuoNE^EfRTB&G!;kox} z)!eeOELta*1!KxV7}(Z3C!d~@qgk?F90F}?sbmyt4H}-+Siva)V60~#<`CW;LBhCuaXy=M&#Jns z8pdtMN)-`$;MTrm#wmkkP$uRIoG=p|y!Y@c9!#p;e-ZD9F<@EvwZXEqjY#SbDB)ti zU5p+KqwtDYTRWQeTj~XLAc(gg$%E-#t+`7O)ux&5?@n8OF{k1@#9sx`bNQ7_#C%cz zHhZV1rxoMIUPg{XxKHF=aVi{=sltMmAwOCSV6grA_5+^3U4hqPxgp3wKF+s;V!Y7Q z&Daopp9=Z+B}Vk9mw%i{_y7KIazB%comc za>Z%hXP!{76%vO7JlmKeu0~q@qm+TUw05w4`uvjL=_EW*q!MfwJYeTi3$9FjHEVPN*9Bz=+HnZ?P zaAEfaC&wMndji&o!>v%;4JM2TSt%kDa;+yUwMzM9dUCM1y11Axc&bJ0{VHbd4xql6 zg>Gh-dE1sqS)TZsrqOC^duozYMiR{wX^MiFGZ%j#Jxk29n!Q_F>R6vLD-W5FH0wgx ze6gXb^|TgvCWsWXt5E@%%SXdp(kIOLH{zw)Z0#<)<>Gq5|17&DzjEBm9YDUBqZ|e% z%~Nj)&Bc_|WvCWT)T6`4z)-`yDf#vJ?h&k%EB>=v!ggmt>E%A4?RCZnZK^^YE8uGP z$F^qbeqM(9;536AU^ocukM4rojx2taHZE3m9a~&nT+Qd5O3fGCJ{Yn2-Df?^xGIU( z978z1OAicdNc3|<;+FJvL%(}xapbcYl{E(^TT&O2GQ18v^Z*U%5xrP)aVf&WCN5@X zY^cEAl;@1$N?8szo6Tje+fsFOt3B2&u1}xM1H?!d?s2O~5jv_)7dH*K_xACYM$P6@ zH1ZLYKgzh>IGYtOi?T9cx-KnNw6-eJ+$?Zu_bzvCN7!S%U$NJ;c#F7cgTAdk8JNyY z9&v_hv#L5hXk2WK5ow1>7*BliZYbKgX}9){Up(cR`5^3fW53lh$!dQ=&U5{40i<*) zG>bdkxgiIZvZd*WFu}=xZJICrgIxw{+>+ZKw)UrlV_|(2f3i65VymN+TQmnY-M^-A z6@~A|nWn8lvaAb%FG5!%d4x$Yt9NFzhx~RWIh@02F*2gl!gPVCjZ6YP3L!mr6?~>! zB;XV*+C<`E8Ad?wBUJTds*ig$Vn*KC+?zYE%qN z=X}z_IDX)3sF%#>QSZ+m8MJbi4u@MQ)pSK6OEb7ov6w-nXwR0Pt%o{RXl$bN#%0Zf zi_eY_qkc!s&;$)9q3TBiwk^HOgUSDV#MpInZ(;>{JT^SOK7}X1m7b?_|ZGj?*D(oG}#< z$4iE1!qkwq{UZCcCn;e1wsDp}tn)KjqjcG?Oh6B-D2s^>L$~;Q}tYpF2 zObWAddO8pSLEHk31|4}H$?*D9ckKust{+6}059RV;i zJ$o-3o|mN(oMOE9qC384*(8#rHx9J^{TY4%3fC@fUtK? zfp&5N)=DM|aV*8Zkt|Fh;DwOali(L_0-#FE>QNhxL#KP-OWCgTsGeOR=d&Pyvt3^e zX7~X=f&`~Pq9s&uvZ0#jE$;bc$dIWdCkVCE-!)Cps~x$W%9u}sL^)2FonN|ZPtRnk z_EI}TnK2;?*61gfMEfG)_PLIkA)rKgl#)hdG-d0m>G#(w|7z<7&lf>@4bn1tS#_-V zsdQ<-rVAptV>1Uyk*L$=WQ>cyEjbwJ>?`#S^ER;QU9pMcD?(tGAVwJagx?hG*CG3& z*O!Av$T)1j=nT~uIwYD&q>G(6^sRNw+<`5I{GTOW15BmS>8t(KxCd!&``$ z6KFK6#=&5eVM+)@^61!#YJ-z7m^4bNe;KVr;O!Qlc&p>S;LmPXOrI&S`Lf-fI0uU! zCfOwYcmfu}c1P;RY{BhFeyVY1J6N)&7S5JZwJ~<))FG+CVMoUBmxx_0jMPe&fP31R z^NOAWf1j+ye#t028L2smHGfhbktz?eZo^*(DN)2F#OxNu+T}ut(?~X7PNx$BK#Q8b zNGGSpWITogKs{~Nv99C3b#f^@60M60XQ@av?cSHagzm97?`Uy-T_F(}oy{G7qW|RD22sojdw^_V?isW&wa5@)UoS%%e}zmk4TcB z$R~ixI_`%<+;9YiwG$Qd(wDEtNpz(FqM~TzY=jqe&Hv@ef(13kv2t1H%{ zy2YYnGS#=~HbPu&ZZexrGis8mSAwsVq9u25$BBxruD3ive6Ky0bF?NVyh0X>s%}LJ ze&h|~f}`Vz%dI1w^P>T?Y z0^qpMKpeofjjw_sVZGz(wxn}B8!HdN(}78bI7|ABm1Cm8aQ9eEc;qkojxjPV=FUA- zH2u<92DG!SrY+V1T2D<%23;pl=0pMtCR2QF_qcf+Uk602VGg2+P1TNA>wh>*6$WKN0}T)#E}P z7hW~((z2G4u{z9UP3O|xQ!O@?R-JHAGXbDn+gkzIzymt=p%RldIX~3-sgCvG{R_!T z09b6!K)xc8;7(1*5}>|PCSe7wk2*HVq^k1JB=5xEX=1)Bz{`K|d89%ZK{8A-1%JkR zJ{E8)eXGl_wVM?oe~ffQx>h&*goo7F9ND#c1f|ug-?<9T!4QOnLVNxTJ`w6G<~4fZ zDV)V&#=d3mXwM+gva5^?W+aa>mKnL4q!m}qgxy>! z8Ark1su&^EXhrHDwLBuMpF>vsC+VHtYsx*$9ad(tw8%>Y5G7-wg{cCd4LkUT>|QD% ziN9T~g9+t~Iw7?Iib>5WUqww&2$E!y(Gt|vb6>e< zHsqTtM_WlwYe-^GYa@^Zv0i6&`>46bLSuqCry=0gkF2zno?803qezephpKC2Ixrfo zcq=Jjf$wc2A98^om@({RQ)us%V&|Qq_tJMZsORL(f}eBcER)zkjqh5kCGu(zOY}8q zY0${BnY20y4kxavQTNs8msKi?pLdCcry722HyA$P!B|Z3Ss%))(D?|NmAQ8|0ij*kNv=WY&F>Io{XLWINtFxfhG$+%LeKrE$Iomh;R zn^kSWeRaMKZnD=JiZtIVVaz#ZW)1mr3t^Yo(;tx*p-8l(hR(gysD-@1SNauk7<+dh zssDQybyoVY7t;i9>h5R4S}=9-38Ue$DgvC4U-Vf*u*M&ABxyV8Sc>i*0Fzvg`VWRi zuPYV`9!FIpUbARc`t-f4kg|jYEgCDV!D~T_L@FXf>s-a4bB;!dPzZ(9v7|Li(;7y! zL$j3oM;`wn_*&v>8LFYZSs9#dr9^d4L_+eeqb3=gCmcK@t^ooE4V1PSYGT^x3~<~D zLXc=3Q$!^+Yp%1B6b7dLV}Y-hlgU@Nt};lsMf0-De^?FC+84H?kj`f>+)dYITZkKuaH9GT`hTVp{@+K zSe!P0EoIc;L885WSxlkbJfc|5beDqZ4vg>_dod&wNPI`c+DyY`=LpzXx3Q$vL3WJN z>4MmA0eH!aNg)e4oCN{gBS+JmH-S;Cz0!?H)hWxQoaGY$XJ7$d17e3p%cn@lV(O1N zo(QceVWxVM5k*PDnj{^?5XT`125v#pN;KXa_>yys{_3Q*?4{4`3pm4QSYqK@2;;%`C-V#hG^gSsES#%49pvuA_Ac=sAO;{R- z5&F{5e6ylqG1_i(djR6OR64CltQa|BQdJauDXg>vV|(!(@*H-ZYjiRzj#4;uA`f|h z<^~~*MMC-AtRg;GK$6gf112wYddU33UL*0XcS+BHm$fdTZS78y$uw00M*0Nw_ zJ}}CgsiyfkX2Jv@g#Vg6L!xo+OyuR@q8#a03Az3% zX^Kb4Z>T@itynNgnqv#En5u8ma7Ah5X{_ZhCTX)K!={#A0YsV6PQXIF`bIWNd@&Vo zw)|Jlf(X{~n3Tl8CyH}y;j0$$F4T%Ud9qAnk6A@uDo`n)49Dr4lCQA%g*Y*VITE79 z2V{EIN%D~%Tu~1K15sHAZuLR-PxVa5*OO%|6vV?GwBl--+ogS@muK8aR7j&_N0 zar+EUFahB(3L6Gz9BBDN6=SCeg+*gYqRoXn>H-wWgcYGykL-1r3?*BOSUd2EqS2F# zAZ;}%LPs5~OOJtwobnAc_6{l27kM|kn~Gp_Ut5nv%h(mA;X4qfXdM+f41kHb%AH%V zQAjMb|N_T7DA)lxf!#n{p!9X5kHJTnvJ@o zlNA7LGm-NousYYj77z471*Vmt(b!gHK1NU&ao}K&*m^6x+$Cj}3bEq0hPxqFjkRD_ zp{QHSvauUIvm*%EikT1k48%cLVm0s#O$hZA9&14{zYt|xb>h`PQfQ#PvSca3B3zV3 z>Uqq}Q7i^&8{|kn8s>-tDF~w^@%$i0k!Wq|kmvvUJ^*6okd10WL%b!!gJ=hBu?n@N z(bBw1@ZK~-*|}(kR*=?&*`9&q75_F^-`FgOt-CWZxM>U?t~DzOC~J^5sIAbKByY9X zr>QFDVMt3!o3BkGOpkW*T$L(2v{(p!fiF^xrMMIFNvHQxoBs8b1LubUzHWi9KuJ|$ zBWJ1h!ePS=Q^9aGL+NQTXNH0Fwl0UoAT}zoYt2%WKCtzXeL#tW+M1?Li}f#}CUNgD z4@r=s$?%!lRY>GPVjeFj8L8&N5WFgcz5^jP_%P0#?gwz#>LX%tw18{{B&is?E-D6I z0)_3hvnG^~{B zt2m4$UrNvdk*zH{&Vwr?7`a>0@?zI9mN{%#zM}kQ%q|J-MD?QeBJ4q=>2qIWv;N-A z-72+LYG52B%9YF~TszXXRxCayW{|wu*!kC|)|kNP9Pn$KiuCEH$ZME!mB3(D zgbuC{Z6BcLH~~zIQ=y|w8!JpbO3cgS?TADM{ZFH`R==n0G7@7Max)2J29!ZZCWxUe2!|GE*D?a0pMC0>XDL9$U;Im;Q zglH++nklWAWz>Ptb`DI|{7WbdPV@KW;Q)dNVbl_k$Z5&L&l*AiQl0pMhDO$={QlV2vv3UR{B)X0O z7;6ZIFzX*g?25M$gD+qjBPo*GT6s4$oT1$8dfOxHb339o7>}PCO6DfJGV&AFWyrK6 zYh?x!yGlbhkd%XPEVJ`iQLaryiV+6WXMGdafb%5-hXnT1EL1r-NMZ&`u3-SrwoHm5 zLya_L_Bud2EiaRb9GnU3E@|^Ft^Pl^KyI&#fAe(OvhX2;mtXF2f@Nmw*5O2tc4N%abZW z2vk?DIKRz@Q3--%v#7vPpELM91nFABM~T)m^&xwSn#_icA|Qq5+t2DmaXG!A2$qMGJ$P9iQz1zsj7dC zv??l8R`VGAZonD}i;it!Dse8ndN!=I62(}<9{WESaod6>snCrpSlZ$wU*u8nb>df* zm<}&5TYud~n&O+pA5GWv6Z=?+xXH)=QFI(rvJkk^Q)9twluG$@zdrT~clH>6$8<@& z%3b59R}avwLo`7HP6ng-i-;oy{2z(s@JEz3$8cmOA@^)u2ga)X($|pw6^&Gj;N)1T z96+xg6MaR}c#CJ_E;V*=rlM=WaIqtQMBOj1+R2*P6ut>PS^qznDtiBA`8&iEmAEvb z9x9!c*^*#Pfn59<*MZ^9l7N2nzB*!cYmi*mC%&AnoZ6E$#$8$J)ZKbm!IsO8o_82o z4gd;daBZB&2s9M)-ff|HlPRrh!SI-18=Xo#S+%P4tHai>BV7lEHz@ilXwelTVoQVP z+J@u?@Q*B6gy7n`|NkW1lY0YuX$+?>qu^HvW7h-9EA+t|rdNSQUz;4;EM*(MPKR!F z;X(vg>si~^y(djk^GWwd4#;c8aAn_?QgA&6w)WLq84E=i&NlrDbM$f+{px(gAH5jf zxax`uUJV&snO>c-_Ub25!5X*g@Oar$xQs~`m+sGAm3yNKswlYH9M2y@DVC)GJxr^;*7)6N0Z+ zBh^Vqbi8CJY$^|>7~%XHDigncW%^}&5&!^LG3)!U;G4IVUdgTz@QMO9m_|a~SL|OS z3A2?ArI9mr4Q$WLJT5YhwyUdOUn*>jD_PsYa9#c_j0f~D`&O(LG~Sz~0{G1r&LWl= ze_qhtE5VSac6V&{QP(+9RG-pY4SDH0e9>DY`PzzAX!XCMg+~A|M8rOV3u$7@F3XyV zht>ZGpBqxyz+MvN^;{3RU(@>FZBGC9;@Ep>INGKt?uTZx%EzR>CIc2-2;PY4|GGeg zYSEXOpAR2v7_!xu8A|=oZEt>VL`C?j&IeD0;c2S>BTi!xJgSGb%D(En6y>0dAmLYO z_@r0(7o>3?vDGQxEoC3^rPq()4B9Y7!CS>}dD=M4Zyb}ECR?#*f4W{wDLI%9*?C1U zT%TSch+YmT2^=S7a4Ckj%)GW7s{0BJhb<+9oRaktI83_!>H;->*Rt_m_oYHcfw zXJg1WPD2QO`49qZ0)@gVAcE9*G#Dn-*GUu?wfJguPJfz=f@`VZx;jUw6DXTj01E2X z1keEj8T_K5;vRUiuZBP3rH_Gj2#RtDE5BvyOd8E`s_kNb?_lp>K8LGLcI(Ua`r`6z zy;`q2Aah{a%f^FBTaXpQ6kLJfI`HZ+JmS*@0f0Ds!j0fDoxw z!O@aveewL^(|cdsKPM8T@NA2FjcwEeFB!wQ4}b+{w-%<#kEuV9wk#=Mr8xTD4_`l= z8zmZn2+_s9BarO6t7l*Q{__Wyl88DW+lt>-zU7j$Q;Wf_&pn(pf~PxIY|I&?lV(Rk zKoBrHdjC(~T{NiX&w`^#4Hk(2>FUA9zyIu6w_ZyEvTT~-{3Bs{sTeLp@T-F1;Sz>e z+gsoM;oCcU;j0S-PIXwwaisDiPZw+gke~Y7J zzy9WV*Gc=L1kCA~^n@7R(qzNSGX4;uee1vb&K%Jp zp3}EZgrtl^`wKuI2zS1@xBv4;1ae}qUY;#nL%~~ApQh*l0zhnLcmKQZ&xCNwb1veE z^JuM36G-UJe)%81=%kFiT0J1X%3@gLrBs|=i6Eoi28r(c^>L}lg1r&q8i#g>8TL3;ehOaAt)vKlX?swJ~z<`Li ze|Yq=;t~C{>B6*eanV&8=C#Ql6en-DsLh{VFP1A3qgh?gzVT)y+}rxh4eRw+_-|)Z z;cLP$irIWGB)b7urQ^(Ceh~l=Vei}XbSwGx3qTysGIa_mcq<@GZBnKSqM-d_MZZM? zu{RUqoi|#jb0}>K!yDmb>@GW7b9ro#X!-Wu=+)el50TOWeG0sKJAYyYkYB|LuStd;4njGr2hx?7_1-fw~eG;Sha8QI=*Yr+H{|aUs zHrZvTPFmKYxGFaQ0JP~s16mjIU*_t-c9dIkdrW#9rPI;=Tu$p)fr9nv+r5H^h z^rWN?JxLnbv!jYt94|Xrn_Hpqb(&qbQZB;ogI^0VqaidKwDoWO= zQk0V;o1R>jwR_#Ej!#cO!Q0gs%2C|jiasWZ>+}F1ccCuVPgfPmbZSUe)0lgXP|oBMsM2d(pdbTi1hO z8f4M03JnjZ{UyUlym%~51Q3C4mZAZ4XA{DfP8&osRk&*gt14=*usMK@KC3s~Tn@}L zBvWE3uu7{aXMXi5~#yVnD~Lon_uEU!r6g zp-g56Zy&=0sW}W{ytVpW)K)Y!P(JDLa}=av3~wTd3ksJYxD14sjA0UcaeP@%|7m^@ zPEXh*pLCl6bUk{>U@JuwyafzToCu)V@c|eFhpj(L<=%{dO90SdY&hLBAS%jObQ!;| z;WkriS|k^HV0dz&1(Lxq0ssN->Lof|2UTO7av zW@Mq zB1E%vRBgGD`@FbqLi?1|o*e+NUSD1O{vSVmcG;!8+piFY2N66ahOY;~ggZO)lh@vV zb7#H~07!^HM)l%47OEZ3iqWCn(}aXX1akfSli&Q}ewP6F6+&>bxQF0BE)1ibA0EGc zeCOSR83GEeOA#Q)u7~2@COwxlxmkZTv4mGIKKg%tk{Tng5QbB8+E9()S49kC^VUzk zxj&!JrCAW{t5?33#Xd2i^|<*Y0stZ;LcT3H0TFe-`G0%__)23qp+tg*;7O6U-LFFY z*8l0vSpx_}0xW_Zk~0WSHf}hwx+k#zYc#9B>)-v)zY(#z`pP4?ey5SL-OaXYEg|gx z__fAIBUh2sbGwn5-6%SdjCAJ0SKksjgae6h{ZHK|qc%sYIkskVy)#T4!IPfaQ(oDK z&l0bHqd|e-@B*N>sRKfeY(Rs1Un&EDQlUVC1cf+4j%nbCCjj}*&z?MufiD2PW>9Qm zI48@t!&xQ;Vw%+MF7%oksk~H3pbk_~=vB(J-71*S?Nq3@5GF#9WRR%$5B4Q53x6|{Sg45LN5?%9*st%S|ymw&|vuW z6=bGHYe`H1K)1gA<@1zBdKmcY!f+x*+YU`DV7HX6?wy|ifCM8Y5gaial2u?D&h0J? zLR4vsVIy7%K9s-t07Ch!=SCiGWJP9 z+17W-Prv%Rzxe*4&|B{#0g|Y3@alJ;|NZyAd2=Z=4I4}}Rs4`0&A?19Admbn9G%+|;`1 zh8SkW)1Itp33Mwb5EGz4`S|hg{^o-}zuTZa$UB?6zp@b9`c@)o{|6Dl<#`_RsWH5n z_Tq|<-V}LD!nMj`L;yh#|K=Be@}rYRw3dwhv+trS`y{T>JVIq+qoQHOp4YU#ca|R} zFWqzul0h*Zrr!^PTk}CR(zPxt0)lMry!qzcx0e8bAR58ugn=0ii4$fGD^`aWI(bY0 zB*|t0B3M5;efrCPTyF^YmO3q6UO8to2%Z+jb+Fddi%Q5hd$0XZZvp_IXoQ^<4*k!_ zOM=6%MliFOHG-XuB)|C8gXd2l_MM0}Iff^(G4m{X%H!$l<`c?u>%bfYdHS_gh**jl zHh&*Cf=mvJ&NxhffWG*f&oAVas%isUXZGRM9403h!&8igjdr@*p8u^pw{koITt3vDp(X)6`=_Uy>??G&S*IpR zRoCj{zxnuT-356^rmDi5ukh)k;NbyOrSn!0CRS4eUVQW;&utYtvHDWjmK!QSK;6@i ze(~kXJFPO)GgHSx)aQ=VhAet}#zAe(@_sin6MF!lP^;$-)5-cU!pHWZM0#=m*@G{> zI_uQFcMgM@;kt#%xDEOArZV`I!7!el9RUE4My$oK3Go1k>6yF>3VAxwlYjc?^!(gP z--*(7+RWFw)7`e@FaQ8P{hbV^42&$cXk*iVQp%jju+vJkdhqxE^62?RCliD|3DAXg zZX$^XcDkEZ(c0cY4*+=fcNgr|;K*W`<5|rHvnk=IAP^C(9{%cA&#u;MzJV!&X@g$h z#xTgF%_;aAf$dKpKNJ8V#$wu|o;yE1`{gg5TwSg@nKO%uACAn$@{jK2>)y(6dzr& zpUQ_HKe>{f)I~6nGY#IBx?^Oulk9X?wK+$5*2>)C@#75Fv<}8BEk-X8&OZM7f;l%T zQdwAAHP;=dYfYp@SMKawQ*jW5)06e$pMsrn$~}{&3U|5s{QlFcjwtHaVG=I=#Cm*< z!0<#{8P>EtV&o!=(?Ihy%Gmw-0+NimC|SK50088}&mX<$D24ozu~ydPbzr!7mz@dQ z9=+kLMRkT-J-(j;3yWd1;uhigM_+z%>5J?w$kuDHK*Vq}BaYObFlz#g9M=|SeG~F_ ze%PfPu_Ii4^vM@byYc?3(huCeGA+gxOE-SaCUHc^^0$wL=S+rl3|>B&VxRxZz2|Eg zJWPR*hpnu^t#{dkTN!R8<4`?bMfl*Cd|}~GJKP8+&t`h?k6%5@Z#FxrrMqnmi=t+V zHT3HyV&6W+_0OLbqc=#LOi%ye;}_>0^Js4~RrXk|u~cj(O)OQW8wmV^@r!?4BP3@5 zqZA`fEmTBt@elv<{HkxS*+LTD%3oIulr3@b z5C7%y#aeAyx#8E8j)bjLt5Uh6qg=jTKby8q;=P|cMOr=Ngc_4|{N((<{>|eg{bqtV z`XTFoJvLQTTj9x?7IEA8biDkRCrIQYBh^%Tiiy^j5B~OVpRV2fQCgx;4g40lbj4nk zP#lTyQlk8IqYpm1sRnHnjfII#l!E)K7Z3mCm*axDdm=rzN!-9VuqMvON(`J91^^;>JtYZW zr+8vhP0xNqz}T=CD5-wI`!zYPK7P6y=a+nGQdl?N*M7W>(#unTCrOCwU+Z<+{{BhK zUBwC8N?^P^zxm$XnIyA2aYfX?M67BX{hC1@6ge2Bu-{8qlOwuistK&KP0td zI~fM%Sxekg&0eftKg6p~esk|q<>`kl0DYn_8Cy*c%J3-lbl6j0+;(rysSs?3KFtpH zXZW3eHv<*Ofxf~--jBXCTNyrG%@N?@i(milsRXH`DKW~P1HJ!SChD;Il4%70v0+%v zm!O=z{^47DbawInA*quI(LV;wBG@ig0*zpT?ga^fAZY#7&wqXjLkNyQA3$(1ab6FC zhuf)uqbKV`2o`_<*xdN>hlc`4UM>z521Rm0h^!;S;1`H!eW8?6LR|mmf4PU!AsADH zTZiECPn{US+0}(ZBM!?!>5~wXpcoNQh{YR!`R<*g~M@ zd&~d(Jq~2*W5W)bN}(8EPqJj*4jxwNUXn6R6gZd=0LAR)_y5f|TD8HBfVI|?^~R)u zZ^}29002nOADK`3#{cH({_^mYjmo5kH9eEXmw zVf<7}O^!Tj79l`37$u9O1bGGOcn?4T!e9MgA9)d{v3^#oXO(~H=Dfhw(1+j&b*%{{ zdYn**gZF;$_Ks!C1T=3ozl{%@O(0lG0=WWnIxPYL{{8>WTk1rK(tivX?qA_QC=aHZ zA+C_7X6^C|f*(EoUwWdfGk{bX&pjD8#<6W`z!yCz z4yKF$9WT*w|A&A2+RPBDB0I^M@epBIeOWn66yZ02@#Eldj|j|aXZ7UM$b+>Eo&bK0 ziqy!aQ0#sG$2VK_#BJbc4%|-Qy<<@UYPc%lO?&_5u1vsmT|Khle5>*UOtE})G7=t_ zklJtlh=i}x@<4=1Ru`6r z{}xm<=JRLY{p&Y`o;Gt-jM5`v0C$!{fMYlFAcS#mA|e2ZpL{?m(0jS`&?j6UmsZ6m znGb$RM2v`t;=OIW(d=tfdTO*0h<*5cdDgk#U0t4YTVAszIm+GK|Wa zO$7)pnLnHgcY_s$D8idRyW41s*TaQzUBsrZR~g?xNAUom7y%-HeE0iBJLSE~sf2=y zridr(h-_69&Bx>J_uiX`I2q+LySauJKKRZfS(MQ6A=~{K^ zG8SFZ&O|5Sbt*BRb-Bnm{vpDE`}X_A^?b{dF`)$JV*YF`zEPlDpo?h0%GK=Sx0czG}3Dy&c?y| zsw5E(&1{;)7}}^akpD%|h~-beyFkmKW2bY^77X^dI&-gTL1Fg*QDV6H;jwLeN;RX3 zhBs+RZNf5XJoF?f+ZdXE*zUaf=AMS%JV!>t2;Lrqd~(oiOB%k@g>_vBfN$K*0V zg^yn;lCD`FJO!ms@$t$R(d^y+$!jfIYTy{w)Jz>GQ5!X@{ga-%TI*Kv+|%;M$GN>K zdjKrRb4{97TVv>58c80sfbV|iKS_iCa+JI(7_QvXe+rOlroDq}#YB(Z z|KRTK90l?jB!^i-bKE-+NFe2X1OP8Qi=$kzW^$T1>KsS_u>0fRJRAT!^=?`WkM8(3 z;&D@?jcZap9IK}!+Z*ry=x!@e@I6xOkLBrx;DICxsSbS)j3RgG*Daj3`bhBeQpJJ(XRi?51feXYaDKwWIAOQOa3o3l#00pM7&Fv>oi2sikAqpgC&P z{mmUOOB$u>3`EZIonCeH#%GtxEtX|qNj$v@hYCjsz82lR3{s90#Af&XAHOjZhQ@s9 z>++Gdugo2<#C{r*qy#3ZX;>MXV@`;XPFkgJ^^iSh=omiwcr6A6&o_aA)J ztq9rt)Dvaag9068UVq7@Cr7|upqARwT`+kf@_CC7zc_v@KSf%ni>-0z}O@sp-Z zh9jW3{TF+`e|Wz3U8mFaL5=oQiD5iWKOd~6teFa6;;aM+hy=Uu{p{@qjM|LA5zJ9S z`VaB7C~VmRK!k0+#e-nt-2$VkldIL`y-$As@Z38F&4)PqsYQKIgS9FQ=gg$RF;z&z zn;1(7fCysuFMqTzJU3Iy9brK7+#LETGl_$8+?wV!JH<;?+u(eDbo=ASU!7glPaeKh zEX&{!ZVR+hLGC>Wp3dV@I1(s)fMVx^zt{}}Rx&=U98}Eh5mezVt+Z}v zWW^YU0RTZPZ|?2Md*_|y51B?okfx6CD9^l^FM29VHWq8ZCUKh{;lN>ru2TD{U$12`RF7&cR{oB3&IwFx%IXl{+kLAkW)Y|?Zz95QGW^B-9JnupOvx)HP})#^7zCEc;6fr^E$3S?xe^P)h!^(V9c z@?_OHNYwSLwT}FRcX8btq*SP_^y&+fQrDLHVv}q z?dS%X{DxP~KlsUkryKe2%_W8py_$Wjdcl)^Mcj(=Ww3K}a>q0Q63z~PaCX_P>g?b` zb!8ksh$S&XiJ5ebK55g*?R$TE$mRkAMJmi~{&=Ven5uP=pdn5kD$j=td*ie$a!*b5 zVs`UKXYvV^*hsZ$qAC$!x~R%pn6mj15byr@u3!l1t;YQzfSWe}?*)&Cx0}D|Orf3y z9GSi+OCwyd12KE^hi9u(o?&W#WOedJt-35g@Rp9>i}Kq(-uv*~wpZA47Te1otq=xb zqFw=mO$|`#a!#3385wlMv)XGx^Y@=$U0v3i!`tN2x_WK80l=hj(Hjj;i(SO_Ti;ox z1aO#Q@07VqSV?H2v_yE25G3#muBTK>oM|H&k-q%)^VNMKtYg!Y2LJ>m!TazcGwB+& zKNRgdKRT=|leuP3(5~=KXvYIGfc#r~fhdl?_vS$zti@@nJ};x-?YY^aI`Hn#UUyTo z={%)%vCKw*Ht{Jep7HBz(Ke6wP){KdVtf00XV2F(JR=;ywOtzaQXz}pf~uHo2Jz(2 z-)TKVhW8!Qg*j}%)M)26M(+;_0t)%F=kj6#I6w6mfIENd#pAE+v_mmYrk@|qrnY$2 zesYlFuS9^OKmS&f@-aB0mJ^^qOP>(FzP-yG98v8Yzdc{#&GBQi``(Mw=aI`2`A*ZL z(HEJy~tk=>-X1@ z1f&&@I2Glofji!Kvbpio50_#<0{4NHjP9|cMVLLcoVPTqahVq}5pfF*QOs_9c(ZLB z%7=zZ4%D%EhLUge_cvEk-)N9fH0{Bkez;`o_Ct;gTq`PRGeAE2_>QvX>Is!EFkO!T zi0vES-0|$O^z{IATT8}Fnhe9E5(46^J^1eTcF`?ZP$?qwGIR!yop4RiIEER++Ikdv z#Ag2oAMWO)<)#?koQ6dW-nKUiglNRxcYe5Ub`p&0OY~q!pXoO~YBMspm#bQm_av>I zVZ`?4`|oDm2`^p65t+I1YfjkAcHaB`aod9hmzQ0e$((+|vtwq6`g_QhL*{-E0daBs z){Rl5b{%rq4ZW#aD+P$nzaaqZyz{}0cJRRRL>;c<86n0bi38BPj6pVg$7TlY#)kli z*dE<}bJ-`rH%ptL*pK}#X>DRsSIY#Oy*uB1Z6*=~90ploN|L(DQgEU_3i6-ekQOxV z%kiKPirtep?$oLVyyl^_NtchXgNI6_`XI-85kVkgyZ_dY-d!{a1t`uBepmaH8PciE zWE>)a_GaSOb03w|+BrCgAh0<+xVh|A#Pey}qS4hwnJzWL*K z)W)J)_};kEz`Yz@_@7wdvD~@y_00>3>C6M=rwd$7Cf^r56^0X6aY?J4&UfGX(Q9oX z??;b-om|9Tr-Zk7pX?t!Z@?n^IH2rAG_ElOj%Osm=IC&~IM0H7eK9d{3O7P4#PD=; z4~Sy_{SR*o#(Yg1>6Y`4O(3ivH9N=^$Tgi33gmw+f(i6+Q6fU_+?>zU)PKR^sH(TN z*^xaS8gNtVP(g~IL==bL{qgN4l#uC!p~2HDwV9OW_l$tqn_>w{cFeHQ%=R@NWK@}o zS=X2pTj*PDE^;Ix?tJ&dlLiF_@A?}EcrW<3p|=?smVNxD6hJeAh-}Hk#)M^(n?Nh#fdhJQfd6Z!Vf1Q9hY&Q&~}V8>MYoX9S2k_6D1ipZs8fxd{)ia<(6^ z&w(A4#tK|?kpP}++B{$7awDAW%;%Se+DG(Dd1uztj(HZnH6qrM4iTEy|LVs}Z{1fa zc_vCvNQQn#!NUxP^)e-{y(pY$3p`f9RNovO9`<&}U|(%V5O1^z%a~+H1!4Bi&)#hy z_hDpT6{y*8`RG`) z84(xX`|Ed_p4gcnWxc|ooCW`;NAHPjAN@EGzgRQcu&l=_DH)P^$($%9K zS3FxPP=Me0d>@h9Y^a3rV*l`%%z?exwue&v2uTcFdo|<+E{rLuL9uAw_-|hqeh=jn zW0#o2L59=kLv#3`C==7(U`zsnh_l2z>k~2ulhm;B;k1bqUyr&9{EMv{Dc}Hl3}& zEGi6!LqgVt_G_#SC!q>ztPx8ba1^uI;X8{0k{PUjGG$y0^leRh1sF#7#$O(#?B9Oc z%d9!WnA7Kcj6=F)qDYt_^VS<3v%}@dNi*RtNE@d~*9Z4;TxFZ!H~-yjbIIRkdW76X zfPzFb7jZAB~8(ckAf2MYgdLfa>xLrt;N=rS=l?h$vPX5rE$K_pjxr zfD%|H9=e)@sF$v|UYX2j{K$^PG0u(bc_!Jy%|UzPs3D-CWAKVt;shwJaCB5QXBaUL zvbpi!yq4;yT*bXp_=u6w8TXU7t>Wx2QO{63LhGoCfC0szGM>pRWPB*>j4vE`!$xktlI z002in+RxO|UvJtM6LV@tjhmV^&}I>4@{!ZV7i*TW{X7DmUu&Yg!+SAa>sR-cGie zfl4XSZXyycsoI#u4qO*<4|-K`_i7MdZnTK@;PpLxWiafYJ+i&lnuC*fZ}x?74AdH- z*V;EOQ6gJZrl1AGZ{ufWX>sed?1KMnqXYRyqu5unwuE5>T+R;PnvV}jOE8Y;3Hh?R zg1=&r$JtEbEL^@Gn;)^=KRRxQiM{}^2~wa%Zw12$*fgsIw^i-(= zaE-eI{RcsnebKaNeh`+o#bVZAFd{a^@HjSo9d!(*rzF+%Wm#IQK{Mu`i)uswu`xAsg&Vep%+mernoUCQ+Z z?!R@i0Lf^sP`w*UBWO5Yy0Vq+s%P)tFg;gXFlE!)S*658Vah@ZZrQY>)yOc)AD(HK zhRJM7om#LsJ3eUIbp%7M(<&C8RnJ7GSoEZt9ReUWZ+)XJ-xb~SK^xsT+$e+n#;DE7 zXJ-2N95~(<- zM(wmf=Bkfdy8Nk3F^UHZ=8{9J$6Z4G44~OPIoWNqir6NpR@KTZ0555&umwcG8|s|D zo+1qK6h4b}teCvw9#2tQ2EynDAx4^Zg;89DvD_1`6KhuCfW`Q#!63x=|RTqx~dK{bxlsBp|lU@o_S59xc_lA6!}py$GI+gyr6DO40G%0D%-X*d`+K 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�YKWQ4?+@%;*CAdk{owWMXNF8 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 O0000 0 + + +def test_linear_scheduler_sigmas_property_no_shift(test_runtime_config): + """ + Test the sigmas property of the LinearScheduler without sigma shift. + """ + scheduler = LinearScheduler(runtime_config=test_runtime_config) + expected_sigmas_from_mflux_0_9_0 = mx.array( + np.load( + io.BytesIO( + bytes.fromhex( + # see: https://gist.github.com/anthonywu/2832147ff5f5f50c81df4d13152d2bed + "934e554d505901003e007b276465736372273a20273c6634272c2027666f727472616e5f6f72646572273a20547275652c20277368617065273a202831352c20297d20202020200a0000803fb7e9793fd92a733f7aa66b3fab38633f30b4593f59df4e3f4f6f423f4b01343f1b10233fc3e30e3f5cedec3e0a90b03e4025483e00000000" + ) + ) + ) + ) + + assert mx.allclose(scheduler.sigmas, expected_sigmas_from_mflux_0_9_0) + assert scheduler.sigmas.shape == (test_runtime_config.num_inference_steps + 1,) + + +def test_linear_scheduler_sigmas_property_with_shift(test_runtime_config): + """ + Test the sigmas property of the LinearScheduler with sigma shift. + """ + test_runtime_config.model_config = ModelConfig.schnell() # requires_sigma_shift=True + scheduler = LinearScheduler(runtime_config=test_runtime_config) + expected_sigmas_from_mflux_0_9_0 = mx.array( + np.load( + io.BytesIO( + bytes.fromhex( + # see: https://gist.github.com/anthonywu/2832147ff5f5f50c81df4d13152d2bed + "934e554d505901003e007b276465736372273a20273c6634272c2027666f727472616e5f6f72646572273a20547275652c20277368617065273a202831352c20297d20202020200a0000803fdbb66d3fb76d5b3f9224493f6edb363f4992243f2549123f0000003fb76ddb3e6edbb63e2549923eb76d5b3e2549123e2549923d00000000" + ) + ) + ) + ) + assert mx.allclose(scheduler.sigmas, expected_sigmas_from_mflux_0_9_0) + assert scheduler.sigmas.shape == (test_runtime_config.num_inference_steps + 1,) diff --git a/tests/schedulers/test_scheduler_lookup.py b/tests/schedulers/test_scheduler_lookup.py new file mode 100644 index 0000000..8c16a51 --- /dev/null +++ b/tests/schedulers/test_scheduler_lookup.py @@ -0,0 +1,17 @@ +import pytest + +import mflux.schedulers + + +def test_scheduler_by_path(): + mflux.schedulers.try_import_external_scheduler("mflux.schedulers.linear_scheduler.LinearScheduler") + + +def test_scheduler_bad_module(): + with pytest.raises(mflux.schedulers.SchedulerModuleNotFound): + mflux.schedulers.try_import_external_scheduler("someone.other.project.BarScheduler") + + +def test_scheduler_bad_classname(): + with pytest.raises(mflux.schedulers.SchedulerClassNotFound): + mflux.schedulers.try_import_external_scheduler("mflux.schedulers.linear_scheduler.FooBarScheduler") diff --git a/uv.lock b/uv.lock index 90f2d61..76bb96b 100644 --- a/uv.lock +++ b/uv.lock @@ -786,6 +786,7 @@ dependencies = [ [package.optional-dependencies] dev = [ + { name = "matplotlib" }, { name = "mlx" }, { name = "pytest" }, { name = "pytest-timer" }, @@ -797,6 +798,7 @@ requires-dist = [ { name = "filelock", specifier = ">=3.18.0" }, { name = "huggingface-hub", specifier = ">=0.24.5,<1.0" }, { name = "matplotlib", specifier = ">=3.9.2,<4.0" }, + { name = "matplotlib", marker = "extra == 'dev'", specifier = ">3.10,<4.0" }, { name = "mlx", specifier = ">=0.27.0,<0.28.0" }, { name = "mlx", marker = "extra == 'dev'", specifier = "==0.27.1" }, { name = "numpy", specifier = ">=2.0.1,<3.0" },