diff --git a/doc/OnlineDocs/contributed_packages/doe/CCSI-license.txt b/doc/OnlineDocs/contributed_packages/doe/CCSI-license.txt new file mode 100644 index 00000000000..4b0dadd9e06 --- /dev/null +++ b/doc/OnlineDocs/contributed_packages/doe/CCSI-license.txt @@ -0,0 +1,43 @@ +# Pyomo.DoE was originally developed as part of the Carbon Capture Simulation for Industry +# Impact (CCSI2) project under the following license: +# +# *** License Agreement *** +# +# Pyomo.DoE Copyright (c) 2022, by the software owners: TRIAD National Security, LLC., Lawrence +# Livermore National Security, LLC., Lawrence Berkeley National Laboratory, +# Pacific Northwest National Laboratory, Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, University of Toledo, +# West Virginia University, et al. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided +# that the following conditions are met: +# (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the +# following disclaimer. +# (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or other materials provided with the distribution. +# (3) Neither the name of the Carbon Capture Simulation for Industry Impact, +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, The University of Pittsburgh, +# U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, +# functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to +# make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, +# without imposing a separate written license agreement for such Enhancements, then you hereby grant +# the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare +# derivative works, incorporate into other computer software, distribute, and sublicense such +# enhancements or derivative works thereof, in binary and source code form. +# +# Lead Developers: Jialu Wang and Alexander Dowling, University of Notre Dame diff --git a/doc/OnlineDocs/contributed_packages/doe/doe.rst b/doc/OnlineDocs/contributed_packages/doe/doe.rst new file mode 100644 index 00000000000..710bc939af9 --- /dev/null +++ b/doc/OnlineDocs/contributed_packages/doe/doe.rst @@ -0,0 +1,415 @@ +Pyomo.DoE +========= + +**Pyomo.DoE** (Pyomo Design of Experiments) is a Python library for model-based design of experiments using science-based models. + +Pyomo.DoE was developed by **Jialu Wang** and **Alexander W. Dowling** at the University of Notre Dame as part of the `Carbon Capture Simulation for Industry Impact (CCSI2) `_. +project, funded through the U.S. Department Of Energy Office of Fossil Energy. + +If you use Pyomo.DoE, please cite: + +[Wang and Dowling, 2022] Wang, Jialu, and Alexander W. Dowling. +"Pyomo. DOE: An open‐source package for model‐based design of experiments in Python." +AIChE Journal 68.12 (2022): e17813. `https://doi.org/10.1002/aic.17813` + +Methodology Overview +--------------------- + +Model-based Design of Experiments (MBDoE) is a technique to maximize the information gain of experiments by directly using science-based models with physically meaningful parameters. It is one key component in the model calibration and uncertainty quantification workflow shown below: + +.. figure:: flowchart.png + :scale: 25 % + + The exploratory analysis, parameter estimation, uncertainty analysis, and MBDoE are combined into an iterative framework to select, refine, and calibrate science-based mathematical models with quantified uncertainty. Currently, Pyomo.DoE focused on increasing parameter precision. + +Pyomo.DoE provides the exploratory analysis and MBDoE capabilities to the Pyomo ecosystem. The user provides one Pyomo model, a set of parameter nominal values, +the allowable design spaces for design variables, and the assumed observation error model. +During exploratory analysis, Pyomo.DoE checks if the model parameters can be inferred from the postulated measurements or preliminary data. +MBDoE then recommends optimized experimental conditions for collecting more data. +Parameter estimation packages such as `Parmest `_ can perform parameter estimation using the available data to infer values for parameters, +and facilitate an uncertainty analysis to approximate the parameter covariance matrix. +If the parameter uncertainties are sufficiently small, the workflow terminates and returns the final model with quantified parametric uncertainty. +If not, MBDoE recommends optimized experimental conditions to generate new data. + +Below is an overview of the type of optimization models Pyomo.DoE can accomodate: + +* Pyomo.DoE is suitable for optimization models of **continuous** variables +* Pyomo.DoE can handle **equality constraints** defining state variables +* Pyomo.DoE supports (Partial) Differential-Algebraic Equations (PDAE) models via Pyomo.DAE +* Pyomo.DoE also supports models with only algebraic constraints + +The general form of a DAE problem that can be passed into Pyomo.DoE is shown below: + +.. math:: + \begin{align*} + & \dot{\mathbf{x}}(t) = \mathbf{f}(\mathbf{x}(t), \mathbf{z}(t), \mathbf{y}(t), \mathbf{u}(t), \overline{\mathbf{w}}, \boldsymbol{\theta}) \\ + & \mathbf{g}(\mathbf{x}(t), \mathbf{z}(t), \mathbf{y}(t), \mathbf{u}(t), \overline{\mathbf{w}},\boldsymbol{\theta})=\mathbf{0} \\ + & \mathbf{y} =\mathbf{h}(\mathbf{x}(t), \mathbf{z}(t), \mathbf{u}(t), \overline{\mathbf{w}},\boldsymbol{\theta}) \\ + & \mathbf{f}^{\mathbf{0}}\left(\dot{\mathbf{x}}\left(t_{0}\right), \mathbf{x}\left(t_{0}\right), \mathbf{z}(t_0), \mathbf{y}(t_0), \mathbf{u}\left(t_{0}\right), \overline{\mathbf{w}}, \boldsymbol{\theta})\right)=\mathbf{0} \\ + & \mathbf{g}^{\mathbf{0}}\left( \mathbf{x}\left(t_{0}\right),\mathbf{z}(t_0), \mathbf{y}(t_0), \mathbf{u}\left(t_{0}\right), \overline{\mathbf{w}}, \boldsymbol{\theta}\right)=\mathbf{0}\\ + &\mathbf{y}^{\mathbf{0}}\left(t_{0}\right)=\mathbf{h}\left(\mathbf{x}\left(t_{0}\right),\mathbf{z}(t_0), \mathbf{u}\left(t_{0}\right), \overline{\mathbf{w}}, \boldsymbol{\theta}\right) + \end{align*} + +where: + +* :math:`\boldsymbol{\theta} \in \mathbb{R}^{N_p}` are unknown model parameters. +* :math:`\mathbf{x} \subseteq \mathcal{X}` are dynamic state variables which characterize trajectory of the system, :math:`\mathcal{X} \in \mathbb{R}^{N_x \times N_t}`. +* :math:`\mathbf{z} \subseteq \mathcal{Z}` are algebraic state variables, :math:`\mathcal{Z} \in \mathbb{R}^{N_z \times N_t}`. +* :math:`\mathbf{u} \subseteq \mathcal{U}` are time-varying decision variables, :math:`\mathcal{U} \in \mathbb{R}^{N_u \times N_t}`. +* :math:`\overline{\mathbf{w}} \in \mathbb{R}^{N_w}` are time-invariant decision variables. +* :math:`\mathbf{y} \subseteq \mathcal{Y}` are measurement response variables, :math:`\mathcal{Y} \in \mathbb{R}^{N_r \times N_t}`. +* :math:`\mathbf{f}(\cdot)` are differential equations. +* :math:`\mathbf{g}(\cdot)` are algebraic equations. +* :math:`\mathbf{h}(\cdot)` are measurement functions. +* :math:`\mathbf{t} \in \mathbb{R}^{N_t \times 1}` is a union of all time sets. + +.. note:: + * Process models provided to Pyomo.DoE should define an extra scenario index for all state variables and all parameters, as the first index before any other index. + * Process models must include an index for time, named ``t``. For steady-state models, t should be [0]. + * Measurements can have an extra index besides time. + * Parameters and design variables should be defined as Pyomo ``var`` components on the model to use ``direct_kaug`` mode, and can be defined as Pyomo ``Param`` object if not using ``direct_kaug``. + * Create model function should take scenarios as the first argument of this function. + * Design variables are defined with and only with a time index. + +Based on the above notation, the form of the MBDoE problem addressed in Pyomo.DoE is shown below: + +.. math:: + \begin{equation} + \begin{aligned} + \underset{\boldsymbol{\varphi}}{\max} \quad & \Psi (\mathbf{M}(\mathbf{\hat{y}}, \boldsymbol{\varphi})) \\ + \text{s.t.} \quad & \mathbf{M}(\boldsymbol{\hat{\theta}}, \boldsymbol{\varphi}) = \sum_r^{N_r} \sum_{r'}^{N_r} \tilde{\sigma}_{(r,r')}\mathbf{Q}_r^\mathbf{T} \mathbf{Q}_{r'} + \mathbf{V}^{-1}_{\boldsymbol{\theta}}(\boldsymbol{\hat{\theta}}) \\ + & \dot{\mathbf{x}}(t) = \mathbf{f}(\mathbf{x}(t), \mathbf{z}(t), \mathbf{y}(t), \mathbf{u}(t), \overline{\mathbf{w}}, \boldsymbol{\theta}) \\ + & \mathbf{g}(\mathbf{x}(t), \mathbf{z}(t), \mathbf{y}(t), \mathbf{u}(t), \overline{\mathbf{w}},\boldsymbol{\theta})=\mathbf{0} \\ + & \mathbf{y} =\mathbf{h}(\mathbf{x}(t), \mathbf{z}(t), \mathbf{u}(t), \overline{\mathbf{w}},\boldsymbol{\theta}) \\ + & \mathbf{f}^{\mathbf{0}}\left(\dot{\mathbf{x}}\left(t_{0}\right), \mathbf{x}\left(t_{0}\right), \mathbf{z}(t_0), \mathbf{y}(t_0), \mathbf{u}\left(t_{0}\right), \overline{\mathbf{w}}, \boldsymbol{\theta})\right)=\mathbf{0} \\ + & \mathbf{g}^{\mathbf{0}}\left( \mathbf{x}\left(t_{0}\right),\mathbf{z}(t_0), \mathbf{y}(t_0), \mathbf{u}\left(t_{0}\right), \overline{\mathbf{w}}, \boldsymbol{\theta}\right)=\mathbf{0}\\ + &\mathbf{y}^{\mathbf{0}}\left(t_{0}\right)=\mathbf{h}\left(\mathbf{x}\left(t_{0}\right),\mathbf{z}(t_0), \mathbf{u}\left(t_{0}\right), \overline{\mathbf{w}}, \boldsymbol{\theta}\right) + \end{aligned} + \end{equation} + +where: + +* :math:`\boldsymbol{\varphi}` are design variables, which are manipulated to maximize the information content of experiments. It should consist of one or more of :math:`\mathbf{u}(t), \mathbf{y}^{\mathbf{0}}({t_0}),\overline{\mathbf{w}}`. With a proper model formulation, the timepoints for control or measurements :math:`\mathbf{t}` can also be degrees of freedom. +* :math:`\mathbf{M}` is the Fisher information matrix (FIM), estimated as the inverse of the covariance matrix of parameter estimates :math:`\boldsymbol{\hat{\theta}}`. A large FIM indicates more information contained in the experiment for parameter estimation. +* :math:`\mathbf{Q}` is the dynamic sensitivity matrix, containing the partial derivatives of :math:`\mathbf{y}` with respect to :math:`\boldsymbol{\theta}`. +* :math:`\Psi` is the design criteria to measure FIM. +* :math:`\mathbf{V}_{\boldsymbol{\theta}}(\boldsymbol{\hat{\theta}})^{-1}` is the FIM of previous experiments. + +Pyomo.DoE provides four design criteria :math:`\Psi` to measure the size of FIM: + +.. list-table:: Pyomo.DoE design criteria + :header-rows: 1 + :class: tight-table + + * - Design criterion + - Computation + - Geometrical meaning + * - A-optimality + - :math:`\text{trace}({\mathbf{M}})` + - Dimensions of the enclosing box of the confidence ellipse + * - D-optimality + - :math:`\text{det}({\mathbf{M}})` + - Volume of the confidence ellipse + * - E-optimality + - :math:`\text{min eig}({\mathbf{M}})` + - Size of the longest axis of the confidence ellipse + * - Modified E-optimality + - :math:`\text{cond}({\mathbf{M}})` + - Ratio of the longest axis to the shortest axis of the confidence ellipse + +In order to solve problems of the above, Pyomo.DoE implements the 2-stage stochastic program. Please see Wang and Dowling (2022) for details. + +Pyomo.DoE Required Inputs +-------------------------------- +The required inputs to the Pyomo.DoE solver are the following: + +* A function that creates the process model +* Dictionary of parameters and their nominal value +* Dictionary of measurements and their measurement time points +* Dictionary of design variables and their control time points +* A Numpy ``array`` containing the Prior FIM +* Local and global optimization solver + +Below is a list of arguments that Pyomo.DoE expects the user to provide. + +param_init : ``dictionary`` + A ``dictionary`` of parameter names and values. If they are an indexed variable, put the variable name and index in a nested ``Dictionary``. + +design_variable_timepoints : ``dictionary`` + A ``dictionary`` of design variable names and its control time points. If this design var is independent of time (constant), set the time to [0] + +measurement_object : ``object`` + An ``object`` of the measurements, provided by the measurement class. + + +create_model : ``function`` + A ``function`` returning a deterministic process model. + + +prior_FIM : ``array`` + An ``array`` defining the Fisher information matrix (FIM) for prior experiments, default is a zero matrix. + +Pyomo.DoE Solver Interface +--------------------------- + +.. figure:: uml.png + :scale: 25 % + + +.. autoclass:: pyomo.contrib.doe.doe.DesignOfExperiments + :members: __init__, stochastic_program, compute_FIM, run_grid_search + +.. Note:: + ``stochastic_program()`` includes the following steps: + #. Build two-stage stochastic programming optimization model where scenarios correspond to finite difference approximations for the Jacobian of the response variables with respect to calibrated model parameters + #. Fix the experiment design decisions and solve a square (i.e., zero degrees of freedom) instance of the two-stage DOE problem. This step is for initialization. + #. Unfix the experiment design decisions and solve the two-stage DOE problem. + +.. autoclass:: pyomo.contrib.doe.measurements.Measurements + :members: __init__, check_subset + +.. autoclass:: pyomo.contrib.doe.scenario.Scenario_generator + :special-members: __init__ + +.. autoclass:: pyomo.contrib.doe.result.FIM_result + :special-members: __init__, calculate_FIM + +.. autoclass:: pyomo.contrib.doe.result.Grid_Search_Result + :special-members: __init__ + + + +Pyomo.DoE Usage Example +------------------------ + +We illustrate the use of Pyomo.DoE using a reaction kinetics example (Wang and Dowling, 2022). +The Arrhenius equations model the temperature dependence of the reaction rate coefficient :math:`k_1, k_2`. Assuming a first-order reaction mechanism gives the reaction rate model. Further, we assume only species A is fed to the reactor. + + +.. math:: + \begin{equation} + \begin{aligned} + k_1 & = A_1 e^{-\frac{E_1}{RT}} \\ + k_2 & = A_2 e^{-\frac{E_2}{RT}} \\ + \frac{d{C_A}}{dt} & = -k_1{C_A} \\ + \frac{d{C_B}}{dt} & = k_1{C_A} - k_2{C_B} \\ + C_{A0}& = C_A + C_B + C_C \\ + C_B(t_0) & = 0 \\ + C_C(t_0) & = 0 \\ + \end{aligned} + \end{equation} + + + +:math:`C_A(t), C_B(t), C_C(t)` are the time-varying concentrations of the species A, B, C, respectively. +:math:`k_1, k_2` are the rates for the two chemical reactions using an Arrhenius equation with activation energies :math:`E_1, E_2` and pre-exponential factors :math:`A_1, A_2`. +The goal of MBDoE is to optimize the experiment design variables :math:`\boldsymbol{\varphi} = (C_{A0}, T(t))`, where :math:`C_{A0},T(t)` are the initial concentration of species A and the time-varying reactor temperature, to maximize the precision of unknown model parameters :math:`\boldsymbol{\theta} = (A_1, E_1, A_2, E_2)` by measuring :math:`\mathbf{y}(t)=(C_A(t), C_B(t), C_C(t))`. +The observation errors are assumed to be independent both in time and across measurements with a constant standard deviation of 1 M for each species. + + +Step 0: Import Pyomo and the Pyomo.DoE module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doctest:: + + >>> # === Required import === + >>> import pyomo.environ as pyo + >>> from pyomo.dae import ContinuousSet, DerivativeVar + >>> from pyomo.contrib.doe import Measurements, DesignOfExperiments + >>> import numpy as np + +Step 1: Define the Pyomo process model +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The process model for the reaction kinetics problem is shown below. + +.. doctest:: + + >>> def create_model(scena, CA_init=5, T_initial=300,args=None): + ... # === Create model == + ... m = pyo.ConcreteModel() + ... m.R = 8.31446261815324 # J/K/mol + ... # === Define set === + ... m.t0 = pyo.Set(initialize=[0]) + ... m.t = ContinuousSet(bounds=(0, 1)) + ... m.t_con = pyo.Set(initialize=[0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]) + ... m.scena = pyo.Set(initialize=scena['scena-name']) + ... m.y_set = pyo.Set(initialize=['CA', 'CB', 'CC']) + ... # === Define variables === + ... m.CA0 = pyo.Var(m.t0, initialize = CA_init, bounds=(1.0,5.0), within=pyo.NonNegativeReals) # mol/L + ... m.T = pyo.Var(m.t, initialize =T_initial, bounds=(300, 700), within=pyo.NonNegativeReals) + ... m.C = pyo.Var(m.scena, m.y_set, m.t, initialize=3, within=pyo.NonNegativeReals) + ... m.dCdt = DerivativeVar(m.C, wrt=m.t) + ... m.kp1 = pyo.Var(m.scena, m.t, initialize=3) + ... m.kp2 = pyo.Var(m.scena, m.t, initialize=1) + ... # === Define Param === + ... m.A1 = pyo.Param(m.scena, initialize=scena['A1'],mutable=True) + ... m.A2 = pyo.Param(m.scena, initialize=scena['A2'],mutable=True) + ... m.E1 = pyo.Param(m.scena, initialize=scena['E1'],mutable=True) + ... m.E2 = pyo.Param(m.scena, initialize=scena['E2'],mutable=True) + ... # === Constraints === + ... def T_control(m,t): + ... if t in m.t_con: + ... return pyo.Constraint.Skip + ... else: + ... j = -1 + ... for t_con in m.t_con: + ... if t>t_con: + ... j+=1 + ... neighbour_t = t_control[j] + ... return m.T[t] == m.T[neighbour_t] + ... def cal_kp1(m,z,t): + ... return m.kp1[z,t] == m.A1[z]*pyo.exp(-m.E1[z]*1000/(m.R*m.T[t])) + ... def cal_kp2(m,z,t): + ... return m.kp2[z,t] == m.A2[z]*pyo.exp(-m.E2[z]*1000/(m.R*m.T[t])) + ... def dCdt_control(m,z,y,t): + ... if y=='CA': + ... return m.dCdt[z,y,t] == -m.kp1[z,t]*m.C[z,'CA',t] + ... elif y=='CB': + ... return m.dCdt[z,y,t] == m.kp1[z,t]*m.C[z,'CA',t] - m.kp2[z,t]*m.C[z,'CB',t] + ... elif y=='CC': + ... return pyo.Constraint.Skip + ... def alge(m,z,t): + ... return m.C[z,'CA',t] + m.C[z,'CB',t] + m.C[z,'CC', t] == m.CA0[0] + ... m.T_rule = pyo.Constraint(m.t, rule=T_control) + ... m.k1_pert_rule = pyo.Constraint(m.scena, m.t, rule=cal_kp1) + ... m.k2_pert_rule = pyo.Constraint(m.scena, m.t, rule=cal_kp2) + ... m.dCdt_rule = pyo.Constraint(m.scena,m.y_set, m.t, rule=dCdt_control) + ... m.alge_rule = pyo.Constraint(m.scena, m.t, rule=alge) + ... for z in m.scena: + ... m.C[z,'CB',0.0].fix(0.0) + ... m.C[z,'CC',0.0].fix(0.0) + ... return m +.. doctest:: + + >>> # === Discretization === + >>> def disc(m, NFE=32): + ... discretizer = pyo.TransformationFactory('dae.collocation') + ... discretizer.apply_to(m, nfe=NFE, ncp=3, wrt=m.t) + ... return m + +.. note:: + The first argument of the ``create_model`` function should be ``scena``. + +.. note:: + The model parameters ( :math:`A_1, A_2, E_1, E_2`) are defined as either ``Var`` or ``Param`` objects. This is suggested since it allows an easy transition when changing mode to ``direct_kaug``. + +Step 2: Define the inputs for Pyomo.DoE +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doctest:: + + >>> # === Design variables, time points + >>> t_control = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] # Control time set [h] + >>> dv_pass = {'CA0': [0],'T': t_control} # design variable and its control time set + + >>> # === Measurement object === + >>> t_measure = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] # Measurement time points [h] + >>> measure_pass = {'C':{'CA': t_measure, 'CB': t_measure, 'CC': t_measure}} + >>> measure_variance = {'C': {'CA': 1, 'CB': 1, 'CC': 1}} # provide measurement uncertainty + >>> measure_class = Measurements(measure_pass, variance=measure_variance) # Use Pyomo.DoE.Measurements to achieve a measurement object + + >>> # === Parameter dictionary === + >>> parameter_dict = {'A1': 84.79, 'A2': 371.72, 'E1': 7.78, 'E2': 15.05} + + >>> # === Define prior information == + >>> prior_none = np.zeros((4,4)) + + +Step 3: Compute the FIM of a square MBDoE problem +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This method computes an MBDoE optimization problem with no degree of freedom. + +This method can be accomplished by two modes, ``direct_kaug`` and ``sequential_finite``. +``direct_kaug`` mode requires the installation of the solver `k_aug `_. + +.. doctest:: + + >>> # === Decide mode === + >>> sensi_opt = 'sequential_finite' + >>> # === Specify an experiment === + >>> exp1 = {'CA0': {0: 5}, 'T': {0: 570, 0.125:300, 0.25:300, 0.375:300, 0.5:300, 0.625:300, 0.75:300, 0.875:300, 1:300}} + >>> # === Create the DOE object === + >>> doe_object = DesignOfExperiments(parameter_dict, dv_pass, measure_class, create_model, + ... prior_FIM=prior_none, discretize_model=disc) + >>> # === Use ``compute_FIM`` to compute one MBDoE square problem === + >>> result = doe_object.compute_FIM(exp1,mode=sensi_opt, FIM_store_name = 'dynamic.csv', + ... store_output = 'store_output') # doctest: +SKIP + >>> # === Use ``calculate_FIM`` method of the result object to evaluate the FIM === + >>> result.calculate_FIM(doe_object.design_values) # doctest: +SKIP + >>> # === Print FIM and its trace, determinant, condition number and minimal eigen value === + >>> result.FIM # doctest: +SKIP + >>> result.trace # doctest: +SKIP + >>> result.det # doctest: +SKIP + >>> result.cond # doctest: +SKIP + >>> result.min_eig # doctest: +SKIP + + +Step 4: Exploratory analysis (Enumeration) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Exploratory analysis is suggested to enumerate the design space to check if the problem is identifiable, i.e., ensure that D-, E-optimality metrics are not small numbers near zero, and Modified E-optimality is not a big number. + +Pyomo.DoE accomplishes the exploratory analysis with the ``run_grid_search`` function. +It allows users to define any number of design decisions. Heatmaps can be drawn by two design variables, fixing other design variables. +1D curve can be drawn by one design variable, fixing all other variables. +The function ``run_grid_search`` enumerates over the design space, each MBDoE problem accomplished by ``compute_FIM`` method. Therefore, ``run_grid_search`` supports only two modes: ``sequential_finite`` and ``direct_kaug``. + + +.. doctest:: + + >>> # === Specify inputs=== + >>> design_ranges = [[1,2,3,4,5], [300,400,500,600,700]] # [CA0 [M], T [K]] + >>> dv_apply_name = ['CA0','T'] + >>> dv_apply_time = [[0],t_control] + >>> exp1 = {'CA0': {0: 5}, 'T': {0: 570, 0.125:300, 0.25:300, 0.375:300, 0.5:300, 0.625:300, 0.75:300, 0.875:300, 1:300}} # CA0 in [M], T in [K] + >>> sensi_opt = 'sequential_finite' + >>> prior_all = np.zeros((4,4)) + >>> prior_pass=np.asarray(prior_all) + + >>> # === Run enumeration === + >>> doe_object = DesignOfExperiments(parameter_dict, dv_pass, measure_class, create_model, + ... prior_FIM=prior_none, discretize_model=disc) # doctest: +SKIP + >>> all_fim = doe_object.run_grid_search(exp1, design_ranges, dv_apply_name, dv_apply_time, mode=sensi_opt) # doctest: +SKIP + + >>> # === Analyze results === + >>> test = all_fim.extract_criteria() # doctest: +SKIP + >>> # === Draw 1D sensitivity curve=== + >>> fixed = {"'CA0'": 5.0} # fix a dimension + >>> all_fim.figure_drawing(fixed, ['T'], 'Reactor case','T [K]','$C_{A0}$ [M]' ) # doctest: +SKIP + >>> # === Draw 2D heatmap === + >>> fixed = {} # do not need to fix + >>> all_fim.figure_drawing(fixed, ['CA0','T'], 'Reactor case','$C_{A0}$ [M]', 'T [K]' ) # doctest: +SKIP + + +Successful run of the above code shows the following figure: + +.. figure:: grid-1.png + :scale: 35 % + +A heatmap shows the change of the objective function, a.k.a. the experimental information content, in the design region. Horizontal and vertical axes are two design variables, while the color of each grid shows the experimental information content. Taking the Fig. Reactor case - A optimality as example, A-optimality shows that the most informative region is around $C_{A0}=5.0$ M, $T=300.0$ K, while the least informative region is around $C_{A0}=1.0$ M, $T=700.0$ K. + +Step 5: Gradient-based optimization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Pyomo.DoE accomplishes gradient-based optimization with the ``stochastic_program`` function for A- and D-optimality design. + +This function solves twice: It solves the square version of the MBDoE problem first, and then unfixes the design variables as degree of freedoms and solves again. In this way the optimization problem can be well initialized. + +.. doctest:: + + >>> # === Specify a starting point === + >>> exp1 = {'CA0': {0: 5}, 'T': {0: 300, 0.125:300, 0.25:300, 0.375:300, 0.5:300, 0.625:300, 0.75:300, 0.875:300, 1:300}} + >>> # === Define DOE object === + >>> doe_object = DesignOfExperiments(parameter_dict, dv_pass, measure_class, createmod, + ... prior_FIM=prior_pass, discretize_model=disc) # doctest: +SKIP + >>> # === Optimize === + >>> square_result, optimize_result= doe_object.stochastic_program(exp1, + ... if_optimize=True, + ... if_Cholesky=True, + ... scale_nominal_param_value=True, + ... objective_option='det', + ... L_initial=None) # doctest: +SKIP + + diff --git a/doc/OnlineDocs/contributed_packages/doe/flowchart.png b/doc/OnlineDocs/contributed_packages/doe/flowchart.png new file mode 100644 index 00000000000..2e66566d2f6 Binary files /dev/null and b/doc/OnlineDocs/contributed_packages/doe/flowchart.png differ diff --git a/doc/OnlineDocs/contributed_packages/doe/grid-1.png b/doc/OnlineDocs/contributed_packages/doe/grid-1.png new file mode 100644 index 00000000000..6c96bbab7e0 Binary files /dev/null and b/doc/OnlineDocs/contributed_packages/doe/grid-1.png differ diff --git a/doc/OnlineDocs/contributed_packages/doe/reactor.png b/doc/OnlineDocs/contributed_packages/doe/reactor.png new file mode 100644 index 00000000000..7664493fd81 Binary files /dev/null and b/doc/OnlineDocs/contributed_packages/doe/reactor.png differ diff --git a/doc/OnlineDocs/contributed_packages/doe/uml.png b/doc/OnlineDocs/contributed_packages/doe/uml.png new file mode 100644 index 00000000000..e5280987722 Binary files /dev/null and b/doc/OnlineDocs/contributed_packages/doe/uml.png differ diff --git a/doc/OnlineDocs/contributed_packages/index.rst b/doc/OnlineDocs/contributed_packages/index.rst index 89c8e0caec0..757269df8c3 100644 --- a/doc/OnlineDocs/contributed_packages/index.rst +++ b/doc/OnlineDocs/contributed_packages/index.rst @@ -16,6 +16,7 @@ Contributed packages distributed with Pyomo: :maxdepth: 1 community.rst + doe/doe.rst gdpopt.rst iis.rst mindtpy.rst diff --git a/pyomo/contrib/doe/__init__.py b/pyomo/contrib/doe/__init__.py new file mode 100644 index 00000000000..e938cc72e49 --- /dev/null +++ b/pyomo/contrib/doe/__init__.py @@ -0,0 +1,14 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# ___________________________________________________________________________ +from .measurements import Measurements +from .doe import DesignOfExperiments +from .scenario import Scenario_generator +from .result import FisherResults, GridSearchResult \ No newline at end of file diff --git a/pyomo/contrib/doe/doe.py b/pyomo/contrib/doe/doe.py new file mode 100644 index 00000000000..a2c500176f1 --- /dev/null +++ b/pyomo/contrib/doe/doe.py @@ -0,0 +1,1361 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +from pyomo.common.dependencies import ( + numpy as np, numpy_available +) + +import pyomo.environ as pyo +from pyomo.opt import SolverFactory +import time +import pickle +from itertools import permutations, product +import logging +from pyomo.contrib.sensitivity_toolbox.sens import sensitivity_calculation, get_dsdp +from pyomo.contrib.doe.scenario import Scenario_generator +from pyomo.contrib.doe.result import FisherResults, GridSearchResult + +class DesignOfExperiments: + def __init__(self, param_init, design_variable_timepoints, measurement_object, create_model, solver=None, + time_set_name = "t", prior_FIM=None, discretize_model=None, args=None): + """ + This package enables model-based design of experiments analysis with Pyomo. + Both direct optimization and enumeration modes are supported. + NLP sensitivity tools, e.g., sipopt and k_aug, are supported to accelerate analysis via enumeration. + It can be applied to dynamic models, where design variables are controlled throughout the experiment. + + Parameters + ---------- + param_init: + A ``dictionary`` of parameter names and values. + If they defined as indexed Pyomo variable, put the variable name and index, such as 'theta["A1"]'. + Note: if sIPOPT is used, parameter shouldn't be indexed. + design_variable_timepoints: + A ``dictionary`` where keys are design variable names, values are its control time points. + If this design var is independent of time (constant), set the time to [0] + measurement_object: + A measurement ``object``. + create_model: + A ``function`` that returns the model + solver: + A ``solver`` object that User specified, default=None. + If not specified, default solver is IPOPT MA57. + time_set_name: + A ``string`` of the name of the time set in the model. Default is "t". + prior_FIM: + A ``list`` of lists containing Fisher information matrix (FIM) for prior experiments. + discretize_model: + A user-specified ``function`` that discretizes the model. Only use with Pyomo.DAE, default=None + args: + Additional arguments for the create_model function. + """ + + # parameters + self.param = param_init + # design variable name + self.design_timeset = design_variable_timepoints + self.design_name = list(self.design_timeset.keys()) + # the control time point for each design variable + self.design_time = list(self.design_timeset.values()) + self.create_model = create_model + self.args = args + + # create the measurement information object + self.measure = measurement_object + self.flatten_measure_name = self.measure.flatten_measure_name + self.flatten_variance = self.measure.flatten_variance + self.flatten_measure_timeset = self.measure.flatten_measure_timeset + + # check if user-defined solver is given + if solver: + self.solver = solver + # if not given, use default solver + else: + self.solver = self._get_default_ipopt_solver() + + # time set name + self.t = time_set_name + + # check if discretization is needed + self.discretize_model = discretize_model + + # check if there is prior info + self.prior_FIM = prior_FIM + + # if print statements + self.logger = logging.getLogger(__name__) + self.logger.setLevel(level=logging.WARN) + + def _check_inputs(self, check_mode=False): + """ + Check if inputs are consistent + + Parameters + ---------- + check_mode: check FIM calculation mode + """ + if self.objective_option not in ['det', 'trace', 'zero']: + raise ValueError('Objective function should be chosen from "det", "zero" and "trace" while receiving {}'.format(self.objective_option)) + + if self.formula not in ['central', 'forward', 'backward', None]: + raise ValueError('Finite difference scheme should be chosen from "central", "forward", "backward" and None while receiving {}.'.formate(self.formula)) + + if type(self.prior_FIM)!=type(None): + if np.shape(self.prior_FIM)[0] != np.shape(self.prior_FIM)[1]: + raise ValueError('Found wrong prior information matrix shape.') + + if check_mode: + curr_available_mode = ['sequential_finite','direct_kaug'] + if self.mode not in curr_available_mode: + raise ValueError('Wrong mode.') + + def stochastic_program(self, design_values, if_optimize=True, objective_option='det', + jac_involved_measurement=None, + scale_nominal_param_value=False, scale_constant_value=1, optimize_opt=None, if_Cholesky=False, L_LB = 1E-7, L_initial=None, + jac_initial=None, fim_initial=None, + formula='central', step=0.001, check=True, tee_opt=True): + """ + Optimize DOE problem with design variables being the decisions. + The DOE model is formed invasively and all scenarios are computed simultaneously. + The function will first run a square problem with design variable being fixed at + the given initial points (Objective function being 0), then a square problem with + design variables being fixed at the given initial points (Objective function being Design optimality), + and then unfix the design variable and do the optimization. + + Parameters + ----------- + design_values: + a ``dict`` where keys are design variable names, values are a dict whose keys are time point + and values are the design variable value at that time point + if_optimize: + if true, continue to do optimization. else, just run square problem with given design variable values + objective_option: + supporting maximizing the 'det' determinant or the 'trace' trace of the FIM + jac_involved_measurement: + the measurement class involved in calculation. If None, take the overall measurement class + scale_nominal_param_value: + if True, the parameters are scaled by its own nominal value in param_init + scale_constant_value: + scale all elements in Jacobian matrix, default is 1. + optimize_opt: + A dictionary, keys are design variables, values are True or False deciding if this design variable will be optimized as DOF or not + if_Cholesky: + if True, Cholesky decomposition is used for Objective function for D-optimality. + L_LB: + L is the Cholesky decomposition matrix for FIM, i.e. FIM = L*L.T. + L_LB is the lower bound for every element in L. + if FIM is positive definite, the diagonal element should be positive, so we can set a LB like 1E-10 + L_initial: + initialize the L + jac_initial: + a matrix used to initialize jacobian matrix + fim_initial: + a matrix used to initialize FIM matrix + formula: + choose from 'central', 'forward', 'backward', None. This option is only used for 'sequential_finite' mode. + step: + Sensitivity perturbation step size, a fraction between [0,1]. default is 0.001 + check: + if True, inputs are checked for consistency, default is True. + + Returns + -------- + analysis_square: result summary of the square problem solved at the initial point + analysis_optimize: result summary of the optimization problem solved + + """ + time0 = time.time() + + # store inputs in object + self.design_values = design_values + self.optimize = if_optimize + self.objective_option = objective_option + self.scale_nominal_param_value = scale_nominal_param_value + self.scale_constant_value = scale_constant_value + self.Cholesky_option = if_Cholesky + self.L_LB = L_LB + self.L_initial = L_initial + self.jac_initial = jac_initial + self.fim_initial = fim_initial + self.formula = formula + self.step = step + self.tee_opt = tee_opt + + # calculate how much the FIM element is scaled by a constant number + # FIM = Jacobian.T@Jacobian, the FIM is scaled by squared value the Jacobian is scaled + self.fim_scale_constant_value = self.scale_constant_value **2 + + # identify measurements involved in calculation + if jac_involved_measurement: + self.jac_involved_name = jac_involved_measurement.flatten_measure_name.copy() + self.timepoint_overall_set = jac_involved_measurement.timepoint_overall_set.copy() + else: + self.jac_involved_name = self.flatten_measure_name.copy() + self.timepoint_overall_set = self.measure.timepoint_overall_set.copy() + + + # check if inputs are valid + # simultaneous mode does not need to check mode and dimension of design variables + if check: + self._check_inputs(check_mode=False) + + # build the large DOE pyomo model + m = self._create_doe_model(no_obj=True) + + # solve model, achieve results for square problem, and results for optimization problem + m, analysis_square = self._compute_stochastic_program(m, optimize_opt) + + if self.optimize: + analysis_optimize = self._optimize_stochastic_program(m) + + time1 = time.time() + analysis_optimize.total_time = time1-time0 + self.logger.info('Total wall clock time [s]: %s', time1-time0) + return analysis_square, analysis_optimize + + else: + time1 = time.time() + # record square problem time + analysis_square.total_time = time1-time0 + self.logger.info('Total wall clock time [s]: %s', time1 - time0) + + return analysis_square + + + def _compute_stochastic_program(self, m, optimize_option): + """ + Solve the stochastic program problem as a square problem. + """ + + # Solve square problem first + # result_square: solver result + time0_solve = time.time() + result_square = self._solve_doe(m, fix=True, opt_option=optimize_option) + time1_solve = time.time() + + time_solve1 = time1_solve-time0_solve + + # extract Jac + jac_square = self._extract_jac(m) + + # create result object + analysis_square = FisherResults(list(self.param.keys()), self.measure, jacobian_info=None, all_jacobian_info=jac_square, + prior_FIM=self.prior_FIM, scale_constant_value=self.scale_constant_value) + # for simultaneous mode, FIM and Jacobian are extracted with extract_FIM() + analysis_square.calculate_FIM(self.design_timeset, result=result_square) + + analysis_square.model = m + + self.analysis_square = analysis_square + analysis_square.solve_time = time_solve1 + self.logger.info('Total solve time with simultaneous_finite mode (Wall clock) [s]: %s', time_solve1) + + return m, analysis_square + + def _optimize_stochastic_program(self, m): + """ + Solve the stochastic program problem with degrees of freedom. + """ + + m = self._add_objective(m) + + self.logger.info('Solve with given objective:') + time0_solve2 = time.time() + result_doe = self._solve_doe(m, fix=False) + time1_solve2 = time.time() + time_solve2 = time1_solve2 - time0_solve2 + + # extract Jac + jac_optimize = self._extract_jac(m) + + # create result object + analysis_optimize = FisherResults(list(self.param.keys()), self.measure, jacobian_info=None, all_jacobian_info=jac_optimize, + prior_FIM=self.prior_FIM) + # for simultaneous mode, FIM and Jacobian are extracted with extract_FIM() + analysis_optimize.calculate_FIM(self.design_timeset, result=result_doe) + analysis_optimize.model = m + + # record optimization time + analysis_optimize.solve_time = time_solve2 + + return analysis_optimize + + + + def compute_FIM(self, design_values, mode='sequential_finite', FIM_store_name=None, specified_prior=None, + tee_opt=True, scale_nominal_param_value=False, scale_constant_value=1, + store_output = None, read_output=None, extract_single_model=None, + formula='central', step=0.001, + objective_option='det'): + """ + This function solves a square Pyomo model with fixed design variables to compute the FIM. + It calculates FIM with sensitivity information from four modes: + 1. sequential_finite: Calculates a one scenario model multiple times for multiple scenarios. + Sensitivity info estimated by finite difference + 2. sequential_sipopt: calculate sensitivity by sIPOPT [Experimental] + 3. sequential_kaug: calculate sensitivity by k_aug [Experimental] + 4. direct_kaug: calculate sensitivity by k_aug with direct sensitivity + + "Simultaneous_finite" mode is not included in this function. + + Parameters + ----------- + design_values: + a ``dict`` where keys are design variable names, + values are a dict whose keys are time point and values are the design variable value at that time point + mode: + use mode='sequential_finite', 'sequential_sipopt', 'sequential_kaug', 'direct_kaug' + FIM_store_name: + if storing the FIM in a .csv or .txt, give the file name here as a string. + specified_prior: + provide alternate prior matrix, default is no prior. + tee_opt: + if True, IPOPT console output is printed + scale_nominal_param_value: + if True, the parameters are scaled by its own nominal value in param_init + scale_constant_value: + scale all elements in Jacobian matrix, default is 1. + store_output: + if storing the output (value stored in Var 'output_record') as a pickle file, give the file name here as a string. + read_output: + if reading the output (value for Var 'output_record') as a pickle file, give the file name here as a string. + extract_single_model: + if True, the solved model outputs for each scenario are all recorded as a .csv file. + The output file uses the name AB.csv, where string A is store_output input, B is the index of scenario. + scenario index is the number of the scenario outputs which is stored. + formula: + choose from 'central', 'forward', 'backward', None. This option is only used for 'sequential_finite' mode. + step: + Sensitivity perturbation step size, a fraction between [0,1]. default is 0.001 + objective_option: + choose from 'det' or 'trace' or 'zero'. Optimization problem maximizes determinant or trace or using 0 as objective function. + + Return + ------ + FIM_analysis: result summary object of this solve + """ + + # save inputs in object + self.design_values = design_values + self.mode = mode + self.scale_nominal_param_value = scale_nominal_param_value + self.scale_constant_value = scale_constant_value + self.formula = formula + self.step = step + + # This method only solves square problem + self.optimize = False + # Set the Objective Function to 0 helps solve square problem quickly + self.objective_option = 'zero' + self.tee_opt = tee_opt + + self.FIM_store_name = FIM_store_name + self.specified_prior = specified_prior + + # calculate how much the FIM element is scaled by a constant number + # As FIM~Jacobian.T@Jacobian, FIM is scaled twice the number the Q is scaled + self.fim_scale_constant_value = self.scale_constant_value ** 2 + + # check inputs valid + self._check_inputs(check_mode=True) + + if self.mode=='sequential_finite': + FIM_analysis = self._sequential_finite(read_output, extract_single_model, store_output) + return FIM_analysis + + elif self.mode =='direct_kaug': + FIM_analysis = self._direct_kaug() + return FIM_analysis + + else: + raise ValueError(self.mode+' is not a valid mode. Choose from "sequential_finite" and "direct_kaug".') + + def _sequential_finite(self, read_output, extract_single_model, store_output): + time00 = time.time() + + # if using sequential model + # call generator function to get scenario dictionary + scena_gen = Scenario_generator(self.param, formula=self.formula, step=self.step) + scena_gen.generate_sequential_para() + + # if measurements are provided + if read_output: + with open(read_output, 'rb') as f: + output_record = pickle.load(f) + f.close() + jac = self._finite_calculation(output_record, scena_gen) + + # if measurements are not provided + else: + # dict for storing model outputs + output_record = {} + + # dict for storing Jacobian + models = [] + time_allbuild = [] + time_allsolve = [] + # loop over each scenario + for no_s in (scena_gen.scena_keys): + + scenario_iter = scena_gen.next_sequential_scenario(no_s) + # create the model + time0_build = time.time() + mod = self.create_model(scenario_iter, args=self.args) + time1_build = time.time() + time_allbuild.append(time1_build-time0_build) + + # discretize if needed + if self.discretize_model: + mod = self.discretize_model(mod) + + # solve model + time0_solve = time.time() + square_result = self._solve_doe(mod, fix=True) + time1_solve = time.time() + time_allsolve.append(time1_solve-time0_solve) + models.append(mod) + + if extract_single_model: + mod_name = store_output + str(no_s) + '.csv' + dataframe = extract_single_model(mod, square_result) + dataframe.to_csv(mod_name) + + # loop over measurement item and time to store model measurements + output_iter = [] + + for j in self.flatten_measure_name: + for t in self.flatten_measure_timeset[j]: + measure_string_name = self.measure.SP_measure_name(j,t,mode='sequential_finite') + C_value = pyo.value(eval(measure_string_name)) + output_iter.append(C_value) + + output_record[no_s] = output_iter + + output_record['design'] = self.design_values + if store_output: + f = open(store_output, 'wb') + pickle.dump(output_record, f) + f.close() + + # calculate jacobian + jac = self._finite_calculation(output_record, scena_gen) + + time11 = time.time() + self.logger.info('Build time with sequential_finite mode [s]: %s', sum(time_allbuild)) + self.logger.info('Solve time with sequential_finite mode [s]: %s', sum(time_allsolve)) + self.logger.info('Total wall clock time [s]: %s', time11-time00) + + # return all models formed + self.models = models + + # Assemble and analyze results + if self.specified_prior is None: + prior_in_use = self.prior_FIM + else: + prior_in_use = self.specified_prior + + FIM_analysis = FisherResults(list(self.param.keys()), self.measure, jacobian_info=None, all_jacobian_info=jac, + prior_FIM=prior_in_use, store_FIM=self.FIM_store_name, scale_constant_value=self.scale_constant_value) + + # Store the Jacobian information for access by users, not necessarily call result object to achieve jacobian information + # It is the overall set of Jacobian information, + # while in the result object the jacobian can be cut to achieve part of the FIM information + self.jac = jac + + if read_output is None: + FIM_analysis.build_time = sum(time_allbuild) + FIM_analysis.solve_time = sum(time_allsolve) + + return FIM_analysis + + def _sequential_sipopt(self,read_output): + time00 = time.time() + # create scenario class for a base case + scena_gen = Scenario_generator(self.param, formula=None, step=self.step) + scenario_all = scena_gen.simultaneous_scenario() + + # sipopt only uses backward difference scheme + # store measurements for scenarios + all_perturb_measure = [] + all_base_measure = [] + # store jacobian info + jac={} + + # if measurements are provided + if read_output: + with open(read_output, 'rb') as f: + output_record = pickle.load(f) + f.close() + jac = self._finite_calculation(output_record, scena_gen) + + else: + # time building time and solving time store list + time_allbuild = [] + time_allsolve = [] + # loop over parameters + for pa in range(len(list(self.param.keys()))): + perturb_mea = [] + base_mea = [] + + # create model + time0_build = time.time() + mod = self.create_model(scenario_all, self.args) + time1_build = time.time() + time_allbuild.append(time1_build - time0_build) + + # discretize if needed + if self.discretize_model: + mod = self.discretize_model(mod) + + # For sIPOPT, fix model DOF + if self.mode =='sequential_sipopt': + mod = self._fix_design(mod, self.design_values, fix_opt=True) + + # add sIPOPT perturbation parameters + mod = self._add_parameter(mod, perturb=pa) + + # solve the square problem with the original parameters for k_aug mode, since k_aug does not calculate these + if self.mode == 'sequential_kaug': + self._solve_doe(mod, fix=True) + + # parameter name lists for sipopt + list_original = [] + list_perturb = [] + for ele in list(self.param.keys()): + # [0] is added as the scenario name + list_original.append(getattr(mod, ele)[0]) + for elem in self.perturb_names: + list_perturb.append(getattr(mod, elem)[0]) + + # solve model + if self.mode =='sequential_sipopt': + time0_solve = time.time() + m_sipopt = sensitivity_calculation('sipopt', mod, list_original, list_perturb, tee=self.tee_opt, solver_options='ma57') + else: + time0_solve = time.time() + m_sipopt = sensitivity_calculation('k_aug', mod, list_original, list_perturb, tee=self.tee_opt, solver_options='ma57') + + time1_solve = time.time() + time_allsolve.append(time1_solve - time0_solve) + + # extract sipopt result + for j in self.flatten_measure_name: + # check if this variable needs split name + if self.measure.ind_string in j: + measure_name = j.split(self.measure.ind_string)[0] + measure_index = j.split(self.measure.ind_string)[1] + # this is needed for using eval(). if the extra index is 'CA', it converts to "'CA'". only for the extra index as a string + if type(measure_index) is str: + measure_index_doublequotes = '"' + measure_index + '"' + for t in self.flatten_measure_timeset[j]: + measure_var = getattr(m_sipopt, measure_name) + # check if this variable is fixed + if (measure_var[0,measure_index,t].fixed == True): + perturb_value = value(measure_var[0,measure_index,t]) + else: + # if it is not fixed, record its perturbed value + if self.mode =='sequential_sipopt': + perturb_value = getattr(m_sipopt.sens_sol_state_1)[getattr(m_sipopt, measure_name)[0, measure_index_doublequotes,t]] + else: + perturb_value = getattr(m_sipopt, measure_name)[0, measure_index_doublequotes, t] + # base case values + if self.mode == 'sequential_sipopt': + base_value = getattr(m_sipopt, measure_name)[0, measure_index_doublequotes, t] + else: + base_value = getattr(mod, measure_name)[0, measure_index_doublequotes, t] + perturb_mea.append(perturb_value) + base_mea.append(base_value) + + else: + # fetch the measurement variable + measure_var = getattr(m_sipopt, j) + for t in self.flatten_measure_timeset[j]: + if (measure_var[0,t].fixed == True): + perturb_value = value(measure_var[0, t]) + else: + # if it is not fixed, record its perturbed value + if self.mode == 'sequential_sipopt': + perturb_value = getattr(m_sipopt.sens_sol_state_1)[getattr(m_sipopt, j)[0,t]] + else: + perturb_value = getattr(m_sipopt, j)[0,t] + + # base case values + if self.mode == 'sequential_sipopt': + base_value = pyo.value(getattr(m_sipopt, j)[0,t]) + else: + base_value = pyo.value(getattr(mod,j)[0,t]) + + perturb_mea.append(perturb_value) + base_mea.append(base_value) + + # store extracted measurements + all_perturb_measure.append(perturb_mea) + all_base_measure.append(base_mea) + + # After collecting outputs from all scenarios, calculate sensitivity + for count, para in enumerate(list(self.param.keys())): + list_jac = [] + for i in range(len(all_perturb_measure[0])): + sensi = -(all_perturb_measure[count][i] - all_base_measure[count][i]) / self.step * self.scale_constant_value + if not self.scale_nominal_param_value: + sensi /= self.param[para] + list_jac.append(sensi) + # get Jacobian dict, keys are parameter name, values are sensitivity info + jac[para] = list_jac + + # check if another prior experiment FIM is provided other than the user-specified one + if specified_prior is None: + prior_in_use = self.prior_FIM + else: + prior_in_use = specified_prior + + # Assemble and analyze results + FIM_analysis = FisherResults(list(self.param.keys()), self.measure, jacobian_info=None, all_jacobian_info=jac, + prior_FIM=prior_in_use, store_FIM=FIM_store_name, scale_constant_value=self.scale_constant_value) + + time11 = time.time() + self.logger.info('Build time with sequential_sipopt or kaug mode [s]: %s', sum(time_allbuild)) + self.logger.info('Solve time with sequential_sipopt or kaug mode [s]: %s', sum(time_allsolve)) + self.logger.info('Total wall clock time [s]: %s', time11-time00) + + self.jac = jac + FIM_analysis.build_time = sum(time_allbuild) + FIM_analysis.solve_time = sum(time_allsolve) + + return FIM_analysis + + def _direct_kaug(self): + time00 = time.time() + # create scenario class for a base case + scena_gen = Scenario_generator(self.param, formula=None, step=self.step) + scenario_all = scena_gen.simultaneous_scenario() + + # create model + time0_build = time.time() + mod = self.create_model(scenario_all, args=self.args) + time1_build = time.time() + time_build = time1_build - time0_build + + # discretize if needed + if self.discretize_model: + mod = self.discretize_model(mod) + + time_set_attr = getattr(mod, self.t) + # get all time + t_all = list(time_set_attr) + + # add objective function + mod.Obj = pyo.Objective(expr=0, sense=pyo.minimize) + + # Check if measurement time points are in this time set + # Also correct the measurement time points + # For e.g. if a measurement time point is 0.0 in the model but is given as 0, it is corrected here + measurement_accurate_time = self.flatten_measure_timeset.copy() + + for j in self.flatten_measure_name: + for no_t, tt in enumerate(self.flatten_measure_timeset[j]): + if tt not in t_all: + self.logger.warning('A measurement time point not measured by this model: %s', tt) + else: + measurement_accurate_time[j][no_t] = t_all[t_all.index(tt)] + + # set ub and lb to parameters + for par in list(self.param.keys()): + component = getattr(mod, par)[0] + component.setlb(self.param[par]) + component.setub(self.param[par]) + + # generate parameter name list and value dictionary with index + var_name = [] + var_dict = {} + for name in list(self.param.keys()): + # [0] is the scenario index + var_name.append(name+'[0]') + var_dict[name+'[0]'] = self.param[name] + + # call k_aug get_dsdp function + time0_solve = time.time() + square_result = self._solve_doe(mod, fix=True) + dsdp_re, col = get_dsdp(mod, var_name, var_dict, tee=self.tee_opt) + time1_solve = time.time() + time_solve = time1_solve - time0_solve + + # analyze result + dsdp_array = dsdp_re.toarray().T + self.dsdp = dsdp_array + self.dsdp = col + # store dsdp returned + dsdp_extract = [] + # get right lines from results + measurement_index = [] + # produce the sensitivity for fixed variables + zero_sens = np.zeros(len(self.param)) + + # loop over measurement variables and their time points + for measurement_name in self.measure.model_measure_name: + # get right line number in kaug results + if self.discretize_model: + # for DAE model, some variables are fixed + try: + kaug_no = col.index(measurement_name) + measurement_index.append(kaug_no) + # get right line of dsdp + dsdp_extract.append(dsdp_array[kaug_no]) + except: + self.logger.debug('The variable is fixed: %s', measurement_name) + # for fixed variables, the sensitivity are a zero vector + dsdp_extract.append(zero_sens) + else: + kaug_no = col.index(measurement_name) + measurement_index.append(kaug_no) + # get right line of dsdp + dsdp_extract.append(dsdp_array[kaug_no]) + + # Extract and calculate sensitivity if scaled by constants or parameters. + # Convert sensitivity to a dictionary + jac = {} + for par in list(self.param.keys()): + jac[par] = [] + + for d in range(len(dsdp_extract)): + for p, par in enumerate(list(self.param.keys())): + # if scaled by parameter value or constant value + sensi = dsdp_extract[d][p]*self.scale_constant_value + if self.scale_nominal_param_value: + sensi *= self.param[par] + jac[par].append(sensi) + + time11 = time.time() + self.logger.info('Build time with direct kaug mode [s]: %s', time_build) + self.logger.info('Solve time with direct kaug mode [s]: %s', time_solve) + self.logger.info('Total wall clock time [s]: %s', time11-time00) + + # check if another prior experiment FIM is provided other than the user-specified one + if self.specified_prior is None: + prior_in_use = self.prior_FIM + else: + prior_in_use = self.specified_prior + + # Assemble and analyze results + FIM_analysis = FisherResults(list(self.param.keys()),self.measure, jacobian_info=None, all_jacobian_info=jac, + prior_FIM=prior_in_use, store_FIM=self.FIM_store_name, + scale_constant_value=self.scale_constant_value) + + self.jac = jac + FIM_analysis.build_time = time_build + FIM_analysis.solve_time = time_solve + + + return FIM_analysis + + + def _finite_calculation(self, output_record, scena_gen): + """ + Calculate Jacobian for sequential_finite mode + + Parameters + ---------- + output_record: a dict of outputs, keys are scenario names, values are a list of measurements values + scena_gen: an object generated by Scenario_creator class + + Returns + -------- + jac: Jacobian matrix, a dictionary, keys are parameter names, values are a list of jacobian values with respect to this parameter + """ + # dictionary form of jacobian + jac = {} + + # After collecting outputs from all scenarios, calculate sensitivity + for para in list(self.param.keys()): + # extract involved scenario No. for each parameter from scenario class + involved_s = scena_gen.scenario_para[para] + + # each parameter has two involved scenarios + s1 = involved_s[0] + s2 = involved_s[1] + list_jac = [] + for i in range(len(output_record[s1])): + sensi = (output_record[s1][i] - output_record[s2][i]) / scena_gen.eps_abs[para] * self.scale_constant_value + if self.scale_nominal_param_value: + sensi *= self.param[para] + list_jac.append(sensi) + # get Jacobian dict, keys are parameter name, values are sensitivity info + jac[para] = list_jac + + return jac + + def _extract_jac(self, m): + """ + Extract jacobian from simultaneous mode + Arguments + --------- + m: solved simultaneous model + Returns + ------ + JAC: the overall jacobian as a dictionary + """ + # dictionary form of jacobian + jac = {} + # loop over parameters + for p in list(self.param.keys()): + jac_para = [] + for name1 in self.jac_involved_name: + for tim in self.timepoint_overall_set: + jac_para.append(pyo.value(m.jac[name1, p, tim])) + jac[p] = jac_para + return jac + + def run_grid_search(self, design_values, design_ranges, design_dimension_names, + design_control_time, mode='sequential_finite', tee_option=False, + scale_nominal_param_value=False, scale_constant_value=1, store_name= None, read_name=None, + filename=None, formula='central', step=0.001): + """ + Enumerate through full grid search for any number of design variables; + solve square problems sequentially to compute FIMs. + It calculates FIM with sensitivity information from four modes: + 1. sequential_finite: Calculates a one scenario model multiple times for multiple scenarios. + Sensitivity info estimated by finite difference + 2. sequential_sipopt: calculate sensitivity by sIPOPT [Experimental] + 3. sequential_kaug: calculate sensitivity by k_aug [Experimental] + 4. direct_kaug: calculate sensitivity by k_aug with direct sensitivity + + Parameters + ----------- + design_values: + a ``dict`` where keys are design variable names, values are a dict whose keys are time point and values are the design variable value at that time point + design_ranges: + a ``list`` of design variable values to go over + design_dimension_names: + a ``list`` of design variable names of each design range + design_control_time: + a ``list`` of control time points that should be fixed to the values in dv_ranges + mode: + use mode='sequential_finite', 'sequential_sipopt', 'sequential_kaug', 'direct_kaug' + tee_option: + if solver console output is made + scale_nominal_param_value: + if True, the parameters are scaled by its own nominal value in param_init + scale_constant_value: + scale all elements in Jacobian matrix, default is 1. + store_name: + a string of file name. If not None, store results with this name. + Since there are maultiple experiments, results are numbered with a scalar number, + and the result for one grid is 'store_name(count).csv' (count is the number of count). + read_name: + a string of file name. If not None, read result files. + Since there are multiple experiments, this string should be the common part of all files; + Real name of the file is "read_name(count)", where count is the number of the experiment. + filename: + if True, grid search results stored with this file name + formula: + choose from 'central', 'forward', 'backward', None. This option is only used for 'sequential_finite' mode. + step: + Sensitivity perturbation step size, a fraction between [0,1]. default is 0.001 + + Return + ------- + figure_draw_object: a combined result object of class Grid_search_result + """ + # time 0 + t_enumeration_begin = time.time() + + # Set the Objective Function to 0 helps solve square problem quickly + self.objective_option='zero' + self.filename = filename + + # calculate how much the FIM element is scaled + self.fim_scale_constant_value = scale_constant_value ** 2 + + # when defining design space, design variable values are defined as in design_values argument + # the design var value defined in dv_ranges only applies to control time points given in dv_apply_time + grid_dimension = len(design_ranges) + + # to store all FIM results + result_combine = {} + + # iteration 0 + count = 0 + failed_count = 0 + # how many sets of design variables will be run + total_count = 1 + for rng in design_ranges: + total_count *= len(rng) + + # generate combinations of design variable values to go over + search_design_set = product(*design_ranges) + + build_time_store=[] + solve_time_store=[] + + # loop over design value combinations + for design_set_iter in search_design_set: + # generate the design variable dictionary needed for running compute_FIM + # first copy value from design_values + design_iter = design_values.copy() + + # update the controlled value of certain time points for certain design variables + for i in range(grid_dimension): + for v, value in enumerate(design_control_time[i]): + design_iter[design_dimension_names[i]][value] = list(design_set_iter)[i] + + self.logger.info('=======Iteration Number: %s =====', count+1) + self.logger.debug('Design variable values of this iteration: %s', design_iter) + + # generate store name + if store_name is None: + store_output_name = None + else: + store_output_name = store_name + str(count) + + if read_name: + read_input_name = read_name+str(count) + else: + read_input_name = None + + # call compute_FIM to get FIM + try: + result_iter = self.compute_FIM(design_iter, mode=mode, + tee_opt=tee_option, + scale_nominal_param_value=scale_nominal_param_value, + scale_constant_value = scale_constant_value, + store_output=store_output_name, read_output=read_input_name, + formula=formula, step=step) + if read_input_name is None: + build_time_store.append(result_iter.build_time) + solve_time_store.append(result_iter.solve_time) + + count += 1 + + result_iter.calculate_FIM(self.design_values) + + t_now = time.time() + + # give run information at each iteration + self.logger.info('This is the %s run out of %s run.', count+1, total_count) + self.logger.info('The code has run %s seconds.', t_now-t_enumeration_begin) + self.logger.info('Estimated remaining time: %s seconds', (t_now-t_enumeration_begin)/(count+1)*(total_count-count-1)) + + # the combined result object are organized as a dictionary, keys are a tuple of the design variable values, values are a result object + result_combine[tuple(design_set_iter)] = result_iter + + except: + self.logger.warning(':::::::::::Warning: Cannot converge this run.::::::::::::') + count += 1 + failed_count += 1 + self.logger.warning('failed count:', failed_count) + result_combine[tuple(design_set_iter)] = None + + # For user's access + self.all_fim = result_combine + + # Create figure drawing object + figure_draw_object = GridSearchResult(design_ranges, design_dimension_names, design_control_time, result_combine, store_optimality_name=filename) + + t_enumeration_stop = time.time() + self.logger.info('Overall model building time [s]: %s', sum(build_time_store)) + self.logger.info('Overall model solve time [s]: %s', sum(solve_time_store)) + self.logger.info('Overall wall clock time [s]: %s', t_enumeration_stop - t_enumeration_begin) + + return figure_draw_object + + + def _create_doe_model(self, no_obj=True): + """ + Add equations to compute sensitivities, FIM, and objective. + + Parameters: + ----------- + no_obj: if True, objective function is 0. + self.design_values: a dict of dictionaries, keys are the name of design variables, + values are a dict where keys are the time points, values are the design variable value at that time point + self.optimize: if True, solve the problem unfixing the design variables. if False, solve the problem as a + square problem + self.objective_option: choose from 'det' or 'trace'. Optimization problem maximizes determinant or trace. + self.scale_nominal_param_value: if True, scale FIM but not scale Jacobian. This toggle can be opened for better performance when the + problem is poorly scaled. + self.tee_opt: if True, print IPOPT console output + self.Cholesky_option: if true, cholesky decomposition is used for Objective function (to optimize determinant). + If true, determinant will not be calculated. + self.L_LB: if FIM is P.D., the diagonal element should be positive, so we can set a LB like 1E-10 + self.L_initial: initialize the L + self.formula: choose from 'central', 'forward', 'backward', None + self.step: Sensitivity perturbation step size, a fraction between [0,1]. default is 0.001 + + Return: + ------- + m: the DOE model + """ + # call generator function to get scenario dictionary + scena_gen = Scenario_generator(self.param, formula=self.formula, step=self.step, store=True) + scenario_all = scena_gen.simultaneous_scenario() + + # create model + m = self.create_model(scenario_all, args= self.args) + # discretize if discretization function is provided + if self.discretize_model: + m = self.discretize_model(m) + + # get time set + time_set_attr = getattr(m, self.t) + + # extract (discretized) time + time_set=list(time_set_attr) + self.time_set = time_set + + # create parameter, measurement, time and measurement time set + m.para_set = pyo.Set(initialize=list(self.param.keys())) + param_name = list(self.param.keys()) + m.y_set = pyo.Set(initialize=self.jac_involved_name) + m.t_set = pyo.Set(initialize=time_set) + + m.tmea_set = pyo.Set(initialize=self.timepoint_overall_set) + + # we can be sure about the name of scenarios, because they are generated by our function + m.scenario = pyo.Set(initialize=scenario_all['scena-name']) + m.optimize = self.optimize + + # check if measurement time points are in the time set + for j in m.y_set: + for t in m.tmea_set: + if not (t in time_set_attr): + raise ValueError('Measure timepoints should be in the time list.') + + # check if control time points are in the time set + for d in range(len(self.design_name)): + if self.design_time[d]: + for t in self.design_time[d]: + if not (t in time_set_attr): + raise ValueError('Control timepoints should be in the time list.') + + ### Define variables + # Elements in Jacobian matrix + if self.jac_initial: + dict_jac = {} + for i, bu in enumerate(m.y_set): + for j, un in enumerate(m.para_set): + for t, tim in enumerate(m.tmea_set): + dict_jac[(bu,un,tim)] = self.jac_initial[i,j,t] + + def jac_initialize(m,i,j,t): + return dict_jac[(bu,un,tim)] + + m.jac = pyo.Var(m.y_set, m.para_set, m.tmea_set, initialize=jac_initialize) + + else: + m.jac = pyo.Var(m.y_set, m.para_set, m.tmea_set, initialize=1E-20) + + # Initialize Hessian with an identity matrix + def identity_matrix(m,j,d): + if j==d: + return 1 + else: + return 0 + + # initialize FIM + if self.fim_initial: + dict_fim = {} + for i, bu in enumerate(m.para_set): + for j, un in enumerate(m.para_set): + dict_fim[(bu, un)] = self.fim_initial[i][j] + + def initialize_fim(m, j, d): + return dict_fim[(j,d)] + m.FIM = pyo.Var(m.para_set, m.para_set, initialize=initialize_fim) + else: + m.FIM = pyo.Var(m.para_set, m.para_set, initialize=identity_matrix) + + # move the L matrix initial point to a dictionary + if type(self.L_initial) != type(None): + dict_cho={} + for i, bu in enumerate(m.para_set): + for j, un in enumerate(m.para_set): + dict_cho[(bu,un)] = self.L_initial[i][j] + # use the L dictionary to initialize L matrix + def init_cho(m,i,j): + return dict_cho[(i,j)] + + if self.Cholesky_option: + # Define elements of Cholesky decomposition matrix as Pyomo variables and either + # Initialize with L in L_initial + if type(self.L_initial) != type(None): + m.L_ele = pyo.Var(m.para_set, m.para_set, initialize=init_cho) + # or initialize with the identity matrix + else: + m.L_ele = pyo.Var(m.para_set, m.para_set, initialize=identity_matrix) + + # loop over parameter name + for c in m.para_set: + for d in m.para_set: + # fix the 0 half of L matrix to be 0.0 + if (param_name.index(c) < param_name.index(d)): + m.L_ele[c,d].fix(0.0) + # Give LB to the diagonal entries + if self.L_LB: + if c==d: + m.L_ele[c,d].setlb(self.L_LB) + + + def jac_numerical(m,j,p,t): + """ + Calculate the Jacobian + j: model responses + p: model parameters + t: timepoints + """ + # A better way to do this: + # https://github.com/IDAES/idaes-pse/blob/274e58bef55f2f969f0df97cbb1fb7d99342388e/idaes/apps/uncertainty_propagation/sens.py#L296 + # check if j is a measurement with extra index by checking if there is '_index_' in its name + up_C_name, lo_C_name, legal_t_option = self.measure.SP_measure_name(j,t,scenario_all=scenario_all, mode='simultaneous_finite', p=p) + if legal_t_option: + up_C = eval(up_C_name) + lo_C = eval(lo_C_name) + if self.scale_nominal_param_value: + return m.jac[j, p, t] == (up_C - lo_C) / scenario_all['eps-abs'][p] * self.param[p] * self.scale_constant_value + else: + return m.jac[j, p, t] == (up_C - lo_C) / scenario_all['eps-abs'][p] * self.scale_constant_value + # if t is not measured, let the value be 0 + else: + return m.jac[j, p, t] == 0 + + #A constraint to calculate elements in Hessian matrix + # transfer prior FIM to be Expressions + dict_fele={} + for i, bu in enumerate(m.para_set): + for j, un in enumerate(m.para_set): + dict_fele[(bu,un)] = self.prior_FIM[i][j] + + def ele_todict(m,i,j): + return dict_fele[(i,j)] + m.refele = pyo.Expression(m.para_set, m.para_set, rule=ele_todict) + + def calc_FIM(m,j,d): + """ + Calculate FIM elements + """ + return m.FIM[j,d] == sum(sum(m.jac[z,j,i]*m.jac[z,d,i] for z in m.y_set) for i in m.tmea_set) + m.refele[j, d]*self.fim_scale_constant_value + + ### Constraints and Objective function + m.dC_value = pyo.Constraint(m.y_set, m.para_set, m.tmea_set, rule=jac_numerical) + m.ele_rule = pyo.Constraint(m.para_set, m.para_set, rule=calc_FIM) + + return m + + def _add_objective(self, m): + + def cholesky_imp(m, c, d): + """ + Calculate Cholesky L matrix using algebraic constraints + """ + # If it is the left bottom half of L + if (list(self.param.keys()).index(c) >= list(self.param.keys()).index(d)): + return m.FIM[c, d] == sum( + m.L_ele[c, list(self.param.keys())[k]] * m.L_ele[d, list(self.param.keys())[k]] for k in range(list(self.param.keys()).index(d) + 1)) + else: + # This is the empty half of L above the diagonal + return pyo.Constraint.Skip + + def trace_calc(m): + """ + Calculate FIM elements. Can scale each element with 1000 for performance + """ + return m.trace == sum(m.FIM[j,j] for j in m.para_set) + + def det_general(m): + """Calculate determinant. Can be applied to FIM of any size. + det(A) = sum_{\sigma \in \S_n} (sgn(\sigma) * \Prod_{i=1}^n a_{i,\sigma_i}) + Use permutation() to get permutations, sgn() to get signature + """ + r_list = list(range(len(m.para_set))) + # get all permutations + object_p = permutations(r_list) + list_p = list(object_p) + + # generate a name_order to iterate \sigma_i + det_perm = 0 + for i in range(len(list_p)): + name_order = [] + x_order = list_p[i] + # sigma_i is the value in the i-th position after the reordering \sigma + for x in range(len(x_order)): + for y, element in enumerate(m.para_set): + if x_order[x] == y: + name_order.append(element) + + # det(A) = sum_{\sigma \in \S_n} (sgn(\sigma) * \Prod_{i=1}^n a_{i,\sigma_i}) + det_perm = sum( self._sgn(list_p[d])*sum(m.FIM[each, name_order[b]] for b, each in enumerate(m.para_set)) for d in range(len(list_p))) + return m.det == det_perm + + if self.Cholesky_option: + m.cholesky_cons = pyo.Constraint(m.para_set, m.para_set, rule=cholesky_imp) + m.Obj = pyo.Objective(expr=2 * sum(pyo.log(m.L_ele[j, j]) for j in m.para_set), sense=pyo.maximize) + # if not cholesky but determinant, calculating det and evaluate the OBJ with det + elif (self.objective_option == 'det'): + m.det_rule = pyo.Constraint(rule=det_general) + m.Obj = pyo.Objective(expr=pyo.log(m.det), sense=pyo.maximize) + # if not determinant or cholesky, calculating the OBJ with trace + elif (self.objective_option == 'trace'): + m.trace_rule = pyo.Constraint(rule=trace_calc) + m.Obj = pyo.Objective(expr=pyo.log(m.trace), sense=pyo.maximize) + elif (self.objective_option == 'zero'): + m.Obj = pyo.Objective(expr=0) + + return m + + def _fix_design(self, m, design_val, fix_opt=True, optimize_option=None): + """ + Fix design variable + + Parameters: + ----------- + m: model + design_val: design variable values dict + fix_opt: if True, fix. Else, unfix + optimize: a dictionary, keys are design variable name, values are True or False, deciding if this design variable is optimized as DOF this time + + Returns: + -------- + m: model + """ + # loop over the design variables and time index and to fix values specified in design_val + for d, dname in enumerate(self.design_name): + # if design variables are indexed by time + if self.design_time[d]: + for time in self.design_time[d]: + fix_v = design_val[dname][time] + + if fix_opt: + getattr(m, dname)[time].fix(fix_v) + else: + if optimize_option is None: + getattr(m, dname)[time].unfix() + else: + if optimize_option[dname]: + getattr(m, dname)[time].unfix() + else: + fix_v = design_val[dname][0] + + if fix_opt: + getattr(m, dname).fix(fix_v) + else: + getattr(m, dname).unfix() + return m + + def _get_default_ipopt_solver(self): + """Default solver + """ + solver = SolverFactory('ipopt') + solver.options['linear_solver'] = 'ma57' + solver.options['halt_on_ampl_error'] = 'yes' + solver.options['max_iter'] = 3000 + return solver + + def _solve_doe(self, m, fix=False, opt_option=None): + """Solve DOE model. + If it's a square problem, fix design variable and solve. + Else, fix design variable and solve square problem firstly, then unfix them and solve the optimization problem + + Parameters: + ----------- + m:model + fix: if true, solve two times (square first). Else, just solve the square problem + opt_option: a dictionary, keys are design variable name, values are True or False, + deciding if this design variable is optimized as DOF this time. + If None, all design variables are optimized as DOF this time. + + Return: + ------- + solver_results: solver results + """ + ### Solve square problem + mod = self._fix_design(m, self.design_values, fix_opt=fix, optimize_option=opt_option) + + # if user gives solver, use this solver. if not, use default IPOPT solver + solver_result = self.solver.solve(mod,tee=self.tee_opt) + + return solver_result + + def _add_parameter(self, m, perturb=0): + """ + For sIPOPT: add parameter perturbation set + + Parameters: + ----------- + m: model name + perturb: which parameter to perturb + """ + # model parameters perturbation, backward disturb + param_backward = self.param_value.copy() + # perturb parameter + param_backward[perturb] *= (1-self.step) + + # generate sIPOPT perturbed parameter names + param_perturb_names = list(self.param.keys()).copy() + for x, xname in enumerate(list(self.param.keys())): + param_perturb_names[x] = xname+'_pert' + + self.perturb_names = param_perturb_names + + for change in range(len(self.perturb_names)): + setattr(m, self.perturb_names[change], Param(m.scena, initialize=param_backward[change])) + return m + + def _sgn(self,p): + """ + This is a helper function for stochastic_program function to compute the determinant formula. + Give the signature of a permutation + + Parameters: + ----------- + p: the permutation (a list) + + Return: + ------ + 1 if the number of exchange is an even number + -1 if the number is an odd number + """ + + if len(p) == 1: + return 1 + + trans = 0 + + for i in range(0, len(p)): + j = i + 1 + + for j in range(j, len(p)): + if p[i] > p[j]: + trans = trans + 1 + + if (trans % 2) == 0: + return 1 + else: + return -1 + + + + diff --git a/pyomo/contrib/doe/example/__init__.py b/pyomo/contrib/doe/example/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/pyomo/contrib/doe/example/fim_5_300_500_scale.csv b/pyomo/contrib/doe/example/fim_5_300_500_scale.csv new file mode 100644 index 00000000000..77c0424aa13 --- /dev/null +++ b/pyomo/contrib/doe/example/fim_5_300_500_scale.csv @@ -0,0 +1,5 @@ +A1,A2,E1,E2 +28.678928056936364,5.412497388906993,-81.73674601413501,-24.023773235011475 +5.412497388906993,26.409350356572013,-12.418164773953235,-139.2399253159117 +-81.73674601413501,-12.418164773953235,240.46276003997696,58.764228064029076 +-24.023773235011475,-139.2399253159117,58.764228064029076,767.255845082616 diff --git a/pyomo/contrib/doe/example/fim_5_300_scale.csv b/pyomo/contrib/doe/example/fim_5_300_scale.csv new file mode 100644 index 00000000000..381e916b9d4 --- /dev/null +++ b/pyomo/contrib/doe/example/fim_5_300_scale.csv @@ -0,0 +1,5 @@ +A1,A2,E1,E2 +22.529430237938822,1.8403431417002734,-70.23273336318343,-11.094329617631416 +1.8403431417002734,18.098481155262718,-5.7356503398877745,-109.15866135211135 +-70.23273336318343,-5.7356503398877745,218.9419284259853,34.576808479575064 +-11.094329617631416,-109.15866135211135,34.576808479575064,658.3764463408718 diff --git a/pyomo/contrib/doe/example/reactor_compute_FIM.py b/pyomo/contrib/doe/example/reactor_compute_FIM.py new file mode 100644 index 00000000000..fb2977463ce --- /dev/null +++ b/pyomo/contrib/doe/example/reactor_compute_FIM.py @@ -0,0 +1,116 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + + +import numpy as np +import pyomo.common.unittest as unittest +from pyomo.contrib.doe.example.reactor_kinetics import create_model, disc_for_measure +from pyomo.contrib.doe import Measurements, DesignOfExperiments + + +def main(): + # Create model function + ## TODO: use create_model directly + createmod = create_model + + # discretization by Pyomo.DAE + ## TODO: directly use + disc = disc_for_measure + + # Control time set [h] + t_control = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + + # Measurement time points [h] + t_measure = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + + # design variable and its control time set + dv_pass = {'CA0': [0],'T': t_control} + + # Create measurement object + measure_pass = {'C':{'CA': t_measure, 'CB': t_measure, 'CC': t_measure}} + measure_class = Measurements(measure_pass) + + # Define parameter nominal value + parameter_dict = {'A1': 84.79085853498033, 'A2': 371.71773413976416, 'E1': 7.777032028026428, 'E2': 15.047135137500822} + + def generate_exp(t_set, CA0, T): + """Generate experiments. + t_set: time control set for T. + CA0: CA0 value + T: A list of T + """ + assert(len(t_set)==len(T)), 'T should have the same length as t_set' + + T_con_initial = {} + for t, tim in enumerate(t_set): + T_con_initial[tim] = T[t] + + dv_dict_overall = {'CA0': {0: CA0},'T': T_con_initial} + return dv_dict_overall + + # empty prior + prior_all = np.zeros((4,4)) + prior_pass=np.asarray(prior_all) + + # choose from 'sequential_finite', 'direct_kaug' + # 'sequential_sipopt', 'sequential_kaug' is also available + #sensi_opt = 'sequential_finite' + sensi_opt = 'direct_kaug' + + # model option + if sensi_opt == 'direct_kaug': + args_ = [False] + else: + args_ = [True] + + + # Define experiments + exp1 = generate_exp(t_control, 5, [570, 300, 300, 300, 300, 300, 300, 300, 300]) + + doe_object = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior_pass, discretize_model=disc, args=args_) + + + result = doe_object.compute_FIM(exp1, mode=sensi_opt, + scale_nominal_param_value=True, + formula='central') + + + result.calculate_FIM(doe_object.design_values) + + # test result + relative_error = abs(np.log10(result.trace) - 2.7885870986653556) + assert relative_error < 0.01 + + relative_error = abs(np.log10(result.det) - 2.82184091661587) + assert relative_error < 0.01 + +if __name__ == "__main__": + main() + diff --git a/pyomo/contrib/doe/example/reactor_grid_search.py b/pyomo/contrib/doe/example/reactor_grid_search.py new file mode 100644 index 00000000000..cb3958113fd --- /dev/null +++ b/pyomo/contrib/doe/example/reactor_grid_search.py @@ -0,0 +1,143 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +import numpy as np +import pyomo.common.unittest as unittest +from pyomo.contrib.doe.example.reactor_kinetics import create_model, disc_for_measure +from pyomo.contrib.doe import Measurements, DesignOfExperiments + + +def main(): + # Create model function + createmod = create_model + + # discretization by Pyomo.DAE + disc = disc_for_measure + + # Control time set [h] + t_control = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + + # Measurement time points [h] + t_measure = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + + # design variable and its control time set + dv_pass = {'CA0': [0],'T': t_control} + + # Create measurement object + measure_pass = {'C':{'CA': t_measure, 'CB': t_measure, 'CC': t_measure}} + measure_class = Measurements(measure_pass) + + # Define parameter nominal value + parameter_dict = {'A1': 84.79085853498033, 'A2': 371.71773413976416, 'E1': 7.777032028026428, 'E2': 15.047135137500822} + + def generate_exp(t_set, CA0, T): + """Generate experiments. + t_set: time control set for T. + CA0: CA0 value + T: A list of T + """ + assert(len(t_set)==len(T)), 'T should have the same length as t_set' + + T_con_initial = {} + for t, tim in enumerate(t_set): + T_con_initial[tim] = T[t] + + dv_dict_overall = {'CA0': {0: CA0},'T': T_con_initial} + return dv_dict_overall + + # Design variable ranges as lists + design_ranges = [list(np.linspace(1,5,5)), list(np.linspace(300,700,5))] + + # Design variable names + dv_apply_name = ['CA0','T'] + + # Design variable should be fixed at these time points + dv_apply_time = [[0],t_control] + + # Define experiments. This is a starting point of which the value does not matter + exp1 = generate_exp(t_control, 5, [300, 300, 300, 300, 300, 300, 300, 300, 300]) + + ## choose from 'sequential_finite', 'direct_kaug' + #sensi_opt = 'sequential_finite' + sensi_opt = 'direct_kaug' + + # model option + if sensi_opt == 'direct_kaug': + args_ = [False] + else: + args_ = [True] + + # add prior information + prior_all = np.zeros((4,4)) + + prior_pass=np.asarray(prior_all) + + doe_object = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior_pass, discretize_model=disc, args=args_) + + all_fim = doe_object.run_grid_search(exp1, design_ranges, dv_apply_name, dv_apply_time, + mode=sensi_opt) + + test = all_fim.extract_criteria() + + + ### 3 design variable example + # Define design ranges + design_ranges = [list(np.linspace(1,5,2)), list(np.linspace(300,700,2)), [300,500]] + + # Define design variable + # Here the two T are for different controlling time subsets + dv_apply_name = ['CA0', 'T', 'T'] + dv_apply_time = [[0], [0], [0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875,1]] + + # Define experiments + exp1 = generate_exp(t_control, 5, [300, 300, 300, 300, 300, 300, 300, 300, 300]) + + ## choose from 'sequential_finite', 'direct_kaug' + #sensi_opt = 'sequential_finite' + sensi_opt = 'direct_kaug' + + # model option + if sensi_opt == 'direct_kaug': + args_ = [False] + else: + args_ = [True] + + doe_object = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior_pass, discretize_model=disc, args=args_) + + all_fim = doe_object.run_grid_search(exp1, design_ranges, dv_apply_name, dv_apply_time, + mode=sensi_opt) + + test = all_fim.extract_criteria() + + +if __name__ == "__main__": + main() diff --git a/pyomo/contrib/doe/example/reactor_kinetics.py b/pyomo/contrib/doe/example/reactor_kinetics.py new file mode 100644 index 00000000000..6ff596b17fb --- /dev/null +++ b/pyomo/contrib/doe/example/reactor_kinetics.py @@ -0,0 +1,237 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +import pyomo.environ as pyo +from pyomo.dae import ContinuousSet, DerivativeVar +import numpy as np +from pyomo.contrib.doe import Measurements + +def disc_for_measure(m, NFE=32): + """Pyomo.DAE discretization + """ + discretizer = pyo.TransformationFactory('dae.collocation') + discretizer.apply_to(m, nfe=NFE, ncp=3, wrt=m.t) + for z in m.scena: + for t in m.t: + m.dCdt_rule[z,'CC',t].deactivate() + return m + + +def create_model(scena, const=False, control_time=None, control_val=None, + t_range=[0.0,1], CA_init=1, C_init=0.1, model_form='dae-index-1', args=[True]): + """ + This is an example user model provided to DoE library. + It is a dynamic problem solved by Pyomo.DAE. + + Arguments + --------- + scena: a dictionary of scenarios, achieved from scenario_generator() + control_time: time-dependent design (control) variables, a list of control timepoints + control_val: control design variable values T at corresponding timepoints + t_range: time range, h + CA_init: time-independent design (control) variable, an initial value for CA + C_init: An initial value for C + model_form: choose from 'ode-index-0' and 'dae-index-1' + args: a list, deciding if the model is for k_aug or not. If [False], it is for k_aug, the parameters are defined as Var instead of Param. + + Return + ------ + m: a Pyomo.DAE model + """ + # parameters initialization, results from parameter estimation + theta_pe = {'A1': 84.79085853498033, 'A2': 371.71773413976416, 'E1': 7.777032028026428, 'E2': 15.047135137500822} + # concentration initialization + y_init = {'CA': CA_init, 'CB':0.0, 'CC':0.0} + + para_list = ['A1', 'A2', 'E1', 'E2'] + + if not control_time: + control_time = [0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1] + + if not control_val: + control_val = [300]*9 + + controls = {} + for i, t in enumerate(control_time): + controls[t]=control_val[i] + + ### Add variables + m = pyo.ConcreteModel() + + m.CA_init = CA_init + m.para_list = para_list + t_control = control_time + + m.scena_all = scena + m.scena = pyo.Set(initialize=scena['scena-name']) + + if model_form == 'ode-index-0': + m.index1 = False + elif model_form == 'dae-index-1': + m.index1 = True + else: + raise ValueError('Please choose from "ode-index-0" and "dae-index-1"') + + # timepoints + m.t = ContinuousSet(bounds=(t_range[0], t_range[1])) + + # Control time points + m.t_con = pyo.Set(initialize=t_control) + + m.t0 = pyo.Set(initialize=[0]) + + # time-independent design variable + m.CA0 = pyo.Var(m.t0, initialize = CA_init, bounds=(1.0,5.0), within=pyo.NonNegativeReals) # mol/L + + # time-dependent design variable, initialized with the first control value + def T_initial(m,t): + if t in m.t_con: + return controls[t] + else: + # count how many control points are before the current t; + # locate the nearest neighbouring control point before this t + j = -1 + for t_con in m.t_con: + if t>t_con: + j+=1 + neighbour_t = t_control[j] + return controls[neighbour_t] + + m.T = pyo.Var(m.t, initialize =T_initial, bounds=(300, 700), within=pyo.NonNegativeReals) + + m.R = 8.31446261815324 # J / K / mole + + # Define parameters as Param + if args[0]: + m.A1 = pyo.Param(m.scena, initialize=scena['A1'],mutable=True) + m.A2 = pyo.Param(m.scena, initialize=scena['A2'],mutable=True) + m.E1 = pyo.Param(m.scena, initialize=scena['E1'],mutable=True) + m.E2 = pyo.Param(m.scena, initialize=scena['E2'],mutable=True) + + # if False, define parameters as Var (for k_aug) + else: + m.A1 = pyo.Var(m.scena, initialize = m.scena_all['A1']) + m.A2 = pyo.Var(m.scena, initialize = m.scena_all['A2']) + m.E1 = pyo.Var(m.scena, initialize = m.scena_all['E1']) + m.E2 = pyo.Var(m.scena, initialize = m.scena_all['E2']) + + # Concentration variables under perturbation + m.C_set = pyo.Set(initialize=['CA','CB','CC']) + m.C = pyo.Var(m.scena, m.C_set, m.t, initialize=C_init, within=pyo.NonNegativeReals) + + # time derivative of C + m.dCdt = DerivativeVar(m.C, wrt=m.t) + + # kinetic parameters + def kp1_init(m,s,t): + return m.A1[s] * pyo.exp(-m.E1[s]*1000/(m.R*m.T[t])) + def kp2_init(m,s,t): + return m.A2[s] * pyo.exp(-m.E2[s]*1000/(m.R*m.T[t])) + + m.kp1 = pyo.Var(m.scena, m.t, initialize=kp1_init) + m.kp2 = pyo.Var(m.scena, m.t, initialize=kp2_init) + + + def T_control(m,t): + """ + T at interval timepoint equal to the T of the control time point at the beginning of this interval + Count how many control points are before the current t; + locate the nearest neighbouring control point before this t + """ + if t in m.t_con: + return pyo.Constraint.Skip + else: + j = -1 + for t_con in m.t_con: + if t>t_con: + j+=1 + neighbour_t = t_control[j] + return m.T[t] == m.T[neighbour_t] + + + def cal_kp1(m,z,t): + """ + Create the perturbation parameter sets + m: model + z: scenario number + t: time + """ + # LHS: 1/h + # RHS: 1/h*(kJ/mol *1000J/kJ / (J/mol/K) / K) + return m.kp1[z,t] == m.A1[z]*pyo.exp(-m.E1[z]*1000/(m.R*m.T[t])) + + def cal_kp2(m,z,t): + """ + Create the perturbation parameter sets + m: model + z: m.pert, upper or normal or lower perturbation + t: time + """ + # LHS: 1/h + # RHS: 1/h*(kJ/mol *1000J/kJ / (J/mol/K) / K) + return m.kp2[z,t] == m.A2[z]*pyo.exp(-m.E2[z]*1000/(m.R*m.T[t])) + + def dCdt_control(m,z,y,t): + """ + Calculate CA in Jacobian matrix analytically + z: scenario No. + y: CA, CB, CC + t: timepoints + """ + if y=='CA': + return m.dCdt[z,y,t] == -m.kp1[z,t]*m.C[z,'CA',t] + elif y=='CB': + return m.dCdt[z,y,t] == m.kp1[z,t]*m.C[z,'CA',t] - m.kp2[z,t]*m.C[z,'CB',t] + elif y=='CC': + return m.dCdt[z,y,t] == m.kp2[z,t]*m.C[z,'CB',t] + + def alge(m,z,t): + """ + The algebraic equation for mole balance + z: m.pert + t: time + """ + return m.C[z,'CA',t] + m.C[z,'CB',t] + m.C[z,'CC', t] == m.CA0[0] + + + # Control time + m.T_rule = pyo.Constraint(m.t, rule=T_control) + + # calculating C, Jacobian, FIM + m.k1_pert_rule = pyo.Constraint(m.scena, m.t, rule=cal_kp1) + m.k2_pert_rule = pyo.Constraint(m.scena, m.t, rule=cal_kp2) + m.dCdt_rule = pyo.Constraint(m.scena,m.C_set, m.t, rule=dCdt_control) + + m.alge_rule = pyo.Constraint(m.scena, m.t, rule=alge) + + # B.C. + for z in m.scena: + m.C[z,'CB',0.0].fix(0.0) + m.C[z,'CC',0.0].fix(0.0) + + return m diff --git a/pyomo/contrib/doe/example/reactor_optimize_doe.py b/pyomo/contrib/doe/example/reactor_optimize_doe.py new file mode 100644 index 00000000000..05b63d72b3c --- /dev/null +++ b/pyomo/contrib/doe/example/reactor_optimize_doe.py @@ -0,0 +1,91 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + +import numpy as np +import pyomo.common.unittest as unittest +from pyomo.contrib.doe.example.reactor_kinetics import create_model, disc_for_measure +from pyomo.contrib.doe import Measurements, DesignOfExperiments + +def main(): + # Create model function + createmod = create_model + + # discretization by Pyomo.DAE + disc = disc_for_measure + + # Control time set [h] + t_control = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + + # Measurement time points [h] + t_measure = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + + # design variable and its control time set + dv_pass = {'CA0': [0],'T': t_control} + + # Create measurement object + measure_pass = {'C':{'CA': t_measure, 'CB': t_measure, 'CC': t_measure}} + measure_class = Measurements(measure_pass) + + # Define parameter nominal value + parameter_dict = {'A1': 84.79085853498033, 'A2': 371.71773413976416, 'E1': 7.777032028026428, 'E2': 15.047135137500822} + + def generate_exp(t_set, CA0, T): + """Generate experiments. + t_set: time control set for T. + CA0: CA0 value + T: A list of T + """ + assert(len(t_set)==len(T)), 'T should have the same length as t_set' + + T_con_initial = {} + for t, tim in enumerate(t_set): + T_con_initial[tim] = T[t] + + dv_dict_overall = {'CA0': {0: CA0},'T': T_con_initial} + return dv_dict_overall + + # prior + exp1 = generate_exp(t_control, 3, [500, 300, 300, 300, 300, 300, 300, 300, 300]) + + # add a prior information (scaled FIM with T=500 and T=300 experiments) + prior = np.asarray([[ 28.67892806 , 5.41249739 , -81.73674601 , -24.02377324], + [ 5.41249739 , 26.40935036 , -12.41816477 , -139.23992532], + [ -81.73674601 , -12.41816477 , 240.46276004 , 58.76422806], + [ -24.02377324 , -139.23992532 , 58.76422806 , 767.25584508]]) + + + doe_object = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior, discretize_model=disc, args=[True]) + + square_result, optimize_result= doe_object.stochastic_program(exp1, if_optimize=True, if_Cholesky=True, + scale_nominal_param_value=True, objective_option='det', + L_initial=np.linalg.cholesky(prior)) + + +if __name__ == "__main__": + main() diff --git a/pyomo/contrib/doe/fim_doe_tutorial.ipynb b/pyomo/contrib/doe/fim_doe_tutorial.ipynb new file mode 100644 index 00000000000..853ddff7372 --- /dev/null +++ b/pyomo/contrib/doe/fim_doe_tutorial.ipynb @@ -0,0 +1,1597 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Reactor Kinetics Example \n", + "\n", + "Jialu Wang (jwang44@nd.edu) and Alex Dowling (adowling@nd.edu)\n", + "\n", + "University of Notre Dame\n", + "\n", + "This notebook conducts design of experiments for a reactor kinetics experiment with the Pyomo.DoE.\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 0: Import Pyomo and Pyomo.DoE module" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "import pyomo.environ as pyo\n", + "import pyomo.common.unittest as unittest\n", + "from pyomo.contrib.doe import DesignOfExperiments, Measurements" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "## check if ipopt available \n", + "\n", + "ipopt_available = pyo.SolverFactory('ipopt').available()\n", + "\n", + "if not (ipopt_available):\n", + " raise RuntimeError('This Pyomo.DoE example requires Ipopt.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 1: Import Reaction Example Mathematical Model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Consider two chemical reactions that convert molecule $A$ to desired product $B$ and a less valuable side-product $C$.\n", + "\n", + "$A \\overset{k_1}{\\rightarrow} B \\overset{k_2}{\\rightarrow} C$\n", + "\n", + "Our ultimate goal is to design a large-scale continous reactor that maximizes the production of $B$. This general sequential reactions problem is widely applicable to CO$_2$ capture and industry more broadly (petrochemicals, pharmaceuticals, etc.).\n", + "\n", + "The rate laws for these two chemical reactions are:\n", + "\n", + "$r_A = -k_1 C_A$\n", + "\n", + "$r_B = k_1 C_A - k_2 C_B$\n", + "\n", + "$r_C = k_2 C_B$\n", + "\n", + "Here, $C_A$, $C_B$, and $C_C$ are the concentrations of each species. The rate constants $k_1$ and $k_2$ depend on temperature as follows:\n", + "\n", + "$k_1 = A_1 \\exp{\\frac{-E_1}{R T}}$\n", + "\n", + "$k_2 = A_2 \\exp{\\frac{-E_2}{R T}}$\n", + "\n", + "$A_1, A_2, E_1$, and $E_2$ are fitted model parameters. $R$ is the ideal-gas constant and $T$ is absolute temperature.\n", + "\n", + "Using the **CCSI$^2$ toolset**, we would like to perform **uncertainty quantification** and **design of experiments** on a small-scale **batch reactor** to infer parameters $A_1$, $A_2$, $E_1$, and $E_2$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Batch reactor\n", + "\n", + "The concentrations in a batch reactor evolve with time per the following differential equations:\n", + "\n", + "$$ \\frac{d C_A}{dt} = r_A = -k_1 C_A $$\n", + "\n", + "$$ \\frac{d C_B}{dt} = r_B = k_1 C_A - k_2 C_B $$\n", + "\n", + "$$ \\frac{d C_C}{dt} = r_C = k_2 C_B $$\n", + "\n", + "This is a linear system of differential equations. Assuming the feed is only species $A$, i.e., \n", + "\n", + "$$C_A(t=0) = C_{A0} \\quad C_B(t=0) = 0 \\quad C_C(t=0) = 0$$\n", + "\n", + "When the temperature is constant, it leads to the following analytic solution:\n", + "\n", + "$$C_A(t) = C_{A,0} \\exp(-k_1 t)$$\n", + "\n", + "$$C_B(t) = \\frac{k_1}{k_2 - k_1} C_{A,0} \\left[\\exp(-k_1 t) - \\exp(-k_2 t) \\right]$$\n", + "\n", + "$$C_C(t) = C_{A,0} - \\frac{k_2}{k_2 - k_1} C_{A,0} \\exp(-k_1 t) + \\frac{k_1}{k_2 - k_1} \\exp(-k_2 t) C_{A,0} = C_{A,0} - C_{A}(t) - C_{B}(t)$$" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# The model is implemented in reactor_kinetics.py \n", + "from pyomo.contrib.doe.example.reactor_kinetics import create_model, disc_for_measure" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Define inputs" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Create model function\n", + "createmod = create_model\n", + "\n", + "# discretization by Pyomo.DAE\n", + "disc = disc_for_measure\n", + "\n", + "# Control time set [h]\n", + "t_control = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]\n", + " \n", + "# Measurement time points [h]\n", + "t_measure = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]\n", + "\n", + "# design variable and its control time set\n", + "dv_pass = {'CA0': [0],'T': t_control}\n", + " \n", + "# Create measurement object\n", + "measure_pass = {'C':{'CA': t_measure, 'CB': t_measure, 'CC': t_measure}}\n", + "measure_class = Measurements(measure_pass)\n", + "\n", + "# Define parameter nominal value \n", + "parameter_dict = {'A1': 84.79085853498033, 'A2': 371.71773413976416, 'E1': 7.777032028026428, 'E2': 15.047135137500822}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_exp(t_set, CA0, T): \n", + " \"\"\"Generate experiments. \n", + " t_set: time control set for T.\n", + " CA0: CA0 value\n", + " T: A list of T \n", + " \"\"\"\n", + " assert(len(t_set)==len(T)), 'T should have the same length as t_set'\n", + " \n", + " T_con_initial = {}\n", + " for t, tim in enumerate(t_set):\n", + " T_con_initial[tim] = T[t]\n", + " \n", + " dv_dict_overall = {'CA0': {0: CA0},'T': T_con_initial}\n", + " return dv_dict_overall" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The prior information FIM: [[0. 0. 0. 0.]\n", + " [0. 0. 0. 0.]\n", + " [0. 0. 0. 0.]\n", + " [0. 0. 0. 0.]]\n", + "Prior Det: 0.0\n", + "Eigenvalue of the prior experiments FIM: [0. 0. 0. 0.]\n" + ] + } + ], + "source": [ + "# empty prior\n", + "prior_pass = np.zeros((4,4))\n", + "\n", + "print('The prior information FIM:', prior_pass)\n", + "print('Prior Det:', np.linalg.det(prior_pass))\n", + "print('Eigenvalue of the prior experiments FIM:', np.linalg.eigvals(prior_pass))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Method: Compute FIM \n", + "\n", + "This method computes an MBDoE optimization problem with no degrees of freedom." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# choose from 'sequential_finite', 'direct_kaug'\n", + "# 'sequential_sipopt', 'sequential_kaug' is also available\n", + "sensi_opt = 'sequential_finite'\n", + "#sensi_opt = 'direct_kaug'\n", + "\n", + "# model option\n", + "if sensi_opt == 'direct_kaug':\n", + " args_ = [False]\n", + "else:\n", + " args_ = [True]\n", + " \n", + "\n", + "# Define experiments\n", + "exp1 = generate_exp(t_control, 5, [570, 300, 300, 300, 300, 300, 300, 300, 300])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.10e+01 9.48e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.87e+02 -1.0 6.24e+01 - 6.67e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.83e-02 5.00e+01 -1.0 1.07e+01 - 8.50e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.57e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6916068545924645e-10 1.6916068545924645e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6916068545924645e-10 1.6916068545924645e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.004\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.09e+01 9.48e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.87e+02 -1.0 6.23e+01 - 6.67e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.83e-02 4.98e+01 -1.0 1.07e+01 - 8.51e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.58e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6933299207266828e-10 1.6933299207266828e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6933299207266828e-10 1.6933299207266828e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.08e+01 9.47e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.87e+02 -1.0 6.22e+01 - 6.67e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.85e-02 5.02e+01 -1.0 1.07e+01 - 8.50e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.58e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6942003355779889e-10 1.6942003355779889e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6942003355779889e-10 1.6942003355779889e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.003\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.09e+01 9.50e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.88e+02 -1.0 6.23e+01 - 6.65e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.83e-02 4.98e+01 -1.0 1.07e+01 - 8.51e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.57e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6935253199790168e-10 1.6935253199790168e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6935253199790168e-10 1.6935253199790168e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.08e+01 9.48e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.87e+02 -1.0 6.23e+01 - 6.67e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.83e-02 4.95e+01 -1.0 1.07e+01 - 8.52e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.57e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6902212962577323e-10 1.6902212962577323e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6902212962577323e-10 1.6902212962577323e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.09e+01 9.48e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.87e+02 -1.0 6.23e+01 - 6.67e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.82e-02 4.98e+01 -1.0 1.07e+01 - 8.51e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.57e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6884449394183321e-10 1.6884449394183321e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6884449394183321e-10 1.6884449394183321e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.007\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.10e+01 9.49e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.87e+02 -1.0 6.24e+01 - 6.67e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.81e-02 4.93e+01 -1.0 1.07e+01 - 8.53e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.70e+02 -1.0 3.57e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6875745245670259e-10 1.6875745245670259e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6875745245670259e-10 1.6875745245670259e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.011\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2955\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 281\n", + "\n", + "Total number of variables............................: 861\n", + " variables with only lower bounds: 289\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 861\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 2.67e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (25018)\n", + " 1 0.0000000e+00 6.09e+01 9.46e+01 -1.0 2.67e+02 - 1.10e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 1.74e+01 2.85e+02 -1.0 6.23e+01 - 6.69e-02 9.90e-01h 1\n", + " 3 0.0000000e+00 6.83e-02 4.97e+01 -1.0 1.07e+01 - 8.51e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.69e-10 2.71e+02 -1.0 3.57e-02 - 9.92e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.6882317765976040e-10 1.6882317765976040e-10\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.6882317765976040e-10 1.6882317765976040e-10\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.003\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "source": [ + "doe_object = DesignOfExperiments(parameter_dict, dv_pass,\n", + " measure_class, createmod,\n", + " prior_FIM=prior_pass, discretize_model=disc, args=args_)\n", + "\n", + "\n", + "result = doe_object.compute_FIM(exp1, mode=sensi_opt, FIM_store_name = 'dynamic.csv', \n", + " store_output = 'store_output', read_output=None,\n", + " scale_nominal_param_value=True,\n", + " formula='central')\n", + "\n", + "\n", + "result.calculate_FIM(doe_object.design_values)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======Result summary======\n", + "Four design criteria log10() value:\n", + "A-optimality: 2.7885851762996685\n", + "D-optimality: 2.8218397017198344\n", + "E-optimality: -1.0123416986411815\n", + "Modified E-optimality: 3.7813961591496428\n" + ] + } + ], + "source": [ + "print('======Result summary======')\n", + "print('Four design criteria log10() value:')\n", + "print('A-optimality:', np.log10(result.trace))\n", + "print('D-optimality:', np.log10(result.det))\n", + "print('E-optimality:', np.log10(result.min_eig))\n", + "print('Modified E-optimality:', np.log10(result.cond))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Method: Optimization\n", + "Gradient-based optimization with IPOPT with .optimize_doe()\n", + "\n", + "This function solves twice: It solves the square version of the MBDoE problem first, and then unfixes the design variables as degree of freedom and solves again. In this way the optimization problem can be well initialized. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "exp1 = generate_exp(t_control, 3, [500, 300, 300, 300, 300, 300, 300, 300, 300])\n", + "\n", + "# add a prior information (scaled FIM with T=500 and T=300 experiments)\n", + "prior = np.asarray([[ 28.67892806 , 5.41249739 , -81.73674601 , -24.02377324],\n", + " [ 5.41249739 , 26.40935036 , -12.41816477 , -139.23992532],\n", + " [ -81.73674601 , -12.41816477 , 240.46276004 , 58.76422806],\n", + " [ -24.02377324 , -139.23992532 , 58.76422806 , 767.25584508]])\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 24104\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1902\n", + "\n", + "Total number of variables............................: 6396\n", + " variables with only lower bounds: 2312\n", + " variables with lower and upper bounds: 88\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 6396\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.66e+02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (282318)\n", + " 1 0.0000000e+00 2.50e+02 6.49e+01 -1.0 7.66e+02 - 1.49e-02 9.90e-01f 1\n", + " 2 0.0000000e+00 5.19e+01 7.82e+01 -1.0 3.36e+02 - 1.17e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.71e+00 3.25e+00 -1.0 5.49e+01 - 9.90e-01 1.00e+00h 1\n", + " 4 0.0000000e+00 1.19e-05 7.45e-05 -1.0 6.81e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 2.96e-13 1.50e-09 -3.8 1.19e-05 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 5\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 1.1368683772161603e-13 2.9576341376014170e-13\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 1.1368683772161603e-13 2.9576341376014170e-13\n", + "\n", + "\n", + "Number of objective function evaluations = 6\n", + "Number of objective gradient evaluations = 6\n", + "Number of equality constraint evaluations = 6\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 6\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 5\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.136\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "Ipopt 3.13.2: linear_solver=ma57\n", + "halt_on_ampl_error=yes\n", + "max_iter=3000\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 25152\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1931\n", + "\n", + "Reallocating memory for MA57: lfact (321469)\n", + "Reallocating memory for MA57: lfact (338851)\n", + "Total number of variables............................: 6416\n", + " variables with only lower bounds: 2316\n", + " variables with lower and upper bounds: 98\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 6406\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 -1.1850752e+01 2.77e+02 1.75e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 -1.3363241e+01 5.90e+01 2.13e+00 -1.0 6.01e+01 - 7.77e-01 1.00e+00f 1\n", + " 2 -1.3735798e+01 6.42e+01 4.93e+00 -1.0 2.99e+02 - 7.67e-01 1.00e+00f 1\n", + " 3 -1.3924774e+01 6.42e+01 1.04e+01 -1.0 1.70e+03 - 7.85e-01 6.71e-02f 1\n", + " 4 -1.3625709e+01 6.26e+01 1.84e+01 -1.0 9.51e+02 - 3.95e-01 1.33e-01f 1\n", + " 5 -1.3304833e+01 1.42e+01 1.31e+01 -1.0 4.29e+01 - 1.00e+00 1.00e+00f 1\n", + " 6 -1.3385384e+01 2.75e+00 7.51e-01 -1.0 1.40e+02 - 1.00e+00 1.00e+00h 1\n", + " 7 -1.3365256e+01 7.10e-02 2.39e-01 -1.0 4.79e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 -1.3371365e+01 3.75e-03 2.13e-02 -1.7 4.51e+00 - 1.00e+00 1.00e+00h 1\n", + " 9 -1.3409142e+01 1.65e-01 1.26e+00 -3.8 2.48e+01 - 8.96e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 -1.3724333e+01 1.21e+01 2.06e+01 -3.8 9.21e+01 - 6.78e-01 1.00e+00h 1\n", + " 11 -1.4459349e+01 7.62e+01 8.38e+01 -3.8 6.43e+02 - 1.69e-01 2.91e-01h 1\n", + " 12 -1.4309962e+01 2.80e+01 5.98e+00 -3.8 1.88e+02 - 7.28e-01 1.00e+00h 1\n", + " 13 -1.4294801e+01 8.04e-01 1.48e+00 -3.8 1.58e+01 - 1.00e+00 1.00e+00h 1\n", + " 14 -1.4293468e+01 1.20e-01 3.70e-02 -3.8 1.55e+01 - 1.00e+00 1.00e+00h 1\n", + " 15 -1.4293051e+01 1.85e-05 3.16e-06 -3.8 1.60e-01 - 1.00e+00 1.00e+00h 1\n", + " 16 -1.4310193e+01 1.00e+00 4.13e-01 -5.7 4.55e+01 - 9.17e-01 1.00e+00f 1\n", + " 17 -1.4308345e+01 8.84e-03 3.25e-03 -5.7 4.40e+00 - 1.00e+00 1.00e+00h 1\n", + " 18 -1.4308378e+01 1.74e-05 9.73e-07 -5.7 3.79e-01 - 1.00e+00 1.00e+00h 1\n", + " 19 -1.4308538e+01 2.20e-04 8.75e-05 -8.6 6.45e-01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 -1.4308537e+01 6.25e-10 1.57e-10 -8.6 2.27e-03 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 20\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: -1.4308537315179255e+01 -1.4308537315179255e+01\n", + "Dual infeasibility......: 1.5671067085104752e-10 1.5671067085104752e-10\n", + "Constraint violation....: 6.2476324114157933e-10 6.2476324114157933e-10\n", + "Complementarity.........: 2.5063247871462084e-09 2.5063247871462084e-09\n", + "Overall NLP error.......: 2.5063247871462084e-09 2.5063247871462084e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 21\n", + "Number of objective gradient evaluations = 21\n", + "Number of equality constraint evaluations = 21\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 21\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 20\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.557\n", + "Total CPU secs in NLP function evaluations = 0.030\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "source": [ + "doe_object = DesignOfExperiments(parameter_dict, dv_pass,\n", + " measure_class, createmod,\n", + " prior_FIM=prior, discretize_model=disc, args=[True])\n", + "\n", + "square_result, optimize_result= doe_object.stochastic_program(exp1, if_optimize=True, if_Cholesky=True, \n", + " scale_nominal_param_value=True, objective_option='det', \n", + " L_initial=np.linalg.cholesky(prior))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======Result summary======\n", + "This optimization is solved with status: converged\n", + "The result FIM is: [[ 46.24824873 24.02029597 -111.11259575 -98.84096348]\n", + " [ 24.02029597 56.00750617 -41.77758393 -257.36193477]\n", + " [-111.11259575 -41.77758393 290.34323272 177.30691665]\n", + " [ -98.84096348 -257.36193477 177.30691665 1245.84730943]]\n", + "Four design criteria log10() value:\n", + "A-optimality: 3.214432211189959\n", + "D-optimality: 6.2141188000894925\n", + "E-optimality: 0.007782956642549842\n", + "Modified E-optimality: 3.119982823770888\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "print('======Result summary======')\n", + "print('This optimization is solved with status:', optimize_result.status)\n", + "print('The result FIM is:', optimize_result.FIM)\n", + "print('Four design criteria log10() value:')\n", + "print('A-optimality:', np.log10(optimize_result.trace))\n", + "print('D-optimality:', np.log10(optimize_result.det))\n", + "print('E-optimality:', np.log10(optimize_result.min_eig))\n", + "print('Modified E-optimality:', np.log10(optimize_result.cond))\n", + "\n", + "t_list = []\n", + "for t in optimize_result.model.t:\n", + " t_list.append(t)\n", + "\n", + "T_list = []\n", + "for i in t_list:\n", + " T_list.append(pyo.value(optimize_result.model.T[i]))\n", + " \n", + "si=16\n", + "plt.rc('axes', titlesize=si)\n", + "plt.rc('axes', labelsize=si)\n", + "plt.rc('xtick', labelsize=si)\n", + "plt.rc('ytick', labelsize=si)\n", + "plt.rc('legend', fontsize=12)\n", + "plt.plot(t_list, T_list, 'b', linewidth=2)\n", + "#plt.scatter(t_list, T_list, 'b')\n", + "plt.ylabel('T [$K$]')\n", + "plt.xlabel('Time [$h$]')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Method: Exploratory analysis (Enumeration)\n", + "\n", + "This method conducts exploratory analysis by enumeration. \n", + "It allows a user to define any number (dimensions) of design variables.\n", + "Heatmaps can be drawn by two design variables, fixing other design variables; \n", + "1D curve can be drawn by one design variable, fixing other design variables." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Specify user inputs" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# Design variable ranges as lists \n", + "design_ranges = [list(np.linspace(1,5,5)), list(np.linspace(300,700,5))]\n", + "\n", + "# Design variable names \n", + "dv_apply_name = ['CA0','T']\n", + "\n", + "# Design variable should be fixed at these time points\n", + "dv_apply_time = [[0],t_control]\n", + "\n", + "# Define experiments. This is a starting point of which the value does not matter\n", + "exp1 = generate_exp(t_control, 5, [300, 300, 300, 300, 300, 300, 300, 300, 300])\n", + " \n", + "## choose from 'sequential_finite', 'direct_kaug'\n", + "#sensi_opt = 'sequential_finite'\n", + "sensi_opt = 'direct_kaug'\n", + "\n", + "# model option\n", + "if sensi_opt == 'direct_kaug':\n", + " args_ = [False]\n", + "else:\n", + " args_ = [True]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(4, 4)\n", + "(4, 4)\n", + "The prior information FIM: [[ 22.52943024 1.84034314 -70.23273336 -11.09432962]\n", + " [ 1.84034314 18.09848116 -5.73565034 -109.15866135]\n", + " [ -70.23273336 -5.73565034 218.94192843 34.57680848]\n", + " [ -11.09432962 -109.15866135 34.57680848 658.37644634]]\n", + "Prior Det: 1.9558434466145787e-08\n" + ] + } + ], + "source": [ + "# add prior information\n", + "prior_all = [[ 22.52943024 , 1.84034314, -70.23273336, -11.09432962],\n", + " [ 1.84034314 , 18.09848116 , -5.73565034 , -109.15866135],\n", + " [ -70.23273336 , -5.73565034 , 218.94192843 , 34.57680848],\n", + " [ -11.09432962 , -109.15866135 , 34.57680848 , 658.37644634]]\n", + "\n", + "print(np.shape(prior_all))\n", + "\n", + "prior_pass=np.asarray(prior_all)\n", + "print(np.shape(prior_pass))\n", + "\n", + "print('The prior information FIM:', prior_pass)\n", + "print('Prior Det:', np.linalg.det(prior_pass))" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "doe_object = DesignOfExperiments(parameter_dict, dv_pass,\n", + " measure_class, createmod,\n", + " prior_FIM=prior_pass, discretize_model=disc, args=args_)\n", + "\n", + "all_fim = doe_object.run_grid_search(exp1, design_ranges, dv_apply_name, dv_apply_time, \n", + " mode=sensi_opt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1D sensitivity curve" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZ0AAAEhCAYAAACk132sAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAA7BklEQVR4nO3dd3hUVfrA8e+bECChhV4CCUgJKEjvxYqoWAALIIi4rl0R3WWVdf2JrqIuuxZEXVHXhl0RLAiIinSQDtKkhV4ChppASN7fH/dGhiFtkmlJ3s/z3CeT2+adk8m8c8499xxRVYwxxphgiAh1AMYYY0oOSzrGGGOCxpKOMcaYoLGkY4wxJmgs6RhjjAkaSzrGGGOCxpKOOYOIDBUR9VhOisgmERktImXDILY/hTKGok5Etnr9fT2X4UGOZbiI9Mtm/SgRCfq9HNk9r1suozx+7yMiDwU7tuKkVKgDMGHrBmAHUAHoC4x0H98fwpiG4rxn/xfCGIqDacCobNZvDW4YDAfmABO91r8JTA1yLDnpjPN/kKUPcCnwfEiiKQYs6ZicLFfVje7j70WkMXCbiDygqpmhDMyfRKSMqp4IdRxBlqyqC0IdRE5UdQdnftCHTDiXU1FlzWsmv5YC0UC1rBUiEiMiz4nIFrcZbouIPCoiER77lBWRF0RktYgcFZE9IvK1iDT1fgIRaSAi77v7nBCRzSLykrttJnAB0NWjOWimx7EdRGSG+xzHROQHEengdf53RGSHiHQWkXkikgr8K7cXLSJ9RWSue97DIrJIRK7x2H6fiMwXkYMikiIiC0Skt9c5SonIP91myjQRSRaROSLSzWu/20Vkhcc+b4lIldziCyZxPCgi692/924RGSciFb32UxF52n0v7BCRVBGZJSKtPPbZCiQAgzz+nu+423Jq5npKRP4iIknu3/hbEanhLp+KyCER2S4iD3sdW11EXheRDSJy3N3nQxGJy8dr/qN5zY3vFiDOI+atIlLLLY8Hsjl+lPuclfNVyCWA1XRMftUHDgEHwPkgxWmmORf4J7AK6AQ8BlQB/uIeVwanWe4pYLe77R5ggYg0VdU97vkaAIuA48DjwG9APeAy9zz3ABOASOBOd91h99jzgZ+BNThNcAo8AvwsIp1UdYXH66gEfAz8G/g7kJrTCxaR+4GxwCScD5ujQBu3LDzL5U2cpqlSwNXANyJypap+5+7zMPAg8CiwHKgItHPLIuu5nnXLbCwwAohzy6y5iHRR1Yyc4iwAcf9+Z1DVU3kc9zROM+srwNec/tu3FJELvGrAQ4BtwH0474EngR9EpLGqHsRpsp0CrOB0U9/+PJ7/ZmA1znuhJvAi8B7O++s7YDxOs/CzIrJKVae4x1UB0tzY9wN1cMp6rvseTMvjebP8E6gOtAeyvnicUNU9IjIJ5335UtbOIhIJ3AZ8qqq/5/M5ij9VtcWWPxZOf2gn4nyIVgb+BJwC7vPY72Z3vx5exz8KnARq5HD+SCAGOAI86LH+PZwP9Tq5xDYTmJPN+s+BFCDWY11F4CAw0WPdO27M1+ajHCq6MU7Ma1+PYyLcMpsOTPZY/01u58FJXBnA/3mt7+rG28ePf9+t7jmzW9rlclzWB/c7XusHu8de47FOgWSgnNdrTAf+6RXLhGyea5Tz0XTGOgU2AKU81j3vrv+Hx7pSwD7g7VxeSyTOFxoF+ubjeUd5vYd2ZHPOC919u3usu8Zd18lff7/isFjzmsnJOpwPiYPAW8DrqjrOY/vlQBIwz20+KuV+e54OROHUegAQkRtFZKGIpOAkr2NAeZzEluUy4BtV3VWAWHu4x6ZkrVDVw8BXOE1ynk7hJIG8dHFjHJ/bTiLSVkS+EZG97rnTgZ6c+dp+Aa50m5y6iUhpr9P0xElYH3iV5UKc2lyPXJ4/wvMY8WjazMV3ON/WvZc1uRzTCafGMsFr/cc4r9u7nKeo6rGsX1R1K7AA58J8QX2vZ9bG1rk/p3k8zylgI05S+YOI3O02XR51493mbvL8OxWYqs7EKb87PVbfCaxUuy50Bks6Jid9cT6IrgRmAPeIyBCP7TVw2uTTvZZF7vaqACJyNfAJsBa4Cejonnc/4NkFuyoFv3hcBafpztsenJqap32av6aqqu7PHGMSkXrAD+7z34+TqNrj9LzyfG2jcZoMrwFmAwdE5G0Rybo+VsP9uZGzy7OiRyzZ+Z/X/vnp2XdQVRdnsxzP5ZispsAzytn9kD/gsT3L3mzOsRen2bCgvJuoTuay/o/yd5tJX8V5H/cDOnD6S5E/bwN4DbheRKqKSALOF7P/+vH8xYJd0zE5Wa1u7zUR+RFYCYwRkS/cb7AHgC3AjTkcv9X9OQDYqKpDszaISBRnf0glU/APpINArWzW13K3ecrv/R/J7s84nOsI2bkc5xrRjer0uAKcDhZnPKFqOvAc8JyI1AKuwmkaigH6414nw6ntZdf2fyCbdVlGAZ410OQc9iusrHKsBfyatdKtkVXl7BhrZnOOmsDOgESXuwHAD6qadZ0x6xqiv70HPIPTRF0Z53rhBwF4niLNko7Jk6qeEJERwGSci7hjcL7NXwccVdV1uRweg9Oc4elmnHZ1T9OBfiJSW1Wzq7UAnMC5aOztZ6C3iFRQ1SMAIlIB56L+zFxiy808nGtMd+DRfOMlK7mkZ60QkSY412KyrSGp03HiTRG5Emjurv4eyATiVfV7X4J0m622+nJMAS3AKf8BOLW7LP1xPkd+9tr/ShEpl9XEJiL1cWoXz3rscwKnR2SgxeB2OvFwawHPlWPMqnpYRD7AaVYrD3zoNvMaD5Z0TL6o6lci8gvwVxEZh/MN7lacHkn/wemFVBpoiNOM1MdtrpkK9BGRF3CupbQFhuFc+Pf0ONAb5xrRaJympjjgclUd7O6zBqeZrz+wCTiiqutxehVd5cbyHE5t5mGcD5snC/h6j4jISOBlEfnCfb1HgFZAmqq+jNNccwp4zy2D2sATONcLPLuNT3bLZylOTaY1Ti3pdfe5NrlxjxORRJwP8DSc6xI9gTdV9aeCvI4cVBORTtms3+MmsbOo6kEReR4YKSLHcHqeNcPpYTcH+NbrkFRguoiMwbkW9ATOB/8LHvusAbqLyFU4TaHJOT1/IU0FHhaRv+M0/14MXF/Ac60BqojI3cBinPfCKo/tr3L6uo41rWUn1D0ZbAmvhdO91xpls+0yd9uD7u9lcZp31uF8AzyIc9F8FG4vI5wP36eAXTjdoX/G+dDdytk9oRoCH+E0EZ0ANgMveGyvhfNhd8SNY6bHto44SeAoTkeFH4AOXud/h2x6HuVRHtfjXNBPxfnQXAhc5bH9Rvf1p+E0Ow1wn2erxz5/wakpHHDPs94toyiv57rZ3e+Y+zrW4jSd1fXj33crOfdeG5fHsYLT9Xs9znWT3Tjdpyt67ac43av/jlPjS8O5ltXKa7+m7vrj7jHvuOtHkX0vsqfy817Fq5cjTs3kNZzriEdwvvw04OyeaTk9r+c+5dz36O/utq3ZlNN64JdQ/y+H6yJuIRljjF+4N3Y+rar/CHUsweY2r64DblfVt0IdTziy5jVjjCkkEakLNMJpRtwNfBjaiMKXdZk2xpjC+zPwI04PvZtUNceRLko6a14zxhgTNFbTMcYYEzR2TScX1apV0/r164c6DGOMKVKWLFmSrKrVs9tmSScX9evXZ/HixaEOwxhjihQRScppmzWvGWOMCRpLOsYYY4LGko4xxpigsaRjjDEmaCzpGGOMCRrrveZnk5btZMy09exKSaVObDQjeiXSp3Vh5q0yxpjiw5KOH01atpORE1eRmu5MTLkzJZWRE51Rzy3xGGOMNa/51Zhp6/9IOFlS0zMYM219iCIyxpjwYknHj3alZD/G386UVDIybYw7Y4yxpONHdWJznnm3x79+4tWZG0k+eiKIERljTHjxOemISGsRmSgiySJySkTauOtHi8jl/g+x6BjRK5HoqMgz1pUtFcHQLvWJrxLDv6aup8szP/LAx8tYvPUgNsK3Maak8akjgYh0w5kSeDPOJEX3eWzOBO7CmY+8RMrqLJBT77WN+44wYcE2vliyg8nLd9G0VgVu7pxAn1ZxlCtjfTqMMcWfT/PpiMgcnHne+wCROPOkt1PVpSLSD3hRVeMDEWgotGvXTgMx4OexE6f4asUu3p+fxJrdhylfphT92sQxuFMCTWpW8PvzGWNMMInIElVtl902X79etwH6qaq686B7SgayHcranKlcmVIM7BDPgPb1WLothQ8WJPHxou28Nz+Jjg2qMLhTAr3Oq0XpUnbJzRhTvPiadNKAmBy21QYOFS6ckkVEaJtQmbYJlXm0dzM+W7KDDxYmcf9Hy6hWvgwDO9RjYIf4XDsoGGNMUeJr89pXQCxwkbsqHWirqstEZDqQrKo3+T3KEAlU81puMjOVn3/bz4T5Sfy4fh8CXNKsJjd3SqBbo2pEREhQ4zHGGF/5s3ntMWAusAL4HFDgFhF5HmgLtC9MoAYiIoSLEmtwUWINth88zkeLtvHJL9v5fs1e6leNYVDHBG5oV5fYmNKhDtUYY3zmU00HwO0iPQbogdOZIBOYDTykqsv8HmEIhaKmk50TpzKYunoP789PYnHS75QpFcHVLetwc6cEWtaLDXV4xhhzhtxqOj4nHY+TlgWqACmqerwQ8YWtcEk6ntbuPsyEBUl8uWwnx09m0CKuEjd3SuDqlnWILh2Z9wmMMSbAApJ0SoJwTDpZjqSl8+WynUxYkMSGvUepWLYUN7Srx6CO8ZxTvXyowzPGlGB+Szoi8mMeu6iqXuJLcOEsnJNOFlVl0ZaDvL8giamr93AqU+nWqBqDOyVwabMalIq0btfGmODyZ0eCCJzOA56qAonAfmCD7+GZwhAROp5TlY7nVGXfkTQ+/WU7Hy7cxl0TllCrYlkGdohnYId61KhYNtShGmOMf5rXRKQhMAl4UFVnFPqEYaIo1HSycyojkx/X7WPCwm3M2rCfUhFCr/NqMahTPJ3PqYqIdbs2xgROUK7piMgg4K+q2tovJwwDRTXpeNqSfIwPFybx6eIdHEpNp1GN8gzuGE+/tnWpWDYq1OEZY4qhYCWdy4AvVbWcX04YBopD0smSlp7BNyt38/6CJFZsTyE6KpI+reswuFMC59WpFOrwjDHFSMCTjohUwRl1uo6qnl/oE4aJ4pR0PK3ckcKEBUl8tWIXaemZtImP5ebOCVzRvDZlo6zbtTGmcPzZe20LZ3ckKA3UdB9fp6pfFSjKMFRck06WQ8fT+XzpDj5YkMTm5GNUjonixvb1GNQhgfiqOQ2xZ4wxufNn0nmHs5NOGpAEfKaqmwoaZDgq7kkni6oyb9MB3p+fxPdr95KpyoVNqjO4UwIXJtYg0sZ7M8b4wG4OLaCSknQ87T6UykeLtvPRom3sP3KCuNhoBnWK58Z29ahWvkyowzPGFAGWdAqoJCadLOkZmXy/Zi/vz09i/uYDREUKV7aozc2dEmibUNm6XRtjcmRJp4BKctLx5DnN9pETp2yabWNMrgqVdEQkk7Ov4+REVbXYfApZ0jnT8ZOnmLzcptk2xuSusMPgPEn+k44pxmJKn55me9n2FCbMPz3NdocGVbjZptk2xuTBmtdyYTWdvB04euKPaba3H0ylWvkyDGhfj4Ed44mzabaNKZHsmk4BWdLJP5tm2xiTxZ+jTGedsCXOyNJnDV2squ8V5JymaLNpto0x+eHrzaGxwLdAp6xV7s8/TqKqARtHRUTuAAYCrYFKQANV3ZrHMUOBt7PZFK2qabkdazWdwsmaZnvCgiR+2WrTbBtTUvizpjMaZ/6cHsBsoC9wCPgT0BkYUIg48yMGmA5MBl7w4bjjQEPPFXklHFN4ZUpFcm2rOK5tFffHNNuTlu3k8yU7zphme9qvexgzbT27UlKpExvNiF6J9GkdF+rwjTEB4GtNZxPwBPABkA60V9Ul7rbXgHKqOiQQgXrF0Q74hfzXdMapqs9zOFtNx/+OpKUzadlO3nen2Y6OiuRkRiYZmaffh9FRkTzTr4UlHmOKqNxqOr72ba0NbFbVDJwx1zxvzpgI9C5YiAEXLSJJIrJDRL4RkWIz509RU6FsFDd3rs+04T345A6nldYz4QCkpmcwZtr6UIRnjAkwX5POHiDWfZyE06SWpZE/AgqA9TjNf9fiXA9KA+aKSOPsdhaRO0RksYgs3r9/fxDDLFmyptlOS8/IdvuulNQgR2SMCQZfk84cTiea94HHReR1EXkFGANM8zUAEXlKRDSP5UJfz5tFVeer6ruqulxVZwP9gU3A/TnsP15V26lqu+rVqxf0aU0+1cnhXh4bXNSY4snXjgRPAHXcx2NwOhX0x7nA/xU5fJDn4UVgQh77bCvAebOlqhkishjItqZjgmtEr0RGTlxFqkeNR4CDx0/y4cJtDOxQzwYXNaYY8SnpuPPlbHIfpwN/cZcCU9VkILkw5/CFOJ9g5wMrgvWcJmdZnQU8e6/dc2FDpq3Zy9+/XMWSpN95um9zm9HUmGLCp6QjIkuB94CPVHVvYELK9flrAbWAJu6qc917h7ap6kF3nx+ARao60v39cWAB8BtQERiGk3TuDm70Jid9Wsed1VNtQId4XvrhN8b+8Btrdh/mv4PbkFC1XIgiNMb4i6/XdPYC/wK2i8gUERkgImeNShBAdwHLcLpsg3Oj6jLgGo99GuL0sssSC4wH1uLc4xMH9FDVRYEO1hRcZITwUM8mvD20PbtSUrnq5Tn8sDbo33OMMX7m89hrIlIDuAkYDLQBjgCfAxNU9Se/RxhCdp9OeNh+8Dh3TVjCr7sOc99FjXiwZxObQtuYMObP+3RQ1X2q+qJ7wvOAV4BLgBkiklS4UI05W70qMXxxdxf6t6vHuJ82MvTtRRw8djLUYRljCqBQE5+o6lqc+XYeBXYBdf0RlDHeykZF8tz15/PcdS1YuOUgV42dzfLtKaEOyxjjowInHRG5WETexrnO8x6wg4J1mTYm3/q3j+eLu7oQESHc8N95TFiQhE3PYUzR4VPSEZHmIvKsiGwDvgcuAF4CmqpqZ1V9NRBBGuOpRd1KfHN/N7o2qsY/Jq3mL5+tIPVk9iMbGGPCi683h67EGVX6M+B99w5/Y4IuNqY0/7ulPS//uJEXf9jAml2H+e/gttSvZt2qjQlnvjav9QdqqeodlnBMqEVECA9c2pi3h7Znz+E0rh43h+/XWLdqY8KZT0lHVT9T1ROBCsaYgrgwsQZf39eN+lXLcft7i/nX1HVnjVxtjAkPPnckEJFbRGSqiKwRkc1ey6ZABGlMXupVieGzuzozsEM9Xp25iSH/W8iBo/b9yJhw4+swOI/hDPq5GlgO2H+1CRtloyJ5pt/5tI6vzGOTVnPVy3N4dVAbWsdXDnVoxhiXrzOHbgW+VNUHAxZRGLERCYqu1TsPcfcHS9hzKI3/u+pcBndKsNGqjQkSf45IUBX4uvAhGRNYzeMq8c193eneuDqPTf6Vhz5dwfGTp0IdljElnq9J52egZSACMcbfKsVE8eaQdvylZxMmLd9Jv1fnsSX5WKjDMqZE8zXpDAduFZEhIlJNRCK8lwDEaEyBRUQI91/SmHdv7cDew2lc8/Icpv26J9RhGVNi+ZokNgDNgazhb9K9FhuF0YSlHk2q8/X93WhQvRx3vr+EZ79bx6mMzFCHZUyJ4+uIBE8CdgOEKZLqVna6VT/x9Rr++/MmVmxP4eWbWlOtfJlQh2ZMieHzfDolifVeK74+X7KDR79cReWY0rwyqA1tE6xbtTH+4tf5dIwpDq5vW5eJ93ShdKkIBoyfz7vzttpo1cYEQUFGJGgtIhNFJFlETolIG3f9aBG53P8hGhMY59WpxNf3daNH4+o8/tWvDP9kuXWrNibAfJ3aoBswH2gKfOh1fCZwl/9CMybwKsVE8caQdozolcjXK3bR55W5bN5/NNRhGVNs+VrTeRaYhjNN9UNe25YCbfwRlDHBFBEh3HtRI977U0eSj57kmnFzmbp6d6jDMqZY8jXptAFeU6fx27sBPBmo7peojAmBbo2r8fX93WhYozx3TVjKM1PWWrdqY/zM16STBsTksK02zgRvxhRZcbHRfHpnJwZ3iuf1WZsZ/NZC9h+xcW2N8Rdfk84cYLiIRHqsy6rx3Ab86JeojAmhMqUieapPC56/sSXLt6fQe+xsFm89GOqwjCkWfE06j+E0sa1wHytwi4j8BHTCmfbAmGKhX5u6fHlPV6JLRzJg/AL+N2eLdas2ppB8nTl0BdADZwicRwEB7nM3X6Cq6/0bnjGh1ax2Rb66rxsXJtbgyW/WMOzj5Rw7Yd2qjSkon+/TUdWlqnoJUAGoC1RU1YtUdZnfozMmDFSKjmL8zW0Z0SuRb1c63ao37rNu1cYURIFHJFDVNFXdparH/RmQMeEoq1v1+7d15OCxk1w7bg5TVlm3amN85evMobl1FMjE6b22BHhLVfcWMraQs7HXTHZ2H0rl7glLWb49hdu7N+Dhy5tSKtJGlDImiz/HXhMgEbgQSADKuj8vBJoBDXA6GKwWkXMLGK8xYa12pWg+vbMzQzon8MbsLdz05kL2HUkLdVjGFAm+Jp3nce7VaauqDVW1i6o2BNq7658AGgP7gaf9GqkxYaR0qQievLY5L/ZvxcodKfQeO4dfrFu1MXnyNek8BYzy7jSgqktwEs5TqroDGIPTy82YYq1P6zgm3duVcm636jdnb7Zu1cbkwtek0wRnuJvs7AcauY83AeUKGpQxRUnTWhX56v5uXNK0Bk99u5b7PlrGUetWbUy2fE06W4E/57DtDnc7QDXgQMFCMqboqVg2itdvbssjVzTlu1W73W7VR0IdljFhx9ek8yTQR0RWisjjInK3+3MlcC2nRyS4FFjoz0CNCXciwl0XNGTCbR35/dhJrh03l29XWrdqYzz5PF21iPTESS5tgSggHVgMPK6qM9x9ygIZqpru33CDy7pMm4LacyiNez5YwtJtKdzWrQGPXNGUKOtWbUoIv05Xrarfq2oXIBqoBUSrateshOPuk+bvhCMiVUTkZRFZJyKpIrJdRF4Tkar5OPY6EVkjIifcn339GZsx3mpVKsvHd3RmaJf6vDVnCze9sYB9h61btTGFGZEgU1X3qWqwJhypA8QBfwNaAINxesh9lNtBItIZ+AT4AGjl/vxMRDoGMlhjSpeKYNQ15/HSgFas3nmY3i/PYeFmu9RpSjafm9fCiYhcCXwDxKrq4Rz2+QSooqo9PdbNAPar6sDczm/Na8Zf1u85wt0TlpB08DiPXN6UP3dvgIiEOixjAqJQzWsikiEiHdzHme7vOS3B7idaETgB5Db+W2dgute6aUCXQAVljLfEWhWYfF9XejarydNT1nLvh0utW7UpkUrlY58ngR0ej8OiaiQiscA/gTdUNbf/3lo4UzF42uuuz+68d+B0/yY+Pr7wgRrjqlA2itcGt2H8rM08N3Ud6/Yc4fXBbWlcs0KoQzMmaELevCYiT+HMzZObi1R1pscx5YCpQAZwuarmeIVWRE4Ct6nq+x7rbgFeV9WyuT2pNa+ZQJm/6QD3f7SU4yczeO6687m6ZZ1Qh2SM3+TWvJafmk6gvQhMyGOfbVkPRKQ8MMX99arcEo5rD2fXampwdu3HmKDp3LAq3w7rzj0fLOX+j5axdNvv/P3KZtat2hR7Pr/DRaS1iEwUkWQROSUibdz1o0Xkcl/Pp6rJqrouj+W4+xwVcGo4kcCVqpqfmbTmAz291vUE5vkaqzH+VLNiWT6+oxO3dq3P23O3MnD8AvZat2pTzPmUdESkG86HeFPgQ6/jM4G7/BfaWc9dAadDQGVgKFBORGq5S2mP/X4QkWc8Dn0JuFhERopIUxEZCVyEU8MyJqSiIiN4/OrzGDuwNWt2H6b32DkssG7VphjztabzLE7Pr/OAh7y2LQXa+COoHLQFOgHnAhuA3R6LZ0+0hkDtrF9UdR4wALgFWAkMAfqrqg3TY8LGNS3rMOnerlSMLsWgNxcyftYmG63aFEu+XtNpA/RTVRUR7/+IZKC6f8I6m9uRIM8bG1S1fjbrPgc+939UxvhPk5oVmHxvV/72+UpGT1nH0qQUxtxwPhXKRoU6NGP8xteaThoQk8O22jjTVRtjCqhC2SheHdSGR69sxvdr93LtuLls2GujVZviw9ekMwcYLiKRHuuyajy3AT/6JSpjSjAR4fYe5/DhnztyOO0U146by+TlO0MdljF+4WvSeQyniW2F+1iBW0TkJ5zrLU/kcqwxxgcdz6nKt8O60TyuIg98vJxRX/3KyVPBGurQmMAoyNQGbTg9HXUkTq+12cBD3tNYF3V2c6gJB+kZmTz73TremrOFNvGxXNOyDm/M3sKulFTqxEYzolcifVrHhTpMY/6Q282hBR6RwJ0zpwqQknUfTXFjSceEk29W7uKhT1ecVduJjorkmX4tLPGYsOHX+XSyuHPm7CquCceYcHPV+XWIjT67J1tqegZjpq0PQUTG+M7G3DCmCNl/5ES263elpAY5EmMKxpKOMUVIndjobNdXjI4iM9NuJjXhz5KOMUXIiF6JREdFnrEuQuBQajpD/rfIajwm7FnSMaYI6dM6jmf6tSAuNhoB4mKj+c8NLRndtwVLt/1OrxdnMWnZThtCx4StkM+nE86s95opSpIOHOOhT1ewJOl3ereozVN9mlO5XOm8DzTGzwo7XXVeU1SHcrpqY4wroWo5Pr2zMyN6JTJ9zR56vTiLn9bvC3VYxpwhv9NVW3XImCIgMkK496JGXJhYnQc/Wc6tb//CoI7xPNq7GTGlw2HORlPSWfNaLqx5zRRlaekZ/Gf6et6cs4WEKjE8378VbeIrhzosUwIE5OZQY0x4KxsVyaO9z+Wj2zuRnqFc/9o8/j1tvY3fZkKqQPVtEWkJJAJlvbep6nuFDcoY4z+dzqnK1OHdeeLrNYz7aSM/rd/Hi/1b0bhmhVCHZkogn5rXRCQW+BZnRGk4PanaHydR1UiKCWteM8XNtF/3MHLiKo6eOMXfeiXyp64NiIjIc25EY3ziz+a10UBVnBGmBegLXAx8AGwGOhQiTmNMgPU6rxbThvegR+NqPPXtWga9uZCddkOpCSJfk04vnMSzwP19h6rOVNUhwAzgAX8GZ4zxv+oVyvDGkHY8d10LVu5I4fIXZvHFkh12Q6kJCl+TTm1gs6pm4Exd7dkoPBHo7a/AjDGBIyL0bx/Pdw/0oGntCvzlsxXcPWEpB4+dDHVoppjzNensAWLdx0lAZ49tjfwRkDEmeOKrxvDxHZ155Iqm/LhuH5e9MIsf1+0NdVimGPM16czhdKJ5H3hcRF4XkVdwZhOd5s/gjDGBFxkh3HVBQybf15Vq5Uvzp3cWM3LiSo6dsAFGjP/52mX6CaCO+3gMTqeC/kAM8BVwv/9CM8YEU7PaFZl8X1de+P43Xp+1ibkbD/D8jS1pV79KqEMzxYiNSJAL6zJtSqpfth7koU+Xs/P3VO68oCEPXtqE0qXsXnKTP7l1mS7ozaH1gHpkf3PojwU5pzEmfLSvX4XvHujBP79ew2szNzFz/X5e6N+SprUqhjo0U8T5enPoOTj35GTdj+N5c6gAajeHGlO8zFizl0cmruRw6in+2qsJt3U7h0i7odTkwp81nTeBeGA4sA6w/pXGFHOXnluTafE9+PuXqxg9ZR0z1u7jPze0pF6VmFCHZoogX2s6R4ChqvpF4EIKH1bTMeY0VeWLpTsZ9dWvAPzf1edyQ9u6iFitx5zJn8Pg7MBqN8aUSCLC9W3rMnV4d5rHVeRvn6/kjveXkHz0RKhDM0VIQcZee1hEygUiGGNM+KtbOYYP/9yJf/Ruxs8b9tPrhVlM/3VPqMMyRYRP13RU9X0RaQpsFZEFwO9n76K3+C06Y0xYiogQ/tz9HLo3dmYoveP9JdzYri6PXXUuFcpGhTo8E8Z8SjoiMhQYCWQAbTi7qc1u+jGmBEmsVYFJ93blpR828NrMTczbdID/3NCSjudUDXVoJkz52rz2BPAlUF1V41S1gddyTgBiNMaEsdKlIhjRqymf3dWZyAhhwBsLGD1lLSdOZYQ6NBOGfE06VYFXVTUlALEYY4qwtglVmDKsOwM7xDN+1maueXkua3YdDnVYJswUZMDPZoEIxBhT9JUrU4rRfVvw9tD2HDx+kmtfmcOrMzeSkWkt78bha9J5ALhdRAaJSFURifBeAhEkgIhUEZGXRWSdiKSKyHYReU1Ecm08FpGhIqLZLGcN4WOM8Y+LmtZg2vAe9Dy3Jv+aup7+r89n24HjoQ7LhAFfk8RaoAXwHrAPSPdaAnkPTx0gDvibG8NgnGmzP8rHscdxJqD7Y1HVtADFaYwBqpQrzSs3teGF/i1Zv/cIl780i48WbbMZSks4X4fBeZIQ9VBT1dVAP49VG0VkBPCNiFRU1dwaj1VV7UYCY4JMROjbui4dG1Tlr5+tYOTEVcxYs5dnrmtBjQrW2FASFempDURkAPA2UEFVs51xyu3m/RbOaAqRwHLgMVVdlsP+dwB3AMTHx7dNSkryf+DGlECZmco787by3NR1xJSO5Jl+Lbi8ee1Qh2UCILdhcIps0hGRWOAX4DtVHZbLfp2BJsAKoALOdakrgZaq+ltuz2Fjrxnjfxv3HeHBT1awauch+rWJY9Q151HRbigtVvw59prfichTOVzo91wu9DqmHPA1sBPnGk+OVHW+qr6rqstVdTbOTKebsFlOjQmJRjUqMPGeLgy7uBGTl+/iihdnM29TcqjDMkGSZ01HRDKAzqq6SEQyyf2ajqqqr6McVAOq5bHbNlU97u5fHpiCM3/PFap61Jfnc8/xNlBLVa/IbT+r6RgTWMu2/c5Dn65gS/IxbuvWgBG9EikbVWym5CqxCjufzpM410OyHvu1PU5Vk4F8fc0RkQrAdzgJ5/ICJhwBzsdpbjPGhFDr+Mp8O6wbz0xZx1tztjBrw35e6N+K5nGVQh2aCZAic03HTTjTgYpAH+CIx+aDqnrS3e8HYJGqjnR/fxxYAPzmHjsMuBnoqqqLcntOq+kYEzw/b9jPiM9WcPDYSYZf2pi7LmhIqciQXwEwBRDW13R80BboBJwLbAB2eyxdPPZriHMvTpZYYDzOPUbTce716ZFXwjHGBNcFTaoz/cEeXN68Fv+evoEbXp/P1uRjoQ7L+JnPNR0RuQUYiDNttXdHe1XVhn6KLeSspmNMaExevpPHJq0mPUN5tHczBnWMtxlKi5DCXtPxPNFjOCNNr8a538WmDDTG+N21reLo0KAKf/t8Jf+YtJoZa/fyr+vOp0ZFu6G0qPOppiMiW4EvVfXBgEUURqymY0xoZWYqExYmMXrKWspGRfJ0nxb0Pt9uKA13/rymUxXn/hhjjAm4iAhhSOf6fDusOwlVYrj3w6UM/3gZh1LTQx2aKSBfk87PQMtABGKMMTlpWL08n9/dheGXNubrlbu5/MVZzN1oN5QWRb4mneHArSIyRESqBXNqA2NMyRYVGcHwS5vw5T1diCkdyaA3FzLqq19JS7cZSosSX5PEBqA5ziCbewnu1AbGGMP5dWP5dlh3hnapzzvzttJ77GxW7kgJdVgmn4rM1AbGGJOlbFQko645j0ub1WTE5yvo9+o87r+4MfdeZDeUhrsiMyJBKFjvNWPC36Hj6fzfV6uZvHwXLevF8vyNLWlYvXyowyrRisuIBMYYc5ZKMVG8NKA1425qTdKBY/QeO5v35m+1GUrDlK/Na8YYE5auOr8O7es7N5T+3+Rf+X7NXsZc35IFmw8wZtp6dqWkUic2mhG9EunTOi7U4ZZYIZ/aIJxZ85oxRY+q8sHCbTz97VpEID0jk/SM0x9b0VHOrKWWeAInrKc2MMYYfxIRBndKoGujalz2ws9nJByA1PQMxkxbb0knRPJMOqr6hMfjUQGNxhhj/KRBtXJnJZwsu1JSgxyNyZJn0hGRi305oar+WPBwjDHGf+Jio9mZTYKpXckGDg2V/DSvzeB0k1pOY4uru00Bm2vWGBMWRvRKZOTEVaR6jVpQKjKCrcnHqF+tXIgiK7nye9H/CPCFu9isSsaYIiHruo1n77We59Zk4tId9B47myeubc51beJsrp4gyk/vtQuAIcB1OPf1fAm8WxKa0az3mjHF066UVIZ/spxFWw5ydcs6PNWnOZWio0IdVrFRqJtDVfVnVb0NqAXcBdQAponINhF5RkSa+TdcY4wJrDqx0Xx0eydG9EpkyqrdXPnSbH7ZejDUYZUI+R6RQFXTVPVDVb0CZ6rql4ArgdUiMi5QARpjTCBERgj3XtSIz+/qTGSE0P/1+Tz//QZOZWSGOrRiraDD4BwAtrqLApX9FI8xxgRV6/jKTHmgO31b12XsD79x4+vz2X7weKjDKrZ8Sjoi0lVE/gvsBt4FjgK9gZsDEJsxxgRF+TKl+M+NLRk7sDW/7T3KlS/NZvLynaEOq1jKM+mISCMReUJENgGzgETgr0AtVR2kqtNU1eqjxpgi75qWdZjyQHcSa1XggY+X8+AnyzmSZlNj+1N+eq9lAoeBicD7QFJu+6vqZr9FF2LWe82YkulURibjftrI2B9+I65yNC/2b03bBLuKkF+59V7Lb9LJkue4a6pabG4OtaRjTMm2JOkgD3y8nN2H0njgksbce1EjIiPsnp68FHbAz1v9HI8xxhQJbROqMOWB7jw2aTXPf7+BOb8l88KAVsTFRoc6tCLLZg7NhdV0jDFZvly2g8cm/YoIjO7bgqtb1gl1SGHLZg41xphC6tu6LlOGdadRjfLc/9Ey/vrZCo6eOBXqsIocSzrGGJNP8VVj+PTOzgy7uNEf47ct354S6rCKFEs6xhjjg6jICB66LJGP7+hM+qlMrn9tHq/8tJGMTLtUkR+WdIwxpgA6NKjCdw/0oFfzWoyZtp6b3lhgk8PlgyUdY4wpoEoxUYwb2Jox15/Pqp2HuOKl2Xy3aneowwprlnSMMaYQRIQb2tXj22HdSagaw90fLOWRL1Zy/KR1MshOoZOOiLQRkT7u0sYfQRljTFHToFo5Pr+rC3df2JBPFm/nqrFzWLXjUKjDCjsFTjoi0lZE1gEfAHcD9wAfich6EWnrrwCNMaaoKF0qgocvb8oHf+7I8ZMZ9HttLq//vIlM62Twh8LUdMYD96lqM1XtpaqXqWoicB/whn/CO5OIvCEim0QkVUT2i8jk/EwiJyLXicgaETnh/uwbiPiMMQagS8NqTB3enUua1uSZ79Zx8/8WsvdwWqjDCguFSTrlVXWG90pV/R4oV4jz5mYxMBRoBvQCBJghIjnOMysinYFPcGpkrdyfn4lIxwDFaIwxxMaU5rXBbXi2XwuWJqVw+YuzmP7rnlCHFXIFHgZHRGYD/wPeU9UMd10kzlhtt6pqV79FmXMM5wMrgKaquj6HfT4BqqhqT491M4D9qjowt/PbMDjGGH/YtP8owz5axq+7DjOoYzz/6H0u0aWLzdjIZwnUMDi3AAOBgyKyVkTWAgeB/u62gBKRcjgJbhvODKY56QxM91o3DegSmMiMMeZMDauXZ+I9Xbijxzl8sHAbV4+bw6+7SmYngwInHVXdrKqXAQ2BQe7SUFV7qupGfwXoTUTuEZGjOLOWXgFcoqoncjmkFrDXa91ed312579DRBaLyOL9+/f7JWZjjClTKpK/X9mMCbd15HBqOn1fmcebszeXuE4Ghe4yrarJqrrUXZIBRKRGfo8XkadERPNYLvQ45AOgNXABsAHn+kxMXmF6P20267Jez3hVbaeq7apXr57fl2GMMfnSrXE1pg7vQY8m1Xnq27UMfecX9h0pOZ0MAnVzqC8XQl7E6RiQ27Ioa2dVPaSqv6nqLOB6oAlwXS7n38PZtZoanF37McaYoKhSrjRvDGnLU32as3DzAa54cTY/risZH0n5mcQtWyJyTS6by+b3PG7tKLmgYbhLmVz2mQ/0BMZ4rOsJzCvgcxpjTKGJCIM7JdCxQRWGfbycP72zmFs6JzDyymaUjSq+nQwKnHSAL4GfcT70vVUoxHmzJSKNcGo0M4D9QF3gEeAE8I3Hfj8Ai1R1pLvqJWCWiIx0Y+4LXAR083eMxhjjq8Y1KzDp3i78a+p63pqzhQWbDzJ2YGsSa/n9YzQsFKZ57TfgNlW9yHuh4DWX3JwALgS+Azbi3HtzBOisqp6d3xsCtbN+UdV5wACcHnUrgSFAf1VdGIAYjTHGZ2VKRfLYVefyzq3tOXDsJFePm8M7c7dQHGd2Lsx9OiOBGar6SzbbHlXVpwsbXKjZfTrGmGBLPnqCEZ+t4Kf1+7kosTpjbmhJtfK5XUEIP7ndp1PgpFMSWNIxxoSCqvLuvK2M/m4dFctG8e8bzufCxHx3Cg45v90cKiLDRaSHiBTPxkZjjAkDIsLQrg346r6uVC1XmqFv/8KTX6/hxKmMUIdWaD7VdEQkDYjCucdlE7AEWJr1U1WL1S22VtMxxoRaWnoGz0xZy7vzk2hWuyJjB7Sicc3w/t7vz2FwzsUZcmYZTrKJBx7H6VF2QESWiMidImKTwxljjB+UjYrkiWub89Yt7dh7OI2rXp7D+wuSimwnA1+Tw3+BL1W1vaoOVNVuQALwMvA7zr0vTwPTchv52RhjjG8uaVaTqcO70/Gcqjw2aTW3v7eEg8dOhjosn/madLoBUzxXqOpBVR0OTMQZ8LMdcB7wV38EaIwxxlGjQlneGdqex646l1kb9nP5i7OY81sg7lAJHF+Tzj6ccc+y8wkwRFW3Ai/gDABqjDHGjyIihNu6NeDLe7tQMTqKwW8tZPSUtZw8lRnq0PLF16TzHvAPEcku8cQB1dzHS3Bu0jTGGBMA59WpxNf3dWNQx3jGz9pM31fnsmn/0VCHlSdfk84/cYa+WSAi74nIABG5UETuBJ7j9ECfZYB0P8ZpjDHGS3TpSJ7u24LxN7dlV0oqV42dw8eLtoV1JwOfko6qpqtqH+B+nMnRPgR+AF4DDgB3urt2wulSbYwxJsAuO68WU4f3oE1CLI9MXMXdE5aScjw8OxkUakQCETkHZ5yz/cBv6p5MRDoBMar6o1+iDBG7T8cYU5RkZipvzN7Mv6evp2q5MjzfvyVdGlbL+0A/C8h01SJS2p09dK6qblCP7KWqC4p6wjHGmKImIkK484KGTLy7KzGlIxn05kKem7qO9Izw6WTg6zA4pUTkaRHZD6SKSLKIfCwiXQIUnzHGGB+1qFuJb4Z1o3+7erw2cxPXvzaPrcnHQh0W4HtN51HgIeAL4GGcqaPPA2aLyCN+js0YY0wBxZQuxbPXnc9rg9qw9cBxrhw7m88Wbw95JwNfJ3EbAvxdVV/wXCkifwJeFZG1qjrZb9EZY4wplCta1KZlvVge+nQ5Iz5fycwN+xndpwWVYkIzaIyvNZ3aOGOunUFV/we8iI1CYIwxYadObDQf/LkTI3olMm31Hq54aRaLthwMSSy+Jp3fgFY5bJsKtCxUNMYYYwIiMkK496JGfHF3F0qXimDA+Pn8Z/r6oHcy8DXpvAX8n4i0ymZbXSD8b4c1xpgSrGW9WL4Z1p1+bery8o8bufH1+Ww7cDxoz+9r0nkZmAksdEckGCgiF4nI7cCzOLUdY4wxYax8mVL8+4aWvDywNRv3HeXKsbP5ctmOoDy3zzeHunPlPAg8gFO7yTIdGKiqv/svvNCym0ONMcXdjt+P8+Any/ll6+9c26oOnRpUZdxPG9mVkkqd2GhG9EqkT+s4n86Z282heSYdEbkUZ1bQs646iUgiziCfSaoanDQZRJZ0jDElQUam8upPG3lhxgZUnamhs0RHRfJMvxY+JZ7CjkgwHdgvIptF5HMRGSkil4lINVVd745IUOwSjjHGlBSREcL9lzSmSrnSeFdDUtMzGDNtvd+eKz/36ZwHtAHaussjQAVARWQHzjQGS7N+qupev0VnjDEmaA4czX6Q0F0pqX57jjyTjqquBdbijD4AgIg0wUlAWcnoL0AlnFpZpN+iM8YYEzR1YqPZmU2CqRMb7bfnKNCAn+4Anx+p6ghVvVhVKwNNgIF+i8wYY0xQjeiVSHTUmfWG6KhIRvRK9Ntz+DoMTo5UdSOw0V/nM8YYE1xZnQXGTFtfqN5rufFb0jHGGFP09Wkd59ck463A8+kYY4wxvrKkY4wxJmgs6RhjjAkaSzrGGGOCxpKOMcaYoPF5wM+SRET2A0kFPLwakOzHcEoCKzPfWHn5xsrLN4UprwRVrZ7dBks6ASIii3Ma8M5kz8rMN1ZevrHy8k2gysua14wxxgSNJR1jjDFBY0kncMaHOoAiyMrMN1ZevrHy8k1Aysuu6RhjjAkaq+kYY4wJGks6xhhjgsaSjjHGmKCxpJNPInKviKwUkcPuMl9EentsFxEZJSK7RCRVRGaKyHle5ygjIi+LSLKIHBORr0SkbvBfTfCJyN9FREVknMc6KzOXWw7qtezx2G5l5UVEaovIuyKyX0TSRGSNiFzgsd3KzIOIbM3mPaYi8q27PSjlZUkn/3YAD+NM0d0O+BGYJCLnu9v/hjNt9/1Ae2Af8L2IVPA4x4vAdTgzrHYHKgLfiEixnuJbRDoBtwMrvTZZmZ1pPVDbY2nhsc3KyoOIxAJzAQF6A81wymafx25WZmdqz5nvrzaAAp+624NTXqpqSwEX4CBwJ84bfzfwqMe2aOAIcKf7eyXgJDDIY596QCbQK9SvJYBlVAnYBFwMzATGueutzM4sp1HA6hy2WVmdXSajgbm5bLcyy7sMHwVSgJhglpfVdApARCJFZABQHpgHNABqAdOz9lHVVGAW0MVd1RaI8tpnO7DWY5/iaDzwuar+6LXeyuxs54jIThHZIiIfi8g57norq7P1ARaKyCcisk9ElovIfSIi7nYrs1y45XQbMEFVjxPE8rKk4wMRaSEiR4ETwH+Bvqq6CuePBbDX65C9HttqARmcPYCe5z7FiojcDjQCHstms5XZmRYCQ4ErcJoiawHzRKQqVlbZOQe4B9gM9AJeAp4F7nW3W5nlridOonnT/T1o5VXKpzDNeqAVEIvTrvmuiFzosd37TlvJZp23/OxT5IhIIk4TSHdVPZnLrlZmgKp+5/m7iCzA+UC9BViQtZvXYSWyrFwRwGJVHen+vkxEGuMknXEe+1mZZe924BdVXe61PuDlZTUdH6jqSVXdqKpZb/blwINAVi8j72xfg9PfHPYAkTjDhee0T3HSGee1rhaRUyJyCrgAuMd9fMDdz8osG6p6FPgVaIy9v7KzG1jjtW4tEO8+tjLLgYjUAK4F3vBYHbTysqRTOBFAGWALzh+kZ9YGESmL07tjnrtqCZDutU9dnF43WfsUJ5Nwel+18lgWAx+7jzdgZZYjtyya4ny42vvrbHOBRK91TTg9/5WVWc6G4lwi+NhjXfDKK9Q9KIrKgtNe3B2oj/Nh+gxOr40r3O0PA4eBfkBz9w+6C6jgcY7XgJ3ApUBr4Cec2lJkqF9fkMpwJm7vNSuzs8rm3zg1wQZAR+Abt2wSrKyyLa/27gfgozjXDW8ADgH32vsr13ITnC98b2SzLSjlFfJCKCoL8A7Ot6gTOP3XZ+DRTdD9Y47C+WaaBvwMNPc6R1ngZZympePA10C9UL+2IJahd9KxMjv9OrP+wU+6/9RfAOdaWeVaZr2BFW55bACG4Q5ibGWWY5ldhHP9pUM224JSXjbKtDHGmKCxazrGGGOCxpKOMcaYoLGkY4wxJmgs6RhjjAkaSzrGGGOCxpKOMcaYoLGkY0wQ5TCJlveyNZfj3/HYb6bH+vruuj977V9NRJaJyEERae+um+FxjgmBeq3GZMcG/DQmuDp7/f4lzg2OozzWncjjHHuAvjh3j+dIRGoCPwA1gYv19OCO9+PMjfJlviI2xo8s6RgTRKq6wPN3ETkBJHuvz8OJvPYXkTichFMJuEBV/xgcU1XXejy3MUFlSceYYkZE4nGmUy+Dk3A2hDgkY/5gSceY4uUcnNkeFeihqltCHI8xZ7CkY0zxMhJndsfzLOGYcGS914wpXqbijBb8koiUCXUwxnizpGNM8fIF8CfgMuAzEYkKcTzGnMGSjjHFjKq+C9wFXA18KCKRIQ7JmD9Y0jGmGFLV8cADwPXAeyJi/+smLFhHAmOKKVUd617X+RdwQkRuU5u10YSYJR1jijFVHeMmnn/iTEF8T4hDMiWcJR1jQkhV6xfkOBEp5RyuGe55tuL0WsvuOZ4CnvI4NgJrWjchYm88Y4qeBCAdZ5ibgpjuHp/gt4iMySexJl5jig4RqQ9Uc389oqrrC3COJkBF99cDdhOpCSZLOsYYY4LGmteMMcYEjSUdY4wxQWNJxxhjTNBY0jHGGBM0lnSMMcYEzf8DDml3CH8VdbEAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZEAAAEhCAYAAAC+650iAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAA8eElEQVR4nO3dd3hUZfbA8e8h9C69BgQEpEhvNmyIXUSxLLpgQV17WVaxYi+s2P2pqysqCAgiKi7FBlZAeu8QIHRCIEB6zu+P9waHyaTMZJJJOZ/nmSeZe99775k3kzlz33KvqCrGGGNMKMpEOgBjjDHFlyURY4wxIbMkYowxJmSWRIwxxoTMkogxxpiQWRIxxhgTMksiYSQiQ0VEfR4pIrJRRJ4XkYpFILabIhlDcSciW7y/62fZrJ/trf81jMccIyJbfJ43944x1K/cIyKyVUTSRGSJt0xFZGQYY9kiImNyKdPc73/A/9E5XPHkRkRqishIEekaYN1sEZldWLFkd1wROcurl7N8lt0nIgMLO7ZQlY10ACXUIGA7UA24Ahjh/X53BGMaivt7/zeCMZQECcAAEammqgmZC0WkGXCmt74g7QT6ABt9jt0TeA4YBUz1iaEP7n0YCS8AXwdYvq4QY6gJPImrg0V+6+4oxDhysgj3d1rls+w+4FdgSiQCCpYlkYKxRFU3eL9/JyInATeLyL2qmhHJwMJJRCqoanKk4yhk3wHnAVcCY3yW3wBsAbYBUQV1cK++5/otPtn7+a6qbvIp61+uMG2K8PFzpKqrci9V8FT1EFn/nsWKNWcVjkVAJaBO5gIRqSwiL4nIZq/Za7OIPCoiZXzKVBSRV0VkhYgcFpFdIvKNiLT1P4CInCgin3plkkVkk4i87q2bDfQFTvNpVpjts21PEfneO8YREfnB+3bru/8xIrJdRPqIyO8ikgi8nNOLFpErROQ3b7+HRGS+iFzms/4uEflDROJEJF5E5orIxX77KCsiz3jNgkkisk9EfhWR0/3KDRORpT5lPhSRWjnFF6JE4Atc0vB1A/ApkOUSECLSUEQ+8eJKFpFlInJ9gHLnisgi7zVsFJHbApQ5rjnL+zuO8VZv9G3CCtScJSKdRORrETkgIone3+eMAMe512u+ShKRBYHKFAQRqS4ib4nIDq+u1orI/SIiPmUym4Cu9N6XB7z31zgRqe2VaQ5s9jb5j8/7fqi3PrtmpQEi8p73njzg/f9FiUgP7313RERWikh/v7h7iMhk738k0Yv7eRGplMvrPa45S1zTZTNgsE/MY0TkKu/3TgH2MVtE/gi2rsPFzkQKR3PgILAf3AcjMBNoBzwDLAd6A48DtYAHve0q4JrBnsU1Y9TCnYbPFZG2qrrL29+JwHzgKO70fT3QFDjf288dwFjcN+TMD6ZD3ranAHNwp9NDcR+CDwNzRKS3qi71eR01gAnAv4FHcB+oAYnI3cAbuOaVIcBhoKtXF7718gHuG3xZ4FJgmohcpKrTvTIPAfcDjwJLgOpAd68uMo/1oldnbwDDgcZenXUQkVNVNT27OEP0CfCDiDRR1e0i0htojUsifX0LikgVXP2egKuzbcD1wKciUllV3/fKnQz8D1gAXIv7248EqgI5xX+Ht78RwEDc+yRgE5a4voFfgMXAMNz75Xbge6+eFnrlbgZewyWniUArYDzuvZhXZbz3uS/N6W8h7gvUt7j3yRO4/4uLgdFAXVz9+XoN+B64DjgJeB5oBJyNq4eBuCYh36a1jeTsNW+ba3DNk4/h3pvn4ZoLY71lU0Skmaru87aLxr0/x+CaE9t7r6EF7u+ZV1fg3gdLcX9/gL1ADLAD9/97rClORNrg3nM3BnGM8FJVe4TpwV8fwm1wb7wTgJuANOAun3I3eOXO9Nv+USAFqJfN/qOAyrg36f0+yz/BfUg3yiG22cCvAZZPBuKBmj7LqgNxwBSfZWO8mC/PQz1U92KckltZn23KeHU2C/jKZ/m0nPaDS0TpwBN+y0/z4h0Qxr/vFlwyFu/3h73l7wC/Bapn4C4vjrP89vU9sAeI8p6PA/YBVXzKNPXeD1v8Xq8CQ32W3eIta+53DAVG+jz/AVgNlPd7T60Gpvr8HbYBM/z2dY23vzG51FFmfIEeh3PZ9hL/1+Yt/wBIBup4z8/yyvnHONhbfq5fLLdk8/8w2+d55j7/61dukbf8dJ9lp3jLhmTzOsR7L18PZAC183Dcs3yWbQHGBtjvSNyXUd/3yGjgAFApXO/zYB/WnFUw1gCpuA/iD4H3VPUtn/UX4L5Z/O4115T1vrXNAsrhzkoAEJGrRWSeiMTjktER3LfTNj77Ox+Ypqo7Qoj1TG/b+MwF6tppv8bvW7V3/Gl52OepXozv51RIRLqJyDQR2e3tOxXox/Gv7U/gIhF5TkROF5Hyfrvph/vgG+dXl/NwZ1tn5nD8Mr7biE9TYk7U/feOBW7w4rkGl8gDOROIVdXZfsvH4r5dt/Oe9wH+p6pHfI6zDfgtLzHlxmtW6QtMAjJ86klwCS2znpp4j8/9dvEF7m+UV88CPfweuTWJnYn70B3vt3wsUB5XR778Y5zkbe9fLhjT/Z6vAY6o6q9+y8AleeBYM9xLIrIRl/BScWemgjtLCof3cV8ir/OOWRF3lv+JqmbbKlDQLIkUjCtw/zQX4f5B7xCRv/usr4dr90z1e8z31me2616Ka05YDfwN6OXtdy/gO2S4NqGPwqmFO/X3twt3JuVrj+ataai29zPbmESkKe6bcS3cqLVTca9tBse/tudxTXSX4Zpi9ovIRyKS2b9Uz/u5gaz1Wd0nlkD+61c+mJFrn+ASwJNAFdzfKZCc6jdzPUBDYHeAcoGWhaIW7qzjcbLW013ACV4SbRjouKqahtccm0cxqrrA77E4DzHGadbBGv51lck/xhTct/LGQcTp74Df8xTcmbr/ceD49+lHuKbBN3BfbHoAdwYoFzLvS+JX3nHAjQKtBbwXjv2HyvpECsYK9UZniciPwDJglIh84X3T3I/r9Ls6m+23eD+vBTao6tDMFSJSjqz/TPsI/R8nDmgQYHkDb52vvN43ILOduDGwIpsyF+D6WK5W1WPJRkQqH3dA1VTgJeAlEWmAa/IYjftGdg1/fbCdT9YPAMj5g28k4HuGuC+bclmo6joRmYfrP5rieybnJ47jz6wyZdZ5Znw7gfoBygVaFop43Lf0t8nmrElVM0QkM+Edd1zvrCWnhBwOcUAtESnv80ENWesqk3+M5XFffGILLsSsvDOCy3FNh6/7LO9YAId7B9cf1w3XP/KLRnikmZ2JFDDvW9Vw3DfmzA6xGbhT4cMBvq0t0L866yqTtQnhBrIOIZ0FXCIiDcleMm6EmL85wMUicqzT1Pv9Um9dKH7H9dHcmkOZzGSR6nPc1ri+jIBUdZeqfoA7u+vgLf4O9+EYnU1dbs5hf1v8ym7J06v7y8vANxyfiPzNAZqIiP/r+huuT2S19/wPXLNdlcwC3tlatvURDO/Lyy9AJ2BRoLryim7H9Yn4f8G5koL/0jkH95k0yG/5YNwZgf9QWP8YB3nbZ45UyjyjyXGEVBhUwP1PpvotHxri/rL7X0VVf8S9Z0bj3hvvhniMsLEzkUKgql+LyJ/AP0XkLVwn6o24bxSv4EZilAda4pptBqjqUVyyGSAir+L6IroB9+B3eo1rUrkY18fyPK5ppzFwgapmDiVdhWtWuwY3QiVBVdfiRodd4sXyEu5s4yHch/zTIb7eBBEZAbwpIl94rzcB6AwkqeqbuESQBnzi1UFD4ClgKz5fbkTkK69+FuHONLrgzmLe84610Yv7LW+kyhwgCZek+wEfqOpPobyOPLzOKeQ+IWwMcC9uNM+juA/pwV5st/k0Dz6L+xCcJSKjcO+HpwhfcxbAA8DPwEwR+RB39lMHNxoqSlUf9s5GngI+EJGPcKPxWuFGfx0K4lgtvFFr/tapqv8ZbqbpuEl274pIXWAlrkn4FuAFny9Xmdr7xNgaN+Fyjqr+4K3fjTt7uVZEluH6EzerajDNcrlS1YMiMhd40DuT24cbUBNq68Aq4AwRuQTXlLfP7wvOu8Dr3nG+CDnwcIlUj35JfPDX6KxWAdad762733teEdecsgb3zSMO14k8EijrlSmD+3DZgRuOOQf3IboFv1EyuAQ0HvfGSgY2Aa/6rG+AGzqY4MUx22ddL9yH+mHcP9oPQE+//Y8BtgdZH1fhOrgTcR9A84BLfNZf7b3+JNwHxrXecbb4lHkQ9w10v7eftV4dlfM71g1euSPe61iNO0NoEsa/7xYCjJrxKzMbv1FwuAT5qc/fZhlwfYBtz8MNv838+90WoD6aE+LoLG/ZybgP3T3ecbbjBlFc5FfuXtzgjyTcsOPTA73vAryGzPiye1yVy/bVvb/bTtzZxzrcEG/xKXOWt6+BXv3Ee+/rz/BGcPmUHYD7UE71rTeyHyV1Xl7e917ZZ/1e93Qvjj3ea7iYrCOvsjuub5m2uLPGowQYEee9nxQYFa73dn4e4gVljDHFgjcx7yegn6p+H9loCp+IDMOdibfWv66METHWnGWMMcWAiLTDtTg8hZvXE/EEApZEjDGmuHgHNxT+d9yw7CLBmrOMMcaEzIb4GmOMCVmpas6qU6eONm/ePNJhGGNMsbJw4cJ9qlo30LpSlUSaN2/OggULci9ojDHmGBGJyW6dNWcZY4wJmSURY4wxIbMkYowxJmSWRIwxxoTMkogxxpiQlarRWcYYU9pMXRzLqJlr2RGfSKOalRjevw0DuuTnvl3HsyRijDEl1NTFsYyYspzEVHfHgdj4REZMWQ4QtkRizVnGGFNCjZq59lgCyZSYms6omWvDdgxLIsYYU0LFxicGXL4jm+WhsCRijDEl0KodhyhbRgKua1QzfHcMtj4RY4wpQTIylI9+38JL09dQuXwUSakZpKRnHFtfqVwUw/u3CdvxLIkYY0wJsTchmX9OWsqcdXs5t209Xr7qFH5Zv89GZxljjMnZT2v28M9JSzmcnMbTl7fnht7NEBEGdGkc1qThz5KIMcYUY0mp6bw4fQ1jft9Cm/rV+GxYb9o0qFZox7ckYowxxdTaXQncO2Exa3YlMPTU5jx8YVsqlosq1BjynEREpDwwEXhVVX8uuJCMMcbkRFX5dG4Mz327mqoVyvLR0B6c3bZeRGLJcxJR1RQROQ94vQDjMcYYk4P9h5P51+Rl/LBmD31b12XUoFOoV61ixOIJtjnrN6A3MDv8oRhjjMnJz+v28uCkpRw8msrjl7TjxlObUyabuSCFJdjJhg8CN4vIXSLSRESiRKSM7yPYAESkoYh8LCJ7RSRJRFaJSN9ctukoInNEJFFEYkXkCRGJbE0aY0wBSU5L59lpq/j7f+dTo1I5pt55GjeffmLEEwgEfyay3Pv5OoGbtTSYfYpITdzZza/AxcBeoAWwJ4dtqgPfAT8DPYA2wBjgCPBKXo9tjDHFwYY9h7ln/GJW7TzE9b2jefSidlQqX7id5zkJNok8jUsU4fIvYKeq/t1n2eZcthkMVAaGqGoisEJETgYeEJHRqhrO+IwxJiJUlfHzt/H0tJVUKhfF+zd04/z2DSIdVhZBJRFVHRnm4w8AZojIROBsYAfwAfB2DsmgD/CLl0AyzQSeAZqTexIyxpgi7cCRFB6esoyZK3dzWqvajL66M/WrR67zPCeRnifSArgDeBV4EegMvOmteyubbRoA2/2W7fZZd1wSEZFbgVsBoqOj8x2wMcYUpN837uOBiUvZfySZERe2ZdgZLYpE30d2QukI7yIiU0Rkn4ikiUhXb/nzInJBCMdfpKojVHWxqn4EvAHcmct2/mcpks1yVPV9Ve2uqt3r1q0bZHjGGFM4UtMzeGnGGgZ/MI/K5aOY8o/TuK1vyyKdQCDIJCIipwN/AG2Bz/y2zwBuD/L4O4FVfstWAzmdMuzCnXH4ypxlsxtjjClmtuw7wlX/9zv/N3sj13RvyrR7TqdjkxqRDitPgm3OehHX/zAAiALu8lm3CPh7gG1y8htudJWv1kBMDtv8AbwkIhVVNclb1g/Xn7IlyOMbY0zEqCqTF27nya9XUi6qDP83uCsXdmwY6bCCEmxzVlfg/7xOb/+mo31AsO1FrwK9ReRREWklIoOAe4C3MwuIyAsi8oPPNp8BR4ExItJBRAYCDwM2MssYU2wcTEzlrvGLGT55GR0b12D6vWcUuwQCwZ+JJOGG1wbSEDgYzM5U9U8RGQA8DzwObPV+vuO335Y+2xwUkX64RLMAOICbHzI6mGMbY0ykzN8cx/0Tl7D7UBLD+7fh9r4tiSrifR/ZCTaJ/ArcJyJf+SzL/PZ/M/BjsAGo6rfAtzmsHxpg2XLgzGCPZYwxkZSWnsEbP6znrZ820LRWZSb/41Q6N60Z6bDyJdgk8jiuH2MpMBmXQIaIyGigG24GuTHGGD/b4o5y74TFLNoaz5Vdm/DU5e2pWiHSsyzyL9jJhktF5ExgFPAobmjtXcAvQF9VXRv+EI0xpnibujiWx6auQATeuK4Ll3VqFOmQwiboNKiqi4BzRaQiUAuIV9WjYY/MGGOKuYSkVJ74aiVfLo6le7MTeO3azjQ5Ibtu5eIppHMp7yKIHYDGwHYRWamqh8IamTHGFGMLYw5w38TF7IhP4v7zWnPn2S0pGxX0/O4iL+gkIiJP4C4JX5W/ZooniMgoVX02nMEZY0xxk56hvP3TBl7/YT0Na1Tk89t6061ZrUiHVWCCSiIi8hSuc/0DYAJuhnh94DrgKREpWwAXaTTGmGIhNj6R+ycsYf6WOC7v3IhnBnSgesVykQ6rQAV7JjIMeEVVh/ssWwn8KCIHcRc6HBmm2IwxptiYtmwHI6YsRxVevaYTV3RpEumQCkWwSaQG7rIngcwA/pG/cIwxpng5kpzGyK9XMmnhdjo3rckb13YhunbJ6jzPSbBJZB5uLsj3Adb18NYbY0ypsHRbPPdOWExM3FHuPqcV95x7EuVKYOd5TnJNIn73Tb8H+FJE0oBJ/NUncjVwE3B5QQRpjDFFSXqG8t7PGxk9ax31qlVgwrDe9GpRO9JhRURezkTSOP5ii4K7mu+LfuUEWJbHfRpjTLG082AiD0xcyh+b9nNxx4Y8f0VHalQu2Z3nOcnLB36476tujDHF0owVO3noi+Wkpmfw8lWnMKhbE0SK54UTwyXXJGJDdo0xpd3RlDSembaa8fO3ckqTGrx+bRdOrFMl0mEVCdb0ZIwxOVgRe5B7Jixm874j3N63JQ/0a035sqWr8zwnoV72pCnQFKjov05Vg74cvDHGFDUZGcqHv27m5ZlrqFWlPONu7sWprepEOqwiJ9gZ6y2AcUDPzEXeT/V+V9xtc40xptjacyiJByct5Zf1+zi/XX1euvIUTqhSPtJhFUnBnol8AEQD9wFrgJRwB2SMMZH0/ard/OuLZRxNSeP5KzpyXc+mpb7zPCfBJpEewFBV/aIggjHGmEhJSk3n+f+t5pM/YmjXsDpvXNeZVvWqRTqsIi/YJLIdO/swxpQwq3ce4t4Ji1m3+zC3nH4iwy9oQ4Wy1jKfF8EmkeeBh0TkR1U9UhABGWNMYVFVxvy+hRemr6F6xXJ8clNPzmxdN9JhFSvB3h73UxFpC2wRkbnAgaxFdEjYojPGmAKy73Aywyct5ae1ezmnbT1evuoU6lStEOmwip1gR2cNBUYA6UBXsjZt2cx2Y0yRN3vtHv45aSmHktJ4+vL23NC7mXWehyjY5qyngC+Bm1U1PvzhGGNMwUlKTeflGWv572+baVO/GuNu6U2bBtZ5nh/BJpHawDuWQIwxxc363QncPX4xa3YlMPTU5jx8YVsqlrPO8/wKNon8CpwM/FAAsRhjTNipKmPnbeXZaauoWqEs/x3anXPa1o90WCVGsEnkXuBzETmAu5Ohf8c6qpoRjsCMMSa/4o6k8K/Jy/h+9W7ObF2Xfw86hXrVslytyeRDsElktffzk2zWawj7NMaYsPt1/T4e+HwJ8UdTefySdtx4anPKlLHO83AL9gPf7i1ijCnSUtIyeGXWWt77eROt6lXloxt70L5RjUiHVWIFO09kZAHFYYwx+bZx72HunbCYFbGHGNwrmscubkel8tZ5XpCs6ckYU+ypKhP/3MZT36yiQrkyvHdDN/q3bxDpsEqFYCcb5navEFXVc/MRjzHGBCX+aAojpixn+opdnNqyNqOv7kyDGtZ5XliCPRMpQ9Y+kdpAG2AvsC4cQRljTHamLo5l1My17IhPpHaV8qRlKIeT0xhxYVuGndHCOs8LWbB9ImcFWi4iLYGpuAs0GmNMgZi6OJYRU5aTmJoOwL4jKQjwQL/W3Na3ZWSDK6XCcqNgVd0IvAiMCsf+jDEmkFEz1x5LIJkUmPDntsgEZMKTRDx7gdZh3J8xxhyTkaHExicGXLcjm+Wm4IUliYhILeABYGOQ240UEfV77MqhfPMA5VVELsjvazDGFF27DiYx5KP52a5vVLNSIUZjfAU7OmszWTvWywOZF6K5MoQY1gJn+TxPz6acrwuApT7P40I4rjGmGPhqSSyPT11BaroyqFsTvlm6g6S0v66uVKlcFMP7t4lghKVbsKOz5pA1iSQBMcAkr28kWGmqmu3ZRzb2h7CNMaYYiT+awmNTVzBt2U66RNdk9NWdObFOFU5rVefY6KxGNSsxvH8bBnRpHOlwS61gR2cNLYAYWohILO4GV/OAR1R1Uy7bTBGRisB64FVVnVwAcRljImTOur38a/JS9h9O4Z/nt+b2vi0pG+Va3wd0aWxJowiJ9Iz1ecBQYA1QD3gM+F1E2qvq/gDlDwP/BH4D0oDLgIkiMkRVxwY6gIjcCtwKEB0dHfYXYIwJn8SUdF6YvppP/ojhpHpV+XBIDzo0tuteFWWiGtz1FEVkCHAdEA34TwtVVQ15sLaIVAU2AS+q6ug8bvMOcLqqnpJb2e7du+uCBQtCDc8YU4CWbIvngYlL2LTvCDeffiLD+7exm0YVESKyUFW7B1oXbMf647hb5K4AlgDJ+Y7Oh6oeFpGVwElBbDYPuDGccRhjCk9qegZv/riBt3/aQP1qFfhsWC9ObVkn0mGZPAq2Oetm4HVVvb8ggvH6OdoCPwWxWWdgZ0HEY4wpWBv2JHD/xKUsjz3IwK6NGXlZe6pXLBfpsEwQQrnH+jfhOriI/Nvb31Zcn8jjQBXgY2/9C0DPzIs6ek1pqcBiIAO4FLgTeChcMRljCl5GhvLxH1t4cfoaKpeP4v8Gd+XCjg0jHZYJQShDfDsBuV3NN6+aAOOBOrgZ73OB3qoa461vCPj3sTwGNMPNJ1kH3JRdp7oxpujZEZ/I8MlL+W3Dfs5uU5eXrrJb1hZnwSaR+3DDa/cD/yPAJL9g7rGuqtfmsn6o3/OP8c5SjDHFi6ry1ZIdPP7VCtIzlOev6Mh1PZsiYlfdLc6CTSKZl3r/KJv1do91Y0wWB464iYPfLt9Jt2YnMPrqTjSrXSXSYZkwsHusG2MK1Oy1e/jX5GUcOJrC8P5tuL1vS6Lsnh8lht1j3RhTII6mpPHct6sZN28rretX5aMbe9C+kU0cLGms6ckYE3aLth7ggYlLiIk7yrAzTuTB823iYEllScQYEzYpaRm88cN63pm9gYY1KjF+WG96t6gd6bBMAbIkYowJi/W7E7j/8yWsiD3EVd2a8OSl7ahmEwdLPEsixph8ychQPvp9Cy/NWEPVCmV59/puXNChQaTDMoXEkogxJmSx8YkMn7SU3zfu57yT6/HCwFOoW61CpMMyhciSiDEmaKrKl4tjefKrlWSo8uLAjlzTwyYOlkZBJ5GCvBS8MaboizuSwqNfLmf6il30aH4CrwzqTHTtypEOy0RIkboUvDGmaPtxzW7+NXk5BxNTePjCtgw7o4VNHCzlitSl4I0xRdOR5DSe/XY14+dvpW2DanxyU0/aNaoe6bBMERDRS8EbY4q+hTFxPPD5UrbGHeW2M1vwwPmtqVDWJg4aJ9KXgjfGFFEpaRm89v063p2zkUY1KzFhWG962cRB4yeil4I3xhRNa3clcP/EJazaeYiruzfh8Uts4qAJzC4Fb4w5JiND+fDXzYyatZZqFcry/g3dOL+9TRw02bNLwRtjANh+4CgPfr6UeZvj6NeuPi8M7EidqjZx0OTMLgVvTCmnqkxeuJ2nvlkFwMtXncKgbk1s4qDJE2t6MqYU2384mUe+XM7MlbvpeWItXhnUiaa1bOKgybtQZqw3BB4E+gK1gP3AbGC0qu4Ka3TGmALzw+rdPPTFMg4lpvHIRW25+XSbOGiCF+yM9dbAL8AJwG/ABqABcC/wdxE5Q1XXhz1KY0zYHE5O49lpq5jw5zZOblidsbd0om0DmzhoQhPsmchLwCGgl6puyVwoIs2AWd76gWGLzhgTVn9uieOBz5ew/UAit/dtyf39TrKJgyZfgk0iZwO3+yYQAFWNEZGRwDthissYE0bJaem8+t163vt5I01OqMTnt/WhR/NakQ7LlADBJpHyQEI26xK89caYImTNrkPcN2EJa3YlcF3Ppjx6cTuqVrAxNSY8gn0nLQHuFpHpvjPTxY0FvMNbb4wpAtIzlA9+2cQrs9ZRvVI5PhzSnXNPrh/psEwJE8pkw2nAahGZCOzEdawPAk4CLg5veMaYUGyLcxMH52+Jo3/7+jx/RUdq28RBUwCCnWw4Q0QuAZ4FHgUEN4N9IXCJqs4Kf4jGmLxSVSYt2M5T36xERPj3oE5c2bWxTRw0BSbohlFVnQHMEJHKuKG+B1T1aNgjM8YEZd/hZEZMWc53q3bTu0Ut/j2oE01OsImDpmCF3LvmJQ5LHsYUAbNW7mLElOUkJKfx2MUnc9NpJ1LGJg6aQpBrEhGRdKCPqs4XkQxyvgCjqqoN+zCmkCQkpfLMtFV8vmA77RpW57NrOtOmQbVIh2VKkbx84D8NbPf53a7ia0wRMG/Tfh6ctJQd8YnceXZL7j23NeXLlol0WKaUyTWJqOpTPr+PLNBojDG5Sk5L55VZ6/jPL5uIrlWZSbf3oVszmzhoIsOanowpRlbtOMQDn7uJg3/rFc2jF51MFZs4aCIo2AswbgKuUNWlAdZ1AL5W1RbhCs4Y46RnKO//vInR362lZuXyfDS0B2e3rRfpsIwJ+kykOZDdjKWKQLN8RWOMyWLr/qM8OGkJf245wIUdGvDcFR2pVcWuMGSKhlB64bLrWO8OxAezIxEZKSLq98jxniQi0lFE5ohIoojEisgTYjOpTAmkqkyYv5ULX/+ZNTsTGH11J94Z3NUSiClS8jLE937gfu+pAt+ISIpfsUq4G1RNCCGGtcBZPs/Tc4ilOvAd8DPQA2gDjAGOAK+EcGxjiqS9Cck8/MUyflizhz4tavPvqzvRuGalSIdlTBZ5ac7aBPzg/T4EWADs9SuTDKwCPgghhrQg7og4GKgMDFHVRGCFiJwMPCAio1XVhh+bYmfq4lhGzVzLjvhEGtWsRP/29Zm6ZAeHk9N4/JJ23Hhqc5s4aIqsvAzx/Qr4Csi8/s4zqropjDG0EJFYIAWYBzySw/77AL94CSTTTOAZXH/NZv8NRORW4FaA6OjoMIZtTP5NXRzLiCnLSUx1J+Cx8Yn897ctNDmhEhNv7c1J9W3ioCnaguoTUdUbw5xA5gFDgQuBYbgrAv8uIrWzKd8A2O23bLfPuixU9X1V7a6q3evWrZv/iI0Jo1Ez1x5LIL4yMtQSiCkWInrZE1Wd7nesubjmsyHA6Ow28w8xm+XGFHmx8YkBl+88mFTIkRgTmiJ12RNVPSwiK3H3JglkF1nPODIHy/ufoRhTpB1MTKVi2TIkpWVkWdfIOtFNMVGkLnsiIhWBtsBP2RT5A3hJRCqqauZXtX7ADmBLQcZmTDit2nGIf4xbSEp6BuXKCKkZf303q1QuiuH920QwOmPyLqJXaxORf4tIXxE5UUR6AZOBKsDH3voXROQHn00+w11+foyIdBCRgcDDgI3MMsXGFwu3M/D/fiMpNZ3Pb+vDqEFu+K4AjWtW4oWBHRnQpXGkwzQmT/LSJ/JjMDtU1XOCKN4EGA/UwQ0bngv0VtUYb31DoKXPvg+KSD/gbdxQ4wO4+SHZ9Z8YU2Qkp6Xz9DerGDdvK71b1OLN67pSt1oFujfHkoYptvLSJ1KG4/tB2uD6Jbbg+iHq44bX7sRNHMwzVb02l/VDAyxbDpwZzHGMibTY+ETuGLuQpdsPclvfFgw/vw1lo+yy7ab4y0ufyFmZv4vIAOB13NnCfJ/lvYCJ3jpjjI+f1+3l3gmLSU1X3r2+Gxd0CDga3ZhiKdivQs8Aj/smEABVnQeMBJ4NU1zGFHsZGcqbP6xnyEfzqVetIl/fdZolEFPiBHsV35PIesmTTHuAVvkLx5iS4eDRVO7/fAk/rtnDgM6NeH5gRyqXt/t+mJIn2Hf1ZuA2YHqAdbdhw2yNYUXsQf4xbiG7Dibx9OXtuaF3M+xC06akCjaJPAWME5EVuOG4mR3rV+HmdwwOb3jGFC+fL9jG41NXUKtKeSbe1oeu0SdEOiRjClRQSURVJ4jIPlwyGQGUA1KBP4H+qvpDTtsbU1Ilpabz1DcrGT9/G6e1qs0b13ahdtXs7t9mTMkRdCOtqn4PfC8iZXDzO/apatbrNhhTSmyLO8od4xaxPPYgd5zVkgfPb0OUXbrdlBIh9/R5iWNPGGMxptiZvXYP901c4u6BfkM3zm9vo69M6RJ0EhGRIcB1QDTuvuq+VFVbZt3KmJIlI0N548f1vP7DetrUr8a713ejeZ0qkQ7LmEIXVBIRkcdx/SErgCW4OxoaU6ocOJLCfROXMGfdXgZ2bcxzAzpSqXxUpMMyJiKCPRO5GXhdVe/PtaQxJdDy7Qe5fexC9iYk89wVHfhbz2gbvmtKtWCTSG3gm4IIxJiibsL8rTzx1UrqVC3P57f3oXPTmpEOyZiICzaJzAE6AUFd2deY4iwpNZ0nvlrB5wu2c8ZJdXj92i7UqlI+0mEZUyQEm0TuA6aIyH7gf0CcfwEb7mtKkq37j/KPcQtZueMQ95zTinvPa23Dd43xEWwSWef9/Cib9RrCPo0pkn5cs5v7JiwB4L9Du3NO2/qRDciYIijYD/wCvce6MUVBeoby+vfreOPHDbRrWJ13r+9GdO3KkQ7LmCIp2MuejCygOIwpEuKOpHDvhMX8sn4fg7o14ZkBHahYzobvGpMda3oyxrNkWzx3jF3IviMpvDiwI9f2jI50SMYUeaHMWG8IPAj0BWoB+4HZwGhV3RXW6IwpBKrKuHlbefqbVdStVoEvbj+Vjk1qRDosY4qFYGestwZ+AU4AfgM24O63fi/wdxE5Q1XXhz1KYwpIYko6j05dzpRFsfRtXZfXrunMCTZ815g8C/ZM5CXgENBLVbdkLhSRZsAsb/3AsEVnTAHasu8It49dyNrdCdx33kncc85JlLHhu8YEJdgkcjZwu28CAVDVGBEZCbwTpriMKVDfrdrNA58voYwIHw3twVlt6kU6JGOKpWCTSHkgIZt1Cd56Y4qs9AzllVlreWf2Rjo2rsE7g7vStJYN3zUmVMEmkSXA3SIy3Xdmurgr0N3hrTemSNp/OJl7Jizmtw37ua5nU568tL0N3zUmn0KZbDgNWC0iE4GduI71QcBJwMXhDc+Y8Fi09QB3jltE3JEUXr7qFK7u3jTSIRlTIgQ72XCGiFwCPAs8CghuBvtC4BJVnRX+EI0Jnary6dwYnpm2igY1KvLFP06lQ2MbvmtMuIRyj/UZwAwRqYwb6ntAVY+GPTJj8uloShqPfrmCLxfHck7berx6dWdqVC4X6bCMKVFyTSIiUgbXTLVZVVdkLvcSx1GvTEeguaravUZMkbBp72H+MXYR6/Yk8GC/1tx5disbvmtMASiThzLXA+OBIzmUSQDGi8h1YYnKmHyYsWIXl7/1G3sSkvj4xp7cfa7N/zCmoOSlOet64CNV3ZxdAVXdIiIfAkNwCceYQpeWnsGoWWt5b84mOjWpwTvXd6NxzUqRDsuYEi0vSaQr8GYeyn0PDM5fOMaEZm9CMveMX8wfm/YzuFc0T1zajgplbfiuMQUtL0mkGnAgD+UOeGWNKVQLY+K4Y9wi4o+m8sqgTlzZrUmkQzKm1MhLn8g+oFkeykV7ZY0pFKrKR79t5pr35lKxXBRf3nGaJRBjCllezkR+xfV1jMul3FCvrDEF7khyGg9PWc43S3dw3sn1eeXqTtSoZMN3jSlseTkTeQ04V0ReFZEs18YSkXIi8jpwDvBqfoIRkUdEREXkrRzKNPfK+D8uyM+xTfGxYc9hBrz9G98u28Hw/m14/4ZulkCMiZBcz0RU9Q8ReRB4BRgsIrOAGG91M6AfUBt4UFXnhhqIiPQGhgHL8rjJBcBSn+dxoR7bFB//W76T4ZOWUrFcFJ/e3IvTWtWJdEjGlGp5mrGuqq+JyCLgYeAKIHPcZCLuroYvquovoQYhIjVwzWU3A0/kcbP9difF0iMtPYOXZqzhP79spkt0Td4Z3JWGNWz4rjGRlufLnqjqz8DP3gz2zK9/+1U1PQxxvA9MVtUfRSSvSWSKiFQE1gOvqurkMMRhiqA9CUnc9dli5m+O4+99mvHYxe0oXzYvLbHGmIIWyrWzMoA94QpARIYBrYAb8rjJYeCfuNvzpgGXARNFZIiqjg2w/1uBWwGio6PDErMpPPM3x3HnZ4tISErltWs6M6BL40iHZIzxEXQSCScRaQM8D5yhqil52UZV9+H6ZzItEJE6wL+ALElEVd/HnenQvXt3zXfQplCoKh/+upkXpq8hulZlPr25J20bVI90WMYYPxFNIkAfXNPYCndfKwCigDNF5Hagiqom52E/84AbCyZEU9gOJ6fx0ORlfLt8J/3b12fUoE5Ur2ijr4wpiiKdRKYCC/yWfYTr53geyNPZCdAZd4MsU8xt2JPAbZ8uZPO+Izx8YVtuO7MFPl8wjDFFTESTiKrGA/G+y0TkCBCXedl5EXkB6Kmq53rPhwCpwGIgA7gUuBN4qNACNwVi2rId/GvyMiqXj2LcLb3p07J2pEMyxuQi0mciedEQaOm37DHcHJV0YB1wU6BOdVM8pKZn8Pz/VvPRb1vo1uwE3v5bVxrUqBjpsIwxeZDvJCIiXXHXzQLYqqqL8rM/VT3L7/lQv+cfAx/n5xim6Nh9KIk7xy1iQcwBhp7anEcuOtmG7xpTjIScRESkG26CoAJbcfdbb+a1X/9NVReGJUJTYs3dtJ+7PlvM0ZQ03riuC5d1ahTpkIwxQcrPmcj7wF2q+r3vQhHpB/wHdx8SY7JQVf7zyyZemrGWZrUr89mwXrSub3cRMKY4yk8SqeqfQABU9bucLqBoSreEpFSGT1rGjJW7uKhjA1668hSq2fBdY4qt/CSRPSJyI/BJ5qVPRCQKN1/D7itisli3O4HbP11ITNxRHrv4ZG4+/UQbvmtMMZefJDIEeBd4TUR2eMsaAfO9dcYc89WSWB7+YjlVK5bls1t60auFDd81piQIOYmo6ibgfO+SI76js+wsxByTkpbBc9+u4uM/YujR3A3frVfdhu8aU1Lke4ivlzSOSxwiUk9Vw3aRRlO8TF0cy6iZa4mNT6R8VBlS0jO45fQTeejCtpSLsuG7xpQkBTXZcAF/nZ2YUmTq4lhGTFlOYqq7Q0BKegblo8rQoXENSyDGlED5mSdyWQ6rrb2iFEpKTWfkNyuPJZBMKekZjJq51i7jbkwJlJ8zkS+BObhJhv5s0H8psmXfEcbNi2HSwu3EH00NWGZHfGIhR2WMKQz5SSLrgZtVdbP/ChHZlo/9mmIgLT2DH9fs4dO5Mfyyfh9lywj92zdg3qb97DuS9eLLjWrarWyNKYnyk0Q+xt0LJEsSwQ39NSXQnoQkJs7fxvj5W9lxMIkG1Sty/3mtubZnU+pXr5ilTwSgUrkohvdvE8GojTEFJT9DfF/IYd1zoe7XFD2qyrzNcYydG8OMFbtIy1DOOKkOT1zanvNOrkdZnw7zzH6PUTPXsiM+kUY1KzG8fxvrDzGmhAoqiYjIfcAiYLGqJhRIRKbIOJSUypeLYhk7N4b1ew5TvWJZhpzanMG9omlRt2q22w3o0tiShjGlRLBnIi8C5QAVkY3AQlxSWQgsUtWDYY7PRMCqHYcYOy+GqYtjOZqSzilNavDyVadw6SmNqFQ+KtLhGWOKkGCTSDvgOyAO2ICbC3IpUBmXWJbiru77H1XNCGegpmAlp6UzffkuPp0bw8KYA1QoW4bLOjXi+t7N6NS0ZqTDM8YUUcEmkXeBL1X1n5kLRKQW8AQwGPgdeA64SkQuUtXA4z1NkbEt7ijj5m3l8wXbiDuSwol1qvDYxSdzVbcm1KxcPtLhGWOKuGCTyOm4Jq1jVDUOuE9EKuHOULrjksk/gWw7303kpGcoc9bt4dM/Ypi9bi8C9GtXn+t7N+O0lnUoU8aurGuMyZtgk8geoAvwY4B1E4EPVfVJEXkVdyVfSyJFyP7DyUxcsI3P5m1l+4FE6larwN1nt+LantE2j8MYE5Jgk8gnwGMi8qOqLvZb1xg3bwRcR/vT+Q3O5J+qsmjrAT79I4b/Ld9FSnoGvVvUYsSFJ3N++/p2PStjTL4Em0SeAU4B5orIROB/wC6gDfAk7sKLABUA6w+JoCPJaUxdEsunf8SwZlcC1SqU5W+9ohncK5qT7Fa0xpgwCSqJeB3lA0TkVmA4cD2guOtnrQRu84r2BjaGMU6TR+t2JzB2bgxTFsVyODmNdg2r88LAjlzWqRFVKhTURZuNMaVVSJ8qqvo+8L6ItAAaAnuB9aqqXpHpuIszmkKQkpbBzJVueO78zXGUjyrDJac0ZHDvZnSNrmm3oDXGFJj8XAq+vHd3w03+61R1br6iMnkSG5/I+HlbmfDnNvYdTqZprUo8fGFbBnVrQu2qFSIdnjGmFAj2sidlgaeAW4FaInIA+B54Q1V/L4D4jJ+MDOWXDfsYOzeGH1bvRoFz2tTj+j7N6HtSXRuea4wpVMGeiTwKPIC7gu8GoClwDvCLiDyqqi/mtLEJ3YEjKUxeuJ2x82KI2X+U2lXKc3vfllzXM5qmtSpHOjxjTCkVbBL5O/CIqr7qu1BEbgLeEZHVqvpV2KIr5VSVpdsP8ukfMXyzbAcpaRn0aH4CD/RrzQUdGlChrF3HyhgTWcEmkYa4Cy4eR1X/KyKtcbPULYnkU2JKOl8vjeXTuTGsiD1ElfJRXN29Cdf3bkbbBtUjHZ4xxhwTbBJZD3Qm8MirGcAd+Q2oNNu49zBj58YweeF2EpLSaFO/Gs8M6MAVXRpT1YbnGmOKoGA/mT4EnhSROaq6xG9dE+BwWKIqRVLTM/h+1W4+nRvD7xv3Uy5KuLBDQ67v3YwezU+w4bnGmCIt2CTyJtAXmOfNWJ+Om7HeCjdjfUZ4wyu5dh9KYvz8rYyfv5Xdh5Jp7N0B8OruTalbzYbnGmOKh2BnrKuIDALuB+7FzVjPNAt4MIyxlTiqyu8b9zN2bgyzVu0mQ5UzT6rLcwOacXbbekTZ8FxjTDGTaxIRkfNwdy2MA/BuNvUK8IqItMFddDFGVbcXaKTF2MHEVL7whudu2nuEmpXLccvpJ/K3XtE0q10l0uEZY0zI8nImMgt318IY/roVbubtcNcCawswvmJtRawbnvvV0liSUjPoEl2T0Vd34qKODalYzobnGmOKv7wkkfZAV6Cb93gYqIZLLNvJep/13QUUa7GQlJrOtGU7GTs3hiXb4qlULoorujRmcK9mdGhcI9LhGWNMWOWaRFR1NbAaGJe5zJsT0o2/ksuDQA3cFX1D/ootIo/gbq/7tqrelUO5jsBbQE/c3RTfA57xuQBkoduy7wjj5sUwaeF24o+m0rJuFZ68tB0DuzahRqVykQrLGGMKVKhX8V0HrAPGZy4TkVa4pBISEekNDAOW5VKuOvAd8DPQA3cvkzHAEVxfTaFJS8/gxzV7GDtvKz+v20vZMsL57d1tZvu0qG3Dc40xJV7YZrCp6gbc9bSCJiI1cGc6NwNP5FJ8MFAZGKKqicAKETkZeEBERhfE2cjUxbGMmrmWHfGJNKpZidvObMGhpFQ+m7eVHQeTqF+9Avef15prezalfvWK4T68McYUWUVlGvT7wGRV/VFEcksifYBfvASSaSburovNgc3hDGzq4lhGTFlOYmo64C6//sTXKwE4vVUdnri0PeedXI+ydptZY0wpFPEkIiLDcJMVb8jjJg0A/+HEu33WHZdEvLsw3goQHR0ddHyjZq49lkB81atWgbG39Ap6f8YYU5JE9OuzN8/keWCwqqYEsal/k5VksxxVfV9Vu6tq97p16wYd4474xIDL9yYkB70vY4wpaSLdBtMHN1lxhYikiUga7rIqd3jPA13/YxfujMNXPe9n2IcXN6pZKajlxhhTmkQ6iUwFOuKuDJz5WABM8H4PdHbyB3CGiPj2YPcDdgBbwh3g8P5tqOQ3MbBSuSiG928T7kMZY0yxE9E+EVWNB+J9l4nIESBOVVd4z18AeqrquV6Rz3AXexwjIs8CrXETIJ8qiJFZA7o0BjhudNbw/m2OLTfGmNIs4h3redAQaJn5RFUPikg/4G3cWcsB3PyQ0QUVwIAujS1pGGNMAEUuiajqWX7PhwYosxw4s5BCMsYYk41I94kYY4wpxiyJGGOMCZklEWOMMSGzJGKMMSZkEsGrpxc6EdkLxORjF3WAfWEKpzSw+gqO1VdwrL6Ck5/6aqaqAS/5UaqSSH6JyAJV7R7pOIoLq6/gWH0Fx+orOAVVX9acZYwxJmSWRIwxxoTMkkhw3o90AMWM1VdwrL6CY/UVnAKpL+sTMcYYEzI7EzHGGBMySyLGGGNCZknEGGNMyEptEhGRO0VkmYgc8h5/iMjFPutFREaKyA4RSRSR2SLS3m8fFUTkTRHZJyJHRORrEWlS+K+m8InIIyKiIvKWzzKrMx9eXajfY5fPeqsvPyLSUEQ+FpG9IpIkIqtEpK/Peqszj4hsCfD+UhH51ltfKHVVapMIsB14COgKdAd+BKaKyCne+n8BDwJ3Az2APcB3IlLNZx+vAVcC1wFnANWBaSJy/K0QSxgR6Q0MA5b5rbI6y2ot7p44mY+OPuusvnyISE3gN0CAi4GTcXWzx6eY1dlfenD8e6sroMDn3vrCqStVtYf3AOKA23Bv4p3Aoz7rKgEJwG3e8xq42/cO9inTFMgA+kf6tRRgHdUANgLnALOBt7zlVmdZ62oksCKbdVZfWevkeeC3HNZbneVcf4/i7hRbuTDrqjSfiRwjIlEici1QFfgdOBFoAMzKLKOqicDPwKneom5AOb8y24DVPmVKoveByar6o99yq7PAWohIrIhsFpEJItLCW271ldUAYJ6ITBSRPSKyRETuEhHx1ludZcOro5uBsap6lEKsq1KdRESko4gcBpKBd4Er1N01sYFXZLffJrt91jUA0sl6QTPfMiWKiAwDWgGPB1htdZbVPGAocCGu+a8B8LuI1MbqK5AWwB3AJqA/8DrwInCnt97qLHv9cInjA+95odVVkbs9biFbC3QGauLaBT8WkbN81vvPxJQAy/zlpUyxIyJtcM0NZ6hqSg5Frc48qjrd97mIzMV9QA4B5mYW89us1NYX7kvtAlUd4T1fLCIn4ZLIWz7lrM6yGgb8qapL/JYXeF2V6jMRVU1R1Q2qmvnGXQLcD2SOoPHPxvX4K7PvAqJwl1fOrkxJ0gf3WleISJqIpAF9gTu83/d75azOsqGqh4GVwEnYeyyQncAqv2WrgWjvd6uzAESkHnA58B+fxYVWV6U6iQRQBqgAbMZVcL/MFSJSETd64Xdv0UIg1a9ME9yIkswyJclU3Miizj6PBcAE7/d1WJ3lyKuPtrgPS3uPZfUb0MZvWWv+ugeQ1VlgQ3FN8hN8lhVeXUV6REEERzK86FVoc9yH4wu4UQkXeusfAg4BA4EO3h9oB1DNZx//B8QC5wFdgJ9wZzNRkX59hVSHs/FGZ1mdBayff+PO1k4EegHTvPppZvUVsL56eB9qj+L63gYBB4E77T2WbZ0J7gvcfwKsK5S6inglRLDyx+C+4STjxk9/j8+wNu+PMxL3rTEJmAN08NtHReBNXFPOUeAboGmkX1sh1qF/ErE6O/61Zv7Tpnj/qF8A7ay+cqyzi4GlXn2sA+7Bu1Cs1VnA+job13/RM8C6Qqkru4qvMcaYkFmfiDHGmJBZEjHGGBMySyLGGGNCZknEGGNMyCyJGGOMCZklEWOMMSGzJGJMPmRzUyD/x5Ycth/jU262z/Lm3rJb/MrXEZHFIhInIj28Zd/77GNsQb1WYwIp7RdgNCa/+vg9/xI3WW6kz7LkXPaxC7gCN7s4WyJSH/gBqA+co39dbO9u3L0hvsxTxMaEkSURY/JBVef6PheRZGCf//JcJOdWXkQa4xJIDaCvqh67UKGqrvY5tjGFypKIMUWciETjbt9cAZdA1kU4JGOOsSRiTNHWAnc3OgXOVNXNEY7HmONYEjGmaBuBu/tce0sgpiiy0VnGFG0zcFdjfV1EKkQ6GGP8WRIxpmj7ArgJOB+YJCLlIhyPMcexJGJMEaeqHwO3A5cCn4lIVIRDMuYYSyLGFAOq+j5wL3AV8ImI2P+uKRKsY92YYkJV3/D6RV4GkkXkZrW7ypkIsyRiTDGiqqO8RPIM7pand0Q4JFPKWRIxJoxUtXko24lIWbe5pnv72YIblRXoGM8Cz/psWwZrmjYRYm88YyKvGZCKu6xJKGZ52zcLW0TG5JFYk6oxkSMizYE63tMEVV0bwj5aA9W9p/ttUqIpTJZEjDHGhMyas4wxxoTMkogxxpiQWRIxxhgTMksixhhjQmZJxBhjTMj+H7F+h6SLtXmZAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "test = all_fim.extract_criteria()\n", + "\n", + "## draw 1D sensitivity curve \n", + "\n", + "fixed = {\"'CA0'\": 5.0}\n", + "\n", + "all_fim.figure_drawing(fixed, ['T'], 'Reactor case','T [K]','$C_{A0}$ [M]' )\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Heatmap" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fixed = {}\n", + "all_fim.figure_drawing(fixed, ['CA0','T'], 'Reactor case','$C_{A0}$ [M]', 'T [K]' )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read Heatmaps\n", + "\n", + "A heatmap shows the change of the objective function, a.k.a. the experimental information content, in the design region. Horizontal and vertical axes are two design variables, while the color of each grid shows the experimental information content. Taking the Fig. Reactor case - A optimality as example, A-optimality shows that the most informative region is around $C_{A0}=5.0$ M, $T=300.0$ K, while the least informative region is around $C_{A0}=1.0$ M, $T=700.0$ K." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Grid search for 3 design variables" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# Define design ranges\n", + "design_ranges = [list(np.linspace(1,5,2)), list(np.linspace(300,700,2)), [300,500]]\n", + "\n", + "# Define design variable \n", + "# Here the two T are for different controlling time subsets\n", + "dv_apply_name = ['CA0', 'T', 'T']\n", + "dv_apply_time = [[0], [0], [0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875,1]]\n", + "\n", + "# Define experiments\n", + "exp1 = generate_exp(t_control, 5, [300, 300, 300, 300, 300, 300, 300, 300, 300])\n", + "\n", + "## choose from 'sequential_finite', 'direct_kaug'\n", + "#sensi_opt = 'sequential_finite'\n", + "sensi_opt = 'direct_kaug'\n", + "\n", + "# model option\n", + "if sensi_opt == 'direct_kaug':\n", + " args_ = [False]\n", + "else:\n", + " args_ = [True]" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "doe_object = DesignOfExperiments(parameter_dict, dv_pass,\n", + " measure_class, createmod,\n", + " prior_FIM=prior_pass, discretize_model=disc, args=args_)\n", + "\n", + "all_fim = doe_object.run_grid_search(exp1, design_ranges, dv_apply_name, dv_apply_time, \n", + " mode=sensi_opt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Draw 1D sensitivity curve" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "test = all_fim.extract_criteria()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbQAAAEhCAYAAAAXn1W2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAABHlklEQVR4nO3dd5gUVdbH8e9vAkmSCAgIEkQlKwIqaVAXRDGD2VVQMaGisOsqa8LVVVGXYMT0ilnWvAYkGMiigwEQRSWpJAEVUTKc949bo0UzEQZ6mDmf5+lnpqtOVd2+09On761bt2RmOOecc7u7lGQXwDnnnCsMntCcc84VC57QnHPOFQue0JxzzhULntCcc84VC57QnHPOFQue0NwuI6mXJIs9NkiaK+l2SWWKQNkuSGYZigtJdSRtjv6+VZNYjoGSjspm+QhJC5JQnq2OK6le9H/QK7bM34c7wBOaS4bTgLbAccBoYABwd1JLBL0A/yApHOcRPlvSgbOSWI6bgW0SGnArcMouLkt2lhD+D96KLeuFvw+3W1qyC+BKpM/M7Nvo97GS9gculHSVmW1JZsEKk6TSZrY+2eVIgvOAWUBFoCdwX3KLszUzm5vsMgBE740Pk12O4sRbaK4o+AQoC/zRPSWpnKRBkuZHXVfzJV0vKSUWU0bSEEmzJP0maamkNyQ1SjyApPqSno5i1kuaJ2lYtO4DoBPQPtYd+kFs20MljYuO8bukdyUdmrD/EZJ+kNRW0hRJa4G7cnvRkk6RNDna76+SPpJ0Ymz9FZKmSvpJ0i+SPpR0XMI+0iTdGnXdrpO0QtIkSR0S4i6S9Hks5nFJVXIr3/aQ1BY4AHgKeBpoJalpPrdNl3SbpAXR33xB9Dw9FpPVTddH0mBJP0paI+lNSfVicVlTIF0f+5sOjNbl1PV3qaQ7ovfIaknPRO/DhpJGR3+nbyX1TCh3w+i9NV/S2ui99ZCkPfN4vVt1Oeb0PpTUKvr9pGz2kfW+S81PHRd33kJzRUE9YBWwEsKHNKErsgmhe2gmcDhwI1AF+Fu0XWmgAnAbofumCtAH+FBSIzNbGu2vPvARsIbQDfUNUAc4OtpPH+AZIBW4JFr2a7RtC2A8MJvQHWTAdcB4SYeb2eex11EJeAG4B/gnsDanFyzpSuBe4DVCK+Y34JCoLuL18hiwgPC/egLwpqRuZjYqirkW6AdcD3xGaBW1juoi61h3RnV2L3ANsE9UZ80ktTOzzTmVczv0BLYAzwLlo3KdF5UzL08CpwO3A5MI3XE3AA2AsxNiBxBe7/lA9WibMZKamtnGaNupwAjg4WibH/I4/gDgg+g1NCF8IdkCtAQeJfxdLwOekJRpZl9E29WK9n018HNU3n8Cb0flyK9s34dmNlvSx9Gy17OCJVUm1Nddhfw33H2ZmT92gwfhA+o+4CvCB+X3wEPAXnlslw7cBMwF1gGfA8dkE1eT8IGyPIqbDXSK7WMQMAP4nZA8ngP2TdhH6aiMK6K4/wG1Y+t7ERLC64QEtgqYAmwCrojFXR3FrY32dS9QivDhuIHwAdackGjWAoui15gKlANWEz7kOwHTgc2ED6Zrs3ndPaLXuoWQ8E5JWP9StHxhVC/Tga7AT8ArsbgRUZlPysffsmJUxlfyio1tk0JIamOA12PL38xtP4SkuBm4KWF5+6i8Jxfie7Q04QN9dGzZ1Ojvk5LHts2i8gxMWH5DtLxF7PVY9DdLicVlvZ4LY8sMuC2bY40AFiTUkQHvJcS9Ei3/a2zZntH79eZcXksa0CHatmU+jtsrtuwDYFI2++wV/R3rxpb1jcpSO6eylLSHdzkWMVEXwsBsVtUifLP+B+HD/K9ABvB8Hru8DbiU8OZvAgwHXpXUMnbMysBkQISBGo2BK4Efo5ByhNbDv6OfJxFaOO9EraksQwkJ4iygI+GD+81sukNOjNZVJHyD/d7M7o/KkgoMBNZHr+8c4FRgMOHDPB04EhgLLCN84P0O3EL45/6d0DJoTfiGPIWQfDKB2yT1iL3utsBIQmsiM3q9L0o6LFbWLkCZqB5bRvt7GXiXkDDjNhESTF7aRWV8JLegqKvpTUnLon1vjMpzYCzsY6CbpH9L6iCpVMJuuhCS4bNR92Ra9DebRmiFZuRy/JT4Nop19+bgJKAyobsxy5OE927nPLbNKsczCcuznifW9UsWO99qZpMJraSCtIgSjUp4/lX0c3TsOD8T3id1spZJKiXpn5K+irqaNwITo9Xxv9WOeAH4BbgotuwS4C0zy6vlWXIkO6P6Y+sH4VvcwHzGdiO0LCrmErMYuCph2cvAM7HntwOTC1jOJoRvl82j55UIradzYjF1ovJ1jZ4P4M8uu9bAsYQPZAP+EcUcGz3P7fEU4cO4R/R8RLTsx2i/PxK6Kb+J9rmR0F30GDA1Vr6RwNjo9w8I3VzjgOdjMQZ8nvDavyG0PLYk/N0W5bPuzon22yyXmDqED7AphG6lw6PXNoqtv+WnE7rzZkb7XA08AVSN1l+fR10+mcd7MR47Io/X9RbhC0UtQmKrDNSP3hfP5rFtVktsj4TlZaLlN0fP60XPL89mH5nAqIS/XUFaaL0T4gZGy9MSli9g6/+f/0Sv8QbCqMo2hFGUia2vnI4bj/mAbFpo0bp7CL0jaYQvjAYcW5D/2+L+8HNou7eKhJbMmlxiShO6yuLWErpEspxMaG2NJLR+FhM+/B+w6D8ph2ND6GICaEX4cB2TFWBm30v6ktAiGQ00jFa9ZNEoR0nvReW5XtIDhG/YvxLOp50exVcmtMguJXT5XUP4Btwd+NbMeklqA5xL6MasQkikL0fbryC0bl8BekpKtz/PsySOwBsNXBGVLau180tCzBhCMv0pYXlOdZVoRfRzH8JowOwcQ/iScLrFvoFLKrfVAcPrGAQMklQDOJ7Qmi0HnEF0XpJwvvBntrUym2VZBgL3Z1PubUjaOzpGGqGLMdEpkiqY2eocdpFVlzUI3ePEnmdXzr2z2cfehPNqu9qZwFNmdlvWAknld8JxHgL6E1rCpxAS6+jcNihpvMtxNxV1E94KPGpmm3IJHQ1cLenAqAupCyER1IzFNCCckJ5HOD80DLgTuDyHY5cifCt9I/ZhW4PQx5/4obeMPz+UKiXuy8LQ5R8JCbJPFLuI0EL5zcwyCd17mwknyDMJ5zGWET60s177suhnL8K5tLKxZWMIH/QbCR+4WaMpa8Ri1se2ySpvVlxLSRVixf4ZqEY4h7c9phAGgVycS0xW4tqYtUDSAYRzRdkys6Vm9hihldksWjyWkNz3NbPMbB7zc9nfgoTYBbmU96+Eur2M8KUo/riaULen5bJ9Vl2embD8nOjnhITlp2rrEa/tgdqElnOWDdFxd7ZyxP5OkfO3c19Z78NtWLjcYAzhC92phP/9YnOZS2HwFlqSSfonYURUltKASfp7bNmxZjYxts0ewBuED/5/5HGIqwgjtGYTWhBzCV1S8X+4FCDTzAZEzz9VuDbscrb+hp41AvEZQqvpRPIm8m65rCWc//g74RzUUsLglHcl/YcwkEVAF0nnR+U14B3gZElDCKMYIZxj+CUWA2Fk43GEb7gAbaOWTmosZjYhoR4Wvc4DCd13EP4m70oaFMX3isrzr3y8/m2Y2WpJA4D7JL1MOIe3GjgYWGdm9xGS0ibgqagOahLOE35H7IuopNej+vmEkGhbElp3D0fHmhuV+/7oNY0ntNjrEM6vPWZm72/P60hwHjAfeDixVS9pIuF92hP4v+w2NrMvJD0PDIzeY1MILegbCV3AMxI2qQC8JulhwpeLOwhdwfHzd7OB4yS9Q6ibxWa2eMdeZrbeIbT8ZwLfEr4wttvOfc0G+kg6g/C/utrM5sTWP0gYVLWRHOqyREt2n2dJfxC6xxrGHi8TRvXFl5WNxZcnfFudCJQvwHHKELq4ROii+iK2biHhgy0efy7we8KyNOBFwsnyGgnrjiJ82FdLWP4FcEv0++NRTMPYehFaK/dE60ZH25QhdHl9RfjWatHvAwnXN71F+GC/jdBFui6KOY7QFbOU0GWadZz9COfILNrfPELX5jXR+hqEQSRZ+/mAMLJyE+Hc37ionL8TRph+kvA6RwA/FPBvfyphcMbaqCzTgONj60+PXvO6qE7OZNvzMH8jXJy7MtrPnKiO0rP5e34Ylf834EvCl5UdHiFHSKIG3JhLzL8JLcX6ucSkR3/PhYQP7IXR8/RYTL3oWH0IXavLCV3ubyXum9CanR77mw6M/a0WZLPP7T2HVpUwaOPn6PEs4Tza9pxDy3ofrs56HyYcOzX6G764sz6TdudH0gvgj4Q/SC6DQgjfSicRRiRW2M79pxO+Rd4eW/YcMDEh7lZgdsJ2L0cfmDWz2W8lQhfP2bFltdl6UEjj6J+0XSymXbTswOj5sdE28eH+Z0cfShWj55cREkCZWMw/CS1WRc8HAXMSyvgI2w4KGZMQM4atB4VMAx5JiPkauCPZ75WS+Mgp+ZSUB6FVbcBfkl2WovhIegH8kfAHySGhRclsKuGb+v7RN7msR6lY3LvxD1tCF1p3wnmyjtH6eUDlWEwbwjfi6wktwtMIgysuj9anES4AXkQYth8/drz1+FAU05nwrf19wkn61FjMKP68ULpt9PsbsfWp0bL3on10jvZ5XyymEqEF9gLhXFH3KMH9LRZTn/BNdighkfYmJNwesZh2/NkCaxT93AgcFos5I9qud7SfYYQWTt1kv1dK4qOkJjRCD0MXwiCi6ckuT1F9JL0A/kj4g+Sc0I4g56HXR8TiFhAbXk24fmc2oYWzgnCOoVY2+z+OcC5mHaEF0pc/Wzv1cjl2r9g+yhBGDa4kdAO9AdRJOE4Vwjm4X6PHM8SSaxSzL+Fc2ppoX/cBpRNimhO6XtcRhjLfnFXehNf+CaGLcT5waTav+1RCt94GQjdc92xi+kT1up7QhZWR7PdJSX2U4IQ2IvryNR1omuzyFNVH1geWc845t1vzYfvOOeeKBR+2n0RVq1a1evXqJbsYzjm3W5k+ffoKM6uWuNwTWhLVq1ePzMzMZBfDOed2K5IWZrfcuxydc84VC57QnHPOFQue0JxzzhULntCcc84VC57QnHPOFQs+ynE389qni7h79BwW/7KWWpXLck3XAzm55T7JLpZzziVdkWihSeojab6kdZKmS+qYR3xzSeMlrZW0SNJNkpQQ0yna1zpJ8yRdms1+ekiaLWl99POUhPUVJA2VtDA61pToRpI5lesRSYm3fik0r326iAGvzGTRL2sxYNEvaxnwykxe+zS7+yk651zJkvSEFt33ZxhwO2Ey2inAKEn75hBfkXDTwmWESXX7Em541z8WU59wC4Yp0T7vINx7qkcspi1htvVnCfehehZ4UdJhscM9RrjhZU/C3IFjgHGStmkSSTo1Ks/OuN8SAHePnsPajZu3WrZ242buHj0nhy2cc67kSHpCIySiEWb2qJl9aWZXEiabvSyH+HMId4jtaWazzOxlwq1C+sdaaZcSbuZ3ZbTPR4EnCTeQzHI18L6Z/TuK+TfhHlhXA0gqC/QArjOzD8zsWzMbSLj1ylZlk1SXkJTPZts71xaaxb+sLdBy55wrSZKa0CSVAloRWj5xY8j5jq9tCffuin+KjwZqEWbizopJ3OdooLWk9Dxiso6bRriVybqEmLVAh9hrSAOeB24zsy9zKHOhqFU5+7vJly+TxoZNfid251zJluwWWlVC0liWsHwZ4V5b2amRQ3zWutxi0qJj5hZTA8DMVhPuP3aDpH0kpUr6KyER1oxtcwuw0sweyqG8W5F0saRMSZnLly/PzyZ/uKbrgZRNT91qWarE6nWbOPH+Scz44ZcC7c8554qTZCe0LIn3sFE2y/KKT1y+vTHxZecS7p78A+FeWH0JrbHNEAaeAL2AC3Ip69YFN3vEzFqbWetq1baZWzNXJ7fchzu6N2efymURsE/lsvzn9IN49LzW/LxmAyc/MJk73v6StRs257kv55wrbpI9bH8FITkktsaqs23rKcvSHOKJbZNTzCbCDSNzi/njuGY2F+gkaQ+gopktkTSScLNIgCMJrbUlsUGWqcAgSVebWe0cXsN2O7nlPtkO0z+0fhXuHPUlD0+Yx+gvlnJnjxYc3mCvwj68c84VWUltoZnZBsIdWLskrOpCGKGYnalAR0llEuIXE+4qnBXTOZt9ZprZxlhMvo5rZr9HyWxPwqjH16NVDwItCKMksx6LgSHAX3Io/05RqWw6d3RvwXO9D2OLwZmPfMj1r85k9bqdNkbFOeeKlKLQ5TgY6CWpt6TGkoYRBngMB5B0h6R3Y/HPAWuAEZKaSeoOXAcMtj9vvz0cqB1dQ9ZYUm9C1+A9sf0MA46SNEBSI0kDCC2uoVkBkrpKOlZSfUldgPeBOcATAGb2YzTS8o8HYZTjUjNLylj6dg2r8s7VHendoT7Pf/QdRw+ZwHtf5dTYdc654iPpCc3MRhKGyt8AfEYYQdjNzLLud1MT2C8Wv4rQkqoFZAIPAP8hJMasmPlANyAj2uf1QN9oiH9WzBTgTMI1ZjOA84AzzGxarHiVgPuBr4CngEnA0bFWXpFUrlQaNxzfhJcva0eFMmlcMCKTq1/4lJ9+35Dsojnn3E6jPxs1bldr3bq17ewbfG7YtIUH3v+WBz/4lgpl0hl4YlNOaFGThIlVnHNutyFpupm1Tlye9Baa27lKpaXQr8sBvHFlB+rsWZa+z3/KRU9lsnRV4uV1zjm3e/OEVkI0qlGRV/q05/pujZn07Qq6DB7P8x99h7fQnXPFhSe0EiQ1RVyU0YB3rsqg6T4VGfDKTM5+dBoLV/6e7KI559wO84RWAtWrugfP9T6cO7o3Z9aiVXQdOoHHJs5j8xZvrTnndl+e0EqolBRx1qH7MrZ/Jzo0rMptb31J94emMGfp6mQXzTnntosntBKuRqUyPHpea+49qyXf/7SG4++byJCxX/tkx8653Y4nNIckTjyoFuP6d6Jb85oMe/cbjr9vIp99/0uyi+acc/nmCc39ocoepRh2Zkse79maX9duovuDk7ntzdk+2bFzbrfgCc1t4y+N92ZM/wzOPHRfHps0n65DJzBl7opkF8s553LlCc1lq2KZdG4/pTnPX3Q4KYKzH53GgFdm8KtPduycK6I8oblctd1vL0ZdlcElGQ0Y+fH3dBk8nrGzfbJj51zR4wnN5alsqVQGdGvMa5e3Z89ypbjoqUyueO4TVvy2PtlFc865P3hCc/nWonZl/ndFB/p3OYDRXyyly+DxvPbpIp8+yzlXJHhCcwVSKi2Fvn/Zn7f6dqTuXntw9cjPuPDJTBb/sjbZRXPOlXCe0Nx2OWDvCrx8WTtuPL4JU+eu5OghE3jmw4Vs8emznHNJ4gnNbbfUFHFhh/qMvjqDg+pU4obXZnHWox8yf4VPduyc2/U8obkdtu9e5XjmwsO4q0cLZi/5lWOGTuDh8XPZtNmnz3LO7Tqe0FyhkMTpbeowrn8nMg6oxh2jvuKUB6cwe/GvyS6ac66E8ITmCtXeFcvwyLmteODsQ1iyai0n3j+J/4yZw/pNPn2Wc27n8oTmCp0kjmtRk7H9OnHiQbW4771vOe7eSUxf+HOyi+acK8Y8obmdZs89SjH4jIN54vw2rFm/iVOHT+GWN75gzYZNyS6ac64Y8oTmdrojD6zOmP6dOPfwujwxeQFHD5nApG98smPnXOHyhOZ2ifKl0/jXSc347yVtSU9N4a+PT+MfL33OqjU+2bFzrnB4QnO71KH1qzDqqo5cdsR+vPzJIjoPGc87s5Ymu1jOuWLAE5rb5cqkp3LtMY14rU97qpYvzaXPTOfyZz9h+Wqf7Ng5t/08obmkaV67Ev+7oj3XdD2QsbOX0XnweF6e/oNPduyc2y6e0FxSpaemcPmRDXn7qo40rF6ev734Ob2e+JhFPtmxc66AikRCk9RH0nxJ6yRNl9Qxj/jmksZLWitpkaSbJCkhplO0r3WS5km6NJv99JA0W9L66OcpCesrSBoqaWF0rCmS2sTWp0saJGmGpN8lLZH0nKR9d7ROSpqG1cvz4iVtGXhCEz5e8BNHDx7PU1MX+GTHzrl8S3pCk3QGMAy4HWgJTAFG5ZQUJFUExgLLgDZAX+AaoH8spj7wdrSvlsAdwH2SesRi2gIjgWeBg6OfL0o6LHa4x4CuQE+gOTAGGCdpn2h9OeAQ4N/Rz5OAOsA7ktK2q0JKsJQU0at9mOz4kLp7ctPrX3DGI1OZu/y3ZBfNObcbULLPV0iaBswws4tiy74BXjKzAdnEXwYMAvY2s7XRshuAy4DaZmaSBgHdzWz/2HaPAU3NrG30fCRQxcy6xGLGAcvN7CxJZYHVQA8zez0WMx0YZWY35PB6mgBfAC3MbGZur71169aWmZmZa/2UVGbGS9N/4NY3Z7Nu0xau7rw/F3VsQHpq0r+DOeeSTNJ0M2uduDypnw6SSgGtCC2fuDFAuxw2awtMzEpmkdFALaBeLCZxn6OB1pLS84jJOm4akAqsS4hZC3TIoWwAFaOfPs/TDpDEaa3rMO5vnTjqwOrc9c4cTn5gMrMWrUp20ZxzRVSyv+5WJSSNZQnLlwE1ctimRg7xWetyi0mLjplbTA0AM1sNTAVukLSPpFRJfyUkwprZFSxK0P8B3jCzH3KIuVhSpqTM5cuX5/ASXZbqFcow/NxWPHTOISz7dT0nPTCZu0d/xbqNPtmxc25ryU5oWRL7PZXNsrziE5dvb0x82bnAFuAHYD3hfN3zwDafptE5s2eAysD5ORbc7BEza21mratVq5ZTmEtwbPOajOufwSkt9+GB9+fS7d6JZC74KdnFcs4VIclOaCsIySGxNVadbVtPWZbmEE9sm5xiNgEr84j547hmNtfMOgHlgTpmdiiQDsyPbxQls+eBFsBfzGwlrtBVLleKe047iKcuOJT1G7dw2sNTGfi/L/h9vU927JxLckIzsw3AdKBLwqouhBGK2ZkKdJRUJiF+MbAgFtM5m31mmtnGWEy+jmtmv5vZEkl7EkY9xgeJpBNGS7YAjjQzn8dpJ8s4oBpj+mXQs209npwaJjse/7V33zpX0iW7hQYwGOglqbekxpKGEQZ4DAeQdIekd2PxzwFrgBGSmknqDlwHDLY/h2wOB2pH15A1ltQb6AXcE9vPMOAoSQMkNZI0ADgSGJoVIKmrpGMl1ZfUBXgfmAM8Ea1PA14EDgfOAkxSjehRthDryCXYo3QaA09syouXtKV0ego9/+8j/vbfz/llzYZkF805lyRJT2hmNhK4GrgB+IwwgrCbmS2MQmoC+8XiVxFaUrWATOABwkCMwbGY+UA3ICPa5/VAXzN7ORYzBTiTcI3ZDOA84AwzmxYrXiXgfuAr4ClgEnB0rJVXm3DtWS1CS3NJ7HHG9taJy7/W9arwdt+OXHFkQ177bBGdB09g1MwlyS6Wcy4Jkn4dWknm16EVri8Wr+IfL83gi8W/ckzTGvzrpKZUr1gm7w2dc7uVInkdmnOFqWmtSrx+eXuuPaYR7835kc6Dx/Ni5vc+2bFzJYQnNFespKWmcNkR+zHqqo4cWKMC17w0g/P+7yO+/2lNsovmnNvJPKG5Ymm/auUZeXFbbj2pKZ8s/JmuQyfwxOT5bPbJjp0rtjyhuWIrJUWc27Yeo/tl0KZeFW55YzanPzyVb39cneyiOed2Ak9ortirvWc5RpzfhsGnH8Tc5b/Rbdgk7n/vGzZu3pLsojnnCpEnNFciSKL7IbUZ268TXZruzT1jvubE+32yY+eKE09orkSpVqE0D5x9CA+f24oVv4XJju8c5ZMdO1cceEJzJVLXpjUY168Tpx5Sm+Hj59Jt2EQ+mu+THTu3O/OE5kqsSuXSGXRqC5658DA2bN7C6Q9P5cbXZrF63ca8N3bOFTme0FyJ12H/qozpl8EF7evzzLSFdB0ygffn/JjsYjnnCqjACU1SS0mvSFohaZOkQ6Llt0s6pvCL6NzOV65UGjed0ISXLm3HHqXTOP+Jj+k/8jN+/t0nO3Zud1GghCapA+G2K40Is97Ht98CXFp4RXNu12tVd0/e7NuBvkc15H+fL6bz4PG8OWOxT5/l3G6goC20O4HRQFOgf8K6T4BDCqNQziVT6bRU+h99IG9c2YFalctyxXOfcvHT01n267pkF805l4uCJrRDgIei+44lfmVdAVQrlFI5VwQ0rlmRV/u0Y8CxjZjw9XI6Dx7PyI+/89aac0VUQRPaOqBcDutqAn6VqitW0lJTuKTTfrxzdQaNa1bk2pdncs5j0/hupU927FxRU9CENgm4WlJqbFnW19ULgfcKpVTOFTH1q+7BCxcdzr9PacaMH1bRdegEHp/kkx07V5QUNKHdSOh2/Dz63YCekt4HDgduKdziOVd0pKSIcw6ry9j+GbTdby9ufXM2PR6awtfLfLJj54qCAiU0M/scyACWAdcDAq6IVncyszmFWzznip6alcryeM/WDDvzYBau/J3j7p3Ive9+w4ZNPtmxc8mk7T3BLakMUAX4xcz8hMJ2aN26tWVmZia7GG4HrPxtPQPfmM0bny+mUY0KDOrRgoPqVE52sZwr1iRNN7PWicu3e6YQM1tnZos9mbmSbK/ypbnvrJY8el5rfl6zgVMenMztb3/J2g0+2bFzu1pBL6y+VtJ9Oay7V9I1hVMs53YvXZrszdj+nTijTR0emTCPY4dNYOrclckulnMlSkFbaOcDM3JY91m03rkSqWKZdO7o3oLneh/GFoOzHv2Qf746k199smPndomCJrR9gW9yWDcPqLtjxXFu99euYVVGX53BRR3r88JH33H04Am899WyZBfLuWKvoAltDbBPDutqA+t3rDjOFQ9lS6Vy/XFNeKVPeyqVTeeCEZlc9cKnrPzN/0Wc21kKmtAmAtdIKh1fGD3/W7TeORc5uE5l3riyA1d33p+3Zy6hy5AJvP7ZIp8+y7mdoEDD9iUdBEwhzNv4DLCI0GL7K7AX0D66Vs3lgw/bL1nmLF3NP16eweff/8JfGlXntlOaUbNS2WQXy7ndTk7D9gt8HZqkQ4F7gHaEFt4WwpRYfzcz/3QuAE9oJc/mLcYTk+dzz5g5pKekMKBbY85sU4eUFCW7aM7tNgrtOjQz+8jMMoAKhPNmFczsiB1JZpL6SJovaZ2k6ZI65hHfXNJ4SWslLZJ0kyQlxHSK9rVO0jxJ29yrTVIPSbMlrY9+npKwvoKkoZIWRseaIqlNQowkDZS0OIr5QFLT7a0LV7ylpojeHRsw+uoMmu1TiX++OpOzH/uQBSt+T3bRnNvt7ciF1WujC6vX7kgBJJ0BDANuB1oSujRHSdo3h/iKwFjC9FttgL7ANcTuzyapPvB2tK+WwB3AfZJ6xGLaAiOBZ4GDo58vSjosdrjHgK5AT6A5MAYYJyk+MOYfhPOHV0bl+REYK6lCwWvDlRR199qD5y46jDu7N+eLRb9yzLAJPDphnk927NwO2K6pr6JzaQcCZRLXmdlTBdzXNGCGmV0UW/YN8JKZDcgm/jJgELB3VjKVdANwGVDbzEzSIKC7me0f2+4xoKmZtY2ejwSqmFmXWMw4YLmZnSWpLLAa6GFmr8dipgOjzOyGqFW4GLjfzP4drS9LSGp/N7OHc3vt3uXoAJauWscNr81k3Jc/clDtStx16kEcWMO/DzmXk0LpcpRUWdJkwt2pnwdGRI8nYo+C7K8U0IrQ8okbQzhHl522wMSEluFooBZQLxaTuM/RQGtJ6XnEZB03DUgl3AMubi3QIfq9PlAjvp+oXBNyKb9zW6lRqQyPntea+85qyQ8/r+X4+yYyZOzXrN/k02c5VxAF7XK8nTCaMYMw0/4pwFGE7rp5wKEF3F9VQtJIvOp0GSFRZKdGDvFZ63KLSYuOmVtMDQAzWw1MBW6QtI+kVEl/JSTCmgnHy3f5JV0sKVNS5vLly7N/ha7EkcQJB9VibP9OHNe8JsPe/YYT7pvEp9/9nOyiObfbKGhC60pIah9Gz38wsw/M7DxgHHDVdpYjsd9T2SzLKz5x+fbGxJedSxjF+QPhovG+hJZp4lfnfJffzB4xs9Zm1rpatWrZhbgSrMoepRh6Zkv+r1drVq/bRPeHpnDrm7NZs2FTsovmXJFX0IRWE5hnZpsJXXHxjv5XgOMKuL8VhOSQ2JqpzratnixLc4gntk1OMZuAlXnE/HFcM5trZp2A8kAdMzsUSAfmx/ZBAcvvXJ6OarQ3Y/plcM5h+/L4pPkcM3QiU75dkexiOVekFTShLQUqR78vJHS/ZWlY0IOb2QZgOtAlYVUXwgjF7EwFOkb3Y4vHLwYWxGI6Z7PPTDPbGIvJ13HN7HczWyJpT0IrNWuQyHxCncQHlpQBOuZSfufypUKZdG47uTkvXHw4KYKzH5vGdS/PYNVan+zYuewUNKFN4s8k9jRws6SHJT0A3E0YVFFQg4FeknpLaixpGGGAx3AASXdIejcW/xxhTskRkppJ6g5cBwy2P4dsDgdqR9eQNZbUG+hFuCA8yzDgKEkDJDWSNAA4EhiaFSCpq6RjJdWX1AV4H5hDNPglOt5Q4DpJ3SU1IwyS+S0qp3M77PAGe/HO1Rlc0qkB/838nqOHjGfsbO8AcG4bZpbvB7Af0DH6PR34D+H80k+ED/C9CrK/2H77EFpX6wkttozYuhHAgoT45oSRhOuAJcDNRJcgxGI6EUZjrie0pC7N5rinAl8BG4AvCUP94+tPB+ZG+1gC3A9USogRMDBavw4YDzTLz+tu1aqVOVcQn3//s3UdMt7qXvumXf7sdFu+el2yi+TcLkfobdvmMzXf16FFQ+xHAkPMbEK+NnK58uvQ3PbYsGkLD4+fy33vfUu50qncfEITTj54HxImy3Gu2Nrh69AsnO/qXJBtnHOFr1RaClf+ZX/e6tuB+lX3oN/Iz7lgxMcs/mWHJu1xbrdX0OQ0GTh8ZxTEOVcw++9dgZcubcdNxzfhw3k/cfSQCTz94UK2+PRZroQqaEL7G3ChpCsk1Y4uNk6JP3ZGIZ1z2UtNERd0qM+YfhkcXKcyN742izMf/ZD5PtmxK4EKej+0LdGvOW1kZpa2w6UqIfwcmitMZsaLmT9w61uz2bBpC/26HEDvDvVJS/Xvma54yekcWkGTz7/IfQYP51ySSOL0NnXodGA1bnxtFneO+oo3Zyzmrh4H0aRWxWQXz7mdbrtm23eFw1tobmcxM0bNWspNr8/ilzUbueyI/bjiqIaUTktNdtGc22HbPcoxujnmQTunWM65nUES3ZrXZGy/Tpx4cC3ue+9bjrt3EtMX+mTHrvjKT+d6PaD0Ti6Hc24n2HOPUgw+/WBGnN+GtRs2c+rwKdzyxhf8vt4nO3bFj58tdq4EOOLA6ozul8G5h9flickL6Dp0AhO/8dsXueIlvwnNT7Q5t5srXzqNf53UjP9e0pZSqSmc+/hH/OOlz1m1xic7dsVDnoNCoqH67xBu9ZIXM7OehVGwksAHhbhkWbdxM8Pe/YZHJsyjyh6luPWkZhzTLKd76jpXtOQ0KCS/CW0pYYLevJiZNdi+IpY8ntBcss1atIp/vDSD2Ut+pVvzGgw8sSnVK5TJe0PnkmhHE9rhZvbRzipcSeUJzRUFGzdv4ZEJ8xj27jeUTU/lpuOb0P0Qn+zYFV07PDmxc654Sk9N4fIjG/J23440rF6ev734OT2f+Jgffl6T7KI5VyCe0JxzADSsXp4XL2nLLSc2JXPBT3QdMoGnpi7wyY7dbsMTmnPuDykpome7eoy+OoND6u7JTa9/wekPT2Xu8t+SXTTn8pRnQjOzFD9/5lzJUqdKOZ664FDuOe0gvvnxN44dNpEH3v+WjZu35L2xc0niLTTnXLYkcWqr2oztn0HnxtW5e/QcTn5gMrMWrUp20ZzLlic051yuqlcow4PntGL4Xw9h2a/rOemBydz1zles27g52UVzbiue0Jxz+XJMs5q8278T3Vvuw4MfzKXbvRPJXPBTsovl3B88oTnn8q1SuXTuPu0gnrrgUNZv3MJpD0/l5tdn8ZtPduyKAE9ozrkCyzigGmP6ZdCzbT2e+nAhXYdMYPzXPtmxS64dTmiSDpF0cvQ4pDAK5Zwr+vYoncbAE5vy0qVtKZOeQs//+4j+//2MX9ZsSHbRXAmVtr0bSmoFPEuYif87QEDdaLqcs81seqGU0DlXpLWqW4W3+nbk/ve+Zfj4uUz4ejn/OqkZ3ZrXTHbRXAmzIy20R4ArzKyxmXU1s6PN7EDgCuDRwimec253UCY9lb93PZDXr2hPjUpl6PPsJ1z69HR+/HVdsovmSpAdSWjlzWxc4kIzGwvssQP7dc7tpprWqsRrfdpz7TGNeG/Oj3QePJ7/Zn5PXpOgO1cYdiSh/SjpfEmpWQskpUrqTf7uneacK4bSUlO47Ij9eOeqjjSqUZF/vDSD8/7vI77/ySc7djvXjiS0nsBZwE+SvpT0JfATcEa0Lt8k9ZE0X9I6SdMldcwjvrmk8ZLWSlok6SYl3OtCUqdoX+skzZN0aTb76SFptqT10c9TEtanSro1Vrb5km6TlBaLKS/pPkk/ROWZI6lfQV6/c8VRg2rleeHiw7n15GZ8svBnjh4ygScmz2ezT3bsdpLtHhRiZvOAoyVVBfaNFn9nZgVqnUk6AxgG9AEmRT9HSWpiZt9lE18RGAtMANoABwIjgN+B/0Qx9YG3gf8D/gp0AB6UtNzMXo5i2gIjgZuBV4DuwIuS2pvZtOhw1wKXExL0TKAF8CThZqe3RjGDgc7AucB8IAN4VNIKM3u6IHXhXHGTkiLOPbwuRzWqzvWvzuSWN2bzxueLuevUFjSsXiHZxXPFTJ43+NyunUrVzezHfMZOA2aY2UWxZd8AL5nZgGziLwMGAXub2dpo2Q3AZUBtMzNJg4DuZrZ/bLvHgKZm1jZ6PhKoYmZdYjHjgOVmdlb0/E1gpZn1jMU8CexlZsdHz2cBL5vZzbGY8cBMM7sit9fuN/h0JYmZ8dpni7jljdmsWb+Zvn9pyCWd9iM91S+HdQWzq2/wma9PaUmlgFbAmIRVY4B2OWzWFpiYlcwio4FaQL1YTOI+RwOtJaXnERM/7iTgSEmNovI2AY4itP7iMSdIqhPFtAMOBt7JofzOlUiSOKVlbcb170SXpntzz5ivOeG+Scz8wSc7doVjR65DOzGX1WXyuZuqQCqwLGH5MkI3XnZqAD9kE5+1bn70M3EE5jLC660KLIlisjtujdjzQUAFYLakzdH2/zazB2MxfYHhwHeSsub/udLM3syu8JIuBi4G2HfffbMLca5Yq1q+NA+cfQgnHrSUG1+bxckPTuaijg24uvP+lElPzXsHzuVguxMa8CownnBBdaKCdo4n9nsqm2V5xScu396Y+LIzgPOAs4EvCC2vYZLmm9njUcyVQHvgRGAh4RzaPZIWmNk2rTQze4RwDR+tW7f2s+OuxOratAaHN9iL29/6kuHj5zL6i6Xc2b05hzXYK9lFc7upHUlo3wAXmtn8xBWSvs/nPlYAm9m6VQRQnW1bT1mW5hBPbJucYjYBK/OIiR/3buAeM3shej5TUl1gAPC4pLLAHcBpZvZGFDND0sHA3/FuR+dyValsOoNObcGJB9fiuldmcMYjH/LXw/fl2mMaUaFMet47cC5mR86hPUnovsvO8PzswMw2ANOBLgmrugBTcthsKtBRUpmE+MXAglhMYpdlFyDTzDbGYvI6bjlCwo3bzJ/1lh49cotxzuWhfcOqjL46gws71OfZad/RdcgE3v8qX+PKnPvDdn/omtkdZvZxDuv+XYBdDQZ6SeotqbGkYYQBHsMBJN0h6d1Y/HPAGmCEpGaSugPXAYPtzyGbw4HakoZG++wN9ALuie1nGHCUpAGSGkkaABwJDI3FvAFcJ+k4SfWi69T6E7pbMbNfCd2ud0o6QlJ9Sb0I3ZSvFqAOnCvxypVK48bjm/DyZe3Yo3Qa54/4mH4jP+On332yY5c/O2XYfoELIfUB/gHUBGYB/cxsQrRuBHCEmdWLxTcHHgAOBX4mJLB/xRIakjoBQ4CmhNbbIDPbquUo6VTgNqABMBe43sxeia2vQLje7BRCd+QS4IXoWOuimBqEbsejgSqE82iPAf+xPCrXh+07l731mzbzwPtzefD9b6lUNp1bTmrKcc1rkjB/giuhchq2X6CEJum9XFZvAVYRuhAfN7OczoG5iCc053L35ZJfufblGcz4YRVdmuzNbSc3Y++K+R1E7YqrwroOTYSZOY4A6hKG59eNnjcG6gM3ArOia7acc267Na5ZkVcua8c/uzViwtfL6Tx4PC989J1PduyyVdCENhhYB7Qys/3MrJ2Z7UeYgmodcAuwP7AcKMh5NOecy1ZaagoXZ+zH6KszaFKzIte9MpNzHpvGdyt9smO3tYImtNuAgWb2aXxhdDPPW4DbzOwHwnD3jMIponPOQb2qe/D8RYdz+ynNmfHDKo4eOp7HJs7zyY7dHwqa0A4g51vDLAcaRr/Pxe+J5pwrZCkp4uzD9mVs/wza7VeV2976kh4PTeHrZauTXTRXBBQ0oS0Aeuew7mL+vA6sKn9ewOycc4WqZqWyPN6zNcPOPJjvflrDcfdOZNi4b9iwaUuyi+aSqKAzhfwLeEbSDOBl4EfCcPYeQDPCFFEQLmqelu0enHOuEEjipIP3oUPDqtzyxmyGjPuat2cu4a5TW3BQncrJLp5LggJfhyapC+F8WSvCLBkbCbPr32xm46KYMsDm2KwcLhs+bN+5wjNu9jJueG0WP65ex4Ud6tO/y4GULeWTHRdHhXIdWsIOUwhdiyvMzNv528ETmnOF69d1G7lz1Fc8N+076u5Vjju7t6Dtfj7ZcXFT6PdDM7MtZvajJzPnXFFRsUw6t5/SnOcuOgyAsx79kAGvzOTXdd5ZVBIUOKFJqinpHkkfS5or6SNJd0VTQDnnXNK1268q71yVwcUZDRj58XccPXgC737pkxcVdwVKaJIOAD4j3NTyN+Aj4HfgKuAzSfsXdgGdc257lC2Vyj+7NeaVPu2pVDadC5/MpO/zn7Lyt/XJLprbSQraQhsE/AocYGZHmtlZZnYk4fq0VdF655wrMg6uU5k3ruxAv84HMGrWEroMmcDrny3y6bOKoYImtCOBG81sQXyhmS0EBkbrnXOuSCmVlsJVnffnrb4d2bdKOa564TN6P5nJklVrk100V4gKmtBKATldkr86Wu+cc0XSAXtX4OXL2nHDcY2ZPHcFXQZP4NlpC9ni02cVCwVNaJ8BV0ZD9v+gcJOiPtF655wrslJTRO+ODRhzdSda1K7E9a/O4uzHPmTBit+TXTS3gwp6P7RjgDcJczWOJNzwsgZwGmGW/ePMbMxOKGex5NehOZdcZsbIj7/n3299yYbNW/jb0QdwQfv6pKVu9xVNbhcotAuro6R2G9CScH80I9zU80YzG10IZS0xPKE5VzQsXbWOG16bxbgvl3FQ7UoMOrUFjWpUTHaxXA52xkwh5YA9gZ/NzG9MtB08oTlXdJgZb81cws2vf8GqtRvpc2RDLj9yP0qn+fRZRc3OmClkjZkt8mTmnCsOJHF8i1qM69+JEw6qxb3vfsPx907ik+9+TnbRXD7lmdAkbZG0OZ+PTbui0M45t7PsuUcphpxxME/0asNv6zfR46Ep3PrmbNZs8I+3oi4/t4/5F+E8mXPOlRhHNqrOmH4ZDHrnKx6fNJ8xs5dyZ/cWtG9YNdlFcznY7nNobsf5OTTndg/T5q3kuldmMn/F75zZpg4DujWmUtn0ZBerxCr0c2jOOVdSHNZgL0Zd1ZFLOjXgv5nf02XweMZ8sTTZxXIJPKE551w+lElPZcCxjXnt8vZU2aMUFz89ncuf+4Tlq32y46LCE5pzzhVAi9phsuO/H30AY79YRpch43n10x98suMiwBOac84VUHpqClcctT9vX9WBBlX3oN/Izzl/xMcs+sUnO04mT2jOObedGlavwIuXtuPmE5owbd5PHD14PE9/6JMdJ0uRSGiS+kiaL2mdpOmSOuYR31zSeElrJS2SdFM0QXI8plO0r3WS5km6NJv99JA0W9L66OcpCetTJd0aK9t8SbdJSkuIO0DSK5J+kbRG0ieSGu9InTjndg+pKeL89vUZ0y+DlvvuyY2vzeLMRz5k3vLfkl20EifpCU3SGcAw4HbC/JBTgFGS9s0hviIwFlgGtCHcPfsaoH8spj7wdrSvlsAdwH2SesRi2hImWH4WODj6+aKkw2KHuxa4PDpGI8KduS8HBiQcazIwHzgKaAbcQLijt3OuhKhTpRxPX3god53agq+W/sqxwyYyfPxcNm3ekuyilRhJvw5N0jRghpldFFv2DfCSmQ3IJv4ywp2x9zaztdGyG4DLgNpmZpIGAd3NbP/Ydo8BTc2sbfR8JFDFzLrEYsYBy83srOj5m8BKM+sZi3kS2MvMjo+ePweYmZ1T0Nfu16E5Vzz9+Os6bnx9FqO/WEazfSpyV4+DaFLLJzsuLEXyOjRJpYBWQOItZ8YA7XLYrC0wMSuZRUYDtYB6sZjEfY4GWktKzyMmftxJwJGSGkXlbUJohb0dPU8BTgBmS3pH0nJJH0etTudcCVW9YhkePrc1D51zCEtXrefE+ydxz+g5rNu4OdlFK9aS3eVYFUgldB/GLSPcZy07NXKIz1qXW0xadMzcYuLHHQQ8TUhYG4EvgCfN7MFofXWgPPBPQnLsAjwPPCvp+OwKL+liSZmSMpcvX57DS3TOFQfHNq/JuP4ZnHTwPtz//rccd+9Epi/8KdnFKraSndCyJPZ7KptlecUnLt/emPiyM4DzgLOBQ6Lf+0i6MFqfVX+vm9lgM/vMzAYD/yWca9u24GaPmFlrM2tdrVq17EKcc8VI5XKl+M/pB/HkBYeybuMWTh0+lYH/+4Lf1/tkx4Ut2QltBbCZbVtj1dm29ZRlaQ7xxLbJKWYTsDKPmPhx7wbuMbMXzGymmT0NDObPQSEron3OTtjPl0C2g1qccyVTpwOqMbpfBucdXpcRUxbQdegEJn7jvTSFKakJzcw2EO523SVhVRfCCMXsTAU6SiqTEL8YWBCL6ZzNPjPNbGMsJq/jliMk3LjNRPUWlf9j4MCEmAOAhTmU3zlXQpUvncYtJzXjxUvbUiothXMf/4hrXvycVWs25r2xy1OyW2gQWjy9JPWW1FjSMMIAj+EAku6Q9G4s/jlgDTBCUjNJ3YHrgMH255DN4UBtSUOjffYGegH3xPYzDDhK0gBJjSQNAI4EhsZi3gCuk3ScpHrRdWr9gVdjMXcBZ0TnxhpKugg4E3hgx6vGOVcctalXhbf7dqTPEfvxyqeL6DxkPO/MWpLsYu3+zCzpD6APoXW1ntBiy4itGwEsSIhvDkwA1gFLgJuJLkGIxXQCPon2OR+4NJvjngp8BWwgdBN2T1hfgZDgFgJrgXmE6+XKJMT1Ar6OYmYAZ+Xndbdq1cqccyXbzB9+sWOHTrC6175plz6dact+XZvsIhV5hN62bT5Tk34dWknm16E55wA2bt7CIxPmMezdbyibnsqNxzehxyH7kDABkosUyevQnHPOhcmOLz+yIW/37cj+1cvz9xc/p+cTH/PDz2uSXbTdiic055wrIhpWL89/L2nLv05qyvQFP3H0kAk8OWWBT3acT57QnHOuCElJEee1rcfofhm0rleFm//3Bac/PJVvf/TpYfPiCc0554qg2nuW48nz2/Cf0w7imx9/o9uwiTzw/rds9MmOc+QJzTnniihJ9GhVm3H9O9G5SXXuHj2Hk+6fzKxFq5JdtCLJE5pzzhVx1SqU5sFzWjH8r4ew/Lf1nPTAZAa985VPdpzAE5pzzu0mjmlWk3H9OtG95T489MFcug2byMcLfLLjLJ7QnHNuN1KpXDp3n3YQT194KBs2b+G04VO56fVZ/OaTHXtCc8653VHH/asx+uoMzm9fj6c/XEjXIRP4YM6PyS5WUnlCc8653dQepdO4+YSmvHRpO8qWSqXXEx/T/7+f8fPvG5JdtKTwhOacc7u5VnX35K2+HbjyqIb877PFdBkynrdnLqGkTW3oCc0554qB0mmp/O3oA/nfFR2oWaksfZ79hEufmc6Pv65LdtF2GU9ozjlXjDSpVZFX+7TjumMb8cGc5XQePJ7/Zn5fIlprntCcc66YSUtN4dJO+zHqqo40qlmRf7w0g3Mf/4jvfyrekx17QnPOuWKqQbXyvHDR4dx2cjM++/4Xjh4ygf+bNJ/NxXSyY09ozjlXjKWkiL8eXpcx/TI4rEEV/vXmbE4bPoVvlq1OdtEKnSc055wrAWpVLssTvdow9IyDmb/id467dxL3vftNsZrs2BOac86VEJI4ueU+jO3fiaOb7s1/xn7NCfdNYuYPxWOyY09ozjlXwlQtX5r7zz6ER85txc9rNnDSA5O4Y9SXu/1kx57QnHOuhDq6aQ3G9OvEGW3q8PD4eRw7bCIfzluZ7GJtN09ozjlXglUqm84d3VvwXO/D2LzFOPORD7n+1ZmsXrcx2UUrME9ozjnnaNewKu9c3ZHeHerz/EffcfSQCbz/1e412bEnNOeccwCUK5XGDcc34eXL2lG+dBrnj/iYq1/4lJ92k8mOPaE555zbSst99+TNvh246i/78+aMJXQZPJ43Pl9c5KfP8oTmnHNuG6XTUunX5QDe7NuB2nuW5crnP+Wip6azdFXRnezYE5pzzrkcNapRkVf6tOf6bo2Z9O1yugwez/MffVckW2ue0JxzzuUqNUVclNGAd67KoOk+FRnwykzOfnQaC1f+nuyibaVIJDRJfSTNl7RO0nRJHfOIby5pvKS1khZJukmSEmI6RftaJ2mepEuz2U8PSbMlrY9+npKwPlXSrbGyzZd0m6S0HMr1iCST9PftqQfnnCvK6lXdg+d6H87tpzRn1qJVdB06gccmzisykx0nPaFJOgMYBtwOtASmAKMk7ZtDfEVgLLAMaAP0Ba4B+sdi6gNvR/tqCdwB3CepRyymLTASeBY4OPr5oqTDYoe7Frg8OkYj4Kro+YBsynVqVJ7FBawC55zbbaSkiLMP25cx/TNov19VbnvrS7o/NIU5S5M/2bGS3Q8qaRoww8wuii37BnjJzLJLHJcBg4C9zWxttOwG4DKgtpmZpEFAdzPbP7bdY0BTM2sbPR8JVDGzLrGYccByMzsrev4msNLMesZingT2MrPjY8vqEpJnZ2AUcL+Z3ZPXa2/durVlZmbmXUnOOVcEmRlvzFjCwP99wep1G7n8yIb0OaIhpdJ2bltJ0nQza524PKktNEmlgFbAmIRVY4B2OWzWFpiYlcwio4FaQL1YTOI+RwOtJaXnERM/7iTgSEmNovI2AY4itP6yXkMa8Dxwm5l9mUOZnXOu2JHEiQfVYlz/TnRrXpOh477hhPsm8dn3vySlPMnucqwKpBK6D+OWATVy2KZGDvFZ63KLSYuOmVtM/LiDgKeB2ZI2Al8AT5rZg7GYWwituIdyKO9WJF0sKVNS5vLly/OziXPOFWlV9ijFsDNb8njP1qxau5HuD07m32/NZu2GXTvZcbITWpbEfk9lsyyv+MTl2xsTX3YGcB5wNnBI9HsfSRdCGHgC9AIuyKWsWxfc7BEza21mratVq5bfzZxzrsj7S+O9GdM/gzMP3ZdHJ86n69AJTJm7YpcdP9kJbQWwmW1bY9XZtvWUZWkO8cS2ySlmE7Ayj5j4ce8G7jGzF8xsppk9DQzmz0EhRwI1gSWSNknaBNQFBkn6IYfyO+dcsVWxTDq3n9Kc5y86HAnOfnQaA16Zya+7YLLjpCY0M9sATAe6JKzqQhhkkZ2pQEdJZRLiFwMLYjGds9lnppltjMXkddxyhIQbt5k/6+1BoAVhlGTWYzEwBPhLDuV3zrlir+1+e/HOVRlcnNGAkR9/R5fB4xk3exmvfbqI9ne+R/3r3qL9ne/x2qeLCu2Y2V5PtYsNBp6W9BEwGbiUMMBjOICkO4BDzSwrQTwH3AyMkHQbcABwHXCL/TlkczhwhaShwMNAe0LX4Fmx4w4DJkgaALwKnEJocXWIxbwBXCdpPuH8WUvC5QFPAZjZj8BW01FH59qWmtmc7a8S55zb/ZUtlco/uzXmuOY1ufblGfR+KpNUic3RR/WiX9Yy4JWZAJzccp8dPl6yuxwxs5HA1cANwGeEhNLNzBZGITWB/WLxqwgtqVpAJvAA8B9CYsyKmQ90AzKifV4P9DWzl2MxU4AzgZ7ADML5sTPMbFqseFcCLxFaYl9Gx3k02p9zzrl8OKhOZf53RQcqlEn7I5llWbtxM3ePLpzv/0m/Dq0k8+vQnHMlSf3r3sp2tJ+A+Xcel+/9FMnr0JxzzpUctSqXLdDygvKE5pxzbpe4puuBlE1P3WpZ2fRUrul6YKHsvygMCnHOOVcCZA38uHv0HBb/spZalctyTdcDC2VACHhCc845twud3HKfQktgibzL0TnnXLHgCc0551yx4AnNOedcseAJzTnnXLHgCc0551yx4DOFJJGk5cDCPAOzV5VwtwKXP15fBeP1VTBeXwW3I3VW18y2uf+WJ7TdlKTM7KZ+cdnz+ioYr6+C8foquJ1RZ97l6JxzrljwhOacc65Y8IS2+3ok2QXYzXh9FYzXV8F4fRVcodeZn0NzzjlXLHgLzTnnXLHgCc0551yx4AnNOedcseAJrYiQdLmkGZJ+jR5TJR0XWy9JAyUtlrRW0geSmibso7Sk+yStkPS7pP9Jqr3rX82uJ+mfkkzS/bFlXmeRqB4s4bE0tt7rKoGkmpKelLRc0jpJsyV1iq33OotIWpDN+8skvRWt3yV15Qmt6PgBuBY4BGgNvAe8JqlFtP4fwN+AK4E2wI/AWEkVYvsYCvQAzgI6AhWBNyVtfYvYYkbS4cBFwIyEVV5nW5sD1Iw9msfWeV3FSKoMTAYEHAc0JtTNj7Ewr7M/tWHr99YhgAH/jdbvmroyM38U0QfwE3AJ4Z9qCXB9bF1ZYDVwSfS8ErABOCcWUwfYAnRN9mvZiXVUCZgLHAV8ANwfLfc627qeBgKzcljndbVtndwOTM5lvddZ7vV3PfALUG5X1pW30IogSamSzgTKA1OA+kANYExWjJmtBSYA7aJFrYD0hJjvgS9jMcXRI8BLZvZewnKvs201kLRI0nxJL0hqEC33utrWycA0SSMl/SjpM0lXSFK03ussB1EdXQg8Y2Zr2IV15QmtCJHUXNJvwHpgOHCKmc0kvBkAliVssiy2rgawmW0n+4zHFCuSLgIaAjdms9rrbGvTgF7AsYTu2RrAFEl74XWVnQZAH2Ae0BUYBtwJXB6t9zrLWRdCEnsser7L6iqtQMV0O9sc4GCgMqEv+UlJR8TWJ14Fr2yWJcpPzG5H0oGEbqGOZrYhl1CvM8DMRsWfS/qQ8GHdE/gwKyxhsxJZV5EUINPMBkTPP5W0PyGh3R+L8zrb1kXAx2b2WcLynV5X3kIrQsxsg5l9a2ZZ/0ifAf2ArNFoid9UqvPnt56lQCrhlgw5xRQnbQmvdZakTZI2AZ2APtHvK6M4r7NsmNlvwBfA/vj7KztLgNkJy74E9o1+9zrLhqTqwEnAo7HFu6yuPKEVbSlAaWA+4Q/eJWuFpDKEkUBTokXTgY0JMbUJo7OyYoqT1wij9A6OPTKBF6Lfv8brLEdRXTQifHD7+2tbk4EDE5YdwJ/3L/Q6y14vwimTF2LLdl1dJXs0jD/+GNFzZ/QHrkf4oL6DMMLn2Gj9tcCvQHegWfSGWQxUiO3jIWAR0BloCbxPaOWlJvv17aI6/IBolKPX2TZ1cw+hBVsfOAx4M6qbul5X2dZXm+gD9nrCedrTgFXA5f7+yrHORPgi+Wg263ZJXSW9Evzxxx9zBOHb33rCNRrjiA1Xjd4sAwnfqNcB44FmCfsoA9xH6G5bA7wB1En2a9uFdZiY0LzO/nydWR8gG6IPjZeBJl5XudbZccDnUX18DfQlmtDd6yzb+jqScL7r0GzW7ZK68tn2nXPOFQt+Ds0551yx4AnNOedcseAJzTnnXLHgCc0551yx4AnNOedcseAJzTnnXLHgCc25YiKHGywmPhbksv2IWNwHseX1omW9E+KrSvpU0k+S2kTLxsX28czOeq3OZccnJ3au+Gib8PxVwoXBA2PL1uexj6XAKYRZHXIkaW/gXWBv4Cj7cyLaKwn3tno1XyV2rhB5QnOumDCzD+PPJa0HViQuz8P6vOIl7UNIZpWATmb2xyS+ZvZl7NjO7VKe0Jxz+SZpX+A9wqTZnczs6yQXybk/eEJzzuVXA8Jdhg3IMLP5SS6Pc1vxhOacy68BhLsKN/Vk5ooiH+XonMuvdwizpg+TVDrZhXEukSc051x+vQxcABwNvCgpPcnlcW4rntCcc/lmZk8ClwInAM9JSk1ykZz7gyc051yBmNkjwFXAqcBTkvxzxBUJPijEOVdgZnZvdB7tLmC9pAvN7xbskswTmnNuu5jZ3VFSuxVYB/RJcpFcCecJzbliyszqbc92ktLC5rY52s8CwujG7I5xG3BbbNsU/FSGSxJ/4znn4uoCGwlTW22PMdH2dQutRM7lk7zb2zkHYVZ9oGr0dLWZzdmOfRwAVIyervQLsN2u5AnNOedcseBdjs4554oFT2jOOeeKBU9ozjnnigVPaM4554oFT2jOOeeKhf8HANG7L3WF8oIAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaYAAAEhCAYAAAA0xARjAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAABC5UlEQVR4nO3dd3gU5fbA8e9JCITeO9J7laLSsdCxUPTarl1QUWleRS7yExUVxQti770jCILSld4EpIkU6R0ivYWS8/vjnei6pG2yyWaT83meeUhm3pk9Owl7Mu+8c15RVYwxxpjMIiLUARhjjDG+LDEZY4zJVCwxGWOMyVQsMRljjMlULDEZY4zJVCwxGWOMyVQsMZmAicidIqI+yxkR2SQiz4lIdCaI7e5QxhDuRGSr38/Xd+mXwbH0E5HuCawfKiIZ/qxLQq/rnZehPt93FZEBGR1bVpIj1AGYsHYDsBPID3QDBnlfPxzCmO7E/V5/EMIYsoKpwNAE1m/N2DDoB8wDxvmtfw+YksGxJKYZ7v9BvK5AW2BkSKLJAiwxmbRYoap/eF9PF5FqwD0i0ldV40IZWDCJSC5VjQ11HBksRlUXhTqIxKjqTv6ZDEImM5+ncGVdeSaYlgO5gWLxK0Qkj4i8ICJbvC6/LSIyWEQifNpEi8goEVkjIsdFZK+ITBSRmv4vICKVRORTr02siGwWkdHetllAG6CFT9fTLJ99LxWRGd5rnBCRmSJyqd/xPxKRnSLSTEQWiMgp4MWk3rSIdBOR+d5xj4rIEhG51mf7QyKyUEQOishhEVkkIl38jpFDRJ7xukRPi0iMiMwTkZZ+7XqKyEqfNu+LSJGk4stI4vQXkfXez3uPiLwmIgX82qmIPOv9LuwUkVMiMkdELvZpsxWoANzq8/P8yNuWWJfaMBF5RES2eT/jH0SkhLd8IyJHRGSHiAz027e4iLwtIhtE5KTX5gsRKZuC9/xXV54X3x1AWZ+Yt4pIKe989E1g/6HeaxZO0UnOBuyKyQRTReAI8Ce4D1tcl1Bt4BlgNdAUGAIUAR7x9suF6wIcBuzxtvUGFolITVXd6x2vErAEOAk8CWwELgLae8fpDXwGRAL3eeuOevvWB2YDa3HdfQo8DswWkaaqutLnfRQEvgJeAv4LnErsDYvIw8ArwHjcB9JxoJF3LnzPy3u4brAcwDXAJBHprKqTvTYDgf7AYGAFUABo4p2L+Nca7p2zV4BHgbLeOasrIs1V9XxicaaCeD+/f1DVc8ns9yyuS/d1YCJ//+wbiEgbvyvp24HtwEO434GngZkiUk1VD+K6h38EVvJ3t+KBZF7/NmAN7nehJPAy8Anu92sy8A6uC3q4iKxW1R+9/YoAp73YDwBlcOd6vvc7eDqZ1433DFAcuASI/+MkVlX3ish43O/l6PjGIhIJ3AN8o6qHUvgaWZ+q2mJLQAt/f7DXwH3QFgbuBs4BD/m0u81r19pv/8HAGaBEIsePBPIAx4D+Pus/wX3wl0kitlnAvATWfwscBgr5rCsAHATG+az7yIv5uhSchwJejOOSa+uzT4R3zqYBE3zWT0rqOLjkdh74P7/1Lbx4uwbx57vVO2ZCS5Mk9ov/cP/Ib/2/vX2v9VmnQAyQ1+89ngWe8YvlswRea6j7+PrHOgU2ADl81o301j/hsy4HsB/4MIn3Eon7o0eBbil43aF+v0M7Ezjm5V7bVj7rrvXWNQ3Wzy8rLNaVZ9JiHe6D5CDwPvC2qr7ms70jsA1Y4HVV5fD+Cp8GROGungAQkX+JyGIROYxLcCeAfLjkF689MElVd6ci1tbevofjV6jqUeB7XPefr3O4RJGc5l6M7yTVSEQai8gkEdnnHfss0I5/vrdfgM5e91ZLEcnpd5h2uKT2ud+5XIy7KmydxOtH+O4jPt2oSZiM+6vff1mbxD5NcVc+n/mt/wr3vv3P84+qeiL+G1XdCizCDSZIren6z6u6dd6/U31e5xzwBy7x/EVEHvC6SY978W73Nvn+nFJNVWfhzt99PqvvA1ap3af6B0tMJi264T6sOgMzgN4icrvP9hK4ewRn/ZYl3vaiACJyDfA18DtwC3CZd9wDgO/w86Kk/oZ3EVw3ob+9uCs+X/s1Zd1iRb1/E41JRC4CZnqv/zAumV2CG1Hm+96ew3VPXgvMBf4UkQ9FJP5+XQnv3z+48HwW8IklIR/4tU/JiMWDqro0geVkEvvEdzv+4zx7ieBPn+3x9iVwjH24LsrU8u8OO5PE+r/Ov9cl+wbu97g7cCl//+EUzEcg3gSuF5GiIlIB98fbW0E8fpZg95hMWqxRb1SeiPwErAJGiMhY7y/hP4EtwL8S2X+r9+9NwB+qemf8BhGJ4sIPshhS/6F1ECiVwPpS3jZfKX0+Jsb7tyzuvkZCOuLuWf1L3UgywA0K+ccLqp4FXgBeEJFSwNW4bqg8wI149+1wV40J3Yv4M4F18YYCvleyMYm0S6v481gK+C1+pXdlV5QLYyyZwDFKArvSJbqk3QTMVNX4+57x9zSD7RPgeVx3eGHc/cvP0+F1wpolJhMUqhorIo8CE3A3nkfgrgp6AMdVdV0Su+fBdZ34ug3Xz+9rGtBdREqrakJXPwCxuBvd/mYDXUQkv6oeAxCR/LiBCLOSiC0pC3D3vHrh01XkJz4BnY1fISLVcfeGErzSUjfY4z0R6QzU9VZPB+KA8qo6PZAgvS6yrYHsk0qLcOf/JtxVYrwbcZ81s/3adxaRvPHdeSJSEXeVMtynTSxupGd6y4M3UMbHXak8VqIxq+pREfkc14WXD/jC61I2PiwxmaBR1e9F5BfgPyLyGu4vwbtwI63+hxtdlROoguuy6up1DU0BuorIKNy9ncZAH9xgBV9PAl1w96yew3VrlQU6quq/vTZrcV2KNwKbgGOquh43WupqL5YXcFdFA3EfSE+n8v0eE5FBwKsiMtZ7v8eAi4HTqvoqrmvoHPCJdw5KA0/h7l/4Dpmf4J2f5bgrooa4q623vdfa5MX9mojUwH3In8bdJ2kHvKeqP6fmfSSimIg0TWD9Xi/RXUBVD4rISGCQiJzAjairhRs5OA/4wW+XU8A0ERmBuzf1FC45jPJpsxZoJSJX47pdYxJ7/TSaAgwUkf/iupqvBK5P5bHWAkVE5AFgKe53YbXP9jf4+z6TdeMlJNSjL2wJv4W/R+VVTWBbe29bf+/7aFxX0jrcX5IHcTf6h+KNnsJ9QA8DduOGgs/GfTBv5cIRXlWAL3HdUbHAZmCUz/ZSuA/EY14cs3y2XYZLFMdxgytmApf6Hf8jEhhRlcz5uB43COEU7oN1MXC1z/Z/ee//NK6L6ybvdbb6tHkEd8Xxp3ec9d45ivJ7rdu8die89/E7rpuuXBB/vltJfFTea8nsK7hh7+tx93H24IaOF/Brp7ih5f/FXTmext1bu9ivXU1v/Ulvn4+89UNJeHTcsJT8ruI3ehN3hfMm7r7mMdwfSJW4cMRdYq/r2yav9zt6yNu2NYHztB74JdT/lzPrIt5JMsaYDOM9HPusqj4R6lgymteVuw7oqarvhzqezMi68owxJgOISDmgKq7Lcg/wRWgjyrxsuLgxxmSMe4GfcCMPb1HVRCuKZHfWlWeMMSZTsSsmY4wxmUrY3GMSV0H5KdzQ2Aq4UVmTcDWwEn24UETuBD5MYFNu9SnMKCK9cYUxS+NGTvVT1bnJxVWsWDGtWLFiyt+IMcYYli1bFqOqxRPaFjaJCVfttyzwGO45gbK45wG+5O/q0ok5iRtm/Be/pHQjruJvb9zzFr2BySJSW1W3k4SKFSuydOnSwN6JMcZkcyKyLbFtYZOYVHUNroZVvD+8SgOTRKSAJv30tKo3dUIiBuCej3jX+/5hEekIPIArg2+MMSaDhPs9pgK4hyyTKiwJkNubOGynV+W5YfwGr4pzY1y5G1/TcAU3jTHGZKCwTUwiUghXZuZdTXrysvW4uYKuA27GPWE+X9w04OBmW43kwkrH+0i46Cci0ktElorI0gMHkpu3zBhjTCBCnpjETYWsySyX++2TFzc75i7cPadEqepCVf1YVVd4gxnia6g97N/UP7QE1sUf8x1VbaKqTYoXT/DenTHGmFTKDPeYXubCicX8/TUAQUTy4WqhgatHltIpjwFQ1fMishSIv2KKwc0M6n91VIKE54sxxhiTjkKemFQ1hhTOD+NNUzAZdzXTUVWPB/p6IiJAfVwlZ1T1jIgsww1DH+PTtB0wNtDjp8T4X3cxYup6dh8+RZlCuXm0Qw26NkzL3GjGGJN1hDwxpZSXlKbhBjx0BfJ6XXrgZts847WbCSxR1UHe90/iqjFv9Pbtg0tMD/gcfiTwqYgsAeYD9+OGpwe9JP34X3cxaNxqTp11E6TuOnyKQeNcRXxLTsYYE0aJCTdyLn5+mA1+267g78neqgA7fLYVAt7BddUdAX4FWqtq/PTeqOrXIlIUeAL3gO0aoLOqJjrOPrVGTF3/V1KKd+rseUZMXW+JyRhjCKPEpKqzcF14ybWr6Pd9f9z8MMnt9wbugd10tftwwnUbE1tvjDHZTchH5WU3ZQolPEt0npyRnIhNatS7McZkDwEnJhFpKCLjRCRGRM6JSCNv/XNetQSThEc71CB3VOQ/1kVGCCfPnKf9qDnM2WDPRRljsreAEpOItAQW4qY7/sJv/zjcoAGThK4Ny/J893qULZQbAcoWys3/bmjAN/c3I1dUBLd/sIT/jFnJ4ZNnQh2qMcaEREDzMYnIPOBP3Ki4SOAM0ERVl4tId+BlVS2fHoFmVk2aNNFgFXE9ffY8r8zcyNtzNlM4T06eua4OneqVDsqxjTEmMxGRZaraJKFtgXblNQLeVJfN/DNaDGBlENIgOiqSxzrWZMKDLSiRPxcPfL6cBz5bxv5jAT1DbIwxYS3QxHQayJPIttK44dgmjeqWLciEh1rwWMcazFy3n3Yj5zBm6Q5stmFjTHYQaGKaB/QTEd+79/Gflvfg5rM3QRAVGUHvy6syuW8rqpfMx6PfruL2D5aw42ByhdSNMSa8BZqYhuC681Z6Xytwh4j8jHv49anghmeqFM/H172a8fR1dVi+7RAdXp7DR/O3EBdnV0/GmKwpoMSkqiuB1rjipoNxD7w+5G1uo6rrgxueAYiIEG5vVpGp/VvTpGIRhk5cyw1vL+SP/cdCHZoxxgRdQKPy/rGjSDRQBDisqtm2fymYo/JSQlUZt3wXT09ay6kz5+nbthq9WlcmKtKelTbGhI9gjsr7i6qeVtXd2TkphYKI0KNxOWYMaEPb2iUYMXU91702nzW7bNyJMSZrCPQ5puQGN6iqXpW2kMJLRl8x+ZuyZi9DJqzh4Ikz9Gpdmb5XVSPar7KEMcZkNsG8YorA3VfyXYoBLYDqpKDIqgmujnVLMaN/G3o0KsubszbRefRclmw5GOqwjDEm1VJ9j+kfBxGpAowH+qvqjDQfMIyE+orJ17yNMTw+bhU7D53itqYVGNipJvlyhU0BeWNMNpIu95h8qeomYDgwIhjHM6nTsloxpvZrzV0tKvLZ4m20Hzmbn9fvD3VYxhgTkGAO5TqA684zIZQ3Vw6evKYO397fnDy5cnDXh78w4OsVHDphRWGNMeEhKIlJRIoAA4BNwTieSbvGFQrzQ5+WPHxlVb5fuZt2o2bzw6o9VtbIGJPpBXQDQkS2cGHx1pxASe/rHsEIygRHrhyRPNK+Bp3qlmbg2FU8+MVy2tcuybCudSlRIDrU4RljTIICHS7+ERcmptPANmCMd68pW8lMgx+Scu58HO/P28LI6RvImSOCIV1qc0OTcojYQEpjTMZLavBDUEblZWfhkpjibT5wnMfHrWbJloO0qFqU57vVp3zRxArGG2NM+kj3UXkmfFQuno+vejZlWNe6rNxxhA4vz+H9eVs4b0VhjTGZhCWmbCgiQvh30wpM69+ayyoX4ZlJa7n+rQVs3GdFYY0xoZdsYhKROBE5n8LlXEYEbYKjTKHcfHjnJbx848VsjTlBl1fm8crMjZw5Fxfq0Iwx2VhKRuU9zYUDHkwWISJ0bViWltWK8dTEtYycvoEfV+/hxevrU79coVCHZ4zJhsJm8IP3rNRTQDugAhADTAKeUNU/k9hvFtAmgU1rVbWO12Yo8KTf9n2qWiq5uMJt8ENypq/dxxPjV3PgWCw9W1WmX9vq5M5pRWGNMcGV1OCHcCqkVgYoCzwGrPW+fgP4EmifxH7dcc9axcsFrAa+8Wu3Hrjc5/vzaQs3PLWrXZJLKxVh+OTfeXvOZqb+tpfhPerTtHLRUIdmjMkmUnXFJCINgBrABU9pquonQYgrpXF0xl01FVLVoync51bgE6Ciqu7w1g0FrlfVuoHGkNWumHwt+COGx8etZvvBk9x6WXke71ST/NFRoQ7LGJMFBO2KSUQKAT8ATeNXef/6ZrcMS0xAASAWCGSywp7A5Pik5KOyiOwCzgCLgf+q6uaEDiAivYBeAOXLlw846HDRvGoxpvRrxchpG/hg/hZ+WrefZ7vV5cqaJZPf2RhjUinQ4eLPAUWB1rik1A24Evgc2AxcGtTokuAlyWeAd1U1RaMBRaQ67n7Tu36bFgN3Ap1wiasUsEBEEuy/UtV3VLWJqjYpXrx46t5AmMiTMwdPXF2bsQ80J390Du7+aCn9vvqVg1YU1hiTTgJNTB1wyWmR9/1OVZ2lqrcDM4C+gQYgIsNERJNZLvfbJy8wEdiFu+eUUj2BPbirvr+o6mRV/UZVV3nzSV2NOzd3BPp+sqqG5Qsz6eFW9L2qGj+s3kPbkbP5fuVuKwprjAm6QBNTaWCzqp7H1cjL77NtHNAlFTG8DNRKZlkS31hE8gGTvW+vVtXTKXkREcmJSzQfJneFparHgd+AaoG8kawuZ44I+rerzsSHW3JR4dz0+fJXen6yjL1HUvQjMMaYFAk0Me0FCnlfbwOa+WyrmpoAVDVGVdcls5wEEJH8wBQgEujsJZCU6oqbBv795BqKSDRQE3d1ZfzULFWAcb1bMLhzLeb9cYB2I2fz5ZLtdvVkjAmKQBPTPP5ORp8CT4rI2yLyOm722qnBDM6Xl5SmAYVx94Pyikgpb8np026miDyfwCF6ATMTGtAgIi+JSBsRqSQilwHfAnmBj9PjvWQFkRFCz9aVmdK3NXXKFmDQuNXc8u5itv15ItShGWPCXKCJ6SncFQu4RPQ6rvvuZuB74OHghXaBxrjRgLWBDbirmfiluU+7Krgux7+ISGXcIA3/QQ/xyuGeh1qP65KMBZqq6rYgxp8lVSyWly/ubcrz3euxZpcrCvve3M1WFNYYk2phU/khs8rKzzEFau+R0zwxfjUzft9Pg4sK8WKP+tQolT/5HY0x2U7Qpr0QkeUi0k9E7EEWc4FSBaN59/YmvHJzQ3YcPMnVr85l1PQNVhTWGBOQQLvy9gEvAjtE5EcRuckbKGAM4IrCXtugDDMGtKFzvdKMnrmRq1+dy4odh0MdmjEmTASUmFS1E+5+zGNACeALYJ+IvC8iV6RDfCZMFcmbk9E3NeT9O5pw9NQ5ur8xn2GT1nLqTLYsQWiMCUCa7jGJSC3gNuAW4CLcA7cVghRbWLB7TMk7evoswyev44vF2ylfJA/De9SjeZVioQ7LGBNC6Ta1uqr+jpuvaTCwG3c1Zcw/FIiO4rlu9fiyZ1MiBG55dzGDxq3i6OmzoQ7NGJMJpToxiciVIvIh7r7TJ8BO0ne4uAlzzaoUZXLf1tzXujJf/7KDdiNnM2PtvlCHZYzJZAIdlVdXRIaLyHZgOq4g6migpqo2U9U30iNIk3XkzhnJoM61GP9gCwrnycm9nyzl4S9/JeZ4bKhDM8ZkEgHdYxKROOAIMAb4VFXnpldg4cLuMaXemXNxvDV7E6/+tJF8uXLw5DV1uO7iMohI8jsbY8JaMO8x3QiUUtVelpRMWuXMEUGfq6rxQ59WVCial35fr+Cej5ey+/CpUIdmjAmhQIeLj1FV63MxQVW9ZH7GPtCcIVfXZuGmP2k/ag6fLdpGnJU1MiZbCnjwg4jcISJTRGStiGz2WzalR5Am64uMEO5pWYmp/VrT4KKCPDF+DTe/u4gtMVYU1pjsJtDBD0OAD4EywApgtt8yJ8jxmWymfNE8fHbPZbzYoz5r9xyl48tzeHv2Js6dt7JGxmQXgQ5+2Ap8p6r90y2iMGODH9LPvqOneWL8Gqav3Ue9sgV5oUd9apcpEOqwjDFBEMzBD0VxU5obk+5KFojmndsa8/otjdhz5BTXvjaP/01bT+w5K2tkTFYWaGKaDTRIj0CMSYiI0KV+aab3b8O1Dcrw6k9/0OWVeSzbdijUoRlj0kmgiakfcJeI3C4ixUQkwn9JhxiNoXDenIy88WI+vOsSTsae4/q3FvDUxN84eeZcqEMzxgRZah6wBUhsJ1XVHGmOKozYPaaMdzz2HC9OWccnC7dRrnBuhnevT8tqVhTWmHCS1D2mQJPI0ySelIzJEPly5eDp6+pydf0yDBy7in+/v5h/NSnH4C61KZg7KtThGWPSyKZWTyO7Ygqt02fPM3rmRt6Zs5mieXPyTNe6dKhTKtRhGWOSkW7TXhgTatFRkQzsWJPxvVtQNF8u7vt0GQ9+vpwDx6xAiTHhKjWVHxqKyDgRiRGRcyLSyFv/nIh0DH6IxiSvXrmCfP9QCx7tUIPpa/fRduRsxi7bifUIGBN+Aq380BJYCNTETavuu38ccH/wQjMmMFGRETx4RVV+7NuSqiXy8ciYldz54S/ssqKwxoSVQK+YhgNTgTrAAL9ty4FGwQjKmLSoWiI/Y+5rxtBravPL1oO0HzmbTxZutaKwxoSJQBNTI+BNdf0j/v/LY4DiQYnKmDSKiBDubOGKwjaqUJj/m/AbN76zkE0Hjoc6NGNMMgJNTKeBPIlsK42bRDDdiMi7IrJJRE6JyAERmSAitVKwXw+vGnqs92+3BNr0FpEtInJaRJaJSKv0eRcmI11UJA+f3H0pI66vz/q9x+g0ei5vzPqDs1YU1phMK9DENA/oJyKRPuvir5zuAX4KSlSJWwrcCdQCOgACzBCRRB9eEZFmwNfA58DF3r9jROQynzY34qaIfw5oCCwAJotI+XR5FyZDiQg3NLmIGY+04coaJXhxynq6vj6fNbvS9e8oY0wqBVr5oQEwH9gKfAsMAV7F1c9rDFyiquuDH2ai8dQHVgI1E3tdEfkaKKKq7XzWzQAOqOrN3veLgVWq2tOnzUbgW1UdlFQM9hxT+Jm8eg9DJvzGoZNnuL9NZR6+shrRUZHJ72iMCZqgPcekqiuB1sA+YDDuiuUhb3ObDE5KeYG7gO24RJmYZsA0v3VTgebecXLikqp/m2nxbRJ47V4islRElh44cCDw4E1IdapXmhkDWtOtYVle/3kTnV+Zy9KtB0MdljHGE/BzTKq6XFWvAvID5YACqnqFqv4a9OgS4N0LOg4cBzoBVyUz3XspXCL1tc9bD1AMiEymzT+o6juq2kRVmxQvbuM9wlGhPDl56YYGfHL3pcSejeOGtxcy9PvfOBFrRWGNCbVUV35Q1dOqultVT6YlABEZJiKazHK5zy6f4+4DtQE24O4XJTYg469w/V82gXUpaWOymNbVizOtf2vuaFaRjxdupf2oOczeYFfBxoRSQEVcRSSpwQ1xuFF5y4D3VdX/CiQxLwOfJdNme/wXqnrEe52NIrIIOAT0AD5NZN+9XHjlU4K/r5BigPPJtDFZWN5cORh6bR2url+ax8au4o4PltCjUTmGXF2LQnlyhjo8Y7KdQK+YBKgBXA5UAKK9fy/HjZSrhBsQsUZEaqfkgKoao6rrklkSuyoTb8mVxEssBNr5rWuHG3mHqp7BJdNE25jsoUnFIvzYpxUPXlGF8St20XbkHCav3hPqsIzJdgJNTCNxzzI1VtUqqtpcVasAl3jrnwKqAQeAZ4MZqIhUFZGBItJYRMqLSHNgDBALTPJpN1NEnvfZdTRwpYgMEpGaIjIIuAJ3peb7vu4UkXtFpJaIjAbKAG8F8z2YzC86KpJHO9Tk+4daULJALh74fDn3f7qM/UdPhzo0Y7KNQBPTMGCo/0AHVV2GS0rDVHUnMAI3ei+YYnFXZpOBP3DPJh0DmqnqXp92VXAP+8bHtgC4CbgDWAXcDtyoqot92nyNm533CWAF0BLorKrbgvweTJioU6YgEx5swcCONflp/X7ajpzNmKU7rCisMRkg0OeYTgHdVXVyAts6AeNUNbeItAamqWp08ELNnOw5pqxv04HjPD52Fb9sPUSrasV4rls9LiqS3HgbY0xSgjkf01bg3kS29eLv54mKAX8GeGxjMqUqxfPxda9mPHNdHZZvO0SHl+fw0fwtnLeisMaki9RMrf6ZiKwCxgL7caPXegB1gVu8dm2BxQkewZgwFBEh3NasIlfULMHg79YwdOJaJq7awws96lG1RP5Qh2dMlhLw1Ooi0g53P6kxEAWcxdWwe1JVZ3htooHzqno2uOFmPtaVl/2oKt/9uounJ63lZOx5+lxVlfvaVCEq0iaENialkurKCzgx+Rw0AtdlF6Oq2bZUsyWm7OvAsViGTvyNH1btoVbpAoy4vj51yxYMdVjGhIVg3mP6i6rGqer+7JyUTPZWPH8uXr+lEW/f1piY47Fc9/p8hk9ex+mz50MdmjFhzfoejEmjDnVKMaN/G65vVI63Zm+i8+i5LNliRWGNSa1kE5OInBeRS72v47zvE1usAqbJlgrmieKF6+vz2T2XceZ8HP96eyFDxq/h2Oksf5vVmKBLyai8p4GdPl/bGFljEtGyWjGm9W/NS1M38OGCLcz8fR/Pdq/HFTVKhDo0Y8JGqgc/GMcGP5jELNt2iMfHrmLj/uN0b1iWIVfXpnBeKwprDAR58IOINBSRcSISIyLnRKSRt/45EemY1mCNySoaVyjMpD4t6XNlVb5fuZu2I2czadVuK2tkTDICSkwi0hJXrbsm8IXf/nHA/cELzZjwlytHJAPa12Diwy0pUyg3D33xK/d9uox9VhTWmEQFesU0HDcteR1ggN+25UCjYARlTFZTq3QBvuvdnEGdajJ7wwHajpzN179st6snYxIQaGJqBLyp7n+T//+oGMDmGTcmETkiI7ivTRWm9GtNrdIFGDh2Nbe+t5jtf6ZpEmhjspxAE9NpILGyyqVxM8saY5JQqVhevurZlGe71WXVziN0eHkO78+zorDGxAs0Mc0D+olIpM+6+P9N9wBJTb1ujPFERAi3XlaB6QNa06xKUZ6ZtJYeby5gw75joQ7NmJALNDENwXXnrfS+VuAOEfkZaIor7mqMSaHSBXPz/h1NGH3TxWz78wRdXpnLKzM3cuacVfoy2VdAiUlVV+Jmpt0HDAYEeMjb3EZV1wc3PGOyPhHhuovLMmNAGzrWLc3I6Ru49rV5rNxxONShGRMSaakuHg0UAQ6rara9e2sP2Jpgm752H0+MX82BY7Hc26oy/dtWJ3fOyOR3NCaMpFd18dOqujs7JyVj0kO72iWZPqANN15yEe/M2Uyn0XNYuMkmhDbZh1UXNyYTKhAdxfPd6/PFvZcRp3Dzu4v473erOWpFYU02YInJmEysedViTO3Xmp6tKvHVku20HzmHn9btC3VYxqQrS0zGZHK5c0YyuEttxvVuQcHcUdz90VL6fvUrfx6PDXVoxqQLS0zGhImLLyrExIdb0q9tNX5cvYd2o+bw/UorCmuyHktMxoSRnDki6Ne2OpMebsVFRfLQ58tf6fnJUvYcORXq0IwJmrBKTCLyrohsEpFTInJARCaISK1k9ukpInNF5KCIHBaRn70q6b5thoqI+i170/fdGJN6NUrlZ9wDzXmiSy3m/RFD+5Fz+GLxduKsrJHJAlIytXpy06ln5NTqS4E7gVpAB9wDvjNEJCqJfS4HvgauAi4D1gNTRaSaX7v1uHp/8Uu9YAZuTLBFRgj3tqrM1H6tqVu2IP/9bjW3vLeIrTEnQh2aMWmS7AO2IjKUAKZTV9UMK0skIvVx5ZFqprTqhIgIsAd4VlVf9dYNBa5X1bqBxmAP2JrMQFX5+pcdPPvD75yNi+ORdjW4u2UlIiMk1KEZk6CkHrDNkdzOqjo06BEFgYjkBe4CtgNbA9g1JxANHPJbX1lEdgFngMXAf1V1cyKv3QvoBVC+fPnAAjcmHYgIN11anstrlOCJ8at59sffmbRqNy9e34AapfKHOjxjAhJW95gARKS3iBwHjgOdgKtUNZBxs8O8fb/3WbcY10XYCegJlAIWiEjRhA6gqu+oahNVbVK8uE1BZTKPUgWjeff2Jrx6c0N2HjrF1a/OZdT0DcSeOx/q0IxJsVTVyhORBkAN3JXHP6jqJwEeaxiuIGxSrlDVWV77gkAJ3H2g/wAXAS1SUhpJRPoCzwBtVXVJEu3yAZuB4ao6MqljWleeyawOnjjD0xN/Y/yK3VQvmY8XetSnYfnCoQ7LGCDprryAEpOIFAJ+wE1xAW7wAfjcg1LVgKpNikgxoFgyzbYnlHhEJCeuS+5+Vf00mdfpi7ta6qSq81IQ18/AOlV9IKl2lphMZvfTun0M/m4Ne4+e5u4WlXikfXXy5Ey2F9+YdJWme0x+ngOK4qa+mAt0w81aezfQDLgp0OBUNQY3LXtqiLfkSrKRyADgaaBzCpNSNFAT+DmVcRmTaVxZsyTT+hfhhSnreH/eFqav3cfw7vVoXjW5vweNCY1A7zF1wCWnRd73O1V1lqreDswA+gYzOF8iUlVEBopIYxEpLyLNgTFALDDJp91MEXne5/tHgeG45LlBREp5S0GfNi+JSBsRqSQilwHfAnmBj9Pr/RiTkfJHRzGsaz2+6tWUCIFb3lvM42NXceSUFYU1mU+giak0sFlVzwOnAd/hPuOALsEKLAGxuGeSJgN/4J5NOgY0U1Xfh2GreHHGexCI8trv8VlG+7QpB3yJe5ZpnPdaTVV1W3q8EWNCpWnlokzp15r72lTmm6U7aD9qNtPXWlFYk7kE2pW3Fyjkfb0N1303y/u+anBCSpiq7sCNmkuuXcWkvk9kn4C7II0JV9FRkQzqVIsu9Urz2Ler6PnJUq6uX5qh19ahWL4ke8WNyRCBXjHNwyUjgE+BJ0XkbRF5HRgBTA1mcMaY9FO/XCG+f6glj7SrzrTf9tF25Gy++3WnFYU1IRfoqLwqQBlVneuVARoO3AjkAaYAD6tqtppq00blmaxg475jPDZ2Fb9uP8wVNYrzbLd6lCmUO9RhmSwsaMPFzYUsMZms4nyc8vGCrYyYup7ICGFgp5rceml5IqyskUkHQU9MInIR7sHWhB6w/SngA4YxS0wmq9lx8CSDxq1m3h8xXFqpCC/0qE+lYnlDHZbJYoL5gG1l4HPg0vhV3r/qfa2BPmAb7iwxmaxIVRmzdCfP/LCWM+fi6N+uOve2rESOyLCrYmYyqWA+YPseUB7oB6zDFTw1xmQxIsK/LrmINjWKM2T8GoZPXscPq/bwQo/61C5TINThmSwu0CumY8Cdqjo2/UIKL3bFZLI6VWXymr3834Q1HD55lgcur8JDV1YlV45s1TligiypK6ZAr8t3YldJxmQrIkLneqWZ3r8N115chld/+oMur8xj2Tb/mWOMCY5AE9NzwEBvLiRjTDZSOG9ORv7rYj666xJOnTnP9W8t4KmJv3EiNr0nrjbZTUD3mFT1UxGpCWwVkUVcONmequodQYvOGJPpXF6jBFP7t+bFKev4cP5Wpq/dx/Pd69Gqms1NZoIj0HtMdwIfAOeB/VzYraeqWjlo0YUBu8dksrMlWw7y+NhVbI45wb+alGNw59oUzBMV6rBMGAjmcPFtwFLgHlU9HJzwwpslJpPdnT57ntEzN/LOnM0UyZuTZ66rS8e6pUIdlsnkgjn4oSjwhiUlY0y86KhIBnasyYQHW1A8Xy7u/2wZvT9fxv5jp0MdmglTqSniWis9AjHGhLe6ZQsy4aEWPNqhBjN+30+7kXMYu8yKwprABZqY+gI9ReRWESkqIhH+S3oEaYwJD1GRETx4RVV+7NOKqiXy8ciYldzx4S/sPHQy1KGZMBLoPaY478vEdlJVDbSaRFize0zGJCwuTvl00TZemLIOAQZ2qsm/L6tgRWENENySRE+TeFIyxpi/REQIdzSvyJU1S/Df71bzfxN+Y+LK3QzvUZ8qxfOFOjyTidm0F2lkV0zGJE9VGbt8F89MWsups+fpe1U1erWuTJQVhc22gjkqzxhjAiYiXN+4HNMHtKZtrRKMmLqerq/PZ82uI6EOzWRClpiMMRmmRP5o3ri1MW/9uxH7jsZy3evzeXHKOk6fPR/q0EwmkmxiEpHzInKp93Wc931iixXNMsYkq2Pd0swc0IbuDcvyxqxNdH5lLku3Hgx1WCaTSMngh6dxVcXjv7abUsaYNCuYJ4oRNzTgmgZlGDRuNTe8vZDbm1bg0Y41yZcrWw3uNX5s8EMa2eAHY9LuROw5Rkxdz8cLt1KmYG6e616PNtWtKGxWlmUGP4jIuyKySUROicgBEZkgIklWohCRO0VEE1ii/dr1FpEtInJaRJaJSKv0fTfGmHh5c+Vg6LV1+Pb+ZkRHRXDHB0sY8M0KDp+06d+yo4ATk4jcISJTRGStiGz2WzalR5A+lgJ34soidQAEmCEiyZUzPgmU9l1U9a9CXiJyIzAaN99UQ2ABMFlEygf7DRhjEte4QhF+6NOKh66oyvcrdtN25Gx+XL0n1GGZDBZo5YchwFPAGm+J9W+jqncFLbrk46kPrARqqur6RNrcCbymqok+0Scii4FVqtrTZ91G4FtVHZRUDNaVZ0z6+G33EQaOXcWaXUfpWKcUT19XhxIFopPf0YSFYFZ+uAcYrar90x5W2niz6N4FbAe2JtM8tzdlRySwAhiiqr96x8kJNAZe8ttnGtA8iCEbYwJQp0xBxvduwbtztzBqxgYWjIzhiatrc0PjcohYWaOsLDXTXkxMj0BSyrsXdBw4DnQCrlLVC67cfKwH7gauA24GTgPzRaSat70YLmHt89tvH5DgpDIi0ktElorI0gMHDqT+zRhjkpQjMoIHLq/ClL6tqFmqAI99u4rbP1jCjoNWFDYrCzQxzQYaBDMAERmWyOAE3+Vyn10+x90HagNsAMaISJ7Ejq+qC1X1Y1VdoapzgRuBTcDD/k39Q0tgXfwx31HVJqrapHhxGzlkTHqrXDwfX/VqyjPX1WH5tkN0eHkOH87fwvk4G1WcFQXaldcPGCcifwI/Ahc8Eaeqcf7rkvEy8Fkybbb7HP8IcATYKCKLgENAD+DTlLyYqp4XkaVA/BVTDG6qeP+roxJceBVljAmRiAjhtmYVubJWSQZ/t5qnJq5l4srdvHh9faqWyB/q8EwQBXrFtAGoC3yI+9A+67cEPLZTVWNUdV0yS2LX7eItuVL6euI6p+sDe7zXPwMsA9r5NW2HG51njMlEyhbKzYd3XsKoGxuwOeYEnUfP47WfNnL2fKB/E5vMKmymvRCRqrgroxnAAaAc8DhuZOAkn3YzgSXxo+lE5ElgEbARKAD0wSWmB3wOPxL4VESWAPOB+4EywFvp+66MMakhInRrWI5W1Yrz5Pe/8dK0DUxatYcR1zegXrmCoQ7PpFFAiUlVh6ZTHCkRC1wOPAIUwl2xzQGaqepen3ZVgB0+3xcC3sF11R0BfgVaq+qS+Aaq+rWIFAWewD3ntAborKrb0um9GGOCoFi+XLx+SyOubbCXIePX0PWN+fRsVZl+basRHRUZ6vBMKllJojSy55iMyRyOnDrLcz/8ztdLd1CpWF6Gd6/HZZWLhjosk4g0lSSy6uLGmHBQMHcUL1xfn8/vvYxzcXHc+M4inhi/mmOnz4Y6NBMgqy5ujMlSWlQtxtR+rfnftA18MH8LP/2+n2e71eOKmiVCHZpJIevKSyPryjMm81q+/RADv13Fxv3H6dawLEOurk2RvDlDHZYhC1UXN8aYQDQqX5hJfVrS56pqTFy5m3YjZzNp1W7sD/LMLdkrJhG5MpADqupPaYoozNgVkzHh4fc9Rxk4dhWrdh6hXe2SDOtal5JWFDZkkrpiSkliiuPv+0qJVU5Ub5uqarYao2mJyZjwce58HB/M38L/pm0gZ44IBneuxY2XXGRFYUMgGNXFjwFjveVEsAIzxpiMlCMygl6tq9C+dikGjl3F4+NW8/3K3QzvXp/yRRMtuWkyWEqumNoAt+OqLkQA3wEfZ7cuu8TYFZMx4SkuTvnqlx089+PvnIuL4z/ta3BXi0pERtjVU0ZI0+AHVZ2tqvfgKifcjytuOlVEtovI88lNbW6MMZlRRIRwy2XlmT6gNc2rFGPYD7/T480FbNh3LNShZXspHpWnqqdV9QtV7QSUx01F3hlYIyKvpVeAxhiTnkoXzM37dzRh9E0Xs/3gSbq8MpfRMzZy5pwVhQ2V1A4X/xM3a+xW3MCHwkGKxxhjMpyIcN3FZZnevzWd6pZm1IwNXPvaPFbuOBzq0LKlgBKTiLQQkbdwU0Z8jJtFtgtwWzrEZowxGapovly8cnND3ru9CYdPnqXbG/N57sffOXXmfKhDy1aSHZXnTTdxG/BvoCKuovd/gDGqejxdozPGmBBoW7skl1YuwvDJ63hnzmam/raX4d3r06yKFYXNCCl9jukoMA43S2ySU0Go6uagRRcGbFSeMVnbgk0xDBq3mm1/nuTmS8szqHNNCkRHhTqssBeMB2zjJVvHwx6wNcZkNafOnGfUjA28N3czJfJH82y3ulxVq2SowwpraX3A9q4gx2OMMWEld85I/tu5Fp3rlWbgt6u45+OlXNugDE9eU5ui+XKFOrwsx6qLp5FdMRmTvZw5F8ebszbx2s8byR8dxZPX1ObaBmWsrFGArLq4McYESc4cEfRtW40f+rSifJE89P1qBfd+vJQ9R06FOrQswxKTMcakQvWS+Rn7QHOe6FKL+ZtiaDdyDp8v3kZcnPVCpZUlJmOMSaXICOHeVpWZ1q8N9csVZPB3a7jlvUVsjbFa12lhickYY9KofNE8fH7vZQzvXo/fdh2lw8tzeGfOJs6dt7JGqWGJyRhjgkBEuOnS8kwf0IZW1Yrz3I/r6PHmAtbtPRrq0MKOJSZjjAmiUgWjeff2xrx2S0N2HjrF1a/MY+T0DcSes7JGKZXmxCQijUSkq7c0CkZQxhgTzkSEq+uXYcaANlzToAyvzNzINa/O49fth0IdWlhIdWISkcYisg74HHgA6A18KSLrRaRxsAL0e813RWSTiJwSkQMiMiG5+aBEZJaIaALLbz5thiawfW96vAdjTPZROG9ORt14MR/eeQnHTp+j+5sLeGbSWk6eORfq0DK1tFwxvQM8pKq1VLWDqrZX1RrAQ8C7wQnvAkuBO4FaQAdAgBkiklThqu5AaZ+lIm6q+G/82q33a1cviHEbY7KxK2qWYFr/1tx6WXnen7eFDi/PYf4fMaEOK9NKS2LKp6oz/Feq6nQgbxqOmyhVfVtV56rqVlVdDjwBlAEqJ7HPQVXdG78ALb34PvBres63naoeSI/3YIzJnvJHRzGsaz2+7tWUHBER3PreYh4fu4ojp86GOrRMJy2Jab+I3CUifxVtFZFIEbkXSPc/BUQkL66O33bchIUp1ROYrKo7/NZXFpFdIrJFRL4SkUSTnTHGpNZllYsyuW8r7mtTmW+W7qDdyNlM+83uHPhKS2K6A7gZOCgiv4vI78BB4EZvW7oQkd4ichw3SWEn4CpVjU3hvtWBNlzY1bgY10XYCZe4SgELRCTByVdEpJeILBWRpQcO2IWVMSYw0VGRDOpUi/EPtqBI3pz0+nQZD32xnJjjKfooy/LSXMRVRIoB5b1vt6tqQFdLIjIMGJxMsytUdZbXviBQAncf6D/ARUALVT2ZgtcaAdwKlFfVRO8+ikg+YDMwXFVHJnVMK+JqjEmLs+fjeHv2Jl6Z+Qd5ckXy5DW16Xpx2SxfFDZN8zGl8gVLqOr+FLYtBhRLptn2hBKPiOQEDgH3q+qnybxOTmAn8K6qJpcIEZGfgXWq+kBS7SwxGWOC4Y/9x3js21Us336Yy2sU59lu9ShbKHeow0o3oagunuJPalWNUdV1ySyJXQ2Jt6RkQpSuuAT4fnINRSQaqAnsSeHbMMaYNKlaIj9j7m/Ok9fUZvHmg7QfOZtPF2XPorApmSgwQSJybRKbo1N73CReryrQA5gBHADKAY8DscAkn3YzgSWqOsjvEL2AmQlN/S4iLwETcQMpSgBDcCP3Pg72+zDGmMRERgh3tahE21olGTRuNUPGr2Hiit0M71GPysXzhTq8DJPqxAR8B8zGXbH4y5+G4yYmFrgceAQoBOwD5gDNvGHg8aoA/xhx542wuxK4KZFjlwO+xF1RHQAWAU1VdVvwwjfGmJS5qEgePr3nUsYs28mwSWvpNHou/dtV596WlcgRmfUryaX6HpNX9aGTqm5JYNsOVb0orcGFA7vHZIxJT/uPnmbIhDVM/W0fdcsW4MUeDahdpkCow0qz9LrH9DGJD1p4Kw3HNcYY4ylRIJq3b2vCm7c2Yu+RWK59bR4vTV3P6bNZtyhsuozKy07siskYk1EOnzzDM5N+Z+zynVQpnpcXr69P4wpFQh1WqoRiVJ4xxpggK5QnJ//7VwM+vvtSTp+N4/q3FjL0+984EZu1isIGdMUkIj8lsTkOOAIsA95X1X1pjC0s2BWTMSYUjseeY8SUdXy8cBvlCufm+e71aFWteKjDSrFgXjEJUAM3Oq4Cblh4Be/7WkAl3FDrNSJSO5XxGmOMSUa+XDl46rq6jLm/GTlzRHDb+0t4dMxKjpwM/6KwgSamkcBpoLGqVlHV5qpaBbjEW/8UUA035PrZoEZqjDHmApdULMKPfVrR+/IqjPt1F21HzWbKmvCuDRBoYhoGDFXVX31XquoyXFIapqo7gRFA6+CEaIwxJinRUZE81rEmEx5sQfF8ubj/s+U88Nky9h87HerQUiXQxFSdxKe0OABU9b7eRDrNyWSMMSZhdcsWZMJDLXi0Qw1mrttPu5Fz+HbZTsJt9HWgiWkrcG8i23rx97xIxYA/UxeSMcaY1IqKjODBK6ryY59WVCuRj/+MWckdH/7CzkPJTsCQaQSamJ4GuorIKhF5UkQe8P5dBVyH684DaIub48gYY0wIVC2Rj2/ua8ZT19Zh6daDtB81h48XbA2LorABP2ArIu1wCagxEAWcxVUTfzJ+qnWvOvd5VQ3/4SHJsOHixpjMbuehk/z3uzXM2XCAJhUKM7xHfaqWCG1R2HSZj0lEInBddjGqGpeG+MKaJSZjTDhQVcYt38XTk9Zy6sx5+ratRq/WlYkKUVHYdKn8oKpxqro/OyclY4wJFyJCj8blmDGgDW1rl2DE1PVc99p81uw6EurQLhBwYhKR0iLykoj8IiKbRGSJiLwoIqXSI0BjjDHBUzx/Lt64tTFv/bsRB47Hct3r83lhyrpMVRQ2oMQkItWBFUAf4DiwBDgB9AVWiEi1YAdojDEm+DrWLc2M/m3o3rAsb87aROfRc/ll68FQhwUEfsX0AnAUqK6qV6jqzap6Be75piPedmOMMWGgYJ4oRtzQgE/vuZQz5+O44a2F/N+ENRwPcVHYQBPTFcAQVd3qu9Kb6XWot90YY0wYaVWtOFP7teauFhX5dNE2Ooyaw6z1+0MWT6CJKSdwLJFtx7ztxhhjwkzeXDl48po6fHt/c3LnjOTOD39hwDcrOHTiTIbHEmhiWgE87A0V/4uICNDb226MMSZMNa5QmB/6tOThK6vy/YrdtBs1mx9X78nQskaBzsfUEZiEq4X3NbAHKAXcgKsq3kVVp6VDnJmWPcdkjMmq1u4+ysCxq1i96wgd6pTkmevqUqJAdFCOHdQHbL3kNAxoiJufSXGTAw5R1alpjDXsWGIyxmRl587H8d68LYyavoFcOSJ44uraREUIL03bwO7DpyhTKDePdqhB14ZlAzpuelV+yAMUBg6pavhUBwwyS0zGmOxg84HjPD5uNUu2HCRCwLfkXu6oSJ7vXi+g5JRelR9Oququ7JyUjDEmu6hcPB9f9WxKodxR+NeBPXX2PCOmrg/aa+VIroGIxOG661JCVTXZYxpjjAk/ERHCkVMJ1+beffhU0F4nJUnkaVKemDKENwpwMtABuEFVv02mfQ/gGaAKbuDGYFX9zq9Nb+BRoDTwG9BPVeemQ/jGGBO2yhTKza4EklCZQrmD9hrJJiZVHRq0VwueR4AUFXYSkWa4EYRPAuOA7sAYEWmhqou9NjcCo3FD3ud5/04Wkdqquj0d4jfGmLD0aIcaDBq3mlM+tfVyR0XyaIcaQXuN0NQ7TwMRaYKrzXdXCnfpB/ysqs+q6u+q+iwwy1sfbwDwkaq+67V5GDcU/oGgBW6MMVlA14Zleb57PcoWyo0AZQvlDnjgQ3LC6n6QiOQHvgTuU9X9rkcvWc2AV/3WTQUe8o6ZEzfp4Ut+baYBzdMUsDHGZEFdG5YNaiLyF25XTG8BU1T1xwD2KQXs81u3z1sPbrLDyGTa/IOI9BKRpSKy9MCBAwGEYowxJjkhT0wiMkxENJnlchG5DWiAG6AQKP/BG5LAupS0cQ1V31HVJqrapHjx4qkIxxhjTGIyQ1fey8BnybTZDtwJ1AaO+3XhfS0iC1W1ZSL77uXCK58S/H2FFIMbSJFUG2OMMRkk5IlJVWNwySFJIjKYC+8DrQb+A0xIYteFQDtghM+6dsAC7/XPiMgyb90YvzZjk4vLGGNMcIU8MaWUqu4Cdvmu866cdqjqZp91M4ElqjrIWzUamCMig4DvgG64eaN8r7BGAp+KyBJgPnA/UAZ3T8sYY0wGCpvEFIAqwI74b1R1gYjchCs8+xTuAdsb459h8tp8LSJFgSdwD9iuATp7EyAmadmyZTEikmy7RBQjBVeL5i92vgJj5ytwds4Ck5bzVSGxDaku4mrSTkSWJlbE0FzIzldg7HwFzs5ZYNLrfIV8VJ4xxhjjyxKTMcaYTMUSU2i9E+oAwoydr8DY+QqcnbPApMv5sntMxhhjMhW7YjLGGJOpWGIyxhiTqVhiMsYYk6lYYgoiEXlQRFaJyFFvWSgiXXy2i4gMFZHdInJKRGaJSB2/Y+QSkVdFJEZETojI9yJSLuPfTcYTkf96RXtf81ln58zjnQf/Asd7fbbbufIjIqVF5GMROSAip0VkrYi08dlu58wjIlsTKaL9g7c9w86VJabg2gkMBBoBTYCfgPEiUt/b/hhu9t2HgUuA/cB0cfNMxXsZ6AHcDLQCCgCTRCQyI95AqIhIU6AnsMpvk52zf1qPq04Sv9Tz2WbnyoeIFMKVGBOgC1ALd272+zSzc/a3S/jn71Yj3AwL33jbM+5cqaot6bgAB4H7cP859gCDfbblBo7hJj4EKAicAW71aXMREAd0CPV7ScdzVBBXKupK3OzCr3nr7Zz98zwNBdYkss3O1YXn5DlgfhLb7Zwlff4GA4eBPBl9ruyKKZ2ISKRXoy8frpJ5JdzUGtPi26jqKWAOf8+U2xiI8muzA/idrD2b7jvAt6r6k996O2cXqiwiu0Rki4h8JSKVvfV2ri7UFVgsIl+LyH4RWSEiD4n8NW+OnbNEeOfoHuAzVT1JBp8rS0xBJiL1ROQ4EIurTt5NVVfz93xPSc2UWwo3N5R/UcREZ9MNdyLSE6gKDElgs52zf1qMm5esE67bsxSwQFwBYjtXF6oM9AY2Ax1wMw0MBx70tts5S1w7XDJ6z/s+Q89VVqwuHmrrgYuBQri+1o9F5HKf7SmeKTfANmFHRGrgultaqeqZJJraOQNUdbLv9yKyCPehewewKL6Z327Z8lx5IoCl+vcUOL+KSDVcYnrNp52dswv1BH5R1RV+6zPkXNkVU5Cp6hlV/UNV4/9DrAD642bShaRnyt0LROJKySfWJitphnuva0TknIicA9oAvb2v//Ta2TlLgKoeB34DqmG/XwnZA6z1W/c7UN772s5ZAkSkBHAd8K7P6gw9V5aY0l8EkAvYgvvBtYvfICLRuJErC7xVy4Czfm3K4UYTxbfJSsbjRpVd7LMsBb7yvt6AnbNEeeeiJu4D2H6/LjQfqOG3rjoQP3+anbOE3Ym7FfGVz7qMPVehHvmRlRZc/3UroCLuA/d53IiUTt72gcBRoDtQ1/vB7wby+xzjTdxMvW2BhsDPuKuuyFC/vww6h7PwRuXZObvg3LyEu6KsBFwGTPLOTQU7Vwmer0u8D8rBuPuYNwBHgAft9yvRcya4PwjfTWBbhp2rkJ+IrLQAH+H+GovFjfGfgc8wSe+HPhT3F+5pYDZQ1+8Y0cCruG6sk8BE4KJQv7cMPIf+icnO2d/vM/6D4Iz3n38sUNvOVZLnrAuw0jsfG4A+eMWr7ZwleL6uwN0PujSBbRl2rqy6uDHGmEzF7jEZY4zJVCwxGWOMyVQsMRljjMlULDEZY4zJVCwxGWOMyVQsMRljjMlULDEZk4kkMlGb/7I1if0/8mk3y2d9RW/dvX7ti4nIryJyUEQu8dbN8DnGZ+n1Xo1JjBVxNSZzaeb3/Xe4B0SH+qyLTeYYe4FuuKf0EyUiJYGZQEngSv27YOfDuLl1vktRxMYEmSUmYzIRVV3k+72IxAIx/uuTEZtcexEpi0tKBYE2qvpXsVNV/d3ntY3JcJaYjMlmRKQ88BOuuHAbVd0Q4pCM+QdLTMZkL5Vxs44q0FpVt4Q4HmMuYInJmOxlEG6W0TqWlExmZaPyjMlepuCqRI8WkVyhDsaYhFhiMiZ7GQvcDbQHxohIVIjjMeYClpiMyWZU9WPgfuAa4AsRiQxxSMb8gyUmY7IhVX0H6AtcD3wiIvZZYDING/xgTDalqq9495leBGJF5B61mUNNJmCJyZhsTFVHeMnpGdx02b1DHJIxlpiMycxUtWJq9hORHG53Pe8dZytuNF5CrzEMGOazbwTWzW9CyH75jMl6KgBncSWHUmOat3+FoEVkTADEupSNyTpEpCJQzPv2mKquT8UxqgMFvG//tAdxTUazxGSMMSZTsa48Y4wxmYolJmOMMZmKJSZjjDGZiiUmY4wxmYolJmOMMZnK/wNU9cXx7aNQ4wAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "## draw 1D sensitivity curve \n", + "\n", + "fixed = {\"'CA0'\": 1.0, \"'T2'\": 300}\n", + "\n", + "all_fim.figure_drawing(fixed, ['T'], 'Reactor case','T [K]','$C_{A0}$ [M]' )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Draw 2D sensitivity curve" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAElCAYAAADp4+XfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAA1yklEQVR4nO3de/yfc/3H8cdzTpMph8VIDptDISlLRKywHDpQKGoH9UvaDzn8JKRGBxVNy6EiWRQd8MOEYX4Uhk2pCKkdZE6b89iGef3+eL8/XPv4HK7v9t3ne23f5/12+9w++1zX+3p/3tf1+e56Xe/D9b4UEZiZWe/Vp6cLYGZmPcuBwMysl3MgMDPr5RwIzMx6OQcCM7NezoHAzKyX65WBQNJISVF4vSTp35K+K6lvBcr2+Z4sw7JC0tslLci/b/8eLMdoSR9usHycpOk9UJ6FvlfShvn/wcjCMv8d9iK9MhAU7AdsD+wFTACOA07t0RLBSMD/AbvHcNLf+ArAAT1Yjm8CbwgEwLeAfTpclkYeJf0/+ENh2Uj8d9hrLN/TBehhd0fEv/K/r5e0CfAFSV+JiFd7smDdSdJKETG/p8vRA4YD9wBvBkYAZ/RscRYWEf/u6TIA5L+N23u6HNZzenuNoN6fgZWB15oRJL1J0vclTctNDNMknSCpTyFNX0mnS7pH0hxJj0kaL+kd9V8gaSNJF+Y08yVNlTQ2r7sJ2BnYodBsdVNh220l3ZC/4wVJEyVtW5f/OEkPS9pe0m2S5gI/aLXTkvaRdGvO9zlJd0r6eGH9oZImSXpK0jOSbpe0V10ey0v6Vm5imydptqRbJO1Yl+6Lkv5aSHOepDValW9RSNoe2BS4ALgQ2EbSFiW3XUHStyVNz7/59Px5hUKaWnPKKEljJD0h6UVJV0nasJCuduv+CYXfdHRe16yJ5hBJp+S/kecl/Sr/HW4saUL+nf4laURduTfOf1vTJM3Nf1s/kbR6m/1dqGmo2d+hpG3yvz/RII/a391yZY6xVUtvrxHU2xB4FngS0smN1GS0Oaka/3dgO+BEYA3g6LzdSsCqwLdJ1ew1gFHA7ZLeERGP5fw2Au4EXiQ1FzwIvB0YmvMZBfwKWA74Ul72XN52K+Bm4B+kansAXwNulrRdRPy1sB9vAX4DnAYcD8xttsOSDgN+DFxOumqeA7w3H4vicfk5MJ30N/Mx4CpJe0bENTnNscCRwAnA3aSr8MH5WNS+63v5mP0YOAZ4Wz5mW0r6QEQsaFbORTACeBX4NdAvl2t4Lmc7vwT2B74L3EJqNvk6MBA4sC7tcaT9PQhYK29znaQtIuLlvO0kYBzws7zNw22+/zjgprwPm5MC+avAe4BzSb/rl4HzJU2JiHvzduvmvI8Ans7lPR64OpejrIZ/hxHxD0mT87IraoklrUY6Xj/o5t/QOiUiet2L10+km5FObKuT2kNfAQ4tpBuW0+1Ut/0JwEvAWk3yXw54E/A8cGRh+QWkE+26Lcp2E3BLg+WXAM8AqxWWvRl4CrissGxcLvMnShyHN+cyXtYubWGbPvmYXQdcUVh+Vat8SMFkAfCNuuU75PLu3Y2/70qkE+GEwrJJwEygT5ttt8zlGV23/Ot5+VaF/QlSYO5TSFfbny8UlgXw7QbfNQ6YXneMArixLt1lefnnCstWz3+v32yxL8sDO+Zt31Pie0eW+DscmX/HDQrLDs9lWa+7fkO/Ovvq7U1D9wMvk06m5wE/i4gzC+t3B2YAt+Wmj+VzLeE6UgfkdrWEkvaXdIekZ0j/KV4gXYluVshvKHBVRDyyCGXdKW/7TG1BRDwHXEmqxhe9Qjoxt/OBXMZzWiXKTQJXSXo85/0ysBsL79tkYE9J35G0o6QV67LZjRREfl13LO8g1Xp2avH9fYrbqNAs18QngNVIgbfml6Qr5l3bbFsrx6/qltc+1x/rS6LQnxQRt5KuyrtyBV7vmrrP9+f3CYXveRp4glSjBEDSipKOl3R/bhJ8GfhTXl38rRbHb0gXJF8sLPsS8IeIaFfTsYrq7YFgH+B9wJ7ADcAoScML69cCNiD9hyq+7szr1wSQ9DHgt8B9pKaD9+d8ZwHF4ahr0r5ZoJk1SM1O9R4jXR0WPRHlquhr5vemZZL0dmBi/v7DSMHjfcC1LLxv3yU1d32cdPJ5UtL5en3Y5lr5/V+88Xi+uVCWRn5Rl/4XbfZrBKn57f8krZabLibkbUe02pDXm7Lqj/VjdetrHm+Qx+OkZq9F9XTd55daLC/+BqcAo0lBay9gW+CTeV23DIuOiHnA+aRBFctL+iCp+eqn3ZG/9Yze3kdwT+RRQ5JuBP4GnCrp0oh4gdRXMI3U/tnI9Pz+GeBfETGytiJ3LNafNGaz6CeIp4ABDZYPyOuKys4tPju/v400uqaR3Ul9DvsXr/gkvWmhL0zt4d8Hvi9pAPBRYAypiezT5H4XUq2o/oRGYX0jo4FiTW12k3RIWjt/x/KkpqB6+0haNSKeb5JF7VgOAIqjemrHvr6cazfIY21Sv0GnfQa4ICK+XVsgqd8S+J6fAEeRal77kP4fTGi1gVVbbw8Er4mI+ZKOIXWCjSLdT3At8ClgTkTc32LzN5GaTIqGkfoKiq4DPilpnYhodHUPMJ/U8VzvZmCv4klM0qqkjtubWpStldtIfRYH0/w/cu2E/3JtgaRNSW3hDWsSkTrHfy5pT1KbO8D1pA7P9SPi+q4UMiKm83rQbedzpL/rL/N6k0rNu4Efke4faVaruDm/fwb4TmH5Z/P7H+vS7ytpdK15SNIOwHqkPomal0ij0Za0N1H4nbKDFjGvZn+HRMS/JV1H6vDfGjg5lqHh1r2RA0FBRFyZR0X8j6QzSSNODgImSvoh8FdgRWAQqQlk74h4kRQw9pZ0OqltfhtSB9ozdV/xTVKV/TZJ3yU1k7wN2D0iPpfT/IPURPVp0hXp8xHxAGnU0kdzWb5Puuo/lvSf/+RF3N/nJR0HnCHp0ry/z5P+c8+LiDNITWavABfkY7AOcBLwEIWmRUlX5OPzZ9IV/3tItYmf5e/6dy73mZI2I51w55HauHcDfh4R/7co+1FnOKkW97OIWKhmJOlPwFdJzUMNA0FE3CvpYmB07sO4jdTefyJwcUT8rW6TVYHLJf0MeCupeeZBFu6f+AcpiF9LOjaPLGI/UTvXAiMk/Z30t/VJUlPeomj2d1hzNumiqUxTnVVdT/dW98SL10cNbdxg3dC87sj8uS+paeJ+0lXSU6SO0dHA8jlNH9IwyEdIbdM3k06E04FxdfkPAi4mNW/MB6YCpxfWDyAN93s+l+Omwrr3k07Mc0id0ROBbevyHwc83MXjsS+p03YuqeP2DuCjhfX75/2fB9xLuloex8IjT44m3ZT0ZM7ngXyMVqj7rmE53Qt5P+4jNfss9oiTfMwDOLFFmu+QaiYbtUizQv49Z5BOdDPy5xUKaTbM3zWK1AQ2K//2f6jPm1R7uisfv9dGJDU4hrU8/6tu+9F5+fJ1y6cDvyp87k/qzH06v35N6s+pHxHU7HuLaZr+Heb1y+Xf8Pc9/f/Zr8V/Kf+oZtYF+aaxacAXI+LnPVycjpO0G6mpc9eImNjT5bHF46YhMytN0iDSjWqnA392EFg29Pbho2bWNSeS7nOYT+qPsWWAm4bMzHo51wjMzHo5BwIzs16u13UW9++/Rmy44Xo9XQzrgr/c9feeLoJ1watARGhx8lheKt1o/WqaXHD3xfm+3q7XBYINN1yPKVOu7OliWBesoo16ugjWBfO6IY8AVimZ9vnC80Ns0fS6QGBm1SfeOD+LLTkOBGZWOSLd3m2d4UBgZpXkGkHnOBCYWeUID2nsJAcCM6sk1wg6x4HAzCrHncWd5UBgZpXjzuLOciAws0pyH0HnOBCYWeW4aaizHAjMrHIcCDrLgcDMKslNQ53jQGBmleMaQWc5EJhZ5XjUUGc5EJhZJblG0DkOBGZWOZ5iorMcCMysklwj6BwHAjOrHHcWd5YDgZlVjjuLO8uBwMwqyTWCznEgMLPKcWdxZzkQmFkluUbQOQ4EZlY5rhF0lo+1mVVObdRQmVfbvKTjJE2W9JykWZLGS9qyxHb7S7pb0ouSZkg6pkGaFSWdLGmapPmSHpJ0eGH9SEnR4NW3kGZ0g/WPldi1buMagZlVTjePGhoCnA1MzlmfDNwgafOIeKrh90t7ABcBhwPXAu8EzpU0NyLOLCS9GHg7cDDwILA2sHJddi8Cg4oLImJeXZoHcjlrFpTct27hQGBmldRdfQQR8ZHiZ0nDgGeBHYDxTTYbBoyPiLPz56mSTgGOlXRWRISkocCuwKCImJ3TTW9chGh3hf9KiTRLjJuGzKxyurNpqIFVSee+p1ukWQmov2qfC6wHbJA/702qZRwl6WFJD0r6saR+ddutnJuWHpZ0laT3NPi+gZJm5iam30ga2OW9WgwOBGZWSX1KvoD+kqYUXge3yXoscDcwqUWaCcDekoZK6iNpU+DovG6d/D4Q2BF4N/Ap4FBgd2BcIZ8HgM8DnwAOIAWXWyVtUkhzBzAS2AP4IjAAuE3Smm32o9u4acjMKqeLU0zMjojBpfKVxpBO3jtGRKt2+HNJ7fpXkLorniMFkNG83n7fBwjgwIh4Nud/KDBB0toR8XhETKIQcCTdRgpCh5H6H4iIa+rKeDswFRgBjCmzX4vLNQIzq6Qu1AhKkXQ66ar8wxExtVXaSI4F+pGaggYAd+bV0/P7o8DMWhDI7svv6zfJdwEwBdik0fqcZg5wb6s03c2BwMwqR8CKJV+l8pPGAgeSgsD9ZcsREQsiYmZEvEQKIpMi4om8+lZg3bo+gU3z+4wm5RCwFSmINCtrX+AdrdJ0NwcCM6uc2g1l3VEjkHQWcBDpRP60pAH51a+Q5hRJEwuf+0v6sqR3Sto6B5L9gCMKWV8EPAmcL2kLSTuQmo8uqQULSd+U9BFJAyVtDZxHCgQ/LXzXaZJ2lrSRpPcDlwCrAL8sfcAWkwOBmVVSN44aGkUaKTSRdJVde/1PIc061I31B4aTRgXdCmwBDImIWvNQrQlnV+AtOd3vgJtJncM1qwHnkJqMrgPeBuxUzIc0EuliUsfyZcB8YLuIaFirWBLcWWxmldOdzyOICJVIM7Lu82xg+xLbPQAMbbH+SODINnl8pt33LGkOBGZWSW6u6BwHAjOrHD+YprMcCMyscvyoys5yIDCzynEg6CwHAjOrJPcRdI4DgZlVjmsEneVAYGaV5EDQOQ4EZlY5HjXUWQ4EZlY5fmZxOZLeBuwGbAesS3o62mzSXco3AzdHxKvt8vGxNrNKWoIPplnqSRoi6SrSTKi/APYkTV+xMun5CEeTptT4T34m8ptb5edAYGaVs4SfULZUywHgauAFYH/grRGxfkRsExE7RsTmpPmPtiY9q3k/4N+SPtIsTzcNmVkl+Sq1qX8B/9XqGce5Oehv+fUdSR8nBYeGHAjMrHI8fLS5iDhiEba5stV6BwIzqxyPGuosBwIzqxzXCMqTtCGNRw3dHhHzyuTR0WY4Sf8t6W+SnsuvSZL2KqxX7uF+RNJcSTdJ2qIuj5UknSFptqQXJF0pab1O7oeZLXnd/cziZYmk1ST9j6T7gX+TnpZ2GvAt4CfAjcAzkn4naUi7/Dp9HB8GjgXeCwwmFfZySVvl9V8lDXs6DHgf8ARwvaRVC3n8CPgU6bFzHwTeDFwlyRcQZssIjxpqTtLRwFTgKGACaeTQxqTO4BWBAaSH6hxLekLa9ZJukLRZszw72jQUEVfULTpB0peB7SX9nfQ80O9FxKUAkkaQgsGBwM8kvQX4AnBQRFyf0wwjPSh6V9JBMbNlQG88yZf0WdLjMK9scrPYE/l1BzBW0rqkx3J+jNRk9AY91keQr+D3A/oBtwEbkSLZdbU0ETFX0h+BDwA/A7Yh9SEV0/xH0n05jQOB2TLAncXNRcR7u5j+EVLtoamOBwJJ7wImAX2BOcA+EfF3SR/ISR6v2+Rx0h1zkALFAlJnSH2aAS2+82DgYID11193scpvZkueO4s7qydqBA+Q7nhbjdTW/8u6zoyoS68Gy+q1TBMR5wDnAAwevFW7vMysAnprR3A7krp0aMrMNdTxQBARL5HujAOYIul9wJHAd/KyAcB/Cpusxeu1hMdIFwr9gVl1af64pMpsZp3lGkFLL3chbVDiPF+F+wj6ACsB00gn+t2AyQCS+pJGBh2T095FOgi7kYZLkYeOvpPUz2BmywjXCJoS8BxwGWmgzGLraCCQ9D3gD6Qr/lVJo4GGAHtFREj6EWkk0f3AP4Gvk/oRLgKIiGclnQecKukJ4ElgDGk+jRs6uS9mtuS4RtDSyaSRQyNILSEXAL+PiDmLmmGng+4A4FekfoKJpHsF9oiIa/L6H5BO7GcBU4B1gKER8XwhjyNJkfC3wK2kQPGxiFjQkT0wsyWuNmqozKttXtJxkibnm1hnSRovacsS2+0v6W5JL0qaIemYBmlWlHSypGmS5kt6SNLhhfUjJUWDV9+6fEblPOZJukvSB5uVKyJGR8QmwM6kC+YfAo9J+rWkoZJU4rAspNP3EYxssz6A0fnVLM080g1nh3Vj0cysYrqxRjCENB3zZFKMORm4QdLmEfFUow0k7UFqiTgcuJbU/HyupLkRcWYh6cXA20mjEh8E1iZN81D0IjCouKA49YOkTwNjgVHALfn9mly+h5rtVETcAtwi6TBgb2AYcBUwS9K3IuKnzbatV4U+AjOzhXRn01BELDQPf74J9VlgB2B8k82GAeMj4uz8eaqkU4BjJZ2Vm7KHkm5kHRQRtSHt0xsXofmU0aQx/uMi4tz8+TBJuwNfBo5rs3u1ATi/k3RTzut/gKFA6UDg/hgzq6QlONfQqnnTp1ukWQmon7BtLrAesEH+vDeplnGUpIclPSjpx5L61W23cm5aeljSVZLeU1shaUXSjbLX1W1zHekm2ZYk9ZX0GUlXk6bwOQA4lTS9RGmuEZhZ5SzhzuKxwN2kG1ubmUCanmEoaSDKxqR50CD1XU4HBgI7AvNJ90StBpxBmgV035z2AdJ0EH8lBaCvALdKendEPEgaCr8cjW+k3bVZ4SR9iFRr2Zd0uC4D9gBuzE3sXeJAYGaV1IWr/f6SphQ+n5NvIn0DSWNIJ+8d2wwwOZfUrn8FqU/6OVIAGU2a3aBWxAAOjIhnc/6HAhMkrR0Rj0fEJAoBR9JtpCB0GKn/oab0jbSSZpCCzf+R+hMujYi5LfalLQcCM6ucPqRpNEuaHRGD2yWSdDrwGeBDETG1Vdp8VX2spONJox1nAbvk1dPz+6PAzFoQyO7L7+vzxqt8ImJBDlqb1MpOCiz1U+QUb6St93ZSB/Q7gO8C320xUCgiYoNmK2scCMyskrqzA1PSWFIQGBIR95fdLtcaZuY8DgAmRcQTefWtwH6S+hXG8G+a3xve6JWHdm5FaioiIl6SdBfpJtnfF5LuBlzapFi/LFv+shwIzKxyurOPQNJZpPb0vYGnJdWuvufUTuB5RNC2EbFL/tyfNDvyTaSO44Py550LWV8EnAicL2k0qY9gLHBJLVhI+iZwO2lo6ZtJzUFbkUYE1YwBLpR0Jym4HEJq+mk46iciDlqkA9GCA4GZVVI3dhaPyu8T65afxOv3LK1D3Vh/YDhpBI5I7fxDIuLO2sqImCNpV1IH8WTSKKTLga8V8liNNOHlANKQ1b8AO9Xl81tJa5JmUlgHuAfYMyK6ZfqIMrQIHcxLtcGDt4opU67s6WJYF6yijXq6CNYF84AFEV2+u7VoKynK/i/dCO4q00ewrJA0sCvp2/WHgGsEZlZBfjBNS/+i/dT8RW0rVw4EZlZJnnSuKfcRmNmyz7OPNhcRHjVkZr2D579pTFKfMk8d6wofazOrnFqNoMyrF3pZ0ra1D0pOLgyL7TIHAjOrHAeClupHZPUBTiDde7BI3DRkZpXjUUNdtljDdR0IzKyS3FzROQ4EZlY5HjXUVqP7CBb57mAHAjOrJAeClsZLeqlu2dWSXq5b5tlHzWwpVrZtqFsHUi4VfB+BmfUCXWkb6mWBwLOPmlnv0JVhQ/WNIdZl7pg3s2ryjQQNSXrvImzTV9I7mq13IDCz6vEdZa38UdKVknaX1PIcLmn9/LjNacBHm6Vz05CZVZMvU5vZDPgWcAXwnKRJpEdfzgLmA6sDA4FtgS1JQeDoiLioWYYOBGZWPb6RoKmImAl8XtLXSFNSfwQ4Cli5kGwa8EfS09ImRJsnkDkQmFn1eI6JtvJzkb+fX0haDegLPBkRXepCdyAws2pyjaBLIuKZRd3WrXBmVj0inZ3KvHq5PA31xyWdJul8SRvk5TtLKjUjqWsEZlZNrhG0JWl14Grg/cBzwKrAGcAM4IvAU8Dh7fJxPDWz6vHw0bJOBd4O7AD0Z+HpqG8AdimTSdMagaQLFrFgJ0bEjEXc1sws8WVqGZ8A/iciJkmqD4sPkYJEW62ahj4HPEYal1rW+sCPSNUSM7NF41FDZfUDZjZZ15eSD6xp10ewd0TcWSYjScsD9dOimpl1ne8jKOsBYCipGajezsDfy2TSqvI1EXi2CwVakLd5rgvbmJm9UTf2EUg6TtJkSc9JmiVpvKQtS2y3v6S7Jb0oaYakYxqkWTE/OH6apPmSHpLUsHNW0gGSQtJVdctH5+XF12Pt9wyAs4AjJJ1AapEBWE3SQcCheX1bTWsEEbFbyYLU0gfQpW3MzJrqvj6CIcDZwGRSiDkZuEHS5hHxVKMNJO0BXEQacXMt8E7gXElzI+LMQtKLSe3wBwMPAmuz8B2+tfwGkjp2/9SkjA/kctYsKLNjEXGupEHASXm/AK4nTc79g4j4dZl8WnUWbxMRd5XJRNKZEXFombRmZm11Y9NQRHxkoaylYaTWjh2A8U02GwaMj4iz8+epkk4BjpV0VkSEpKHArsCgiJid002vz0jSCqSAcQLwIdLonnqvRETZWsBCIuJrkn5CuhBfC3gSuD4ippbNo1XMnSDpXe0ykHQe8OWyX2hm1lats7jMq+tWJZ37nm6RZiVgXt2yucB6QO3Rj3uTahlHSXpY0oOSfiypX9123wGmR0SrJ4sNlDQzNzH9JtcgSouIGRHx84j4bkT8rCtBAFoHgv+Qqk+bNVqZ72a7kDTp0Te68qVmZm2V7yPoL2lK4XVwm5zHAncDk1qkmQDsLWmopD6SNgWOzuvWye8DgR2BdwOfIrXJ7w6Mq2WSaw2fBg5p8V13ACOBPUg3gQ0AbpO0Zpv9QNJBkkY3WTda0oh2eUDrUUO7AjcDEyXtHBH/LnzBcqT2s/2Ar0bEaWW+zMyslNoUE+XMjojBpbKVxpBO3jtGRKt2+HOBQaSpnlcgDYIZC4zm9fb7PkAAB0bEszn/Q0mtKWvndOPy+qa1j4i4pq6MtwNTgRHAmDa79BXgvCbrngCOoMQzjpse6oh4EvgwMIcUDNbPhVwBuJQUBL7iIGBmS0Q331ks6XTgAODD7ZpOIjmWNE5/A9JVem0o/fT8/igwsxYEsvvy+/qkZwGsQ2pZeUXSK8BwYM/8uWFrS0TMAe4FNimxWxvntI3cRwpmbbWMuXma012AV4AbJW0CXAl8DPhSRJxR5kvMzLqkm6eYkDQWOJAUBO4vW4yIWBARMyPiJVIQmZTPiwC3AuvW9Qlsmt9nkPoP3gVsXXhdSRo5tDXpmQGNytoXeAcp0LTzCo07nwHeWmJ7oMSkcxExU9KHSA85uJf0E42MiAvLfomZWZd10/BRSWeRRgHtDTwtaUBeNSdffZNHBG0bEbvkz/1JrR43kTqOD8qfdy5kfRFwInB+bqdfjdR8dEkhWNxTV5ZngOUj4p7CstNIo5ceIo36ORFYhRJNOqRayiHA7xqsO4QUjNpqNXz083WLLgKOA64BVqhfHxG/KPOFZmZtCVix23Ibld8n1i0/idTmD6kJp74ZZThp7L9IHctDijMtRMQcSbuSZvucTBqFdDnpqWBdsR5peGl/0uMmbwe2Kzln23dITU93AD8nTTfxNuC/gPdS8t4uNXuCmaRXy2SQRUQsFTeEDx68VUyZcmVPF8O6YBVt1NNFsC6YByyIKDXHTTODV1dM+VC5tPpf7irbWbwskvQJ0hxvGxQWTweOiIhSJ7tWTUP+32dmPcNzDZUWEVcAV+TO5zVJo6j+2ZU8Wk0x4RlEzazneBrqLomIBxZ12174hLIVgQ17uhDWBS/EF3u6CNYFgwf/7+Jn4hpBl0h6N7AZaerphURE22fLtOosvhEYVXaolaQ+pKlQvxQRD5bZxsysKQeCtiStBvwB2K62KL8XO3/bBoJWla8hpDk5SpdpEbYxM3ujJTvX0LLku6R+gZ1IR20f0o3AvybdnbxtmUzaNQ1dLqkrTyhrPATJzKwr3DRU1kdIw2Bvz58fzrNG35RnJP0KaRhsS60CQZmbGRqZ3T6JmVkb7iwuYx1gakQskDSPhVtkLgN+UyaTVqOGDlq88pmZLSLXCMp6jHRHM6RpLbYn3Q0NaR6iUnrhqCEzWyq4RlDGLaST/1XAhcA3JW1ImoNoBGluo7YcCMyserp3ioll2UnAuvnfp5I6jj8NvIkUBA4rk4kDgZlVT9eeR9Br5efE/Dv/+2XSw3OObrlRAz7UZlZN3fw8gmWNpBUlPSXp44ubl2sEZlY97ixuKyJeyg+7qX+2cpc1rRFImppvWzYz67w+JV+92+XAvoubSasawYakBzKYmXWWawRlXQP8WNIlpKDwKHU39kbEje0ycdOQmVVPbYoJa+fS/P7J/KoJ0lEMSoTUdoHAU0aYWee5RlDWh+mG83S7QHCSpDJTRkREjFjcwpiZvcbt/21FxE3dkU+7QLA1UGbSOdcczKz7uEZQiqSpwD4R8dcG67YEroyIge3yaRcI9i4+rNnMrGMcCMrYkOaDevqy8HOMm3JnsZlVj+8s7opmLTKDgWfKZOBAYGbV41FDTUk6EjgyfwxgvKSX6pKtDKzB4k5DbWbWo9w01MxUYGL+9whgCjCrLs184B/Az8tk2Op5BK6YmVnPcGdxUxFxBXAFgCSAkyNi2uLk6ZO9mVVTN00xIek4SZMlPSdplqTxeURNu+32l3S3pBclzZB0TIM0K0o6WdI0SfMlPSTp8Cb5HSApJF3VYN2onMc8SXdJ+mD7PUsPEFvcIAAOBGZWRbUaQffMPjoEOBv4AOkGrFeAGySt0fTrpT2Ai4BzgC2BUcCRkg6tS3oxsDtwMLAZsB/wtwb5DSQ9L+BPDdZ9GhhLehD9e4DbgGskrd+kbEdK6tt8dxtu815Juzdb70BgZtVT6ywu82ojIj4SEedHxD0R8XdgGPBWYIcWmw0DxkfE2RExNSL+AJwCHKvcHiNpKLArsGdEXB8R0yPijvqbvCStQAoYJ5Da9+sdBYyLiHMj4r6IOIw0Z9CXm5RtODBd0vdaTQwqaXVJwyRdR3qS2ZubpXUgMLPq6d4aQb1VSee+p1ukWYk3Tu88F1iP18fm7w1MBo6S9LCkByX9WFK/uu2+A0yPiF/Wf4mkFYFtgOvqVl1HqsE08l7gq8AewF8kPSPpT5Iuk3SxpGsl/ROYDfwMmAlsHhG/a7azHjVkZtW05C5TxwJ3A5NapJkAjM1X/TeQHgRfe/LXOsB0YCCwI2mEzqdID5E/g/ToyH3htVrDp0mzNDTSnxTOHq9b/jiptvEGERHABcAFkt5Papp6fy5PX+BJUhPUd4ArIuKZFvsJOBCYWRV1bdRQf0lTCp/PiYhzGmYrjSGdvHeMiAUt8jwXGEQanbMC8BwpgIwGatv1IY3jPzAins35HwpMkLR2Tjcur29V+4A33hSmBsveuFHEHcAd7dK140BgZtVUPhDMjojB7RJJOh34DPChiGjUVv+afNV9rKTjgQGkcfq75NXT8/ujwMxaEMjuy+/rA6uQag835G4FyPWc/GSxLYBppIAxoK4Ia/HGWsIS40BgZtXTzVNMSBpLCgJDIuL+stvlWsPMnMcBwKSIeCKvvhXYT1K/iJiTl22a32cALwDvqsvy28DqwH8D0/LjJu8CdgN+X0i3G68/a6DZPq1F6ifYnHQXMcBTpBvJrimUsy0HAjOrnm6cYkLSWaRRQHsDT0uqXX3PqZ3AJZ0CbBsRu+TP/UlDQW8idRwflD/vXMj6IuBE4HxJo0l9BGOBSwon4XvqyvIMsHxEFJePAS6UdCcpuBxC6mf4aZP96UNq/z8SWBF4kdTxrVyGNwEvSfoRcFyu3bTkQGBm1dR9dxaPyu8T65afRGrzh9SEM6hu/XDS2H+ROpaHFGdjjog5knYldRBPJp2MLwe+1pXCRcRvJa0JfD2X4x7SkNQZTTY5DjiCFAwujIjpxZWSNiAFvhOA53O6lhwIzKx6unGKiYhQiTQj6z7PBrYvsd0DwNAulGVkk+Vnk256K+OLpCv9HzXJawbwbUkvAF/BgcDMllq+y6mZtYG/lEj355y2LR9qM6ueJXtD2dLuPlLHdzsHAKU6xl0jMLNq6p0n+TJOBi6RtBnwK+BeUv9EkEYPbQF8ltSxvW+ZDB0IzKx6/GCapiLickl7keY++jmNb0b7K/CxiLimTJ4OBGZWPX5UZUsRMYF0B/N6pBrAGqSj9hRwb0T8pyv5ORCYWTW5aaitiHgYeHhx83HMNbPqcWfxYpPUX9JOZdI6EJhZNXXTE8p6sZ2B/yuT0E1DZlY9fUiTJ1hHOBCYWTX5ar8hSb8omXSD9kkSBwIzq55unGJiGTQSeBaY0ybdymUzdCAws2pyjaCZh4DrIuLgVokk7Qv8tkyGDgRmVj2uEbQyBWj7IB5KPOGsxjHXzKrJw0ebuZL0YPp2/kGajqIt1wjMrHo8xURTEXEB6eH17dLdR3rmQlsOBGZWPW4a6igHAjOrJjdcd4wPtZlVj6eYKEXSq5IWNHm9IulJSddLavkUtY4GAkmjJUXd67HCeuU0j0iaK+kmSVvU5bGSpDMkzZb0gqQr8wx8ZrYs8RQTZXwL+A8wCxgHfB/4Zf78MHAh8FbgGkkfbZZJTzQNPQAMKXxeUPj3V4GjSTdMPAB8A7he0mYR8XxO8yPgE6Sn7zwJjAGukrRNRBTzMrOllaeYKGseMA3YIyLm1RZKWhm4hhQQ3gv8ATgeuKpRJj0RT1+JiMcKr1mQagPAEcD3IuLSiLgHGAGsChyY07wF+AJwTERcHxF/BoYBWwG79sC+mNmS4hpBGYcApxeDAEBEzAVOBw6JiFdJD7DZqlkmPXEYB0qaKWmapN9IGpiXbwQMAK6rJcw780fgA3nRNqRBZcU0/yE9w7OWxsyWBVqu3Kt3W4vmA21XBNbM/55N6nlpqNOB4A5Ss88ewBdJJ/7bJK2Z/w3weN02jxfWDSA1JdXfTFFM8waSDpY0RdKUWbNmLdYOmFkniNRyXebVq00BRktap7hQ0rrAN/N6SBPQPdIsk44exfrnZ0q6HZhKagK6vZasbjM1WFavZZqIOAc4B2Dw4MGlb7s2s55SCwRlzF+SBam6rwATgWmSJgFPkGoJ2wMvAp/L6TYGLmqWSY+2sEXEHOBeYBOgNnqo/sp+LV6vJTxGGjDWv0UaM1vquUZQRu4n3Zg0aOZV4F35/YfAJhFxd073jYj4ZrN8ejQQSOoLvAN4lNTz/RiwW936DwK35UV3AS/XpVkPeGchjZkt9QT0Lflqk5N0nKTJkp6TNEvSeElblthuf0l3S3pR0gxJxzRIs6Kkk3Of53xJD0k6vLB+v9ws/Uwe7n63pBF1ebQcVt9ORDwZEcdHxC4RsXl+PyEiniybR0fDqaTTgPGkaVTXAk4EVgF+GREh6UfACZLuB/4JfJ005/ZFABHxrKTzgFMlPcHrw0f/BtzQyX0xsyWpK01DbQ0BzgYm54xPBm6QtHlEPNXw26U9SOedw4FrSReb50qaGxFnFpJeDLwdOBh4EFibhZ8D8CTwbeB+0kXsR4HzJM2KiKsL6VoNq29L0hqk5qA1SH2odzTbt0Y6Xa9aj3Tg+pPGt94ObBcRM/L6H5AO4lnA6qTO5aGFewgAjgReIc2zvTKpfWy47yEwW5Z0XyCIiI8slLM0jPRglx1IF6aNDAPGR8TZ+fNUSacAx0o6K1+4DiUNWx8UEbUBLNPrvvvGunzH5hrBB4FiIHglIkrXAur259uk+69WKiyeL+m0iDixTB6d7iz+TJv1AYzOr2Zp5gGH5ZeZLbOW2NDQVUnN4k+3SLMS6Watormki9kNSCf8vUm1jKMkDc/rrwGOz/2fC8n3Sn0Y2Aw4oW71QEkzgZdIF8DHR8TUdjsi6QjSjWLnAb8iNa8PIHUSH59rHj9ul0/v7mkxs4rqUo2gv6Qphc/n5JGCzYwF7gYmtUgzgXT1PpTU7Lwx6aobYB1SIBgI7EgatvQpYDXgDGBdYN/X9iTdCDuTFFwWAP9dN4KyNqz+flKT+ddJw+q3KNHOfwgwNiKOLCx7ALhZ0hxgFOBAYGZLoy4FgtkRUeaJXUgaQzp579imOflcYBBwBemGredIAWQ0r7ff9yENWz8wIp7N+R8KTJC0dkTURjI+D2wN9AN2AcZImh4RE6HtsPoxbXZpQ9L0EY38Afhym+1f2xEzs4rpQ3eNGqqRdDppjrIPt2t2ieRY0sl7A1Jzy5159fT8/igwsxYEsvvy+/qFvF6NiH9FxN0R8UPg96TmnGbfXRxW386TQLMRUFvk9W05EJhZRXXffQSSxpLmLPtwRNxftgQRsSAiZkbES6QgMikinsirbwXWldSvsMmm+X0GzfVh4Y7d+rIWh9W387/AtyQNk7RC3n55SQeQRkddWiIPNw2ZWRV136ghSWeRRgHtDTwtqXbT6pxap24eEbRtROySP/cH9gNuIp20D8qfdy5kfRFpCPz5kkaT+gjGApfUgoWkE0h9AFNzPnvmsrw22KXVsPoSu3cc8O6c9heSniINIV0OuIUWNY8iBwIzq6BuvY9gVH6fWLf8JF4fobgOqU+gaDhwai7MJGBIRNSah4iIOZJ2JXUQTyaNQroc+Fohj37AT0ijjeaSOoSHR8TFhTTthtU3FRHPS9oJ2AvYiTTs/ingZuCaPBKzLQcCM6ugbr2PoOmsm4U0I+s+zybdoNVuuweApk//iojjSFftrfJoOay+RBmC9JyBhs8aKMOBwMwqqDbFhNWT9CrtJ+KsiYhoe553IDCzCurWpqFlzcmUDwSl+EibWQU5EDQTEaO7O08faTOrIAeCTvKRNrMKciDoJB9pM6sgB4JO8pE2swoSLW6+tW7mQGBmFeQaQSf5SJtZBTkQdJKPtJlVlE9PneIjbWYV5BpBJ/lIm1kFORB0ko+0mVVQ7cE01gkOBGZWUT49dYqPtJlVkJuGOslH2swqyIGgk3ykzayCHAg6yUfazCrID6bpJAcCM6sg1wg6yUfazCpIwHI9XYhew4HAzCrINYJO8pE2swpyIOgkH2kzqyifnjrFR9rMKshTTHSSA4GZVZCbhjqpT08XwMzsjWqBoMyrTU7ScZImS3pO0ixJ4yVtWWK7/SXdLelFSTMkHdMgzYqSTpY0TdJ8SQ9JOrywfj9JUyQ9I+mFnN+IBvmMynnMk3SXpA+23bFu5JBrZhXVbaenIcDZwGRShDkZuEHS5hHxVKMNJO0BXAQcDlwLvBM4V9LciDizkPRi4O3AwcCDwNrAyoX1TwLfBu4HXgY+CpwnaVZEXJ2/69PAWGAUcEt+vyaX76HF3/32HAjMrIK6r2koIj6yUM7SMOBZYAdgfJPNhgHjI+Ls/HmqpFOAYyWdFREhaSiwKzAoImbndNPrvvvGunzH5hrBB4Gr87KjgHERcW7+fJik3YEvA8d1YVcXmZuGzKyCuq9pqIFVSee+p1ukWQmYV7dsLrAesEH+vDeplnGUpIclPSjpx5L6NcpQyS7AZsAf87IVgW2A6+qSXwd8oPQeLSbXCMysgro0aqi/pCmFz+dExDkt0o8F7gYmtUgzgXT1PhS4AdgYODqvW4d05T8Q2BGYD3wKWA04A1gX2LeWkaS3ADNJwWUB8N8RcU2t7KRbqB+v+/7HSbWNjnAgMLOKKn16mh0Rg8sklDSGdPLeMSIWtEh6LjAIuAJYAXiOFEBGk07mkKJVAAdGxLM5/0OBCZLWjojayf15YGugH7ALMEbS9IiYWPi+qC9qg2VLjJuGzKyCur9pSNLpwAHAhyNiaqu0kRxLOnlvAAwA7syrp+f3R4GZtSCQ3Zff1y/k9WpE/Csi7o6IHwK/B47Pq2eTAsuAuiKsxRtrCUuMA4GZVVD3BgJJY4EDSUHg/rKliIgFETEzIl4iBZFJEfFEXn0rsG5dn8Cm+X1Gi2z7kJqJyPneBexWl2Y34Lay5VxcbhoyswrqvtlHJZ1FGgW0N/C0pNrV95yImJPTnAJsGxG75M/9gf2Am0gn7YPy550LWV8EnAicL2k0qY9gLHBJLVhIOgG4A5ia89kzl+WwQj5jgAsl3UkKLoeQ+hl+2i0HoAQHAjOroG59MM2o/D6xbvlJpDZ/SB3Ag+rWDwdOzYWZBAyJiFrzEBExR9KupA7iyaRRSJcDXyvk0Q/4CWm00VzS/QTDI+LiQj6/lbQm8PVcjnuAPSOiVa2iWzkQmFkFdet9BCqRZmTd59nA9iW2ewAY2mL9cZS4FyDfr3B2u3RLigOBmVWQ5xrqJB9pM6sgB4JO8pE2swpyIOgkH2kzqyifnjpFER27ea0SJM2i9RjfpVV/0s0ptvRYVn+zDSLirYuTgaRrScenjNkRsfvifF9v1+sCwbJK0pSyt9lbNfg3s6rwncVmZr2cA4GZWS/nQLDsaDXtrlWTfzOrBPcRmJn1cq4RmJn1cg4EZma9nAOBmVkv50CwFJC0k6QrJc2UFJJGltjmXZJuljQ3b/cNSW1nYbTFJ2l0/p2Kr8fabOPfy3qM7+FeOvQjzVF+QX61JOnNwPXAH4H3AZsB44AXgB8usVJa0QPAkMLnps/H9e9lPc2BYCkQEVcDVwNIGldik88CbwJGRMRc4B5J7wSOkjQmPFSsE16JiJa1gAL/Xtaj3DS0bNoe+FM+qdRMID3+bsMeKVHvMzA38UyT9BtJA1uk9e9lPcqBYNk0AHi8btnjhXW2ZN0BjAT2AL5IOua35ccRNuLfy3qUm4aWXfXNCWqy3LpZRFxT/CzpdtLDy0eQHlTecLO6z/69rGNcI1g2PcYbryTXyu/1V562hEXEHOBeYJMmSfx7WY9yIFg2TQI+KKlvYdluwCPA9B4pUS+Wf4d3AI82SeLfy3qUA8FSQFI/SVtL2pr0m62fP6+f158iaWJhk4uAF4FxkraU9Enga4BHoHSApNMk7SxpI0nvBy4BVgF+mdf797JKcSBYOgwG/pJfKwMn5X+fnNevAwyqJY6IZ0lXlOsCU4CzSOPRm7VPW/daD7iYdC/BZcB8YLuIqD0Zz7+XVYpnHzUz6+VcIzAz6+UcCMzMejkHAjOzXs6BwMysl3MgMDPr5RwIzMx6OQcCM7NezoHAFpmk7SX9TtIjkl6S9KSk6yWNkLTcEvrOcYWnft1UWD6ysHzTBtsNKazftbD864XlDy+JMptVnQOBLRJJRwC3AmsAxwK7Ap8H/gn8BPjoEvz6x0hz+I9qsO55YFiD5cPzunrn57yu7rbSmS1lPA21dZmknUjTH5wZEYfXrb5C0hjS3DpLyvyIuL3JusuAz0n6Rm2eHkkrA58CLiU9J+A1ETETmClp1hIsr1mluUZgi+JrwFPAVxutjIh/R8TfOluk11wIbADsWFi2D7AcKRCYWR0HAuuS3PY/BLguIub1cHEamUF6CHyxeWg48L/AnB4pkVnFORBYV/UnzYA6o13CHnQBsJ+kvpLWIfVfXNDDZTKrLAcCW+IkrSLpOUm/rls+SNItkv4p6S+SBnfTV/4eWAn4GPBZUufyxJZbmPViDgTWVU8Cc0nt8GV9GvgrsJek1QvLfwqMi4hNSf0Nv5akRhl0RUQ8D1xOah4aDvw6Il5d3HzNllUOBNYlEfEKcBOwm6SVSm72BdKDViaQrtCR9FZgO/JTuyLi+px2m24q6gXAXsC7cLOQWUsOBLYovgesCZzaaGV+RONW+d/vJD2N6yrgPFJQAFgfeCQiXi5sOiMv7w7XA78DfhoR93ZTnmbLJN9HYF0WEX+UdBQwJp/oxwEPAasDuwD/BRwI/I104r8wIl6RdAOwhqRmV/2L3SxUKOMC4IDuys9sWeYagS2SiPgRaaz+M8BpwI2kgPBO4EvAeEkrkNrpD5Q0HZgKvIUUHB4C1s1pajbIy82sg1wjsEUWEbcBtzVbL2kf4KGIeF9h2UbAn4GjgTtJd/qeK2k3Uo3grjLfLWn5VIRYkMsyjhSIWpX3JupqHblzern65Wa9iWsEtiR9gXSn72siYhpwD7AfcAhwkKR/kvobPlubFqKNDYCX6Z4hoSfkvIZ3Q15mSyWV+39nVg2SNiTd1AbwfEQ8sJj5rQO8LX98qQenxjDrMQ4EZma9nJuGzMx6OQcCM7NezoHAzKyXcyAwM+vlHAjMzHo5BwIzs17OgcDMrJdzIDAz6+X+H637arEaN+ucAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fixed = {\"'T2'\": 300}\n", + "\n", + "all_fim.figure_drawing(fixed, ['CA0','T'], 'Reactor case','$C_{A0}$ [M]', 'T [K]' )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/pyomo/contrib/doe/measurements.py b/pyomo/contrib/doe/measurements.py new file mode 100644 index 00000000000..b4a57195598 --- /dev/null +++ b/pyomo/contrib/doe/measurements.py @@ -0,0 +1,276 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +from pyomo.common.dependencies import ( + numpy as np, numpy_available, + pandas as pd, pandas_available, + matplotlib as plt, matplotlib_available, +) + + +class Measurements: + def __init__(self, measurement_index_time, variance=None, ind_string='_index_'): + """ + This class stores information on which algebraic and differential variables in the Pyomo model are considered measurements. + This includes the functionality to specify indices for these measurement variables. + For example, with a partial differential algebraic equation model, + these measurement index sets can specify which spatial and temporal coordinates each measurement is available. + Moreover, this class supports defining the covariance matrix for all measurements. + + Parameters + ---------- + measurement_index_time: + a ``dict``, keys are measurement variable names, + if there are extra index, for e.g., Var[scenario, extra_index, time]: + values are a dictionary, keys are its extra index, values are its measuring time points. + if there are no extra index, for e.g., Var[scenario, time]: + values are a list of measuring time point. + For e.g., for the kinetics illustrative example, it should be {'C':{'CA':[0,1,..], 'CB':[0,2,...]}, 'k':[0,4,..]}, + so the measurements are C[scenario, 'CA', 0]..., k[scenario, 0].... + variance: + a ``dict``, keys are measurement variable names, values are a dictionary, keys are its extra index, + values are its variance (a scalar number), values are its variance if there is no extra index for this measurement. + For e.g., for the kinetics illustrative example, it should be {'C':{'CA': 10, 'CB': 1, 'CC': 2}}. + If given None, the default is {'C':{'CA': 1, 'CB': 1, 'CC': 1}}. + ind_string: + a ''string'', used to flatten the name of variables and extra index. Default is '_index_'. + For e.g., for {'C':{'CA': 10, 'CB': 1, 'CC': 2}}, the reformulated name is 'C_index_CA'. + """ + self.measurement_all_info = measurement_index_time + self.ind_string = ind_string + # a list of measurement names + self.measurement_name = list(measurement_index_time.keys()) + # begin flatten + self._name_and_index_generator(self.measurement_all_info) + self._generate_flatten_name(self.name_and_index) + self._generate_variance(self.flatten_measure_name, variance, self.name_and_index) + self._generate_flatten_timeset(self.measurement_all_info, self.flatten_measure_name, self.name_and_index) + self._model_measure_name() + + # generate the overall measurement time points set, including the measurement time for all measurements + flatten_timepoint = list(self.flatten_measure_timeset.values()) + overall_time = [] + for i in flatten_timepoint: + overall_time += i + timepoint_overall_set = list(set(overall_time)) + self.timepoint_overall_set = timepoint_overall_set + + + def _name_and_index_generator(self, all_info): + """ + Generate a dictionary, keys are the variable names, values are the indexes of this variable. + For e.g., name_and_index = {'C': ['CA', 'CB', 'CC']} + Parameters + --------- + all_info: a dictionary, keys are measurement variable names, + values are a dictionary, keys are its extra index, values are its measuring time points + values are a list of measuring time point if there is no extra index for this measurement + Note: all_info can be the self.measurement_all_info, but does not have to be it. + """ + measurement_name = list(all_info.keys()) + # a list of measurement extra indexes + measurement_extra_index = [] + # check if the measurement has extra indexes + for i in measurement_name: + if type(all_info[i]) is dict: + index_list = list(all_info[i].keys()) + measurement_extra_index.append(index_list) + elif type(all_info[i]) is list: + measurement_extra_index.append(None) + # a dictionary, keys are measurement names, values are a list of extra indexes + self.name_and_index = dict(zip(measurement_name, measurement_extra_index)) + + def _generate_flatten_name(self, measure_name_and_index): + """ + Generate measurement flattened names + Parameters + ---------- + measure_name_and_index: a dictionary, keys are measurement names, values are lists of extra indexes + + Returns + ------ + jac_involved_name: a list of flattened measurement names + """ + flatten_names = [] + for j in measure_name_and_index.keys(): + if measure_name_and_index[j] is not None: # if it has extra index + for ind in measure_name_and_index[j]: + flatten_name = j + self.ind_string + str(ind) + flatten_names.append(flatten_name) + else: + flatten_names.append(j) + + self.flatten_measure_name = flatten_names + + def _generate_variance(self, flatten_measure_name, variance, name_and_index): + """ + Generate the variance dictionary + Parameters + ---------- + flatten_measure_name: flattened measurement names. For e.g., flattenning {'C':{'CA': 10, 'CB': 1, 'CC': 2}} will be 'C_index_CA', ..., 'C_index_CC'. + variance: + a ``dict``, keys are measurement variable names, values are a dictionary, keys are its extra index name, + values are its variance as a scalar number. + For e.g., for the kinetics illustrative example, it should be {'C':{'CA': 10, 'CB': 1, 'CC': 2}}. + If given None, the default is {'C':{'CA': 1, 'CB': 1, 'CC': 1}}. + If there is no extra index, it is a dict, keys are measurement variable names, values are its variance as a scalar number. + name_and_index: + a dictionary, keys are measurement names, values are a list of extra indexes. + """ + flatten_variance = {} + for i in flatten_measure_name: + if variance is None: + flatten_variance[i] = 1 + else: + # split the flattened name if needed + if self.ind_string in i: + measure_name = i.split(self.ind_string)[0] + measure_index = i.split(self.ind_string)[1] + if type(name_and_index[measure_name][0]) is int: + measure_index = int(measure_index) + flatten_variance[i] = variance[measure_name][measure_index] + else: + flatten_variance[i] = variance[i] + self.flatten_variance = flatten_variance + + def _generate_flatten_timeset(self, all_info, flatten_measure_name,name_and_index): + """ + Generate flatten variables timeset. Return a dict where keys are the flattened variable names, + values are a list of measurement time. + + """ + flatten_measure_timeset = {} + for i in flatten_measure_name: + # split the flattened name if needed + if self.ind_string in i: + measure_name = i.split(self.ind_string)[0] + measure_index = i.split(self.ind_string)[1] + if type(name_and_index[measure_name][0]) is int: + measure_index = int(measure_index) + flatten_measure_timeset[i] = all_info[measure_name][measure_index] + else: + flatten_measure_timeset[i] = all_info[i] + self.flatten_measure_timeset = flatten_measure_timeset + + def _model_measure_name(self): + """Return pyomo string name + """ + # store pyomo string name + measurement_names = [] + # loop over measurement name + for mname in self.flatten_measure_name: + # check if there is extra index + if self.ind_string in mname: + measure_name = mname.split(self.ind_string)[0] + measure_index = mname.split(self.ind_string)[1] + for tim in self.flatten_measure_timeset[mname]: + # get the measurement name in the model + measurement_name = measure_name + '[0,' + measure_index + ',' + str(tim) + ']' + measurement_names.append(measurement_name) + else: + for tim in self.flatten_measure_timeset[mname]: + # get the measurement name in the model + measurement_name = mname + '[0,' + str(tim) + ']' + measurement_names.append(measurement_name) + self.model_measure_name = measurement_names + + def SP_measure_name(self, j, t,scenario_all=None, p=None, mode='sequential_finite', legal_t=True): + """Return pyomo string name for different modes + Arguments + --------- + j: flatten measurement name + t: time + scenario_all: all scenario object, only needed for simultaneous finite mode + p: parameter, only needed for simultaneous finite mode + mode: mode name, can be 'simultaneous_finite' or 'sequential_finite' + legal_t: if the time point is legal for this measurement. default is True + + Return + ------ + up_C, lo_C: two measurement pyomo string names for simultaneous mode + legal_t: if the time point is legal for this measurement + string_name: one measurement pyomo string name for sequential + """ + if mode=='simultaneous_finite': + # check extra index + if self.ind_string in j: + measure_name = j.split(self.ind_string)[0] + measure_index = j.split(self.ind_string)[1] + if type(self.name_and_index[measure_name][0]) is str: + measure_index = '"' + measure_index + '"' + if t in self.flatten_measure_timeset[j]: + up_C = 'm.' + measure_name + '[' + str(scenario_all['jac-index'][p][0]) + ',' + measure_index + ',' + str(t) + ']' + lo_C = 'm.' + measure_name + '[' + str(scenario_all['jac-index'][p][1]) + ',' + measure_index + ',' + str(t) + ']' + else: + legal_t = False + else: + up_C = 'm.' + j + '[' + str(scenario_all['jac-index'][p][0]) + ',' + str(t) + ']' + lo_C = 'm.' + j + '[' + str(scenario_all['jac-index'][p][1]) + ',' + str(t) + ']' + + return up_C, lo_C, legal_t + + elif mode == 'sequential_finite': + if self.ind_string in j: + measure_name = j.split(self.ind_string)[0] + measure_index = j.split(self.ind_string)[1] + if type(self.name_and_index[measure_name][0]) is str: + measure_index = '"' + measure_index + '"' + if t in self.flatten_measure_timeset[j]: + string_name = 'mod.' + measure_name + '[0,' + str((measure_index)) + ',' + str(t) + ']' + else: + string_name = 'mod.' + j + '[0,' + str(t) + ']' + + return string_name + + + def check_subset(self,subset, throw_error=True, valid_subset=True): + """ + Check if the subset is correctly defined with right name, index and time. + + subset: + a ''dict'' where measurement name and index are involved in jacobian calculation + throw_error: + if the given subset is not a subset of the measurement set, throw error message + """ + flatten_subset = subset.flatten_measure_name + flatten_timeset = subset.flatten_measure_timeset + # loop over subset measurement names + for i in flatten_subset: + # check if subset measurement names are in the overall measurement names + if i not in self.flatten_measure_name: + valid_subset = False + if throw_error: + raise ValueError('This is not a legal subset of the measurement overall set!') + else: + # check if subset measurement timepoints are in the overall measurement timepoints + for t in flatten_timeset[i]: + if t not in self.flatten_measure_timeset[i]: + valid_subset = False + if throw_error: + raise ValueError('The time of {} is not included as measurements before.'.format(t)) + return valid_subset \ No newline at end of file diff --git a/pyomo/contrib/doe/result.py b/pyomo/contrib/doe/result.py new file mode 100644 index 00000000000..01f977e1e98 --- /dev/null +++ b/pyomo/contrib/doe/result.py @@ -0,0 +1,722 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +from pyomo.common.dependencies import ( + numpy as np, numpy_available, + pandas as pd, pandas_available, + matplotlib as plt, matplotlib_available, +) + +from itertools import product +import logging +from pyomo.opt import SolverStatus, TerminationCondition + +class FisherResults: + def __init__(self, para_name, measure_object, jacobian_info=None, all_jacobian_info=None, + prior_FIM=None, store_FIM=None, scale_constant_value=1, max_condition_number=1.0E12, + verbose=True): + """Analyze the FIM result for a single run + + Parameters + ----------- + para_name: + A ``list`` of parameter names + measure_object: + measurement information object + jacobian_info: + the jacobian for this measurement object + all_jacobian_info: + the overall jacobian + prior_FIM: + if there's prior FIM to be added + store_FIM: + if storing the FIM in a .csv or .txt, give the file name here as a string + scale_constant_value: + scale all elements in Jacobian matrix, default is 1. + max_condition_number: + max condition number + verbose: + if True, print statements are used + """ + self.para_name = para_name + self.measure_object = measure_object + self.measurement_variables = measure_object.measurement_name + self.measurement_timeset = measure_object.flatten_measure_timeset + self.flatten_all_measure = measure_object.flatten_measure_name + + if jacobian_info is None: + self.jaco_information = all_jacobian_info + else: + self.jaco_information = jacobian_info + self.all_jacobian_info = all_jacobian_info + + self.prior_FIM = prior_FIM + self.store_FIM = store_FIM + self.scale_constant_value = scale_constant_value + self.fim_scale_constant_value = scale_constant_value ** 2 + self.max_condition_number = max_condition_number + self.verbose = verbose + self.logger = logging.getLogger(__name__) + self.logger.setLevel(level=logging.WARN) + + + def calculate_FIM(self, dv_values, result=None): + """Calculate FIM from Jacobian information. This is for grid search (combined models) results + + Parameters + ---------- + dv_values: + a ``dict`` where keys are design variable names, values are a dict whose keys are time point and values are the design variable value at that time point + result: + solver status returned by IPOPT + """ + self.result = result + self.doe_result = None + + # get number of parameters + no_param = len(self.para_name) + + # reform jacobian, split the overall Q into Q_r, each r is a flattened measurement name + Q_response_list, variance_list = self._jac_reform_3D(self.jaco_information, Q_response=True) + + fim = np.zeros((no_param, no_param)) + + for i in range(len(Q_response_list)): + fim += ((1/variance_list[i])*(Q_response_list[i]@Q_response_list[i].T)) + + # add prior information + if (self.prior_FIM is not None): + try: + fim = fim + self.prior_FIM + self.logger.info('Existed information has been added.') + except: + raise ValueError('Check the shape of prior FIM.') + + if np.linalg.cond(fim) > self.max_condition_number: + self.logger.info("Warning: FIM is near singular. The condition number is: %s ;", np.linalg.cond(fim)) + self.logger.info('A condition number bigger than %s is considered near singular.', self.max_condition_number) + + # call private methods + self._print_FIM_info(fim, dv_set=dv_values) + if self.result is not None: + self._get_solver_info() + + # if given store file name, store the FIM + if (self.store_FIM is not None): + self._store_FIM() + + def subset(self, measurement_subset): + """Create new FisherResults object corresponding to provided measurement_subset. + This requires that measurement_subset is a true subset of the original measurement object. + Arguments: + measurement_subset: Instance of Measurements class + Returns: + new_result: New instance of FisherResults + """ + + # Check that measurement_subset is a valid subset of self.measurement + self.measure_object.check_subset(measurement_subset) + + # Split Jacobian (should already be 3D) + small_jac = self._split_jacobian(measurement_subset) + + # create a new subject + FIM_subclass = FisherResults(self.para_name, measurement_subset, jacobian_info=small_jac, prior_FIM=self.prior_FIM, store_FIM=self.store_FIM, scale_constant_value=self.scale_constant_value, max_condition_number=self.max_condition_number) + + return FIM_subclass + + def _split_jacobian(self, measurement_subset): + """ + Split jacobian + Args: + measure_subset: the object of the measurement subsets + + Returns: + jaco_info: splitted Jacobian + """ + # create a dict for FIM. It has the same keys as the Jacobian dict. + jaco_info = {} + + # convert the form of jacobian for split + jaco_3D = self._jac_reform_3D(self.jacobian_info) + + involved_flatten_index = measurement_subset.flatten_measure_name + + # reorganize the jacobian subset with the same form of the jacobian + # loop over parameters + for p, par in enumerate(self.para_name): + jaco_info[par] = [] + # loop over flatten measurements + for n, nam in enumerate(involved_flatten_index): + if nam in self.flatten_all_measure: + n_all_measure = self.flatten_all_measure.index(nam) + # loop over time + for d in range(len(jaco_3D[n_all_measure, p, :])): + jaco_info[par].append(jaco_3D[n_all_measure, p, d]) + return jaco_info + + def _jac_reform_3D(self, jac_original, Q_response=False): + """ + Reform the Jacobian returned by _finite_calculation() to be a 3D numpy array, [measurements, parameters, time] + """ + # 3-D array form of jacobian [measurements, parameters, time] + self.measure_timeset = list(self.measurement_timeset.values())[0] + no_time = len(self.measure_timeset) + jac_3Darray = np.zeros((len(self.flatten_all_measure), len(self.para_name), no_time)) + # reorganize the matrix + for m, mname in enumerate(self.flatten_all_measure): + for p, para in enumerate(self.para_name): + for t, tim in enumerate(self.measure_timeset): + jac_3Darray[m, p, t] = jac_original[para][m * no_time + t] + if Q_response: + Qr_list = [] + var_list = [] + for m, mname in enumerate(self.flatten_all_measure): + Qr_list.append(jac_3Darray[m, :, :]) + var_list.append(self.measure_object.flatten_variance[mname]) + + return Qr_list, var_list + else: + return jac_3Darray + + + def _print_FIM_info(self, FIM, dv_set=None): + """ + using a dictionary to store all FIM information + + Parameters: + ----------- + FIM: the Fisher Information Matrix, needs to be P.D. and symmetric + dv_set: design variable dictionary + + Return: + ------ + fim_info: a FIM dictionary containing the following key:value pairs + ~['FIM']: a list of FIM itself + ~[design variable name]: a list of design variable values at each time point + ~['Trace']: a scalar number of Trace + ~['Determinant']: a scalar number of determinant + ~['Condition number:']: a scalar number of condition number + ~['Minimal eigen value:']: a scalar number of minimal eigen value + ~['Eigen values:']: a list of all eigen values + ~['Eigen vectors:']: a list of all eigen vectors + """ + eig = np.linalg.eigvals(FIM) + self.FIM = FIM + self.trace = np.trace(FIM) + self.det = np.linalg.det(FIM) + self.min_eig = min(eig) + self.cond = max(eig) / min(eig) + self.eig_vals = eig + self.eig_vecs = np.linalg.eig(FIM)[1] + + dv_names = list(dv_set.keys()) + + FIM_dv_info = {} + FIM_dv_info[dv_names[0]] = dv_set[dv_names[0]] + FIM_dv_info[dv_names[1]] = dv_set[dv_names[1]] + + self.dv_info = FIM_dv_info + + self.logger.info('FIM: %s; \n Trace: %s; \n Determinant: %s;', self.FIM, self.trace, self.det) + self.logger.info('Condition number: %s; \n Min eigenvalue: %s.', self.cond, self.min_eig) + + def _solution_info(self, m, dv_set): + """ + Solution information. Only for optimization problem + + Parameters: + ----------- + m: model + dv_set: design variable dictionary + + Return: + ------ + model_info: model solutions dictionary containing the following key:value pairs + -['obj']: a scalar number of objective function value + -['det']: a scalar number of determinant calculated by the model (different from FIM_info['det'] which + is calculated by numpy) + -['trace']: a scalar number of trace calculated by the model + -[design variable name]: a list of design variable solution + """ + self.obj_value = value(m.obj) + + # When scaled with constant values, the effect of the scaling factors are removed here + # For determinant, the scaling factor to determinant is scaling factor ** (Dim of FIM) + # For trace, the scaling factor to trace is the scaling factor. + if self.obj == 'det': + self.obj_det = np.exp(value(m.obj)) / (self.fim_scale_constant_value) ** (len(self.para_name)) + elif self.obj == 'trace': + self.obj_trace = np.exp(value(m.obj)) / (self.fim_scale_constant_value) + + dv_names = list(dv_set.keys()) + dv_times = list(dv_set.values()) + + solution = {} + for d, dname in enumerate(dv_names): + sol = [] + if dv_times[d] is not None: + for t, time in enumerate(dv_times[d]): + newvar = getattr(m, dname)[time] + sol.append(value(newvar)) + else: + newvar = getattr(m, dname) + sol.append(value(newvar)) + + solution[dname] = sol + self.solution = solution + + def _store_FIM(self): + # if given store file name, store the FIM + store_dict = {} + for i, name in enumerate(self.para_name): + store_dict[name] = self.FIM[i] + FIM_store = pd.DataFrame(store_dict) + FIM_store.to_csv(self.store_FIM, index=False) + + def _get_solver_info(self): + """ + Solver information dictionary + + Return: + ------ + solver_status: a solver infomation dictionary containing the following key:value pairs + -['square']: a string of square result solver status + -['doe']: a string of doe result solver status + """ + + if (self.result.solver.status == SolverStatus.ok) and ( + self.result.solver.termination_condition == TerminationCondition.optimal): + self.status = 'converged' + elif (self.result.solver.termination_condition == TerminationCondition.infeasible): + self.status = 'infeasible' + else: + self.status = self.result.solver.status + + + + + +class GridSearchResult: + def __init__(self, design_ranges, design_dimension_names, design_control_time, FIM_result_list, store_optimality_name=None, verbose=True): + """ + This class deals with the FIM results from grid search, providing A, D, E, ME-criteria results for each design variable. + Can choose to draw 1D sensitivity curves and 2D heatmaps. + + Parameters: + ----------- + design_ranges: + a ``dict`` whose keys are design variable names, values are a list of design variable values to go over + design_dimension_names: + a ``list`` of design variables names + design_control_time: + a ``list`` of design control timesets + FIM_result_list: + a ``dict`` containing FIM results, keys are a tuple of design variable values, values are FIM result objects + store_optimality_name: + a .csv file name containing all four optimalities value + verbose: + if True, print statements + """ + # design variables + self.design_names = design_dimension_names + self.design_ranges = design_ranges + self.design_control_time = design_control_time + self.FIM_result_list = FIM_result_list + + self.store_optimality_name = store_optimality_name + self.verbose = verbose + + def extract_criteria(self): + """ + Extract design criteria values for every 'grid' (design variable combination) searched. + + Returns: + ------- + self.store_all_results_dataframe: a pandas dataframe with columns as design variable names and A, D, E, ME-criteria names. + Each row contains the design variable value for this 'grid', and the 4 design criteria value for this 'grid'. + """ + + # a list store all results + store_all_results = [] + + # generate combinations of design variable values to go over + search_design_set = product(*self.design_ranges) + + # loop over deign value combinations + for design_set_iter in search_design_set: + + # locate this grid in the dictionary of combined results + result_object_asdict = {k:v for k,v in self.FIM_result_list.items() if k==design_set_iter} + # an result object is identified by a tuple of the design variable value it uses + result_object_iter = result_object_asdict[design_set_iter] + + # store results as a row in the dataframe + store_iteration_result = list(design_set_iter) + store_iteration_result.append(result_object_iter.trace) + store_iteration_result.append(result_object_iter.det) + store_iteration_result.append(result_object_iter.min_eig) + store_iteration_result.append(result_object_iter.cond) + + # add this row to the dataframe + store_all_results.append(store_iteration_result) + + # generate column names for the dataframe + column_names = [] + # this count is for repeated design variable names which can happen in dynamic problems + count = 0 + for i in self.design_names: + # if a name is in the design variable name list more than once, name them as name_itself, name_itself2, ... + # this is because it can be erroneous when we extract values from a dataframe with two columns having the same name + if i in column_names: + count += 1 + i = i+str(count+1) + column_names.append(i) + + # Each design criteria has a column to store values + column_names.append('A') + column_names.append('D') + column_names.append('E') + column_names.append('ME') + # generate the dataframe + self.store_all_results_dataframe = pd.DataFrame(store_all_results, columns=column_names) + # if needs to store the values + if self.store_optimality_name is not None: + self.store_all_results_dataframe.to_csv(self.store_optimality_name, index=False) + + + def figure_drawing(self, fixed_design_dimensions, sensitivity_dimension, title_text, xlabel_text, ylabel_text, font_axes=16, font_tick=14, log_scale=True): + """ + Extract results needed for drawing figures from the overall result dataframe. + Draw 1D sensitivity curve or 2D heatmap. + It can be applied to results of any dimensions, but requires design variable values in other dimensions be fixed. + + Parameters: + ---------- + fixed_design_dimensions: a dictionary, keys are the design variable names to be fixed, values are the value of it to be fixed. + sensitivity_dimension: a list of design variable names to draw figures. + If only one name is given, a 1D sensitivity curve is drawn + if two names are given, a 2D heatmap is drawn. + title_text: name of the figure, a string + xlabel_text: x label title, a string. + In a 1D sensitivity curve, it is the design variable by which the curve is drawn. + In a 2D heatmap, it should be the second design variable in the design_ranges + ylabel_text: y label title, a string. + A 1D sensitivity curve does not need it. In a 2D heatmap, it should be the first design variable in the dv_ranges + font_axes: axes label font size + font_tick: tick label font size + log_scale: if True, the result matrix will be scaled by log10 + + Returns: + -------- + None + """ + self.fixed_design_names = list(fixed_design_dimensions.keys()) + self.fixed_design_values = list(fixed_design_dimensions.values()) + self.sensitivity_dimension = sensitivity_dimension + + if len(self.fixed_design_names)+len(self.sensitivity_dimension)!=len(self.design_names): + raise ValueError('Error: All dimensions except for those the figures are drawn by should be fixed.') + + if len(self.sensitivity_dimension) not in [1,2]: + raise ValueError("Error: Either 1D or 2D figures can be drawn.") + + # generate a combination of logic sentences to filter the results of the DOF needed. + # an example filter: (self.store_all_results_dataframe["CA0"]==5). + if len(self.fixed_design_names) != 0: + filter = '' + for i in range(len(self.fixed_design_names)): + filter += '(self.store_all_results_dataframe[' + filter += str(self.fixed_design_names[i]) + filter += ']==' + filter += str(self.fixed_design_values[i]) + filter += ')' + if i != (len(self.fixed_design_names)-1): + filter += '&' + # extract results with other dimensions fixed + figure_result_data = self.store_all_results_dataframe.loc[eval(filter)] + # if there is no other fixed dimensions + else: + figure_result_data = self.store_all_results_dataframe + + # add results for figures + self.figure_result_data = figure_result_data + + # if one design variable name is given as DOF, draw 1D sensitivity curve + if (len(sensitivity_dimension) == 1): + self._curve1D(title_text, xlabel_text, font_axes=16, font_tick=14, log_scale=True) + # if two design variable names are given as DOF, draw 2D heatmaps + elif (len(sensitivity_dimension) == 2): + self._heatmap(title_text, xlabel_text, ylabel_text, font_axes=16, font_tick=14, log_scale=True) + + + def _curve1D(self, title_text, xlabel_text, font_axes=16, font_tick=14, log_scale=True): + """ + Draw 1D sensitivity curves for all design criteria + + Parameters: + ---------- + title_text: name of the figure, a string + xlabel_text: x label title, a string. + In a 1D sensitivity curve, it is the design variable by which the curve is drawn. + font_axes: axes label font size + font_tick: tick label font size + log_scale: if True, the result matrix will be scaled by log10 + + Returns: + -------- + 4 Figures of 1D sensitivity curves for each criteria + """ + + # extract the range of the DOF design variable + x_range = self.figure_result_data[self.sensitivity_dimension[0]].values.tolist() + + # decide if the results are log scaled + if log_scale: + y_range_A = np.log10(self.figure_result_data['A'].values.tolist()) + y_range_D = np.log10(self.figure_result_data['D'].values.tolist()) + y_range_E = np.log10(self.figure_result_data['E'].values.tolist()) + y_range_ME = np.log10(self.figure_result_data['ME'].values.tolist()) + else: + y_range_A = self.figure_result_data['A'].values.tolist() + y_range_D = self.figure_result_data['D'].values.tolist() + y_range_E = self.figure_result_data['E'].values.tolist() + y_range_ME = self.figure_result_data['ME'].values.tolist() + + # Draw A-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + #plt.rcParams.update(params) + ax.plot(x_range, y_range_A) + ax.scatter(x_range, y_range_A) + ax.set_ylabel('$log_{10}$ Trace') + ax.set_xlabel(xlabel_text) + plt.pyplot.title(title_text + ' - A optimality') + plt.pyplot.show() + + # Draw D-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + # plt.rcParams.update(params) + ax.plot(x_range, y_range_D) + ax.scatter(x_range, y_range_D) + ax.set_ylabel('$log_{10}$ Determinant') + ax.set_xlabel(xlabel_text) + plt.pyplot.title(title_text + ' - D optimality') + plt.pyplot.show() + + # Draw E-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + # plt.rcParams.update(params) + ax.plot(x_range, y_range_E) + ax.scatter(x_range, y_range_E) + ax.set_ylabel('$log_{10}$ Minimal eigenvalue') + ax.set_xlabel(xlabel_text) + plt.pyplot.title(title_text + ' - E optimality') + plt.pyplot.show() + + # Draw Modified E-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + # plt.rcParams.update(params) + ax.plot(x_range, y_range_ME) + ax.scatter(x_range, y_range_ME) + ax.set_ylabel('$log_{10}$ Condition number') + ax.set_xlabel(xlabel_text) + plt.pyplot.title(title_text + ' - Modified E optimality') + plt.pyplot.show() + + def _heatmap(self, title_text, xlabel_text, ylabel_text, font_axes=16, font_tick=14, log_scale=True): + """ + Draw 2D heatmaps for all design criteria + + Parameters: + ---------- + title_text: name of the figure, a string + xlabel_text: x label title, a string. + In a 2D heatmap, it should be the second design variable in the design_ranges + ylabel_text: y label title, a string. + In a 2D heatmap, it should be the first design variable in the dv_ranges + font_axes: axes label font size + font_tick: tick label font size + log_scale: if True, the result matrix will be scaled by log10 + + Returns: + -------- + 4 Figures of 2D heatmap for each criteria + """ + + # achieve the design variable ranges this figure needs + # create a dictionary for sensitivity dimensions + sensitivity_dict = {} + for i, nam in enumerate(self.design_names): + if nam in self.sensitivity_dimension: + sensitivity_dict[nam] = self.design_ranges[i] + + x_range = sensitivity_dict[self.sensitivity_dimension[0]] + y_range = sensitivity_dict[self.sensitivity_dimension[1]] + + + # extract the design criteria values + A_range = self.figure_result_data['A'].values.tolist() + D_range = self.figure_result_data['D'].values.tolist() + E_range = self.figure_result_data['E'].values.tolist() + ME_range = self.figure_result_data['ME'].values.tolist() + + # reshape the design criteria values for heatmaps + cri_a = np.asarray(A_range).reshape(len(x_range), len(y_range)) + cri_d = np.asarray(D_range).reshape(len(x_range), len(y_range)) + cri_e = np.asarray(E_range).reshape(len(x_range), len(y_range)) + cri_e_cond = np.asarray(ME_range).reshape(len(x_range), len(y_range)) + + self.cri_a = cri_a + self.cri_d = cri_d + self.cri_e = cri_e + self.cri_e_cond = cri_e_cond + + # decide if log scaled + if log_scale: + hes_a = np.log10(self.cri_a) + hes_e = np.log10(self.cri_e) + hes_d = np.log10(self.cri_d) + hes_e2 = np.log10(self.cri_e_cond) + else: + hes_a = self.cri_a + hes_e = self.cri_e + hes_d = self.cri_d + hes_e2 = self.cri_e_cond + + # set heatmap x,y ranges + xLabel = x_range + yLabel = y_range + + # A-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + plt.pyplot.rcParams.update(params) + ax.set_yticks(range(len(yLabel))) + ax.set_yticklabels(yLabel) + ax.set_ylabel(ylabel_text) + ax.set_xticks(range(len(xLabel))) + ax.set_xticklabels(xLabel) + ax.set_xlabel(xlabel_text) + im = ax.imshow(hes_a.T, cmap=plt.pyplot.cm.hot_r) + ba = plt.pyplot.colorbar(im) + ba.set_label('log10(trace(FIM))') + plt.pyplot.title(title_text + ' - A optimality') + plt.pyplot.show() + + # D-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + plt.pyplot.rcParams.update(params) + ax.set_yticks(range(len(yLabel))) + ax.set_yticklabels(yLabel) + ax.set_ylabel(ylabel_text) + ax.set_xticks(range(len(xLabel))) + ax.set_xticklabels(xLabel) + ax.set_xlabel(xlabel_text) + im = ax.imshow(hes_d.T, cmap=plt.pyplot.cm.hot_r) + ba = plt.pyplot.colorbar(im) + ba.set_label('log10(det(FIM))') + plt.pyplot.title(title_text + ' - D optimality') + plt.pyplot.show() + + # E-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + plt.pyplot.rcParams.update(params) + ax.set_yticks(range(len(yLabel))) + ax.set_yticklabels(yLabel) + ax.set_ylabel(ylabel_text) + ax.set_xticks(range(len(xLabel))) + ax.set_xticklabels(xLabel) + ax.set_xlabel(xlabel_text) + im = ax.imshow(hes_e.T, cmap=plt.pyplot.cm.hot_r) + ba = plt.pyplot.colorbar(im) + ba.set_label('log10(minimal eig(FIM))') + plt.pyplot.title(title_text + ' - E optimality') + plt.pyplot.show() + + # modified E-optimality + fig = plt.pyplot.figure() + plt.pyplot.rc('axes', titlesize=font_axes) + plt.pyplot.rc('axes', labelsize=font_axes) + plt.pyplot.rc('xtick', labelsize=font_tick) + plt.pyplot.rc('ytick', labelsize=font_tick) + ax = fig.add_subplot(111) + params = {'mathtext.default': 'regular'} + plt.pyplot.rcParams.update(params) + ax.set_yticks(range(len(yLabel))) + ax.set_yticklabels(yLabel) + ax.set_ylabel(ylabel_text) + ax.set_xticks(range(len(xLabel))) + ax.set_xticklabels(xLabel) + ax.set_xlabel(xlabel_text) + im = ax.imshow(hes_e2.T, cmap=plt.pyplot.cm.hot_r) + ba = plt.pyplot.colorbar(im) + ba.set_label('log10(cond(FIM))') + plt.pyplot.title(title_text + ' - Modified E-optimality') + plt.pyplot.show() + diff --git a/pyomo/contrib/doe/scenario.py b/pyomo/contrib/doe/scenario.py new file mode 100644 index 00000000000..8a2efab9273 --- /dev/null +++ b/pyomo/contrib/doe/scenario.py @@ -0,0 +1,290 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + +import pickle + +class Scenario_generator: + def __init__(self, para_dict, formula='central', step=0.001, store=False): + """Generate scenarios. + DoE library first calls this function to generate scenarios. + For sequential and simultaneous models, call different functions in this class. + + Parameters + ----------- + para_dict: + a ``dict`` of parameter, keys are names of ''string'', values are their nominal value of ''float''. + for e.g., {'A1': 84.79, 'A2': 371.72, 'E1': 7.78, 'E2': 15.05} + formula: + choose from 'central', 'forward', 'backward', None. + step: + Sensitivity perturbation step size, a fraction between [0,1]. default is 0.001 + store: + if True, store results. + """ + + if formula not in ['central', 'forward', 'backward', None]: + raise ValueError('Undefined formula. Available formulas: central, forward, backward, none.') + + # get info from parameter dictionary + self.para_dict = para_dict + self.para_names = list(para_dict.keys()) + self.no_para = len(self.para_names) + self.formula = formula + self.step = step + self.store = store + self.scenario_nominal = [para_dict[d] for d in self.para_names] + + def simultaneous_scenario(self): + """ + Generate scenario dict for simultaneous models + + Returns: + ------- + scena_overall: a dictionary containing scenarios dictionaries. + scena_overall[name of parameter]: a dict, keys are the scenario name(numeric integer starting from 0), values are parameter value in this scenario + scena_overall['jac-index']: keys are parameter name, values are the scenario names perturbing this parameter. + scena_overall['eps-abs']: keys are parameter name, values are the step it is perturbed + scena_overall['scena-name']: a list of scenario names + + For e.g., if a dict {'P':100, 'D':20} is given, step=0.1, formula='central', it will return: + scena_overall = {'P': {0: 101.0, 1: 100, 2: 99.0, 3: 100}, 'D': {0: 20, 1: 20.2, 2: 20, 3: 19.8}, 'jac-index': {'P': [0, 2], 'D': [1, 3]}, 'eps-abs': {'P': 2.0, 'D': 0.4}, 'scena-name': [0, 1, 2, 3]} + if formula ='forward', it will return: + scena_overall = {'P':{'0':110, '1':100, '2':100}, 'D':{'0':20, '1':22, '2':20}, 'jac-index':{'P':[0,2], 'D':[1,2]}, 'eps-abs':{'P':10,'D':2}, 'scena-name': [0,1,2]} + """ + # generate scenarios + scena_keys, scena = self._scena_generate(self.scenario_nominal, self.formula) + self.scena_keys = scena_keys + self.scena = scena + + # call scenario class and method + scenario_object = Scenario_data(self.para_dict, self.scena_keys, self.scena, self.formula, self.step) + scenario_overall = scenario_object.create_scenario() + + # store scenario + if self.store: + with open('scenario_simultaneous.pickle', 'wb') as f: + pickle.dump(scenario_overall, f) + + return scenario_overall + + + def next_sequential_scenario(self, count): + """ + Generate a single scenario class for one of the sequential models + + Parameters: + ---------- + count: the No. of the sequential models + + Returns: + ------- + scenario_next: scenario dict for this sequential model + """ + scena_keys, scena = self._scena_generate(list(self.scena[count].values()), None) + + # each model is basically a 'none' case of an invasive model + scenario_object = Scenario_data(self.scena[count], scena_keys, scena, None, self.step) + scenario_next = scenario_object.create_scenario() + + return scenario_next + + def generate_sequential_para(self): + """ + Generate object and some 'parameters' for sequential models + + Returns (added to self object): + ------- + self.scena_keys: scenario name, a list of numbers + self.scena: a list of parameter dictionaries for all sequential models + self.scenario_para: a list of two No. of models involved in calculating one parameter sensitivity + self.eps_abs: keys are parameter name, values are the step it is perturbed + """ + + scena_keys, scena = self._scena_generate(self.scenario_nominal, self.formula) + self.scena_keys = scena_keys + self.scena = scena + + # record the number of scenarios involved in calculating a certain parameter sensitivities + scenario_para = {} + for p, para in enumerate(self.para_names): + # the scenario involved in Jacobian calculation + if self.formula == 'central': + scenario_para[para] = [p, p + self.no_para] + elif self.formula == None: + raise ValueError('Finite difference scheme should be chosen.') + else: + scenario_para[para] = [p, self.no_para] + + self.scenario_para = scenario_para + + # calculate the perturbation size of every parameter + eps_abs = {} + for para in self.para_names: + # for central difference scheme, perturbation size is two times the step size + eps_abs[para] = self.step * self.para_dict[para] + if self.formula == 'central': + eps_abs[para] *= 2 + + + self.eps_abs = eps_abs + + def _scena_generate(self, para_nominal, formula): + """ + Generate scenario logics + + Returns: (store in self object) + -------- + self.scena_keys: a list of scenario names + self.scena: a dict, keys are scenario names, values are a list of parameter values + """ + # generate scenario names + if formula == 'central': + scena_keys = list(range(2 * self.no_para)) + elif formula == None: + scena_keys = [0] + else: + scena_keys = list(range(self.no_para + 1)) + + # generate all parameter dict needed for creating a scenario + scena = {} + # generate a dict, keys are scenario number, values are a list of parameter values in this scenario + for i, name in enumerate(scena_keys): + scenario = para_nominal.copy() + + if formula == 'central': + # scenario 0 to #_of_para-1 are forward perturbed + if i < self.no_para: + scenario[i] *= (1 + self.step) + # scenario #_of_para to 2*#_of_para-1 are backward perturbed + else: + scenario[i - self.no_para] *= (1 - self.step) + + elif formula == 'forward': + # scenario 0 to #_of_para-1 are forward perturbed + if i < self.no_para: + scenario[i] *= (1 + self.step) + + elif formula == 'backward': + # scenario 0 to #_of_para-1 are backward perturbed + if i < self.no_para: + scenario[i] *= (1 - self.step) + + scenario_dict = {} + for n, pname in enumerate(self.para_names): + scenario_dict[pname] = scenario[n] + + scena[name] = scenario_dict + + return scena_keys, scena + + # TODO: need to consider how to store both hyperparameter and scenario classes in pickle + # if self.store: + # f = open('scenario_combine','wb') + # pickle.dump(scenario_comp, f) + # f.close() + + +class Scenario_data: + def __init__(self, parameter_dict, scena_keys, scena, form, step): + """ + Generate scenario for a simultaneous model + + parameter_dict: parameter dictionaries + scena_keys: scenario name, a list of numbers + scena: a list of parameter dictionaries for all sequential models + form: choose from 'central', 'forward', 'backward', 'none'. + step: stepsize of a fraction, such as 0.01 + + """ + # get info from parameter dictionary + self.para_dict = parameter_dict + self.para_names = list(parameter_dict.keys()) + + self.scena = scena + self.scena_keys = scena_keys + self.no_para = len(self.para_names) + self.formula = form + self.step = step + + # This is the parameter nominal values + self.scenario_nominal = [] + for d in self.para_names: + self.scenario_nominal.append(parameter_dict[d]) + + def create_scenario(self): + """ + Returns: + -------- + scena_dict: a dictionary containing scenarios dictionaries. + scena_dict[name of parameter]: a dict, keys are the scenario name(numeric integer starting from 0), + values are parameter value in this scenario + scena_dict['jac-index']: keys are parameter name, values are the scenario names perturbing this parameter. + scena_dict['eps-abs']: keys are parameter name, values are the step it is perturbed + scena_dict['scena-name']: a list of scenario names + + For e.g., if a dict {'P':100, 'D':20} is given, step=0.1, formula='central', it will return: + scena_dict = {'P': {0: 101.0, 1: 100, 2: 99.0, 3: 100}, 'D': {0: 20, 1: 20.2, 2: 20, 3: 19.8}, + 'jac-index': {'P': [0, 2], 'D': [1, 3]}, 'eps-abs': {'P': 2.0, 'D': 0.4}, 'scena-name': [0, 1, 2, 3]} + if formula ='forward', it will return: + scena_dict = {'P':{'0':110, '1':100, '2':100}, 'D':{'0':20, '1':22, '2':20}, + 'jac-index':{'P':[0,2], 'D':[1,2]}, 'eps-abs':{'P':10,'D':2}, 'scena-name': [0,1,2]} + """ + # overall dict to return + scenario_dict = {} + # dict for scenario position + jac_index = {} + # dict for parameter perturbation step size + eps_abs = {} + + # loop over parameter name + for p, para in enumerate(self.para_names): + scena_p = {} + for n in self.scena_keys: + scena_p[n] = self.scena[n][para] + + # a dictionary of scenarios and its corresponding parameter values + scenario_dict[para] = scena_p + + # for central difference scheme, perturbation size is two times the step size + if self.formula == 'central': + eps_abs[para] = 2 * self.step * self.para_dict[para] + else: + eps_abs[para] = self.step * self.para_dict[para] + + # the scenario involved in Jacobian calculation + if self.formula == 'central': + jac_index[para] = [p, p + self.no_para] + elif self.formula == None: + jac_index[para] = [0] + else: + jac_index[para] = [p, self.no_para] + + scenario_dict['jac-index'] = jac_index + scenario_dict['eps-abs'] = eps_abs + scenario_dict['scena-name'] = self.scena_keys + + return scenario_dict diff --git a/pyomo/contrib/doe/tests/__init__.py b/pyomo/contrib/doe/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/pyomo/contrib/doe/tests/test_example.py b/pyomo/contrib/doe/tests/test_example.py new file mode 100644 index 00000000000..d78220227da --- /dev/null +++ b/pyomo/contrib/doe/tests/test_example.py @@ -0,0 +1,61 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +from pyomo.common.dependencies import ( + numpy as np, numpy_available, + pandas as pd, pandas_available, + scipy_available, +) + +import pyomo.common.unittest as unittest + +from pyomo.opt import SolverFactory +ipopt_available = SolverFactory('ipopt').available() + +class TestReactorExample(unittest.TestCase): + + @unittest.skipIf(not ipopt_available, "The 'ipopt' command is not available") + @unittest.skipIf(not scipy_available, "scipy is not available") + def test_reactor_compute_FIM(self): + from pyomo.contrib.doe.example import reactor_compute_FIM + reactor_compute_FIM.main() + + @unittest.skipIf(not ipopt_available, "The 'ipopt' command is not available") + def test_reactor_optimize_doe(self): + from pyomo.contrib.doe.example import reactor_optimize_doe + reactor_optimize_doe.main() + + @unittest.skipIf(not ipopt_available, "The 'ipopt' command is not available") + @unittest.skipIf(not pandas_available, "pandas is not available") + def test_reactor_grid_search(self): + from pyomo.contrib.doe.example import reactor_grid_search + reactor_grid_search.main() + + +if __name__ == "__main__": + unittest.main() diff --git a/pyomo/contrib/doe/tests/test_fim_doe.py b/pyomo/contrib/doe/tests/test_fim_doe.py new file mode 100644 index 00000000000..479ddd351de --- /dev/null +++ b/pyomo/contrib/doe/tests/test_fim_doe.py @@ -0,0 +1,79 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + +import pyomo.common.unittest as unittest +from pyomo.contrib.doe import Measurements, Scenario_generator + +class TestMeasurement(unittest.TestCase): + """Test the measurement class + """ + def test_setup(self): + # generate a set of measurements with extra index CA, CB, CC + # each extra index has different measure time points + t_measure_ca = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + t_measure_cb = [0, 0.25, 0.5, 0.75, 1] + t_measure_cc = [0, 0.125, 0.375, 0.625, 0.875, 1] + var = {'C':{'CA': 5, 'CB': 2, 'CC': 1}} + measure_pass = {'C':{"CA": t_measure_ca, "CB": t_measure_cb, "CC": t_measure_cc}} + + measure_class = Measurements(measure_pass, variance=var) + + # test names, variance, time sets + self.assertEqual(measure_class.flatten_measure_name, ['C_index_CA', 'C_index_CB', 'C_index_CC']) + self.assertEqual(measure_class.flatten_variance, {'C_index_CA': 5, 'C_index_CB': 2, 'C_index_CC': 1}) + self.assertEqual(measure_class.flatten_measure_timeset['C_index_CB'], [0, 0.25, 0.5, 0.75, 1]) + + # test subset feature + subset_1 = {'C':{'CA': t_measure_cb}} + measure_subclass1 = Measurements(subset_1) + self.assertTrue(measure_class.check_subset(measure_subclass1)) + + +class TestParameter(unittest.TestCase): + """ Test the parameter class + """ + def test_setup(self): + # set up parameter class + param_dict = {'A1': 84.79, 'A2': 371.72, 'E1': 7.78, 'E2': 15.05} + + scenario_gene = Scenario_generator(param_dict, formula='central', step=0.1) + parameter_set = scenario_gene.simultaneous_scenario() + + self.assertAlmostEqual(parameter_set['A1'][0], 93.269, places=1) + self.assertAlmostEqual(parameter_set['A1'][4], 76.311, places=1) + self.assertEqual(parameter_set['jac-index']['A2'], [1,5]) + self.assertEqual(parameter_set['scena-name'], [0, 1, 2, 3, 4, 5, 6, 7]) + self.assertAlmostEqual(parameter_set['eps-abs']['E1'], 1.556, places=1) + + scenario_gene.generate_sequential_para() + self.assertEqual(scenario_gene.scenario_para['A2'], [1,5]) + self.assertAlmostEqual(scenario_gene.eps_abs['A1'], 16.958, places=1) + self.assertAlmostEqual(scenario_gene.next_sequential_scenario(2)['E1'][0], 8.558, places=1) + self.assertEqual(scenario_gene.next_sequential_scenario(2)['scena-name'], [0]) + +if __name__ == '__main__': + unittest.main() diff --git a/pyomo/contrib/doe/tests/test_reactor_example.py b/pyomo/contrib/doe/tests/test_reactor_example.py new file mode 100644 index 00000000000..739eb303063 --- /dev/null +++ b/pyomo/contrib/doe/tests/test_reactor_example.py @@ -0,0 +1,153 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2022 +# National Technology and Engineering Solutions of Sandia, LLC +# Under the terms of Contract DE-NA0003525 with National Technology and +# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain +# rights in this software. +# This software is distributed under the 3-clause BSD License. +# +# Pyomo.DoE was produced under the Department of Energy Carbon Capture Simulation +# Initiative (CCSI), and is copyright (c) 2022 by the software owners: +# TRIAD National Security, LLC., Lawrence Livermore National Security, LLC., +# Lawrence Berkeley National Laboratory, Pacific Northwest National Laboratory, +# Battelle Memorial Institute, University of Notre Dame, +# The University of Pittsburgh, The University of Texas at Austin, +# University of Toledo, West Virginia University, et al. All rights reserved. +# +# NOTICE. This Software was developed under funding from the +# U.S. Department of Energy and the U.S. Government consequently retains +# certain rights. As such, the U.S. Government has been granted for itself +# and others acting on its behalf a paid-up, nonexclusive, irrevocable, +# worldwide license in the Software to reproduce, distribute copies to the +# public, prepare derivative works, and perform publicly and display +# publicly, and to permit other to do so. +# ___________________________________________________________________________ + + +# import libraries +from pyomo.common.dependencies import ( + numpy as np, numpy_available, + pandas_available +) + +import pyomo.common.unittest as unittest +from pyomo.contrib.doe import DesignOfExperiments, Measurements +from pyomo.environ import value + +from pyomo.opt import SolverFactory +ipopt_available = SolverFactory('ipopt').available() + +class Test_doe_object(unittest.TestCase): + """ Test the kinetics example with both the sequential_finite mode and the direct_kaug mode + """ + @unittest.skipIf(not ipopt_available, "The 'ipopt' solver is not available") + @unittest.skipIf(not numpy_available, "Numpy is not available") + @unittest.skipIf(not pandas_available, "Pandas is not available") + def test_setUP(self): + from pyomo.contrib.doe.example import reactor_kinetics as reactor + + # define create model function + createmod = reactor.create_model + + # discretizer + disc = reactor.disc_for_measure + + # design variable and its control time set + t_control = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + dv_pass = {'CA0': [0],'T': t_control} + + # Define measurement time points + t_measure = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1] + measure_pass = {'C':{'CA': t_measure, 'CB': t_measure, 'CC': t_measure}} + measure_class = Measurements(measure_pass) + + # Define parameter nominal value + parameter_dict = {'A1': 84.79085853498033, 'A2': 371.71773413976416, 'E1': 7.777032028026428, 'E2': 15.047135137500822} + + def generate_exp(t_set, CA0, T): + """Generate experiments. + t_set: time control set for T. + CA0: CA0 value + T: A list of T + """ + assert(len(t_set)==len(T)), 'T should have the same length as t_set' + + T_con_initial = {} + for t, tim in enumerate(t_set): + T_con_initial[tim] = T[t] + + dv_dict_overall = {'CA0': {0: CA0},'T': T_con_initial} + return dv_dict_overall + + # empty prior + prior_all = np.zeros((4,4)) + + prior_pass=np.asarray(prior_all) + + ### Test sequential_finite mode + exp1 = generate_exp(t_control, 5, [300, 300, 300, 300, 300, 300, 300, 300, 300]) + + doe_object = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior_pass, discretize_model=disc, args=[True]) + + + result = doe_object.compute_FIM(exp1,mode='sequential_finite', FIM_store_name = 'dynamic.csv', + store_output = 'store_output', read_output=None, + scale_nominal_param_value=True, formula='central') + + + result.calculate_FIM(doe_object.design_values) + + self.assertAlmostEqual(np.log10(result.trace), 2.96, places=2) + self.assertAlmostEqual(result.FIM[0][1], 1.84, places=2) + self.assertAlmostEqual(result.FIM[0][2], -70.238, places=2) + + ### Test direct_kaug mode + exp2 = generate_exp(t_control, 5, [570, 300, 300, 300, 300, 300, 300, 300, 300]) + + doe_object2 = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior_pass, discretize_model=disc, args=[False]) + result2 = doe_object2.compute_FIM(exp2,mode='direct_kaug', FIM_store_name = 'dynamic.csv', + store_output = 'store_output', read_output=None, + scale_nominal_param_value=True, formula='central') + + result2.calculate_FIM(doe_object2.design_values) + + self.assertAlmostEqual(np.log10(result2.trace), 2.788587, places=2) + self.assertAlmostEqual(np.log10(result2.det), 2.821840, places=2) + self.assertAlmostEqual(np.log10(result2.min_eig), -1.012346, places=2) + + ### Test stochastic_program mode + + # prior + exp1 = generate_exp(t_control, 3, [500, 300, 300, 300, 300, 300, 300, 300, 300]) + + # add a prior information (scaled FIM with T=500 and T=300 experiments) + prior = np.asarray([[ 17.22501773 , 14.37041814 , -36.47520583 , -71.0809284 ], + [ 14.37041814 , 34.96329376 , -27.32915307, -169.61728922], + [ -36.47520583 , -27.32915307 , 78.42752049, 135.96877921], + [ -71.0809284 , -169.61728922, 135.96877921 , 829.77538611]]) + + + doe_object3 = DesignOfExperiments(parameter_dict, dv_pass, + measure_class, createmod, + prior_FIM=prior, discretize_model=disc, args=[True]) + + square_result, optimize_result= doe_object3.stochastic_program(exp1, if_optimize=True, if_Cholesky=True, + scale_nominal_param_value=True, objective_option='det', + L_initial=np.linalg.cholesky(prior)) + + + self.assertAlmostEqual(value(optimize_result.model.T[0]), 300, places=2) + self.assertAlmostEqual(value(optimize_result.model.T[0.5]), 300, places=2) + self.assertAlmostEqual(np.log10(optimize_result.trace), 3.273840, places=2) + self.assertAlmostEqual(np.log10(optimize_result.det), 5.506772, places=2) + + + +if __name__ == '__main__': + unittest.main() diff --git a/pyomo/contrib/sensitivity_toolbox/sens.py b/pyomo/contrib/sensitivity_toolbox/sens.py index 46e6a7c35c4..ca29f51ce53 100644 --- a/pyomo/contrib/sensitivity_toolbox/sens.py +++ b/pyomo/contrib/sensitivity_toolbox/sens.py @@ -162,6 +162,8 @@ def sensitivity_calculation(method, instance, paramList, perturbList, if method == 'sipopt': ipopt_sens = SolverFactory('ipopt_sens', solver_io='nl') ipopt_sens.options['run_sens'] = 'yes' + if solver_options is not None: + ipopt_sens.options['linear_solver'] = solver_options # Send the model to ipopt_sens and collect the solution results = ipopt_sens.solve(m, keepfiles=keepfiles, tee=tee) @@ -302,9 +304,9 @@ def get_dfds_dcds(model, theta_names, tee=False, solver_options=None): gradient_c: scipy.sparse.csr.csr_matrix Ncon by Nvar size sparse matrix. A Jacobian matrix of the constraints with respect to the (decision variables, parameters) - at the optimal solution. Each row contains [column number, - row number, and value], column order follows variable order in col - and index starts from 1. Note that it follows k_aug. + at the optimal solution. Each row contains [row number, + column number, and value], column order follows variable order in col + and index starts from 0. Note that it follows k_aug. If no constraint exists, return [] col: list Size Nvar list of variable names