From 7fa2503366e3d0bf33dbb950d30e7c0a4143aa3a Mon Sep 17 00:00:00 2001 From: Thibaut Modrzyk <52449813+Tmodrzyk@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:11:45 +0100 Subject: [PATCH] Initial commit for the pnp tutorial --- .../2025-02-02-tutorial-plug-and-play.md | 348 ++++++++++++++++++ collections/images/plug_and_play/abs_prox.jpg | Bin 0 -> 144732 bytes .../images/plug_and_play/convergent.jpg | Bin 0 -> 32415 bytes .../images/plug_and_play/inverse_problems.jpg | Bin 0 -> 1387986 bytes collections/images/plug_and_play/radon.jpg | Bin 0 -> 239561 bytes collections/images/plug_and_play/tv.jpg | Bin 0 -> 97324 bytes 6 files changed, 348 insertions(+) create mode 100644 collections/_tutorials/2025-02-02-tutorial-plug-and-play.md create mode 100644 collections/images/plug_and_play/abs_prox.jpg create mode 100644 collections/images/plug_and_play/convergent.jpg create mode 100644 collections/images/plug_and_play/inverse_problems.jpg create mode 100644 collections/images/plug_and_play/radon.jpg create mode 100644 collections/images/plug_and_play/tv.jpg diff --git a/collections/_tutorials/2025-02-02-tutorial-plug-and-play.md b/collections/_tutorials/2025-02-02-tutorial-plug-and-play.md new file mode 100644 index 00000000..f6440435 --- /dev/null +++ b/collections/_tutorials/2025-02-02-tutorial-plug-and-play.md @@ -0,0 +1,348 @@ +--- +layout: post +title: "Introduction to Plug-and-Play methods for image restoration" +author: 'Thibaut Modrzyk' +date: 2024-02-02 +categories: optimization, deep learning +--- + +# Note + +This tutorial introduces a relatively recent family of algorithms for solving inverse problems, with a particular focus on image restoration. +While prior knowledge of inverse problems and optimization is not strictly required, it will help in following the discussion more easily. +In the first section I'll briefly go over the key concepts of inverse problems in order for the tutorial to be self-sufficient. For a deeper dive on the topic I strongly recommend Amir Beck's textbook **First-Order Methods in Optimization** [^1]. + +Note also that this tutorial is heavily influenced by the first part of Samuel Hurault's Thesis **Convergent plug-and-play methods for image inverse problems with explicit and nonconvex deep regularization**. + +Finally all of what is discussed here relies on denoising, so having some intuition as to how denoiser and data are related through Tweedie's formula might help. See for instance [my video](https://www.youtube.com/watch?v=0V96wE7lY4w) on the topic. + + + +# Summary + +- [Note](#note) +- [Summary](#summary) +- [Inverse Problems and Optimization](#inverse-problems-and-optimization) + - [Inverse Problems](#inverse-problems) + - [Ill-posedness](#ill-posedness) + - [Variational formulation](#variational-formulation) + - [Proximal operator](#proximal-operator) +- [Plug-and-Play algorithms](#plug-and-play-algorithms) + - [The denoising prior](#the-denoising-prior) + - [Neural Networks as proximal operators](#neural-networks-as-proximal-operators) + - [What about convergence ?](#what-about-convergence-) +- [Explicit Denoising Regularization](#explicit-denoising-regularization) + - [Gradient-Step denoiser](#gradient-step-denoiser) + - [Gradient-Step Proximal Gradient Descent](#gradient-step-proximal-gradient-descent) + - [Proximal denoiser](#proximal-denoiser) +- [Conclusion and Perspectives](#conclusion-and-perspectives) +- [References](#references) + + + +# Inverse Problems and Optimization + +## Inverse Problems + +Inverse problems encompass a very broad family of situations where one aims at recovering a latent "clean" variable from a set of degraded observations. +For instance one can think of the classical example of Computed Tomography (CT), where scanners are rotating around an object and acquiring projection data at several angles, forming a sinogram. +Retrieving a clean image of the object from this sinogram is a typical exemple of inverse problem. + +
Figure 1. The tomographic recontruction inverse problem. The goal is to retrieve the image of a patient's body from the sinogram on the right. Here the forward model is the Radon transform.
+ +A more formal definition of the problem would be to retrieve an image $$ x \in \mathbb{R}^n $$ from an observation $$ y \in \mathbb{R}^m $$: + +$$ y = \mathcal{N}(Ax)$$ + +with $$ A \in \mathbb{R}^{m \times n} $$ representing the degradation, and $$ \mathcal{N} $$ being a noise model. +The matrix $$ A $$ is often called *forward model*, or *system matrix*, depending on the application. +Although one might think that assuming the degradation to be linear would be restrictive, most inverse problems that we face in imaging fall under these assumptions. Here's a non-exhaustive list of well-known linear inverse problems in imaging: +- Deconvolution (aka deblurring) +- Super-resolution (aka upscaling) +- Impainting +- Denoising +- Hyperspectral unmixing (aka source separation) +- Pansharpening + +Figure 2. The tomographic recontruction inverse problem. The goal is to retrieve the image of a patient's body from the sinogram on the right. Here the forward model is the Radon transform.
+ + + +## Ill-posedness + +Even with a linear degradation, solving such problems proves fairly challenging. +Indeed most image reconstruction problems are what we call *ill-posed* inverse problems, meaning that many reconstruction candidate $$ x $$ might fit the observation $$ y $$. +[Hadamard](https://en.wikipedia.org/wiki/Jacques_Hadamard) proposed a more formal definition in stating that the problem is ill-posed if $$ x $$ does not change continually with respect to $$ y $$, meaning that small changes in the observation might result in widely different reconstructions $$ x $$. +This is for instance the case when $$ A $$ is not invertible, or when its condition number $$\kappa$$ is small. +Let us recall that the condition number is defined as: + +$$ \kappa(A) = \left| \frac{\lambda_{max}}{\lambda_{min}} \right| $$ + +where $$ \lambda_{max}, \lambda_{min}$$ are respectively the biggest and smallest eigenvalues of $$A$$. +A small condition number typically causes the noise in $$y$$ to explode when computing the pseudo-inverse $$A^{\dagger}$$. + + + +## Variational formulation + +A typical approach to adress ill-posed inverse problems is to formulate them as optimization problems integrating what is often called a *regularization* term: + +$$ \hat{x} = \arg \min_x f(x) + \lambda g(x) $$ + +where $$ \hat{x} $$ is our reconstruction, $$ f $$ is often called the *data-fidelity* term and $$ g $$ the *regularization*. As the name indicates, the data-fidelity function is there to ensure that our reconstruction $$ \hat{x} $$ matches the observation $$ y $$. In most cases, this function is the $$ L_2 $$ squared distance: + +$$ f (x) = \| y - Ax \|^2_2 $$ + +We call this form a *variational* problem because we study the variations of the objective function to find a minimum. A benefit of this formulation is that it makes the connection with a whole other theoretical toolbox called **Optimization**. Optimization is a well-established field, thus many tools and algorithms have already been developed to solve our problem. +For simplicity, let's assume that the objective function $$f + \lambda g$$ is convex, and that the regularization $$g$$ is smooth. In this case, a well-known algorithm to find a minimum of our objective function is the *gradient descent*. + +$$ x^{n+1} = x^{n} - \tau \nabla (f(x^{n}) + \lambda g(x^{n}))$$ + +where $$\tau$$ is the gradient step size, aka *learning rate*. +We also know that this hyper-parameter should be chosen carefully for the algorithm to converge. Namely, if $$f + \lambda g$$ is $$L$$-smooth, meaning that we have $$L > 0$$ so that: + +$$\forall x, y \in \mathbb{R}^n ~ \| \nabla f(x) - \nabla f(y)\| \leq L \|x - y\|$$ + +then $$\tau$$ should be taken smaller than $$2 / L$$. + + + +## Proximal operator + +This is all well and good but actually the regularizations we want to use are usually non-smooth. Worse than that, they are not even differentiable everywhere. Indeed many regularizations rely on the absolute value, for instance the Total Variation (TV) regularization, and the absolute value is non-differentiable at 0 (it has two different derivatives whether you are left or right of zero). + +This is why mathematicians have developed a new tool in order to be able to take a sort of gradient step on functions that are not differentiable everywhere: the *proximal operator*. Funnily enough, this operator is itself defined as an optimization problem: + +$$ \text{prox}_{\tau g} (x) = \arg \min_u g(u) + \| x - u\|_2^2$$ + +This operator has *many* different interpretations, but let's just say that we compute the minimum of a smoothed version of our original pointy objective function $$g$$. Interestingly, if $$g$$ is convex we know that $$\text{prox}_{\tau g} (x)$$ is single-valued, meaning it really is a function. +When we have a closed-form expression to compute the proximal operator of a function in any points, we say this function is *proximable*. These expressions are typically found in textbooks or on the website [Prox Repository](https://proximity-operator.net/). + +Figure 3. The famous example of the absolute value and its proximal operator. For each point, we can draw the orange tangent function. The proximal operator is computed by taking the minimum of this function at each point.
+ +This operator enables us to construct many other optimization algorithms with convergence guarantees even when $$g$$ is non-differentiable. The most simple of them is the *Forward-Backward* splitting, or *Proximal Gradient Descent*. This is a so-called *splitting* method, because we alternate between the minimization of $$f$$ using a gradient step, and $$g$$ using a proximal step: + +$$x^{n+1} = \text{prox}_{\tau g} \circ (\text{Id} - \tau \nabla f) (x^{n}) $$ + +This algorithm has good convergence properties in most of the cases that we encounter in image processing, meaning that it converges to a minimum of our objective function, or at least a **local minimum**. + +Figure 4. Typical look of a reconstructions made using the TV regularization. Here the algorithm is not the proximal gradient descent but another algorithm using proximal operators called ADMM.
+ + + +# Plug-and-Play algorithms + +Until recently, image restoration was primarily approached by formulating an optimization problem and designing an appropriate regularization. However, with the rise of deep learning over a decade ago, data-driven methods quickly gained popularity, outperforming hand-crafted regularization techniques. + +One major drawback of these deep learning methods is the lack of theoretical guarantees that their outputs truly correspond to valid solutions of the inverse problem. This is particularly concerning because, while they may perform well on a given dataset, they often fail on out-of-domain data. Many deep learning approaches to inverse problems follow an "end-to-end" paradigm, where a neural network is trained to map an observation $$y$$ to the target $$x$$, given a forward model $$A$$. The problem, however, is that if $$A$$ changes, the trained network becomes ineffective. + +Plug-and-Play (PnP) methods offer an elegant solution by reinterpreting neural networks as regularizers, decoupling them from the forward model $$A$$, which is typically embedded in the data-fidelity term. More importantly, PnP methods provide convergence guarantees—something exceedingly rare in deep learning-based approaches. Interestingly, these methods were first introduced in 2013, roughly the same period as deep learning’s take off, yet they originally did not involve neural networks at all. + + + +## The denoising prior + +Plug-and-Play methods start with the 2013 paper of Venkatakrishnan *et al.* [^2]. +This paper starts with the simple observation that if one has a good Gaussian denoiser at hand, it is a solution of the Gaussian denoising optimization problem. + +The Bayesian formulation of inverse problem is: + +$$ D_\sigma (y) = \arg \max_x p(x \mid y) = \arg \min_x - \log p(y \mid x) - \log p(x) $$ + +where $$-\log p(y \mid x)$$ is the negative log-likelihood, which is basically the data-fidelity term, and $$ \log p(x) $$ is the prior over the clean data distribution $$x$$. + +In the special case of Gaussian denoising, we have: + +$$D_\sigma(y) = \arg \min_x \frac{1}{2} \| x - y \|^2 - \sigma^2 \log p(x)$$ + +where $$\sigma$$ is the standard deviation of the Gaussian noise, sometimes called *noise level*. +Does it reminds you of anything ? Well yes, the denoiser can actually be written as a proximal operator over an unknown prior $$- \sigma^2 \log p(x)$$ ! + +$$ D_\sigma(y) = \text{prox}_{- \sigma^2 \log p(x)} (y)$$ + +This observation leads Venkatakrishnan to interpret state-of-the-art Gaussian denoisers as explicit proximal operators. At the time, the best denoiser was BM3D [^3], which is not a neural network at all but rather relies on non-local self-similarity and transform-domain filtering. + + + +## Neural Networks as proximal operators + +As of 2025, deep convolutional neural networks remain the gold standard for Gaussian denoising, offering state-of-the-art performance with fast inference. +Early models like DnCNN [^4] required retraining for each noise level $$\sigma$$, meaning if one wanted to use different noise levels it required a family of trained models tuned for each noise level. +The most widely used denoising model is a convolutional UNet nicknamed DRUNet [^5] developed by Kai Zhang in 2022. +This model takes the noise level $$\sigma$$ as input, meaning we now only need a single model for the vast majority of noise levels we encounter. +Due to its convenience of use and very good performances, it is currently the baseline in the vast majority of Plug-and-Play papers. + +As mentionened previously, since these denoisers act as Gaussian denoisers, we can also interpret them as approximating a proximal operator over an implicit prior $$- \sigma ^2 \log p(x)$$ related to our data distribution +(*Shameless plug*: if you want more intuitions regarding this distribution, check out [my video](https://www.youtube.com/watch?v=0V96wE7lY4w) on the topic). +This denoiser can then be "plugged" in many optimization algorithms originally designed with a proximal step over an explicit regularization in mind. +Here are a few examples of such algorithms: + +**Plug-and-Play Proximal Gradient Descent (PnP-PGD)** + +$$x^{n+1} = D_\sigma \circ \left( \text{Id} - \tau \nabla f \right) (x^{n})$$ + +**Plug-and-Play Douglas-Rachford Splitting (PnP-DRS)** + +$$x^{n+1} = \left( \beta (2 D_{\sigma} - \text{Id}) \circ \alpha \text{prox}_{\tau f} + (1 - \beta) \text{Id} \right) (x^n)$$ + +**Plug-and-Play Alternating Direction Method of Multipliers (PnP-ADMM)** + +$$\left\{ + \begin{array}{ll} + y^{n+1} = \text{prox}_{\tau \lambda f} (x^n) \\ + z^{n+1} = D_\sigma(y^{n+1} + x^{n}) \\ + x^{n+1} = x^n + (y^{n+1} - z^{n+1}) + \end{array} + \right.$$ + +The benefit of the Plug-and-Play framework is that we can use all of what we know about optimization and just "Plug" state-of-the-art denoisers, including neural networks, to achieve excellent perfomances. +We can also accelerate these algorithms easily thanks to known methods such as Nesterov [^5] or Polyak's [^6] iterations for first-order methods. + +## What about convergence ? + +Figure 5. Typical look of a metric / loss function for image restoration algorithms. In most cases, you reach a maximum at a given iterations and then at best you see diminishing returns, at worse you start degrading your image. Convergent algorithms however reach a sort of stationnary point.
+ +We identify Gaussian denoisers to proximal operators thanks to the Bayesian MAP interpretation, but this is a rather hand-wavy explanation. +While this actually works experimentally, meaning that these PnP algorithms show very good performances, one might want to recover convergence guarantees of the original algorithms. + +**Why don't we have convergence directly since we say denoisers are proximal operators ?** + +- *Ideal* denoisers can be seen as proximal operators, but no denoiser is optimal and we never have a loss of zero when training / testing a model +- Proximal operators have other properties that are required for convergence proofs, and these properties are not easily met by neural networks +- The regularization is *implicit*, meaning we have no idea what its true expression is, nor do we have a mean to compute its value, so we can't experimentally verify the convergence +- We train neural network denoisers using *Denoising Score Matching* [^8], which actually implies that our denoisers approximate the MMSE of the denoising problems, not the MAP + +# Explicit Denoising Regularization + +Several works have attempted to bridge the theoretical gap preventing convergence guarantees for PnP algorithms. Unfortunately, this often requires imposing strong and unrealistic assumptions on the network. + +One such condition is *non-expansiveness*, meaning that for any inputs $$x$$ and $$y$$, the denoiser does not increase the distance between the inputs: + +$$\| D_{\sigma} (y) - D_{\sigma} (x) \| < \| y - x\|$$ + +This is equivalent to impose that the gradient of the denoiser is Lipschitz continuous with a Lipschitz constant smaller than 1: + +$$\| \nabla D_\sigma (x) \| < 1$$ + +Enforcing this property typically requires architectural constraints on the network. Unfortunately, attempts in this direction have led to a noticeable degradation in denoising performance. +An alternative approach is to modify the training objective to encourage non-expansiveness. However, this does not strictly guarantee contractiveness across all inputs, leaving theoretical guarantees uncertain. + +## Gradient-Step denoiser + +So what we would really like is to have a neural network that does not only *approximates* as proximal operator, but rather that *is* a proximal operator. +A somewhat related intermediate step to achieve this is to create a neural network that is formulated as an explicit gradient-step. +This is exactly what Samuel Hurault *et al.* and Regev Cohen *et al.* simultanuously proposed in 2021 at NeurIPS and ICLR. +The idea is to formulate a **potential** $$g_{\sigma}$$ from a neural network $$N_{\theta}$$ to create a denoiser $$D_\sigma$$ which is an explicit gradient-step over the potential: + +$$D_\sigma(x) = x - \tau \nabla g_\sigma(x)$$ + +The main difference between the works of Cohen and Hurault lies in their scope. In Cohen *et al.* [^9], multiple examples of potentials $$g_\sigma$$ are proposed, along with a general convergence theorem that applies to all these cases. +However, some assumptions are again imposed on these potentials, that are not easily met. +In contrast, Hurault's NeurIPS paper [^10] focuses on a single instance of such a potential, which only requires realistic assumptions, and offers a particularly elegant Bayesian interpretation. +In the following, we will focus on Hurault's work, which he has further developed and refined throughout his thesis. Also, he's French (cocorico). + +So the idea is to focus on the potential: + +$$g_\sigma = \| x - N_{\theta} (x) \|^2_2$$ + +One then formulates the denoiser as an explicit gradient step over this potential, and trains it like a regular Gaussian denoiser, with denoising score matching: + +$$\mathbb{E}_{x \sim p(x), \epsilon \sim \mathcal{N(0, 1)}} \| D_\sigma(x + \sigma^2 \epsilon) - x \|^2_2$$ + +which with this choice of $$g_\sigma$$ is equal to: + +$$\mathbb{E}_{x \sim p(x), \epsilon \sim \mathcal{N(0, 1)}} \| \nabla g_\sigma (x + \sigma^2 \epsilon) - \sigma^2 \epsilon \|^2_2$$ + +You might notice that this effectively imposes a special form to our neural network based denoiser $$D_{\sigma}$$. +However Hurault *et al.* verify experimentally that this does not impact the denoising performances of the model $$N_{\theta}$$, which they choose as the state-of-the-art DRUNet architecture. +If you want to learn more about these results, check the [blog post](https://creatis-myriad.github.io/2025/01/18/GradientStepDenoiser.html) about of this specific paper. +A nice interpretation links $$g_\sigma$$ to our implicit prior over the training data $$p(x)$$. +We know thanks to Tweedie's formula that we have: + +$$\begin{align} + D_\sigma(x) &\approx x + \sigma^2 \nabla \log p_{\sigma}(x) \\ + \nabla g_\sigma (x) &\approx - \sigma^2 \nabla \log p_{\sigma}(x) \\ + g_\sigma (x) &\approx - \sigma^2 \log p_{\sigma}(x) + C +\end{align} +$$ + +So the potential $$\| x - N_\sigma(x)\|^2_2$$ is somewhat related to the smoothed version of our prior $$p(x)$$. + +## Gradient-Step Proximal Gradient Descent + +A nice property of $$g_\sigma$$ as defined by Hurault *et al.* is that it is $$L$$-smooth, meaning it has $$L$$-Lipschitz gradient. +This enables them to write a slightly modified version of the Proximal-Gradient-Descent and drectly use the convergence proofs available. +The usual gradient-descent scheme reads as: + +$$x^{n+1} = \text{prox}_{\tau g} \circ (\text{Id} - \tau \nabla f) (x^{n}) $$ + +However here we have our denoiser is a gradient step on $$g$$ and not on $$f$$. So what Hurault did is simply swap the two in the algorithm. +This is unusual but makes everything much easier to prove. +Meaning the iterations read as: + +$$ x^{n+1} = \text{Prox}_{\tau f} \circ \left( \text{Id} - \tau \lambda \nabla g_\sigma \right) (x^{n})$$ + +And if we replace with the expression of the denoiser: + +$$ x^{n+1} = \text{Prox}_{\tau f} \circ D_\sigma (x^{n})$$ + +So to sum up usually we have two differentiable convex functions $$f$$ and $$g$$, with the regularization $$g$$ generally non-smooth (for instance TV). +And here we sort of swap the assumptions: we have $$g_\sigma$$ $$L$$-smooth, possibly non-convex, and $$f$$ convex possibly non-smooth. + +**Is it truly Plug-and-Play**? Not exactly—we don’t strictly replace a proximal operator with a denoiser. However, in a broader sense, yes: the denoiser acts as a form of regularization, and we can integrate any network while still preserving convergence guarantees. + +I won't get into more details as to the actual proof, but it follows a very classic scheme in optimization that we can use mainly because of the "hack" of swapping $$f$$ and $$g$$. + +**Why is this work important ?** Well although it does not exactly match the Plug-and-Play framework, it is the first algorithm to make realistic assumptions on the neural netwwork while both preserving convergence guarantees and offering state-of-the-art performances on several inverse problems. + +## Proximal denoiser + +The gradient-step denoiser was a stepping stone to a denoiser that exactly matches the usual Plug-and-Play framework. In their ICML 2022 paper [^11], Hurault *et al.* propose a new interpretation to their previous work enabling to see it as a proximal step over an implicit function $$\phi_{\sigma}$$: + +$$D_{\sigma} (x) = x - \nabla g_{\sigma} (x) = \text{prox}_{\phi_{\sigma}} (x)$$ + +I'll skip over these details because it is purely theoretical and does not change anything regarding the actual denoiser $$D_\sigma$$: it is still the same gradient-step denoiser. However, formulating it as a proximal operator better fits the original Plug-and-Play vision, and opens up more naturally to extending the convergence results to well-known optimization algorithms. + +# Conclusion and Perspectives + +This is time to conclude this tutorial on Plug-and-Play methods. What have we (hopefully) learned here: + +- Image restoration tasks can often be formulated as inverse problems, and the resolution of such problems heavily relies on optimization +- Recent developments on Gaussian denoisers parametrized with neural networks can be connected to optimization +- While this link was informal it provided very good experimental results +- However standard convergence guarantees of these algorithms were still out of reach without sacrificing perfomances +- Thanks to Gradient-Step denoisers, Plug-and-Play algorithms are now rigorously proven, while providing state-of-the-art performances on inverse problems + +**Why do we even care ?** Theoretical understanding is precisely what much of modern machine learning research lacks. Establishing connections between new methods and well-understood domains is essential for advancing and solidifying our field. More importantly, it allows us to leverage decades of prior work to build better, more principled approaches. + +**What's even left to do ?** At first glance, Plug-and-Play might seem *solved*. In a sense, it is—the connection between these methods and classical optimization is now well-established. However, the landscape of deep neural networks has evolved. While convolutionnal Gaussian denoisers were at their peak in 2017, the focus has now shifted towards more powerful generative models like **Diffusion Models**[^12] and **Flow Matching**[^13] as effective regularizers. + +We still lack a solid theoretical framework linking these modern generative models to optimization algorithms. The answer likely lies at the intersection of differential equations, optimization, and optimal transport. + + + +# References + +[^1]: First-Order Methods in Optimization, Amir Beck, 2017 +[^2]: Plug-and-Play Priors for Model Based Reconstruction, Singanallur V. Venkatakrishnan *et al.*, 2013 +[^3]: Image Denoising by Sparse 3-D Transform-Domain Collaborative Filtering, Kostadin Dabov *et al.*, 2007 +[^4]: Beyond a Gaussian Denoiser: Residual Learning of Deep CNN for Image Denoising, Kai Zhang *et al.*, 2017 +[^5]: Plug-and-Play Image Restoration With Deep Denoiser Prior, Kai Zhang *et al.*, 2022 +[^6]: A method for solving the convex programming problem with convergence rate O (1/k2), Yuri Nesterov, 1983 +[^7]: Some methods of speeding up the convergence of iteration methods, Boris Polyak, 1964 +[^8]: A Connection Between Score Matching and Denoising Autoencoders, Pascal Vincent, 2011 +[^9]: It Has Potential: Gradient-Driven Denoisers for Convergent Solutions to Inverse Problems, Regev Cohen *et al*, 2021 +[^10]: Gradient Step Denoiser for convergent Plug-and-Play, Samuel Hurault *et al.*, 2021 +[^11]: Proximal Denoiser for Convergent Plug-and-Play Optimization with Nonconvex Regularization, Samuel Hurault *et al.*, 2022 +[^12]: Denoising Diffusion Models for Plug-and-Play Image Restoration, Zhu *et al.*, 2023 +[^13]: PnP-Flow: Plug-and-Play Image Restoration with Flow Matching, martin *et al.*, 2024 \ No newline at end of file diff --git a/collections/images/plug_and_play/abs_prox.jpg b/collections/images/plug_and_play/abs_prox.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ca554c2647e6d90ee764a56282addfcec82891f2 GIT binary patch literal 144732 zcmeFZ1z43$&@g-uK~X{^l$J&ikd{`IRJx==KspcIii$`{NQbnv(v6^k)s5-YiJ_3?@djR z4(vPO>6#^`b9W+0dFl(-uKKBuMb(Xj@+pjGuIAN$=X0~Oq?WMq`;?qSr(4Z#oI^fW z2;9ht^Tden(q=b=8x*asbVj$`?XZje@yHQ{G3@rSZ&^u>`E+U6AvCtks;K%^Oa$~r|*-0{$WJdyrv(f zT>=a??0cCuB_HN8u>=a246`#IK6?WA$@_;Dyw#=+6NsW>?l>)5H~VOmo?Wzt3^jNW zS6-s8Dpz=VPa;CdRPhIjbt}cqGz~^k$y^F_Zw5cTA0FWmX@H~;KZnw67pAwkuw5d` z4^GUqihKj6h2uxL3f%Ju)#bdPiic=*e`HZgLN?bc5M=jxf*7q>O dU`O%QeV2L!J77ZG^Mp&n?)Om!x>DhdtO8spm}(fIjLx^D#O&tX#ni9x z4-bC>Iq9sHy}A90XTGO4u0>aNQjl51-ywXt|NfPXSe?ZixtM0XY&38+rGtYw<)n4C zSKLnbRp0RA(9Aw3e*tiPVDGpi4VOi140XrTC9 yP9wL+NBw1M_pDMM&GNw>$Mzb<@cPA^)VajLamtj@C&|LKGigPTtsI=^34Lbz z%V1Kh@-G=U4U)1b861PgmN-5lMz|S))$!eZwl08gn&rYm_#8h&khTL0TyXER(1>Mz zMMK0{^TDnHvKg+)l{1<4OR^pxNk)qjV@7bvaXblYc!cY0i3$xVH^!2mwoT8 &k`dHWUn5@JF{h m-AI0 zj&okOx4D(35?>G3&_*}+c=-S}xEI#7yO0IvvG8nJov1BwI19XW{`69pk5$ !pF zantb1DCab|&XC6>SI80*O}h~bZ7w%yHgd?Y#K@*@wvL@DWwhInkbG;pDTt)?iGc-4 z;|oC<`Cf+TE;xIupbrAP-7FF|W6ARMmLV?mm%1N$KV5of=*(Bf-$SD$BLVKhZvA2& zz9PEpJ0qpW7&iVq$^$3uhF;UzhD)>sTtK; umNGL&|goV92?JiAi7*XNz( q~ysG7XVeTFc=z2Sl&ON7B++ky?fV)bjqA5koR%aHqte$&AWa zRrhx5*7<5Y)7)Oalo`TQZYyg!qZlKcXJ|pI Q8mVz zbpKE$Rn;{g`jml2cW)8#r01AEw4Op_hGsPbBtmgSaN@cN )2H#>$ylWYTDOs;b3H|HFT1Og)~Qan-(<_^e$o=(h^O6g%LoCJ)*Nf&DFx4xBe)_ zLq`F o@bvBcsvK5oTW= Llop%H~+j^vT+vF9Y$W|-?qg%#gaj@o{N5Bnbonq+xy{G49bZYdmuW`uk z(trHk4`D-7oeIq)4NFF}{^i~3qRkGsSTZ#q2{hX3rJg0Ix7;UxJX=JhU;MLsPP5qs z!w{)WS#F&0K_!;tdIp&YR=EHR_YUFP0Uy3oP@wmkgS190elfV`TYY+!W=E7}l!*wZ z8FJ5F3DMX-3*5k&lEgKrB3gn))UQZr4Y95YeU3-N$sl{dNlxTI%Gz!pAWSh&eiGhM zuz1H{ S~0p7N2l9%Y|2HJy_@3c@OEkKDLI jg(T9q^I1V!zc6JKTlDDSFcs5%h$V@w8=Aj6fL)Z`@*wj zj})u#Gy=f4Y)VF*N#e3GY26KeikCh&>v&}}N+U4;l@;N%rZRl3#KVAEVA>$=?qzg~ zO4SJgsQ&W?c?vhFkuvGB@6Tg%Ye|s%WTslg+Ggq8;6r2VtZ|K=?g@G=b*+Q(+z5+$ zx|WFW2D(N^EFod~cnDX|vW)7yF6Pi8c-&Yp;o@h5*DY22k`^2a*YV#&bYBF^jO9+1 z=b-Cf _=h!^9T)G30e9VMepGMMBYK7zqH!4%l z4pu5st4k49C0xkq$g!@34u10}rKWElr5YY$p?A 1-zT93=Nzek zt-Nx{b{TUTa*Rh&`e=-~c3lyP8FR%0bcT+rWOLU%^w>IK@q&B!3Cl`)w{X{$Bj$+p zJrb?7ncj?`4#u=IX3P%scug sw~3ynO|mk09g zMwGOxjo*09)pSzcF>(A_)2wS;z;-Lfz1e17AH4(kF;>IU!e=Qux5X7eH3YO8f+Es| zHrE2VI&|kB^f*bJy4*!fpK8!f{<1}O JLq&US{?% z3lBbI=XAX6<`LH5+bR=0DR3SGJH2H2t$mkJv;ISi#upeQ%es$ZXHZVyN4@o|04dU` z&|7_ pyv;VL`aVWIrJK3oE5zuMC81Rduwz^v3B+R9!(NWRm`LZz#}QhomB?Sw zO+89Z!){^FT*><48^{iW8tG27JZ}uG%4!-bHxM_Ln &(eC|v%Uy5qEvxj`RXV3#^=Fw!l%T_8KY1yQyJdN>&1R1lrfq) zJTCyZZD868gr6%QZBsTnTf0QRHcB6Rv-5W5gV~QKNRbG_%e}&+(^?)XWJ(`5&-ayu zb2wMtu)XI|u{!Gbh}g8@T$bvD+Cx mE3~6qC>IOX#@`E0zAEF=PR-CJNsBaOC 1&U=rY|u &&LfbSg!zZNKyHe}xbu zC4jmU7x2CI4oDZP^tT?v0`sgx=bzgqdsTv9)w6+LxF5l~SdI0b1 zQ$Fr5y8$(~PZ;lVaiVK?sAX!0WPs}z^(#+aD7y9e@t#Z2n*J0~^5U@(x-!`1YL ?IT@U(K*OyrDT_&lw{?Y1%gXj)TRas@fxY+>tpuqz#b zEc6KQQQwi=K%mff_9Jk~GL-t*P$Dq1*^m(XS{?ha?Phn2JPWbq0^|Yp5YhOa4azn^ z4 c4Kl zDzFnG^1WpYy^g5ZGeHUUY6_Gb75e&FI0PPl0~O~gedrS4TWA(bxF|B1@X?H@5ktF{ zOmN=&$b2ysbZ*JB_FS1Y_sN`H(WyKdxYTPZEPhLHEkef#)r63I+;*L&pE-fIHs=*b zj0Alp<3l%e>&A`pIYFW8uF(d8X$tfiVK1E=0 zSkGRL+QPEcv1&lEz=N?$=0~{OjWjTp;nD`1%WnM6d=z@oFmtnv@MBQNb>7Ez&AS0w zyQY)wJlAl_yMc8B{gP#*U>uu cq zUuDYzMy~AO`>R&RfxWn!evQH;(@!EYJ8&Xv!+*-Y+JbAifWWlJE6=c^J4by+;oS;# z`$-j&Z)XOGv*L}I!bx FQnB zDEiu*?_MvLJO9D!>3U%TxSg=PJ C9e3PH zF8jBLCy0zZ33_1Pe#nue0`{%Zpz=CG7@2t372&mWnglP)>t1RJFvMUrB96nGIkVjg zyYdeUFud;#{)^_vNZ@$!Q1lSjY17-AsNY4t?TCw81Q!Z}g5L5zc3_%)&B5L1nsrs@ z$*uoeKaX!_JebLnwCBEaJg~FaXwNq`vF97JS}ArKT;qO2zjPR}up6m42*lI*=26_N zqN_=FR~Ppp2SNnTe*=;8*AfS ;UC^>ICFca9m zH|kmZo~Blj0V2XAa>?`jpNMf)=vV45ZHu^MwXNwHHf9I0r@sVDHW}F$7P0gBwPhQ( zhT93KP>Q~=%&Ze1i|BO6+r8x$fZlSK0=L{Fz3V`{cjcl|m9XF}B7Y$rQty>9%7hD| zy_dbL9$awfsI1YwQ2h0y?S~7YA-tYcG*z!wo)H# O7W@$>fTJS`bmNim5!2}h+8 z%Y0XH@pC@8w3~=fwfK!B2?_a)yIO6hCVQOqJys&G^hht##)P#Of@j!FZ;XE)j3*2m z>TgO@04bvBD9mZgBaiqz3JY~4l;c%Ri&V3;ga2V{V`k7hpD5%9ncyM2+jDI6-BelQ z3P602o}A0{^-Eh>*HdM(48*!^c4rl2B)corqjW}L Xnxdp1N4S!c=UouN~Vo~DWcHh)(No-e;9wf{Sh%Ws%Vwv_AE8(S9H{Un*q zbL(=jTEC>$bJ|-t;Fo9nT=dex!FkupB-fVB7~P<{!tp(^2-Pvc qAB2UZt59@(dkT^iaPrwL2CE4^mW0gsw(|0W|ZU{F8R!P{Hdl+M8i zlY=A)lHK}c!@v*)_%g^?g*W81aA1z)CPwTX_qS0X*SyPQr1Q>OW-K4hx%(^5iv6(- zjKw+>bPfZ033~c6VdNeG%Ird%i3PXR=!~YGQKqPIk~j4mL?O6Yu-PSFA&$l(R#h0g z0mMCB6f}9($ZE@dQCye|`$HG1F_VefO*Ye>d|^~f6!7;ebfL{SL}O?M1NV8gJ^wBE z@hs7~Oe*O7upxd_BYQBotg%Hltw2(l6Z_%x(@&SQi)~(UUAj~7yw%?${jM&1z=IrV zlvkcTQt03FV0ZK)*Jhjf>F#z~`fj`<=%fW60h0O}vFa;397e%lhZ2uHhPQ5&ST-Du zCa(4l Ke2`D zLO;_wtL!T~>26WgQG%1kwUSM<6wiS#fk{ou>Kg0Z7f z?gPc%d>mde-9iai2K7 Of=C_j!r-F6d1=~Mo`QB}j zYfY%Jq9G5?^k4K^F*Tsoo4P3Ys(4QDEO!W$lUmcQ62!#p&Uod%Lw`QXCiIRG9=Ky{ zh2Ak*13vxTl{Ignvt>D$VYEv7%mBBoV)KREbtzm7IB^{GMnZzSWdqb12 #$rwuW zzM$m}=%4qN^FNifE+H5dA`l`>9~Dsxou`o;aCKd`B#TmfS?#pZq{_i*+|Oa>c6x~H zk`JS1&eCa8G+LIuiQ^Kf;*?fpx&i|syC25OJ#jCH~&RCXDcpDnNwr!8b8 zu+rxGTF (zmpHS{A`V8py sj?bylu zQ2W;fj}w{)zwhD)BxN#Rgj3|-S>G67gSjzrNXrj^I|Uz7F@GfcWYD9GodjVYF9GHG zq^jei@+%1B%G}vTqf1l>9*<~UeVi+LeEU9^j?fVpY4kIuF$O^6A|$3@q%mVyd%s z@+hy_T-Mq$9f(ZDd1gYQlbJ*HD#`x;W9}`$s_vG)VH5 ) z?(XjHZjkQoZctJ{N)X?Taf|mk=XuU~&--21xAwkt^N(3Gv)0V|&B|zGajtiu;s#$! zyOX_AtfuTH{PD>cu#~W9ST2TbHE@cb8^ouLQX`9b{TdO2v~;|I@o>CxyH-)JvC$!l zOnFhlz|6)Wd|}zf7Hk-a$42U!7Nub3UIQp1Ie_9*j%*)x6GE%07wh@&n(bdFS4 zXIjZWt}^`nLp0plP$Xy>|KES;Rmc7(BAo6b;{7u9;mG%01?c`1tvdhn=e$(Qwe!FJ zbX=F1unqk;AKcl!{r>s1^IlNdna9?0cMn%PBU)BFs4r6%iNs_SRLNW+iq7C*9P=)T zK2{0dcXO)`MZTcMoNbMxZ44R3yRcwzOA011+=QC1Z#SKjqE*Tq&PABw4^ xL&fnejLJmOrPB zk0qbsa!3{0I6e;TGH7&sgo kO7fp-HE>(yQ zPBJ`vy7(uKaJISczB$@S?%^lx?fI)=F%WF<_Pv_7I?^F_R>~GQi(MHqcjj_6Ck~hy znro#f2oj9NezaV{xVCgce?+#xA|7O+_P6$t3^drv!R5d2-}gil@-WgUE##+2Da=N4 zMd}l=DYYqO$Qgfwv8SZDvSFD;KjXRnUk!1b?I`D~;WCq&TCA=m{C(EHzjhn_z0ao5 zlM~q(rrI!y^fs+$tjz7v+pUjEBzZ&YiCvmBVTza2B17vdA|ggoH?95;R$B34Vd?7y zZf}AHa%m@scHDm<5#{hmbJPV;ulMvTm_RcE(44Hbx<66(7f|E$z0bv&xl%g_;&$|B zu6uiw3i5T1#{tK|75h~;!Jrjte+TSe_@Y3~I;r{~HI@Y$<4ZTHoxc!}z$z`AUUX{H z_DaT}s?Sp9Q~_O*r!Am_&gjNwE;ySTti(tab&7`(ww2zgQ9|{GIkq^b )6_qa_DXA!0|p?yPI6}JgrF~8w&@Q)r8ONn#jp}>f!Y3F3XrvIh&iI;0x7~Cqd z-7&cT<3DgmChXR0BHzGv9@W0V;4_Zzsilb=Ta?1lXZ(7K@$ukt^&CD3^NND#6=|X5 z`Vlz-l3kzRH!#yH>9=|~{GhSy>KB!yRuP~;$?_Z6g+>9U504w*)i RCX9%uOY?I%@)GCaI4z? z5PPygo*)D8yPN%#a@PlF_DJH85-3i&I9$Y0ovT;$ufEW?qn%Ii+iqEb8ZqjR?MYM& zzWoDDyW7?kFiDG;8^iRd*|SSAWs8D37Js-sJIV#n*%jbHCS(hJnMroDCP5j8G$u%9 zL2^*#L!^ZRw8`dZVnI<0%2Nii?=NDBAp2@a`7SDKbBLSq@`DqRbRBO9ThjNf)S9^B zvumnUfm6od*xinwDo%aPrqPYzb6-v;KPh-B@doP80Ar_r>1oYV!Xtw&GbYB*pvgyn znE`*AzoKyt;AI3Ze-AZMX9D8avURSnQRBDFNj7iptx|rS0v>YD(6apxK)>B!7bUcn z7xRXMcCz%DkUzy9XvxG+K%aq>5M<{{KFL^0PxUZ#(2Akpjv{)=m1v6t8HE@H>LmUV z;_&7F;h#=1GywhmOV2q#9n7Jg@RKHK{h$frKRxvn)~wUYZ?|&md_PS!AJn+$KbE|{ zpRa!Jka|zw0`>NO!~5=6a>U|X!2|wtWLl6V&kWP<*VNn- bq>5=ZbhYzg^nWJZG)}5m~RNz&ZYFEp>Z%v 9NKsb^4z2s<$?P9Mr=}`Nl5Rf zzD&}~#^n!A8SF8gW4#G(5z)+|2P#ktK97+$`~Js2+ JQ%kzrBD^ukw@C|CX3=w`CdKZ^{2Va^B+wl9{ZGm47Mnza!@(U(f?8jsK3w z4;2IL_ViExk*%j$a!HELxDx`&tVlnC7%C%yB}Zln<0Oa5Me#U4KU0Wa(EL8~?MScS zFwpcI`GcG_64eu$7oeqwX?Ib}wezLE1g}Ns$1m(eYx)?zfn6EdoHr5IL>qo-gaJ*t zM0aQC1+7vVQv$g>fL&0R>m}2H3LX??Be}ORdbVSFaie)(@_|Y3m;w-V25R4Q^jF=J z`g#-mm8w 6H1v3R-}zLkYWI8sRnj3?&6^b%8zLg)bcUREQS`XeXE5daEcQ%c9NI zqN=wa?;IxRwsi{-E2El>so^QA3ZOacc6F;^3r~&BiH!MF!sv+B=F0=*DB~yQm31%I2c(b-u8NGb3YJeV z1;s~*TA`3uAFm`esY}78L^WV?xTTITNxZJ}Qp!F(t~-;I-N0G1hX2Iwdj$_?TaDqf z rY8C!FD6(%}&`D(HMyQ9~cR)MPDqSbva?0@+uNz?Jnng zT$+%)NDZV}60YFh=!{b`W}r%MNHZtjG+7E>bT6Ye?2^o%d~GF#N(7U@eeDF0&;R;k zB?f3ghL;`mH2h;t s}%S>XH y)v_h)6Klg zYMqDEE$IXA%ae!z#*gJI!pyNjvnglWKpU>GBZGl )&@<0e|#}@6k7~7!$A|a2%MJSGeA6 z_+1(e%ZJ3}p9H~IE(k6Qc2JN678g|A(Z7M!Zi~$JmU~Bj^b!)~Gm+G({M4qUoh@g! zNlzsA@(i%cagi+rt+)Yq?edsqgPng@4$3>e?C=#Kl9cp^<3>iE*aXBMM*HCILL z>xZLdn(u_P4jbfEzpiM``bwkt)qGrZL9gR&qV5{VK<^!0q-TB^gx6r-m&0k^9+y^D zo1U^pnwP>9b1PUvBWJde|GpsCdC~U9LNrN!)oii28!Mp$k<;x&6K8WVqMs0w(*S*ixhPU44_ zcG)2Us5H?4{rFD`lNlj_X>^5*E49?J&j)T|%ojH`YD ~iGrU8eS!FSC5Z)#YPoUIrm_MWVh(!xgz%+AS4J>VYQ> zM(F+U#sk{2VtaB1!;TK}iB!I^r|;>PIUfwxhMik>0&ALnq+>bjJndcB=`ALrCD1~L zN}CUi@j_;}j?ImB$ky3UU1SZz?D#9r`x(^X5~aFb&Ijwrb9ePQSkYs9T@!fpDb)j2 ziXHkx-(^EWOdW+@1}odmU$L)!74pGgi9A7oq|#I9JM4enMK^uX*mh8ZD}hvbUi)IB zCu}a43YWb%OhrLJZ!t|X)_($ru;uAH@9w(uFNv?@O`N=Hh98+BEHxG%1d(S=svjp& zl*Nl24hAwkPs!^Qxn+ZwYlsPs{YYp5$lEZ=sjM|l8k$_5tv6x!e4D!1R}oZW5% ~4?EiG!~I&E0I2C=&F=S_sMPjiA4iMBRz=I17oh)K)qeI;g@CNl*1> zPhxQGj#j8XL-?= R{z_t_qHeTh~HN zSYrcAqC@m?+C@6p`wNAn>l{%AGkkX{<$}h^_xqUf*PnTU6 p;E2j+nb&p zRz1NmVHVHl(s_TLZ?}(lePJ=~HZ>7#@u~YUrn*x+$!5KPxg;Qx6OJ 2lQf~PC~OmF zR+;Z{M{{KE{Hx#Uu({j>zdic~W?wpCRf50Ia4V27KfJVB$MO-8*N!+!&QZeS *;F{r rw0=b2NbK6|>V%cPK~GQ8YwXACeeSXPQcz%q zWF+s)+mAd#u2kfJuTWndauSH}_MXxe(fecz2dlW%zuMr6BaY|{3WJ%n4AF%h>@1Aa z&P<6D&40?YQio3>R^Jwvw (ajjc|qp{$_HItFl3#10Z3M+&=ZA_kG< z`(7207$s-feqwrY^1RA uI>Iy`lo^x zXg!Z=(;y=YlII`YMOJ;$qN3#cMMvCk2F>$=LD&Hr=tXGIOMo_RU4CW&23K3^1Lc zk ;k9C;vNxT(kMsls9Y2J%Hp2Q26uS 8;gC+CRt~DWl37myii6{pvR+@mbnkO$`dCfT+U&bhvk}{+_}dd zmnbFzj!NWF(i3=RW9Zw*Pm#-7;6>?f@!iRCX&idRpw;jf8TcKtXcD7pX%JO?A^hU_ z-dN+4tZwsr!G^({(zxyc9Q!fT!L}EZ VruI29_dX2W9 zc$gO@t{0g1)+$pr 1^) s!(-}Q z;o$uS7KwCymVfE7nr=CGlq^nSzD0#ZSbjLjDZnhi!OHWIfl3yr;{J$uqbHD?Ls|j8 z`^H909?UQ+q^xDc#kJs^W>+5#J)UUkn(uL+56Jr$BlL5@wF?hhI)~YUACV;xW0)+` z718=+hv=bed6NEe_XXsz9wV^_Enl`5qvUNXaT9|i^jg)^-dUQMOJB@Gw^(hTm*S?@ zbVkk8+q{`YkWpRl-&g10G4-P;A*IRv%yQ6x_RsEFZJlSq0&q97LWt32KfzUz3bv>j zOdFI}M-=N0eo9VEN(tYZQdPq{)xV`6EkbHiTG;yrRyk!&BLKSl!0E4ZkScdC)JYU} ztea5E5gB}-J3_RR I zqiw6}EWLNi^pl0)NE2&(^h^&T%qwa0m%YnazkTnOcsym3Y@!tZA_7#2V4m{Z(GFV^ zbQ)Wha_(Kb)fzBVWmnR_xxx-x>2T1d*Ho+&cJ=tth50ls^kEm=IKb4gcykHfIZ4G` zao)Z}F5CRw^`3qUd(>MpgPLRDXgeIO%S7w6K^>nJidmwYpxAfcszcyh>5dYs@9mgR z+F0C*9)Zqia3w7zu6JJ;lBmZ~6zd#h%03GvbY-dNS@)&q{lF(&NsFTsITQ^RZTsYJ zDEq_}a+*lsl?2Wg-F9AoQ5@FVAsC&gHTed{aOWOVrF89g_PHdnZHO-|$87pe=k_a= z{43YGvx|$a#`HXWXIA|9idBG2$8ReXh7sUudpcb3bXh%7ic8FK^ahB&{VD42w&lGu zRjiB!(pax62(I6&j9j?8kcZnk$>SRs8372aG9!b5u vCjyYDOgh#c%;^yo (-ckmjCLp{qy5u0E1os~q&L1C&%8 z7g25pbTFakURLz&{T GJQDs4uaLZs!fC6z% jN>o}G zEYZX?>q&!=KI6k@+yg4UtId8?*Wh|1eU2whgInE}v-KY LwD1={GU!VnQQx>!F!;$I36YtMUCiu)-Mnoj_M5F>8E-%1_#f}W zMZK7RkFX8}W#s1fU9^G;W{lvZ7*racdX-<#R8-QXeX`{3{4U-kjVC!q^w2Xo)z?4C z(?s-$Mck6}RI;Jio&R7UR_s!2r=j*UZr=L1tgL)pAYDdHU^hpoPF4)sABju$Z%Mue zbRXGV7{)YHuNi*&_gysMzo&uBzbBZ$A4!L``Q^`_lmt|_3J0MK*pqVk`S}H>s$%t$ z#G*5DIUkn^w&-|n4}6U!i1C#mdZDV>--IU7IS5Mbp1*>y2#8nT+x-ScBgoi1{xlWq z9S#Yos1`U@@jL^;DM@kiSgOZvoaf=X6uX(Uui@+_r@kxKFjAyzNk)^Llb?MUS2}vU zAe4t|Sim(je0n)l{uIheLP{Vi|Fkj`L)z!S$Qu2^wi0VMu49S6<{a<7W+cR4*z>=y zW7N^X?1(C;g)U~o&D(;jutx~(S(oq_xg+I=^qU^(dqW&?OxLv_Kk+?J1DBj 4Yd6iVC+T;SW*dL&u}^QCk1PL0 zTZCOoMAJcVVofX^SaV=N%E~cvUrf?t*OuD{GjWNm5>Nq|xgXDX`9*P$oU{wHlD~l+ zpeSQfa)FeGs7GpNSn>itS0a&$*iIz$7^J;mX{G>1we#eAX*6d5rIcNgnUWd_;44e~ zqEnbjJ{ix{O>A2&4-E#)*t*FZ5J389Xc6!9*eED(IqZV6a1fj(v97KWYDW>W9|9FY z1-WNIJZJshTH?YTt?YUTXmAI$MKGrhYiX@ruJHPExumvXf;5OqD~AShk-~&1VHea^ zkXVj`;Eb-G{#i6MaTXQG>bq05NGjgud5_ di3jZcFC^z7%E#<|y_ Y&S(6zl5JGV>I zTCDnWa^4nv7|$A`VkFfYTY{~{Fslo6KN!^cM14kt?{8bzAsJXG@Ze B5oy5bc(t_)f#it(C5fY6KR6nH;1&d z1_>CAAsH!LpkW`~cjKIgOxcQNz5|9#xXTez=^T7_Y&M>%CMer>QwVaOj{?7hDPJ;) zHj1*;b~b>@O4VVL$TIcuRmxp|lvtk{n%xkK(8M+t9#JQDDB Dn?PorbL?5wMh#HaNl5m$ivjq%?a*0prD)s&^+T5IFtox zL6n^V0}WStpO8uDfU3O}&|@LW*Cv=tx*o!W?JnJL#4`7T{TX(s$2WPO*EexFAUlk_ zhu&|&ik^7o4yJzP8dXF9OPD}N#AW6~i4n6vU~XAYEaY`FLs7+~WP%4!+_!(D4PmzM zstSyis(v^H_eOjGAg7$$q@~M>sAR*jo9ksJwKjE<#S(W6f7|hq6ONTcAc-V{;*n64 zZOYkOQ#yH~yWOQ7Y%`DvLiVP3q-@8-fE@eAka;5xN~WF8(8&j+knwI$9-!?!I>l1% zpmK9*rCErJwU<7$RsLb&hqm_6NW!~9Nzza3S~G7mhQAWMj|%Vu4e}ma?KBA_Fq4w9 z`JncQa?~3O6U3o3Ct78_6WV3RlP4+4f1lh5?n_2<6nDogjFQ7*k_!3xplg?Y l@g@9%n*h19w#u@-SH7QH0bKr y@!HJLQ655}gcYT)Nz)-hnTl1`uxs%4q+rUI)Hn24RSy z{01!ee0|tqI+F_{DHXxCRJgO8C8+(QHiE)0>0N6L10q-x5Ou2$OZoFGY|>;0++WO{ zRbn;EO0RBINE_>9wTQ~70~_V93g&U`Or<81HA*#I#3>CL1SrI;#opy6NNX^`bJ<2k zyNUh)RfZ5j-V W#Je}_200|4UuiTZ5kGc6csZ$IDLufg-2EF4@LtZkqY?1A%6JA zBrtoAyEw~dGSfvBU$_d7dHuZzL-wAzCpFv`66#c|o-BW+-B%#kSMd{3&0+vQ99W>P zFdc6QAsN}=F^hcAvEWh9j+sbo;sQ0Z%37?enegzacn$MEZDgd+ XqnliKnTcFeIq){UrIH tHeTdT;-U?JH z3)@DMWX4> JPsc)sqHTI{rc_@j!q#mMzS0&*MqAa zFB*i8VuvLCnF;U7Sg_1P+)K3|2^_r^U=zO )~fl_+upQ&tN?|b@q3Q2<)dpr)gjtcYR%GW<1EG-Re{4?=1^9^nn zGR(-*%4c*_MmAD(hVqly$q9xWy4lHfZrN&Rpq5`tNEr+5=vq1MQ>lOP(`L5*EYh3& zz42l~T1;^h)U}% {{1ptMV$0A<*{R=#)pN3x%@YX&phC{_)2dMzDANtm#(sgxVFuKn&;F9any;=rZ zidGtAOfGgOkgvhDcYR@Eu1D|M89frsL_o^nNuDp#Eg!v6e*LwW`ECXaG^Ga)6chWt zU4T!l +I?s&*TIoh)Z|uT?IhI#6bZwqC+7yRM5DA^H}Exoj(O zP;%ejhKKdx_uiMKnQ$*^0>}KX!bFrM%FMxNRbv+FOB`xG@a_6o@uyP% zfPgsUW`pl&7(eb^(;=Ov1WE)Mf2Ynt~`2Xyu)>oJNa|E=J?#HnnLq9=$ z3IPT6_z48~eNO=d@-xOKC`3&BK KjnU?gMazk;6KbK84bco=u{2nWadxxoG%g%07y>8&AN~l >@n}GH_hXHScWWDWiTwTW$PKhUh>LwSBYn+E0zAXVTgf;Mo zv{u_NBwGd*2u@icb)2nd%XrE14jEOlb#j&c@Gerj5xR$Q+okDyE{o5;fuUzX?*XoE zit9Q1Gje@2cpOdy#{_?6YYJKVHWA5c06~l3;nQbccm`ei+<{Zluxi=3N9)bN&q%-I zOQ?V?*3Za|o--e|qz^m)&8%I0B3S;U=ymClS~ns;!U$Cpa6W&rpo_3mLQ#D)GL>)Y zvX< fmuqEp5PqWNw%6C73?d%+FX+Ce*t zN?K|c wT_{4}=AD z77HyU!6%e#JXCyP#>R>en?6x |0nsv{rF_{adz;QiIGzff$%2 zLB%>iqSMSnCYB_0q4=gZd4A`PYA0$`Z&O58s|$P0zVq r~LE;WS>o>TaO$dl7dM0-y0Y$k__5>5h3S_!)U*xo0V=|N=e5bn6Bnk z`)&2JjPs?a%AH6Jn~}$u50xGzxPq+_{tCDa{U{uPrx`eF>3yQelT(VHgU%hzCg>_M z&uVW&yj#zjd1^;4*#7k!nCH9$M;-gr_DcM~Oka*m)GrI)L_W_e5Xv$`|8VZq_S>eq zyhU(y_jyh9xrAqgce`-9;axZgDv2-=19t_zuSP)Q&$688NbM!HwwZ6m#=pwjqq2{w z6TpDf)hTvVRabnt&-G?x<-w0Eq$U#K>@#M>i`V$@$vcR{(B*ni ^P1mVRLpRy z#~g!Sm57--9AcAasad*vALk_cG&XZ~H*N_vdK_}RII;Nc*!*i5P{C W(-CkLk*!vp 7@5|qRaanybX&rZ-MZo zS-!*_2BJ6^3Yz8`fOljQ8|iC81c=$@lxb`D?htgld$nC0y+3tm?j~>c_hoDbtS9Q< z0t4XN57>}552tr<`4wXfaloO1etSHp%ZA|EH6|7c#wCE}-Zi&N22^#Ih1|k6Os9?T z>!<$0@!3X8sS n0&d;1c^Ej7Y))tPUJ!slu0bi=svg0O-|f{3drMCUMl^1xah{lv?>mjR zWg+w~UYPV`m~!gqAA|A^B$J`g5GB&KFX1=*(*0heF6Wya(TEy2<7HEt>+M4%ZYG7- zfK?it^z4HXvv7l}7kW_y{`R9z`!sIQgRf&ykdmZNo!O6i?R8nUy?Zo-h=(U=WQtBj z_m}Dd@jZW_l*T|Z<1i901!dEhpVGTD4rg?YefN7q>Xd7O?c*)5XjU>BNhGu+)35S= zd#eyru-aqlDHL61mJ^>5q7sbAU@C%I#@lel#C`L%MP4n3zgm)!qanjj)!dp${!eM3 zys*;tiF+hjv_#rQPIC8=jH8{(9#DPK5sDAwFF`e`x3&zuXc)He&42^fPK84!LU;5& zM5=}_d +m=v22*u8dNe3WJ&jONP N4+!mS^$889CM12$}JO_J@<^-}ns_R>(?x*)0Z*g8hYP$}KjmBUbf| zuwQly7E?lzdAQW(H8NHpkd1|$Z*Tq )h~D2EWUYs7G{UL0(r< z32c`H(!ySC+*RCf?f6$1skR1oi7c4F8)XT1`a95hlCc9y3tcpEKa{Yzq}c);2YSDB zURxjjRp(DIdIKdv+cpMIAo*d3>m50aB3o3`S*K&f1Q=L=wg%|>4d|O+*cUFaB11*` zs(!htddA#|oix|7ha%+$@_=1541+#qjVBxE?s9DLd@M8U3*MGSSlH~pkR`WJXK*{R zAHN7qjUNA*Yi<_Z-OUp(p4qxCoDxb!mgYq4Y8$7p-=Z|yi6*iTchK;Omib${(EH!6 z2 *X23+a4~uXzbsZA{r2v&Od15)&MtY}LH!ETxYQ8N!|Sm*sUWDfd*4 z7v hjJFA zJ(e*eQi;lqpOd0L?qI5&jYcPDSevQA@Fr^4)`OxT5XG^!V<22AJ=3XO^A-;j3fTF8 z2MT$9#v4u nmP`k{v%#g%49$y@LG+%cK>x3T-|E{7vhP!+T^#t zbza{!d)I6tuz4=z01|xPMEi;<=O7%v^;PCMH`dpRdVRIE?fGY-fgeZ}C!`*0L85 z;+TzN?>*mU;5;=BLIq)P?V^iA28^TkGP2#*e4bE5o%&F+#yL==0BR&e34TXKM~rFX zt3l_NEY>|D P `CFL}nVcN95+h=-nr6G|)EYh+8)<0@BMDcpJ2~I7AN^LXN)K4Ug!5ze zp>ki-kgr3c1K8YJgEDeG&9MS(-S)e>6_28~t(#9SGMngpg9geU!LbQiL=#JaHgEot z4wjA$_1o=^;^^zh(jzhsu@R^u<+b*8p79S84YMIHv#E`3!*~&HHvWa03(8k)l0I$~ z24?_a5ZYYrb&Y%%2Mlr-Jns<5Jdd?hy}}r_^DnQzJf<6P{Sd1D$b>vD=_>YjEt-c= zz=Q6NTx$XywV`WPgsq_jeE;@K|1z68%9HNu) &$Z}9Y_}0 z%=KB<>Lz1UE#!_v|1MHrln&4w^79xK&lU8zq)`G3>ViI&m>>fc= DC*tf*Ec873}zAEK%TrM?jS?7*F^- zp^huo5uYHHDLxh53)&MagJC`rF5la2;@Fh|>F~f?r=yrsJ@F+nxk-<6;!8N+v7Qj{ z5KxG<)Kyc3hzCD*2-__XA2=Vypj*x6J)p9${n2F;R%VXrZCQo(OjjF*=>cg((+{|1 zm|o=LzW|ys(1&znkt*k1EEcOPcjnNwY;Qu+DSwX$+ xmRT5KFF&7ursCP znvCo+5WvNu*@IB5^x>`(Xeu0A4SbZ<_|NdQAMBd}qkkSn{HGZIo_u~3Q&_JmAO*hH z=fWlfk~M$guwQ#+ISA)5ZAP{+?B7DJe+sexy=QWqxQqV1Cm%?i6y$`AZD~DLtQYk8 zU*x^#&|h}5p|$b 9G1#m~1AzJO#LQDV2^fy+fxt~U%hT(@tz`Yrb= zGPcJb6$Ed-m>Ro^O_R*lFMJ^OKP%p>XEeZ`Fja=_A{Y$%XkY-7HA4e;rWcWH2=?Ru z<<;WD507nV{#kSgijD?}Bl0xaks5ejPlY0NFlx@r*>tlteJKWRZ)f-el_{}TKK$s1 z3teWECs1DIlC_i5>GaFVBRQYOQ{rA4OF(P1v$6gKv >Yze>3PtZztxTueerKuo!c zs!hrx2McV*tWMjKE;Hnqm7-IKIje07%$`8VS{zEg0M`}ABj($eaGxPt$}?v?2?xU` zPmiR3_5jXQ&@4*cMJ7xMpuXwxxRnwh#qg_|E?K}ei%sgNfCK*K7SGDmE64`hNUAP8 zgh-d{T>x4GC9_(Mh!1`RclsB7{G2#?m1bjCQAidL)QK&^+Wkl=6r>Dnu#3?}p$S6) z`Ip6Q!}U#V-Wc;tz9*mGe*KWPp(XkaY$f21?8jfgZ3CT+bitC?sYHX))L(tJEw;!h zJ9;A+ctw&F-@sr!eV(y!D~Q6x?pyVA79}%>^jENaT kYnjWwRucaZM>tVSu zEsCJlXt!^lCVQ(SwtMYdOAFwlLz`hkX*3%kBGAVpVQJbi) %PY_ zC!k^~p$oS3<&K^U2E?xe<##IV{WsO?*k0SLP&RadI)!BYsKeb}f2as6A|jw!dF3ya zM>XN9@}QfqWjx? MS?-qn(!+)s}YQROD9@~#1p)qIpdRM zI_L}f-_B{PTHic&F(BvnA1d`dG3Z>WAa|5XHqz;yy%FQcP2YyF&N&9CvgAkL-U1CS zX6Q6(l_yXAxH6zCiXfq=Mr_P5r7C-txN=XpnN7%jVaF`wcREdw$&D_r6QP3H{(`Eq zbxqy91{KYeu^PcHBi376l8nm|hMxYsI9_uWBq~8t2)VMF6u gaWSC~4nF*%qh 2;uw9PaWX0m zJT0IS3#+|iNbETDfWxDu$AH#>1q5TFt|2I)gwxGRNp!c*2@L19he%`I75NHwgNYT? zQ$`+HS!2Ajso`e4$fcI;a}yIz_#VSM`CjTryvUxs2C6t13s=*eW$ &q)nMZ98QkmfX82p6IksXl;j5wM^@B`DA#W z7K523Ww1g=smM&<6?ze#
KNAmWGm*1_DJB)_!MW@m7a xS zL)A_-6pryK1KlP<*G(&uPm{K#-;cV}amEO`H8)j3sT8c}bMxwE$X^lOl=&v{1p_1x zJFB#5iB_i%vSXbbdAvolDLO9(Oar`BfB4G2g;9=6=}(XxhU4u$h|eH-(j$;yDv<=Y zz1A3~)u26RQ|wZ%kQ6L7NoQ=TX=A0PcC@;TQ9qt}nle{h$$j<)F9I$qaYID(%~;lp z^z==f*&4K|El`A8TjFcsyG$vRba#BtU-GB~8!Gf+r3lGZ{Im0dK3;n*5jxeOV!g>{ zCuq!S0MYiBhEH&iDF_*tLjBQl*?F2vSYNrRA2Zfvz&*y%gu^s0OC4~}cQ*o~g!JgC zE7lnVfi YFynVJL^9e4yq^K zR1Tfkw0%_;9kQD?DEkL_3H-5(q;`$SfqAU*5zjPiqAbkkicH{#HX$U66{BTPQ7_^2 z%&Lv>erFQoZ>y_nY)MHqwnDc*Ls^B*SSw06#y)XX24?~adr@gY(xCYv4o}Dvb!h8B zdgL$u)!CB2xZxCeDL4oeKp2F(X2h`#_hA-eY;cV;SyBhg=a*FXRp*Fm{qkQun KCQ-)^ROjJ#?&39Fl$0Eot=c=d`~QMYtPmg zpo9^xA)n{#1sk15Rq?XOgA!duW!Na^@% Gaz*rW6WM2G&JmJ@p9L zuakXPWxH1ypOt6g6eNlgBW+B;^^*IUO`DmjTg!~CD0E`g>dMor{gSgA(D__r8xIEB zJRB$b8<+-v@Rf?O5$h(U$`ke*J}R6cg2Y^9KSAMk=!gPzy7i^MWi-S-gp6s2synF2 zLclg)a`5`{gA`h=rC||hFs?58{8xm@Etts|+b6?_6&xr7{^FG}Bk@~U0c73F>ooQy zfc5sVmFc}yny~IwFMEWF*+mD~K=8pVthdo3>%p* qxKBTqwLqL(DE?> zi2K|bUvj&A_az;GBKgIl1|U 0?#WRcY21PP`fu zcCIHfZ4g{-$LJYif}F{P#kkkd>}>1*U3{5iKH*?{HMmveg;()XdDPXZWQ`#Y@Ifp4 zT*)zqlTIB6WVLJ-;Uiu+_Lh^}Xif(c2aaskO(Kd2doDQkCeTR7+pns@#NN~n$x_LQ zoZSZvrTH!c^!{r-A#^;iF9(?#X38A8gWe5-%TR6JtQUP|&;%O5bH_^xkj_3`Rm#xc zNczKUHp_g)A9ci-?_&>ic{2Hjv^0St=?-k-pt~v1SZMW Dux3 zQ{R|4@{DeOZAjdj3ABu8+=3J9SmlFijPv|W3xL0Q3nZ{@*n7~^2S#W81gF2hcWMi| zGiIHjc>IF+R4OV3Z7+PWW8%zt69>cw{F_@0uT=}=Yop Gfw6X!uxqL#Uq+ab&qGWrdoHTj })1_B?=~5kOVUvaExG_htlvIHrqffs^CfH3%L?rzEuHg%(#lH^;l0p z73gV75aDdJNq6hQQVnc6ZypLeXuxB{Xg{98$*2Rx)!)FHz5?MD0tIU<` JQ))g>y&g?iPnjKIhJpGX-!k}2jwcQb0) z3Bi`_=H^Wq%;cWe6Bg%u> `!Thxq`FELL7^cJ)NaFSAaHqH#1Mg0lqIttpfyT5sJu3v4ru9dYJR%>ew zB!5q%s_cxQ4JTo1YmV^|og)=Bsl48hyMjja^*El*T97PD^J?$CyTHECy3G9sMlw}) zk#^hL7=qrpF{fkiuUqOM@orlaQRhf+qTE%pBjsyFdo3e3CF>*#o$xcY8cbD-Zm!S8 zCH1e#Y_M|$4-s$;@*o#nW55<;I3 `2AKwRaI&RKu4Fo{&X@=HsRf7VpSX~ zU|nT1gLPb(l6Zi1Jf9h_oGj`Z^wKJxI@;hzcDcDXYTgDnn5td9aaGUAUw(RGQ@~L= zqk|RNXKu}OdXa`m=A_#||Ks6oLl;Pwi~LM Styy0`Zm z7(b-ul=9mJw7zEi&ZXWQ2^j~7t6rh*3l5J}mFU2Rnm#5PQIqoQW5^jMY1Ku5Vp016 z&(IqMEN-Fp9zptEf49TdOlJjUjm%DKYYW;s1nClcmf$){x#irB)7o!fISJ8~JzEnd z >F zYPlZ#A)F#eH+^&FMe>nX<;TE*3>~_ebqqE8)Go8Ow-$2G)wJY3xggr&$Dlj~9oSig zzR% ;Qq^E9QTgL!7rWGcCpfo;mB466K+@uM +6#R=Gb~Y?*>0ry^#HBp48*F_CX2FVFjK{RXL!2+aXBU0N zQ`{j3P_e|~pbs)WSFFprSBeyYUWL#PrNn(#RYCB*7Ga-(wD?RjBF#auw!v~qq2bU1 zIi(jcdk}eX@FpdW_=f;qVY<@p^I0gT9Mr4a)97l|bDAc-pDQO~;|~(y6(~W4YE=;m zU-wKp#M~~qj&i~&z$3_)AdKN=vE{|-PuW7Jb;Rl5i}kl^e9cM}hAy>bk|iaz^!)M8 zuU{0Ysb@X^krgWkh%0d9uMoyAjJj|2m7Yi6*Gjf|_!?bR&Bcu6h-(|Ih9C8{{iF%T z@uJRGx$9H (~%lP6@)5;80>cQW{Hr-J9vp zRi-27#9aJ-QY-;<(PTIBKKgr4dxi(*Ubhy$d0qax%^*-mw*r^FI`64xgUGA33;Z3P z=MEh0@gnLHwe<-JF7!c>JAvDBQ4`9%Zaex41DzhmW2Z{qEOb2<@EypHI1Ez2>F2U@ zn;ttkNb)111RRGKX`*!7!1)he ;l&G;?U%dtUOt_GFm6M%6C!>rjKW$g@P4?5){Jkl!jOiidjG%i(n z>Q8=xxwm7(R1vZ)m7nbTgK|{t`GGZspQyH2UUu41_K=%dt1f_v9~e0TlJB6;%d(RU z!qp5h_v7XxID19PR>9~5@UB*30#iw!$gVENtGCuhl vwpf+NgI}wPNBx~b-#M<+8xbGV}iKSh5K;Ud0|1FCk7A4Ep)Jx0) zoQr;aW%63~+5Ivh)gf5Y!Pxz7)bO2N>${!on&YqPP|aZv@Z ?|DS8y57(X+ae exG_vGkY zk|+(#pt|p$Bl4sHF9Bm+czR-Y^*SDd)?vX&S9`J;g% 9hb_9@XIPK?KcFOew&+(RJGo5Nwo$S8T~IqkTMjP=M?ab-#w{_ zpb&ukh|fRO?`0b!H^>dSZ2nchpAB4dg1;I+Uo_0m?rrJ~%5Wt&)8<5ZaTTc?_%x$n zw83c(;XW+#`rtgCvwjne00HKVJFuE&8TV^0UKGZBVi1}XbME6qA{U+jkB rh48DkQq+IrC#g?!=B9c`!~kEaYj-BJx?Sy)~}%q^tZ?)KU2Ya@F*; z6{|;$$`O&D;3cJ+Sht~zebG9r8tuLGETFz+3pb+L3KjGdJq)tGcI`SknHE5tMD}5I zwI$V{6D!iH{aEBsDvUR>dR!|vdIO|8XFpoM$Ca`#9oRZN+#s()C>jzpUqpMaq42Gr zQKG#D1#bqN ?T0;wW`(69{wc_ylz|Hi1Po2R&;;ga{M0#XN%?bD}-l$h*i ztXh%sXh(T9h3<1qxUEZ)pABh=Lks}Db;maGI~23? gnJr}_PgcL*;^iEHNWH0Rtwf4cdg<-c$6B?C;Uaav4t!nAjgW%1S2^3(XyvI z5&ZCTstw-XbDt27rCoeL;x8Vpmj-zB zYY(@0G=K*ABdp7&*LP=*3GWpVRix`k+mm*^*z <*fpT&i`2Ro7)5(49L@tUikw zi3vz0KlFm3Q($!=lqoRkPRdjJ4l=13c&!Jti8spnEqmq35Pu~ Al6sqd?Z7vLLSxH)PV)p7hmPjQ=|zX?AwH(W4=NFbzIohA z*8NlV&pJ`F#dK8d%ss<{>VOEdu`LH|)@H#5D{MrE)XE9JWtfdEu=eUzblbD7?{tO4 z^ Z2 C3^c-8!2!W%3i1GIv4R~WObHSTB!ciJo9$%HP6du1*^Bh zD+W ^QL{?R7FS znAXvv6NPYH88My68aO8|MmHu=AC#GV2fegC6#R4V_3;D<_2%kjoi*Z65=v27ZDmRe zqEl}e5c3T7<9uR*?{{Y@(ItC8yDEwmP_xE|sbRiTfsL0Nq)}`nyRa%U?y5wUc{p<* zT 4g?wdgoOUX9-1FGfIO&;u5qLXWc8D^3$xw-h) zsRE+6Tl}d?;DA)_bK=)t)d2pi;P}r_XEMuK!VfOA-7%N?nf->Z5S9^^g{8W~eZNGI zE(mztH;kO0nut6+A_9fNx8J|djLa|TKz-VpZNu{&)2bN_KHw5&{NWPT*_86=t0dCi zG~@X!O3XE{7FdI8_ZA)-aH^+vnx*9B*N#vP_f1vUQHVZwl@~*!){CO(!)qbGwP67V z8V(CF;7%tGbdchYMNmwpP%&?|V8D@f@jATv;s1(wms*NVVIDlu$2hpjAD=%c5oSt; zHR${!u)8<){Sx7JfUPnqPhwE$6NcvnzQ_-)xw8QGukR9HJ27h|iAO|#784uMV0NM4 zrxWgUN2>$XFI<0ExxWO*JzndnezrllR{^VRi4E#E20XENU?)AVlz&8OAAEq GQmJRs4LW}Dwrg=GDj|L$6c3~EBmOlGk zO86C<9C5f+MmdN6X;*!kILJOGOeeeLPZ#>ryH|ebGJ0pKZ8Gl+c=&-ZmEhKgS7x^i z;}d6y1^U3^g!XlCVd*Yp=cAFpH5F_O12PU>(_7ROV^6_(^Vr8L&n$9%U{f{a5;EKO zsc27DMJ>bpJTzRfg`t; 6_JIg-U-;_fhn1zz%DkMh zL*!qc!fDe{K`UUg+YckXsEBP~FH(==;nT!yYU^PKW9|vO7;Y<6`PkhS0xR|QP&rSH zJ`ADgvpTsdTIJ`Nff!@SSuDCI)|FXm^=MH9M#I3Noz(aI4e{V*VC8pgz`+*G<+^ z>-ZcN*n_g%6y%&As~!E%!My!tdI+d7h-DN*{PXzrus;zXe|i(CyWHHV?{^eDY%$G# zBdXu`q`<{8@;$v5aYcJF@e@VGYR%BichOl<+a&!WiC;oBHOeVAhWe9~8%3oNL=$5Z z+Ku0%ra!M3KLKSaiW>xlHwX2T-)zD@3J*`Mi8JqU$^A1wz#s$#FjIDHT5B2zpJ``H zhM{1d!p|H;-Z?Z}I@4{y3p)~vafO`Y*T{z^5s4M)`ow+Pk^Dqfzy&|vc`R+zG7zl+ z8|-In7HXev8DDy2>fD>s>hNR!RYOCWbx4eJ+s8J+))GPL5<9%y%3KiL>Sy~9L9~@0 z5fuhHQ@T@YryE4#{1)a|FDbc)Y@*s9MzeRZxV0QyV@}Y7R_v#L_^RRnd0H5KkmbOG zDl9m_Slr1LZCE>)`eZHRRbOKGdjrkBDc90#m3)dOIRmOy^>haPaIHa_3?u}Vrn!=i>f<}_=R(`3 z*|F821HXeNPQA_^$Jzv+I}N(0m{HM5LO;^1FBCh~^)T0G#KNll8aQM%G;W>K-Uq|1 zy!W^Y<3SMIQhf!RvVHU{xtKr}fIb3n ?TLE`1mEhxpF|+PMo>HTAJF;~m>F`je?$HBl~W{i0_HG|;S7cprmL zGO)ICg1&= qjDRrRQU#J>@?S2znjoVb!%0Q z*P5A5vpGqN?03)_kp=E|kQ(u5lOr8$&gNjnVn?oAcRxG=qO=v5++YZeEUbL(RMKo= z3Hw@KCU*v03<+8zKJ8+^oC06KFlJ!qdaKCe1L|ZlIbQEBBO8k~9c8H(YptKcl?9cP z%e6kmpYTi9s}$2El-pjCdA890;n?`3YuJ_tRNk>BrLOS4*R(<7oae$IbFlm6U4+?6 zKBZb9tL`J#ylrHXNmuD_VvNt)y&cmxsYU&1dp>phzr1>2ae>Ps+Mt+*R49>>ySQOa zXjM!TCg
TQvQOf~YG zqgY_Yq2OesLd@l@6QNyco%Ehys8H%en7r{q-+|yePgU)b=1P>N+8XNWj9Gl}Y?2?R zqm0R#_BtV8b(!@-11-?>m}O@x^PFHZ>H&6rJtG^Df(U(1cTxa4obNWXmHek)vono| z6-p3pI=TLMxWrI44r(!R1ydbOvQSx5eR%*rii#;<4qA+NFCcc6P^;fUB%@8mqd3KX z5R$ic_WBLx34SKeBLTv418DUC#KR9V+b_hKcY*?!D;FP1xQ inx#yT>x1-;@yaZ5pNsnY3q^&Rw=$SMbX`Po^Y;TilYqMSrlnBmGIx5;{ZU^?yG zkh*>ZG&d;^BSQ^0sjji KVn^H&n&*is(fhB!jM3A z=T0ZUH$<%3Bxm13J<3QB@9+Z+i*`@v@l$SGY~|t=i0NF4{0 zXKgWH(J;ZQ;!$;%C*w0r`dqHH-iS_xV8^$q%gpHHKq`K?HvgJ!P>h95NJu(49o)A_ zgV*xT>ur2dC$%o3e`AHOsz&!&ua|l>-%uMae~SU!d}P5lyKk|t*RnP`ZPZ+QW&T <&|}nTad+N_(Q0hoM(XExS+jof3c1e>=n7j{>Iv(Y!c2m+2)Dh&F)?j(viC~r z^_P=285?(11(5}A0Rb}$D#u=LfMhfN``Mqe)r8rL{SG>Z(WPwa;_C53RUUFmfY*g3 z$K;wZXJ*d2bO}i*WVITSBTzO(ml3)qF2nj$g{Z2)OIWjOqP6z5W*h0pYf+e(Ou~t# zGyi-*d@m(p5?q+Gm&8rF9Bw`9 kEKXPAOc^R)Kq+7$P3?2=_HArwaa6bA z@+2X%s4L+80&7*v1N2eOT#;?a7X&W|{*>XPi0WZE6t<$rOh-oSYtt%@K{(=9aToUY zk&Y|7y&k;yEDV@!8nB<>>N1Kd3LGp@gEm*7qKmM(mfj{(RM*c>5FN%e9p#$Y0qK?# z)_=r5Oi4zWyCE&*4{@YxIRs0K0s;QF&KvbUlxmI$ijaGECJvTGB(g27Tm)#%Q+k&7 zO$lz_tRa6COXyNhE;5pV*n(0Bo4VcACn{)hb0aCAc_3N!?;b4sgtLB|Al)e+jYF&B zy-Nj1>UT!F_byT35iR? cspp|G(NLSUg~sG?c|O^WwiB(*oYudO^%$OAilXI zND`U(^iO4f4#M);;e%&0-o^%^*u;;OW{B1gSh5d2bQbSsy0JbG7Mh8NZ0adrZ6^9A zjxnO>cMt=~C?DYcJs`v#&&x&DEMGpqc!Wlw3OMoA0S);8j7aKl_qhlW(XsD#+UwVa z;$aUT5T+7U{fK cNX*vB&;5=>OkBst z?Zhab0Wk^oqW@Gh;%`SbpnerTYBE~>Ah0m9dbi2aX|wi2e-NO_!NjI_#RMx6vY0Qh z`rOHWee}2ET5-A}>X+v_Qimq&2dU~h)j^F7YoAru7@uc3l=kg31irgcGakDv6^Axx zI@|_lNHZCBrfB?`c6 `D9YEu<{w<+*lBlPsB0c$p#|0etEJV+ nDtP`rMHr=U!2Z zFqO?Xuhq%eO#R#(Rf4_`vaOsH9II+AxYb_8>_n?SLVa^>vs~(TP;8gN)j1 !r;A^$}+x>6< zW)c7U9*-A3b4EeAPP#V wC8W$ZWWc 30WQtq(%>}(>TINR&EY9K4FD;>|8=J>^lJd|0 ztryfsCKNiT50Ih27Rt4Srlh_5E&7yG5z%L7N<|aU?VQj6AW100C4JX?B;l&mjP3uQ ztN*jTN`ZDZXkL_DvTvWOLm*4=;m!aiLjZ~Z1?)2F{{RiWy%{z5YV!Wa?N4s}-%5c0 z%1T0V#UB)OGx+-dmNkUnW@H(drT=Jp#FKV~u;XiVFF6?uar^V8be6foE{Qhh>C5v3 zDaD Ek|&Gmo$_*0Q9>6>tiEUd>XE^RGOF4XOesur{!8 zO65A}`1fA@AIsmfn;qQ=bqW3 ^G}-fGi|g+bfYhnK(F`;wM%#@uIYZsYT46{23~ zn1Rag@*9uGuD`1dcSfkDa!R>Dpjy&T$!b$k1t^5==Wk4ccad-)$))nt8-qfA# {J!GW ze3xzuSSw~oqC)R?Hn;dCf2)MfuyY{*2;sVO8WIo>FZY;Ik^5KfHnC3V%3Epr@qv|6 z`hWAHRW4P-vj2B45e x1o2}=eqizxyj0PsyIA>w~3VTH%GTdnDXHRqSqS!vkr|i z2cGvK!JzTiCRhxtZi)J*jO|}F{N}4*8cb0fhKSdb1qc7H`I)K#e$Zt*>KBa5n}3eo z%lcvDt$`34mC&2|J%&&IF~)A-KF03gM^H7iM`~`x!O%_^5J_JDWWC@yJmSN#8Ehtd ztLKG!gQ5iyp3D@6>MxQsIJ4KjW`+e%ClZ-V%A30iNO3LH{|2JTnNa(+N49?NFVhNO zG(7 Wde@m%4XlLr_H&&+xOzwz@KI#K?H!d;UCNu^L0aKo z{AMd!nYZ5vKkGTboqM_Z8&u~xvStj)<`!%t-BAv&9aLeeuI<6XJ@MQ&iLjp6lmg_0 z*cyS2=p)G39~cw0d{{rVPZyolX+ C%O|6D{QsLy+3mHfvsNc%DZ$w8TDGgei+R{E0MYs_4ZoH z5(GGfTu$$HN5FKAG#8E&z}39gHg9o-*$X)86LzNv3Gb_J>3nmS?t02o_Db|}+5He@ z5x$Fde}(UY^P}Vl2Lv6}?N11s(Vl0b;VJ&7Y2Gf|O2h5 gJ9qd1X*M>54h2FA1l{H5rb8s zb3T{!_ =VsZ3GvGU@UKh#0>nkQLP0 %`F5yFp36g$etqoFxQ|eIiH&0NDXKfn^QP{J&_B_)>PpL? zDm9jY=)xMg+$4d(@DCHjPpmDxlV@@i{*g+M4-<|X7GJ+SbB0b2cqd%>#a+k39nW_~ z2uXd4l|7x^G4rtx1!%Raz$4XNpu{Lr^!#!XIrMX~()tYZoFelFxmN2ZCwQTT9kCG) z9ioZdebzrrO}4*Zc=E9O+cez)os4afZ=dI~LX%8U5gNLH+@=vR!&io_@#}Aj2Q0bL zr{lt1EfFM(5s05LWSQW#SEF3(gd+Q})d*KABH6&V6d^Ozgi2y$?H5)~~>^P{Ey zAiQu+j)CqV6b3&S*f>Qcf)9~=1Uiw=b3RT~)$PE=q1ziGqL324KZzw^!@ME&dVBFn z>GCmmaL?Qyi?33m_+CW=2UI>qgCnOA(W23Luhj5;R4 LO5~L`u6*^T15{wn zfRRCqCfvE|``Sv5@TND0_A7zUXkadxK9}iABbfG&oYt3)A<=qK>}|6u4%8a QUY=WD7f+fbaL)I5{7|j;IvX&OtF3zkxijT5kZ%c z^&i4#b^Sp5&TIo^Ah!NqDTKH@+rfgC9YY+Smy_n_qBbn~fC{ZUB7Bf5(Eo}A-{xtu z5T(dj1u5tB) > zpIgH}aX1UNZnpmg9Omv)?cBFuK3-!H{8jY1lDonsf!)NX`(!%AOF^`Vy3$_&S+ ^~iz5URQPbd7)}!652JvA2lguh}B}CkG3D)qM(x zPo`;c$KpH58?o}y?;x7he`tu|4@3WVP}jYspCTbye(-hA(c639P9ebDLrj->dTR`b zUWcB-_y+08s9{GMVw?Q>2o>uay~Z9-q!RhPFbHh5e}Tj;Viil 0hoKb0 z9e=I&r4S0b^!ISBN*O*$5=VK?BbFlVxOLd|jzD+IG$%zG&p*2gZcriwU6%rXQUaMW zF_n>;hB|xD$li%9FyZx^8``e;